diff --git a/src/include/net_message.h b/src/include/net_message.h index 85f7a66c7..b0cac354c 100644 --- a/src/include/net_message.h +++ b/src/include/net_message.h @@ -51,8 +51,9 @@ class CNetworkHost { public: - const unsigned char *Serialize() const; - void Deserialize(const unsigned char *p); + CNetworkHost() { Clear(); } + size_t Serialize(unsigned char *) const; + size_t Deserialize(const unsigned char *p); void Clear(); static size_t Size() { return 4 + 2 + 2 + NetPlayerNameSize; } @@ -64,15 +65,15 @@ public: char PlyName[NetPlayerNameSize]; /// Name of player }; - /** ** Multiplayer game setup menu state */ class CServerSetup { public: - const unsigned char *Serialize() const; - void Deserialize(const unsigned char *p); + CServerSetup() { Clear(); } + size_t Serialize(unsigned char *p) const; + size_t Deserialize(const unsigned char *p); static size_t Size() { return 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 * PlayerMax + 1 * PlayerMax + 1 * PlayerMax; } void Clear() { ResourcesOption = 0; @@ -111,7 +112,7 @@ enum _ic_message_subtype_ { ICMEngineMismatch, /// Stratagus engine version doesn't match ICMProtocolMismatch, /// Network protocol version doesn't match - ICMEngineConfMismatch, /// Engine configuration isn't identical + ICMEngineConfMismatch, /// UNUSED:Engine configuration isn't identical ICMMapUidMismatch, /// MAP UID doesn't match ICMGameFull, /// No player slots available @@ -132,36 +133,145 @@ enum _ic_message_subtype_ { ICMIAH /// Client answers I am here }; -/** -** Network init message. -** -** @todo Transfering the same data in each message is waste of bandwidth. -** I mean the versions and the UID ... -*/ -class CInitMessage +class CInitMessage_Header { public: - CInitMessage(); - CInitMessage(uint8_t type, uint8_t subtype); + CInitMessage_Header() {} + CInitMessage_Header(unsigned char type, unsigned char subtype) : + type(type), + subtype(subtype) + {} + + unsigned char GetType() const { return type; } + unsigned char GetSubType() const { return subtype; } + + size_t Serialize(unsigned char *p) const; + size_t Deserialize(const unsigned char *p); + static size_t Size() { return 2; } +private: + unsigned char type; + unsigned char subtype; +}; + +class CInitMessage_Hello +{ +public: + CInitMessage_Hello() {} + explicit CInitMessage_Hello(const char *name); + const CInitMessage_Header &GetHeader() const { return header; } const unsigned char *Serialize() const; void Deserialize(const unsigned char *p); - static size_t Size() { return 1 + 1 + 1 + 1 + 4 + 4 + 4 + 4 + 4 + 4 + std::max(256u, std::max(CNetworkHost::Size() * PlayerMax, CServerSetup::Size())); } - - uint8_t Type; /// Init message type - uint8_t SubType; /// Init message subtype - uint8_t HostsCount; /// Number of hosts - uint8_t padding; /// padding for alignment + static size_t Size() { return CInitMessage_Header::Size() + NetPlayerNameSize + 2 * 4; } +private: + CInitMessage_Header header; +public: + char PlyName[NetPlayerNameSize]; /// Name of player int32_t Stratagus; /// Stratagus engine version int32_t Version; /// Network protocol version - uint32_t MapUID; /// UID of map to play. FIXME: add MAP name, path, etc +}; + +class CInitMessage_Config +{ +public: + CInitMessage_Config(); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + 4 + PlayerMax * CNetworkHost::Size(); } +private: + CInitMessage_Header header; +public: + int32_t HostsCount; /// Number of hosts + CNetworkHost Hosts[PlayerMax]; /// Participant information +}; + +class CInitMessage_EngineMismatch +{ +public: + CInitMessage_EngineMismatch(); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + 4; } +private: + CInitMessage_Header header; +public: + int32_t Stratagus; /// Stratagus engine version +}; + +class CInitMessage_ProtocolMismatch +{ +public: + CInitMessage_ProtocolMismatch(); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + 4; } +private: + CInitMessage_Header header; +public: + int32_t Version; /// Network protocol version +}; + +class CInitMessage_Welcome +{ +public: + CInitMessage_Welcome(); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + PlayerMax * CNetworkHost::Size() + 2 * 4; } +private: + CInitMessage_Header header; +public: + CNetworkHost hosts[PlayerMax]; /// Participant information int32_t Lag; /// Lag time int32_t Updates; /// Update frequency +}; - union { - CNetworkHost Hosts[PlayerMax]; /// Participant information - char MapPath[256]; - CServerSetup State; /// Server Setup State information - } u; +class CInitMessage_Map +{ +public: + CInitMessage_Map() {} + CInitMessage_Map(const char *path, uint32_t mapUID); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + 256 + 4; } +private: + CInitMessage_Header header; +public: + char MapPath[256]; + uint32_t MapUID; /// UID of map to play. +}; + +class CInitMessage_State +{ +public: + CInitMessage_State() {} + CInitMessage_State(int type, const CServerSetup &data); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + CServerSetup::Size(); } +private: + CInitMessage_Header header; +public: + CServerSetup State; /// Server Setup State information +}; + +class CInitMessage_Resync +{ +public: + CInitMessage_Resync(); + const CInitMessage_Header &GetHeader() const { return header; } + const unsigned char *Serialize() const; + void Deserialize(const unsigned char *p); + static size_t Size() { return CInitMessage_Header::Size() + CNetworkHost::Size() * PlayerMax; } +private: + CInitMessage_Header header; +public: + CNetworkHost hosts[PlayerMax]; /// Participant information }; /** diff --git a/src/include/netconnect.h b/src/include/netconnect.h index 15fc13939..c778ac0d6 100644 --- a/src/include/netconnect.h +++ b/src/include/netconnect.h @@ -31,7 +31,6 @@ //@{ -#include #include "net_message.h" /*---------------------------------------------------------------------------- diff --git a/src/network/net_message.cpp b/src/network/net_message.cpp index 7fcacac19..f555a7209 100644 --- a/src/network/net_message.cpp +++ b/src/network/net_message.cpp @@ -84,6 +84,14 @@ int serialize8(unsigned char *buf, int8_t data) } return sizeof(data); } +template +int serialize(unsigned char *buf, const char (&data)[N]) +{ + if (buf) { + memcpy(buf, data, N); + } + return N; +} int deserialize32(const unsigned char *buf, uint32_t *data) { @@ -115,30 +123,38 @@ int deserialize8(const unsigned char *buf, int8_t *data) *data = *buf; return sizeof(*data); } +template +int deserialize(const unsigned char *buf, char (&data)[N]) +{ + memcpy(data, buf, N); + return N; +} // // CNetworkHost // -const unsigned char *CNetworkHost::Serialize() const +size_t CNetworkHost::Serialize(unsigned char *buf) const { - unsigned char *buf = new unsigned char[CNetworkHost::Size()]; unsigned char *p = buf; p += serialize32(p, this->Host); p += serialize16(p, this->Port); p += serialize16(p, this->PlyNr); - memcpy(p, this->PlyName, sizeof(this->PlyName)); + p += serialize(p, this->PlyName); - return buf; + return p - buf; } -void CNetworkHost::Deserialize(const unsigned char *p) +size_t CNetworkHost::Deserialize(const unsigned char *p) { + const unsigned char *buf = p; + p += deserialize32(p, &Host); p += deserialize16(p, &Port); p += deserialize16(p, &PlyNr); - memcpy(this->PlyName, p, sizeof(this->PlyName)); + p += deserialize(p, this->PlyName); + return p - buf; } void CNetworkHost::Clear() @@ -158,9 +174,8 @@ void CNetworkHost::SetName(const char *name) // CServerSetup // -const unsigned char *CServerSetup::Serialize() const +size_t CServerSetup::Serialize(unsigned char *buf) const { - unsigned char *buf = new unsigned char[CServerSetup::Size()]; unsigned char *p = buf; p += serialize8(p, this->ResourcesOption); @@ -180,11 +195,12 @@ const unsigned char *CServerSetup::Serialize() const for (int i = 0; i < PlayerMax; ++i) { p += serialize8(p, this->Race[i]); } - return buf; + return p - buf; } -void CServerSetup::Deserialize(const unsigned char *p) +size_t CServerSetup::Deserialize(const unsigned char *p) { + const unsigned char *buf = p; p += deserialize8(p, &this->ResourcesOption); p += deserialize8(p, &this->UnitsOption); p += deserialize8(p, &this->FogOfWar); @@ -202,101 +218,260 @@ void CServerSetup::Deserialize(const unsigned char *p) for (int i = 0; i < PlayerMax; ++i) { p += deserialize8(p, &this->Race[i]); } + return p - buf; } // -// CInitMessage +// CInitMessage_Header // -CInitMessage::CInitMessage() +size_t CInitMessage_Header::Serialize(unsigned char *p) const { - memset(this, 0, sizeof(CInitMessage)); + unsigned char *buf = p; + p += serialize8(p, type); + p += serialize8(p, subtype); + return p - buf; } -CInitMessage::CInitMessage(uint8_t type, uint8_t subtype) +size_t CInitMessage_Header::Deserialize(const unsigned char *p) { - this->Type = type; - this->SubType = subtype; + const unsigned char *buf = p; + p += deserialize8(p, &type); + p += deserialize8(p, &subtype); + return p - buf; +} + +// +// CInitMessage_Hello +// + +CInitMessage_Hello::CInitMessage_Hello(const char *name) : + header(MessageInit_FromClient, ICMHello) +{ + strncpy_s(this->PlyName, sizeof(this->PlyName), name, _TRUNCATE); this->Stratagus = StratagusVersion; this->Version = NetworkProtocolVersion; - this->Lag = NetworkLag; - this->Updates = NetworkUpdates; } -const unsigned char *CInitMessage::Serialize() const +const unsigned char *CInitMessage_Hello::Serialize() const { - unsigned char *buf = new unsigned char[CInitMessage::Size()]; + unsigned char *buf = new unsigned char[Size()]; unsigned char *p = buf; - p += serialize8(p, this->Type); - p += serialize8(p, this->SubType); - p += serialize8(p, this->HostsCount); - p += serialize8(p, this->padding); + p += header.Serialize(p); + p += serialize(p, this->PlyName); p += serialize32(p, this->Stratagus); p += serialize32(p, this->Version); - p += serialize32(p, this->MapUID); - p += serialize32(p, this->Lag); - p += serialize32(p, this->Updates); + return buf; +} - switch (this->SubType) { - case ICMHello: - case ICMConfig: - case ICMWelcome: - case ICMResync: - case ICMGo: - for (int i = 0; i < PlayerMax; ++i) { - const unsigned char *x = this->u.Hosts[i].Serialize(); - memcpy(p, x, CNetworkHost::Size()); - p += CNetworkHost::Size(); - delete[] x; - } - break; - case ICMMap: - memcpy(p, this->u.MapPath, sizeof(this->u.MapPath)); - p += sizeof(this->u.MapPath); - break; - case ICMState: { - const unsigned char *x = this->u.State.Serialize(); - memcpy(p, x, CServerSetup::Size()); - p += CServerSetup::Size(); - delete[] x; - break; - } +void CInitMessage_Hello::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); + p += deserialize(p, this->PlyName); + p += deserialize32(p, &this->Stratagus); + p += deserialize32(p, &this->Version); +} + +// +// CInitMessage_Config +// + +CInitMessage_Config::CInitMessage_Config() : + header(MessageInit_FromServer, ICMConfig) +{ +} + +const unsigned char *CInitMessage_Config::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + p += serialize32(p, this->HostsCount); + for (int i = 0; i != PlayerMax; ++i) { + p += this->Hosts[i].Serialize(p); } return buf; } -void CInitMessage::Deserialize(const unsigned char *p) +void CInitMessage_Config::Deserialize(const unsigned char *p) { - p += deserialize8(p, &this->Type); - p += deserialize8(p, &this->SubType); - p += deserialize8(p, &this->HostsCount); - p += deserialize8(p, &this->padding); + p += header.Deserialize(p); + p += deserialize32(p, &this->HostsCount); + for (int i = 0; i != PlayerMax; ++i) { + p += this->Hosts[i].Deserialize(p); + } +} + +// +// CInitMessage_EngineMismatch +// + +CInitMessage_EngineMismatch::CInitMessage_EngineMismatch() : + header(MessageInit_FromServer, ICMEngineMismatch) +{ + this->Stratagus = StratagusVersion; +} + +const unsigned char *CInitMessage_EngineMismatch::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + p += serialize32(p, this->Stratagus); + return buf; +} + +void CInitMessage_EngineMismatch::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); p += deserialize32(p, &this->Stratagus); +} + +// +// CInitMessage_ProtocolMismatch +// + +CInitMessage_ProtocolMismatch::CInitMessage_ProtocolMismatch() : + header(MessageInit_FromServer, ICMProtocolMismatch) +{ + this->Version = NetworkProtocolVersion; +} + +const unsigned char *CInitMessage_ProtocolMismatch::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + p += serialize32(p, this->Version); + return buf; +} + +void CInitMessage_ProtocolMismatch::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); p += deserialize32(p, &this->Version); - p += deserialize32(p, &this->MapUID); +} + +// +// CInitMessage_Welcome +// + +CInitMessage_Welcome::CInitMessage_Welcome() : + header(MessageInit_FromServer, ICMWelcome) +{ + this->Lag = NetworkLag; + this->Updates = NetworkUpdates; +} + +const unsigned char *CInitMessage_Welcome::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + for (int i = 0; i < PlayerMax; ++i) { + p += this->hosts[i].Serialize(p); + } + p += serialize32(p, this->Lag); + p += serialize32(p, this->Updates); + return buf; +} + +void CInitMessage_Welcome::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); + for (int i = 0; i < PlayerMax; ++i) { + p += this->hosts[i].Deserialize(p); + } p += deserialize32(p, &this->Lag); p += deserialize32(p, &this->Updates); +} - switch (this->SubType) { - case ICMHello: - case ICMConfig: - case ICMWelcome: - case ICMResync: - case ICMGo: - for (int i = 0; i < PlayerMax; ++i) { - this->u.Hosts[i].Deserialize(p); - p += CNetworkHost::Size(); - } - break; - case ICMMap: - memcpy(this->u.MapPath, p, sizeof(this->u.MapPath)); - p += sizeof(this->u.MapPath); - break; - case ICMState: - this->u.State.Deserialize(p); - p += CServerSetup::Size(); - break; +// +// CInitMessage_Map +// + +CInitMessage_Map::CInitMessage_Map(const char *path, uint32_t mapUID) : + header(MessageInit_FromServer, ICMMap), + MapUID(mapUID) +{ + strncpy_s(MapPath, sizeof(MapPath), path, _TRUNCATE); +} + +const unsigned char *CInitMessage_Map::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + p += serialize(p, MapPath); + p += serialize32(p, this->MapUID); + return buf; +} + +void CInitMessage_Map::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); + p += deserialize(p, this->MapPath); + p += deserialize32(p, &this->MapUID); +} + +// +// CInitMessage_State +// + +CInitMessage_State::CInitMessage_State(int type, const CServerSetup &data) : + header(type, ICMState), + State(data) +{ +} + +const unsigned char *CInitMessage_State::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + p += this->State.Serialize(p); + return buf; +} + +void CInitMessage_State::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); + p += this->State.Deserialize(p); +} + +// +// CInitMessage_Resync +// + +CInitMessage_Resync::CInitMessage_Resync() : + header(MessageInit_FromServer, ICMResync) +{ +} + +const unsigned char *CInitMessage_Resync::Serialize() const +{ + unsigned char *buf = new unsigned char[Size()]; + unsigned char *p = buf; + + p += header.Serialize(p); + for (int i = 0; i < PlayerMax; ++i) { + p += this->hosts[i].Serialize(p); + } + return buf; +} + +void CInitMessage_Resync::Deserialize(const unsigned char *p) +{ + p += header.Deserialize(p); + for (int i = 0; i < PlayerMax; ++i) { + p += this->hosts[i].Deserialize(p); } } diff --git a/src/network/netconnect.cpp b/src/network/netconnect.cpp index 94ba5a03a..cd5252add 100644 --- a/src/network/netconnect.cpp +++ b/src/network/netconnect.cpp @@ -104,11 +104,11 @@ public: void MarkClientsAsResync(); void KickClient(int c); private: - int Parse_Hello(int h, const CInitMessage &msg, unsigned long host, int port); + int Parse_Hello(int h, const CInitMessage_Hello &msg, unsigned long host, int port); void Parse_Resync(const int h); void Parse_Waiting(const int h); void Parse_Map(const int h); - void Parse_State(const int h, const CInitMessage &msg); + void Parse_State(const int h, const CInitMessage_State &msg); void Parse_GoodBye(const int h); void Parse_SeeYou(const int h); @@ -162,11 +162,12 @@ private: void Send_Hello(unsigned long tick); void Send_GoodBye(unsigned long tick); - void NetworkSendRateLimitedClientMessage(const CInitMessage &msg, unsigned long tick, unsigned long msecs); + template + void SendRateLimited(const T &msg, unsigned long tick, unsigned long msecs); void NetClientCheckLocalState(); - void SetConfig(const CInitMessage &msg, unsigned long host, int port); - void SetState(const CInitMessage &msg); + void SetConfig(const CInitMessage_Config &msg, unsigned long host, int port); + void SetState(const CInitMessage_State &msg); void Parse_GameFull(); void Parse_ProtocolMismatch(const unsigned char *buf); @@ -198,14 +199,20 @@ static CClient Client; ** @param host Host to send to (network byte order). ** @param port Port of host to send to (network byte order). ** @param msg The message to send -** -** @todo FIXME: we don't need to put the header into all messages. -** (header = msg->Stratagus ... ) */ -static void NetworkSendICMessage(unsigned long host, int port, const CInitMessage &msg) +template +static void NetworkSendICMessage(unsigned long host, int port, const T &msg) { const unsigned char *buf = msg.Serialize(); - NetSendUDP(NetworkFildes, host, port, buf, CInitMessage::Size()); + NetSendUDP(NetworkFildes, host, port, buf, msg.Size()); + delete[] buf; +} + +void NetworkSendICMessage(unsigned long host, int port, const CInitMessage_Header &msg) +{ + unsigned char *buf = new unsigned char [msg.Size()]; + msg.Serialize(buf); + NetSendUDP(NetworkFildes, host, port, buf, msg.Size()); delete[] buf; } @@ -258,13 +265,23 @@ static const char *icmsgsubtypenames[] = { }; #endif -static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMessage &msg) +template +static void NetworkSendICMessage_Log(unsigned long ip, int port, const T &msg) { NetworkSendICMessage(ip, port, msg); DebugPrint("Sending to %d.%d.%d.%d:%d -> %s\n" _C_ NIPQUAD(ntohl(ip)) _C_ ntohs(port) - _C_ icmsgsubtypenames[msg.SubType]); + _C_ icmsgsubtypenames[msg.GetHeader().GetSubType()]); +} + +static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMessage_Header &msg) +{ + NetworkSendICMessage(ip, port, msg); + + DebugPrint("Sending to %d.%d.%d.%d:%d -> %s\n" + _C_ NIPQUAD(ntohl(ip)) _C_ ntohs(port) + _C_ icmsgsubtypenames[msg.GetSubType()]); } /** @@ -274,23 +291,46 @@ static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMess ** @param tick current tick ** @param msecs microseconds to delay */ -void CClient::NetworkSendRateLimitedClientMessage(const CInitMessage &msg, unsigned long tick, unsigned long msecs) +template +void CClient::SendRateLimited(const T &msg, unsigned long tick, unsigned long msecs) { const unsigned long now = tick; if (now - networkState.LastFrame < msecs) { return; } networkState.LastFrame = now; - if (msg.SubType == lastMsgTypeSent) { + const unsigned char subtype = msg.GetHeader().GetSubType(); + if (subtype == lastMsgTypeSent) { ++networkState.MsgCnt; } else { networkState.MsgCnt = 0; - lastMsgTypeSent = msg.SubType; + lastMsgTypeSent = subtype; } NetworkSendICMessage(serverIP, serverPort, msg); DebugPrint("[%s] Sending (%s:#%d)\n" _C_ ncconstatenames[networkState.State] _C_ - icmsgsubtypenames[msg.SubType] _C_ networkState.MsgCnt); + icmsgsubtypenames[subtype] _C_ networkState.MsgCnt); +} + +template<> +void CClient::SendRateLimited(const CInitMessage_Header &msg, unsigned long tick, unsigned long msecs) +{ + const unsigned long now = tick; + if (now - networkState.LastFrame < msecs) { + return; + } + networkState.LastFrame = now; + const unsigned char subtype = msg.GetSubType(); + if (subtype == lastMsgTypeSent) { + ++networkState.MsgCnt; + } else { + networkState.MsgCnt = 0; + lastMsgTypeSent = subtype; + } + NetworkSendICMessage(serverIP, serverPort, msg); + DebugPrint("[%s] Sending (%s:#%d)\n" _C_ + ncconstatenames[networkState.State] _C_ + icmsgsubtypenames[subtype] _C_ networkState.MsgCnt); } bool CClient::SetupServerAddress(const std::string &serveraddr, int port) @@ -339,7 +379,7 @@ void CClient::NetClientCheckLocalState() bool CClient::Update_disconnected() { Assert(networkState.State == ccs_disconnected); - const CInitMessage message(MessageInit_FromClient, ICMSeeYou); + const CInitMessage_Header message(MessageInit_FromClient, ICMSeeYou); // Spew out 5 and trust in God that they arrive for (int i = 0; i < 5; ++i) { @@ -489,69 +529,65 @@ bool CClient::Update_started(unsigned long tick) void CClient::Send_Go(unsigned long tick) { - const CInitMessage message(MessageInit_FromClient, ICMGo); + const CInitMessage_Header message(MessageInit_FromClient, ICMGo); - NetworkSendRateLimitedClientMessage(message, tick, 250); + SendRateLimited(message, tick, 250); } void CClient::Send_Config(unsigned long tick) { - const CInitMessage message(MessageInit_FromClient, ICMConfig); + const CInitMessage_Header message(MessageInit_FromClient, ICMConfig); - NetworkSendRateLimitedClientMessage(message, tick, 250); + SendRateLimited(message, tick, 250); } void CClient::Send_MapUidMismatch(unsigned long tick) { - CInitMessage message(MessageInit_FromClient, ICMMapUidMismatch); + const CInitMessage_Header message(MessageInit_FromClient, ICMMapUidMismatch); // MAP Uid doesn't match - message.MapUID = Map.Info.MapUID; // MAP Uid doesn't match - NetworkSendRateLimitedClientMessage(message, tick, 650); + SendRateLimited(message, tick, 650); } void CClient::Send_Map(unsigned long tick) { - CInitMessage message(MessageInit_FromClient, ICMMap); + CInitMessage_Header message(MessageInit_FromClient, ICMMap); - message.MapUID = Map.Info.MapUID; - NetworkSendRateLimitedClientMessage(message, tick, 650); + SendRateLimited(message, tick, 650); } void CClient::Send_Resync(unsigned long tick) { - const CInitMessage message(MessageInit_FromClient, ICMResync); + const CInitMessage_Header message(MessageInit_FromClient, ICMResync); - NetworkSendRateLimitedClientMessage(message, tick, 450); + SendRateLimited(message, tick, 450); } void CClient::Send_State(unsigned long tick) { - CInitMessage message(MessageInit_FromClient, ICMState); + const CInitMessage_State message(MessageInit_FromClient, LocalSetupState); - message.u.State = LocalSetupState; - message.MapUID = Map.Info.MapUID; - NetworkSendRateLimitedClientMessage(message, tick, 450); + SendRateLimited(message, tick, 450); } void CClient::Send_Waiting(unsigned long tick, unsigned long msec) { - const CInitMessage message(MessageInit_FromClient, ICMWaiting); - NetworkSendRateLimitedClientMessage(message, tick, msec); + const CInitMessage_Header message(MessageInit_FromClient, ICMWaiting); + + SendRateLimited(message, tick, msec); } void CClient::Send_Hello(unsigned long tick) { - CInitMessage message(MessageInit_FromClient, ICMHello); + const CInitMessage_Hello message(Parameters::Instance.LocalPlayerName.c_str()); - message.u.Hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str()); - NetworkSendRateLimitedClientMessage(message, tick, 500); + SendRateLimited(message, tick, 500); } void CClient::Send_GoodBye(unsigned long tick) { - const CInitMessage message(MessageInit_FromClient, ICMGoodBye); + const CInitMessage_Header message(MessageInit_FromClient, ICMGoodBye); - NetworkSendRateLimitedClientMessage(message, tick, 100); + SendRateLimited(message, tick, 100); } /* @@ -576,42 +612,42 @@ bool CClient::Update(unsigned long tick) return true; } -void CClient::SetState(const CInitMessage &msg) +void CClient::SetState(const CInitMessage_State &msg) { - ServerSetupState = msg.u.State; + ServerSetupState = msg.State; } -void CClient::SetConfig(const CInitMessage &msg, unsigned long host, int port) +void CClient::SetConfig(const CInitMessage_Config &msg, unsigned long host, int port) { HostsCount = 0; for (int i = 0; i < msg.HostsCount - 1; ++i) { - if (msg.u.Hosts[i].Host || msg.u.Hosts[i].Port) { - Hosts[HostsCount] = msg.u.Hosts[i]; + if (msg.Hosts[i].Host || msg.Hosts[i].Port) { + Hosts[HostsCount] = msg.Hosts[i]; HostsCount++; DebugPrint("Client %d = %d.%d.%d.%d:%d [%.*s]\n" _C_ - msg.u.Hosts[i].PlyNr _C_ NIPQUAD(ntohl(msg.u.Hosts[i].Host)) _C_ - ntohs(msg.u.Hosts[i].Port) _C_ - static_cast(sizeof(msg.u.Hosts[i].PlyName)) _C_ - msg.u.Hosts[i].PlyName); + msg.Hosts[i].PlyNr _C_ NIPQUAD(ntohl(msg.Hosts[i].Host)) _C_ + ntohs(msg.Hosts[i].Port) _C_ + static_cast(sizeof(msg.Hosts[i].PlyName)) _C_ + msg.Hosts[i].PlyName); } else { // Own client - NetLocalPlayerNumber = msg.u.Hosts[i].PlyNr; - DebugPrint("SELF %d [%.*s]\n" _C_ msg.u.Hosts[i].PlyNr _C_ - static_cast(sizeof(msg.u.Hosts[i].PlyName)) _C_ - msg.u.Hosts[i].PlyName); + NetLocalPlayerNumber = msg.Hosts[i].PlyNr; + DebugPrint("SELF %d [%.*s]\n" _C_ msg.Hosts[i].PlyNr _C_ + static_cast(sizeof(msg.Hosts[i].PlyName)) _C_ + msg.Hosts[i].PlyName); } } // server is last: Hosts[HostsCount].Host = host; Hosts[HostsCount].Port = port; - Hosts[HostsCount].PlyNr = msg.u.Hosts[msg.HostsCount - 1].PlyNr; - Hosts[HostsCount].SetName(msg.u.Hosts[msg.HostsCount - 1].PlyName); + Hosts[HostsCount].PlyNr = msg.Hosts[msg.HostsCount - 1].PlyNr; + Hosts[HostsCount].SetName(msg.Hosts[msg.HostsCount - 1].PlyName); ++HostsCount; NetPlayers = HostsCount + 1; DebugPrint("Server %d = %d.%d.%d.%d:%d [%.*s]\n" _C_ - msg.u.Hosts[msg.HostsCount - 1].PlyNr _C_ NIPQUAD(ntohl(host)) _C_ + msg.Hosts[msg.HostsCount - 1].PlyNr _C_ NIPQUAD(ntohl(host)) _C_ ntohs(port) _C_ - static_cast(sizeof(msg.u.Hosts[msg.HostsCount - 1].PlyName)) _C_ - msg.u.Hosts[msg.HostsCount - 1].PlyName); + static_cast(sizeof(msg.Hosts[msg.HostsCount - 1].PlyName)) _C_ + msg.Hosts[msg.HostsCount - 1].PlyName); // put ourselves to the end, like on the server.. Hosts[HostsCount].Host = 0; @@ -622,14 +658,15 @@ void CClient::SetConfig(const CInitMessage &msg, unsigned long host, int port) bool CClient::Parse(const unsigned char *buf, unsigned long host, int port) { - const unsigned char msgtype = buf[0]; + CInitMessage_Header header; + header.Deserialize(buf); - if (msgtype != MessageInit_FromServer) { + if (header.GetType() != MessageInit_FromServer) { return true; } // Assert(host == this->serverIP); // Assert(port == this->serverPort); - const unsigned char msgsubtype = buf[1]; + const unsigned char msgsubtype = header.GetSubType(); DebugPrint("Received %s in state %s\n" _C_ icmsgsubtypenames[msgsubtype] _C_ ncconstatenames[networkState.State]); @@ -733,15 +770,15 @@ void CClient::Parse_Map(const unsigned char *buf) if (networkState.State != ccs_connected) { return; } - CInitMessage msg; + CInitMessage_Map msg; msg.Deserialize(buf); - if (!IsSafeMapName(msg.u.MapPath)) { + if (!IsSafeMapName(msg.MapPath)) { fprintf(stderr, "Unsecure map name!\n"); networkState.State = ccs_badmap; return; } - NetworkMapName = std::string(msg.u.MapPath, sizeof(msg.u.MapPath)); + NetworkMapName = std::string(msg.MapPath, sizeof(msg.MapPath)); std::string mappath = StratagusLibPath + "/" + NetworkMapName; LoadStratagusMapInfo(mappath); if (msg.MapUID != Map.Info.MapUID) { @@ -759,13 +796,13 @@ void CClient::Parse_Welcome(const unsigned char *buf) if (networkState.State != ccs_connecting) { return; } - CInitMessage msg; + CInitMessage_Welcome msg; msg.Deserialize(buf); networkState.State = ccs_connected; networkState.MsgCnt = 0; - NetLocalHostsSlot = msg.u.Hosts[0].PlyNr; - Hosts[0].SetName(msg.u.Hosts[0].PlyName); // Name of server player + NetLocalHostsSlot = msg.hosts[0].PlyNr; + Hosts[0].SetName(msg.hosts[0].PlyName); // Name of server player NetworkLag = msg.Lag; NetworkUpdates = msg.Updates; @@ -773,7 +810,7 @@ void CClient::Parse_Welcome(const unsigned char *buf) Hosts[0].Port = serverPort; for (int i = 1; i < PlayerMax; ++i) { if (i != NetLocalHostsSlot) { - Hosts[i] = msg.u.Hosts[i]; + Hosts[i] = msg.hosts[i]; } else { Hosts[i].PlyNr = i; Hosts[i].SetName(Parameters::Instance.LocalPlayerName.c_str()); @@ -783,7 +820,7 @@ void CClient::Parse_Welcome(const unsigned char *buf) void CClient::Parse_State(const unsigned char *buf) { - CInitMessage msg; + CInitMessage_State msg; msg.Deserialize(buf); if (networkState.State == ccs_mapinfo) { @@ -809,7 +846,7 @@ void CClient::Parse_Config(const unsigned char *buf, unsigned long ip, int port) if (networkState.State != ccs_synced) { return; } - CInitMessage msg; + CInitMessage_Config msg; msg.Deserialize(buf); SetConfig(msg, ip, port); @@ -822,14 +859,14 @@ void CClient::Parse_Resync(const unsigned char *buf) if (networkState.State != ccs_async) { return; } - CInitMessage msg; + CInitMessage_Resync msg; msg.Deserialize(buf); for (int i = 1; i < PlayerMax - 1; ++i) { if (i != NetLocalHostsSlot) { - Hosts[i] = msg.u.Hosts[i]; + Hosts[i] = msg.hosts[i]; } else { - Hosts[i].PlyNr = msg.u.Hosts[i].PlyNr; + Hosts[i].PlyNr = msg.hosts[i].PlyNr; Hosts[i].SetName(Parameters::Instance.LocalPlayerName.c_str()); } } @@ -852,7 +889,7 @@ void CClient::Parse_ProtocolMismatch(const unsigned char *buf) if (networkState.State != ccs_connecting) { return; } - CInitMessage msg; + CInitMessage_ProtocolMismatch msg; msg.Deserialize(buf); fprintf(stderr, "Incompatible network protocol version " @@ -868,7 +905,7 @@ void CClient::Parse_EngineMismatch(const unsigned char *buf) if (networkState.State != ccs_connecting) { return; } - CInitMessage msg; + CInitMessage_EngineMismatch msg; msg.Deserialize(buf); fprintf(stderr, "Incompatible Stratagus version %d <-> %d\n" @@ -885,7 +922,7 @@ void CClient::Parse_EngineMismatch(const unsigned char *buf) */ void CClient::Parse_AreYouThere() { - const CInitMessage message(MessageInit_FromClient, ICMIAH); // IAmHere + const CInitMessage_Header message(MessageInit_FromClient, ICMIAH); // IAmHere NetworkSendICMessage(serverIP, serverPort, message); } @@ -930,31 +967,27 @@ void CServer::Init() void CServer::Send_AreYouThere(const CNetworkHost &host) { - const CInitMessage message(MessageInit_FromServer, ICMAYT); // AreYouThere + const CInitMessage_Header message(MessageInit_FromServer, ICMAYT); // AreYouThere NetworkSendICMessage(host.Host, host.Port, message); } void CServer::Send_GameFull(unsigned long host, int port) { - const CInitMessage message(MessageInit_FromServer, ICMGameFull); + const CInitMessage_Header message(MessageInit_FromServer, ICMGameFull); NetworkSendICMessage_Log(host, port, message); } void CServer::Send_Welcome(const CNetworkHost &host, int index) { - CInitMessage message(MessageInit_FromServer, ICMWelcome); + CInitMessage_Welcome message; - message.u.Hosts[0].PlyNr = index; // Host array slot number - message.u.Hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str()); // Name of server player + message.hosts[0].PlyNr = index; // Host array slot number + message.hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str()); // Name of server player for (int i = 1; i < PlayerMax - 1; ++i) { // Info about other clients - if (i != index) { - if (Hosts[i].PlyNr) { - message.u.Hosts[i] = Hosts[i]; - } else { - message.u.Hosts[i].Clear(); - } + if (i != index && Hosts[i].PlyNr) { + message.hosts[i] = Hosts[i]; } } NetworkSendICMessage_Log(host.Host, host.Port, message); @@ -962,15 +995,11 @@ void CServer::Send_Welcome(const CNetworkHost &host, int index) void CServer::Send_Resync(const CNetworkHost &host, int hostIndex) { - CInitMessage message(MessageInit_FromServer, ICMResync); + CInitMessage_Resync message; for (int i = 1; i < PlayerMax - 1; ++i) { // Info about other clients - if (i != hostIndex) { - if (Hosts[i].PlyNr) { - message.u.Hosts[i] = Hosts[i]; - } else { - message.u.Hosts[i].Clear(); - } + if (i != hostIndex && Hosts[i].PlyNr) { + message.hosts[i] = Hosts[i]; } } NetworkSendICMessage_Log(host.Host, host.Port, message); @@ -978,25 +1007,21 @@ void CServer::Send_Resync(const CNetworkHost &host, int hostIndex) void CServer::Send_Map(const CNetworkHost& host) { - CInitMessage message(MessageInit_FromServer, ICMMap); + const CInitMessage_Map message(NetworkMapName.c_str(), Map.Info.MapUID); - strncpy_s(message.u.MapPath, sizeof(message.u.MapPath), NetworkMapName.c_str(), NetworkMapName.size()); - message.MapUID = Map.Info.MapUID; NetworkSendICMessage_Log(host.Host, host.Port, message); } void CServer::Send_State(const CNetworkHost& host) { - CInitMessage message(MessageInit_FromServer, ICMState); + const CInitMessage_State message(MessageInit_FromServer, ServerSetupState); - message.u.State = ServerSetupState; - message.MapUID = Map.Info.MapUID; NetworkSendICMessage_Log(host.Host, host.Port, message); } void CServer::Send_GoodBye(const CNetworkHost& host) { - const CInitMessage message(MessageInit_FromServer, ICMGoodBye); + const CInitMessage_Header message(MessageInit_FromServer, ICMGoodBye); NetworkSendICMessage_Log(host.Host, host.Port, message); } @@ -1037,7 +1062,7 @@ void CServer::MarkClientsAsResync() ** ** @return host index */ -int CServer::Parse_Hello(int h, const CInitMessage &msg, unsigned long host, int port) +int CServer::Parse_Hello(int h, const CInitMessage_Hello &msg, unsigned long host, int port) { if (h == -1) { // it is a new client for (int i = 1; i < PlayerMax - 1; ++i) { @@ -1053,7 +1078,7 @@ int CServer::Parse_Hello(int h, const CInitMessage &msg, unsigned long host, int Hosts[h].Host = host; Hosts[h].Port = port; Hosts[h].PlyNr = h; - Hosts[h].SetName(msg.u.Hosts[0].PlyName); + Hosts[h].SetName(msg.PlyName); DebugPrint("New client %d.%d.%d.%d:%d [%s]\n" _C_ NIPQUAD(ntohl(host)) _C_ ntohs(port) _C_ Hosts[h].PlyName); networkStates[h].State = ccs_connecting; @@ -1181,7 +1206,7 @@ void CServer::Parse_Map(const int h) networkStates[h].MsgCnt = 0; /* Fall through */ case ccs_mapinfo: { - // this code path happens until client acknoledges the state info + // this code path happens until client acknowledges the state info // by falling back to ICMWaiting with prev. State synced Send_State(Hosts[h]); @@ -1203,7 +1228,7 @@ void CServer::Parse_Map(const int h) ** @param h slot number of host msg originates from ** @param msg message received */ -void CServer::Parse_State(const int h, const CInitMessage &msg) +void CServer::Parse_State(const int h, const CInitMessage_State &msg) { switch (networkStates[h].State) { case ccs_mapinfo: @@ -1214,8 +1239,8 @@ void CServer::Parse_State(const int h, const CInitMessage &msg) // networkStates[h].State = ccs_async; networkStates[h].MsgCnt = 0; // Use information supplied by the client: - ServerSetupState.Ready[h] = msg.u.State.Ready[h]; - ServerSetupState.Race[h] = msg.u.State.Race[h]; + ServerSetupState.Ready[h] = msg.State.Ready[h]; + ServerSetupState.Race[h] = msg.State.Race[h]; // Add additional info usage here! // Resync other clients (and us..) @@ -1297,16 +1322,16 @@ void CServer::Parse_SeeYou(const int h) ** ** @return 0 if the versions match, -1 otherwise */ -static int CheckVersions(const CInitMessage &msg, unsigned long host, int port) +static int CheckVersions(const CInitMessage_Hello &msg, unsigned long host, int port) { if (msg.Stratagus != StratagusVersion) { fprintf(stderr, "Incompatible Stratagus version " "%d <-> %d\n" "from %d.%d.%d.%d:%d\n", - msg.Stratagus, StratagusVersion, + StratagusVersion, msg.Stratagus, NIPQUAD(ntohl(host)), ntohs(port)); - const CInitMessage message(MessageInit_FromServer, ICMEngineMismatch); + const CInitMessage_EngineMismatch message; NetworkSendICMessage_Log(host, port, message); return -1; } @@ -1316,11 +1341,11 @@ static int CheckVersions(const CInitMessage &msg, unsigned long host, int port) NetworkProtocolFormatString " <-> " NetworkProtocolFormatString "\n" "from %d.%d.%d.%d:%d\n", - NetworkProtocolFormatArgs(msg.Version), NetworkProtocolFormatArgs(NetworkProtocolVersion), + NetworkProtocolFormatArgs(msg.Version), NIPQUAD(ntohl(host)), ntohs(port)); - const CInitMessage message(MessageInit_FromServer, ICMProtocolMismatch); + const CInitMessage_ProtocolMismatch message; NetworkSendICMessage_Log(host, port, message); return -1; } @@ -1334,7 +1359,7 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign if (index == -1) { if (msgsubtype == ICMHello) { - CInitMessage msg; + CInitMessage_Hello msg; msg.Deserialize(buf); if (CheckVersions(msg, host, port)) { @@ -1349,7 +1374,7 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign networkStates[index].LastFrame = frameCounter; switch (msgsubtype) { case ICMHello: { // a new client has arrived - CInitMessage msg; + CInitMessage_Hello msg; msg.Deserialize(buf); Parse_Hello(index, msg, host, port); @@ -1360,19 +1385,15 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign case ICMMap: Parse_Map(index); break; case ICMState: { - CInitMessage msg; + CInitMessage_State msg; msg.Deserialize(buf); Parse_State(index, msg); break; } - case ICMMapUidMismatch: - case ICMGoodBye: - Parse_GoodBye(index); - break; - + case ICMMapUidMismatch: // Parse_MapUidMismatch(index, buf); break; + case ICMGoodBye: Parse_GoodBye(index); break; case ICMSeeYou: Parse_SeeYou(index); break; - case ICMIAH: break; default: @@ -1399,7 +1420,9 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos { Assert(NetConnectRunning != 0); - const char msgtype = buf[0]; + CInitMessage_Header header; + header.Deserialize(buf); + const unsigned char msgtype = header.GetType(); if ((msgtype == MessageInit_FromClient && NetConnectRunning != 1) || (msgtype == MessageInit_FromServer && NetConnectRunning != 2)) { if (NetConnectRunning == 2 && Client.GetNetworkState() == ccs_started) { @@ -1410,7 +1433,7 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos } return 0; } - const char msgsubtype = buf[1]; + const unsigned char msgsubtype = header.GetSubType(); DebugPrint("Received %s (%d) from %d.%d.%d.%d:%d\n" _C_ icmsgsubtypenames[int(msgsubtype)] _C_ msgsubtype _C_ @@ -1476,6 +1499,7 @@ void NetworkInitClientConnect() ServerSetupState.Clear(); LocalSetupState.Clear(); } + /** ** Server user has finally hit the start game button */ @@ -1625,19 +1649,15 @@ void NetworkServerStartGame() std::swap(Hosts[0], Hosts[HostsCount]); // Prepare the final config message: - CInitMessage message(MessageInit_FromServer, ICMConfig); + CInitMessage_Config message; message.HostsCount = NetPlayers; - message.MapUID = Map.Info.MapUID; for (int i = 0; i < NetPlayers; ++i) { - message.u.Hosts[i] = Hosts[i]; - message.u.Hosts[i].PlyNr = Hosts[i].PlyNr; + message.Hosts[i] = Hosts[i]; + message.Hosts[i].PlyNr = Hosts[i].PlyNr; } // Prepare the final state message: - CInitMessage statemsg(MessageInit_FromServer, ICMState); - statemsg.HostsCount = NetPlayers; - statemsg.u.State = ServerSetupState; - statemsg.MapUID = Map.Info.MapUID; + const CInitMessage_State statemsg(MessageInit_FromServer, ServerSetupState); DebugPrint("Ready, sending InitConfig to %d host(s)\n" _C_ HostsCount); // Send all clients host:ports to all clients. @@ -1647,15 +1667,15 @@ breakout: // Send to all clients. for (int i = 0; i < HostsCount; ++i) { if (num[Hosts[i].PlyNr] == 1) { // not acknowledged yet - unsigned long host = message.u.Hosts[i].Host; - int port = message.u.Hosts[i].Port; - message.u.Hosts[i].Host = message.u.Hosts[i].Port = 0; + unsigned long host = message.Hosts[i].Host; + int port = message.Hosts[i].Port; + message.Hosts[i].Host = message.Hosts[i].Port = 0; NetworkSendICMessage_Log(host, port, message); - message.u.Hosts[i].Host = host; - message.u.Hosts[i].Port = port; + message.Hosts[i].Host = host; + message.Hosts[i].Port = port; } else if (num[Hosts[i].PlyNr] == 2) { - unsigned long host = message.u.Hosts[i].Host; - int port = message.u.Hosts[i].Port; + unsigned long host = message.Hosts[i].Host; + int port = message.Hosts[i].Port; NetworkSendICMessage_Log(host, port, statemsg); } } @@ -1671,16 +1691,13 @@ breakout: len _C_ NIPQUAD(ntohl(host)) _C_ ntohs(port)); continue; } + CInitMessage_Header header; + header.Deserialize(buf); + const unsigned char type = header.GetType(); + const unsigned char subtype = header.GetSubType(); - if (len != (int)CInitMessage::Size()) { - DebugPrint("Unexpected message size\n"); - continue; - } - CInitMessage msg; - - msg.Deserialize(buf); - if (msg.Type == MessageInit_FromClient) { - switch (msg.SubType) { + if (type == MessageInit_FromClient) { + switch (subtype) { case ICMConfig: { DebugPrint("Got ack for InitConfig from %d.%d.%d.%d:%d\n" _C_ NIPQUAD(ntohl(host)) _C_ ntohs(port)); @@ -1709,23 +1726,22 @@ breakout: break; } default: - DebugPrint("Server: Config ACK: Unhandled subtype %d\n" _C_ msg.SubType); + DebugPrint("Server: Config ACK: Unhandled subtype %d\n" _C_ subtype); break; } } else { - DebugPrint("Unexpected Message Type %d while waiting for Config ACK\n" _C_ msg.Type); + DebugPrint("Unexpected Message Type %d while waiting for Config ACK\n" _C_ type); } } } DebugPrint("DONE: All configs acked - Now starting..\n"); - // Give clients a quick-start kick.. - message.SubType = ICMGo; + const CInitMessage_Header message_go(MessageInit_FromServer, ICMGo); for (int i = 0; i < HostsCount; ++i) { - const unsigned long host = message.u.Hosts[i].Host; - const int port = message.u.Hosts[i].Port; - NetworkSendICMessage_Log(host, port, message); + const unsigned long host = Hosts[i].Host; + const int port = Hosts[i].Port; + NetworkSendICMessage_Log(host, port, message_go); } } diff --git a/tests/network/test_netconnect.cpp b/tests/network/test_netconnect.cpp index ed1d8641e..5400da52c 100644 --- a/tests/network/test_netconnect.cpp +++ b/tests/network/test_netconnect.cpp @@ -37,7 +37,7 @@ void FillCustomValue(CNetworkHost *obj) { obj->Host = 0x12345678; obj->Port = 0x9ABC; - for (int i = 0; i != sizeof(CNetworkHost::PlyName); ++i) { + for (int i = 0; i != sizeof(obj->PlyName); ++i) { obj->PlyName[i] = i + 1; } obj->PlyNr = 0xDEF0; @@ -64,20 +64,64 @@ void FillCustomValue(CServerSetup *obj) } } -void FillCustomValue(CInitMessage *obj) +void FillCustomValue(CInitMessage_Header *obj) { - obj->Type = 0x22; - obj->SubType = ICMHello; - obj->HostsCount = 0x04; - obj->padding = 0x33; + *obj = CInitMessage_Header(0x12, 0x34); +} + +void FillCustomValue(CInitMessage_Hello *obj) +{ + for (int i = 0; i != sizeof(obj->PlyName); ++i) { + obj->PlyName[i] = i + 1; + } obj->Stratagus = 0x12345678; obj->Version = 0x90ABCDEF; - obj->MapUID = 0x09BADCFE; - obj->Lag = 0x13245768; - obj->Updates = 0x9A0BCEDF; - // it is the biggest data size. +} + +void FillCustomValue(CInitMessage_Config *obj) +{ + obj->HostsCount = PlayerMax; for (int i = 0; i != PlayerMax; ++i) { - FillCustomValue(&obj->u.Hosts[i]); + FillCustomValue(&obj->Hosts[i]); + } +} + +void FillCustomValue(CInitMessage_EngineMismatch *obj) +{ + obj->Stratagus = 0x01020304; +} + +void FillCustomValue(CInitMessage_ProtocolMismatch *obj) +{ + obj->Version = 0x01020304; +} + +void FillCustomValue(CInitMessage_Welcome *obj) +{ + obj->Lag = 0x01020304; + obj->Updates = 0x05060708; + for (int i = 0; i != PlayerMax; ++i) { + FillCustomValue(&obj->hosts[i]); + } +} + +void FillCustomValue(CInitMessage_Map *obj) +{ + obj->MapUID = 0x01234567; + for (int i = 0; i != sizeof(obj->MapPath); ++i) { + obj->MapPath[i] = 1 + i; + } +} + +void FillCustomValue(CInitMessage_State *obj) +{ + FillCustomValue(&obj->State); +} + +void FillCustomValue(CInitMessage_Resync *obj) +{ + for (int i = 0; i != PlayerMax; ++i) { + FillCustomValue(&obj->hosts[i]); } } @@ -86,16 +130,36 @@ bool CheckSerialization() { T obj1; + FillCustomValue(&obj1); + + unsigned char *buffer = new unsigned char [obj1.Size()]; + unsigned char *end = buffer + obj1.Serialize(buffer); + bool res = size_t(end - buffer) == obj1.Size(); + T obj2; + obj2.Deserialize(buffer); + delete [] buffer; + res &= memcmp(&obj1, &obj2, sizeof(T)) == 0; // may fail with padding + return res; +} + +template +bool CheckSerialization_return() +{ + T obj1; + + memset(&obj1, 0, sizeof(T)); FillCustomValue(&obj1); const unsigned char *buffer = obj1.Serialize(); T obj2; + memset(&obj2, 0, sizeof(T)); obj2.Deserialize(buffer); - bool res = memcmp(&obj1, &obj2, sizeof(T)) == 0; + bool res = memcmp(&obj1, &obj2, sizeof(T)) == 0; // may fail with padding delete [] buffer; return res; } + TEST(CNetworkHost) { CHECK(CheckSerialization()); @@ -106,7 +170,47 @@ TEST(CServerSetup) CHECK(CheckSerialization()); } -TEST(CInitMessage) +TEST(CInitMessage_Header) { - CHECK(CheckSerialization()); + CHECK(CheckSerialization()); +} + +TEST(CInitMessage_Hello) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_Config) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_EngineMismatch) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_ProtocolMismatch) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_Welcome) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_Map) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_State) +{ + CHECK(CheckSerialization_return()); +} + +TEST(CInitMessage_Resync) +{ + CHECK(CheckSerialization_return()); }