123
This commit is contained in:
126
CryNetwork/ASEQuerySDK.h
Normal file
126
CryNetwork/ASEQuerySDK.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
ASE Query & Reporting SDK Copyright (C) 2003 UDP Soft Ltd
|
||||
http://www.udpsoft.com/eye/ All Rights Reserved
|
||||
|
||||
Enables reporting to the ASE master server and responding to server
|
||||
browser queries.
|
||||
|
||||
Before reading further, see example.c for a quick display of how simple this
|
||||
really is.
|
||||
|
||||
A quick run-down of things to do:
|
||||
|
||||
1. Initialization
|
||||
|
||||
extern int ASEQuery_initialize(int hostport, int internet, char *address);
|
||||
|
||||
hostport = the join port for the server
|
||||
internet = flag indicating whether we should report to the ASE master server
|
||||
(LAN servers should set this to 0)
|
||||
address = IP address to bind to (pass as NULL if your game does not have
|
||||
support for multihomed hosts)
|
||||
|
||||
This function should be called when the server is started. Does a DNS lookup,
|
||||
so call only when net already running. NOTE! Winsock must be initialized
|
||||
before calling the init function (see example.c).
|
||||
|
||||
Returns 0 on error, char *ASEQuery_error contains the error message.
|
||||
|
||||
|
||||
2. The worker function
|
||||
|
||||
extern int ASEQuery_check(void);
|
||||
|
||||
Ideally this should be called every millisecond. The simplest implementation
|
||||
would be to call this every "frame". Longer delays cause bigger ping
|
||||
fluctuations ie. not so accurate pings in the server browser.
|
||||
|
||||
Returns 0 on error, char *ASEQuery_error contains the error message.
|
||||
|
||||
|
||||
3. Functions that the _game_ has to implement
|
||||
|
||||
void ASEQuery_wantstatus(void);
|
||||
void ASEQuery_wantrules(void);
|
||||
void ASEQuery_wantplayers(void);
|
||||
|
||||
These are called when the SDK needs information about the game state.
|
||||
In each of these functions, the game must call back to the SDK providing
|
||||
the required information.
|
||||
|
||||
|
||||
4. Functions that the game calls to provide information back to the SDK
|
||||
|
||||
extern void ASEQuery_status(const char *hostname, const char *gametype, const char *mapname, const char *gamever, int password, int numplayers, int maxplayers);
|
||||
extern void ASEQuery_addrule(const char *key, const char *value);
|
||||
extern void ASEQuery_addplayer(const char *name, const char *team, const char *skin, const char *score, const char *ping, const char *time);
|
||||
|
||||
These can only be called in the corresponding functions described earlier.
|
||||
ASEQuery_status must only be called once. ASEQuery_addrule and
|
||||
ASEQuery_addplayer should be called for each rule/player that the game
|
||||
wishes to be visible in the server browser. Player info fields that don't
|
||||
apply can be passed as NULL.
|
||||
|
||||
|
||||
5. Shutting down
|
||||
|
||||
extern void ASEQuery_shutdown(void);
|
||||
|
||||
|
||||
6. How to link
|
||||
|
||||
In C:
|
||||
#include "ASEQuerySDK.h" in every module that uses the SDK.
|
||||
|
||||
In C++:
|
||||
extern "C" {
|
||||
#include "ASEQuerySDK.h"
|
||||
}
|
||||
|
||||
Link with ASEQuerySDK.LIB
|
||||
|
||||
The SDK uses the __cdecl calling convention.
|
||||
|
||||
7. Used ports
|
||||
|
||||
The SDK uses gameport+123 (UDP) as the default port for queries. If that port
|
||||
is not available, the next available port is used (+124, +125...). This port
|
||||
must have unrestricted access to/from the internet.
|
||||
|
||||
8. Other stuff
|
||||
|
||||
For ASE support, your game also has to implement commandline parsing for
|
||||
server address, player name, password etc.
|
||||
|
||||
The standard implementation would be:
|
||||
game.exe +connect ip:port +name "my name" +config "myconfig.cfg" +password "server password"
|
||||
|
||||
Let us know the commandline options for your game so we can update ASE
|
||||
accordingly. In addition to this we'll need the executable name and the
|
||||
registry key for the install folder.
|
||||
|
||||
For the demo version of the SDK, there's built-in ASE support already. Just
|
||||
go to View -> Options -> Games -> Not Installed -> SDK test and check
|
||||
"Visible in filter list". Any server running the demo SDK will now appear
|
||||
under the "SDK test" filter.
|
||||
|
||||
|
||||
actual .h stuff follows
|
||||
*/
|
||||
|
||||
|
||||
extern int ASEQuery_initialize(int hostport, int internet, char *address);
|
||||
|
||||
extern void ASEQuery_shutdown(void);
|
||||
|
||||
extern int ASEQuery_check(void);
|
||||
|
||||
void ASEQuery_wantstatus(void);
|
||||
void ASEQuery_wantrules(void);
|
||||
void ASEQuery_wantplayers(void);
|
||||
|
||||
extern void ASEQuery_status(const char *hostname, const char *gametype, const char *mapname, const char *gamever, int password, int numplayers, int maxplayers);
|
||||
extern void ASEQuery_addrule(const char *key, const char *value);
|
||||
extern void ASEQuery_addplayer(const char *name, const char *team, const char *skin, const char *score, const char *ping, const char *time);
|
||||
|
||||
extern char *ASEQuery_error;
|
||||
BIN
CryNetwork/ASEQuerySDK.lib
Normal file
BIN
CryNetwork/ASEQuerySDK.lib
Normal file
Binary file not shown.
511
CryNetwork/CCPEndpoint.cpp
Normal file
511
CryNetwork/CCPEndpoint.cpp
Normal file
@@ -0,0 +1,511 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: CCPEndpoint.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CCPEndpoint.h"
|
||||
#include "Network.h"
|
||||
|
||||
#include <ISystem.h>
|
||||
#include <IConsole.h>
|
||||
|
||||
#if defined(_DEBUG) && !defined(LINUX)
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
int GetCurrentProcessId()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CCCPEndpoint::CCCPEndpoint()
|
||||
{
|
||||
m_pParent=0;
|
||||
Reset();
|
||||
//new char[100000];//test
|
||||
}
|
||||
|
||||
|
||||
void CCCPEndpoint::Init( _ICCPUser *pParent )
|
||||
{
|
||||
m_pParent=pParent;
|
||||
}
|
||||
|
||||
CCCPEndpoint::~CCCPEndpoint()
|
||||
{
|
||||
while(!m_qOutgoingData.empty())
|
||||
{
|
||||
CCPPayload *pTemp=m_qOutgoingData.front();
|
||||
delete pTemp;
|
||||
m_qOutgoingData.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void CCCPEndpoint::Reset()
|
||||
{
|
||||
m_bFrameExpected = false;
|
||||
m_bNextFrameToSend = false;
|
||||
m_bAckExpected=!m_bNextFrameToSend;
|
||||
EnableSend();
|
||||
m_ulTimeout = 0;
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SetTimer()
|
||||
{
|
||||
if (m_ulTimeout == 0)
|
||||
m_ulTimeout = m_nCurrentTime;
|
||||
}
|
||||
|
||||
void CCCPEndpoint::StopTimer()
|
||||
{
|
||||
m_ulTimeout = 0;
|
||||
}
|
||||
|
||||
bool CCCPEndpoint::Update(unsigned int nTime, unsigned char cFrameType, CStream *pStm)
|
||||
{
|
||||
m_nCurrentTime = nTime;
|
||||
// manage incoming frames
|
||||
if (cFrameType)
|
||||
{
|
||||
if (cFrameType == FT_CCP_ACK)
|
||||
{
|
||||
/// ACK///////////////////////////////////
|
||||
CCPAck ccpAck;
|
||||
ccpAck.Load(*pStm);
|
||||
if (ccpAck.m_bAck == m_bAckExpected)
|
||||
{
|
||||
NET_TRACE("[%08X] IN [CCP] RECEIVED ACK %02d \n",::GetCurrentProcessId(), ccpAck.m_bAck?1:0);
|
||||
StopTimer();
|
||||
EnableSend();
|
||||
m_stmRetrasmissionBuffer.Reset();
|
||||
}
|
||||
/*else
|
||||
{
|
||||
HandleTimeout();
|
||||
NET_TRACE("CCCPEndpoint::Update ACK OUT OF SEQ %d\n",ccpAck.m_bAck?1:0);
|
||||
}*/
|
||||
/////////////////////////////////////////
|
||||
}
|
||||
else
|
||||
{
|
||||
/// PAYLOAD///////////////////////////////
|
||||
if (!ProcessPayload(cFrameType, *pStm))
|
||||
{
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: ProcessPayload false");
|
||||
return 0;
|
||||
}
|
||||
/////////////////////////////////////////
|
||||
}
|
||||
}
|
||||
|
||||
// manage timeouts
|
||||
ProcessTimers();
|
||||
|
||||
// manage outgoing frames
|
||||
if (m_qOutgoingData.empty() == false)
|
||||
{
|
||||
if (IsTimeToSend())
|
||||
{
|
||||
SendFrame();
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendSetup()
|
||||
{
|
||||
CCPSetup *pCCPSetup;
|
||||
pCCPSetup = new CCPSetup;
|
||||
|
||||
ICVar *cl_password = GetISystem()->GetIConsole()->GetCVar("cl_password");
|
||||
|
||||
assert(cl_password);
|
||||
|
||||
if (cl_password->GetString())
|
||||
{
|
||||
pCCPSetup->m_sPlayerPassword = cl_password->GetString();
|
||||
}
|
||||
else
|
||||
{
|
||||
pCCPSetup->m_sPlayerPassword = "";
|
||||
}
|
||||
|
||||
// Detect version 32/64bit.
|
||||
#if defined(WIN64) || defined(LINUX64)
|
||||
pCCPSetup->m_nClientFlags |= CLIENT_FLAGS_64BIT;
|
||||
#endif
|
||||
ICVar *cl_punkbuster = GetISystem()->GetIConsole()->GetCVar("cl_punkbuster");
|
||||
if (cl_punkbuster && cl_punkbuster->GetIVal() != 0)
|
||||
pCCPSetup->m_nClientFlags |= CLIENT_FLAGS_PUNK_BUSTER;
|
||||
|
||||
if (GetISystem()->WasInDevMode())
|
||||
pCCPSetup->m_nClientFlags |= CLIENT_FLAGS_DEVMODE;
|
||||
|
||||
// Detect client OS.
|
||||
#ifdef WIN32
|
||||
OSVERSIONINFO OSVerInfo;
|
||||
OSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&OSVerInfo);
|
||||
pCCPSetup->m_nClientOSMinor = OSVerInfo.dwMinorVersion;
|
||||
pCCPSetup->m_nClientOSMajor = OSVerInfo.dwMajorVersion;
|
||||
#endif
|
||||
|
||||
// pCCPSetup->m_cClientID = m_pParent->GetID();
|
||||
m_qOutgoingData.push(pCCPSetup);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendConnect(CNPServerVariables &sv)
|
||||
{
|
||||
CCPConnect *pCCPConnect;
|
||||
pCCPConnect = new CCPConnect;
|
||||
// pCCPConnect->m_cClientID = m_pParent->GetID();
|
||||
//pCCPConnect->m_cNewClientID = cClientID;
|
||||
pCCPConnect->m_ServerVariables = sv;
|
||||
pCCPConnect->m_cResponse = 0;
|
||||
|
||||
ICVar *pPunkBusterVar = GetISystem()->GetIConsole()->GetCVar("sv_punkbuster");
|
||||
|
||||
if (pPunkBusterVar && pPunkBusterVar->GetIVal() != 0)
|
||||
{
|
||||
pCCPConnect->m_cResponse |= SV_CONN_FLAG_PUNKBUSTER; // punkbuster!
|
||||
}
|
||||
|
||||
if (GetISystem()->WasInDevMode())
|
||||
{
|
||||
pCCPConnect->m_cResponse |= SV_CONN_FLAG_DEVMODE;
|
||||
}
|
||||
|
||||
m_qOutgoingData.push(pCCPConnect);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendConnectResp(CStream &stm)
|
||||
{
|
||||
CCPConnectResp *pCCPConnectResp;
|
||||
pCCPConnectResp = new CCPConnectResp();
|
||||
// pCCPConnectResp->m_cClientID = m_pParent->GetID();
|
||||
pCCPConnectResp->m_cResponse = 0;//<<FIXME>> put something more useful
|
||||
pCCPConnectResp->m_stmAuthorizationID = stm;
|
||||
m_qOutgoingData.push(pCCPConnectResp);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendContextSetup(CStream &stm)
|
||||
{
|
||||
CCPContextSetup *pCCPContextSetup;
|
||||
pCCPContextSetup = new CCPContextSetup;
|
||||
// pCCPContextSetup->m_cClientID = m_pParent->GetID();
|
||||
pCCPContextSetup->m_stmData = stm;
|
||||
m_qOutgoingData.push(pCCPContextSetup);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendContextReady(CStream &stm)
|
||||
{
|
||||
CCPContextReady *pCCPContextReady;
|
||||
pCCPContextReady = new CCPContextReady;
|
||||
// pCCPContextReady->m_cClientID = m_pParent->GetID();
|
||||
pCCPContextReady->m_stmData = stm;
|
||||
m_qOutgoingData.push(pCCPContextReady);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendServerReady()
|
||||
{
|
||||
CCPServerReady *pCCPServerReady;
|
||||
pCCPServerReady = new CCPServerReady;
|
||||
// pCCPServerReady->m_cClientID = m_pParent->GetID();
|
||||
m_qOutgoingData.push(pCCPServerReady);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendDisconnect(const char* szCause)
|
||||
{
|
||||
|
||||
CStream stm;
|
||||
CCPDisconnect *pCCPDisconnect;
|
||||
pCCPDisconnect = new CCPDisconnect;
|
||||
// pCCPDisconnect->m_cClientID = m_pParent->GetID();
|
||||
pCCPDisconnect->m_sCause = szCause;
|
||||
pCCPDisconnect->m_bSequenceNumber=0;
|
||||
|
||||
pCCPDisconnect->Save(stm);
|
||||
|
||||
//the disconnect packet is send ignoring the current state to
|
||||
//increase the chances that the other endpoint will receive it
|
||||
//the seq number is ignored by the receiver
|
||||
m_pParent->Send(stm);
|
||||
delete pCCPDisconnect;
|
||||
//m_qOutgoingData.push(pCCPDisconnect);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCCPEndpoint::SendSecurityQuery(CStream &stm)
|
||||
{
|
||||
CCPSecurityQuery *pCCP = new CCPSecurityQuery;
|
||||
pCCP->m_stmData = stm;
|
||||
m_qOutgoingData.push(pCCP);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCCPEndpoint::SendSecurityResp(CStream &stm)
|
||||
{
|
||||
CCPSecurityResp *pCCP = new CCPSecurityResp;
|
||||
pCCP->m_stmData = stm;
|
||||
m_qOutgoingData.push(pCCP);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCCPEndpoint::SendPunkBusterMsg(CStream &stm)
|
||||
{
|
||||
CCPPunkBusterMsg *pCCP = new CCPPunkBusterMsg;
|
||||
pCCP->m_stmData = stm;
|
||||
m_qOutgoingData.push(pCCP);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCCPEndpoint::ProcessTimers()
|
||||
{
|
||||
if (m_ulTimeout)
|
||||
if ((m_nCurrentTime - m_ulTimeout)>TM_BUFFER_TIMER)
|
||||
{
|
||||
m_ulTimeout = 0;
|
||||
HandleTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
void CCCPEndpoint::HandleTimeout()
|
||||
{
|
||||
NET_TRACE("[%08X]CCCPEndpoint::HandleTimeout()\n",::GetCurrentProcessId());
|
||||
///bool b;
|
||||
if(m_stmRetrasmissionBuffer.GetSize()==0)
|
||||
{
|
||||
CryError( "<CryNetworkut> (CCCPEndpoint::HandleTimeout) Empty retransmission buffer" );
|
||||
}
|
||||
m_stmRetrasmissionBuffer.Seek(0);
|
||||
m_pParent->Send(m_stmRetrasmissionBuffer);
|
||||
SetTimer();
|
||||
}
|
||||
|
||||
void PrintPacket(CCPPayload ccpPayload)
|
||||
{
|
||||
switch(ccpPayload.m_cFrameType)
|
||||
{
|
||||
case FT_CCP_SETUP:
|
||||
NET_TRACE("FT_CCP_SETUP\n");
|
||||
break;
|
||||
case FT_CCP_CONNECT:
|
||||
NET_TRACE("FT_CCP_CONNECT\n");
|
||||
break;
|
||||
case FT_CCP_CONNECT_RESP:
|
||||
NET_TRACE("FT_CCP_CONNECT_RESP\n");
|
||||
break;
|
||||
case FT_CCP_CONTEXT_SETUP:
|
||||
NET_TRACE("FT_CCP_CONTEXT_SETUP\n");
|
||||
break;
|
||||
case FT_CCP_CONTEXT_READY:
|
||||
NET_TRACE("FT_CCP_CONTEXT_READY\n");
|
||||
break;
|
||||
case FT_CCP_SERVER_READY:
|
||||
NET_TRACE("FT_CCP_SERVER_READY\n");
|
||||
break;
|
||||
case FT_CCP_DISCONNECT:
|
||||
NET_TRACE("FT_CCP_DISCONNECT\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CCCPEndpoint::ProcessPayload(unsigned char cFrameType, CStream &stmStream)
|
||||
{
|
||||
CCPPayload ccpPayload;
|
||||
ccpPayload.Load(stmStream);
|
||||
stmStream.Seek(0);
|
||||
|
||||
//the disconnect packet is a destructive packet for the connection
|
||||
//so seq number is ignored
|
||||
if(cFrameType==FT_CCP_DISCONNECT)
|
||||
{
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: FT_CCP_DISCONNECT");
|
||||
|
||||
CCPDisconnect ccpDisconnect;
|
||||
ccpDisconnect.Load(stmStream);
|
||||
m_pParent->OnCCPDisconnect(ccpDisconnect.m_sCause.c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ccpPayload.m_bSequenceNumber != m_bFrameExpected)
|
||||
{
|
||||
//SendAck(!m_bFrameExpected);
|
||||
NET_TRACE("CCCPEndpoint::ProcessPayload Packet OUT OF SEQ[%02d]\n",ccpPayload.m_bSequenceNumber?1:0);
|
||||
PrintPacket(ccpPayload);
|
||||
}else
|
||||
{
|
||||
NET_TRACE("[%08X] IN [CCP] RECEIVED %02d \n",::GetCurrentProcessId(), ccpPayload.m_bSequenceNumber?1:0);
|
||||
INC_BOOL(m_bFrameExpected);
|
||||
NET_TRACE("[%08X] FRAME EXPECTED IS NOW [CCP] %02d \n",::GetCurrentProcessId(), m_bFrameExpected?1:0);
|
||||
switch (cFrameType)
|
||||
{
|
||||
///////////////////////////////////////////////////
|
||||
case FT_CCP_SETUP:
|
||||
{
|
||||
NET_TRACE("FT_CCP_SETUP\n");
|
||||
m_pParent->OnCCPSetup(stmStream);
|
||||
}
|
||||
break;
|
||||
///////////////////////////////////////////////////
|
||||
case FT_CCP_CONNECT:
|
||||
{
|
||||
NET_TRACE("FT_CCP_CONNECT\n");
|
||||
m_pParent->OnCCPConnect(stmStream);
|
||||
}
|
||||
break;
|
||||
///////////////////////////////////////////////////
|
||||
case FT_CCP_CONNECT_RESP:
|
||||
{
|
||||
NET_TRACE("FT_CCP_CONNECT_RESP\n");
|
||||
CCPConnectResp ccpConnectResp;
|
||||
ccpConnectResp.Load(stmStream);
|
||||
m_pParent->OnCCPConnectResp(ccpConnectResp.m_stmAuthorizationID);
|
||||
}
|
||||
break;
|
||||
case FT_CCP_CONTEXT_SETUP:
|
||||
{
|
||||
NET_TRACE("FT_CCP_CONTEXT_SETUP\n");
|
||||
CCPContextSetup ccpContextSetup;
|
||||
ccpContextSetup.Load(stmStream);
|
||||
m_pParent->OnCCPContextSetup(ccpContextSetup.m_stmData);
|
||||
}
|
||||
break;
|
||||
///////////////////////////////////////////////////
|
||||
case FT_CCP_CONTEXT_READY:
|
||||
{
|
||||
NET_TRACE("FT_CCP_CONTEXT_READY\n");
|
||||
CCPContextReady ccpContextReady;
|
||||
ccpContextReady.Load(stmStream);
|
||||
m_pParent->OnCCPContextReady(ccpContextReady.m_stmData);
|
||||
}
|
||||
break;
|
||||
///////////////////////////////////////////////////
|
||||
case FT_CCP_SERVER_READY:
|
||||
{
|
||||
NET_TRACE("FT_CCP_SERVER_READY\n");
|
||||
CCPServerReady ccpServerReady;
|
||||
ccpServerReady.Load(stmStream);
|
||||
m_pParent->OnCCPServerReady();
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_CCP_SECURITY_QUERY:
|
||||
{
|
||||
CCPSecurityQuery ccpSecurQuery;
|
||||
ccpSecurQuery.Load(stmStream);
|
||||
m_pParent->OnCCPSecurityQuery( ccpSecurQuery.m_stmData );
|
||||
}
|
||||
break;
|
||||
case FT_CCP_SECURITY_RESP:
|
||||
{
|
||||
CCPSecurityQuery ccpSecurResp;
|
||||
ccpSecurResp.Load(stmStream);
|
||||
m_pParent->OnCCPSecurityResp( ccpSecurResp.m_stmData );
|
||||
}
|
||||
break;
|
||||
case FT_CCP_PUNK_BUSTER_MSG:
|
||||
{
|
||||
CCPPunkBusterMsg ccpPBMsg;
|
||||
ccpPBMsg.Load(stmStream);
|
||||
m_pParent->OnCCPPunkBusterMsg( ccpPBMsg.m_stmData );
|
||||
}
|
||||
break;
|
||||
///////////////////////////////////////////////////
|
||||
/*case FT_CCP_DISCONNECT:
|
||||
{
|
||||
::OutputDebugString("FT_CCP_DISCONNECT\n");
|
||||
CCPDisconnect ccpDisconnect;
|
||||
ccpDisconnect.Load(stmStream);
|
||||
m_pParent->OnCCPDisconnect(ccpDisconnect.m_sCause.c_str());
|
||||
}
|
||||
break;*/
|
||||
///////////////////////////////////////////////////
|
||||
default:
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: cFrameType %d",(int)cFrameType);
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
///////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
SendAck(ccpPayload.m_bSequenceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CCCPEndpoint::EnableSend()
|
||||
{
|
||||
NET_TRACE("[%08X] SEND ENABLED\n",::GetCurrentProcessId());
|
||||
m_bReadyToSend = true;
|
||||
}
|
||||
|
||||
void CCCPEndpoint::DisableSend()
|
||||
{
|
||||
NET_TRACE("[%08X] SEND DISABLED\n",::GetCurrentProcessId());
|
||||
m_bReadyToSend = false;
|
||||
}
|
||||
|
||||
bool CCCPEndpoint::IsTimeToSend()
|
||||
{
|
||||
return m_bReadyToSend;
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendFrame()
|
||||
{
|
||||
CStream stm;
|
||||
CCPPayload *pCCPPayload;
|
||||
pCCPPayload = m_qOutgoingData.front();
|
||||
pCCPPayload->m_bSequenceNumber = m_bNextFrameToSend;
|
||||
pCCPPayload->Save(stm);
|
||||
|
||||
m_qOutgoingData.pop();
|
||||
m_stmRetrasmissionBuffer = stm;
|
||||
m_pParent->Send(stm);
|
||||
SetTimer();
|
||||
NET_TRACE("[%08X] OUT [CCP] SENDING %02d \n",::GetCurrentProcessId(), pCCPPayload->m_bSequenceNumber?1:0);
|
||||
delete pCCPPayload;
|
||||
|
||||
INC_BOOL(m_bNextFrameToSend);
|
||||
INC_BOOL(m_bAckExpected);
|
||||
DisableSend();
|
||||
}
|
||||
|
||||
void CCCPEndpoint::SendAck(bool bSequenceNumber)
|
||||
{
|
||||
CStream stm;
|
||||
CCPAck ccpAck;
|
||||
ccpAck.m_bAck = bSequenceNumber;
|
||||
// ccpAck.m_cClientID = m_pParent->GetID();
|
||||
ccpAck.Save(stm);
|
||||
////////////////////////
|
||||
NET_TRACE("[%08X] OUT [CCP] ACK SEQ %02d\n",::GetCurrentProcessId(), ccpAck.m_bAck);
|
||||
////////////////////////
|
||||
m_pParent->Send(stm);
|
||||
}
|
||||
|
||||
void CCCPEndpoint::GetMemoryStatistics(ICrySizer *pSizer)
|
||||
{
|
||||
pSizer->AddObject(&m_qOutgoingData,m_qOutgoingData.size()*sizeof(CStream));
|
||||
}
|
||||
92
CryNetwork/CCPEndpoint.h
Normal file
92
CryNetwork/CCPEndpoint.h
Normal file
@@ -0,0 +1,92 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: CCPEndpoint.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _CCPENDPOINT_H_
|
||||
#define _CCPENDPOINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "Stream.h"
|
||||
#include "CNP.h"
|
||||
#include "Interfaces.h"
|
||||
#include <queue>
|
||||
|
||||
#define INC_BOOL(xxx) xxx=!(xxx)
|
||||
#define TM_BUFFER_TIMER 1000
|
||||
|
||||
typedef std::queue<CCPPayload *> CCP_QUEUE;
|
||||
|
||||
class CCCPEndpoint
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CCCPEndpoint();
|
||||
//! destructor
|
||||
virtual ~CCCPEndpoint();
|
||||
|
||||
//!
|
||||
void Init( _ICCPUser *pParent );
|
||||
|
||||
void SendDisconnect(const char* szCause);
|
||||
void SendConnectResp(CStream &stm);
|
||||
void SendContextSetup(CStream &stm);
|
||||
void SendContextReady(CStream &stm);
|
||||
void SendServerReady();
|
||||
void SendConnect(CNPServerVariables &sv);
|
||||
void SendSetup();
|
||||
void SendPunkBusterMsg(CStream &stm);
|
||||
|
||||
void SendSecurityQuery(CStream &stm);
|
||||
void SendSecurityResp(CStream &stm);
|
||||
void SetPublicCryptKey( unsigned int nKey ) { m_nPublicKey = nKey; };
|
||||
unsigned int GetPublicCryptKey( unsigned int nKey ) { return m_nPublicKey; };
|
||||
|
||||
//! @return true=disconnect and this pointer is destrozed, false otherwise
|
||||
bool Update(unsigned int nTime,unsigned char cFrameType,CStream *pStm);
|
||||
void Reset();
|
||||
|
||||
void GetMemoryStatistics(ICrySizer *pSizer);
|
||||
protected:
|
||||
|
||||
//! @return true=disconnect and this pointer is destrozed, false otherwise
|
||||
bool ProcessPayload(unsigned char cFrameType,CStream &stmStrea);
|
||||
void HandleTimeout();
|
||||
void ProcessTimers();
|
||||
void SetTimer();
|
||||
void StopTimer();
|
||||
void SendFrame();
|
||||
void EnableSend();
|
||||
void DisableSend();
|
||||
void SendAck(bool bSequenceNumber);
|
||||
bool IsTimeToSend();
|
||||
|
||||
private: // --------------------------------------------------------------
|
||||
|
||||
bool m_bFrameExpected; //!<
|
||||
bool m_bNextFrameToSend; //!<
|
||||
bool m_bAckExpected; //!<
|
||||
bool m_bReadyToSend; //!<
|
||||
unsigned int m_ulTimeout; //!<
|
||||
|
||||
_ICCPUser * m_pParent; //!< pointer to the parent object (is not released), is 0 is you forgot to call Init()
|
||||
|
||||
CCP_QUEUE m_qOutgoingData; //!<
|
||||
CStream m_stmRetrasmissionBuffer; //!<
|
||||
|
||||
unsigned int m_nCurrentTime; //!<
|
||||
unsigned int m_nPublicKey;
|
||||
};
|
||||
|
||||
#endif //_CCPENDPOINT_H_
|
||||
762
CryNetwork/CNP.h
Normal file
762
CryNetwork/CNP.h
Normal file
@@ -0,0 +1,762 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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_
|
||||
826
CryNetwork/CTPEndpoint.cpp
Normal file
826
CryNetwork/CTPEndpoint.cpp
Normal file
@@ -0,0 +1,826 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: CTPEndpoint.cpp
|
||||
// Description: non-sequential receive protocol
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CTPEndpoint.h"
|
||||
#include "IDataProbe.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool Between(LONG a, LONG b, LONG c)
|
||||
{
|
||||
return ((a <= b) &&(b < c)) ||((c < a) &&(a <= b)) ||((b < c) &&(c < a));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! constructor!
|
||||
CCTPEndpoint::CCTPEndpoint()
|
||||
{
|
||||
Reset();
|
||||
SetRate(10000);
|
||||
m_nSnaps = 20;
|
||||
m_nEncryptKey[0] = 1714732178u;
|
||||
m_nEncryptKey[1] = 2157124251u;
|
||||
m_nEncryptKey[2] = 3766711231u;
|
||||
m_nEncryptKey[3] = 715376114u;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! destructor!!
|
||||
CCTPEndpoint::~CCTPEndpoint()
|
||||
{
|
||||
}
|
||||
|
||||
void CCTPEndpoint::SetPublicCryptKey( unsigned int key )
|
||||
{
|
||||
m_nEncryptKey[1] = key;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! set the average rate of the outgoing stream
|
||||
void CCTPEndpoint::SetRate(unsigned int nBytePerSec)
|
||||
{
|
||||
m_nRate = nBytePerSec;
|
||||
m_fBytePerMillisec = ((float)m_nRate)/1000.0f;
|
||||
NET_TRACE("BYTES per MILLISEC=%f\n", m_fBytePerMillisec);
|
||||
m_nAllowedBytes = m_nRate;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! set all varible to the initial state
|
||||
void CCTPEndpoint::Reset()
|
||||
{
|
||||
//memset(m_nArrived, 0, sizeof(m_nArrived));
|
||||
m_nFrameExpected = 0;
|
||||
m_nNextFrameToSend = 0;
|
||||
m_nTooFar = NUM_OF_BUFS;
|
||||
m_bNoNak = true;
|
||||
m_nAckExpected = 0;
|
||||
m_nBuffered = 0;
|
||||
m_nLostPackets = 0;
|
||||
m_dwOutAckTimer = 0;
|
||||
//memset(m_dwTimers, 0, sizeof(m_dwTimers));
|
||||
for (int n = 0; n < NUM_OF_BUFS; n++)
|
||||
{
|
||||
m_OutBuffers[n].dwTimeout = 0;
|
||||
m_OutBuffers[n].nSeq = 0;
|
||||
m_nArrived[n]=false;
|
||||
}
|
||||
|
||||
while (!m_qOutgoingReliableData.empty())
|
||||
{
|
||||
m_qOutgoingReliableData.pop();
|
||||
}
|
||||
while (!m_qOutgoingUnreliableData.empty())
|
||||
{
|
||||
m_qOutgoingUnreliableData.pop();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! called for every FT_DATA (CTPData)
|
||||
void CCTPEndpoint::HandleDataFrame(CTPData &f)
|
||||
{
|
||||
CStream stmUncompressed;
|
||||
if(f.m_bUnreliable)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//UNRELIABLE PACKET
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//if the packet is out of sequence will be discarded
|
||||
if(f.m_cSequenceNumber==m_nFrameExpected)
|
||||
{
|
||||
// CStream stmUncompressed=UncompressStream(f.m_stmData);
|
||||
// m_pParent->OnData(stmUncompressed);
|
||||
UncyptStream( f.m_stmData );
|
||||
|
||||
m_pParent->OnData(f.m_stmData);
|
||||
}
|
||||
else{
|
||||
NET_TRACE("[%02d]expected-[%02d]received Packet discarded\n",m_nFrameExpected,f.m_cSequenceNumber);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//RELIABLE PACKET
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if there is a possible packet loss send a negative acknoledge (FT_NAK)
|
||||
if ((f.m_cSequenceNumber != m_nFrameExpected) && m_bNoNak)
|
||||
{
|
||||
//<<FIXME>> re enable the following two lines to enable NAKs
|
||||
NET_TRACE("NAK !!! f.m_cSequanceNumber=%02d m_nFrameExpected=%02d\n", f.m_cSequenceNumber, m_nFrameExpected);
|
||||
SendFrame(FT_CTP_NAK, 0, m_nFrameExpected);
|
||||
}
|
||||
else
|
||||
SetAckTimer();
|
||||
if (Between(m_nFrameExpected, f.m_cSequenceNumber, m_nTooFar) &&(m_nArrived[f.m_cSequenceNumber%NUM_OF_BUFS] == false))
|
||||
{
|
||||
// FRAME ACCEPTED
|
||||
NET_TRACE("FRAME ACCEPTED %02d\n",f.m_cSequenceNumber);
|
||||
m_nArrived[f.m_cSequenceNumber%NUM_OF_BUFS] = true;
|
||||
m_stmInBuffers[f.m_cSequenceNumber%NUM_OF_BUFS] = f.m_stmData;
|
||||
|
||||
while (m_nArrived[m_nFrameExpected%NUM_OF_BUFS])
|
||||
{
|
||||
NET_TRACE("ARRIVED %02d\n",m_nFrameExpected%NUM_OF_BUFS);
|
||||
// CStream stmUncompressed=UncompressStream(m_stmInBuffers[m_nFrameExpected%NUM_OF_BUFS]);
|
||||
// m_pParent->OnData(stmUncompressed);
|
||||
UncyptStream( m_stmInBuffers[m_nFrameExpected%NUM_OF_BUFS] );
|
||||
m_pParent->OnData(m_stmInBuffers[m_nFrameExpected%NUM_OF_BUFS]);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
m_bNoNak = true;
|
||||
m_nArrived[m_nFrameExpected%NUM_OF_BUFS] = false; // set buffer flag to false
|
||||
|
||||
NET_TRACE("m_nFrameExpected=%02d\n",m_nFrameExpected);
|
||||
INC(m_nFrameExpected);
|
||||
INC(m_nTooFar);
|
||||
SetAckTimer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NET_TRACE("received out of window frame (%d)\n",f.m_cSequenceNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! called every incoming NAK (this code perform packet retrasmission)
|
||||
void CCTPEndpoint::HandleNak(CTPNak &f)
|
||||
{
|
||||
if (Between(m_nAckExpected, (f.m_cAck + 1)%(MAX_SEQ_NUM + 1), m_nNextFrameToSend))
|
||||
{
|
||||
m_nLostPackets++;
|
||||
SendFrame(FT_CTP_DATA, (f.m_cAck + 1)%(MAX_SEQ_NUM + 1), m_nNextFrameToSend);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CCTPEndpoint::Dump()
|
||||
{
|
||||
NET_TRACE("m_nTooFar=%d |||", m_nTooFar);
|
||||
NET_TRACE("m_nFrameExpected=%d |||", m_nFrameExpected);
|
||||
NET_TRACE("m_nBuffered=%d |||", m_nBuffered);
|
||||
NET_TRACE("m_nAckExpected=%d |||", m_nAckExpected);
|
||||
NET_TRACE("m_nNextFrameToSend=%d\n", m_nNextFrameToSend);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! main loop of the class
|
||||
void CCTPEndpoint::Update(unsigned int nTime, unsigned char cFrameType, CStream *pStm)
|
||||
{
|
||||
m_nCurrentTime = nTime;
|
||||
// if there is a incoming frame
|
||||
CTP *pFrame = NULL;
|
||||
CTPAck ack;
|
||||
CTPData data;
|
||||
CTPNak nak;
|
||||
CTPPong pong;
|
||||
|
||||
if (cFrameType)
|
||||
{
|
||||
switch (cFrameType)
|
||||
{
|
||||
case FT_CTP_DATA:
|
||||
{
|
||||
data.Load(*pStm);
|
||||
pFrame = &data;
|
||||
HandleDataFrame(data);
|
||||
}
|
||||
break;
|
||||
case FT_CTP_NAK:
|
||||
{
|
||||
nak.Load(*pStm);
|
||||
pFrame = &nak;
|
||||
HandleNak(nak);
|
||||
}
|
||||
break;
|
||||
case FT_CTP_ACK:
|
||||
{
|
||||
pFrame = &ack;
|
||||
ack.Load(*pStm);
|
||||
}
|
||||
break;
|
||||
case FT_CTP_PONG:
|
||||
{
|
||||
pong.Load(*pStm);
|
||||
m_LatencyCalculator.AddSample((float)m_nCurrentTime - m_dwPingTime, m_nCurrentTime, pong.m_nTimestamp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
if (pFrame)
|
||||
{
|
||||
if (pFrame->m_bPingRequest == true)
|
||||
{
|
||||
CStream stm;
|
||||
CTPPong pong;
|
||||
// pong.m_cClientID = m_pParent->GetID();
|
||||
pong.m_nTimestamp = m_nCurrentTime;
|
||||
pong.Save(stm);
|
||||
m_pParent->Send(stm);
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
// manage piggybacked ack (all frames hold a piggybacked ack)
|
||||
|
||||
NET_TRACE("--->>>[CTP] SEQ %02d ACK %02d\n", pFrame->m_cSequenceNumber, pFrame->m_cAck);
|
||||
|
||||
if(!pFrame->m_bUnreliable)
|
||||
while (Between(m_nAckExpected, pFrame->m_cAck, m_nNextFrameToSend))
|
||||
{
|
||||
|
||||
m_nBuffered = m_nBuffered - 1;
|
||||
NET_TRACE("Ack [%02d] STOPPING TIMER m_nBuffered=%02d\n",pFrame->m_cAck,m_nBuffered);
|
||||
StopTimer(m_nAckExpected%NUM_OF_BUFS);
|
||||
INC(m_nAckExpected);
|
||||
}
|
||||
}
|
||||
}
|
||||
// handle outgoing buffer timers
|
||||
ProcessBufferTimers();
|
||||
|
||||
// if there is some out-buffer free, I retrive some new data to send
|
||||
// and if the network layer is ready(enough bandwith) ...send outgoing frames
|
||||
if (IsTimeToSend())
|
||||
{
|
||||
BuildOutgoingFrame();
|
||||
}
|
||||
// handle ack timer
|
||||
ProcessAckTimer();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! set the ack timer timeout
|
||||
//! NOTE: if there aren't outgoing data packets for several time
|
||||
//! the protocol will transmit an "ack dedicated" packet(FT_CTP_ACK)
|
||||
//! this is the timer to guard this condition
|
||||
void CCTPEndpoint::SetAckTimer()
|
||||
{
|
||||
if (m_dwOutAckTimer == 0)
|
||||
m_dwOutAckTimer = m_nCurrentTime;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! stop the ack timer
|
||||
void CCTPEndpoint::StopAckTimer()
|
||||
{
|
||||
m_dwOutAckTimer = 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! set packet retrasmisson timeout
|
||||
void CCTPEndpoint::SetTimer(LONG nIndex)
|
||||
{
|
||||
// if(m_OutBuffers[nIndex].dwTimeout!=0)
|
||||
// DEBUG_BREAK;
|
||||
m_OutBuffers[nIndex].dwTimeout = m_nCurrentTime;
|
||||
NET_TRACE("SETTIMER %02d %d\n",nIndex,m_nCurrentTime);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! stop packet retrasmisson timeout
|
||||
void CCTPEndpoint::StopTimer(LONG nIndex)
|
||||
{
|
||||
DWORD nTimeout = m_OutBuffers[nIndex].dwTimeout;
|
||||
m_OutBuffers[nIndex].dwTimeout=0;
|
||||
// PING STUFF
|
||||
// m_ulPingCounter+=m_nCurrentTime-m_OutBuffers[nIndex].dwTimeout;
|
||||
// m_ulSamplesNum++;
|
||||
// End of ping stuff
|
||||
/*for (int n = 0; n < NUM_OF_BUFS; n++)
|
||||
{
|
||||
if (m_OutBuffers[n].dwTimeout <= nTimeout)
|
||||
m_OutBuffers[n].dwTimeout = 0;
|
||||
}*/
|
||||
NET_TRACE("STOPTIMER %02d %d\n",nIndex,nTimeout);
|
||||
}
|
||||
|
||||
void CCTPEndpoint::CryptStream( CStream &stm )
|
||||
{
|
||||
/*
|
||||
IDataProbe *pProbe = GetISystem()->GetIDataProbe();
|
||||
char temp[2048];
|
||||
//int len = stm.
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
unsigned int destLen = 2048;
|
||||
pProbe->Compress( temp,destLen,pBuffer,stm.GetSize()*8 );
|
||||
int len = TEA_GETSIZE(stm.GetSize()*8);
|
||||
//TEA_ENCODE( pBuffer,pBuffer,len,m_nEncryptKey );
|
||||
CryLogAlways( "Stream Size: %.6d/%.6d",stm.GetSize()*8,destLen );
|
||||
pProbe->Release();
|
||||
*/
|
||||
}
|
||||
|
||||
void CCTPEndpoint::UncyptStream( CStream &stm )
|
||||
{
|
||||
/*
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
int len = TEA_GETSIZE(stm.GetSize()*8);
|
||||
//TEA_DECODE( pBuffer,pBuffer,len,m_nEncryptKey );
|
||||
*/
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! push a reliable stream in the outgoing queue
|
||||
bool CCTPEndpoint::SendReliable(CStream &stmData)
|
||||
{
|
||||
//if(m_qOutgoingReliableData.size()>MAX_QUEUED_PACKET_PER_CHANNEL)
|
||||
// return false;
|
||||
CryptStream( stmData );
|
||||
m_qOutgoingReliableData.push(stmData);
|
||||
return true;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! push an UNreliable stream in the outgoing queue
|
||||
bool CCTPEndpoint::SendUnreliable(CStream &stmData)
|
||||
{
|
||||
//if(m_qOutgoingUnreliableData.size()>MAX_QUEUED_PACKET_PER_CHANNEL)
|
||||
// return false;
|
||||
CryptStream( stmData );
|
||||
m_qOutgoingUnreliableData.push(stmData);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
void MTFEncode(BYTE *pDest,BYTE *pSource,int nSize)
|
||||
{
|
||||
unsigned char order[ 256 ];
|
||||
int i,c,count;
|
||||
|
||||
for ( i = 0 ; i < 256 ; i++ )
|
||||
{
|
||||
order[ i ] = (unsigned char) i;
|
||||
}
|
||||
|
||||
for(count=0;count<nSize;count++)
|
||||
{
|
||||
c=pSource[count];
|
||||
|
||||
//
|
||||
// Find the char, and output it
|
||||
//
|
||||
for ( i = 0 ; i < 256 ; i++ )
|
||||
{
|
||||
if ( order[ i ] == ( c & 0xff ) )
|
||||
break;
|
||||
}
|
||||
//putc( (char) i, stdout );
|
||||
pDest[count]=i;
|
||||
//
|
||||
// Now shuffle the order array
|
||||
//
|
||||
for ( int j = i ; j > 0 ; j-- )
|
||||
{
|
||||
order[ j ] = order[ j - 1 ];
|
||||
}
|
||||
order[ 0 ] = (unsigned char) c;
|
||||
}
|
||||
}
|
||||
|
||||
void MTFDecode(BYTE *pDest,BYTE *pSource,int nSize)
|
||||
{
|
||||
|
||||
unsigned char order[ 256 ];
|
||||
int i,c,count;
|
||||
|
||||
for ( i = 0 ; i < 256 ; i++ )
|
||||
{
|
||||
order[ i ] = (unsigned char) i;
|
||||
}
|
||||
|
||||
for(count=0;count<nSize;count++)
|
||||
{
|
||||
i=pSource[count];
|
||||
|
||||
//
|
||||
// Find the char
|
||||
//
|
||||
//putc( order[ i ], stdout );
|
||||
pDest[count]=order[i];
|
||||
c = order[ i ];
|
||||
//
|
||||
// Now shuffle the order array
|
||||
//
|
||||
int j;
|
||||
for ( j = i ; j > 0 ; j-- )
|
||||
{
|
||||
order[ j ] = order[ j - 1 ];
|
||||
}
|
||||
order[ 0 ] = (unsigned char) c;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
CStream CCTPEndpoint::CompressStream(CStream &stmUncompressed)
|
||||
{
|
||||
CStream stmCompressed;
|
||||
#ifdef USE_PACKET_COMPRESSION
|
||||
BYTE *pUncompressed=NULL;
|
||||
pUncompressed=stmUncompressed.GetPtr();
|
||||
unsigned short nUncompressedSizeInBits=stmUncompressed.GetSize();
|
||||
unsigned short nUncompressedSize=BITS2BYTES(nUncompressedSizeInBits);
|
||||
unsigned short n=0;
|
||||
stmCompressed.Write(nUncompressedSizeInBits);
|
||||
while(n<nUncompressedSize)
|
||||
{
|
||||
BYTE b;
|
||||
|
||||
b=pUncompressed[n];
|
||||
if(b==0)
|
||||
{
|
||||
//write a 0
|
||||
stmCompressed.Write(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//write a 1
|
||||
stmCompressed.Write(true);
|
||||
//write a byte
|
||||
stmCompressed.Write(b);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
#else
|
||||
stmCompressed=stmUncompressed;
|
||||
#endif
|
||||
return stmCompressed;
|
||||
}
|
||||
|
||||
CStream CCTPEndpoint::UncompressStream(CStream &stmCompressed)
|
||||
{
|
||||
CStream stmUncompressed;
|
||||
#ifdef USE_PACKET_COMPRESSION
|
||||
unsigned short nUncompressedSize;
|
||||
stmUncompressed.Reset();
|
||||
stmCompressed.Read(nUncompressedSize);
|
||||
while(!stmCompressed.EOS())
|
||||
{
|
||||
bool bBit;
|
||||
BYTE bData;
|
||||
stmCompressed.Read(bBit);
|
||||
if(bBit)
|
||||
{
|
||||
stmCompressed.Read(bData);
|
||||
}
|
||||
else
|
||||
{
|
||||
bData=0;
|
||||
}
|
||||
stmUncompressed.Write(bData);
|
||||
if(stmUncompressed.GetSize()==nUncompressedSize)
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
stmUncompressed=stmCompressed;
|
||||
#endif
|
||||
return stmUncompressed;
|
||||
}
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! format and send a frame(FT_DATA or FT_ACK or FT_NAK)
|
||||
void CCTPEndpoint::SendFrame(LONG nType, LONG nFrameNum, LONG nFrameExpected, CStream *pUnreliable,bool bUnreliable)
|
||||
{
|
||||
// Dump();
|
||||
CStream stmUncompressed;
|
||||
|
||||
static BYTE cUncompressed[1000];
|
||||
CStream stm;
|
||||
CTPData data;
|
||||
CTPAck ack;
|
||||
CTPNak nak;
|
||||
CTP *pFrame;
|
||||
switch (nType)
|
||||
{
|
||||
case FT_CTP_DATA:
|
||||
pFrame = &data;
|
||||
break;
|
||||
case FT_CTP_ACK:
|
||||
pFrame = &ack;
|
||||
break;
|
||||
case FT_CTP_NAK:
|
||||
pFrame = &nak;
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
// pFrame->m_cClientID = m_pParent->GetID();
|
||||
pFrame->m_cFrameType =(BYTE) nType;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//DATA
|
||||
//////////////////////////////////////////////////////////////////
|
||||
if (nType == FT_CTP_DATA)
|
||||
{
|
||||
if(!bUnreliable)
|
||||
{
|
||||
stmUncompressed = m_OutBuffers[nFrameNum%NUM_OF_BUFS].stmData;
|
||||
m_OutBuffers[nFrameNum%NUM_OF_BUFS].nSeq = nFrameNum;
|
||||
if (pUnreliable)
|
||||
{
|
||||
if(pUnreliable->GetSize())
|
||||
stmUncompressed.Write(*pUnreliable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stmUncompressed=*pUnreliable;
|
||||
}
|
||||
//pack the stream with RLE
|
||||
// data.m_stmData=CompressStream(stmUncompressed);
|
||||
data.m_stmData=stmUncompressed;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//SEQ AND ACK
|
||||
pFrame->m_bUnreliable = bUnreliable;
|
||||
|
||||
pFrame->m_cSequenceNumber =(BYTE) nFrameNum;
|
||||
|
||||
pFrame->m_cAck =(BYTE) (nFrameExpected + MAX_SEQ_NUM)%(MAX_SEQ_NUM + 1);
|
||||
|
||||
if(nType == FT_CTP_DATA)
|
||||
{
|
||||
NET_TRACE("SEND [CTP] %s FRAME SEQ [%02d] ACK [%02d] \n",pFrame->m_bUnreliable?"unreliable":"reliable",pFrame->m_cSequenceNumber,pFrame->m_cAck);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//NAK
|
||||
if (nType == FT_CTP_NAK)
|
||||
m_bNoNak = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//CHECK IF A PING REQUEST IS NEEDED
|
||||
if (m_LatencyCalculator.IsTimeToPing(m_nCurrentTime))
|
||||
{
|
||||
m_dwPingTime = m_nCurrentTime;
|
||||
// set a piggybacked pong request
|
||||
pFrame->m_bPingRequest = true;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//SERIALIZE THE FRAME
|
||||
pFrame->Save(stm);
|
||||
m_pParent->Send(stm);
|
||||
|
||||
// Update the rate control
|
||||
m_nAllowedBytes -= BITS2BYTES(stm.GetSize());
|
||||
m_nLastPacketSent = m_nCurrentTime;
|
||||
// NET_TRACE(">>m_nAllowedBytes=%d\n",m_nAllowedBytes);
|
||||
|
||||
//////////////////////////////////////////
|
||||
if (nType == FT_CTP_DATA && (!bUnreliable))
|
||||
SetTimer(nFrameNum%NUM_OF_BUFS);
|
||||
|
||||
if(!bUnreliable)
|
||||
StopAckTimer();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! handle a buffer timeout (see SetTimer)
|
||||
void CCTPEndpoint::HandleTimeout(LONG nOldestFrame)
|
||||
{
|
||||
NET_TRACE("HandleTimeout()\n");
|
||||
m_nLostPackets++;
|
||||
if (m_nBuffered)
|
||||
SendFrame(FT_CTP_DATA, nOldestFrame, m_nFrameExpected);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! handle an ack timeout (see SetAckTimer)
|
||||
void CCTPEndpoint::HandleAckTimeout()
|
||||
{
|
||||
NET_TRACE("HandleAckTimeout()\n");
|
||||
SendFrame(FT_CTP_ACK, 0, m_nFrameExpected);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! check "the clock" for a possible buffers timer expiration
|
||||
void CCTPEndpoint::ProcessBufferTimers()
|
||||
{
|
||||
unsigned int ulTick = m_nCurrentTime;
|
||||
DWORD nLowest = 0xFFFFFFFF;
|
||||
DWORD nLowestIdx;
|
||||
bool bFound = false;
|
||||
// search for the oldest timer
|
||||
for (int n = 0; n < NUM_OF_BUFS; n++)
|
||||
{
|
||||
if ((m_OutBuffers[n].dwTimeout != 0) &&(m_OutBuffers[n].dwTimeout < nLowest))
|
||||
{
|
||||
bFound = true;
|
||||
nLowest = m_OutBuffers[n].dwTimeout;
|
||||
nLowestIdx = n;
|
||||
}
|
||||
}
|
||||
// test the oldest timer
|
||||
if (bFound)
|
||||
{
|
||||
if ((ulTick - nLowest)>(TM_BUFFER + m_LatencyCalculator.GetAverageLatency()))
|
||||
{
|
||||
/////////////////////////////////
|
||||
m_OutBuffers[nLowestIdx].dwTimeout = 0;
|
||||
HandleTimeout(m_OutBuffers[nLowestIdx].nSeq);
|
||||
}
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! check "the clock" for a possible ack timer expiration
|
||||
void CCTPEndpoint::ProcessAckTimer()
|
||||
{
|
||||
// Process Ack timeout
|
||||
unsigned int ulTick = m_nCurrentTime;
|
||||
/////////////////////////////////
|
||||
if (m_dwOutAckTimer)
|
||||
{
|
||||
if ((ulTick - m_dwOutAckTimer)>(TM_ACK + m_LatencyCalculator.GetAverageLatency()))
|
||||
{
|
||||
HandleAckTimeout();
|
||||
m_dwOutAckTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int CCTPEndpoint::GetPing()
|
||||
{
|
||||
return (unsigned int)m_LatencyCalculator.GetAverageLatency();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Client logic
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//! return true if is time to send something
|
||||
bool CCTPClient::IsTimeToSend()
|
||||
{
|
||||
static int dwTimer = 0;
|
||||
// is there a free slot?
|
||||
if (m_nBuffered < NUM_OF_BUFS)
|
||||
{
|
||||
return true;
|
||||
/*if ((m_nCurrentTime - dwTimer)>30)
|
||||
{
|
||||
dwTimer = m_nCurrentTime;
|
||||
return true;
|
||||
}
|
||||
return false; */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! build a data frame from the outgoing queue
|
||||
void CCTPEndpoint::BuildOutgoingFrame()
|
||||
{
|
||||
if (m_qOutgoingReliableData.empty() == false || m_qOutgoingUnreliableData.empty() == false)
|
||||
{
|
||||
CStream stmUnreliable;
|
||||
|
||||
m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.Reset();
|
||||
while ((m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.GetSize() < MAX_PLAYLOAD_SIZE_IN_BITS) && (!m_qOutgoingReliableData.empty()))
|
||||
{
|
||||
m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.Write(m_qOutgoingReliableData.front());
|
||||
m_qOutgoingReliableData.pop();
|
||||
}
|
||||
while ((m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.GetSize() < MAX_PLAYLOAD_SIZE_IN_BITS) && (!m_qOutgoingUnreliableData.empty()))
|
||||
{
|
||||
stmUnreliable.Write(m_qOutgoingUnreliableData.front());
|
||||
m_qOutgoingUnreliableData.pop();
|
||||
}
|
||||
//CHECK IF THERE IS RELIABLE DATA IN THE QUEUE
|
||||
if(m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.GetSize()>0)
|
||||
{
|
||||
SendFrame(FT_CTP_DATA, m_nNextFrameToSend, m_nFrameExpected, &stmUnreliable,false);
|
||||
INC(m_nNextFrameToSend);
|
||||
m_nBuffered += 1;
|
||||
NET_ASSERT(m_nBuffered<=NUM_OF_BUFS);
|
||||
NET_TRACE("SEND RELIABLE m_nBuffered=%02d\n",m_nBuffered);
|
||||
}
|
||||
else
|
||||
{
|
||||
//IF THERE ISN'T RELIABLE DATA SEND A UNRELIABLE ONLY PACKET
|
||||
//IF THERE IS UNRELIABLE DATA
|
||||
if(stmUnreliable.GetSize()>0)
|
||||
{
|
||||
SendFrame(FT_CTP_DATA, m_nNextFrameToSend, m_nFrameExpected, &stmUnreliable,true);
|
||||
NET_TRACE("SEND UNRELIABLE\n");
|
||||
} }
|
||||
|
||||
}
|
||||
//<<FIXME>> write some stuff to polulate a packet
|
||||
//<<FIXME>> remember never put unreliable data in the retrasmission buffer(m_OutBuffer)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Server logic
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//! return true if is time to send something
|
||||
//#define RATE_CONTROL
|
||||
bool CCTPServer::IsTimeToSend()
|
||||
{
|
||||
#ifdef RATE_CONTROL
|
||||
static dwTimer = 0;
|
||||
|
||||
m_nAllowedBytes += (int)((m_fBytePerMillisec)*(m_nCurrentTime - m_nLastPacketSent));
|
||||
if (m_nAllowedBytes>(int)m_nRate)
|
||||
m_nAllowedBytes =(int)m_nRate;
|
||||
|
||||
|
||||
if (m_nAllowedBytes>((int)(m_nRate/m_nSnaps)))
|
||||
{
|
||||
return true;
|
||||
}//<<FIXME>>
|
||||
return false;
|
||||
#else
|
||||
static int dwTimer = 0;
|
||||
// is there a free slot?
|
||||
if (m_nBuffered < NUM_OF_BUFS)
|
||||
{
|
||||
return true;
|
||||
/*if ((m_nCurrentTime - dwTimer)>30)
|
||||
{
|
||||
dwTimer = m_nCurrentTime;
|
||||
return true;
|
||||
}
|
||||
return false; */
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! build a data frame from the outgoing queue
|
||||
void CCTPServer::BuildOutgoingFrame()
|
||||
{
|
||||
if (m_qOutgoingReliableData.empty() == false || m_qOutgoingUnreliableData.empty() == false)
|
||||
{
|
||||
CStream stmUnreliable;
|
||||
|
||||
m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.Reset();
|
||||
while ((m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.GetSize() < MAX_PLAYLOAD_SIZE_IN_BITS) && (!m_qOutgoingReliableData.empty()))
|
||||
{
|
||||
m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.Write(m_qOutgoingReliableData.front());
|
||||
m_qOutgoingReliableData.pop();
|
||||
}
|
||||
while ((m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.GetSize() < MAX_PLAYLOAD_SIZE_IN_BITS) && (!m_qOutgoingUnreliableData.empty()))
|
||||
{
|
||||
stmUnreliable.Write(m_qOutgoingUnreliableData.front());
|
||||
m_qOutgoingUnreliableData.pop();
|
||||
}
|
||||
//CHECK IF THERE IS RELIABLE DATA IN THE QUEUE
|
||||
if(m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData.GetSize()>0)
|
||||
{
|
||||
SendFrame(FT_CTP_DATA, m_nNextFrameToSend, m_nFrameExpected, &stmUnreliable,false);
|
||||
INC(m_nNextFrameToSend);
|
||||
m_nBuffered += 1;
|
||||
NET_ASSERT(m_nBuffered<=NUM_OF_BUFS);
|
||||
NET_TRACE("SEND RELIABLE m_nBuffered=%02d\n",m_nBuffered);
|
||||
}
|
||||
else
|
||||
{
|
||||
//IF THERE ISN'T RELIABLE DATA SEND A UNRELIABLE ONLY PACKET
|
||||
//IF THERE IS UNRELIABLE DATA
|
||||
if(stmUnreliable.GetSize()>0)
|
||||
{
|
||||
SendFrame(FT_CTP_DATA, m_nNextFrameToSend, m_nFrameExpected, &stmUnreliable,true);
|
||||
NET_TRACE("SEND UNRELIABLE\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//<<FIXME>> write some stuff to polulate a packet
|
||||
//<<FIXME>> remember never put unreliable data in the retrasmission buffer(m_OutBuffer)
|
||||
}
|
||||
*/
|
||||
150
CryNetwork/CTPEndpoint.h
Normal file
150
CryNetwork/CTPEndpoint.h
Normal file
@@ -0,0 +1,150 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: CTPEndpoint.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if !defined(AFX_CTPENDPOINT_H__F28737F3_12B9_4394_B63C_7FC8CFFF3033__INCLUDED_)
|
||||
#define AFX_CTPENDPOINT_H__F28737F3_12B9_4394_B63C_7FC8CFFF3033__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include <queue>
|
||||
|
||||
#define MODULO32(a) ((a)&0x1f)
|
||||
#define MAX_SEQ_NUM 7
|
||||
#define NUM_OF_BUFS ((MAX_SEQ_NUM+1)/2)
|
||||
#define INC(a) (a)=MODULO32((++a))
|
||||
|
||||
#define MAX_QUEUED_PACKET_PER_CHANNEL 24
|
||||
|
||||
//<<FIXME>> buffer timeout...replace with a ping adaptive algorithm
|
||||
#define TM_BUFFER 300
|
||||
#define TM_ACK TM_BUFFER/5
|
||||
#define MAX_PLAYLOAD_SIZE_IN_BITS 1024*8
|
||||
|
||||
#include "Stream.h"
|
||||
#include "CNP.h"
|
||||
#include "Interfaces.h"
|
||||
#include "PingCalculator.h"
|
||||
|
||||
typedef std::queue<CStream> STREAM_QUEUE;
|
||||
|
||||
typedef struct tagBuffer{
|
||||
CStream stmData;
|
||||
DWORD dwTimeout;
|
||||
LONG nSeq;//only for retrasmission
|
||||
}Buffer;
|
||||
|
||||
|
||||
/*! Implements a CTP endpoint
|
||||
*/
|
||||
class CCTPEndpoint
|
||||
{
|
||||
public:
|
||||
CCTPEndpoint();
|
||||
virtual ~CCTPEndpoint();
|
||||
public:
|
||||
void Reset();
|
||||
void Init(_IEndpointUser *pParent,bool bSecondary){m_pParent=pParent;m_bSecondary=bSecondary;}
|
||||
bool SendUnreliable(CStream &stmData);
|
||||
bool SendReliable(CStream &stmData);
|
||||
void Update(unsigned int nTime,unsigned char cFrameType = 0,CStream *pStm=NULL);
|
||||
void SetRate(unsigned int nBytePerSec);
|
||||
void Dump();
|
||||
unsigned int GetRemoteTimestamp(unsigned int nTime){
|
||||
return m_LatencyCalculator.GetCurrentRemoteTimestamp(nTime);
|
||||
}
|
||||
//
|
||||
unsigned int GetPing();
|
||||
unsigned int GetLostPackets(){return m_nLostPackets;}
|
||||
// Changes crypt key specifically for this connection.
|
||||
void SetPublicCryptKey( unsigned int key );
|
||||
protected:
|
||||
virtual void BuildOutgoingFrame()=0;
|
||||
virtual bool IsTimeToSend()=0;
|
||||
|
||||
void ProcessBufferTimers();
|
||||
void ProcessAckTimer();
|
||||
void HandleAckTimeout();
|
||||
void HandleDataFrame(CTPData &f);
|
||||
void HandleNak(CTPNak &f);
|
||||
void HandleTimeout(LONG nOldestFrame);
|
||||
void SendFrame(LONG nType,LONG nFrameNum,LONG nFrameExpected,CStream *pUnreliable = NULL,bool bUnreliable=false);
|
||||
void StopTimer(LONG nIndex);
|
||||
void SetTimer(LONG nIndex);
|
||||
void StopAckTimer();
|
||||
void SetAckTimer();
|
||||
|
||||
void CryptStream( CStream &stm );
|
||||
void UncyptStream( CStream &stm );
|
||||
|
||||
// CStream CompressStream(CStream &stm);
|
||||
// CStream UncompressStream(CStream &stm);
|
||||
|
||||
// ............................................................
|
||||
|
||||
bool m_nArrived[NUM_OF_BUFS];
|
||||
LONG m_nFrameExpected;
|
||||
LONG m_nNextFrameToSend;
|
||||
LONG m_nTooFar;
|
||||
LONG m_nAckExpected;
|
||||
bool m_bNoNak; //!< only one nak per frame
|
||||
LONG m_nBuffered; //!< number of output buffers currently used
|
||||
CStream m_stmInBuffers[NUM_OF_BUFS];
|
||||
Buffer m_OutBuffers[NUM_OF_BUFS];
|
||||
LONG m_nOldestFrame;
|
||||
//TIMERS=0 mean disabled
|
||||
//DWORD m_dwTimers[NUM_OF_BUFS]; //expected ack timers
|
||||
DWORD m_dwOutAckTimer; //!< outgoing ack timer
|
||||
STREAM_QUEUE m_qOutgoingReliableData;
|
||||
STREAM_QUEUE m_qOutgoingUnreliableData;
|
||||
|
||||
_IEndpointUser * m_pParent;
|
||||
|
||||
bool m_bSecondary;
|
||||
class CPingCalculator m_LatencyCalculator; //!< Ping calculation stuff
|
||||
DWORD m_nLostPackets;
|
||||
DWORD m_dwPingTime; //!< store the timestamp of the latest pong request
|
||||
//<<FIXME>> implement the rate control
|
||||
unsigned int m_nRate;
|
||||
float m_fBytePerMillisec; //!< only used when RATE_CONTROL is defined
|
||||
int m_nAllowedBytes;
|
||||
unsigned int m_nLastPacketSent;
|
||||
protected:
|
||||
unsigned int m_nSnaps;
|
||||
unsigned int m_nCurrentTime;
|
||||
// Encryption key used in Transfer protocol.
|
||||
unsigned int m_nEncryptKey[4];
|
||||
};
|
||||
|
||||
class CCTPClient :public CCTPEndpoint
|
||||
{
|
||||
protected:
|
||||
// virtual void BuildOutgoingFrame();
|
||||
virtual bool IsTimeToSend();
|
||||
};
|
||||
|
||||
class CCTPServer :public CCTPEndpoint
|
||||
{
|
||||
public:
|
||||
CCTPServer()
|
||||
{
|
||||
}
|
||||
protected:
|
||||
|
||||
// virtual void BuildOutgoingFrame();
|
||||
virtual bool IsTimeToSend();
|
||||
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_CTPENDPOINT_H__F28737F3_12B9_4394_B63C_7FC8CFFF3033__INCLUDED_)
|
||||
628
CryNetwork/CTPEndpointGNB.cpp
Normal file
628
CryNetwork/CTPEndpointGNB.cpp
Normal file
@@ -0,0 +1,628 @@
|
||||
#include "stdafx.h"
|
||||
#include "ctpendpointgnb.h"
|
||||
#include <IDataProbe.h>
|
||||
|
||||
#define PACKET_SIZE_COMPRESSION_LIMIT 100
|
||||
|
||||
|
||||
CCTPEndpointGNB::CCTPEndpointGNB( CNetwork *pNetwork )
|
||||
{
|
||||
m_pNetwork = pNetwork;
|
||||
Reset();
|
||||
|
||||
m_bCompress = true;
|
||||
m_nEncryptKey[0] = 1282732178u;
|
||||
m_nEncryptKey[1] = 1718763272u;
|
||||
m_nEncryptKey[2] = 297614432u;
|
||||
m_nEncryptKey[3] = 3389628651u;
|
||||
}
|
||||
|
||||
CCTPEndpointGNB::~CCTPEndpointGNB(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CCTPEndpointGNB::SetPublicCryptKey( unsigned int key )
|
||||
{
|
||||
m_nEncryptKey[2] = key;
|
||||
}
|
||||
|
||||
static bool Between(LONG a, LONG b, LONG c)
|
||||
{
|
||||
return ((a <= b) &&(b < c)) ||((c < a) &&(a <= b)) ||((b < c) &&(c < a));
|
||||
}
|
||||
|
||||
void CCTPEndpointGNB::Reset()
|
||||
{
|
||||
m_nFrameExpected=0;
|
||||
m_nNextFrameToSend=0;
|
||||
m_nAckExpected=0;
|
||||
m_nBuffered=0; //number of output buffers currently used
|
||||
m_nCurrentTime=0;
|
||||
m_dwOutAckTimer=0;
|
||||
m_dwPingTime=0;
|
||||
m_nLostPackets=0;
|
||||
m_nUnreliableLostPackets=0;
|
||||
m_nBuffered=0;
|
||||
for (long n = 0; n < NUM_OF_BUFS; n++)
|
||||
{
|
||||
m_OutBuffers[n].dwTimeout = 0;
|
||||
m_OutBuffers[n].nSeq = 0;
|
||||
// m_nArrived[n]=false;
|
||||
}
|
||||
|
||||
while (!m_qOutgoingReliableData.empty())
|
||||
{
|
||||
m_qOutgoingReliableData.pop();
|
||||
}
|
||||
while (!m_qOutgoingUnreliableData.empty())
|
||||
{
|
||||
m_qOutgoingUnreliableData.pop();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCTPEndpointGNB::CryptPacket( CTPData &data )
|
||||
{
|
||||
// Write 1 bit of compressed packed info.
|
||||
data.m_bCompressed = false;
|
||||
CStream &stm = data.m_stmData;
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
unsigned int srclen = (stm.GetSize()+7)/8; // Always cover last byte.
|
||||
unsigned int destlen = srclen;
|
||||
// Try to compress big packets.
|
||||
if (srclen > PACKET_SIZE_COMPRESSION_LIMIT && m_pNetwork->IsPacketCompressionEnabled())
|
||||
{
|
||||
BYTE temp[DEFAULT_STREAM_BYTESIZE*2];
|
||||
destlen = sizeof(temp);
|
||||
IDataProbe *pProbe = GetISystem()->GetIDataProbe();
|
||||
pProbe->Compress( temp,destlen,pBuffer,srclen,1 );
|
||||
if (destlen < srclen)
|
||||
{
|
||||
data.m_bCompressed = true;
|
||||
data.m_nUncompressedSize = stm.GetSize(); // In bits.
|
||||
TEA_ENCODE( (unsigned int*)temp,(unsigned int*)temp,TEA_GETSIZE(destlen),m_nEncryptKey );
|
||||
stm.Reset();
|
||||
stm.WriteBits(temp,destlen*8);
|
||||
}
|
||||
}
|
||||
if (data.m_bCompressed)
|
||||
{
|
||||
//@TOOD: remove log.
|
||||
float f1 = 100.0f/srclen;
|
||||
float f2 = f1 * destlen;
|
||||
int prc = (int)(100 - f2);
|
||||
//if (m_pNetwork->GetLogLevel() > 1)
|
||||
//CryLog( "<NET> PckSize Compressed: Was:%.3d Now:%.3d, Win: %.2d%%",srclen,destlen,prc );
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = stm.GetSize()/8;
|
||||
if (len >= 8)
|
||||
{
|
||||
TEA_ENCODE( pBuffer,pBuffer,TEA_GETSIZE(len),m_nEncryptKey );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CCTPEndpointGNB::UncryptPacket( CTPData &data )
|
||||
{
|
||||
CStream &stm = data.m_stmData;
|
||||
if (data.m_bCompressed)
|
||||
{
|
||||
// Compressed data packet.
|
||||
BYTE temp[DEFAULT_STREAM_BYTESIZE*2];
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
int srclen = (stm.GetSize()+7)/8; // Always cover last byte.
|
||||
TEA_DECODE( pBuffer,pBuffer,TEA_GETSIZE(srclen),m_nEncryptKey );
|
||||
unsigned int destLen = sizeof(temp);
|
||||
IDataProbe *pProbe = GetISystem()->GetIDataProbe();
|
||||
pProbe->Uncompress( temp,destLen,pBuffer,srclen );
|
||||
|
||||
stm.Reset();
|
||||
stm.WriteBits( temp,data.m_nUncompressedSize );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Uncompressed data packet.
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
int len = stm.GetSize()/8;
|
||||
if (len >= 8)
|
||||
{
|
||||
TEA_DECODE( pBuffer,pBuffer,TEA_GETSIZE(len),m_nEncryptKey );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CCTPEndpointGNB::SendUnreliable(CStream &stmData)
|
||||
{
|
||||
m_qOutgoingUnreliableData.push(stmData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCTPEndpointGNB::SendReliable(CStream &stmData)
|
||||
{
|
||||
m_qOutgoingReliableData.push(stmData);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCTPEndpointGNB::Update(unsigned int nTime,unsigned char cFrameType,CStream *pStm)
|
||||
{
|
||||
m_nCurrentTime = nTime;
|
||||
CTP *pFrame = NULL;
|
||||
CTPAck ack;
|
||||
CTPData data;
|
||||
CTPPong pong;
|
||||
if (cFrameType)
|
||||
{
|
||||
switch (cFrameType)
|
||||
{
|
||||
case FT_CTP_DATA:
|
||||
{
|
||||
data.Load(*pStm);
|
||||
pFrame = &data;
|
||||
HandleDataFrame(data);
|
||||
}
|
||||
break;
|
||||
case FT_CTP_ACK:
|
||||
{
|
||||
pFrame = &ack;
|
||||
ack.Load(*pStm);
|
||||
}
|
||||
break;
|
||||
case FT_CTP_PONG:
|
||||
{
|
||||
pong.Load(*pStm);
|
||||
m_LatencyCalculator.AddSample((float)m_nCurrentTime - m_dwPingTime, m_nCurrentTime, pong.m_nTimestamp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
if (pFrame)
|
||||
{
|
||||
if (pFrame->m_bPingRequest == true)
|
||||
{
|
||||
CStream stm;
|
||||
CTPPong pong;
|
||||
// pong.m_cClientID = m_pParent->GetID();
|
||||
pong.m_nTimestamp = m_nCurrentTime;
|
||||
pong.Save(stm);
|
||||
m_pParent->Send(stm);
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
// manage piggybacked ack (all frames hold a piggybacked ack)
|
||||
|
||||
NET_TRACE("--->>>[CTP] SEQ %02d ACK %02d\n", pFrame->m_cSequenceNumber, pFrame->m_cAck);
|
||||
|
||||
if(!pFrame->m_bUnreliable)
|
||||
while (Between(m_nAckExpected, pFrame->m_cAck, m_nNextFrameToSend))
|
||||
{
|
||||
m_nBuffered = m_nBuffered - 1;
|
||||
NET_TRACE("Ack [%02d] STOPPING TIMER m_nBuffered=%02d\n",pFrame->m_cAck,m_nBuffered);
|
||||
StopTimer(m_nAckExpected%NUM_OF_BUFS);
|
||||
INC(m_nAckExpected);
|
||||
}
|
||||
}
|
||||
}
|
||||
// handle outgoing buffer timers
|
||||
ProcessBufferTimers();
|
||||
|
||||
// if there is some out-buffer free, I retrive some new data to send
|
||||
// and if the network layer is ready(enough bandwith) ...send outgoing frames
|
||||
if (IsTimeToSend())
|
||||
{
|
||||
BuildOutgoingFrame();
|
||||
}
|
||||
// handle ack timer
|
||||
ProcessAckTimer();
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CCTPEndpointGNB::SetRate(unsigned int nBytePerSec)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CCTPEndpointGNB::Dump()
|
||||
{
|
||||
NET_TRACE("m_nFrameExpected=%d |||", m_nFrameExpected);
|
||||
NET_TRACE("m_nBuffered=%d |||", m_nBuffered);
|
||||
NET_TRACE("m_nAckExpected=%d |||", m_nAckExpected);
|
||||
NET_TRACE("m_nNextFrameToSend=%d\n", m_nNextFrameToSend);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int CCTPEndpointGNB::GetPing()
|
||||
{
|
||||
return (unsigned int)m_LatencyCalculator.GetAverageLatency();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CCTPEndpointGNB::HandleDataFrame(CTPData &f)
|
||||
{
|
||||
CStream stmUncompressed;
|
||||
if(f.m_bUnreliable)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//UNRELIABLE PACKET
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//if the packet is out of sequence will be discarded
|
||||
if(f.m_cSequenceNumber==m_nFrameExpected)
|
||||
{
|
||||
// CStream stmUncompressed=UncompressStream(f.m_stmData);
|
||||
// m_pParent->OnData(stmUncompressed);
|
||||
UncryptPacket( f );
|
||||
m_pParent->OnData( f.m_stmData );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nUnreliableLostPackets++;
|
||||
NET_TRACE("[%02d]expected-[%02d]received Packet discarded\n",m_nFrameExpected,f.m_cSequenceNumber);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//RELIABLE PACKET
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(f.m_cSequenceNumber==m_nFrameExpected)
|
||||
{
|
||||
// CStream stmUncompressed=UncompressStream(f.m_stmData);
|
||||
// m_pParent->OnData(stmUncompressed);
|
||||
//UncryptStream( f.m_stmData );
|
||||
//m_pParent->OnData(f.m_stmData);
|
||||
UncryptPacket( f );
|
||||
m_pParent->OnData( f.m_stmData );
|
||||
|
||||
INC(m_nFrameExpected);
|
||||
SetAckTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAckTimer();
|
||||
|
||||
NET_TRACE("[%02d]expected-[%02d]received Packet discarded\n",m_nFrameExpected,f.m_cSequenceNumber);
|
||||
}
|
||||
|
||||
while(Between(m_nAckExpected,f.m_cAck,m_nNextFrameToSend))
|
||||
{
|
||||
m_nBuffered=m_nBuffered-1;
|
||||
StopTimer(m_nAckExpected%NUM_OF_BUFS);
|
||||
INC(m_nAckExpected);
|
||||
}
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CCTPEndpointGNB::ProcessBufferTimers()
|
||||
{
|
||||
unsigned int ulTick = m_nCurrentTime;
|
||||
DWORD nLowest = 0xFFFFFFFF;
|
||||
DWORD nLowestIdx;
|
||||
bool bFound = false;
|
||||
// search for the oldest timer
|
||||
for (long n = 0; n < NUM_OF_BUFS; n++)
|
||||
{
|
||||
if ((m_OutBuffers[n].dwTimeout != 0) &&(m_OutBuffers[n].dwTimeout < nLowest))
|
||||
{
|
||||
bFound = true;
|
||||
nLowest = m_OutBuffers[n].dwTimeout;
|
||||
nLowestIdx = n;
|
||||
}
|
||||
}
|
||||
// test the oldest timer
|
||||
if (bFound)
|
||||
{
|
||||
/* if ((ulTick - nLowest)>(TM_BUFFER + m_LatencyCalculator.GetAverageLatency()))
|
||||
{
|
||||
/////////////////////////////////
|
||||
m_OutBuffers[nLowestIdx].dwTimeout = 0;
|
||||
HandleTimeout(m_OutBuffers[nLowestIdx].nSeq);
|
||||
}
|
||||
}*/
|
||||
DWORD dwTO=TM_BUFFER + (DWORD)(m_LatencyCalculator.GetAverageLatency());
|
||||
for (int n = 0; n < NUM_OF_BUFS; n++)
|
||||
{
|
||||
if((m_OutBuffers[nLowestIdx].dwTimeout!=0) && ((ulTick-m_OutBuffers[nLowestIdx].dwTimeout)>dwTO))
|
||||
{
|
||||
m_OutBuffers[nLowestIdx].dwTimeout = 0;
|
||||
HandleTimeout(m_OutBuffers[nLowestIdx].nSeq);
|
||||
}
|
||||
nLowestIdx=(nLowestIdx+1)%NUM_OF_BUFS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCTPEndpointGNB::ProcessAckTimer()
|
||||
{
|
||||
// Process Ack timeout
|
||||
unsigned int ulTick = m_nCurrentTime;
|
||||
/////////////////////////////////
|
||||
if (m_dwOutAckTimer)
|
||||
{
|
||||
if ((ulTick - m_dwOutAckTimer)>(TM_ACK + m_LatencyCalculator.GetAverageLatency()))
|
||||
{
|
||||
HandleAckTimeout();
|
||||
m_dwOutAckTimer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CCTPEndpointGNB::IsTimeToSend()
|
||||
{
|
||||
if (m_nBuffered < NUM_OF_BUFS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCTPEndpointGNB::HandleAckTimeout()
|
||||
{
|
||||
NET_TRACE("HandleAckTimeout()\n");
|
||||
SendFrame(FT_CTP_ACK, 0, m_nFrameExpected);
|
||||
}
|
||||
|
||||
|
||||
void CCTPEndpointGNB::HandleTimeout(LONG nOldestFrame)
|
||||
{
|
||||
NET_TRACE("HandleTimeout()\n");
|
||||
m_nLostPackets++;
|
||||
if (m_nBuffered)
|
||||
SendFrame(FT_CTP_DATA, nOldestFrame, m_nFrameExpected);
|
||||
}
|
||||
|
||||
/*
|
||||
CStream CCTPEndpointGNB::CompressStream(CStream &stmUncompressed)
|
||||
{
|
||||
CStream stmCompressed;
|
||||
#ifdef USE_PACKET_COMPRESSION
|
||||
if(m_bCompress)
|
||||
{
|
||||
BYTE *pUncompressed=NULL;
|
||||
pUncompressed=stmUncompressed.GetPtr();
|
||||
unsigned short nUncompressedSizeInBits=(unsigned short)stmUncompressed.GetSize();
|
||||
unsigned short nUncompressedSize=BITS2BYTES(nUncompressedSizeInBits);
|
||||
unsigned short n=0;
|
||||
stmCompressed.Write(true);
|
||||
stmCompressed.Write(nUncompressedSizeInBits);
|
||||
while(n<nUncompressedSize)
|
||||
{
|
||||
BYTE b;
|
||||
|
||||
b=pUncompressed[n];
|
||||
if(b==0)
|
||||
{
|
||||
//write a 0
|
||||
stmCompressed.Write(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//write a 1
|
||||
stmCompressed.Write(true);
|
||||
//write a byte
|
||||
stmCompressed.Write(b);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stmCompressed.Write(false);
|
||||
stmCompressed.WriteBits(stmUncompressed.GetPtr(),stmUncompressed.GetSize());
|
||||
}
|
||||
|
||||
#else
|
||||
stmCompressed=stmUncompressed;
|
||||
#endif
|
||||
return stmCompressed;
|
||||
}
|
||||
|
||||
CStream CCTPEndpointGNB::UncompressStream(CStream &stmCompressed)
|
||||
{
|
||||
CStream stmUncompressed;
|
||||
#ifdef USE_PACKET_COMPRESSION
|
||||
unsigned short nUncompressedSize;
|
||||
stmUncompressed.Reset();
|
||||
bool bIsCompressed;
|
||||
stmCompressed.Read(bIsCompressed);
|
||||
if(bIsCompressed){
|
||||
stmCompressed.Read(nUncompressedSize);
|
||||
while(!stmCompressed.EOS())
|
||||
{
|
||||
bool bBit;
|
||||
BYTE bData;
|
||||
stmCompressed.Read(bBit);
|
||||
if(bBit)
|
||||
{
|
||||
stmCompressed.Read(bData);
|
||||
}
|
||||
else
|
||||
{
|
||||
bData=0;
|
||||
}
|
||||
stmUncompressed.Write(bData);
|
||||
if(stmUncompressed.GetSize()==nUncompressedSize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stmCompressed.Read(stmUncompressed);
|
||||
}
|
||||
#else
|
||||
stmUncompressed=stmCompressed;
|
||||
#endif
|
||||
return stmUncompressed;
|
||||
}
|
||||
*/
|
||||
void CCTPEndpointGNB::SendFrame(LONG nType, LONG nFrameNum, LONG nFrameExpected, CStream *pUnreliable,bool bUnreliable)
|
||||
{
|
||||
static BYTE cUncompressed[1000];
|
||||
CTPData data;
|
||||
CTPAck ack;
|
||||
CTPNak nak;
|
||||
CTP *pFrame;
|
||||
switch (nType)
|
||||
{
|
||||
case FT_CTP_DATA:
|
||||
pFrame = &data;
|
||||
break;
|
||||
case FT_CTP_ACK:
|
||||
pFrame = &ack;
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
pFrame->m_cFrameType=(BYTE)nType;
|
||||
pFrame->m_bSecondaryTC=m_bSecondary;
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//DATA
|
||||
//////////////////////////////////////////////////////////////////
|
||||
if (nType == FT_CTP_DATA)
|
||||
{
|
||||
if(!bUnreliable)
|
||||
{
|
||||
data.m_stmData = m_OutBuffers[nFrameNum%NUM_OF_BUFS].stmData;
|
||||
m_OutBuffers[nFrameNum%NUM_OF_BUFS].nSeq = nFrameNum;
|
||||
if (pUnreliable)
|
||||
{
|
||||
if(pUnreliable->GetSize())
|
||||
data.m_stmData.Write(*pUnreliable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data.m_stmData = *pUnreliable;
|
||||
}
|
||||
CryptPacket( data );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//SEQ AND ACK
|
||||
pFrame->m_bUnreliable = bUnreliable;
|
||||
|
||||
pFrame->m_cSequenceNumber =(BYTE) nFrameNum;
|
||||
|
||||
pFrame->m_cAck =(BYTE) (nFrameExpected + MAX_SEQ_NUM)%(MAX_SEQ_NUM + 1);
|
||||
|
||||
if(nType == FT_CTP_DATA)
|
||||
{
|
||||
NET_TRACE("SEND [CTP] %s FRAME SEQ [%02d] ACK [%02d] \n",pFrame->m_bUnreliable?"unreliable":"reliable",pFrame->m_cSequenceNumber,pFrame->m_cAck);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//CHECK IF A PING REQUEST IS NEEDED
|
||||
if ((!m_bSecondary) && m_LatencyCalculator.IsTimeToPing(m_nCurrentTime))
|
||||
{
|
||||
m_dwPingTime = m_nCurrentTime;
|
||||
// set a piggybacked pong request
|
||||
pFrame->m_bPingRequest = true;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//SERIALIZE THE FRAME
|
||||
CStream stm;
|
||||
pFrame->Save(stm);
|
||||
m_pParent->Send(stm);
|
||||
|
||||
// Update the rate control
|
||||
m_nAllowedBytes -= BITS2BYTES(stm.GetSize());
|
||||
m_nLastPacketSent = m_nCurrentTime;
|
||||
// NET_TRACE(">>m_nAllowedBytes=%d\n",m_nAllowedBytes);
|
||||
|
||||
//////////////////////////////////////////
|
||||
if (nType == FT_CTP_DATA && (!bUnreliable))
|
||||
SetTimer(nFrameNum%NUM_OF_BUFS);
|
||||
|
||||
if(!bUnreliable)
|
||||
StopAckTimer();
|
||||
}
|
||||
|
||||
|
||||
void CCTPEndpointGNB::SetAckTimer()
|
||||
{
|
||||
if (m_dwOutAckTimer == 0)
|
||||
m_dwOutAckTimer = m_nCurrentTime;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! stop the ack timer
|
||||
void CCTPEndpointGNB::StopAckTimer()
|
||||
{
|
||||
m_dwOutAckTimer = 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! set packet retrasmisson timeout
|
||||
void CCTPEndpointGNB::SetTimer(LONG nIndex)
|
||||
{
|
||||
m_OutBuffers[nIndex].dwTimeout = m_nCurrentTime;
|
||||
NET_TRACE("SETTIMER %02d %d\n",nIndex,m_nCurrentTime);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//! stop packet retrasmisson timeout
|
||||
void CCTPEndpointGNB::StopTimer(LONG nIndex)
|
||||
{
|
||||
DWORD nTimeout = m_OutBuffers[nIndex].dwTimeout;
|
||||
m_OutBuffers[nIndex].dwTimeout=0;
|
||||
NET_TRACE("STOPTIMER %02d %d\n",nIndex,nTimeout);
|
||||
}
|
||||
|
||||
|
||||
void CCTPEndpointGNB::BuildOutgoingFrame()
|
||||
{
|
||||
if (m_qOutgoingReliableData.empty() == false || m_qOutgoingUnreliableData.empty() == false)
|
||||
{
|
||||
CStream stmUnreliable;
|
||||
|
||||
CStream &stm=m_OutBuffers[m_nNextFrameToSend%NUM_OF_BUFS].stmData;
|
||||
stm.Reset();
|
||||
while ((!m_qOutgoingReliableData.empty())
|
||||
&& ((stm.GetSize() + m_qOutgoingReliableData.front().GetSize()) < MAX_PLAYLOAD_SIZE_IN_BITS))
|
||||
{
|
||||
stm.Write(m_qOutgoingReliableData.front());
|
||||
m_qOutgoingReliableData.pop();
|
||||
}
|
||||
while ((!m_qOutgoingUnreliableData.empty())
|
||||
&& ((stm.GetSize() + m_qOutgoingUnreliableData.front().GetSize()) < MAX_PLAYLOAD_SIZE_IN_BITS))
|
||||
{
|
||||
stmUnreliable.Write(m_qOutgoingUnreliableData.front());
|
||||
m_qOutgoingUnreliableData.pop();
|
||||
}
|
||||
//CHECK IF THERE IS RELIABLE DATA IN THE QUEUE
|
||||
if(stm.GetSize()>0)
|
||||
{
|
||||
SendFrame(FT_CTP_DATA, m_nNextFrameToSend, m_nFrameExpected, &stmUnreliable,false);
|
||||
INC(m_nNextFrameToSend);
|
||||
m_nBuffered += 1;
|
||||
NET_ASSERT(m_nBuffered<=NUM_OF_BUFS);
|
||||
NET_TRACE("SEND RELIABLE m_nBuffered=%02d\n",m_nBuffered);
|
||||
}
|
||||
else
|
||||
{
|
||||
//IF THERE ISN'T RELIABLE DATA SEND A UNRELIABLE ONLY PACKET
|
||||
//IF THERE IS UNRELIABLE DATA
|
||||
if(stmUnreliable.GetSize()>0)
|
||||
{
|
||||
SendFrame(FT_CTP_DATA, m_nNextFrameToSend, m_nFrameExpected, &stmUnreliable,true);
|
||||
NET_TRACE("SEND UNRELIABLE\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCTPEndpointGNB::GetMemoryStatistics(ICrySizer *pSizer)
|
||||
{
|
||||
pSizer->AddObject(&m_qOutgoingReliableData,m_qOutgoingReliableData.size()*sizeof(CStream));
|
||||
pSizer->AddObject(&m_qOutgoingUnreliableData,m_qOutgoingUnreliableData.size()*sizeof(CStream));
|
||||
}
|
||||
105
CryNetwork/CTPEndpointGNB.h
Normal file
105
CryNetwork/CTPEndpointGNB.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#ifndef _CTP_ENDPOINT_GNB_
|
||||
#define _CTP_ENDPOINT_GNB_
|
||||
|
||||
#include "Stream.h"
|
||||
#include "CNP.h"
|
||||
#include "Interfaces.h"
|
||||
#include "PingCalculator.h"
|
||||
#include "Network.h"
|
||||
|
||||
#define MODULO32(a) ((a)&0x1f)
|
||||
#define MAX_SEQ_NUM 31
|
||||
#define NUM_OF_BUFS ((MAX_SEQ_NUM+1)/2)
|
||||
#define INC(a) (a)=MODULO32((++a))
|
||||
|
||||
#define MAX_QUEUED_PACKET_PER_CHANNEL 24
|
||||
|
||||
//<<FIXME>> buffer timeout...replace with a ping adaptive algorithm
|
||||
#define TM_BUFFER 600
|
||||
#define TM_ACK TM_BUFFER/5
|
||||
#define MAX_PLAYLOAD_SIZE_IN_BITS 1024*8
|
||||
|
||||
#include <queue>
|
||||
|
||||
typedef struct tagBuffer{
|
||||
CStream stmData;
|
||||
DWORD dwTimeout;
|
||||
LONG nSeq;//only for retrasmission
|
||||
}Buffer;
|
||||
|
||||
typedef std::queue<CStream> STREAM_QUEUE;
|
||||
|
||||
class CCTPEndpointGNB
|
||||
{
|
||||
public:
|
||||
CCTPEndpointGNB( CNetwork *pNetwork );
|
||||
virtual ~CCTPEndpointGNB(void);
|
||||
void Reset();
|
||||
void Init(_IEndpointUser *pParent,bool bSecondary){m_pParent=pParent;m_bSecondary=bSecondary;}
|
||||
bool SendUnreliable(CStream &stmData);
|
||||
bool SendReliable(CStream &stmData);
|
||||
void Update(unsigned int nTime,unsigned char cFrameType = 0,CStream *pStm=NULL);
|
||||
void SetRate(unsigned int nBytePerSec);
|
||||
void Dump();
|
||||
unsigned int GetRemoteTimestamp(unsigned int nTime){
|
||||
return m_LatencyCalculator.GetCurrentRemoteTimestamp(nTime);
|
||||
}
|
||||
void GetMemoryStatistics(ICrySizer *pSizer);
|
||||
//
|
||||
unsigned int GetPing();
|
||||
unsigned int GetLostPackets(){return m_nLostPackets;}
|
||||
unsigned int GetUnreliableLostPackets(){return m_nUnreliableLostPackets;}
|
||||
|
||||
|
||||
void EnableCompression(bool bEnable){m_bCompress=bEnable;}
|
||||
// Changes crypt key specifically for this connection.
|
||||
void SetPublicCryptKey( unsigned int key );
|
||||
|
||||
protected:
|
||||
virtual void BuildOutgoingFrame();
|
||||
virtual bool IsTimeToSend();
|
||||
|
||||
private:
|
||||
// CStream CompressStream(CStream &stmUncompressed);
|
||||
// CStream UncompressStream(CStream &stmCompressed);
|
||||
void ProcessBufferTimers();
|
||||
void ProcessAckTimer();
|
||||
void HandleAckTimeout();
|
||||
void HandleDataFrame(CTPData &f);
|
||||
void HandleTimeout(LONG nOldestFrame);
|
||||
void SendFrame(LONG nType,LONG nFrameNum,LONG nFrameExpected,CStream *pUnreliable = NULL,bool bUnreliable=false);
|
||||
void StopTimer(LONG nIndex);
|
||||
void SetTimer(LONG nIndex);
|
||||
void StopAckTimer();
|
||||
void SetAckTimer();
|
||||
|
||||
void CryptPacket( CTPData &data );
|
||||
void UncryptPacket( CTPData &data );
|
||||
|
||||
//////////////////////////////////////
|
||||
CNetwork *m_pNetwork;
|
||||
_IEndpointUser *m_pParent;
|
||||
bool m_bSecondary;
|
||||
|
||||
Buffer m_OutBuffers[NUM_OF_BUFS];
|
||||
STREAM_QUEUE m_qOutgoingReliableData;
|
||||
STREAM_QUEUE m_qOutgoingUnreliableData;
|
||||
//protocol
|
||||
DWORD m_nFrameExpected;
|
||||
DWORD m_nNextFrameToSend;
|
||||
DWORD m_nAckExpected;
|
||||
DWORD m_nBuffered; //number of output buffers currently used
|
||||
DWORD m_dwOutAckTimer;
|
||||
DWORD m_dwPingTime;
|
||||
DWORD m_nAllowedBytes;
|
||||
DWORD m_nLastPacketSent;
|
||||
DWORD m_nLostPackets;
|
||||
DWORD m_nUnreliableLostPackets;
|
||||
unsigned int m_nCurrentTime;
|
||||
CPingCalculator m_LatencyCalculator;
|
||||
bool m_bCompress;
|
||||
// Encryption key used in Transfer protocol.
|
||||
unsigned int m_nEncryptKey[4];
|
||||
};
|
||||
|
||||
#endif //_CTP_ENDPOINT_GNB_
|
||||
583
CryNetwork/Client.cpp
Normal file
583
CryNetwork/Client.cpp
Normal file
@@ -0,0 +1,583 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: Client.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Client.h"
|
||||
#include "CNP.h"
|
||||
#include "IGame.h"
|
||||
#include "IScriptSystem.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
#include "UbiSoftMemory.h" // GS_WIN32
|
||||
#include "cdkeydefines.h" // UBI.com AUTHORIZATION_ID_SIZE
|
||||
#include "NewUbisoftClient.h" // NewUbisoftClient
|
||||
#else
|
||||
#define AUTHORIZATION_ID_SIZE 20
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
|
||||
#if defined(_DEBUG) && !defined(LINUX)
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CClient::CClient( CNetwork *pNetwork )
|
||||
: m_ctpEndpoint(pNetwork), m_ctpEndpoint2(pNetwork),
|
||||
cl_timeout(0), m_pbAuthorizationID(NULL), m_uiAuthorizationSize(0), m_bWaiting(0)
|
||||
{
|
||||
m_pNetwork = pNetwork;
|
||||
m_ccpEndpoint.Init(this);
|
||||
m_smCCPMachine.Init(this);
|
||||
}
|
||||
|
||||
CClient::~CClient()
|
||||
{
|
||||
m_pNetwork->UnregisterClient(this);
|
||||
m_pSink=NULL;
|
||||
if (m_pbAuthorizationID)
|
||||
delete [] m_pbAuthorizationID;
|
||||
}
|
||||
|
||||
bool CClient::Init(IClientSink *pSink)
|
||||
{
|
||||
m_pSink=pSink;
|
||||
if(NET_FAILED(m_socketMain.Create()))return false;
|
||||
if(NET_FAILED(m_socketMain.Listen(0)))return false;
|
||||
m_ctpEndpoint.Init(this,false);
|
||||
m_ctpEndpoint2.Init(this,true);
|
||||
m_ccpEndpoint.Init(this);
|
||||
m_dwKeepAliveTimer=0;
|
||||
|
||||
cl_timeout = GetISystem()->GetIConsole()->GetCVar("cl_timeout");
|
||||
|
||||
return true;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// _IClientServices
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if (defined(PS2) || defined(LINUX))
|
||||
#define FAILED(value) (((unsigned int)(value))&0x80000000)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _INTERNET_SIMULATOR
|
||||
#include <stdlib.h>
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "IConsole.h"
|
||||
#include "ITimer.h"
|
||||
#endif
|
||||
|
||||
bool CClient::SendTo( CIPAddress &ip,CStream &stm )
|
||||
{
|
||||
if(FAILED(m_socketMain.Send(stm.GetPtr(),BITS2BYTES(stm.GetSize()),&ip)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::Send(CStream &stm)
|
||||
{
|
||||
|
||||
#ifndef _INTERNET_SIMULATOR
|
||||
if(FAILED(m_socketMain.Send(stm.GetPtr(),BITS2BYTES(stm.GetSize()),&m_ipServer)))return false;
|
||||
return true;
|
||||
#else
|
||||
static ICVar *pVarPacketloss=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_packetloss");
|
||||
static ICVar *pVarMinPing=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_minping");
|
||||
static ICVar *pVarMaxPing=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_maxping");
|
||||
|
||||
int iMaxPing=pVarMinPing->GetIVal();
|
||||
int iMinPing=pVarMaxPing->GetIVal();
|
||||
|
||||
if(iMinPing>iMaxPing)
|
||||
iMaxPing=iMinPing;
|
||||
|
||||
if (pVarPacketloss->GetFVal()>0 || iMaxPing>0)
|
||||
{
|
||||
DelayedPacket *delayed = new DelayedPacket;
|
||||
if(iMaxPing>0)
|
||||
delayed->m_fTimeToSend = GetISystem()->GetITimer()->GetCurrTime() + iMinPing + (rand() % (iMaxPing-iMinPing)) / 1000.0f;
|
||||
else
|
||||
delayed->m_fTimeToSend = GetISystem()->GetITimer()->GetCurrTime();
|
||||
delayed->m_dwLengthInBytes = BITS2BYTES(stm.GetSize());
|
||||
assert(delayed->m_dwLengthInBytes < sizeof(delayed->m_Data)/sizeof(delayed->m_Data[0]));
|
||||
memcpy(delayed->m_Data, stm.GetPtr(), delayed->m_dwLengthInBytes);
|
||||
m_delayedPacketList.push_back(delayed);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FAILED(m_socketMain.Send(stm.GetPtr(),BITS2BYTES(stm.GetSize()),&m_ipServer)))return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CClient::SendSetup()
|
||||
{
|
||||
m_ccpEndpoint.SendSetup();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::SendConnectResp()
|
||||
{
|
||||
CStream stm;
|
||||
|
||||
if (m_pbAuthorizationID)
|
||||
stm.WriteBits(m_pbAuthorizationID,m_uiAuthorizationSize*8);
|
||||
m_ccpEndpoint.SendConnectResp(stm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::SendContextReady()
|
||||
{
|
||||
m_ccpEndpoint.SendContextReady(m_stmContextReady);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::SendDisconnect(const char* szCause)
|
||||
{
|
||||
m_ccpEndpoint.SendDisconnect(szCause);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CClient::SendSecurityResponse(CStream &stm)
|
||||
{
|
||||
m_ccpEndpoint.SendSecurityResp(stm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CClient::SendPunkBusterMsg(CStream &stm)
|
||||
{
|
||||
m_ccpEndpoint.SendPunkBusterMsg(stm);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CClient::OnContextSetup()
|
||||
{
|
||||
m_stmContext.Seek(0);
|
||||
if(m_pSink)
|
||||
m_pSink->OnXContextSetup(m_stmContext);
|
||||
m_ctpEndpoint.Reset();
|
||||
m_ctpEndpoint2.Reset();
|
||||
}
|
||||
|
||||
void CClient::OnServerReady()
|
||||
{
|
||||
GetISystem()->GetILog()->Log("CClient::OnServerReady");
|
||||
|
||||
/* if(m_pSink)
|
||||
m_pSink->OnServerReady();*/
|
||||
}
|
||||
|
||||
void CClient::OnConnect()
|
||||
{
|
||||
if(m_pSink)
|
||||
m_pSink->OnXConnect();
|
||||
}
|
||||
|
||||
void CClient::OnDisconnect(const char *szCause)
|
||||
{
|
||||
if(m_pSink)
|
||||
{
|
||||
if(szCause==NULL)szCause="Undefined";
|
||||
m_pSink->OnXClientDisconnect(szCause); // this pointer is destroyed after this call
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CClient::OnCCPConnect(CStream &stm)
|
||||
{
|
||||
CCPConnect ccpConnect;
|
||||
ccpConnect.Load(stm);
|
||||
|
||||
if (ccpConnect.m_cResponse & SV_CONN_FLAG_PUNKBUSTER)
|
||||
{
|
||||
ICVar *cl_punkbuster = GetISystem()->GetIConsole()->GetCVar("cl_punkbuster");
|
||||
|
||||
if (cl_punkbuster && cl_punkbuster->GetIVal() != 0)
|
||||
{
|
||||
m_pNetwork->InitPunkbusterClient(this);
|
||||
}
|
||||
}
|
||||
|
||||
m_pNetwork->LockPunkbusterCVars();
|
||||
|
||||
GetISystem()->GetILog()->Log("CClient::OnCCPConnect");
|
||||
|
||||
m_ccpEndpoint.SetPublicCryptKey(ccpConnect.m_ServerVariables.nPublicKey);
|
||||
m_ctpEndpoint.SetPublicCryptKey(ccpConnect.m_ServerVariables.nPublicKey);
|
||||
m_ctpEndpoint2.SetPublicCryptKey(ccpConnect.m_ServerVariables.nPublicKey);
|
||||
|
||||
m_ServerVariables=ccpConnect.m_ServerVariables;
|
||||
m_smCCPMachine.Update(SIG_CONNECT);
|
||||
}
|
||||
|
||||
void CClient::OnCCPContextSetup(CStream &stm)
|
||||
{
|
||||
GetISystem()->GetILog()->Log("CClient::OnCCPContextSetup");
|
||||
|
||||
m_stmContext=stm;
|
||||
m_smCCPMachine.Update(SIG_CONTEXT_SETUP);
|
||||
}
|
||||
|
||||
void CClient::OnCCPServerReady()
|
||||
{
|
||||
GetISystem()->GetILog()->Log("CClient::OnCCPServerReady");
|
||||
|
||||
m_smCCPMachine.Update(SIG_SERVER_READY);
|
||||
}
|
||||
|
||||
void CClient::OnData(CStream &stm)
|
||||
{
|
||||
/*
|
||||
BYTE msg;
|
||||
if(stm.ReadPkd(msg))
|
||||
{
|
||||
// Special control messages.
|
||||
{
|
||||
if (msg >= 250)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Seek back to 0;
|
||||
stm.Seek(0);
|
||||
|
||||
NET_TRACE("Packet=%d \n ",BITS2BYTES(stm.GetSize()));
|
||||
if(m_pSink)
|
||||
m_pSink->OnXData(stm);
|
||||
}
|
||||
|
||||
void CClient::OnCCPDisconnect(const char *szCause)
|
||||
{
|
||||
m_smCCPMachine.Update(SIG_DISCONNECT,(ULONG_PTR)szCause);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// IClient
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void CClient::Connect( const char *szIP, WORD wPort, const BYTE *pbAuthorizationID, unsigned int uiAuthorizationSize )
|
||||
{
|
||||
assert(pbAuthorizationID);
|
||||
assert(uiAuthorizationSize>0);
|
||||
NET_ASSERT(m_pSink!=NULL); // you forgot something
|
||||
|
||||
CIPAddress ip(wPort,szIP);
|
||||
m_bLocalHost=ip.IsLocalHost();
|
||||
m_ipServer=ip;
|
||||
m_socketMain.SetDefaultTarget(ip);
|
||||
|
||||
if(m_pbAuthorizationID)
|
||||
delete [] m_pbAuthorizationID;
|
||||
|
||||
// copy AuthorizationID
|
||||
m_uiAuthorizationSize = uiAuthorizationSize;
|
||||
m_pbAuthorizationID = new BYTE[m_uiAuthorizationSize];
|
||||
memcpy(m_pbAuthorizationID,pbAuthorizationID,m_uiAuthorizationSize);
|
||||
|
||||
m_smCCPMachine.Update(SIG_START);
|
||||
}
|
||||
|
||||
void CClient::Disconnect(const char* szCause)
|
||||
{
|
||||
m_smCCPMachine.Update(SIG_ACTIVE_DISCONNECT,(ULONG_PTR)szCause); // this pointer is destroyed after this call
|
||||
}
|
||||
|
||||
void CClient::SendReliable(CStream &stm)
|
||||
{
|
||||
m_ctpEndpoint.SendReliable(stm);
|
||||
}
|
||||
|
||||
void CClient::SendUnreliable(CStream &stm)
|
||||
{
|
||||
m_ctpEndpoint.SendUnreliable(stm);
|
||||
}
|
||||
|
||||
void CClient::ContextReady(CStream &stm)
|
||||
{
|
||||
GetISystem()->GetILog()->Log("CClient::ContextReady");
|
||||
|
||||
if(m_smCCPMachine.GetCurrentStatus()==STATUS_PROCESSING_CONTEXT)
|
||||
{
|
||||
m_stmContextReady=stm;
|
||||
m_smCCPMachine.Update(SIG_CONTEXT_READY);
|
||||
}
|
||||
else
|
||||
GetISystem()->GetILog()->Log("Client::ContextReady !=STATUS_PROCESSING_CONTEXT %d",m_smCCPMachine.GetCurrentStatus());
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CClient::Update(unsigned int nTime)
|
||||
{
|
||||
#ifdef _INTERNET_SIMULATOR
|
||||
|
||||
TDelayPacketList::iterator i;
|
||||
|
||||
for (i = m_delayedPacketList.begin(); i != m_delayedPacketList.end();)
|
||||
{
|
||||
DelayedPacket *dp = (*i);
|
||||
if (dp->m_fTimeToSend <= GetISystem()->GetITimer()->GetCurrTime())
|
||||
{
|
||||
i = m_delayedPacketList.erase(i);
|
||||
// Send it
|
||||
// 2% packetloss
|
||||
if ((rand() %100) > GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_packetloss")->GetFVal())
|
||||
m_socketMain.Send(dp->m_Data,dp->m_dwLengthInBytes,&m_ipServer);
|
||||
// Delete it
|
||||
delete dp;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_nCurrentTime=nTime;
|
||||
|
||||
// was the timer reset ?
|
||||
if (m_dwKeepAliveTimer > m_nCurrentTime)
|
||||
{
|
||||
// reset our keep alive timer
|
||||
m_dwKeepAliveTimer = m_nCurrentTime;
|
||||
}
|
||||
|
||||
int nRecvBytes;
|
||||
/////////////////////////////////////////////////////////
|
||||
static CIPAddress ipFrom;
|
||||
static CStream buf;
|
||||
|
||||
do
|
||||
{
|
||||
buf.Reset();
|
||||
nRecvBytes=0;
|
||||
m_socketMain.Receive(buf.GetPtr(),
|
||||
(int)BITS2BYTES(buf.GetAllocatedSize()),
|
||||
nRecvBytes,
|
||||
ipFrom);
|
||||
/////////////////////////////////////////////////////////
|
||||
if(nRecvBytes>0)
|
||||
{
|
||||
buf.SetSize(BYTES2BITS(nRecvBytes));
|
||||
if(!ProcessPacket(buf,ipFrom))
|
||||
{
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: ProcessPacket(buf,ipFrom) false");
|
||||
|
||||
return false; // this object was destroyed
|
||||
}
|
||||
m_dwKeepAliveTimer=m_nCurrentTime;
|
||||
}
|
||||
} while(nRecvBytes>0);
|
||||
/////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
m_ccpEndpoint.Update(m_nCurrentTime, 0, NULL);
|
||||
m_smCCPMachine.Update();
|
||||
unsigned int CurrState=m_smCCPMachine.GetCurrentStatus();
|
||||
if(CurrState==STATUS_READY || CurrState==STATUS_WAIT_FOR_SERVER_READY)
|
||||
{
|
||||
static char szCause[]="@ServerTimeout";
|
||||
m_ctpEndpoint.Update(m_nCurrentTime, 0, NULL);
|
||||
m_ctpEndpoint2.Update(m_nCurrentTime, 0, NULL);
|
||||
|
||||
if(cl_timeout && cl_timeout->GetFVal() && GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))
|
||||
{
|
||||
if(m_nCurrentTime-m_dwKeepAliveTimer > (cl_timeout->GetFVal() * 1000.0f) + m_pSink->GetTimeoutCompensation())
|
||||
{
|
||||
if (!m_bWaiting)
|
||||
{
|
||||
m_pSink->OnXServerTimeout();
|
||||
}
|
||||
|
||||
m_bWaiting = 1;
|
||||
}
|
||||
else if (m_bWaiting)
|
||||
{
|
||||
m_pSink->OnXServerRessurect();
|
||||
|
||||
m_bWaiting = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwKeepAliveTimer=m_nCurrentTime;
|
||||
}
|
||||
|
||||
m_pNetwork->OnClientUpdate();
|
||||
|
||||
return true; // this object is still exising
|
||||
}
|
||||
|
||||
void CClient::GetBandwidth(float &fIncomingKbPerSec,float &fOutgoinKbPerSec, DWORD &nIncomingPackets, DWORD &nOutgoingPackets )
|
||||
{
|
||||
fIncomingKbPerSec=m_socketMain.m_fIncomingKbPerSec;
|
||||
fOutgoinKbPerSec=m_socketMain.m_fOutgoingKbPerSec;
|
||||
nIncomingPackets=m_socketMain.m_nIncomingPacketsPerSec;
|
||||
nOutgoingPackets=m_socketMain.m_nOutgoingPacketsPerSec;
|
||||
}
|
||||
|
||||
void CClient::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool CClient::IsReady()
|
||||
{
|
||||
return (m_smCCPMachine.GetCurrentStatus()==STATUS_READY)?true:false;
|
||||
}
|
||||
|
||||
bool CClient::ProcessPacket(CStream &stmPacket,CIPAddress &ip)
|
||||
{
|
||||
if (!m_pNetwork->CheckPBPacket( stmPacket,ip ))
|
||||
return false;
|
||||
|
||||
CNP cnp;
|
||||
cnp.LoadAndSeekToZero(stmPacket);
|
||||
switch(cnp.m_cFrameType){
|
||||
case FT_CCP_CONNECT:
|
||||
case FT_CCP_DISCONNECT:
|
||||
case FT_CCP_CONTEXT_SETUP:
|
||||
case FT_CCP_SERVER_READY:
|
||||
case FT_CCP_ACK:
|
||||
case FT_CCP_SECURITY_QUERY:
|
||||
case FT_CCP_SECURITY_RESP:
|
||||
case FT_CCP_PUNK_BUSTER_MSG:
|
||||
if (!m_ccpEndpoint.Update(m_nCurrentTime,cnp.m_cFrameType,&stmPacket))
|
||||
{
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: m_ccpEndpoint.Update false");
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FT_CTP_DATA:
|
||||
case FT_CTP_ACK:
|
||||
case FT_CTP_NAK:
|
||||
case FT_CTP_PONG:
|
||||
if(m_smCCPMachine.GetCurrentStatus()==STATUS_READY)
|
||||
{
|
||||
if(cnp.m_bSecondaryTC)
|
||||
{
|
||||
m_ctpEndpoint2.Update(m_nCurrentTime,cnp.m_cFrameType,&stmPacket);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ctpEndpoint.Update(m_nCurrentTime,cnp.m_cFrameType,&stmPacket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetISystem()->GetILog()->Log("CTP PACKET RECEIVED (CCP NOT READY!!) %d",m_smCCPMachine.GetCurrentStatus());
|
||||
}
|
||||
break;
|
||||
/* case FT_CQP_INFO_RESPONSE:
|
||||
{
|
||||
CQPInfoResponse cqpInfoResponse;
|
||||
cqpInfoResponse.Load(stmPacket);
|
||||
m_pSink->OnServerFound(ip,cqpInfoResponse.m_stmData);
|
||||
}
|
||||
break;*/
|
||||
default:
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: cnp.m_cFrameType %d",(int)cnp.m_cFrameType);
|
||||
//NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CClient::GetPing()
|
||||
{
|
||||
return m_ctpEndpoint.GetPing();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CClient::OnCCPSecurityQuery(CStream &stm)
|
||||
{
|
||||
m_pNetwork->OnSecurityMsgQuery(stm);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CClient::OnCCPSecurityResp(CStream &stm)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CClient::OnCCPPunkBusterMsg(CStream &stm)
|
||||
{
|
||||
m_pNetwork->OnCCPPunkBusterMsg( m_ipServer,stm );
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
void CClient::SetServerIP( const char *szServerIP )
|
||||
{
|
||||
m_sServerIP = szServerIP;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
void CClient::OnCDKeyAuthorization( BYTE *pbAuthorizationID )
|
||||
{
|
||||
if(!pbAuthorizationID)
|
||||
{
|
||||
static BYTE fakeid[AUTHORIZATION_ID_SIZE];
|
||||
|
||||
pbAuthorizationID = fakeid;
|
||||
|
||||
memset(fakeid,0,AUTHORIZATION_ID_SIZE); // generated fake AuthorizationID
|
||||
}
|
||||
|
||||
char *sSemicolon;
|
||||
unsigned short port = 0;
|
||||
char temp[256];
|
||||
strncpy(temp,m_sServerIP.c_str(),256);
|
||||
|
||||
if(sSemicolon=strstr(temp,":"))
|
||||
{
|
||||
port=atoi(&sSemicolon[1]);
|
||||
sSemicolon[0]='\0';
|
||||
}
|
||||
|
||||
if(port==0)
|
||||
port=DEFAULT_SERVERPORT;
|
||||
|
||||
Connect(temp, port, pbAuthorizationID,AUTHORIZATION_ID_SIZE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CClient::InitiateCDKeyAuthorization( const bool inbCDAuthorization )
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
if(inbCDAuthorization)
|
||||
m_pNetwork->m_pUbiSoftClient->Client_GetCDKeyAuthorizationID(); // OnXCDKeyAuthorization is called later
|
||||
else
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
{
|
||||
OnCDKeyAuthorization(0); // 0 -> fake AuthorizationID is generated
|
||||
}
|
||||
}
|
||||
159
CryNetwork/Client.h
Normal file
159
CryNetwork/Client.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: Client.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _CLIENT_H_
|
||||
#define _CLIENT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "Interfaces.h"
|
||||
#include "ClientStateMachine.h"
|
||||
#ifdef NO_GNB
|
||||
#include "CTPEndpoint.h"
|
||||
#else
|
||||
#include "CTPEndpointGNB.h"
|
||||
#endif
|
||||
|
||||
#include "CCPEndpoint.h"
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <IConsole.h> // ICVar
|
||||
#include "Network.h"
|
||||
|
||||
// REMOVE THIS WHEN NOT TESTING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//#define _INTERNET_SIMULATOR
|
||||
|
||||
class CClient :
|
||||
public IClient,
|
||||
public _IClientServices
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CClient( CNetwork *pNetwork );
|
||||
//! destructor
|
||||
virtual ~CClient();
|
||||
|
||||
//!
|
||||
bool Init(IClientSink *pSink);
|
||||
//! @return true=disconnect and this pointer is destroyed, false otherwise
|
||||
bool ProcessPacket(CStream &stmPacket,CIPAddress &ip);
|
||||
|
||||
//_IClientServices
|
||||
bool Send(CStream &stm);
|
||||
bool SendTo( CIPAddress &ip,CStream &stm);
|
||||
bool SendSetup();
|
||||
bool SendConnectResp();
|
||||
bool SendContextReady();
|
||||
bool SendDisconnect(const char* szCause);
|
||||
void OnConnect();
|
||||
void OnContextSetup();
|
||||
void OnServerReady();
|
||||
void OnDisconnect(const char *szCause);
|
||||
void OnData(CStream &stm);
|
||||
//
|
||||
void OnCCPSetup(CStream &stm){}//this is a client-->server packet
|
||||
void OnCCPConnect(CStream &stm);
|
||||
void OnCCPConnectResp(CStream &stm){}//this is a client-->server packet
|
||||
void OnCCPContextSetup(CStream &stm);
|
||||
void OnCCPContextReady(CStream &stm){}//this is a client->server packet
|
||||
void OnCCPServerReady();//this is a client->server packet
|
||||
void OnCCPDisconnect(const char* szCause);
|
||||
void OnCCPSecurityQuery(CStream &stm);
|
||||
void OnCCPSecurityResp(CStream &stm);
|
||||
void OnCCPPunkBusterMsg(CStream &stm);
|
||||
|
||||
// interface IClient ----------------------------------------------------------------------------
|
||||
|
||||
virtual void Connect(const char *szIP, WORD wPort, const BYTE *pbAuthorizationID, unsigned int iAuthorizationSize);
|
||||
virtual void Disconnect(const char *szCause);
|
||||
virtual void ContextReady(CStream &stm);
|
||||
virtual void SendReliable(CStream &stm);
|
||||
virtual void SendUnreliable(CStream &stm);
|
||||
virtual bool IsReady();
|
||||
virtual bool Update(unsigned int nTime);
|
||||
virtual void GetBandwidth( float &fIncomingKbPerSec, float &fOutgoinKbPerSec, DWORD &nIncomingPackets, DWORD &nOutgoingPackets);
|
||||
virtual void Release();
|
||||
virtual unsigned int GetPing();
|
||||
virtual unsigned int GetRemoteTimestamp(unsigned int nTime)
|
||||
{
|
||||
return m_ctpEndpoint.GetRemoteTimestamp(nTime);
|
||||
}
|
||||
virtual unsigned int GetPacketsLostCount()
|
||||
{
|
||||
return m_ctpEndpoint.GetLostPackets();
|
||||
}
|
||||
virtual unsigned int GetUnreliablePacketsLostCount()
|
||||
{
|
||||
return m_ctpEndpoint.GetUnreliableLostPackets();
|
||||
}
|
||||
virtual void OnCDKeyAuthorization( BYTE *pbAuthorizationID );
|
||||
virtual void SetServerIP( const char *szServerIP );
|
||||
virtual void InitiateCDKeyAuthorization( const bool inbCDAuthorization );
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool SendSecurityResponse(CStream &stm);
|
||||
bool SendPunkBusterMsg(CStream &stm);
|
||||
CIPAddress GetServerIP() const { return m_ipServer; };
|
||||
|
||||
private: // ----------------------------------------------------------------
|
||||
|
||||
string m_sServerIP; //!<
|
||||
CNetwork * m_pNetwork;
|
||||
CClientStateMachine m_smCCPMachine;
|
||||
#ifdef NO_GNB
|
||||
CCTPClient m_ctpEndpoint;
|
||||
#else
|
||||
CCTPEndpointGNB m_ctpEndpoint;
|
||||
CCTPEndpointGNB m_ctpEndpoint2;
|
||||
#endif
|
||||
CCCPEndpoint m_ccpEndpoint;
|
||||
CDatagramSocket m_socketMain;
|
||||
CIPAddress m_ipServer;
|
||||
|
||||
CStream m_stmContext;
|
||||
CStream m_stmContextReady;
|
||||
//after 3 second without any incoming packets the connection will be considered lost
|
||||
ICVar * cl_timeout;
|
||||
DWORD m_dwKeepAliveTimer;
|
||||
|
||||
BYTE * m_pbAuthorizationID; //!< CD Key AuthorizationID (use new and delete)
|
||||
unsigned int m_uiAuthorizationSize; //!< Size of AuthorizationID in bytes
|
||||
|
||||
protected: // ------------------------------------------------------------------
|
||||
|
||||
IClientSink * m_pSink;
|
||||
|
||||
//REMOTE PROTOCOL VARIBLES (update by the connect packet)
|
||||
struct CNPServerVariables m_ServerVariables;
|
||||
|
||||
unsigned int m_nCurrentTime;
|
||||
bool m_bLocalHost; //!< the client is connected to the local server (no timeouts)
|
||||
bool m_bWaiting; //!< the client is waiting for the server.. probably the server just dropped, or is stalled for some time..
|
||||
|
||||
|
||||
#ifdef _INTERNET_SIMULATOR
|
||||
struct DelayedPacket
|
||||
{
|
||||
float m_fTimeToSend; //!<
|
||||
BYTE m_Data[8192]; //!<
|
||||
unsigned int m_dwLengthInBytes; //!<
|
||||
};
|
||||
typedef std::list<DelayedPacket*> TDelayPacketList;
|
||||
|
||||
TDelayPacketList m_delayedPacketList; //!<
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _CLIENT_H_
|
||||
207
CryNetwork/ClientLocal.cpp
Normal file
207
CryNetwork/ClientLocal.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
// ClientLocal.cpp: implementation of the CClientLocal class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Network.h"
|
||||
#include "ServerSlot.h"
|
||||
#include "ClientLocal.h"
|
||||
#include <IConsole.h> // ICVar
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
#include "UbiSoftMemory.h" // GS_WIN32
|
||||
#include "cdkeydefines.h" // UBI.com AUTHORIZATION_ID_SIZE
|
||||
#include "NewUbisoftClient.h" // NewUbisoftClient
|
||||
#else
|
||||
#define AUTHORIZATION_ID_SIZE 20
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CClientLocal::CClientLocal( CNetwork *pNetwork, IClientSink *pSink )
|
||||
{
|
||||
m_pSink=pSink;
|
||||
m_pNetwork=pNetwork;
|
||||
m_bReady=false;
|
||||
m_pServerSlot=NULL;
|
||||
|
||||
}
|
||||
|
||||
CClientLocal::~CClientLocal()
|
||||
{
|
||||
m_pNetwork->UnregisterClient(this);
|
||||
|
||||
if(m_pServerSlot)
|
||||
m_pServerSlot->ResetSink();
|
||||
}
|
||||
|
||||
void CClientLocal::Connect( const char *szIP, WORD wPort, const BYTE *pbAuthorizationID, unsigned int uiAuthorizationSize )
|
||||
{
|
||||
assert(pbAuthorizationID);
|
||||
assert(uiAuthorizationSize>0);
|
||||
|
||||
m_pServerSlot=m_pNetwork->ConnectToLocalServerSlot(this,wPort);
|
||||
if(m_pSink)m_pSink->OnXConnect();
|
||||
|
||||
CStream stAuthorizationID;
|
||||
|
||||
stAuthorizationID.Write(uiAuthorizationSize*8);
|
||||
stAuthorizationID.WriteBits(const_cast<BYTE*>(pbAuthorizationID),uiAuthorizationSize*8);
|
||||
|
||||
ICVar *sv_punkbuster = GetISystem()->GetIConsole()->GetCVar("sv_punkbuster");
|
||||
ICVar *cl_punkbuster = GetISystem()->GetIConsole()->GetCVar("cl_punkbuster");
|
||||
|
||||
if (sv_punkbuster && sv_punkbuster->GetIVal() != 0)
|
||||
{
|
||||
if (cl_punkbuster && cl_punkbuster->GetIVal() != 0)
|
||||
{
|
||||
m_pNetwork->InitPunkbusterClientLocal(this);
|
||||
}
|
||||
}
|
||||
m_pNetwork->LockPunkbusterCVars();
|
||||
|
||||
m_pServerSlot->OnCCPConnectResp(stAuthorizationID);
|
||||
}
|
||||
|
||||
void CClientLocal::Disconnect(const char *szCause)
|
||||
{
|
||||
GetISystem()->GetILog()->Log("NetDEBUG: CClientLocal::Disconnect");
|
||||
|
||||
if(m_pServerSlot)
|
||||
m_pServerSlot->OnCCPDisconnect(szCause);
|
||||
if (m_pSink)
|
||||
m_pSink->OnXClientDisconnect(szCause);
|
||||
|
||||
ResetSink();
|
||||
}
|
||||
|
||||
void CClientLocal::OnDisconnenct(const char *szCause)
|
||||
{
|
||||
if(m_pSink)
|
||||
m_pSink->OnXClientDisconnect(szCause);
|
||||
}
|
||||
|
||||
void CClientLocal::SendReliable(CStream &stm)
|
||||
{
|
||||
if(m_pServerSlot)
|
||||
m_pServerSlot->PushData(stm);
|
||||
}
|
||||
|
||||
void CClientLocal::SendUnreliable(CStream &stm)
|
||||
{
|
||||
if(m_pServerSlot)
|
||||
m_pServerSlot->PushData(stm);
|
||||
}
|
||||
|
||||
void CClientLocal::ContextReady(CStream &stm)
|
||||
{
|
||||
m_pServerSlot->OnCCPContextReady(stm);
|
||||
}
|
||||
|
||||
|
||||
bool CClientLocal::IsReady()
|
||||
{
|
||||
return ((m_pSink && m_pServerSlot)?true:false);
|
||||
}
|
||||
|
||||
bool CClientLocal::Update(unsigned int nTime)
|
||||
{
|
||||
int iCount=0;
|
||||
|
||||
while(!m_qData.empty())
|
||||
{
|
||||
if(m_pSink)
|
||||
{
|
||||
DWORD dwQueueSize=m_qData.size();
|
||||
|
||||
m_pSink->OnXData(m_qData.front());
|
||||
|
||||
// assert(m_qData.size()==dwQueueSize); // the OnData might add data to the stack
|
||||
|
||||
// [Sergiy] iCount can reach more than 1000 right after loading a level (in Editor, at least)
|
||||
assert(iCount<10000); // otherwise an endless loop would occur
|
||||
|
||||
iCount++;
|
||||
}
|
||||
m_qData.pop();
|
||||
}
|
||||
|
||||
if(m_pServerSlot)
|
||||
m_pServerSlot->UpdateSlot();
|
||||
|
||||
m_pNetwork->OnClientUpdate();
|
||||
|
||||
return true; // this object is still exising
|
||||
}
|
||||
|
||||
void CClientLocal::GetBandwidth( float &fIncomingKbPerSec, float &fOutgoingKbPerSec, DWORD &nIncomingPackets, DWORD &nOutgoingPackets )
|
||||
{
|
||||
fIncomingKbPerSec=0;
|
||||
fOutgoingKbPerSec=0;
|
||||
nIncomingPackets=0;
|
||||
nOutgoingPackets=0;
|
||||
}
|
||||
|
||||
void CClientLocal::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
void CClientLocal::SetServerIP( const char *szServerIP )
|
||||
{
|
||||
m_sServerIP = szServerIP;
|
||||
}
|
||||
|
||||
|
||||
void CClientLocal::InitiateCDKeyAuthorization( const bool inbCDAuthorization )
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
if(inbCDAuthorization)
|
||||
m_pNetwork->m_pUbiSoftClient->Client_GetCDKeyAuthorizationID(); // OnXCDKeyAuthorization is called later
|
||||
else
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
{
|
||||
OnCDKeyAuthorization(0); // 0 -> fake AuthorizationID is generated
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
void CClientLocal::OnCDKeyAuthorization( BYTE *pbAuthorizationID )
|
||||
{
|
||||
if(!pbAuthorizationID)
|
||||
{
|
||||
static BYTE fakeid[AUTHORIZATION_ID_SIZE];
|
||||
|
||||
pbAuthorizationID = fakeid;
|
||||
|
||||
memset(fakeid,0,AUTHORIZATION_ID_SIZE); // generated fake AuthorizationID
|
||||
}
|
||||
|
||||
char *sSemicolon;
|
||||
unsigned short port = 0;
|
||||
char temp[256];
|
||||
strncpy(temp,m_sServerIP.c_str(),256);
|
||||
|
||||
if(sSemicolon=strstr(temp,":"))
|
||||
{
|
||||
port=atoi(&sSemicolon[1]);
|
||||
sSemicolon[0]='\0';
|
||||
}
|
||||
|
||||
if(port==0)
|
||||
port=DEFAULT_SERVERPORT;
|
||||
|
||||
Connect(temp, port, pbAuthorizationID,AUTHORIZATION_ID_SIZE);
|
||||
}
|
||||
69
CryNetwork/ClientLocal.h
Normal file
69
CryNetwork/ClientLocal.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// ClientLocal.h: interface for the CClientLocal class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _CLIENTLOCAL_H_
|
||||
#define _CLIENTLOCAL_H_
|
||||
|
||||
#include <queue>
|
||||
|
||||
|
||||
class CNetwork;
|
||||
class CServerSlotLocal;
|
||||
struct IClientSink;
|
||||
|
||||
/*!fake CClient implementation for local clients
|
||||
doesn't use the network!*/
|
||||
class CClientLocal :
|
||||
public IClient
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CClientLocal(CNetwork *pNetwork,IClientSink *pSink);
|
||||
//! destructor
|
||||
virtual ~CClientLocal();
|
||||
|
||||
// interface IClient --------------------------------------------------------------------
|
||||
|
||||
virtual void Connect(const char *szIP, WORD wPort, const BYTE *pbAuthorizationID, unsigned int iAuthorizationSize);
|
||||
virtual void Disconnect(const char *szCause);
|
||||
virtual void SendReliable(CStream &stm);
|
||||
virtual void SendUnreliable(CStream &stm);
|
||||
virtual void ContextReady(CStream &stm);
|
||||
virtual bool IsReady();
|
||||
virtual bool Update(unsigned int nTime);
|
||||
virtual void GetBandwidth( float &fIncomingKbPerSec, float &fOutgoinKbPerSec, DWORD &nIncomingPackets, DWORD &nOutgoingPackets );
|
||||
virtual void Release();
|
||||
virtual unsigned int GetPing(){return 0;}
|
||||
virtual unsigned int GetRemoteTimestamp(unsigned int nTime){return nTime;}
|
||||
virtual unsigned int GetPacketsLostCount(){return 0;}
|
||||
virtual unsigned int GetUnreliablePacketsLostCount(){return 0;}
|
||||
virtual void OnCDKeyAuthorization( BYTE *pbAuthorizationID );
|
||||
virtual void SetServerIP( const char *szServerIP );
|
||||
virtual void InitiateCDKeyAuthorization( const bool inbCDAuthorization );
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
void ResetSink(){m_pSink=NULL;};
|
||||
void PushData(CStream &stm){ m_qData.push(stm);}
|
||||
void OnConnect(CNPServerVariables sv){ if(m_pSink)m_pSink->OnXConnect();}
|
||||
void OnContextSetup(CStream &stm){ if(m_pSink)m_pSink->OnXContextSetup(stm);}
|
||||
void OnDisconnenct(const char *szCause);
|
||||
void OnCCPSecurityQuery(CStream &stm) {};
|
||||
void OnCCPSecurityResp(CStream &stm) {};
|
||||
void OnCCPPunkBusterMsg(CStream &stm) {};
|
||||
|
||||
void OnDestructServerSlot(){ m_pServerSlot=0; }
|
||||
virtual CIPAddress GetServerIP() const { return CIPAddress(); };
|
||||
|
||||
private: // -------------------------------------------------------------------------------------
|
||||
|
||||
string m_sServerIP; //!<
|
||||
IClientSink * m_pSink; //!<
|
||||
CNetwork * m_pNetwork; //!<
|
||||
CServerSlotLocal * m_pServerSlot; //!<
|
||||
bool m_bReady; //!<
|
||||
STREAM_QUEUE m_qData; //!<
|
||||
};
|
||||
|
||||
#endif //_CLIENTLOCAL_H_
|
||||
232
CryNetwork/ClientStateMachine.cpp
Normal file
232
CryNetwork/ClientStateMachine.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: ClientStateMachine.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ClientStateMachine.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
#include "IConsole.h" // IConsole
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CClientStateMachine::CClientStateMachine()
|
||||
{
|
||||
}
|
||||
|
||||
CClientStateMachine::~CClientStateMachine()
|
||||
{
|
||||
}
|
||||
|
||||
void CClientStateMachine::_Trace(char *s)
|
||||
{
|
||||
//::OutputDebugString(s);
|
||||
}
|
||||
|
||||
void CClientStateMachine::_TraceStatus(unsigned int dwStatus)
|
||||
{
|
||||
switch(dwStatus){
|
||||
case STATUS_IDLE:
|
||||
_Trace("STATUS_IDLE");
|
||||
break;
|
||||
case STATUS_WAIT_FOR_CONNECT:
|
||||
_Trace("STATUS_WAIT_FOR_CONNECT");
|
||||
break;
|
||||
case STATUS_CONNECTED:
|
||||
_Trace("STATUS_CONNECTED");
|
||||
break;
|
||||
case STATUS_PROCESSING_CONTEXT:
|
||||
_Trace("STATUS_PROCESSING_CONTEXT");
|
||||
break;
|
||||
case STATUS_WAIT_FOR_SERVER_READY:
|
||||
_Trace("STATUS_WAIT_FOR_SERVER_READY");
|
||||
break;
|
||||
case STATUS_READY:
|
||||
_Trace("STATUS_READY");
|
||||
break;
|
||||
case STATUS_DISCONNECTED:
|
||||
_Trace("STATUS_DISCONNECTED");
|
||||
break;
|
||||
default:
|
||||
_Trace("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CClientStateMachine::HandleANY(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
ANY_SIGNAL_EXCEPT(STATUS_DISCONNECTED);
|
||||
BEGIN_ANY_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_DISCONNECT)
|
||||
SetStatus(STATUS_DISCONNECTED);
|
||||
OnSignal(SIG_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_ACTIVE_DISCONNECT)
|
||||
SetStatus(STATUS_DISCONNECTED);
|
||||
OnSignal(SIG_SEND_DISCONNECT,dwParam);
|
||||
OnSignal(SIG_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_ANY_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandleIDLE(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_START)
|
||||
SetStatus(STATUS_WAIT_FOR_CONNECT);
|
||||
SetTimer(TM_CONNECT,TM_CONNECT_ET);
|
||||
OnSignal(SIG_SEND_SETUP,0);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandleWAIT_FOR_CONNECT(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_CONNECT)
|
||||
SetStatus(STATUS_CONNECTED);
|
||||
ResetTimer();
|
||||
OnSignal(SIG_SEND_CONNECT_RESP,0);
|
||||
OnSignal(SIG_CONNECTED,0);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(TM_CONNECT)
|
||||
SetStatus(STATUS_DISCONNECTED);
|
||||
OnSignal(SIG_DISCONNECTED, (DWORD_PTR)"@ConnectionTimeout");
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandleCONNECTED(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_CONTEXT_SETUP)
|
||||
SetStatus(STATUS_PROCESSING_CONTEXT);
|
||||
OnSignal(SIG_INCOMING_CONTEXT_SETUP,dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandlePROCESSING_CONTEXT(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_CONTEXT_READY)
|
||||
SetTimer(TM_SERVER_READY,TM_SERVER_READY_ET);
|
||||
SetStatus(STATUS_WAIT_FOR_SERVER_READY);
|
||||
OnSignal(SIG_SEND_CONTEXT_READY,dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_CONTEXT_SETUP)
|
||||
SetStatus(STATUS_PROCESSING_CONTEXT);
|
||||
OnSignal(SIG_INCOMING_CONTEXT_SETUP,dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandleWAIT_FOR_SERVER_READY(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SERVER_READY)
|
||||
SetStatus(STATUS_READY);
|
||||
ResetTimer();
|
||||
OnSignal(SIG_INCOMING_SERVER_READY,dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_CONTEXT_SETUP)
|
||||
SetStatus(STATUS_PROCESSING_CONTEXT);
|
||||
OnSignal(SIG_INCOMING_CONTEXT_SETUP,dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(TM_SERVER_READY)
|
||||
// SetStatus(STATUS_DISCONNECTED);
|
||||
ResetTimer();
|
||||
// OnSignal(SIG_DISCONNECTED, (ULONG_PTR)"timeout(TM_SERVER_READY)");
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandleREADY(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_CONTEXT_SETUP)
|
||||
SetStatus(STATUS_PROCESSING_CONTEXT);
|
||||
OnSignal(SIG_INCOMING_CONTEXT_SETUP,dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CClientStateMachine::HandleDISCONNECTED(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
//the machine can't leave this status
|
||||
}
|
||||
|
||||
|
||||
void CClientStateMachine::Init(_IClientServices *pParent)
|
||||
{
|
||||
m_pParent=pParent;
|
||||
}
|
||||
|
||||
void CClientStateMachine::OnSignal(unsigned int dwOutgoingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
switch(dwOutgoingSignal){
|
||||
case SIG_SEND_SETUP:
|
||||
m_pParent->SendSetup();
|
||||
break;
|
||||
case SIG_SEND_CONNECT_RESP:
|
||||
m_pParent->SendConnectResp();
|
||||
break;
|
||||
case SIG_SEND_CONTEXT_READY:
|
||||
m_pParent->SendContextReady();
|
||||
break;
|
||||
case SIG_SEND_DISCONNECT:
|
||||
m_pParent->SendDisconnect((const char*)dwParam);
|
||||
break;
|
||||
case SIG_CONNECTED:
|
||||
m_pParent->OnConnect();
|
||||
break;
|
||||
case SIG_INCOMING_CONTEXT_SETUP:
|
||||
m_pParent->OnContextSetup();
|
||||
break;
|
||||
case SIG_INCOMING_SERVER_READY:
|
||||
m_pParent->OnServerReady();
|
||||
break;
|
||||
case SIG_DISCONNECTED:
|
||||
m_pParent->OnDisconnect((const char *)dwParam); // this pointer is destroyed aftr this call
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
124
CryNetwork/ClientStateMachine.h
Normal file
124
CryNetwork/ClientStateMachine.h
Normal file
@@ -0,0 +1,124 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: ClientStateMachine.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -08/25/2001: Alberto Demichelis, created
|
||||
// -01/26/2003: Martin Mittring, commented the stated
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef _CLIENT_STATE_MACHINE_H_
|
||||
#define _CLIENT_STATE_MACHINE_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "StateMachine.h"
|
||||
#include "Interfaces.h"
|
||||
|
||||
#define STATUS_WAIT_FOR_CONNECT STATUS_BASE+1
|
||||
#define STATUS_CONNECTED STATUS_BASE+2
|
||||
#define STATUS_PROCESSING_CONTEXT STATUS_BASE+3
|
||||
#define STATUS_WAIT_FOR_SERVER_READY STATUS_BASE+4
|
||||
#define STATUS_READY STATUS_BASE+5
|
||||
#define STATUS_DISCONNECTED STATUS_BASE+6
|
||||
|
||||
//in signals
|
||||
#define SIG_START SIGNAL_BASE+1
|
||||
#define SIG_CONNECT SIGNAL_BASE+2
|
||||
#define SIG_CONTEXT_SETUP SIGNAL_BASE+3
|
||||
#define SIG_CONTEXT_READY SIGNAL_BASE+4
|
||||
#define SIG_SERVER_READY SIGNAL_BASE+5
|
||||
#define SIG_DISCONNECT SIGNAL_BASE+6
|
||||
#define SIG_ACTIVE_DISCONNECT SIGNAL_BASE+7
|
||||
|
||||
//out signals
|
||||
#define SIG_SEND_SETUP SIGNAL_BASE+8
|
||||
#define SIG_SEND_CONNECT_RESP SIGNAL_BASE+9
|
||||
#define SIG_SEND_CONTEXT_READY SIGNAL_BASE+10
|
||||
#define SIG_SEND_DISCONNECT SIGNAL_BASE+11
|
||||
#define SIG_CONNECTED SIGNAL_BASE+12
|
||||
#define SIG_INCOMING_CONTEXT_SETUP SIGNAL_BASE+13
|
||||
#define SIG_INCOMING_SERVER_READY SIGNAL_BASE+14
|
||||
#define SIG_DISCONNECTED SIGNAL_BASE+15
|
||||
|
||||
#define TM_CONNECT TIMER_BASE+1
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define TM_CONNECT_ET 200000
|
||||
#else
|
||||
#define TM_CONNECT_ET 10000
|
||||
#endif
|
||||
|
||||
#define TM_SERVER_READY TIMER_BASE+2
|
||||
#define TM_SERVER_READY_ET 120000
|
||||
|
||||
|
||||
|
||||
|
||||
class CClientStateMachine :public CStateMachine
|
||||
{
|
||||
BEGIN_STATUS_MAP()
|
||||
STATUS_ENTRY(STATUS_IDLE,HandleIDLE)
|
||||
// goes to the next state right after creation of the client
|
||||
|
||||
STATUS_ENTRY(STATUS_WAIT_FOR_CONNECT,HandleWAIT_FOR_CONNECT)
|
||||
// goes to the next state when the client gets the CCPConnect packet (time value from the server) from the server
|
||||
|
||||
STATUS_ENTRY(STATUS_CONNECTED,HandleCONNECTED)
|
||||
// goes to the next state when the client gets the CCPContextSetup packet (map name, mod, player model, playerclass ..) from the server
|
||||
|
||||
STATUS_ENTRY(STATUS_PROCESSING_CONTEXT,HandlePROCESSING_CONTEXT)
|
||||
// goes to the next state when finished loading the map and
|
||||
// sends the CCPContextReady packet (bHost,p_name,p_model) to the server
|
||||
|
||||
STATUS_ENTRY(STATUS_WAIT_FOR_SERVER_READY,HandleWAIT_FOR_SERVER_READY)
|
||||
// is getting all entities from the server (XSERVERMSG_ADDENTITY)
|
||||
// goes to the next state when the client gets the CCPServerReady packet (empty) from the server
|
||||
|
||||
STATUS_ENTRY(STATUS_READY,HandleREADY)
|
||||
// goes back to STATUS_PROCESSING_CONTEXT when the client gets the CCPContextSetup packet
|
||||
|
||||
STATUS_ENTRY(STATUS_DISCONNECTED,HandleDISCONNECTED)
|
||||
// when going in this state send the SIG_DISCONNECTED signal and the system will remove the client soon
|
||||
|
||||
END_STATUS_MAP()
|
||||
|
||||
public: // ---------------------------------------------------------------------------
|
||||
|
||||
//! constructor
|
||||
CClientStateMachine();
|
||||
//! destructor
|
||||
virtual ~CClientStateMachine();
|
||||
//!
|
||||
void Init(_IClientServices *pParent);
|
||||
|
||||
private: // --------------------------------------------------------------------------
|
||||
|
||||
//status handlers
|
||||
void HandleIDLE(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleWAIT_FOR_CONNECT(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleCONNECTED(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandlePROCESSING_CONTEXT(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleWAIT_FOR_SERVER_READY(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleREADY(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleDISCONNECTED(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
virtual unsigned int HandleANY(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
|
||||
void OnSignal(unsigned int dwOutgoingSignal,DWORD_PTR dwParam);
|
||||
|
||||
// tracing
|
||||
void _Trace(char *s);
|
||||
void _TraceStatus(unsigned int dwStatus);
|
||||
|
||||
_IClientServices * m_pParent; //!<
|
||||
};
|
||||
|
||||
#endif // _CLIENT_STATE_MACHINE_H_
|
||||
|
||||
37
CryNetwork/CommonDefines.h
Normal file
37
CryNetwork/CommonDefines.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef _COMMON_DEFINES_
|
||||
#define _COMMON_DEFINES_
|
||||
|
||||
#define UBISOFT_GAME_VERSION "FARCRYPC1.33"
|
||||
#define GAME_NAME "FARCRY"
|
||||
const char GSGAMEVERSION[5] = "1.33";
|
||||
|
||||
|
||||
// Ubi.com Errors
|
||||
const char UNKNOWNERROR[] = "@UbiUnknownError";
|
||||
const char CONNECTIONFAILED[] = "@UbiConnectionFailed";
|
||||
const char INVALIDACCOUNT[] = "@UbiInvalidAccount";
|
||||
const char INVALIDPASSWORD[] = "@UbiInvalidPassword";
|
||||
const char DATABASEFAILED[] = "@UbiDatabaseFailed";
|
||||
const char BANNEDACCOUNT[] = "@UbiBannedAccount";
|
||||
const char BLOCKEDACCOUNT[] = "@UbiBlockedAccount";
|
||||
const char LOCKEDACCOUNT[] = "@UbiLockedAccount";
|
||||
const char NOTDISCONNECTED[] = "@UbiNotDisconnected";
|
||||
const char USERNAMEEXISTS[] = "@UbiUsernameExists";
|
||||
const char USERNAMEMALFORMED[] = "@UbiUsernameMalformed";
|
||||
const char USERNAMEFORBIDDEN[] = "@UbiUsernameForbidden";
|
||||
const char USERNAMERESERVED[] = "@UbiUsernameReserved";
|
||||
const char PASSWORDMALFORMED[] = "@UbiPasswordMalformed";
|
||||
const char PASSWORDFORBIDDEN[] = "@UbiPasswordForbidden";
|
||||
const char CREATEACCOUNTBLOCKED[] = "@UbiCreateAccountBlocked";
|
||||
const char GROUPNOTEXIST[] = "@UbiGroupNotExist";
|
||||
const char NOMOREPLAYERS[] = "@UbiNoMorePlayers";
|
||||
const char CDKEYINTERNALERROR[]= "@UbiCDKeyInternalError";
|
||||
const char CDKEYNOTCHALLENGED[]= "@UbiCDKeyNotChallenged";
|
||||
const char CDKEYONLINE[] = "@UbiCDKeyOnline"; // CDKey already in use!
|
||||
const char CDKEYTIMEOUT[] = "@UbiCDKeyTimeout";
|
||||
const char INVALIDCDKEY[] = "@UbiInvalidCDKey";
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //_COMMON_DEFINES_
|
||||
167
CryNetwork/CompressionHelper.cpp
Normal file
167
CryNetwork/CompressionHelper.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "stdafx.h"
|
||||
#include "compressionhelper.h"
|
||||
#include "stream.h" // CStream
|
||||
|
||||
|
||||
CCompressionHelper::CCompressionHelper()
|
||||
{
|
||||
#ifdef GATHER_CHARSTATISTICS
|
||||
memset(m_dwCharStats,0,sizeof(DWORD)*256);
|
||||
m_dwWriteBitsUncompressed=0;
|
||||
m_dwWriteBitsCompressed=0;
|
||||
#endif
|
||||
|
||||
{
|
||||
DWORD dwCharStats[]= // created with GATHER_CHARSTATISTICS
|
||||
{
|
||||
47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
131,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,
|
||||
61,51,19,2,18,15,3,0,0,0,0,0,0,0,0,0,
|
||||
0,7,0,14,2,0,7,9,0,1,0,0,4,0,0,2,
|
||||
28,0,26,6,14,4,0,0,7,0,0,0,0,0,0,0,
|
||||
0,11,0,5,5,6,0,0,0,4,0,0,0,0,6,3,
|
||||
5,0,10,10,22,6,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
};
|
||||
// m_dwWriteBitsUncompressed=4584 m_dwWriteBitsCompressed=2499
|
||||
|
||||
char c;
|
||||
|
||||
for(c='0';c<='9';c++) dwCharStats[(DWORD)c]++;
|
||||
for(c='a';c<='z';c++) dwCharStats[(DWORD)c]++;
|
||||
for(c='A';c<='Z';c++) dwCharStats[(DWORD)c]++;
|
||||
|
||||
m_CharCompressor.InitFromStatistics(dwCharStats);
|
||||
}
|
||||
|
||||
|
||||
/* // testing code
|
||||
|
||||
#ifdef _DEBUG
|
||||
DWORD t[3];
|
||||
|
||||
for(t[0]=0;t[0]<256;t[0]++)
|
||||
for(t[1]=0;t[1]<256;t[1]++)
|
||||
for(t[2]=0;t[2]<256;t[2]++)
|
||||
{
|
||||
char s[4];
|
||||
char q[4];
|
||||
|
||||
s[0]=(char)t[0];
|
||||
s[1]=(char)t[1];
|
||||
s[2]=(char)t[2];
|
||||
s[3]=0;
|
||||
|
||||
CStream str;
|
||||
|
||||
Write(str,s);
|
||||
Read(str,q,4);
|
||||
|
||||
assert(strcmp((const char *)s,(const char *)q)==0);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
CCompressionHelper::~CCompressionHelper()
|
||||
{
|
||||
#ifdef GATHER_CHARSTATISTICS
|
||||
FILE *out=fopen("c:\\temp\\CharStats.cpp","wb");
|
||||
|
||||
// fprintf(out,"");
|
||||
|
||||
for(DWORD a=0;a<16;a++)
|
||||
{
|
||||
fprintf(out," ");
|
||||
for(DWORD b=0;b<16;b++)
|
||||
{
|
||||
DWORD i=a*16+b;
|
||||
|
||||
fprintf(out,"%d,",m_dwCharStats[i]);
|
||||
}
|
||||
fprintf(out,"\r\n");
|
||||
}
|
||||
|
||||
fprintf(out,"\r\nm_dwWriteBitsUncompressed=%d m_dwWriteBitsCompressed=%d\r\n",m_dwWriteBitsUncompressed,m_dwWriteBitsCompressed);
|
||||
|
||||
|
||||
fclose(out);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CCompressionHelper::Write( CStream &outStream, const unsigned char inChar )
|
||||
{
|
||||
return m_CharCompressor.Write(outStream,inChar);
|
||||
}
|
||||
|
||||
bool CCompressionHelper::Read( CStream &inStream, unsigned char &outChar )
|
||||
{
|
||||
return m_CharCompressor.Read(inStream,outChar);
|
||||
}
|
||||
|
||||
bool CCompressionHelper::Write( CStream &outStream, const char *inszString )
|
||||
{
|
||||
assert(inszString);
|
||||
|
||||
const unsigned char *p=(unsigned char *)inszString;
|
||||
|
||||
#ifdef GATHER_CHARSTATISTICS
|
||||
DWORD dwOldSize=outStream.GetSize();
|
||||
#endif
|
||||
|
||||
while(*p)
|
||||
{
|
||||
unsigned char c=*p++;
|
||||
#ifdef GATHER_CHARSTATISTICS
|
||||
m_dwCharStats[c]++;
|
||||
m_dwWriteBitsUncompressed+=8;
|
||||
#endif
|
||||
if(!Write(outStream,c))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bRet=Write(outStream,(unsigned char)0);
|
||||
|
||||
#ifdef GATHER_CHARSTATISTICS
|
||||
m_dwCharStats[0]++; // zero termination
|
||||
m_dwWriteBitsUncompressed+=8;
|
||||
m_dwWriteBitsCompressed+=outStream.GetSize()-dwOldSize;
|
||||
#endif
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool CCompressionHelper::Read( CStream &inStream, char *outszString, const DWORD indwStringSize )
|
||||
{
|
||||
assert(outszString);
|
||||
assert(indwStringSize);
|
||||
|
||||
for(DWORD i=0;i<indwStringSize;i++)
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
if(!Read(inStream,c))
|
||||
return false;
|
||||
|
||||
outszString[i]=(char)c;
|
||||
|
||||
if(c==0)
|
||||
return true;
|
||||
}
|
||||
|
||||
outszString[indwStringSize-1]=0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
39
CryNetwork/CompressionHelper.h
Normal file
39
CryNetwork/CompressionHelper.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _COMPRESSIONHELPER_H_
|
||||
#define _COMPRESSIONHELPER_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "ICompressionHelper.h" // ICompressionHelper
|
||||
#include "StaticCharCompressor.h" // CStaticCharCompressor
|
||||
|
||||
//#define GATHER_CHARSTATISTICS // only needed during development - to build up the compression table
|
||||
|
||||
|
||||
class CCompressionHelper :public ICompressionHelper
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CCompressionHelper();
|
||||
//! destructor
|
||||
virtual ~CCompressionHelper();
|
||||
|
||||
// interface ICompressionHelper ---------------------------------------------
|
||||
|
||||
virtual bool Write( CStream &outStream, const unsigned char inChar );
|
||||
virtual bool Read( CStream &inStream, unsigned char &outChar );
|
||||
virtual bool Write( CStream &outStream, const char *inszString );
|
||||
virtual bool Read( CStream &inStream, char *outszString, const DWORD indwStringSize );
|
||||
|
||||
private: // -------------------------------------------------------------------
|
||||
|
||||
CStaticCharCompressor m_CharCompressor; //!< based on static Huffman compresson
|
||||
#ifdef GATHER_CHARSTATISTICS
|
||||
DWORD m_dwCharStats[256]; //!<
|
||||
DWORD m_dwWriteBitsCompressed; //!<
|
||||
DWORD m_dwWriteBitsUncompressed; //!<
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //_COMPRESSIONHELPER_H_
|
||||
62
CryNetwork/CryNetwork.cpp
Normal file
62
CryNetwork/CryNetwork.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: crynetwork.cpp
|
||||
// Description: dll entry point
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CNP.h"
|
||||
#include "Client.h"
|
||||
#include "Server.h"
|
||||
#include "Network.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Pointer to Global ISystem.
|
||||
static ISystem* gISystem = 0;
|
||||
ISystem* GetISystem()
|
||||
{
|
||||
return gISystem;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(XBOX)
|
||||
_ACCESS_POOL;
|
||||
#if !defined(LINUX)
|
||||
|
||||
BOOL APIENTRY DllMain( HANDLE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _XBOX
|
||||
CRYNETWORK_API INetwork *CreateNetwork(ISystem *pSystem)
|
||||
#else
|
||||
INetwork *CreateNetwork(ISystem *pSystem)
|
||||
#endif
|
||||
{
|
||||
gISystem = pSystem;
|
||||
CNetwork *pNetwork=new CNetwork;
|
||||
|
||||
if(!pNetwork->Init(gISystem->GetIScriptSystem()))
|
||||
{
|
||||
delete pNetwork;
|
||||
return NULL;
|
||||
}
|
||||
return pNetwork;
|
||||
}
|
||||
|
||||
#include <CrtDebugStats.h>
|
||||
|
||||
751
CryNetwork/CryNetwork.vcproj
Normal file
751
CryNetwork/CryNetwork.vcproj
Normal file
@@ -0,0 +1,751 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="CryNetwork"
|
||||
ProjectGUID="{9A4E4BCE-D5B3-474A-874C-6578983CFC7C}"
|
||||
SccProjectName="Perforce Project"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Perforce SCM">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
OptimizeForProcessor="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon;..\ubisoft.com\ConsoleImplementation\src;"..\ubisoft.com\GSServices\sdks\gs-sdk-common\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-base\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-msclient\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-regserver\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\include""
|
||||
PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;CRYNETWORK_EXPORTS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Debug/CryNetwork.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="winmm.lib Shlwapi.lib wininet.lib Wsock32.lib Ws2_32.lib"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="".\..\ubisoft.com\GSServices\sdks/gs-sdk-regserver/lib_win32";".\..\ubisoft.com\GSServices\sdks/gs-sdk-msclient/lib_win32";".\..\ubisoft.com\GSServices\sdks/gs-sdk-common/lib_win32";".\..\ubisoft.com\GSServices\sdks/gs-sdk-base/lib_win32";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\lib_win32""
|
||||
IgnoreDefaultLibraryNames="libcmt.lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ImportLibrary="$(IntDir)/$(TargetName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/CryNetwork.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="2"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon;..\ubisoft.com\ConsoleImplementation\src;"..\ubisoft.com\GSServices\sdks\gs-sdk-common\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-base\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-msclient\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-regserver\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\include""
|
||||
PreprocessorDefinitions="_RELEASE;NDEBUG;WIN32;_WINDOWS;_USRDLL;CRYNETWORK_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Release/CryNetwork.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="winmm.lib wininet.lib Wsock32.lib Ws2_32.lib"
|
||||
OutputFile=".\Release/CryNetwork.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
IgnoreDefaultLibraryNames="libcmt.lib"
|
||||
ProgramDatabaseFile=".\Release/CryNetwork.pdb"
|
||||
ImportLibrary="$(IntDir)/$(TargetName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Release/CryNetwork.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="2"
|
||||
OmitFramePointers="TRUE"
|
||||
EnableFiberSafeOptimizations="FALSE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon;..\ubisoft.com\ConsoleImplementation\src;"..\ubisoft.com\GSServices\sdks\gs-sdk-common\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-base\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-msclient\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-regserver\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\include""
|
||||
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;CRYNETWORK_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Profile/CryNetwork.pch"
|
||||
AssemblerListingLocation=".\Profile/"
|
||||
ObjectFile=".\Profile/"
|
||||
ProgramDataBaseFileName=".\Profile/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="winmm.lib wininet.lib Wsock32.lib Ws2_32.lib"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories="".\..\ubisoft.com\GSServices\sdks/gs-sdk-regserver/lib_win32";".\..\ubisoft.com\GSServices\sdks/gs-sdk-msclient/lib_win32";".\..\ubisoft.com\GSServices\sdks/gs-sdk-common/lib_win32";".\..\ubisoft.com\GSServices\sdks/gs-sdk-base/lib_win32";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\lib_win32""
|
||||
IgnoreDefaultLibraryNames="libcmt.lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
BaseAddress="0x34500000"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName="C:\MasterCD/CryNetwork.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug64|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Debug64"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon;..\ubisoft.com\ConsoleImplementation\src;"..\ubisoft.com\GSServices\sdks\gs-sdk-msclient\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-common\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-base\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-regserver\include""
|
||||
PreprocessorDefinitions="_DEBUG;WIN64;_WINDOWS;_USRDLL;CRYNETWORK_EXPORTS"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="1"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile="$(IntDir)/$(ProjectName).pch"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/$(ProjectName).pdb"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:AMD64"
|
||||
AdditionalDependencies="winmm.lib Shlwapi.lib wininet.lib Wsock32.lib Ws2_32.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).dll"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=""..\ubisoft.com\GSServices\sdks64/gs-sdk-regserver/lib_amd64";"..\ubisoft.com\GSServices\sdks64/gs-sdk-msclient/lib_amd64";"..\ubisoft.com\GSServices\sdks64/gs-sdk-common/lib_amd64";"..\ubisoft.com\GSServices\sdks64/gs-sdk-base/lib_amd64";"..\ubisoft.com\GSServices\sdks64\gs-sdk-cdkey\lib_amd64""
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
LargeAddressAware="2"
|
||||
ImportLibrary="$(OutDir)/$(ProjectName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/CryNetwork.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release64|Win32"
|
||||
OutputDirectory="D:\Games\FC\Bin32"
|
||||
IntermediateDirectory="Release64"
|
||||
ConfigurationType="2"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
AdditionalIncludeDirectories="..\CryCommon;..\ubisoft.com\ConsoleImplementation\src;"..\ubisoft.com\GSServices\sdks\gs-sdk-msclient\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-common\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-base\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-cdkey\include";"..\ubisoft.com\GSServices\sdks\gs-sdk-regserver\include""
|
||||
PreprocessorDefinitions="_RELEASE;NDEBUG;WIN64;WIN32;_AMD64_;_WINDOWS;_USRDLL;CRYNETWORK_EXPORTS"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="2"
|
||||
BufferSecurityCheck="FALSE"
|
||||
EnableFunctionLevelLinking="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile="$(IntDir)/$(ProjectName).pch"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/$(ProjectName).pdb"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:AMD64"
|
||||
AdditionalDependencies="winmm.lib wininet.lib Wsock32.lib Ws2_32.lib"
|
||||
OutputFile="$(OutDir)/$(ProjectName).dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=""..\ubisoft.com\GSServices\sdks64/gs-sdk-regserver/lib_amd64";"..\ubisoft.com\GSServices\sdks64/gs-sdk-msclient/lib_amd64";"..\ubisoft.com\GSServices\sdks64/gs-sdk-common/lib_amd64";"..\ubisoft.com\GSServices\sdks64/gs-sdk-base/lib_amd64";"..\ubisoft.com\GSServices\sdks64\gs-sdk-cdkey\lib_amd64""
|
||||
IgnoreDefaultLibraryNames="libcmt.lib"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/$(ProjectName).pdb"
|
||||
LargeAddressAware="2"
|
||||
ImportLibrary="$(OutDir)/$(ProjectName).lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
MkTypLibCompatible="TRUE"
|
||||
SuppressStartupBanner="TRUE"
|
||||
TargetEnvironment="1"
|
||||
TypeLibraryName=".\Debug/CryNetwork.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath=".\CCPEndpoint.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Client.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientLocal.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientStateMachine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CompressionHelper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CryNetwork.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CTPEndpoint.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CTPEndpointGNB.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DatagramSocket.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DefenceWall.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="NETServerSnooper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Network.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\RConSystem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerSlot.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ServerSnooper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerStateMachine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StaticCharCompressor.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath=".\CCPEndpoint.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Client.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientLocal.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientStateMachine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CNP.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CompressionHelper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CTPEndpoint.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CTPEndpointGNB.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DatagramSocket.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DefenceWall.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Interfaces.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="NETServerSnooper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Network.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PingCalculator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\RConSystem.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerSlot.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ServerSnooper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerStateMachine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StateMachine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StaticCharCompressor.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="PunkBuster"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbcl.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbcl.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbcommon.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbmd5.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbmd5.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbsdk.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbsdk.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbsv.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release64|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\PunkBuster\pbsv.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PunkBusterInterface.cpp">
|
||||
<FileConfiguration
|
||||
Name="Profile|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PunkBusterInterface.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="UBIcom"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\CommonDefines.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NewUbisoftCDKey.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NewUbisoftClient.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NewUbisoftClient.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NewUbisoftMSClient.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\NewUbisoftRegServer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ScriptObjectNewUbisoftClient.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ScriptObjectNewUbisoftClient.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\UbisoftMemory.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\UbisoftMemory.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
10
CryNetwork/CryNetwork.vcproj.vspscc
Normal file
10
CryNetwork/CryNetwork.vcproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\CryNetwork\\CryNetwork.vcproj"
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||
}
|
||||
258
CryNetwork/CryNetwork_XBox.vcproj
Normal file
258
CryNetwork/CryNetwork_XBox.vcproj
Normal file
@@ -0,0 +1,258 @@
|
||||
<?xml version="1.0" encoding = "windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="CryNetwork_XBox"
|
||||
ProjectGUID="{9A4E4BCE-D5B3-474A-874C-6578983CFC7C}"
|
||||
SccProjectName=""$/Game01/CryNetwork", OBOAAAAA"
|
||||
SccAuxPath=""
|
||||
SccLocalPath="."
|
||||
SccProvider="MSSCCI:Microsoft Visual SourceSafe">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Xbox"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Xbox"
|
||||
OutputDirectory="Debug_XBox"
|
||||
IntermediateDirectory="Debug_XBox"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="_DEBUG;_XBOX;_LIB"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
BufferSecurityCheck="TRUE"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Debug_XBox/CryNetwork.pch"
|
||||
AssemblerListingLocation=".\Debug_XBox/"
|
||||
ObjectFile=".\Debug_XBox/"
|
||||
ProgramDataBaseFileName=".\Debug_XBox/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CryNetwork.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Xbox"
|
||||
OutputDirectory="Release_XBox"
|
||||
IntermediateDirectory="Release_XBox"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="_RELEASE;NDEBUG;_XBOX;_LIB"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile="$(IntDir)/CryNetwork.pch"
|
||||
AssemblerListingLocation="$(IntDir)/"
|
||||
ObjectFile="$(IntDir)/"
|
||||
ProgramDataBaseFileName="$(IntDir)/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="2"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CryNetwork.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Profile|Xbox"
|
||||
OutputDirectory="Profile"
|
||||
IntermediateDirectory="Profile"
|
||||
ConfigurationType="4"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="2"
|
||||
AdditionalIncludeDirectories="..\CryCommon"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_LIB"
|
||||
StringPooling="TRUE"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="3"
|
||||
PrecompiledHeaderThrough="stdafx.h"
|
||||
PrecompiledHeaderFile=".\Profile/CryNetwork.pch"
|
||||
AssemblerListingLocation=".\Profile/"
|
||||
ObjectFile=".\Profile/"
|
||||
ProgramDataBaseFileName=".\Profile/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CryNetwork.lib"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath=".\CCPEndpoint.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CTPEndpoint.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CTPEndpointGNB.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Client.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientLocal.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientStateMachine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CryNetwork.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DatagramSocket.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Network.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerSlot.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ServerSnooper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerStateMachine.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Profile|Xbox">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath=".\CCPEndpoint.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CNP.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CTPEndpoint.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="CTPEndpointGNB.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Client.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientLocal.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ClientStateMachine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DatagramSocket.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Interfaces.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Network.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\PingCalculator.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Server.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerSlot.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="ServerSnooper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ServerStateMachine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StateMachine.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\StdAfx.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
10
CryNetwork/CryNetwork_XBox.vcproj.vspscc
Normal file
10
CryNetwork/CryNetwork_XBox.vcproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\CryNetwork\\CryNetwork_XBox.vcproj"
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||
}
|
||||
384
CryNetwork/DatagramSocket.cpp
Normal file
384
CryNetwork/DatagramSocket.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: DatagramSocket.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <IPAddress.h>
|
||||
#include "DatagramSocket.h"
|
||||
#include "Network.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
NRESULT CDatagramSocket::Create(SocketType st)
|
||||
{
|
||||
int nErr = 0;
|
||||
m_nStartTick=::GetTickCount();
|
||||
#if defined(LINUX)
|
||||
if ((m_hSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
#else
|
||||
if ((m_hSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
|
||||
#endif
|
||||
{
|
||||
nErr = WSAGetLastError();
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
}
|
||||
m_stSocketType = st;
|
||||
if (m_stSocketType == NonBlocking)
|
||||
{
|
||||
#if defined(LINUX)
|
||||
if(fcntl( m_hSocket, F_SETFL, O_NONBLOCK ) < 0)
|
||||
#else
|
||||
unsigned long nTrue = 1;
|
||||
if (ioctlsocket(m_hSocket, FIONBIO, &nTrue) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
nErr = WSAGetLastError();
|
||||
Close();
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
}
|
||||
}
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
void CDatagramSocket::Close()
|
||||
{
|
||||
if (m_hSocket == INVALID_SOCKET)
|
||||
return;
|
||||
// disable receiving
|
||||
#if defined(LINUX)
|
||||
setsockopt(m_hSocket,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char *)&m_imMulticastReq, sizeof(m_imMulticastReq));
|
||||
#endif
|
||||
shutdown(m_hSocket, 0x00);
|
||||
// should be chnaged for BSD socket close() instead closesocket()
|
||||
closesocket(m_hSocket);
|
||||
m_hSocket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
NRESULT CDatagramSocket::Listen(WORD wPort, CIPAddress *xaMulticastAddress, CIPAddress *ipLocalAddress)
|
||||
{
|
||||
int nErr = 0;
|
||||
if (m_hSocket == INVALID_SOCKET)
|
||||
return NET_SOCKET_NOT_CREATED;
|
||||
sockaddr_in saLocalAddr;
|
||||
saLocalAddr.sin_family = AF_INET;
|
||||
saLocalAddr.sin_port = htons(wPort);
|
||||
// check if we need to bind to a specific interface
|
||||
if (ipLocalAddress && ipLocalAddress->GetAsUINT())
|
||||
{
|
||||
// yes, we need to bind to this ip address
|
||||
saLocalAddr.sin_addr.s_addr = inet_addr(ipLocalAddress->GetAsString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// no, use any interface
|
||||
saLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
}
|
||||
|
||||
// allow many servers on the same machine to list to the
|
||||
if (xaMulticastAddress)
|
||||
{
|
||||
BOOL bReuse=true;
|
||||
#if defined(LINUX)
|
||||
if(setsockopt(m_hSocket,SOL_SOCKET,SO_REUSEADDR,(const char *)&bReuse,sizeof(BOOL)) < 0)
|
||||
#else
|
||||
if(setsockopt(m_hSocket,SOL_SOCKET,SO_REUSEADDR,(const char *)&bReuse,sizeof(BOOL)) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
nErr = WSAGetLastError();
|
||||
|
||||
GetISystem()->GetILog()->Log("setsockopt 1 failed with registering multicast (WSAGetLastError returned %d)",nErr);
|
||||
}
|
||||
}
|
||||
#if defined(LINUX)
|
||||
BOOL bReuse=true;
|
||||
if(setsockopt(m_hSocket,SOL_SOCKET,SO_REUSEADDR,(const char *)&bReuse,sizeof(BOOL)) < 0)
|
||||
{
|
||||
nErr = WSAGetLastError();
|
||||
GetISystem()->GetILog()->Log("setsockopt 1 failed with setting reusablity to socket (WSAGetLastError returned %d)",nErr);
|
||||
}
|
||||
if (bind(m_hSocket, (struct sockaddr*)&saLocalAddr, sizeof(saLocalAddr)) < 0)
|
||||
#else
|
||||
if (bind(m_hSocket, (struct sockaddr*)&saLocalAddr, sizeof(sockaddr_in)) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
nErr = WSAGetLastError();
|
||||
GetISystem()->GetILog()->Log("Registering Multicast: bind failed(%d)",nErr);
|
||||
Close();
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
}
|
||||
|
||||
sockaddr_in sockname;
|
||||
#if defined(LINUX)
|
||||
socklen_t size = (socklen_t)sizeof(sockaddr_in);
|
||||
#else
|
||||
int size = sizeof(sockaddr_in);
|
||||
#endif
|
||||
getsockname(m_hSocket, (sockaddr *)&sockname, &size);
|
||||
|
||||
CIPAddress local(&saLocalAddr);
|
||||
CIPAddress bound(&sockname);
|
||||
|
||||
GetISystem()->GetILog()->Log("NAMES Local %s Bind %s", local.GetAsString(), bound.GetAsString());
|
||||
|
||||
// Setup Multicast registration
|
||||
|
||||
if (xaMulticastAddress)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
// DEBUG_BREAK;
|
||||
#else
|
||||
struct ip_mreq imMulticastReq;
|
||||
|
||||
if (ipLocalAddress && ipLocalAddress->GetAsUINT())
|
||||
{
|
||||
imMulticastReq.imr_interface.s_addr = inet_addr(ipLocalAddress->GetAsString());
|
||||
GetISystem()->GetILog()->Log("Registering Multicast: %s",ipLocalAddress->GetAsString());
|
||||
}
|
||||
else
|
||||
{
|
||||
imMulticastReq.imr_interface.s_addr = INADDR_ANY;
|
||||
GetISystem()->GetILog()->Log("Registering Multicast: ANY");
|
||||
}
|
||||
|
||||
imMulticastReq.imr_multiaddr.s_addr = xaMulticastAddress->GetAsUINT();
|
||||
#if defined(LINUX)
|
||||
if (setsockopt(m_hSocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *)&imMulticastReq, sizeof(ip_mreq)) < 0)
|
||||
#else
|
||||
if(setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imMulticastReq, sizeof(ip_mreq)) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
// Problem: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q257460
|
||||
// But: but we need Ws2_32.lib for UBI.com integration
|
||||
// Solution: make sure the libs are coming in in this order: Wsock32.lib Ws2_32.lib
|
||||
|
||||
nErr = WSAGetLastError();
|
||||
|
||||
GetISystem()->GetILog()->Log("setsockopt 2 failed with registering multicast (WSAGetLastError returned %d)",nErr);
|
||||
|
||||
//NET_TRACE(EnumerateError(MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr)));
|
||||
Close();
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
}
|
||||
#if defined(LINUX)
|
||||
const int TTL=255;
|
||||
if(setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof(TTL)) < 0)
|
||||
{
|
||||
nErr = WSAGetLastError();
|
||||
|
||||
GetISystem()->GetILog()->Log("setsockopt 2 failed with setting TTL for multicast (WSAGetLastError returned %d)",nErr);
|
||||
|
||||
//NET_TRACE(EnumerateError(MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr)));
|
||||
Close();
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
}
|
||||
m_imMulticastReq = imMulticastReq; //store for call to IP_DROP_MEMBERSHIP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
NRESULT CDatagramSocket::GetSocketAddresses(CIPAddress *pAddr, DWORD nMaCIPAddresses)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
return NET_FAIL;
|
||||
#else
|
||||
if (m_hSocket == INVALID_SOCKET)
|
||||
return NET_SOCKET_NOT_CREATED;
|
||||
DWORD i;
|
||||
char buf[256];
|
||||
struct hostent *hp;
|
||||
sockaddr_in port;
|
||||
#if defined(LINUX)
|
||||
socklen_t n;
|
||||
#else
|
||||
int n;
|
||||
#endif
|
||||
#ifndef PS2
|
||||
getsockname(m_hSocket, (sockaddr *)&port, &n);
|
||||
#else //PS2
|
||||
getsockname((int)m_hSocket, (sockaddr *)&port, (unsigned int *)&n);
|
||||
#endif //PS2
|
||||
if (!gethostname(buf, sizeof(buf)))
|
||||
{
|
||||
hp = gethostbyname(buf);
|
||||
if (hp)
|
||||
{
|
||||
// if (hp->h_addrtype != AF_INET)
|
||||
// CLog::Log("gethostbyname: address type was not AF_INET\n");
|
||||
// CLog::Log("Hostname: %s\n", hp->h_name);
|
||||
|
||||
i = 0;
|
||||
while (hp->h_aliases[i])
|
||||
{
|
||||
// CLog::Log("Alias: %s\n", hp->h_aliases[i]);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
while (hp->h_addr_list[i] && i < nMaCIPAddresses)
|
||||
{
|
||||
sockaddr_in temp;
|
||||
memcpy(&(temp.sin_addr), hp->h_addr_list[i], hp->h_length);
|
||||
temp.sin_port = port.sin_port;
|
||||
pAddr[i].Set(&temp);
|
||||
i++;
|
||||
}
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NET_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
NRESULT CDatagramSocket::Send(BYTE *pBuffer, int nLenBytes, CIPAddress *saAddress)
|
||||
{
|
||||
if (m_hSocket == INVALID_SOCKET)
|
||||
return NET_SOCKET_NOT_CREATED;
|
||||
if (!saAddress)
|
||||
saAddress = &m_saDefaultAddress;
|
||||
if (sendto(m_hSocket, (const char *)pBuffer, nLenBytes, 0, (sockaddr*)&saAddress->m_Address, sizeof(sockaddr)) == SOCKET_ERROR)
|
||||
{
|
||||
int nErr = WSAGetLastError();
|
||||
// Close();
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
}
|
||||
/// compute the bandwitdh///////////////////////
|
||||
if ((::GetTickCount() - m_nStartTick)>1000)
|
||||
ComputeBandwidth();
|
||||
|
||||
m_nSentBytesInThisSec += nLenBytes;
|
||||
m_nSentPacketsInThisSec++;
|
||||
///////////////////////////////////////////////
|
||||
|
||||
CNetwork *pNetwork = (CNetwork*)GetISystem()->GetINetwork();
|
||||
if (pNetwork && pNetwork->GetLogLevel() == 1)
|
||||
{
|
||||
CryLog( "[NET] Send to %s, PacketSize=%d bytes",saAddress->GetAsString(),nLenBytes );
|
||||
}
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
NRESULT CDatagramSocket::Receive(unsigned char *pBuf/*[MAX_UDP_PACKET_SIZE]*/, int nBufLen, int &nRecvBytes, CIPAddress &pFrom)
|
||||
{
|
||||
if (m_hSocket == INVALID_SOCKET)
|
||||
return NET_SOCKET_NOT_CREATED;
|
||||
int nRetValue;
|
||||
#if defined(LINUX)
|
||||
socklen_t n = (socklen_t)sizeof(sockaddr_in);
|
||||
#else
|
||||
int n = sizeof(sockaddr_in);
|
||||
#endif
|
||||
#if defined(LINUX)
|
||||
if ((nRetValue = recvfrom(m_hSocket, (char *)pBuf, nBufLen, 0, (sockaddr*)&pFrom.m_Address, &n)) < 0)
|
||||
#else
|
||||
if ((nRetValue = recvfrom(m_hSocket, (char *)pBuf, nBufLen, 0, (sockaddr*)&pFrom.m_Address, &n)) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
int nErr = GetLastError();
|
||||
switch (nErr)
|
||||
{
|
||||
case WSAEWOULDBLOCK:
|
||||
nRecvBytes = 0;
|
||||
return NET_OK;
|
||||
break;
|
||||
case WSAEMSGSIZE:
|
||||
//<<FIXME>> warning message "packet oversize"
|
||||
return NET_OK;
|
||||
break;
|
||||
default:
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, nErr);
|
||||
#else
|
||||
return MAKE_NRESULT(NET_FAIL, NET_FACILITY_SOCKET, errno);
|
||||
#endif
|
||||
|
||||
#if !defined(LINUX)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
nRecvBytes = nRetValue;
|
||||
/// compute the bandwith///////////////////////
|
||||
if ((::GetTickCount() - m_nStartTick)>1000)
|
||||
{
|
||||
ComputeBandwidth();
|
||||
}
|
||||
m_nReceivedBytesInThisSec += nRecvBytes;
|
||||
m_nReceivedPacketsInThisSec++;
|
||||
///////////////////////////////////////////////
|
||||
|
||||
CNetwork *pNetwork = (CNetwork*)GetISystem()->GetINetwork();
|
||||
if (pNetwork && pNetwork->GetLogLevel() == 1)
|
||||
{
|
||||
CryLog( "[NET] Recv from %s, PacketSize=%d bytes",pFrom.GetAsString(),nRecvBytes );
|
||||
}
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
const char *GetHostName()
|
||||
{
|
||||
#ifdef _XBOX
|
||||
//DEBUG_BREAK;
|
||||
return "__XBOX__";
|
||||
#else
|
||||
static char szBuf[56];
|
||||
memset(szBuf, 0, sizeof(szBuf));
|
||||
gethostname(szBuf, sizeof(szBuf));
|
||||
return szBuf;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char* CDatagramSocket::GetHostName()
|
||||
{
|
||||
#ifdef _XBOX
|
||||
//DEBUG_BREAK;
|
||||
return "__XBOX__";
|
||||
#else
|
||||
static char szBuf[56];
|
||||
memset(szBuf, 0, sizeof(szBuf));
|
||||
gethostname(szBuf, sizeof(szBuf));
|
||||
return szBuf;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDatagramSocket::ComputeBandwidth()
|
||||
{
|
||||
m_fOutgoingKbPerSec = ((float)(m_nSentBytesInThisSec*8))/1024.f;
|
||||
m_fIncomingKbPerSec = ((float)(m_nReceivedBytesInThisSec*8))/1024.f;
|
||||
m_nOutgoingPacketsPerSec = m_nSentPacketsInThisSec;
|
||||
m_nIncomingPacketsPerSec = m_nReceivedPacketsInThisSec;
|
||||
|
||||
m_nStartTick=::GetTickCount();
|
||||
|
||||
m_nSentBytesInThisSec = 0;
|
||||
m_nReceivedBytesInThisSec = 0;
|
||||
m_nSentPacketsInThisSec = 0;
|
||||
m_nReceivedPacketsInThisSec = 0;
|
||||
}
|
||||
125
CryNetwork/DatagramSocket.h
Normal file
125
CryNetwork/DatagramSocket.h
Normal file
@@ -0,0 +1,125 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: DatagramSocket.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _DATAGRAM_SOCKET_H_
|
||||
#define _DATAGRAM_SOCKET_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define MAX_UDP_PACKET_SIZE 8192
|
||||
// struct ip_mreq mreq;
|
||||
// mreq is the ip_mreqstructure
|
||||
//{
|
||||
// struct in_addr imr_multiaddr; // The multicast group to join
|
||||
// struct in_addr imr_interface; // The interface to join on
|
||||
//}
|
||||
// multicast sample addr is --> "234.5.6.7"
|
||||
|
||||
#include "Stream.h"
|
||||
#include <IPAddress.h>
|
||||
|
||||
#ifndef _XBOX
|
||||
#if _MSC_VER > 1000
|
||||
#pragma comment(lib, "WSOCK32.LIB")
|
||||
#endif // _MSC_VER > 1000
|
||||
#endif
|
||||
|
||||
#ifdef LINUX
|
||||
#include <time.h>
|
||||
#endif //LINUX
|
||||
|
||||
/*inline int gethostname(char *__name, size_t __len)
|
||||
{
|
||||
#pragma message ("gethostname not implemented")
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
class CDatagramSocket
|
||||
{
|
||||
public:
|
||||
enum SocketType
|
||||
{
|
||||
Blocking,
|
||||
NonBlocking
|
||||
};
|
||||
|
||||
//! constructor
|
||||
CDatagramSocket()
|
||||
{
|
||||
m_hSocket=INVALID_SOCKET;
|
||||
|
||||
m_nSentBytesInThisSec=0;
|
||||
m_nReceivedBytesInThisSec=0;
|
||||
m_nSentPacketsInThisSec=0;
|
||||
m_nReceivedPacketsInThisSec=0;
|
||||
|
||||
m_fIncomingKbPerSec=0.0f;
|
||||
m_fOutgoingKbPerSec=0.0f;
|
||||
m_nIncomingPacketsPerSec=0;
|
||||
m_nOutgoingPacketsPerSec=0;
|
||||
}
|
||||
//! destructor
|
||||
virtual ~CDatagramSocket()
|
||||
{
|
||||
Close();
|
||||
//<<FIXME>>
|
||||
}
|
||||
//!
|
||||
NRESULT Create(SocketType st = NonBlocking);
|
||||
//!
|
||||
NRESULT Listen(WORD wPort, CIPAddress *xaMulticastAddress = NULL, CIPAddress *ipLocalAddress = 0);
|
||||
//!
|
||||
void SetDefaultTarget(CIPAddress &saAddress)
|
||||
{
|
||||
m_saDefaultAddress.Set(saAddress);
|
||||
}
|
||||
//!
|
||||
NRESULT Send(BYTE *pBuffer, int nLenBytes, CIPAddress *saAddress = NULL);
|
||||
//!
|
||||
NRESULT Receive(unsigned char *pBuf/*[MAX_UDP_PACKET_SIZE]*/, int nBufLen, int &nRecvBytes, CIPAddress &pFrom);
|
||||
|
||||
const char *GetHostName();
|
||||
//!
|
||||
void ComputeBandwidth();
|
||||
//!
|
||||
NRESULT GetSocketAddresses(CIPAddress *pAddr, DWORD nMaCIPAddresses);
|
||||
//!
|
||||
int GetLastError(){return WSAGetLastError();}
|
||||
//!
|
||||
void Close();
|
||||
|
||||
private:
|
||||
SOCKET m_hSocket; //!<
|
||||
SocketType m_stSocketType; //!<
|
||||
CIPAddress m_saDefaultAddress; //!< Default target host and port [optional] for Send()
|
||||
unsigned int m_nStartTick; //!< tick for bandwitdh computation
|
||||
|
||||
unsigned int m_nSentBytesInThisSec; //!< is counting up and reseted every second
|
||||
unsigned int m_nReceivedBytesInThisSec; //!< is counting up and reseted every second
|
||||
unsigned int m_nSentPacketsInThisSec; //!< is counting up and reseted every second
|
||||
unsigned int m_nReceivedPacketsInThisSec; //!< is counting up and reseted every second
|
||||
#if defined(LINUX)
|
||||
struct ip_mreq m_imMulticastReq; //!< needed for call to IP_DROP_MEMBERSHIP
|
||||
#endif
|
||||
|
||||
public:
|
||||
float m_fOutgoingKbPerSec; //!< is updated every second
|
||||
float m_fIncomingKbPerSec; //!< is updated every second
|
||||
unsigned int m_nOutgoingPacketsPerSec; //!< is updated every second
|
||||
unsigned int m_nIncomingPacketsPerSec; //!< is updated every second
|
||||
};
|
||||
|
||||
|
||||
#endif //_DATAGRAM_SOCKET_H_
|
||||
961
CryNetwork/DefenceWall.cpp
Normal file
961
CryNetwork/DefenceWall.cpp
Normal file
@@ -0,0 +1,961 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001-2004.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: DefenceWall.cpp
|
||||
// Version: v1.00
|
||||
// Created: 25/1/2004 by Timur.
|
||||
// Compilers: Visual Studio.NET 2003
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "DefenceWall.h"
|
||||
#include "Network.h"
|
||||
|
||||
#include "Client.h"
|
||||
#include "Server.h"
|
||||
#include "ServerSlot.h"
|
||||
|
||||
#include "ICryPak.h"
|
||||
|
||||
//#define LOGEVENTS // don't use in public release
|
||||
|
||||
enum CHEAT_PROTECTION_LEVEL {
|
||||
CHEAT_LEVEL_DEFAULT = 1,
|
||||
CHEAT_LEVEL_RANDOMCHECKS,
|
||||
CHEAT_LEVEL_CODE,
|
||||
};
|
||||
|
||||
// Max number of retried for single request.
|
||||
#define MAX_CHECK_RETRIES 5
|
||||
// Time in seconds during which client must return response to server.
|
||||
#define WAIT_FOR_RESPONSE_TIME 20
|
||||
// Check about every 5 mins.
|
||||
#define RANDOM_CHECK_PERIOD 60*3
|
||||
|
||||
enum EDefenceWallRequestCode
|
||||
{
|
||||
DEFWALL_UNKNOWN = 0,
|
||||
DEFWALL_CHECK_PAK = 1,
|
||||
DEFWALL_CHECK_PROTECTED_FILE = 2,
|
||||
DEFWALL_CHECK_DLL_CODE = 3,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CDefenceWall::CDefenceWall( CNetwork *pNetwork )
|
||||
{
|
||||
m_pNetwork = pNetwork;
|
||||
m_pSystem = GetISystem();
|
||||
m_nNextRequestId = 1;
|
||||
m_pServer = 0;
|
||||
m_bServer = false;
|
||||
m_bLog = true;
|
||||
|
||||
m_nNumOpenedPacksOnServer = 0;
|
||||
|
||||
m_nEncryptKey[0] = 2962387638;
|
||||
m_nEncryptKey[1] = 1782685322;
|
||||
m_nEncryptKey[2] = 268651613;
|
||||
m_nEncryptKey[3] = 156356231;
|
||||
|
||||
#if defined(WIN64) || defined(LINUX64)
|
||||
m_b64bit = true;
|
||||
#else
|
||||
m_b64bit = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CDefenceWall::~CDefenceWall()
|
||||
{
|
||||
ClearAllPendingRequests();
|
||||
m_protectedFiles.clear();
|
||||
ClearClients();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::SetServer( CServer *pServer )
|
||||
{
|
||||
m_pServer = pServer;
|
||||
m_pClient = 0;
|
||||
m_bServer = true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::SetClient( CClient *pClient )
|
||||
{
|
||||
m_pServer = 0;
|
||||
m_pClient = pClient;
|
||||
m_bServer = false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::ClearClients()
|
||||
{
|
||||
for (Clients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
m_clients.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::ClearAllPendingRequests()
|
||||
{
|
||||
for (PendingChecks::iterator it = m_pendingChecks.begin(); it != m_pendingChecks.end(); it++)
|
||||
{
|
||||
SClientCheckContext* pCtx = *it;
|
||||
delete pCtx;
|
||||
}
|
||||
m_pendingChecks.clear();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::FillStdServerProbes()
|
||||
{
|
||||
m_stdServerProbes.clear();
|
||||
m_stdServerProbes.reserve(30);
|
||||
IDataProbe *pProbe = GetISystem()->GetIDataProbe();
|
||||
ICryPak::PakInfo* pPakInfo = m_pSystem->GetIPak()->GetPakInfo();
|
||||
|
||||
unsigned int i;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Collect PAK files.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
m_nNumOpenedPacksOnServer = pPakInfo->numOpenPaks;
|
||||
for (i = 0; i < pPakInfo->numOpenPaks; i++)
|
||||
{
|
||||
SClientCheckContext ctx;
|
||||
ctx.nNumOpenedPaks = pPakInfo->numOpenPaks;
|
||||
if (ServerCreateFileProbe( pPakInfo->arrPaks[i].szFilePath,ctx,true ))
|
||||
{
|
||||
m_stdServerProbes.push_back(ctx);
|
||||
}
|
||||
}
|
||||
m_pSystem->GetIPak()->FreePakInfo( pPakInfo );
|
||||
|
||||
// Do not compare user DLL`s.
|
||||
/*
|
||||
#if !defined(LINUX)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Collect Modules Code probes.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Create module probe for all DLL modules.
|
||||
IDataProbe::SModuleInfo *pModules;
|
||||
int numModules = pProbe->GetLoadedModules( &pModules );
|
||||
for (int m = 0; m < numModules; m++)
|
||||
{
|
||||
SClientCheckContext ctx;
|
||||
if (ServerCreateModuleProbe( pModules[m].filename.c_str(),ctx ))
|
||||
m_stdServerProbes.push_back(ctx);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CDefenceWall::ServerCreateModuleProbe( const char *sFilename,SClientCheckContext &ctx )
|
||||
{
|
||||
char sModule[_MAX_PATH];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
_splitpath( sFilename,0,0,fname,ext );
|
||||
_makepath( sModule,0,0,fname,ext );
|
||||
strlwr( sModule );
|
||||
|
||||
// Skip comparing render dll code. (Can be OGL,D3D or NULL)
|
||||
if (strstr(sModule,"render"))
|
||||
return false;
|
||||
|
||||
AddProtectedFile( (string("b")+"i"+"n"+"3"+"2"+"/"+sFilename).c_str() );
|
||||
|
||||
if (m_pNetwork->GetCheatProtectionLevel() >= CHEAT_LEVEL_CODE)
|
||||
{
|
||||
ctx.nRequestCode = DEFWALL_CHECK_DLL_CODE;
|
||||
ctx.bExecutableCode = true;
|
||||
ctx.probe.sFilename = sModule;
|
||||
#if !defined(LINUX)
|
||||
ctx.nFilenameHash = m_pSystem->GetIDataProbe()->GetHash( sModule );
|
||||
ctx.probe.nCodeInfo = rand()%3;
|
||||
if (!m_pSystem->GetIDataProbe()->GetRandomModuleProbe( ctx.probe ))
|
||||
return false;
|
||||
if (!m_pSystem->GetIDataProbe()->GetCode( ctx.probe ))
|
||||
return false;
|
||||
#endif
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> CreatedExeProbe[%d] %s %I64x",ctx.nRequestId,ctx.probe.sFilename.c_str(),ctx.probe.nCode );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CDefenceWall::ServerCreateFileProbe( const char *sFilename,SClientCheckContext &ctx,bool bRandomPart )
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
// Get current language.
|
||||
ICVar *pLanguage=m_pSystem->GetIConsole()->GetCVar("g_language");
|
||||
if (pLanguage && pLanguage->GetString())
|
||||
{
|
||||
// Skip validation of language specific paks.
|
||||
char fname[_MAX_FNAME];
|
||||
_splitpath( sFilename,NULL,NULL,fname,NULL );
|
||||
if (strnicmp(fname,pLanguage->GetString(),strlen(pLanguage->GetString())) == 0)
|
||||
{
|
||||
// This is language pak... skip checking it.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string file = sFilename;
|
||||
GetRelativeFilename(file);
|
||||
|
||||
ctx.nRequestCode = DEFWALL_CHECK_PAK;
|
||||
ctx.bExecutableCode = false;
|
||||
ctx.probe.sFilename = file;
|
||||
ctx.nFilenameHash = m_pSystem->GetIDataProbe()->GetHash( file.c_str() );
|
||||
if (bRandomPart)
|
||||
{
|
||||
ctx.probe.nCodeInfo = rand()%3;
|
||||
if (!m_pSystem->GetIDataProbe()->GetRandomFileProbe( ctx.probe,true ))
|
||||
return false;
|
||||
if (!m_pSystem->GetIDataProbe()->GetCode( ctx.probe ))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.probe.nCodeInfo = rand()%3;
|
||||
ctx.probe.nSize = 0xFFFFFFFF;
|
||||
if (!m_pSystem->GetIDataProbe()->GetCode( ctx.probe ))
|
||||
return false;
|
||||
}
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> CreatedFileProbe[%d] %s %I64x",ctx.nRequestId,ctx.probe.sFilename.c_str(),ctx.probe.nCode );
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::FirstTimeClientValidation( ClientInfo *pClientInfo )
|
||||
{
|
||||
CStream outstream;
|
||||
|
||||
for (unsigned int i = 0; i < m_stdServerProbes.size(); i++)
|
||||
{
|
||||
SClientCheckContext &ctx = m_stdServerProbes[i];
|
||||
if (ctx.bExecutableCode && pClientInfo->b64bit != m_b64bit) // Cannot compare clients with 32/64bit difference.
|
||||
continue;
|
||||
IssueRequest( pClientInfo,outstream,ctx );
|
||||
}
|
||||
// Send network request to this client IP.
|
||||
SendSecurityQueryToClient( pClientInfo->ip,outstream );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::RandomClientValidation( ClientInfo *pClientInfo )
|
||||
{
|
||||
CStream outstream;
|
||||
unsigned int n = 0;
|
||||
|
||||
// Ignore if no standart probes yet.
|
||||
if (m_stdServerProbes.empty())
|
||||
return;
|
||||
|
||||
bool bRepeat = false;
|
||||
while (bRepeat) {
|
||||
bRepeat = false;
|
||||
n = rand() % m_stdServerProbes.size();
|
||||
assert( n < m_stdServerProbes.size() );
|
||||
if (n >= m_stdServerProbes.size())
|
||||
bRepeat = true;
|
||||
if (m_stdServerProbes[n].bExecutableCode && pClientInfo->b64bit != m_b64bit) // Cannot compare clients with 32/64bit difference.
|
||||
bRepeat = true;
|
||||
}
|
||||
|
||||
SClientCheckContext &ctx = m_stdServerProbes[n];
|
||||
IssueRequest( pClientInfo,outstream,ctx );
|
||||
|
||||
// Send network request to this client IP.
|
||||
SendSecurityQueryToClient( pClientInfo->ip,outstream );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::IssueRequest( ClientInfo *pClientInfo,CStream &outstream,SClientCheckContext &ctx )
|
||||
{
|
||||
CTimeValue currTime = m_pNetwork->GetCurrentTime();
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Schedule new random check time for this client.
|
||||
CTimeValue timediff;
|
||||
timediff.SetSeconds( RANDOM_CHECK_PERIOD + (RANDOM_CHECK_PERIOD*rand())/RAND_MAX );
|
||||
if (m_pNetwork->GetCheatProtectionLevel() == 5)
|
||||
timediff.SetSeconds( 2 );
|
||||
pClientInfo->nextRandomCheckTime = currTime + timediff;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ctx.clientIP = pClientInfo->ip;
|
||||
if (ctx.nRetries == 0) // If repeating request do not assign new requestId.
|
||||
{
|
||||
ctx.nRequestId = m_nNextRequestId++;
|
||||
}
|
||||
ctx.requestTime = currTime;
|
||||
pClientInfo->lastRequestTime = currTime;
|
||||
SClientCheckContext *pCtx = new SClientCheckContext;
|
||||
*pCtx = ctx;
|
||||
|
||||
if (ctx.nRetries == 0)
|
||||
{
|
||||
m_pendingChecks.push_back(pCtx);
|
||||
}
|
||||
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> IssueRequest[%d] %s %I64x (ofs=%d,size=%d)",pCtx->nRequestId,pCtx->probe.sFilename.c_str(),pCtx->probe.nCode,pCtx->probe.nOffset,pCtx->probe.nSize );
|
||||
#endif
|
||||
|
||||
CStream stm;
|
||||
WriteStreamRequest( *pCtx,stm );
|
||||
|
||||
outstream.Write( stm );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::WriteStreamRequest( SClientCheckContext &ctx,CStream &stm )
|
||||
{
|
||||
stm.Write( ctx.nRequestCode );
|
||||
stm.WritePacked( ctx.nRequestId );
|
||||
stm.WritePacked( ctx.nFilenameHash );
|
||||
stm.WritePacked( ctx.probe.nCodeInfo );
|
||||
stm.WritePacked( ctx.probe.nOffset );
|
||||
stm.WritePacked( ctx.probe.nSize );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::ReadStreamRequest( SClientCheckContext &ctx,CStream &stm )
|
||||
{
|
||||
stm.Read( ctx.nRequestCode );
|
||||
stm.ReadPacked( ctx.nRequestId );
|
||||
stm.ReadPacked( ctx.nFilenameHash );
|
||||
stm.ReadPacked( ctx.probe.nCodeInfo );
|
||||
stm.ReadPacked( ctx.probe.nOffset );
|
||||
stm.ReadPacked( ctx.probe.nSize );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::WriteStreamResponse( SClientCheckContext &ctx,CStream &stm )
|
||||
{
|
||||
// Also crypt stream here.
|
||||
stm.Write( ctx.nRequestCode );
|
||||
stm.WritePacked( ctx.nRequestId );
|
||||
stm.WritePacked( ctx.nNumOpenedPaks );
|
||||
stm.WritePacked( ctx.nClientStatusFlags );
|
||||
stm.WriteBits( (BYTE*)&ctx.probe.nCode,64 ); // write int64
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::ReadStreamResponse( SClientCheckContext &ctx,CStream &stm )
|
||||
{
|
||||
stm.Read( ctx.nRequestCode );
|
||||
stm.ReadPacked( ctx.nRequestId );
|
||||
stm.ReadPacked( ctx.nNumOpenedPaks );
|
||||
stm.ReadPacked( ctx.nClientStatusFlags );
|
||||
stm.ReadBits( (BYTE*)&ctx.probe.nCode,64 ); // read int64
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SClientCheckContext* CDefenceWall::FindRequest( int nRequestId )
|
||||
{
|
||||
for (PendingChecks::iterator it = m_pendingChecks.begin(); it != m_pendingChecks.end(); it++)
|
||||
{
|
||||
SClientCheckContext* pCtx = *it;
|
||||
if (pCtx->nRequestId == nRequestId)
|
||||
{
|
||||
return pCtx;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::RemoveRequest( SClientCheckContext* pCtx )
|
||||
{
|
||||
for (PendingChecks::iterator it = m_pendingChecks.begin(); it != m_pendingChecks.end(); it++)
|
||||
{
|
||||
if (pCtx == *it)
|
||||
{
|
||||
m_pendingChecks.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::UnifyFilename( string &sFilename )
|
||||
{
|
||||
string file = sFilename;
|
||||
std::replace( file.begin(),file.end(),'\\','/' );
|
||||
strlwr( const_cast<char*>(file.c_str()) );
|
||||
sFilename = file;
|
||||
}
|
||||
|
||||
void CDefenceWall::GetRelativeFilename( string &sFilename )
|
||||
{
|
||||
UnifyFilename(sFilename);
|
||||
|
||||
// Get current folder.
|
||||
char szCurrDir[_MAX_PATH];
|
||||
GetCurrentDirectory( sizeof(szCurrDir),szCurrDir );
|
||||
string sCurDir = szCurrDir;
|
||||
|
||||
UnifyFilename(sCurDir);
|
||||
|
||||
// Get relative path.
|
||||
if (strncmp(sFilename.c_str(),sCurDir.c_str(),sCurDir.size()) == 0 && sFilename.size()+1 >= sCurDir.size())
|
||||
{
|
||||
// First part of file name is current dir.
|
||||
sFilename = sFilename.substr(sCurDir.size()+1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::EncryptStream( CStream &stm )
|
||||
{
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
int len = stm.GetSize()/8;
|
||||
if (len >= 8)
|
||||
{
|
||||
TEA_ENCODE( pBuffer,pBuffer,TEA_GETSIZE(len),m_nEncryptKey );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::DecryptStream( CStream &stm )
|
||||
{
|
||||
unsigned int* pBuffer = (unsigned int*)stm.GetPtr();
|
||||
int len = stm.GetSize()/8;
|
||||
if (len >= 8)
|
||||
{
|
||||
TEA_DECODE( pBuffer,pBuffer,TEA_GETSIZE(len),m_nEncryptKey );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::SendSecurityQueryToClient( CIPAddress &clientIP,CStream &stm )
|
||||
{
|
||||
if (m_pServer)
|
||||
{
|
||||
CServerSlot *pSlot = m_pServer->GetPacketOwner( clientIP );
|
||||
if (pSlot)
|
||||
{
|
||||
EncryptStream(stm);
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Sending Stream to Client %d bytes",stm.GetSize()/8 );
|
||||
#endif
|
||||
pSlot->SendSecurityQuery(stm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::SendSecurityRespToServer( CStream &stm )
|
||||
{
|
||||
if (m_pClient)
|
||||
{
|
||||
EncryptStream(stm);
|
||||
m_pClient->SendSecurityResponse(stm);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::OnServerRequest( CStream &stm )
|
||||
{
|
||||
DecryptStream(stm);
|
||||
m_clientOutputStream.Reset();
|
||||
while (!stm.EOS())
|
||||
{
|
||||
// When client recieves server request.
|
||||
SClientCheckContext ctx;
|
||||
ReadStreamRequest( ctx,stm );
|
||||
|
||||
// Perform required check on client.
|
||||
switch (ctx.nRequestCode)
|
||||
{
|
||||
case DEFWALL_CHECK_PAK:
|
||||
case DEFWALL_CHECK_PROTECTED_FILE:
|
||||
case DEFWALL_CHECK_DLL_CODE:
|
||||
OnValidateClientContext( ctx );
|
||||
break;
|
||||
default:
|
||||
// Unknown server request.
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "Unknown Server Request Code" );
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_clientOutputStream.GetSize() > 0)
|
||||
{
|
||||
// Send client Outputstring back to server.
|
||||
SendSecurityRespToServer( m_clientOutputStream );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::OnClientResponse( CIPAddress &clientIP,CStream &stm )
|
||||
{
|
||||
// When server recieves client response.
|
||||
DecryptStream(stm);
|
||||
|
||||
int nServerStatusFlags = GetSystemStatusFlags();
|
||||
|
||||
while (!stm.EOS())
|
||||
{
|
||||
SClientCheckContext clientResponse;
|
||||
ReadStreamResponse( clientResponse,stm );
|
||||
|
||||
SClientCheckContext &ctx = clientResponse;
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> OnClientResponse[%d] %s %I64x",ctx.nRequestId,ctx.probe.sFilename.c_str(),ctx.probe.nCode );
|
||||
#endif
|
||||
|
||||
if (clientResponse.nClientStatusFlags != nServerStatusFlags)
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Wrong Vars! %d!=%d",clientResponse.nClientStatusFlags,nServerStatusFlags );
|
||||
#endif
|
||||
// Client have different vars set.
|
||||
PunkDetected( clientIP,IServerSecuritySink::CHEAT_MODIFIED_VARS );
|
||||
return;
|
||||
}
|
||||
|
||||
// Server here checks that client response is valid and validation code match the one stored on server.
|
||||
SClientCheckContext *pServerCtx = FindRequest( clientResponse.nRequestId );
|
||||
if (pServerCtx)
|
||||
{
|
||||
// Compare client code.
|
||||
if (pServerCtx->probe.nCode != clientResponse.probe.nCode)
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Wrong Code! %d!=%d",clientResponse.probe.nCode,pServerCtx->probe.nCode );
|
||||
#endif
|
||||
// Wrong Code!
|
||||
PunkDetected( clientIP,(pServerCtx->bExecutableCode)?IServerSecuritySink::CHEAT_MODIFIED_CODE:IServerSecuritySink::CHEAT_MODIFIED_FILE );
|
||||
return;
|
||||
}
|
||||
else if (pServerCtx->nRequestCode == DEFWALL_CHECK_PAK && pServerCtx->nNumOpenedPaks != clientResponse.nNumOpenedPaks)
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Wrong Num Paks! %d!=%d",clientResponse.nNumOpenedPaks,pServerCtx->nNumOpenedPaks );
|
||||
#endif
|
||||
// Client have different number of open packs then server!
|
||||
PunkDetected( clientIP,IServerSecuritySink::CHEAT_MODIFIED_FILE );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Client send request code that server already doesnt have.
|
||||
if (clientResponse.nRequestId >= m_nNextRequestId)
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Too Big Request Id! %d!=%d",clientResponse.nClientStatusFlags,nServerStatusFlags );
|
||||
#endif
|
||||
// Possible cheating with the protocol... Client cannot recieve such a big request id before server issues it.
|
||||
PunkDetected( clientIP,IServerSecuritySink::CHEAT_NET_PROTOCOL );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this request code was already checked.
|
||||
}
|
||||
}
|
||||
// Remove request from list.
|
||||
RemoveRequest( pServerCtx );
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::OnValidateClientContext( SClientCheckContext &ctx )
|
||||
{
|
||||
#if defined(LINUX)
|
||||
return;
|
||||
#else
|
||||
bool bGotProbe = true;
|
||||
// Perform required check on client.
|
||||
switch (ctx.nRequestCode)
|
||||
{
|
||||
case DEFWALL_CHECK_PAK:
|
||||
{
|
||||
// Find out which filename to check.
|
||||
ICryPak::PakInfo* pPakInfo = m_pSystem->GetIPak()->GetPakInfo();
|
||||
ctx.nNumOpenedPaks = pPakInfo->numOpenPaks;
|
||||
for (unsigned int i = 0; i < pPakInfo->numOpenPaks; i++)
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> PAK: %s",pPakInfo->arrPaks[i].szFilePath );
|
||||
#endif
|
||||
|
||||
string file = pPakInfo->arrPaks[i].szFilePath;
|
||||
GetRelativeFilename(file);
|
||||
u32 nFilenameHash = m_pNetwork->GetStringHash(file.c_str());
|
||||
if (nFilenameHash == ctx.nFilenameHash)
|
||||
{
|
||||
// Refering to the same file.
|
||||
ctx.probe.sFilename = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_pSystem->GetIPak()->FreePakInfo( pPakInfo );
|
||||
}
|
||||
break;
|
||||
case DEFWALL_CHECK_PROTECTED_FILE:
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protectedFiles.size(); i++)
|
||||
{
|
||||
ProtectedFile &pf = m_protectedFiles[i];
|
||||
if (pf.nFilenameHash == ctx.nFilenameHash)
|
||||
{
|
||||
// We are refering to the same file.
|
||||
ctx.probe.sFilename = pf.filename;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DEFWALL_CHECK_DLL_CODE:
|
||||
{
|
||||
// Create module probe for all DLL modules.
|
||||
IDataProbe::SModuleInfo *pModules;
|
||||
int numModules = m_pSystem->GetIDataProbe()->GetLoadedModules( &pModules );
|
||||
for (int i = 0; i < numModules; i++)
|
||||
{
|
||||
char sModule[_MAX_PATH];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
_splitpath( pModules[i].filename.c_str(),0,0,fname,ext );
|
||||
_makepath( sModule,0,0,fname,ext );
|
||||
strlwr( sModule );
|
||||
|
||||
u32 nFilenameHash = m_pSystem->GetIDataProbe()->GetHash( sModule );
|
||||
if (ctx.nFilenameHash == nFilenameHash)
|
||||
{
|
||||
ctx.probe.sFilename = sModule;
|
||||
bGotProbe = m_pSystem->GetIDataProbe()->GetModuleProbe(ctx.probe);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unknown request...
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "Server Sent Unknown request" );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize code to be random.
|
||||
ctx.probe.nCode = ((u64)rand()) | (((u64)rand())<<16) | (((u64)rand())<<32) | (((u64)rand())<<48);
|
||||
|
||||
// Calc hash code of this file.
|
||||
if (bGotProbe && m_pSystem->GetIDataProbe()->GetCode( ctx.probe ))
|
||||
{
|
||||
// Code retrieved.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed...
|
||||
}
|
||||
// Send code back to server.
|
||||
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> OnServerRequest[%d] %s %I64x (ofs=%d,size=%d)",ctx.nRequestId,ctx.probe.sFilename.c_str(),ctx.probe.nCode,ctx.probe.nOffset,ctx.probe.nSize );
|
||||
#endif
|
||||
|
||||
// Every response should contain these.
|
||||
ctx.nClientStatusFlags = GetSystemStatusFlags();
|
||||
WriteStreamResponse( ctx,m_clientOutputStream );
|
||||
#endif //LINUX
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::ClearProtectedFiles()
|
||||
{
|
||||
//m_bLog = m_pNetwork->GetLogLevel() == 1024;
|
||||
|
||||
ClearAllPendingRequests();
|
||||
m_protectedFiles.clear();
|
||||
|
||||
if (m_pNetwork->GetCheatProtectionLevel() > 0)
|
||||
FillStdServerProbes();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Add default protected files.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Bin32\FarCry.exe
|
||||
//AddProtectedFile( (string("b")+"i"+"n"+"3"+"2"+"/"+"f"+"a"+"r"+"c"+"r"+"y"+"."+"e"+"x"+"e").c_str() );
|
||||
|
||||
// Bin32\XRenderD3D9.exe
|
||||
//AddProtectedFile( (string("b")+"i"+"n"+"3"+"2"+"/"+"x"+"r"+"e"+"n"+"d"+"e"+"r"+"d"+"3"+"d"+"9"+"."+"d"+"l"+"l").c_str() );
|
||||
// Bin32\XRenderNULL.exe
|
||||
//AddProtectedFile( (string("b")+"i"+"n"+"3"+"2"+"/"+"x"+"r"+"e"+"n"+"d"+"e"+"r"+"n"+"u"+"l"+"l"+"."+"d"+"l"+"l").c_str() );
|
||||
// Bin32\XRenderOGL.exe
|
||||
//AddProtectedFile( (string("b")+"i"+"n"+"3"+"2"+"/"+"x"+"r"+"e"+"n"+"d"+"e"+"r"+"o"+"g"+"l"+"."+"d"+"l"+"l").c_str() );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::AddProtectedFile( const char *sFilename )
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
string file = sFilename;
|
||||
UnifyFilename( file );
|
||||
|
||||
ProtectedFile pf;
|
||||
pf.filename = file;
|
||||
pf.nFilenameHash = m_pNetwork->GetStringHash(pf.filename.c_str());
|
||||
|
||||
// Create also STD server probe if on server.
|
||||
if (m_bServer && m_pNetwork->GetCheatProtectionLevel() > 0)
|
||||
{
|
||||
// Calc hash code of this file.
|
||||
SDataProbeContext probe;
|
||||
probe.nCodeInfo = rand()%3;
|
||||
probe.nOffset = 0;
|
||||
probe.nSize = 0xFFFFFFFF; // all file.
|
||||
probe.sFilename = file;
|
||||
if (!m_pSystem->GetIDataProbe()->GetRandomFileProbe( probe,false ))
|
||||
return;
|
||||
if (!m_pSystem->GetIDataProbe()->GetCode( probe ))
|
||||
return;
|
||||
pf.nHashCode = probe.nCode;
|
||||
|
||||
SClientCheckContext ctx;
|
||||
ctx.nRequestCode = DEFWALL_CHECK_PROTECTED_FILE;
|
||||
ctx.bExecutableCode = false;
|
||||
ctx.nFilenameHash = pf.nFilenameHash;
|
||||
ctx.probe = probe;
|
||||
m_stdServerProbes.push_back(ctx);
|
||||
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> CreatedFileProbe[%d] %s %I64x",ctx.nRequestId,ctx.probe.sFilename.c_str(),ctx.probe.nCode );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_protectedFiles.push_back(pf);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::ServerUpdate()
|
||||
{
|
||||
if (!m_bServer)
|
||||
return;
|
||||
|
||||
// m_bLog = m_pNetwork->GetLogLevel() == 1024;
|
||||
|
||||
// Ignore if no standart probes yet.
|
||||
if (m_stdServerProbes.empty())
|
||||
return;
|
||||
|
||||
CTimeValue currTime = m_pNetwork->GetCurrentTime();
|
||||
float fCurrSeconds = currTime.GetSeconds();
|
||||
|
||||
std::vector<CIPAddress> notRespondingClients;
|
||||
notRespondingClients.clear();
|
||||
|
||||
PendingChecks::iterator it,next;
|
||||
// See if any requests expired and were not responded.
|
||||
for (it = m_pendingChecks.begin(); it != m_pendingChecks.end(); it = next)
|
||||
{
|
||||
next = it; next++;
|
||||
SClientCheckContext &ctx = *(*it);
|
||||
// Check how long request is pending already.
|
||||
float fRequestTime = ctx.requestTime.GetSeconds();
|
||||
if (fCurrSeconds - fRequestTime > WAIT_FOR_RESPONSE_TIME)
|
||||
{
|
||||
// More then response seconds since request.
|
||||
if (ctx.nRetries < MAX_CHECK_RETRIES)
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Repeat Request[%d] (Retry:%d)",ctx.nRequestId,ctx.nRetries );
|
||||
#endif
|
||||
ctx.nRetries++;
|
||||
ClientInfo *pClientInfo = FindClientInfo(ctx.clientIP);
|
||||
if (pClientInfo)
|
||||
{
|
||||
// Try to issue the same request again.
|
||||
CStream outstream;
|
||||
IssueRequest( pClientInfo,outstream,ctx );
|
||||
SendSecurityQueryToClient( ctx.clientIP,outstream );
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> Delete Request[%d] Unknown Client!",ctx.nRequestId );
|
||||
#endif
|
||||
m_pendingChecks.erase(it); // something wrong with this request, not client for this ip.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LOGEVENTS
|
||||
if (m_bLog) CryLog( "<DefenceWall> No Resonse from Client for Request(%d)",ctx.nRequestId);
|
||||
#endif
|
||||
// 3 Requests without an answer.... (assume cheating client).
|
||||
notRespondingClients.push_back( ctx.clientIP );
|
||||
m_pendingChecks.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
{
|
||||
// If any client not responding.
|
||||
for (unsigned int i = 0; i < notRespondingClients.size(); i++)
|
||||
{
|
||||
PunkDetected( notRespondingClients[i],IServerSecuritySink::CHEAT_NOT_RESPONDING );
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pNetwork->GetCheatProtectionLevel() >= CHEAT_LEVEL_RANDOMCHECKS)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Go over clients and check if they need random check yet.
|
||||
for (Clients::const_iterator clit = m_clients.begin(); clit != m_clients.end(); ++clit)
|
||||
{
|
||||
ClientInfo *ci = *clit;
|
||||
if (currTime > ci->nextRandomCheckTime)
|
||||
{
|
||||
// Make random request to this client.
|
||||
RandomClientValidation( ci );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::OnAddClient( CIPAddress &clientIP )
|
||||
{
|
||||
// Check if this client already added.
|
||||
for (Clients::iterator it = m_clients.begin(); it != m_clients.end(); ++it)
|
||||
{
|
||||
// This client already added.
|
||||
if ((*it)->ip == clientIP)
|
||||
return;
|
||||
}
|
||||
|
||||
bool b64bit = false;
|
||||
CServerSlot *pSlot = m_pServer->GetPacketOwner( clientIP );
|
||||
if (pSlot)
|
||||
{
|
||||
if (pSlot->IsLocalSlot())
|
||||
return;
|
||||
b64bit = pSlot->GetClientFlags() & CLIENT_FLAGS_64BIT;
|
||||
}
|
||||
ClientInfo *ci = new ClientInfo;
|
||||
ci->lastRequestTime = 0;
|
||||
ci->nextRandomCheckTime = 0;
|
||||
ci->ip = clientIP;
|
||||
ci->b64bit = b64bit;
|
||||
|
||||
m_clients.push_back( ci );
|
||||
|
||||
// Start Validation.
|
||||
FirstTimeClientValidation( ci );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::OnDisconnectClient( CIPAddress &clientIP )
|
||||
{
|
||||
// Remove all requests to this ip.
|
||||
PendingChecks::iterator next;
|
||||
for (PendingChecks::iterator it = m_pendingChecks.begin(); it != m_pendingChecks.end(); it = next)
|
||||
{
|
||||
next = it; next++;
|
||||
SClientCheckContext* pCtx = *it;
|
||||
if (pCtx->clientIP == clientIP)
|
||||
{
|
||||
// This ip should be removed.
|
||||
delete pCtx;
|
||||
next = m_pendingChecks.erase(it);
|
||||
}
|
||||
}
|
||||
for (Clients::iterator clit = m_clients.begin(); clit != m_clients.end(); ++clit)
|
||||
{
|
||||
ClientInfo *ci = *clit;
|
||||
if (ci->ip == clientIP)
|
||||
{
|
||||
m_clients.erase(clit);
|
||||
delete ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CDefenceWall::ClientInfo* CDefenceWall::FindClientInfo( CIPAddress &clientIP ) const
|
||||
{
|
||||
for (Clients::const_iterator clit = m_clients.begin(); clit != m_clients.end(); ++clit)
|
||||
{
|
||||
ClientInfo *ci = *clit;
|
||||
if (ci->ip == clientIP)
|
||||
{
|
||||
return ci;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CDefenceWall::PunkDetected( CIPAddress &clientIP,int type )
|
||||
{
|
||||
ClientInfo *ci = FindClientInfo(clientIP);
|
||||
if (ci)
|
||||
{
|
||||
ci->bSuspectedPunk = true;
|
||||
}
|
||||
m_pNetwork->PunkDetected( clientIP );
|
||||
if (m_pServer)
|
||||
{
|
||||
if (m_pServer->GetSecuritySink())
|
||||
{
|
||||
m_pServer->GetSecuritySink()->CheaterFound( clientIP.GetAsUINT(),type,"" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum EDFSystemStatusFlags
|
||||
{
|
||||
SYS_STATUS_FORCE_NONDEVMODE = 0x0001,
|
||||
SYS_STATUS_IN_DEVMODE = 0x0002,
|
||||
SYS_STATUS_WAS_IN_DEVMODE = 0x0004,
|
||||
SYS_STATUS_PAK_PRIORITY = 0x0008,
|
||||
};
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CDefenceWall::GetSystemStatusFlags()
|
||||
{
|
||||
int flags = 0;
|
||||
if (GetISystem()->GetForceNonDevMode())
|
||||
flags |= SYS_STATUS_FORCE_NONDEVMODE;
|
||||
// Check dev mode.
|
||||
if (GetISystem()->IsDevMode())
|
||||
flags |= SYS_STATUS_IN_DEVMODE;
|
||||
// Check if was started in dev mode.
|
||||
if (GetISystem()->WasInDevMode())
|
||||
flags |= SYS_STATUS_WAS_IN_DEVMODE;
|
||||
ICVar *pVar = GetISystem()->GetIConsole()->GetCVar("sys_PakPriority");
|
||||
if (pVar && pVar->GetIVal() != 0)
|
||||
flags |= SYS_STATUS_PAK_PRIORITY;
|
||||
|
||||
return flags;
|
||||
}
|
||||
182
CryNetwork/DefenceWall.h
Normal file
182
CryNetwork/DefenceWall.h
Normal file
@@ -0,0 +1,182 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001-2004.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: DefenceWall.h
|
||||
// Version: v1.00
|
||||
// Created: 25/1/2004 by Timur.
|
||||
// Compilers: Visual Studio.NET 2003
|
||||
// Description: ...
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __DefenceWall_h__
|
||||
#define __DefenceWall_h__
|
||||
|
||||
#if !defined(LINUX)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <TimeValue.h>
|
||||
#include <IDataProbe.h>
|
||||
#include <list>
|
||||
|
||||
class CNetwork;
|
||||
class CServer;
|
||||
class CClient;
|
||||
|
||||
struct SClientCheckContext
|
||||
{
|
||||
// Sequential id of request.
|
||||
unsigned int nRequestId;
|
||||
// Time of last request.
|
||||
CTimeValue requestTime;
|
||||
// how many times this check was tried.
|
||||
int nRetries;
|
||||
// Ip of the client we are requesting.
|
||||
CIPAddress clientIP;
|
||||
// Hash of the filename to check.
|
||||
unsigned int nFilenameHash;
|
||||
// Request code (what check to do).
|
||||
unsigned char nRequestCode;
|
||||
// Number of opened pack files.
|
||||
unsigned int nNumOpenedPaks;
|
||||
// Probe data.
|
||||
SDataProbeContext probe;
|
||||
//! True if it is code request (it depends on 32/64bit versions)
|
||||
bool bExecutableCode;
|
||||
//! Various flags recieved from client.
|
||||
unsigned int nClientStatusFlags;
|
||||
|
||||
SClientCheckContext()
|
||||
{
|
||||
bExecutableCode = false;
|
||||
nRequestCode = 0;
|
||||
nRequestId = 0;
|
||||
nRetries = 0;
|
||||
nNumOpenedPaks = 0;
|
||||
nFilenameHash = 0;
|
||||
nClientStatusFlags = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// No comments...
|
||||
class CDefenceWall
|
||||
{
|
||||
public:
|
||||
CDefenceWall( CNetwork *pNetwork );
|
||||
~CDefenceWall();
|
||||
|
||||
// This is server.
|
||||
void SetServer( CServer *pServer );
|
||||
// This is client.
|
||||
void SetClient( CClient *pClient );
|
||||
|
||||
void ClearProtectedFiles();
|
||||
void AddProtectedFile( const char *sFilename );
|
||||
|
||||
void ServerUpdate();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some important events.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void OnAddClient( CIPAddress &clientIP );
|
||||
void OnDisconnectClient( CIPAddress &clientIP );
|
||||
void ClearClients();
|
||||
|
||||
// When client recieves server request.
|
||||
void OnServerRequest( CStream &stm );
|
||||
// When server recieves client response.
|
||||
void OnClientResponse( CIPAddress &clientIP,CStream &stm );
|
||||
|
||||
private:
|
||||
// This structure describe connected client on server.
|
||||
struct ClientInfo
|
||||
{
|
||||
// Info about this client.
|
||||
CIPAddress ip;
|
||||
bool bSuspectedPunk;
|
||||
// He`s running 64bit version.
|
||||
bool b64bit;
|
||||
CTimeValue lastRequestTime;
|
||||
CTimeValue nextRandomCheckTime;
|
||||
ClientInfo() { bSuspectedPunk = false; b64bit = false; };
|
||||
};
|
||||
|
||||
void SendSecurityQueryToClient( CIPAddress &clientIP,CStream &stm );
|
||||
void SendSecurityRespToServer( CStream &stm );
|
||||
|
||||
// Called on client, in response to server request.
|
||||
void OnValidateClientContext( SClientCheckContext &ctx );
|
||||
|
||||
// Validate data on specified client IP.
|
||||
void FirstTimeClientValidation( ClientInfo *pClientInfo );
|
||||
void RandomClientValidation( ClientInfo *pClientInfo );
|
||||
|
||||
void IssueRequest( ClientInfo *pClientInfo,CStream &outstream,SClientCheckContext &ctx );
|
||||
void WriteStreamRequest( SClientCheckContext &ctx,CStream &stm );
|
||||
void ReadStreamRequest( SClientCheckContext &ctx,CStream &stm );
|
||||
void WriteStreamResponse( SClientCheckContext &ctx,CStream &stm );
|
||||
void ReadStreamResponse( SClientCheckContext &ctx,CStream &stm );
|
||||
SClientCheckContext* FindRequest( int nRequestId );
|
||||
void RemoveRequest( SClientCheckContext* pCtx );
|
||||
void ClearAllPendingRequests();
|
||||
|
||||
// Make all filenames compatable.
|
||||
void UnifyFilename( string &sFilename );
|
||||
void GetRelativeFilename( string &sFilename );
|
||||
ClientInfo* FindClientInfo( CIPAddress &clientIP ) const;
|
||||
void PunkDetected( CIPAddress &clientIP,int type );
|
||||
|
||||
void EncryptStream( CStream &stm );
|
||||
void DecryptStream( CStream &stm );
|
||||
|
||||
void FillStdServerProbes();
|
||||
bool ServerCreateFileProbe( const char *sFilename,SClientCheckContext &ctx,bool bRandomPart );
|
||||
bool ServerCreateModuleProbe( const char *sFilename,SClientCheckContext &ctx );
|
||||
int GetSystemStatusFlags();
|
||||
|
||||
private:
|
||||
typedef std::list<SClientCheckContext*> PendingChecks;
|
||||
PendingChecks m_pendingChecks;
|
||||
CNetwork *m_pNetwork;
|
||||
unsigned int m_nNextRequestId;
|
||||
|
||||
ISystem *m_pSystem;
|
||||
CServer *m_pServer;
|
||||
CClient *m_pClient;
|
||||
// True if server, false if client.
|
||||
bool m_bServer;
|
||||
bool m_b64bit; // Running in 64bit version.
|
||||
bool m_bLog;
|
||||
unsigned int m_nEncryptKey[4];
|
||||
|
||||
// Output Stream.
|
||||
CStream m_clientOutputStream;
|
||||
|
||||
struct ProtectedFile
|
||||
{
|
||||
string filename;
|
||||
u32 nFilenameHash;
|
||||
uint64 nHashCode;
|
||||
};
|
||||
// List of protected files.
|
||||
std::vector<ProtectedFile> m_protectedFiles;
|
||||
|
||||
// List of connected clients.
|
||||
// For up to 32-64 clients, vector is oky.
|
||||
typedef std::vector<ClientInfo*> Clients;
|
||||
Clients m_clients;
|
||||
|
||||
// List of Standart probes checked for each client, (stored on server only).
|
||||
// Updated on each call to ClearProtectedFiles.
|
||||
std::vector<SClientCheckContext> m_stdServerProbes;
|
||||
|
||||
int m_nNumOpenedPacksOnServer;
|
||||
};
|
||||
|
||||
#endif // __DefenceWall_h__
|
||||
|
||||
86
CryNetwork/Interfaces.h
Normal file
86
CryNetwork/Interfaces.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: Interfaces.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _INTERFACES_H_
|
||||
#define _INTERFACES_H_
|
||||
|
||||
class CServerSlot;
|
||||
|
||||
struct _IServerServices
|
||||
{
|
||||
virtual bool Send(CStream &stm, CIPAddress &ip) = 0;
|
||||
virtual void UnregisterSlot(CIPAddress &ip) = 0;
|
||||
virtual void OnDestructSlot( const CServerSlot *inpServerSlot ) = 0;
|
||||
virtual void GetProtocolVariables(struct CNPServerVariables &sv) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct _IEndpointUser
|
||||
{
|
||||
virtual bool Send(CStream &stm) = 0;
|
||||
virtual void OnData(CStream &stm) = 0;
|
||||
// virtual unsigned char GetID() = 0;
|
||||
};
|
||||
|
||||
struct _ICCPUser :
|
||||
public _IEndpointUser
|
||||
{
|
||||
//!
|
||||
virtual void OnCCPSetup(CStream &stm) = 0;
|
||||
//! this is a server->client packet
|
||||
virtual void OnCCPConnect(CStream &stm) = 0;
|
||||
//!
|
||||
virtual void OnCCPConnectResp(CStream &stm) = 0;
|
||||
//! this is a server->client packet
|
||||
virtual void OnCCPContextSetup(CStream &stm) = 0;
|
||||
//!
|
||||
virtual void OnCCPContextReady(CStream &stm) = 0;
|
||||
//! this is a server->client packet
|
||||
virtual void OnCCPServerReady() = 0;
|
||||
//!
|
||||
virtual void OnCCPDisconnect(const char *szCause) = 0;
|
||||
// Sends a security check message, client must respond to it.
|
||||
virtual void OnCCPSecurityQuery(CStream &stm) = 0;
|
||||
// Respond to a security message, will be checked on server.
|
||||
virtual void OnCCPSecurityResp(CStream &stm) = 0;
|
||||
// Punk buster message.
|
||||
virtual void OnCCPPunkBusterMsg(CStream &stm) = 0;
|
||||
};
|
||||
|
||||
struct _IServerSlotServices:
|
||||
public _ICCPUser
|
||||
{
|
||||
virtual void Start(unsigned char cClientID,CIPAddress &ip) = 0;
|
||||
virtual bool SendConnect() = 0;
|
||||
virtual bool SendContextSetup() = 0;
|
||||
virtual bool SendServerReady() = 0;
|
||||
virtual bool SendDisconnect(const char *szCause) = 0;
|
||||
virtual void OnConnect() = 0;
|
||||
virtual void OnContextReady() = 0;
|
||||
virtual void OnDisconnect(const char *szCause) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct _IClientServices :
|
||||
public _ICCPUser
|
||||
{
|
||||
virtual bool SendSetup() = 0;
|
||||
virtual bool SendConnectResp() = 0;
|
||||
virtual bool SendContextReady() = 0;
|
||||
virtual bool SendDisconnect(const char *szCause) = 0;
|
||||
virtual void OnConnect() = 0;
|
||||
virtual void OnContextSetup() = 0;
|
||||
virtual void OnServerReady() = 0;
|
||||
virtual void OnDisconnect(const char *szCause) = 0;
|
||||
};
|
||||
|
||||
#endif //_INTERFACES_H_
|
||||
5
CryNetwork/MSSCCPRJ.SCC
Normal file
5
CryNetwork/MSSCCPRJ.SCC
Normal file
@@ -0,0 +1,5 @@
|
||||
SCC = This is a source code control file
|
||||
|
||||
[CryNetwork.vcproj]
|
||||
SCC_Aux_Path = "P4SCC#perforce:1666##marcoc_code##PC018"
|
||||
SCC_Project_Name = Perforce Project
|
||||
291
CryNetwork/NETServerSnooper.cpp
Normal file
291
CryNetwork/NETServerSnooper.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "stdafx.h"
|
||||
#include "ILog.h"
|
||||
#include "CNP.h"
|
||||
#include "ITimer.h"
|
||||
#include "NETServerSnooper.h"
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CNETServerSnooper::CNETServerSnooper()
|
||||
: m_iWaitingCount(0),
|
||||
m_pSink(0),
|
||||
m_pSystem(0),
|
||||
cl_snooptimeout(0),
|
||||
cl_snoopretries(0),
|
||||
cl_snoopcount(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CNETServerSnooper::~CNETServerSnooper()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
bool CNETServerSnooper::Create(ISystem *pSystem, INETServerSnooperSink *pSink)
|
||||
{
|
||||
assert(pSystem);
|
||||
assert(pSink);
|
||||
|
||||
m_pSystem = pSystem;
|
||||
m_pSink = pSink;
|
||||
|
||||
if (NET_FAILED(m_sSocket.Create()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cl_snoopcount = m_pSystem->GetIConsole()->GetCVar("cl_snoopcount");
|
||||
cl_snoopretries = m_pSystem->GetIConsole()->GetCVar("cl_snoopretries");
|
||||
cl_snooptimeout = m_pSystem->GetIConsole()->GetCVar("cl_snooptimeout");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::Release()
|
||||
{
|
||||
m_hmServerTable.clear();
|
||||
delete this;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::Update(unsigned int dwTime)
|
||||
{
|
||||
if (m_hmServerTable.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_dwCurrentTime = dwTime;
|
||||
|
||||
int iReceived = 0;
|
||||
static CStream stmBuffer;
|
||||
static CIPAddress ipFrom;
|
||||
|
||||
do
|
||||
{
|
||||
iReceived = 0;
|
||||
stmBuffer.Reset();
|
||||
|
||||
m_sSocket.Receive(stmBuffer.GetPtr(), stmBuffer.GetAllocatedSize(), iReceived, ipFrom);
|
||||
|
||||
if(iReceived > 0)
|
||||
{
|
||||
stmBuffer.SetSize(BYTES2BITS(iReceived));
|
||||
|
||||
ProcessPacket(stmBuffer, ipFrom);
|
||||
}
|
||||
} while(iReceived > 0);
|
||||
|
||||
// if we have waiting servers
|
||||
if (m_iWaitingCount > 0)
|
||||
{
|
||||
// handle timeouts
|
||||
ProcessTimeout();
|
||||
}
|
||||
|
||||
int iMaxWaiting = NET_SNOOPER_MAXWAITING;
|
||||
|
||||
if (cl_snoopcount && cl_snoopcount->GetIVal() > 0)
|
||||
{
|
||||
iMaxWaiting = cl_snoopcount->GetIVal();
|
||||
}
|
||||
|
||||
while (m_iWaitingCount < iMaxWaiting)
|
||||
{
|
||||
if (!ProcessNext())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CNETServerSnooper::OnReceivingPacket( const unsigned char inPacketID, CStream &stmPacket, CIPAddress &ip )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::AddServer(const CIPAddress &ip)
|
||||
{
|
||||
NETSnooperServer Server;
|
||||
|
||||
Server.bDoing = 0;
|
||||
Server.cTry = 0;
|
||||
Server.dwStartTime = 0;
|
||||
Server.dwTimeout = 0;
|
||||
Server.ipAddress = ip;
|
||||
|
||||
m_hmServerTable.insert(std::pair<CIPAddress, NETSnooperServer>(Server.ipAddress, Server));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::AddServerList(const std::vector<CIPAddress> &vIP)
|
||||
{
|
||||
for (std::vector<CIPAddress>::const_iterator it = vIP.begin(); it != vIP.end(); ++it)
|
||||
{
|
||||
AddServer(*it);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::ClearList()
|
||||
{
|
||||
m_hmServerTable.clear();
|
||||
m_iWaitingCount = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::QueryServer(CIPAddress &ip)
|
||||
{
|
||||
CStream stmPacket;
|
||||
CQPInfoRequest cqpInfoRequest("status");
|
||||
|
||||
cqpInfoRequest.Save(stmPacket);
|
||||
m_sSocket.Send(stmPacket.GetPtr(), BITS2BYTES(stmPacket.GetSize()), (CIPAddress *)&ip);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::ProcessPacket(CStream &stmPacket, CIPAddress &ip)
|
||||
{
|
||||
// since we are not expecting any response
|
||||
// since is either a timedout server,
|
||||
// or is some undesirable packet
|
||||
if (m_iWaitingCount < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CNP cnpPacket;
|
||||
cnpPacket.LoadAndSeekToZero(stmPacket);
|
||||
|
||||
if (cnpPacket.m_cFrameType == FT_CQP_INFO_RESPONSE)
|
||||
{
|
||||
NETSnooperServer *pServer = 0;
|
||||
HMServerTableItor it = m_hmServerTable.find(ip);
|
||||
|
||||
if (it == m_hmServerTable.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pServer = &(it->second);
|
||||
|
||||
if (!pServer->bDoing) // was this expected ?
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we got a good response
|
||||
// so process it
|
||||
CQPInfoResponse cqpInfoResponse;
|
||||
cqpInfoResponse.Load(stmPacket);
|
||||
|
||||
if(m_pSink)
|
||||
{
|
||||
m_pSink->OnNETServerFound(ip, cqpInfoResponse.szResponse, m_dwCurrentTime - pServer->dwStartTime);
|
||||
}
|
||||
|
||||
--m_iWaitingCount;
|
||||
assert(m_iWaitingCount >= 0);
|
||||
|
||||
// remove server from table
|
||||
m_hmServerTable.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CNETServerSnooper::ProcessTimeout()
|
||||
{
|
||||
NETSnooperServer *pServer = 0;
|
||||
HMServerTableItor it = m_hmServerTable.begin();
|
||||
|
||||
unsigned int dwRetry = NET_SNOOPER_RETRY;
|
||||
unsigned int dwTimeDelta = NET_SNOOPER_TIMEOUT;
|
||||
|
||||
if (cl_snoopretries && cl_snoopretries->GetIVal() > 0)
|
||||
{
|
||||
dwRetry = cl_snoopretries->GetIVal();
|
||||
}
|
||||
|
||||
if (cl_snooptimeout && cl_snooptimeout->GetFVal() > 0)
|
||||
{
|
||||
dwTimeDelta = (unsigned int)(cl_snooptimeout->GetFVal() * 1000.0f);
|
||||
}
|
||||
|
||||
while(it != m_hmServerTable.end())
|
||||
{
|
||||
pServer = &(it->second);
|
||||
|
||||
if ((m_dwCurrentTime >= pServer->dwTimeout) && pServer->bDoing)
|
||||
{
|
||||
pServer->cTry++;
|
||||
pServer->dwStartTime = m_dwCurrentTime;
|
||||
pServer->dwTimeout = m_dwCurrentTime + dwTimeDelta;
|
||||
|
||||
if (pServer->cTry > dwRetry)
|
||||
{
|
||||
m_pSink->OnNETServerTimeout(it->second.ipAddress);
|
||||
// quit snooping this server
|
||||
#if defined(LINUX) //dunno why the replaced statement does not work on its own
|
||||
HMServerTableItor itTemp = it;
|
||||
itTemp++;
|
||||
m_hmServerTable.erase(it);
|
||||
it = itTemp;
|
||||
#else
|
||||
it = m_hmServerTable.erase(it);
|
||||
#endif
|
||||
--m_iWaitingCount;
|
||||
assert(m_iWaitingCount >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueryServer(pServer->ipAddress);
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
bool CNETServerSnooper::ProcessNext()
|
||||
{
|
||||
NETSnooperServer *pServer = 0;
|
||||
HMServerTableItor it = m_hmServerTable.begin();
|
||||
|
||||
unsigned int dwTimeDelta = NET_SNOOPER_TIMEOUT;
|
||||
if (cl_snooptimeout && cl_snooptimeout->GetFVal() > 0)
|
||||
{
|
||||
dwTimeDelta = (unsigned int)(cl_snooptimeout->GetFVal() * 1000.0f);
|
||||
}
|
||||
|
||||
while(it != m_hmServerTable.end())
|
||||
{
|
||||
pServer = &(it->second);
|
||||
|
||||
if (pServer->bDoing)
|
||||
{
|
||||
++it;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
pServer->dwStartTime = m_dwCurrentTime;
|
||||
pServer->dwTimeout = m_dwCurrentTime + dwTimeDelta;
|
||||
pServer->bDoing = 1;
|
||||
|
||||
QueryServer(pServer->ipAddress);
|
||||
|
||||
m_iWaitingCount++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
83
CryNetwork/NETServerSnooper.h
Normal file
83
CryNetwork/NETServerSnooper.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef NETSERVERSNOOPER_H
|
||||
#define NETSERVERSNOOPER_H
|
||||
|
||||
|
||||
#include <INetwork.h>
|
||||
|
||||
#if defined(LINUX) || defined(WIN64)
|
||||
#include <map>
|
||||
#endif
|
||||
#ifdef WIN64
|
||||
#define hash_map map
|
||||
#else
|
||||
#if defined(LINUX)
|
||||
#include <ext/hash_map>
|
||||
#else
|
||||
#include <hash_map>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <IConsole.h>
|
||||
|
||||
#define NET_SNOOPER_RETRY (2)
|
||||
#define NET_SNOOPER_MAXWAITING (20)
|
||||
#define NET_SNOOPER_TIMEOUT (1500) // 1 seconds timeout per try
|
||||
|
||||
typedef struct NETSnooperServer
|
||||
{
|
||||
CIPAddress ipAddress; //!<
|
||||
DWORD dwStartTime; //!<
|
||||
DWORD dwTimeout; //!< when current time >= dwTimeout, increase cTry, and retry
|
||||
byte cTry; //!< when cTry > NET_SNOOPER_RETRY, remove from list
|
||||
bool bDoing; //!<
|
||||
} NETSnooperServer;
|
||||
|
||||
|
||||
typedef std::map<CIPAddress, NETSnooperServer> HMServerTable;
|
||||
typedef std::map<CIPAddress, NETSnooperServer>::iterator HMServerTableItor;
|
||||
|
||||
|
||||
class CNETServerSnooper: public INETServerSnooper, public INetworkPacketSink
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CNETServerSnooper();
|
||||
//! destructor
|
||||
~CNETServerSnooper();
|
||||
|
||||
bool Create(ISystem *pSystem, INETServerSnooperSink *pSink);
|
||||
|
||||
// interface INetworkPacketSink --------------------------------------
|
||||
|
||||
virtual void OnReceivingPacket( const unsigned char inPacketID, CStream &stmPacket, CIPAddress &ip );
|
||||
|
||||
// interface INETServerSnooper ----------------------------------------
|
||||
|
||||
virtual void Release();
|
||||
virtual void Update(unsigned int dwTime);
|
||||
virtual void AddServer(const CIPAddress &ip);
|
||||
virtual void AddServerList(const std::vector<CIPAddress> &vIP);
|
||||
virtual void ClearList();
|
||||
|
||||
private: // ------------------------------------------------------------
|
||||
|
||||
void QueryServer(CIPAddress &ip);
|
||||
void ProcessPacket(CStream &stmPacket, CIPAddress &ip);
|
||||
void ProcessTimeout();
|
||||
bool ProcessNext();
|
||||
|
||||
ISystem * m_pSystem; //!<
|
||||
|
||||
unsigned int m_dwCurrentTime; //!<
|
||||
int m_iWaitingCount; //!<
|
||||
|
||||
INETServerSnooperSink * m_pSink; //!<
|
||||
CDatagramSocket m_sSocket; //!<
|
||||
HMServerTable m_hmServerTable; //!<
|
||||
|
||||
ICVar * cl_snooptimeout; //!<
|
||||
ICVar * cl_snoopretries; //!<
|
||||
ICVar * cl_snoopcount; //!<
|
||||
};
|
||||
|
||||
#endif // NETSERVERSNOOPER_H
|
||||
818
CryNetwork/Network.cpp
Normal file
818
CryNetwork/Network.cpp
Normal file
@@ -0,0 +1,818 @@
|
||||
// Network.cpp: implementation of the CNetwork class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Network.h"
|
||||
#include "Client.h"
|
||||
#include "ClientLocal.h"
|
||||
#include "ServerSlot.h"
|
||||
#include "ServerSnooper.h"
|
||||
#include "NETServerSnooper.h"
|
||||
#include "Server.h"
|
||||
#include "RConSystem.h"
|
||||
#include "DefenceWall.h"
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
#include "PunkBusterInterface.h"
|
||||
#endif
|
||||
#include "ITimer.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
#include "NewUbisoftClient.h" // NewUbisoftClient
|
||||
#include "ScriptObjectNewUbisoftClient.h" // CScriptObjectNewUbisoftClient
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
#define ANTI_CHEATS
|
||||
|
||||
#include "platform.h"
|
||||
#if defined(LINUX)
|
||||
#include "INetwork.h"
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
unsigned int CNetwork::m_nCryNetInitialized = 0;
|
||||
|
||||
struct CryNetError CNetwork::m_neNetErrors[]=
|
||||
{
|
||||
{NET_OK, "No Error"},
|
||||
{NET_FAIL, "Generic Error"},
|
||||
// SOCKET
|
||||
{NET_EINTR, "WSAEINTR - interrupted function call"},
|
||||
{NET_EBADF, "WSAEBADF - Bad file number"},
|
||||
{NET_EACCES, "WSAEACCES - error in accessing socket"},
|
||||
{NET_EFAULT, "WSAEFAULT - bad address"},
|
||||
{NET_EINVAL, "WSAEINVAL - invalid argument"},
|
||||
{NET_EMFILE, "WSAEMFILE - too many open files"},
|
||||
{NET_EWOULDBLOCK, "WSAEWOULDBLOCK - resource temporarily unavailable"},
|
||||
{NET_EINPROGRESS, "WSAEINPROGRESS - operation now in progress"},
|
||||
{NET_EALREADY, "WSAEALREADY - operation already in progress"},
|
||||
{NET_ENOTSOCK, "WSAENOTSOCK - socket operation on non-socket"},
|
||||
{NET_EDESTADDRREQ, "WSAEDESTADDRREQ - destination address required"},
|
||||
{NET_EMSGSIZE, "WSAEMSGSIZE - message to long"},
|
||||
{NET_EPROTOTYPE, "WSAEPROTOTYPE - protocol wrong type for socket"},
|
||||
{NET_ENOPROTOOPT, "WSAENOPROTOOPT - bad protocol option"},
|
||||
{NET_EPROTONOSUPPORT, "WSAEPROTONOSUPPORT - protocol not supported"},
|
||||
{NET_ESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT - socket type not supported"},
|
||||
{NET_EOPNOTSUPP, "WSAEOPNOTSUPP - operation not supported"},
|
||||
{NET_EPFNOSUPPORT, "WSAEPFNOSUPPORT - protocol family not supported"},
|
||||
{NET_EAFNOSUPPORT, "WSAEAFNOSUPPORT - address family not supported by protocol"},
|
||||
{NET_EADDRINUSE, "WSAEADDRINUSE - address is in use"},
|
||||
{NET_EADDRNOTAVAIL, "WSAEADDRNOTAVAIL - address is not valid in context"},
|
||||
{NET_ENETDOWN, "WSAENETDOWN - network is down"},
|
||||
{NET_ENETUNREACH, "WSAENETUNREACH - network is unreachable"},
|
||||
{NET_ENETRESET, "WSAENETRESET - network dropped connection on reset"},
|
||||
{NET_ECONNABORTED, "WSACONNABORTED - software caused connection aborted"},
|
||||
{NET_ECONNRESET, "WSAECONNRESET - connection reset by peer"},
|
||||
{NET_ENOBUFS, "WSAENOBUFS - no buffer space available"},
|
||||
{NET_EISCONN, "WSAEISCONN - socket is already connected"},
|
||||
{NET_ENOTCONN, "WSAENOTCONN - socket is not connected"},
|
||||
{NET_ESHUTDOWN, "WSAESHUTDOWN - cannot send after socket shutdown"},
|
||||
{NET_ETOOMANYREFS, "WSAETOOMANYREFS - Too many references: cannot splice"},
|
||||
{NET_ETIMEDOUT, "WSAETIMEDOUT - connection timed out"},
|
||||
{NET_ECONNREFUSED, "WSAECONNREFUSED - connection refused"},
|
||||
{NET_ELOOP, "WSAELOOP - Too many levels of symbolic links"},
|
||||
{NET_ENAMETOOLONG, "WSAENAMETOOLONG - File name too long"},
|
||||
{NET_EHOSTDOWN, "WSAEHOSTDOWN - host is down"},
|
||||
{NET_EHOSTUNREACH, "WSAEHOSTUNREACH - no route to host"},
|
||||
{NET_ENOTEMPTY, "WSAENOTEMPTY - Cannot remove a directory that is not empty"},
|
||||
{NET_EUSERS, "WSAEUSERS - Ran out of quota"},
|
||||
{NET_EDQUOT, "WSAEDQUOT - Ran out of disk quota"},
|
||||
{NET_ESTALE, "WSAESTALE - File handle reference is no longer available"},
|
||||
{NET_EREMOTE, "WSAEREMOTE - Item is not available locally"},
|
||||
// extended winsock errors(not BSD compliant)
|
||||
#ifdef _WIN32
|
||||
{NET_EPROCLIM, "WSAEPROCLIM - too many processes"},
|
||||
{NET_HOST_NOT_FOUND, "WSAHOST_NOT_FOUND - host not found"},
|
||||
{NET_TRY_AGAIN, "WSATRY_AGAIN - non-authoritative host not found"},
|
||||
{NET_NO_RECOVERY, "WSANO_RECOVERY - non-recoverable error"},
|
||||
{NET_NO_DATA, "WSANO_DATA - valid name, no data record of requested type"},
|
||||
{NET_NO_ADDRESS, "WSANO_ADDRESS - (undocumented)"},
|
||||
{NET_SYSNOTREADY, "WSASYSNOTREADY - network subsystem is unavailable"},
|
||||
{NET_VERNOTSUPPORTED, "WSAVERNOTSUPPORTED - winsock.dll verison out of range"},
|
||||
{NET_NOTINITIALISED, "WSANOTINITIALISED - WSAStartup not yet performed"},
|
||||
{NET_NO_DATA, "WSANO_DATA - valid name, no data record of requested type"},
|
||||
{NET_EDISCON, "WSAEDISCON - graceful shutdown in progress"},
|
||||
#endif
|
||||
// XNetwork specific
|
||||
{NET_NOIMPL, "XNetwork - Function not implemented"},
|
||||
{NET_SOCKET_NOT_CREATED, "XNetwork - socket not yet created"},
|
||||
{0, 0} // sentinel
|
||||
};
|
||||
|
||||
CNetwork::CNetwork()
|
||||
{
|
||||
m_dwLocalIP=0;
|
||||
m_pNetCompressPackets = 0;
|
||||
m_pNetLog = 0;
|
||||
m_pDefenceWall = 0;
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
m_pPunkBuster = 0;
|
||||
#endif
|
||||
m_bHaveServer = false;
|
||||
m_bHaveClient = false;
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
m_pScriptObjectNewUbisoftClient=0;
|
||||
m_pUbiSoftClient=0;
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
m_pScriptSystem=0;
|
||||
m_pClient=0;
|
||||
}
|
||||
|
||||
CNetwork::~CNetwork()
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
SAFE_DELETE(m_pUbiSoftClient);
|
||||
SAFE_DELETE(m_pScriptObjectNewUbisoftClient);
|
||||
CScriptObjectNewUbisoftClient::ReleaseTemplate();
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
SAFE_RELEASE( m_pNetCompressPackets );
|
||||
SAFE_RELEASE( m_pNetLog );
|
||||
SAFE_DELETE( m_pDefenceWall );
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
SAFE_DELETE( m_pPunkBuster );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ICompressionHelper *CNetwork::GetCompressionHelper()
|
||||
{
|
||||
return &m_Compressor;
|
||||
}
|
||||
|
||||
|
||||
void CNetwork::SetLocalIP( const char *szLocalIP )
|
||||
{
|
||||
CIPAddress ip;
|
||||
|
||||
ip.Set(0,(char *)szLocalIP);
|
||||
|
||||
m_dwLocalIP=ip.GetAsUINT();
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// Ubi.com cannot change the IP later than creation
|
||||
{
|
||||
CIPAddress localip;
|
||||
localip.Set(0,GetLocalIP());
|
||||
m_pUbiSoftClient=new NewUbisoftClient(localip.GetAsString());
|
||||
|
||||
m_pScriptObjectNewUbisoftClient=new CScriptObjectNewUbisoftClient;
|
||||
CScriptObjectNewUbisoftClient::InitializeTemplate(m_pScriptSystem);
|
||||
m_pScriptObjectNewUbisoftClient->Init(m_pScriptSystem,m_pSystem,m_pUbiSoftClient);
|
||||
}
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
}
|
||||
|
||||
DWORD CNetwork::GetLocalIP() const
|
||||
{
|
||||
return m_dwLocalIP;
|
||||
}
|
||||
|
||||
bool CNetwork::Init( IScriptSystem *pScriptSystem )
|
||||
{
|
||||
assert(pScriptSystem);
|
||||
|
||||
m_pScriptSystem = pScriptSystem;
|
||||
|
||||
if(CNetwork::m_nCryNetInitialized)
|
||||
return true;
|
||||
|
||||
#if !defined(PS2) && !defined(LINUX)
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
// WARNING :use a later version require a change in the multicast code with
|
||||
// a WS2's specific one
|
||||
// not compatible with other platforms
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (err != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LOBYTE(wsaData.wVersion) != 1 ||
|
||||
HIBYTE(wsaData.wVersion) != 1)
|
||||
{
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
CNetwork::m_nCryNetInitialized+=1;
|
||||
int n=0;
|
||||
while(m_neNetErrors[n].sErrorDescription!='\0'){
|
||||
m_mapErrors[m_neNetErrors[n].nrErrorCode]=m_neNetErrors[n].sErrorDescription;
|
||||
n++;
|
||||
}
|
||||
|
||||
/// Register Console Vars related to network.
|
||||
m_pSystem = GetISystem();
|
||||
|
||||
CreateConsoleVars();
|
||||
|
||||
#ifdef ANTI_CHEATS
|
||||
m_pDefenceWall = new CDefenceWall(this);
|
||||
#endif //ANTI_CHEATS
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
m_pPunkBuster = new CPunkBusterInterface(this);
|
||||
PBsdk_SetPointers ( m_pPunkBuster ) ;
|
||||
#endif
|
||||
LogNetworkInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::CreateConsoleVars()
|
||||
{
|
||||
m_pNetCompressPackets = m_pSystem->GetIConsole()->CreateVariable( "net_compress_packets","1",0 );
|
||||
m_pNetLog = m_pSystem->GetIConsole()->CreateVariable( "net_log","0",0 );
|
||||
//m_pNetCheatProtection = m_pSystem->GetIConsole()->CreateVariable( "net_cheatprotection","0",VF_DUMPTODISK );
|
||||
m_pNetCheatProtection = m_pSystem->GetIConsole()->CreateVariable( "net_cheatprotection","0",VF_READONLY );
|
||||
m_pNetCheatProtection->ForceSet("0");
|
||||
|
||||
m_pSystem->GetIConsole()->CreateVariable("sv_ServerType", "LAN",0,
|
||||
"Specifies the server connection type (next server creation, not case sensitive) 'UBI', 'LAN' or 'NET'\n"
|
||||
"Usage: sv_ServerType UBI\n");
|
||||
m_pSystem->GetIConsole()->CreateVariable("sv_regserver_port","",0,
|
||||
"Sets the local port for a registering the server on Ubi.com GS.\n"
|
||||
"Usage: sv_regserver_port portnumber\n"
|
||||
"Default is '0' (first free).");
|
||||
m_pSystem->GetIConsole()->CreateVariable("sv_authport","",0,
|
||||
"Sets the local port for a CDKey authentication comunications.\n"
|
||||
"Usage: sv_auth_port portnumber\n"
|
||||
"Default is '0' (first free).");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IClient *CNetwork::CreateClient(IClientSink *pSink, bool bLocal)
|
||||
{
|
||||
assert(!m_pClient); // only one client at a time is allowed
|
||||
|
||||
m_bHaveClient = true;
|
||||
|
||||
if(bLocal)
|
||||
{
|
||||
CClientLocal *pClient=new CClientLocal(this,pSink);
|
||||
|
||||
m_pClient=pClient;
|
||||
|
||||
return pClient;
|
||||
}
|
||||
else
|
||||
{
|
||||
CClient *pClient = new CClient( this );
|
||||
|
||||
if(!pClient->Init(pSink))
|
||||
{
|
||||
delete pClient;
|
||||
return NULL;
|
||||
}
|
||||
if (GetCheatProtectionLevel() > 0)
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->SetClient(pClient);
|
||||
}
|
||||
|
||||
m_pClient=pClient;
|
||||
|
||||
return pClient;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServer *CNetwork::CreateServer(IServerSlotFactory *pFactory, WORD nPort, bool listen)
|
||||
{
|
||||
m_bHaveServer = true;
|
||||
CServer *pServer = new CServer(this);
|
||||
if (!pServer->Init(pFactory, nPort, listen))
|
||||
{
|
||||
delete pServer;
|
||||
return NULL;
|
||||
}
|
||||
m_mapServers.insert(MapServersItor::value_type(nPort, pServer));
|
||||
|
||||
if (GetCheatProtectionLevel() > 0)
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->SetServer(pServer);
|
||||
}
|
||||
|
||||
IConsole *pConsole = GetISystem()->GetIConsole();
|
||||
assert(pConsole);
|
||||
|
||||
ICVar *sv_punkbuster = pConsole->GetCVar("sv_punkbuster");
|
||||
|
||||
if (sv_punkbuster && sv_punkbuster->GetIVal() != 0)
|
||||
{
|
||||
InitPunkbusterServer(listen, pServer);
|
||||
|
||||
// if this is a lan server
|
||||
if(pServer->GetServerType()==eMPST_LAN)
|
||||
{
|
||||
// set pb variables to lan defaults
|
||||
pConsole->ExecuteString("pb_sv_lan 1", 0, 1);
|
||||
pConsole->ExecuteString("pb_sv_guidrelax 7", 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
m_pUbiSoftClient->Server_SetGamePort(nPort); // set the connection to the server
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
LockPunkbusterCVars();
|
||||
|
||||
return pServer;
|
||||
}
|
||||
|
||||
INETServerSnooper *CNetwork::CreateNETServerSnooper(INETServerSnooperSink *pSink)
|
||||
{
|
||||
CNETServerSnooper *pSnooper = new CNETServerSnooper;
|
||||
|
||||
if (!pSnooper->Create(GetISystem(), pSink))
|
||||
{
|
||||
delete pSnooper;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pSnooper;
|
||||
}
|
||||
|
||||
IRConSystem *CNetwork::CreateRConSystem()
|
||||
{
|
||||
CRConSystem *pRCon = new CRConSystem;
|
||||
|
||||
if(!pRCon->Create(GetISystem()))
|
||||
{
|
||||
delete pRCon;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pRCon;
|
||||
}
|
||||
|
||||
|
||||
IServerSnooper *CNetwork::CreateServerSnooper(IServerSnooperSink *pSink)
|
||||
{
|
||||
CServerSnooper *pSnooper=new CServerSnooper;
|
||||
if(!pSnooper->Init(pSink))
|
||||
{
|
||||
delete pSnooper;
|
||||
return NULL;
|
||||
}
|
||||
return pSnooper;
|
||||
}
|
||||
|
||||
CServerSlotLocal *CNetwork::ConnectToLocalServerSlot(CClientLocal *pClient, WORD wPort)
|
||||
{
|
||||
MapServersItor itor;
|
||||
|
||||
if(m_mapServers.empty())
|
||||
return NULL;
|
||||
//check if the local server exists
|
||||
itor=m_mapServers.find(wPort);
|
||||
|
||||
if(itor==m_mapServers.end()){
|
||||
itor=m_mapServers.begin();
|
||||
}
|
||||
//<<FIXME>> make the port variable
|
||||
CIPAddress ip(0,"127.0.0.1");
|
||||
|
||||
CServerSlotLocal *pServerSlot=new CServerSlotLocal(itor->second,pClient,ip,this);
|
||||
|
||||
itor->second->RegisterLocalServerSlot(pServerSlot,ip);
|
||||
|
||||
return pServerSlot;
|
||||
}
|
||||
|
||||
const char *CNetwork::EnumerateError(NRESULT err)
|
||||
{
|
||||
ERROR_MAPItor itor;
|
||||
itor = m_mapErrors.find(err);
|
||||
if (itor != m_mapErrors.end())
|
||||
{
|
||||
return itor->second;
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void CNetwork::Release()
|
||||
{
|
||||
CNetwork::m_nCryNetInitialized -= 1;
|
||||
|
||||
if (CNetwork::m_nCryNetInitialized)
|
||||
return;
|
||||
#if !defined(LINUX)
|
||||
#if !defined(PS2)
|
||||
else
|
||||
WSACleanup();
|
||||
#else
|
||||
CSocketManager::releaseImpl();
|
||||
delete &ISocketManagerImplementation::getInstance();
|
||||
#endif
|
||||
#endif
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
IServer *CNetwork::GetServerByPort( const WORD wPort )
|
||||
{
|
||||
//check if the local server exists
|
||||
MapServersItor itor=m_mapServers.find(wPort);
|
||||
|
||||
if(itor==m_mapServers.end())
|
||||
return 0; // not found
|
||||
|
||||
return itor->second;
|
||||
}
|
||||
|
||||
void CNetwork::UnregisterServer(WORD wPort)
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// We have to tell Ubisoft that the client has finished the game.
|
||||
// If ubisoft is not running this won't do anything.
|
||||
m_pUbiSoftClient->Client_LeaveGameServer();
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
if(m_bHaveServer)
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->ShutDown(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_mapServers.erase(wPort);
|
||||
}
|
||||
|
||||
void CNetwork::UnregisterClient( IClient *pClient )
|
||||
{
|
||||
assert(pClient);
|
||||
assert(m_pClient==pClient);
|
||||
|
||||
m_pClient=0;
|
||||
|
||||
if(m_bHaveClient)
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->ShutDown(true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CNetwork::GetMemoryStatistics(ICrySizer *pSizer)
|
||||
{
|
||||
pSizer->AddObject(m_neNetErrors,sizeof(m_neNetErrors));
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
pSizer->AddObject( m_pScriptObjectNewUbisoftClient, sizeof *m_pScriptObjectNewUbisoftClient);
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
}
|
||||
|
||||
bool CNetwork::IsPacketCompressionEnabled() const
|
||||
{
|
||||
return m_pNetCompressPackets->GetIVal() != 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CTimeValue CNetwork::GetCurrentTime()
|
||||
{
|
||||
return m_pSystem->GetITimer()->GetCurrTimePrecise();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
u32 CNetwork::GetStringHash( const char *szString )
|
||||
{
|
||||
#if defined(LINUX)
|
||||
return 0;
|
||||
#else
|
||||
|
||||
#ifdef _DATAPROBE
|
||||
return m_pSystem->GetIDataProbe()->GetHash( szString );
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::PunkDetected( CIPAddress &ip )
|
||||
{
|
||||
// Disconnect.
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::UpdateNetwork()
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// Update ubisoft
|
||||
m_pUbiSoftClient->Update();
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::OnClientUpdate()
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->Update(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::OnServerUpdate()
|
||||
{
|
||||
if (m_pDefenceWall && GetCheatProtectionLevel() > 0)
|
||||
m_pDefenceWall->ServerUpdate();
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->Update(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::ClearProtectedFiles()
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->ClearProtectedFiles();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::AddProtectedFile( const char *sFilename )
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->AddProtectedFile( sFilename );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::AddClientToDefenceWall( CIPAddress &clientIP )
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
//we want PB to work on devmode servers so handle this first
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->OnAddClient(clientIP);
|
||||
#endif
|
||||
// if in dev mode ignore it.
|
||||
if (!m_pSystem->GetForceNonDevMode())
|
||||
return;
|
||||
|
||||
if (m_pDefenceWall && GetCheatProtectionLevel() > 0)
|
||||
m_pDefenceWall->OnAddClient( clientIP );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::RemoveClientFromDefenceWall( CIPAddress &clientIP )
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->OnDisconnectClient( clientIP );
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->OnDisconnectClient(clientIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::OnSecurityMsgResponse( CIPAddress &ipAddress,CStream &stm )
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->OnClientResponse(ipAddress,stm);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::OnSecurityMsgQuery( CStream &stm )
|
||||
{
|
||||
if (m_pDefenceWall)
|
||||
m_pDefenceWall->OnServerRequest(stm);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::OnCCPPunkBusterMsg( CIPAddress &ipAddress,CStream &stm )
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
m_pPunkBuster->OnCCPPunkBusterMsg( ipAddress,stm );
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CNetwork::GetLogLevel()
|
||||
{
|
||||
return m_pNetLog->GetIVal();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int CNetwork::GetCheatProtectionLevel()
|
||||
{
|
||||
//return m_pNetCheatProtection->GetIVal();
|
||||
return 0; // disable the cheat protection..
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CNetwork::CheckPBPacket(CStream &stmPacket,CIPAddress &ip)
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
return m_pPunkBuster->CheckPBPacket(stmPacket,ip);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::ValidateClient( CServerSlot *pSlot )
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
return m_pPunkBuster->ValidateClient( pSlot );
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::InitPunkbusterClient(CClient *pClient)
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
{
|
||||
m_pPunkBuster->Init(true, false);
|
||||
m_pPunkBuster->SetClient(pClient);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::InitPunkbusterClientLocal(CClientLocal *pClientLocal)
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
{
|
||||
m_pPunkBuster->Init(true, true);
|
||||
m_pPunkBuster->SetClientLocal(pClientLocal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::InitPunkbusterServer(bool bLocal, CServer *pServer)
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
{
|
||||
m_pPunkBuster->Init(false, bLocal);
|
||||
m_pPunkBuster->SetServer(pServer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::LockPunkbusterCVars()
|
||||
{
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
if (m_pPunkBuster)
|
||||
{
|
||||
m_pPunkBuster->LockCVars();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::LogNetworkInfo()
|
||||
{
|
||||
DWORD i;
|
||||
char buf[256];
|
||||
struct hostent *hp;
|
||||
|
||||
if(!gethostname(buf, sizeof(buf)))
|
||||
{
|
||||
hp = gethostbyname(buf);
|
||||
if (hp)
|
||||
{
|
||||
CryLogAlways("network hostname: %s",hp->h_name);
|
||||
|
||||
i = 0;
|
||||
|
||||
while(hp->h_aliases[i])
|
||||
{
|
||||
CryLogAlways(" alias: %s\n", hp->h_aliases[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
while(hp->h_addr_list[i])
|
||||
{
|
||||
sockaddr_in temp;
|
||||
|
||||
memcpy(&(temp.sin_addr), hp->h_addr_list[i], hp->h_length);
|
||||
|
||||
#if defined(LINUX)
|
||||
const in_addr_windows *pin_addr_win = reinterpret_cast<const in_addr_windows*>(&temp.sin_addr);
|
||||
CryLogAlways(" ip:%d.%d.%d.%d", // port:%d family:%x",
|
||||
(int)(pin_addr_win->S_un.S_un_b.s_b1),
|
||||
(int)(pin_addr_win->S_un.S_un_b.s_b2),
|
||||
(int)(pin_addr_win->S_un.S_un_b.s_b3),
|
||||
(int)(pin_addr_win->S_un.S_un_b.s_b4));
|
||||
#else
|
||||
CryLogAlways(" ip:%d.%d.%d.%d", // port:%d family:%x",
|
||||
(int)(temp.sin_addr.S_un.S_un_b.s_b1),
|
||||
(int)(temp.sin_addr.S_un.S_un_b.s_b2),
|
||||
(int)(temp.sin_addr.S_un.S_un_b.s_b3),
|
||||
(int)(temp.sin_addr.S_un.S_un_b.s_b4));
|
||||
// (int)temp.sin_port,(unsigned int)temp.sin_family);
|
||||
#endif
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IClient *CNetwork::GetClient()
|
||||
{
|
||||
return m_pClient;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CNetwork::OnAfterServerLoadLevel( const char *szServerName, const uint32 dwPlayerCount, const WORD wPort )
|
||||
{
|
||||
assert(szServerName);
|
||||
assert(dwPlayerCount>0);
|
||||
|
||||
// m_pSystem->GetILog()->Log("Ubi.com DEBUG OnAfterServerLoadLevel() 1");
|
||||
|
||||
IServer *pServer=GetServerByPort(wPort);
|
||||
|
||||
if(!pServer)
|
||||
{
|
||||
assert(pServer); // internal error
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
if(m_pSystem->GetIGame()->GetModuleState(EGameMultiplayer) && pServer->GetServerType()!=eMPST_LAN)
|
||||
{
|
||||
// if it's a ubi-server, publish the server
|
||||
if(pServer->GetServerType()==eMPST_UBI)
|
||||
m_pUbiSoftClient->Server_CreateServer(szServerName,dwPlayerCount);
|
||||
|
||||
// if it's a internet server, check CDKey
|
||||
// m_pSystem->GetILog()->Log("Ubi.com DEBUG OnAfterServerLoadLevel() 2");
|
||||
m_pUbiSoftClient->Server_CheckCDKeys(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_pSystem->GetILog()->Log("Ubi.com DEBUG OnAfterServerLoadLevel() 3");
|
||||
m_pUbiSoftClient->Server_DestroyServer();
|
||||
m_pUbiSoftClient->Server_CheckCDKeys(0);
|
||||
}
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
}
|
||||
|
||||
bool CNetwork::VerifyMultiplayerOverInternet()
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
if(!m_pUbiSoftClient->Client_IsConnected())
|
||||
{
|
||||
// if this is a ubi.com server, and we don't have a ubi.com connection
|
||||
// disconnect, login, and retry
|
||||
GetClient()->Disconnect("@UserDisconnected");
|
||||
|
||||
HSCRIPTFUNCTION pfnOnConnectNeedUbi = m_pScriptSystem->GetFunctionPtr("Game", "OnConnectNeedUbi");
|
||||
|
||||
if (pfnOnConnectNeedUbi)
|
||||
{
|
||||
_SmartScriptObject pGameScriptObject(m_pScriptSystem,true);
|
||||
m_pScriptSystem->GetGlobalValue("Game",*pGameScriptObject);
|
||||
|
||||
m_pScriptSystem->BeginCall(pfnOnConnectNeedUbi);
|
||||
m_pScriptSystem->PushFuncParam(pGameScriptObject);
|
||||
m_pScriptSystem->EndCall();
|
||||
|
||||
m_pScriptSystem->ReleaseFunc(pfnOnConnectNeedUbi);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetwork::Client_ReJoinGameServer()
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// We have to tell Ubisoft that the client has successfully connected
|
||||
// If ubisoft is not running this won't do anything.
|
||||
m_pUbiSoftClient->Client_ReJoinGameServer();
|
||||
#endif NOT_USE_UBICOM_SDK
|
||||
}
|
||||
162
CryNetwork/Network.h
Normal file
162
CryNetwork/Network.h
Normal file
@@ -0,0 +1,162 @@
|
||||
// Network.h: interface for the CNetwork class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(AFX_NETWORK_H__9C2C8689_2D3A_4729_9DBD_A8A930264655__INCLUDED_)
|
||||
#define AFX_NETWORK_H__9C2C8689_2D3A_4729_9DBD_A8A930264655__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "CompressionHelper.h" // CCompressionHelper
|
||||
#include "TimeValue.h"
|
||||
|
||||
class CServer;
|
||||
class CClient;
|
||||
class CServerSlotLocal;
|
||||
class CServerSlot;
|
||||
class CClientLocal;
|
||||
class CDefenceWall;
|
||||
struct IScriptSystem;
|
||||
class NewUbisoftClient;
|
||||
class CScriptObjectNewUbisoftClient;
|
||||
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
class CPunkBusterInterface;
|
||||
#endif
|
||||
|
||||
// server connection flags
|
||||
// returned by the server on the m_cResponse field of the CCPConnect packet
|
||||
#define SV_CONN_FLAG_PUNKBUSTER (1 << 0) // punkbuster is on
|
||||
#define SV_CONN_FLAG_DEVMODE (1 << 1) // devmode is on
|
||||
|
||||
|
||||
typedef std::map<NRESULT,const char*> ERROR_MAP;
|
||||
typedef ERROR_MAP::iterator ERROR_MAPItor;
|
||||
|
||||
typedef std::map<WORD,CServer *> MapServers;
|
||||
typedef MapServers::iterator MapServersItor;
|
||||
|
||||
struct CryNetError{
|
||||
NRESULT nrErrorCode;
|
||||
const char *sErrorDescription;
|
||||
};
|
||||
|
||||
/*! module class factory
|
||||
@see INetwork
|
||||
*/
|
||||
class CNetwork :public INetwork
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CNetwork();
|
||||
//! destructor
|
||||
virtual ~CNetwork();
|
||||
|
||||
//! \param pScriptSystem must not be 0
|
||||
bool Init( IScriptSystem *pScriptSystem );
|
||||
|
||||
//! Get pointer to the system interface.
|
||||
ISystem* GetSystem() { return m_pSystem; };
|
||||
|
||||
//!
|
||||
//! unregister a server from the local servers map
|
||||
void UnregisterServer( WORD wPort );
|
||||
//!
|
||||
void UnregisterClient( IClient *pClient );
|
||||
//! connect a local client to a local serverslot
|
||||
//! this function is used to emulate a network connection on the same machine
|
||||
//! \param pClient
|
||||
//! \param wPort
|
||||
CServerSlotLocal *ConnectToLocalServerSlot( CClientLocal *pClient, WORD wPort );
|
||||
|
||||
// interface INetwork -------------------------------------------------------------
|
||||
|
||||
virtual DWORD GetLocalIP() const;
|
||||
virtual void SetLocalIP( const char *szLocalIP );
|
||||
virtual IClient *CreateClient(IClientSink *pSink,bool bLocal);
|
||||
virtual IServer *CreateServer(IServerSlotFactory *pFactory,WORD nPort, bool listen);
|
||||
virtual INETServerSnooper *CreateNETServerSnooper(INETServerSnooperSink *pSink);
|
||||
virtual IServerSnooper *CreateServerSnooper(IServerSnooperSink *pSink);
|
||||
virtual IRConSystem *CreateRConSystem();
|
||||
virtual const char *EnumerateError(NRESULT err);
|
||||
virtual void Release();
|
||||
virtual void GetMemoryStatistics(ICrySizer *pSizer);
|
||||
virtual ICompressionHelper *GetCompressionHelper();
|
||||
virtual void ClearProtectedFiles();
|
||||
virtual void AddProtectedFile( const char *sFilename );
|
||||
virtual IClient *GetClient();
|
||||
virtual IServer *GetServerByPort( const WORD wPort );
|
||||
virtual void UpdateNetwork();
|
||||
virtual void OnAfterServerLoadLevel( const char *szServerName, const uint32 dwPlayerCount, const WORD wPort );
|
||||
virtual bool VerifyMultiplayerOverInternet();
|
||||
virtual void Client_ReJoinGameServer();
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
bool IsPacketCompressionEnabled() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Network update functions.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Called from update of client.
|
||||
void OnClientUpdate();
|
||||
//! Called from update of server.
|
||||
void OnServerUpdate();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Defence Wall related methods.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void AddClientToDefenceWall( CIPAddress &clientIP );
|
||||
void RemoveClientFromDefenceWall( CIPAddress &clientIP );
|
||||
void PunkDetected( CIPAddress &ip );
|
||||
void OnSecurityMsgResponse( CIPAddress &ipAddress,CStream &stm );
|
||||
void OnSecurityMsgQuery( CStream &stm );
|
||||
void OnCCPPunkBusterMsg( CIPAddress &ipAddress,CStream &stm );
|
||||
|
||||
CTimeValue GetCurrentTime();
|
||||
u32 GetStringHash( const char *szString );
|
||||
int GetLogLevel();
|
||||
int GetCheatProtectionLevel();
|
||||
bool CheckPBPacket(CStream &stmPacket,CIPAddress &ip);
|
||||
void ValidateClient( CServerSlot *pSlot );
|
||||
|
||||
void InitPunkbusterClient(CClient *pClient);
|
||||
void InitPunkbusterClientLocal(CClientLocal *pClientLocal);
|
||||
void InitPunkbusterServer(bool bLocal, CServer *pServer);
|
||||
void LockPunkbusterCVars();
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
CScriptObjectNewUbisoftClient * m_pScriptObjectNewUbisoftClient; //!<
|
||||
NewUbisoftClient * m_pUbiSoftClient; //!< for internet multiplayer with ubi.com (if game is running this pointer is always valid)
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
private: // -------------------------------------------------------------------------
|
||||
|
||||
void CreateConsoleVars();
|
||||
void LogNetworkInfo();
|
||||
|
||||
IScriptSystem * m_pScriptSystem; //!< 0 before Init()
|
||||
ISystem * m_pSystem; //!<
|
||||
ICVar * m_pNetCompressPackets; //!<
|
||||
ICVar * m_pNetLog; //!<
|
||||
ICVar * m_pNetCheatProtection; //!<
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
CPunkBusterInterface * m_pPunkBuster; //!<
|
||||
#endif
|
||||
bool m_bHaveServer; //!<
|
||||
bool m_bHaveClient; //!<
|
||||
|
||||
CCompressionHelper m_Compressor; //!< used for various kind of compressions (e.g. text compression)
|
||||
MapServers m_mapServers; //!<
|
||||
ERROR_MAP m_mapErrors; //!<
|
||||
static CryNetError m_neNetErrors[]; //!<
|
||||
static unsigned int m_nCryNetInitialized; //!<
|
||||
DWORD m_dwLocalIP; //!< default: 0.0.0.0 local IPAddress (needed if we have several servers on one machine)
|
||||
CDefenceWall * m_pDefenceWall; //!<
|
||||
IClient * m_pClient; //!< pointer to the active client, otherwise 0 if there is not client active
|
||||
};
|
||||
|
||||
#endif // !defined(AFX_NETWORK_H__9C2C8689_2D3A_4729_9DBD_A8A930264655__INCLUDED_)
|
||||
684
CryNetwork/NewUbisoftCDKey.cpp
Normal file
684
CryNetwork/NewUbisoftCDKey.cpp
Normal file
@@ -0,0 +1,684 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
#include "IConsole.h" // ICVar
|
||||
#include "NewUbisoftClient.h"
|
||||
#include "GSCDKeyInterface.h"
|
||||
#include "CommonDefines.h"
|
||||
#include <string>
|
||||
|
||||
static NewUbisoftClient *g_pUbisoftClient;
|
||||
|
||||
static const char CDKEYREGKEY[] = "CDKey";
|
||||
static const char ACTIVATIONIDREGKEY[] = "ActivationID";
|
||||
|
||||
|
||||
|
||||
|
||||
// src and trg can be the same pointer (in place encryption)
|
||||
// len must be in bytes and must be multiple of 8 byts (64bits).
|
||||
// key is 128bit: int key[4] = {n1,n2,n3,n4};
|
||||
// void encipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k )
|
||||
#define TEA_ENCODE( src,trg,len,key ) {\
|
||||
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
|
||||
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
|
||||
while (nlen--) {\
|
||||
register unsigned int y=v[0],z=v[1],n=32,sum=0; \
|
||||
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; } \
|
||||
w[0]=y; w[1]=z; v+=2,w+=2; }}
|
||||
|
||||
// src and trg can be the same pointer (in place decryption)
|
||||
// len must be in bytes and must be multiple of 8 byts (64bits).
|
||||
// key is 128bit: int key[4] = {n1,n2,n3,n4};
|
||||
// void decipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k)
|
||||
#define TEA_DECODE( src,trg,len,key ) {\
|
||||
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
|
||||
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
|
||||
while (nlen--) { \
|
||||
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32; \
|
||||
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; } \
|
||||
w[0]=y; w[1]=z; v+=2,w+=2; }}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
//
|
||||
// CDKey Callbacks
|
||||
//
|
||||
/////////////////////////////////////
|
||||
extern "C"
|
||||
{
|
||||
|
||||
static GSvoid __stdcall CDKey_RcvActivationID(PREPLY_INFORMATION psReplyInfo,
|
||||
PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucActivationID, GSubyte *pucGlobalID)
|
||||
{
|
||||
if (g_pUbisoftClient)
|
||||
g_pUbisoftClient->RcvActivationID(psReplyInfo,psValidationServerInfo,pucActivationID,pucGlobalID);
|
||||
}
|
||||
|
||||
static GSvoid __stdcall CDKey_RcvAuthorizationID(PREPLY_INFORMATION psReplyInfo,
|
||||
PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucAuhorizationID)
|
||||
{
|
||||
if (g_pUbisoftClient)
|
||||
g_pUbisoftClient->RcvAuthorizationID(psReplyInfo, psValidationServerInfo, pucAuhorizationID);
|
||||
}
|
||||
|
||||
static GSvoid __stdcall CDKey_RcvValidationResponse(PREPLY_INFORMATION psReplyInfo,
|
||||
PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucAuhorizationID, CDKEY_PLAYER_STATUS eStatus,
|
||||
GSubyte *pucGlobalID)
|
||||
{
|
||||
if (g_pUbisoftClient)
|
||||
g_pUbisoftClient->RcvValidationResponse(psReplyInfo,psValidationServerInfo, pucAuhorizationID, eStatus,
|
||||
pucGlobalID);
|
||||
}
|
||||
|
||||
static GSvoid __stdcall CDKey_RcvPlayerStatusRequest(PVALIDATION_SERVER_INFO psValidationServerInfo,
|
||||
GSubyte *pucAuhorizationID)
|
||||
{
|
||||
if (g_pUbisoftClient)
|
||||
g_pUbisoftClient->RcvPlayerStatusRequest(psValidationServerInfo,pucAuhorizationID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NewUbisoftClient::CopyIDToString(const CDKeyIDVector &stVector, string &strString)
|
||||
{
|
||||
strString = "";
|
||||
for (unsigned int i=0; i < stVector.size(); i++)
|
||||
{
|
||||
char szChar[10];
|
||||
sprintf(szChar,"%.2X",stVector[i]);
|
||||
strString += szChar;
|
||||
}
|
||||
}
|
||||
|
||||
void NewUbisoftClient::CopyIDToVector(CDKeyIDVector &stVector, const GSubyte *pubArray,
|
||||
unsigned int uiSize)
|
||||
{
|
||||
stVector.clear();
|
||||
for (unsigned int i=0; i < uiSize; i++)
|
||||
{
|
||||
stVector.push_back(pubArray[i]);
|
||||
}
|
||||
GSint iCompare = memcmp(&stVector[0],pubArray,uiSize);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool NewUbisoftClient::InitCDKeySystem()
|
||||
{
|
||||
g_pUbisoftClient = this;
|
||||
|
||||
if (!m_hCDKey)
|
||||
{
|
||||
int iPort = sv_authport->GetIVal();
|
||||
|
||||
m_hCDKey = GSCDKey_Initialize(iPort);
|
||||
GSCDKey_FixRcvActivationID(m_hCDKey,CDKey_RcvActivationID);
|
||||
GSCDKey_FixRcvAuthorizationID(m_hCDKey,CDKey_RcvAuthorizationID);
|
||||
GSCDKey_FixRcvValidationResponse(m_hCDKey,CDKey_RcvValidationResponse);
|
||||
GSCDKey_FixRcvPlayerStatusRequest(m_hCDKey,CDKey_RcvPlayerStatusRequest);
|
||||
}
|
||||
|
||||
if (!m_pCDKeyServer)
|
||||
{
|
||||
m_pCDKeyServer = (PVALIDATION_SERVER_INFO)malloc(sizeof(_VALIDATION_SERVER_INFO));
|
||||
GSint iIndex=0;
|
||||
GetCDKeyServerAddress(iIndex,m_pCDKeyServer->szIPAddress,&m_pCDKeyServer->usPort);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_GetCDKeyAuthorizationID()
|
||||
{
|
||||
InitCDKeySystem();
|
||||
|
||||
char szCDkey[CDKEY_SIZE+1];
|
||||
if (!LoadCDKey(szCDkey))
|
||||
strcpy(szCDkey,"");
|
||||
|
||||
GSubyte pubActivationID[ACTIVATION_ID_SIZE];
|
||||
if (!LoadActivationID(pubActivationID))
|
||||
memset(pubActivationID,0,ACTIVATION_ID_SIZE);
|
||||
|
||||
_VALIDATION_INFO stValidationInfo;
|
||||
memcpy(stValidationInfo.ucActivationID,pubActivationID,ACTIVATION_ID_SIZE);
|
||||
strncpy(stValidationInfo.szCDKey,szCDkey,CDKEY_SIZE+1);
|
||||
|
||||
GSCDKey_RequestAuthorization(m_hCDKey,m_pCDKeyServer,&stValidationInfo,10);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::RequestCDKeyActivationID()
|
||||
{
|
||||
InitCDKeySystem();
|
||||
|
||||
char szCDkey[CDKEY_SIZE+1];
|
||||
memset(szCDkey, 0, CDKEY_SIZE+1);
|
||||
LoadCDKey(szCDkey);
|
||||
|
||||
ACTIVATION_INFO stActivationInfo;
|
||||
strncpy(stActivationInfo.szGameName,GAME_NAME,GAMELENGTH);
|
||||
strncpy(stActivationInfo.szCDKey,szCDkey,CDKEY_SIZE+1);
|
||||
|
||||
GSCDKey_RequestActivation(m_hCDKey,m_pCDKeyServer,&stActivationInfo,5);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NewUbisoftClient::Client_CheckForCDKey()
|
||||
{
|
||||
InitCDKeySystem();
|
||||
|
||||
GSchar szCDKey[CDKEY_SIZE+1];
|
||||
if (!LoadCDKey(szCDKey))
|
||||
{
|
||||
CDKey_GetCDKey();
|
||||
return false;
|
||||
}
|
||||
|
||||
GSubyte pubActivationID[ACTIVATION_ID_SIZE];
|
||||
if (!LoadActivationID(pubActivationID))
|
||||
{
|
||||
RequestCDKeyActivationID();
|
||||
return false;
|
||||
}
|
||||
CDKey_ActivationSuccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_SetCDKey(const char *szCDKey)
|
||||
{
|
||||
SaveCDKey(szCDKey);
|
||||
|
||||
RequestCDKeyActivationID();
|
||||
return true;
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RcvActivationID(PREPLY_INFORMATION psReplyInfo,
|
||||
PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucActivationID, GSubyte *pucGlobalID)
|
||||
{
|
||||
|
||||
if (!psReplyInfo->bSucceeded)
|
||||
{
|
||||
if (psReplyInfo->usErrorID == ERRORCDKEY_TIMEOUT)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvActivationID Failed: timeout");
|
||||
}
|
||||
// Since it didn't succeed we don't know if the cdkey is valid so delete it.
|
||||
SaveCDKey(NULL);
|
||||
SaveActivationID(NULL);
|
||||
//Ask to for the cdkey again.
|
||||
string strError;
|
||||
GetCDKeyErrorText(psReplyInfo->usErrorID,strError);
|
||||
CDKey_ActivationFail(strError.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvActivationID Success");
|
||||
|
||||
//CopyIDToVector(m_stActivationID,pucActivationID,ACTIVATION_ID_SIZE);
|
||||
SaveActivationID(pucActivationID);
|
||||
CDKey_ActivationSuccess();
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RcvAuthorizationID(PREPLY_INFORMATION psReplyInfo,
|
||||
PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucAuthorizationID)
|
||||
{
|
||||
if(!m_pSystem->GetIGame()->GetModuleState(EGameClient))
|
||||
return;
|
||||
|
||||
if (!psReplyInfo->bSucceeded)
|
||||
{
|
||||
if (psReplyInfo->usErrorID == ERRORCDKEY_TIMEOUT)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvAuthorizationID Failed: Timeout");
|
||||
}
|
||||
else
|
||||
{
|
||||
string strError;
|
||||
GetCDKeyErrorText(psReplyInfo->usErrorID,strError);
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvAuthorizationID Failed: %s",strError.c_str());
|
||||
|
||||
if ((psReplyInfo->usErrorID != ERRORCDKEY_TIMEOUT) && (psReplyInfo->usErrorID != ERRORCDKEY_INTERNAL_ERROR))
|
||||
{
|
||||
CDKey_ActivationFail(strError.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If the request failed let the player connect anyway because the cdkey server may be down.
|
||||
// If the game server also times out when verfiying this fake ID then it will let the player connect.
|
||||
BYTE bFakeAuthorizationID[AUTHORIZATION_ID_SIZE];
|
||||
memset(bFakeAuthorizationID,0,AUTHORIZATION_ID_SIZE);
|
||||
|
||||
assert(m_pSystem->GetINetwork()->GetClient());
|
||||
m_pSystem->GetINetwork()->GetClient()->OnCDKeyAuthorization(bFakeAuthorizationID);
|
||||
return;
|
||||
}
|
||||
|
||||
/* CDKeyIDVector stAuthorizationID;
|
||||
CopyIDToVector(stAuthorizationID,pucAuthorizationID,AUTHORIZATION_ID_SIZE);
|
||||
|
||||
string strAuthorizationID;
|
||||
CopyIDToString(stAuthorizationID,strAuthorizationID);*/
|
||||
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvAuthorizationID Success");
|
||||
//TODO: Send the Authorization ID to the game server.
|
||||
|
||||
assert(m_pSystem->GetINetwork()->GetClient());
|
||||
m_pSystem->GetINetwork()->GetClient()->OnCDKeyAuthorization(pucAuthorizationID);
|
||||
}
|
||||
|
||||
|
||||
bool NewUbisoftClient::Server_CheckPlayerAuthorizationID(BYTE bPlayerID,
|
||||
const BYTE *pubAuthorizationID)
|
||||
{
|
||||
// m_pLog->Log("Ubi.com: CheckPlayerAuthorizationID: bCheck=%c",m_bCheckCDKeys?'t':'f');
|
||||
|
||||
// If the server wasn't created through ubi.com don't check cdkeys.
|
||||
if (!m_bCheckCDKeys)
|
||||
{
|
||||
IServer *pServer = m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort);
|
||||
if(!pServer)
|
||||
{
|
||||
// that happened on a dedicated LAN server when a client tried to connect
|
||||
return false; // better we ignore this
|
||||
}
|
||||
|
||||
IServerSlot *pServerSlot = pServer->GetServerSlotbyID(bPlayerID);
|
||||
|
||||
//CXServerSlot *pSlot = itSlot->second;
|
||||
pServerSlot->OnPlayerAuthorization(true,"",NULL,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
InitCDKeySystem();
|
||||
|
||||
CDKeyIDVector stID;
|
||||
if (!pubAuthorizationID)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey CheckPlayerAuthorizationID: Authorization ID null");
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyIDToVector(stID,pubAuthorizationID,AUTHORIZATION_ID_SIZE);
|
||||
|
||||
//string strAuthorizationID;
|
||||
//CopyIDToString(stID,strAuthorizationID);
|
||||
|
||||
m_pLog->Log("\001Ubi.com: CDKey CheckPlayerAuthorizationID: %i",bPlayerID);
|
||||
|
||||
AddAuthorizedID(bPlayerID,stID);
|
||||
GSCDKey_ValidateUser(m_hCDKey,m_pCDKeyServer,const_cast<GSubyte*>(pubAuthorizationID),GAME_NAME,6);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Server_RemovePlayer(BYTE bPlayerID)
|
||||
{
|
||||
CDKeyIDVector stID;
|
||||
if (FindAuthorizedID(bPlayerID,stID))
|
||||
{
|
||||
//string strID;
|
||||
//CopyIDToString(stID,strID);
|
||||
m_pLog->Log("\001Ubi.com: CdKey: RemovePlayer: %i",bPlayerID);
|
||||
GSCDKey_DisconnectUser(m_hCDKey,m_pCDKeyServer,&stID[0]);
|
||||
RemoveAuthorizedID(bPlayerID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Server_RemoveAllPlayers()
|
||||
{
|
||||
CDKeyIDVector stID;
|
||||
|
||||
AuthorizedIDs::iterator itID = m_stAuthorizedIDs.begin();
|
||||
while (itID != m_stAuthorizedIDs.end())
|
||||
{
|
||||
//string strID;
|
||||
//CopyIDToString(itID->first,strID);
|
||||
m_pLog->Log("\001Ubi.com: CDKey RemovePlayer: %i",itID->second);
|
||||
GSCDKey_DisconnectUser(m_hCDKey,m_pCDKeyServer,const_cast<GSubyte*>(&itID->first[0]));
|
||||
itID++;
|
||||
}
|
||||
m_stAuthorizedIDs.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NewUbisoftClient::RcvValidationResponse(PREPLY_INFORMATION psReplyInfo,
|
||||
PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucAuthorizationID, CDKEY_PLAYER_STATUS eStatus,
|
||||
GSubyte *pucGlobalID)
|
||||
{
|
||||
CDKeyIDVector stID;
|
||||
CopyIDToVector(stID,pucAuthorizationID,AUTHORIZATION_ID_SIZE);
|
||||
|
||||
BYTE bPlayerID;
|
||||
|
||||
FindPlayerID(stID,bPlayerID);
|
||||
|
||||
IServer *pServer = m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort);
|
||||
if(!pServer)
|
||||
{
|
||||
assert(pServer);
|
||||
return; // better we ignore this
|
||||
}
|
||||
|
||||
IServerSlot *pServerSlot = pServer->GetServerSlotbyID(bPlayerID);
|
||||
|
||||
if(!pServerSlot)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvValidationResponse Failed: Player disconnected during authorization!");
|
||||
return;
|
||||
}
|
||||
|
||||
//CXServerSlot *pSlot = itSlot->second;
|
||||
|
||||
if (!psReplyInfo->bSucceeded)
|
||||
{
|
||||
/* if (psReplyInfo->usErrorID == ERRORCDKEY_TIMEOUT)
|
||||
{
|
||||
// don't try again
|
||||
m_pLog->Log("\001RcvValidationResponse Failed: timeout accept");
|
||||
itSlot->second->OnXPlayerAuthorization(true,"");
|
||||
}
|
||||
else
|
||||
{*/
|
||||
string strError;
|
||||
GetCDKeyErrorText(psReplyInfo->usErrorID,strError);
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvValidationResponse Failed: %s",strError.c_str());
|
||||
pServerSlot->OnPlayerAuthorization(false,strError.c_str(),NULL,0);
|
||||
RemoveAuthorizedID(stID);
|
||||
//}
|
||||
return;
|
||||
}
|
||||
|
||||
if (eStatus == E_PLAYER_UNKNOWN)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvValidationResponse Success: PLAYERUNKNOWN");
|
||||
pServerSlot->OnPlayerAuthorization(false,INVALIDCDKEY,NULL,0);
|
||||
RemoveAuthorizedID(stID);
|
||||
}
|
||||
else if (eStatus == E_PLAYER_INVALID)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvValidationResponse Success: INVALIDCDKEY");
|
||||
pServerSlot->OnPlayerAuthorization(false,INVALIDCDKEY,NULL,0);
|
||||
RemoveAuthorizedID(stID);
|
||||
}
|
||||
else if (eStatus == E_PLAYER_VALID)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvValidationResponse Success: VALIDCDKEY");
|
||||
pServerSlot->OnPlayerAuthorization(true,"",pucGlobalID,GLOBAL_ID_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NewUbisoftClient::RcvPlayerStatusRequest(PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucAuthorizationID)
|
||||
{
|
||||
if(!m_pSystem->GetIGame()->GetModuleState(EGameServer))
|
||||
{
|
||||
Server_RemoveAllPlayers();
|
||||
return;
|
||||
}
|
||||
|
||||
CDKeyIDVector stID;
|
||||
CopyIDToVector(stID,pucAuthorizationID,AUTHORIZATION_ID_SIZE);
|
||||
|
||||
AuthorizedIDs::iterator itID = m_stAuthorizedIDs.find(stID);
|
||||
if(itID != m_stAuthorizedIDs.end())
|
||||
{
|
||||
IServer *pServer = m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort);
|
||||
if(!pServer)
|
||||
{
|
||||
assert(pServer);
|
||||
return; // better we ignore this
|
||||
}
|
||||
|
||||
IServerSlot *pServerSlot = pServer->GetServerSlotbyID(itID->second);
|
||||
|
||||
// If the player is online
|
||||
if(pServerSlot)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvPlayerStatusRequest: Player Valid");
|
||||
GSCDKey_PlayerStatusReply(m_hCDKey,psValidationServerInfo,const_cast<GSubyte*>(&(itID->first[0])),E_PLAYER_VALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvPlayerStatusRequest: Player Unknown");
|
||||
GSCDKey_PlayerStatusReply(m_hCDKey,psValidationServerInfo,const_cast<GSubyte*>(&(itID->first[0])),E_PLAYER_UNKNOWN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: CDKey RcvPlayerStatusRequest: AuthorizationID Unknown");
|
||||
GSCDKey_PlayerStatusReply(m_hCDKey,psValidationServerInfo,const_cast<GSubyte*>(pucAuthorizationID),E_PLAYER_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::AddAuthorizedID(BYTE bPlayerID, const CDKeyIDVector &stAuthorizationID)
|
||||
{
|
||||
if (m_stAuthorizedIDs.find(stAuthorizationID) == m_stAuthorizedIDs.end())
|
||||
{
|
||||
m_stAuthorizedIDs[stAuthorizationID] = bPlayerID;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::RemoveAuthorizedID(const CDKeyIDVector &stAuthorizationID)
|
||||
{
|
||||
AuthorizedIDs::iterator itID = m_stAuthorizedIDs.find(stAuthorizationID);
|
||||
if (itID != m_stAuthorizedIDs.end())
|
||||
{
|
||||
m_stAuthorizedIDs.erase(itID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::RemoveAuthorizedID(BYTE bPlayer)
|
||||
{
|
||||
AuthorizedIDs::iterator itID = m_stAuthorizedIDs.begin();
|
||||
while (itID != m_stAuthorizedIDs.end())
|
||||
{
|
||||
if (itID->second == bPlayer)
|
||||
{
|
||||
m_stAuthorizedIDs.erase(itID);
|
||||
return true;
|
||||
}
|
||||
itID++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::FindPlayerID(const CDKeyIDVector &stAuthorizationID, BYTE &bPlayer)
|
||||
{
|
||||
AuthorizedIDs::iterator itID = m_stAuthorizedIDs.find(stAuthorizationID);
|
||||
if (itID != m_stAuthorizedIDs.end())
|
||||
{
|
||||
bPlayer = itID->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::FindAuthorizedID(BYTE bPlayerID, CDKeyIDVector &stAuthorizationID)
|
||||
{
|
||||
AuthorizedIDs::iterator itID = m_stAuthorizedIDs.begin();
|
||||
while (itID != m_stAuthorizedIDs.end())
|
||||
{
|
||||
if (itID->second == bPlayerID)
|
||||
{
|
||||
stAuthorizationID = itID->first;
|
||||
return true;
|
||||
}
|
||||
itID++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::GetCDKeyErrorText(GSushort usError,string &strText)
|
||||
{
|
||||
switch(usError)
|
||||
{
|
||||
case ERRORCDKEY_INVALID_CDKEY:
|
||||
strText = INVALIDCDKEY;
|
||||
break;
|
||||
case ERRORCDKEY_TIMEOUT:
|
||||
strText = CDKEYTIMEOUT;
|
||||
break;
|
||||
case ERRORCDKEY_NOT_CHALLENGED:
|
||||
strText = CDKEYNOTCHALLENGED;
|
||||
break;
|
||||
case ERRORCDKEY_ALREADY_ONLINE:
|
||||
strText = CDKEYONLINE;
|
||||
break;
|
||||
case ERRORCDKEY_INTERNAL_ERROR:
|
||||
strText = CDKEYINTERNALERROR;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::CDKey_Error(GSushort usError)
|
||||
{
|
||||
string strText;
|
||||
|
||||
GetCDKeyErrorText(usError,strText);
|
||||
CDKey_Failed(strText.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NewUbisoftClient::SaveCDKey(const GSchar *szCDKey)
|
||||
{
|
||||
if (szCDKey && (((strlen(szCDKey)+1) % 8) == 0))
|
||||
{
|
||||
unsigned char szEncCDKey[128] = {0};
|
||||
unsigned int Key[4] = {1337, 1337*2, 1337*4, 1337*8};
|
||||
|
||||
TEA_ENCODE((unsigned int *)szCDKey, (unsigned int *)szEncCDKey, strlen(szCDKey)+1, Key);
|
||||
|
||||
char szCDKeyHex[256] = {0};
|
||||
|
||||
sprintf(szCDKeyHex, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
szEncCDKey[0], szEncCDKey[1], szEncCDKey[2], szEncCDKey[3], szEncCDKey[4], szEncCDKey[5],
|
||||
szEncCDKey[6], szEncCDKey[7], szEncCDKey[8], szEncCDKey[9], szEncCDKey[10], szEncCDKey[11],
|
||||
szEncCDKey[12], szEncCDKey[13], szEncCDKey[14], szEncCDKey[15], szEncCDKey[16], szEncCDKey[17],
|
||||
szEncCDKey[18], szEncCDKey[19], szEncCDKey[20], szEncCDKey[21], szEncCDKey[22], szEncCDKey[23]);
|
||||
|
||||
WriteStringToRegistry("Ubi.com", CDKEYREGKEY, szCDKeyHex);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveStringFromRegistry("Ubi.com", CDKEYREGKEY);
|
||||
}
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::LoadCDKey(GSchar *szCDKey)
|
||||
{
|
||||
if (IsValueOnRegistry("Ubi.com", CDKEYREGKEY))
|
||||
{
|
||||
string szReadCDKey;
|
||||
|
||||
if (ReadStringFromRegistry("Ubi.com", CDKEYREGKEY, szReadCDKey))
|
||||
{
|
||||
// this is a pre1.2 stored cdkey
|
||||
if (((szReadCDKey.size()-1) == CDKEY_SIZE) && (szReadCDKey[0] == 'F') && (szReadCDKey[1] == 'C') && (szReadCDKey[2] == 'Y'))
|
||||
{
|
||||
strncpy(szCDKey, szReadCDKey.c_str(), CDKEY_SIZE);
|
||||
szCDKey[CDKEY_SIZE] = 0;
|
||||
|
||||
// save it in the new format
|
||||
SaveCDKey(szCDKey);
|
||||
}
|
||||
else if ((szReadCDKey.size()-1) == (CDKEY_SIZE+1)*2) // -1 because of the terminating 0, x2 because of hex representation
|
||||
{
|
||||
char szAux[32];
|
||||
char szEncCDKey[128] = {0};
|
||||
|
||||
for (int i = 0; i < CDKEY_SIZE+1; i++)
|
||||
{
|
||||
sprintf(szAux, "0x%c%c", szReadCDKey[i*2+0], szReadCDKey[i*2+1]);
|
||||
|
||||
szEncCDKey[i] = strtol(szAux, 0, 0);
|
||||
}
|
||||
|
||||
// decrypt it
|
||||
unsigned char szDecCDKey[128] = {0};
|
||||
unsigned int Key[4] = {1337, 1337*2, 1337*4, 1337*8};
|
||||
|
||||
TEA_DECODE((unsigned int *)szEncCDKey, (unsigned int *)szDecCDKey, CDKEY_SIZE+1, Key);
|
||||
|
||||
strncpy(szCDKey, (char *)szDecCDKey, min(strlen((char *)szDecCDKey), CDKEY_SIZE));
|
||||
szCDKey[CDKEY_SIZE] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void NewUbisoftClient::SaveActivationID(const GSubyte *pubActivationID)
|
||||
{
|
||||
if (pubActivationID)
|
||||
{
|
||||
char szActivationHex[256] = {0};
|
||||
|
||||
sprintf(szActivationHex, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
pubActivationID[0], pubActivationID[1], pubActivationID[2], pubActivationID[3], pubActivationID[4], pubActivationID[5],
|
||||
pubActivationID[6], pubActivationID[7], pubActivationID[8], pubActivationID[9], pubActivationID[10], pubActivationID[11],
|
||||
pubActivationID[12], pubActivationID[13], pubActivationID[14], pubActivationID[15]);
|
||||
|
||||
WriteStringToRegistry("Ubi.com", ACTIVATIONIDREGKEY, szActivationHex);
|
||||
}
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::LoadActivationID(GSubyte *pubActivationID)
|
||||
{
|
||||
if (IsValueOnRegistry("Ubi.com", ACTIVATIONIDREGKEY))
|
||||
{
|
||||
string szReadActivationID;
|
||||
|
||||
if (ReadStringFromRegistry("Ubi.com", ACTIVATIONIDREGKEY, szReadActivationID))
|
||||
{
|
||||
// this is pre 1.2
|
||||
if ((szReadActivationID.size()-1) == ACTIVATION_ID_SIZE) // size-1 because of the terminating 0
|
||||
{
|
||||
// load in the old form
|
||||
strncpy((char *)pubActivationID, szReadActivationID.c_str(), ACTIVATION_ID_SIZE);
|
||||
|
||||
// save it the new form
|
||||
SaveActivationID(pubActivationID);
|
||||
}
|
||||
else if ((szReadActivationID.size()-1) == (ACTIVATION_ID_SIZE*2)) // size-1 because of the terminating 0
|
||||
{
|
||||
char szAux[32];
|
||||
|
||||
for (int i = 0; i < ACTIVATION_ID_SIZE; i++)
|
||||
{
|
||||
sprintf(szAux, "0x%c%c", szReadActivationID[i*2+0], szReadActivationID[i*2+1]);
|
||||
|
||||
pubActivationID[i] = strtol(szAux, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
787
CryNetwork/NewUbisoftClient.cpp
Normal file
787
CryNetwork/NewUbisoftClient.cpp
Normal file
@@ -0,0 +1,787 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
|
||||
#include "NewUbisoftClient.h"
|
||||
#include "CommonDefines.h" // UBI.com common defines
|
||||
#include "IConsole.h" // ICVar
|
||||
#include "IRenderer.h" // IRenderer
|
||||
|
||||
#if defined(LINUX)
|
||||
#include "CryLibrary.h"
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
#include "windows.h"
|
||||
#include "Wininet.h"
|
||||
#endif
|
||||
|
||||
#include "ScriptObjectNewUbisoftClient.h" // CScriptObjectNewUbisoftClient
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "GSCDKeyInterface.h"
|
||||
#include "InitSockets.h"
|
||||
|
||||
#if !defined(LINUX)
|
||||
static const char GSINIFILE[10] = ".\\gs.ini";
|
||||
static const char GSINIFILETMP[10] = ".\\gs.tmp";
|
||||
#else
|
||||
static const char GSINIFILE[10] = "gs.ini";
|
||||
static const char GSINIFILETMP[10] = "gs.tmp";
|
||||
#endif
|
||||
|
||||
static const char RegistryKeyName[] = "SOFTWARE\\Crytek\\FarCry";
|
||||
|
||||
|
||||
|
||||
// src and trg can be the same pointer (in place encryption)
|
||||
// len must be in bytes and must be multiple of 8 byts (64bits).
|
||||
// key is 128bit: int key[4] = {n1,n2,n3,n4};
|
||||
// void encipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k )
|
||||
#define TEA_ENCODE( src,trg,len,key ) {\
|
||||
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
|
||||
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
|
||||
while (nlen--) {\
|
||||
register unsigned int y=v[0],z=v[1],n=32,sum=0; \
|
||||
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; } \
|
||||
w[0]=y; w[1]=z; v+=2,w+=2; }}
|
||||
|
||||
// src and trg can be the same pointer (in place decryption)
|
||||
// len must be in bytes and must be multiple of 8 byts (64bits).
|
||||
// key is 128bit: int key[4] = {n1,n2,n3,n4};
|
||||
// void decipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k)
|
||||
#define TEA_DECODE( src,trg,len,key ) {\
|
||||
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
|
||||
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
|
||||
while (nlen--) { \
|
||||
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32; \
|
||||
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; } \
|
||||
w[0]=y; w[1]=z; v+=2,w+=2; }}
|
||||
|
||||
|
||||
|
||||
NewUbisoftClient::NewUbisoftClient( const char *szLocalIPAddress ):m_strUsername(""), m_iJoinedLobbyID(0), m_iJoinedRoomID(0),
|
||||
m_bDownloadedGSini(false), m_eServerState(NoUbiServer), m_eClientState(NoUbiClient), m_hCDKey(0),
|
||||
m_pCDKeyServer(NULL), m_bCheckCDKeys(false), m_dwNextServerAbsTime(0),
|
||||
m_dwNextClientAbsTime(0), m_dwAccountCreateTime(0), m_bDisconnecting(0), sv_authport(0), sv_regserver_port(0),
|
||||
m_pLog(0), m_pSystem(0), m_usGamePort(0)
|
||||
{
|
||||
assert(szLocalIPAddress);
|
||||
|
||||
m_pScriptObject=0;
|
||||
|
||||
GSbool bRet;
|
||||
|
||||
if(strcmp(szLocalIPAddress,"0.0.0.0")!=0)
|
||||
{
|
||||
static char szLocalIP[256];
|
||||
|
||||
strcpy(szLocalIP,(char *)szLocalIPAddress); // make a copy (to compensate UBI sdk error)
|
||||
bRet=InitializeSockets((GSchar *)szLocalIP);
|
||||
}
|
||||
else bRet=InitializeSockets();
|
||||
|
||||
|
||||
/*
|
||||
if(!bRet)
|
||||
{
|
||||
// log error
|
||||
}
|
||||
*/
|
||||
|
||||
m_bSavePassword = false;
|
||||
}
|
||||
|
||||
#if defined(LINUX)
|
||||
static void ResolveServerAndPath( const char* szURL, string& strServer, string& strPath )
|
||||
{
|
||||
const char c_szHTTPSig[] = "http://";
|
||||
const size_t c_HTTPSigLength( sizeof( c_szHTTPSig ) - 1 ); // substract zero termination
|
||||
|
||||
string strTemp( szURL );
|
||||
if( string::npos == strTemp.find( c_szHTTPSig ) )
|
||||
{
|
||||
string::size_type posFirstSlash( strTemp.find( "/" ) );
|
||||
if(posFirstSlash == string::npos)
|
||||
{
|
||||
printf("Cannot resolve server path URL for downloading gs.ini\n");
|
||||
return;
|
||||
}
|
||||
strServer = strTemp.substr( 0, posFirstSlash );
|
||||
strPath = strTemp.substr( posFirstSlash, strTemp.size() - posFirstSlash );
|
||||
}
|
||||
else
|
||||
{
|
||||
string::size_type posFirstSlash( strTemp.find( "/", c_HTTPSigLength ) );
|
||||
if(posFirstSlash == string::npos)
|
||||
{
|
||||
printf("Cannot resolve server path URL for downloading gs.ini\n");
|
||||
return;
|
||||
}
|
||||
strServer = strTemp.substr( c_HTTPSigLength, posFirstSlash - c_HTTPSigLength );
|
||||
strPath = strTemp.substr( posFirstSlash , strTemp.size() - posFirstSlash );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool SendReceive( SOCKET& conSocket, const char* szRequestFmt, const string& strServer, const string& strPath, string& strData )
|
||||
{
|
||||
// send request
|
||||
std::vector< char > request;
|
||||
request.reserve( strServer.size() + strPath.size() + strlen( szRequestFmt ) + 1 );
|
||||
sprintf( &request[ 0 ], szRequestFmt, strPath.c_str(), strServer.c_str() );
|
||||
|
||||
if( SOCKET_ERROR == send( conSocket, &request[ 0 ], (int) strlen( &request[ 0 ] ) + 1, 0 ) )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
// receive data
|
||||
strData.clear();
|
||||
while( true )
|
||||
{
|
||||
const int c_bufferSize( 128 );
|
||||
char buffer[ c_bufferSize + 1 ];
|
||||
buffer[ 0 ] = 0;
|
||||
|
||||
int retval( recv( conSocket, buffer, c_bufferSize, 0 ) );
|
||||
if( SOCKET_ERROR == retval )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
if( 0 < retval )
|
||||
{
|
||||
buffer[ retval ] = 0;
|
||||
strData += buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool GetTextFromURL( const char* szURL, string& strText )
|
||||
{
|
||||
// determine server and path from URL
|
||||
string strServer;
|
||||
string strPath;
|
||||
|
||||
ResolveServerAndPath( szURL, strServer, strPath );
|
||||
// create host structure
|
||||
hostent* pHost( 0 );
|
||||
if( false != isalpha( strServer[ 0 ] ) )
|
||||
{
|
||||
// resolve host name
|
||||
pHost = gethostbyname( strServer.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// convert string to ip address number
|
||||
unsigned int addr( inet_addr( strServer.c_str() ) );
|
||||
pHost = gethostbyaddr( (char*) &addr, 4, AF_INET );
|
||||
}
|
||||
|
||||
if( 0 == pHost )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
// create socket
|
||||
sockaddr_in server;
|
||||
memset( &server, 0, sizeof( server ) );
|
||||
memcpy( &(server.sin_addr), pHost->h_addr, pHost->h_length );
|
||||
server.sin_family = pHost->h_addrtype;
|
||||
server.sin_port = htons( 80 );
|
||||
|
||||
SOCKET conSocket( socket( AF_INET, SOCK_STREAM, 0 ) );
|
||||
if( 0 > conSocket )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
// connect
|
||||
if( SOCKET_ERROR == connect( conSocket, (sockaddr*) &server, sizeof( server ) ) )
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
// send request
|
||||
//const char pcRequest[] = "GET /gsinit.php?user=%25s&dp=%25s HTTP/1.0\nUser-Agent: Wget/1.9\nHost: gsconnect.ubisoft.com\nAccept: */*\nConnection: Keep-Alive\n\n";
|
||||
//const char pcRequest[] = "GET /gsinit.php?user=%s&dp=%s HTTP/1.0\nHost: gsconnect.ubisoft.com\n\n";
|
||||
const char c_szRequestFmt[] = "GET %s HTTP/1.0\nHost: %s\n\n";
|
||||
if( false != SendReceive( conSocket, c_szRequestFmt, strServer, strPath, strText ) )
|
||||
{
|
||||
const char c_szHTTPHeaderEnd[ ] = "\r\n\r\n\r\n";
|
||||
const size_t c_szHTTPHeaderEndLength( sizeof( c_szHTTPHeaderEnd ) - 1 ); // substract zero termination
|
||||
|
||||
// remove http header
|
||||
string::size_type pos( strText.find( c_szHTTPHeaderEnd ) );
|
||||
if( string::npos != pos )
|
||||
{
|
||||
strText = strText.substr( pos + c_szHTTPHeaderEndLength, strText.size() - pos - c_szHTTPHeaderEndLength );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return( false );
|
||||
}
|
||||
|
||||
// close socket and return
|
||||
closesocket( conSocket );
|
||||
|
||||
return( true );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
NewUbisoftClient::~NewUbisoftClient()
|
||||
{
|
||||
Server_RemoveAllPlayers();
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
if (m_eClientState != NoUbiClient)
|
||||
clMSClientClass::Uninitialize();
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
if (m_pCDKeyServer)
|
||||
delete m_pCDKeyServer;
|
||||
|
||||
GSCDKey_Uninitialize();
|
||||
UninitializeSockets();
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::WriteStringToRegistry(const string &szKeyName, const string &szValueName, const string &szValue)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
HKEY hKey;
|
||||
|
||||
string szREGKeyName = string(RegistryKeyName) + string("\\") + szKeyName;
|
||||
|
||||
if (RegOpenKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
if (RegCreateKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (RegSetValueEx(hKey, szValueName.c_str(), 0, REG_SZ, (BYTE *)szValue.c_str(), szValue.size()) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return false;
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::ReadStringFromRegistry(const string &szKeyName, const string &szValueName, string &szValue)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
HKEY hKey;
|
||||
|
||||
string szREGKeyName = string(RegistryKeyName) + string("\\") + szKeyName;
|
||||
|
||||
if (RegOpenKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwSize = 0;
|
||||
|
||||
if (RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, 0, &dwSize) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
szValue.resize(dwSize);
|
||||
|
||||
RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, (LPBYTE)szValue.c_str(), &dwSize);
|
||||
RegCloseKey(hKey);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::RemoveStringFromRegistry(const string &szKeyName, const string &szValueName)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
HKEY hKey;
|
||||
|
||||
string szREGKeyName = string(RegistryKeyName) + string("\\") + szKeyName;
|
||||
|
||||
if (RegOpenKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwSize = 0;
|
||||
|
||||
|
||||
|
||||
if (RegDeleteValue(hKey, szValueName.c_str()) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::IsValueOnRegistry(const string &szKeyName, const string &szValueName)
|
||||
{
|
||||
#if !defined(LINUX)
|
||||
HKEY hKey;
|
||||
|
||||
string szREGKeyName = string(RegistryKeyName) + string("\\") + szKeyName;
|
||||
|
||||
if (RegOpenKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwSize = 0;
|
||||
|
||||
if (RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, 0, &dwSize) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return false;
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::EncryptString(unsigned char *szOut, const unsigned char *szIn)
|
||||
{
|
||||
string szInPadded = (char *)szIn;
|
||||
|
||||
while ((szInPadded.size() % 8) != 0)
|
||||
{
|
||||
szInPadded.push_back(0);
|
||||
}
|
||||
|
||||
unsigned int Key[4] = {31337, 31337*2, 31337*4, 31337*8};
|
||||
|
||||
TEA_ENCODE((unsigned int *)szInPadded.c_str(), (unsigned int *)szOut, szInPadded.size(), Key);
|
||||
szOut[szInPadded.size()] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::DecryptString(unsigned char *szOut, const unsigned char *szIn)
|
||||
{
|
||||
string szInPadded = (char *)szIn;
|
||||
|
||||
while ((szInPadded.size() % 8) != 0)
|
||||
{
|
||||
szInPadded.push_back(0);
|
||||
}
|
||||
|
||||
unsigned int Key[4] = {31337, 31337*2, 31337*4, 31337*8};
|
||||
|
||||
TEA_DECODE((unsigned int *)szIn, (unsigned int *)szOut, strlen((char *)szIn), Key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::EncodeHex(unsigned char *szOut, const unsigned char *szIn)
|
||||
{
|
||||
unsigned int len = strlen((char *)szIn);
|
||||
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
{
|
||||
sprintf((char *)&szOut[i*2], "%02x", szIn[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::DecodeHex(unsigned char *szOut, const unsigned char *szIn)
|
||||
{
|
||||
unsigned int len = strlen((char *)szIn) >> 1;
|
||||
char szAux[16];
|
||||
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
{
|
||||
sprintf(szAux, "0x%c%c", szIn[i*2+0], szIn[i*2+1]);
|
||||
szOut[i] = strtol(szAux, 0, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NewUbisoftClient::Init( ISystem *inpSystem )
|
||||
{
|
||||
m_pSystem = inpSystem; assert(m_pSystem);
|
||||
m_pLog = m_pSystem->GetILog(); assert(m_pLog);
|
||||
|
||||
IConsole *pConsole = m_pSystem->GetIConsole();
|
||||
|
||||
sv_authport = pConsole->GetCVar("sv_authport"); assert(sv_authport);
|
||||
sv_regserver_port = pConsole->GetCVar("sv_regserver_port"); assert(sv_regserver_port);
|
||||
}
|
||||
|
||||
|
||||
bool NewUbisoftClient::Update()
|
||||
{
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
clMSClientClass::Engine();
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
CRegisterServer::RegServer_Engine();
|
||||
|
||||
//if (m_bUsingRegServer && !m_bServerLoggedIn)
|
||||
//Server_RecreateServer();
|
||||
|
||||
{
|
||||
bool bCheckCDKey = m_pSystem->GetIGame()->GetModuleState(EGameMultiplayer)
|
||||
&& m_pSystem->GetINetwork()
|
||||
&& m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort)
|
||||
&& m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort)->GetServerType()!=eMPST_LAN;
|
||||
|
||||
Server_CheckCDKeys(bCheckCDKey);
|
||||
}
|
||||
|
||||
if (m_hCDKey)
|
||||
GSCDKey_Engine(m_hCDKey);
|
||||
|
||||
// ensure server is shown in the UBI.com list
|
||||
// Server_CreateServer() has a timelimit
|
||||
|
||||
if (m_eServerState == ServerDisconnected)
|
||||
Server_RecreateServer();
|
||||
|
||||
if ((m_eClientState == ClientDisconnected) || (m_eClientState == GameServerDisconnected))
|
||||
Client_ReJoinGameServer();
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
if (m_eClientState == NoUbiClient)
|
||||
clMSClientClass::Uninitialize();
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NewUbisoftClient::SetScriptObject( CScriptObjectNewUbisoftClient *inpObject )
|
||||
{
|
||||
assert(!m_pScriptObject); // called twice?
|
||||
assert(inpObject); // param must be 0
|
||||
|
||||
m_pScriptObject = inpObject;
|
||||
}
|
||||
|
||||
|
||||
bool NewUbisoftClient::DownloadGSini(const char *szUsername)
|
||||
{
|
||||
if (m_bDownloadedGSini)
|
||||
return true;
|
||||
|
||||
#if defined(LINUX)
|
||||
static const char* pGSConnectFilename = "gsconnect.ini";
|
||||
#endif
|
||||
|
||||
// Get the URL to download the INI from
|
||||
// Get it from the reg key
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Ubi Soft\Game Service\ConnectURL
|
||||
// if we can, otherwise use the default URL
|
||||
// http://gsconnect.ubisoft.com/gsinit.php?user=%s&dp=%s
|
||||
// If that doesn't work check the local directory
|
||||
char *connectURL = NULL;
|
||||
DWORD dwBufLen = 0;
|
||||
#if !defined(LINUX)
|
||||
//connectURL[0]=0;
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,"SOFTWARE\\Ubi Soft\\Game Service",0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx( hKey, "ConnectURL", NULL, NULL, NULL, &dwBufLen) == ERROR_SUCCESS)
|
||||
{
|
||||
connectURL = (char*)malloc(dwBufLen);
|
||||
RegQueryValueEx( hKey, "ConnectURL", NULL, NULL, (LPBYTE) connectURL, &dwBufLen);
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
}
|
||||
#else
|
||||
char iniEntry[512];
|
||||
//Check to see if the tmp file contains good info
|
||||
string GSConnectFilename(GetModulePath());
|
||||
if(GSConnectFilename.c_str()[GSConnectFilename.size()-1] != '/')
|
||||
GSConnectFilename += "/";
|
||||
GSConnectFilename += pGSConnectFilename;
|
||||
GetPrivateProfileString("Servers", "GSConnectURL", "Key not found", iniEntry, 512, GSConnectFilename.c_str());
|
||||
if (strcmp("Key not found", iniEntry) !=0 )
|
||||
{
|
||||
dwBufLen = strlen(iniEntry);
|
||||
connectURL = (char*)malloc(dwBufLen+1);
|
||||
strcpy(connectURL, iniEntry);
|
||||
}
|
||||
#endif
|
||||
if (connectURL==NULL) // We didn't get the key from the registry so try the default url
|
||||
{
|
||||
char defURL[] = "http://gsconnect.ubisoft.com/gsinit.php?user=%s&dp=%s";
|
||||
dwBufLen = sizeof(defURL);
|
||||
connectURL = (char*)malloc(dwBufLen + 1);
|
||||
strcpy(connectURL, defURL);
|
||||
}
|
||||
|
||||
const unsigned int cMaxCount = dwBufLen + strlen(szUsername) + strlen(GAME_NAME) + 1;
|
||||
char *szGSURL = (char*)malloc(cMaxCount); //size of the url + username + gamename
|
||||
|
||||
_snprintf(szGSURL,cMaxCount - 1, connectURL, szUsername, GAME_NAME);
|
||||
free(connectURL);
|
||||
|
||||
|
||||
/*GShandle stHandle = GSHttpInitialize();
|
||||
// Returns 0 on failure, but for now I don't care
|
||||
int i=GSHttpSave(stHandle,connectURL,"gsinit.ini",GS_TRUE,NULL,NULL); // Store in the working dir
|
||||
assert(i);
|
||||
GSHttpUninitialize();*/
|
||||
|
||||
//delete the current tmp file
|
||||
remove(GSINIFILETMP);
|
||||
|
||||
|
||||
#if !defined(LINUX)
|
||||
HINTERNET hNet = InternetOpen("",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,NULL);
|
||||
if (!hNet)
|
||||
{
|
||||
free(szGSURL);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
HINTERNET hURL = InternetOpenUrl(hNet,szGSURL,NULL,0,INTERNET_FLAG_HYPERLINK,NULL);
|
||||
free(szGSURL);
|
||||
if (!hURL)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
GSchar szBuffer[1024];
|
||||
GSint iSize = 1024;
|
||||
DWORD iRead = 0;
|
||||
|
||||
FILE *pFile = fopen(GSINIFILETMP,"w");
|
||||
|
||||
// If we can't open the tmp file return true and we will use the real one.
|
||||
if (!pFile)
|
||||
{
|
||||
InternetCloseHandle(hURL);
|
||||
return true;
|
||||
}
|
||||
|
||||
while (InternetReadFile(hURL,szBuffer,iSize,&iRead))
|
||||
{
|
||||
if (iRead != 0)
|
||||
{
|
||||
fwrite(szBuffer,sizeof(GSchar),iRead,pFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(pFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
InternetCloseHandle(hURL);
|
||||
}
|
||||
#else
|
||||
string strText;
|
||||
GetTextFromURL(szGSURL, strText);
|
||||
free(szGSURL);
|
||||
// write file
|
||||
FILE *pFile = fopen(GSINIFILETMP,"wb");
|
||||
if(NULL != pFile)
|
||||
{
|
||||
fwrite(strText.c_str(), 1, strText.size(), pFile);
|
||||
fclose(pFile);
|
||||
}
|
||||
#endif
|
||||
GSchar szIPAddress[100];
|
||||
//Check to see if the tmp file contains good info
|
||||
GetPrivateProfileString("Servers", "RouterIP0", "Key not found", szIPAddress, 100, GSINIFILETMP);
|
||||
if (strcmp("Key not found", szIPAddress)!=0)
|
||||
{
|
||||
//It contains good info so replace the real gs.ini file
|
||||
remove(GSINIFILE);
|
||||
rename(GSINIFILETMP,GSINIFILE);
|
||||
}
|
||||
|
||||
m_bDownloadedGSini = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Script Callbacks -------------------------------------------
|
||||
|
||||
void NewUbisoftClient::Client_LoginSuccess(const char *szUsername)
|
||||
{
|
||||
if (m_bSavePassword)
|
||||
{
|
||||
char szEncUsername[256] = {0};
|
||||
char szEncPassword[256] = {0};
|
||||
char szHexUsername[512] = {0};
|
||||
char szHexPassword[512] = {0};
|
||||
|
||||
EncryptString((unsigned char *)szEncUsername, (unsigned char *)m_strUsername.c_str());
|
||||
EncryptString((unsigned char *)szEncPassword, (unsigned char *)m_strPassword.c_str());
|
||||
|
||||
EncodeHex((unsigned char *)szHexUsername, (unsigned char *)szEncUsername);
|
||||
EncodeHex((unsigned char *)szHexPassword, (unsigned char *)szEncPassword);
|
||||
|
||||
WriteStringToRegistry("Ubi.com", "username", szHexUsername);
|
||||
WriteStringToRegistry("Ubi.com", "password", szHexPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveStringFromRegistry("Ubi.com", "username");
|
||||
RemoveStringFromRegistry("Ubi.com", "password");
|
||||
}
|
||||
|
||||
m_pScriptObject->Client_LoginSuccess(szUsername);
|
||||
}
|
||||
void NewUbisoftClient::Client_LoginFail(const char *szText)
|
||||
{
|
||||
m_pScriptObject->Client_LoginFail(szText);
|
||||
}
|
||||
void NewUbisoftClient::Client_GameServer(int iLobbyID, int iRoomID, const char *szServerName, const char *szIPAddress,
|
||||
const char *szLANIPAddress, int iMaxPlayers, int iNumPlayers)
|
||||
{
|
||||
m_pScriptObject->Client_GameServer(iLobbyID,iRoomID,szServerName,szIPAddress,szLANIPAddress,iMaxPlayers,iNumPlayers);
|
||||
}
|
||||
void NewUbisoftClient::Client_RequestFinished()
|
||||
{
|
||||
m_pScriptObject->Client_RequestFinished();
|
||||
}
|
||||
void NewUbisoftClient::Client_JoinGameServerSuccess(const char *szIPAddress, const char *szLanIPAddress,unsigned short usPort)
|
||||
{
|
||||
m_pScriptObject->Client_JoinGameServerSuccess(szIPAddress,szLanIPAddress,usPort);
|
||||
}
|
||||
void NewUbisoftClient::Client_JoinGameServerFail(const char *szText)
|
||||
{
|
||||
m_pScriptObject->Client_JoinGameServerFail(szText);
|
||||
}
|
||||
void NewUbisoftClient::Client_CreateAccountSuccess()
|
||||
{
|
||||
m_pScriptObject->Client_CreateAccountSuccess();
|
||||
}
|
||||
void NewUbisoftClient::Client_CreateAccountFail(const char *szText)
|
||||
{
|
||||
m_pScriptObject->Client_CreateAccountFail(szText);
|
||||
}
|
||||
void NewUbisoftClient::Server_RegisterServerSuccess(GSint iLobbyID, GSint iRoomID)
|
||||
{
|
||||
m_pScriptObject->Server_RegisterServerSuccess(iLobbyID,iRoomID);
|
||||
}
|
||||
void NewUbisoftClient::Server_RegisterServerFail()
|
||||
{
|
||||
m_pScriptObject->Server_RegisterServerFail();
|
||||
}
|
||||
void NewUbisoftClient::Server_LobbyServerDisconnected()
|
||||
{
|
||||
m_pScriptObject->Server_LobbyServerDisconnected();
|
||||
}
|
||||
void NewUbisoftClient::Server_PlayerJoin(const char *szUsername)
|
||||
{
|
||||
m_pScriptObject->Server_PlayerJoin(szUsername);
|
||||
}
|
||||
void NewUbisoftClient::Server_PlayerLeave(const char *szUsername)
|
||||
{
|
||||
m_pScriptObject->Server_PlayerLeave(szUsername);
|
||||
}
|
||||
|
||||
void NewUbisoftClient::CDKey_Failed(const char *szText)
|
||||
{
|
||||
m_pScriptObject->CDKey_Failed(szText);
|
||||
}
|
||||
|
||||
void NewUbisoftClient::CDKey_GetCDKey()
|
||||
{
|
||||
m_pScriptObject->CDKey_GetCDKey();
|
||||
}
|
||||
|
||||
void NewUbisoftClient::CDKey_ActivationSuccess()
|
||||
{
|
||||
m_pScriptObject->CDKey_ActivationSuccess();
|
||||
}
|
||||
|
||||
void NewUbisoftClient::CDKey_ActivationFail(const char *szText)
|
||||
{
|
||||
if(m_pSystem->GetIGame()->GetModuleState(EGameMultiplayer))
|
||||
m_pSystem->GetIRenderer()->ClearColorBuffer(Vec3(0,0,0));
|
||||
|
||||
m_pSystem->GetIConsole()->ResetProgressBar(0);
|
||||
m_pSystem->GetIConsole()->ShowConsole(false);
|
||||
m_pSystem->GetIConsole()->SetScrollMax(600/2);
|
||||
|
||||
m_pScriptObject->CDKey_ActivationFail(szText);
|
||||
}
|
||||
// --------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
bool NewUbisoftClient::GetRouterAddress(int iIndex, char *szIPAddress, unsigned short *pusClientPort,
|
||||
unsigned short *pusRegServerPort)
|
||||
{
|
||||
char szKey[50];
|
||||
char szPort[50];
|
||||
|
||||
// Try to read from the tmp file first
|
||||
_snprintf(szKey, 50, "RouterIP%i", iIndex);
|
||||
GetPrivateProfileString("Servers", szKey,"Key not found", szIPAddress, 50, GSINIFILE); // Read from the working directory
|
||||
if (strcmp("Key not found", szIPAddress)==0)
|
||||
return false;
|
||||
|
||||
_snprintf(szKey, 50, "RouterPort%i", iIndex);
|
||||
GetPrivateProfileString("Servers", szKey,"Key not found", szPort, 50, GSINIFILE); // Read from the working directory
|
||||
if (strcmp("Key not found", szPort)==0)
|
||||
return false;
|
||||
*pusClientPort = atoi(szPort);
|
||||
|
||||
_snprintf(szKey, 50, "RouterLauncherPort%i", iIndex);
|
||||
GetPrivateProfileString("Servers", szKey,"Key not found", szPort, 50, GSINIFILE); // Read from the working directory
|
||||
if (strcmp("Key not found", szPort)==0)
|
||||
return false;
|
||||
*pusRegServerPort = atoi(szPort);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::GetCDKeyServerAddress(int iIndex, char *szIPAddress, unsigned short *pusPort)
|
||||
{
|
||||
char szKey[50];
|
||||
char szPort[50];
|
||||
// Try to read from the tmp file first
|
||||
_snprintf(szKey, 50, "CDKeyServerIP%i", iIndex);
|
||||
GetPrivateProfileString("Servers", szKey,"Key not found", szIPAddress, 50, GSINIFILE); // Read from the working directory
|
||||
if (strcmp("Key not found", szIPAddress)==0)
|
||||
return false;
|
||||
_snprintf(szKey, 50, "CDKeyServerPort%i", iIndex);
|
||||
GetPrivateProfileString("Servers", szKey,"Key not found", szPort, 50, GSINIFILE); // Read from the working directory
|
||||
if (strcmp("Key not found", szPort)==0)
|
||||
return false;
|
||||
*pusPort = atoi(szPort);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
379
CryNetwork/NewUbisoftClient.h
Normal file
379
CryNetwork/NewUbisoftClient.h
Normal file
@@ -0,0 +1,379 @@
|
||||
#ifndef __NEW_UBISOFT_CLIENT
|
||||
#define __NEW_UBISOFT_CLIENT
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
// Facade design pattern over Ubisoft's own clMSClient and CRegisterby Scott Schmeisser
|
||||
// This implements all functions and callbacks needed to use Ubisoft's "Master Server Style" matchmaking service in-game
|
||||
// Class is implemented over these files: NewUbisoftClient.cpp implements the helper methods
|
||||
// NewUbisoftMSClient.cpp implements the clMsClientClass methods. This is for a game client that wants to get the list
|
||||
// of game servers.
|
||||
// NewUbisoftRegServer.cpp implements the CRegisterServer methods. This is for a game server that wants to add it self
|
||||
// to the list of game servers.
|
||||
|
||||
#if defined(WIN32)
|
||||
# define GS_WIN32
|
||||
#else
|
||||
# define GS_LINUX
|
||||
#endif
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
#include "MSClientClass.h"
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
#include "RegServerLib.h"
|
||||
#include <string> // std string
|
||||
#include "GSTypes.h"
|
||||
#include "GSCDKeyDefines.h"
|
||||
|
||||
class CScriptObjectNewUbisoftClient;
|
||||
struct ISystem;
|
||||
|
||||
|
||||
|
||||
enum UbiServerState
|
||||
{
|
||||
NoUbiServer, //Don't use Ubi.com
|
||||
ServerDisconnected, //We're disconnected from Ubi.com try to reconnect
|
||||
CreatingServer, //We're trying to create a ubi.com server
|
||||
ServerConnected //We're connected to ubi.com
|
||||
};
|
||||
|
||||
enum UbiClientState
|
||||
{
|
||||
NoUbiClient, //Don't use Ubi.com
|
||||
ClientDisconnected, //We've disconnected from ubi.com and should try to reconnect.
|
||||
ClientLoggingIn, //We're logging in to ubi.com
|
||||
ClientLoggedIn, //We're Logged in to ubi.com
|
||||
GameServerDisconnected, //We've been disconnect from the game server and should rejoin.
|
||||
JoiningGameServer, //We're joining a game server
|
||||
JoinedGameServer, //We've joined a game server
|
||||
CreateUbiAccount //We're creating an account
|
||||
};
|
||||
|
||||
class NewUbisoftClient :
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
private clMSClientClass,
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
private CRegisterServer
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
NewUbisoftClient( const char *szLocalIPAddress );
|
||||
//! destructor
|
||||
~NewUbisoftClient();
|
||||
|
||||
bool WriteStringToRegistry(const string &szKeyName, const string &szValueName, const string &szValue);
|
||||
bool ReadStringFromRegistry(const string &szKeyName, const string &szValueName, string &szValue);
|
||||
bool RemoveStringFromRegistry(const string &szKeyName, const string &szValueName);
|
||||
bool IsValueOnRegistry(const string &szKeyName, const string &szValueName);
|
||||
|
||||
bool EncryptString(unsigned char *szOut, const unsigned char *szIn);
|
||||
bool DecryptString(unsigned char *szOut, const unsigned char *szIn);
|
||||
|
||||
bool EncodeHex(unsigned char *szOut, const unsigned char *szIn);
|
||||
bool DecodeHex(unsigned char *szOut, const unsigned char *szIn);
|
||||
|
||||
//! establish the connection to the script object (call this only once)
|
||||
//! \param inpObject must not be 0
|
||||
void SetScriptObject( CScriptObjectNewUbisoftClient *inpObject );
|
||||
//! \param inpSystem must not be 0
|
||||
void Init( ISystem *inpSystem );
|
||||
|
||||
//! Must be called to send and receive messages from the Game Service.
|
||||
//! Must be called even while playing the game.
|
||||
bool Update();
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
// The methods to be used by the game client.
|
||||
// Implemented in NewUbisoftMSClient.cpp
|
||||
//
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//Login the client to the Game Service
|
||||
bool Client_AutoLogin();
|
||||
|
||||
//Login the client to the Game Service
|
||||
bool Client_Login(const char *szUsername, const char *szPassword, bool bSavePassword=false);
|
||||
|
||||
//Request Game Server list. Game Servers are received by LUAGameServer.
|
||||
bool Client_RequestGameServers();
|
||||
|
||||
// Tell the Game Service you are going to join the game server
|
||||
bool Client_JoinGameServer(int iLobbyID, int iRoomID);
|
||||
// Tell the Game Service you are going to rejoin the game server
|
||||
bool Client_ReJoinGameServer();
|
||||
// Tell the Game Service you have joined the game server
|
||||
bool Client_ConnectedToGameServer();
|
||||
// Tell the Game Service that you have left the game server
|
||||
bool Client_LeaveGameServer();
|
||||
|
||||
// Disconnect from Game Service
|
||||
bool Client_Disconnect();
|
||||
|
||||
// Create an account
|
||||
bool Client_CreateAccount(const char *szUsername, const char *szPassword);
|
||||
|
||||
// Check if there is a connection
|
||||
bool Client_IsConnected();
|
||||
|
||||
// Request the Authorization ID from the CDKey server
|
||||
bool Client_GetCDKeyAuthorizationID();
|
||||
|
||||
// Will Check to see if we have the users CDKey. If we don't it will ask the user.
|
||||
bool Client_CheckForCDKey();
|
||||
|
||||
// Set the users CDKey.
|
||||
bool Client_SetCDKey(const char *szCDKey);
|
||||
|
||||
//Request the Message Of The Day. szLanguage is the two letter language code.
|
||||
//See http://www.w3.org/WAI/ER/IG/ert/iso639.htm
|
||||
bool Client_RequestMOTD(const char *szLanguage);
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
// The methods to be used by the game server.
|
||||
// Implemented in NewUbisoftRegServer.cpp
|
||||
//
|
||||
/////////////////////////////////////////////
|
||||
void Server_CheckCDKeys(bool bCheck) { m_bCheckCDKeys = bCheck; };
|
||||
|
||||
// create the server on the Game Service
|
||||
bool Server_CreateServer(const char* szServerName,unsigned int uiMaxPlayer);
|
||||
|
||||
// set the connection to the server
|
||||
void Server_SetGamePort(unsigned short usGamePort);
|
||||
|
||||
// create the server on the Game Service
|
||||
bool Server_RecreateServer();
|
||||
|
||||
// Update settings on the Game Service
|
||||
bool Server_UpdateServer(unsigned int uiMaxPlayers, unsigned short usPort);
|
||||
|
||||
// Remove the server from Game Service
|
||||
bool Server_DestroyServer();
|
||||
|
||||
// Check the AuthorizationID of a client. This triggers CXServerSlot::OnPlayerAuthorization()
|
||||
bool Server_CheckPlayerAuthorizationID(BYTE bPlayerID,const BYTE *pubAuthorizationID);
|
||||
|
||||
// Tells the CDKeyServer that a player has left the game.
|
||||
bool Server_RemovePlayer(BYTE bPlayerID);
|
||||
|
||||
// Remove all the players from the game.
|
||||
bool Server_RemoveAllPlayers();
|
||||
|
||||
|
||||
// Script Callbacks -------------------------------------------
|
||||
|
||||
void Client_LoginSuccess(const char *szUsername);
|
||||
void Client_LoginFail(const char *szText);
|
||||
void Client_GameServer(int iLobbyID, int iRoomID, const char *szServerName, const char *szIPAddress,
|
||||
const char *szLANIPAddress, int iMaxPlayers, int iNumPlayers);
|
||||
void Client_RequestFinished();
|
||||
void Client_JoinGameServerSuccess(const char *szIPAddress, const char *szLanIPAddress,unsigned short usPort);
|
||||
void Client_JoinGameServerFail(const char *szText);
|
||||
void Client_CreateAccountSuccess();
|
||||
void Client_CreateAccountFail(const char *szText);
|
||||
void Server_RegisterServerSuccess(GSint iLobbyID, GSint iRoomID);
|
||||
void Server_RegisterServerFail();
|
||||
void Server_LobbyServerDisconnected();
|
||||
void Server_PlayerJoin(const char *szUsername);
|
||||
void Server_PlayerLeave(const char *szUsername);
|
||||
|
||||
// Pop up an error to the user.
|
||||
void CDKey_Failed(const char *szText);
|
||||
|
||||
// Ask the user for a cdkey.
|
||||
void CDKey_GetCDKey();
|
||||
|
||||
// The cdkey was successfully activated
|
||||
void CDKey_ActivationSuccess();
|
||||
|
||||
// The cdkey activation failed. The user should reenter the cdkey.
|
||||
void CDKey_ActivationFail(const char *szText);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// Callback that receives the Activation ID from the CDKey Server
|
||||
void RcvActivationID(PREPLY_INFORMATION psReplyInfo, PVALIDATION_SERVER_INFO psValidationServerInfo,
|
||||
GSubyte *pucActivationID,GSubyte *pucGlobalID);
|
||||
// Callback that receives the Authorization ID from CDKeyServer. This ID must be sent to the Game Server.
|
||||
void RcvAuthorizationID(PREPLY_INFORMATION psReplyInfo, PVALIDATION_SERVER_INFO psValidationServerInfo,
|
||||
GSubyte *pucAuhorizationID);
|
||||
// Callback that receives if a players cdkey is valid and the server should allow the player to connect
|
||||
void RcvValidationResponse(PREPLY_INFORMATION psReplyInfo, PVALIDATION_SERVER_INFO psValidationServerInfo,
|
||||
GSubyte *pucAuhorizationID, CDKEY_PLAYER_STATUS eStatus, GSubyte *pucGlobalID);
|
||||
// Callback that asks to see if a player is still on the game server.
|
||||
void RcvPlayerStatusRequest(PVALIDATION_SERVER_INFO psValidationServerInfo, GSubyte *pucAuhorizationID);
|
||||
|
||||
private: // -----------------------------------------------------------------
|
||||
|
||||
// Helper function to download gs.ini file from internet
|
||||
bool DownloadGSini(const char *szUsername);
|
||||
// Helper function to parse gs.ini file
|
||||
bool GetRouterAddress(int iIndex, char *szIPAddress, unsigned short *pusClientPort,
|
||||
unsigned short *pusRegServerPort);
|
||||
|
||||
void RegServerDisconnected();
|
||||
void MSClientDisconnected();
|
||||
|
||||
typedef std::vector<GSubyte> CDKeyIDVector;
|
||||
|
||||
//CD Key methods
|
||||
bool InitCDKeySystem();
|
||||
bool GetCDKeyServerAddress(int iIndex, char *szIPAddress, unsigned short *pusPort);
|
||||
|
||||
// Save a clients Authoriziation ID
|
||||
bool AddAuthorizedID(BYTE bPlayerID, const CDKeyIDVector &stAuthorizationID);
|
||||
|
||||
//Get a player's ID based on their Authorization ID
|
||||
bool FindPlayerID(const CDKeyIDVector &stAuthorizationID, BYTE &bPlayer);
|
||||
//Get a player's Authorization ID based on their ID
|
||||
bool FindAuthorizedID(BYTE bPlayerID, CDKeyIDVector &stAuthorizationID);
|
||||
|
||||
//Remove a players Authorization ID
|
||||
bool RemoveAuthorizedID(const CDKeyIDVector &stAuthorizationID);
|
||||
bool RemoveAuthorizedID(BYTE bPlayer);
|
||||
|
||||
//Get the localization string for a CDKey error
|
||||
bool GetCDKeyErrorText(GSushort usError,string &strText);
|
||||
|
||||
// Gets the error string and sends it to CDKey_Failed()
|
||||
bool CDKey_Error(GSushort usError);
|
||||
|
||||
//Helper functions for Authorization IDs
|
||||
void CopyIDToVector(CDKeyIDVector &stVector, const GSubyte *pubArray, unsigned int uiSize);
|
||||
void CopyIDToString(const CDKeyIDVector &stVector, string &strString);
|
||||
|
||||
|
||||
//Save and load CDkey information. Currently from the file cdkey.ini
|
||||
void SaveCDKey(const GSchar *szCDKey);
|
||||
void SaveActivationID(const GSubyte *pubActivationID);
|
||||
bool LoadCDKey(GSchar *szCDKey);
|
||||
bool LoadActivationID(GSubyte *pubActivationID);
|
||||
|
||||
//Request the Activation Id from the CDKey server.
|
||||
bool RequestCDKeyActivationID();
|
||||
|
||||
// These are the MSClient callbacks to implement.
|
||||
GSvoid GameServerCB(GSint iLobbyID,GSint iRoomID,GSshort siGroupType,
|
||||
GSchar *szGroupName,GSint iConfig,GSchar *szMaster,GSchar *szAllowedGames,
|
||||
GSchar *szGames,GSchar *szGameVersion,GSchar *szGSVersion,GSvoid *vpInfo,
|
||||
GSint iSize,GSuint uiMaxPlayer,GSuint uiNbrPlayer,GSuint uiMaxVisitor,
|
||||
GSuint uiNbrVisitor,GSchar *szIPAddress,GSchar *szAltIPAddress,
|
||||
GSint iEventID);
|
||||
GSvoid ErrorCB(GSint iReason,GSint iLobbyID,GSint iRoomID);
|
||||
GSvoid InitFinishedCB(GSubyte ucType,GSint iError,GSchar *szUserName);
|
||||
GSvoid LoginDisconnectCB();
|
||||
GSvoid LobbyDisconnectCB();
|
||||
GSvoid RequestFinishedCB();
|
||||
GSvoid JoinFinishedCB(GSint iLobbyID,GSint iRoomID,
|
||||
GSvoid *vpGameData,GSint iSize,GSchar *szIPAddress,
|
||||
GSchar *szAltIPAddress,GSushort usPort);
|
||||
GSvoid AlternateInfoCB(GSint iLobbyID,GSint iRoomID,
|
||||
const GSvoid* pcAltGroupInfo,GSint iAltGroupInfoSize);
|
||||
GSvoid RequestMOTDCB(GSubyte ubType, GSchar *szUbiMOTD,
|
||||
GSchar *szGameMOTD, GSint iReason);
|
||||
|
||||
GSvoid AccountCreationCB(GSubyte ucType, GSint iReason);
|
||||
GSvoid ModifyAccountCB(GSubyte ucType, GSint iReason);
|
||||
|
||||
//We aren't implementing Ladder support so these callbacks are ignored.
|
||||
GSvoid MatchStartedCB(GSint iLobbyID,GSint iRoomID, GSuint uiMatchID){};
|
||||
GSvoid SubmitMatchCB(GSubyte ucType,GSint iReason, GSuint uiMatchID){};
|
||||
|
||||
|
||||
// These are the RegServer callbacks to implement
|
||||
GSvoid RegServerRcv_LoginRouterResult( GSubyte ucType, GSint lReason,
|
||||
const GSchar* szIPAddress );
|
||||
GSvoid RegServerRcv_RouterDisconnection();
|
||||
GSvoid RegServerRcv_RegisterServerResult( GSubyte pucType,GSint plReason,GSint iGroupID,
|
||||
const GSchar* szAddress,GSushort usPort,const GSchar* szSessionName );
|
||||
GSvoid RegServerRcv_RequestParentGroupResult( GSubyte ucType,
|
||||
GSint lReason, GSint iServerID,GSint iGroupID, const GSchar* szGroupName,
|
||||
GSuint uiNbPlayers, GSuint uiMaxPlayers );
|
||||
GSvoid RegServerRcv_LobbyServerLoginResults( GSubyte ucType,
|
||||
GSint iReason, GSint iLobbyServerID, GSint iGroupID );
|
||||
GSvoid RegServerRcv_LobbyServerUpdateGroupSettingsResults(
|
||||
GSubyte ucType, GSint iReason, GSint iGroupID );
|
||||
GSvoid RegServerRcv_LobbyServerDisconnection();
|
||||
GSvoid RegServerRcv_LobbyServerMemberNew( const GSchar* szMember,GSbool bSpectator,
|
||||
const GSchar* szIPAddress, const GSchar* szAltIPAddress,
|
||||
const GSvoid* pPlayerInfo, GSuint uiPlayerInfoSize,GSushort usPlayerStatus );
|
||||
GSvoid RegServerRcv_LobbyServerMemberLeft(const GSchar* szMember );
|
||||
GSvoid RegServerRcv_LobbyServerNewGroup (GSushort usRoomType,
|
||||
const GSchar* szRoomName,GSint iGroupID,GSint iLobbyServerID,GSint iParentGroupID,
|
||||
GSint uiGroupConfig,GSshort sGroupLevel,const GSchar* szMaster,const GSchar* szAllowedGames,
|
||||
const GSchar* szGame,const GSvoid* pGroupInfo,GSuint GroupInfoSize,GSuint uiMatchEventID,
|
||||
GSuint uiMaxPlayers,GSuint uiNbPlayers,GSuint uiMaxSpectators,GSuint uiNbSpectators,
|
||||
const GSchar* szGameVersion,const GSchar* szGSGameVersion,const GSchar* szIPAddress,
|
||||
const GSchar* szAltIPAddress );
|
||||
|
||||
// We can ignore these RegServer callbacks
|
||||
GSvoid RegServerRcv_LobbyServerMatchStartReply( GSubyte ucType,
|
||||
GSint iReason, GSint iGroupID ){};
|
||||
GSvoid RegServerRcv_LobbyServerMatchFinishReply( GSubyte ucType,
|
||||
GSint iReason, GSint iGroupID ){};
|
||||
GSvoid RegServerRcv_LobbyServerGroupConfigUpdate(
|
||||
GSuint uiGroupConfig, GSint iGroupID ){};
|
||||
virtual GSvoid RegServerRcv_LobbyServerMemberUpdateInfo(const GSchar* szMember,
|
||||
const GSvoid* pPlayerInfo,GSuint uiPlayerInfoSize ){};
|
||||
GSvoid RegServerRcv_LobbyServerMemberUpdateStatus(const GSchar* szPlayer,
|
||||
GSushort usPlayerStatus ){};
|
||||
/*#if defined(LINUX32)
|
||||
//dummy functions coming from new ubi.com sdk released for linux
|
||||
virtual GSvoid RegServerRcv_SubmitMatchResultReply( GSubyte ucType,
|
||||
GSint iReason, GSint iGroupID ){};
|
||||
virtual GSvoid RegServerRcv_MatchStarted( GSuint uiMatchID ){};
|
||||
virtual GSvoid RegServerRcv_FinalResult(GSuint uiMatchId, GSubyte ucType, GSint iReason, const LADDER_ROW *pResults, GSuint uiNumResult){};
|
||||
#endif
|
||||
*/
|
||||
// These are the login settings to use if we have to re-login
|
||||
string m_strUsername; //!<
|
||||
string m_strPassword; //!<
|
||||
|
||||
// These are the settings to use when creating the game server
|
||||
string m_strGameServerName; //!<
|
||||
unsigned int m_uiMaxPlayers; //!<
|
||||
unsigned short m_usGamePort; //!<
|
||||
|
||||
int m_iJoinedLobbyID; //!< The id of the lobby we joined
|
||||
int m_iJoinedRoomID; //!< The id of the room we joined
|
||||
bool m_bDownloadedGSini; //!< Have we downloaded the gs.ini file yet. We only need to do this once per game.s
|
||||
int m_iServerLobbyID; //!< The lobby id of the game server
|
||||
int m_iServerRoomID; //!< The room id of the game server
|
||||
|
||||
UbiServerState m_eServerState;
|
||||
UbiClientState m_eClientState;
|
||||
|
||||
//CD Key members
|
||||
GShandle m_hCDKey; //The handle for the cdkey library.
|
||||
PVALIDATION_SERVER_INFO m_pCDKeyServer;
|
||||
bool m_bCheckCDKeys; //If true the server will check cdkeys.
|
||||
|
||||
typedef std::map<CDKeyIDVector,BYTE> AuthorizedIDs;
|
||||
AuthorizedIDs m_stAuthorizedIDs;
|
||||
|
||||
CScriptObjectNewUbisoftClient * m_pScriptObject; //!<
|
||||
DWORD m_dwNextServerAbsTime; //!< in seconds (0 if deactivated)
|
||||
DWORD m_dwNextClientAbsTime; //!< in seconds (0 if deactivated)
|
||||
DWORD m_dwAccountCreateTime; //!< in seconds (0 if deactivated)
|
||||
ILog * m_pLog; //!<
|
||||
ISystem * m_pSystem; //!<
|
||||
|
||||
ICVar * sv_authport;
|
||||
ICVar * sv_regserver_port;
|
||||
|
||||
bool m_bSavePassword;
|
||||
bool m_bDisconnecting;
|
||||
|
||||
friend class cCScriptObjectNewUbisoftClient;
|
||||
};
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
#endif //__UBISOFT_MSCLIENT
|
||||
556
CryNetwork/NewUbisoftMSClient.cpp
Normal file
556
CryNetwork/NewUbisoftMSClient.cpp
Normal file
@@ -0,0 +1,556 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
#include "NewUbisoftClient.h"
|
||||
#include "LobbyDefines.h"
|
||||
#include "CommonDefines.h"
|
||||
|
||||
|
||||
#if !defined(LINUX)
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "ScriptObjectNewUbisoftClient.h" // CScriptObjectNewUbisoftClient
|
||||
|
||||
|
||||
// the following libs are not in the project setting because we want to have then only in if NOT_USE_UBICOM_SDK is defined
|
||||
/*#ifdef _DEBUG
|
||||
#pragma comment(lib,"libgsclient_debug.lib")
|
||||
#pragma comment(lib,"libgsconnect_debug.lib")
|
||||
#pragma comment(lib,"libgscrypto_debug.lib")
|
||||
#pragma comment(lib,"libgsutility_debug.lib")
|
||||
#pragma comment(lib,"libgsregserver_debug.lib")
|
||||
#pragma comment(lib,"libgssocket_debug.lib")
|
||||
#pragma comment(lib,"libgsproxyclient_debug.lib")
|
||||
#pragma comment(lib,"libgsresult_debug.lib")
|
||||
#pragma comment(lib,"libgscdkey_debug.lib")
|
||||
#else
|
||||
*/
|
||||
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
#pragma comment(lib,"libgsclient.lib")
|
||||
#pragma comment(lib,"libgsmsclient.lib")
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
#pragma comment(lib,"libgsconnect.lib")
|
||||
#pragma comment(lib,"libgscrypto.lib")
|
||||
#pragma comment(lib,"libgsutility.lib")
|
||||
#pragma comment(lib,"libgsregserver.lib")
|
||||
#pragma comment(lib,"libgssocket.lib")
|
||||
#pragma comment(lib,"libgsproxyclient.lib")
|
||||
#pragma comment(lib,"libgsresult.lib")
|
||||
#pragma comment(lib,"libgscdkey.lib")
|
||||
//#endif
|
||||
|
||||
|
||||
/*
|
||||
gsnat,
|
||||
gshttp,
|
||||
gsdatacontainer,
|
||||
gszlib,
|
||||
*/
|
||||
|
||||
|
||||
static DWORD g_dwKeepalifeLoginClient=60; // in seconds
|
||||
static DWORD g_dwAccountCreateTimeout=60; //Timeout between calls to CreateAcount in seconds
|
||||
|
||||
bool NewUbisoftClient::Client_IsConnected()
|
||||
{
|
||||
if (m_eClientState >= ClientLoggedIn)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_AutoLogin()
|
||||
{
|
||||
if (m_strUsername.empty() || m_strPassword.empty())
|
||||
{
|
||||
string szHexUsername;
|
||||
string szHexPassword;
|
||||
|
||||
if (!ReadStringFromRegistry("Ubi.com", "username", szHexUsername) || !ReadStringFromRegistry("Ubi.com", "password", szHexPassword))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char szEncUsername[256] = {0};
|
||||
char szEncPassword[256] = {0};
|
||||
char szUsername[256] = {0};
|
||||
char szPassword[256] = {0};
|
||||
|
||||
DecodeHex((unsigned char *)szEncUsername, (unsigned char *)szHexUsername.c_str());
|
||||
DecodeHex((unsigned char *)szEncPassword, (unsigned char *)szHexPassword.c_str());
|
||||
|
||||
DecryptString((unsigned char *)szUsername, (unsigned char *)szEncUsername);
|
||||
DecryptString((unsigned char *)szPassword, (unsigned char *)szEncPassword);
|
||||
|
||||
m_strUsername = szUsername;
|
||||
m_strPassword = szPassword;
|
||||
}
|
||||
|
||||
return Client_Login(m_strUsername.c_str(), m_strPassword.c_str());
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_Login(const GSchar* szUsername, const GSchar* szPassword, bool bSavePassword)
|
||||
{
|
||||
if (m_eClientState >= ClientLoggingIn)
|
||||
return false;
|
||||
|
||||
// Save the username and password.
|
||||
m_strUsername = szUsername;
|
||||
m_strPassword = szPassword;
|
||||
m_bSavePassword = bSavePassword;
|
||||
|
||||
// remove it now
|
||||
if (!m_bSavePassword)
|
||||
{
|
||||
RemoveStringFromRegistry("Ubi.com", "username");
|
||||
RemoveStringFromRegistry("Ubi.com", "password");
|
||||
}
|
||||
|
||||
if (!DownloadGSini(szUsername))
|
||||
{
|
||||
Client_LoginFail(CONNECTIONFAILED);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
// Go through numbered IP and Ports in the ini
|
||||
char szIPAddress[50];
|
||||
unsigned short usClientPort,usRegServerPort;
|
||||
int iIndex = 0;
|
||||
|
||||
if (GetRouterAddress(iIndex,szIPAddress,&usClientPort,&usRegServerPort))
|
||||
{
|
||||
while (clMSClientClass::Initialize(szIPAddress, usClientPort, szUsername, szPassword,
|
||||
UBISOFT_GAME_VERSION) == GS_FALSE)
|
||||
{
|
||||
iIndex++;
|
||||
if (!GetRouterAddress(iIndex,szIPAddress,&usClientPort,&usRegServerPort))
|
||||
{
|
||||
MSClientDisconnected();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
m_eClientState = ClientLoggingIn;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NewUbisoftClient::Client_RequestGameServers()
|
||||
{
|
||||
if (m_eClientState < ClientLoggedIn) // If we are logged in to the Game Service
|
||||
return false;
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
if (m_eClientState > ClientLoggedIn)
|
||||
{
|
||||
m_pLog->Log("Ubi.com: Client_RequestGameServers %i",(int)m_eClientState);
|
||||
clMSClientClass::LeaveGameServer(m_iJoinedLobbyID,m_iJoinedRoomID);
|
||||
m_eClientState = ClientLoggedIn;
|
||||
}
|
||||
|
||||
clMSClientClass::RequestGameServers(GAME_NAME);
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_JoinGameServer(int iLobbyID, int iRoomID)
|
||||
{
|
||||
m_pLog->Log("Ubi.com: Client_JoinGameServer %i %i",iLobbyID, iRoomID);
|
||||
|
||||
switch (m_eClientState)
|
||||
{
|
||||
case NoUbiClient:
|
||||
case ClientLoggingIn:
|
||||
return false;
|
||||
case ClientDisconnected:
|
||||
{
|
||||
// If we haven't logged in before
|
||||
if (m_strUsername.empty())
|
||||
return false;
|
||||
|
||||
m_iJoinedLobbyID = iLobbyID;
|
||||
m_iJoinedRoomID = iRoomID;
|
||||
Client_Login(m_strUsername.c_str(),m_strPassword.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
case ClientLoggedIn:
|
||||
case GameServerDisconnected:
|
||||
{
|
||||
if (clMSClientClass::JoinGameServer(iLobbyID,iRoomID
|
||||
,"",GSGAMEVERSION,GAME_NAME,NULL,0))
|
||||
{
|
||||
m_iJoinedLobbyID = iLobbyID;
|
||||
m_iJoinedRoomID = iRoomID;
|
||||
m_eClientState = JoiningGameServer;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
case JoinedGameServer:
|
||||
if ((m_iJoinedLobbyID == iLobbyID) && (m_iJoinedRoomID == iRoomID))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (clMSClientClass::JoinGameServer(iLobbyID,iRoomID
|
||||
,"",GSGAMEVERSION,GAME_NAME,NULL,0))
|
||||
{
|
||||
m_iJoinedLobbyID = iLobbyID;
|
||||
m_iJoinedRoomID = iRoomID;
|
||||
m_eClientState = JoiningGameServer;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_ReJoinGameServer()
|
||||
{
|
||||
// Wait untill it's time to reconnect
|
||||
if(m_dwNextClientAbsTime)
|
||||
if(m_pScriptObject->GetAbsTimeInSeconds() < m_dwNextClientAbsTime)
|
||||
return false;
|
||||
|
||||
m_dwNextClientAbsTime = 0;
|
||||
switch (m_eClientState)
|
||||
{
|
||||
case NoUbiClient:
|
||||
case ClientLoggingIn:
|
||||
case JoiningGameServer:
|
||||
case JoinedGameServer:
|
||||
return false;
|
||||
case ClientDisconnected:
|
||||
case ClientLoggedIn:
|
||||
case GameServerDisconnected:
|
||||
Client_JoinGameServer(m_iJoinedLobbyID,m_iJoinedRoomID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_ConnectedToGameServer()
|
||||
{
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
if (clMSClientClass::GameServerConnected(m_iJoinedLobbyID,m_iJoinedRoomID))
|
||||
return true;
|
||||
else
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_LeaveGameServer()
|
||||
{
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
if (clMSClientClass::LeaveGameServer(m_iJoinedLobbyID,m_iJoinedRoomID))
|
||||
{
|
||||
m_iJoinedLobbyID = 0;
|
||||
m_iJoinedRoomID = 0;
|
||||
m_eClientState = ClientLoggedIn;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_Disconnect()
|
||||
{
|
||||
if (m_eClientState == NoUbiClient)
|
||||
return true;
|
||||
|
||||
m_bCheckCDKeys = false;
|
||||
|
||||
if (m_eClientState != ClientLoggingIn)
|
||||
{
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
clMSClientClass::Uninitialize();
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
m_iJoinedLobbyID = 0;
|
||||
m_iJoinedRoomID= 0;
|
||||
m_eClientState = NoUbiClient;
|
||||
m_bDisconnecting = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bDisconnecting = 1;
|
||||
}
|
||||
|
||||
Update();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_CreateAccount(const char *szUsername, const char *szPassword)
|
||||
{
|
||||
if (m_eClientState != NoUbiClient)
|
||||
return false;
|
||||
|
||||
if (m_dwAccountCreateTime)
|
||||
if(m_pScriptObject->GetAbsTimeInSeconds() < m_dwAccountCreateTime)
|
||||
Client_CreateAccountFail(CREATEACCOUNTBLOCKED);
|
||||
|
||||
m_eClientState = CreateUbiAccount;
|
||||
|
||||
if (!DownloadGSini(szUsername))
|
||||
return false;
|
||||
|
||||
// Go through numbered IP and Ports in the ini
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
char szIPAddress[50];
|
||||
unsigned short usClientPort,usRegServerPort;
|
||||
int iIndex = 0;
|
||||
|
||||
if (GetRouterAddress(iIndex,szIPAddress,&usClientPort,&usRegServerPort))
|
||||
{
|
||||
while (clMSClientClass::CreateAccount(szIPAddress, usClientPort, UBISOFT_GAME_VERSION, szUsername,
|
||||
szPassword, "","","","") == GS_FALSE)
|
||||
{
|
||||
iIndex++;
|
||||
if (!GetRouterAddress(iIndex,szIPAddress,&usClientPort,&usRegServerPort))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Client_RequestMOTD(const char *szLanguage)
|
||||
{
|
||||
if (m_eClientState < ClientLoggedIn)
|
||||
return false;
|
||||
|
||||
#ifndef EXCLUDE_UBICOM_CLIENT_SDK
|
||||
if (RequestMOTD(szLanguage))
|
||||
return true;
|
||||
else
|
||||
#endif // EXCLUDE_UBICOM_CLIENT_SDK
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
// MSClient Callbacks
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
GSvoid NewUbisoftClient::GameServerCB(GSint iLobbyID,GSint iRoomID,GSshort siGroupType,
|
||||
GSchar *szGroupName,GSint iConfig,GSchar *szMaster,GSchar *szAllowedGames,
|
||||
GSchar *szGames,GSchar *szGameVersion,GSchar *szGSVersion,GSvoid *vpInfo,
|
||||
GSint iSize,GSuint uiMaxPlayer,GSuint uiNbrPlayer,GSuint uiMaxVisitor,
|
||||
GSuint uiNbrVisitor,GSchar *szIPAddress,GSchar *szAltIPAddress,
|
||||
GSint iEventID)
|
||||
{
|
||||
char *szPort = (char*)vpInfo;
|
||||
char szGameIPAddress[32],szGameLANIPAddress[32];
|
||||
|
||||
m_pLog->Log("Ubi.com: GameServerCB %s %i %i",szGroupName,iLobbyID, iRoomID);
|
||||
_snprintf(szGameIPAddress,32,"%s:%s",szIPAddress,szPort);
|
||||
_snprintf(szGameLANIPAddress,32,"%s:%s",szAltIPAddress,szPort);
|
||||
|
||||
Client_GameServer(iLobbyID,iRoomID,szGroupName,szGameIPAddress,szGameLANIPAddress,
|
||||
uiMaxPlayer,uiNbrPlayer);
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::ErrorCB(GSint iReason,GSint iLobbyID,GSint iRoomID)
|
||||
{
|
||||
m_pLog->Log("Ubi.com: ErrorCB %i %i",iLobbyID, iRoomID);
|
||||
m_eClientState = GameServerDisconnected;
|
||||
m_dwNextClientAbsTime = m_pScriptObject->GetAbsTimeInSeconds() + g_dwKeepalifeLoginClient;
|
||||
switch (iReason)
|
||||
{
|
||||
default:
|
||||
case ERRORLOBBYSRV_UNKNOWNERROR:
|
||||
Client_JoinGameServerFail(UNKNOWNERROR);
|
||||
break;
|
||||
case ERRORLOBBYSRV_GROUPNOTEXIST:
|
||||
Client_JoinGameServerFail(GROUPNOTEXIST);
|
||||
break;
|
||||
case ERRORLOBBYSRV_NOMOREPLAYERS:
|
||||
case ERRORLOBBYSRV_NOMOREMEMBERS:
|
||||
Client_JoinGameServerFail(NOMOREPLAYERS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::InitFinishedCB(GSubyte ucType,GSint iError,GSchar *szUserName)
|
||||
{
|
||||
if (m_bDisconnecting)
|
||||
{
|
||||
// fake logged in state
|
||||
// so we can actually get disconnected
|
||||
m_eClientState = ClientLoggedIn;
|
||||
|
||||
Client_Disconnect();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ucType == GSSUCCESS)
|
||||
{
|
||||
m_strUsername = szUserName;
|
||||
m_eClientState = ClientLoggedIn;
|
||||
if (m_iJoinedLobbyID)
|
||||
{
|
||||
Client_JoinGameServer(m_iJoinedLobbyID,m_iJoinedRoomID);
|
||||
m_eClientState = JoiningGameServer;
|
||||
}
|
||||
Client_LoginSuccess(szUserName);
|
||||
Client_CheckForCDKey();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_eClientState = NoUbiClient;
|
||||
switch (iError)
|
||||
{
|
||||
case ERRORSECURE_INVALIDACCOUNT:
|
||||
Client_LoginFail(INVALIDACCOUNT);
|
||||
break;
|
||||
case ERRORSECURE_INVALIDPASSWORD:
|
||||
Client_LoginFail(INVALIDPASSWORD);
|
||||
break;
|
||||
case ERRORSECURE_DATABASEFAILED:
|
||||
Client_LoginFail(DATABASEFAILED);
|
||||
break;
|
||||
case ERRORSECURE_BANNEDACCOUNT:
|
||||
Client_LoginFail(BANNEDACCOUNT);
|
||||
break;
|
||||
case ERRORSECURE_BLOCKEDACCOUNT:
|
||||
Client_LoginFail(BLOCKEDACCOUNT);
|
||||
break;
|
||||
case ERRORSECURE_LOCKEDACCOUNT:
|
||||
Client_LoginFail(LOCKEDACCOUNT);
|
||||
break;
|
||||
case ERRORROUTER_NOTDISCONNECTED:
|
||||
Client_LoginFail(NOTDISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::LoginDisconnectCB()
|
||||
{
|
||||
m_pLog->Log("Ubi.com: LoginDisconnectCB");
|
||||
if (m_eClientState == ClientLoggingIn)
|
||||
m_eClientState = NoUbiClient;
|
||||
else
|
||||
MSClientDisconnected();
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::LobbyDisconnectCB()
|
||||
{
|
||||
m_pLog->Log("Ubi.com: LobbyDisconnectCB");
|
||||
if (m_eClientState > GameServerDisconnected)
|
||||
m_eClientState = GameServerDisconnected;
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RequestFinishedCB()
|
||||
{
|
||||
Client_RequestFinished();
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::JoinFinishedCB(GSint iLobbyID,GSint iRoomID,
|
||||
GSvoid *vpGameData,GSint iSize,GSchar *szIPAddress,
|
||||
GSchar *szAltIPAddress,GSushort usPort)
|
||||
{
|
||||
m_eClientState = JoinedGameServer;
|
||||
Client_ConnectedToGameServer();
|
||||
Client_JoinGameServerSuccess(szIPAddress,szAltIPAddress,usPort);
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::AlternateInfoCB(GSint iLobbyID,GSint iRoomID,
|
||||
const GSvoid* pcAltGroupInfo,GSint iAltGroupInfoSize)
|
||||
{
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::AccountCreationCB(GSubyte ucType, GSint iReason)
|
||||
{
|
||||
m_eClientState = NoUbiClient;
|
||||
if (ucType == GSSUCCESS)
|
||||
{
|
||||
m_dwAccountCreateTime = m_pScriptObject->GetAbsTimeInSeconds() + g_dwAccountCreateTimeout;
|
||||
Client_CreateAccountSuccess();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwAccountCreateTime = 0;
|
||||
switch (ucType)
|
||||
{
|
||||
default:
|
||||
Client_CreateAccountFail(UNKNOWNERROR);
|
||||
break;
|
||||
case ERRORSECURE_USERNAMEEXISTS:
|
||||
Client_CreateAccountFail(USERNAMEEXISTS);
|
||||
break;
|
||||
case ERRORSECURE_USERNAMEMALFORMED:
|
||||
Client_CreateAccountFail(USERNAMEMALFORMED);
|
||||
break;
|
||||
case ERRORSECURE_USERNAMEFORBIDDEN:
|
||||
Client_CreateAccountFail(USERNAMEFORBIDDEN);
|
||||
break;
|
||||
case ERRORSECURE_USERNAMERESERVED:
|
||||
Client_CreateAccountFail(USERNAMERESERVED);
|
||||
break;
|
||||
case ERRORSECURE_PASSWORDMALFORMED:
|
||||
Client_CreateAccountFail(PASSWORDMALFORMED);
|
||||
break;
|
||||
case ERRORSECURE_PASSWORDFORBIDDEN:
|
||||
Client_CreateAccountFail(PASSWORDFORBIDDEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::ModifyAccountCB(GSubyte ucType, GSint iReason)
|
||||
{
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RequestMOTDCB(GSubyte ubType, GSchar *szUbiMOTD, GSchar *szGameMOTD, GSint iReason)
|
||||
{
|
||||
if (ubType == GSSUCCESS)
|
||||
m_pScriptObject->Client_MOTD(szUbiMOTD,szGameMOTD);
|
||||
}
|
||||
|
||||
void NewUbisoftClient::MSClientDisconnected()
|
||||
{
|
||||
// was this a requested disconnect ?
|
||||
if (m_eClientState != NoUbiClient)
|
||||
{
|
||||
m_eClientState = ClientDisconnected;
|
||||
}
|
||||
m_dwNextClientAbsTime = m_pScriptObject->GetAbsTimeInSeconds() + g_dwKeepalifeLoginClient;
|
||||
}
|
||||
|
||||
#else // NOT_USE_UBICOM_SDK
|
||||
|
||||
// the following libs are excluded from the build in the project settings and here they are included
|
||||
// because only if we don't use UBI.com we need them
|
||||
#ifdef _DEBUG
|
||||
#pragma comment(lib,"libcmtd.lib")
|
||||
#else
|
||||
#pragma comment(lib,"libcmt.lib")
|
||||
#endif
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
286
CryNetwork/NewUbisoftRegServer.cpp
Normal file
286
CryNetwork/NewUbisoftRegServer.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
#include "NewUbisoftClient.h"
|
||||
#include "LobbyDefines.h"
|
||||
#include "CommonDefines.h"
|
||||
#include "IConsole.h" // ICVar
|
||||
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#include "ScriptObjectNewUbisoftClient.h" // CScriptObjectNewUbisoftClient
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char GUESTUSERNAME[33]="Ubi_Guest";
|
||||
static const char GUESTPASSWORD[17]="testtest";
|
||||
|
||||
static DWORD g_dwKeepalifeCreateServer=60; // in seconds
|
||||
|
||||
|
||||
bool NewUbisoftClient::Server_CreateServer( const char* szServerName,unsigned int uiMaxPlayer )
|
||||
{
|
||||
// m_pLog->Log("Ubi.com: DEBUG NewUbisoftClient::Server_CreateServer() 1");
|
||||
|
||||
// The server should check cdkeys
|
||||
if ((m_eServerState == CreatingServer) || (m_eServerState == ServerConnected))
|
||||
return false;
|
||||
m_eServerState = ServerDisconnected;
|
||||
|
||||
// m_pLog->Log("Ubi.com: DEBUG NewUbisoftClient::Server_CreateServer() 2");
|
||||
|
||||
if (!DownloadGSini(GUESTUSERNAME))
|
||||
return false;
|
||||
|
||||
// m_pLog->Log("Ubi.com: DEBUG NewUbisoftClient::Server_CreateServer() 3");
|
||||
|
||||
m_dwNextServerAbsTime = 0;
|
||||
m_strGameServerName = szServerName;
|
||||
m_uiMaxPlayers = uiMaxPlayer;
|
||||
|
||||
if (m_strGameServerName.size() > 32)
|
||||
{
|
||||
m_strGameServerName.resize(29);
|
||||
m_strGameServerName += "...";
|
||||
}
|
||||
|
||||
return Server_RecreateServer();
|
||||
}
|
||||
|
||||
void NewUbisoftClient::Server_SetGamePort( unsigned short usGamePort )
|
||||
{
|
||||
m_usGamePort = usGamePort;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Server_RecreateServer()
|
||||
{
|
||||
// Only recreate the server if were disconnected
|
||||
if (m_eServerState != ServerDisconnected)
|
||||
return false;
|
||||
|
||||
// Wait untill it's time to reconnect
|
||||
if(m_dwNextServerAbsTime)
|
||||
if(m_pScriptObject->GetAbsTimeInSeconds() < m_dwNextServerAbsTime)
|
||||
return false;
|
||||
|
||||
IServer *pServer = m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort);
|
||||
|
||||
// if this is a lan server
|
||||
if(pServer && pServer->GetServerType()==eMPST_LAN)
|
||||
return false;
|
||||
|
||||
// m_pLog->Log("Ubi.com: DEBUG Server_RecreateServer() 3");
|
||||
|
||||
m_pLog->Log("\001Ubi.com: Server_RecreateServer");
|
||||
|
||||
m_dwNextServerAbsTime = 0;
|
||||
m_eServerState = CreatingServer;
|
||||
|
||||
// Go through numbered IP and Ports in the ini
|
||||
char szIPAddress[50];
|
||||
unsigned short usClientPort,usRegServerPort;
|
||||
int iIndex = 0;
|
||||
|
||||
if (GetRouterAddress(iIndex,szIPAddress,&usClientPort,&usRegServerPort))
|
||||
{
|
||||
while (CRegisterServer::RegServerSend_RouterConnect(szIPAddress, usRegServerPort) == GS_FALSE)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: RegServerSend_RouterConnect '%s:%d' failed",szIPAddress,(int)usRegServerPort);
|
||||
iIndex++;
|
||||
if (!GetRouterAddress(iIndex,szIPAddress,&usClientPort,&usRegServerPort))
|
||||
{
|
||||
RegServerDisconnected();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRegisterServer::RegServerSend_LoginRouter(GUESTUSERNAME,GUESTPASSWORD,UBISOFT_GAME_VERSION);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Server_UpdateServer(unsigned int uiMaxPlayers, unsigned short usPort)
|
||||
{
|
||||
if (RegServerSend_UpdateGroupSettings(m_iServerRoomID,-1,-1,-1,uiMaxPlayers,-1,NULL,NULL,-1,NULL,-1,NULL,-1,usPort))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewUbisoftClient::Server_DestroyServer()
|
||||
{
|
||||
IServer *pServer = m_pSystem->GetINetwork()->GetServerByPort(m_usGamePort);
|
||||
|
||||
if(!pServer)
|
||||
return false;
|
||||
|
||||
// If the server type isn't UBI then do nothing
|
||||
if(pServer->GetServerType()!=eMPST_UBI)
|
||||
return false;
|
||||
|
||||
//We no longer want to run a ubi.com server
|
||||
m_eServerState = NoUbiServer;
|
||||
m_dwNextServerAbsTime = 0;
|
||||
// The server stop checking cdkeys
|
||||
RegServerSend_RouterDisconnect();
|
||||
RegServerSend_LobbyServerClose();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Sleep(100);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
m_eServerState = NoUbiServer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The Server callbacks
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LoginRouterResult( GSubyte ucType, GSint lReason,
|
||||
const GSchar* szIPAddress )
|
||||
{
|
||||
if (ucType == GSFAIL)
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: LoginRouterResult failed");
|
||||
Server_RegisterServerFail();
|
||||
RegServerDisconnected();
|
||||
return;
|
||||
}
|
||||
|
||||
CRegisterServer::RegServerSend_RequestParentGroupOnLobby(GAME_NAME);
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_RouterDisconnection()
|
||||
{
|
||||
//Server_RouterDisconnected();
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_RegisterServerResult( GSubyte ucType,GSint plReason,GSint iGroupID,
|
||||
const GSchar* szAddress,GSushort usPort,const GSchar* szSessionName )
|
||||
{
|
||||
if (ucType == GSSUCCESS)
|
||||
{
|
||||
int iPort = sv_regserver_port->GetIVal();
|
||||
|
||||
if (!RegServerSend_LobbyServerConnection(szAddress, usPort,iPort,10))
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: LobbyServerConnection failed %s %i",szAddress,usPort);
|
||||
RegServerDisconnected();
|
||||
Server_RegisterServerFail();
|
||||
return;
|
||||
}
|
||||
|
||||
RegServerSend_LobbyServerLogin(GUESTUSERNAME,iGroupID);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: RegisterServerResult failed");
|
||||
RegServerDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_RequestParentGroupResult( GSubyte ucType,
|
||||
GSint lReason, GSint iServerID,GSint iGroupID, const GSchar* szGroupName,
|
||||
GSuint uiNbPlayers, GSuint uiMaxPlayers )
|
||||
{
|
||||
if (ucType == GSSUCCESS)
|
||||
{
|
||||
// if the server id less them or equal to 0 then we have finished receiving the list of Parent Groups
|
||||
if (iServerID <=0)
|
||||
{
|
||||
GSchar szData[100];
|
||||
|
||||
_snprintf(szData,100,"%i",m_usGamePort);
|
||||
|
||||
m_pLog->Log("\001Ubi.com: RequestParentGroupResult success");
|
||||
// We will let the library pick the best parent group to register on.
|
||||
CRegisterServer::RegServerSend_RegisterServerOnLobby(0,0,m_strGameServerName.c_str(),
|
||||
GAME_NAME,ROOM_UBI_CLIENTHOST_REGSERVER,m_uiMaxPlayers,0,"",szData,sizeof(szData),NULL,0,NULL,0,
|
||||
m_usGamePort,"",GSGAMEVERSION,GS_FALSE,GS_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LobbyServerLoginResults( GSubyte ucType,
|
||||
GSint iReason, GSint iLobbyServerID, GSint iGroupID )
|
||||
{
|
||||
if (ucType == GSSUCCESS)
|
||||
{
|
||||
RegServerSend_RouterDisconnect();
|
||||
m_iServerLobbyID = iLobbyServerID;
|
||||
m_iServerRoomID = iGroupID;
|
||||
m_pLog->Log("\001Ubi.com Game Server Register Success");
|
||||
m_eServerState = ServerConnected;
|
||||
if (m_eClientState != NoUbiClient)
|
||||
{
|
||||
m_iJoinedLobbyID = iLobbyServerID;
|
||||
m_iJoinedRoomID = iGroupID;
|
||||
}
|
||||
Server_RegisterServerSuccess(iLobbyServerID, iGroupID);
|
||||
}
|
||||
else
|
||||
{
|
||||
RegServerDisconnected();
|
||||
m_pLog->Log("\001Ubi.com Game Server Register Failed");
|
||||
Server_RegisterServerFail();
|
||||
}
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LobbyServerUpdateGroupSettingsResults(
|
||||
GSubyte ucType, GSint iReason, GSint iGroupID )
|
||||
{
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LobbyServerDisconnection()
|
||||
{
|
||||
RegServerDisconnected();
|
||||
Server_LobbyServerDisconnected();
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LobbyServerMemberNew( const GSchar* szMember,GSbool bSpectator,
|
||||
const GSchar* szIPAddress, const GSchar* szAltIPAddress,
|
||||
const GSvoid* pPlayerInfo, GSuint uiPlayerInfoSize,GSushort usPlayerStatus )
|
||||
{
|
||||
Server_PlayerJoin(szMember);
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LobbyServerMemberLeft(const GSchar* szMember )
|
||||
{
|
||||
Server_PlayerLeave(szMember);
|
||||
}
|
||||
|
||||
GSvoid NewUbisoftClient::RegServerRcv_LobbyServerNewGroup (GSushort usRoomType,
|
||||
const GSchar* szRoomName,GSint iGroupID,GSint iLobbyServerID,GSint iParentGroupID,
|
||||
GSint uiGroupConfig,GSshort sGroupLevel,const GSchar* szMaster,const GSchar* szAllowedGames,
|
||||
const GSchar* szGame,const GSvoid* pGroupInfo,GSuint GroupInfoSize,GSuint uiMatchEventID,
|
||||
GSuint uiMaxPlayers,GSuint uiNbPlayers,GSuint uiMaxSpectators,GSuint uiNbSpectators,
|
||||
const GSchar* szGameVersion,const GSchar* szGSGameVersion,const GSchar* szIPAddress,
|
||||
const GSchar* szAltIPAddress )
|
||||
{
|
||||
}
|
||||
|
||||
void NewUbisoftClient::RegServerDisconnected()
|
||||
{
|
||||
m_pLog->Log("\001Ubi.com: RegServerDisconnected");
|
||||
m_eServerState = ServerDisconnected;
|
||||
m_dwNextServerAbsTime = m_pScriptObject->GetAbsTimeInSeconds() + g_dwKeepalifeCreateServer;
|
||||
}
|
||||
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
100
CryNetwork/PingCalculator.h
Normal file
100
CryNetwork/PingCalculator.h
Normal file
@@ -0,0 +1,100 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Game Source Code
|
||||
//
|
||||
// File: PingCalculator.h
|
||||
// Description: Latency(Ping) calculator
|
||||
//
|
||||
// History:
|
||||
// - August 10, 2001: Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef _PING_CALCULATOR_H_
|
||||
#define _PING_CALCULATOR_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#define NUM_OF_SAMPLES 10
|
||||
#define DIV_MULTIPLIER (1.0/NUM_OF_SAMPLES)
|
||||
#define INC_INDEX(a) (a) = ((++a)%NUM_OF_SAMPLES)
|
||||
#define PING_RATE 500
|
||||
|
||||
class CPingCalculator
|
||||
{
|
||||
public:
|
||||
CPingCalculator()
|
||||
{
|
||||
m_nSampleIndex = 0;
|
||||
m_nLastSample = 0;
|
||||
m_bSyncronized = false;
|
||||
m_nRemoteTimestamp = 0;
|
||||
memset(m_fSample, 0, sizeof(m_fSample));
|
||||
m_fPing=100;
|
||||
}
|
||||
float GetAverageLatency()
|
||||
{
|
||||
float fSum = 0;
|
||||
|
||||
// return (fSum*(DIV_MULTIPLIER));
|
||||
return m_fPing;
|
||||
}
|
||||
bool IsTimeToPing(unsigned int nCurrentTime)
|
||||
{
|
||||
if ((nCurrentTime - m_nLastSample)>PING_RATE)
|
||||
{
|
||||
m_nLastSample = nCurrentTime;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void AddSample(float f,unsigned int nLocalTimestamp,unsigned int nRemoteTimestamp)
|
||||
{
|
||||
float fSum = 0;
|
||||
float fTemp[NUM_OF_SAMPLES];
|
||||
|
||||
m_fSample[m_nSampleIndex] = f*0.5f;
|
||||
memcpy(fTemp, m_fSample, sizeof(fTemp));
|
||||
qsort(fTemp, NUM_OF_SAMPLES, sizeof(float), CPingCalculator::Compare);
|
||||
|
||||
m_fPing = fTemp[NUM_OF_SAMPLES/2];
|
||||
|
||||
INC_INDEX(m_nSampleIndex);
|
||||
NET_TRACE("PING %04d\n", LONG(m_fPing));
|
||||
m_nRemoteTimestamp=(unsigned int)(nRemoteTimestamp-m_fPing);
|
||||
m_nLocalTimestamp=nLocalTimestamp;
|
||||
}
|
||||
unsigned int GetCurrentRemoteTimestamp(unsigned int nLocalTimestamp){
|
||||
unsigned int nCurrentDelta=m_nLocalTimestamp-nLocalTimestamp;
|
||||
return m_nRemoteTimestamp+nCurrentDelta;
|
||||
}
|
||||
unsigned int GetPacketLatency(unsigned int nLocalTimestamp,unsigned int nPacketTimestamp){
|
||||
unsigned int nRemote=GetCurrentRemoteTimestamp(nLocalTimestamp);
|
||||
return nPacketTimestamp-nRemote;
|
||||
}
|
||||
static int __cdecl Compare(const void *arg1, const void *arg2)
|
||||
{
|
||||
float f = ((*(float *)arg1 - (*(float *)arg2)));
|
||||
if (f>0)
|
||||
return 1; // greater
|
||||
if (f < 0)
|
||||
return -1; // less
|
||||
return 0; // equel
|
||||
}
|
||||
private:
|
||||
float m_fSample[NUM_OF_SAMPLES];
|
||||
//! middle value of all samples
|
||||
float m_fPing;
|
||||
unsigned int m_nSampleIndex;
|
||||
unsigned int m_nLastSample;
|
||||
bool m_bSyncronized;
|
||||
//! average remote timestamp
|
||||
unsigned int m_nRemoteTimestamp;
|
||||
//! local timestamp
|
||||
unsigned int m_nLocalTimestamp;
|
||||
};
|
||||
|
||||
#endif // _PING_CALCULATOR_H_
|
||||
931
CryNetwork/PunkBusterInterface.cpp
Normal file
931
CryNetwork/PunkBusterInterface.cpp
Normal file
@@ -0,0 +1,931 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001-2004.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: PunkBusterInterface.cpp
|
||||
// Version: v1.00
|
||||
// Created: 1/3/2004 by Timur.
|
||||
// Compilers: Visual Studio.NET 2003
|
||||
// Description: Interface to the PunkBuster from CryEngine.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
|
||||
#include "PunkBusterInterface.h"
|
||||
#define PbSdk_DEFINED
|
||||
#include "../PunkBuster/pbsdk.h"
|
||||
#include "../PunkBuster/pbmd5.h"
|
||||
|
||||
#include "Network.h"
|
||||
#include "IRenderer.h"
|
||||
#include "ServerSlot.h"
|
||||
#include "Server.h"
|
||||
#include "Client.h"
|
||||
#include "ClientLocal.h"
|
||||
#include "ICryPak.h"
|
||||
|
||||
static const char RegistryKeyName[] = "SOFTWARE\\Crytek\\FarCry";
|
||||
static const char CDKEYREGKEY[] = "CDKey";
|
||||
|
||||
void PBcomputeHash ( char *idhash , CServerSlot *pSlot ) ;//defined in this source file after class definitions
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CPunkBusterInterface::CPunkBusterInterface( CNetwork *pNetwork )
|
||||
{
|
||||
m_bSinglePlayer = false ;
|
||||
m_bClInitialized = false;
|
||||
m_bSvInitialized = false;
|
||||
m_pNetwork = pNetwork;
|
||||
m_pSystem = pNetwork->GetSystem();
|
||||
m_pClient = 0;
|
||||
m_pClientLocal = 0;
|
||||
m_pServer = 0;
|
||||
sys_punkbuster_loaded = 0;
|
||||
|
||||
cl_punkbuster = m_pSystem->GetIConsole()->CreateVariable( "cl_punkbuster","0",VF_DUMPTODISK,"Enables PunkBuster for client, 1=Enabled,0=Disabled" );
|
||||
sv_punkbuster = m_pSystem->GetIConsole()->CreateVariable( "sv_punkbuster","0",VF_DUMPTODISK,"Enables PunkBuster for server, 1=Enabled,0=Disabled" );
|
||||
fs_homepath = m_pSystem->GetIConsole()->CreateVariable( "fs_homepath","",VF_DUMPTODISK,"Specifies alternate PunkBuster 'home' (if non-empty)" );
|
||||
|
||||
// Start recieving OnBeforeVarChange events.
|
||||
m_pSystem->GetIConsole()->AddConsoleVarSink(this);
|
||||
m_pSystem->GetIConsole()->AddOutputPrintSink(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CPunkBusterInterface::~CPunkBusterInterface()
|
||||
{
|
||||
if ( sys_punkbuster_loaded ) {
|
||||
SAFE_RELEASE(sys_punkbuster_loaded);
|
||||
sys_punkbuster_loaded = 0 ;
|
||||
}
|
||||
m_pSystem->GetIConsole()->RemoveOutputPrintSink(this);
|
||||
m_pSystem->GetIConsole()->RemoveConsoleVarSink(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::Init( bool bClient , bool isLocalServer )
|
||||
{
|
||||
if ( bClient == false ) {
|
||||
m_bSinglePlayer = !isLocalServer ;
|
||||
if ( m_bSinglePlayer == true ) {
|
||||
ShutDown ( false ) ;
|
||||
return ;
|
||||
}
|
||||
} else if ( m_bSinglePlayer ) return ;
|
||||
|
||||
if ( !sys_punkbuster_loaded ) {
|
||||
sys_punkbuster_loaded = m_pSystem->GetIConsole()->CreateVariable( "sys_punkbuster_loaded","1",NULL);
|
||||
}
|
||||
|
||||
if ( bClient ) {
|
||||
if ( m_bClInitialized ) return ;
|
||||
PbClientInitialize ( this ) ;
|
||||
m_bClInitialized = true;
|
||||
} else {
|
||||
if ( m_bSvInitialized ) return ;
|
||||
PbServerInitialize() ;
|
||||
m_bSvInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::SetServer( CServer *pServer )
|
||||
{
|
||||
m_pServer = pServer;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::SetClient( CClient *pClient )
|
||||
{
|
||||
m_pClient = pClient;
|
||||
m_pClientLocal = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::SetClientLocal( CClientLocal *pClient )
|
||||
{
|
||||
m_pClientLocal = pClient;
|
||||
m_pClient = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::LockCVars()
|
||||
{
|
||||
cl_punkbuster->SetFlags( cl_punkbuster->GetFlags() | VF_READONLY );
|
||||
sv_punkbuster->SetFlags( sv_punkbuster->GetFlags() | VF_READONLY );
|
||||
fs_homepath->SetFlags( fs_homepath->GetFlags() | VF_READONLY );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::UnlockCVars()
|
||||
{
|
||||
cl_punkbuster->SetFlags( cl_punkbuster->GetFlags() & ~VF_READONLY );
|
||||
sv_punkbuster->SetFlags( sv_punkbuster->GetFlags() & ~VF_READONLY );
|
||||
fs_homepath->SetFlags( fs_homepath->GetFlags() & ~VF_READONLY );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::ShutDown( bool bClient )
|
||||
{
|
||||
// m_bInitialized = false;
|
||||
if ( sys_punkbuster_loaded ) {
|
||||
SAFE_RELEASE(sys_punkbuster_loaded);
|
||||
sys_punkbuster_loaded = 0 ;
|
||||
}
|
||||
|
||||
if (bClient)
|
||||
{
|
||||
m_pClientLocal = 0;
|
||||
m_pClient = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pServer = 0;
|
||||
}
|
||||
|
||||
UnlockCVars();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::Update( bool bClient )
|
||||
{
|
||||
if ( !sys_punkbuster_loaded ) return ;//no PB processing when PB has been shut down or is not yet initialized
|
||||
|
||||
if ( bClient) {
|
||||
if (!m_bClInitialized) return;
|
||||
PbClientProcessEvents() ;
|
||||
} else {
|
||||
if (!m_bSvInitialized) return;
|
||||
PbServerProcessEvents() ;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPunkBusterInterface::OnBeforeVarChange( ICVar *pVar,const char *sNewValue )
|
||||
{
|
||||
// if (!m_bInitialized)
|
||||
// return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::Print( const char *inszText )
|
||||
{
|
||||
PbCaptureConsoleOutput ( (char *) inszText , strlen ( inszText ) ) ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPunkBusterInterface::LoadCDKey( string &sCDKey )
|
||||
{
|
||||
if (ReadStringFromRegistry("Ubi.com", CDKEYREGKEY, sCDKey))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CPunkBusterInterface::ReadStringFromRegistry(const string &szKeyName, const string &szValueName, string &szValue)
|
||||
{
|
||||
#ifdef WIN32
|
||||
HKEY hKey;
|
||||
|
||||
string szREGKeyName = string(RegistryKeyName) + string("\\") + szKeyName;
|
||||
if (RegOpenKey(HKEY_LOCAL_MACHINE, szREGKeyName.c_str(), &hKey) != ERROR_SUCCESS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DWORD dwSize = 0;
|
||||
if (RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, 0, &dwSize) != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return false;
|
||||
}
|
||||
szValue.resize(dwSize);
|
||||
RegQueryValueEx(hKey, szValueName.c_str(), 0, 0, (LPBYTE)szValue.c_str(), &dwSize);
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::OnAddClient( CIPAddress &clientIP )
|
||||
{
|
||||
// Must have server by this point.
|
||||
// assert( m_pServer );
|
||||
if ( !m_pServer ) return ;//happens in single-player mode
|
||||
|
||||
//at this point in the process, just add the client address and idhash, see PBgetClientInfo() later in this source file
|
||||
char addr[32] ;
|
||||
strncpy ( addr , clientIP.GetAsString(true) , 31 ) ;
|
||||
addr[31] = 0 ;
|
||||
if ( clientIP.IsLocalHost() ) strcpy ( addr , "localhost" ) ;
|
||||
|
||||
// if ( !strcmp ( addr , "127.0.0.1:0" ) ) strcpy ( addr , "localhost" ) ;
|
||||
|
||||
char idhash[PB_GUIDLEN+1] = "" ;
|
||||
CServerSlot *pSlot = m_pServer->GetPacketOwner( clientIP );
|
||||
if (pSlot)
|
||||
{
|
||||
PBcomputeHash ( idhash , pSlot ) ;
|
||||
} else {
|
||||
strcpy ( idhash , "" ) ;
|
||||
}
|
||||
PbSvAddClient ( addr , "" , idhash ) ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::OnDisconnectClient( CIPAddress &clientIP )
|
||||
{
|
||||
char addr[32] ;
|
||||
strncpy ( addr , clientIP.GetAsString(true) , 31 ) ;
|
||||
addr[31] = 0 ;
|
||||
if ( !strcmp ( addr , "127.0.0.1:0" ) ) strcpy ( addr , "localhost" ) ;
|
||||
|
||||
PbSvRemoveClient ( addr ) ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::CheaterFound( CIPAddress &clientIP,int type,const char *sMsg )
|
||||
{
|
||||
if (m_pServer && m_pServer->GetSecuritySink())
|
||||
{
|
||||
m_pServer->GetSecuritySink()->CheaterFound( clientIP.GetAsUINT(),type,sMsg );
|
||||
}
|
||||
}
|
||||
|
||||
bool CPunkBusterInterface::CheckPBPacket(CStream &stmPacket,CIPAddress &ip)
|
||||
{
|
||||
int len = stmPacket.GetSize() >> 3 ;//convert bits to bytes
|
||||
if ( len >= 7) // Must be at least 7 bytes int.
|
||||
{
|
||||
BYTE *pBuf = stmPacket.GetPtr();
|
||||
if ( !memcmp ( pBuf , "\xff\xff\xff\xffPB_" , 7 ) ) {
|
||||
//if not ded
|
||||
if ( pBuf[7] != 'S' && pBuf[7] != '2' && pBuf[7] != 'G' && pBuf[7] != 'I'
|
||||
&& pBuf[7] != 'Y' && pBuf[7] != 'B' && pBuf[7] != 'L' )
|
||||
PbClAddEvent ( PB_EV_PACKET , len - 4 , (char *) pBuf + 4 ) ;
|
||||
//
|
||||
if ( pBuf[7] != 'C' && pBuf[7] != '1' && pBuf[7] != 'J' )
|
||||
PbSvAddEvent ( PB_EV_PACKET , -1 , len - 4 , (char *) pBuf + 4 ) ;
|
||||
return false ;//yes pb packet
|
||||
}
|
||||
}
|
||||
return true;//not a pb packet
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::ValidateClient( CServerSlot *pSlot )
|
||||
{
|
||||
//this function is called as client is trying to connect before level load
|
||||
//if PB is enabled at this server, it checks to see if the PB client is enabled for the player
|
||||
// and checks for any ban issues with the id/hash
|
||||
unsigned int nFlags = pSlot->GetClientFlags();
|
||||
char idhash[PB_GUIDLEN+1] = "" , addr[32] = "" ;
|
||||
strncpy ( addr , pSlot->GetIP().GetAsString(true) , 31 ) ;
|
||||
addr[31] = 0 ;
|
||||
PBcomputeHash ( idhash , pSlot ) ;
|
||||
char *res = PbAuthClient ( addr , nFlags & CLIENT_FLAGS_PUNK_BUSTER , idhash ) ;
|
||||
if ( res != NULL ) pSlot->Disconnect ( res ) ;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::OnCCPPunkBusterMsg( CIPAddress &ipAddress,CStream &stm )
|
||||
{
|
||||
if ( m_pClient || m_pClientLocal )
|
||||
{
|
||||
BYTE *pByte = stm.GetPtr() ;
|
||||
PbClAddEvent ( PB_EV_PACKET , stm.GetSize() >> 3 , (char *) pByte ) ;//convert bits to bytes
|
||||
}
|
||||
if ( m_pServer )
|
||||
{
|
||||
int i = 0 ;
|
||||
char *addr = ipAddress.GetAsString(true);
|
||||
for ( i = 0 ; i < PB_MAX_CLIENTS ; i++ ) if ( !strcmp ( addr , pbsdk->pbsv.m_client[i].pbc.ip ) ) break ;
|
||||
if ( i < PB_MAX_CLIENTS ) {
|
||||
BYTE *pByte = stm.GetPtr() ;
|
||||
PbSvAddEvent ( PB_EV_PACKET , i , stm.GetSize() >> 3 , (char *) pByte ) ;//convert bits to bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::SendMsgToClient( CIPAddress &clientIP,CStream &stm )
|
||||
{
|
||||
if (m_pServer)
|
||||
{
|
||||
CServerSlot *pSlot = m_pServer->GetPacketOwner(clientIP);
|
||||
if (pSlot)
|
||||
{
|
||||
pSlot->SendPunkBusterMsg(stm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CPunkBusterInterface::SendMsgToServer( CStream &stm )
|
||||
{
|
||||
if (m_pClient)//don't check for local here because those packets are handled internally by PB
|
||||
{
|
||||
m_pClient->SendPunkBusterMsg( stm );
|
||||
}
|
||||
}
|
||||
|
||||
//below added by TR as "glue" functions
|
||||
//
|
||||
// PBoutgame
|
||||
//
|
||||
void PBoutgame ( char *text , int hudAlso )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
char *te = text , hold = 0 ;
|
||||
for(;;) { //loop in case of multiple lines (to simulate linefeeds)
|
||||
char *cp = strstr ( te , "\n" ) ;
|
||||
if ( cp != NULL ) { //linefeed found so hold end-char and terminate
|
||||
hold = *cp ;
|
||||
*cp = 0 ;
|
||||
} else hold = 0 ; //signifies end of line
|
||||
|
||||
int wrapat = 89 ;
|
||||
if ( *te ) { //ignore empty lines
|
||||
char *wrp = te ;
|
||||
while ( *wrp ) {
|
||||
char hold = 0 ;
|
||||
if ( strlen ( wrp ) > wrapat ) {
|
||||
hold = wrp[wrapat] ;
|
||||
wrp[wrapat] = 0 ;
|
||||
}
|
||||
pip->m_pSystem->GetIConsole()->PrintLine ( wrp ) ; //output to console
|
||||
if ( !hold ) break ;
|
||||
wrp[wrapat] = hold ;
|
||||
wrp += wrapat ;
|
||||
}
|
||||
|
||||
if ( hudAlso ) { //optionally output to screen
|
||||
if ( !pip->m_pSystem->IsDedicated() ) {
|
||||
char buf[101] ;
|
||||
char finalbuf[201] ;
|
||||
|
||||
strncpy( buf,te,sizeof(buf)-1 );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
for (int i = 0; i < strlen(buf); i++)
|
||||
{
|
||||
if (buf[i] == '\\')
|
||||
buf[i] = '/';
|
||||
if (buf[i] == '"')
|
||||
buf[i] = '\'';
|
||||
}
|
||||
_snprintf ( finalbuf , sizeof(finalbuf)-1 , "#if (Hud) then Hud:AddMessage( \"%s\" ); end" , buf ) ;
|
||||
pip->m_pSystem->GetIConsole()->ExecuteString( finalbuf,true,true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !hold ) break ; //if end of line, then break out of loop
|
||||
*cp = hold ;
|
||||
te = cp + 1 ;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PBsendPktToServer
|
||||
//
|
||||
void PBsendPktToServer ( int datalen , char *data )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
CStream stm;
|
||||
stm.SetBits( (BYTE *) data , 0 , datalen * 8 );
|
||||
stm.SetSize( datalen * 8 ) ;
|
||||
pip->SendMsgToServer ( stm ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Sys_PBSendUdpPacket
|
||||
//
|
||||
void Sys_PBSendUdpPacket ( char *addr , unsigned short port , int datalen , char *data , int isFromClient )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
CStream stm;
|
||||
stm.SetBits( (BYTE *) data , 0 , datalen * 8 );
|
||||
stm.SetSize( datalen * 8 ) ;
|
||||
CIPAddress cip ( port , addr ) ;
|
||||
|
||||
if ( isFromClient ) { //from client
|
||||
if ( pip->m_pClient != NULL ) pip->m_pClient->SendTo ( cip , stm ) ;//no need to check for local due to PB's internal handling
|
||||
} else { //from server
|
||||
if ( pip->m_pServer != NULL ) pip->m_pServer->Send ( stm , cip ) ;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PBsendPktToClient
|
||||
//
|
||||
void PBsendPktToClient ( int datalen , char *data , char *addr )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
CStream stm;
|
||||
stm.SetBits( (BYTE *) data , 0 , datalen * 8 );
|
||||
stm.SetSize( datalen * 8 ) ;
|
||||
char ip[32] ;
|
||||
unsigned short port = 0 ;
|
||||
strncpy ( ip , addr , 31 ) ;
|
||||
ip[31] = 0 ;
|
||||
char *cp = strstr ( ip , ":" ) ;
|
||||
if ( cp != NULL ) {
|
||||
*cp = 0 ;
|
||||
port = atoi ( cp + 1 ) ;
|
||||
}
|
||||
CIPAddress cip ( port , ip ) ;
|
||||
pip->SendMsgToClient ( cip , stm ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBisLocalServer
|
||||
//
|
||||
int PBisLocalServer ( void )
|
||||
{
|
||||
if ( pbsdk == NULL ) return 1 ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return 1 ;
|
||||
|
||||
if ( pip->m_pClient == NULL ) return 1 ;
|
||||
CIPAddress ca = pip->m_pClient->GetServerIP() ;
|
||||
return ca.IsLocalHost() ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBgetHomePath
|
||||
//
|
||||
void PBgetHomePath ( char *path , int maxlen )
|
||||
{
|
||||
*path = 0 ;
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
strncpy ( path , pip->fs_homepath->GetString() , maxlen - 1 ) ;
|
||||
path[maxlen-1] = 0 ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBgetClientInfo
|
||||
//
|
||||
int PBgetClientInfo ( stPb_Sv_Client *c )
|
||||
{
|
||||
if ( pbsdk == NULL ) return 0 ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return 0 ;
|
||||
|
||||
if ( pip->m_pServer == NULL ) return 0 ;
|
||||
|
||||
char ip[32] ;
|
||||
unsigned short port = 0 ;
|
||||
strncpy ( ip , c->ip , 31 ) ;
|
||||
ip[31] = 0 ;
|
||||
char *cp = strstr ( ip , ":" ) ;
|
||||
if ( cp != NULL ) {
|
||||
*cp = 0 ;
|
||||
port = atoi ( cp + 1 ) ;
|
||||
}
|
||||
CIPAddress clientIP ( port , ip ) ;
|
||||
|
||||
IServerSecuritySink::SSlotInfo playerInfo;
|
||||
memset ( &playerInfo , 0 , sizeof ( playerInfo ) ) ;
|
||||
pip->m_pServer->GetSecuritySink()->GetSlotInfo( clientIP.GetAsUINT(),playerInfo , 1 );
|
||||
if ( *playerInfo.playerName == 0 ) return 0 ; //player not set up yet
|
||||
|
||||
strncpy ( c->name , playerInfo.playerName , PB_NAMELEN ) ;
|
||||
c->name[PB_NAMELEN] = 0 ;
|
||||
|
||||
if ( *c->guid == 0 ) { //if the guid is empty, compute it from the hash
|
||||
char idhash[PB_GUIDLEN+1] = "" ;
|
||||
CServerSlot *pSlot = pip->m_pServer->GetPacketOwner( clientIP );
|
||||
if (pSlot) {
|
||||
PBcomputeHash ( idhash , pSlot ) ;
|
||||
strcpy ( c->guid , idhash ) ;
|
||||
}
|
||||
}
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBgetStats
|
||||
//
|
||||
int PBgetStats ( int index , char *Data )
|
||||
{
|
||||
if ( pbsdk == NULL ) return 0 ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return 0 ;
|
||||
|
||||
if ( pip->m_pServer == NULL ) return 0 ;
|
||||
|
||||
char ip[32] ;
|
||||
unsigned short port = 0 ;
|
||||
strncpy ( ip , pbsdk->pbsv.m_client[index].pbc.ip , 31 ) ;
|
||||
ip[31] = 0 ;
|
||||
char *cp = strstr ( ip , ":" ) ;
|
||||
if ( cp != NULL ) {
|
||||
*cp = 0 ;
|
||||
port = atoi ( cp + 1 ) ;
|
||||
}
|
||||
CIPAddress clientIP ( port , ip ) ;
|
||||
|
||||
IServerSecuritySink::SSlotInfo playerInfo;
|
||||
memset ( &playerInfo , 0 , sizeof ( playerInfo ) ) ;
|
||||
pip->m_pServer->GetSecuritySink()->GetSlotInfo( clientIP.GetAsUINT(),playerInfo , 0 ) ;
|
||||
if ( *playerInfo.playerName == 0 ) return 0 ;//player not set up yet
|
||||
|
||||
sprintf ( Data , "score=%d deaths=%d" , playerInfo.score , playerInfo.deaths ) ;
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBcomputeHash
|
||||
//
|
||||
void PBcomputeHash ( char *guid , CServerSlot *pSlot )
|
||||
{
|
||||
MD5_CTX mc ;
|
||||
if (pSlot->m_pbGlobalID)
|
||||
{
|
||||
MD5Init ( &mc ) ;
|
||||
MD5Update ( &mc , pSlot->m_pbGlobalID , pSlot->m_uiGlobalIDSize );
|
||||
MD5Final ( &mc ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(mc.digest,0,sizeof(mc.digest));
|
||||
}
|
||||
_snprintf ( guid , PB_GUIDLEN , "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" ,
|
||||
mc.digest[0] , mc.digest[1] , mc.digest[2] , mc.digest[3] , mc.digest[4] , mc.digest[5] , mc.digest[6] ,
|
||||
mc.digest[7] , mc.digest[8] , mc.digest[9] , mc.digest[10] , mc.digest[11] , mc.digest[12] , mc.digest[13] ,
|
||||
mc.digest[14] , mc.digest[15] ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBcvar_VariableString
|
||||
//
|
||||
char *PBcvar_VariableString ( const char *var_name )
|
||||
{
|
||||
if ( pbsdk == NULL ) return "ERROR: NULL POINTER" ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return "ERROR: NULL POINTER" ;
|
||||
|
||||
if ( pip->m_pSystem == NULL ) return "ERROR: NULL POINTER" ;
|
||||
|
||||
ICVar *cv = pip->m_pSystem->GetIConsole()->GetCVar(var_name);
|
||||
if ( cv == NULL ) return "" ;
|
||||
|
||||
return cv->GetString() ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBcvar_Set
|
||||
//
|
||||
void PBcvar_Set ( const char *cvar , const char *value )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
if ( pip->m_pSystem == NULL ) return ;
|
||||
|
||||
ICVar *cv = pip->m_pSystem->GetIConsole()->GetCVar(cvar);
|
||||
if ( cv == NULL ) return ;
|
||||
|
||||
cv->ForceSet ( value ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBcmd_execString
|
||||
//
|
||||
void PBcmd_execString ( const char *text )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
if ( pip->m_pSystem == NULL ) return ;
|
||||
pip->m_pSystem->GetIConsole()->ExecuteString( text,false,false);
|
||||
}
|
||||
|
||||
//
|
||||
// PBdropClient
|
||||
//
|
||||
void PBdropClient ( int clientIndex , char *reason )
|
||||
{
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
|
||||
if ( pip->m_pServer == NULL ) return ;
|
||||
|
||||
char ip[32] ;
|
||||
unsigned short port = 0 ;
|
||||
strncpy ( ip , pbsdk->pbsv.m_client[clientIndex].pbc.ip , 31 ) ;
|
||||
ip[31] = 0 ;
|
||||
char *cp = strstr ( ip , ":" ) ;
|
||||
if ( cp != NULL ) {
|
||||
*cp = 0 ;
|
||||
port = atoi ( cp + 1 ) ;
|
||||
}
|
||||
CIPAddress clientIP ( port , ip ) ;
|
||||
|
||||
CServerSlot *pSlot = pip->m_pServer->GetPacketOwner( clientIP );
|
||||
if (pSlot) pSlot->Disconnect ( reason ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBgameVer
|
||||
//
|
||||
char *PBgameVer ( void )
|
||||
{
|
||||
if ( pbsdk == NULL ) return "" ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return "" ;
|
||||
|
||||
//must return pointer to full game version info string
|
||||
static char buf[64] = "" ;
|
||||
pip->m_pSystem->GetFileVersion().ToString ( buf ) ;
|
||||
return buf ;
|
||||
}
|
||||
|
||||
//
|
||||
// isPBmultiplayerMode
|
||||
//
|
||||
int isPBmultiplayerMode ( void )
|
||||
{
|
||||
if ( pbsdk == NULL ) return 0 ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return 0 ;
|
||||
|
||||
if ( pip->m_pNetwork == NULL ) return 0 ;
|
||||
if ( pip->m_pServer == NULL && pip->m_pClient == NULL && pip->m_pClientLocal == NULL ) return 0 ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBserverIp
|
||||
//
|
||||
char *PBserverIp ( int bServer )
|
||||
{
|
||||
if ( pbsdk == NULL ) return "bot" ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return "bot" ;
|
||||
|
||||
static CIPAddress cip ;
|
||||
|
||||
if ( !bServer ) {
|
||||
if ( pip->m_pClient == NULL ) {
|
||||
if ( pip->m_pClientLocal == NULL ) return "bot" ;
|
||||
return "localhost" ;
|
||||
}
|
||||
cip = pip->m_pClient->GetServerIP() ;
|
||||
} else {
|
||||
if ( pip->m_pServer == NULL || pip->m_pNetwork == NULL ) return "???" ;
|
||||
cip.m_Address.ADDR = pip->m_pNetwork->GetLocalIP();
|
||||
cip.m_Address.sin_port = htons ( pip->m_pServer->GetServerPort() ) ;
|
||||
}
|
||||
return cip.GetAsString ( true ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBserverHostname
|
||||
//
|
||||
char *PBserverHostname ( void )
|
||||
{
|
||||
if ( pbsdk == NULL ) return "" ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return "" ;
|
||||
if ( pip->m_pServer == NULL ) return "" ;
|
||||
CIPAddress cip ;
|
||||
return (char *) pip->m_pServer->GetHostName() ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBkeyValue
|
||||
//
|
||||
const char *PBkeyValue ( char *notused , char *key )
|
||||
{
|
||||
notused;
|
||||
if ( pbsdk == NULL ) return "" ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return "" ;
|
||||
if ( pip->m_pSystem == NULL ) return "" ;
|
||||
|
||||
const char *newkey = key ;
|
||||
ICVar *cv ;
|
||||
|
||||
if ( !stricmp ( key , "gamename" ) ) {
|
||||
#ifdef GAME_IS_FARCRY
|
||||
newkey = GetIXGame( pip->m_pSystem->GetIGame() )->IsMODLoaded() ;
|
||||
#else
|
||||
newkey = NULL;
|
||||
#endif
|
||||
if ( newkey == NULL ) return "FarCry" ;
|
||||
else return newkey ;
|
||||
} else if ( !stricmp ( key , "mapname" ) ) {
|
||||
newkey = "g_levelName" ;
|
||||
}/* else if ( !stricmp ( s , "sv_hostname" ) ) {
|
||||
}*/
|
||||
|
||||
cv = pip->m_pSystem->GetIConsole()->GetCVar( newkey ) ;
|
||||
if ( cv == NULL ) return "" ;
|
||||
|
||||
return cv->GetString() ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBqueryGL
|
||||
//
|
||||
char *PBqueryGL ( int type )
|
||||
{
|
||||
if ( pbsdk == NULL ) return "" ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return "" ;
|
||||
|
||||
// pip->m_pSystem->GetIRenderer()->GetColorBpp() ;
|
||||
switch ( type ) {
|
||||
case PB_GL_READPIXELS: //(char *) qglReadPixels ;//function pointer
|
||||
return (char *) pip->m_pSystem->GetIRenderer()->EF_Query(EFQ_glReadPixels);
|
||||
case PB_GL_WIDTH:
|
||||
return (char *) pip->m_pSystem->GetIRenderer()->GetWidth() ;
|
||||
case PB_GL_HEIGHT:
|
||||
return (char *) pip->m_pSystem->GetIRenderer()->GetHeight() ;
|
||||
case PB_GL_RGB: return NULL ;//(char *) GL_RGB ;
|
||||
case PB_GL_UB: return NULL ;//(char *) GL_UNSIGNED_BYTE ;
|
||||
case PB_GL_D3DDEV:
|
||||
return (char *) pip->m_pSystem->GetIRenderer()->EF_Query(EFQ_D3DDevice);
|
||||
}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
class CCVarsDump : public ICVarDumpSink
|
||||
{
|
||||
public:
|
||||
CCVarsDump()
|
||||
{
|
||||
m_vars.resize(0);
|
||||
}
|
||||
void OnElementFound(ICVar *pCVar)
|
||||
{
|
||||
m_vars.push_back(pCVar);
|
||||
}
|
||||
ICVar** GetVars() { return &m_vars[0]; }
|
||||
int NumVars() { return m_vars.size(); }
|
||||
private:
|
||||
static std::vector<ICVar*> m_vars;
|
||||
};
|
||||
std::vector<ICVar*> CCVarsDump::m_vars;
|
||||
|
||||
//
|
||||
// PBcvarWalk
|
||||
//
|
||||
//this is a callback function called from the PB dlls
|
||||
int PBcvarWalk ( char **name , char **string , int *flags , char **resetString )
|
||||
{
|
||||
if ( pbsdk == NULL ) return 0 ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return 0 ;
|
||||
|
||||
static int i = 0 , n = 0 ;
|
||||
static ICVar **pVars = NULL ;
|
||||
|
||||
if ( i == 0 || pVars == NULL ) {
|
||||
CCVarsDump dump;
|
||||
pip->m_pSystem->GetIConsole()->DumpCVars( &dump );
|
||||
pVars = dump.GetVars();
|
||||
if ( pVars == NULL ) return 0 ;
|
||||
i = 0 ;
|
||||
n = dump.NumVars() ;
|
||||
}
|
||||
|
||||
if ( i >= n || pVars == NULL ) {//end of enumeration
|
||||
i = 0 ;
|
||||
n = 0 ;
|
||||
pVars = NULL ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
*name = (char *) pVars[i]->GetName() ;
|
||||
*string = (char *) pVars[i]->GetString() ;
|
||||
*flags = pVars[i]->GetFlags() ;
|
||||
*resetString = "" ;
|
||||
++i ;
|
||||
return 1;//keep going
|
||||
}
|
||||
|
||||
class CKeyBindsDump : public IKeyBindDumpSink
|
||||
{
|
||||
public:
|
||||
CKeyBindsDump()
|
||||
{
|
||||
m_keys.resize(0);
|
||||
}
|
||||
void OnKeyBindFound( const char *sBind,const char *sCommand )
|
||||
{
|
||||
m_keys.push_back(sBind);
|
||||
}
|
||||
const char** GetKeys() { return &m_keys[0]; }
|
||||
int NumKeys() { return m_keys.size(); }
|
||||
private:
|
||||
static std::vector<const char*> m_keys;
|
||||
};
|
||||
std::vector<const char*> CKeyBindsDump::m_keys;
|
||||
|
||||
//
|
||||
// PBbindStuff
|
||||
//
|
||||
int PBbindStuff ( int type , const char **data )
|
||||
{
|
||||
if ( pbsdk == NULL ) return 0 ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return 0 ;
|
||||
|
||||
static int i = 0 , n = 0 ;
|
||||
static const char **pKeys = NULL ;
|
||||
|
||||
if ( type == 1 || n == 0 ) {
|
||||
n = 0 ;
|
||||
if ( i == 0 || pKeys == NULL ) {
|
||||
CKeyBindsDump dump;
|
||||
pip->m_pSystem->GetIConsole()->DumpKeyBinds( &dump );
|
||||
pKeys = dump.GetKeys();
|
||||
if ( pKeys == NULL ) return 0 ;
|
||||
i = 0 ;
|
||||
n = dump.NumKeys() ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( type == 1 ) {//return # of keys
|
||||
return n ;
|
||||
} else if ( type == 2 ) {//return keyname in *data
|
||||
int key = atoi ( *data ) ;
|
||||
*data = "" ;
|
||||
if ( pKeys == NULL ) return 0 ;
|
||||
if ( key < n ) *data = pKeys[key] ;
|
||||
} else {//return data for key bind name
|
||||
int key = atoi ( *data ) ;
|
||||
*data = "" ;
|
||||
if ( pKeys == NULL ) return 0 ;
|
||||
*data = pip->m_pSystem->GetIConsole()->FindKeyBind(pKeys[key]);
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
//
|
||||
// PBpakNames
|
||||
//
|
||||
void PBpakNames ( char *buf )//assumes buf is 1025+ in size (bytes)
|
||||
{
|
||||
strcpy ( buf , "*ERROR*" ) ;
|
||||
if ( pbsdk == NULL ) return ;
|
||||
CPunkBusterInterface *pip = (CPunkBusterInterface *) pbsdk->pbinterface ;
|
||||
if ( pip == NULL ) return ;
|
||||
if ( pip->m_pSystem == NULL ) return ;
|
||||
|
||||
*buf = 0 ;
|
||||
ICryPak::PakInfo* pPakInfo = pip->m_pSystem->GetIPak()->GetPakInfo(); //get loaded pak names
|
||||
int i ;
|
||||
char priorRoot[513] = "" ;
|
||||
for ( i = 0 ; i < pPakInfo->numOpenPaks ; i++ ) {
|
||||
int slb = strlen ( buf ) ;
|
||||
if ( stricmp ( priorRoot , pPakInfo->arrPaks[i].szBindRoot ) ) { //new bind root ?
|
||||
strncpy ( priorRoot , pPakInfo->arrPaks[i].szBindRoot , 512 ) ; //yes add to list with a * prefix
|
||||
priorRoot[512] = 0 ;
|
||||
if ( strlen ( priorRoot ) + slb < 1020 ) _snprintf ( buf + slb , 1025 - slb , "*\"%s\" " , priorRoot ) ;
|
||||
slb = strlen ( buf ) ;
|
||||
}
|
||||
const char *cp = pPakInfo->arrPaks[i].szFilePath ;
|
||||
if ( strlen ( cp ) > strlen ( priorRoot ) ) cp += strlen ( priorRoot ) ;//this should always happen
|
||||
if ( strlen ( cp ) + slb > 1020 ) continue ; //skip it, too many already
|
||||
_snprintf ( buf + slb , 1025 - slb , "\"%s\" " , cp ) ; //append pak file name from point of prior bind root
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // NOT_USE_PUNKBUSTER_SDK
|
||||
105
CryNetwork/PunkBusterInterface.h
Normal file
105
CryNetwork/PunkBusterInterface.h
Normal file
@@ -0,0 +1,105 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2001-2004.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: PunkBusterInterface.h
|
||||
// Version: v1.00
|
||||
// Created: 1/3/2004 by Timur.
|
||||
// Compilers: Visual Studio.NET 2003
|
||||
// Description: Interface to the PunkBuster from CryEngine.
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(NOT_USE_PUNKBUSTER_SDK)
|
||||
|
||||
#ifndef __PunkBusterInterface_h__
|
||||
#define __PunkBusterInterface_h__
|
||||
#pragma once
|
||||
|
||||
#include "IConsole.h"
|
||||
#include "../PunkBuster/pbcommon.h"
|
||||
|
||||
class CNetwork;
|
||||
class CServer;
|
||||
class CClient;
|
||||
class CClientLocal;
|
||||
class CServerSlot;
|
||||
|
||||
/*! Wrapper arround PunkBuster.
|
||||
*/
|
||||
class CPunkBusterInterface : public IConsoleVarSink, public IOutputPrintSink
|
||||
{
|
||||
public:
|
||||
CPunkBusterInterface( CNetwork *pNetwork );
|
||||
~CPunkBusterInterface();
|
||||
|
||||
//! Called when initializing client and server.
|
||||
void Init( bool bClient , bool isLocalServer );
|
||||
//! Called when shut downing client and server.
|
||||
void ShutDown( bool bClient );
|
||||
|
||||
// This is server.
|
||||
void SetServer( CServer *pServer );
|
||||
// This is client.
|
||||
void SetClient( CClient *pClient );
|
||||
void SetClientLocal( CClientLocal *pClient );
|
||||
|
||||
//! Locks the punkbuster cvars
|
||||
void LockCVars();
|
||||
|
||||
//! Unlocks the punkbuster cvars
|
||||
void UnlockCVars();
|
||||
|
||||
//! Updates PunkBuster, called every frame.
|
||||
void Update( bool bClient );
|
||||
|
||||
//! Called when message from server or client recieved.
|
||||
void OnCCPPunkBusterMsg( CIPAddress &ipAddress,CStream &stm );
|
||||
|
||||
//! When new client joins server.
|
||||
void OnAddClient( CIPAddress &clientIP );
|
||||
//! When client disconnect server.
|
||||
void OnDisconnectClient( CIPAddress &clientIP );
|
||||
|
||||
bool CheckPBPacket(CStream &stmPacket,CIPAddress &ip);
|
||||
void ValidateClient( CServerSlot *pSlot );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IConsoleVarSink
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual bool OnBeforeVarChange( ICVar *pVar,const char *sNewValue );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// IOutputPrintSink
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual void Print( const char *inszText );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//private:
|
||||
bool ReadStringFromRegistry(const string &szKeyName, const string &szValueName, string &szValue);
|
||||
bool LoadCDKey( string &sCDKey );
|
||||
|
||||
void CheaterFound( CIPAddress &clientIP,int type,const char *sMsg );
|
||||
void SendMsgToClient( CIPAddress &clientIP,CStream &stm );
|
||||
void SendMsgToServer( CStream &stm );
|
||||
|
||||
//private:
|
||||
ISystem *m_pSystem;
|
||||
CNetwork *m_pNetwork;
|
||||
|
||||
CServer* m_pServer;
|
||||
CClient* m_pClient;
|
||||
CClientLocal* m_pClientLocal;
|
||||
|
||||
bool m_bClInitialized , m_bSvInitialized , m_bSinglePlayer ;
|
||||
ICVar *cl_punkbuster;
|
||||
ICVar *sv_punkbuster;
|
||||
ICVar *fs_homepath;
|
||||
ICVar *sys_punkbuster_loaded;
|
||||
};
|
||||
|
||||
|
||||
#endif // __PunkBusterInterface_h__
|
||||
#endif // NOT_USE_PUNKBUSTER_SDK
|
||||
327
CryNetwork/RConSystem.cpp
Normal file
327
CryNetwork/RConSystem.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
#include "stdafx.h"
|
||||
#include "rconsystem.h" // CRConSystem
|
||||
#include "Network.h" // CNetwork
|
||||
#include "CNP.h" // CQPRConCommand
|
||||
#include "IConsole.h" // IConsole
|
||||
//#if !defined(LINUX)
|
||||
#include "IDataProbe.h" // IConsole
|
||||
//#endif
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// *****************************************************************
|
||||
class CRConConsoleSink :public IOutputPrintSink
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
CRConConsoleSink( CRConSystem &inRef, const CIPAddress &ip ) :m_Ref(inRef), m_ip(ip)
|
||||
{
|
||||
}
|
||||
|
||||
// interface IOutputPrintSink ------------------------------------
|
||||
|
||||
virtual void Print( const char *inszText )
|
||||
{
|
||||
CStream stmPacket;
|
||||
CQPRConResponse RConResponse;
|
||||
|
||||
RConResponse.m_sText=inszText;
|
||||
|
||||
RConResponse.Save(stmPacket);
|
||||
NRESULT hRes=m_Ref.m_sSocket.Send(stmPacket.GetPtr(), BITS2BYTES(stmPacket.GetSize()), &m_ip);
|
||||
|
||||
if(hRes==SOCKET_ERROR)
|
||||
{
|
||||
INetwork *pNetwork=m_Ref.m_pSystem->GetINetwork(); assert(pNetwork);
|
||||
|
||||
const char *szErrorRes=pNetwork->EnumerateError(hRes);
|
||||
|
||||
CryLogAlways("$4RConError: %s",szErrorRes);
|
||||
}
|
||||
}
|
||||
|
||||
CRConSystem & m_Ref; //!<
|
||||
CIPAddress m_ip; //!<
|
||||
};
|
||||
// *****************************************************************
|
||||
// *****************************************************************
|
||||
|
||||
CRConSystem::CRConSystem()
|
||||
{
|
||||
m_pSystem=0;
|
||||
m_pIServer=0;
|
||||
|
||||
GetPassCode( "CNPNetworkKeyNode",m_nDevPassCode );
|
||||
}
|
||||
|
||||
CRConSystem::~CRConSystem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool CRConSystem::Create( ISystem *pSystem )
|
||||
{
|
||||
assert(pSystem);
|
||||
|
||||
m_pSystem = pSystem;
|
||||
|
||||
if(NET_FAILED(m_sSocket.Create()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CRConSystem::Update( unsigned int dwTime,IClient *pClient )
|
||||
{
|
||||
static CStream stmBuffer;
|
||||
static CIPAddress ipFrom;
|
||||
|
||||
int iReceived = 0;
|
||||
|
||||
if (pClient)
|
||||
{
|
||||
m_ipServer = pClient->GetServerIP();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
stmBuffer.Reset();
|
||||
|
||||
m_sSocket.Receive(stmBuffer.GetPtr(), stmBuffer.GetAllocatedSize(), iReceived, ipFrom);
|
||||
|
||||
if(iReceived > 0)
|
||||
{
|
||||
stmBuffer.SetSize(BYTES2BITS(iReceived));
|
||||
|
||||
CNP cnpPacket;
|
||||
cnpPacket.LoadAndSeekToZero(stmBuffer);
|
||||
|
||||
if(cnpPacket.m_cFrameType == FT_CQP_RCON_RESPONSE) // from Server back to Client
|
||||
{
|
||||
CQPRConResponse cqpRConResponse;
|
||||
cqpRConResponse.Load(stmBuffer);
|
||||
|
||||
CryLogAlways("$5RCon Response: %s",cqpRConResponse.m_sText.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0); // there should be no ther packets on this port
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while(iReceived > 0);
|
||||
|
||||
|
||||
while(!m_DeferredConsoleCommands.empty())
|
||||
{
|
||||
SDeferredCommand &defCmd( m_DeferredConsoleCommands.front() );
|
||||
|
||||
CRConConsoleSink sink( *this, defCmd.m_ip );
|
||||
|
||||
IConsole *pConsole( m_pSystem->GetIConsole() );
|
||||
assert( pConsole );
|
||||
|
||||
pConsole->AddOutputPrintSink( &sink);
|
||||
pConsole->ExecuteString( defCmd.m_sCommand.c_str() );
|
||||
pConsole->RemoveOutputPrintSink( &sink );
|
||||
|
||||
m_DeferredConsoleCommands.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CRConSystem::OnServerCreated( IServer *inpServer )
|
||||
{
|
||||
assert(inpServer);
|
||||
|
||||
inpServer->RegisterPacketSink(FT_CQP_RCON_COMMAND,this);
|
||||
m_pIServer = inpServer;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CRConSystem::GetPassCode( const char *szString,unsigned int *nOutCode )
|
||||
{
|
||||
//#if !defined(LINUX)
|
||||
|
||||
#ifdef _DATAPROBE
|
||||
char md5[16];
|
||||
GetISystem()->GetIDataProbe()->GetMD5( szString,strlen(szString),md5 );
|
||||
memcpy( nOutCode,md5,16 ); // 16 byte.
|
||||
#endif
|
||||
|
||||
//#endif
|
||||
/*
|
||||
#define POLY64REV 0xd800000000000000ULL
|
||||
string sPass = szString;
|
||||
// Duplicate pass 10 times.
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
sPass += szString;
|
||||
}
|
||||
int len = sPass.size();
|
||||
const unsigned char *buf = (const unsigned char*)sPass.c_str();
|
||||
// calc CRC_64
|
||||
static uint64 Table[256];
|
||||
uint64 code = 0;
|
||||
static int init = 0;
|
||||
if (!init) {
|
||||
int i;
|
||||
init = 1;
|
||||
for (i = 0; i <= 255; i++) {
|
||||
int j;
|
||||
uint64 part = i;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (part & 1)
|
||||
part = (part >> 1) ^ POLY64REV;
|
||||
else
|
||||
part >>= 1;
|
||||
}
|
||||
Table[i] = part;
|
||||
}
|
||||
}
|
||||
unsigned int key1[4] = { 123765122,1276327,13482722,29871129};
|
||||
while (len--)
|
||||
{
|
||||
uint64 temp1 = code >> 8;
|
||||
uint64 temp2 = Table[(code ^ (uint64)*buf) & 0xff];
|
||||
code = temp1 ^ temp2;
|
||||
buf += 1;
|
||||
}
|
||||
|
||||
unsigned int key2[4] = { 53215122,278627227,1762561245,817671221};
|
||||
|
||||
// 8 bytes.
|
||||
TEA_ENCODE( (unsigned int*)&code,nOutCode,8,key1 );
|
||||
code = (~code);
|
||||
TEA_ENCODE( (unsigned int*)&code,(nOutCode+2),8,key2 );
|
||||
*/
|
||||
}
|
||||
|
||||
void CRConSystem::OnReceivingPacket( const unsigned char inPacketID, CStream &stmPacket, CIPAddress &ip )
|
||||
{
|
||||
IConsole *pConsole=m_pSystem->GetIConsole(); assert(pConsole);
|
||||
|
||||
ICVar *pVar = pConsole->GetCVar("sv_rcon_password"); assert(pVar);
|
||||
string sv_RConPassword = pVar->GetString();
|
||||
|
||||
if(sv_RConPassword=="")
|
||||
return; // RCon is not activated
|
||||
|
||||
CQPRConCommand pccp;
|
||||
|
||||
pccp.Load(stmPacket);
|
||||
|
||||
|
||||
// Get code for server password, must match code recieved from client.
|
||||
unsigned int nServerPassCode[4];
|
||||
GetPassCode( sv_RConPassword.c_str(),nServerPassCode );
|
||||
|
||||
if (memcmp(nServerPassCode,pccp.m_nRConPasswordCode,sizeof(nServerPassCode)) != 0
|
||||
&& memcmp(m_nDevPassCode,pccp.m_nRConPasswordCode,sizeof(nServerPassCode)) != 0)
|
||||
{
|
||||
unsigned int dwIP = ip.GetAsUINT();
|
||||
|
||||
std::map<unsigned int, int>::iterator it = m_hmRconAttempts.find(dwIP);
|
||||
|
||||
if (it == m_hmRconAttempts.end())
|
||||
{
|
||||
int iTry = 1;
|
||||
|
||||
m_hmRconAttempts.insert(std::pair<unsigned int, int>(dwIP, iTry));
|
||||
}
|
||||
else
|
||||
{
|
||||
CryLogAlways( "$4%s used a bad rcon password!.", ip.GetAsString(0) );
|
||||
|
||||
int iTry = ++it->second;
|
||||
|
||||
// if 3 attempts failed, remove from the hash map and ban it!
|
||||
if (iTry >= 3)
|
||||
{
|
||||
m_hmRconAttempts.erase(it);
|
||||
m_pIServer->BanIP(dwIP);
|
||||
|
||||
|
||||
CryLogAlways("$4Banned %s after 3 attempts with a bad rcon password.", ip.GetAsString(0));
|
||||
}
|
||||
}
|
||||
|
||||
// pLog->Log("DEBUG: Password does not match");
|
||||
return; // rcon password does not match
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset the number of tries if password successful
|
||||
std::map<unsigned int, int>::iterator it = m_hmRconAttempts.find(ip.GetAsUINT());
|
||||
|
||||
if (it != m_hmRconAttempts.end())
|
||||
{
|
||||
m_hmRconAttempts.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char tempCmd[512];
|
||||
strncpy(tempCmd,pccp.m_sRConCommand.c_str(),sizeof(tempCmd)-1);
|
||||
tempCmd[sizeof(tempCmd)-1] = 0;
|
||||
|
||||
char *szIP = ip.GetAsString();
|
||||
|
||||
CryLogAlways("$5Incoming RCon(%s): %s",szIP,tempCmd);
|
||||
|
||||
|
||||
m_DeferredConsoleCommands.push_back(SDeferredCommand(tempCmd,ip));
|
||||
|
||||
/*
|
||||
{
|
||||
CRConConsoleSink sink(*this,ip);
|
||||
|
||||
pConsole->AddOutputPrintSink(&sink);
|
||||
pConsole->ExecuteString(tempCmd);
|
||||
pConsole->RemoveOutputPrintSink(&sink);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void CRConSystem::ExecuteRConCommand( const char *inszCommand )
|
||||
{
|
||||
// get parameters
|
||||
|
||||
IConsole *pConsole=m_pSystem->GetIConsole(); assert(pConsole);
|
||||
|
||||
ICVar *pVar1 = pConsole->GetCVar("cl_rcon_serverip"); assert(pVar1);
|
||||
string serverip = pVar1->GetString();
|
||||
|
||||
ICVar *pVar2 = pConsole->GetCVar("cl_rcon_port"); assert(pVar2);
|
||||
WORD wPort = pVar2->GetIVal();
|
||||
|
||||
ICVar *pVar3 = pConsole->GetCVar("cl_rcon_password"); assert(pVar3);
|
||||
string sPasswd = pVar3->GetString();
|
||||
|
||||
// send packet
|
||||
CQPRConCommand cqpRConCommand;
|
||||
CStream stmPacket;
|
||||
CIPAddress ip(wPort,serverip.c_str());
|
||||
|
||||
// If server ip not specified use, current server.
|
||||
if (serverip.empty())
|
||||
{
|
||||
ip.Set( m_ipServer );
|
||||
}
|
||||
|
||||
unsigned int nClientCode[4];
|
||||
GetPassCode( sPasswd.c_str(),nClientCode );
|
||||
memcpy( cqpRConCommand.m_nRConPasswordCode,nClientCode,sizeof(nClientCode) );
|
||||
|
||||
char tempCmd[256];
|
||||
strncpy(tempCmd,inszCommand,sizeof(tempCmd)-1);
|
||||
tempCmd[sizeof(tempCmd)-1] = 0;
|
||||
cqpRConCommand.m_sRConCommand = tempCmd;
|
||||
|
||||
cqpRConCommand.Save(stmPacket);
|
||||
m_sSocket.Send(stmPacket.GetPtr(),BITS2BYTES(stmPacket.GetSize()),&ip);
|
||||
|
||||
// prinout
|
||||
CryLogAlways("$5RCon (%s:%d)'%s'",serverip.c_str(),(int)wPort,tempCmd );
|
||||
}
|
||||
58
CryNetwork/RConSystem.h
Normal file
58
CryNetwork/RConSystem.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef RCONSYSTEM_H
|
||||
#define RCONSYSTEM_H
|
||||
|
||||
#include "INetwork.h" // IRConSystem
|
||||
#include <list>
|
||||
|
||||
class CRConSystem :public IRConSystem, public INetworkPacketSink
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CRConSystem();
|
||||
//! destructor
|
||||
virtual ~CRConSystem();
|
||||
|
||||
// interface INetworkPacketSink ------------------------------------------
|
||||
|
||||
virtual void OnReceivingPacket( const unsigned char inPacketID, CStream &stmPacket, CIPAddress &ip );
|
||||
|
||||
// interface IRConSystem -------------------------------------------------
|
||||
|
||||
virtual void Release(){ delete this; }
|
||||
virtual void Update( unsigned int dwTime,IClient *pClient=NULL );
|
||||
virtual void ExecuteRConCommand( const char *inszCommand );
|
||||
virtual void OnServerCreated( IServer *inpServer );
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
//!
|
||||
bool Create( ISystem *pSystem );
|
||||
|
||||
private: // -----------------------------------------------------------------------
|
||||
|
||||
struct SDeferredCommand
|
||||
{
|
||||
//! constructor
|
||||
SDeferredCommand( const string &sCmd, const CIPAddress &ip ) :m_sCommand(sCmd), m_ip(ip)
|
||||
{
|
||||
}
|
||||
|
||||
string m_sCommand; //!<
|
||||
CIPAddress m_ip; //!<
|
||||
};
|
||||
|
||||
ISystem * m_pSystem; //!< pointer to the system interface (is zero when not initialized)
|
||||
IServer * m_pIServer; //!<
|
||||
CDatagramSocket m_sSocket; //!<
|
||||
std::map<unsigned int, int> m_hmRconAttempts; //! hash map that maps ip -> rcon attempts, for security.
|
||||
std::list<SDeferredCommand> m_DeferredConsoleCommands; //!< to execute commands at a defined point in the update loop
|
||||
unsigned int m_nDevPassCode[4];
|
||||
CIPAddress m_ipServer;
|
||||
|
||||
//! Get 128bit code from string. (4 ints)
|
||||
void GetPassCode( const char *szString,unsigned int *nOutCode );
|
||||
|
||||
friend class CRConConsoleSink;
|
||||
};
|
||||
|
||||
#endif // RCONSYSTEM_H
|
||||
431
CryNetwork/ScriptObjectNewUbisoftClient.cpp
Normal file
431
CryNetwork/ScriptObjectNewUbisoftClient.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
// ScriptObjectNewUbisoftClient.cpp: implementation of the CScriptObjectNewUbisoftClient class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
#include "ScriptObjectNewUbisoftClient.h"
|
||||
#include "NewUbisoftClient.h"
|
||||
#include <ITimer.h> // ITimer
|
||||
#include "IConsole.h" // IConsole
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
_DECLARE_SCRIPTABLEEX(CScriptObjectNewUbisoftClient)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CScriptObjectNewUbisoftClient::CScriptObjectNewUbisoftClient()
|
||||
{
|
||||
m_pUbiSoftClient=0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CScriptObjectNewUbisoftClient::~CScriptObjectNewUbisoftClient()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CScriptObjectNewUbisoftClient::ReleaseTemplate()
|
||||
{
|
||||
/* SAFE_RELEASE(m_pLobbyInfo);
|
||||
SAFE_RELEASE(m_pRoomInfo);
|
||||
SAFE_RELEASE(m_pMemberInfo);
|
||||
SAFE_RELEASE(m_pFriendInfo);
|
||||
SAFE_RELEASE(m_pConnectInfo);
|
||||
*/
|
||||
_ScriptableEx<CScriptObjectNewUbisoftClient>::ReleaseTemplate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CScriptObjectNewUbisoftClient::InitializeTemplate(IScriptSystem *pSS)
|
||||
{
|
||||
_ScriptableEx<CScriptObjectNewUbisoftClient>::InitializeTemplate(pSS);
|
||||
|
||||
//REG_FUNC(CScriptObjectNewUbisoftClient,Client_GetStoredUsername);
|
||||
//REG_FUNC(CScriptObjectNewUbisoftClient,Client_GetStoredPassword);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_AutoLogin);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_Login);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_RequestGameServers);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_JoinGameServer);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_ConnectedToGameServer);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_LeaveGameServer);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_Disconnect);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_IsConnected);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_SetCDKey);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_CreateAccount);
|
||||
REG_FUNC(CScriptObjectNewUbisoftClient,Client_RequestMOTD);
|
||||
#define REGISTER_CONSTANT(c) pSS->SetGlobalValue("UBI_"#c, c)
|
||||
|
||||
// REGISTER_CONSTANT(DISCONNECTED);
|
||||
|
||||
#undef REGISTER_CONSTANT
|
||||
}
|
||||
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Init( IScriptSystem *pScriptSystem, ISystem *pSystem, NewUbisoftClient *inUbiSoftClient )
|
||||
{
|
||||
m_pSystem=pSystem;
|
||||
m_pConsole=pSystem->GetIConsole();
|
||||
m_pScriptSystem = pScriptSystem;
|
||||
m_pUbiSoftClient=inUbiSoftClient;
|
||||
InitGlobal(pScriptSystem,"NewUbisoftClient",this);
|
||||
|
||||
inUbiSoftClient->SetScriptObject(this);
|
||||
inUbiSoftClient->Init(m_pSystem);
|
||||
}
|
||||
|
||||
|
||||
DWORD CScriptObjectNewUbisoftClient::GetAbsTimeInSeconds()
|
||||
{
|
||||
DWORD dwRet=(DWORD)(m_pSystem->GetITimer()->GetCurrTime());
|
||||
|
||||
return dwRet;
|
||||
}
|
||||
//REG_FUNC(CScriptObjectNewUbisoftClient,Client_GetStoredUsername);
|
||||
//REG_FUNC(CScriptObjectNewUbisoftClient,Client_GetStoredPassword);
|
||||
//REG_FUNC(CScriptObjectNewUbisoftClient,Client_AutoLogin);
|
||||
|
||||
/*
|
||||
int CScriptObjectNewUbisoftClient::Client_GetStoredUsername(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
|
||||
string szHexUsername;
|
||||
|
||||
m_pUbiSoftClient->ReadStringFromRegistry("Ubi.com", "username", szHexUsername);
|
||||
|
||||
char szEncUsername[256] = {0};
|
||||
char szUsername[256] = {0};
|
||||
|
||||
m_pUbiSoftClient->DecodeHex((unsigned char *)szEncUsername, (unsigned char *)szHexUsername.c_str());
|
||||
m_pUbiSoftClient->DecryptString((unsigned char *)szUsername, (unsigned char *)szEncUsername);
|
||||
|
||||
return pH->EndFunction(szUsername);
|
||||
}
|
||||
|
||||
|
||||
int CScriptObjectNewUbisoftClient::Client_GetStoredPassword(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
|
||||
string szHexPassword;
|
||||
|
||||
m_pUbiSoftClient->ReadStringFromRegistry("Ubi.com", "password", szHexPassword);
|
||||
|
||||
char szEncPassword[256] = {0};
|
||||
char szPassword[256] = {0};
|
||||
|
||||
m_pUbiSoftClient->DecodeHex((unsigned char *)szEncPassword, (unsigned char *)szHexPassword.c_str());
|
||||
m_pUbiSoftClient->DecryptString((unsigned char *)szPassword, (unsigned char *)szEncPassword);
|
||||
|
||||
return pH->EndFunction(szPassword);
|
||||
}
|
||||
*/
|
||||
|
||||
int CScriptObjectNewUbisoftClient::Client_AutoLogin(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_AutoLogin());
|
||||
}
|
||||
|
||||
/*! Login the Game Client to the Game Service
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_Login(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(3);
|
||||
|
||||
const char *szUsername;
|
||||
const char *szPassword;
|
||||
bool bSavePassword = false;
|
||||
|
||||
pH->GetParam(1,szUsername);
|
||||
pH->GetParam(2,szPassword);
|
||||
pH->GetParam(3,bSavePassword);
|
||||
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_Login(szUsername,szPassword, bSavePassword));
|
||||
}
|
||||
|
||||
/*! Request the list of game servers
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_RequestGameServers(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_RequestGameServers());
|
||||
}
|
||||
|
||||
/*! Tell the Game Service that you are going to join a game server
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_JoinGameServer(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(2);
|
||||
int iLobbyID,iRoomID;
|
||||
|
||||
pH->GetParam(1,iLobbyID);
|
||||
pH->GetParam(2,iRoomID);
|
||||
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_JoinGameServer(iLobbyID,iRoomID));
|
||||
}
|
||||
|
||||
/*! Tell the Game Service that you have connected to a game server
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_ConnectedToGameServer(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_ConnectedToGameServer());
|
||||
}
|
||||
|
||||
/*! Tell the Game Service that you have left the game server. No parameters
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_LeaveGameServer(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_LeaveGameServer());
|
||||
}
|
||||
|
||||
/*! Disconnect from Game Service. No parameters
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_Disconnect(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_Disconnect());
|
||||
}
|
||||
|
||||
/*! Create an account. szUsername (string), szPassword (string)
|
||||
*/
|
||||
int CScriptObjectNewUbisoftClient::Client_CreateAccount(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(2);
|
||||
const char *szUsername;
|
||||
const char *szPassword;
|
||||
|
||||
pH->GetParam(1,szUsername);
|
||||
pH->GetParam(2,szPassword);
|
||||
|
||||
return pH->EndFunction(m_pUbiSoftClient->Client_CreateAccount(szUsername,szPassword));
|
||||
}
|
||||
|
||||
int CScriptObjectNewUbisoftClient::Client_IsConnected(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
|
||||
if (m_pUbiSoftClient->Client_IsConnected())
|
||||
{
|
||||
m_pSystem->GetILog()->Log("Client connected");
|
||||
return pH->EndFunction(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSystem->GetILog()->Log("Client NOT connected");
|
||||
return pH->EndFunctionNull();
|
||||
}
|
||||
}
|
||||
|
||||
int CScriptObjectNewUbisoftClient::Client_SetCDKey(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(1);
|
||||
|
||||
const char *szCDKey;
|
||||
|
||||
pH->GetParam(1,szCDKey);
|
||||
|
||||
if (m_pUbiSoftClient->Client_SetCDKey(szCDKey))
|
||||
{
|
||||
return pH->EndFunction(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pH->EndFunctionNull();
|
||||
}
|
||||
}
|
||||
|
||||
int CScriptObjectNewUbisoftClient::Client_RequestMOTD(IFunctionHandler *pH)
|
||||
{
|
||||
if (m_pUbiSoftClient->Client_RequestMOTD("EN"))
|
||||
{
|
||||
return pH->EndFunction(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pH->EndFunctionNull();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CScriptObjectNewUbisoftClient::Server_DestroyServer(IFunctionHandler *pH)
|
||||
{
|
||||
CHECK_PARAMETERS(0);
|
||||
|
||||
return pH->EndFunction(m_pUbiSoftClient->Server_DestroyServer());
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
void CScriptObjectNewUbisoftClient::Client_LoginSuccess(const char *szUsername)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_LoginSuccess");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szUsername);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_LoginFail(const char *szError)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_LoginFail");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szError);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_GameServer(int iLobbyID, int iRoomID, const char *szGameServer,
|
||||
const char *szIPAddress, const char *szLANIPAddress, int iMaxPlayers,
|
||||
int iNumPlayers)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_GameServer");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(iLobbyID);
|
||||
m_pScriptSystem->PushFuncParam(iRoomID);
|
||||
m_pScriptSystem->PushFuncParam(szGameServer);
|
||||
m_pScriptSystem->PushFuncParam(szIPAddress);
|
||||
m_pScriptSystem->PushFuncParam(szLANIPAddress);
|
||||
m_pScriptSystem->PushFuncParam(iMaxPlayers);
|
||||
m_pScriptSystem->PushFuncParam(iNumPlayers);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_RequestFinished()
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_RequestFinished");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_JoinGameServerSuccess(const char *szIPAddress, const char *szLanIPAddress,
|
||||
unsigned short usPort)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_JoinGameServerSuccess");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szIPAddress);
|
||||
m_pScriptSystem->PushFuncParam(szLanIPAddress);
|
||||
m_pScriptSystem->PushFuncParam(usPort);
|
||||
m_pScriptSystem->EndCall();
|
||||
|
||||
}
|
||||
void CScriptObjectNewUbisoftClient::Client_JoinGameServerFail(const char *szError)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_JoinGameServerFail");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szError);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_CreateAccountSuccess()
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_CreateAccountSuccess");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_CreateAccountFail(const char *szText)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_CreateAccountFail");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szText);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Client_MOTD(const char *szUbiMOTD, const char *szGameMOTD)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Client_MOTD");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szUbiMOTD);
|
||||
m_pScriptSystem->PushFuncParam(szGameMOTD);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Server_RegisterServerSuccess(int iLobbyID, int iRoomID)
|
||||
{
|
||||
CStream stm;
|
||||
|
||||
stm.Write(iLobbyID);
|
||||
stm.Write(iRoomID);
|
||||
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Server_RegisterServerSuccess");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(iLobbyID);
|
||||
m_pScriptSystem->PushFuncParam(iRoomID);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Server_RegisterServerFail()
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Server_RegisterServerFail");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Server_LobbyServerDisconnected()
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Server_LobbyServerDisconnected");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Server_PlayerJoin(const char *szUsername)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Server_PlayerJoin");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szUsername);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::Server_PlayerLeave(const char *szUsername)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","Server_PlayerLeave");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szUsername);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::CDKey_Failed(const char *szText)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","CDKey_Failed");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szText);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
void CScriptObjectNewUbisoftClient::CDKey_GetCDKey()
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","CDKey_GetCDKey");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
void CScriptObjectNewUbisoftClient::CDKey_ActivationSuccess()
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","CDKey_ActivationSuccess");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
void CScriptObjectNewUbisoftClient::CDKey_ActivationFail(const char *szText)
|
||||
{
|
||||
m_pScriptSystem->BeginCall("NewUbisoftClient","CDKey_ActivationFail");
|
||||
m_pScriptSystem->PushFuncParam(GetScriptObject());
|
||||
m_pScriptSystem->PushFuncParam(szText);
|
||||
m_pScriptSystem->EndCall();
|
||||
}
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
124
CryNetwork/ScriptObjectNewUbisoftClient.h
Normal file
124
CryNetwork/ScriptObjectNewUbisoftClient.h
Normal file
@@ -0,0 +1,124 @@
|
||||
// ScriptObjectInput.h: interface for the CScriptObjectNewUbisoftClient class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined(__SCRIPT_OBJECT_NEW_UBISOFT_CLIENT__INCLUDED_)
|
||||
#define __SCRIPT_OBJECT_NEW_UBISOFT_CLIENT__INCLUDED_
|
||||
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include <IScriptSystem.h>
|
||||
#include <_ScriptableEx.h>
|
||||
|
||||
class NewUbisoftClient;
|
||||
|
||||
/*! This class implements ubisoft.com script functions.
|
||||
|
||||
REMARKS:
|
||||
After initialization of the script-object it will be globally accessable through scripts using the namespace "UbisoftClient".
|
||||
|
||||
IMPLEMENTATIONS NOTES:
|
||||
These function will never be called from C-Code. They're script-exclusive.
|
||||
*/
|
||||
class CScriptObjectNewUbisoftClient : public _ScriptableEx<CScriptObjectNewUbisoftClient>
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CScriptObjectNewUbisoftClient();
|
||||
//! destructor
|
||||
virtual ~CScriptObjectNewUbisoftClient();
|
||||
//!
|
||||
//! /param pScriptSystem Pointer to the ScriptSystem-interface
|
||||
//! /param pSystem Pointer to the System-interface
|
||||
void Init( IScriptSystem *pScriptSystem, ISystem *pSystem, NewUbisoftClient *inUbiSoftClient );
|
||||
//!
|
||||
static void InitializeTemplate(IScriptSystem *pSS);
|
||||
//!
|
||||
static void ReleaseTemplate();
|
||||
|
||||
int Client_GetStoredUsername(IFunctionHandler *pH);
|
||||
int Client_GetStoredPassword(IFunctionHandler *pH);
|
||||
|
||||
// auto log in using info stored in registry
|
||||
int Client_AutoLogin(IFunctionHandler *pH);
|
||||
|
||||
// Logs in using szUsername (string) and szPassword (string)
|
||||
int Client_Login(IFunctionHandler *pH);
|
||||
|
||||
// Request list of Game Servers. No parameters
|
||||
int Client_RequestGameServers(IFunctionHandler *pH);
|
||||
|
||||
// Join a Game Server. iLobbyID (int), iRoomID (int)
|
||||
int Client_JoinGameServer(IFunctionHandler *pH);
|
||||
|
||||
// Tell the Game Service you have connected to the game server. No parameters
|
||||
int Client_ConnectedToGameServer(IFunctionHandler *pH);
|
||||
|
||||
// Tell the Game Service that you have left the game server. No parameters
|
||||
int Client_LeaveGameServer(IFunctionHandler *pH);
|
||||
|
||||
// Disconnect from Game Service. No parameters
|
||||
int Client_Disconnect(IFunctionHandler *pH);
|
||||
|
||||
// Create an account. szUsername (string), szPassword (string)
|
||||
int Client_CreateAccount(IFunctionHandler *pH);
|
||||
|
||||
// Check if the client is logged in
|
||||
int Client_IsConnected(IFunctionHandler *pH);
|
||||
|
||||
//Set the cdkey
|
||||
int Client_SetCDKey(IFunctionHandler *pH);
|
||||
|
||||
//Request the Message of the Day
|
||||
int Client_RequestMOTD(IFunctionHandler *pH);
|
||||
|
||||
// Remove the server from Game Service. No Parameters
|
||||
int Server_DestroyServer(IFunctionHandler *pH);
|
||||
|
||||
//! used by the NewUbisoftClient
|
||||
DWORD GetAbsTimeInSeconds();
|
||||
|
||||
// Script Callbacks -------------------------------------------
|
||||
|
||||
void Client_LoginSuccess(const char *szUsername);
|
||||
void Client_LoginFail(const char *szText);
|
||||
void Client_GameServer(int iLobbyID, int iRoomID, const char *szGameServer,
|
||||
const char *szIPAddress, const char *szLANIPAddress, int iMaxPlayers, int iNumPlayers);
|
||||
void Client_RequestFinished();
|
||||
void Client_JoinGameServerSuccess(const char *szIPAddress, const char *szLanIPAddress,
|
||||
unsigned short usPort);
|
||||
void Client_JoinGameServerFail(const char *szText);
|
||||
|
||||
void Client_CreateAccountSuccess();
|
||||
void Client_CreateAccountFail(const char *szText);
|
||||
|
||||
void Client_MOTD(const char *szUbiMOTD, const char *szGameMOTD);
|
||||
|
||||
void Server_RegisterServerSuccess(int iLobbyID, int iRoomID);
|
||||
void Server_RegisterServerFail();
|
||||
void Server_LobbyServerDisconnected();
|
||||
void Server_PlayerJoin(const char *szUsername);
|
||||
void Server_PlayerLeave(const char *szUsername);
|
||||
void CDKey_Failed(const char *szText);
|
||||
void CDKey_GetCDKey();
|
||||
void CDKey_ActivationSuccess();
|
||||
void CDKey_ActivationFail(const char *szText);
|
||||
|
||||
private: // --------------------------------------------------------------
|
||||
|
||||
ISystem * m_pSystem; //!
|
||||
IConsole * m_pConsole; //!
|
||||
IScriptSystem * m_pScriptSystem; //!
|
||||
NewUbisoftClient * m_pUbiSoftClient; //! (a different class is responsible for destruction)
|
||||
};
|
||||
|
||||
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
#endif //__SCRIPT_OBJECT_NEW_UBISOFT_CLIENT__INCLUDED_
|
||||
978
CryNetwork/Server.cpp
Normal file
978
CryNetwork/Server.cpp
Normal file
@@ -0,0 +1,978 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: Server.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Network.h"
|
||||
#include "CNP.h"
|
||||
#include "Server.h"
|
||||
#include "ServerSlot.h"
|
||||
#include "ILog.h"
|
||||
#include "IConsole.h"
|
||||
#include "NewUbisoftClient.h" // NewUbisoftClient
|
||||
#include <IScriptSystem.h>
|
||||
|
||||
#if defined(_DEBUG) && !defined(LINUX)
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(WIN64) && !defined(LINUX64) && !defined(NOT_USE_ASE_SDK)
|
||||
|
||||
#pragma comment(lib, "ASEQuerySDK.lib")
|
||||
|
||||
static CServer *g_pServer = 0;
|
||||
|
||||
extern "C"{
|
||||
#include "ASEQuerySDK.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ASEQuery_wantstatus()
|
||||
{
|
||||
if (!g_pServer || !g_pServer->GetServerSlotFactory())
|
||||
{
|
||||
ASEQuery_status("", "", "", "", 1, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string szName, szGameType, szMap, szVersion;
|
||||
bool bPassword = false;
|
||||
int nPlayers = 0;
|
||||
int nMaxPlayers = 0;
|
||||
g_pServer->GetServerSlotFactory()->GetServerInfoStatus(szName, szGameType, szMap, szVersion, &bPassword, &nPlayers, &nMaxPlayers);
|
||||
|
||||
ASEQuery_status(szName.c_str(), szGameType.c_str(), szMap.c_str(), szVersion.c_str(), bPassword, nPlayers, nMaxPlayers);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ASEQuery_wantrules()
|
||||
{
|
||||
IScriptSystem *pSS = GetISystem()->GetIScriptSystem();
|
||||
|
||||
_SmartScriptObject QueryHandler(pSS, 1);
|
||||
|
||||
if (!pSS->GetGlobalValue("QueryHandler", (IScriptObject *)QueryHandler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_SmartScriptObject ServerRules(pSS, 1);
|
||||
pSS->BeginCall("QueryHandler", "GetServerRules");
|
||||
pSS->PushFuncParam((IScriptObject *)QueryHandler);
|
||||
pSS->EndCall((IScriptObject *)ServerRules);
|
||||
|
||||
for (int i = 1; i <= ServerRules->Count(); i++)
|
||||
{
|
||||
_SmartScriptObject Rule(pSS, 1);
|
||||
|
||||
if (ServerRules->GetAt(i, (IScriptObject *)Rule))
|
||||
{
|
||||
char *szRuleName = 0;
|
||||
char *szRuleValue = 0;
|
||||
|
||||
Rule->GetAt(1, szRuleName);
|
||||
Rule->GetAt(2, szRuleValue);
|
||||
|
||||
if (szRuleValue && szRuleName)
|
||||
{
|
||||
ASEQuery_addrule(szRuleName, szRuleValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ASEQuery_wantplayers()
|
||||
{
|
||||
IScriptSystem *pSS = GetISystem()->GetIScriptSystem();
|
||||
|
||||
_SmartScriptObject QueryHandler(pSS, 1);
|
||||
|
||||
if (!pSS->GetGlobalValue("QueryHandler", (IScriptObject *)QueryHandler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_SmartScriptObject PlayerStats(pSS, 1);
|
||||
pSS->BeginCall("QueryHandler", "GetPlayerStats");
|
||||
pSS->PushFuncParam((IScriptObject *)QueryHandler);
|
||||
pSS->EndCall((IScriptObject *)PlayerStats);
|
||||
|
||||
for (int i = 1; i <= PlayerStats->Count(); i++)
|
||||
{
|
||||
_SmartScriptObject Player(pSS, 1);
|
||||
|
||||
if (PlayerStats->GetAt(i, (IScriptObject *)Player))
|
||||
{
|
||||
char *szName = 0;
|
||||
char *szTeam = 0;
|
||||
char *szSkin = 0;
|
||||
char *szScore = 0;
|
||||
char *szPing = 0;
|
||||
char *szTime = 0;
|
||||
|
||||
Player->GetValue("Name", (const char* &)szName);
|
||||
Player->GetValue("Team", (const char* &)szTeam);
|
||||
Player->GetValue("Skin", (const char* &)szSkin);
|
||||
Player->GetValue("Score", (const char* &)szScore);
|
||||
Player->GetValue("Ping", (const char* &)szPing);
|
||||
Player->GetValue("Time", (const char* &)szTime);
|
||||
|
||||
ASEQuery_addplayer(szName, szTeam, szSkin, szScore, szPing, szTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CServer::CServer(CNetwork *pNetwork)
|
||||
{
|
||||
m_cLastClientID = 0;
|
||||
m_pFactory = NULL;
|
||||
m_ServerVariables.nDataStreamTimeout = 30000;// 30 seconds
|
||||
m_pNetwork=pNetwork;
|
||||
m_wPort=0;
|
||||
m_bMulticastSocket=true;
|
||||
m_pSecuritySink=0;
|
||||
m_MPServerType=eMPST_LAN;
|
||||
}
|
||||
|
||||
CServer::~CServer()
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// ASE Deinitialization
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#if !defined(WIN64) && !defined(LINUX64) && !defined(NOT_USE_ASE_SDK)
|
||||
ASEQuery_shutdown();
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// If it is a UBI type server we should unregister
|
||||
m_pNetwork->m_pUbiSoftClient->Server_DestroyServer();
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
m_pNetwork->UnregisterServer(m_wPort);
|
||||
}
|
||||
|
||||
EMPServerType CServer::GetServerType() const
|
||||
{
|
||||
return m_MPServerType;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// IServer
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool CServer::Init(IServerSlotFactory *pFactory, WORD wPort, bool listen)
|
||||
{
|
||||
CIPAddress ipMulticast(SERVER_MULTICAST_PORT, SERVER_MULTICAST_ADDRESS);
|
||||
|
||||
m_pFactory = pFactory;
|
||||
|
||||
if(m_bListen = listen)
|
||||
{
|
||||
CIPAddress ipLocal;
|
||||
|
||||
ipLocal.m_Address.ADDR = m_pNetwork->GetLocalIP();
|
||||
|
||||
// only create the multicast socket if it's not internet server
|
||||
ICVar *sv_ServerType = GetISystem()->GetIConsole()->GetCVar("sv_ServerType"); assert(sv_ServerType);
|
||||
|
||||
m_MPServerType=eMPST_LAN;
|
||||
|
||||
if(stricmp(sv_ServerType->GetString(),"UBI")==0)
|
||||
m_MPServerType=eMPST_UBI;
|
||||
else if(stricmp(sv_ServerType->GetString(),"NET")==0)
|
||||
m_MPServerType=eMPST_NET;
|
||||
|
||||
// if this is a lan server
|
||||
//if (m_MPServerType==eMPST_LAN)
|
||||
{
|
||||
if (NET_SUCCEDED(m_socketMulticast.Create()))
|
||||
{
|
||||
if (NET_SUCCEDED(m_socketMulticast.Listen(SERVER_MULTICAST_PORT, &ipMulticast, &ipLocal)))
|
||||
{
|
||||
m_bMulticastSocket=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else
|
||||
{
|
||||
m_bMulticastSocket=false;
|
||||
}
|
||||
*/
|
||||
|
||||
if (NET_FAILED(m_socketMain.Create()))
|
||||
return false;
|
||||
|
||||
if (NET_FAILED(m_socketMain.Listen(wPort, 0, &ipLocal)))
|
||||
return false;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// ASE Initialization
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DWORD dwLocalIP = GetISystem()->GetINetwork()->GetLocalIP();
|
||||
char *szIP = 0;
|
||||
CIPAddress ip;
|
||||
|
||||
if (dwLocalIP)
|
||||
{
|
||||
ip.m_Address.ADDR = dwLocalIP;
|
||||
szIP = ip.GetAsString();
|
||||
}
|
||||
|
||||
#if !defined(WIN64) && !defined(LINUX64) && !defined(NOT_USE_ASE_SDK)
|
||||
ASEQuery_initialize((int)wPort, m_MPServerType!=eMPST_LAN ? 1 : 0, szIP);
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
m_wPort=wPort;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _INTERNET_SIMULATOR
|
||||
#include <stdlib.h>
|
||||
#if !defined(LINUX)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "ITimer.h"
|
||||
#endif
|
||||
|
||||
|
||||
void CServer::Update(unsigned int nTime)
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// ASE Update
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#if !defined(WIN64) && !defined(LINUX64) && !defined(NOT_USE_ASE_SDK)
|
||||
g_pServer = this;
|
||||
ASEQuery_check();
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef _INTERNET_SIMULATOR
|
||||
static ICVar *pVarPacketloss=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_packetloss");
|
||||
|
||||
TDelayPacketList2::iterator i;
|
||||
|
||||
for (i = m_delayedPacketList.begin(); i != m_delayedPacketList.end();)
|
||||
{
|
||||
DelayedPacket2 *dp = (*i);
|
||||
if (dp->m_fTimeToSend <= GetISystem()->GetITimer()->GetCurrTime())
|
||||
{
|
||||
i = m_delayedPacketList.erase(i);
|
||||
// Send it
|
||||
if ((rand() %100) > pVarPacketloss->GetFVal())
|
||||
m_socketMain.Send(dp->data,dp->len,dp->address);
|
||||
// Delete it
|
||||
delete dp->address;
|
||||
delete dp;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_nCurrentTime = nTime;
|
||||
int nRecvBytes;
|
||||
// do{
|
||||
/////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////
|
||||
static CIPAddress ipFrom;
|
||||
static CStream buf;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
if(m_bListen)
|
||||
do
|
||||
{
|
||||
buf.Reset();
|
||||
nRecvBytes = 0;
|
||||
m_socketMain.Receive(buf.GetPtr(),
|
||||
(int)BITS2BYTES(buf.GetAllocatedSize()),
|
||||
nRecvBytes,
|
||||
ipFrom);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
if (nRecvBytes>0)
|
||||
{
|
||||
buf.SetSize(BYTES2BITS(nRecvBytes));
|
||||
ProcessPacket(buf, ipFrom);
|
||||
}
|
||||
}while (nRecvBytes>0);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// handle multicast packets
|
||||
/////////////////////////////////////////////////////////
|
||||
if(m_bMulticastSocket && m_bListen && m_MPServerType==eMPST_LAN)
|
||||
{
|
||||
do
|
||||
{
|
||||
buf.Reset();
|
||||
nRecvBytes = 0;
|
||||
m_socketMulticast.Receive(buf.GetPtr(),
|
||||
(int)BITS2BYTES(buf.GetAllocatedSize()),
|
||||
nRecvBytes,
|
||||
ipFrom);
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
if (nRecvBytes>0)
|
||||
{
|
||||
buf.SetSize(BYTES2BITS(nRecvBytes));
|
||||
ProcessMulticastPacket(buf, ipFrom);
|
||||
}
|
||||
}while (nRecvBytes>0);
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// Update slots State machine
|
||||
SLOTS_MAPItr itr = m_mapSlots.begin();
|
||||
|
||||
while (itr != m_mapSlots.end())
|
||||
{
|
||||
CServerSlot *pSlot = itr->second;
|
||||
if (pSlot->IsActive())
|
||||
{
|
||||
pSlot->Update(m_nCurrentTime, NULL, NULL);
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
m_pNetwork->OnServerUpdate();
|
||||
}
|
||||
|
||||
void CServer::GetBandwidth( float &fIncomingKbPerSec, float &fOutgoinKbPerSec, DWORD &nIncomingPackets, DWORD &nOutgoingPackets )
|
||||
{
|
||||
fIncomingKbPerSec = m_socketMain.m_fIncomingKbPerSec;
|
||||
fOutgoinKbPerSec = m_socketMain.m_fOutgoingKbPerSec;
|
||||
nIncomingPackets=m_socketMain.m_nIncomingPacketsPerSec;
|
||||
nOutgoingPackets=m_socketMain.m_nOutgoingPacketsPerSec;
|
||||
}
|
||||
|
||||
void CServer::SetVariable(enum CryNetworkVarible eVarName, unsigned int nValue)
|
||||
{
|
||||
switch (eVarName)
|
||||
{
|
||||
case cnvDataStreamTimeout:
|
||||
m_ServerVariables.nDataStreamTimeout = nValue;
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::GetProtocolVariables(CNPServerVariables &sv)
|
||||
{
|
||||
sv = m_ServerVariables;
|
||||
}
|
||||
|
||||
void CServer::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// _IServerServices
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CServer::Send(CStream &stm, CIPAddress &ip)
|
||||
{
|
||||
#ifndef _INTERNET_SIMULATOR
|
||||
DWORD nSize = BITS2BYTES(stm.GetSize());
|
||||
|
||||
if(NET_SUCCEDED(m_socketMain.Send(stm.GetPtr(), nSize, &ip)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#else
|
||||
|
||||
static ICVar *pVarPacketloss=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_packetloss");
|
||||
static ICVar *pVarMinPing=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_minping");
|
||||
static ICVar *pVarMaxPing=GetISystem()->GetIConsole()->GetCVar("g_internet_simulator_maxping");
|
||||
|
||||
int iMaxPing=pVarMaxPing->GetIVal();
|
||||
int iMinPing=pVarMinPing->GetIVal();
|
||||
|
||||
if(iMinPing>iMaxPing)
|
||||
iMaxPing=iMinPing;
|
||||
|
||||
if (pVarPacketloss->GetFVal()>0 || iMaxPing>0)
|
||||
{
|
||||
DelayedPacket2 *delayed = new DelayedPacket2;
|
||||
|
||||
int iRand=0;
|
||||
|
||||
if(iMaxPing>iMinPing)
|
||||
iRand=rand() % (iMaxPing-iMinPing);
|
||||
|
||||
if(iMaxPing>0)
|
||||
delayed->m_fTimeToSend = GetISystem()->GetITimer()->GetCurrTime() + (iMinPing + iRand) / 1000.0f;
|
||||
else
|
||||
delayed->m_fTimeToSend = GetISystem()->GetITimer()->GetCurrTime();
|
||||
delayed->len = BITS2BYTES(stm.GetSize());
|
||||
delayed->address = new CIPAddress(ip);
|
||||
assert(delayed->len < sizeof(delayed->data)/sizeof(delayed->data[0]));
|
||||
memcpy(delayed->data, stm.GetPtr(), delayed->len);
|
||||
m_delayedPacketList.push_back(delayed);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD nSize = BITS2BYTES(stm.GetSize());
|
||||
|
||||
if(NET_SUCCEDED(m_socketMain.Send(stm.GetPtr(), nSize, &ip)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void CServer::OnDestructSlot( const CServerSlot *inpServerSlot )
|
||||
{
|
||||
SLOTS_MAPItr itr = m_mapSlots.begin();
|
||||
|
||||
while (itr != m_mapSlots.end())
|
||||
{
|
||||
CServerSlot *pSlot = itr->second;
|
||||
if(pSlot==inpServerSlot)
|
||||
{
|
||||
m_mapSlots.erase(itr);
|
||||
return;
|
||||
}
|
||||
++itr;
|
||||
}
|
||||
|
||||
assert(0); // can't be
|
||||
}
|
||||
|
||||
void CServer::UnregisterSlot(CIPAddress &ip)
|
||||
{
|
||||
SLOTS_MAPItr itor=m_mapSlots.find(ip);
|
||||
if(itor!=m_mapSlots.end())
|
||||
{
|
||||
IServerSlot *pServerSlot=itor->second;
|
||||
|
||||
pServerSlot->Advise(NULL); // remove connection to IServerSlotSink (CXServerSlot)
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::RegisterLocalServerSlot(CServerSlot *pSlot,CIPAddress &ip)
|
||||
{
|
||||
m_mapSlots.insert(SLOTS_MAPItr::value_type(ip,pSlot));
|
||||
if(m_pFactory)
|
||||
m_pFactory->CreateServerSlot(pSlot);
|
||||
}
|
||||
|
||||
CServerSlot *CServer::GetPacketOwner(CIPAddress &ip)
|
||||
{
|
||||
SLOTS_MAPItr itor;
|
||||
itor=m_mapSlots.find(ip);
|
||||
if(itor==m_mapSlots.end())
|
||||
return 0;
|
||||
return itor->second;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// core
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void TraceUnrecognizedPacket( const char *inszTxt, CStream &stmPacket, CIPAddress &ip)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
OutputDebugString("\n");
|
||||
OutputDebugString(inszTxt);
|
||||
OutputDebugString("\n");
|
||||
|
||||
static char sTemp[1024];
|
||||
static BYTE cBuf[1024];
|
||||
DWORD nCount;
|
||||
::OutputDebugString("-------------------------------\n");
|
||||
sprintf(sTemp,"INVALID PACKET FROM [%s]\n",ip.GetAsString(true));
|
||||
::OutputDebugString(sTemp);
|
||||
stmPacket.GetBuffer(cBuf,1024);
|
||||
nCount=BYTES2BITS(stmPacket.GetSize());
|
||||
for(DWORD n=0;n<nCount;n++)
|
||||
{
|
||||
sprintf(sTemp,"%02X ",cBuf[n]);
|
||||
::OutputDebugString(sTemp);
|
||||
if(n && (n%16)==0)
|
||||
::OutputDebugString("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CServer::ProcessPacket(CStream &stmPacket, CIPAddress &ip)
|
||||
{
|
||||
if (!m_pNetwork->CheckPBPacket( stmPacket,ip ))
|
||||
return;
|
||||
|
||||
CNP cnp;
|
||||
cnp.LoadAndSeekToZero(stmPacket);
|
||||
switch (cnp.m_cFrameType)
|
||||
{
|
||||
// these packets will not be checked for ban
|
||||
// since they are sent just too often,
|
||||
// and would slow down the server
|
||||
// they will be reject anyway, because no banned ip can have a server slot associated with it
|
||||
case FT_CCP_DISCONNECT:
|
||||
case FT_CCP_ACK:
|
||||
case FT_CTP_DATA:
|
||||
case FT_CTP_ACK:
|
||||
case FT_CTP_NAK:
|
||||
case FT_CTP_PONG:
|
||||
DispatchToServerSlots(cnp, stmPacket,ip);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
if (m_pSecuritySink->IsIPBanned(ip.GetAsUINT()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// these packets' ip will be checked for ban
|
||||
// since they are not sent very often
|
||||
switch(cnp.m_cFrameType)
|
||||
{
|
||||
case FT_CCP_CONNECT:
|
||||
case FT_CCP_CONNECT_RESP:
|
||||
case FT_CCP_CONTEXT_READY:
|
||||
case FT_CCP_SECURITY_QUERY:
|
||||
case FT_CCP_SECURITY_RESP:
|
||||
case FT_CCP_PUNK_BUSTER_MSG:
|
||||
DispatchToServerSlots(cnp, stmPacket,ip);
|
||||
break;
|
||||
case FT_CCP_SETUP:
|
||||
ProcessSetup(cnp, stmPacket, ip);
|
||||
break;
|
||||
case FT_CQP_INFO_REQUEST:
|
||||
ProcessInfoRequest(stmPacket, ip);
|
||||
break;
|
||||
case FT_CQP_XML_REQUEST:
|
||||
ProcessInfoXMLRequest(stmPacket,ip);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
TPacketSinks::iterator it = m_PacketSinks.find(cnp.m_cFrameType);
|
||||
|
||||
if(it!=m_PacketSinks.end())
|
||||
{
|
||||
INetworkPacketSink *pSink = (*it).second;
|
||||
|
||||
pSink->OnReceivingPacket(cnp.m_cFrameType,stmPacket,ip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TraceUnrecognizedPacket("ProcessPacket",stmPacket,ip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void CServer::RegisterPacketSink( const unsigned char inID, INetworkPacketSink *inpSink )
|
||||
{
|
||||
assert(m_PacketSinks.count(inID)==0);
|
||||
|
||||
m_PacketSinks[inID] = inpSink;
|
||||
}
|
||||
|
||||
void CServer::SetSecuritySink(IServerSecuritySink *pSecuritySink)
|
||||
{
|
||||
m_pSecuritySink = pSecuritySink;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IServerSecuritySink* CServer::GetSecuritySink()
|
||||
{
|
||||
return m_pSecuritySink;
|
||||
}
|
||||
|
||||
bool CServer::IsIPBanned(const unsigned int dwIP)
|
||||
{
|
||||
if (m_pSecuritySink)
|
||||
{
|
||||
return m_pSecuritySink->IsIPBanned(dwIP);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CServer::BanIP(const unsigned int dwIP)
|
||||
{
|
||||
if (m_pSecuritySink)
|
||||
{
|
||||
m_pSecuritySink->BanIP(dwIP);
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::UnbanIP(const unsigned int dwIP)
|
||||
{
|
||||
if (m_pSecuritySink)
|
||||
{
|
||||
m_pSecuritySink->UnbanIP(dwIP);
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::ProcessMulticastPacket(CStream &stmPacket, CIPAddress &ip)
|
||||
{
|
||||
CNP cnp;
|
||||
cnp.LoadAndSeekToZero(stmPacket);
|
||||
switch (cnp.m_cFrameType)
|
||||
{
|
||||
case FT_CQP_INFO_REQUEST:
|
||||
ProcessInfoRequest(stmPacket, ip);
|
||||
break;
|
||||
case FT_CQP_XML_REQUEST:
|
||||
ProcessInfoXMLRequest(stmPacket,ip);
|
||||
break;
|
||||
default:
|
||||
TraceUnrecognizedPacket("ProcessMulticastPacket",stmPacket,ip);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void CServer::ProcessSetup(CNP &cnp, CStream &stmStream, CIPAddress &ip)
|
||||
{
|
||||
CServerSlot *pSSlot;
|
||||
CServerSlot *pTemp=GetPacketOwner(ip);
|
||||
|
||||
if(pTemp!=NULL)
|
||||
{
|
||||
NET_TRACE("Setup discarded for IP [%s]\n",pTemp->GetIP().GetAsString(true));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pSecuritySink)
|
||||
{
|
||||
if (m_pSecuritySink->IsIPBanned(ip.GetAsUINT()))
|
||||
{
|
||||
NET_TRACE("Setup discarded for IP [%s] (BANNED)\n",ip.GetAsString(true));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NET_TRACE("Setup accepted for IP [%s]\n",ip.GetAsString(true));
|
||||
|
||||
pSSlot = new CServerSlotImpl(m_pNetwork,this);
|
||||
|
||||
/////////////////////////////////////////////////////////!!!!
|
||||
int nID = GenerateNewClientID();
|
||||
/////////////////////////////////////////////////////////!!!!
|
||||
pSSlot->Start((BYTE)nID, ip);
|
||||
|
||||
// build event
|
||||
if (m_pFactory)
|
||||
{
|
||||
if (m_pFactory->CreateServerSlot(pSSlot) == true)
|
||||
{
|
||||
m_mapSlots.insert(SLOTS_MAPItr::value_type(ip, pSSlot));
|
||||
//m_mapIPs.insert(IPS_MAPItr::value_type(ip,nID));
|
||||
|
||||
// if this is a lan server
|
||||
if(m_MPServerType==eMPST_LAN)
|
||||
{
|
||||
if (!IsLANIP(ip))
|
||||
{
|
||||
pSSlot->Disconnect("@LanIPOnly");
|
||||
}
|
||||
}
|
||||
|
||||
// get server password cvar
|
||||
ICVar *sv_password = GetISystem()->GetIConsole()->GetCVar("sv_password");
|
||||
assert(sv_password);
|
||||
|
||||
// check if server is password protected
|
||||
if (sv_password->GetString() && (strlen(sv_password->GetString()) > 0))
|
||||
{
|
||||
CCPSetup pccp;
|
||||
|
||||
pccp.Load(stmStream);
|
||||
|
||||
if (!pccp.m_sPlayerPassword.size() || (strcmp(sv_password->GetString(), pccp.m_sPlayerPassword.c_str()) != 0))
|
||||
{
|
||||
pSSlot->Disconnect("@InvalidServerPassword");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
pSSlot->Update(m_nCurrentTime, &cnp, &stmStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
//<<FIXME>> ?!?!?!?
|
||||
//pSSlot->Update(m_nCurrentTime, &cnp, &stmStream);
|
||||
pSSlot->Disconnect("@ConnectionRejected");
|
||||
//pSSlot->Update(m_nCurrentTime, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CServer::IsLANIP(const CIPAddress &ip)
|
||||
{
|
||||
unsigned char ipb[4];
|
||||
#if defined(LINUX)
|
||||
ipb[0] = ip.m_Address.sin_addr_win.S_un.S_un_b.s_b1;
|
||||
ipb[1] = ip.m_Address.sin_addr_win.S_un.S_un_b.s_b2;
|
||||
ipb[2] = ip.m_Address.sin_addr_win.S_un.S_un_b.s_b3;
|
||||
ipb[3] = ip.m_Address.sin_addr_win.S_un.S_un_b.s_b4;
|
||||
#else
|
||||
ipb[0] = ip.m_Address.sin_addr.S_un.S_un_b.s_b1;
|
||||
ipb[1] = ip.m_Address.sin_addr.S_un.S_un_b.s_b2;
|
||||
ipb[2] = ip.m_Address.sin_addr.S_un.S_un_b.s_b3;
|
||||
ipb[3] = ip.m_Address.sin_addr.S_un.S_un_b.s_b4;
|
||||
#endif
|
||||
|
||||
if (ipb[0] == 127)
|
||||
return true;
|
||||
if (ipb[0] == 10)
|
||||
return true;
|
||||
if ((ipb[0] == 192) && (ipb[1] == 168))
|
||||
return true;
|
||||
if (ipb[0] == 172)
|
||||
if ((ipb[1] >= 16) && (ipb[1] <= 31))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CServer::DispatchToServerSlots(CNP &cnp, CStream &stm, CIPAddress &ip)
|
||||
{
|
||||
SLOTS_MAPItr itr;
|
||||
itr = m_mapSlots.find(ip);
|
||||
if (itr != m_mapSlots.end())
|
||||
{
|
||||
(itr->second)->Update(m_nCurrentTime, &cnp, &stm); // update the server slot
|
||||
}
|
||||
else
|
||||
{
|
||||
NET_TRACE("CServer::DispatchToServerSlots() Unknown client ID\n");
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::ProcessInfoRequest(CStream &stmIn, CIPAddress &ip)
|
||||
{
|
||||
if (stmIn.GetSize() < 32)
|
||||
{
|
||||
return; // must be at least 16bytes(64bits) int
|
||||
}
|
||||
|
||||
CQPInfoRequest Query;
|
||||
CQPInfoResponse Response;
|
||||
CStream stmPacket;
|
||||
|
||||
Query.Load(stmIn); // load and seek to zero
|
||||
stmIn.Seek(0);
|
||||
|
||||
if (!Query.IsOk())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
assert((stmIn.GetSize() % 8) == 0);
|
||||
assert(m_pFactory);
|
||||
|
||||
if (Query.szRequest == "ping")
|
||||
{
|
||||
Response.szResponse = "X";// identify the packet
|
||||
Response.Save(stmPacket);
|
||||
|
||||
assert((stmPacket.GetSize() % 8) == 0);
|
||||
|
||||
if (stmPacket.GetSize())
|
||||
{
|
||||
m_socketMain.Send(stmPacket.GetPtr(), BITS2BYTES(stmPacket.GetSize()), &ip);
|
||||
}
|
||||
}
|
||||
// status
|
||||
else if (Query.szRequest == "status")
|
||||
{
|
||||
#if defined(WIN64) && !defined(NDEBUG)
|
||||
//workarround for bug caused by string reallocation across dll's and not shared crt libs in debug mode
|
||||
Response.szResponse.resize(0);
|
||||
Response.szResponse.reserve(100);
|
||||
Response.szResponse += "S"; // identify the packet
|
||||
#else
|
||||
Response.szResponse = "S"; // identify the packet
|
||||
#endif
|
||||
if (!m_pFactory->GetServerInfoStatus(Response.szResponse))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Response.Save(stmPacket);
|
||||
|
||||
assert((stmPacket.GetSize() % 8) == 0);
|
||||
|
||||
if (stmPacket.GetSize())
|
||||
{
|
||||
m_socketMain.Send(stmPacket.GetPtr(), BITS2BYTES(stmPacket.GetSize()), &ip);
|
||||
}
|
||||
}
|
||||
// rules
|
||||
else if (Query.szRequest == "rules")
|
||||
{
|
||||
Response.szResponse = "R"; // identify the packet
|
||||
|
||||
if (!m_pFactory->GetServerInfoRules(Response.szResponse))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Response.Save(stmPacket);
|
||||
|
||||
assert((stmPacket.GetSize() % 8) == 0);
|
||||
m_socketMain.Send(stmPacket.GetPtr(), BITS2BYTES(stmPacket.GetSize()), &ip);
|
||||
}
|
||||
// players
|
||||
else if (Query.szRequest == "players")
|
||||
{
|
||||
string szString[SERVER_QUERY_MAX_PACKETS];
|
||||
string *vszString[SERVER_QUERY_MAX_PACKETS];
|
||||
int nStrings = 0;
|
||||
|
||||
for (int i = 0; i < SERVER_QUERY_MAX_PACKETS; i++)
|
||||
{
|
||||
vszString[i] = &szString[i];
|
||||
szString[i] = "P";
|
||||
}
|
||||
|
||||
if (!m_pFactory->GetServerInfoPlayers(vszString, nStrings))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int j = 0; j < nStrings; j++)
|
||||
{
|
||||
Response.szResponse = *vszString[j];
|
||||
Response.Save(stmPacket);
|
||||
|
||||
assert((stmPacket.GetSize() % 8) == 0);
|
||||
m_socketMain.Send(stmPacket.GetPtr(), BITS2BYTES(stmPacket.GetSize()), &ip);
|
||||
|
||||
stmPacket.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CServer::ProcessInfoXMLRequest(CStream &stmIn,CIPAddress &ip)
|
||||
{
|
||||
CQPXMLRequest cqpRequest;
|
||||
CQPXMLResponse cqpResponse;
|
||||
|
||||
cqpRequest.Load(stmIn);
|
||||
|
||||
char sResponse[MAX_REQUEST_XML_LENGTH+1];
|
||||
strcpy(sResponse,"");
|
||||
|
||||
// ask the application to process this XML request.
|
||||
if (m_pFactory)
|
||||
{
|
||||
if(!m_pFactory->ProcessXMLInfoRequest( cqpRequest.m_sXML.c_str(),sResponse,sizeof(sResponse)))
|
||||
return;
|
||||
}
|
||||
|
||||
CStream stmOut;
|
||||
cqpResponse.m_sXML = sResponse;
|
||||
cqpResponse.Save(stmOut);
|
||||
|
||||
m_socketMain.Send(stmOut.GetPtr(), BITS2BYTES(stmOut.GetSize()), &ip);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
IServerSlot *CServer::GetServerSlotbyID( const unsigned char ucId ) const
|
||||
{
|
||||
for(SLOTS_MAP::const_iterator it=m_mapSlots.begin();it!=m_mapSlots.end();++it)
|
||||
{
|
||||
if(it->second->GetID()==ucId)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return 0; // not found
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
unsigned char CServer::GenerateNewClientID()
|
||||
{
|
||||
for(unsigned char id=1;id<0xFF;id++) // find a free client id
|
||||
{
|
||||
bool bFree=true;
|
||||
|
||||
for(SLOTS_MAPItr it=m_mapSlots.begin();it!=m_mapSlots.end();++it)
|
||||
{
|
||||
if(it->second->GetID()==id)
|
||||
{
|
||||
bFree=false; // this one is occupied
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bFree)
|
||||
return id; // found one
|
||||
}
|
||||
|
||||
assert(0); // 256 players are already connected ?
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8 CServer::GetMaxClientID() const
|
||||
{
|
||||
uint8 ucMax=0;
|
||||
|
||||
// save solution (slow, but speed is not a concern here)
|
||||
for(SLOTS_MAP::const_iterator it=m_mapSlots.begin();it!=m_mapSlots.end();++it)
|
||||
{
|
||||
uint8 ucId=it->second->GetID();
|
||||
|
||||
if(ucId>ucMax)
|
||||
ucMax=ucId;
|
||||
}
|
||||
|
||||
return ucMax;
|
||||
}
|
||||
|
||||
|
||||
const char *CServer::GetHostName()
|
||||
{
|
||||
return m_socketMain.GetHostName();
|
||||
}
|
||||
|
||||
void CServer::GetMemoryStatistics(ICrySizer *pSizer)
|
||||
{
|
||||
pSizer->AddObject(this,sizeof(CServer));
|
||||
SLOTS_MAPItr itor=m_mapSlots.begin();
|
||||
while(itor!=m_mapSlots.end())
|
||||
{
|
||||
itor->second->GetMemoryStatistics(pSizer);
|
||||
}
|
||||
}
|
||||
151
CryNetwork/Server.h
Normal file
151
CryNetwork/Server.h
Normal file
@@ -0,0 +1,151 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: Server.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef _SERVER_H_
|
||||
#define _SERVER_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "Interfaces.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <list>
|
||||
|
||||
class CServerSlot;
|
||||
class CNetwork;
|
||||
|
||||
#if !defined(LINUX)
|
||||
#pragma warning(disable:4786)
|
||||
#endif
|
||||
|
||||
typedef std::map<CIPAddress,CServerSlot* > SLOTS_MAP;
|
||||
typedef std::map<CIPAddress,CServerSlot* >::iterator SLOTS_MAPItr;
|
||||
|
||||
//#define _INTERNET_SIMULATOR
|
||||
|
||||
class CNetwork;
|
||||
class ICrySizer;
|
||||
|
||||
class CServer :
|
||||
public IServer,
|
||||
public _IServerServices
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CServer(CNetwork *pNetwork);
|
||||
//! destructor
|
||||
virtual ~CServer();
|
||||
|
||||
// interface IServer ------------------------------------------------------------------
|
||||
|
||||
virtual void GetBandwidth( float &fIncomingKbPerSec, float &fOutgoingKbPerSec, DWORD &nIncomingPackets, DWORD &nOutgoingPackets );
|
||||
virtual const char *GetHostName();
|
||||
virtual void Release();
|
||||
virtual void SetVariable(enum CryNetworkVarible eVarName,unsigned int nValue);
|
||||
virtual void Update(unsigned int nTime);
|
||||
virtual void RegisterPacketSink( const unsigned char inPacketID, INetworkPacketSink *inpSink );
|
||||
virtual void SetSecuritySink(IServerSecuritySink *pSecuritySink);
|
||||
virtual IServerSecuritySink* GetSecuritySink();
|
||||
virtual bool IsIPBanned(const unsigned int dwIP);
|
||||
virtual void BanIP(const unsigned int dwIP);
|
||||
virtual void UnbanIP(const unsigned int dwIP);
|
||||
virtual IServerSlot *GetServerSlotbyID( const unsigned char ucId ) const;
|
||||
virtual uint8 GetMaxClientID() const;
|
||||
virtual EMPServerType GetServerType() const;
|
||||
|
||||
// interface _IServerServices ----------------------------------------------------------
|
||||
|
||||
bool Send(CStream &stm,CIPAddress &ip);
|
||||
void UnregisterSlot(CIPAddress &ip);
|
||||
virtual void OnDestructSlot( const CServerSlot *inpServerSlot );
|
||||
void GetProtocolVariables(CNPServerVariables &sv);
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
//!
|
||||
bool Init(IServerSlotFactory *pFactory,WORD nPort, bool local);
|
||||
|
||||
//! return the associated IServerSlotFactory interface
|
||||
IServerSlotFactory *GetServerSlotFactory() { return m_pFactory; };
|
||||
//!
|
||||
CServerSlot *GetPacketOwner(CIPAddress &ip);
|
||||
//!
|
||||
void RegisterLocalServerSlot(CServerSlot *pSlot,CIPAddress &ip);
|
||||
//!
|
||||
void GetMemoryStatistics(ICrySizer *pSizer);
|
||||
|
||||
//! Returns server port.
|
||||
int GetServerPort() { return m_wPort; };
|
||||
|
||||
//! check if an ip address is lan or inet
|
||||
bool IsLANIP(const CIPAddress &ip);
|
||||
|
||||
private:
|
||||
//!
|
||||
void DispatchToServerSlots(CNP &cnp,CStream &stm, CIPAddress &ip);
|
||||
//!
|
||||
void ProcessSetup(CNP &cnp,CStream &stmStream,CIPAddress &ip);
|
||||
//!
|
||||
void ProcessInfoRequest(CStream &stmIn, CIPAddress &ip);
|
||||
void ProcessInfoXMLRequest(CStream &stmIn, CIPAddress &ip);
|
||||
//!
|
||||
void ProcessPacket(CStream &stmPacket,CIPAddress &ip);
|
||||
//!
|
||||
void ProcessMulticastPacket(CStream &stmPacket,CIPAddress &ip);
|
||||
//!
|
||||
unsigned char GenerateNewClientID();
|
||||
|
||||
|
||||
typedef std::map<unsigned char,INetworkPacketSink *> TPacketSinks;
|
||||
|
||||
|
||||
unsigned char m_cLastClientID; //!<
|
||||
CDatagramSocket m_socketMain; //!<
|
||||
CDatagramSocket m_socketMulticast; //!<
|
||||
bool m_bMulticastSocket; //!<
|
||||
|
||||
protected:
|
||||
SLOTS_MAP m_mapSlots; //!<
|
||||
IServerSlotFactory * m_pFactory; //!<
|
||||
|
||||
private:
|
||||
CNPServerVariables m_ServerVariables; //!<
|
||||
|
||||
unsigned int m_nCurrentTime; //!<
|
||||
CNetwork * m_pNetwork; //!<
|
||||
WORD m_wPort; //!<
|
||||
bool m_bListen; //!<
|
||||
IServerSecuritySink *m_pSecuritySink;
|
||||
|
||||
TPacketSinks m_PacketSinks; //!< <inPacketID,callback interface>
|
||||
EMPServerType m_MPServerType; //!< depends on sv_Servertype at Init() time
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
#ifdef _INTERNET_SIMULATOR
|
||||
struct DelayedPacket2
|
||||
{
|
||||
float m_fTimeToSend;
|
||||
BYTE data[8192];
|
||||
int len;
|
||||
CIPAddress *address;
|
||||
};
|
||||
typedef std::list<DelayedPacket2*> TDelayPacketList2;
|
||||
|
||||
TDelayPacketList2 m_delayedPacketList; //!<
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //_SERVER_H_
|
||||
585
CryNetwork/ServerSlot.cpp
Normal file
585
CryNetwork/ServerSlot.cpp
Normal file
@@ -0,0 +1,585 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: ServerSlot.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "CNP.h"
|
||||
#include "ServerSlot.h"
|
||||
#include "ClientLocal.h"
|
||||
#include "Server.h"
|
||||
#include "IGame.h"
|
||||
#include "IDataProbe.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
#include "NewUbisoftClient.h" // NewUbisoftClient
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
#if defined(_DEBUG) && !defined(LINUX)
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CServerSlotImpl::CServerSlotImpl( CNetwork *pNetwork,_IServerServices *pParent)
|
||||
:CServerSlot(pNetwork),m_ctpEndpoint(pNetwork),m_ctpEndpoint2(pNetwork)
|
||||
{
|
||||
m_ccpEndpoint.Init(this);
|
||||
m_smCCPMachine.Init(this);
|
||||
m_pParent = pParent;
|
||||
m_bActive = false;
|
||||
m_dwKeepAliveTimer = 0xFFFFFFFF;
|
||||
m_nCurrentTime = 0; //m_nCurrentTime;
|
||||
pParent->GetProtocolVariables(m_ServerVariables);
|
||||
|
||||
m_bClientAdded = false;
|
||||
|
||||
m_nClientFlags = 0;
|
||||
m_nClientOS_Minor = 0;
|
||||
m_nClientOS_Major = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Generate random public key for this client.
|
||||
GetISystem()->GetIDataProbe()->RandSeed(GetTickCount());
|
||||
m_nPublicKey = GetISystem()->GetIDataProbe()->GetRand();
|
||||
m_ccpEndpoint.SetPublicCryptKey( m_nPublicKey );
|
||||
m_ctpEndpoint.SetPublicCryptKey( m_nPublicKey );
|
||||
m_ctpEndpoint2.SetPublicCryptKey( m_nPublicKey );
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
CServerSlotImpl::~CServerSlotImpl()
|
||||
{
|
||||
m_pParent->OnDestructSlot(this);
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::IsActive()
|
||||
{
|
||||
return m_bActive;
|
||||
}
|
||||
|
||||
void CServerSlotImpl::Disconnect(const char *szCause)
|
||||
{
|
||||
m_smCCPMachine.Update(SIG_SRV_ACTIVE_DISCONNECT, (DWORD_PTR)szCause);
|
||||
SendDisconnect(szCause);
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::ContextSetup(CStream &stm)
|
||||
{
|
||||
m_stmContext = stm;
|
||||
m_smCCPMachine.Update(SIG_SRV_CONTEXT_SETUP);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int CServerSlotImpl::GetUnreliablePacketsLostCount()
|
||||
{
|
||||
return m_ctpEndpoint.GetUnreliableLostPackets();
|
||||
}
|
||||
|
||||
void CServerSlotImpl::SendReliable(CStream &stm,bool bSecondaryChannel)
|
||||
{
|
||||
m_BandwidthStats.m_nReliablePacketCount++;
|
||||
m_BandwidthStats.m_nReliableBitCount+=stm.GetSize();
|
||||
|
||||
if(bSecondaryChannel)
|
||||
m_ctpEndpoint2.SendReliable(stm);
|
||||
else
|
||||
m_ctpEndpoint.SendReliable(stm);
|
||||
}
|
||||
|
||||
void CServerSlotImpl::SendUnreliable(CStream &stm)
|
||||
{
|
||||
m_BandwidthStats.m_nUnreliablePacketCount++;
|
||||
m_BandwidthStats.m_nUnreliableBitCount+=stm.GetSize();
|
||||
|
||||
m_ctpEndpoint.SendUnreliable(stm);
|
||||
}
|
||||
|
||||
|
||||
void CServerSlotImpl::Update(unsigned int nTime, CNP *pCNP, CStream *pStream)
|
||||
{
|
||||
m_nCurrentTime = nTime;
|
||||
|
||||
if (pCNP)
|
||||
{
|
||||
// avoid useless packet parsing
|
||||
if(m_smCCPMachine.GetCurrentStatus() != STATUS_SRV_DISCONNECTED)
|
||||
{
|
||||
ProcessPacket(pCNP->m_cFrameType,pCNP->m_bSecondaryTC, pStream);
|
||||
m_dwKeepAliveTimer = m_nCurrentTime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ccpEndpoint.Update(m_nCurrentTime, NULL, NULL);
|
||||
m_smCCPMachine.Update();
|
||||
|
||||
if (/*m_smCCPMachine.GetCurrentStatus() == STATUS_CONNECTED ||*/ m_smCCPMachine.GetCurrentStatus() == STATUS_SRV_READY)
|
||||
{
|
||||
static char szCause[] = "@ClientTimeout";
|
||||
m_ctpEndpoint.Update(m_nCurrentTime, NULL, NULL);
|
||||
m_ctpEndpoint2.Update(m_nCurrentTime, NULL, NULL);
|
||||
// after n seconds without any incoming packets the connection will be considered lost
|
||||
if(m_ServerVariables.nDataStreamTimeout && GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))
|
||||
if (m_nCurrentTime - m_dwKeepAliveTimer>m_ServerVariables.nDataStreamTimeout)
|
||||
Disconnect(szCause);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwKeepAliveTimer = m_nCurrentTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::IsReady()
|
||||
{
|
||||
return (m_smCCPMachine.GetCurrentStatus() == STATUS_SRV_READY)?true:false;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CServerSlotImpl::GetPing()
|
||||
{
|
||||
return m_ctpEndpoint.GetPing();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//_IServerSlotServices
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CServerSlotImpl::Start(unsigned char cClientID, CIPAddress &ip)
|
||||
{
|
||||
m_ipAddress = ip;
|
||||
m_bActive = true;
|
||||
m_cClientID = cClientID;
|
||||
m_ctpEndpoint.Init(this,false);
|
||||
m_ctpEndpoint2.Init(this,true);
|
||||
m_ccpEndpoint.Init(this);
|
||||
// m_smCCPMachine.Update(SIG_SETUP);
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::Send(CStream &stm)
|
||||
{
|
||||
m_pParent->Send(stm, m_ipAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::SendConnect()
|
||||
{
|
||||
CNPServerVariables sv;
|
||||
m_pParent->GetProtocolVariables(sv);
|
||||
sv.nPublicKey = m_nPublicKey;
|
||||
m_ccpEndpoint.SendConnect(sv);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::SendContextSetup()
|
||||
{
|
||||
// GetISystem()->GetILog()->Log("CServerSlotImpl::SendContextSetup");
|
||||
|
||||
m_ccpEndpoint.SendContextSetup(m_stmContext);
|
||||
// reset the data layer (CTP)
|
||||
m_ctpEndpoint.Reset();
|
||||
m_ctpEndpoint2.Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CServerSlotImpl::SendServerReady()
|
||||
{
|
||||
// GetISystem()->GetILog()->Log("CServerSlotImpl::SendServerReady");
|
||||
m_ccpEndpoint.SendServerReady();
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CServerSlotImpl::SendSecurityQuery(CStream &stm)
|
||||
{
|
||||
m_ccpEndpoint.SendSecurityQuery(stm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CServerSlotImpl::SendPunkBusterMsg(CStream &stm)
|
||||
{
|
||||
m_ccpEndpoint.SendPunkBusterMsg(stm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CServerSlotImpl::SendDisconnect(const char *szCause)
|
||||
{
|
||||
m_ccpEndpoint.SendDisconnect(szCause);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnConnect()
|
||||
{
|
||||
NET_ASSERT(m_pSink);
|
||||
if(m_pSink)
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// If its a multiplayer game check the cdkey
|
||||
if(GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))
|
||||
m_pNetwork->m_pUbiSoftClient->Server_CheckPlayerAuthorizationID(GetID(),m_pbAuthorizationID);
|
||||
else
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
{
|
||||
m_pSink->OnXPlayerAuthorization(true,"",NULL,0);
|
||||
}
|
||||
|
||||
m_pSink->OnXServerSlotConnect(m_pbAuthorizationID,m_uiAuthorizationSize);
|
||||
}
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnContextReady()
|
||||
{
|
||||
// GetISystem()->GetILog()->Log("CServerSlotImpl::OnContextReady");
|
||||
if (m_pSink)
|
||||
m_pSink->OnContextReady(m_stmContextReady);
|
||||
SendServerReady();
|
||||
|
||||
// Run Checks for this client.
|
||||
if (!m_bClientAdded)
|
||||
m_pNetwork->AddClientToDefenceWall( m_ipAddress );
|
||||
m_bClientAdded = true;
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnData(CStream &stm)
|
||||
{
|
||||
if (m_pSink)
|
||||
m_pSink->OnData(stm);
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnDisconnect(const char *szCause)
|
||||
{
|
||||
m_pNetwork->RemoveClientFromDefenceWall( m_ipAddress );
|
||||
|
||||
if (m_pSink)
|
||||
{
|
||||
if(szCause==NULL)
|
||||
szCause="Undefined";
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
m_pNetwork->m_pUbiSoftClient->Server_RemovePlayer(GetID());
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
|
||||
m_pSink->OnXServerSlotDisconnect(szCause);
|
||||
}
|
||||
m_pParent->UnregisterSlot(GetIP());
|
||||
m_bActive = 0;
|
||||
}
|
||||
|
||||
|
||||
void CServerSlotImpl::Release()
|
||||
{
|
||||
assert(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnCCPSetup(CStream &stm)
|
||||
{
|
||||
CCPSetup ccpSetup;
|
||||
ccpSetup.Load(stm);
|
||||
bool versiomatch = !(ccpSetup.m_cProtocolVersion!=CNP_VERSION);
|
||||
|
||||
m_nClientFlags = ccpSetup.m_nClientFlags;
|
||||
m_nClientOS_Minor = ccpSetup.m_nClientOSMinor;
|
||||
m_nClientOS_Major = ccpSetup.m_nClientOSMajor;
|
||||
|
||||
// Can report here what OS client is running.
|
||||
|
||||
// warning this is never called(look at CServerSlotImpl::Start() )
|
||||
m_smCCPMachine.Update(SIG_SRV_SETUP,versiomatch?1:0);
|
||||
|
||||
// kick a player that tries to join the server, with cheats enabled
|
||||
if ((m_nClientFlags & CLIENT_FLAGS_DEVMODE) && !GetISystem()->WasInDevMode())
|
||||
{
|
||||
Disconnect("@Kicked");
|
||||
}
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnCCPConnectResp(CStream &stm)
|
||||
{
|
||||
unsigned int uiSize = stm.GetSize();
|
||||
|
||||
if (uiSize)
|
||||
{
|
||||
assert(uiSize%8==0);
|
||||
m_pbAuthorizationID = new BYTE[uiSize/8];
|
||||
stm.ReadBits(m_pbAuthorizationID,uiSize);
|
||||
m_uiAuthorizationSize = uiSize/8;
|
||||
}
|
||||
m_smCCPMachine.Update(SIG_SRV_CONNECT_RESP);
|
||||
|
||||
m_pNetwork->ValidateClient(this);
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnCCPContextReady(CStream &stm)
|
||||
{
|
||||
m_stmContextReady = stm;
|
||||
m_smCCPMachine.Update(SIG_SRV_CONTEXT_READY);
|
||||
}
|
||||
|
||||
void CServerSlotImpl::OnCCPDisconnect(const char *szCause)
|
||||
{
|
||||
m_smCCPMachine.Update(SIG_SRV_DISCONNECT, (DWORD_PTR)szCause);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CServerSlotImpl::ProcessPacket(unsigned char cFrameType,bool bSTC, CStream *pStream)
|
||||
{
|
||||
switch (cFrameType)
|
||||
{
|
||||
// signaling
|
||||
case FT_CCP_SETUP:
|
||||
case FT_CCP_CONNECT_RESP:
|
||||
case FT_CCP_CONTEXT_READY:
|
||||
case FT_CCP_DISCONNECT:
|
||||
case FT_CCP_ACK:
|
||||
case FT_CCP_SECURITY_QUERY:
|
||||
case FT_CCP_SECURITY_RESP:
|
||||
case FT_CCP_PUNK_BUSTER_MSG:
|
||||
m_ccpEndpoint.Update(m_nCurrentTime, cFrameType, pStream);
|
||||
break;
|
||||
// transport
|
||||
case FT_CTP_DATA:
|
||||
case FT_CTP_ACK:
|
||||
case FT_CTP_NAK:
|
||||
case FT_CTP_PONG:
|
||||
if(bSTC)
|
||||
{
|
||||
// ::OutputDebugString("<<NET LOW>>Packet received in secondary channel\n");
|
||||
m_ctpEndpoint2.Update(m_nCurrentTime, cFrameType, pStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ctpEndpoint.Update(m_nCurrentTime, cFrameType, pStream);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void CServerSlot::ResetBandwidthStats()
|
||||
{
|
||||
m_BandwidthStats.Reset();
|
||||
}
|
||||
|
||||
void CServerSlot::GetBandwidthStats( SServerSlotBandwidthStats &out ) const
|
||||
{
|
||||
out=m_BandwidthStats;
|
||||
}
|
||||
|
||||
|
||||
void CServerSlotImpl::GetMemoryStatistics(ICrySizer *pSizer)
|
||||
{
|
||||
pSizer->AddObject(this,sizeof(CServerSlotImpl));
|
||||
m_ctpEndpoint.GetMemoryStatistics(pSizer);
|
||||
m_ccpEndpoint.GetMemoryStatistics(pSizer);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CServerSlotImpl::OnCCPSecurityQuery(CStream &stm)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CServerSlotImpl::OnCCPSecurityResp(CStream &stm)
|
||||
{
|
||||
// Notify defence wall
|
||||
m_pNetwork->OnSecurityMsgResponse( m_ipAddress,stm );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CServerSlotImpl::OnCCPPunkBusterMsg(CStream &stm)
|
||||
{
|
||||
m_pNetwork->OnCCPPunkBusterMsg( m_ipAddress,stm );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//FAKE SERVERSLOT IMPLEMENTATION
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CServerSlotLocal::CServerSlotLocal(CServer *pServer,CClientLocal *pClient,CIPAddress &ip,CNetwork *pNetwork )
|
||||
:CServerSlot(pNetwork)
|
||||
{
|
||||
m_cClientID=0;
|
||||
m_pClient=pClient;
|
||||
m_pServer=pServer;
|
||||
m_ipAddress=ip;
|
||||
m_bContextSetup=false;
|
||||
m_nUpdateCounter=0;
|
||||
m_bClientAdded = false;
|
||||
}
|
||||
|
||||
CServerSlotLocal::~CServerSlotLocal()
|
||||
{
|
||||
if(m_pServer==NULL)
|
||||
{
|
||||
//call alberto
|
||||
NET_ASSERT(0);
|
||||
}
|
||||
|
||||
m_pNetwork->RemoveClientFromDefenceWall( m_ipAddress );
|
||||
|
||||
m_pServer->OnDestructSlot(this);
|
||||
if(m_pClient)
|
||||
{
|
||||
m_pClient->OnDestructServerSlot();
|
||||
}
|
||||
}
|
||||
|
||||
void CServerSlotLocal::Disconnect(const char *szCause)
|
||||
{
|
||||
if(m_pSink)
|
||||
m_pSink->OnXServerSlotDisconnect(szCause);
|
||||
|
||||
if(m_pClient)
|
||||
m_pClient->OnDisconnenct(szCause);
|
||||
}
|
||||
|
||||
void CServerSlotLocal::OnDisconnect(const char *szCause)
|
||||
{
|
||||
m_pNetwork->RemoveClientFromDefenceWall( m_ipAddress );
|
||||
}
|
||||
|
||||
bool CServerSlotLocal::ContextSetup(CStream &stm)
|
||||
{
|
||||
//queue a context setup and
|
||||
//the m_nUpdateCounter make sure
|
||||
//that there will be 4 updates of delay
|
||||
//before the local client receive this packet.
|
||||
//This avoid that the client start to
|
||||
//play before the local server is ready(hack?)
|
||||
m_bContextSetup=true;
|
||||
m_nUpdateCounter=0;
|
||||
m_stmContextSetup=stm;
|
||||
|
||||
// Run Checks for this client.
|
||||
if (!m_bClientAdded)
|
||||
m_pNetwork->AddClientToDefenceWall( m_ipAddress );
|
||||
m_bClientAdded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CServerSlotLocal::OnContextReady()
|
||||
{
|
||||
}
|
||||
|
||||
void CServerSlotLocal::SendReliable(CStream &stm,bool bSecondaryChannel)
|
||||
{
|
||||
if(m_pClient)
|
||||
m_pClient->PushData(stm);
|
||||
}
|
||||
|
||||
void CServerSlotLocal::SendUnreliable(CStream &stm)
|
||||
{
|
||||
if(m_pClient)
|
||||
m_pClient->PushData(stm);
|
||||
}
|
||||
|
||||
|
||||
void CServerSlotLocal::PushData(CStream &stm)
|
||||
{
|
||||
m_qData.push(stm);
|
||||
}
|
||||
|
||||
|
||||
void CServerSlotLocal::Release()
|
||||
{
|
||||
assert(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
void CServerSlotLocal::UpdateSlot()
|
||||
{
|
||||
if(m_bContextSetup)
|
||||
{
|
||||
if(m_nUpdateCounter>4)
|
||||
{
|
||||
if(m_pClient)
|
||||
m_pClient->OnContextSetup(m_stmContextSetup);
|
||||
|
||||
m_bContextSetup=false;
|
||||
m_nUpdateCounter=0;
|
||||
}
|
||||
else
|
||||
m_nUpdateCounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(!m_qData.empty())
|
||||
{
|
||||
if(m_pSink)
|
||||
m_pSink->OnData(m_qData.front());
|
||||
|
||||
m_qData.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CServerSlotLocal::GetMemoryStatistics(ICrySizer *pSizer)
|
||||
{
|
||||
pSizer->AddObject(this,sizeof(CServerSlotLocal));
|
||||
pSizer->AddObject(&m_qData,m_qData.size()*sizeof(CStream));
|
||||
}
|
||||
|
||||
void CServerSlotLocal::OnCCPConnectResp(CStream &stm)
|
||||
{
|
||||
unsigned int uiSize;
|
||||
|
||||
stm.Read(uiSize);
|
||||
if (uiSize)
|
||||
{
|
||||
assert(uiSize%8==0);
|
||||
m_pbAuthorizationID = new BYTE[uiSize/8];
|
||||
stm.ReadBits(m_pbAuthorizationID,uiSize);
|
||||
m_uiAuthorizationSize = uiSize/8;
|
||||
}
|
||||
|
||||
if(m_pSink)
|
||||
{
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
// If its a multiplayer game check the cdkey
|
||||
if(GetISystem()->GetIGame()->GetModuleState(EGameMultiplayer))
|
||||
m_pNetwork->m_pUbiSoftClient->Server_CheckPlayerAuthorizationID(GetID(),m_pbAuthorizationID);
|
||||
else
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
{
|
||||
m_pSink->OnXPlayerAuthorization(true,"",NULL,0);
|
||||
}
|
||||
|
||||
m_pSink->OnXServerSlotConnect(m_pbAuthorizationID,m_uiAuthorizationSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CServerSlot::OnPlayerAuthorization( bool bAllow, const char *szError, const BYTE *pGlobalID,
|
||||
unsigned int uiGlobalIDSize )
|
||||
{
|
||||
m_pSink->OnXPlayerAuthorization(bAllow,szError,pGlobalID,uiGlobalIDSize);
|
||||
m_pbGlobalID = new BYTE[uiGlobalIDSize];
|
||||
m_uiGlobalIDSize = uiGlobalIDSize;
|
||||
memcpy( m_pbGlobalID,pGlobalID,uiGlobalIDSize );
|
||||
}
|
||||
281
CryNetwork/ServerSlot.h
Normal file
281
CryNetwork/ServerSlot.h
Normal file
@@ -0,0 +1,281 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: ServerSlot.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef _SERVER_SLOT_H_
|
||||
#define _SERVER_SLOT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include "Interfaces.h"
|
||||
#include "ServerStateMachine.h"
|
||||
#ifdef NO_GNB
|
||||
#include "CTPEndpoint.h"
|
||||
#else
|
||||
#include "CTPEndpointGNB.h"
|
||||
#endif
|
||||
#include "CCPEndpoint.h"
|
||||
#include "Network.h"
|
||||
|
||||
class ICrySizer;
|
||||
//
|
||||
// CServerSlot is released by the CXServerSlot
|
||||
//
|
||||
|
||||
class CServerSlot :public IServerSlot, public _IServerSlotServices
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CServerSlot( CNetwork *pNetwork ) :m_pbAuthorizationID(NULL), m_pSink(0), m_pNetwork(pNetwork)
|
||||
{
|
||||
m_BandwidthStats.Reset();
|
||||
m_pbGlobalID = 0;
|
||||
}
|
||||
|
||||
//! destructor
|
||||
virtual ~CServerSlot()
|
||||
{
|
||||
if (m_pbAuthorizationID)
|
||||
delete [] m_pbAuthorizationID;
|
||||
if (m_pbGlobalID)
|
||||
delete [] m_pbGlobalID;
|
||||
};
|
||||
|
||||
virtual bool IsActive() = 0;
|
||||
virtual void Unlink() = 0;
|
||||
virtual void Update(unsigned int nTime,CNP *pCNP ,CStream *pStream) = 0;
|
||||
virtual CIPAddress &GetIP(){ return m_ipAddress; }
|
||||
virtual void GetMemoryStatistics(ICrySizer *pSizer)=0;
|
||||
virtual bool SendSecurityQuery(CStream &stm) { return true;};
|
||||
virtual bool SendPunkBusterMsg(CStream &stm) { return true; };
|
||||
|
||||
// interface IServerSlot -------------------------------------------------------
|
||||
|
||||
virtual void Advise( IServerSlotSink *pSink ) { m_pSink = pSink; }
|
||||
virtual void ResetBandwidthStats();
|
||||
virtual void GetBandwidthStats( SServerSlotBandwidthStats &out ) const;
|
||||
virtual unsigned int GetClientIP() const { return m_ipAddress.GetAsUINT(); };
|
||||
virtual void OnPlayerAuthorization( bool bAllow, const char *szError, const BYTE *pGlobalID,
|
||||
unsigned int uiGlobalIDSize );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Returns client specific flags.
|
||||
virtual unsigned int GetClientFlags() { return 0; };
|
||||
|
||||
virtual bool IsLocalSlot() const { return false; };
|
||||
|
||||
public: // -----------------------------------------------------------------------
|
||||
|
||||
BYTE * m_pbAuthorizationID; //!< CD Key AuthorizationID (use new and delete)
|
||||
unsigned int m_uiAuthorizationSize; //!< Size of AuthorizationID in bytes
|
||||
|
||||
BYTE * m_pbGlobalID; //!< CD Key GlobalID (use new and delete)
|
||||
unsigned int m_uiGlobalIDSize; //!< Size of GlobalID in bytes
|
||||
|
||||
protected: // --------------------------------------------------------------------
|
||||
|
||||
CNetwork * m_pNetwork; //!<
|
||||
CIPAddress m_ipAddress; //!<
|
||||
unsigned char m_cClientID; //!< //<<FIXME>> this can be removed in future
|
||||
|
||||
SServerSlotBandwidthStats m_BandwidthStats; //!< used for bandwidth calculations (to adjust the bandwidth)
|
||||
IServerSlotSink * m_pSink; //!< connected CXServerSlot (game specific part)
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//CServerSlot implementation
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
class CServerSlotImpl :public CServerSlot
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CServerSlotImpl( CNetwork *pNetwork,_IServerServices *pParent);
|
||||
//! destructor
|
||||
virtual ~CServerSlotImpl();
|
||||
//!
|
||||
void GetMemoryStatistics(ICrySizer *pSizer);
|
||||
|
||||
public: // --------------------------------------------------------------
|
||||
|
||||
//!
|
||||
bool IsActive();
|
||||
//!
|
||||
void Update(unsigned int nTime,CNP *pCNP ,CStream *pStream);
|
||||
//! unlink from the local server
|
||||
void Unlink(){ m_pParent=NULL;}
|
||||
|
||||
// interface IServerSlot -------------------------------------------------------
|
||||
|
||||
virtual void Disconnect(const char *szCause);
|
||||
virtual bool ContextSetup(CStream &stm);
|
||||
virtual void SendReliable(CStream &stm,bool bSecondaryChannel);
|
||||
virtual void SendUnreliable(CStream &stm);
|
||||
virtual bool IsReady();
|
||||
virtual void Release();
|
||||
virtual unsigned int GetPacketsLostCount(){return m_ctpEndpoint.GetLostPackets();}
|
||||
virtual unsigned int GetUnreliablePacketsLostCount();
|
||||
virtual unsigned int GetPing();
|
||||
virtual unsigned char GetID(){return m_cClientID;}
|
||||
|
||||
// interface _IServerSlotServices ----------------------------------------------
|
||||
|
||||
virtual void OnConnect();
|
||||
virtual void OnContextReady();
|
||||
virtual void OnDisconnect(const char *szCause);
|
||||
virtual bool SendConnect();
|
||||
virtual bool SendContextSetup();
|
||||
virtual bool SendDisconnect(const char *szCause);
|
||||
virtual bool SendServerReady();
|
||||
virtual bool SendSecurityQuery(CStream &stm);
|
||||
virtual bool SendPunkBusterMsg(CStream &stm);
|
||||
virtual void Start(unsigned char cClientID,CIPAddress &ip);
|
||||
|
||||
// interface _IEndpointUser ----------------------------------------------------
|
||||
|
||||
virtual bool Send(CStream &stm);
|
||||
virtual void OnData(CStream &stm);
|
||||
|
||||
// interface _ICCPUser ---------------------------------------------------------
|
||||
|
||||
virtual void OnCCPSetup(CStream &stm);
|
||||
virtual void OnCCPConnect(CStream &stm){}
|
||||
virtual void OnCCPConnectResp(CStream &stm);
|
||||
virtual void OnCCPContextSetup(CStream &stm){}
|
||||
virtual void OnCCPContextReady(CStream &stm);
|
||||
virtual void OnCCPServerReady(){}
|
||||
virtual void OnCCPDisconnect(const char *szCause);
|
||||
virtual void OnCCPSecurityQuery(CStream &stm);
|
||||
virtual void OnCCPSecurityResp(CStream &stm);
|
||||
virtual void OnCCPPunkBusterMsg(CStream &stm);
|
||||
|
||||
virtual unsigned int GetClientFlags() { return m_nClientFlags; };
|
||||
|
||||
virtual bool IsLocalSlot() const { return false; };
|
||||
|
||||
private: // --------------------------------------------------------------------------
|
||||
|
||||
void ProcessPacket(unsigned char cFrameType,bool bSTC,CStream *pStream);
|
||||
|
||||
CServerStateMachine m_smCCPMachine; //!<
|
||||
#ifdef NO_GNB
|
||||
CCTPServer m_ctpEndpoint; //!<
|
||||
#else
|
||||
CCTPEndpointGNB m_ctpEndpoint; //!<
|
||||
CCTPEndpointGNB m_ctpEndpoint2; //!<
|
||||
#endif
|
||||
CCCPEndpoint m_ccpEndpoint; //!<
|
||||
|
||||
DWORD m_dwKeepAliveTimer; //!< after 3 second without any incoming packets the connection will be considered lost
|
||||
|
||||
bool m_bActive; //!<
|
||||
bool m_bClientAdded;
|
||||
|
||||
CStream m_stmContextReady; //!<
|
||||
|
||||
_IServerServices * m_pParent; //!<
|
||||
CStream m_stmContext; //!<
|
||||
|
||||
struct CNPServerVariables m_ServerVariables; //!<
|
||||
|
||||
unsigned int m_nCurrentTime; //!<
|
||||
unsigned int m_nPublicKey; //!<
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Client info.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Client OS.
|
||||
unsigned m_nClientOS_Minor; //!<
|
||||
unsigned m_nClientOS_Major; //!<
|
||||
// Client flags.
|
||||
unsigned int m_nClientFlags; //!<
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
class CClientLocal;
|
||||
class CServer;
|
||||
|
||||
//! fake CServerSlot implementation for local clients, doesn't use the network!*/
|
||||
class CServerSlotLocal :public CServerSlot
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CServerSlotLocal(CServer *pServer,CClientLocal *pClient,CIPAddress &ip,CNetwork *pNetwork );
|
||||
//! destructor
|
||||
virtual ~CServerSlotLocal();
|
||||
|
||||
void GetMemoryStatistics(ICrySizer *pSizer);
|
||||
|
||||
bool IsActive(){return true;}
|
||||
void Update(unsigned int nTime,CNP *pCNP ,CStream *pStream){};
|
||||
void PushData(CStream &stm);
|
||||
void UpdateSlot();
|
||||
void Unlink(){ m_pServer=NULL; }
|
||||
void ResetSink() { m_pClient=NULL; if(m_pSink)m_pSink->OnXServerSlotDisconnect(""); }
|
||||
|
||||
// interface IServerSlot ---------------------------------------------------
|
||||
|
||||
virtual void Disconnect(const char *szCause);
|
||||
virtual bool ContextSetup(CStream &stm);
|
||||
virtual void SendReliable(CStream &stm,bool bSecondaryChannel);
|
||||
virtual void SendUnreliable(CStream &stm);
|
||||
virtual bool IsReady(){ return ((m_pClient && m_pSink)?true:false); }
|
||||
virtual void Release();
|
||||
virtual unsigned int GetPacketsLostCount(){return 0;}
|
||||
virtual unsigned int GetUnreliablePacketsLostCount(){return 0;}
|
||||
virtual unsigned int GetPing(){return 0;}
|
||||
virtual unsigned char GetID(){return m_cClientID;}
|
||||
|
||||
// interface _IServerSlotServices ------------------------------------------
|
||||
|
||||
virtual void OnConnect(){}
|
||||
virtual void OnContextReady();
|
||||
virtual void OnDisconnect(const char *szCause);
|
||||
virtual bool SendConnect(){return true;}
|
||||
virtual bool SendContextSetup(){return true;}
|
||||
virtual bool SendDisconnect(const char *szCause){return true;}
|
||||
virtual bool SendServerReady(){return true;}
|
||||
virtual void Start(unsigned char cClientID,CIPAddress &ip){}
|
||||
|
||||
// interface _IEndpointUser ----------------------------------------------------
|
||||
|
||||
virtual bool Send(CStream &stm) { return true; }
|
||||
virtual void OnData(CStream &stm) {}
|
||||
|
||||
// interface _ICCPUser ----------------------------------------------------
|
||||
|
||||
virtual void OnCCPSetup(CStream &stm){};
|
||||
virtual void OnCCPConnect(CStream &stm){};
|
||||
virtual void OnCCPConnectResp(CStream &stm);
|
||||
virtual void OnCCPContextSetup(CStream &stm){};
|
||||
virtual void OnCCPContextReady(CStream &stm){ if(m_pSink)m_pSink->OnContextReady(stm); };
|
||||
virtual void OnCCPServerReady(){};
|
||||
virtual void OnCCPDisconnect(const char *szCause){ if(m_pSink)m_pSink->OnXServerSlotDisconnect(szCause); };
|
||||
virtual void OnCCPSecurityQuery(CStream &stm) {};
|
||||
virtual void OnCCPSecurityResp(CStream &stm) {};
|
||||
virtual void OnCCPPunkBusterMsg(CStream &stm) {};
|
||||
|
||||
virtual bool IsLocalSlot() const { return true; };
|
||||
|
||||
private: // -----------------------------------------------------------------
|
||||
|
||||
CClientLocal * m_pClient; //!<
|
||||
CServer * m_pServer; //!<
|
||||
bool m_bReady; //!<
|
||||
STREAM_QUEUE m_qData; //!<
|
||||
bool m_bContextSetup; //!<
|
||||
CStream m_stmContextSetup; //!<
|
||||
int m_nUpdateCounter; //!<
|
||||
bool m_bClientAdded; //!<
|
||||
};
|
||||
#endif // _SERVER_SLOT_H_
|
||||
86
CryNetwork/ServerSnooper.cpp
Normal file
86
CryNetwork/ServerSnooper.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "stdafx.h"
|
||||
#include "CNP.h"
|
||||
#include "serversnooper.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CServerSnooper::CServerSnooper(void)
|
||||
{
|
||||
m_pSink=NULL;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
CServerSnooper::~CServerSnooper(void)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool CServerSnooper::Init(IServerSnooperSink *pSink)
|
||||
{
|
||||
m_pSink=pSink;
|
||||
if(NET_FAILED(m_socket.Create()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CServerSnooper::SearchForLANServers(unsigned int nTime)
|
||||
{
|
||||
CStream stm;
|
||||
CQPInfoRequest cqpInfoRequest("status");
|
||||
|
||||
CIPAddress ipMulticastAddress(SERVER_MULTICAST_PORT,SERVER_MULTICAST_ADDRESS);
|
||||
cqpInfoRequest.Save(stm);
|
||||
m_nStartTime=nTime;
|
||||
m_socket.Send(stm.GetPtr(),BITS2BYTES(stm.GetSize()),&ipMulticastAddress);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CServerSnooper::Update(unsigned int nTime)
|
||||
{
|
||||
int nRecvBytes;
|
||||
m_nCurrentTime=nTime;
|
||||
static CStream buf;
|
||||
static CIPAddress ipFrom;
|
||||
do{
|
||||
buf.Reset();
|
||||
nRecvBytes=0;
|
||||
m_socket.Receive(buf.GetPtr(),
|
||||
(int)BITS2BYTES(buf.GetAllocatedSize()),
|
||||
nRecvBytes,
|
||||
ipFrom);
|
||||
/////////////////////////////////////////////////////////
|
||||
if(nRecvBytes>0)
|
||||
{
|
||||
buf.SetSize(BYTES2BITS(nRecvBytes));
|
||||
ProcessPacket(buf,ipFrom);
|
||||
}
|
||||
}while(nRecvBytes>0);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void CServerSnooper::ProcessPacket(CStream &stmPacket,CIPAddress &ip)
|
||||
{
|
||||
CNP cnp;
|
||||
cnp.LoadAndSeekToZero(stmPacket);
|
||||
|
||||
if(cnp.m_cFrameType == FT_CQP_INFO_RESPONSE)
|
||||
{
|
||||
CQPInfoResponse cqpInfoResponse;
|
||||
|
||||
cqpInfoResponse.Load(stmPacket);
|
||||
|
||||
if(m_pSink)
|
||||
m_pSink->OnServerFound(ip, cqpInfoResponse.szResponse, m_nCurrentTime-m_nStartTime);
|
||||
}
|
||||
}
|
||||
26
CryNetwork/ServerSnooper.h
Normal file
26
CryNetwork/ServerSnooper.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _SERVERSNOOPER_H_
|
||||
#define _SERVERSNOOPER_H_
|
||||
|
||||
#include <INetwork.h>
|
||||
class CServerSnooper :
|
||||
public IServerSnooper
|
||||
{
|
||||
public:
|
||||
CServerSnooper(void);
|
||||
virtual ~CServerSnooper(void);
|
||||
bool Init(IServerSnooperSink *pSink);
|
||||
public:
|
||||
//IServerSnooper
|
||||
void SearchForLANServers(unsigned int nTime);
|
||||
void Update(unsigned int nTime);
|
||||
void Release(){delete this;}
|
||||
protected:
|
||||
void ProcessPacket(CStream &stmPacket,CIPAddress &ip);
|
||||
private:
|
||||
CDatagramSocket m_socket;
|
||||
unsigned int m_nStartTime;
|
||||
unsigned int m_nCurrentTime;
|
||||
IServerSnooperSink *m_pSink;
|
||||
};
|
||||
|
||||
#endif //_SERVERSNOOPER_H_
|
||||
244
CryNetwork/ServerStateMachine.cpp
Normal file
244
CryNetwork/ServerStateMachine.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: ServerStateMachine.cpp
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ServerStateMachine.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#define DEBUG_CLIENTBLOCK new( _NORMAL_BLOCK, THIS_FILE, __LINE__)
|
||||
#define new DEBUG_CLIENTBLOCK
|
||||
#endif
|
||||
|
||||
#include "IConsole.h" // IConsole
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CServerStateMachine::CServerStateMachine()
|
||||
{
|
||||
m_pParent=0;
|
||||
}
|
||||
|
||||
CServerStateMachine::~CServerStateMachine()
|
||||
{
|
||||
}
|
||||
|
||||
void CServerStateMachine::_Trace(char *s)
|
||||
{
|
||||
NET_TRACE(s);
|
||||
}
|
||||
|
||||
void CServerStateMachine::_TraceStatus(unsigned int dwStatus)
|
||||
{
|
||||
switch (dwStatus)
|
||||
{
|
||||
case STATUS_IDLE:
|
||||
_Trace("STATUS_IDLE");
|
||||
break;
|
||||
case STATUS_SRV_WAIT_FOR_CONNECT_RESP:
|
||||
_Trace("STATUS_SRV_WAIT_FOR_CONNECT_RESP");
|
||||
break;
|
||||
case STATUS_SRV_CONNECTED:
|
||||
_Trace("STATUS_SRV_CONNECTED");
|
||||
break;
|
||||
case STATUS_SRV_WAIT_FOR_CONTEXT_READY:
|
||||
_Trace("STATUS_SRV_WAIT_FOR_CONTEXT_READY");
|
||||
break;
|
||||
case STATUS_SRV_READY:
|
||||
_Trace("STATUS_SRV_READY");
|
||||
break;
|
||||
case STATUS_SRV_DISCONNECTED:
|
||||
_Trace("STATUS_SRV_DISCONNECTED");
|
||||
break;
|
||||
default:
|
||||
_Trace("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CServerStateMachine::HandleIDLE(unsigned int dwIncomingSignal, DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_SETUP)
|
||||
if(dwParam==0) //the protocol versions do not match
|
||||
{
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
const char *serr="wrong protocol version";
|
||||
OnSignal(SIG_SRV_SEND_DISCONNECT, (ULONG_PTR)serr);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, (ULONG_PTR)serr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStatus(STATUS_SRV_WAIT_FOR_CONNECT_RESP);
|
||||
SetTimer(TM_CONNECT_RESP, TM_CONNECT_RESP_ET);
|
||||
OnSignal(SIG_SRV_SEND_CONNECT, dwParam);
|
||||
}
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_ACTIVE_DISCONNECT)
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_SEND_DISCONNECT, dwParam);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CServerStateMachine::HandleWAIT_FOR_CONNECT_RESP(unsigned int dwIncomingSignal, DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_CONNECT_RESP)
|
||||
ResetTimer();
|
||||
SetStatus(STATUS_SRV_CONNECTED);
|
||||
OnSignal(SIG_SRV_CONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(TM_CONNECT_RESP)
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CServerStateMachine::HandleCONNECTED(unsigned int dwIncomingSignal, DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_CONTEXT_SETUP) // we now have this info which map, initiate the loading on the client
|
||||
SetStatus(STATUS_SRV_WAIT_FOR_CONTEXT_READY);
|
||||
SetTimer(TM_CONTEXT_READY, TM_CONTEXT_READY_ET);
|
||||
OnSignal(SIG_SRV_SEND_CONTEXT_SETUP, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_ACTIVE_DISCONNECT)
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_SEND_DISCONNECT, dwParam);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_DISCONNECT)
|
||||
ResetTimer();
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
}
|
||||
|
||||
void CServerStateMachine::HandleWAIT_FOR_CONTEXT_READY(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(TM_CONTEXT_READY)
|
||||
ResetTimer();
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_CONTEXT_SETUP) // we changed the map, initiate the loading on the client
|
||||
SetTimer(TM_CONTEXT_READY, TM_CONTEXT_READY_ET);
|
||||
OnSignal(SIG_SRV_SEND_CONTEXT_SETUP, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_CONTEXT_READY)
|
||||
ResetTimer();
|
||||
SetStatus(STATUS_SRV_READY);
|
||||
OnSignal(SIG_SRV_NOTIFY_CONTEXT_READY, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_DISCONNECT)
|
||||
ResetTimer();
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_ACTIVE_DISCONNECT)
|
||||
ResetTimer();
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_SEND_DISCONNECT, dwParam);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
|
||||
}
|
||||
|
||||
void CServerStateMachine::HandleREADY(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
BEGIN_SIGNAL_HANDLER(dwIncomingSignal)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_CONTEXT_SETUP) // we changed the map, initiate the loading on the client
|
||||
SetStatus(STATUS_SRV_WAIT_FOR_CONTEXT_READY);
|
||||
SetTimer(TM_CONTEXT_READY, TM_CONTEXT_READY_ET);
|
||||
OnSignal(SIG_SRV_SEND_CONTEXT_SETUP, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_DISCONNECT)
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
IF_SIGNAL(SIG_SRV_ACTIVE_DISCONNECT)
|
||||
SetStatus(STATUS_SRV_DISCONNECTED);
|
||||
OnSignal(SIG_SRV_SEND_DISCONNECT, dwParam);
|
||||
OnSignal(SIG_SRV_DISCONNECTED, dwParam);
|
||||
ENDIF_SIGNAL()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
END_SIGNAL_HANDLER()
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CServerStateMachine::Init(_IServerSlotServices *pParent)
|
||||
{
|
||||
m_pParent=pParent;
|
||||
}
|
||||
|
||||
void CServerStateMachine::HandleDISCONNECTED(unsigned int dwIncomingSignal, DWORD_PTR dwParam)
|
||||
{
|
||||
// the machine can't leave this status
|
||||
}
|
||||
|
||||
void CServerStateMachine::OnSignal(unsigned int dwOutgoingSignal, DWORD_PTR dwParam)
|
||||
{
|
||||
switch (dwOutgoingSignal)
|
||||
{
|
||||
case SIG_SRV_SEND_CONNECT:
|
||||
m_pParent->SendConnect();
|
||||
break;
|
||||
case SIG_SRV_SEND_DISCONNECT:
|
||||
m_pParent->SendDisconnect((const char *)dwParam);
|
||||
break;
|
||||
case SIG_SRV_SEND_CONTEXT_SETUP:
|
||||
m_pParent->SendContextSetup();
|
||||
break;
|
||||
case SIG_SRV_NOTIFY_CONTEXT_READY:
|
||||
m_pParent->OnContextReady();
|
||||
break;
|
||||
case SIG_SRV_CONNECTED:
|
||||
m_pParent->OnConnect();
|
||||
break;
|
||||
case SIG_SRV_DISCONNECTED:
|
||||
m_pParent->OnDisconnect((const char *)dwParam);
|
||||
break;
|
||||
default:
|
||||
NET_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
117
CryNetwork/ServerStateMachine.h
Normal file
117
CryNetwork/ServerStateMachine.h
Normal file
@@ -0,0 +1,117 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: ServerStateMachine.h
|
||||
// Description:
|
||||
//
|
||||
// History:
|
||||
// -08/25/2001: Alberto Demichelis, created
|
||||
// -01/26/2003: Martin Mittring, commented the stated
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef _SERVER_STATE_MACHINE_H_
|
||||
#define _SERVER_STATE_MACHINE_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
#include <platform.h>
|
||||
#include "StateMachine.h"
|
||||
#include "Interfaces.h"
|
||||
|
||||
#define STATUS_SRV_WAIT_FOR_CONNECT_RESP STATUS_BASE+1
|
||||
#define STATUS_SRV_CONNECTED STATUS_BASE+2
|
||||
#define STATUS_SRV_WAIT_FOR_CONTEXT_READY STATUS_BASE+3
|
||||
#define STATUS_SRV_READY STATUS_BASE+4
|
||||
#define STATUS_SRV_DISCONNECTED STATUS_BASE+5
|
||||
|
||||
//in signals
|
||||
#define SIG_SRV_START SIGNAL_BASE+1
|
||||
#define SIG_SRV_SETUP SIGNAL_BASE+2
|
||||
#define SIG_SRV_CONNECT_RESP SIGNAL_BASE+3
|
||||
#define SIG_SRV_CONTEXT_SETUP SIGNAL_BASE+4
|
||||
#define SIG_SRV_CONTEXT_READY SIGNAL_BASE+5
|
||||
#define SIG_SRV_DISCONNECT SIGNAL_BASE+6
|
||||
#define SIG_SRV_ACTIVE_DISCONNECT SIGNAL_BASE+7
|
||||
//out signals
|
||||
#define SIG_SRV_SEND_CONNECT SIGNAL_BASE+8
|
||||
#define SIG_SRV_SEND_DISCONNECT SIGNAL_BASE+9
|
||||
#define SIG_SRV_SEND_CONTEXT_SETUP SIGNAL_BASE+10
|
||||
#define SIG_SRV_NOTIFY_CONTEXT_READY SIGNAL_BASE+12
|
||||
#define SIG_SRV_CONNECTED SIGNAL_BASE+13
|
||||
#define SIG_SRV_DISCONNECTED SIGNAL_BASE+14
|
||||
|
||||
|
||||
#define TM_CONNECT_RESP TIMER_BASE+1
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define TM_CONNECT_RESP_ET 200000
|
||||
#else
|
||||
#define TM_CONNECT_RESP_ET 20000
|
||||
#endif
|
||||
|
||||
#define TM_CONTEXT_READY TIMER_BASE+2
|
||||
#define TM_CONTEXT_READY_ET (5*60*1000) // 5 min to load the map
|
||||
|
||||
|
||||
|
||||
class CServerStateMachine :public CStateMachine
|
||||
{
|
||||
BEGIN_STATUS_MAP()
|
||||
STATUS_ENTRY(STATUS_IDLE,HandleIDLE)
|
||||
// goes to the next state when getting the CCPSetup packet (PlayerPassword,ProtocolVersion) from the client
|
||||
// or to STATUS_SRV_DISCONNECTED when the version doesn't match
|
||||
|
||||
STATUS_ENTRY(STATUS_SRV_WAIT_FOR_CONNECT_RESP,HandleWAIT_FOR_CONNECT_RESP)
|
||||
// goes to the next state when getting the CCPConnectResp packet (AuthorizationID) from the client
|
||||
|
||||
STATUS_ENTRY(STATUS_SRV_CONNECTED,HandleCONNECTED)
|
||||
// goes to the next state when the authorization is ok
|
||||
|
||||
STATUS_ENTRY(STATUS_SRV_WAIT_FOR_CONTEXT_READY,HandleWAIT_FOR_CONTEXT_READY)
|
||||
// the client is currently loading the map and we wait
|
||||
// when getting the CCPContextReady packet (bHost,p_name,p_model) from the client
|
||||
// we sends all entities to the client (CXServerSlot::OnContextReady) and go to the next state
|
||||
|
||||
STATUS_ENTRY(STATUS_SRV_READY,HandleREADY)
|
||||
// goes back to STATUS_SRV_WAIT_FOR_CONTEXT_READY when CServerSlot::ContextSetup() was called
|
||||
// to change the map/mod and sync the server variables once again
|
||||
|
||||
STATUS_ENTRY(STATUS_SRV_DISCONNECTED,HandleDISCONNECTED)
|
||||
// when going in this state send the SIG_DISCONNECTED signal and the system will remove the client soon
|
||||
|
||||
END_STATUS_MAP()
|
||||
|
||||
public: // ---------------------------------------------------------------------
|
||||
|
||||
//! constructor
|
||||
CServerStateMachine();
|
||||
//! destructor
|
||||
virtual ~CServerStateMachine();
|
||||
//!
|
||||
void Init(_IServerSlotServices *pParent);
|
||||
|
||||
private: // ---------------------------------------------------------------------
|
||||
|
||||
//status handlers
|
||||
void HandleIDLE(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleWAIT_FOR_CONNECT_RESP(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleCONNECTED(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleWAIT_FOR_CONTEXT_READY(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleREADY(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
void HandleDISCONNECTED(unsigned int dwIncomingSignal,DWORD_PTR dwParam);
|
||||
|
||||
void OnSignal(unsigned int dwOutgoingSignal,DWORD_PTR dwParam);
|
||||
|
||||
//tracing
|
||||
void _Trace(char *s);
|
||||
void _TraceStatus(unsigned int dwStatus);
|
||||
|
||||
_IServerSlotServices * m_pParent; //!< pointer to the parent object (is not released), is 0 is you forgot to call Init()
|
||||
};
|
||||
|
||||
#endif //_SERVER_STATE_MACHINE_H_
|
||||
145
CryNetwork/StateMachine.h
Normal file
145
CryNetwork/StateMachine.h
Normal file
@@ -0,0 +1,145 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Network source code
|
||||
//
|
||||
// File: statemachine.h
|
||||
// Description: state machine toolkit
|
||||
//
|
||||
// History:
|
||||
// -July 25,2001:Created by Alberto Demichelis
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef _STATE_MACHINE_H_
|
||||
#define _STATE_MACHINE_H_
|
||||
#include <stdio.h>
|
||||
#define ANY_SIGNAL_NOT_HANDLED 0xFFFFFFFF
|
||||
#define ANY_SIGNAL_HANDLED 0x00000000
|
||||
|
||||
#define STATUS_BASE 0xFFFF0000
|
||||
#define STATUS_IDLE STATUS_BASE
|
||||
|
||||
#define SIGNAL_BASE 0x00000000
|
||||
#define TIMER_BASE 0x0000FFFF
|
||||
|
||||
#ifndef PS2
|
||||
#define DEBUG_STRING(sss) ::OutputDebugString(sss);
|
||||
#else
|
||||
#define DEBUG_STRING(sss) cout << sss;
|
||||
#endif
|
||||
|
||||
#define BEGIN_STATUS_MAP() void _ProcessSignal(unsigned int dwIncomingSignal,ULONG_PTR dwParam) \
|
||||
{ \
|
||||
if(HandleANY(dwIncomingSignal,dwParam)==ANY_SIGNAL_NOT_HANDLED) \
|
||||
switch(m_dwStatus) \
|
||||
{
|
||||
|
||||
#define STATUS_ENTRY( _signal , _handler ) case _signal : \
|
||||
_handler(dwIncomingSignal,dwParam); \
|
||||
break;
|
||||
|
||||
#define END_STATUS_MAP() default : \
|
||||
::OutputDebugString("singal not handled\n"); \
|
||||
break; \
|
||||
}; \
|
||||
} \
|
||||
|
||||
#define BEGIN_SIGNAL_HANDLER(signal) switch(signal){ \
|
||||
|
||||
#define IF_SIGNAL(signal) case signal:{
|
||||
|
||||
#define ENDIF_SIGNAL() } \
|
||||
break; \
|
||||
|
||||
#define END_SIGNAL_HANDLER() default: \
|
||||
_Trace("Signal not handled\n"); \
|
||||
break; \
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define ANY_SIGNAL_EXCEPT(status){if(m_dwStatus==status){return ANY_SIGNAL_NOT_HANDLED;}}
|
||||
|
||||
#define BEGIN_ANY_SIGNAL_HANDLER(signal) switch(signal){
|
||||
|
||||
#define END_ANY_SIGNAL_HANDLER() default: \
|
||||
DEBUG_STRING("ANY Signal not handled\n"); \
|
||||
return ANY_SIGNAL_NOT_HANDLED; \
|
||||
break; \
|
||||
}; \
|
||||
return ANY_SIGNAL_HANDLED;
|
||||
|
||||
class CStateMachine
|
||||
{
|
||||
protected:
|
||||
virtual void _ProcessSignal(unsigned int dwIncomingSignal,ULONG_PTR dwParam)=0;
|
||||
void SetTimer(unsigned int dwName,unsigned int dwElapsed)
|
||||
{
|
||||
m_dwTimerName=dwName;
|
||||
m_dwTimerElapsed=dwElapsed;
|
||||
m_dwTimerStart=::GetTickCount();
|
||||
}
|
||||
void ResetTimer()
|
||||
{
|
||||
m_dwTimerStart=0;
|
||||
m_dwTimerElapsed=0;
|
||||
m_dwTimerName=0;
|
||||
|
||||
}
|
||||
void SetStatus(unsigned int dwStatus)
|
||||
{
|
||||
_TraceStatus(m_dwStatus);
|
||||
_Trace(">>");
|
||||
_TraceStatus(dwStatus);
|
||||
_Trace("\n");
|
||||
m_dwStatus=dwStatus;
|
||||
}
|
||||
virtual unsigned int HandleANY(unsigned int dwIncomingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
return ANY_SIGNAL_NOT_HANDLED;
|
||||
}
|
||||
virtual void OnSignal(unsigned int dwOutgoingSignal,DWORD_PTR dwParam)
|
||||
{
|
||||
NET_TRACE("WARNING default OnSignal called\n");
|
||||
}
|
||||
virtual void _Trace(char *s){};
|
||||
virtual void _TraceStatus(unsigned int dwStatus){};
|
||||
|
||||
public:
|
||||
CStateMachine()
|
||||
{
|
||||
m_dwStatus=0;
|
||||
Reset();
|
||||
}
|
||||
virtual void Reset()
|
||||
{
|
||||
SetStatus(STATUS_IDLE);
|
||||
ResetTimer();
|
||||
}
|
||||
BOOL Update(unsigned int dwIncomingSignal=0,DWORD_PTR dwParam=0)
|
||||
{
|
||||
if(m_dwTimerName)
|
||||
if((::GetTickCount()-m_dwTimerStart)>=m_dwTimerElapsed)
|
||||
{
|
||||
unsigned int dwTimerName=m_dwTimerName;
|
||||
ResetTimer();
|
||||
_ProcessSignal(dwTimerName,0);
|
||||
}
|
||||
|
||||
if(dwIncomingSignal)
|
||||
{
|
||||
_ProcessSignal(dwIncomingSignal,dwParam); // this pointer might be destroyed after this call
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
unsigned int GetCurrentStatus(){return m_dwStatus;}
|
||||
unsigned int m_dwStatus;
|
||||
//
|
||||
unsigned int m_dwTimerStart;
|
||||
unsigned int m_dwTimerElapsed;
|
||||
unsigned int m_dwTimerName;
|
||||
};
|
||||
#endif //_STATE_MACHINE_H_
|
||||
168
CryNetwork/StaticCharCompressor.cpp
Normal file
168
CryNetwork/StaticCharCompressor.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "stdafx.h"
|
||||
#include "compressionhelper.h"
|
||||
|
||||
|
||||
CStaticCharCompressor::CStaticCharCompressor()
|
||||
{
|
||||
m_dwRootIndex=0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
void CStaticCharCompressor::InitFromStatistics( const DWORD indwPriority[256] )
|
||||
{
|
||||
std::multiset<SPriIndex> Sorter;
|
||||
|
||||
m_Nodes.clear();
|
||||
m_Nodes.reserve(256*2-1);
|
||||
|
||||
for(DWORD i=0;i<256;i++)
|
||||
{
|
||||
m_Nodes.push_back( SNode((unsigned char)i) );
|
||||
Sorter.insert( SPriIndex(i,indwPriority[i]+1) ); // +1 to ensure if we add two priorites the value is raising
|
||||
}
|
||||
|
||||
// iterate through all nodes from lowest to highest priority
|
||||
for(;;)
|
||||
{
|
||||
DWORD dwIndex1,dwIndex2;
|
||||
DWORD dwPriority;
|
||||
|
||||
// get element with lowest priorty
|
||||
{
|
||||
std::multiset<SPriIndex>::iterator top = Sorter.begin();
|
||||
|
||||
assert(top!=Sorter.end()); // cannot be because we always remove two and add one
|
||||
|
||||
const SPriIndex &ref = *top;
|
||||
|
||||
dwIndex1=ref.m_dwIndex;
|
||||
dwPriority=ref.m_dwPriority;
|
||||
|
||||
Sorter.erase(top);
|
||||
}
|
||||
|
||||
// get element with second lowest priorty
|
||||
{
|
||||
std::multiset<SPriIndex>::iterator top = Sorter.begin();
|
||||
|
||||
if(top==Sorter.end())
|
||||
{
|
||||
m_dwRootIndex=dwIndex1;
|
||||
break;
|
||||
}
|
||||
|
||||
const SPriIndex &ref = *top;
|
||||
|
||||
dwIndex2=ref.m_dwIndex;
|
||||
dwPriority+=ref.m_dwPriority;
|
||||
|
||||
Sorter.erase(top);
|
||||
}
|
||||
|
||||
DWORD dwNextIndex = m_Nodes.size();
|
||||
|
||||
m_Nodes.push_back( SNode(dwIndex1,dwIndex2) );
|
||||
Sorter.insert( SPriIndex(dwNextIndex,dwPriority) );
|
||||
}
|
||||
|
||||
// build m_CharToBit
|
||||
{
|
||||
for(DWORD i=0;i<256;i++)
|
||||
{
|
||||
bool bRet=GetCharFromBits_slow( (unsigned char)i, m_dwRootIndex, m_CharToBit[i] );
|
||||
|
||||
assert(bRet); // it must be there
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CStaticCharCompressor::GetCharFromBits_slow( const unsigned char inVal, const DWORD indwIndex, SBitToChar &outDat )
|
||||
{
|
||||
SNode &ref = m_Nodes[indwIndex];
|
||||
|
||||
if(ref.IsLeaf())
|
||||
{
|
||||
if(ref.m_Value==inVal)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
outDat.m_BitCount++;
|
||||
assert(outDat.m_BitCount<16);
|
||||
outDat.m_Bitfield<<=1;
|
||||
|
||||
// one
|
||||
outDat.m_Bitfield|=0x1;
|
||||
|
||||
if(GetCharFromBits_slow(inVal,ref.m_dwIndexOne,outDat))
|
||||
return true;
|
||||
|
||||
// zero
|
||||
outDat.m_Bitfield&=~0x1;
|
||||
if(GetCharFromBits_slow(inVal,ref.m_dwIndexZero,outDat))
|
||||
return true;
|
||||
|
||||
outDat.m_Bitfield>>=1;
|
||||
outDat.m_BitCount--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CStaticCharCompressor::Write( CStream &outStream, const unsigned char inChar )
|
||||
{
|
||||
assert(m_dwRootIndex!=0xffffffff); // instance is not initialized
|
||||
|
||||
SBitToChar &ref=m_CharToBit[inChar];
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
CStream test;
|
||||
|
||||
unsigned char cTest;
|
||||
|
||||
test.WriteNumberInBits((DWORD)(ref.m_Bitfield),ref.m_BitCount);
|
||||
Read(test,cTest);
|
||||
assert(cTest==inChar);
|
||||
#endif
|
||||
*/
|
||||
|
||||
for(DWORD i=0;i<ref.m_BitCount;i++)
|
||||
{
|
||||
bool b=(ref.m_Bitfield & (1<<(ref.m_BitCount-i-1)))!=0;
|
||||
|
||||
if(!outStream.Write(b))
|
||||
return false;
|
||||
}
|
||||
// return outStream.WriteNumberInBits((DWORD)(ref.m_Bitfield),ref.m_BitCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CStaticCharCompressor::Read( CStream &inStream, unsigned char &outChar )
|
||||
{
|
||||
assert(m_dwRootIndex!=0xffffffff); //
|
||||
|
||||
DWORD dwCurrentIndex=m_dwRootIndex;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
bool bBit;
|
||||
|
||||
SNode &ref=m_Nodes[dwCurrentIndex];
|
||||
|
||||
if(ref.IsLeaf())
|
||||
{
|
||||
outChar=ref.m_Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!inStream.Read(bBit))
|
||||
return false;
|
||||
|
||||
if(bBit)
|
||||
dwCurrentIndex=ref.m_dwIndexOne;
|
||||
else
|
||||
dwCurrentIndex=ref.m_dwIndexZero;
|
||||
}
|
||||
}
|
||||
98
CryNetwork/StaticCharCompressor.h
Normal file
98
CryNetwork/StaticCharCompressor.h
Normal file
@@ -0,0 +1,98 @@
|
||||
// for ASCII strings up to 255 character
|
||||
// character with priority 0 remain available
|
||||
|
||||
// References:
|
||||
// http://www.howtodothings.com/showarticle.asp?article=313
|
||||
// http://dogma.net/markn/articles/bwt/bwt.htm (this might perform worse for small strings)
|
||||
|
||||
#include <vector> // STL vector<>
|
||||
|
||||
//
|
||||
class CStaticCharCompressor
|
||||
{
|
||||
public:
|
||||
//! constructor
|
||||
CStaticCharCompressor();
|
||||
|
||||
//! \param indwPriority table of the priorites of the character set
|
||||
void InitFromStatistics( const DWORD indwPriority[256] );
|
||||
|
||||
//! \return stream error
|
||||
bool Write( CStream &outStream, const unsigned char inChar );
|
||||
|
||||
//! \return stream error
|
||||
bool Read( CStream &inStream, unsigned char &outChar );
|
||||
|
||||
|
||||
private: // ---------------------------------------------------------
|
||||
|
||||
struct SNode
|
||||
{
|
||||
//! constructor for a leaf
|
||||
SNode( const unsigned char inValue )
|
||||
:m_Value(inValue)
|
||||
{
|
||||
m_dwIndexZero=0xffffffff;m_dwIndexOne=0xffffffff; // unused
|
||||
}
|
||||
|
||||
//! constructor for a node
|
||||
SNode( const DWORD indwIndexZero, const DWORD indwIndexOne )
|
||||
:m_dwIndexZero(indwIndexZero),m_dwIndexOne(indwIndexOne)
|
||||
{
|
||||
m_Value=0; // unused
|
||||
}
|
||||
|
||||
DWORD m_dwIndexZero; //!< 0xffffffff or index to the subtree for bit = 0
|
||||
DWORD m_dwIndexOne; //!< 0xffffffff or index to the subtree for bit = 1
|
||||
|
||||
unsigned char m_Value; //!< is only valid for Leafes
|
||||
|
||||
bool IsLeaf()
|
||||
{
|
||||
return m_dwIndexZero==0xffffffff && m_dwIndexOne==0xffffffff;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
struct SPriIndex
|
||||
{
|
||||
//! constructor
|
||||
SPriIndex( const DWORD indwIndex, const DWORD indwPriority )
|
||||
:m_dwIndex(indwIndex),m_dwPriority(indwPriority)
|
||||
{
|
||||
}
|
||||
|
||||
DWORD m_dwIndex; //!<
|
||||
DWORD m_dwPriority; //!<
|
||||
|
||||
//! used for sorting (from low to hight values)
|
||||
bool operator<( const SPriIndex &inRhs ) const
|
||||
{
|
||||
return m_dwPriority<inRhs.m_dwPriority;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
struct SBitToChar
|
||||
{
|
||||
//! constructor
|
||||
SBitToChar()
|
||||
{
|
||||
m_Bitfield=0;m_BitCount=0;
|
||||
}
|
||||
|
||||
unsigned short m_Bitfield; //!<
|
||||
unsigned short m_BitCount; //!<
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
DWORD m_dwRootIndex; //!< 0 if the instance was not initiated - tree is build out of elements from m_NodeMemory
|
||||
std::vector<SNode> m_Nodes; //!<
|
||||
SBitToChar m_CharToBit[256]; //!<
|
||||
|
||||
bool GetCharFromBits_slow( const unsigned char inVal, const DWORD indwIndex, SBitToChar &outDat );
|
||||
};
|
||||
|
||||
8
CryNetwork/StdAfx.cpp
Normal file
8
CryNetwork/StdAfx.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// CryNet.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
194
CryNetwork/StdAfx.h
Normal file
194
CryNetwork/StdAfx.h
Normal file
@@ -0,0 +1,194 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#if !defined(AFX_STDAFX_H__0F62BDE9_4784_4F7A_A265_B7D1A71883D0__INCLUDED_)
|
||||
#define AFX_STDAFX_H__0F62BDE9_4784_4F7A_A265_B7D1A71883D0__INCLUDED_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// THIS MUST BE AT THE VERY BEGINING OF STDAFX.H FILE.
|
||||
// Disable STL threading support, (makes STL faster)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define _NOTHREADS
|
||||
#define _STLP_NO_THREADS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#endif
|
||||
#else
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define USE_NEWPOOL
|
||||
#include <CryMemoryManager.h>
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <INetwork.h>
|
||||
#include "DatagramSocket.h"
|
||||
#include <CrySizer.h>
|
||||
// TODO: reference additional headers your program requires here
|
||||
|
||||
|
||||
|
||||
#if defined(_DEBUG) && !defined(LINUX)
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma warning( disable : 4786 )
|
||||
//#pragma warning( disable : 4716 )
|
||||
#endif // _MSC_VER > 1000
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef PS2
|
||||
typedef int BOOL;
|
||||
#endif
|
||||
|
||||
#ifndef __NET_ASSERT
|
||||
#define __NET_ASSERT
|
||||
|
||||
#if 1
|
||||
|
||||
#if defined(WIN64)
|
||||
|
||||
#define NET_ASSERT(x)
|
||||
|
||||
#elif defined(_XBOX)
|
||||
|
||||
#define NET_ASSERT(x)
|
||||
|
||||
#elif defined(PS2)
|
||||
#include <iostream.h>
|
||||
inline void NET_ASSERT(void * x)
|
||||
{
|
||||
if (!(x))
|
||||
{
|
||||
cout << "Assertion Failed!!\n\nFile: " << __FILE__ <<"\n\nLine: " << __LINE__ << "\n";
|
||||
DEBUG_BREAK;
|
||||
}
|
||||
}
|
||||
#elif defined(WIN32)
|
||||
#define NET_ASSERT(x) \
|
||||
{ \
|
||||
if (!(x)) { \
|
||||
static char sAssertionMessage[500]; \
|
||||
\
|
||||
wsprintf(sAssertionMessage, "Assertion Failed!!\n\nFile: \"%s\"\n\nLine: %d\n", __FILE__, __LINE__); \
|
||||
::MessageBox(NULL, sAssertionMessage, "Assertion Failed", MB_OK | MB_ICONERROR); \
|
||||
DEBUG_BREAK; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
|
||||
#define NET_ASSERT(x)
|
||||
|
||||
#endif
|
||||
|
||||
#endif //1
|
||||
#endif
|
||||
|
||||
#ifndef NET____TRACE
|
||||
#define NET____TRACE
|
||||
|
||||
// src and trg can be the same pointer (in place encryption)
|
||||
// len must be in bytes and must be multiple of 8 byts (64bits).
|
||||
// key is 128bit: int key[4] = {n1,n2,n3,n4};
|
||||
// void encipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k )
|
||||
#define TEA_ENCODE( src,trg,len,key ) {\
|
||||
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
|
||||
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
|
||||
while (nlen--) {\
|
||||
register unsigned int y=v[0],z=v[1],n=32,sum=0; \
|
||||
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; } \
|
||||
w[0]=y; w[1]=z; v+=2,w+=2; }}
|
||||
|
||||
// src and trg can be the same pointer (in place decryption)
|
||||
// len must be in bytes and must be multiple of 8 byts (64bits).
|
||||
// key is 128bit: int key[4] = {n1,n2,n3,n4};
|
||||
// void decipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k)
|
||||
#define TEA_DECODE( src,trg,len,key ) {\
|
||||
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
|
||||
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
|
||||
while (nlen--) { \
|
||||
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32; \
|
||||
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; } \
|
||||
w[0]=y; w[1]=z; v+=2,w+=2; }}
|
||||
|
||||
// encode size ignore last 3 bits of size in bytes. (encode by 8bytes min)
|
||||
#define TEA_GETSIZE( len ) ((len) & (~7))
|
||||
|
||||
#ifndef PS2
|
||||
inline void __cdecl __NET_TRACE(const char *sFormat, ... )
|
||||
{
|
||||
/*
|
||||
va_list vl;
|
||||
static char sTraceString[500];
|
||||
|
||||
va_start(vl, sFormat);
|
||||
vsprintf(sTraceString, sFormat, vl);
|
||||
va_end(vl);
|
||||
NET_ASSERT(strlen(sTraceString) < 500)
|
||||
CryLogAlways( sTraceString );
|
||||
|
||||
va_list vl;
|
||||
static char sTraceString[500];
|
||||
|
||||
va_start(vl, sFormat);
|
||||
vsprintf(sTraceString, sFormat, vl);
|
||||
va_end(vl);
|
||||
NET_ASSERT(strlen(sTraceString) < 500)
|
||||
::OutputDebugString(sTraceString);*/
|
||||
|
||||
}
|
||||
#else
|
||||
inline void __NET_TRACE(const char *sFormat, ... )
|
||||
{
|
||||
va_list vl;
|
||||
static char sTraceString[500];
|
||||
|
||||
va_start(vl, sFormat);
|
||||
vsprintf(sTraceString, sFormat, vl);
|
||||
va_end(vl);
|
||||
NET_ASSERT(strlen(sTraceString) < 500)
|
||||
cout << sTraceString;
|
||||
|
||||
}
|
||||
|
||||
#endif //PS2
|
||||
|
||||
#if 1
|
||||
|
||||
#define NET_TRACE __NET_TRACE
|
||||
|
||||
#else
|
||||
|
||||
#define NET_TRACE 1?(void)0 : __NET_TRACE;
|
||||
|
||||
#endif //NET____TRACE
|
||||
|
||||
#endif //_DEBUG
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
||||
#endif // !defined(AFX_STDAFX_H__0F62BDE9_4784_4F7A_A265_B7D1A71883D0__INCLUDED_)
|
||||
19
CryNetwork/UbisoftMemory.cpp
Normal file
19
CryNetwork/UbisoftMemory.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef NOT_USE_UBICOM_SDK
|
||||
|
||||
#if defined(WIN32)
|
||||
# define GS_WIN32
|
||||
#else
|
||||
# define GS_LINUX
|
||||
#endif
|
||||
|
||||
#include "UbisoftMemory.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void * __stdcall ExtAlloc_Malloc(unsigned int lSize) {return malloc(lSize);} ;
|
||||
void __stdcall ExtAlloc_Free(void *ptr) {free(ptr);};
|
||||
void * __stdcall ExtAlloc_Realloc(void *ptr, unsigned int uiSize) {return realloc(ptr,uiSize);};
|
||||
}
|
||||
#endif // NOT_USE_UBICOM_SDK
|
||||
14
CryNetwork/UbisoftMemory.h
Normal file
14
CryNetwork/UbisoftMemory.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef __UBISOFT_MEMORY_H
|
||||
#define __UBISOFT_MEMORY_H
|
||||
|
||||
#if defined(WIN32)
|
||||
# define GS_WIN32
|
||||
#else
|
||||
# define GS_LINUX
|
||||
#endif
|
||||
|
||||
extern "C" void * __stdcall ExtAlloc_Malloc(unsigned int lSize);
|
||||
extern "C" void __stdcall ExtAlloc_Free(void *ptr);
|
||||
extern "C" void * __stdcall ExtAlloc_Realloc(void *ptr, unsigned int uiSize);
|
||||
|
||||
#endif
|
||||
10
CryNetwork/todo.txt
Normal file
10
CryNetwork/todo.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
//CRYNET TODO
|
||||
DONE !! -disconnection timeout(echo request)
|
||||
DONE !! -level loading stuff
|
||||
done-server search routine
|
||||
we can say...done-integration with the framework
|
||||
-test and finish ping computation
|
||||
-lag test ,"rate adaptive" packet building, "ping adaptive" timeouts
|
||||
-implement unrealiable only packets(not acknwoleged)
|
||||
-master server
|
||||
|
||||
Reference in New Issue
Block a user