engine/game/netDispatch.cc
2024-01-07 04:36:33 +00:00

981 lines
28 KiB
C++

//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#pragma warning(disable:4786) // Remove STL warnings.
#include "Platform/platform.h"
#include "Core/dnet.h"
#include "console/simBase.h"
#include "Sim/netConnection.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "Core/bitStream.h"
#include "Sim/netObject.h"
#include "game/gameConnection.h"
#include "game/serverQuery.h"
#include "game/targetManager.h"
#include "game/netDispatch.h"
#include "Platform/gameInterface.h"
#include "game/tribesGame.h"
#include "game/banList.h"
const char *gServerConnectionName = "ServerConnection";
const char *gLocalClientConnectionName = "LocalClientConnection";
bool gAllowConnections = false;
bool isServerOnline()
{
if(Game->isJournalReading())
{
U32 res;
Game->journalRead(&res);
return bool(res);
}
else
{
bool ret = false;
// Authentication removed...
ret = true;
if(Game->isJournalWriting())
Game->journalWrite(U32(ret));
return ret;
}
}
bool isClientOnline()
{
if(Game->isJournalReading())
{
U32 res;
Game->journalRead(&res);
return bool(res);
}
else
{
bool ret = false;
// Authentication removed...
ret = true;
if(Game->isJournalWriting())
Game->journalWrite(U32(ret));
return ret;
}
}
bool validateAuthenticatedServer()
{
return true;
}
bool validateAuthenticatedClient()
{
return true;
}
//----------------------------------------------------------------
ConsoleFunction(startHeartbeat, void, 1, 1, "startHeartbeat()")
{
argc; argv;
if(validateAuthenticatedServer())
startHeartbeat();
}
enum {
MaxConnectArgs = 16,
MaxPendingConnects = 20,
PendingConnectTimeout = 7000, // 7 seconds
ChallengeRetryCount = 4,
ChallengeRetryTime = 2500, // 2.5 seconds
ConnectRetryCount = 4,
ConnectRetryTime = 2500,
TimeoutCheckInterval = 1500, // check for timeouts every 1.5 secs
MaxAuthInfoSize = 1024,
MaxPasswordLength = 16,
};
//----------------------------------------------------------------
// Client add and drop management
//----------------------------------------------------------------
void GameClientAdded(GameConnection *newClient, S32 argc, const char **argv)
{
SimGroup *g = Sim::getClientGroup();
g->addObject(newClient);
const char *vargs[MaxConnectArgs + 2];
vargs[0] = "onConnect";
vargs[1] = NULL;
if(argc > MaxConnectArgs)
argc = MaxConnectArgs;
for(S32 i = 0; i < argc; i++)
vargs[i + 2] = argv[i];
Con::execute(newClient, argc + 2, vargs);
}
//---------------------------------------------------------------
//----------------------------------------------------------------
// Connect protocol message formats
//----------------------------------------------------------------
// ConnectChallengeRequest
// ProtocolVersion
// Certificate
// ClientConnectSequence
// Password
// ConnectChallengeResponse
// ProtocolVersion
// ServerConnectSequence
// ClientConnectSequence
// ConnectChallengeReject
// ClientConnectSequence
// Reason
// ConnectRequest
// ServerConnectSequence
// ClientConnectSequence
// ProtocolVersion
// console args
// ConnectAccept
// ServerConnectSequence
// ClientConnectSequence
// ProtocolVersion
// ClientID
// ConnectReject
// ServerConnectSequence
// ClientConnectSequence
// Reason
// Disconnect
// ServerConnectSequence
// ClientConnectSequence
// Reason string
//----------------------------------------------------------------
// Connect request and server response structures
//----------------------------------------------------------------
struct ConnectRequestStruct
{
enum {
NotConnecting,
Challenging,
Connecting,
} state;
U32 clientConnectSequence;
U32 serverConnectSequence;
U32 protocolVersion;
U32 lastSendTime;
U32 sendCount;
NetAddress serverAddress;
U32 challenge;
bool authenticated;
char password[MaxPasswordLength + 1];
U32 argc;
char *argv[MaxConnectArgs];
U8 argBuffer[MaxPacketDataSize];
};
struct ConnectRequestPending
{
// Certificate needs to be stored here.
// V12: Challenge stuff was partially hacked out
U32 challenge1;
NetAddress sourceAddress;
U32 clientProtocolVersion;
U32 clientConnectSequence;
U32 serverConnectSequence;
U32 lastRecvTime;
};
ConnectRequestStruct gConnectRequest;
ConnectRequestPending gPendingConnects[MaxPendingConnects];
U32 gNumPendingConnects;
void connectRequestRejected(const char *buffer)
{
Con::executef(2, "onConnectRequestRejected", buffer);
}
void challengeRequestRejected(const char *buffer)
{
Con::executef(2, "onChallengeRequestRejected", buffer);
}
void connectRequestTimedOut()
{
gConnectRequest.state = ConnectRequestStruct::NotConnecting;
Con::executef(1, "onConnectRequestTimedOut");
}
void connectionToServerTimedOut()
{
Con::executef(1, "onConnectionToServerTimedOut");
}
void connectionToServerLost(const char* msg)
{
Con::executef(2, "onConnectionToServerLost", msg);
}
//----------------------------------------------------------------
// Connect request and server response functions
//----------------------------------------------------------------
void sendConnectChallengeRequest()
{
BitStream *out = BitStream::getPacketStream();
out->write(U8(ConnectChallengeRequest));
out->write(CurrentProtocolVersion);
out->write(gConnectRequest.clientConnectSequence);
out->writeString(gConnectRequest.password);
// Authentication removed...
gConnectRequest.sendCount++;
gConnectRequest.lastSendTime = Platform::getVirtualMilliseconds();
Con::printf("Connect Challenge Request: %d", gConnectRequest.sendCount);
BitStream::sendPacketStream(&gConnectRequest.serverAddress);
}
void sendConnectChallengeResponse(U32 index)
{
ConnectRequestPending *p = gPendingConnects + index;
BitStream *out = BitStream::getPacketStream();
out->write(U8(ConnectChallengeResponse));
out->write(CurrentProtocolVersion);
out->write(p->serverConnectSequence);
out->write(p->clientConnectSequence);
// Authentication removed...
p->lastRecvTime = Platform::getVirtualMilliseconds();
Con::printf("Sent challenge response");
BitStream::sendPacketStream(&p->sourceAddress);
}
void rejectConnectChallengeRequest(const NetAddress *source, U32 clientConnectSequence, const char *reason)
{
BitStream *out = BitStream::getPacketStream();
out->write(U8(ConnectChallengeReject));
out->write(clientConnectSequence);
out->writeString(reason);
BitStream::sendPacketStream(source);
}
void handleConnectChallengeRequest(const NetAddress *source, BitStream *stream)
{
if(!gAllowConnections)
return;
// reasons for rejection
// password wrong
// server full
// bad protocol version
// invalid certificate
// don't meet tribe/UID connect restrictions
U32 protoVersion;
U32 clientConnectSequence;
const char *rejectString = NULL;
char joinPassword[MaxPasswordLength + 1];
stream->read(&protoVersion);
stream->read(&clientConnectSequence);
if(protoVersion < MinRequiredProtocolVersion)
{
rejectConnectChallengeRequest(source, clientConnectSequence, "CHR_PROTOCOL");
return;
}
if(protoVersion > CurrentProtocolVersion)
protoVersion = CurrentProtocolVersion;
// first time out any outstanding challenge requests:
U32 time = Platform::getVirtualMilliseconds();
for(U32 i = 0; i < gNumPendingConnects;)
{
ConnectRequestPending *p = gPendingConnects + i;
// see if this is already in the list:
if(Net::compareAddresses(source, &p->sourceAddress) && p->clientConnectSequence == clientConnectSequence)
{
// just up the time and ping back
sendConnectChallengeResponse(i);
return;
}
if(time > p->lastRecvTime + PendingConnectTimeout)
*p = gPendingConnects[--gNumPendingConnects];
else
i++;
}
// Test the password:
stream->readString(joinPassword);
const char* password = Con::getVariable( "$Host::Password" );
if ( password[0] )
{
if ( dStrncmp( password, joinPassword, MaxPasswordLength ) != 0 )
{
// IMPORTANT! Do NOT change the message here, it is used by the game.
rejectConnectChallengeRequest(source, clientConnectSequence, "PASSWORD");
return;
}
}
// V12: Challenge stuff was partially hacked out
U32 challenge1 = 0;
if(stream->readFlag())
{
U8 buffer[MaxAuthInfoSize];
U32 size = stream->readInt(16);
if(size > MaxAuthInfoSize)
{
rejectConnectChallengeRequest(source, clientConnectSequence, "CHR_INVALID_CHALLENGE_PACKET");
return;
}
// V12: Used to have WON stuff here...
}
U32 index;
if(gNumPendingConnects == MaxPendingConnects)
index = mRandI(0, MaxPendingConnects-1);
else
index = gNumPendingConnects++;
ConnectRequestPending *p = gPendingConnects + index;
p->challenge1 = challenge1;
p->clientConnectSequence = clientConnectSequence;
p->sourceAddress = *source;
p->clientProtocolVersion = protoVersion;
p->serverConnectSequence = Platform::getVirtualMilliseconds();
Con::printf("Got challenge request");
sendConnectChallengeResponse(index);
}
void sendConnectRequest()
{
gConnectRequest.sendCount++;
gConnectRequest.lastSendTime = Platform::getVirtualMilliseconds();
BitStream *out = BitStream::getPacketStream();
out->write(U8(ConnectRequest));
out->write(gConnectRequest.serverConnectSequence);
out->write(gConnectRequest.clientConnectSequence);
out->write(gConnectRequest.protocolVersion);
if(out->writeFlag(gConnectRequest.authenticated))
{
out->write(gConnectRequest.challenge);
}
out->write(gConnectRequest.argc);
for(U32 i = 0; i < gConnectRequest.argc; i++)
out->writeString(gConnectRequest.argv[i]);
Con::printf("Sent connect request");
BitStream::sendPacketStream(&gConnectRequest.serverAddress);
}
void handleConnectChallengeResponse(const NetAddress *addr, BitStream *stream)
{
if(gConnectRequest.state != ConnectRequestStruct::Challenging)
return;
if(!Net::compareAddresses(&gConnectRequest.serverAddress, addr))
return;
U32 serverProtocol;
U32 serverConnectSequence;
U32 clientConnectSequence;
stream->read(&serverProtocol);
stream->read(&serverConnectSequence);
stream->read(&clientConnectSequence);
// must be an old connect request...
if(clientConnectSequence != gConnectRequest.clientConnectSequence)
return;
// check if it's authenticated
gConnectRequest.authenticated = stream->readFlag();
if(gConnectRequest.authenticated)
{
// V12: Authentication removed...
// V12: Used to have WON stuff here...
}
gConnectRequest.state = ConnectRequestStruct::Connecting;
gConnectRequest.serverConnectSequence = serverConnectSequence;
gConnectRequest.sendCount = 0;
gConnectRequest.protocolVersion = serverProtocol < CurrentProtocolVersion ? serverProtocol : CurrentProtocolVersion;
Con::printf("Got challenge response");
sendConnectRequest();
}
void GameConnection::connectionError(const char *errorString)
{
if(isServerConnection())
{
Con::printf("Connection error: %s.", errorString);
connectionToServerLost( errorString );
}
else
{
Con::printf("Client %d packet error: %s.", getId(), errorString);
setDisconnectReason("Packet Error.");
}
deleteObject();
}
void handleDisconnect(const NetAddress *addr, BitStream *stream)
{
Con::printf("Got disconnect packet.");
NetConnection *conn = NetConnection::lookup(addr);
U32 serverConnectSequence, clientConnectSequence;
stream->read(&serverConnectSequence);
stream->read(&clientConnectSequence);
char reason[256];
stream->readString(reason);
U32 cServerConnectSequence, cClientConnectSequence;
if(!conn)
return;
conn->getSequences(&cClientConnectSequence, &cServerConnectSequence);
if(cClientConnectSequence != clientConnectSequence ||
cServerConnectSequence != serverConnectSequence)
return;
// ok, it's gone.
if(conn->isServerConnection())
{
Con::printf("Connection with server lost.");
connectionToServerLost( reason );
}
else
{
Con::printf("Client %d disconnected.", conn->getId());
((GameConnection *) conn)->setDisconnectReason(reason);
}
conn->deleteObject();
}
void handleConnectAccept(const NetAddress *addr, BitStream *stream)
{
if(gConnectRequest.state != ConnectRequestStruct::Connecting)
return;
if(!Net::compareAddresses(&gConnectRequest.serverAddress, addr))
return;
U32 serverConnectSequence, clientConnectSequence;
U32 protocol, id;
stream->read(&serverConnectSequence);
stream->read(&clientConnectSequence);
stream->read(&protocol);
stream->read(&id);
if(serverConnectSequence != gConnectRequest.serverConnectSequence ||
clientConnectSequence != gConnectRequest.clientConnectSequence ||
protocol > CurrentProtocolVersion ||
protocol < MinRequiredProtocolVersion)
return;
// ok, we can connect up now:
gConnectRequest.state = ConnectRequestStruct::NotConnecting;
GameConnection *conn = new GameConnection(false, true, true);
conn->registerObject();
NetConnection::setServerConnection(conn);
conn->setProtocolVersion(protocol);
conn->setSequences(clientConnectSequence, serverConnectSequence);
conn->setConnectSequence(clientConnectSequence ^ serverConnectSequence);
conn->setNetAddress(addr);
conn->setNetworkConnection(true);
Sim::getRootGroup()->addObject(conn, gServerConnectionName);
Con::executef(1, "ServerConnectionAccepted");
Con::printf("Connection accepted - id %d protocol %d", id, protocol);
}
void sendConnectAccept(NetConnection *conn)
{
BitStream *out = BitStream::getPacketStream();
out->write(U8(ConnectAccept));
U32 clientConnectSeq, serverConnectSeq;
U32 protocol;
conn->getSequences(&clientConnectSeq, &serverConnectSeq);
protocol = conn->getProtocolVersion();
out->write(serverConnectSeq);
out->write(clientConnectSeq);
out->write(protocol);
out->write(U32(conn->getId()));
Con::printf("Sending connect accept: %d", conn->getId());
BitStream::sendPacketStream(conn->getNetAddress());
}
void handleConnectReject(const NetAddress *address, BitStream *stream)
{
if(gConnectRequest.state != ConnectRequestStruct::Connecting)
return;
U32 clientConnectSequence, serverConnectSequence;
stream->read(&serverConnectSequence);
stream->read(&clientConnectSequence);
if(!Net::compareAddresses(address, &gConnectRequest.serverAddress) ||
clientConnectSequence != gConnectRequest.clientConnectSequence ||
serverConnectSequence != gConnectRequest.serverConnectSequence)
return;
char buffer[256];
stream->readString(buffer);
gConnectRequest.state = ConnectRequestStruct::NotConnecting;
connectRequestRejected(buffer);
}
void handleConnectChallengeReject(const NetAddress *address, BitStream *stream)
{
if(gConnectRequest.state != ConnectRequestStruct::Challenging)
return;
U32 clientConnectSequence;
stream->read(&clientConnectSequence);
if(!Net::compareAddresses(address, &gConnectRequest.serverAddress) ||
clientConnectSequence != gConnectRequest.clientConnectSequence)
return;
char buffer[256];
stream->readString(buffer);
gConnectRequest.state = ConnectRequestStruct::NotConnecting;
challengeRequestRejected(buffer);
}
void handleConnectRequest(const NetAddress *address, BitStream *stream)
{
if(!gAllowConnections)
return;
char addrString[256];
Net::addressToString(address, addrString);
Con::printf("Connection request from: %s", addrString);
U32 serverConnectSequence;
U32 clientConnectSequence;
U32 protocolRequestVersion;
stream->read(&serverConnectSequence);
stream->read(&clientConnectSequence);
stream->read(&protocolRequestVersion);
const char *rejectString = NULL;
if(protocolRequestVersion < MinRequiredProtocolVersion ||
protocolRequestVersion > CurrentProtocolVersion)
rejectString = "CR_INVALID_PROTOCOL_VERSION";
U32 i;
for(i = 0; i < gNumPendingConnects; i++)
{
ConnectRequestPending *p = gPendingConnects + i;
if(Net::compareAddresses(address, &p->sourceAddress) &&
p->clientConnectSequence == clientConnectSequence &&
p->serverConnectSequence == serverConnectSequence)
break;
}
if(i == gNumPendingConnects)
{
// if it's not in the pending list, check if
// we're already connected to this guy:
NetConnection *connect = NetConnection::lookup(address);
if(connect)
{
U32 clientConSeq, serverConSeq;
connect->getSequences(&clientConSeq, &serverConSeq);
// we already accepted this connection:
if(clientConSeq == clientConnectSequence &&
serverConSeq == serverConnectSequence)
sendConnectAccept(connect);
}
return;
}
U32 clientId = 0;
// check the peer auth...
if(stream->readFlag())
{
// V12: Authentication removed...
// V12: Also used to have WON stuff here...
rejectString = "CR_INVALID_CONNECT_PACKET";
}
if ( !rejectString )
{
if ( gBanList.isBanned( 0 /* V12: Was Won net ID */, addrString ) )
rejectString = "CR_YOUAREBANNED";
else if ( Con::getIntVariable( "$HostGamePlayerCount" ) >= Con::getIntVariable( "$Host::MaxPlayers" ) )
rejectString = "CR_SERVERFULL";
}
// erase the request from the pending list
gPendingConnects[i] = gPendingConnects[--gNumPendingConnects];
gPendingConnects[gNumPendingConnects].challenge1 = NULL; // kill the byte buffer.
const char *argv[MaxConnectArgs];
char argbuf[MaxConnectArgs][256];
U32 argc;
stream->read(&argc);
if(argc > MaxConnectArgs)
rejectString = "CR_INVALID_CONNECT_PACKET";
else
{
for(U32 i = 0; i < argc; i++)
{
argv[i] = argbuf[i];
stream->readString(argbuf[i]);
}
}
if(rejectString)
{
BitStream *out = BitStream::getPacketStream();
out->write(U8(ConnectReject));
out->write(serverConnectSequence);
out->write(clientConnectSequence);
out->writeString(rejectString);
BitStream::sendPacketStream(address);
}
else
{
Con::printf("Accepting connect... CLIENT ID = %d", clientId);
// let this guy into the game:
GameConnection *conn = new GameConnection(true, false, true);
conn->registerObject();
conn->setProtocolVersion(protocolRequestVersion);
conn->setNetAddress(address);
conn->setNetworkConnection(true);
conn->setSequences(clientConnectSequence, serverConnectSequence);
conn->setConnectSequence(clientConnectSequence ^ serverConnectSequence);
sendConnectAccept(conn);
GameClientAdded(conn, argc, argv);
}
}
static void cConnect(SimObject *, S32 argc, const char **argv)
{
if(!validateAuthenticatedClient())
return;
gConnectRequest.state = ConnectRequestStruct::Challenging;
gConnectRequest.clientConnectSequence = Platform::getVirtualMilliseconds();
if(!Net::stringToAddress(argv[1], &gConnectRequest.serverAddress))
return;
gConnectRequest.protocolVersion = CurrentProtocolVersion;
dStrncpy( gConnectRequest.password, argv[2], MaxPasswordLength );
argc -= 3;
if(argc > MaxConnectArgs)
argc = MaxConnectArgs;
U32 bufPos = 0;
U32 i;
for(i = 0; i < argc; i++)
{
const char *str = argv[i + 3];
U32 len = dStrlen(str);
if(bufPos + len + 1 > MaxPacketDataSize)
break;
dStrcpy((char *) gConnectRequest.argBuffer + bufPos, str);
gConnectRequest.argv[i] = (char *) gConnectRequest.argBuffer + bufPos;
bufPos += len + 1;
}
gConnectRequest.argc = i;
gConnectRequest.sendCount = 0;
// Authentication removed...
sendConnectChallengeRequest();
}
//----------------------------------------------------------------
// Connection initiation console commands
//----------------------------------------------------------------
static void cAllowConnections(SimObject *, S32, const char **argv)
{
if(!validateAuthenticatedServer())
return;
gAllowConnections = dAtob(argv[1]);
}
static void cLocalConnect(SimObject *, S32 argc, const char** argv)
{
if(!validateAuthenticatedClient())
return;
GameConnection *clientConnection = new GameConnection(false, true, true);
GameConnection *serverConnection = new GameConnection(true, false, true);
clientConnection->registerObject();
Sim::getRootGroup()->addObject(clientConnection, gServerConnectionName);
serverConnection->registerObject();
serverConnection->assignName(gLocalClientConnectionName);
NetConnection::setServerConnection(clientConnection);
NetConnection::setLocalClientConnection(serverConnection);
clientConnection->setRemoteConnectionObjectId(serverConnection->getId());
serverConnection->setRemoteConnectionObjectId(clientConnection->getId());
// V12: Used to have WON stuff here...
clientConnection->setProtocolVersion(CurrentProtocolVersion);
serverConnection->setProtocolVersion(CurrentProtocolVersion);
clientConnection->setConnectSequence(0);
serverConnection->setConnectSequence(0);
GameClientAdded(serverConnection, argc - 1, argv + 1);
Con::executef( 1, "LocalConnectionAccepted" );
}
void clientNetProcess()
{
NetConnection *con = NetConnection::getServerConnection();
if (con)
con->checkPacketSend();
}
void serverNetProcess()
{
NetObject::collapseDirtyList(); // collapse all the mask bits...
SimGroup *clientGroup = Sim::getClientGroup();
for(SimGroup::iterator i = clientGroup->begin(); i != clientGroup->end(); i++)
{
NetConnection *con = (NetConnection *)(*i);
if(con->isLocalConnection() || con->isNetworkConnection())
con->checkPacketSend();
}
}
BitStream gPacketStream(NULL, 0);
void TribesGame::processPacketReceiveEvent(PacketReceiveEvent * prEvent)
{
U32 dataSize = prEvent->size - PacketReceiveEventHeaderSize;
gPacketStream.setBuffer(prEvent->data, dataSize);
if(!(prEvent->data[0] & 0x01)) // it's a non-protocol packet of some sort...
{
U8 packetType;
gPacketStream.read(&packetType);
NetAddress *addr = &prEvent->sourceAddress;
if(packetType <= GameHeartbeat)
handleInfoPacket(addr, packetType, &gPacketStream);
else
{
switch(packetType)
{
case ConnectChallengeRequest:
handleConnectChallengeRequest(addr, &gPacketStream);
break;
case ConnectRequest:
handleConnectRequest(addr, &gPacketStream);
break;
case ConnectChallengeResponse:
handleConnectChallengeResponse(addr, &gPacketStream);
break;
case ConnectAccept:
handleConnectAccept(addr, &gPacketStream);
break;
case Disconnect:
handleDisconnect(addr, &gPacketStream);
break;
case ConnectReject:
handleConnectReject(addr, &gPacketStream);
break;
case ConnectChallengeReject:
handleConnectChallengeReject(addr, &gPacketStream);
break;
}
}
}
else
{
// lookup the connection in the addressTable
NetConnection *conn = NetConnection::lookup(&prEvent->sourceAddress);
if(conn)
conn->processRawPacket(&gPacketStream);
}
}
void dispatchInit()
{
gConnectRequest.state = ConnectRequestStruct::NotConnecting;
gNumPendingConnects = 0;
Con::addCommand("allowConnections", cAllowConnections, "allowConnections(bool);", 2, 2);
Con::addCommand("localConnect", cLocalConnect, "localConnect();", 1, 16);
Con::addCommand("connect", cConnect, "connect(addr);", 2, 17);
}
//void GameConnectionRemoved(GameConnection *conn)
//{
// if(conn->isNetworkConnection())
// {
// Con::printf("Issuing Disconnect packet.");
//
// // send a disconnect packet...
// U32 serverConnectSequence, clientConnectSequence;
// conn->getSequences(&clientConnectSequence, &serverConnectSequence);
//
// BitStream *out = BitStream::getPacketStream();
// out->write(U8(Disconnect));
// out->write(serverConnectSequence);
// out->write(clientConnectSequence);
// out->writeString("");
//
// BitStream::sendPacketStream(conn->getNetAddress());
// }
//}
void dispatchCheckTimeouts()
{
static U32 lastTimeoutCheckTime = 0;
U32 time = Platform::getVirtualMilliseconds();
if(time > lastTimeoutCheckTime + TimeoutCheckInterval)
{
// check the connection state:
if(gConnectRequest.state == ConnectRequestStruct::Challenging &&
time > gConnectRequest.lastSendTime + ChallengeRetryTime)
{
if(gConnectRequest.sendCount > ChallengeRetryCount)
connectRequestTimedOut();
else
sendConnectChallengeRequest();
}
else if(gConnectRequest.state == ConnectRequestStruct::Connecting &&
time > gConnectRequest.lastSendTime + ConnectRetryTime)
{
if(gConnectRequest.sendCount > ConnectRetryCount)
connectRequestTimedOut();
else
sendConnectRequest();
}
lastTimeoutCheckTime = time;
NetConnection *walk = NetConnection::getConnectionList();
while(walk)
{
NetConnection *next = walk->getNext();
if(walk->checkTimeout(time))
{
// this baddie timed out
if(walk->isServerConnection())
{
Con::printf("Connection to server timed out");
connectionToServerTimedOut();
}
else
{
Con::printf("Client %d timed out.", walk->getId());
((GameConnection *) walk)->setDisconnectReason("TimedOut");
}
walk->deleteObject();
}
walk = next;
}
}
}
//----------------------------------------------------------------
// DNet external function declarations
//----------------------------------------------------------------
void GameConnectionRejected(NetConnectionId id, BitStream *stream)
{
GameConnection *conn = (GameConnection *) Sim::findObject(id);
if(conn)
conn->deleteObject();
Con::printf("Connection rejected: %s", stream->getBuffer());
}
void GameConnectionEstablished(NetConnectionId id)
{
Con::printf("Connection established %d", id);
}
ConsoleFunction(startRecord, void, 2, 2, "startRecord(fileName)")
{
argc;
NetConnection *conn = NetConnection::getServerConnection();
if(!conn)
return;
conn->startDemoRecord(argv[1]);
}
ConsoleFunction(stopRecord, void, 1, 1, "stopRecord();")
{
argc; argv;
NetConnection *conn = NetConnection::getServerConnection();
if(!conn)
return;
conn->stopRecording();
}
ConsoleFunction(playDemo, void, 2, 2, "playDemo(recFileName)")
{
argc;
GameConnection *conn = new GameConnection(false, true, false);
conn->registerObject();
NetConnection::setServerConnection(conn);
Sim::getRootGroup()->addObject(conn, gServerConnectionName);
if(!conn->replayDemoRecord(argv[1]))
{
Con::printf("Unable to open demo file %s.", argv[1]);
conn->deleteObject();
}
}