package net.johnewart.gearman.common.packets;
import com.google.common.primitives.Ints;
import net.johnewart.gearman.constants.PacketType;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
public abstract class Packet {
protected PacketType type;
protected int size;
protected byte[] rawdata;
private byte[] header;
public Packet() {
header = null;
}
public Packet(byte[] fromdata)
{
byte[] typebytes = Arrays.copyOfRange(fromdata, 4, 8);
byte[] sizebytes = Arrays.copyOfRange(fromdata, 8, 12);
this.type = PacketType.fromPacketMagicNumber(Ints.fromByteArray(typebytes));
this.size = Ints.fromByteArray(sizebytes);
this.rawdata = Arrays.copyOfRange(fromdata, 12, fromdata.length);
}
public byte[] getHeader()
{
if (header == null)
{
byte[] typebytes = Ints.toByteArray(this.type.getIndex());
byte[] sizebytes = Ints.toByteArray(this.getPayloadSize());
header = concatByteArrays(getMagic(), typebytes, sizebytes);
}
return header.clone();
}
public PacketType getType()
{
return type;
}
public abstract byte[] toByteArray();
public abstract int getPayloadSize();
public abstract byte[] getMagic();
public int getSize()
{
return 12 + this.getPayloadSize();
}
public String toString()
{
//return String.Format("{0} packet. Data: {1} bytes", type.ToString("g"), rawdata.Length);
return this.type.toString();
}
protected int parseString(int offset, AtomicReference<String> storage)
{
int pStart;
int pOff;
pOff = pStart = offset;
for(; pOff < rawdata.length && rawdata[pOff] != 0; pOff++);
storage.set(new String(Arrays.copyOfRange(rawdata, pStart, pOff)));
// Return 1 past where we are...
return pOff + 1;
}
protected byte[] stringsToTerminatedByteArray(String first, String ... rest)
{
return stringsToTerminatedByteArray(true, first, rest);
}
protected byte[] stringsToTerminatedByteArray(boolean terminateFinal, String first, String... rest)
{
StringBuffer fullString = new StringBuffer();
fullString.append(first);
fullString.append('\000');
for(int i = 0; i < rest.length; i++)
{
String member = rest[i];
fullString.append(member);
// If we don't want to terminate the last one, then skip
// For packets where we don't have any data, we need to
// not have a null byte at the end. (i.e STATUS_RES)
if(terminateFinal == true || i < rest.length - 1)
fullString.append('\000');
}
return fullString.toString().getBytes();
}
protected byte[] concatByteArrays(byte[] first, byte[]... rest) {
int totalLength = first.length;
for (byte[] array : rest) {
totalLength += array.length;
}
byte[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (byte[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
}