Replace CInitMessage by more specific classes.
This commit is contained in:
parent
829e03df97
commit
9e6958e19b
5 changed files with 676 additions and 272 deletions
|
@ -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<size_t>(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
|
||||
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
|
||||
} u;
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
//@{
|
||||
|
||||
#include <stdint.h>
|
||||
#include "net_message.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -84,6 +84,14 @@ int serialize8(unsigned char *buf, int8_t data)
|
|||
}
|
||||
return sizeof(data);
|
||||
}
|
||||
template <int N>
|
||||
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 N>
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <typename T>
|
||||
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 <typename T>
|
||||
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 <typename T>
|
||||
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 <typename T>
|
||||
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<CInitMessage_Header>(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<int>(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<int>(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<int>(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<int>(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<int>(sizeof(msg.u.Hosts[msg.HostsCount - 1].PlyName)) _C_
|
||||
msg.u.Hosts[msg.HostsCount - 1].PlyName);
|
||||
static_cast<int>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <typename T>
|
||||
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<CNetworkHost>());
|
||||
|
@ -106,7 +170,47 @@ TEST(CServerSetup)
|
|||
CHECK(CheckSerialization<CServerSetup>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage)
|
||||
TEST(CInitMessage_Header)
|
||||
{
|
||||
CHECK(CheckSerialization<CInitMessage>());
|
||||
CHECK(CheckSerialization<CInitMessage_Header>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_Hello)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_Hello>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_Config)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_Config>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_EngineMismatch)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_EngineMismatch>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_ProtocolMismatch)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_ProtocolMismatch>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_Welcome)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_Welcome>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_Map)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_Map>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_State)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_State>());
|
||||
}
|
||||
|
||||
TEST(CInitMessage_Resync)
|
||||
{
|
||||
CHECK(CheckSerialization_return<CInitMessage_Resync>());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue