#ifndef NETWORK_PACKET_HH
#define NETWORK_PACKET_HH
#include "Config.hh"
#include "../Vector.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 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;
/**
* Convenience function to read() and return the value of the given type
*
* @return T The value
*/
template <typename T> T read_val (void);
/**
* @defgroup read_* Read methods
* 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);
};
/**
* Write-interface for network packets
*/
class NetworkPacketOutput {
public:
/**
* 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);
/**
* @defgroup write* Write methods
* 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);
};
/**
* 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 buffer size, the amount of data in the buffer, and the current read/write offset
/**
* 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);
/**
* 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);
/*
* 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; }
/**
* 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 */