| package jnr.posix; |
| |
| import jnr.ffi.Pointer; |
| import jnr.ffi.Runtime; |
| import jnr.ffi.StructLayout; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.charset.Charset; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author Bob McWhirter |
| */ |
| public abstract class BaseMsgHdr implements MsgHdr { |
| |
| protected final NativePOSIX posix; |
| protected final Pointer memory; |
| |
| protected BaseMsgHdr(NativePOSIX posix, StructLayout layout) { |
| this.posix = posix; |
| this.memory = posix.getRuntime().getMemoryManager().allocateTemporary(layout.size(), true); |
| } |
| |
| public void setName(String name) { |
| if (name == null) { |
| setNamePointer(null); |
| setNameLen(0); |
| return; |
| } |
| byte[] nameBytes = name.getBytes(Charset.forName("US-ASCII")); |
| Pointer p = Runtime.getSystemRuntime().getMemoryManager().allocateTemporary(nameBytes.length, true); |
| p.put(0, nameBytes, 0, nameBytes.length); |
| setNamePointer(p); |
| setNameLen(nameBytes.length); |
| } |
| |
| public String getName() { |
| Pointer ptr = getNamePointer(); |
| if (ptr == null) { |
| return null; |
| } |
| return ptr.getString(0, getNameLen(), Charset.forName( "US-ASCII" )); |
| } |
| |
| public CmsgHdr allocateControl(int dataLength) { |
| CmsgHdr[] controls = allocateControls(new int[]{dataLength}); |
| return controls[0]; |
| } |
| |
| public CmsgHdr[] allocateControls(int[] dataLengths) { |
| CmsgHdr[] cmsgs = new CmsgHdr[dataLengths.length]; |
| |
| int totalSize = 0; |
| for (int i = 0; i < dataLengths.length; ++i) { |
| totalSize += posix.socketMacros().CMSG_SPACE(dataLengths[i]); |
| } |
| |
| Pointer ptr = posix.getRuntime().getMemoryManager().allocateDirect(totalSize); |
| |
| int offset = 0; |
| for (int i = 0; i < dataLengths.length; ++i) { |
| int eachSpace = posix.socketMacros().CMSG_SPACE(dataLengths[i]); |
| int len = posix.socketMacros().CMSG_LEN(dataLengths[i]); |
| CmsgHdr each = allocateCmsgHdrInternal(posix, ptr.slice(offset, eachSpace), len); |
| cmsgs[i] = each; |
| offset += eachSpace; |
| } |
| |
| setControlPointer(ptr); |
| setControlLen(totalSize); |
| |
| return cmsgs; |
| } |
| |
| public CmsgHdr[] getControls() { |
| int len = getControlLen(); |
| if (len == 0) { |
| return new CmsgHdr[0]; |
| } |
| |
| List<CmsgHdr> control = new ArrayList<CmsgHdr>(); |
| |
| int offset = 0; |
| |
| Pointer controlPtr = getControlPointer(); |
| |
| while (offset < len) { |
| CmsgHdr each = allocateCmsgHdrInternal(posix, controlPtr.slice(offset), -1); |
| offset += posix.socketMacros().CMSG_SPACE(each.getLen()); |
| control.add(each); |
| } |
| |
| return control.toArray(new CmsgHdr[control.size()]); |
| } |
| |
| public void setIov(ByteBuffer[] buffers) { |
| Pointer iov = Runtime.getSystemRuntime().getMemoryManager().allocateDirect(BaseIovec.layout.size() * buffers.length); |
| |
| for (int i = 0; i < buffers.length; ++i) { |
| Pointer eachIovecPtr = iov.slice(BaseIovec.layout.size() * i); |
| BaseIovec eachIovec = new BaseIovec(posix, eachIovecPtr); |
| eachIovec.set(buffers[i]); |
| } |
| |
| setIovPointer(iov); |
| setIovLen(buffers.length); |
| } |
| |
| public ByteBuffer[] getIov() { |
| int len = getIovLen(); |
| |
| ByteBuffer[] buffers = new ByteBuffer[len]; |
| |
| Pointer iov = getIovPointer(); |
| |
| for (int i = 0; i < len; ++i) { |
| Pointer eachPtr = iov.slice(BaseIovec.layout.size() * i); |
| BaseIovec eachIov = new BaseIovec(posix, eachPtr); |
| buffers[i] = eachIov.get(); |
| } |
| |
| return buffers; |
| } |
| |
| abstract void setNamePointer(Pointer name); |
| |
| abstract Pointer getNamePointer(); |
| |
| abstract void setNameLen(int len); |
| |
| abstract int getNameLen(); |
| |
| abstract void setIovPointer(Pointer iov); |
| |
| abstract Pointer getIovPointer(); |
| |
| abstract int getIovLen(); |
| |
| abstract void setIovLen(int len); |
| |
| abstract CmsgHdr allocateCmsgHdrInternal(NativePOSIX posix, Pointer pointer, int len); |
| |
| abstract void setControlPointer(Pointer control); |
| |
| abstract Pointer getControlPointer(); |
| |
| abstract void setControlLen(int len); |
| |
| } |