123
This commit is contained in:
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user