netConnection.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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 "core/dnet.h"
  24. #include "console/simBase.h"
  25. #include "sim/netConnection.h"
  26. #include "core/stream/bitStream.h"
  27. #include "core/stream/fileStream.h"
  28. #ifndef TORQUE_TGB_ONLY
  29. #include "scene/pathManager.h"
  30. #endif
  31. #include "console/consoleTypes.h"
  32. #include "sim/netInterface.h"
  33. #include "console/engineAPI.h"
  34. #include <stdarg.h>
  35. IMPLEMENT_SCOPE( NetAPI, Net,, "Networking functionality." );
  36. IMPLEMENT_NONINSTANTIABLE_CLASS( NetEvent,
  37. "An event to be sent over the network." )
  38. END_IMPLEMENT_CLASS;
  39. S32 gNetBitsSent = 0;
  40. extern S32 gNetBitsReceived;
  41. U32 gGhostUpdates = 0;
  42. enum NetConnectionConstants {
  43. PingTimeout = 4500, ///< milliseconds
  44. DefaultPingRetryCount = 15,
  45. };
  46. SimObjectPtr<NetConnection> NetConnection::mServerConnection;
  47. SimObjectPtr<NetConnection> NetConnection::mLocalClientConnection;
  48. //----------------------------------------------------------------------
  49. /// ConnectionMessageEvent
  50. ///
  51. /// This event is used inside by the connection and subclasses to message
  52. /// itself when sequencing events occur. Right now, the message event
  53. /// only uses 6 bits to transmit the message, so
  54. class ConnectionMessageEvent : public NetEvent
  55. {
  56. U32 sequence;
  57. U32 message;
  58. U32 ghostCount;
  59. public:
  60. typedef NetEvent Parent;
  61. ConnectionMessageEvent(U32 msg=0, U32 seq=0, U32 gc=0)
  62. { message = msg; sequence = seq; ghostCount = gc;}
  63. void pack(NetConnection *, BitStream *bstream)
  64. {
  65. bstream->write(sequence);
  66. bstream->writeInt(message, 3);
  67. bstream->writeInt(ghostCount, NetConnection::GhostIdBitSize + 1);
  68. }
  69. void write(NetConnection *, BitStream *bstream)
  70. {
  71. bstream->write(sequence);
  72. bstream->writeInt(message, 3);
  73. bstream->writeInt(ghostCount, NetConnection::GhostIdBitSize + 1);
  74. }
  75. void unpack(NetConnection *, BitStream *bstream)
  76. {
  77. bstream->read(&sequence);
  78. message = bstream->readInt(3);
  79. ghostCount = bstream->readInt(NetConnection::GhostIdBitSize + 1);
  80. }
  81. void process(NetConnection *ps)
  82. {
  83. ps->handleConnectionMessage(message, sequence, ghostCount);
  84. }
  85. DECLARE_CONOBJECT(ConnectionMessageEvent);
  86. };
  87. IMPLEMENT_CO_NETEVENT_V1(ConnectionMessageEvent);
  88. ConsoleDocClass( ConnectionMessageEvent,
  89. "@brief This event is used inside by the connection and subclasses to message itself when sequencing events occur.\n\n"
  90. "Not intended for game development, for editors or internal use only.\n\n "
  91. "@internal");
  92. void NetConnection::sendConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
  93. {
  94. postNetEvent(new ConnectionMessageEvent(message, sequence, ghostCount));
  95. }
  96. //--------------------------------------------------------------------
  97. IMPLEMENT_CONOBJECT(NetConnection);
  98. ConsoleDocClass( NetConnection,
  99. "@brief Provides the basis for implementing a multiplayer game protocol.\n\n"
  100. "NetConnection combines a low-level notify protocol implemented in ConnectionProtocol with a SimGroup, "
  101. "and implements several distinct subsystems:\n\n"
  102. "- <b>Event Manager</b> This is responsible for transmitting NetEvents over the wire. "
  103. "It deals with ensuring that the various types of NetEvents are delivered appropriately, "
  104. "and with notifying the event of its delivery status.\n\n"
  105. "- <b>Move Manager</b> This is responsible for transferring a Move to the server 32 "
  106. "times a second (on the client) and applying it to the control object (on the server).\n\n"
  107. "- <b>Ghost Manager</b> This is responsible for doing scoping calculations (on the server "
  108. "side) and transmitting most-recent ghost information to the client.\n\n"
  109. "- <b>File Transfer</b> It is often the case that clients will lack important files when "
  110. "connecting to a server which is running a mod or new map. This subsystem allows the "
  111. "server to transfer such files to the client.\n\n"
  112. "- <b>Networked String Table</b> String data can easily soak up network bandwidth, so for "
  113. "efficiency, we implement a networked string table. We can then notify the connection "
  114. "of strings we will reference often, such as player names, and transmit only a tag, "
  115. "instead of the whole string.\n\n"
  116. "- <b>Demo Recording</b> A demo in Torque is a log of the network traffic between client "
  117. "and server; when a NetConnection records a demo, it simply logs this data to a file. When "
  118. "it plays a demo back, it replays the logged data.\n\n"
  119. "- <b>Connection Database</b> This is used to keep track of all the NetConnections; it can "
  120. "be iterated over (for instance, to send an event to all active connections), or queried "
  121. "by address.\n\n"
  122. "The NetConnection is a SimGroup. On the client side, it contains all the objects which have been "
  123. "ghosted to that client. On the server side, it is empty; it can be used (typically in script) to "
  124. "hold objects related to the connection. For instance, you might place an observation camera in the "
  125. "NetConnnection. In both cases, when the connection is destroyed, so are the contained objects.\n\n"
  126. "The NetConnection also has the concept of local connections. These are used when the client and "
  127. "server reside in the same process. A local connection is typically required to use the standard "
  128. "Torque world building tools. A local connection is also required when building a single player "
  129. "game.\n\n"
  130. "@see @ref Networking, @ref ghosting_scoping, @ref netconnection_simgroup, @ref local_connections, GameConnection, AIConnection, and AIClient.\n\n"
  131. "@ingroup Networking\n");
  132. NetConnection* NetConnection::mConnectionList = NULL;
  133. NetConnection* NetConnection::mHashTable[NetConnection::HashTableSize] = { NULL, };
  134. bool NetConnection::mFilesWereDownloaded = false;
  135. static inline U32 HashNetAddress(const NetAddress *addr)
  136. {
  137. return addr->getHash() % NetConnection::HashTableSize;
  138. }
  139. NetConnection *NetConnection::lookup(const NetAddress *addr)
  140. {
  141. U32 hashIndex = HashNetAddress(addr);
  142. for(NetConnection *walk = mHashTable[hashIndex]; walk; walk = walk->mNextTableHash)
  143. if(Net::compareAddresses(addr, walk->getNetAddress()))
  144. return walk;
  145. return NULL;
  146. }
  147. void NetConnection::netAddressTableInsert()
  148. {
  149. U32 hashIndex = HashNetAddress(&mNetAddress);
  150. mNextTableHash = mHashTable[hashIndex];
  151. mHashTable[hashIndex] = this;
  152. }
  153. void NetConnection::netAddressTableRemove()
  154. {
  155. U32 hashIndex = HashNetAddress(&mNetAddress);
  156. NetConnection **walk = &mHashTable[hashIndex];
  157. while(*walk)
  158. {
  159. if(*walk == this)
  160. {
  161. *walk = mNextTableHash;
  162. mNextTableHash = NULL;
  163. return;
  164. }
  165. walk = &((*walk)->mNextTableHash);
  166. }
  167. }
  168. void NetConnection::setNetAddress(const NetAddress *addr)
  169. {
  170. mNetAddress = *addr;
  171. }
  172. const NetAddress *NetConnection::getNetAddress()
  173. {
  174. return &mNetAddress;
  175. }
  176. void NetConnection::setSequence(U32 sequence)
  177. {
  178. mConnectSequence = sequence;
  179. }
  180. U32 NetConnection::getSequence()
  181. {
  182. return mConnectSequence;
  183. }
  184. static U32 gPacketRateToServer = 32;
  185. static U32 gPacketUpdateDelayToServer = 32;
  186. static U32 gPacketRateToClient = 10;
  187. static U32 gPacketSize = 508;
  188. void NetConnection::consoleInit()
  189. {
  190. Con::addVariable("$pref::Net::PacketRateToServer", TypeS32, &gPacketRateToServer,
  191. "@brief Sets how often packets are sent from the client to the server.\n\n"
  192. "It is possible to control how often packets may be sent to the server. This may be "
  193. "used to throttle the amount of bandwidth being used, but should be adjusted with "
  194. "caution.\n\n"
  195. "The actual formula used to calculate the delay between sending packets to the server is:\n"
  196. "@code\n"
  197. "Packet Update Delay To Server = 1024 / $pref::Net::PacketRateToServer"
  198. "@endcode\n"
  199. "with the result in ms. A minimum rate of 8 is enforced in the source code. The default "
  200. "value is 32.\n\n"
  201. "@note When using a local connection (@ref local_connections) be aware that this variable "
  202. "is always forced to 128.\n\n"
  203. "@ingroup Networking");
  204. Con::addVariable("$pref::Net::PacketRateToClient", TypeS32, &gPacketRateToClient,
  205. "@brief Sets how often packets are sent from the server to a client.\n\n"
  206. "It is possible to control how often packets may be sent to the clients. This may be "
  207. "used to throttle the amount of bandwidth being used, but should be adjusted with "
  208. "caution.\n\n"
  209. "The actual formula used to calculate the delay between sending packets to a client is:\n"
  210. "@code\n"
  211. "Packet Update Delay To Client = 1024 / $pref::Net::PacketRateToClient"
  212. "@endcode\n"
  213. "with the result in ms. A minimum rate of 1 is enforced in the source code. The default "
  214. "value is 10.\n\n"
  215. "@note When using a local connection (@ref local_connections) be aware that this variable "
  216. "is always forced to 128.\n\n"
  217. "@ingroup Networking");
  218. Con::addVariable("$pref::Net::PacketSize", TypeS32, &gPacketSize,
  219. "@brief Sets the maximum size in bytes an individual network packet may be.\n\n"
  220. "It is possible to control how large each individual network packet may be. Increasing "
  221. "its size from the default allows for more data to be sent on each network send. "
  222. "However, this value should be changed with caution as too large a value will cause "
  223. "packets to be split up by the networking platform or hardware, which is something "
  224. "Torque cannot handle.\n\n"
  225. "A minimum packet size of 100 bytes is enforced in the source code. There is no "
  226. "enforced maximum. The default value is 200 bytes.\n\n"
  227. "@note When using a local connection (@ref local_connections) be aware that this variable "
  228. "is always forced to 1024 bytes.\n\n"
  229. "@ingroup Networking");
  230. Con::addVariable("$Stats::netBitsSent", TypeS32, &gNetBitsSent,
  231. "@brief The number of bytes sent during the last packet send operation.\n\n"
  232. "@note Even though this variable has 'Bits' in it, the value is indeed reported in bytes. This name "
  233. "is a legacy holdover and remains for compatibility reasons.\n"
  234. "@ingroup Networking");
  235. Con::addVariable("$Stats::netBitsReceived", TypeS32, &gNetBitsReceived,
  236. "@brief The number of bytes received during the last packet process operation.\n\n"
  237. "@note Even though this variable has 'Bits' in it, the value is indeed reported in bytes. This name "
  238. "is a legacy holdover and remains for compatibility reasons.\n"
  239. "@ingroup Networking");
  240. Con::addVariable("$Stats::netGhostUpdates", TypeS32, &gGhostUpdates,
  241. "@brief The total number of ghosts added, removed, and/or updated on the client "
  242. "during the last packet process operation.\n\n"
  243. "@ingroup Networking");
  244. }
  245. void NetConnection::checkMaxRate()
  246. {
  247. // Enforce some minimum limits to the network settings.
  248. gPacketRateToServer = getMax( gPacketRateToServer, (U32)8 );
  249. gPacketRateToClient = getMax( gPacketRateToClient, (U32)1 );
  250. gPacketSize = getMax( gPacketSize, (U32)100 );
  251. U32 packetRateToServer = gPacketRateToServer;
  252. U32 packetRateToClient = gPacketRateToClient;
  253. U32 packetSize = gPacketSize;
  254. if (isLocalConnection())
  255. {
  256. packetRateToServer = 128;
  257. packetRateToClient = 128;
  258. // These changes introduced in T3D 1.1 Preview reduce the packet headroom which leads
  259. // to some spells and effects running out of room when dynamic variables are used
  260. // to send launch-time parameters to clients.
  261. packetSize = 512;
  262. }
  263. gPacketUpdateDelayToServer = 1024 / packetRateToServer;
  264. U32 toClientUpdateDelay = 1024 / packetRateToClient;
  265. if(mMaxRate.updateDelay != toClientUpdateDelay || mMaxRate.packetSize != packetSize)
  266. {
  267. mMaxRate.updateDelay = toClientUpdateDelay;
  268. mMaxRate.packetSize = packetSize;
  269. mMaxRate.changed = true;
  270. }
  271. }
  272. void NetConnection::setSendingEvents(bool sending)
  273. {
  274. AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
  275. mSendingEvents = sending;
  276. }
  277. void NetConnection::setTranslatesStrings(bool xl)
  278. {
  279. AssertFatal(!mEstablished, "Error, cannot change event behavior after a connection has been established.");
  280. mTranslateStrings = xl;
  281. if(mTranslateStrings)
  282. mStringTable = new ConnectionStringTable(this);
  283. }
  284. void NetConnection::setNetClassGroup(U32 grp)
  285. {
  286. AssertFatal(!mEstablished, "Error, cannot change net class group after a connection has been established.");
  287. mNetClassGroup = grp;
  288. }
  289. NetConnection::NetConnection()
  290. : mNetAddress()
  291. {
  292. mTranslateStrings = false;
  293. mConnectSequence = 0;
  294. mStringTable = NULL;
  295. mSendingEvents = true;
  296. mNetClassGroup = NetClassGroupGame;
  297. AssertFatal(mNetClassGroup >= NetClassGroupGame && mNetClassGroup < NetClassGroupsCount,
  298. "Invalid net event class type.");
  299. mSimulatedPing = 0;
  300. mSimulatedPacketLoss = 0;
  301. #ifdef TORQUE_DEBUG_NET
  302. mLogging = false;
  303. #endif
  304. mEstablished = false;
  305. mLastUpdateTime = 0;
  306. mRoundTripTime = 0;
  307. mPacketLoss = 0;
  308. mNextTableHash = NULL;
  309. mSendDelayCredit = 0;
  310. mConnectionState = NotConnected;
  311. mCurrentDownloadingFile = NULL;
  312. mCurrentFileBuffer = NULL;
  313. mNextConnection = NULL;
  314. mPrevConnection = NULL;
  315. mNotifyQueueHead = NULL;
  316. mNotifyQueueTail = NULL;
  317. mCurRate.updateDelay = 102;
  318. mCurRate.packetSize = 200;
  319. mCurRate.changed = false;
  320. mMaxRate.updateDelay = 102;
  321. mMaxRate.packetSize = 200;
  322. mMaxRate.changed = false;
  323. checkMaxRate();
  324. // event management data:
  325. mNotifyEventList = NULL;
  326. mSendEventQueueHead = NULL;
  327. mSendEventQueueTail = NULL;
  328. mUnorderedSendEventQueueHead = NULL;
  329. mUnorderedSendEventQueueTail = NULL;
  330. mWaitSeqEvents = NULL;
  331. mNextSendEventSeq = FirstValidSendEventSeq;
  332. mNextRecvEventSeq = FirstValidSendEventSeq;
  333. mLastAckedEventSeq = -1;
  334. // ghost management data:
  335. mScopeObject = NULL;
  336. mGhostingSequence = 0;
  337. mGhosting = false;
  338. mScoping = false;
  339. mGhostArray = NULL;
  340. mGhostRefs = NULL;
  341. mGhostLookupTable = NULL;
  342. mLocalGhosts = NULL;
  343. mGhostsActive = 0;
  344. mMissionPathsSent = false;
  345. mDemoWriteStream = NULL;
  346. mDemoReadStream = NULL;
  347. mPingSendCount = 0;
  348. mPingRetryCount = DefaultPingRetryCount;
  349. mLastPingSendTime = Platform::getVirtualMilliseconds();
  350. mCurrentDownloadingFile = NULL;
  351. mCurrentFileBuffer = NULL;
  352. mCurrentFileBufferSize = 0;
  353. mCurrentFileBufferOffset = 0;
  354. mNumDownloadedFiles = 0;
  355. // Disable starting a new journal recording or playback from here on
  356. Journal::Disable();
  357. // Ensure NetAddress is cleared
  358. dMemset(&mNetAddress, '\0', sizeof(NetAddress));
  359. }
  360. NetConnection::~NetConnection()
  361. {
  362. AssertFatal(mNotifyQueueHead == NULL, "Uncleared notifies remain.");
  363. netAddressTableRemove();
  364. dFree(mCurrentFileBuffer);
  365. if(mCurrentDownloadingFile)
  366. delete mCurrentDownloadingFile;
  367. delete[] mLocalGhosts;
  368. delete[] mGhostLookupTable;
  369. delete[] mGhostRefs;
  370. delete[] mGhostArray;
  371. delete mStringTable;
  372. if(mDemoWriteStream)
  373. delete mDemoWriteStream;
  374. if(mDemoReadStream)
  375. delete mDemoReadStream;
  376. }
  377. NetConnection::PacketNotify::PacketNotify()
  378. {
  379. rateChanged = false;
  380. maxRateChanged = false;
  381. sendTime = 0;
  382. eventList = 0;
  383. ghostList = 0;
  384. subList = NULL;
  385. nextPacket = NULL;
  386. }
  387. bool NetConnection::checkTimeout(U32 time)
  388. {
  389. if(!isNetworkConnection())
  390. return false;
  391. if(time > mLastPingSendTime + PingTimeout)
  392. {
  393. if(mPingSendCount >= mPingRetryCount)
  394. return true;
  395. mLastPingSendTime = time;
  396. mPingSendCount++;
  397. sendPingPacket();
  398. }
  399. return false;
  400. }
  401. void NetConnection::keepAlive()
  402. {
  403. mLastPingSendTime = Platform::getVirtualMilliseconds();
  404. mPingSendCount = 0;
  405. }
  406. void NetConnection::handleConnectionEstablished()
  407. {
  408. }
  409. //--------------------------------------------------------------------------
  410. #ifndef TORQUE_TGB_ONLY
  411. DefineEngineMethod( NetConnection, transmitPaths, void, (),,
  412. "@brief Sent by the server during phase 2 of the mission download to update motion spline paths.\n\n"
  413. "The server transmits all spline motion paths that are within the mission (Path) separate from "
  414. "other objects. This is due to the potentially large number of nodes within each path, which may "
  415. "saturate a packet sent to the client. By managing this step separately, Torque has finer control "
  416. "over how packets are organised vs. doing it during the ghosting stage.\n\n"
  417. "Internally a PathManager is used to track all paths defined within a mission on the server, and each "
  418. "one is transmitted using a PathManagerEvent. The client side collects these events and builds the "
  419. "given paths within its own PathManager. This is typically done during the standard mission start "
  420. "phase 2 when following Torque's example mission startup sequence.\n\n"
  421. "When a mission is ended, all paths need to be cleared from their respective path managers."
  422. "@tsexample\n"
  423. "function serverCmdMissionStartPhase2Ack(%client, %seq, %playerDB)\n"
  424. "{\n"
  425. " // Make sure to ignore calls from a previous mission load\n"
  426. " if (%seq != $missionSequence || !$MissionRunning)\n"
  427. " return;\n"
  428. " if (%client.currentPhase != 1.5)\n"
  429. " return;\n"
  430. " %client.currentPhase = 2;\n"
  431. "\n"
  432. " // Set the player datablock choice\n"
  433. " %client.playerDB = %playerDB;\n"
  434. "\n"
  435. " // Update mission paths (SimPath), this needs to get there before the objects.\n"
  436. " %client.transmitPaths();\n"
  437. "\n"
  438. " // Start ghosting objects to the client\n"
  439. " %client.activateGhosting();\n"
  440. "}\n"
  441. "@endtsexample\n"
  442. "@see clearPaths()\n"
  443. "@see Path\n")
  444. {
  445. gServerPathManager->transmitPaths(object);
  446. object->setMissionPathsSent(true);
  447. }
  448. DefineEngineMethod( NetConnection, clearPaths, void, (),,
  449. "@brief On the server, resets the connection to indicate that motion spline paths have not been transmitted.\n\n"
  450. "Typically when a mission has ended on the server, all connected clients are informed of this change "
  451. "and their connections are reset back to a starting state. This method resets a connection on the "
  452. "server to indicate that motion spline paths have not been transmitted.\n\n"
  453. "@tsexample\n"
  454. " // Inform the clients\n"
  455. " for (%clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++)\n"
  456. " {\n"
  457. " // clear ghosts and paths from all clients\n"
  458. " %cl = ClientGroup.getObject(%clientIndex);\n"
  459. " %cl.endMission();\n"
  460. " %cl.resetGhosting();\n"
  461. " %cl.clearPaths();\n"
  462. " }\n"
  463. "@endtsexample\n"
  464. "@see transmitPaths()\n"
  465. "@see Path\n")
  466. {
  467. object->setMissionPathsSent(false);
  468. }
  469. #endif
  470. DefineEngineMethod( NetConnection, getAddress, const char *, (),,
  471. "@brief Returns the far end network address for the connection.\n\n"
  472. "The address will be in one of the following forms:\n"
  473. "- <b>IP:Broadcast:&lt;port&gt;</b> for broadcast type addresses\n"
  474. "- <b>IP:&lt;address&gt;:&lt;port&gt;</b> for IP addresses\n"
  475. "- <b>local</b> when connected locally (server and client running in same process\n")
  476. {
  477. if(object->isLocalConnection())
  478. return "local";
  479. char *buffer = Con::getReturnBuffer(256);
  480. Net::addressToString(object->getNetAddress(), buffer);
  481. return buffer;
  482. }
  483. DefineEngineMethod( NetConnection, setSimulatedNetParams, void, (F32 packetLoss, S32 delay),,
  484. "@brief Simulate network issues on the connection for testing.\n\n"
  485. "@param packetLoss The fraction of packets that will be lost. Ranges from 0.0 (no loss) to 1.0 (complete loss)\n"
  486. "@param delay Delays packets being transmitted by simulating a particular ping. This is an absolute "
  487. "integer, measured in ms.\n")
  488. {
  489. object->setSimulatedNetParams(packetLoss, delay);
  490. }
  491. DefineEngineMethod( NetConnection, getPing, S32, (),,
  492. "@brief Returns the average round trip time (in ms) for the connection.\n\n"
  493. "The round trip time is recalculated every time a notify packet is received. Notify "
  494. "packets are used to information the connection that the far end successfully received "
  495. "the sent packet.\n")
  496. {
  497. return( S32( object->getRoundTripTime() ) );
  498. }
  499. DefineEngineMethod( NetConnection, getPacketLoss, S32, (),,
  500. "@brief Returns the percentage of packets lost per tick.\n\n"
  501. "@note This method is not yet hooked up.\n")
  502. {
  503. return( S32( 100 * object->getPacketLoss() ) );
  504. }
  505. DefineEngineMethod( NetConnection, checkMaxRate, void, (),,
  506. "@brief Ensures that all configured packet rates and sizes meet minimum requirements.\n\n"
  507. "This method is normally only called when a NetConnection class is first constructed. It need "
  508. "only be manually called if the global variables that set the packet rate or size have changed.\n\n"
  509. "@note If @$pref::Net::PacketRateToServer, @$pref::Net::PacketRateToClient or @$pref::Net::PacketSize "
  510. "have been changed since a NetConnection has been created, this method must be called on "
  511. "all connections for them to follow the new rates or size.\n")
  512. {
  513. object->checkMaxRate();
  514. }
  515. #ifdef TORQUE_DEBUG_NET
  516. DefineEngineMethod( NetConnection, setLogging, void, (bool state),,
  517. "@brief Sets if debug statements should be written to the console log.\n\n"
  518. "@note Only valid if the executable has been compiled with TORQUE_DEBUG_NET.\n")
  519. {
  520. object->setLogging(state);
  521. }
  522. #endif
  523. //--------------------------------------------------------------------
  524. void NetConnection::setEstablished()
  525. {
  526. AssertFatal(!mEstablished, "NetConnection::setEstablished - Error, this NetConnection has already been established.");
  527. mEstablished = true;
  528. mNextConnection = mConnectionList;
  529. if(mConnectionList)
  530. mConnectionList->mPrevConnection = this;
  531. mConnectionList = this;
  532. if(isNetworkConnection())
  533. netAddressTableInsert();
  534. }
  535. void NetConnection::onRemove()
  536. {
  537. // delete any ghosts that may exist for this connection, but aren't added
  538. while(mGhostAlwaysSaveList.size())
  539. {
  540. delete mGhostAlwaysSaveList[0].ghost;
  541. mGhostAlwaysSaveList.pop_front();
  542. }
  543. if(mNextConnection)
  544. mNextConnection->mPrevConnection = mPrevConnection;
  545. if(mPrevConnection)
  546. mPrevConnection->mNextConnection = mNextConnection;
  547. if(mConnectionList == this)
  548. mConnectionList = mNextConnection;
  549. while(mNotifyQueueHead)
  550. handleNotify(false);
  551. ghostOnRemove();
  552. eventOnRemove();
  553. Parent::onRemove();
  554. }
  555. String NetConnection::mErrorBuffer;
  556. void NetConnection::setLastError(const char *fmt, ...)
  557. {
  558. va_list argptr;
  559. va_start(argptr, fmt);
  560. mErrorBuffer = String::ToString(fmt, argptr);
  561. va_end(argptr);
  562. #ifdef TORQUE_DEBUG_NET
  563. // setLastErrors assert in net_debug builds
  564. AssertFatal(false, mErrorBuffer.c_str());
  565. #endif
  566. }
  567. //--------------------------------------------------------------------
  568. void NetConnection::handleNotify(bool recvd)
  569. {
  570. // Con::printf("NET %d: NOTIFY - %d %s", getId(), gPacketId, recvd ? "RECVD" : "DROPPED");
  571. PacketNotify *note = mNotifyQueueHead;
  572. AssertFatal(note != NULL, "Error: got a notify with a null notify head.");
  573. mNotifyQueueHead = mNotifyQueueHead->nextPacket;
  574. if(note->rateChanged && !recvd)
  575. mCurRate.changed = true;
  576. if(note->maxRateChanged && !recvd)
  577. mMaxRate.changed = true;
  578. if(recvd)
  579. {
  580. // Running average of roundTrip time
  581. U32 curTime = Platform::getVirtualMilliseconds();
  582. mRoundTripTime = (mRoundTripTime + (curTime - note->sendTime)) * 0.5;
  583. packetReceived(note);
  584. }
  585. else
  586. packetDropped(note);
  587. delete note;
  588. }
  589. void NetConnection::processRawPacket(BitStream *bstream)
  590. {
  591. if(mDemoWriteStream)
  592. recordBlock(BlockTypePacket, bstream->getReadByteSize(), bstream->getBuffer());
  593. ConnectionProtocol::processRawPacket(bstream);
  594. }
  595. void NetConnection::handlePacket(BitStream *bstream)
  596. {
  597. // Con::printf("NET %d: RECV - %d", getId(), mLastSeqRecvd);
  598. // clear out any errors
  599. mErrorBuffer = String();
  600. if(bstream->readFlag())
  601. {
  602. mCurRate.updateDelay = bstream->readInt(12);
  603. mCurRate.packetSize = bstream->readInt(12);
  604. }
  605. if(bstream->readFlag())
  606. {
  607. U32 omaxDelay = bstream->readInt(12);
  608. S32 omaxSize = bstream->readInt(12);
  609. if(omaxDelay < mMaxRate.updateDelay)
  610. omaxDelay = mMaxRate.updateDelay;
  611. if(omaxSize > mMaxRate.packetSize)
  612. omaxSize = mMaxRate.packetSize;
  613. if(omaxDelay != mCurRate.updateDelay || omaxSize != mCurRate.packetSize)
  614. {
  615. mCurRate.updateDelay = omaxDelay;
  616. mCurRate.packetSize = omaxSize;
  617. mCurRate.changed = true;
  618. }
  619. }
  620. readPacket(bstream);
  621. if(mErrorBuffer.isNotEmpty())
  622. connectionError(mErrorBuffer);
  623. }
  624. void NetConnection::connectionError(const char *errorString)
  625. {
  626. TORQUE_UNUSED(errorString);
  627. }
  628. //--------------------------------------------------------------------
  629. NetConnection::PacketNotify *NetConnection::allocNotify()
  630. {
  631. return new PacketNotify;
  632. }
  633. /// Used when simulating lag.
  634. ///
  635. /// We post this SimEvent when we want to send a packet; it delays for a bit, then
  636. /// sends the actual packet.
  637. class NetDelayEvent : public SimEvent
  638. {
  639. U8 buffer[Net::MaxPacketDataSize];
  640. BitStream stream;
  641. public:
  642. NetDelayEvent(BitStream *inStream) : stream(NULL, 0)
  643. {
  644. dMemcpy(buffer, inStream->getBuffer(), inStream->getPosition());
  645. stream.setBuffer(buffer, inStream->getPosition());
  646. stream.setPosition(inStream->getPosition());
  647. }
  648. void process(SimObject *object)
  649. {
  650. ((NetConnection *) object)->sendPacket(&stream);
  651. }
  652. };
  653. void NetConnection::checkPacketSend(bool force)
  654. {
  655. U32 curTime = Platform::getVirtualMilliseconds();
  656. U32 delay = isConnectionToServer() ? gPacketUpdateDelayToServer : mCurRate.updateDelay;
  657. if(!force)
  658. {
  659. if(curTime < mLastUpdateTime + delay - mSendDelayCredit)
  660. return;
  661. mSendDelayCredit = curTime - (mLastUpdateTime + delay - mSendDelayCredit);
  662. if(mSendDelayCredit > 1000)
  663. mSendDelayCredit = 1000;
  664. if(mDemoWriteStream)
  665. recordBlock(BlockTypeSendPacket, 0, 0);
  666. }
  667. if(windowFull())
  668. return;
  669. BitStream *stream = BitStream::getPacketStream(mCurRate.packetSize);
  670. buildSendPacketHeader(stream);
  671. mLastUpdateTime = curTime;
  672. PacketNotify *note = allocNotify();
  673. if(!mNotifyQueueHead)
  674. mNotifyQueueHead = note;
  675. else
  676. mNotifyQueueTail->nextPacket = note;
  677. mNotifyQueueTail = note;
  678. note->nextPacket = NULL;
  679. note->sendTime = curTime;
  680. note->rateChanged = mCurRate.changed;
  681. note->maxRateChanged = mMaxRate.changed;
  682. if(stream->writeFlag(mCurRate.changed))
  683. {
  684. stream->writeInt(mCurRate.updateDelay, 12);
  685. stream->writeInt(mCurRate.packetSize, 12);
  686. mCurRate.changed = false;
  687. }
  688. if(stream->writeFlag(mMaxRate.changed))
  689. {
  690. stream->writeInt(mMaxRate.updateDelay, 12);
  691. stream->writeInt(mMaxRate.packetSize, 12);
  692. mMaxRate.changed = false;
  693. }
  694. #ifdef TORQUE_DEBUG_NET
  695. U32 start = stream->getCurPos();
  696. #endif
  697. DEBUG_LOG(("PKLOG %d START", getId()) );
  698. writePacket(stream, note);
  699. DEBUG_LOG(("PKLOG %d END - %d", getId(), stream->getCurPos() - start) );
  700. if(mSimulatedPacketLoss && Platform::getRandom() < mSimulatedPacketLoss)
  701. {
  702. //Con::printf("NET %d: SENDDROP - %d", getId(), mLastSendSeq);
  703. return;
  704. }
  705. if(mSimulatedPing)
  706. {
  707. Sim::postEvent(getId(), new NetDelayEvent(stream), Sim::getCurrentTime() + mSimulatedPing);
  708. return;
  709. }
  710. sendPacket(stream);
  711. }
  712. Net::Error NetConnection::sendPacket(BitStream *stream)
  713. {
  714. //Con::printf("NET %d: SEND - %d", getId(), mLastSendSeq);
  715. // do nothing on send if this is a demo replay.
  716. if(mDemoReadStream)
  717. return Net::NoError;
  718. gNetBitsSent = stream->getPosition();
  719. if(isLocalConnection())
  720. {
  721. // short circuit connection to the other side.
  722. // handle the packet, then force a notify.
  723. stream->setBuffer(stream->getBuffer(), stream->getPosition(), stream->getPosition());
  724. mRemoteConnection->processRawPacket(stream);
  725. return Net::NoError;
  726. }
  727. else
  728. {
  729. return Net::sendto(getNetAddress(), stream->getBuffer(), stream->getPosition());
  730. }
  731. }
  732. //--------------------------------------------------------------------
  733. //--------------------------------------------------------------------
  734. // these are the virtual function defs for Connection -
  735. // if your subclass has additional data to read / write / notify, add it in these functions.
  736. void NetConnection::readPacket(BitStream *bstream)
  737. {
  738. eventReadPacket(bstream);
  739. ghostReadPacket(bstream);
  740. }
  741. void NetConnection::writePacket(BitStream *bstream, PacketNotify *note)
  742. {
  743. eventWritePacket(bstream, note);
  744. ghostWritePacket(bstream, note);
  745. }
  746. void NetConnection::packetReceived(PacketNotify *note)
  747. {
  748. eventPacketReceived(note);
  749. ghostPacketReceived(note);
  750. }
  751. void NetConnection::packetDropped(PacketNotify *note)
  752. {
  753. eventPacketDropped(note);
  754. ghostPacketDropped(note);
  755. }
  756. //--------------------------------------------------------------------
  757. //--------------------------------------------------------------------
  758. void NetConnection::writeDemoStartBlock(ResizeBitStream* stream)
  759. {
  760. ConnectionProtocol::writeDemoStartBlock(stream);
  761. stream->write(mRoundTripTime);
  762. stream->write(mPacketLoss);
  763. #ifndef TORQUE_TGB_ONLY
  764. // Write all the current paths to the stream...
  765. gClientPathManager->dumpState(stream);
  766. #endif
  767. stream->validate();
  768. mStringTable->writeDemoStartBlock(stream);
  769. U32 start = 0;
  770. PacketNotify *note = mNotifyQueueHead;
  771. while(note)
  772. {
  773. start++;
  774. note = note->nextPacket;
  775. }
  776. stream->write(start);
  777. eventWriteStartBlock(stream);
  778. ghostWriteStartBlock(stream);
  779. }
  780. bool NetConnection::readDemoStartBlock(BitStream* stream)
  781. {
  782. ConnectionProtocol::readDemoStartBlock(stream);
  783. stream->read(&mRoundTripTime);
  784. stream->read(&mPacketLoss);
  785. #ifndef TORQUE_TGB_ONLY
  786. // Read
  787. gClientPathManager->readState(stream);
  788. #endif
  789. mStringTable->readDemoStartBlock(stream);
  790. U32 pos;
  791. stream->read(&pos); // notify count
  792. for(U32 i = 0; i < pos; i++)
  793. {
  794. PacketNotify *note = allocNotify();
  795. note->nextPacket = NULL;
  796. if(!mNotifyQueueHead)
  797. mNotifyQueueHead = note;
  798. else
  799. mNotifyQueueTail->nextPacket = note;
  800. mNotifyQueueTail = note;
  801. }
  802. eventReadStartBlock(stream);
  803. ghostReadStartBlock(stream);
  804. return true;
  805. }
  806. bool NetConnection::startDemoRecord(const char *fileName)
  807. {
  808. FileStream *fs = new FileStream;
  809. if((fs = FileStream::createAndOpen( fileName, Torque::FS::File::Write )) == NULL)
  810. return false;
  811. mDemoWriteStream = fs;
  812. mDemoWriteStream->write(mProtocolVersion);
  813. ResizeBitStream bs;
  814. // then write out the start block
  815. writeDemoStartBlock(&bs);
  816. U32 size = bs.getPosition() + 1;
  817. mDemoWriteStream->write(size);
  818. mDemoWriteStream->write(size, bs.getBuffer());
  819. return true;
  820. }
  821. bool NetConnection::replayDemoRecord(const char *fileName)
  822. {
  823. Stream *fs;
  824. if((fs = FileStream::createAndOpen( fileName, Torque::FS::File::Read )) == NULL)
  825. return false;
  826. mDemoReadStream = fs;
  827. mDemoReadStream->read(&mProtocolVersion);
  828. U32 size;
  829. mDemoReadStream->read(&size);
  830. U8 *block = new U8[size];
  831. mDemoReadStream->read(size, block);
  832. BitStream bs(block, size);
  833. bool res = readDemoStartBlock(&bs);
  834. delete[] block;
  835. if(!res)
  836. return false;
  837. // prep for first block read
  838. // type/size stored in U16: [type:4][size:12]
  839. U16 typeSize;
  840. mDemoReadStream->read(&typeSize);
  841. mDemoNextBlockType = typeSize >> 12;
  842. mDemoNextBlockSize = typeSize & 0xFFF;
  843. if(mDemoReadStream->getStatus() != Stream::Ok)
  844. return false;
  845. return true;
  846. }
  847. void NetConnection::stopRecording()
  848. {
  849. if(mDemoWriteStream)
  850. {
  851. delete mDemoWriteStream;
  852. mDemoWriteStream = NULL;
  853. }
  854. }
  855. void NetConnection::recordBlock(U32 type, U32 size, void *data)
  856. {
  857. AssertFatal(type < MaxNumBlockTypes, "NetConnection::recordBlock: invalid type");
  858. AssertFatal(size < MaxBlockSize, "NetConnection::recordBlock: invalid size");
  859. if((type >= MaxNumBlockTypes) || (size >= MaxBlockSize))
  860. return;
  861. if(mDemoWriteStream)
  862. {
  863. // store type/size in U16: [type:4][size:12]
  864. U16 typeSize = (type << 12) | size;
  865. mDemoWriteStream->write(typeSize);
  866. if(size)
  867. mDemoWriteStream->write(size, data);
  868. }
  869. }
  870. void NetConnection::handleRecordedBlock(U32 type, U32 size, void *data)
  871. {
  872. switch(type)
  873. {
  874. case BlockTypePacket: {
  875. BitStream bs(data, size);
  876. processRawPacket(&bs);
  877. break;
  878. }
  879. case BlockTypeSendPacket:
  880. checkPacketSend(true);
  881. break;
  882. }
  883. }
  884. void NetConnection::demoPlaybackComplete()
  885. {
  886. }
  887. void NetConnection::stopDemoPlayback()
  888. {
  889. demoPlaybackComplete();
  890. deleteObject();
  891. }
  892. bool NetConnection::processNextBlock()
  893. {
  894. U8 buffer[Net::MaxPacketDataSize];
  895. // read in and handle
  896. if(mDemoReadStream->read(mDemoNextBlockSize, buffer))
  897. handleRecordedBlock(mDemoNextBlockType, mDemoNextBlockSize, buffer);
  898. U16 typeSize;
  899. mDemoReadStream->read(&typeSize);
  900. mDemoNextBlockType = typeSize >> 12;
  901. mDemoNextBlockSize = typeSize & 0xFFF;
  902. if(mDemoReadStream->getStatus() != Stream::Ok)
  903. {
  904. stopDemoPlayback();
  905. return false;
  906. }
  907. return true;
  908. }
  909. //--------------------------------------------------------------------
  910. //--------------------------------------------------------------------
  911. // some handy string functions for compressing strings over a connection:
  912. enum NetStringConstants
  913. {
  914. NullString = 0,
  915. CString,
  916. TagString,
  917. Integer
  918. };
  919. void NetConnection::validateSendString(const char *str)
  920. {
  921. if(U8(*str) == StringTagPrefixByte)
  922. {
  923. NetStringHandle strHandle(dAtoi(str + 1));
  924. checkString(strHandle);
  925. }
  926. }
  927. void NetConnection::packString(BitStream *stream, const char *str)
  928. {
  929. if(!*str)
  930. {
  931. stream->writeInt(NullString, 2);
  932. return;
  933. }
  934. if(U8(str[0]) == StringTagPrefixByte)
  935. {
  936. stream->writeInt(TagString, 2);
  937. stream->writeInt(dAtoi(str + 1), ConnectionStringTable::EntryBitSize);
  938. return;
  939. }
  940. if(str[0] == '-' || (str[0] >= '0' && str[0] <= '9'))
  941. {
  942. char buf[16];
  943. S32 num = dAtoi(str);
  944. dSprintf(buf, sizeof(buf), "%d", num);
  945. if(!String::compare(buf, str))
  946. {
  947. stream->writeInt(Integer, 2);
  948. if(stream->writeFlag(num < 0))
  949. num = -num;
  950. if(stream->writeFlag(num < 128))
  951. {
  952. stream->writeInt(num, 7);
  953. return;
  954. }
  955. if(stream->writeFlag(num < 32768))
  956. {
  957. stream->writeInt(num, 15);
  958. return;
  959. }
  960. else
  961. {
  962. stream->writeInt(num, 31);
  963. return;
  964. }
  965. }
  966. }
  967. stream->writeInt(CString, 2);
  968. stream->writeString(str);
  969. }
  970. void NetConnection::unpackString(BitStream *stream, char readBuffer[1024])
  971. {
  972. U32 code = stream->readInt(2);
  973. switch(code)
  974. {
  975. case NullString:
  976. readBuffer[0] = 0;
  977. return;
  978. case CString:
  979. {
  980. stream->readString(readBuffer);
  981. return;
  982. }
  983. case TagString:
  984. U32 tag;
  985. tag = stream->readInt(ConnectionStringTable::EntryBitSize);
  986. readBuffer[0] = StringTagPrefixByte;
  987. dSprintf(readBuffer+1, 1023, "%d", tag);
  988. return;
  989. case Integer:
  990. bool neg;
  991. neg = stream->readFlag();
  992. S32 num;
  993. if(stream->readFlag())
  994. num = stream->readInt(7);
  995. else if(stream->readFlag())
  996. num = stream->readInt(15);
  997. else
  998. num = stream->readInt(31);
  999. if(neg)
  1000. num = -num;
  1001. dSprintf(readBuffer, 1024, "%d", num);
  1002. }
  1003. }
  1004. void NetConnection::packNetStringHandleU(BitStream *stream, NetStringHandle &h)
  1005. {
  1006. if(stream->writeFlag(h.isValidString() ))
  1007. {
  1008. bool isReceived;
  1009. U32 netIndex = checkString(h, &isReceived);
  1010. if(stream->writeFlag(isReceived))
  1011. stream->writeInt(netIndex, ConnectionStringTable::EntryBitSize);
  1012. else
  1013. stream->writeString(h.getString());
  1014. }
  1015. }
  1016. NetStringHandle NetConnection::unpackNetStringHandleU(BitStream *stream)
  1017. {
  1018. NetStringHandle ret;
  1019. if(stream->readFlag())
  1020. {
  1021. if(stream->readFlag())
  1022. ret = mStringTable->lookupString(stream->readInt(ConnectionStringTable::EntryBitSize));
  1023. else
  1024. {
  1025. char buf[256];
  1026. stream->readString(buf);
  1027. ret = NetStringHandle(buf);
  1028. }
  1029. }
  1030. return ret;
  1031. }
  1032. //----------------------------------------------------------------------------
  1033. //----------------------------------------------------------------------------
  1034. //----------------------------------------------------------------------------
  1035. void NetConnection::setAddressDigest(U32 digest[4])
  1036. {
  1037. mAddressDigest[0] = digest[0];
  1038. mAddressDigest[1] = digest[1];
  1039. mAddressDigest[2] = digest[2];
  1040. mAddressDigest[3] = digest[3];
  1041. }
  1042. void NetConnection::getAddressDigest(U32 digest[4])
  1043. {
  1044. digest[0] = mAddressDigest[0];
  1045. digest[1] = mAddressDigest[1];
  1046. digest[2] = mAddressDigest[2];
  1047. digest[3] = mAddressDigest[3];
  1048. }
  1049. bool NetConnection::canRemoteCreate()
  1050. {
  1051. return false;
  1052. }
  1053. void NetConnection::onTimedOut()
  1054. {
  1055. }
  1056. void NetConnection::connect(const NetAddress *address)
  1057. {
  1058. mNetAddress = *address;
  1059. GNet->startConnection(this);
  1060. }
  1061. void NetConnection::onConnectTimedOut()
  1062. {
  1063. }
  1064. void NetConnection::sendDisconnectPacket(const char *reason)
  1065. {
  1066. GNet->sendDisconnectPacket(this, reason);
  1067. }
  1068. void NetConnection::onDisconnect(const char *reason)
  1069. {
  1070. TORQUE_UNUSED(reason);
  1071. }
  1072. void NetConnection::onConnectionRejected(const char *reason)
  1073. {
  1074. }
  1075. void NetConnection::onConnectionEstablished(bool isInitiator)
  1076. {
  1077. }
  1078. void NetConnection::handleStartupError(const char *errorString)
  1079. {
  1080. }
  1081. void NetConnection::writeConnectRequest(BitStream *stream)
  1082. {
  1083. stream->write(mNetClassGroup);
  1084. stream->write(U32(AbstractClassRep::getClassCRC(mNetClassGroup)));
  1085. }
  1086. bool NetConnection::readConnectRequest(BitStream *stream, const char **errorString)
  1087. {
  1088. U32 classGroup, classCRC;
  1089. stream->read(&classGroup);
  1090. stream->read(&classCRC);
  1091. if(classGroup == mNetClassGroup && classCRC == AbstractClassRep::getClassCRC(mNetClassGroup))
  1092. return true;
  1093. *errorString = "CHR_INVALID";
  1094. return false;
  1095. }
  1096. void NetConnection::writeConnectAccept(BitStream *stream)
  1097. {
  1098. TORQUE_UNUSED(stream);
  1099. }
  1100. bool NetConnection::readConnectAccept(BitStream *stream, const char **errorString)
  1101. {
  1102. TORQUE_UNUSED(stream);
  1103. TORQUE_UNUSED(errorString);
  1104. return true;
  1105. }
  1106. DefineEngineMethod( NetConnection, resolveGhostID, S32, (S32 ghostID),,
  1107. "@brief On the client, convert a ghost ID from this connection to a real SimObject ID.\n\n"
  1108. "Torque's network ghosting system only exchanges ghost ID's between the server and client. Use "
  1109. "this method on the client to discover an object's local SimObject ID when you only have a "
  1110. "ghost ID.\n"
  1111. "@param ghostID The ghost ID of the object as sent by the server.\n"
  1112. "@returns The SimObject ID of the object, or 0 if it could not be resolved.\n\n"
  1113. "@tsexample\n"
  1114. "%object = ServerConnection.resolveGhostID( %ghostId );\n"
  1115. "@endtsexample\n\n"
  1116. "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
  1117. {
  1118. // Safety check
  1119. if(ghostID < 0 || ghostID > NetConnection::MaxGhostCount) return 0;
  1120. NetObject *foo = object->resolveGhost(ghostID);
  1121. if(foo)
  1122. return foo->getId();
  1123. else
  1124. return 0;
  1125. }
  1126. DefineEngineMethod( NetConnection, resolveObjectFromGhostIndex, S32, (S32 ghostID),,
  1127. "@brief On the server, convert a ghost ID from this connection to a real SimObject ID.\n\n"
  1128. "Torque's network ghosting system only exchanges ghost ID's between the server and client. Use "
  1129. "this method on the server to discover an object's local SimObject ID when you only have a "
  1130. "ghost ID.\n"
  1131. "@param ghostID The ghost ID of the object as sent by the server.\n"
  1132. "@returns The SimObject ID of the object, or 0 if it could not be resolved.\n\n"
  1133. "@tsexample\n"
  1134. "%object = %client.resolveObjectFromGhostIndex( %ghostId );\n"
  1135. "@endtsexample\n\n"
  1136. "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
  1137. {
  1138. // Safety check
  1139. if(ghostID < 0 || ghostID > NetConnection::MaxGhostCount) return 0;
  1140. NetObject *foo = object->resolveObjectFromGhostIndex(ghostID);
  1141. if(foo)
  1142. return foo->getId();
  1143. else
  1144. return 0;
  1145. }
  1146. DefineEngineMethod( NetConnection, getGhostID, S32, (S32 realID),,
  1147. "@brief On server or client, convert a real id to the ghost id for this connection.\n\n"
  1148. "Torque's network ghosting system only exchanges ghost ID's between the server and client. Use "
  1149. "this method on the server or client to discover an object's ghost ID based on its real SimObject ID.\n"
  1150. "@param realID The real SimObject ID of the object.\n"
  1151. "@returns The ghost ID of the object for this connection, or -1 if it could not be resolved.\n\n"
  1152. "@see @ref ghosting_scoping for a description of the ghosting system.\n\n")
  1153. {
  1154. NetObject * foo;
  1155. if(Sim::findObject(realID, foo))
  1156. {
  1157. return object->getGhostIndex(foo);
  1158. }
  1159. else
  1160. {
  1161. Con::errorf("NetConnection::serverToGhostID - could not find specified object");
  1162. return -1;
  1163. }
  1164. }
  1165. DefineEngineMethod( NetConnection, connect, void, (const char* remoteAddress),,
  1166. "@brief Connects to the remote address.\n\n"
  1167. "Attempts to connect with another NetConnection on the given address. Typically once "
  1168. "connected, a game's information is passed along from the server to the client, followed "
  1169. "by the player entering the game world. The actual procedure is dependent on "
  1170. "the NetConnection subclass that is used. i.e. GameConnection.\n"
  1171. "@param remoteAddress The address to connect to in the form of IP:&lt;address&gt;:&lt;port&rt; "
  1172. "although the <i>IP:</i> portion is optional. The <i>address</i> portion may be in the form "
  1173. "of w.x.y.z or as a host name, in which case a DNS lookup will be performed. You may also "
  1174. "substitue the word <i>broadcast</i> for the address to broadcast the connect request over "
  1175. "the local subnet.\n\n"
  1176. "@see NetConnection::connectLocal() to connect to a server running within the same process "
  1177. "as the client.\n"
  1178. )
  1179. {
  1180. NetAddress addr;
  1181. if (Net::stringToAddress(remoteAddress, &addr) != Net::NoError)
  1182. {
  1183. Con::errorf("NetConnection::connect: invalid address - %s", remoteAddress);
  1184. return;
  1185. }
  1186. object->connect(&addr);
  1187. }
  1188. DefineEngineMethod( NetConnection, connectLocal, const char*, (),,
  1189. "@brief Connects with the server that is running within the same process as the client.\n\n"
  1190. "@returns An error text message upon failure, or an empty string when successful.\n\n"
  1191. "@see See @ref local_connections for a description of local connections and their use. See "
  1192. "NetConnection::connect() to connect to a server running in another process (on the same machine or not).\n")
  1193. {
  1194. ConsoleObject *co = ConsoleObject::create(object->getClassName());
  1195. NetConnection *client = object;
  1196. NetConnection *server = dynamic_cast<NetConnection *>(co);
  1197. BitStream *stream = BitStream::getPacketStream();
  1198. if(!server || !server->canRemoteCreate())
  1199. {
  1200. delete co;
  1201. return "error";
  1202. }
  1203. server->registerObject();
  1204. server->setIsLocalClientConnection();
  1205. server->setSequence(0);
  1206. client->setSequence(0);
  1207. client->setRemoteConnectionObject(server);
  1208. server->setRemoteConnectionObject(client);
  1209. //We need to reset the maxrate's here, because we
  1210. // can't test if it is a local connection until RemoteConnectionObject
  1211. // has been set
  1212. server->checkMaxRate();
  1213. client->checkMaxRate();
  1214. stream->setPosition(0);
  1215. client->writeConnectRequest(stream);
  1216. stream->setPosition(0);
  1217. const char* error;
  1218. if( !server->readConnectRequest( stream, &error ) )
  1219. {
  1220. client->onConnectionRejected( error );
  1221. server->deleteObject();
  1222. return "error";
  1223. }
  1224. stream->setPosition(0);
  1225. server->writeConnectAccept(stream);
  1226. stream->setPosition(0);
  1227. if( !client->readConnectAccept( stream, &error ) )
  1228. {
  1229. client->handleStartupError( error );
  1230. server->deleteObject();
  1231. return "error";
  1232. }
  1233. client->onConnectionEstablished(true);
  1234. server->onConnectionEstablished(false);
  1235. client->setEstablished();
  1236. server->setEstablished();
  1237. client->setConnectSequence(0);
  1238. server->setConnectSequence(0);
  1239. NetConnection::setLocalClientConnection(server);
  1240. server->assignName("LocalClientConnection");
  1241. return "";
  1242. }