diff --git a/source/ps/Network/AllNetMessages.h b/source/ps/Network/AllNetMessages.h index 6504849245..7cf5a63083 100755 --- a/source/ps/Network/AllNetMessages.h +++ b/source/ps/Network/AllNetMessages.h @@ -2,6 +2,7 @@ #define _AllNetMessages_H #include "types.h" +#include "CStr.h" enum NetMessageType { @@ -40,11 +41,13 @@ enum NetMessageType START_NMTS() START_NMT_CLASS(AlohaMessage, NMT_Aloha) - NMT_FIELD_INT(m_AlohaCode, uint, 4) +// NMT_FIELD_INT(m_AlohaCode, u64, 8) + NMT_FIELD(CStr, m_AlohaCode) END_NMT_CLASS() START_NMT_CLASS(SayonaraMessage, NMT_Sayonara) - NMT_FIELD_INT(m_SayonaraCode, uint, 4) +// NMT_FIELD_INT(m_SayonaraCode, u64, 8) + NMT_FIELD(CStr, m_SayonaraCode) END_NMT_CLASS() END_NMTS() diff --git a/source/ps/Network/NMTCreator.h b/source/ps/Network/NMTCreator.h index 8326f569f3..0544cd59b4 100755 --- a/source/ps/Network/NMTCreator.h +++ b/source/ps/Network/NMTCreator.h @@ -9,6 +9,7 @@ #undef END_NMTS #undef START_NMT_CLASS #undef NMT_FIELD_INT +#undef NMT_FIELD #undef END_NMT_CLASS #else @@ -23,17 +24,45 @@ #define START_NMTS() #define END_NMTS() +/** + * Start the definition of a network message type. + * + * @param _nm The name of the class + * @param _tp The NetMessageType associated with the class. IT is *not* safe to + * have several classes with the same value of _tp in the same executable + */ #define START_NMT_CLASS(_nm, _tp) \ -CNetMessage *Deserialize##_nm(u8 *, uint); \ +CNetMessage *Deserialize##_nm(const u8 *, uint); \ struct _nm: public CNetMessage \ { \ _nm(): CNetMessage(_tp) {} \ virtual uint GetSerializedLength() const; \ virtual void Serialize(u8 *buffer) const; +/** + * Add an integer field to the message type. + * + * @param _nm The name of the field + * @param _hosttp The local type of the field (the data type used in the field + * definition) + * @param _netsz The number of bytes that should be serialized. If the variable + * has a value larger than the maximum value of the specified network size, + * higher order bytes will be discarded. + */ #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \ _hosttp _nm; +/** + * Add a generic field to the message type. The data type must be a class + * implementing the ISerializable interface + * + * @param _tp The local data type of the field + * @param _nm The name of the field + * @see ISerializable + */ +#define NMT_FIELD(_tp, _nm) \ + _tp _nm; + #define END_NMT_CLASS() }; #include "NMTCreator.h" @@ -53,6 +82,9 @@ uint _nm::GetSerializedLength() const \ #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \ ret += _netsz; +#define NMT_FIELD(_tp, _nm) \ + ret += _nm.GetSerializedLength(); + #define END_NMT_CLASS() \ return ret; \ }; @@ -67,11 +99,14 @@ uint _nm::GetSerializedLength() const \ #define START_NMT_CLASS(_nm, _tp) \ void _nm::Serialize(u8 *buffer) const \ { \ - printf("In " #_nm "::Serialize()\n"); \ + /*printf("In " #_nm "::Serialize()\n");*/ \ u8 *pos=buffer; \ #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \ - pos=SerializeInt<_hosttp, _netsz>(pos, _nm); \ + Serialize_int_##_netsz(pos, _nm); \ + +#define NMT_FIELD(_tp, _nm) \ + pos=_nm.Serialize(pos); #define END_NMT_CLASS() } @@ -82,17 +117,23 @@ void _nm::Serialize(u8 *buffer) const \ #define START_NMTS() #define END_NMTS() +#define BAIL_DESERIALIZER STMT( delete ret; return NULL; ) + #define START_NMT_CLASS(_nm, _tp) \ -CNetMessage *Deserialize##_nm(u8 *buffer, uint length) \ +CNetMessage *Deserialize##_nm(const u8 *buffer, uint length) \ { \ - printf("In Deserialize" #_nm "\n"); \ + /*printf("In Deserialize" #_nm "\n"); */\ _nm *ret=new _nm(); \ - u8 *pos=buffer; \ - u8 *end=buffer+length; \ + const u8 *pos=buffer; \ + const u8 *end=buffer+length; \ #define NMT_FIELD_INT(_nm, _hosttp, _netsz) \ - ret->_nm=DeserializeInt<_hosttp, _netsz>(&pos); \ - printf("\t" #_nm " == 0x%x\n", ret->_nm); + if (pos+_netsz >= end) BAIL_DESERIALIZER; \ + Deserialize_int_##_netsz(pos, (ret->_nm)); \ + /*printf("\t" #_nm " == 0x%x\n", ret->_nm);*/ + +#define NMT_FIELD(_tp, _nm) \ + if ((pos=ret->_nm.Deserialize(pos, end)) == NULL) BAIL_DESERIALIZER; #define END_NMT_CLASS() \ return ret; \ @@ -100,6 +141,8 @@ CNetMessage *Deserialize##_nm(u8 *buffer, uint length) \ #include "NMTCreator.h" +#undef BAIL_DESERIALIZER + /*************************************************************************/ // Pass 5, Deserializer Registration #define START_NMTS() SNetMessageDeserializerRegistration g_DeserializerRegistrations[] = { @@ -110,6 +153,8 @@ CNetMessage *Deserialize##_nm(u8 *buffer, uint length) \ #define NMT_FIELD_INT(_nm, _hosttp, _netsz) +#define NMT_FIELD(_tp, _nm) + #define END_NMT_CLASS() #include "NMTCreator.h" diff --git a/source/ps/Network/NetMessage.h b/source/ps/Network/NetMessage.h index db09ff57cc..37802164b0 100755 --- a/source/ps/Network/NetMessage.h +++ b/source/ps/Network/NetMessage.h @@ -14,21 +14,36 @@ protected: inline CNetMessage(NetMessageType type): m_Type(type) {} -public: - inline CNetMessage(): m_Type(NMT_NONE) - {} +public: inline NetMessageType GetType() const { return m_Type; } + /** + * @returns The length of the message when serialized. + */ virtual uint GetSerializedLength() const; + /** + * Serialize the message into the buffer. The buffer will have the size + * returned from the last call to GetSerializedLength() + */ virtual void Serialize(u8 *buffer) const; + /** + * Deserialize a net message, using the globally registered deserializers. + * + * @param type The NetMessageType of the message + * @param buffer A pointer to the buffer holding the message data + * @param length The length of the message data + * + * @returns a pointer to a newly created CNetMessage subclass, or NULL if + * there was an error in data format. + */ static CNetMessage *DeserializeMessage(NetMessageType type, u8 *buffer, uint length); }; class CNetMessage; -typedef CNetMessage * (*NetMessageDeserializer) (u8 *buffer, uint length); +typedef CNetMessage * (*NetMessageDeserializer) (const u8 *buffer, uint length); struct SNetMessageDeserializerRegistration { diff --git a/source/ps/Network/Serialization.h b/source/ps/Network/Serialization.h index e4dad6cb2b..d49582bdbc 100755 --- a/source/ps/Network/Serialization.h +++ b/source/ps/Network/Serialization.h @@ -2,29 +2,94 @@ #define _Serialization_H #include "types.h" +#include "misc.h" -template -inline u8 *SerializeInt(u8 *pos, _T val) -{ - for (int i=0;i>= 8; - } - return pos; -} +#define Serialize_int_1(_pos, _val) \ + STMT( *((_pos)++) = _val&0xff; ) -template -inline _T DeserializeInt(u8 **pos) +#define Serialize_int_2(_pos, _val) STMT(\ + Serialize_int_1(_pos, _val>>8); \ + Serialize_int_1(_pos, _val); \ +) + +#define Serialize_int_3(_pos, _val) STMT(\ + Serialize_int_1(_pos, _val>>16); \ + Serialize_int_2(_pos, _val); \ +) + +#define Serialize_int_4(_pos, _val) STMT(\ + Serialize_int_1(_pos, _val>>24); \ + Serialize_int_3(_pos, _val); \ +) + +#define Serialize_int_8(_pos, _val) STMT(\ + Serialize_int_4(_pos, _val>>32); \ + Serialize_int_4(_pos, _val); \ +) + +#define Deserialize_int_1(_pos, _val) STMT(\ + (_val) -= (_val) & 0xff; \ + (_val) += *((_pos)++); ) + +#define Deserialize_int_2(_pos, _val) STMT(\ + Deserialize_int_1(_pos, _val); \ + _val <<= 8; \ + Deserialize_int_1(_pos, _val); ) + +#define Deserialize_int_3(_pos, _val) STMT(\ + Deserialize_int_2(_pos, _val); \ + _val <<= 8; \ + Deserialize_int_1(_pos, _val); ) + +#define Deserialize_int_4(_pos, _val) STMT(\ + Deserialize_int_3(_pos, _val); \ + _val <<= 8; \ + Deserialize_int_1(_pos, _val); ) + +#define Deserialize_int_8(_pos, _val) STMT(\ + Deserialize_int_4(_pos, _val); \ + _val <<= 8; \ + Deserialize_int_4(_pos, _val); ) + +/*#define Serialize_CStr(_pos, _str) STMT( \ + uint len=_str.Length(); \ + Serialize_int_4(_pos, len); \ + memcpy(_pos, _str, len+1); _pos += len+1; ) + +#define Deserialize_CStr(_pos, _str) STMT( \ + uint len; Deserialize_int_4(_pos, len); \ + _str=CStr((char *)_pos); _pos += len+1; )*/ + +/** + * An interface for serializable objects. For a serializable object to be usable + * as a network message field, it must have a constructor without arguments. + */ +class ISerializable { - _T val=0; - uint i=netsize; - while (i--) - { - val = (val << 8) + (*pos)[i]; - } - (*pos) += netsize; - return val; -} +public: + /** + * Return the length of the serialized form of this object + */ + virtual uint GetSerializedLength() const = 0; + /** + * Serialize the object into the passed buffer. + * + * @return a pointer to the location in the buffer right after the + * serialized object + */ + virtual u8 *Serialize(u8 *buffer) const = 0; + /** + * Deserialize the object (i.e. read in data from the buffer and initialize + * the object's fields). Note that it is up to the deserializer to detect + * errors in data format. + * + * @param buffer A pointer pointing to the start of the serialized data. + * @param end A pointer to the end of the message. + * + * @returns a pointer to the location in the buffer right after the + * serialized object, or NULL if there was a data format error + */ + virtual const u8 *Deserialize(const u8 *buffer, const u8 *end) = 0; +}; #endif