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 eachLen = posix.socketMacros().CMSG_SPACE(dataLengths[i]);
CmsgHdr each = allocateCmsgHdrInternal(posix, ptr.slice(offset, eachLen), eachLen);
cmsgs[i] = each;
offset += eachLen;
}
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 += 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);
}