Java tutorial
/******************************************************************************* * Copyright (c) 2007, 2014 Massimiliano Ziccardi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package it.jnrpe.net; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Random; import java.util.zip.CRC32; import org.apache.commons.lang.ArrayUtils; /** * This class represent a generic NRPE protocol packet. * * @author Massimiliano Ziccardi * @version $Revision: 1.0 $ */ class JNRPEProtocolPacket { /** * Max amount of data we'll send in one query/response. */ private static final int MAX_PACKETBUFFER_LENGTH = 1024; // FIXME : charset from configuration... /** * The charset. */ private Charset charset = Charset.defaultCharset(); /** * The CRC value. */ private int crcValue; /** * The packet type. */ private int packetTypeCode; /** * The packet version. */ private int packetVersion; /** * The result code. */ private int resultCode; /** * The packet buffer. */ private byte[] byteBufferAry = new byte[MAX_PACKETBUFFER_LENGTH]; /** * Dummy bytes. */ private final byte[] dummyBytesAry = new byte[2]; /** * Returns the packet CRC value. * * @return the CRC value */ int getCRC() { return crcValue; } /** * Returns the packet type. * * @return The packet type */ PacketType getPacketType() { return PacketType.fromIntValue(packetTypeCode); } /** * Returns the packet version. * * @return The packet version */ public PacketVersion getPacketVersion() { return PacketVersion.fromIntValue(packetVersion); } /** * Sets the CRC value. * * @param crc * The new CRC value */ void setCRC(final int crc) { crcValue = crc; } /** * Sets the packet type. * * @param packetType * The new packet type */ protected void setPacketType(final PacketType packetType) { packetTypeCode = packetType.intValue(); } /** * Sets the packet version. * * @param version * The packet version */ public void setPacketVersion(final PacketVersion version) { packetVersion = version.intValue(); } /** * Changes the default charset. * * @param newCharset * the new charset, */ public void setCharset(final Charset newCharset) { charset = newCharset; } /** * Returns the result code. * * @return The result code */ public int getResultCode() { return resultCode; } /** * Sets the result code. * * @param status * The new result code */ public void setResultCode(final int status) { resultCode = status; } /** * Validates the packet CRC. * * @throws BadCRCException * If the CRC can't be validated */ public void validate() throws BadCRCException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); try { dout.writeShort(packetVersion); dout.writeShort(packetTypeCode); dout.writeInt(0); // NO CRC dout.writeShort(resultCode); dout.write(byteBufferAry); dout.write(dummyBytesAry); dout.close(); byte[] vBytes = bout.toByteArray(); CRC32 crcAlg = new CRC32(); crcAlg.update(vBytes); if (!(((int) crcAlg.getValue()) == crcValue)) { throw new BadCRCException("Bad CRC"); } } catch (IOException e) { // Never happens... throw new IllegalStateException(e.getMessage(), e); } } /** * @return the received raw data buffer */ protected byte[] getBuffer() { return byteBufferAry; } /** * @return The string representation of the buffer. */ protected String getPacketString() { byte[] buffer = getBuffer(); int zeroIndex = ArrayUtils.indexOf(buffer, (byte) 0); if (zeroIndex == ArrayUtils.INDEX_NOT_FOUND) { return new String(buffer, charset); } else { return new String(buffer, 0, zeroIndex, charset); } } /** * Initializes the arrays with random data. Not sure it is really needed... */ private void initRandomBuffer() { Random rnd = new Random(System.currentTimeMillis()); rnd.nextBytes(byteBufferAry); rnd.nextBytes(dummyBytesAry); } /** * Sets the value of the data buffer. * * @param buffer the buffer value */ protected void setBuffer(final String buffer) { initRandomBuffer(); byteBufferAry = Arrays.copyOf(buffer.getBytes(charset), MAX_PACKETBUFFER_LENGTH); } /** * Sets the dummy buffer value. * * @param dummyBytes the new value */ void setDummy(final byte[] dummyBytes) { if (dummyBytes == null || dummyBytes.length != 2) { int currentSize; if (dummyBytes == null) { currentSize = 0; } else { currentSize = dummyBytes.length; } throw new IllegalArgumentException( "Dummy bytes array must have exactly two elements. Current size is : " + currentSize); } System.arraycopy(dummyBytes, 0, dummyBytesAry, 0, 2); } /** * @return the dummy buffer value. */ byte[] getDummy() { return dummyBytesAry; } /** * Updates the CRC value. */ void updateCRC() { setCRC(0); CRC32 crcAlg = new CRC32(); crcAlg.update(toByteArray()); setCRC((int) crcAlg.getValue()); } /** * Converts the packet object to its byte array representation. * * @return The byte array representation of this packet. */ public byte[] toByteArray() { ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); try { dout.writeShort(packetVersion); dout.writeShort(packetTypeCode); dout.writeInt(crcValue); dout.writeShort(resultCode); dout.write(byteBufferAry); dout.write(dummyBytesAry); dout.close(); } catch (IOException e) { // Never happens... throw new IllegalStateException(e.getMessage(), e); } return bout.toByteArray(); } /** * Loads the packet from the given input stream. * * @param in the packet input stream * @throws IOException on any error */ protected void fromInputStream(final InputStream in) throws IOException { DataInputStream din = new DataInputStream(in); packetVersion = din.readShort(); packetTypeCode = din.readShort(); crcValue = din.readInt(); resultCode = din.readShort(); din.readFully(byteBufferAry); din.readFully(dummyBytesAry); } /** * Method toString. * @return String */ @Override public String toString() { return "JNRPEProtocolPacket [charset=" + charset + ", crcValue=" + crcValue + ", packetTypeCode=" + packetTypeCode + ", packetVersion=" + packetVersion + ", resultCode=" + resultCode + ", byteBufferAry=" + Arrays.toString(byteBufferAry) + ", dummyBytesAry=" + Arrays.toString(dummyBytesAry) + "]"; } }