📄 rpgnetconnection.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "core/dnet.h"
#include "console/simBase.h"
#include "core/bitStream.h"
#include "sim/pathManager.h"
#include "core/fileStream.h"
#include "core/resManager.h"
#include "sim/pathManager.h"
#include "console/consoleTypes.h"
#include "sim/netInterface.h"
#include <stdarg.h>
#include "server/conn/RPGNetConnection.h"
#include "server/conn/GhostConnection.h"
#include "server/conn/connectionMessageEvent.h"
//#define TGE_RPGTESTING
//namespace CS
//{
S32 gNetBitsSent = 0;
extern S32 gNetBitsReceived;
U32 gGhostUpdates = 0;
enum NetConnectionConstants {
PingTimeout = 4500, ///< milliseconds
DefaultPingRetryCount = 15,
};
SimObjectPtr<NetConnection> NetConnection::mServerConnection;
SimObjectPtr<NetConnection> NetConnection::mLocalClientConnection;
IMPLEMENT_CO_NETEVENT_V1(ConnectionMessageEvent);
void NetConnection::sendConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
{
postNetEvent(new ConnectionMessageEvent(message, sequence, ghostCount));
}
//--------------------------------------------------------------------
IMPLEMENT_CONOBJECT(NetConnection);
NetConnection* NetConnection::mConnectionList = NULL;
NetConnection* NetConnection::mHashTable[NetConnection::HashTableSize] = { NULL, };
MutexInstance NetConnection::ms_mutexConnTable;
bool NetConnection::mFilesWereDownloaded = false;
static inline U32 HashNetAddress(const NetAddress *addr)
{
return *((U32 *)addr->netNum) % NetConnection::HashTableSize;
}
NetConnection *NetConnection::lookup(const NetAddress *addr)
{
U32 hashIndex = HashNetAddress(addr);
NetConnection *walk = NULL;
ms_mutexConnTable.lock(true);
for(walk = mHashTable[hashIndex]; walk; walk = walk->mNextTableHash)
{
if(Net::compareAddresses(addr, walk->getNetAddress()))
break;
}
ms_mutexConnTable.unlock();
return walk;
}
void NetConnection::netAddressTableInsert()
{
U32 hashIndex = HashNetAddress(&mNetAddress);
ms_mutexConnTable.lock(true);
{
mNextTableHash = mHashTable[hashIndex];
mHashTable[hashIndex] = this;
}
ms_mutexConnTable.unlock();
}
void NetConnection::netAddressTableRemove()
{
U32 hashIndex = HashNetAddress(&mNetAddress);
ms_mutexConnTable.lock(true);
{
NetConnection **walk = &mHashTable[hashIndex];
while(*walk)
{
if(*walk == this)
{
*walk = mNextTableHash;
mNextTableHash = NULL;
break;//reurn;
}
walk = &((*walk)->mNextTableHash);
}
}
ms_mutexConnTable.unlock();
}
void NetConnection::setNetAddress(const NetAddress *addr)
{
mNetAddress = *addr;
}
const NetAddress *NetConnection::getNetAddress()
{
return &mNetAddress;
}
void NetConnection::setSequence(U32 sequence)
{
mConnectSequence = sequence;
}
U32 NetConnection::getSequence()
{
return mConnectSequence;
}
static U32 gPacketRateToServer = 32;
static U32 gPacketUpdateDelayToServer = 32;
static U32 gPacketRateToClient = 10;
static U32 gPacketSize = 200;
void NetConnection::consoleInit()
{
Con::addVariable("pref::Net::PacketRateToServer", TypeS32, &gPacketRateToServer);
Con::addVariable("pref::Net::PacketRateToClient", TypeS32, &gPacketRateToClient);
Con::addVariable("pref::Net::PacketSize", TypeS32, &gPacketSize);
Con::addVariable("Stats::netBitsSent", TypeS32, &gNetBitsSent);
Con::addVariable("Stats::netBitsReceived", TypeS32, &gNetBitsReceived);
Con::addVariable("Stats::netGhostUpdates", TypeS32, &gGhostUpdates);
}
void NetConnection::checkMaxRate()
{
// Limit packet rate to server.
if(gPacketRateToServer > 32)
gPacketRateToServer = 32;
if(gPacketRateToServer < 8)
gPacketRateToServer = 8;
// Limit packet rate to client.
if(gPacketRateToClient > 32)
gPacketRateToClient = 32;
if(gPacketRateToClient < 1)
gPacketRateToClient = 1;
// Limit packet size.
if(gPacketSize > 450)
gPacketSize = 450;
if(gPacketSize < 100)
gPacketSize = 100;
gPacketUpdateDelayToServer = 1024 / gPacketRateToServer;
U32 toClientUpdateDelay = 1024 / gPacketRateToClient;
if(mMaxRate.updateDelay != toClientUpdateDelay || mMaxRate.packetSize != gPacketSize)
{
mMaxRate.updateDelay = toClientUpdateDelay;
mMaxRate.packetSize = gPacketSize;
mMaxRate.changed = true;
}
}
//void NetConnection::setSendingEvents(bool sending)
//{
// AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
// mSendingEvents = sending;
//}
void NetConnection::setTranslatesStrings(bool xl)
{
//#ifdef _RPG_NOCOMMENT
AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
mTranslateStrings = xl;
if(mTranslateStrings)
mStringTable = new ConnectionStringTable(this);
//#endif
}
void NetConnection::setNetClassGroup(U32 grp)
{
AssertFatal(!mEstablished, "Error, cannot change net class group after a connection has been established.");
mNetClassGroup = grp;
}
NetConnection::NetConnection()
:m_streamRecv(0,0)
,m_streamSend(0,0)
{
mTranslateStrings = false;
mConnectSequence = 0;
mStringTable = NULL;
//mSendingEvents = true;
mNetClassGroup = NetClassGroupGame;
AssertFatal(mNetClassGroup >= NetClassGroupGame && mNetClassGroup < NetClassGroupsCount,
"Invalid net event class type.");
mSimulatedPing = 0;
mSimulatedPacketLoss = 0;
#ifdef TORQUE_DEBUG_NET
mLogging = false;
#endif
mEstablished = false;
mLastUpdateTime = 0;
mRoundTripTime = 0;
mPacketLoss = 0;
mNextTableHash = NULL;
mSendDelayCredit = 0;
mConnectionState = NotConnected;
mCurrentDownloadingFile = NULL;
mCurrentFileBuffer = NULL;
mNextConnection = NULL;
mPrevConnection = NULL;
mNotifyQueueHead = NULL;
mNotifyQueueTail = NULL;
mCurRate.updateDelay = 102;
mCurRate.packetSize = 200;
mCurRate.changed = false;
mMaxRate.updateDelay = 102;
mMaxRate.packetSize = 200;
mMaxRate.changed = false;
checkMaxRate();
// event management data:
//mNotifyEventList = NULL;
//mSendEventQueueHead = NULL;
//mSendEventQueueTail = NULL;
//mUnorderedSendEventQueueHead = NULL;
//mUnorderedSendEventQueueTail = NULL;
//mWaitSeqEvents = NULL;
//mNextSendEventSeq = FirstValidSendEventSeq;
//mNextRecvEventSeq = FirstValidSendEventSeq;
//mLastAckedEventSeq = -1;
//// ghost management data:
//mScopeObject = NULL;
//mGhostingSequence = 0;
//mGhosting = false;
//mScoping = false;
//mGhostArray = NULL;
//mGhostRefs = NULL;
//mGhostLookupTable = NULL;
//mLocalGhosts = NULL;
//mGhostsActive = 0;
mMissionPathsSent = false;
mDemoWriteStream = NULL;
mDemoReadStream = NULL;
mPingSendCount = 0;
mPingRetryCount = DefaultPingRetryCount;
mLastPingSendTime = Platform::getVirtualMilliseconds();
mCurrentDownloadingFile = NULL;
mCurrentFileBuffer = NULL;
mCurrentFileBufferSize = 0;
mCurrentFileBufferOffset = 0;
mNumDownloadedFiles = 0;
m_pAuthSocket = NULL;
}
NetConnection::~NetConnection()
{
AssertFatal(mNotifyQueueHead == NULL, "Uncleared notifies remain.");
netAddressTableRemove();
dFree(mCurrentFileBuffer);
if(mCurrentDownloadingFile)
ResourceManager->closeStream(mCurrentDownloadingFile);
//delete[] mLocalGhosts;
//delete[] mGhostLookupTable;
//delete[] mGhostRefs;
//delete[] mGhostArray;
delete mStringTable;
if(mDemoWriteStream)
delete mDemoWriteStream;
if(mDemoReadStream)
ResourceManager->closeStream(mDemoReadStream);
}
NetConnection::PacketNotify::PacketNotify()
{
rateChanged = false;
maxRateChanged = false;
sendTime = 0;
eventList = 0;
ghostList = 0;
}
bool NetConnection::checkTimeout(U32 time)
{
#ifdef TORQUE_DEBUG
return false;/// TGE_Net 取消超时处理
#endif
if(!isNetworkConnection())
return false;
if(time > mLastPingSendTime + PingTimeout)
{
if(mPingSendCount >= mPingRetryCount)
return true;
mLastPingSendTime = time;
mPingSendCount++;
sendPingPacket();
}
return false;
}
void NetConnection::keepAlive()
{
mLastPingSendTime = Platform::getVirtualMilliseconds();
mPingSendCount = 0;
}
void NetConnection::handleConnectionEstablished()
{
}
//--------------------------------------------------------------------------
ConsoleMethod(NetConnection,transmitPaths,void,2,2,"conn.transmitPaths();")
{
argc; argv;
//#ifdef _RPG_NOCOMMENT
gServerPathManager->transmitPaths(object);
object->setMissionPathsSent(true);
//#endif
}
ConsoleMethod(NetConnection,clearPaths,void,2,2,"conn.clearPaths();")
{
argc; argv;
object->setMissionPathsSent(false);
}
ConsoleMethod(NetConnection,getAddress,const char *,2,2,"Returns the address we're connected to.")
{
argc; argv;
if(object->isLocalConnection())
return "local";
char *buffer = Con::getReturnBuffer(256);
Net::addressToString(object->getNetAddress(), buffer);
return buffer;
}
ConsoleMethod(NetConnection,setSimulatedNetParams,void,4, 4,"(float packetLoss, int delay)")
{
argc;
object->setSimulatedNetParams(dAtof(argv[2]), dAtoi(argv[3]));
}
ConsoleMethod( NetConnection, getPing, S32, 2, 2, "conn.getPing()" )
{
argc; argv;
return( S32( object->getRoundTripTime() ) );
}
ConsoleMethod( NetConnection, getPacketLoss, S32, 2, 2, "conn.getPacketLoss()" )
{
argc; argv;
return( S32( 100 * object->getPacketLoss() ) );
}
ConsoleMethod( NetConnection, checkMaxRate, void, 2, 2, "conn.checkMaxRate()")
{
argc; argv;
object->checkMaxRate();
}
#ifdef TORQUE_DEBUG_NET
ConsoleMethod( NetConnection, setLogging, void, 3, 3, "conn.setLogging(bool)")
{
argc;
object->setLogging(dAtob(argv[2]));
}
#endif
//--------------------------------------------------------------------
void NetConnection::setEstablished()
{
AssertFatal(!mEstablished, "NetConnection::setEstablished - Error, this NetConnection has already been established.");
ms_mutexConnTable.lock(true);
{
mEstablished = true;
mNextConnection = mConnectionList;
if(mConnectionList)
mConnectionList->mPrevConnection = this;
mConnectionList = this;
}
ms_mutexConnTable.unlock();
//由本身调用lock
if(isNetworkConnection())
netAddressTableInsert();
}
void NetConnection::onRemove()
{
// delete any ghosts that may exist for this connection, but aren't added
while(mGhostAlwaysSaveList.size())
{
delete mGhostAlwaysSaveList[0].ghost;
mGhostAlwaysSaveList.pop_front();
}
ms_mutexConnTable.lock(true);
{
if(mNextConnection)
mNextConnection->mPrevConnection = mPrevConnection;
if(mPrevConnection)
mPrevConnection->mNextConnection = mNextConnection;
if(mConnectionList == this)
mConnectionList = mNextConnection;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -