natsock.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * $Archive:: /Commando/Code/Commando/natsock.cpp $*
  25. * *
  26. * $Author:: Steve_t $*
  27. * *
  28. * $Modtime:: 12/09/01 6:58p $*
  29. * *
  30. * $Revision:: 4 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * *
  35. * SocketHandlerClass::SocketHandlerClass -- Class constructor *
  36. * SocketHandlerClass::~SocketHandlerClass -- Class destrctor *
  37. * SocketHandlerClass::Open -- Opens a socket and binds it to the given port. *
  38. * SocketHandlerClass::Close -- Closes the socket if it's open. Shuts down the class. *
  39. * *
  40. * *
  41. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  42. #include <stdlib.h>
  43. #include "natsock.h"
  44. #include "nataddr.h"
  45. #include "systimer.h"
  46. /*
  47. ** All instances are tracked here.
  48. */
  49. DynamicVectorClass<SocketHandlerClass*> SocketHandlerClass::AllSocketHandlers;
  50. /***********************************************************************************************
  51. * SocketHandlerClass::SocketHandlerClass -- Class constructor *
  52. * *
  53. * *
  54. * *
  55. * INPUT: Nothing *
  56. * *
  57. * OUTPUT: Nothing *
  58. * *
  59. * WARNINGS: None *
  60. * *
  61. * HISTORY: *
  62. * 2/24/00 12:23PM ST : Created *
  63. *=============================================================================================*/
  64. SocketHandlerClass::SocketHandlerClass(void)
  65. {
  66. Socket = INVALID_SOCKET;
  67. IncomingPort = -1;
  68. OutgoingPort = -1;
  69. CanService = true;
  70. for (int i=0 ; i<MAX_STATIC_BUFFERS ; i++) {
  71. StaticInBuffers[i].InUse = false;
  72. StaticInBuffers[i].IsAllocated = false;
  73. StaticOutBuffers[i].InUse = false;
  74. StaticOutBuffers[i].IsAllocated = false;
  75. }
  76. InBuffersUsed = 0;
  77. OutBuffersUsed = 0;
  78. InBufferArrayPos = 0;
  79. OutBufferArrayPos = 0;
  80. AllSocketHandlers.Add(this);
  81. }
  82. /***********************************************************************************************
  83. * SocketHandlerClass::~SocketHandlerClass -- Class destrctor *
  84. * *
  85. * *
  86. * *
  87. * INPUT: Nothing *
  88. * *
  89. * OUTPUT: Nothing *
  90. * *
  91. * WARNINGS: None *
  92. * *
  93. * HISTORY: *
  94. * 2/24/00 12:24PM ST : Created *
  95. *=============================================================================================*/
  96. SocketHandlerClass::~SocketHandlerClass(void)
  97. {
  98. Close();
  99. AllSocketHandlers.Delete(this);
  100. }
  101. /***********************************************************************************************
  102. * SocketHandlerClass::Open -- Opens a socket and binds it to the given port. *
  103. * *
  104. * *
  105. * *
  106. * INPUT: port number *
  107. * *
  108. * OUTPUT: true if socket was opened and bound OK *
  109. * *
  110. * WARNINGS: None *
  111. * *
  112. * HISTORY: *
  113. * 2/24/00 12:41PM ST : Created *
  114. *=============================================================================================*/
  115. bool SocketHandlerClass::Open(int inport, int outport)
  116. {
  117. LINGER ling;
  118. struct sockaddr_in addr;
  119. static int socket_transmit_buffer_size = SOCKET_BUFFER_SIZE;
  120. static int socket_receive_buffer_size = SOCKET_BUFFER_SIZE;
  121. /*
  122. ** Create our UDP socket
  123. */
  124. DebugString(("SocketHandlerClass - About to open a UDP socket\n"));
  125. Socket = socket(AF_INET, SOCK_DGRAM, 0);
  126. if (Socket == INVALID_SOCKET) {
  127. return(false);
  128. }
  129. DebugString(("SocketHandlerClass - Socket %d opened OK\n", Socket));
  130. /*
  131. ** Bind our UDP socket to our UDP port number
  132. */
  133. addr.sin_family = AF_INET;
  134. addr.sin_port = (unsigned short) htons((unsigned short)inport);
  135. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  136. DebugString(("SocketHandlerClass - About to bind the UDP socket to port %d\n", inport));
  137. if (bind (Socket, (LPSOCKADDR)&addr, sizeof(addr) ) == SOCKET_ERROR) {
  138. DebugString(("SocketHandlerClass - bind failed with error code %d\n", WSAGetLastError()));
  139. Close();
  140. return(false);
  141. }
  142. DebugString(("SocketHandlerClass - Socket bound OK\n"));
  143. IncomingPort = inport;
  144. OutgoingPort = outport;
  145. /*
  146. ** Use gethostbyname to find the name of the local host. We will need this to look up
  147. ** the local ip address.
  148. */
  149. DebugString(("SocketHandlerClass - About to query the host name\n"));
  150. char hostname[128];
  151. if (gethostname(hostname, 128) == 0) {
  152. DebugString(("Host name is '%s'\n", hostname));
  153. }
  154. DebugString(("SocketHandlerClass - About to call gethostbyname\n"));
  155. struct hostent *host_info = gethostbyname(hostname);
  156. if (!host_info) {
  157. DebugString(("SocketHandlerClass - gethostbyname failed! Error code %d\n", LAST_ERROR));
  158. }
  159. /*
  160. ** Clear out any old local addresses from the local address list.
  161. */
  162. while (LocalAddresses.Count()) {
  163. delete LocalAddresses[0];
  164. LocalAddresses.Delete(0);
  165. }
  166. /*
  167. ** Add all local IP addresses to the list. This list will be used to discard any packets that
  168. ** we send to ourselves by mistake.
  169. */
  170. unsigned long **addresses = (unsigned long**) (host_info->h_addr_list);
  171. for ( ;; ) {
  172. if ( !*addresses ) break;
  173. /*
  174. ** Read the next address
  175. */
  176. unsigned long address = **addresses++;
  177. DebugString(("SocketHandlerClass - Found local address: %d.%d.%d.%d\n", address & 0xff, (address & 0xff00) >> 8, (address & 0xff0000) >> 16, (address & 0xff000000) >> 24));
  178. /*
  179. ** Add it to the local address list.
  180. */
  181. unsigned char *a = new unsigned char [4];
  182. * ((unsigned long*) a) = address;
  183. LocalAddresses.Add (a);
  184. }
  185. /*
  186. ** Set linger options for the UDP socket. Don't think this is needed.
  187. */
  188. ling.l_onoff = 0; // linger off
  189. ling.l_linger = 0; // timeout in seconds (ie close now)
  190. setsockopt (Socket, SOL_SOCKET, SO_LINGER, (LPSTR)&ling, sizeof(ling));
  191. /*
  192. ** Specify the size of the receive buffer.
  193. */
  194. int err = setsockopt(Socket, SOL_SOCKET, SO_RCVBUF, (char*)&socket_receive_buffer_size, 4);
  195. if (err == INVALID_SOCKET) {
  196. DebugString(("SocketHandlerClass - Failed to set socket option SO_RCVBUF - error code %d.\n", LAST_ERROR));
  197. fw_assert ( err != INVALID_SOCKET);
  198. } else {
  199. DebugString(("SocketHandlerClass - Socket option SO_RCVBUF set OK\n"));
  200. }
  201. /*
  202. ** Specify the size of the send buffer.
  203. */
  204. err = setsockopt ( Socket, SOL_SOCKET, SO_SNDBUF, (char*)&socket_transmit_buffer_size, 4);
  205. if ( err == INVALID_SOCKET ) {
  206. DebugString(("SocketHandlerClass - Failed to set socket option SO_SNDBUF - error code %d.\n", LAST_ERROR));
  207. fw_assert ( err != INVALID_SOCKET );
  208. } else {
  209. DebugString(("SocketHandlerClass - Socket option SO_SNDBUF set OK\n"));
  210. }
  211. /*
  212. ** Set the blocking mode of the socket to non-blocking.
  213. */
  214. unsigned long nonblocking = true;
  215. err = ioctlsocket(Socket, FIONBIO, &nonblocking);
  216. if (err) {
  217. DebugString(("SocketHandlerClass - Failed to set socket to non-blocking - error code %d.\n", LAST_ERROR));
  218. }
  219. DebugString(("SocketHandlerClass - UDP Socket init complete\n"));
  220. return (true);
  221. }
  222. /***********************************************************************************************
  223. * SocketHandlerClass::Close -- Closes the socket if it's open. Shuts down the class. *
  224. * *
  225. * *
  226. * *
  227. * INPUT: Nothing *
  228. * *
  229. * OUTPUT: Nothing *
  230. * *
  231. * WARNINGS: None *
  232. * *
  233. * HISTORY: *
  234. * 2/24/00 12:43PM ST : Created *
  235. *=============================================================================================*/
  236. void SocketHandlerClass::Close(void)
  237. {
  238. /*
  239. ** Clear out any old local addresses from the local address list.
  240. */
  241. while (LocalAddresses.Count()) {
  242. delete LocalAddresses[0];
  243. LocalAddresses.Delete(0);
  244. }
  245. if (Socket != INVALID_SOCKET) {
  246. DebugString(("SocketHandlerClass - Closing socket %d bound to port %d\n", Socket, IncomingPort));
  247. if (closesocket(Socket) != 0) {
  248. DebugString(("SocketHandlerClass - closesocket failed with error code %d\n", LAST_ERROR));
  249. }
  250. Socket = INVALID_SOCKET;
  251. Service_Never();
  252. }
  253. }
  254. /***********************************************************************************************
  255. * SocketHandlerClass::Discard_In_Buffers -- Discard any packets in our incoming buffers *
  256. * *
  257. * *
  258. * *
  259. * INPUT: Nothing *
  260. * *
  261. * OUTPUT: Nothing *
  262. * *
  263. * WARNINGS: None *
  264. * *
  265. * HISTORY: *
  266. * 3/1/00 11:52AM ST : Created *
  267. *=============================================================================================*/
  268. void SocketHandlerClass::Discard_In_Buffers(void)
  269. {
  270. WinsockBufferType *packet;
  271. while (InBuffers.Count()) {
  272. packet = InBuffers[0];
  273. if (packet->IsAllocated) {
  274. delete packet;
  275. } else {
  276. packet->InUse = false;
  277. InBuffersUsed--;
  278. }
  279. InBuffers.Delete(0);
  280. }
  281. InBuffersUsed = 0;
  282. InBufferArrayPos = 0;
  283. }
  284. /***********************************************************************************************
  285. * SocketHandlerClass::Discard_Out_Buffers -- Discard any packets in our outgoing buffers *
  286. * *
  287. * *
  288. * *
  289. * INPUT: Nothing *
  290. * *
  291. * OUTPUT: Nothing *
  292. * *
  293. * WARNINGS: None *
  294. * *
  295. * HISTORY: *
  296. * 3/1/00 11:51AM ST : Created *
  297. *=============================================================================================*/
  298. void SocketHandlerClass::Discard_Out_Buffers(void)
  299. {
  300. WinsockBufferType *packet;
  301. while (OutBuffers.Count()) {
  302. packet = OutBuffers[0];
  303. if (packet->IsAllocated) {
  304. delete packet;
  305. } else {
  306. packet->InUse = false;
  307. OutBuffersUsed--;
  308. }
  309. OutBuffers.Delete(0);
  310. }
  311. OutBuffersUsed = 0;
  312. OutBufferArrayPos = 0;
  313. }
  314. /***********************************************************************************************
  315. * SocketHandlerClass::Clear_Socket_Error -- Clear any outstanding erros on the socket *
  316. * *
  317. * *
  318. * *
  319. * INPUT: Nothing *
  320. * *
  321. * OUTPUT: Nothing *
  322. * *
  323. * WARNINGS: None *
  324. * *
  325. * HISTORY: *
  326. * 3/1/00 11:51AM ST : Created *
  327. *=============================================================================================*/
  328. void SocketHandlerClass::Clear_Socket_Error(void)
  329. {
  330. unsigned long error_code;
  331. int length = 4;
  332. if (Socket != INVALID_SOCKET) {
  333. getsockopt (Socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);
  334. error_code = 0;
  335. setsockopt (Socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, length);
  336. }
  337. }
  338. /***********************************************************************************************
  339. * SocketHandlerClass::Write -- Add packet into the outgoing queue *
  340. * *
  341. * *
  342. * *
  343. * INPUT: ptr to buffer containing data to send *
  344. * length of data to send *
  345. * address to send data to. *
  346. * *
  347. * OUTPUT: Nothing *
  348. * *
  349. * *
  350. * HISTORY: *
  351. * 3/1/00 11:51AM ST : Created *
  352. *=============================================================================================*/
  353. void SocketHandlerClass::Write(void *buffer, int buffer_len, void *address, unsigned short port)
  354. {
  355. /*
  356. ** Create a temporary holding area for the packet.
  357. */
  358. WinsockBufferType *packet = (WinsockBufferType*) Get_New_Out_Buffer();
  359. fw_assert (packet != NULL);
  360. /*
  361. ** Copy the packet into the holding buffer.
  362. */
  363. memcpy (packet->Buffer, buffer, buffer_len);
  364. packet->BufferLen = buffer_len;
  365. packet->IsBroadcast = false;
  366. memcpy (packet->Address, address, 4);
  367. packet->Port = port;
  368. Build_Packet_CRC(packet);
  369. /*
  370. ** Add it to our out list.
  371. */
  372. OutBuffers.Add(packet);
  373. /*
  374. ** Send it now if possible.
  375. */
  376. Service();
  377. }
  378. /***********************************************************************************************
  379. * SocketHandlerClass::Read -- Get the next pending incoming packet *
  380. * *
  381. * *
  382. * *
  383. * INPUT: ptr to buffer to receive input *
  384. * length of buffer *
  385. * ptr to address to fill with address that packet was sent from *
  386. * ptr to address of port number to return *
  387. * packet number to read *
  388. * *
  389. * OUTPUT: number of bytes transfered to buffer *
  390. * *
  391. * WARNINGS: *
  392. * None. *
  393. * *
  394. * HISTORY: *
  395. * 3/8/00 1:12PM ST : Created *
  396. *=============================================================================================*/
  397. int SocketHandlerClass::Read(void *buffer, int buffer_len, void *address, unsigned short *port, int packetnum)
  398. {
  399. /*
  400. ** Call the Service function in case there are any outstanding unqueued packets.
  401. */
  402. Service();
  403. /*
  404. ** If there are no available packets then return 0
  405. */
  406. if (InBuffers.Count() == 0) return (0);
  407. #ifdef SIM_BAD_CONNECTION
  408. bool found = false;
  409. for (int b=0 ; b<InBuffers.Count() ; b++) {
  410. if (InBuffers[b]->Lag == 0) {
  411. packetnum = b;
  412. found = true;
  413. break;
  414. }
  415. }
  416. if (!found) {
  417. return (0);
  418. }
  419. #endif //_SIM_BAD_CONNECTION
  420. /*
  421. ** If the packet number is out of range then return 0.
  422. */
  423. if (packetnum >= InBuffers.Count()) {
  424. return(0);
  425. }
  426. WinsockBufferType *packet = InBuffers[packetnum];
  427. fw_assert(packet != NULL);
  428. if (packet == NULL) {
  429. return(0);
  430. }
  431. fw_assert(packet->InUse);
  432. fw_assert(buffer_len >= packet->BufferLen);
  433. /*
  434. ** Copy the data and the address it came from into the supplied buffers.
  435. */
  436. int bytes = min(packet->BufferLen, (int)sizeof(packet->Buffer));
  437. bytes = min(bytes, buffer_len);
  438. memcpy(buffer, packet->Buffer, bytes);
  439. memcpy(address, packet->Address, sizeof (packet->Address));
  440. if (port) {
  441. *port = packet->Port;
  442. }
  443. /*
  444. ** Delete the temporary storage for the packet now that it is being passed to the game.
  445. */
  446. InBuffers.Delete(packetnum);
  447. if (packet->IsAllocated) {
  448. delete packet;
  449. }else{
  450. packet->InUse = false;
  451. InBuffersUsed--;
  452. }
  453. DebugString(("SocketHandlerClass - SocketHandlerClass::Read - Returning %d bytes. %d InBuffers left\n", bytes, InBuffers.Count()));
  454. return (bytes);
  455. }
  456. /***********************************************************************************************
  457. * SocketHandlerClass::Peek -- Get a copy of the specified packet *
  458. * *
  459. * *
  460. * *
  461. * INPUT: ptr to buffer to receive input *
  462. * length of buffer *
  463. * ptr to address to fill with address that packet was sent from *
  464. * ptr to address of port number to return *
  465. * packet number to read *
  466. * *
  467. * OUTPUT: number of bytes transfered to buffer *
  468. * *
  469. * WARNINGS: *
  470. * None. *
  471. * *
  472. * HISTORY: *
  473. * 3/8/00 1:12PM ST : Created *
  474. *=============================================================================================*/
  475. int SocketHandlerClass::Peek(void *buffer, int buffer_len, void *address, unsigned short *port, int packetnum)
  476. {
  477. /*
  478. ** Call the Service function in case there are any outstanding unqueued packets.
  479. */
  480. Service();
  481. /*
  482. ** If there are no available packets then return 0
  483. */
  484. if (InBuffers.Count() == 0) return (0);
  485. /*
  486. ** If the packet number is out of range then return 0.
  487. */
  488. if (packetnum >= InBuffers.Count()) {
  489. return(0);
  490. }
  491. WinsockBufferType *packet = InBuffers[packetnum];
  492. fw_assert(packet != NULL);
  493. if (packet == NULL) {
  494. return(0);
  495. }
  496. fw_assert(packet->InUse);
  497. fw_assert(buffer_len >= packet->BufferLen);
  498. /*
  499. ** Copy the data and the address it came from into the supplied buffers.
  500. */
  501. int bytes = min(packet->BufferLen, (int)sizeof(packet->Buffer));
  502. bytes = min(bytes, buffer_len);
  503. memcpy(buffer, packet->Buffer, bytes);
  504. memcpy(address, packet->Address, sizeof (packet->Address));
  505. if (port) {
  506. *port = packet->Port;
  507. }
  508. DebugString(("SocketHandlerClass - SocketHandlerClass::Peek - Returning packet %d of %d bytes. %d InBuffers left\n", packetnum, bytes, InBuffers.Count()));
  509. return (bytes);
  510. }
  511. /***********************************************************************************************
  512. * SocketHandlerClass::Build_Packet_CRC -- Create a CRC value for a packet. *
  513. * *
  514. * *
  515. * *
  516. * INPUT: ptr to packet *
  517. * *
  518. * OUTPUT: Nothing *
  519. * *
  520. * WARNINGS: None *
  521. * *
  522. * HISTORY: *
  523. * 10/5/99 1:26PM ST : Created *
  524. *=============================================================================================*/
  525. void SocketHandlerClass::Build_Packet_CRC(WinsockBufferType *packet)
  526. {
  527. fw_assert (packet->InUse);
  528. fw_assert (packet->BufferLen);
  529. packet->CRC = 0;
  530. unsigned long *crc_ptr = &(packet->CRC);
  531. unsigned long *packetptr = (unsigned long*) &(packet->Buffer[0]);
  532. for (int i=0 ; i<packet->BufferLen/4 ; i++) {
  533. Add_CRC (crc_ptr, *packetptr++);
  534. }
  535. int leftover = packet->BufferLen & 3;
  536. if (leftover) {
  537. unsigned long val = *packetptr;
  538. val = val & (0xffffffff >> ((4-leftover) << 3));
  539. Add_CRC (crc_ptr, val);
  540. }
  541. }
  542. /***********************************************************************************************
  543. * WIC::Passes_CRC_Check -- Checks the CRC for a packet *
  544. * *
  545. * *
  546. * *
  547. * INPUT: ptr to packet *
  548. * *
  549. * OUTPUT: true if packet passes CRC check *
  550. * *
  551. * WARNINGS: None *
  552. * *
  553. * HISTORY: *
  554. * 10/5/99 1:26PM ST : Created *
  555. *=============================================================================================*/
  556. bool SocketHandlerClass::Passes_CRC_Check(WinsockBufferType *packet)
  557. {
  558. fw_assert (packet->InUse);
  559. fw_assert (packet->BufferLen < 768);
  560. if (packet->BufferLen >= 768) {
  561. return (false);
  562. }
  563. unsigned long crc = 0;
  564. unsigned long *crc_ptr = &crc;
  565. unsigned long *packetptr = (unsigned long*) &(packet->Buffer[0]);
  566. for (int i=0 ; i<packet->BufferLen/4 ; i++) {
  567. Add_CRC (crc_ptr, *packetptr++);
  568. }
  569. int leftover = packet->BufferLen & 3;
  570. if (leftover) {
  571. unsigned long val = *packetptr;
  572. val = val & (0xffffffff >> ((4-leftover) << 3));
  573. Add_CRC (crc_ptr, val);
  574. }
  575. if (crc == packet->CRC) {
  576. return (true);
  577. }
  578. fw_assert (crc == packet->CRC);
  579. DebugString(("SocketHandlerClass - Error in Winsock packet CRC\n"));
  580. return (false);
  581. }
  582. /***********************************************************************************************
  583. * SocketHandlerClass::Get_New_Out_Buffer -- Get a holding buffer for an outgoing packet *
  584. * *
  585. * *
  586. * *
  587. * INPUT: Nothing *
  588. * *
  589. * OUTPUT: ptr to out buffer *
  590. * *
  591. * WARNINGS: None *
  592. * *
  593. * HISTORY: *
  594. * 3/2/00 12:39PM ST : Created *
  595. *=============================================================================================*/
  596. void *SocketHandlerClass::Get_New_Out_Buffer(void)
  597. {
  598. WinsockBufferType *buffer = NULL;
  599. int pos;
  600. fw_assert (OutBuffersUsed <= MAX_STATIC_BUFFERS);
  601. /*
  602. ** If there are no more free buffers in the heap then allocate one.
  603. */
  604. if (OutBuffersUsed == MAX_STATIC_BUFFERS) {
  605. buffer = new WinsockBufferType;
  606. buffer->IsAllocated = true;
  607. buffer->InUse = true;
  608. }else{
  609. /*
  610. ** Find the next free buffer in the heap.
  611. */
  612. for (int i=0 ; i<MAX_STATIC_BUFFERS ; i++) {
  613. pos = OutBufferArrayPos++;
  614. if (OutBufferArrayPos > MAX_STATIC_BUFFERS-1) {
  615. OutBufferArrayPos = 0;
  616. }
  617. if (StaticOutBuffers[pos].InUse == false) {
  618. buffer = &StaticOutBuffers[pos];
  619. buffer->InUse = true;
  620. OutBuffersUsed++;
  621. break;
  622. }
  623. }
  624. }
  625. fw_assert (buffer != NULL);
  626. return (buffer);
  627. }
  628. /***********************************************************************************************
  629. * SocketHandlerClass::Get_New_In_Buffer -- Get a holding buffer for an incoming packet *
  630. * *
  631. * *
  632. * *
  633. * INPUT: Nothing *
  634. * *
  635. * OUTPUT: ptr to in buffer *
  636. * *
  637. * WARNINGS: None *
  638. * *
  639. * HISTORY: *
  640. * 3/2/00 12:39PM ST : Created *
  641. *=============================================================================================*/
  642. void *SocketHandlerClass::Get_New_In_Buffer(void)
  643. {
  644. WinsockBufferType *buffer = NULL;
  645. int pos;
  646. fw_assert (InBuffersUsed <= MAX_STATIC_BUFFERS);
  647. /*
  648. ** If there are no more free buffers in the heap then allocate one.
  649. */
  650. if (InBuffersUsed == MAX_STATIC_BUFFERS) {
  651. buffer = new WinsockBufferType;
  652. buffer->IsAllocated = true;
  653. buffer->InUse = true;
  654. }else{
  655. /*
  656. ** Find the next free buffer in the heap.
  657. */
  658. for (int i=0 ; i<MAX_STATIC_BUFFERS ; i++) {
  659. pos = InBufferArrayPos++;
  660. if (InBufferArrayPos > MAX_STATIC_BUFFERS-1) {
  661. InBufferArrayPos = 0;
  662. }
  663. if (StaticInBuffers[pos].InUse == false) {
  664. buffer = &StaticInBuffers[pos];
  665. buffer->InUse = true;
  666. InBuffersUsed++;
  667. break;
  668. }
  669. }
  670. }
  671. fw_assert (buffer != NULL);
  672. return (buffer);
  673. }
  674. /***********************************************************************************************
  675. * SocketHandlerClass::Service_All -- Service all socket handlers. *
  676. * *
  677. * *
  678. * *
  679. * INPUT: Nothing *
  680. * *
  681. * OUTPUT: Nothing *
  682. * *
  683. * WARNINGS: None *
  684. * *
  685. * HISTORY: *
  686. * 8/6/2001 2:08PM ST : Created *
  687. *=============================================================================================*/
  688. void SocketHandlerClass::Service_All(void)
  689. {
  690. for (int i=0 ; i<AllSocketHandlers.Count() ; i++) {
  691. AllSocketHandlers[i]->Service();
  692. }
  693. }
  694. /***********************************************************************************************
  695. * SocketHandlerClass::Service -- Service the connection - do all reads and writes *
  696. * *
  697. * *
  698. * *
  699. * INPUT: Nothing *
  700. * *
  701. * OUTPUT: Nothing *
  702. * *
  703. * WARNINGS: None *
  704. * *
  705. * HISTORY: *
  706. * 3/2/00 1:04PM ST : Created *
  707. *=============================================================================================*/
  708. void SocketHandlerClass::Service(void)
  709. {
  710. unsigned long bytes;
  711. struct sockaddr_in addr;
  712. int addr_len;
  713. WinsockBufferType *packet;
  714. int result;
  715. unsigned long timeout_check = TIMEGETTIME();
  716. int times = 0;
  717. if (!CanService) {
  718. return;
  719. }
  720. for (;;) {
  721. /*
  722. ** Some bail out code, just in case things get stuck.
  723. */
  724. if (times > 5 && (TIMEGETTIME() - timeout_check) > (TIMER_SECOND*5)) {
  725. break;
  726. }
  727. times++;
  728. Sleep(0);
  729. /*
  730. **
  731. ** First, check to see if there is any data waiting to be read.
  732. **
  733. **
  734. **
  735. */
  736. result = ioctlsocket(Socket, FIONREAD, &bytes);
  737. /*
  738. ** Result of 0 is success.
  739. */
  740. if (result != 0) {
  741. DebugString(("ioctlsocket returned error code %d\n", LAST_ERROR));
  742. break;
  743. } else {
  744. /*
  745. ** If there is outstanding data, 'bytes' will contain the size of the next queued datagram.
  746. */
  747. if (bytes == 0) {
  748. break;
  749. } else {
  750. /*
  751. ** Call recvfrom function to get the outstanding packet.
  752. */
  753. addr_len = sizeof(addr);
  754. result = recvfrom(Socket, (char*)ReceiveBuffer, sizeof(ReceiveBuffer), 0, (LPSOCKADDR)&addr, &addr_len);
  755. /*
  756. ** See if we got an error.
  757. */
  758. if (result == SOCKET_ERROR) {
  759. DebugString(("SocketHandlerClass - recvfrom returned error code %d\n", LAST_ERROR));
  760. Clear_Socket_Error();
  761. break;
  762. } else {
  763. /*
  764. ** Possibly throw away packet if loss testing is enabled.
  765. */
  766. #ifdef PACKET_LOSS_PERCENTAGE
  767. fw_assert(RAND_MAX < 0x10000 * 100);
  768. int r = rand();
  769. if (((r*100) / RAND_MAX) < PACKET_LOSS_PERCENTAGE) {
  770. continue;
  771. }
  772. #endif //PACKET_LOSS_PERCENTAGE
  773. /*
  774. ** No error, result should be the requested number of bytes.
  775. ** Not so, it can be less if there are multiple packets waiting.
  776. */
  777. //fw_assert(result == (int)bytes);
  778. /*
  779. ** Create a new holding buffer to store this packet in.
  780. */
  781. packet = (WinsockBufferType*) Get_New_In_Buffer();
  782. fw_assert (packet != NULL);
  783. /*
  784. ** Store the packet into the holding buffer.
  785. ** result is the number of bytes read.
  786. */
  787. packet->BufferLen = result - sizeof(packet->CRC);
  788. packet->CRC = *((unsigned long*) (&ReceiveBuffer[0]));
  789. memcpy (packet->Buffer, ReceiveBuffer + sizeof(packet->CRC), packet->BufferLen);
  790. /*
  791. ** Make sure the CRC looks right.
  792. */
  793. if (!Passes_CRC_Check(packet)) {
  794. /*
  795. ** Bad CRC, throw away the packet.
  796. */
  797. DebugString(("SocketHandlerClass - Throwing away malformed packet\n"));
  798. if (packet->IsAllocated) {
  799. delete packet;
  800. }else{
  801. packet->InUse = false;
  802. OutBuffersUsed--;
  803. }
  804. } else {
  805. /*
  806. ** Copy the address data into the holding buffer address area.
  807. */
  808. memset (packet->Address, 0, sizeof (packet->Address));
  809. memcpy (packet->Address, &addr.sin_addr.s_addr, 4);
  810. packet->Port = ntohs(addr.sin_port);
  811. DebugString(("SocketHandlerClass - recvfrom %s ; %d\n", IPAddressClass(packet->Address).As_String(), (unsigned int)((unsigned short)ntohs(addr.sin_port))));
  812. #ifdef SIM_BAD_CONNECTION
  813. /*
  814. ** Add in any simulated lag.
  815. */
  816. int lag = Sim_Random_Pick(MINIMUM_LAG, MAXIMUM_LAG);
  817. packet->Lag = (lag * TIMER_SECOND) / 1000;
  818. #endif //SIM_BAD_CONNECTION
  819. /*
  820. ** Add the holding buffer to the packet list.
  821. */
  822. InBuffers.Add (packet);
  823. DebugString(("SocketHandlerClass - InBuffers.Count() == %d\n", InBuffers.Count()));
  824. }
  825. }
  826. }
  827. }
  828. }
  829. //DebugString(("SocketHandlerClass - SocketHandler service\n"));
  830. timeout_check = TIMEGETTIME();
  831. times = 0;
  832. /*
  833. **
  834. ** Send any packets in the outgoing queue.
  835. **
  836. **
  837. **
  838. */
  839. while (OutBuffers.Count()) {
  840. /*
  841. ** Some bail out code, just in case things get stuck.
  842. */
  843. if (times > 5 && (TIMEGETTIME() - timeout_check) > (TIMER_SECOND*5)) {
  844. break;
  845. }
  846. times++;
  847. Sleep(0);
  848. /*
  849. ** Get a pointer to the first packet.
  850. */
  851. packet = OutBuffers[0];
  852. fw_assert (packet->InUse);
  853. /*
  854. ** Set up the address structure of the outgoing packet
  855. */
  856. addr.sin_family = AF_INET;
  857. if (packet->Port == 0) {
  858. addr.sin_port = (unsigned short) htons((unsigned short)OutgoingPort);
  859. } else {
  860. addr.sin_port = htons(packet->Port);
  861. }
  862. memcpy (&addr.sin_addr.s_addr, packet->Address, 4);
  863. DebugString(("SocketHandlerClass - sendto %s ; %d\n", IPAddressClass(packet->Address).As_String(), (unsigned int)((unsigned short)ntohs(addr.sin_port))));
  864. /*
  865. ** Send it.
  866. */
  867. result = sendto(Socket, ((char const *)packet->Buffer) - sizeof(packet->CRC), packet->BufferLen + sizeof(packet->CRC), 0, (LPSOCKADDR)&addr, sizeof (addr));
  868. if (result == SOCKET_ERROR){
  869. if (LAST_ERROR != WSAEWOULDBLOCK) {
  870. DebugString(("SocketHandlerClass - sendto returned error code %d\n", LAST_ERROR));
  871. Clear_Socket_Error();
  872. } else {
  873. /*
  874. ** No more room for outgoing packets.
  875. */
  876. DebugString(("SocketHandlerClass - sendto returned WSAEWOULDBLOCK\n"));
  877. Sleep(0);
  878. }
  879. break;
  880. }
  881. /*
  882. ** Delete the sent packet.
  883. */
  884. OutBuffers.Delete(0);
  885. if (packet->IsAllocated) {
  886. delete packet;
  887. }else{
  888. packet->InUse = false;
  889. OutBuffersUsed--;
  890. }
  891. }
  892. }
  893. /***********************************************************************************************
  894. * Add_CRC -- Adds a value to a CRC *
  895. * *
  896. * *
  897. * INPUT: crc ptr to crc *
  898. * val value to add *
  899. * *
  900. * OUTPUT: Nothing *
  901. * *
  902. * WARNINGS: None *
  903. * *
  904. * HISTORY: *
  905. * 05/09/1995 BRR : Created *
  906. *=============================================================================================*/
  907. void SocketHandlerClass::Add_CRC(unsigned long *crc, unsigned long val)
  908. {
  909. int hibit;
  910. if ((*crc) & 0x80000000) {
  911. hibit = 1;
  912. } else {
  913. hibit = 0;
  914. }
  915. (*crc) <<= 1;
  916. (*crc) += val;
  917. (*crc) += hibit;
  918. }