123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "network/connectionProtocol.h"
- #include "console/consoleTypes.h"
- #include "sim/simBase.h"
- #include "io/bitStream.h"
- #include "game/gameConnection.h"
- #include "io/resource/resourceManager.h"
- #include "gameConnection_ScriptBinding.h"
- //----------------------------------------------------------------------------
- #define MAX_MOVE_PACKET_SENDS 4
- #define ControlRequestTime 5000
- const U32 GameConnection::CurrentProtocolVersion = 12;
- const U32 GameConnection::MinRequiredProtocolVersion = 12;
- //----------------------------------------------------------------------------
- IMPLEMENT_CONOBJECT(GameConnection);
- S32 GameConnection::mLagThresholdMS = 0;
- //----------------------------------------------------------------------------
- GameConnection::GameConnection()
- {
- mLagging = false;
- mAuthInfo = NULL;
- mConnectArgc = 0;
- for(U32 i = 0; i < MaxConnectArgs; i++)
- mConnectArgv[i] = 0;
- mJoinPassword = NULL;
- mDisconnectReason[0] = 0;
-
- }
- GameConnection::~GameConnection()
- {
- delete mAuthInfo;
- for(U32 i = 0; i < mConnectArgc; i++)
- dFree(mConnectArgv[i]);
- dFree(mJoinPassword);
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- bool GameConnection::canRemoteCreate()
- {
- return true;
- }
- void GameConnection::setConnectArgs(U32 argc, const char **argv)
- {
- if(argc > MaxConnectArgs)
- argc = MaxConnectArgs;
- mConnectArgc = argc;
- for(U32 i = 0; i < mConnectArgc; i++)
- mConnectArgv[i] = dStrdup(argv[i]);
- }
- void GameConnection::setJoinPassword(const char *password)
- {
- mJoinPassword = dStrdup(password);
- }
- void GameConnection::onTimedOut()
- {
- if(isConnectionToServer())
- {
- Con::printf("Connection to server timed out");
- Con::executef(this, 1, "onConnectionTimedOut");
- }
- else
- {
- Con::printf("Client %d timed out.", getId());
- setDisconnectReason("TimedOut");
- }
- }
- void GameConnection::onConnectionEstablished(bool isInitiator)
- {
- if(isInitiator)
- {
- setGhostFrom(false);
- setGhostTo(true);
- setSendingEvents(true);
- setTranslatesStrings(true);
- setIsConnectionToServer();
- mServerConnection = this;
- Con::printf("Connection established %d", getId());
- Con::executef(this, 1, "onConnectionAccepted");
- }
- else
- {
- setGhostFrom(true);
- setGhostTo(false);
- setSendingEvents(true);
- setTranslatesStrings(true);
- Sim::getClientGroup()->addObject(this);
- const char *argv[MaxConnectArgs + 2];
- argv[0] = "onConnect";
- for(U32 i = 0; i < mConnectArgc; i++)
- argv[i + 2] = mConnectArgv[i];
- Con::execute(this, mConnectArgc + 2, argv);
- }
- }
- void GameConnection::onConnectTimedOut()
- {
- Con::executef(this, 1, "onConnectRequestTimedOut");
- }
- void GameConnection::onDisconnect(const char *reason)
- {
- if(isConnectionToServer())
- {
- Con::printf("Connection with server lost.");
- Con::executef(this, 2, "onConnectionDropped", reason);
- }
- else
- {
- Con::printf("Client %d disconnected.", getId());
- setDisconnectReason(reason);
- }
- }
- void GameConnection::onConnectionRejected(const char *reason)
- {
- Con::executef(this, 2, "onConnectRequestRejected", reason);
- }
- void GameConnection::handleStartupError(const char *errorString)
- {
- Con::executef(this, 2, "onConnectRequestRejected", errorString);
- }
- void GameConnection::writeConnectAccept(BitStream *stream)
- {
- Parent::writeConnectAccept(stream);
- stream->write(getProtocolVersion());
- }
- bool GameConnection::readConnectAccept(BitStream *stream, const char **errorString)
- {
- if(!Parent::readConnectAccept(stream, errorString))
- return false;
- U32 protocolVersion;
- stream->read(&protocolVersion);
- if(protocolVersion < MinRequiredProtocolVersion || protocolVersion > CurrentProtocolVersion)
- {
- *errorString = "CHR_PROTOCOL"; // this should never happen unless someone is faking us out.
- return false;
- }
- return true;
- }
- void GameConnection::writeConnectRequest(BitStream *stream)
- {
- Parent::writeConnectRequest(stream);
- stream->writeString(GameString);
- stream->write(CurrentProtocolVersion);
- stream->write(MinRequiredProtocolVersion);
- stream->writeString(mJoinPassword);
- stream->write(mConnectArgc);
- for(U32 i = 0; i < mConnectArgc; i++)
- stream->writeString(mConnectArgv[i]);
- }
- bool GameConnection::readConnectRequest(BitStream *stream, const char **errorString)
- {
- if(!Parent::readConnectRequest(stream, errorString))
- return false;
- U32 currentProtocol, minProtocol;
- char gameString[256];
- stream->readString(gameString);
- if(dStrcmp(gameString, GameString))
- {
- *errorString = "CHR_GAME";
- return false;
- }
- stream->read(¤tProtocol);
- stream->read(&minProtocol);
- char joinPassword[256];
- stream->readString(joinPassword);
- if(currentProtocol < MinRequiredProtocolVersion)
- {
- *errorString = "CHR_PROTOCOL_LESS";
- return false;
- }
- if(minProtocol > CurrentProtocolVersion)
- {
- *errorString = "CHR_PROTOCOL_GREATER";
- return false;
- }
- setProtocolVersion(currentProtocol < CurrentProtocolVersion ? currentProtocol : CurrentProtocolVersion);
- const char *serverPassword = Con::getVariable("Pref::Server::Password");
- if(serverPassword[0])
- {
- if(dStrcmp(joinPassword, serverPassword))
- {
- *errorString = "CHR_PASSWORD";
- return false;
- }
- }
- stream->read(&mConnectArgc);
- if(mConnectArgc > MaxConnectArgs)
- {
- *errorString = "CR_INVALID_ARGS";
- return false;
- }
- const char *connectArgv[MaxConnectArgs + 3];
- for(U32 i = 0; i < mConnectArgc; i++)
- {
- char argString[256];
- stream->readString(argString);
- mConnectArgv[i] = dStrdup(argString);
- connectArgv[i + 3] = mConnectArgv[i];
- }
- connectArgv[0] = "onConnectRequest";
- char buffer[256];
- Net::addressToString(getNetAddress(), buffer);
- connectArgv[2] = buffer;
- const char *ret = Con::execute(this, mConnectArgc + 3, connectArgv);
- if(ret[0])
- {
- *errorString = ret;
- return false;
- }
- return true;
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- void GameConnection::connectionError(const char *errorString)
- {
- if(isConnectionToServer())
- {
- Con::printf("Connection error: %s.", errorString);
- Con::executef(this, 2, "onConnectionError", errorString);
- }
- else
- {
- Con::printf("Client %d packet error: %s.", getId(), errorString);
- setDisconnectReason("Packet Error.");
- }
- deleteObject();
- }
- void GameConnection::setAuthInfo(const AuthInfo *info)
- {
- mAuthInfo = new AuthInfo;
- *mAuthInfo = *info;
- }
- const AuthInfo *GameConnection::getAuthInfo()
- {
- return mAuthInfo;
- }
- //----------------------------------------------------------------------------
- bool GameConnection::onAdd()
- {
- if (!Parent::onAdd())
- return false;
- return true;
- }
- void GameConnection::onRemove()
- {
- if(isNetworkConnection())
- {
- sendDisconnectPacket(mDisconnectReason);
- }
- if(!isConnectionToServer())
- Con::executef(this, 2, "onDrop", mDisconnectReason);
- Parent::onRemove();
- }
- void GameConnection::setDisconnectReason(const char *str)
- {
- dStrncpy(mDisconnectReason, str, sizeof(mDisconnectReason) - 1);
- mDisconnectReason[sizeof(mDisconnectReason) - 1] = 0;
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- void GameConnection::readPacket(BitStream *bstream)
- {
- //Con::printf("GameConnection::handlePacket - readPacket ---");
- char stringBuf[256];
- stringBuf[0] = 0;
- bstream->setStringBuffer(stringBuf);
- bstream->clearCompressionPoint();
-
- Parent::readPacket(bstream);
- bstream->clearCompressionPoint();
- bstream->setStringBuffer(NULL);
- }
- void GameConnection::writePacket(BitStream *bstream, PacketNotify *note)
- {
- char stringBuf[256];
- bstream->clearCompressionPoint();
- stringBuf[0] = 0;
- bstream->setStringBuffer(stringBuf);
-
- Parent::writePacket(bstream, note);
- bstream->clearCompressionPoint();
- bstream->setStringBuffer(NULL);
- }
- void GameConnection::detectLag()
- {
- //see if we're lagging...
- S32 curTime = Sim::getCurrentTime();
- if (curTime - mLastPacketTime > mLagThresholdMS)
- {
- if (!mLagging)
- {
- mLagging = true;
- Con::executef(this, 2, "setLagIcon", "true");
- }
- }
- else if (mLagging)
- {
- mLagging = false;
- Con::executef(this, 2, "setLagIcon", "false");
- }
- }
- GameConnection::GamePacketNotify::GamePacketNotify()
- {
- // need to fill in empty notifes for demo start block
-
- }
- NetConnection::PacketNotify *GameConnection::allocNotify()
- {
- return new GamePacketNotify;
- }
- void GameConnection::packetReceived(PacketNotify *note)
- {
- //record the time so we can tell if we're lagging...
- mLastPacketTime = Sim::getCurrentTime();
- Parent::packetReceived(note);
- }
- void GameConnection::packetDropped(PacketNotify *note)
- {
- Parent::packetDropped(note);
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
-
- void GameConnection::handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
- {
- Parent::handleConnectionMessage(message, sequence, ghostCount);
- }
- //--------------------------------------------------------------------------
- void GameConnection::consoleInit()
- {
- Con::addVariable("Pref::Net::LagThreshold", TypeS32, &mLagThresholdMS);
- }
|