netConnection.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "network/connectionProtocol.h"
  24. #include "sim/simBase.h"
  25. #include "network/netConnection.h"
  26. #include "io/bitStream.h"
  27. #include "io/fileStream.h"
  28. #include "io/resource/resourceManager.h"
  29. #include "console/consoleTypes.h"
  30. #include "netInterface.h"
  31. #include <stdarg.h>
  32. #include "netConnection_ScriptBinding.h"
  33. S32 gNetBitsSent = 0;
  34. extern S32 gNetBitsReceived;
  35. U32 gGhostUpdates = 0;
  36. enum NetConnectionConstants {
  37. PingTimeout = 4500, ///< milliseconds
  38. DefaultPingRetryCount = 15,
  39. };
  40. SimObjectPtr<NetConnection> NetConnection::mServerConnection;
  41. SimObjectPtr<NetConnection> NetConnection::mLocalClientConnection;
  42. //----------------------------------------------------------------------
  43. /// ConnectionMessageEvent
  44. ///
  45. /// This event is used inside by the connection and subclasses to message
  46. /// itself when sequencing events occur. Right now, the message event
  47. /// only uses 6 bits to transmit the message, so
  48. class ConnectionMessageEvent : public NetEvent
  49. {
  50. U32 sequence;
  51. U32 message;
  52. U32 ghostCount;
  53. public:
  54. ConnectionMessageEvent(U32 msg=0, U32 seq=0, U32 gc=0)
  55. { message = msg; sequence = seq; ghostCount = gc;}
  56. void pack(NetConnection *, BitStream *bstream)
  57. {
  58. bstream->write(sequence);
  59. bstream->writeInt(message, 3);
  60. bstream->writeInt(ghostCount, NetConnection::GhostIdBitSize + 1);
  61. }
  62. void write(NetConnection *, BitStream *bstream)
  63. {
  64. bstream->write(sequence);
  65. bstream->writeInt(message, 3);
  66. bstream->writeInt(ghostCount, NetConnection::GhostIdBitSize + 1);
  67. }
  68. void unpack(NetConnection *, BitStream *bstream)
  69. {
  70. bstream->read(&sequence);
  71. message = bstream->readInt(3);
  72. ghostCount = bstream->readInt(NetConnection::GhostIdBitSize + 1);
  73. }
  74. void process(NetConnection *ps)
  75. {
  76. ps->handleConnectionMessage(message, sequence, ghostCount);
  77. }
  78. DECLARE_CONOBJECT(ConnectionMessageEvent);
  79. };
  80. IMPLEMENT_CO_NETEVENT_V1(ConnectionMessageEvent);
  81. void NetConnection::sendConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
  82. {
  83. postNetEvent(new ConnectionMessageEvent(message, sequence, ghostCount));
  84. }
  85. //--------------------------------------------------------------------
  86. IMPLEMENT_CONOBJECT(NetConnection);
  87. NetConnection* NetConnection::mConnectionList = NULL;
  88. NetConnection* NetConnection::mHashTable[NetConnection::HashTableSize] = { NULL, };
  89. bool NetConnection::mFilesWereDownloaded = false;
  90. static inline U32 HashNetAddress(const NetAddress *addr)
  91. {
  92. return *((U32 *)addr->netNum) % NetConnection::HashTableSize;
  93. }
  94. NetConnection *NetConnection::lookup(const NetAddress *addr)
  95. {
  96. U32 hashIndex = HashNetAddress(addr);
  97. for(NetConnection *walk = mHashTable[hashIndex]; walk; walk = walk->mNextTableHash)
  98. if(Net::compareAddresses(addr, walk->getNetAddress()))
  99. return walk;
  100. return NULL;
  101. }
  102. void NetConnection::netAddressTableInsert()
  103. {
  104. U32 hashIndex = HashNetAddress(&mNetAddress);
  105. mNextTableHash = mHashTable[hashIndex];
  106. mHashTable[hashIndex] = this;
  107. }
  108. void NetConnection::netAddressTableRemove()
  109. {
  110. U32 hashIndex = HashNetAddress(&mNetAddress);
  111. NetConnection **walk = &mHashTable[hashIndex];
  112. while(*walk)
  113. {
  114. if(*walk == this)
  115. {
  116. *walk = mNextTableHash;
  117. mNextTableHash = NULL;
  118. return;
  119. }
  120. walk = &((*walk)->mNextTableHash);
  121. }
  122. }
  123. void NetConnection::setNetAddress(const NetAddress *addr)
  124. {
  125. mNetAddress = *addr;
  126. }
  127. const NetAddress *NetConnection::getNetAddress()
  128. {
  129. return &mNetAddress;
  130. }
  131. void NetConnection::setSequence(U32 sequence)
  132. {
  133. mConnectSequence = sequence;
  134. }
  135. U32 NetConnection::getSequence()
  136. {
  137. return mConnectSequence;
  138. }
  139. static U32 gPacketRateToServer = 32;
  140. static U32 gPacketUpdateDelayToServer = 32;
  141. static U32 gPacketRateToClient = 10;
  142. static U32 gPacketSize = 200;
  143. void NetConnection::consoleInit()
  144. {
  145. Con::addVariable("pref::Net::PacketRateToServer", TypeS32, &gPacketRateToServer);
  146. Con::addVariable("pref::Net::PacketRateToClient", TypeS32, &gPacketRateToClient);
  147. Con::addVariable("pref::Net::PacketSize", TypeS32, &gPacketSize);
  148. Con::addVariable("Stats::netBitsSent", TypeS32, &gNetBitsSent);
  149. Con::addVariable("Stats::netBitsReceived", TypeS32, &gNetBitsReceived);
  150. Con::addVariable("Stats::netGhostUpdates", TypeS32, &gGhostUpdates);
  151. }
  152. void NetConnection::checkMaxRate()
  153. {
  154. // Limit packet rate to server.
  155. if(gPacketRateToServer > 32)
  156. gPacketRateToServer = 32;
  157. if(gPacketRateToServer < 8)
  158. gPacketRateToServer = 8;
  159. // Limit packet rate to client.
  160. if(gPacketRateToClient > 32)
  161. gPacketRateToClient = 32;
  162. if(gPacketRateToClient < 1)
  163. gPacketRateToClient = 1;
  164. // Limit packet size.
  165. if(gPacketSize > 450)
  166. gPacketSize = 450;
  167. if(gPacketSize < 100)
  168. gPacketSize = 100;
  169. gPacketUpdateDelayToServer = 1024 / gPacketRateToServer;
  170. U32 toClientUpdateDelay = 1024 / gPacketRateToClient;
  171. if(mMaxRate.updateDelay != toClientUpdateDelay || mMaxRate.packetSize != gPacketSize)
  172. {
  173. mMaxRate.updateDelay = toClientUpdateDelay;
  174. mMaxRate.packetSize = gPacketSize;
  175. mMaxRate.changed = true;
  176. }
  177. }
  178. void NetConnection::setSendingEvents(bool sending)
  179. {
  180. AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
  181. mSendingEvents = sending;
  182. }
  183. void NetConnection::setTranslatesStrings(bool xl)
  184. {
  185. AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
  186. mTranslateStrings = xl;
  187. if(mTranslateStrings)
  188. mStringTable = new ConnectionStringTable(this);
  189. }
  190. void NetConnection::setNetClassGroup(U32 grp)
  191. {
  192. AssertFatal(!mEstablished, "Error, cannot change net class group after a connection has been established.");
  193. mNetClassGroup = grp;
  194. }
  195. NetConnection::NetConnection()
  196. {
  197. mTranslateStrings = false;
  198. mConnectSequence = 0;
  199. mStringTable = NULL;
  200. mSendingEvents = true;
  201. mNetClassGroup = NetClassGroupGame;
  202. AssertFatal(mNetClassGroup >= NetClassGroupGame && mNetClassGroup < NetClassGroupsCount,
  203. "Invalid net event class type.");
  204. mSimulatedPing = 0;
  205. mSimulatedPacketLoss = 0;
  206. #ifdef TORQUE_DEBUG_NET
  207. mLogging = false;
  208. #endif
  209. mEstablished = false;
  210. mLastUpdateTime = 0;
  211. mRoundTripTime = 0;
  212. mPacketLoss = 0;
  213. mNextTableHash = NULL;
  214. mSendDelayCredit = 0;
  215. mConnectionState = NotConnected;
  216. mCurrentDownloadingFile = NULL;
  217. mCurrentFileBuffer = NULL;
  218. mNextConnection = NULL;
  219. mPrevConnection = NULL;
  220. mNotifyQueueHead = NULL;
  221. mNotifyQueueTail = NULL;
  222. mCurRate.updateDelay = 102;
  223. mCurRate.packetSize = 200;
  224. mCurRate.changed = false;
  225. mMaxRate.updateDelay = 102;
  226. mMaxRate.packetSize = 200;
  227. mMaxRate.changed = false;
  228. checkMaxRate();
  229. // event management data:
  230. mNotifyEventList = NULL;
  231. mSendEventQueueHead = NULL;
  232. mSendEventQueueTail = NULL;
  233. mUnorderedSendEventQueueHead = NULL;
  234. mUnorderedSendEventQueueTail = NULL;
  235. mWaitSeqEvents = NULL;
  236. mNextSendEventSeq = FirstValidSendEventSeq;
  237. mNextRecvEventSeq = FirstValidSendEventSeq;
  238. mLastAckedEventSeq = -1;
  239. // ghost management data:
  240. mScopeObject = NULL;
  241. mGhostingSequence = 0;
  242. mGhosting = false;
  243. mScoping = false;
  244. mGhostArray = NULL;
  245. mGhostRefs = NULL;
  246. mGhostLookupTable = NULL;
  247. mLocalGhosts = NULL;
  248. mGhostsActive = 0;
  249. mMissionPathsSent = false;
  250. mDemoWriteStream = NULL;
  251. mDemoReadStream = NULL;
  252. mPingSendCount = 0;
  253. mPingRetryCount = DefaultPingRetryCount;
  254. mLastPingSendTime = Platform::getVirtualMilliseconds();
  255. mCurrentDownloadingFile = NULL;
  256. mCurrentFileBuffer = NULL;
  257. mCurrentFileBufferSize = 0;
  258. mCurrentFileBufferOffset = 0;
  259. mNumDownloadedFiles = 0;
  260. }
  261. NetConnection::~NetConnection()
  262. {
  263. AssertFatal(mNotifyQueueHead == NULL, "Uncleared notifies remain.");
  264. netAddressTableRemove();
  265. dFree(mCurrentFileBuffer);
  266. if(mCurrentDownloadingFile)
  267. ResourceManager->closeStream(mCurrentDownloadingFile);
  268. delete[] mLocalGhosts;
  269. delete[] mGhostLookupTable;
  270. delete[] mGhostRefs;
  271. delete[] mGhostArray;
  272. delete mStringTable;
  273. if(mDemoWriteStream)
  274. delete mDemoWriteStream;
  275. if(mDemoReadStream)
  276. ResourceManager->closeStream(mDemoReadStream);
  277. }
  278. NetConnection::PacketNotify::PacketNotify()
  279. {
  280. rateChanged = false;
  281. maxRateChanged = false;
  282. sendTime = 0;
  283. eventList = 0;
  284. ghostList = 0;
  285. }
  286. bool NetConnection::checkTimeout(U32 time)
  287. {
  288. if(!isNetworkConnection())
  289. return false;
  290. if(time > mLastPingSendTime + PingTimeout)
  291. {
  292. if(mPingSendCount >= mPingRetryCount)
  293. return true;
  294. mLastPingSendTime = time;
  295. mPingSendCount++;
  296. sendPingPacket();
  297. }
  298. return false;
  299. }
  300. void NetConnection::keepAlive()
  301. {
  302. mLastPingSendTime = Platform::getVirtualMilliseconds();
  303. mPingSendCount = 0;
  304. }
  305. void NetConnection::handleConnectionEstablished()
  306. {
  307. }
  308. //--------------------------------------------------------------------------
  309. void NetConnection::setEstablished()
  310. {
  311. AssertFatal(!mEstablished, "NetConnection::setEstablished - Error, this NetConnection has already been established.");
  312. mEstablished = true;
  313. mNextConnection = mConnectionList;
  314. if(mConnectionList)
  315. mConnectionList->mPrevConnection = this;
  316. mConnectionList = this;
  317. if(isNetworkConnection())
  318. netAddressTableInsert();
  319. }
  320. void NetConnection::onRemove()
  321. {
  322. // delete any ghosts that may exist for this connection, but aren't added
  323. while(mGhostAlwaysSaveList.size())
  324. {
  325. delete mGhostAlwaysSaveList[0].ghost;
  326. mGhostAlwaysSaveList.pop_front();
  327. }
  328. if(mNextConnection)
  329. mNextConnection->mPrevConnection = mPrevConnection;
  330. if(mPrevConnection)
  331. mPrevConnection->mNextConnection = mNextConnection;
  332. if(mConnectionList == this)
  333. mConnectionList = mNextConnection;
  334. while(mNotifyQueueHead)
  335. handleNotify(false);
  336. ghostOnRemove();
  337. eventOnRemove();
  338. Parent::onRemove();
  339. }
  340. char NetConnection::mErrorBuffer[256];
  341. void NetConnection::setLastError(const char *fmt, ...)
  342. {
  343. va_list argptr;
  344. va_start(argptr, fmt);
  345. dVsprintf(mErrorBuffer, sizeof(mErrorBuffer), fmt, argptr);
  346. va_end(argptr);
  347. #ifdef TORQUE_DEBUG_NET
  348. // setLastErrors assert in net_debug builds
  349. AssertFatal(false, mErrorBuffer);
  350. #endif
  351. }
  352. //--------------------------------------------------------------------
  353. void NetConnection::handleNotify(bool recvd)
  354. {
  355. // Con::printf("NET %d: NOTIFY - %d %s", getId(), gPacketId, recvd ? "RECVD" : "DROPPED");
  356. PacketNotify *note = mNotifyQueueHead;
  357. AssertFatal(note != NULL, "Error: got a notify with a null notify head.");
  358. mNotifyQueueHead = mNotifyQueueHead->nextPacket;
  359. if(note->rateChanged && !recvd)
  360. mCurRate.changed = true;
  361. if(note->maxRateChanged && !recvd)
  362. mMaxRate.changed = true;
  363. if(recvd)
  364. {
  365. // Running average of roundTrip time
  366. U32 curTime = Platform::getVirtualMilliseconds();
  367. mRoundTripTime = (mRoundTripTime + (curTime - note->sendTime)) * 0.5f;
  368. packetReceived(note);
  369. }
  370. else
  371. packetDropped(note);
  372. delete note;
  373. }
  374. void NetConnection::processRawPacket(BitStream *bstream)
  375. {
  376. if(mDemoWriteStream)
  377. recordBlock(BlockTypePacket, bstream->getReadByteSize(), bstream->getBuffer());
  378. ConnectionProtocol::processRawPacket(bstream);
  379. }
  380. void NetConnection::handlePacket(BitStream *bstream)
  381. {
  382. // Con::printf("NET %d: RECV - %d", getId(), mLastSeqRecvd);
  383. // clear out any errors
  384. mErrorBuffer[0] = 0;
  385. if(bstream->readFlag())
  386. {
  387. mCurRate.updateDelay = bstream->readInt(10);
  388. mCurRate.packetSize = bstream->readInt(10);
  389. }
  390. if(bstream->readFlag())
  391. {
  392. U32 omaxDelay = bstream->readInt(10);
  393. S32 omaxSize = bstream->readInt(10);
  394. if(omaxDelay < mMaxRate.updateDelay)
  395. omaxDelay = mMaxRate.updateDelay;
  396. if(omaxSize > mMaxRate.packetSize)
  397. omaxSize = mMaxRate.packetSize;
  398. if(omaxDelay != mCurRate.updateDelay || omaxSize != mCurRate.packetSize)
  399. {
  400. mCurRate.updateDelay = omaxDelay;
  401. mCurRate.packetSize = omaxSize;
  402. mCurRate.changed = true;
  403. }
  404. }
  405. readPacket(bstream);
  406. if(mErrorBuffer[0])
  407. connectionError(mErrorBuffer);
  408. }
  409. void NetConnection::connectionError(const char *errorString)
  410. {
  411. }
  412. //--------------------------------------------------------------------
  413. NetConnection::PacketNotify *NetConnection::allocNotify()
  414. {
  415. return new PacketNotify;
  416. }
  417. /// Used when simulating lag.
  418. ///
  419. /// We post this SimEvent when we want to send a packet; it delays for a bit, then
  420. /// sends the actual packet.
  421. class NetDelayEvent : public SimEvent
  422. {
  423. U8 buffer[MaxPacketDataSize];
  424. BitStream stream;
  425. public:
  426. NetDelayEvent(BitStream *inStream) : stream(NULL, 0)
  427. {
  428. dMemcpy(buffer, inStream->getBuffer(), inStream->getPosition());
  429. stream.setBuffer(buffer, inStream->getPosition());
  430. stream.setPosition(inStream->getPosition());
  431. }
  432. void process(SimObject *object)
  433. {
  434. ((NetConnection *) object)->sendPacket(&stream);
  435. }
  436. };
  437. void NetConnection::checkPacketSend(bool force)
  438. {
  439. U32 curTime = Platform::getVirtualMilliseconds();
  440. U32 delay = isConnectionToServer() ? gPacketUpdateDelayToServer : mCurRate.updateDelay;
  441. if(!force)
  442. {
  443. if(curTime < mLastUpdateTime + delay - mSendDelayCredit)
  444. return;
  445. mSendDelayCredit = curTime - (mLastUpdateTime + delay - mSendDelayCredit);
  446. if(mSendDelayCredit > 1000)
  447. mSendDelayCredit = 1000;
  448. if(mDemoWriteStream)
  449. recordBlock(BlockTypeSendPacket, 0, 0);
  450. }
  451. if(windowFull())
  452. return;
  453. BitStream *stream = BitStream::getPacketStream(mCurRate.packetSize);
  454. buildSendPacketHeader(stream);
  455. mLastUpdateTime = curTime;
  456. PacketNotify *note = allocNotify();
  457. if(!mNotifyQueueHead)
  458. mNotifyQueueHead = note;
  459. else
  460. mNotifyQueueTail->nextPacket = note;
  461. mNotifyQueueTail = note;
  462. note->nextPacket = NULL;
  463. note->sendTime = curTime;
  464. note->rateChanged = mCurRate.changed;
  465. note->maxRateChanged = mMaxRate.changed;
  466. if(stream->writeFlag(mCurRate.changed))
  467. {
  468. stream->writeInt(mCurRate.updateDelay, 10);
  469. stream->writeInt(mCurRate.packetSize, 10);
  470. mCurRate.changed = false;
  471. }
  472. if(stream->writeFlag(mMaxRate.changed))
  473. {
  474. stream->writeInt(mMaxRate.updateDelay, 10);
  475. stream->writeInt(mMaxRate.packetSize, 10);
  476. mMaxRate.changed = false;
  477. }
  478. DEBUG_LOG(("PKLOG %d START", getId()) );
  479. writePacket(stream, note);
  480. DEBUG_LOG(("PKLOG %d END - %d", getId(), stream->getCurPos() - start) );
  481. if(mSimulatedPacketLoss && Platform::getRandom() < mSimulatedPacketLoss)
  482. {
  483. //Con::printf("NET %d: SENDDROP - %d", getId(), mLastSendSeq);
  484. return;
  485. }
  486. if(mSimulatedPing)
  487. {
  488. Sim::postEvent(getId(), new NetDelayEvent(stream), Sim::getCurrentTime() + mSimulatedPing);
  489. return;
  490. }
  491. sendPacket(stream);
  492. }
  493. Net::Error NetConnection::sendPacket(BitStream *stream)
  494. {
  495. //Con::printf("NET %d: SEND - %d", getId(), mLastSendSeq);
  496. // do nothing on send if this is a demo replay.
  497. if(mDemoReadStream)
  498. return Net::NoError;
  499. gNetBitsSent = stream->getStreamSize();
  500. if(isLocalConnection())
  501. {
  502. // short circuit connection to the other side.
  503. // handle the packet, then force a notify.
  504. stream->setBuffer(stream->getBuffer(), stream->getPosition(), stream->getPosition());
  505. mRemoteConnection->processRawPacket(stream);
  506. return Net::NoError;
  507. }
  508. else
  509. {
  510. return Net::sendto(getNetAddress(), stream->getBuffer(), stream->getPosition());
  511. }
  512. }
  513. //--------------------------------------------------------------------
  514. //--------------------------------------------------------------------
  515. // these are the virtual function defs for Connection -
  516. // if your subclass has additional data to read / write / notify, add it in these functions.
  517. void NetConnection::readPacket(BitStream *bstream)
  518. {
  519. eventReadPacket(bstream);
  520. ghostReadPacket(bstream);
  521. }
  522. void NetConnection::writePacket(BitStream *bstream, PacketNotify *note)
  523. {
  524. eventWritePacket(bstream, note);
  525. ghostWritePacket(bstream, note);
  526. }
  527. void NetConnection::packetReceived(PacketNotify *note)
  528. {
  529. eventPacketReceived(note);
  530. ghostPacketReceived(note);
  531. }
  532. void NetConnection::packetDropped(PacketNotify *note)
  533. {
  534. eventPacketDropped(note);
  535. ghostPacketDropped(note);
  536. }
  537. //--------------------------------------------------------------------
  538. //--------------------------------------------------------------------
  539. void NetConnection::writeDemoStartBlock(ResizeBitStream* stream)
  540. {
  541. ConnectionProtocol::writeDemoStartBlock(stream);
  542. stream->write(mRoundTripTime);
  543. stream->write(mPacketLoss);
  544. stream->validate();
  545. mStringTable->writeDemoStartBlock(stream);
  546. U32 start = 0;
  547. PacketNotify *note = mNotifyQueueHead;
  548. while(note)
  549. {
  550. start++;
  551. note = note->nextPacket;
  552. }
  553. stream->write(start);
  554. eventWriteStartBlock(stream);
  555. ghostWriteStartBlock(stream);
  556. }
  557. bool NetConnection::readDemoStartBlock(BitStream* stream)
  558. {
  559. ConnectionProtocol::readDemoStartBlock(stream);
  560. stream->read(&mRoundTripTime);
  561. stream->read(&mPacketLoss);
  562. // Read
  563. mStringTable->readDemoStartBlock(stream);
  564. U32 pos;
  565. stream->read(&pos); // notify count
  566. for(U32 i = 0; i < pos; i++)
  567. {
  568. PacketNotify *note = allocNotify();
  569. note->nextPacket = NULL;
  570. if(!mNotifyQueueHead)
  571. mNotifyQueueHead = note;
  572. else
  573. mNotifyQueueTail->nextPacket = note;
  574. mNotifyQueueTail = note;
  575. }
  576. eventReadStartBlock(stream);
  577. ghostReadStartBlock(stream);
  578. return true;
  579. }
  580. bool NetConnection::startDemoRecord(const char *fileName)
  581. {
  582. FileStream *fs = new FileStream;
  583. if(!ResourceManager->openFileForWrite(*fs, fileName))
  584. {
  585. delete fs;
  586. return false;
  587. }
  588. mDemoWriteStream = fs;
  589. mDemoWriteStream->write(mProtocolVersion);
  590. ResizeBitStream bs;
  591. // then write out the start block
  592. writeDemoStartBlock(&bs);
  593. U32 size = bs.getPosition() + 1;
  594. mDemoWriteStream->write(size);
  595. mDemoWriteStream->write(size, bs.getBuffer());
  596. return true;
  597. }
  598. bool NetConnection::replayDemoRecord(const char *fileName)
  599. {
  600. Stream *fs = ResourceManager->openStream(fileName);
  601. if(!fs)
  602. return false;
  603. mDemoReadStream = fs;
  604. mDemoReadStream->read(&mProtocolVersion);
  605. U32 size;
  606. mDemoReadStream->read(&size);
  607. U8 *block = new U8[size];
  608. mDemoReadStream->read(size, block);
  609. BitStream bs(block, size);
  610. bool res = readDemoStartBlock(&bs);
  611. delete[] block;
  612. if(!res)
  613. return false;
  614. // prep for first block read
  615. // type/size stored in U16: [type:4][size:12]
  616. U16 typeSize;
  617. mDemoReadStream->read(&typeSize);
  618. mDemoNextBlockType = typeSize >> 12;
  619. mDemoNextBlockSize = typeSize & 0xFFF;
  620. if(mDemoReadStream->getStatus() != Stream::Ok)
  621. return false;
  622. return true;
  623. }
  624. void NetConnection::stopRecording()
  625. {
  626. if(mDemoWriteStream)
  627. {
  628. delete mDemoWriteStream;
  629. mDemoWriteStream = NULL;
  630. }
  631. }
  632. void NetConnection::recordBlock(U32 type, U32 size, void *data)
  633. {
  634. AssertFatal(type < MaxNumBlockTypes, "NetConnection::recordBlock: invalid type");
  635. AssertFatal(size < MaxBlockSize, "NetConnection::recordBlock: invalid size");
  636. if((type >= MaxNumBlockTypes) || (size >= MaxBlockSize))
  637. return;
  638. if(mDemoWriteStream)
  639. {
  640. // store type/size in U16: [type:4][size:12]
  641. U16 typeSize = (type << 12) | size;
  642. mDemoWriteStream->write(typeSize);
  643. if(size)
  644. mDemoWriteStream->write(size, data);
  645. }
  646. }
  647. void NetConnection::handleRecordedBlock(U32 type, U32 size, void *data)
  648. {
  649. switch(type)
  650. {
  651. case BlockTypePacket: {
  652. BitStream bs(data, size);
  653. processRawPacket(&bs);
  654. break;
  655. }
  656. case BlockTypeSendPacket:
  657. checkPacketSend(true);
  658. break;
  659. }
  660. }
  661. void NetConnection::demoPlaybackComplete()
  662. {
  663. }
  664. void NetConnection::stopDemoPlayback()
  665. {
  666. demoPlaybackComplete();
  667. deleteObject();
  668. }
  669. bool NetConnection::processNextBlock()
  670. {
  671. U8 buffer[MaxPacketDataSize];
  672. // read in and handle
  673. if(mDemoReadStream->read(mDemoNextBlockSize, buffer))
  674. handleRecordedBlock(mDemoNextBlockType, mDemoNextBlockSize, buffer);
  675. U16 typeSize;
  676. mDemoReadStream->read(&typeSize);
  677. mDemoNextBlockType = typeSize >> 12;
  678. mDemoNextBlockSize = typeSize & 0xFFF;
  679. if(mDemoReadStream->getStatus() != Stream::Ok)
  680. {
  681. stopDemoPlayback();
  682. return false;
  683. }
  684. return true;
  685. }
  686. //--------------------------------------------------------------------
  687. //--------------------------------------------------------------------
  688. // some handy string functions for compressing strings over a connection:
  689. enum NetStringConstants
  690. {
  691. NullString = 0,
  692. CString,
  693. TagString,
  694. Integer
  695. };
  696. void NetConnection::validateSendString(const char *str)
  697. {
  698. if(U8(*str) == StringTagPrefixByte)
  699. {
  700. NetStringHandle strHandle(dAtoi(str + 1));
  701. checkString(strHandle);
  702. }
  703. }
  704. void NetConnection::packString(BitStream *stream, const char *str)
  705. {
  706. char buf[16];
  707. if(!*str)
  708. {
  709. stream->writeInt(NullString, 2);
  710. return;
  711. }
  712. if(U8(str[0]) == StringTagPrefixByte)
  713. {
  714. stream->writeInt(TagString, 2);
  715. stream->writeInt(dAtoi(str + 1), ConnectionStringTable::EntryBitSize);
  716. return;
  717. }
  718. if(str[0] == '-' || (str[0] >= '0' && str[0] <= '9'))
  719. {
  720. S32 num = dAtoi(str);
  721. dSprintf(buf, sizeof(buf), "%d", num);
  722. if(!dStrcmp(buf, str))
  723. {
  724. stream->writeInt(Integer, 2);
  725. if(stream->writeFlag(num < 0))
  726. num = -num;
  727. if(stream->writeFlag(num < 128))
  728. {
  729. stream->writeInt(num, 7);
  730. return;
  731. }
  732. if(stream->writeFlag(num < 32768))
  733. {
  734. stream->writeInt(num, 15);
  735. return;
  736. }
  737. else
  738. {
  739. stream->writeInt(num, 31);
  740. return;
  741. }
  742. }
  743. }
  744. stream->writeInt(CString, 2);
  745. stream->writeString(str);
  746. }
  747. void NetConnection::unpackString(BitStream *stream, char readBuffer[1024])
  748. {
  749. U32 code = stream->readInt(2);
  750. switch(code)
  751. {
  752. case NullString:
  753. readBuffer[0] = 0;
  754. return;
  755. case CString:
  756. stream->readString(readBuffer);
  757. return;
  758. case TagString:
  759. U32 tag;
  760. tag = stream->readInt(ConnectionStringTable::EntryBitSize);
  761. readBuffer[0] = StringTagPrefixByte;
  762. dSprintf(readBuffer+1, 1023, "%d", tag);
  763. return;
  764. case Integer:
  765. bool neg;
  766. neg = stream->readFlag();
  767. S32 num;
  768. if(stream->readFlag())
  769. num = stream->readInt(7);
  770. else if(stream->readFlag())
  771. num = stream->readInt(15);
  772. else
  773. num = stream->readInt(31);
  774. if(neg)
  775. num = -num;
  776. dSprintf(readBuffer, 1024, "%d", num);
  777. }
  778. }
  779. void NetConnection::packNetStringHandleU(BitStream *stream, NetStringHandle &h)
  780. {
  781. if(stream->writeFlag(h.isValidString() ))
  782. {
  783. bool isReceived;
  784. U32 netIndex = checkString(h, &isReceived);
  785. if(stream->writeFlag(isReceived))
  786. stream->writeInt(netIndex, ConnectionStringTable::EntryBitSize);
  787. else
  788. stream->writeString(h.getString());
  789. }
  790. }
  791. NetStringHandle NetConnection::unpackNetStringHandleU(BitStream *stream)
  792. {
  793. NetStringHandle ret;
  794. if(stream->readFlag())
  795. {
  796. if(stream->readFlag())
  797. ret = mStringTable->lookupString(stream->readInt(ConnectionStringTable::EntryBitSize));
  798. else
  799. {
  800. char buf[256];
  801. stream->readString(buf);
  802. ret = NetStringHandle(buf);
  803. }
  804. }
  805. return ret;
  806. }
  807. //----------------------------------------------------------------------------
  808. //----------------------------------------------------------------------------
  809. //----------------------------------------------------------------------------
  810. void NetConnection::setAddressDigest(U32 digest[4])
  811. {
  812. mAddressDigest[0] = digest[0];
  813. mAddressDigest[1] = digest[1];
  814. mAddressDigest[2] = digest[2];
  815. mAddressDigest[3] = digest[3];
  816. }
  817. void NetConnection::getAddressDigest(U32 digest[4])
  818. {
  819. digest[0] = mAddressDigest[0];
  820. digest[1] = mAddressDigest[1];
  821. digest[2] = mAddressDigest[2];
  822. digest[3] = mAddressDigest[3];
  823. }
  824. bool NetConnection::canRemoteCreate()
  825. {
  826. return false;
  827. }
  828. void NetConnection::onTimedOut()
  829. {
  830. }
  831. void NetConnection::connect(const NetAddress *address)
  832. {
  833. mNetAddress = *address;
  834. GNet->startConnection(this);
  835. }
  836. void NetConnection::onConnectTimedOut()
  837. {
  838. }
  839. void NetConnection::sendDisconnectPacket(const char *reason)
  840. {
  841. GNet->sendDisconnectPacket(this, reason);
  842. }
  843. void NetConnection::onDisconnect(const char *reason)
  844. {
  845. }
  846. void NetConnection::onConnectionRejected(const char *reason)
  847. {
  848. }
  849. void NetConnection::onConnectionEstablished(bool isInitiator)
  850. {
  851. }
  852. void NetConnection::handleStartupError(const char *errorString)
  853. {
  854. }
  855. void NetConnection::writeConnectRequest(BitStream *stream)
  856. {
  857. stream->write(mNetClassGroup);
  858. stream->write(U32(AbstractClassRep::getClassCRC(mNetClassGroup)));
  859. }
  860. bool NetConnection::readConnectRequest(BitStream *stream, const char **errorString)
  861. {
  862. U32 classGroup, classCRC;
  863. stream->read(&classGroup);
  864. stream->read(&classCRC);
  865. if(classGroup == mNetClassGroup && classCRC == AbstractClassRep::getClassCRC(mNetClassGroup))
  866. return true;
  867. *errorString = "CHR_INVALID";
  868. return false;
  869. }
  870. void NetConnection::writeConnectAccept(BitStream *stream)
  871. {
  872. }
  873. bool NetConnection::readConnectAccept(BitStream *stream, const char **errorString)
  874. {
  875. return true;
  876. }