gameConnection.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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 "console/consoleTypes.h"
  25. #include "sim/simBase.h"
  26. #include "io/bitStream.h"
  27. #include "game/gameConnection.h"
  28. #include "io/resource/resourceManager.h"
  29. #include "gameConnection_ScriptBinding.h"
  30. //----------------------------------------------------------------------------
  31. #define MAX_MOVE_PACKET_SENDS 4
  32. #define ControlRequestTime 5000
  33. const U32 GameConnection::CurrentProtocolVersion = 12;
  34. const U32 GameConnection::MinRequiredProtocolVersion = 12;
  35. //----------------------------------------------------------------------------
  36. IMPLEMENT_CONOBJECT(GameConnection);
  37. S32 GameConnection::mLagThresholdMS = 0;
  38. //----------------------------------------------------------------------------
  39. GameConnection::GameConnection()
  40. {
  41. mLagging = false;
  42. mAuthInfo = NULL;
  43. mConnectArgc = 0;
  44. for(U32 i = 0; i < MaxConnectArgs; i++)
  45. mConnectArgv[i] = 0;
  46. mJoinPassword = NULL;
  47. mDisconnectReason[0] = 0;
  48. }
  49. GameConnection::~GameConnection()
  50. {
  51. delete mAuthInfo;
  52. for(U32 i = 0; i < mConnectArgc; i++)
  53. dFree(mConnectArgv[i]);
  54. dFree(mJoinPassword);
  55. }
  56. //----------------------------------------------------------------------------
  57. //----------------------------------------------------------------------------
  58. bool GameConnection::canRemoteCreate()
  59. {
  60. return true;
  61. }
  62. void GameConnection::setConnectArgs(U32 argc, const char **argv)
  63. {
  64. if(argc > MaxConnectArgs)
  65. argc = MaxConnectArgs;
  66. mConnectArgc = argc;
  67. for(U32 i = 0; i < mConnectArgc; i++)
  68. mConnectArgv[i] = dStrdup(argv[i]);
  69. }
  70. void GameConnection::setJoinPassword(const char *password)
  71. {
  72. mJoinPassword = dStrdup(password);
  73. }
  74. void GameConnection::onTimedOut()
  75. {
  76. if(isConnectionToServer())
  77. {
  78. Con::printf("Connection to server timed out");
  79. Con::executef(this, 1, "onConnectionTimedOut");
  80. }
  81. else
  82. {
  83. Con::printf("Client %d timed out.", getId());
  84. setDisconnectReason("TimedOut");
  85. }
  86. }
  87. void GameConnection::onConnectionEstablished(bool isInitiator)
  88. {
  89. if(isInitiator)
  90. {
  91. setGhostFrom(false);
  92. setGhostTo(true);
  93. setSendingEvents(true);
  94. setTranslatesStrings(true);
  95. setIsConnectionToServer();
  96. mServerConnection = this;
  97. Con::printf("Connection established %d", getId());
  98. Con::executef(this, 1, "onConnectionAccepted");
  99. }
  100. else
  101. {
  102. setGhostFrom(true);
  103. setGhostTo(false);
  104. setSendingEvents(true);
  105. setTranslatesStrings(true);
  106. Sim::getClientGroup()->addObject(this);
  107. const char *argv[MaxConnectArgs + 2];
  108. argv[0] = "onConnect";
  109. for(U32 i = 0; i < mConnectArgc; i++)
  110. argv[i + 2] = mConnectArgv[i];
  111. Con::execute(this, mConnectArgc + 2, argv);
  112. }
  113. }
  114. void GameConnection::onConnectTimedOut()
  115. {
  116. Con::executef(this, 1, "onConnectRequestTimedOut");
  117. }
  118. void GameConnection::onDisconnect(const char *reason)
  119. {
  120. if(isConnectionToServer())
  121. {
  122. Con::printf("Connection with server lost.");
  123. Con::executef(this, 2, "onConnectionDropped", reason);
  124. }
  125. else
  126. {
  127. Con::printf("Client %d disconnected.", getId());
  128. setDisconnectReason(reason);
  129. }
  130. }
  131. void GameConnection::onConnectionRejected(const char *reason)
  132. {
  133. Con::executef(this, 2, "onConnectRequestRejected", reason);
  134. }
  135. void GameConnection::handleStartupError(const char *errorString)
  136. {
  137. Con::executef(this, 2, "onConnectRequestRejected", errorString);
  138. }
  139. void GameConnection::writeConnectAccept(BitStream *stream)
  140. {
  141. Parent::writeConnectAccept(stream);
  142. stream->write(getProtocolVersion());
  143. }
  144. bool GameConnection::readConnectAccept(BitStream *stream, const char **errorString)
  145. {
  146. if(!Parent::readConnectAccept(stream, errorString))
  147. return false;
  148. U32 protocolVersion;
  149. stream->read(&protocolVersion);
  150. if(protocolVersion < MinRequiredProtocolVersion || protocolVersion > CurrentProtocolVersion)
  151. {
  152. *errorString = "CHR_PROTOCOL"; // this should never happen unless someone is faking us out.
  153. return false;
  154. }
  155. return true;
  156. }
  157. void GameConnection::writeConnectRequest(BitStream *stream)
  158. {
  159. Parent::writeConnectRequest(stream);
  160. stream->writeString(GameString);
  161. stream->write(CurrentProtocolVersion);
  162. stream->write(MinRequiredProtocolVersion);
  163. stream->writeString(mJoinPassword);
  164. stream->write(mConnectArgc);
  165. for(U32 i = 0; i < mConnectArgc; i++)
  166. stream->writeString(mConnectArgv[i]);
  167. }
  168. bool GameConnection::readConnectRequest(BitStream *stream, const char **errorString)
  169. {
  170. if(!Parent::readConnectRequest(stream, errorString))
  171. return false;
  172. U32 currentProtocol, minProtocol;
  173. char gameString[256];
  174. stream->readString(gameString);
  175. if(dStrcmp(gameString, GameString))
  176. {
  177. *errorString = "CHR_GAME";
  178. return false;
  179. }
  180. stream->read(&currentProtocol);
  181. stream->read(&minProtocol);
  182. char joinPassword[256];
  183. stream->readString(joinPassword);
  184. if(currentProtocol < MinRequiredProtocolVersion)
  185. {
  186. *errorString = "CHR_PROTOCOL_LESS";
  187. return false;
  188. }
  189. if(minProtocol > CurrentProtocolVersion)
  190. {
  191. *errorString = "CHR_PROTOCOL_GREATER";
  192. return false;
  193. }
  194. setProtocolVersion(currentProtocol < CurrentProtocolVersion ? currentProtocol : CurrentProtocolVersion);
  195. const char *serverPassword = Con::getVariable("Pref::Server::Password");
  196. if(serverPassword[0])
  197. {
  198. if(dStrcmp(joinPassword, serverPassword))
  199. {
  200. *errorString = "CHR_PASSWORD";
  201. return false;
  202. }
  203. }
  204. stream->read(&mConnectArgc);
  205. if(mConnectArgc > MaxConnectArgs)
  206. {
  207. *errorString = "CR_INVALID_ARGS";
  208. return false;
  209. }
  210. const char *connectArgv[MaxConnectArgs + 3];
  211. for(U32 i = 0; i < mConnectArgc; i++)
  212. {
  213. char argString[256];
  214. stream->readString(argString);
  215. mConnectArgv[i] = dStrdup(argString);
  216. connectArgv[i + 3] = mConnectArgv[i];
  217. }
  218. connectArgv[0] = "onConnectRequest";
  219. char buffer[256];
  220. Net::addressToString(getNetAddress(), buffer);
  221. connectArgv[2] = buffer;
  222. const char *ret = Con::execute(this, mConnectArgc + 3, connectArgv);
  223. if(ret[0])
  224. {
  225. *errorString = ret;
  226. return false;
  227. }
  228. return true;
  229. }
  230. //----------------------------------------------------------------------------
  231. //----------------------------------------------------------------------------
  232. void GameConnection::connectionError(const char *errorString)
  233. {
  234. if(isConnectionToServer())
  235. {
  236. Con::printf("Connection error: %s.", errorString);
  237. Con::executef(this, 2, "onConnectionError", errorString);
  238. }
  239. else
  240. {
  241. Con::printf("Client %d packet error: %s.", getId(), errorString);
  242. setDisconnectReason("Packet Error.");
  243. }
  244. deleteObject();
  245. }
  246. void GameConnection::setAuthInfo(const AuthInfo *info)
  247. {
  248. mAuthInfo = new AuthInfo;
  249. *mAuthInfo = *info;
  250. }
  251. const AuthInfo *GameConnection::getAuthInfo()
  252. {
  253. return mAuthInfo;
  254. }
  255. //----------------------------------------------------------------------------
  256. bool GameConnection::onAdd()
  257. {
  258. if (!Parent::onAdd())
  259. return false;
  260. return true;
  261. }
  262. void GameConnection::onRemove()
  263. {
  264. if(isNetworkConnection())
  265. {
  266. sendDisconnectPacket(mDisconnectReason);
  267. }
  268. if(!isConnectionToServer())
  269. Con::executef(this, 2, "onDrop", mDisconnectReason);
  270. Parent::onRemove();
  271. }
  272. void GameConnection::setDisconnectReason(const char *str)
  273. {
  274. dStrncpy(mDisconnectReason, str, sizeof(mDisconnectReason) - 1);
  275. mDisconnectReason[sizeof(mDisconnectReason) - 1] = 0;
  276. }
  277. //----------------------------------------------------------------------------
  278. //----------------------------------------------------------------------------
  279. //----------------------------------------------------------------------------
  280. void GameConnection::readPacket(BitStream *bstream)
  281. {
  282. //Con::printf("GameConnection::handlePacket - readPacket ---");
  283. char stringBuf[256];
  284. stringBuf[0] = 0;
  285. bstream->setStringBuffer(stringBuf);
  286. bstream->clearCompressionPoint();
  287. Parent::readPacket(bstream);
  288. bstream->clearCompressionPoint();
  289. bstream->setStringBuffer(NULL);
  290. }
  291. void GameConnection::writePacket(BitStream *bstream, PacketNotify *note)
  292. {
  293. char stringBuf[256];
  294. bstream->clearCompressionPoint();
  295. stringBuf[0] = 0;
  296. bstream->setStringBuffer(stringBuf);
  297. Parent::writePacket(bstream, note);
  298. bstream->clearCompressionPoint();
  299. bstream->setStringBuffer(NULL);
  300. }
  301. void GameConnection::detectLag()
  302. {
  303. //see if we're lagging...
  304. S32 curTime = Sim::getCurrentTime();
  305. if (curTime - mLastPacketTime > mLagThresholdMS)
  306. {
  307. if (!mLagging)
  308. {
  309. mLagging = true;
  310. Con::executef(this, 2, "setLagIcon", "true");
  311. }
  312. }
  313. else if (mLagging)
  314. {
  315. mLagging = false;
  316. Con::executef(this, 2, "setLagIcon", "false");
  317. }
  318. }
  319. GameConnection::GamePacketNotify::GamePacketNotify()
  320. {
  321. // need to fill in empty notifes for demo start block
  322. }
  323. NetConnection::PacketNotify *GameConnection::allocNotify()
  324. {
  325. return new GamePacketNotify;
  326. }
  327. void GameConnection::packetReceived(PacketNotify *note)
  328. {
  329. //record the time so we can tell if we're lagging...
  330. mLastPacketTime = Sim::getCurrentTime();
  331. Parent::packetReceived(note);
  332. }
  333. void GameConnection::packetDropped(PacketNotify *note)
  334. {
  335. Parent::packetDropped(note);
  336. }
  337. //----------------------------------------------------------------------------
  338. //----------------------------------------------------------------------------
  339. //----------------------------------------------------------------------------
  340. //----------------------------------------------------------------------------
  341. void GameConnection::handleConnectionMessage(U32 message, U32 sequence, U32 ghostCount)
  342. {
  343. Parent::handleConnectionMessage(message, sequence, ghostCount);
  344. }
  345. //--------------------------------------------------------------------------
  346. void GameConnection::consoleInit()
  347. {
  348. Con::addVariable("Pref::Net::LagThreshold", TypeS32, &mLagThresholdMS);
  349. }