support for building without Network/Graphics, although the disable-graphics case is kind of hackish still
#ifndef NETWORK_PACKET_HH
#define NETWORK_PACKET_HH
/**
* @file
*
* Provides the NetworkPackets that are used to communicate over a NetworkTCP/NetworkUDP sockets.
*/
#include "../Config.hh"
#include "../Types.hh"
#include "../Error.hh"
/**
* Base class of errors thrown by NetworkPacket* methods
*/
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:
/**
* Abstract method to get a pointer to \a len bytes of raw in-memory binary data, advancing the read offset
*
* @param len the number of bytes to consume
*/
virtual const void* read_ptr (size_t len) = 0;
/**
* Abstract method that copies len bytes from the packet to ptr, first testing that they exist
*/
virtual void read (
void *ptr, //<<< where to copy
size_t len //<<< number of bytes to copy
) = 0;
/**
* Abstract method to get the number of input bytes remaining.
*
* @return number of input bytes still readable
*/
virtual size_t tell_remaining (void) = 0;
/**
* Convenience function to read() and return the value of the given type
*
* @return T The value
*/
template <typename T> T read_val (void);
// @{
/**
* Collection of methods to write out simple types, these convert from network-endianness and return the value
*/
/** 32-bit unsigned int */
uint32_t read_uint32 (void);
/** 16-bit unsigned int */
uint16_t read_uint16 (void);
/** 8-bit unsigned int */
uint8_t read_uint8 (void);
/** 32-bit signed int */
int32_t read_int32 (void);
/** 16-bit signed int */
int16_t read_int16 (void);
/** 8-bit signed int */
int8_t read_int8 (void);
/** 32-bit float */
float read_float32 (void);
// @}
/**
* Read a Vector from the packet:
* float32 vec_x
* float32 vec_y
*
* @return Vector (vec_x, vec_y)
*/
Vector read_vector (void);
/**
* Read compressed data written with write_compressed. The given buffer must be the same size as passed to
* write_compressed. Returns the number of bytes that were decompressed into buf.
*/
size_t read_uncompressed (void *buf, size_t len);
};
/**
* Write-interface for network packets
*/
class NetworkPacketOutput {
protected:
/**
* Adjust size of the most recent write_ptr area of buf_len bytes to data_len bytes.
*
* You must not call write() between calls to write_ptr() and write_ptr_adjust(). This is only valid for the
* most recent write_ptr()
*/
virtual void write_ptr_adjust (size_t buf_len, size_t data_len) = 0;
public:
/**
* Abstract method to get a pointer to \a len bytes of raw in-memory binary data, advancing the write offset
*
* @param len number of bytes to commit
*/
virtual void* write_ptr (size_t len) = 0;
/**
* Abstract method that copies len bytes from ptr to the packet, first testing that they fit
*/
virtual void write (
const void *ptr, //<<< where to copy from
size_t len //<<< number of bytes to copy
) = 0;
/**
* Convenience function to write() the value of the given type-value
*
* @param val The value
*/
template <typename T> void write_val (const T &val);
// @{
/**
* Collection of methods to write out simple types, these convert the given value to network-byte-order
*/
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);
// @{
/**
* Write a vector to the packet:
* float32 vec_x
* float32 vec_y
*
* @param vec a Vector(vec_x, vec_y)
*/
void write_vector (const Vector &vec);
/**
* This write()s the contents of the given NetworkPacketBuffer to this packet.
*
* @param pkt the sub-packet to write()
*/
void write_packet (const NetworkPacketBuffer &pkt);
/**
* This will compress the given data buffer into this packet for reading with read_compressed. The compressed
* data will use at most write_compressed_size(len) bytes of data.
*/
void write_compressed (const void *ptr, uint32_t len);
/**
* Return upper bound on packet size of compressed data, including header.
*/
static size_t write_compressed_size (uint32_t len);
};
/**
* Implements an in-memory seekable buffer used by NetworkPackets
*
* @see NetworkPacketInput
* @see NetworkPacketOutput
*/
class NetworkPacketBuffer : public NetworkPacketInput, public NetworkPacketOutput {
protected:
/**
* Pointer to the packet data
*/
char *buf_ptr;
/**
* The size of the memory region pointed to by buf_ptr
*/
size_t buf_size;
/**
* The number of bytes of read()-able data stored at buf_ptr
*/
size_t data_size;
/**
* The current offset at which to run the next read/write
*/
size_t offset;
/**
* Assert that the given number of bytes fits into the buffer at offset. Throws NetworkPacketError if not.
*
* The default implementation just checks offset and buf_size
*
* @param item_size the size of the item that should to be written
*/
virtual void check_write_size (size_t item_size);
/**
* Assert that the given number of bytes is available from the buffer. Throws NetworkPacketError if not
*
* The default implementation just checks offset and data_size
*
* @param item_size the size of the item that should be read
*/
virtual void check_read_size (size_t item_size);
public:
/**
* Construct the NetworkPacketBuffer using the given buf_ptr, buf_size and data_size
*/
NetworkPacketBuffer (char *buf_ptr, size_t buf_size, size_t data_size);
/**
* Returns a read-only pointer to \a len bytes of internal buffer memory, calling check_read_size first and
* updating offset
*
* @param len number of bytes from the buffer to consume
*/
virtual const void* read_ptr (size_t len);
/**
* Returns a read-write pointer to \a len bytes of internal buffer memory, calling check_write_size first and
* updating offset+data_size
*
* @param len number of bytes in the buffer to commit
*/
virtual void* write_ptr (size_t len);
/**
* Copy bytes from the packet buffer to ptr using memcpy(), calling check_read_size first.
*
* @param ptr where to copy the data to
* @param len number of bytes to copy
*/
virtual void read (void *ptr, size_t len);
/**
* Copy bytes from ptr to the packet buffer using memcpy(), calling check_write_size first
*
* @param ptr where to copy the data from
* @param len number of bytes to copy
*/
virtual void write (const void *ptr, size_t len);
virtual void write_ptr_adjust (size_t buf_len, size_t data_len);
/**
* Returns our data_size - read-offset
*/
virtual size_t tell_remaining (void);
/*
* Accessor functions, used by the actual socket code to read/write the buffer
*
* XXX: own abstract class for these? Virtual methods <3
*/
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; }
/**
* If the contents of buf_ptr is replaced with a new packet, call this to update offset/data_size
*
* @param size new amount of data in the buffer
*/
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.
*
* @see NetworkPacketBuffer
* @see NETWORK_PACKET_SIZE
*/
class NetworkPacket : public NetworkPacketBuffer {
private:
/**
* The static buffer, NETWORK_PACKET_SIZE bytes
*/
char _buf[NETWORK_PACKET_SIZE];
public:
NetworkPacket (void);
};
/**
* This is intended for sending bigger packets via TCP; a buffer of the given size is allocated on the heap.
*
* @see NetworkPacketBuffer
*/
class BigNetworkPacket : public NetworkPacketBuffer {
public:
/**
* Allocates a buffer of the given size on the heap and uses it for NetworkPacketBuffer
*/
BigNetworkPacket (size_t size);
private:
/**
* Object must not be copied
*/
BigNetworkPacket (const BigNetworkPacket &pkt);
BigNetworkPacket& operator= (const BigNetworkPacket &pkt);
public:
/**
* Frees the heap buffer
*/
virtual ~BigNetworkPacket (void);
};
#endif /* NETWORK_PACKET_HH */