netmsgr.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // NetMsgr.cpp
  19. // Project: Net Messenger
  20. //
  21. // History:
  22. // 05/24/97 MJR Final assault begins.
  23. //
  24. // 05/25/97 JMI Filled out CNetMsgr::InfoMsg declaration.
  25. //
  26. // MJR Made some changes to union, structs, etc.
  27. //
  28. // 05/26/97 MJR Moved some functions from header to here.
  29. //
  30. // 06/11/97 JMI Added FINISH_REALM and FINISHED_REALM net messages.
  31. //
  32. // 06/14/97 MJR Removed LOAD_REALM and FINISHED_REALM messages and
  33. // modified START_GAME message.
  34. //
  35. // 08/13/97 MJR Changed from ASSERT() to TRACE() when message len is
  36. // incorrect.
  37. //
  38. // 08/14/97 MJR Changed from TRACE() when message len is incorrect to
  39. // generating an actual error. This is safer in case this
  40. // ever occurs in a real game situation.
  41. //
  42. // Also fixed bug where the message byte would be ungotten
  43. // twice if the message hadn't been fully received yet.
  44. //
  45. // 08/15/97 MJR Cleaned up usage of CBufQ along with some other potential
  46. // (actual???) bugs.
  47. //
  48. // 08/18/97 MJR Added "ChangeReq" and "Changed" messages.
  49. //
  50. // 09/01/97 MJR Lots of changes as part of overall network overhaul.
  51. //
  52. // 09/02/97 MJR Tested and tuned alot, and fixed a bunch of bugs. Now
  53. // appears to be very stable.
  54. //
  55. // 09/07/97 MJR Added "Proceed" message.
  56. //
  57. // 06/02/98 JMI The handling of variable length messages was assuming the
  58. // message size was 2 (a short) but it was really a long.
  59. // Fixed.
  60. //
  61. ////////////////////////////////////////////////////////////////////////////////
  62. #include "RSPiX.h"
  63. #include "netmsgr.h"
  64. #include "NetDlg.h"
  65. ////////////////////////////////////////////////////////////////////////////////
  66. // This macro creates the horrendous amount of crap needed to declare the
  67. // various pieces of information about a particular message struct.
  68. //
  69. // For each struct, we get it's size and pointers to it's Read() and Write()
  70. // functions. The usage of these function pointers is very similar to C++
  71. // virtual functions, but for various reasons, we went with structs instead
  72. // of classes, so we have to do our own table of function pointers.
  73. ////////////////////////////////////////////////////////////////////////////////
  74. #define INFO(x) NetMsg::x::Size, \
  75. NetMsg::x::Read, \
  76. NetMsg::x::Write
  77. ////////////////////////////////////////////////////////////////////////////////
  78. // Initialize array of information about each message struct.
  79. ////////////////////////////////////////////////////////////////////////////////
  80. CNetMsgr::InfoMsg CNetMsgr::ms_aInfoMsg[NetMsg::NumMessages] =
  81. {
  82. { NetMsg::NOTHING , INFO(Nothing) },
  83. { NetMsg::STAT , INFO(Stat) },
  84. { NetMsg::ERR , INFO(Err) },
  85. { NetMsg::LOGIN , INFO(Login) },
  86. { NetMsg::LOGIN_ACCEPT , INFO(LoginAccept) },
  87. { NetMsg::LOGIN_DENY , INFO(LoginDeny) },
  88. { NetMsg::LOGOUT , INFO(Logout) },
  89. { NetMsg::JOIN_REQ , INFO(JoinReq) },
  90. { NetMsg::JOIN_ACCEPT , INFO(JoinAccept) },
  91. { NetMsg::JOIN_DENY , INFO(JoinDeny) },
  92. { NetMsg::JOINED , INFO(Joined) },
  93. { NetMsg::CHANGE_REQ , INFO(ChangeReq) },
  94. { NetMsg::CHANGED , INFO(Changed) },
  95. { NetMsg::DROP_REQ , INFO(DropReq) },
  96. { NetMsg::DROPPED , INFO(Dropped) },
  97. { NetMsg::DROP_ACK , INFO(DropAck) },
  98. { NetMsg::INPUT_REQ , INFO(InputReq) },
  99. { NetMsg::INPUT_DATA , (size_t) (INFO(InputData)) },
  100. { NetMsg::INPUT_MARK , INFO(InputMark) },
  101. { NetMsg::CHAT_REQ , INFO(ChatReq) },
  102. { NetMsg::CHAT , INFO(Chat) },
  103. { NetMsg::SETUP_GAME , INFO(SetupGame) },
  104. { NetMsg::START_GAME , INFO(StartGame) },
  105. { NetMsg::ABORT_GAME , INFO(AbortGame) },
  106. { NetMsg::READY_REALM , INFO(ReadyRealm) },
  107. { NetMsg::BAD_REALM , INFO(BadRealm) },
  108. { NetMsg::START_REALM , INFO(StartRealm) },
  109. { NetMsg::HALT_REALM , INFO(HaltRealm) },
  110. { NetMsg::NEXT_REALM , INFO(NextRealm) },
  111. { NetMsg::PROGRESS_REALM , INFO(ProgressRealm) },
  112. { NetMsg::PROCEED , INFO(Proceed) },
  113. { NetMsg::PING , INFO(Ping) },
  114. { NetMsg::RAND , INFO(Rand) }
  115. };
  116. ////////////////////////////////////////////////////////////////////////////////
  117. // Update (must be called regularly)
  118. ////////////////////////////////////////////////////////////////////////////////
  119. void CNetMsgr::Update(void)
  120. {
  121. switch (m_state)
  122. {
  123. case Disconnected:
  124. // Nothing to do
  125. break;
  126. case Connecting:
  127. {
  128. short serr = m_socket.Connect(&m_address);
  129. if (serr == 0)
  130. {
  131. m_state = Connected;
  132. m_lMsgRecvTime = rspGetMilliseconds();
  133. m_lMsgSentTime = rspGetMilliseconds();
  134. }
  135. else if (serr != RSocket::errWouldBlock)
  136. {
  137. TRACE("CNetMsgr::Connect(): Attempt to connect failed!\n");
  138. // It may seem harsh, but resetting is just fine in this
  139. // situation because it cleans everything up, and there's
  140. // nothing to be "nice" about -- we're not connected to anyone!
  141. Reset();
  142. }
  143. }
  144. break;
  145. case Connected:
  146. ReceiveData();
  147. SendData();
  148. break;
  149. case Disconnecting:
  150. // When disconnecting, we only send data (we don't bother receiving it).
  151. // If there's no more data to send, or there's a send error, then disconnect.
  152. SendData();
  153. if (!IsMoreToSend())
  154. Disconnect();
  155. break;
  156. default:
  157. TRACE("CNetMsgr::Update(): Unknown state!\n");
  158. break;
  159. }
  160. }
  161. ////////////////////////////////////////////////////////////////////////////////
  162. // Get message
  163. ////////////////////////////////////////////////////////////////////////////////
  164. bool CNetMsgr::GetMsg( // True if message was available, false otherwise
  165. NetMsg* pmsg) // Out: Message is returned here
  166. {
  167. bool bGotOne = false;
  168. // If there is no error condition
  169. if (m_error == NetMsg::NoError)
  170. {
  171. // See how much data (if any) is available
  172. long lGetable = m_bufIn.CheckGetable();
  173. if (lGetable >= 1)
  174. {
  175. // Peek at first byte of data, which ought to be the message type
  176. unsigned char ucMsg;
  177. if (m_bufIn.Get(&ucMsg) == 1)
  178. {
  179. // Make sure it's a valid message type
  180. if ((ucMsg >= 0) && (ucMsg < NetMsg::NumMessages))
  181. {
  182. // Get the expected message length. A value of -1 indicates a
  183. // variable-sized message, in which case the next 2 bytes (if
  184. // they are available) would indicate the message size.
  185. long lMsgSize = ms_aInfoMsg[ucMsg].size;
  186. if (lMsgSize == -1)
  187. {
  188. // Check if at least enough is available (beyond the ucMsg byte we got)
  189. if (lGetable >= sizeof(ucMsg) + sizeof(lMsgSize) )
  190. {
  191. // Get the message size. We assume this will always succeed because
  192. // we were just told that enough was available.
  193. m_bufIn.Get(&lMsgSize);
  194. // Undo the get of lMsgSize.
  195. short sInc;
  196. for (sInc = 0; sInc < sizeof(lMsgSize); sInc++)
  197. {
  198. m_bufIn.UnGet();
  199. }
  200. }
  201. else
  202. {
  203. // Set fake message size so we'll realize message is not available
  204. lMsgSize = 0x7fffffff;
  205. }
  206. }
  207. // Undo the get of ucMsg byte.
  208. m_bufIn.UnGet();
  209. // If entire message is available, then we can get it
  210. if (lGetable >= lMsgSize)
  211. {
  212. // Make sure the read func is the right one . . .
  213. ASSERT(ms_aInfoMsg[ucMsg].ucType == ucMsg);
  214. // Read the message
  215. (ms_aInfoMsg[ucMsg].funcRead)(pmsg, &m_bufIn);
  216. // Verify that the correct number of bytes were read
  217. long lNewGetable = m_bufIn.CheckGetable();
  218. if ((lGetable - lNewGetable) == lMsgSize)
  219. {
  220. // Update most-recent receive time
  221. m_lMsgRecvTime = rspGetMilliseconds();
  222. // Indicate that we got a message
  223. bGotOne = true;
  224. /* // 12/7/97 AJC
  225. #ifdef WIN32
  226. if (g_GameSettings.m_bLogNetTime)
  227. {
  228. if (ucMsg == NetMsg::INPUT_DATA)
  229. WriteTimeStamp("CNetMsgr::GetMsg()",
  230. (char*)pmsg->msg.inputData.id ,
  231. ucMsg,
  232. 0,
  233. 0,
  234. true);
  235. else if (ucMsg != NetMsg::NOTHING)
  236. WriteTimeStamp("CNetMsgr::GetMsg()",
  237. NULL,
  238. ucMsg,
  239. 0,
  240. 0,
  241. true);
  242. }
  243. #endif
  244. // 12/7/97 AJC
  245. */
  246. }
  247. else
  248. {
  249. m_error = NetMsg::ReceiveError;
  250. TRACE("CNetMsgr::GetMsg(): Msg len should be %ld but was %ld !\n", lMsgSize, lGetable - lNewGetable);
  251. }
  252. }
  253. }
  254. else
  255. {
  256. // An invalid message type means we're in deep shit. There's no real way to
  257. // recover because we can't tell where messages start and end.
  258. m_error = NetMsg::ReceiveError;
  259. TRACE("CNetMsgr::GetMsg(): Invalid message type: %hd !\n", (short)ucMsg);
  260. }
  261. }
  262. }
  263. }
  264. // If there's an error condition then we need to generate an error message. Note that
  265. // the error condition might have existed before we got into this function, in which
  266. // case we would not have tried to get a message above. If there was no error on the
  267. // way in, and there is one now, then it occured while trying to get a message above.
  268. // Either way, we catch it here.
  269. if (m_error != NetMsg::NoError)
  270. {
  271. pmsg->msg.err.ucType = NetMsg::ERR;
  272. pmsg->msg.err.error = m_error;
  273. // Got one.
  274. bGotOne = true;
  275. // Clear error now that user has been notified.
  276. m_error = NetMsg::NoError;
  277. /* // 12/7/97 AJC
  278. #ifdef WIN32
  279. if (g_GameSettings.m_bLogNetTime)
  280. {
  281. WriteTimeStamp("CNetMsgr::GetMsg()",
  282. NULL,
  283. NetMsg::ERR,
  284. 0,
  285. 0,
  286. true);
  287. }
  288. #endif
  289. // 12/7/97 AJC
  290. */
  291. }
  292. // If we didn't get a message, then generate a "nothing" message
  293. if (!bGotOne)
  294. pmsg->msg.nothing.ucType = NetMsg::NOTHING;
  295. //==============================================================================
  296. // MUST BE AT END OF FUNCTION!!!
  297. //
  298. // If it's a send error and we're disconnecting, then disconnect now.
  299. //
  300. // We do this at the end of this function because if we disconnect, we don't
  301. // want anyone to accidentally change any member variables afterwards!
  302. //==============================================================================
  303. if (m_state == Disconnecting)
  304. {
  305. if (pmsg->msg.nothing.ucType == NetMsg::ERR)
  306. {
  307. if (IsSendError(pmsg->msg.err.error))
  308. Disconnect();
  309. }
  310. }
  311. return bGotOne;
  312. }
  313. ////////////////////////////////////////////////////////////////////////////////
  314. // Send message
  315. ////////////////////////////////////////////////////////////////////////////////
  316. void CNetMsgr::SendMsg(
  317. NetMsg* pmsg, // In: Message to send
  318. bool bSendNow /*= true*/) // In: Whether to send now or wait until Update()
  319. {
  320. ASSERT(m_state == Connected);
  321. // Only send messages if we're connected
  322. if (m_state == Connected)
  323. {
  324. // Get msg type.
  325. U8 ucMsg = pmsg->msg.nothing.ucType;
  326. // Make sure it's a valid message type
  327. if ((ucMsg >= 0) && (ucMsg < NetMsg::NumMessages))
  328. {
  329. // Determine message size. A size of -1 indicates a variable-sized message,
  330. // in which case the actual size is stored within the message itself.
  331. long lMsgSize = ms_aInfoMsg[ucMsg].size;
  332. if (lMsgSize == -1)
  333. lMsgSize = pmsg->msg.nothing.lSize;
  334. // Check available space in the queue, and if it's enough for the message, go ahead
  335. long lPutable = m_bufOut.CheckPutable();
  336. if (lPutable >= lMsgSize)
  337. {
  338. // Make sure the write func is the right one . . .
  339. ASSERT(ms_aInfoMsg[ucMsg].ucType == ucMsg);
  340. // Write the message . . .
  341. (ms_aInfoMsg[ucMsg].funcWrite)(pmsg, &m_bufOut);
  342. // Verify that the correct number of bytes were written
  343. long lNewPutable = m_bufOut.CheckPutable();
  344. if ((lPutable - lNewPutable) == lMsgSize)
  345. {
  346. // Update time last message was sent (hmmmm....not really! This merely indicates
  347. // that the message was queued up, but not that it was actually sent! Perhaps
  348. // this needs to be changed at some point to be more accurate. It would have to
  349. // be moved to wherever we actually transmit the data to the socket. Of course,
  350. // at that level, it's hard to tell if an entire message was sent, but still, it
  351. // would be more accurate than this.
  352. m_lMsgSentTime = rspGetMilliseconds();
  353. }
  354. else
  355. {
  356. m_error = NetMsg::SendError;
  357. TRACE("CNetMsgr::SendMsg(): Msg len should be %ld but was %ld !\n", lMsgSize, lPutable - lNewPutable);
  358. }
  359. }
  360. else
  361. {
  362. m_error = NetMsg::OutQFullError;
  363. TRACE("CNetMsgr::SendMsg(): Output queue is full!\n");
  364. }
  365. }
  366. else
  367. {
  368. // This should obviously never occur as it would indicate a humongous internal problem,
  369. // like the program has blown itself up or something.
  370. m_error = NetMsg::SendError;
  371. TRACE("CNetMsgr::SendMsg(): Attempting to write invalid message type: %hd !\n", (short)ucMsg);
  372. ASSERT(0);
  373. }
  374. // If "send now" flag is set, do it
  375. if (bSendNow)
  376. {
  377. /* // 12/7/97 AJC
  378. #ifdef WIN32
  379. if (g_GameSettings.m_bLogNetTime)
  380. {
  381. if (ucMsg == NetMsg::INPUT_DATA)
  382. WriteTimeStamp("CNetMsgr::SendMsg()",
  383. (char*)pmsg->msg.inputData.id ,
  384. ucMsg,
  385. 0,
  386. 0,
  387. false);
  388. else if (ucMsg != NetMsg::NOTHING)
  389. WriteTimeStamp("CNetMsgr::SendMsg()",
  390. NULL,
  391. ucMsg,
  392. 0,
  393. 0,
  394. false);
  395. }
  396. #endif
  397. // 12/7/97 AJC
  398. */
  399. SendData();
  400. }
  401. }
  402. }
  403. ////////////////////////////////////////////////////////////////////////////////
  404. // Receive data (copy data from socket into input buffer)
  405. ////////////////////////////////////////////////////////////////////////////////
  406. void CNetMsgr::ReceiveData(void)
  407. {
  408. // If there's bytes waiting to be received and no errors, then get them.
  409. // This was originally a while() loop but that was too dangerous because a
  410. // constant stream of data would have kept us in the loop forever! Instead
  411. // we now loop twice. The reason is that our buffer is implimented in such
  412. // a way that if the largest block we can write to it is from the current
  413. // position to the end of the buffer. However, there might be additional
  414. // space at the beginning of the buffer -- all we have to do is "wrap around"
  415. // to the beginning. Doing two gets does exactly that.
  416. for (short sGet = 0; sGet < 2; sGet++)
  417. {
  418. if (m_socket.CheckReceivableBytes() && (m_error == NetMsg::NoError))
  419. {
  420. // Call watchdog to let it know we're still going (we're in a loop!)
  421. NetBlockingWatchdog();
  422. // No bytes received yet
  423. long lReceivedBytes = 0;
  424. // Lock the buffer so we can write directly into it
  425. U8* pu8Put;
  426. long lMaxPuttableBytes;
  427. m_bufIn.LockPutPtr(&pu8Put, &lMaxPuttableBytes);
  428. // Make sure there's room in the buffer
  429. if (lMaxPuttableBytes > 0)
  430. {
  431. // Receive up to the specified number of bytes
  432. short serr = m_socket.Receive(pu8Put, lMaxPuttableBytes, &lReceivedBytes);
  433. if ((serr != 0) && (serr != RSocket::errWouldBlock))
  434. {
  435. m_error = NetMsg::ReceiveError;
  436. TRACE("CNetMsgr::Update(): Receive error!\n");
  437. }
  438. }
  439. else
  440. {
  441. TRACE("CNetMsgr::Update(): Warning! Input queue is full!\n");
  442. }
  443. // Release pointer, telling it how many bytes we actually added to it
  444. m_bufIn.ReleasePutPtr(lReceivedBytes);
  445. }
  446. else
  447. break;
  448. }
  449. }
  450. ////////////////////////////////////////////////////////////////////////////////
  451. // Send data (copy data output buffer to socket)
  452. ////////////////////////////////////////////////////////////////////////////////
  453. void CNetMsgr::SendData(void)
  454. {
  455. // If we have data to send and there's no errors, then try to send it. It's
  456. // safe to loop because we can't get stuck -- there's only so much data to send!
  457. while (!m_bufOut.IsEmpty() && (m_error == NetMsg::NoError))
  458. {
  459. // We don't check this in the while() because it may be somewhat slow,
  460. // depending on the underlying implimentation. Instead, we only check
  461. // it after we've already determined that we actually have data to send.
  462. if (m_socket.CanSendWithoutBlocking())
  463. {
  464. // Call watchdog to let it know we're still going (we're in a loop!)
  465. NetBlockingWatchdog();
  466. // No bytes sent yet
  467. long lSentBytes = 0;
  468. // Lock the buffer so we can read directly from it
  469. U8* pu8Get;
  470. long lMaxGettableBytes;
  471. m_bufOut.LockGetPtr(&pu8Get, &lMaxGettableBytes);
  472. // Make sure we can get something from buffer (this is not really
  473. // necessary since we already check IsEmpty() above, but what the hell...
  474. if (lMaxGettableBytes > 0)
  475. {
  476. // Receive up to the specified number of bytes
  477. short serr = m_socket.Send(pu8Get, lMaxGettableBytes, &lSentBytes);
  478. if ((serr != 0) && (serr != RSocket::errWouldBlock))
  479. {
  480. m_error = NetMsg::SendError;
  481. TRACE("CNetMsgr::Update(): Send error!\n");
  482. }
  483. }
  484. else
  485. {
  486. // If for some unbelievable reason this test fails even though the
  487. // previous test said there was data, then we're in deep shit, but
  488. // let's avoid an infinite loop in any case...
  489. TRACE("CNetMsgr::Update(): Internal inconsistancy detected!!!\n");
  490. ASSERT(0);
  491. break;
  492. }
  493. // Release pointer, telling it how many bytes we actually got from it
  494. m_bufOut.ReleaseGetPtr(lSentBytes);
  495. }
  496. else
  497. {
  498. // If we can't send without blocking, then break out of the loop
  499. break;
  500. }
  501. }
  502. }
  503. ////////////////////////////////////////////////////////////////////////////////
  504. // EOF
  505. ////////////////////////////////////////////////////////////////////////////////