jnetperf/src/main/java/biz/nellemann/jperf/Datagram.java

142 lines
3.4 KiB
Java

package biz.nellemann.jperf;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* Datagram consists of the following
* <p>
* <------------------------- HEADER 32 bytes --------------> <---------- DATA min 32 bytes -------->
* _long _int _int _long _long
* 8_bytes 4_bytes 4_bytes 8_bytes 8_bytes
* MAGIC-ID TYPE LENGTH CUR_PKT MAX_PKT
*
*/
public class Datagram {
final Logger log = LoggerFactory.getLogger(Datagram.class);
private final Random random = new Random();
private final int HEADER_LENGTH = 32;
private final byte[] MAGIC_ID = "jPerfTok".getBytes(StandardCharsets.UTF_8); // Must be 8-bytes
private final int type;
private final int length;
private final int realLength;
private final long curPkt;
private final long maxPkt;
private final byte[] data;
/**
* Create new empty datagram
* @param type
* @param length
* @param currentPkt
*/
public Datagram(int type, int length, long currentPkt, long maxPkt) {
log.debug("Datagram() - of type: {}, length: {}, sequence: {}", type, length, currentPkt, maxPkt);
this.type = type;
this.length = length;
this.curPkt = currentPkt;
this.maxPkt = maxPkt;
if(type == DataType.DATA.getValue()) {
realLength = length;
data = new byte[length - HEADER_LENGTH];
} else {
realLength = HEADER_LENGTH * 2;
data = new byte[HEADER_LENGTH * 2];
}
//random.nextBytes(data);
}
/**
* Assemble datagram from payload
* @param payload
*/
public Datagram(byte[] payload) throws IOException {
log.debug("Datagram() magic ID is: {} bytes long and contains: {}", MAGIC_ID.length, MAGIC_ID.toString());
ByteBuffer buffer = ByteBuffer.wrap(payload);
byte[] id = new byte[8];
buffer.get(id);
if(!Arrays.equals(id, MAGIC_ID)) {
log.warn("Datagram() - magic ID does not match!");
throw new IOException();
}
// Order is importent when assembling header fields like this
type = buffer.getInt();
length = buffer.getInt();
curPkt = buffer.getLong();
maxPkt = buffer.getLong();
realLength = length;
if(type == DataType.DATA.getValue()) {
data = new byte[length - HEADER_LENGTH];
buffer.get(data, 0, data.length);
} else {
data = new byte[HEADER_LENGTH * 2];
}
}
public int getLength() {
return length;
}
public int getRealLength() {
return realLength;
}
public byte[] getPayload() throws IOException {
log.debug("getPayload() - with type: {}, length: {}, sequence: {}", type, length, curPkt);
ByteBuffer buffer = ByteBuffer.allocate(data.length + HEADER_LENGTH);
// Order is important
buffer.put(MAGIC_ID);
buffer.putInt(type);
buffer.putInt(length);
buffer.putLong(curPkt);
buffer.putLong(maxPkt);
buffer.put(data);
return buffer.array();
}
public int getType() {
return type;
}
public long getCurPkt() {
return curPkt;
}
public long getMaxPkt() {
return maxPkt;
}
}