src/Network/Packet.hh
author terom
Mon, 08 Dec 2008 01:12:00 +0000
changeset 277 40f4a03917e2
parent 203 3ec7ab40755f
child 284 27ce69fd1e06
permissions -rw-r--r--
fix NetworkClient handleInput
#ifndef NETWORK_PACKET_HH
#define NETWORK_PACKET_HH

#include "Config.hh"
#include "../Vector.hh"
#include "../Error.hh"

class NetworkPacketError : public Error {
    public:
        NetworkPacketError (const std::string &message) : Error(message) { }
};

// forward-declare for write_packet
class NetworkPacketBuffer;

/*
 * Read-interface for network packets
 */
class NetworkPacketInput {
    public:
        /*
         * Copies len bytes from the packet to ptr, first testing that they exist
         */
        virtual void read (void *ptr, size_t len) = 0;
       
        /*
         * Convenience function to read() and return the value of the given type
         */
        template <typename T> T read_val (void);

        // thse handle network-endianlness
        uint32_t read_uint32 (void);
        uint16_t read_uint16 (void);
        uint8_t read_uint8 (void);

        int32_t read_int32 (void);
        int16_t read_int16 (void);
        int8_t read_int8 (void);
        
        float read_float32 (void);
        
        Vector read_vector (void);
};

/*
 * Write-interface for network packets
 */
class NetworkPacketOutput {
    public:    
        /*
         * Copies len bytes from ptr to the packet, first testing that they fit
         */
        virtual void write (const void *ptr, size_t len) = 0;

        /*
         * Convenience function to write() the value of the given type-value
         */
        template <typename T> void write_val (const T &val);

        // thse handle network-endianlness
        void write_uint32 (uint32_t val);
        void write_uint16 (uint16_t val);
        void write_uint8 (uint8_t val);

        void write_int32 (int32_t val);
        void write_int16 (int16_t val);
        void write_int8 (int8_t val);
        
        void write_float32 (float val);

        void write_vector (const Vector &vec);
        
        /*
         * This copies the contents of the given packet into this packet
         */
        void write_packet (const NetworkPacketBuffer &pkt);
};

/*
 * Implements the in-memory seekable buffer used by NetworkPackets.
 */
class NetworkPacketBuffer : public NetworkPacketInput, public NetworkPacketOutput {
    protected:
        // the pointer to the buffer
        char *buf_ptr;
        
        // the buffer size, the amount of data in the buffer, and the current read/write offset
        size_t buf_size, data_size, offset;
        
        /*
         * Assert that the given number of bytes fits into the buffer. Throws NetworkPacketError if not.
         *
         * The default implementation just checks offset and buf_size
         */
        virtual void check_write_size (size_t item_size);

        /*
         * Assert that the give number of bytes is available from the buffer. Throws NetworkPacketError if not
         *
         * The default implementation just checks offset and data_size
         */
        virtual void check_read_size (size_t item_size);
         
    public:
        /*
         * Construct the NetworkPacketBuffer using the given initial buf_ptr and buf_size
         */
        NetworkPacketBuffer (char *buf_ptr, size_t buf_size, size_t data_size);
        
        /*
         * These memcpy() into/out of the buf_ptr, using ceck_read/write_size
         */
        virtual void read (void *ptr, size_t len);
        virtual void write (const void *ptr, size_t len);

        /*
         * Accessor functions, used by the actual socket code to read/write the buffer
         */
        char* get_buf (void) { return buf_ptr; }
        const char* get_buf (void) const { return buf_ptr; }
        size_t get_data_size (void) const { return data_size; }
        size_t get_buf_size (void) const { return buf_size; }
        
        /*
         * Used by the socket code after recv() to mark how many bytes of data the buffer has
         */
        void set_data_size (size_t size) { offset = 0; data_size = size; }
};

/*
 * The common case is a packet that fits in a single UDP packet, so this just uses a static buffer of a fixed size,
 * NETWORK_PACKET_SIZE.
 */
class NetworkPacket : public NetworkPacketBuffer {
    private:
        char _buf[NETWORK_PACKET_SIZE];

    public:
        NetworkPacket (void);
};

/*
 * This is intended for sending bigger packets via TCP; the buffer is allocated on the heap.
 *
 * XXX: let the buffer grow as well
 */
class BigNetworkPacket : public NetworkPacketBuffer {
    public:
        BigNetworkPacket (size_t size);

    private:
        // no copies
        BigNetworkPacket (const BigNetworkPacket &pkt);
        BigNetworkPacket& operator= (const BigNetworkPacket &pkt);

    public:
        virtual ~BigNetworkPacket (void);
};

#endif /* NETWORK_PACKET_HH */