Subversion Repositories programming

Rev

Rev 218 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*******************************************************************************
 * File: P2_Packet.java
 * Author: Ira W. Snyder (devel@irasnyder.com)
 * License: GNU General Public License v2
 * Class: CS380 - Computer Networking
 *
 * Assignment: Project #2
 * Date Last Modified: 2006-02-06
 *
 * Purpose: Create and Decode packets for the P2_Server and P2_Client.
 * ****************************************************************************/

class P2_Packet
{
    private static final byte packetBegin = (byte)0xaa; // 0b10101010
    private static final byte packetEnd   = (byte)0x55; // 0b01010101
    private byte packetType;
    private byte packetNumber;
    private byte packetDataSize;
    private byte[] packetData;
    private static byte lastPacketNum = -1;

    // Fake an enum
    public static final byte DROP = 0;
    public static final byte TRANSREQ = 1;
    public static final byte TRANSREPL = 2;
    public static final byte QUIT = 3;
    public static final byte BADPACKET = 4;

    /**
     * Packet Format:
     * 1 byte: packetBegin
     * 1 byte: packetType
     * 1 byte: packetNumber
     * 1 byte: packetDataSize
     * packetDataSize bytes: data
     * 1 byte: packetEnd
     */

    /**
     * Method: P2_Packet constructor
     * Purpose: Construct a P2_Packet given the type and data
     */
    public P2_Packet (byte type, byte[] data)
    {
        byte[] p = P2_Packet.createPacket(type, data);
        P2_Packet pp = new P2_Packet (p);

        packetType = pp.packetType;
        packetNumber = pp.packetNumber;
        packetDataSize = pp.packetDataSize;
        packetData = pp.packetData;
    }

    /**
     * Method: P2_Packet constructor
     * Purpose: Construct a P2_Packet from a byte[].
     * Note: Checks to make sure the byte[] is a valid packet.
     */
    public P2_Packet (byte[] bytes)
    {
        int i;

        if (bytes.length < 5)
            throw new IllegalArgumentException(); // Definitely a bad packet

        if (bytes[0] != packetBegin)
            throw new IllegalArgumentException(); // Definitely a bad packet

        packetType     = bytes[1];
        packetNumber   = bytes[2];
        packetDataSize = bytes[3];
        packetData = new byte[packetDataSize];

        for (i=0; i<packetDataSize; i++)
            packetData[i] = bytes[i+4];

        if (bytes[i+4] != packetEnd)
            throw new IllegalArgumentException(); // Definitely a bad packet
    }

    /**
     * Method: createPacket()
     * Purpose: Create a packet suitable for transmission over the network,
     * using the current values of this class.
     */
    public byte[] createPacket ()
    {
        return P2_Packet.createPacket (packetType, packetData);
    }

    /**
     * Method: createPacket()
     * Purpose: Create a packet suitable for sending over the network,
     * using the parameters passed in.
     * NOTE: Automatically sets the packetNumber.
     */
    public static byte[] createPacket (byte type, byte[] data)
    {
        int i;
        byte[] packet = new byte[data.length+5];

        packet[0] = packetBegin;
        packet[1] = type;
        packet[2] = ++lastPacketNum;
        packet[3] = (byte)data.length;

        for (i=0; i<data.length; i++)
            packet[i+4] = data[i];

        packet[i+4] = packetEnd;

        return packet;
    }

    /**
     * Method: createPacket()
     * Purpose: Create a packet suitable for transmission over the network,
     * using the parameters passed in.
     */
    public static byte[] createPacket (byte type, byte[] data, int packetNum)
    {
        int i;
        byte[] packet = new byte[data.length+5];

        packet[0] = packetBegin;
        packet[1] = type;
        packet[2] = (byte)packetNum;
        packet[3] = (byte)data.length;

        for (i=0; i<data.length; i++)
            packet[i+4] = data[i];

        packet[i+4] = packetEnd;

        return packet;
    }
    
    /**
     * Method: toString()
     * Purpose: Convert a P2_Packet into a string for printing by a
     * PrintStream object.
     */
    public String toString ()
    {
        int i;
        String s;

        s = new String (    "packetBegin: " + packetBegin + "\n");
        s = new String (s + "packetType: " + packetType + "\n");
        s = new String (s + "packetNumber: " + packetNumber + "\n");
        s = new String (s + "packetDataSize: " + packetDataSize + "\n");
        s = new String (s + "packetData: ");

        for (i=0; i<packetDataSize; i++)
            s = new String (s + packetData[i]+ " ");

        s = new String (s + "\n");
        s = new String (s + "packetEnd: " + packetEnd);

        return s;
    }

    /**
     * Method: getPacketType()
     * Purpose: Getter method. Allow access to a private field.
     */
    public byte getPacketType () { return packetType; }

    /**
     * Method: getPacketNumber()
     * Purpose: Getter method. Allow access to a private field.
     */
    public byte getPacketNumber () { return packetNumber; }

    /**
     * Method: getPacketDataSize()
     * Purpose: Getter method. Allow access to a private field.
     */
    public byte getPacketDataSize () { return packetDataSize; }

    /**
     * Method: getPacketData()
     * Purpose: Getter method. Allow access to a private field.
     */
    public byte[] getPacketData () { return packetData; }
}