NetClient.cpp 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760
  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. // NetClient.cpp
  19. // Project: RSPiX
  20. //
  21. // History:
  22. // 09/01/97 MJR Nearing the end of a major overhaul.
  23. //
  24. // 09/07/97 MJR Fixed problem with DROPPED message, whereby the caller
  25. // couldn't recognize when he himself was dropped because
  26. // the ID was no longer valid.
  27. //
  28. // Added support for PROCEED and PROGRESS_REALM messages.
  29. //
  30. // 09/10/97 MJR Changed return value from StartJoinProcess() so that
  31. // caller could determine whether the failure was due to
  32. // unsupported protocol (RSocket::errNotSupported).
  33. //
  34. // 09/12/97 MJR Added SendText() as alternative to SendChat().
  35. //
  36. // 09/12/97 MJR Now checks to make sure we're joined before it tries to
  37. // send chat or text.
  38. //
  39. // 11/25/97 JMI Changed m_error to m_msgError so we could store a whole
  40. // error message instead of just the error type.
  41. // Also, now notices the difference between a version mismatch
  42. // and a platform mismatch and reports separate errors for
  43. // each.
  44. //
  45. // 11/26/97 JMI Masking error in evaluation of version mismatch problem
  46. // such that platform mismatch was never detected.
  47. //
  48. // 12/18/97 SPA Changed ReceiveFromPeers to limit by number of times through
  49. // the loop (to number of joined peers *2) instead of a time limit.
  50. // Changed SendToPeers to write it's own data directly instead of
  51. // sending it out over the net just to receive it again later.
  52. // Also limited the resending of the same packet multiple times
  53. // to a maximum number (set from prefs - NumSendsPerBurst - default 2)
  54. // and a repeat interval for burst (set from prefs - SendInterval -
  55. // default 1000 ms).
  56. // Added variable frame rate (really more of a self regulating frame rate).
  57. // Each peer keeps track of how long it took between frames (as measured
  58. // in CanDoFrame) and then sends that value to all other peers in the
  59. // next available frame that hasn't been yet. Each peer then averages the
  60. // frame times for that frame (which is really the time it took for the
  61. // frame that happened MaxFrameLag frames ago). This is stored in an array
  62. // which contains the average frame times for the last eight frames. The
  63. // values in this array are then averaged and the result is used as the
  64. // elapsed game time for the current frame (passed back in psFrameTime).
  65. // This last step is done to smooth out any rapid changes in the speed.
  66. // Also changed msg INPUT_REQ and INPUT_DATA to update frame time from above.
  67. //
  68. // 12/22/97 SPA Rewrote SendToPeers to send only one packet per frame with each packet
  69. // containing all the frames that that peer might need. This is frames
  70. // starting from the previous frame (which is the one that we have all
  71. // the data for) minus MaxFrameLag up to current frame plus MaxFrameLag.
  72. // This means that we send (MaxFrameLag *2 + 2) frames per packet. This also
  73. // means that each frame is sent (MaxFrameLag *2 + 2) times which should
  74. // replace most lost or misplaced packets. In case we do loose multiple
  75. // packets, there is also a request mechanism. If we are unable to render
  76. // a frame after a time out has expired, we request frame data from the
  77. // peers that are missing (as well as resending the last packet sent to
  78. // them, just in case the reason he didn't send the data is because he
  79. // didn't get our data). The request is checked for in ReceiveFromPeers
  80. // and the requested data sent immediately. To simplify the request mechanism
  81. // I pulled the center loop of SendToPeers out into it's own method (SendToPeer).
  82. //
  83. // 1/5/98 SPA Fixed problem were we would not go to next level because the data for the
  84. // halt frame was not being sent so that everyone was stuck waiting to
  85. // render the last frame.
  86. //
  87. // 1/6/98 SPA TimePerFrame from .ini now used for maximum time per frame instead of actual
  88. // time per frame. SendInputInterval from .ini now used as timeout value for
  89. // frame request mechanism.
  90. //
  91. // 06/02/98 JMI Added an additional condition to avoid indexing into the
  92. // peers array with our ID when it is invalid in
  93. // SetLocalInput().
  94. //
  95. ////////////////////////////////////////////////////////////////////////////////
  96. #include "RSPiX.h"
  97. #include "netclient.h"
  98. #include "NetDlg.h"
  99. // This is the maximum size of the peer messages.
  100. #define PEER_MSG_HEADER_SIZE (1 + 2 + 2 + 2 + 2)
  101. #define PEER_MSG_MAX_SIZE (PEER_MSG_HEADER_SIZE + ((Net::MaxAheadSeq * 2) * (sizeof(UINPUT) + sizeof(U8)))) // *SPA
  102. ////////////////////////////////////////////////////////////////////////////////
  103. // Get values from buffer in proper endian order (buffer contents are always
  104. // in network order, which is big-endian).
  105. ////////////////////////////////////////////////////////////////////////////////
  106. //------------------------------------------------------------------------------
  107. // Get a U8
  108. //------------------------------------------------------------------------------
  109. inline void Get(U8* &pget, U8* pval)
  110. {
  111. *pval = *pget++;
  112. }
  113. //------------------------------------------------------------------------------
  114. // Get an S8
  115. //------------------------------------------------------------------------------
  116. inline void Get(U8* &pget, S8* pval)
  117. {
  118. Get(pget, (U8*)pval);
  119. }
  120. //------------------------------------------------------------------------------
  121. // Get a U16
  122. //------------------------------------------------------------------------------
  123. inline void Get(U8* &pget, U16* pval)
  124. {
  125. #ifdef SYS_ENDIAN_LITTLE
  126. U8* ptmp = ((U8*)(pval)) + 1;
  127. *ptmp-- = *pget++;
  128. *ptmp = *pget++;
  129. #else
  130. U8* ptmp = (U8*)(pval);
  131. *ptmp++ = *pget++;
  132. *ptmp = *pget++;
  133. #endif
  134. }
  135. //------------------------------------------------------------------------------
  136. // Get an S16
  137. //------------------------------------------------------------------------------
  138. inline void Get(U8* &pget, S16* pval)
  139. {
  140. Get(pget, (U16*)pval);
  141. }
  142. //------------------------------------------------------------------------------
  143. // Get a U32
  144. //------------------------------------------------------------------------------
  145. inline void Get(U8* &pget, U32* pval)
  146. {
  147. #ifdef SYS_ENDIAN_LITTLE
  148. U8* ptmp = ((U8*)(pval)) + 3;
  149. *ptmp-- = *pget++;
  150. *ptmp-- = *pget++;
  151. *ptmp-- = *pget++;
  152. *ptmp = *pget++;
  153. #else
  154. U8* ptmp = (U8*)(pval);
  155. *ptmp++ = *pget++;
  156. *ptmp++ = *pget++;
  157. *ptmp++ = *pget++;
  158. *ptmp = *pget++;
  159. #endif
  160. }
  161. //------------------------------------------------------------------------------
  162. // Get a U64
  163. //------------------------------------------------------------------------------
  164. inline void Get(U8* &pget, U64* pval)
  165. {
  166. #ifdef SYS_ENDIAN_LITTLE
  167. U8* ptmp = ((U8*)(pval)) + 3;
  168. *ptmp-- = *pget++;
  169. *ptmp-- = *pget++;
  170. *ptmp-- = *pget++;
  171. *ptmp-- = *pget++;
  172. *ptmp-- = *pget++;
  173. *ptmp-- = *pget++;
  174. *ptmp-- = *pget++;
  175. *ptmp = *pget++;
  176. #else
  177. U8* ptmp = (U8*)(pval);
  178. *ptmp++ = *pget++;
  179. *ptmp++ = *pget++;
  180. *ptmp++ = *pget++;
  181. *ptmp++ = *pget++;
  182. *ptmp++ = *pget++;
  183. *ptmp++ = *pget++;
  184. *ptmp++ = *pget++;
  185. *ptmp = *pget++;
  186. #endif
  187. }
  188. //------------------------------------------------------------------------------
  189. // Get an S32
  190. //------------------------------------------------------------------------------
  191. inline void Get(U8* &pget, S32* pval)
  192. {
  193. Get(pget, (U32*)pval);
  194. }
  195. ////////////////////////////////////////////////////////////////////////////////
  196. // Put values into buffer in proper endian order (buffer contents are always
  197. // in network order, which is big-endian).
  198. ////////////////////////////////////////////////////////////////////////////////
  199. //------------------------------------------------------------------------------
  200. // Put a U8
  201. //------------------------------------------------------------------------------
  202. inline void Put(U8* &pput, U8 val)
  203. {
  204. *pput++ = val;
  205. }
  206. //------------------------------------------------------------------------------
  207. // Put an S8
  208. //------------------------------------------------------------------------------
  209. inline void Put(U8* &pput, S8 val)
  210. {
  211. Put(pput, (U8)val);
  212. }
  213. //------------------------------------------------------------------------------
  214. // Put a U16
  215. //------------------------------------------------------------------------------
  216. inline void Put(U8* &pput, U16 val)
  217. {
  218. #ifdef SYS_ENDIAN_LITTLE
  219. U8* ptmp = ((U8*)(&val)) + 1;
  220. *pput++ = *ptmp--;
  221. *pput++ = *ptmp;
  222. #else
  223. U8* ptmp = (U8*)(&val);
  224. *pput++ = *ptmp++;
  225. *pput++ = *ptmp;
  226. #endif
  227. }
  228. //------------------------------------------------------------------------------
  229. // Put an S16
  230. //------------------------------------------------------------------------------
  231. inline void Put(U8* &pput, S16 val)
  232. {
  233. Put(pput, (U16)val);
  234. }
  235. //------------------------------------------------------------------------------
  236. // Put a U32
  237. //------------------------------------------------------------------------------
  238. inline void Put(U8* &pput, U32 val)
  239. {
  240. #ifdef SYS_ENDIAN_LITTLE
  241. U8*ptmp = ((U8*)(&val)) + 3;
  242. *pput++ = *ptmp--;
  243. *pput++ = *ptmp--;
  244. *pput++ = *ptmp--;
  245. *pput++ = *ptmp;
  246. #else
  247. U8*ptmp = (U8*)(&val);
  248. *pput++ = *ptmp++;
  249. *pput++ = *ptmp++;
  250. *pput++ = *ptmp++;
  251. *pput++ = *ptmp;
  252. #endif
  253. }
  254. //------------------------------------------------------------------------------
  255. // Put a U64
  256. //------------------------------------------------------------------------------
  257. inline void Put(U8* &pput, U64 val)
  258. {
  259. #ifdef SYS_ENDIAN_LITTLE
  260. U8*ptmp = ((U8*)(&val)) + 3;
  261. *pput++ = *ptmp--;
  262. *pput++ = *ptmp--;
  263. *pput++ = *ptmp--;
  264. *pput++ = *ptmp--;
  265. *pput++ = *ptmp--;
  266. *pput++ = *ptmp--;
  267. *pput++ = *ptmp--;
  268. *pput++ = *ptmp;
  269. #else
  270. U8*ptmp = (U8*)(&val);
  271. *pput++ = *ptmp++;
  272. *pput++ = *ptmp++;
  273. *pput++ = *ptmp++;
  274. *pput++ = *ptmp++;
  275. *pput++ = *ptmp++;
  276. *pput++ = *ptmp++;
  277. *pput++ = *ptmp++;
  278. *pput++ = *ptmp;
  279. #endif
  280. }
  281. //------------------------------------------------------------------------------
  282. // Put an S32
  283. //------------------------------------------------------------------------------
  284. inline void Put(U8* &pput, S32 val)
  285. {
  286. Put(pput, (U32)val);
  287. }
  288. ////////////////////////////////////////////////////////////////////////////////
  289. // Startup
  290. ////////////////////////////////////////////////////////////////////////////////
  291. void CNetClient::Startup(
  292. RSocket::BLOCK_CALLBACK callback) // In: Blocking callback
  293. {
  294. // Do a reset to be sure we're starting at a good point
  295. Reset();
  296. // Save callback
  297. m_callback = callback;
  298. }
  299. ////////////////////////////////////////////////////////////////////////////////
  300. // Shutdown
  301. ////////////////////////////////////////////////////////////////////////////////
  302. void CNetClient::Shutdown(void)
  303. {
  304. Reset();
  305. }
  306. ////////////////////////////////////////////////////////////////////////////////
  307. // Start the process of joining the game on the specified host. The port in
  308. // in the host's address is assumed to be the so-called "base port".
  309. //
  310. // If this function returns an error, it indicates that the join process has
  311. // failed, most likely because the currently selected protocol is not supported.
  312. // Even if this happens, it is still safe to call Update() and GetMsg() as if
  313. // no error occurred, realizing, of course, that the join process will not
  314. // succeed and GetMsg() will shortly return an error to that effect.
  315. ////////////////////////////////////////////////////////////////////////////////
  316. short CNetClient::StartJoinProcess( // Returns 0 if successfull, non-zero otherwise
  317. RSocket::Address* paddressHost, // In: Host's address
  318. char* pszName, // In: Joiner's name
  319. unsigned char ucColor, // In: Joiner's color
  320. unsigned char ucTeam, // In: Joiner's team
  321. short sBandwidth) // In: Joiner's Net::Bandwidth
  322. {
  323. // Save server address (containing the base port)
  324. m_addressServer = *paddressHost;
  325. // Calculate server's listen address (the port is simply offset from the base port)
  326. m_addressServerListen = *paddressHost;
  327. RSocket::SetAddressPort(RSocket::GetAddressPort(&m_addressServer) + Net::ListenPortOffset, &m_addressServerListen);
  328. // Temporarily stash the join data in peer #0
  329. memcpy(m_aPeers[0].m_acName, pszName, sizeof(m_aPeers[0].m_acName));
  330. m_aPeers[0].m_acName[sizeof(m_aPeers[0].m_acName)-1] = 0;
  331. m_aPeers[0].m_ucColor = ucColor;
  332. m_aPeers[0].m_ucTeam = ucTeam;
  333. m_aPeers[0].m_sBandwidth = sBandwidth;
  334. // Start the asynchronous connection process. If an error is returned, it's
  335. // never going to succeed. If it doesn't return an error, we poll m_msgr's
  336. // state in Update() to determine whether it failed or succeeded. We also
  337. // set a timer so that if it takes too long, we'll give up.
  338. // NOTE: Even though the caller could obviously check the result and not
  339. // bother calling Update() if the result indicates failure, we do allow
  340. // for the caller to ignore the value and go right into the normal "loop"
  341. // which includes calling Update() and GetMsg(), so they can handle errors
  342. // the "normal" way -- via GetMsg().
  343. short sResult = m_msgr.Connect(&m_addressServerListen, m_callback);
  344. m_state = WaitForConnect;
  345. m_lTimeOut = rspGetMilliseconds() + Net::MaxConnectWaitTime;
  346. return sResult;
  347. }
  348. ////////////////////////////////////////////////////////////////////////////////
  349. // Update (must be called regularly)
  350. ////////////////////////////////////////////////////////////////////////////////
  351. void CNetClient::Update(void)
  352. {
  353. NetMsg msg;
  354. // If there's an error message that the user hasn't retrieved yet, then
  355. // we can't do anything.
  356. if (m_msgError.msg.err.error == NetMsg::NoError)
  357. {
  358. switch (m_state)
  359. {
  360. case Nothing:
  361. // Nothing to do
  362. break;
  363. case WaitForConnect:
  364. // Wait for connect attempt to complete or fail or timeout
  365. m_msgr.Update();
  366. switch(m_msgr.GetState())
  367. {
  368. case CNetMsgr::Connecting:
  369. if (rspGetMilliseconds() > m_lTimeOut)
  370. {
  371. TRACE("CNetClient::Update(): Timed-out trying to connect to server!\n");
  372. m_msgError.msg.err.error = NetMsg::ConnectTimeoutError;
  373. Drop();
  374. }
  375. break;
  376. case CNetMsgr::Connected:
  377. // Send login message to server and set state to wait for response
  378. msg.msg.login.ucType = NetMsg::LOGIN;
  379. msg.msg.login.ulMagic = CNetMsgr::MagicNum;
  380. msg.msg.login.ulVersion = CNetMsgr::CurVersionNum;
  381. SendMsg(&msg);
  382. m_state = WaitForLoginResponse;
  383. m_status = NetMsg::Connected;
  384. break;
  385. case CNetMsgr::Disconnecting:
  386. case CNetMsgr::Disconnected:
  387. default:
  388. TRACE("CNetClient::Update(): Error trying to connect to server!\n");
  389. m_msgError.msg.err.error = NetMsg::CantConnectError;
  390. Drop();
  391. break;
  392. }
  393. break;
  394. case WaitForLoginResponse:
  395. // Wait for response to our LOGIN message
  396. m_msgr.Update();
  397. m_msgr.GetMsg(&msg);
  398. msg.ucSenderID = Net::InvalidID;
  399. switch(msg.msg.nothing.ucType)
  400. {
  401. case NetMsg::NOTHING:
  402. break;
  403. case NetMsg::LOGIN_ACCEPT:
  404. ////////////////////////////////////////////////////////////////
  405. // Version negotiation and useful error results ////////////////
  406. ////////////////////////////////////////////////////////////////
  407. //
  408. // In net implementation for Postal net version 1, both the
  409. // server and the client would check the version numbers -- the
  410. // server would check msg.login.ulVersion against its
  411. // MinVersionNum & CurVersionNum and, if the server accepted the
  412. // login, the client would check msg.loginAccept.ulVersion
  413. // against its MinVersionNum & CurVersionNum. Although the
  414. // version 1 client would display an error message when it
  415. // decided it could not support the server's version, the server
  416. // would refuse a login before that, never giving the client a
  417. // chance to notice and report this to the user.
  418. // To remedy this, the Postal Net version 2's server NEVER
  419. // rejects a client and, instaed, relies on the client to reject
  420. // it. This gives the client a chance to report the error.
  421. // Since under our new scheme we never send a LOGIN_DENY, we
  422. // know, if we receive a LOGIN_DENY, that we are dealing with a
  423. // version 1 server.
  424. //
  425. // Additionally, bit fifteen of the version number is set if on
  426. // a Mac platform so we can use the same mechanism to determine
  427. // if we are attempting to connect a Mac and a PC.
  428. //
  429. // Here's the actual scenarios and results for version conflicts:
  430. //
  431. // Server 1 vs Client 2 -- Server sends Client a LOGIN_DENY so
  432. // the client knows it's dealing with a version 1 server and
  433. // reports the problem.
  434. //
  435. // Server 2 vs Client 1 -- Server accepts connection. Client
  436. // drops, though, when it sees the server's version is 2 and
  437. // reports the problem.
  438. //
  439. // For future versions:
  440. //
  441. // Server 3 vs Client 1 -- Server accepts connection. Client
  442. // drops, though, when it sees the server's version is 3 and
  443. // reports the problem.
  444. //
  445. // Server 3 vs Client 2 -- Server accepts connection. Client
  446. // drops, though, when it sees the server's version is 3 and
  447. // reports the problem.
  448. //
  449. // (see NetMsg::LOGIN_DENY case for handling of net version 1)
  450. //
  451. ////////////////////////////////////////////////////////////////
  452. // Check server's version number to see if we can support it
  453. if ( (msg.msg.loginAccept.ulVersion >= CNetMsgr::MinVersionNum) && (msg.msg.loginAccept.ulVersion <= CNetMsgr::CurVersionNum))
  454. {
  455. // Save our assigned ID
  456. m_id = msg.msg.loginAccept.idAssigned;
  457. // Send join request and set state to wait for response. After this point, we no
  458. // longer care about the data we temporarily stashed in peer #0 because if our join
  459. // request is accepted, the server will send us info about ALL the clients, including
  460. // ourself. If our request is denied, then nothing matters.
  461. msg.msg.joinReq.ucType = NetMsg::JOIN_REQ;
  462. memcpy(msg.msg.joinReq.acName, m_aPeers[0].m_acName, sizeof(msg.msg.joinReq.acName));
  463. msg.msg.joinReq.ucColor = m_aPeers[0].m_ucColor;
  464. msg.msg.joinReq.ucTeam = m_aPeers[0].m_ucTeam;
  465. msg.msg.joinReq.sBandwidth = m_aPeers[0].m_sBandwidth;
  466. SendMsg(&msg);
  467. m_state = WaitForJoinResponse;
  468. m_status = NetMsg::LoginAccepted;
  469. }
  470. else
  471. {
  472. // Determine error type (possibilities are incompatible
  473. // versions and/or incompatible platforms).
  474. if ( (msg.msg.loginAccept.ulVersion & CNetMsgr::MacVersionBit) ^ (CNetMsgr::MinVersionNum & CNetMsgr::MacVersionBit) )
  475. {
  476. // One of us is a Mac and one is a PC.
  477. m_msgError.msg.err.error = NetMsg::ClientPlatformMismatchError;
  478. }
  479. else
  480. {
  481. // Incompatible version number.
  482. m_msgError.msg.err.error = NetMsg::ClientVersionMismatchError;
  483. m_msgError.msg.err.ulParam = msg.msg.loginAccept.ulVersion & ~CNetMsgr::MacVersionBit;
  484. }
  485. // Unsupported version number -- send LOGOUT message
  486. msg.msg.logout.ucType = NetMsg::LOGOUT;
  487. SendMsg(&msg);
  488. Drop();
  489. TRACE("CNetClient::Update(): Error trying to login to server -- unsupported version number!\n");
  490. }
  491. break;
  492. case NetMsg::LOGIN_DENY:
  493. Drop();
  494. // There's ONLY ONE reason we'll ever get a LOGIN_DENY message and that is
  495. // a version 1 server refused our connection b/c of our later version number
  496. // so ... Incompatible version number.
  497. m_msgError.msg.err.error = NetMsg::ClientVersionMismatchError;
  498. m_msgError.msg.err.ulParam = 1;
  499. // m_msgError.msg.err.error = NetMsg::LoginDeniedError;
  500. TRACE("CNetClient::Update(): Login denied!\n");
  501. break;
  502. default:
  503. TRACE("CNetClient::Update(): Unexpected message received while waiting for login response!\n");
  504. break;
  505. }
  506. break;
  507. case WaitForJoinResponse:
  508. // Wait for response to our JOIN_REQ message
  509. m_msgr.Update();
  510. m_msgr.GetMsg(&msg);
  511. msg.ucSenderID = Net::InvalidID;
  512. switch(msg.msg.nothing.ucType)
  513. {
  514. case NetMsg::NOTHING:
  515. break;
  516. case NetMsg::JOIN_ACCEPT:
  517. {
  518. // Calculate our peer port based on the server's base port
  519. unsigned short usPeerPort = RSocket::GetAddressPort(&m_addressServer) + Net::FirstPeerPortOffset + m_id;
  520. // Open peer socket (this is an unconnected datagram socket, so all the peers
  521. // simply hurl their data at this port, and we figure out who it came from).
  522. if (m_socketPeers.Open(usPeerPort, RSocket::typDatagram, RSocket::optDontBlock, m_callback) == 0)
  523. {
  524. // We are now fully joined. HOWEVER, we don't adjust the m_sNumJoined here
  525. // because we want to allow the server to be in direct control of that by
  526. // virtue of JOINED and DROPPED messages.
  527. m_state = Joined;
  528. m_status = NetMsg::JoinAccepted;
  529. }
  530. else
  531. {
  532. Drop();
  533. m_msgError.msg.err.error = NetMsg::CantOpenPeerSocketError;
  534. TRACE("CNetClient::Update(): Error opening port!\n");
  535. }
  536. }
  537. break;
  538. case NetMsg::JOIN_DENY:
  539. Drop();
  540. m_msgError.msg.err.error = NetMsg::JoinDeniedError;
  541. TRACE("CNetClient::Update(): Join denied!\n");
  542. break;
  543. default:
  544. TRACE("CNetClient::Update(): Unexpected message received while waiting for join response!\n");
  545. break;
  546. }
  547. break;
  548. case Joined:
  549. // Update messenger to server
  550. m_msgr.Update();
  551. // Always try receiving from peers before sending, because the data we
  552. // receive can influence the data we'll send.
  553. ReceiveFromPeers();
  554. SendToPeers();
  555. // If nothing was sent in a while, do a ping to tell server we're still alive
  556. #if NET_PING
  557. if ((rspGetMilliseconds() - m_msgr.GetMostRecentMsgSentTime()) > MaxTimeBetweenSends)
  558. {
  559. // Send ping msg
  560. msg.msg.ping.ucType = NetMsg::PING;
  561. msg.msg.ping.lTimeStamp = rspGetMilliseconds();
  562. msg.msg.ping.lLatestPingResult = m_lLatestPingResult;
  563. SendMsg(&msg);
  564. }
  565. #endif
  566. break;
  567. default:
  568. TRACE("CNetClient::Update(): Unknown state!\n");
  569. break;
  570. }
  571. }
  572. }
  573. ////////////////////////////////////////////////////////////////////////////////
  574. // Get next available message from server
  575. ////////////////////////////////////////////////////////////////////////////////
  576. void CNetClient::GetMsg(
  577. NetMsg* pmsg) // Out: Message is returned here
  578. {
  579. // This indicates whether we got a message to be returned to the caller
  580. bool bGotMsgForCaller = false;
  581. if (m_msgError.msg.err.error != NetMsg::NoError)
  582. {
  583. // If an error occurred, generate an error message, then reset the error flag
  584. *pmsg = m_msgError;
  585. bGotMsgForCaller = true;
  586. m_msgError.msg.err.error = NetMsg::NoError;
  587. m_msgError.msg.err.ulParam = 0;
  588. // Return this message to caller
  589. bGotMsgForCaller = true;
  590. }
  591. else if (m_status != NetMsg::NoStatus)
  592. {
  593. // If a status occurred, generate a status message, then reset the status flag
  594. pmsg->msg.stat.ucType = NetMsg::STAT;
  595. pmsg->msg.stat.status = m_status;
  596. bGotMsgForCaller = true;
  597. m_status = NetMsg::NoStatus;
  598. // Return this message to caller
  599. bGotMsgForCaller = true;
  600. }
  601. else if (m_state == Joined)
  602. {
  603. // If we're waiting for the end the of the realm and we've reached the halt
  604. // frame, then we generate a NEXT_REALM message for the caller.
  605. if (m_bNextRealmPending && m_bReachedHaltFrame)
  606. {
  607. // Clear the flags
  608. m_bUseHaltFrame = false;
  609. m_bNextRealmPending = false;
  610. m_bReachedHaltFrame = false;
  611. // Create NEXT_REALM message (note that seqHalt is meaningless to caller)
  612. pmsg->msg.nextRealm.ucType = NetMsg::NEXT_REALM;
  613. pmsg->msg.nextRealm.seqHalt = 0;
  614. // Return this message to caller
  615. bGotMsgForCaller = true;
  616. }
  617. else
  618. {
  619. // If we're in the joined state, get the next message from the server and
  620. // fill in the sender ID (it's always the server, which is Net::InvalidID)
  621. m_msgr.GetMsg(pmsg);
  622. pmsg->ucSenderID = Net::InvalidID;
  623. switch (pmsg->msg.nothing.ucType)
  624. {
  625. case NetMsg::NOTHING:
  626. break;
  627. case NetMsg::STAT:
  628. // Return this message to caller
  629. bGotMsgForCaller = true;
  630. break;
  631. case NetMsg::ERR:
  632. // If an error occurs, there's no way to recover, so we have to drop.
  633. // The drop may not fully work if there's a problem communicating with
  634. // the server, but there's no harm in trying.
  635. TRACE("CNetClient::GetMsg(): Error message received from messenger!\n");
  636. Drop();
  637. // Return this message to caller
  638. bGotMsgForCaller = true;
  639. break;
  640. case NetMsg::JOINED:
  641. {
  642. // Get id and verify that it's unused
  643. Net::ID id = pmsg->msg.joined.id;
  644. ASSERT(m_aPeers[id].m_state == CPeer::Unused);
  645. // Save this peer's info
  646. m_aPeers[id].m_address = pmsg->msg.joined.address;
  647. memcpy(m_aPeers[id].m_acName, pmsg->msg.joined.acName, sizeof(m_aPeers[id].m_acName));
  648. m_aPeers[id].m_ucColor = pmsg->msg.joined.ucColor;
  649. m_aPeers[id].m_ucTeam = pmsg->msg.joined.ucTeam;
  650. // Change state to "joined"
  651. m_aPeers[id].m_state = CPeer::Joined;
  652. // Adjust number of joined peers. Note that we rely fully on the server to send the
  653. // appropriate JOINED and DROPPED messages -- if it screws up, our number will be off.
  654. m_sNumJoined++;
  655. // Return this message to caller
  656. bGotMsgForCaller = true;
  657. }
  658. break;
  659. case NetMsg::CHANGED:
  660. {
  661. // Get id and verify that it's joined
  662. Net::ID id = pmsg->msg.changed.id;
  663. ASSERT(m_aPeers[id].m_state == CPeer::Joined);
  664. // Change this peer's info
  665. memcpy(m_aPeers[id].m_acName, pmsg->msg.changed.acName, sizeof(m_aPeers[id].m_acName));
  666. m_aPeers[id].m_ucColor = pmsg->msg.changed.ucColor;
  667. m_aPeers[id].m_ucTeam = pmsg->msg.changed.ucTeam;
  668. // Return this message to caller
  669. bGotMsgForCaller = true;
  670. }
  671. break;
  672. case NetMsg::DROPPED:
  673. {
  674. // Get id and verify that it's joined
  675. Net::ID id = pmsg->msg.dropped.id;
  676. ASSERT(m_aPeers[id].m_state == CPeer::Joined);
  677. // If it was me that was dropped, it's a different case
  678. if (id == m_id)
  679. {
  680. // We're done playing
  681. m_bPlaying = false;
  682. // Disconnect cleanly
  683. m_msgr.Disconnect(true);
  684. // Clear net ID
  685. m_id = Net::InvalidID;
  686. // Reset state
  687. m_state = Nothing;
  688. // Since we cleared our own ID, the caller will no longer be able to
  689. // recognize himself, because the ID in the message will not match
  690. // our own ID. Instead, we change the ID in the message to Net::InvalidID
  691. // as a flag that indicates "you yourself have been dropped".
  692. pmsg->msg.dropped.id = Net::InvalidID;
  693. }
  694. else
  695. {
  696. // If the game has started, dropping is easy. Otherwise, we merely
  697. // kick off the beginning of a long sequence...
  698. if (pmsg->msg.dropped.sContext == -1)
  699. {
  700. // Change specified peer's state to "unused"
  701. m_aPeers[id].m_state = CPeer::Unused;
  702. }
  703. else
  704. {
  705. // Change specified peer's state to "dropped"
  706. m_aPeers[id].m_state = CPeer::Dropped;
  707. // Stop playing until we get a START_REALM, which the server
  708. // will send when the drop process is completely done.
  709. m_bPlaying = false;
  710. // Respond with a DROP_ACK message that tells the server what frame
  711. // we're on and the last input seq we got from the dropee.
  712. NetMsg msg;
  713. msg.msg.dropAck.ucType = NetMsg::DROP_ACK;
  714. msg.msg.dropAck.seqLastDropeeInput = (Net::SEQ)(m_aPeers[id].m_netinput.FindFirstInvalid() - (Net::SEQ)1);
  715. msg.msg.dropAck.seqLastDoneFrame = (Net::SEQ)(m_seqFrame - (Net::SEQ)1);
  716. SendMsg(&msg);
  717. }
  718. }
  719. // Adjust number of joined peers. Note that we rely fully on the server to send
  720. // appropriate JOINED and DROPPED messages -- if it screws up, our number will be off.
  721. m_sNumJoined--;
  722. // Return this message to caller
  723. bGotMsgForCaller = true;
  724. }
  725. break;
  726. case NetMsg::INPUT_REQ:
  727. {
  728. // Get id
  729. Net::ID id = pmsg->msg.inputReq.id;
  730. // In response to this, we need to generate an INPUT_DATA message, which is a
  731. // variable-size message. We'll have the message allocate memory for the
  732. // input data, which is what varies in size. It will free the memory when it
  733. // gets destroyed.
  734. NetMsg msg;
  735. msg.msg.inputData.ucType = NetMsg::INPUT_DATA;
  736. msg.msg.inputData.id = id;
  737. msg.msg.inputData.seqStart = pmsg->msg.inputReq.seqStart;
  738. msg.msg.inputData.sNum = pmsg->msg.inputReq.sNum;
  739. msg.msg.inputData.pInputs = (UINPUT*)msg.AllocVar((long)pmsg->msg.inputReq.sNum * sizeof(UINPUT));
  740. msg.msg.inputData.pFrameTimes = (U8*)msg.AllocVar((long)pmsg->msg.inputReq.sNum * sizeof(U8));
  741. // Copy the requested values into the allocated memory
  742. Net::SEQ seq = msg.msg.inputData.seqStart;
  743. for (short s = 0; s < msg.msg.inputData.sNum; s++)
  744. {
  745. msg.msg.inputData.pFrameTimes[s] = m_aPeers[id].m_netinput.GetFrameTime(seq); // *SPA
  746. msg.msg.inputData.pInputs[s] = m_aPeers[id].m_netinput.Get(seq++);
  747. }
  748. // Send to server. We force this to send immediately with no possibility
  749. // of buffering because this message will be destroyed upon leaving this
  750. // section of code, and with it will go the buffer containing all the
  751. // inputs. Obviously, it must be sent BEFORE that happens.
  752. SendMsg(&msg, true);
  753. }
  754. break;
  755. case NetMsg::INPUT_DATA:
  756. {
  757. // Get id and verify that it's for a dropped client, which is the only
  758. // situation in which we currently use this mechanism.
  759. Net::ID id = pmsg->msg.inputData.id;
  760. ASSERT(m_aPeers[id].m_state == CPeer::Dropped);
  761. // Copy the supplied data to the input buffer for the specified peer. We
  762. // have blind faith in the server, and assume it would never send us anything
  763. // that was bad for us. :)
  764. Net::SEQ seq = pmsg->msg.inputData.seqStart;
  765. for (short s = 0; s < pmsg->msg.inputData.sNum; s++)
  766. {
  767. m_aPeers[id].m_netinput.PutFrameTime(seq, pmsg->msg.inputData.pFrameTimes[s]); // *SPA
  768. m_aPeers[id].m_netinput.Put(seq++, pmsg->msg.inputData.pInputs[s]);
  769. }
  770. }
  771. break;
  772. case NetMsg::INPUT_MARK:
  773. {
  774. // Get id and verify that it's for a dropped client, which is the only
  775. // situation in which we currently use this mechanism.
  776. Net::ID id = pmsg->msg.inputMark.id;
  777. ASSERT(m_aPeers[id].m_state == CPeer::Dropped);
  778. // The specified seq indicates the last seq for which the peer's input buffer
  779. // should be used. This value could be ahead of m_seqFrame if other peer's
  780. // are further ahead than us, or could be equal to m_SeqFrame (which, remember
  781. // is the frame we're trying to do). Or, it could be one LESS than m_seqFrame!
  782. // Consider that if we happen to be the furthest ahead of anyone, then the
  783. // frame we last did would be the frame the entire drop sequence was based
  784. // on, so that would be the last valid frame for the dropped peer. And the
  785. // last frame we did is one LESS than m_seqFrame. So, we verify that the
  786. // specified seq is >= m_seqFrame-1.
  787. ASSERT(SEQ_GTE(pmsg->msg.inputMark.seqMark, (Net::SEQ)(m_seqFrame - (Net::SEQ)1)));
  788. // Set peers last active frame
  789. m_aPeers[id].m_seqLastActive = pmsg->msg.inputMark.seqMark;
  790. // If the specified seq is m_seqFrame-1, then the peer is already inactive
  791. // since we already used that input. Otherwise, it will remain active until
  792. // we use that input.
  793. if (m_aPeers[id].m_seqLastActive == (Net::SEQ)(m_seqFrame - (Net::SEQ)1))
  794. m_aPeers[id].m_bInactive = true;
  795. else
  796. m_aPeers[id].m_bInactive = false;
  797. }
  798. break;
  799. case NetMsg::CHAT:
  800. // Return this message to caller
  801. bGotMsgForCaller = true;
  802. break;
  803. case NetMsg::SETUP_GAME:
  804. // Return this message to caller
  805. bGotMsgForCaller = true;
  806. break;
  807. case NetMsg::START_GAME:
  808. // Get some items of interest out of the message
  809. m_idServer = pmsg->msg.startGame.idServer;
  810. m_lFrameTime = (long)pmsg->msg.startGame.sFrameTime;
  811. m_seqMaxAhead = pmsg->msg.startGame.seqMaxAhead;
  812. m_seqInputNotYetSent = m_seqMaxAhead + 1; // *SPA
  813. // Game started, but we always start out "not playing"
  814. m_bGameStarted = true;
  815. m_bPlaying = false;
  816. // Return this message to caller
  817. bGotMsgForCaller = true;
  818. break;
  819. case NetMsg::ABORT_GAME:
  820. // Return this message to caller
  821. bGotMsgForCaller = true;
  822. m_bPlaying = false;
  823. break;
  824. case NetMsg::START_REALM:
  825. {
  826. // Start playing
  827. m_bPlaying = true;
  828. // *SPA 12/30/97 We can send the first frame now
  829. m_bSendNextFrame = true;
  830. m_u16PackageID = 0;
  831. Net::ID id = 0;
  832. for (id = 0; id < Net::MaxNumIDs; id++)
  833. {
  834. // Only set time for peers that are joined
  835. if (m_aPeers[id].m_state == CPeer::Joined)
  836. m_aPeers[id].m_lLastReceiveTime = rspGetMilliseconds();
  837. }
  838. }
  839. break;
  840. case NetMsg::HALT_REALM:
  841. // Set the halt frame
  842. SetHaltFrame(pmsg->msg.haltRealm.seqHalt);
  843. break;
  844. case NetMsg::NEXT_REALM:
  845. // Set the halt frame. The server will never (in theory) allow more
  846. // than one halt frame to be in effect at any time.
  847. SetHaltFrame(pmsg->msg.nextRealm.seqHalt);
  848. m_bSendNextFrame = false;
  849. // Note that we don't return this message to the caller. Instead,
  850. // we set this flag, which tells us to generate a NEXT_REALM for
  851. // the caller when we reach the halt frame.
  852. m_bNextRealmPending = true;
  853. break;
  854. case NetMsg::PROGRESS_REALM:
  855. // Whenever the server receives a READY_REALM message from a client,
  856. // it sends this message to all clients, telling them how many clients
  857. // are ready. This is just a simple status message intended to allow
  858. // the app to give the user feedback about what is happening.
  859. // Return this message to caller
  860. bGotMsgForCaller = true;
  861. break;
  862. case NetMsg::PROCEED:
  863. // This is a simple app-level message used by the server to tell all
  864. // players to "proceed" to whatever the next step of the program is
  865. // Return this message to caller
  866. bGotMsgForCaller = true;
  867. break;
  868. case NetMsg::PING:
  869. // Calculate ping time and stuff result back into message so high
  870. // level has easy access to it.
  871. // m_lLatestPingTime = rspGetMilliseconds() - pmsg->msg.ping.lTimeStamp;
  872. // pmsg->msg.ping.lLatestPingResult = m_lLatestPingTime;
  873. break;
  874. case NetMsg::RAND:
  875. break;
  876. default:
  877. TRACE("CNetClient::GetMsg(): Unexpected message received!\n");
  878. break;
  879. }
  880. }
  881. }
  882. // If we have a message for the caller, use it. Otherwise, return a NOTHING msg
  883. if (!bGotMsgForCaller)
  884. {
  885. // Create a nothing message
  886. pmsg->msg.nothing.ucType = NetMsg::NOTHING;
  887. }
  888. }
  889. ////////////////////////////////////////////////////////////////////////////////
  890. // Send message to server
  891. ////////////////////////////////////////////////////////////////////////////////
  892. void CNetClient::SendMsg(
  893. NetMsg* pmsg, // In: Message to send
  894. bool bSendNow /*= true*/) // In: Whether to send now or wait until Update()
  895. {
  896. // We purposefully don't check m_msgError.msg.error here because there's no
  897. // particular reason not to allow sending messages, since m_msgError.msg.error
  898. // doesn't currently get modified here, so there's no danger of overwriting a
  899. // previous error.
  900. // No point in sending message if we're not connected
  901. if (m_msgr.GetState() == CNetMsgr::Connected)
  902. m_msgr.SendMsg(pmsg, bSendNow);
  903. }
  904. ////////////////////////////////////////////////////////////////////////////////
  905. // Send chat message (text is sent with player's name as a prefix)
  906. ////////////////////////////////////////////////////////////////////////////////
  907. void CNetClient::SendChat(
  908. const char* pszText) // In: Text to send
  909. {
  910. if (m_state == Joined)
  911. {
  912. // Create chat message. For now, we set the mask to include everyone. In
  913. // the future, we could allow the user to specify who will/won't get it.
  914. NetMsg msg;
  915. msg.msg.chatReq.ucType = NetMsg::CHAT_REQ;
  916. msg.msg.chatReq.u16Mask = 0xffff;
  917. // We're assuming the chat field is longer than the maximum name
  918. ASSERT(sizeof(msg.msg.chatReq.acText) > sizeof(m_aPeers[m_id].m_acName));
  919. // Calculate number of chars required to display name, including the brackets
  920. // and the space and the null.
  921. int iNameChars = strlen(m_aPeers[m_id].m_acName) + 4;
  922. // Calculate space remaining for chat text
  923. int iChatChars = sizeof(msg.msg.chatReq.acText) - iNameChars;
  924. // Form chat string. Note that a maximum of iChatChars worth of chat text is printed.
  925. sprintf(msg.msg.chatReq.acText, "[%s] %.*s", m_aPeers[m_id].m_acName, iChatChars, pszText);
  926. // Send message
  927. SendMsg(&msg);
  928. }
  929. }
  930. ////////////////////////////////////////////////////////////////////////////////
  931. // Send text message (text is send as is)
  932. ////////////////////////////////////////////////////////////////////////////////
  933. void CNetClient::SendText(
  934. const char* pszText) // In: Text to send
  935. {
  936. if (m_state == Joined)
  937. {
  938. // Create chat message. For now, we set the mask to include everyone. In
  939. // the future, we could allow the user to specify who will/won't get it.
  940. NetMsg msg;
  941. msg.msg.chatReq.ucType = NetMsg::CHAT_REQ;
  942. msg.msg.chatReq.u16Mask = 0xffff;
  943. // Copy text, truncating in case the specified text is too long
  944. strncpy(msg.msg.chatReq.acText, pszText, sizeof(msg.msg.chatReq.acText));
  945. msg.msg.chatReq.acText[sizeof(msg.msg.chatReq.acText)-1] = 0;
  946. // Send message
  947. SendMsg(&msg);
  948. }
  949. }
  950. ////////////////////////////////////////////////////////////////////////////////
  951. // Send realm status
  952. ////////////////////////////////////////////////////////////////////////////////
  953. void CNetClient::SendRealmStatus(
  954. bool bReady)
  955. {
  956. NetMsg msg;
  957. if (bReady)
  958. {
  959. msg.msg.readyRealm.ucType = NetMsg::READY_REALM;
  960. SendMsg(&msg);
  961. }
  962. else
  963. {
  964. msg.msg.badRealm.ucType = NetMsg::BAD_REALM;
  965. SendMsg(&msg);
  966. }
  967. }
  968. ////////////////////////////////////////////////////////////////////////////////
  969. // Drop self
  970. ////////////////////////////////////////////////////////////////////////////////
  971. void CNetClient::Drop(void)
  972. {
  973. NetMsg msg;
  974. switch (m_state)
  975. {
  976. case Nothing:
  977. // Nothing to do
  978. break;
  979. case WaitForConnect:
  980. // The disconnect at the end is all we need to do
  981. break;
  982. case WaitForLoginResponse:
  983. // We already sent a LOGIN but don't know if it'll be accepted. If so,
  984. // this LOGOUT will be fine, and if not, it won't matter.
  985. msg.msg.logout.ucType = NetMsg::LOGOUT;
  986. SendMsg(&msg);
  987. break;
  988. case WaitForJoinResponse:
  989. // We already sent a JOIN_REQ but don't know if it'll be accepted. The
  990. // safe thing to do is to send a LOGOUT, which will work either way.
  991. msg.msg.logout.ucType = NetMsg::LOGOUT;
  992. SendMsg(&msg);
  993. break;
  994. case Joined:
  995. // Send drop request
  996. msg.msg.dropReq.ucType = NetMsg::DROP_REQ;
  997. SendMsg(&msg);
  998. break;
  999. default:
  1000. TRACE("CNetClient::Drop(): Unknown state!\n");
  1001. break;
  1002. }
  1003. // Disconnect cleanly
  1004. m_msgr.Disconnect(true);
  1005. // Clear net ID
  1006. m_id = Net::InvalidID;
  1007. // Reset state
  1008. m_state = Nothing;
  1009. }
  1010. ////////////////////////////////////////////////////////////////////////////////
  1011. // Receive messages from peers
  1012. ////////////////////////////////////////////////////////////////////////////////
  1013. void CNetClient::ReceiveFromPeers(void)
  1014. {
  1015. /*** 12/10/97 AJC ***/
  1016. // Limit the number of times we spend in the loop to the number of players
  1017. // Process incoming messages, but limit the maximum time we spend in the loop,
  1018. // because if there's a ton of incoming data, we could get stuck here forever!
  1019. // This is done as a do/while so that we can more easily debug it (otherwise,
  1020. // when single-stepping, the time expires before we ever get into the loop!)
  1021. //long lMaxTime = rspGetMilliseconds() + Net::MaxPeerReceiveTime;
  1022. short sIterations = 0;
  1023. do {
  1024. // Call watchdog to let it know we're still going (we're in a loop!)
  1025. NetBlockingWatchdog();
  1026. // Make sure maximum message size is <= maximum datagram size
  1027. ASSERT(PEER_MSG_MAX_SIZE <= Net::MaxDatagramSize);
  1028. // Get next datagram, If we get a too-large datagram, an error occurs and
  1029. // and the unreceived portion is automatically discarded. Such a message
  1030. // could come from a foreign app that is using the same port as us.
  1031. U8 msg[PEER_MSG_MAX_SIZE];
  1032. long lReceived;
  1033. short serr = m_socketPeers.ReceiveFrom(msg, sizeof(msg), &lReceived, NULL);
  1034. if (serr == 0)
  1035. {
  1036. // Make sure size is within proper range
  1037. if ((lReceived >= PEER_MSG_HEADER_SIZE) && (lReceived <= PEER_MSG_MAX_SIZE))
  1038. {
  1039. // Get the id from the message
  1040. Net::ID id;
  1041. U8* pget = msg;
  1042. Get(pget, &id);
  1043. // Make sure id is valid
  1044. if ((id >= 0) && (id < Net::MaxNumIDs))
  1045. {
  1046. // Make sure peer is joined (could be an old message from a dropped peer)
  1047. if (m_aPeers[id].m_state == CPeer::Joined)
  1048. {
  1049. // Calculate the number of input values the message contains. *SPA add sizeof frame time
  1050. long lNumInputs = (lReceived - PEER_MSG_HEADER_SIZE) / (sizeof(UINPUT) + sizeof(U8));
  1051. // Get the rest of the message
  1052. // U16 u16SenderPing;
  1053. // U16 u16ReceiverPing;
  1054. U16 u16MsgType; // *SPA
  1055. U16 u16PackageID; // *SPA
  1056. Net::SEQ seqWhatHeNeeds;
  1057. Net::SEQ seqInputs;
  1058. Get(pget, &u16PackageID); // *SPA
  1059. Get(pget, &u16MsgType); // *SPA
  1060. // Get(pget, &u16SenderPing);
  1061. // Get(pget, &u16ReceiverPing);
  1062. Get(pget, &seqWhatHeNeeds);
  1063. Get(pget, &seqInputs);
  1064. // Reset the receive timer for this peer *SPA
  1065. m_aPeers[id].m_lLastReceiveTime = rspGetMilliseconds();
  1066. /* // 12/7/97 AJC
  1067. #ifdef WIN32
  1068. if (g_GameSettings.m_bLogNetTime)
  1069. {
  1070. WriteTimeStamp("ReceiveFromPeers()",
  1071. m_aPeers[id].m_acName,
  1072. NetMsg::INPUT_DATA,
  1073. seqInputs,
  1074. lNumInputs,
  1075. true,
  1076. u16PackageID);
  1077. }
  1078. #endif
  1079. // 12/7/97 AJC
  1080. */
  1081. // Add input values to peer's input buffer
  1082. UINPUT input;
  1083. U8 frameTime;
  1084. for (short s = 0; s < lNumInputs; s++)
  1085. {
  1086. // Add input to peer's buffer
  1087. Get(pget, &input);
  1088. m_aPeers[id].m_netinput.Put(seqInputs, input);
  1089. // Add frame time to peer's buffer *SPA
  1090. Get(pget, &frameTime);
  1091. m_aPeers[id].m_netinput.PutFrameTime(seqInputs++, frameTime);
  1092. }
  1093. // If u16MsgType is 1 then this is a reqest for data *SPA
  1094. if (u16MsgType == 1)
  1095. {
  1096. // So let's send him data starting from the frame he needs now *SPA
  1097. SendToPeer(id, seqWhatHeNeeds, false);
  1098. }
  1099. // Now that I got new inputs, determine the first input seq I need from him
  1100. // m_aPeers[id].m_seqWhatINeed = m_aPeers[id].m_netinput.FindFirstInvalid();
  1101. // Since messages can arrive in the wrong order, we want to ignore older
  1102. // versions of this value so we don't send him more than he really needs.
  1103. // We can safely assume that what he needs will never go backwards from what
  1104. // he previously said -- it will stay the same or go further ahead. So we
  1105. // only use the new value if it's greater than what we have.
  1106. // if (SEQ_GTE(seqWhatHeNeeds, m_aPeers[id].m_seqWhatHeNeeds))
  1107. // m_aPeers[id].m_seqWhatHeNeeds = seqWhatHeNeeds;
  1108. #if 0
  1109. // Add his ping time into the average
  1110. m_aPeers[id].m_lHisPingSum += (long)u16SenderPing;
  1111. m_aPeers[id].m_sHisNumPings++;
  1112. // Calculate the time our ping took to get back (it won't be valid until
  1113. // he starts getting my ping times -- before that, he'll set it to 0xffff)
  1114. if (u16ReceiverPing != 0xffff)
  1115. {
  1116. }
  1117. #endif
  1118. }
  1119. else
  1120. TRACE("CNetClient::ReceiveFromPeers(): Ignoring message from non-joined player!\n");
  1121. }
  1122. else
  1123. TRACE("CNetClient::ReceiveFromPeers(): Ignoring message with invalid id!\n");
  1124. }
  1125. else
  1126. TRACE("CNetClient::ReceiveFromPeers(): Ignoring incorrectly sized message!\n");
  1127. }
  1128. else
  1129. {
  1130. if (serr != RSocket::errWouldBlock)
  1131. TRACE("CNetClient::ReceiveFromPeers(): Error receiving datagram -- ignored!\n");
  1132. // Break out of the loop (there's no data or we got an error)
  1133. break;
  1134. }
  1135. /*** 12/10/97 AJC ***/
  1136. //} while (rspGetMilliseconds() < lMaxTime);
  1137. sIterations++;
  1138. } while (sIterations < (m_sNumJoined * 2));
  1139. /*** 12/10/97 AJC ***/
  1140. }
  1141. ////////////////////////////////////////////////////////////////////////////////
  1142. // Send messages to peers
  1143. ////////////////////////////////////////////////////////////////////////////////
  1144. // 12/30/97 *SPA Pulled center loop out to seperate routine (SendToPeer) and
  1145. // simplified to send only one packet per frame
  1146. void CNetClient::SendToPeers(void)
  1147. {
  1148. // Are we ready to send the next frame
  1149. if (m_bSendNextFrame)
  1150. {
  1151. m_bSendNextFrame = false;
  1152. // Go through all the peers
  1153. Net::ID id = 0;
  1154. for (id = 0; id < Net::MaxNumIDs; id++)
  1155. {
  1156. // Only send messages to joined peers
  1157. if (m_aPeers[id].m_state == CPeer::Joined)
  1158. {
  1159. // An interesting note: If the "halt frame" is in effect, we don't
  1160. // need to explicitly check for it here. It is checked for by the
  1161. // function that handles the getting of local input. That function
  1162. // simply will not add any addition local input beyond the halt frame,
  1163. // so we are automatically prevented from sending out anything that
  1164. // we don't have.
  1165. // If it is not us (we've already set our own in SetLocalInput)
  1166. if (id != m_id)
  1167. {
  1168. // Send to peer starting from the first frame after the one we know he has
  1169. // (since we have all the inputs for frame m_seqFrame - 1, everyone must have
  1170. // rendered frame (m_seqFrame - MaxAheadSeq - 1) or else they would not have
  1171. // sent out frame m_seqFrame.
  1172. // Since this is just a routine send, we don't need to request a frame.
  1173. // Make sure we don't try to send any frame before frame 0!!
  1174. if (m_seqFrame < (m_seqMaxAhead + 1))
  1175. SendToPeer(id, 0, false);
  1176. else
  1177. SendToPeer(id, m_seqFrame - m_seqMaxAhead - 1, false);
  1178. }
  1179. }
  1180. }
  1181. }
  1182. }
  1183. ////////////////////////////////////////////////////////////////////////////////
  1184. // Send message to single peer *SPA
  1185. ////////////////////////////////////////////////////////////////////////////////
  1186. void CNetClient::SendToPeer(Net::ID id, // id of peer to send to
  1187. Net::SEQ seqStart, // frame to start at
  1188. bool bSeqReq) // true if this is a request for data
  1189. {
  1190. // Set the header values
  1191. U8 msg[PEER_MSG_MAX_SIZE];
  1192. U8* pput = msg;
  1193. // Increment the package number
  1194. m_u16PackageID++;
  1195. Put(pput, m_id);
  1196. Put(pput, m_u16PackageID );
  1197. if (!bSeqReq)
  1198. {
  1199. Put(pput, (U16)0);
  1200. Put(pput, (U16)0);
  1201. }
  1202. else
  1203. {
  1204. // If bSeqReq then set flag for data request
  1205. Put(pput, (U16)1);
  1206. // request the data for the current frame (since that must be the one that we can't render)
  1207. Put(pput, (U16)m_seqFrame);
  1208. }
  1209. Put(pput, seqStart);
  1210. ASSERT((pput - msg) == PEER_MSG_HEADER_SIZE);
  1211. // Fill in all the inputs between what he needs and the newest I have,
  1212. // up to the maximum amount. We know we'll get at least 1 because
  1213. // we already determined the one he needs is available (see above).
  1214. UINPUT input;
  1215. U8 frameTime; // *SPA
  1216. short s;
  1217. for (s = seqStart; s < m_seqInputNotYetSent; s++)
  1218. {
  1219. input = m_netinput.Get(s);
  1220. // Send game time for this frame *SPA
  1221. frameTime = m_netinput.GetFrameTime(s);
  1222. if (input != CNetInput::Invalid)
  1223. {
  1224. Put(pput, input);
  1225. Put(pput, frameTime); // *SPA
  1226. }
  1227. else
  1228. break;
  1229. }
  1230. /* // 12/7/97 AJC
  1231. #ifdef WIN32
  1232. if (g_GameSettings.m_bLogNetTime)
  1233. {
  1234. if (!bSeqReq)
  1235. WriteTimeStamp("SendToPeer()",
  1236. m_aPeers[id].m_acName,
  1237. NetMsg::INPUT_DATA,
  1238. seqStart,
  1239. s - seqStart,
  1240. false,
  1241. m_u16PackageID);
  1242. else
  1243. WriteTimeStamp("SendFrameRequest",
  1244. m_aPeers[id].m_acName,
  1245. NetMsg::INPUT_DATA,
  1246. seqStart,
  1247. s - seqStart,
  1248. false,
  1249. m_u16PackageID);
  1250. }
  1251. #endif
  1252. // 12/7/97 AJC
  1253. */
  1254. // Calculate size of message. The peer uses the message size to determine
  1255. // how many input values it contains.
  1256. ASSERT((pput - msg) <= PEER_MSG_MAX_SIZE);
  1257. long lSize = pput - msg;
  1258. // Make sure maximum message size is <= maximum datagram size
  1259. ASSERT(PEER_MSG_MAX_SIZE <= Net::MaxDatagramSize);
  1260. // Send message to peer. If an error occurs, I'm going to ignore it in the
  1261. // hopes that the next time we try, it will work. This may not be a good
  1262. // idea. Although datagram messages are not guaranteed to arrive, getting
  1263. // a send error probably indicates a real problem that may not go away.
  1264. long lSent;
  1265. short serr = m_socketPeers.SendTo(msg, lSize, &lSent, &m_aPeers[id].m_address);
  1266. if (serr == 0)
  1267. {
  1268. if (lSent != lSize)
  1269. TRACE("Error sending message to peer -- should have sent %ld bytes but actually sent %ld.\n", (long)lSize, (long)lSent);
  1270. }
  1271. else
  1272. {
  1273. if (serr != RSocket::errWouldBlock)
  1274. TRACE("Error sending message to peer -- SendTo() failed!\n");
  1275. }
  1276. }
  1277. ////////////////////////////////////////////////////////////////////////////////
  1278. // Determine whether another frame can be done. If so, the necessary peer
  1279. // inputs are returned in the supplied array and the result is true.
  1280. // Otherwise, the result is false, and a frame cannot be done.
  1281. ////////////////////////////////////////////////////////////////////////////////
  1282. bool CNetClient::CanDoFrame( // Returns true if frame can be done, false otherwise
  1283. UINPUT aInputs[], // Out: Total of Net::MaxNumIDs inputs returned here
  1284. short* psFrameTime) // Out the current frames elapsed time
  1285. {
  1286. bool bResult = false;
  1287. long lFrameTime = 0; // The sum of the frame times of the joined players *SPA
  1288. short sCount = 0; // Count of the number of joined players *SPA
  1289. // If we playing, we might be able to do this, otherwise, we definitely can't
  1290. if (m_bPlaying)
  1291. {
  1292. // Try to get the required input seq from each peer
  1293. bResult = true;
  1294. for (Net::ID id = 0; id < Net::MaxNumIDs; id++)
  1295. {
  1296. if (m_aPeers[id].m_state == CPeer::Joined)
  1297. {
  1298. // Try to get the input for the frame we're trying to do
  1299. aInputs[id] = m_aPeers[id].m_netinput.Get(m_seqFrame);
  1300. long temp = m_aPeers[id].m_netinput.GetFrameTime(m_seqFrame); // *SPA
  1301. lFrameTime += temp; // *SPA
  1302. sCount++;
  1303. if (aInputs[id] == CNetInput::Invalid)
  1304. {
  1305. bResult = false;
  1306. break;
  1307. }
  1308. }
  1309. else if (m_aPeers[id].m_state == CPeer::Dropped)
  1310. {
  1311. // If dropped peer is inactive, always return "suicide", otherwise
  1312. // continue returning what is left of his inputs.
  1313. if (m_aPeers[id].m_bInactive)
  1314. {
  1315. aInputs[id] = INPUT_SUICIDE;
  1316. }
  1317. else
  1318. {
  1319. // Get the next input -- note that a dropped player should NEVER return
  1320. // an invalid value, because there's no way to figure out what it
  1321. // should be now that he's dropped!
  1322. aInputs[id] = m_aPeers[id].m_netinput.Get(m_seqFrame);
  1323. ASSERT(aInputs[id] != CNetInput::Invalid);
  1324. }
  1325. }
  1326. }
  1327. // Check to see if we've not been able to render this frame for a while *SPA
  1328. long lCurTime = rspGetMilliseconds();
  1329. if (lCurTime > m_lMaxWaitTime)
  1330. {
  1331. for (Net::ID id = 0; id < Net::MaxNumIDs; id++)
  1332. {
  1333. if ((m_aPeers[id].m_state == CPeer::Joined) && (id != m_id))
  1334. {
  1335. // Send a request for the current frame data from each peer that we don't have
  1336. // This also resends the last data we sent, just in case it needs it before it
  1337. // can send what we need
  1338. aInputs[id] = m_aPeers[id].m_netinput.Get(m_seqFrame);
  1339. if (aInputs[id] == CNetInput::Invalid)
  1340. {
  1341. // Make sure we don't try to send any frame before frame 0!!
  1342. if (m_seqFrame < (m_seqMaxAhead + 1))
  1343. SendToPeer(id, 0, true);
  1344. else
  1345. SendToPeer(id, m_seqFrame - m_seqMaxAhead - 1, true);
  1346. }
  1347. }
  1348. }
  1349. // Reset timer
  1350. m_lMaxWaitTime = rspGetMilliseconds() + g_GameSettings.m_sNetSendInputInterval;
  1351. }
  1352. // *SPA
  1353. // If we have everything we need to go to the next frame, do it now
  1354. if (bResult)
  1355. {
  1356. // Let SendToPeers know we have a frame to render
  1357. m_bSendNextFrame = true;
  1358. // Set our max time out for the next frame
  1359. m_lMaxWaitTime = rspGetMilliseconds() + g_GameSettings.m_sNetSendInputInterval;
  1360. // Calculate frame time of the frame were about to render *SPA
  1361. // This is the average time for the current frame
  1362. m_alAvgFrameTimes[m_seqFrame & 0x7] = lFrameTime / sCount;
  1363. long lAvgTime = 0;
  1364. // This averages the frame times of the last 8 frames
  1365. for (short i = 0; i< 8; i++)
  1366. {
  1367. lAvgTime += m_alAvgFrameTimes[i];
  1368. }
  1369. *psFrameTime = lAvgTime / 8;
  1370. /** 12/15/97 *SPA **/
  1371. m_lFrameTime = *psFrameTime;
  1372. // Calculate the time since the last time here *SPA
  1373. // long lCurTime = rspGetMilliseconds();
  1374. long frameTime = lCurTime - m_lStartTime;
  1375. m_lStartTime = lCurTime;
  1376. // Limit our frame rate to minimum set by .ini (TimePerFrame) *SPA
  1377. if (frameTime > g_GameSettings.m_sNetTimePerFrame)
  1378. {
  1379. frameTime = g_GameSettings.m_sNetTimePerFrame;
  1380. }
  1381. // Put this time into the next frame that we know has not been sent to anybody *SPA
  1382. m_netinput.PutFrameTime(m_seqInputNotYetSent, (U8)(frameTime & 0x00ff));
  1383. // This is the only place where we increment the frame seq, so it's the
  1384. // right place to check if we've reached the halt frame (if there is one).
  1385. // If we reach it, stop playing. Remember, it's okay to actually DO this
  1386. // frame, we just can't do the frame beyond it, and m_seqFrame always
  1387. // indicates the frame it is TRYING to do, not the frame it already did,
  1388. // so if m_seqFrame ends up one BEYOND m_seqHaltFrame, it's perfect!
  1389. if (m_bUseHaltFrame && (m_seqFrame == m_seqHaltFrame))
  1390. {
  1391. // We're at the halt frame, so stop
  1392. m_bReachedHaltFrame = true;
  1393. m_bPlaying = false;
  1394. }
  1395. // Increment actual frame seq
  1396. m_seqFrame++;
  1397. m_seqInputNotYetSent++; // *SPA
  1398. // Increment my net input buffer
  1399. m_netinput.IncFrame();
  1400. // Handle the peer input buffers
  1401. for (Net::ID id = 0; id < Net::MaxNumIDs; id++)
  1402. {
  1403. if (m_aPeers[id].m_state == CPeer::Joined)
  1404. {
  1405. // For joined players, just inc it
  1406. m_aPeers[id].m_netinput.IncFrame();
  1407. }
  1408. else if (m_aPeers[id].m_state == CPeer::Dropped)
  1409. {
  1410. // If dropped player is still active, check if he's hit his final active seq
  1411. if (!m_aPeers[id].m_bInactive)
  1412. {
  1413. // If his frame is currently on the final active seq, then he's done. We
  1414. // know that the frame he's currently on is the one that was just returned
  1415. // to the caller, so it makes sense that if we just used his last active
  1416. // seq, he should now become inactive. If he hasn't reached his final seq,
  1417. // then we just inc his frame.
  1418. if (m_aPeers[id].m_netinput.GetFrameSeq() == m_aPeers[id].m_seqLastActive)
  1419. m_aPeers[id].m_bInactive = true;
  1420. else
  1421. m_aPeers[id].m_netinput.IncFrame();
  1422. }
  1423. }
  1424. }
  1425. }
  1426. }
  1427. return bResult;
  1428. }
  1429. ////////////////////////////////////////////////////////////////////////////////
  1430. // Check whether local input is required
  1431. ////////////////////////////////////////////////////////////////////////////////
  1432. bool CNetClient::IsLocalInputNeeded(void)
  1433. {
  1434. bool bResult = false;
  1435. // Only if we're currently playing
  1436. if (m_bPlaying)
  1437. {
  1438. // Check if timer expired
  1439. // long lCurTime = rspGetMilliseconds();
  1440. // if (lCurTime > m_lNextLocalInputTime)
  1441. // {
  1442. // The input seq is only allowed to get m_seqMaxAhead ahead of the
  1443. // frame seq. Both m_seqInput and m_seqFrame are really refering to
  1444. // the NEXT seq. When we say we're "on frame 0", we really mean we're
  1445. // waiting for all the inputs for frame 0 to arrive. As soon as they
  1446. // do, we increment to frame 1 and start waiting again. The input
  1447. // seq is the same way -- it really indicates the seq that we're GOING
  1448. // TO GET. Therefore, we can let the input seq get m_seqMaxAhead
  1449. // ahead of the frame seq, but we DON'T actually get local input when it's
  1450. // at that point. Only when the frame moves up will we get local input
  1451. // for that position.
  1452. // SPA 12/30/97 Changed m_seqMaxAhead to m_seqMaxAhead+1 (we were getting
  1453. // one less ahead than we thought we were)
  1454. ASSERT((Net::SEQ)(m_seqInput - m_seqFrame) <= (m_seqMaxAhead+1));
  1455. if ((Net::SEQ)(m_seqInput - m_seqFrame) < (m_seqMaxAhead+1))
  1456. {
  1457. // Don't send out any inputs BEYOND the stop seq. CanDoFrame() will
  1458. // let us DO the m_seqHalt frame, so we need to send out inputs up to
  1459. // and including that frame, but not beyond it. This will allow
  1460. // everyone to DO that frame, just like we did, but they will not be
  1461. // able to go beyond it (certainly not without our input, if nothing
  1462. // else).
  1463. if ( !(m_bUseHaltFrame && SEQ_GT(m_seqInput, m_seqHaltFrame)) )
  1464. {
  1465. // We need local input!
  1466. bResult = true;
  1467. // Don't reset the timer until we have actually decided we need
  1468. // local input. The idea is that if we can't move the input
  1469. // ahead for whatever reason, then the instant we CAN move ahead
  1470. // we want to do so. By waiting until here to reset the timer,
  1471. // we ensure that if we don't get here, it will remain expired.
  1472. // m_lNextLocalInputTime = lCurTime + m_lFrameTime;
  1473. }
  1474. else if (m_bUseHaltFrame)
  1475. {
  1476. UINPUT input = m_netinput.Get(m_seqFrame);
  1477. m_aPeers[m_id].m_netinput.Put(m_seqFrame, input);
  1478. U8 frameTime = m_netinput.GetFrameTime(m_seqFrame);
  1479. m_aPeers[m_id].m_netinput.PutFrameTime(m_seqFrame, frameTime);
  1480. }
  1481. }
  1482. // }
  1483. }
  1484. return bResult;
  1485. }
  1486. ////////////////////////////////////////////////////////////////////////////////
  1487. // Set local input.
  1488. // Call this if and only if IsLocalInputNeeded() returns true!
  1489. ////////////////////////////////////////////////////////////////////////////////
  1490. void CNetClient::SetLocalInput(
  1491. UINPUT input)
  1492. {
  1493. // Add to buffer and increment input seq
  1494. m_netinput.Put(m_seqInput, input);
  1495. m_seqInput++;
  1496. if (m_bPlaying && m_id != Net::InvalidID)
  1497. {
  1498. // Set our own peer data for the current frame from the local data *SPA 12/30/97
  1499. input = m_netinput.Get(m_seqFrame);
  1500. m_aPeers[m_id].m_netinput.Put(m_seqFrame, input);
  1501. U8 frameTime = m_netinput.GetFrameTime(m_seqFrame);
  1502. m_aPeers[m_id].m_netinput.PutFrameTime(m_seqFrame, frameTime);
  1503. // Reset the receive timer *SPA
  1504. m_aPeers[m_id].m_lLastReceiveTime = rspGetMilliseconds();
  1505. }
  1506. }
  1507. ////////////////////////////////////////////////////////////////////////////////
  1508. // This is normally used to handle a HALT_REALM message when we get one from
  1509. // the server.
  1510. //
  1511. // It is also used the local server, if there is one, to directly inform the
  1512. // local client (that would be us) about the halt frame. This is a necessary
  1513. // breach of client/server separation that is more fully explained elsewhere.
  1514. // (It may indicate a design flaw, but I'm at a loss for a better solution.)
  1515. ////////////////////////////////////////////////////////////////////////////////
  1516. void CNetClient::SetHaltFrame(
  1517. Net::SEQ seqHalt)
  1518. {
  1519. // This sets the last input seq we are allowed to send to any peers,
  1520. // including ourself! This effectively halts all the peers, including
  1521. // ourself, when they reach the specified frame, because they will not
  1522. // have any inputs from us beyond that frame.
  1523. // Set the frame to halt on and set the flag so we'll check for it
  1524. m_seqHaltFrame = seqHalt;
  1525. m_bUseHaltFrame = true;
  1526. // I'm not sure this can happen, but it's certainly worth checking. The
  1527. // halt frame is presumably a frame we haven't done yet. And remember
  1528. // that m_seqFrame indicates the frame we're trying to do, not the frame
  1529. // we already did. If, for some reason, we are sent a halt frame that
  1530. // is LESS than m_seqFrame, then it means something has gone very wrong.
  1531. // So let's make sure that the halt frame is always greater than or equal
  1532. // to m_seqFrame.
  1533. ASSERT(SEQ_GTE(m_seqHaltFrame, m_seqFrame));
  1534. }
  1535. ////////////////////////////////////////////////////////////////////////////////
  1536. // This is used to see if any peers have not sent data for too long of a period
  1537. //
  1538. // It returns the id of the first peer it finds that has exceeded the time limit
  1539. // so that the server can drop him. It should only be called if this client is
  1540. // attached to the server. If more than one peer has exceeded the time limit,
  1541. // it will be handled on a subsequent pass. By then the first late peer will
  1542. // have been marked as dropped.
  1543. // Returns Net::MaxNumIDs if no peer has exceeded time limit 1/13/98 *SPA
  1544. ////////////////////////////////////////////////////////////////////////////////
  1545. Net::ID CNetClient::CheckForLostPeer(void)
  1546. {
  1547. if (m_bPlaying)
  1548. {
  1549. for (Net::ID id = 0; id < Net::MaxNumIDs; id++)
  1550. {
  1551. if (m_aPeers[id].m_state == CPeer::Joined)
  1552. {
  1553. if (id != m_id)
  1554. {
  1555. long lElapsedTime = rspGetMilliseconds() - m_aPeers[id].m_lLastReceiveTime;
  1556. if (lElapsedTime > g_GameSettings.m_lPeerDropMaxWaitTime)
  1557. return id;
  1558. }
  1559. }
  1560. }
  1561. }
  1562. return Net::MaxNumIDs;
  1563. }
  1564. ////////////////////////////////////////////////////////////////////////////////
  1565. // EOF
  1566. ////////////////////////////////////////////////////////////////////////////////