netConnection.cc 28 KB

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