package com.intrbiz.bergamot.nrpe.model;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import com.intrbiz.bergamot.nrpe.util.CRC32;
/**
* A packet in the NRPE protocol
*/
public class NRPEPacket
{
public static final int PACKET_LENGTH = 1036;
public static final byte NULL = (byte) 0;
public static final String NRPE_HELLO = "_NRPE_CHECK";
private PacketVersion version = PacketVersion.NRPE_2;
private PacketType type = PacketType.QUERY;
private short responseCode = 0;
private String message;
private double runtime;
public NRPEPacket()
{
super();
}
public PacketVersion getVersion()
{
return version;
}
public void setVersion(PacketVersion version)
{
this.version = version;
}
public NRPEPacket version(PacketVersion version)
{
this.version = version;
return this;
}
public NRPEPacket version2()
{
this.version = PacketVersion.NRPE_2;
return this;
}
public PacketType getType()
{
return type;
}
public void setType(PacketType type)
{
this.type = type;
}
public NRPEPacket type(PacketType type)
{
this.type = type;
return this;
}
public NRPEPacket query()
{
this.type = PacketType.QUERY;
return this;
}
public NRPEPacket response()
{
this.type = PacketType.RESPONSE;
return this;
}
public NRPEPacket response(short responseCode)
{
this.type = PacketType.RESPONSE;
this.responseCode = responseCode;
return this;
}
public short getResponseCode()
{
return responseCode;
}
public void setResponseCode(short responseCode)
{
this.responseCode = responseCode;
}
public NRPEPacket responseCode(short responseCode)
{
this.type = PacketType.RESPONSE;
this.responseCode = responseCode;
return this;
}
public String getMessage()
{
return message;
}
public String getOutput()
{
return this.message;
}
public String getCommand()
{
return this.message;
}
public void setMessage(String message)
{
this.message = message;
}
public NRPEPacket message(String message)
{
this.message = message;
return this;
}
public NRPEPacket command(String command)
{
this.type = PacketType.QUERY;
this.message = command;
return this;
}
public NRPEPacket command(String command, String... args)
{
this.type = PacketType.QUERY;
StringBuilder sb = new StringBuilder(command);
if (args != null)
{
for (String arg : args)
{
sb.append("!").append(arg);
}
}
this.message = sb.toString();
return this;
}
public NRPEPacket command(String command, List<String> args)
{
this.type = PacketType.QUERY;
StringBuilder sb = new StringBuilder(command);
if (args != null)
{
for (String arg : args)
{
sb.append("!").append(arg);
}
}
this.message = sb.toString();
return this;
}
public NRPEPacket hello()
{
this.type = PacketType.QUERY;
this.message = NRPE_HELLO;
return this;
}
public double getRuntime()
{
return runtime;
}
public void setRuntime(double runtime)
{
this.runtime = runtime;
}
/**
* Encode this packet to its binary form
* @return
*/
public byte[] encodePacket()
{
byte[] buffer = new byte[PACKET_LENGTH];
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
// put the version
byteBuffer.putShort(this.version.getValue());
// put the type
byteBuffer.putShort(this.type.getValue());
// skip the crc
byteBuffer.putInt(0);
// put the response code
byteBuffer.putShort(this.responseCode);
// write message
byteBuffer.put(this.message.getBytes());
// ensure null terminated
byteBuffer.put(NULL);
// compute the crc
int crc = CRC32.computeCRC32(buffer);
// set the crc
byteBuffer.position(4);
byteBuffer.putInt(crc);
return buffer;
}
/**
* Decode this packet from its binary form
* @param buffer
* @param offset
* @param length
* @throws IOException if the CRC is invalid
*/
public void decodePacket(byte[] buffer, int offset, int length) throws IOException
{
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, offset, length);
// get the version
this.version = PacketVersion.valueOf(byteBuffer.getShort());
// get the type
this.type = PacketType.valueOf(byteBuffer.getShort());
// get the crc
int crc = byteBuffer.getInt();
// get the response code
this.responseCode = byteBuffer.getShort();
// get the output
// how much I loath C string :(
int strLen = 0;
while (byteBuffer.hasRemaining() && byteBuffer.get() != NULL)
{
strLen++;
}
this.message = new String(buffer, offset + 10, strLen);
// validate the CRC
byteBuffer.position(4);
byteBuffer.putInt(0);
int expectedCrc = CRC32.computeCRC32(buffer, offset, length);
if (expectedCrc != crc) throw new IOException("Invalid CRC checksum on NRPE Packet");
}
public static NRPEPacket parse(byte[] buffer) throws IOException
{
return parse(buffer, 0, buffer.length);
}
public static NRPEPacket parse(byte[] buffer, int offset, int length) throws IOException
{
NRPEPacket packet = new NRPEPacket();
packet.decodePacket(buffer, offset, length);
return packet;
}
}