763 lines
17 KiB
C
763 lines
17 KiB
C
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Crytek Network source code
|
|
//
|
|
// File: CNP.h
|
|
// Description: Crytek network protocol declarations
|
|
//
|
|
// History:
|
|
// * 7/25/2001 Created by Alberto Demichelis
|
|
// * 11/5/2003 MM cleaned up, documented
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#ifndef _CNP_H_
|
|
#define _CNP_H_
|
|
|
|
#define CNP_VERSION 0x02
|
|
|
|
// CCP = Crytek Control protocol
|
|
#define FT_CCP_SETUP 0x10
|
|
#define FT_CCP_CONNECT 0x20
|
|
#define FT_CCP_CONNECT_RESP 0x30
|
|
#define FT_CCP_DISCONNECT 0x40
|
|
#define FT_CCP_CONTEXT_SETUP 0x50
|
|
#define FT_CCP_CONTEXT_READY 0x60
|
|
#define FT_CCP_SERVER_READY 0x70
|
|
#define FT_CCP_ACK 0x80
|
|
#define FT_CCP_SECURITY_QUERY 0x90
|
|
#define FT_CCP_SECURITY_RESP 0x91
|
|
#define FT_CCP_PUNK_BUSTER_MSG 0x92
|
|
|
|
// CQP = Crytek Transport protocol
|
|
#define FT_CTP_DATA 0x01
|
|
#define FT_CTP_ACK 0x02
|
|
#define FT_CTP_NAK 0x03
|
|
#define FT_CTP_PONG 0x04
|
|
|
|
// CQP = Crytek Query protocol (serverlist queries, RCon system for server remote control)
|
|
#define FT_CQP_INFO_REQUEST 0xff // ask server about it's settings (for serverlist) or XML request.
|
|
#define FT_CQP_INFO_RESPONSE 0xff // respond server settings (for serverlist) or XML response.
|
|
|
|
#define FT_CQP_XML_REQUEST 0x15 // XML request to server.
|
|
#define FT_CQP_XML_RESPONSE 0x16 // XML response from server.
|
|
|
|
#define FT_CQP_RCON_COMMAND 0x13 // execute remote a command on a server
|
|
#define FT_CQP_RCON_RESPONSE 0x14 // get the response back from the server
|
|
|
|
|
|
#define IS_TRANSPORT_FRAME(a)((a)&0x0F)?1:0
|
|
#define IS_CONTROL_FRAME(a)((a)&0xF0)?1:0
|
|
|
|
#define MAX_REQUEST_XML_LENGTH 1024
|
|
|
|
// Available Client flags
|
|
enum EClientFlags
|
|
{
|
|
// This client running 64 bit version.
|
|
CLIENT_FLAGS_64BIT = (1 << 0),
|
|
// This client running with PunkBuster enabled.
|
|
CLIENT_FLAGS_PUNK_BUSTER = (1 << 1),
|
|
// This client is/has cheated
|
|
CLIENT_FLAGS_DEVMODE = (1 << 3),
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
struct CNPServerVariables
|
|
{
|
|
void Save(CStream &stm)
|
|
{
|
|
stm.Write(nPublicKey);
|
|
stm.Write(nDataStreamTimeout);
|
|
}
|
|
void Load(CStream &stm)
|
|
{
|
|
stm.Read(nPublicKey);
|
|
stm.Read(nDataStreamTimeout);
|
|
}
|
|
|
|
unsigned int nDataStreamTimeout; //!< time elapsed without any data packet
|
|
unsigned int nPublicKey;
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CNP
|
|
{
|
|
CNP()
|
|
{
|
|
//m_cClientID = 0;
|
|
m_cFrameType = 0;
|
|
m_bSecondaryTC=false;
|
|
}
|
|
virtual ~CNP(){}
|
|
//BYTE m_cClientID;
|
|
BYTE m_cFrameType;
|
|
bool m_bSecondaryTC;
|
|
void Save(CStream &stm)
|
|
{
|
|
stm.WritePkd(m_cFrameType);
|
|
stm.Write(m_bSecondaryTC);
|
|
}
|
|
void Load(CStream &stm)
|
|
{
|
|
stm.ReadPkd(m_cFrameType);
|
|
stm.Read(m_bSecondaryTC);
|
|
}
|
|
void LoadAndSeekToZero(CStream &stm)
|
|
{
|
|
CNP::Load(stm);
|
|
//stm.Read(m_cFrameType);
|
|
stm.Seek(0);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CTP :public CNP
|
|
{
|
|
CTP()
|
|
{
|
|
m_cSequenceNumber = 0;
|
|
m_cAck = 0;
|
|
m_bPingRequest = false;
|
|
m_bUnreliable = false;
|
|
}
|
|
virtual ~CTP(){}
|
|
BYTE m_cSequenceNumber;//<<FIXME>> will be 6 bits
|
|
BYTE m_cAck;//<<FIXME>> will be 6 bits
|
|
bool m_bPingRequest;
|
|
bool m_bUnreliable;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CNP::Save(stm);
|
|
stm.WritePkd(m_cSequenceNumber);
|
|
stm.WritePkd(m_cAck);
|
|
stm.Write(m_bPingRequest);
|
|
stm.Write(m_bUnreliable);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CNP::Load(stm);
|
|
stm.ReadPkd(m_cSequenceNumber);
|
|
stm.ReadPkd(m_cAck);
|
|
stm.Read(m_bPingRequest);
|
|
stm.Read(m_bUnreliable);
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCP :public CNP
|
|
{
|
|
virtual ~CCP(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CNP::Save(stm);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CNP::Load(stm);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
// should be a byte aligned, so it can be manipulated by not-so-low level languages, like web languages (php, perl, ..)
|
|
// should always start with 4bytes 0x7f 0xff 0xff 0xff
|
|
// fist 10bits are CNP properties, wich are 0 11111111 1
|
|
// next 6bits are control bits, 111111
|
|
// and then two bytes 0xff 0xff
|
|
struct CQP :public CNP
|
|
{
|
|
CQP()
|
|
{
|
|
m_bSecondaryTC = true;
|
|
for (int i=0; i<6; i++)
|
|
m_bControlBits[i] = 0;
|
|
m_cControlBytes[0] = 0;
|
|
m_cControlBytes[1] = 0;
|
|
}
|
|
virtual ~CQP(){}
|
|
|
|
bool m_bControlBits[6]; // control bits, must be all 1
|
|
unsigned char m_cControlBytes[2]; // control bytes, must be all 0xff;
|
|
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CNP::Save(stm);
|
|
for(int i=0; i<6; i++) // write 6 control bits
|
|
stm.Write(true);
|
|
stm.Write((unsigned char)0xff); // write the two control bytes
|
|
stm.Write((unsigned char)0xff);
|
|
}
|
|
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CNP::Load(stm);
|
|
|
|
for(int i=0; i<6; i++)
|
|
{
|
|
if (stm.GetReadPos() < stm.GetSize())
|
|
stm.Read(m_bControlBits[i]);
|
|
else
|
|
return;
|
|
}
|
|
if (stm.GetSize()-stm.GetReadPos() >= 16)
|
|
{
|
|
stm.Read(m_cControlBytes[0]);
|
|
stm.Read(m_cControlBytes[1]);
|
|
}
|
|
}
|
|
|
|
bool IsOk()
|
|
{
|
|
for (int i=0; i < 6; i++)
|
|
{
|
|
if (!m_bControlBits[i])
|
|
return false;
|
|
}
|
|
return (m_cControlBytes[0] == 0xff) && (m_cControlBytes[0] == 0xff);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CQPInfoRequest: public CQP
|
|
{
|
|
CQPInfoRequest() { m_cFrameType = FT_CQP_INFO_REQUEST; };
|
|
CQPInfoRequest(const string &szQuery): szRequest(szQuery) { m_cFrameType = FT_CQP_INFO_REQUEST; };
|
|
virtual ~CQPInfoRequest(){}
|
|
|
|
string szRequest;
|
|
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CQP::Save(stm);
|
|
// write every byte, because if we write the string, it will get compressed :(
|
|
for (uint32 i=0; i<szRequest.size(); i++)
|
|
stm.Write(szRequest[i]);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
szRequest.resize(0);
|
|
|
|
CQP::Load(stm);
|
|
|
|
while(stm.GetSize()-stm.GetReadPos() >= 8)
|
|
{
|
|
char cByte;
|
|
stm.Read(cByte);
|
|
szRequest.push_back(cByte);
|
|
}
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CQPInfoResponse :public CQP
|
|
{
|
|
CQPInfoResponse()
|
|
{
|
|
m_cFrameType = FT_CQP_INFO_RESPONSE;
|
|
}
|
|
virtual ~CQPInfoResponse(){}
|
|
string szResponse;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CQP::Save(stm);
|
|
// write every byte, because if we write the string, it will get compressed :(
|
|
for (uint32 i=0; i<szResponse.size(); i++)
|
|
stm.Write(szResponse[i]);
|
|
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
szResponse.resize(0);
|
|
|
|
CQP::Load(stm);
|
|
|
|
while(stm.GetSize()-stm.GetReadPos() >= 8)
|
|
{
|
|
char cByte;
|
|
stm.Read(cByte);
|
|
szResponse.push_back(cByte);
|
|
}
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
struct CQPXMLRequest :public CQP
|
|
{
|
|
CQPXMLRequest()
|
|
{
|
|
m_cFrameType = FT_CQP_XML_REQUEST;
|
|
}
|
|
virtual ~CQPXMLRequest(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CQP::Save(stm);
|
|
if (m_sXML.size() > MAX_REQUEST_XML_LENGTH)
|
|
m_sXML.resize(MAX_REQUEST_XML_LENGTH);
|
|
stm.Write(m_sXML.c_str());
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CQP::Load(stm);
|
|
static char sTemp[MAX_REQUEST_XML_LENGTH+1];
|
|
stm.Read( (char*)sTemp,sizeof(sTemp)-1 );
|
|
sTemp[sizeof(sTemp)-1] = 0;
|
|
m_sXML = sTemp;
|
|
}
|
|
string m_sXML;
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CQPXMLResponse :public CQP
|
|
{
|
|
CQPXMLResponse()
|
|
{
|
|
m_cFrameType = FT_CQP_XML_RESPONSE;
|
|
}
|
|
virtual ~CQPXMLResponse(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CQP::Save(stm);
|
|
if (m_sXML.size() > MAX_REQUEST_XML_LENGTH)
|
|
m_sXML.resize(MAX_REQUEST_XML_LENGTH);
|
|
stm.Write(m_sXML.c_str());
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CQP::Load(stm);
|
|
static char sTemp[MAX_REQUEST_XML_LENGTH+1];
|
|
stm.Read( (char*)sTemp,sizeof(sTemp)-1 );
|
|
sTemp[sizeof(sTemp)-1] = 0;
|
|
m_sXML = sTemp;
|
|
}
|
|
string m_sXML;
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
//! remote command to a server
|
|
struct CQPRConCommand :public CQP
|
|
{
|
|
CQPRConCommand()
|
|
{
|
|
m_cFrameType = FT_CQP_RCON_COMMAND;
|
|
}
|
|
virtual ~CQPRConCommand(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CQP::Save(stm);
|
|
stm.WriteData( &m_nRConPasswordCode,16 );
|
|
stm.Write(m_sRConCommand.c_str());
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
static char sTemp[512];
|
|
CQP::Load(stm);
|
|
|
|
stm.ReadData( &m_nRConPasswordCode,16 );
|
|
stm.Read((char *)sTemp,sizeof(sTemp)-1 );
|
|
sTemp[sizeof(sTemp)-1] = 0;
|
|
m_sRConCommand = sTemp;
|
|
}
|
|
|
|
unsigned int m_nRConPasswordCode[4];
|
|
string m_sRConCommand; //!<
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
//! response from a server on a remote command
|
|
struct CQPRConResponse :public CQP
|
|
{
|
|
CQPRConResponse()
|
|
{
|
|
m_cFrameType = FT_CQP_RCON_RESPONSE;
|
|
}
|
|
virtual ~CQPRConResponse(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CQP::Save(stm);
|
|
stm.Write(m_sText.c_str());
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
static char sTemp[512];
|
|
CQP::Load(stm);
|
|
|
|
stm.Read((char *)sTemp,512);
|
|
m_sText = sTemp;
|
|
}
|
|
string m_sText; //!<
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPPayload :public CCP
|
|
{
|
|
CCPPayload(){
|
|
m_bSequenceNumber = 0;
|
|
}
|
|
virtual ~CCPPayload(){}
|
|
bool m_bSequenceNumber;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CCP::Save(stm);
|
|
stm.Write(m_bSequenceNumber);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CCP::Load(stm);
|
|
stm.Read(m_bSequenceNumber);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPAck :public CCP
|
|
{
|
|
bool m_bAck;
|
|
CCPAck()
|
|
{
|
|
m_cFrameType = FT_CCP_ACK;
|
|
}
|
|
virtual ~CCPAck(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CCP::Save(stm);
|
|
stm.Write(m_bAck);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CCP::Load(stm);
|
|
stm.Read(m_bAck);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPSetup :public CCPPayload
|
|
{
|
|
CCPSetup()
|
|
{
|
|
m_cFrameType = FT_CCP_SETUP;
|
|
m_cProtocolVersion = CNP_VERSION;
|
|
m_nClientFlags = 0;
|
|
m_nClientOSMinor = 0;
|
|
m_nClientOSMajor = 0;
|
|
}
|
|
virtual ~CCPSetup(){}
|
|
BYTE m_cProtocolVersion;
|
|
string m_sPlayerPassword;
|
|
// What version client is running.
|
|
unsigned int m_nClientFlags;
|
|
// What OS client is running.
|
|
unsigned int m_nClientOSMinor;
|
|
unsigned int m_nClientOSMajor;
|
|
//string m_sSpectatorPassword;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CCPPayload::Save(stm);
|
|
stm.Write(m_cProtocolVersion);
|
|
stm.Write(m_sPlayerPassword.c_str());
|
|
stm.Write(m_nClientFlags);
|
|
stm.Write(m_nClientOSMinor);
|
|
stm.Write(m_nClientOSMajor);
|
|
//stm.Write(m_sSpectatorPassword.c_str());
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
static char sTemp[512];
|
|
CCPPayload::Load(stm);
|
|
stm.Read(m_cProtocolVersion);
|
|
stm.Read((char *)sTemp,512);
|
|
m_sPlayerPassword = sTemp;
|
|
stm.Read(m_nClientFlags);
|
|
stm.Read(m_nClientOSMinor);
|
|
stm.Read(m_nClientOSMajor);
|
|
//stm.Read((char *)sTemp);
|
|
//m_sSpectatorPassword = sTemp;
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPConnect :public CCPPayload
|
|
{
|
|
CCPConnect()
|
|
{
|
|
m_cFrameType = FT_CCP_CONNECT;
|
|
m_cResponse = 0;
|
|
//m_cNewClientID = 0;
|
|
}
|
|
virtual ~CCPConnect(){}
|
|
BYTE m_cResponse; //!< bitflag to specify early information about the server! i.e. punkbuster or not..
|
|
// Random part of key used for encryption.
|
|
//BYTE m_cNewClientID;
|
|
// protocol variables
|
|
CNPServerVariables m_ServerVariables;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CCPPayload::Save(stm);
|
|
stm.Write(m_cResponse);
|
|
//stm.Write(m_cNewClientID);
|
|
// protocol variables
|
|
m_ServerVariables.Save(stm);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CCPPayload::Load(stm);
|
|
stm.Read(m_cResponse);
|
|
//stm.Read(m_cNewClientID);
|
|
// protocol variables
|
|
m_ServerVariables.Load(stm);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPConnectResp :public CCPPayload
|
|
{
|
|
CCPConnectResp()
|
|
{
|
|
m_cFrameType = FT_CCP_CONNECT_RESP;
|
|
m_cResponse = 0;
|
|
}
|
|
virtual ~CCPConnectResp(){}
|
|
BYTE m_cResponse;
|
|
CStream m_stmAuthorizationID;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
unsigned int uiSize;
|
|
|
|
CCPPayload::Save(stm);
|
|
stm.Write(m_cResponse);
|
|
|
|
uiSize = m_stmAuthorizationID.GetSize();
|
|
stm.Write(uiSize);
|
|
stm.Write(m_stmAuthorizationID);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
unsigned int uiSize;
|
|
CCPPayload::Load(stm);
|
|
stm.Read(m_cResponse);
|
|
stm.Read(uiSize);
|
|
m_stmAuthorizationID.Reset();
|
|
m_stmAuthorizationID.SetSize(uiSize);
|
|
stm.ReadBits(m_stmAuthorizationID.GetPtr(),uiSize);
|
|
//stm.Read(m_stmAuthorizationID);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPContextSetup:public CCPPayload
|
|
{
|
|
CCPContextSetup()
|
|
{
|
|
m_cFrameType = FT_CCP_CONTEXT_SETUP;
|
|
}
|
|
virtual ~CCPContextSetup(){}
|
|
CStream m_stmData;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
usSize = (unsigned short)m_stmData.GetSize();
|
|
CCPPayload::Save(stm);
|
|
stm.Write(usSize);
|
|
stm.Write(m_stmData);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
CCPPayload::Load(stm);
|
|
stm.Read(usSize);
|
|
m_stmData.Reset();
|
|
m_stmData.SetSize(usSize);
|
|
stm.ReadBits(m_stmData.GetPtr(), usSize);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPContextReady :public CCPPayload
|
|
{
|
|
CCPContextReady()
|
|
{
|
|
m_cFrameType = FT_CCP_CONTEXT_READY;
|
|
}
|
|
virtual ~CCPContextReady(){}
|
|
CStream m_stmData;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
usSize = (unsigned short)m_stmData.GetSize();
|
|
CCPPayload::Save(stm);
|
|
stm.Write(usSize);
|
|
stm.Write(m_stmData);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
CCPPayload::Load(stm);
|
|
stm.Read(usSize);
|
|
m_stmData.Reset();
|
|
m_stmData.SetSize(usSize);
|
|
stm.ReadBits(m_stmData.GetPtr(), usSize);
|
|
};
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPServerReady :public CCPPayload
|
|
{
|
|
CCPServerReady()
|
|
{
|
|
m_cFrameType = FT_CCP_SERVER_READY;
|
|
}
|
|
virtual ~CCPServerReady(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CCPPayload::Save(stm);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CCPPayload::Load(stm);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPDisconnect :public CCPPayload
|
|
{
|
|
CCPDisconnect()
|
|
{
|
|
m_cFrameType = FT_CCP_DISCONNECT;
|
|
}
|
|
virtual ~CCPDisconnect(){}
|
|
string m_sCause;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CCPPayload::Save(stm);
|
|
stm.Write(m_sCause);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CCPPayload::Load(stm);
|
|
stm.Read(m_sCause);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPSecurityQuery :public CCPPayload
|
|
{
|
|
CCPSecurityQuery()
|
|
{
|
|
m_cFrameType = FT_CCP_SECURITY_QUERY;
|
|
}
|
|
virtual ~CCPSecurityQuery(){}
|
|
CStream m_stmData;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
usSize = (unsigned short)m_stmData.GetSize();
|
|
CCPPayload::Save(stm);
|
|
stm.Write(usSize);
|
|
stm.Write(m_stmData);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
CCPPayload::Load(stm);
|
|
stm.Read(usSize);
|
|
m_stmData.Reset();
|
|
m_stmData.SetSize(usSize);
|
|
stm.ReadBits(m_stmData.GetPtr(), usSize);
|
|
};
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPSecurityResp :public CCPSecurityQuery
|
|
{
|
|
CCPSecurityResp()
|
|
{
|
|
m_cFrameType = FT_CCP_SECURITY_RESP;
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
struct CCPPunkBusterMsg :public CCPSecurityQuery
|
|
{
|
|
CCPPunkBusterMsg()
|
|
{
|
|
m_cFrameType = FT_CCP_PUNK_BUSTER_MSG;
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
struct CTPData :public CTP
|
|
{
|
|
CTPData()
|
|
{
|
|
m_cFrameType = FT_CTP_DATA;
|
|
m_bCompressed = false;
|
|
m_nUncompressedSize = 0;
|
|
}
|
|
virtual ~CTPData(){}
|
|
CStream m_stmData;
|
|
bool m_bCompressed; // Compressed data.
|
|
unsigned short m_nUncompressedSize;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
usSize = (unsigned short)m_stmData.GetSize();
|
|
CTP::Save(stm);
|
|
stm.Write(m_bCompressed);
|
|
if (m_bCompressed)
|
|
stm.WritePkd(m_nUncompressedSize);
|
|
stm.WritePkd(usSize);
|
|
stm.Write(m_stmData);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
unsigned short usSize;
|
|
CTP::Load(stm);
|
|
stm.Read(m_bCompressed);
|
|
if (m_bCompressed)
|
|
stm.ReadPkd(m_nUncompressedSize);
|
|
stm.ReadPkd(usSize);
|
|
m_stmData.Reset();
|
|
m_stmData.SetSize(usSize);
|
|
stm.ReadBits(m_stmData.GetPtr(), usSize);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CTPNak :public CTP
|
|
{
|
|
CTPNak()
|
|
{
|
|
m_cFrameType = FT_CTP_NAK;
|
|
}
|
|
virtual ~CTPNak(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CTP::Save(stm);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CTP::Load(stm);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
struct CTPAck :public CTP
|
|
{
|
|
CTPAck()
|
|
{
|
|
m_cFrameType = FT_CTP_ACK;
|
|
}
|
|
virtual ~CTPAck(){}
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CTP::Save(stm);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CTP::Load(stm);
|
|
}
|
|
};
|
|
|
|
|
|
// this packet is unreliable(sequence number and ack are ignored)
|
|
struct CTPPong :public CTP
|
|
{
|
|
CTPPong()
|
|
{
|
|
m_cFrameType = FT_CTP_PONG;
|
|
m_nTimestamp = 0;
|
|
}
|
|
virtual ~CTPPong(){}
|
|
unsigned int m_nTimestamp;
|
|
virtual void Save(CStream &stm)
|
|
{
|
|
CTP::Save(stm);
|
|
stm.Write(m_nTimestamp);
|
|
}
|
|
virtual void Load(CStream &stm)
|
|
{
|
|
CTP::Load(stm);
|
|
stm.Read(m_nTimestamp);
|
|
}
|
|
};
|
|
///////////////////////////////////////////////////////////////
|
|
#endif //_CNP_H_
|