TCPIP.CPP 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. /*
  2. ** Command & Conquer Red Alert(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 - Red Alert *
  23. * *
  24. * File Name : TCPIP.CPP *
  25. * *
  26. * Programmer : Steve Tall *
  27. * *
  28. * Start Date : March 11th, 1996 *
  29. * *
  30. * Last Update : March 20th, 1996 [ST] *
  31. * *
  32. *-------------------------------------------------------------------------*
  33. * Overview: *
  34. * *
  35. * Member functions of the TcpipManagerClass which provides the Winsock *
  36. * interface for C&C *
  37. * *
  38. * *
  39. *-------------------------------------------------------------------------*
  40. * Functions: *
  41. * *
  42. * TMC::TcpipManagerClass -- constructor for the TcpipManagerClass *
  43. * TMC::~TcpipManagerClass -- destructor for the TcpipManagerClass *
  44. * TMC::Close -- restores any currently in use Winsock resources *
  45. * TMC::Init -- Initialised Winsock for use. *
  46. * TMC::Start_Server -- Initialise connection and start listening. *
  47. * TMC::Read -- read any pending input from the stream socket *
  48. * TMC::Write -- Send data via the Winsock streaming socket *
  49. * TMC::Add_Client -- A client has requested to connect. *
  50. * TMC::Message_Handler -- Message handler for Winsock. *
  51. * TMC::Set_Host_Address -- Set the address of the host *
  52. * TMC::Start_Client -- Start trying to connect to a game host *
  53. * TMC::Close_Socket -- Close an opened Winsock socket. *
  54. * TMC::Copy_To_In_Buffer -- copy data from our winsock buffer *
  55. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  56. #ifdef WIN32
  57. #include "function.h"
  58. #include "tcpip.h"
  59. /*
  60. ** Nasty globals
  61. */
  62. #ifndef WOLAPI_INTEGRATION
  63. BOOL Server; //Is this player acting as client or server
  64. #endif
  65. TcpipManagerClass Winsock; //The object for interfacing with Winsock
  66. /***********************************************************************************************
  67. * TMC::TcpipManagerClass -- constructor for the TcpipManagerClass *
  68. * *
  69. * *
  70. * *
  71. * INPUT: Nothing *
  72. * *
  73. * OUTPUT: Nothing *
  74. * *
  75. * WARNINGS: None *
  76. * *
  77. * HISTORY: *
  78. * 3/20/96 2:51PM ST : Created *
  79. *=============================================================================================*/
  80. TcpipManagerClass::TcpipManagerClass(void)
  81. {
  82. WinsockInitialised = FALSE;
  83. Connected = FALSE;
  84. UseUDP = TRUE;
  85. SocketReceiveBuffer = 4096;
  86. SocketSendBuffer = 4096;
  87. }
  88. /***********************************************************************************************
  89. * TMC::~TcpipManagerClass -- destructor for the TcpipManagerClass *
  90. * *
  91. * *
  92. * *
  93. * INPUT: Nothing *
  94. * *
  95. * OUTPUT: Nothing *
  96. * *
  97. * WARNINGS: None *
  98. * *
  99. * HISTORY: *
  100. * 3/20/96 2:52PM ST : Created *
  101. *=============================================================================================*/
  102. TcpipManagerClass::~TcpipManagerClass(void)
  103. {
  104. Close();
  105. }
  106. /***********************************************************************************************
  107. * TMC::Close -- restores any currently in use Winsock resources *
  108. * *
  109. * *
  110. * *
  111. * INPUT: Nothing *
  112. * *
  113. * OUTPUT: Nothing *
  114. * *
  115. * WARNINGS: None *
  116. * *
  117. * HISTORY: *
  118. * 3/20/96 2:52PM ST : Created *
  119. *=============================================================================================*/
  120. void TcpipManagerClass::Close(void)
  121. {
  122. /*
  123. ** If we never initialised the class in the first place then just return
  124. */
  125. if (!WinsockInitialised) return;
  126. /*
  127. ** Cancel any outstaning asyncronous events
  128. */
  129. if (Async){
  130. WSACancelAsyncRequest(Async);
  131. }
  132. /*
  133. ** Close any open sockets
  134. */
  135. if (ConnectSocket != INVALID_SOCKET){
  136. Close_Socket(ConnectSocket);
  137. ConnectSocket = INVALID_SOCKET;
  138. }
  139. if (ListenSocket != INVALID_SOCKET){
  140. Close_Socket(ListenSocket);
  141. ListenSocket = INVALID_SOCKET;
  142. }
  143. if (UDPSocket != INVALID_SOCKET){
  144. Close_Socket(ListenSocket);
  145. UDPSocket = INVALID_SOCKET;
  146. }
  147. /*
  148. ** Call the Winsock cleanup function to say we are finished using Winsock
  149. */
  150. WSACleanup();
  151. WinsockInitialised = FALSE;
  152. Connected = FALSE;
  153. }
  154. /***********************************************************************************************
  155. * TMC::Init -- Initialised Winsock for use. *
  156. * *
  157. * *
  158. * *
  159. * INPUT: Nothing *
  160. * *
  161. * OUTPUT: TRUE if Winsock is available and was initialised *
  162. * *
  163. * WARNINGS: None *
  164. * *
  165. * HISTORY: *
  166. * 3/20/96 2:54PM ST : Created *
  167. *=============================================================================================*/
  168. BOOL TcpipManagerClass::Init(void)
  169. {
  170. short version;
  171. int rc;
  172. /*
  173. ** Just return true if we are already set up
  174. */
  175. if (WinsockInitialised) return (TRUE);
  176. /*
  177. ** Initialise sockets to null
  178. */
  179. ListenSocket = INVALID_SOCKET;
  180. ConnectSocket =INVALID_SOCKET;
  181. UDPSocket = INVALID_SOCKET;
  182. /*
  183. ** Start WinSock, and fill in our WinSockData
  184. */
  185. version = (WINSOCK_MINOR_VER << 8) | WINSOCK_MAJOR_VER;
  186. rc = WSAStartup(version, &WinsockInfo);
  187. if (rc != 0) {
  188. return (FALSE);
  189. }
  190. /*
  191. ** Check the Winsock version number
  192. */
  193. if ((WinsockInfo.wVersion & 0x00ff) != (version & 0x00ff) ||
  194. (WinsockInfo.wVersion >> 8) != (version >> 8)) {
  195. return (FALSE);
  196. }
  197. /*
  198. ** Everything is OK so return success
  199. */
  200. WinsockInitialised = TRUE;
  201. return (TRUE);
  202. }
  203. /***********************************************************************************************
  204. * TMC::Start_Server -- initialise out connection as the server. Start listening for clients. *
  205. * *
  206. * *
  207. * *
  208. * INPUT: Nothing *
  209. * *
  210. * OUTPUT: Nothing *
  211. * *
  212. * WARNINGS: None *
  213. * *
  214. * HISTORY: *
  215. * 3/20/96 2:56PM ST : Created *
  216. *=============================================================================================*/
  217. void TcpipManagerClass::Start_Server(void)
  218. {
  219. int i;
  220. //struct sockaddr_in addr;
  221. Start_Client();
  222. /*
  223. ** Set up the incoming and outgoing data buffers head and tail pointers
  224. */
  225. TXBufferHead = 0;
  226. TXBufferTail = 0;
  227. RXBufferHead = 0;
  228. RXBufferTail = 0;
  229. for (i=0 ; i<WS_NUM_TX_BUFFERS ; i++){
  230. TransmitBuffers[i].InUse = false;
  231. }
  232. for (i=0 ; i<WS_NUM_RX_BUFFERS ; i++){
  233. ReceiveBuffers[i].InUse = false;
  234. }
  235. /*
  236. ** Flag that we are the server side not the client
  237. */
  238. IsServer = TRUE;
  239. UseUDP = TRUE;
  240. ConnectStatus = CONNECTING;
  241. }
  242. /***********************************************************************************************
  243. * TMC::Read -- read any pending input from the stream socket *
  244. * *
  245. * *
  246. * *
  247. * INPUT: ptr to buffer to receive input *
  248. * length of buffer *
  249. * *
  250. * OUTPUT: number of bytes transfered to buffer *
  251. * *
  252. * WARNINGS: None *
  253. * *
  254. * HISTORY: *
  255. * 3/20/96 2:58PM ST : Created *
  256. *=============================================================================================*/
  257. int TcpipManagerClass::Read(void *buffer, int buffer_len)
  258. {
  259. int bytes_copied = 0;
  260. char *dest_buf = (char*) buffer;
  261. /*
  262. ** Make sure the message loop gets called because all the Winsock notifications
  263. ** are done via messages.
  264. */
  265. Keyboard->Check();
  266. /*
  267. ** Copy any outstanding incoming data to the buffer provided
  268. */
  269. if (ReceiveBuffers[RXBufferTail].InUse){
  270. memcpy (buffer, ReceiveBuffers[RXBufferTail].Buffer,
  271. MIN(ReceiveBuffers[RXBufferTail].DataLength, buffer_len));
  272. ReceiveBuffers[RXBufferTail].InUse = false;
  273. bytes_copied = MIN(ReceiveBuffers[RXBufferTail++].DataLength, buffer_len);
  274. RXBufferTail &= WS_NUM_RX_BUFFERS-1;
  275. }
  276. return (bytes_copied);
  277. }
  278. /***********************************************************************************************
  279. * TMC::Write -- Send data via the Winsock UDP socket *
  280. * *
  281. * *
  282. * *
  283. * INPUT: ptr to buffer containing data to send *
  284. * length of data to send *
  285. * *
  286. * OUTPUT: Nothing *
  287. * *
  288. * WARNINGS: None *
  289. * *
  290. * HISTORY: *
  291. * 3/20/96 3:00PM ST : Created *
  292. *=============================================================================================*/
  293. void TcpipManagerClass::Write(void *buffer, int buffer_len)
  294. {
  295. char *source_buf = (char*) buffer;
  296. /*
  297. ** Copy the data to one of the classes internal buffers
  298. */
  299. if (!TransmitBuffers[TXBufferHead].InUse){
  300. memcpy (TransmitBuffers[TXBufferHead].Buffer,
  301. buffer,
  302. MIN (buffer_len, WS_INTERNET_BUFFER_LEN));
  303. TransmitBuffers[TXBufferHead].InUse = true;
  304. TransmitBuffers[TXBufferHead++].DataLength = MIN(buffer_len, WS_INTERNET_BUFFER_LEN);
  305. TXBufferHead &= WS_NUM_TX_BUFFERS-1;
  306. }
  307. /*
  308. ** Send a message to ourselves to start off the event
  309. */
  310. if (UseUDP){
  311. SendMessage(MainWindow, WM_UDPASYNCEVENT, 0, (LONG)FD_WRITE);
  312. }else{
  313. SendMessage(MainWindow, WM_ASYNCEVENT, 0, (LONG)FD_WRITE);
  314. }
  315. /*
  316. ** Make sure the message loop gets called because all the Winsock notifications
  317. ** are done via messages.
  318. */
  319. Keyboard->Check();
  320. }
  321. /***********************************************************************************************
  322. * TMC::Add_Client -- a client has requested to connect. Make the connection *
  323. * *
  324. * *
  325. * *
  326. * INPUT: Nothing *
  327. * *
  328. * OUTPUT: TRUE if client was successfully connected *
  329. * *
  330. * WARNINGS: None *
  331. * *
  332. * HISTORY: *
  333. * 3/20/96 3:02PM ST : Created *
  334. *=============================================================================================*/
  335. BOOL TcpipManagerClass::Add_Client(void)
  336. {
  337. struct sockaddr_in addr;
  338. int addrsize;
  339. bool delay = TRUE;
  340. /*
  341. ** Accept the connection. If there is an error then dont do anything else
  342. */
  343. addrsize = sizeof(addr);
  344. ConnectSocket = accept (ListenSocket, (LPSOCKADDR)&addr, &addrsize);
  345. if (ConnectSocket == INVALID_SOCKET) {
  346. //Show_Error("accept", WSAGetLastError());
  347. return(FALSE);
  348. }
  349. /*
  350. ** Set options for this socket
  351. */
  352. setsockopt (ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&delay, 4);
  353. setsockopt (ConnectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);
  354. setsockopt (ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);
  355. /*
  356. ** Save the clients address
  357. */
  358. memcpy(&ClientIPAddress, &addr.sin_addr.s_addr,4);
  359. memcpy(&UDPIPAddress, &addr.sin_addr.s_addr,4);
  360. /*
  361. ** Initiate an asynchronous host lookup by address. Our window will receive notification
  362. ** when this is complete or when it times out.
  363. */
  364. Async = WSAAsyncGetHostByAddr (MainWindow, WM_HOSTBYADDRESS,
  365. (char const *)&addr.sin_addr, 4, PF_INET, &HostBuff[0],
  366. MAXGETHOSTSTRUCT);
  367. /*
  368. ** Enable asynchronous events on this socket
  369. */
  370. if (WSAAsyncSelect (ConnectSocket, MainWindow, WM_ASYNCEVENT,
  371. FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR){
  372. WSACancelAsyncRequest(Async);
  373. Close_Socket (ConnectSocket);
  374. return(FALSE);
  375. }
  376. /*
  377. ** Create our UDP socket
  378. */
  379. UDPSocket = socket(AF_INET, SOCK_DGRAM, 0);
  380. if (UDPSocket == INVALID_SOCKET) {
  381. return (FALSE);
  382. }
  383. /*
  384. ** Bind our UDP socket to our UDP port number
  385. */
  386. addr.sin_family = AF_INET;
  387. addr.sin_port = htons(PlanetWestwoodPortNumber);
  388. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  389. if (bind(UDPSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==
  390. SOCKET_ERROR) {
  391. Close_Socket(UDPSocket);
  392. ConnectStatus = NOT_CONNECTING;
  393. return(FALSE);
  394. }
  395. /*
  396. ** Set options for the UDP socket
  397. */
  398. setsockopt (UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);
  399. setsockopt (UDPSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);
  400. /*
  401. ** Enable asynchronous events on this socket
  402. */
  403. if (WSAAsyncSelect (UDPSocket, MainWindow, WM_UDPASYNCEVENT,
  404. FD_READ | FD_WRITE) == SOCKET_ERROR){
  405. WSACancelAsyncRequest(Async);
  406. Close_Socket (UDPSocket);
  407. Close_Socket (ConnectSocket);
  408. return(FALSE);
  409. }
  410. return (TRUE);
  411. }
  412. /***********************************************************************************************
  413. * TMC::Message_Handler -- Message handler function for Winsock related messages *
  414. * *
  415. * *
  416. * *
  417. * INPUT: Windows message handler stuff *
  418. * *
  419. * OUTPUT: Nothing *
  420. * *
  421. * WARNINGS: None *
  422. * *
  423. * HISTORY: *
  424. * 3/20/96 3:05PM ST : Created *
  425. *=============================================================================================*/
  426. void TcpipManagerClass::Message_Handler(HWND, UINT message, UINT , LONG lParam)
  427. {
  428. struct hostent *hentry;
  429. struct sockaddr_in addr;
  430. int event;
  431. int rc;
  432. int addr_len;
  433. switch (message){
  434. /*
  435. ** Handle the GetHostByAddress result
  436. */
  437. case WM_HOSTBYADDRESS:
  438. if (IsServer){
  439. /*
  440. ** We are the server
  441. */
  442. ConnectStatus = CONNECTING;
  443. if (WSAGETASYNCERROR(lParam)==0) {
  444. hentry = (struct hostent *)&HostBuff[0];
  445. strcpy (&ClientName[0], hentry->h_name);
  446. }
  447. Async = 0;
  448. return;
  449. }else{
  450. /*
  451. ** We are the client
  452. */
  453. ConnectStatus = CONTACTING_SERVER;
  454. if (WSAGETASYNCERROR(lParam)==0) {
  455. hentry = (struct hostent *)&HostBuff[0];
  456. strcpy (Server.Name, hentry->h_name);
  457. }
  458. else {
  459. Server.Name[0] = 0;
  460. }
  461. Async = 0;
  462. return;
  463. }
  464. /*
  465. ** Retrieve host by name: Start connecting now that we have the
  466. ** address.
  467. */
  468. case WM_HOSTBYNAME:
  469. if (WSAGETASYNCERROR(lParam)==0) {
  470. hentry = (struct hostent *)&HostBuff[0];
  471. memcpy (&(Server.Addr.s_addr), hentry->h_addr, 4);
  472. memcpy(&UDPIPAddress, hentry->h_addr, 4);
  473. strcpy (Server.DotAddr, inet_ntoa(Server.Addr));
  474. ConnectStatus = CONNECTED_OK;
  475. Connected = TRUE;
  476. }
  477. else {
  478. Server.Name[0] = 0;
  479. strcpy (Server.DotAddr, "????");
  480. ConnectStatus = SERVER_ADDRESS_LOOKUP_FAILED;
  481. }
  482. Async = 0;
  483. return;
  484. /*
  485. ** Connection is ready - accept the client
  486. */
  487. case WM_ACCEPT:
  488. rc = WSAGETSELECTERROR(lParam);
  489. if (rc != 0) {
  490. ConnectStatus = UNABLE_TO_ACCEPT_CLIENT;
  491. return;
  492. }
  493. if (Add_Client()) {
  494. ConnectStatus = CONNECTED_OK;
  495. Connected = TRUE;
  496. }
  497. else {
  498. ConnectStatus = UNABLE_TO_ACCEPT_CLIENT;
  499. }
  500. return;
  501. /*
  502. ** Handle UDP packet events
  503. */
  504. case WM_UDPASYNCEVENT:
  505. event = WSAGETSELECTEVENT(lParam);
  506. switch (event) {
  507. case FD_READ:
  508. rc = WSAGETSELECTERROR(lParam);
  509. if (rc != 0) {
  510. Clear_Socket_Error(UDPSocket);
  511. return;
  512. }
  513. addr_len = sizeof(addr);
  514. rc = recvfrom(UDPSocket, ReceiveBuffer, WS_RECEIVE_BUFFER_LEN, 0,
  515. (LPSOCKADDR)&addr, &addr_len);
  516. if (rc == SOCKET_ERROR) {
  517. Clear_Socket_Error(UDPSocket);
  518. return;
  519. }
  520. memcpy(&UDPIPAddress, &addr.sin_addr.s_addr, 4);
  521. Copy_To_In_Buffer(rc);
  522. return;
  523. case FD_WRITE:
  524. if (UseUDP){
  525. rc = WSAGETSELECTERROR(lParam);
  526. if (rc != 0) {
  527. Clear_Socket_Error(UDPSocket);
  528. return;
  529. }
  530. addr.sin_family = AF_INET;
  531. addr.sin_port = htons(PlanetWestwoodPortNumber);
  532. memcpy (&addr.sin_addr.s_addr, &UDPIPAddress, 4);
  533. /*
  534. ** Send as many bytes as there are in the buffer; if there's
  535. ** an error, just bail out. If we get a WOULDBLOCK error,
  536. ** WinSock will send us another message when the socket is
  537. ** available for another write.
  538. */
  539. while (TransmitBuffers[TXBufferTail].InUse){
  540. rc = sendto(UDPSocket,
  541. TransmitBuffers[TXBufferTail].Buffer,
  542. TransmitBuffers[TXBufferTail].DataLength,
  543. 0,
  544. (LPSOCKADDR)&addr,
  545. sizeof (addr));
  546. if (rc == SOCKET_ERROR){
  547. if (WSAGetLastError() != WSAEWOULDBLOCK) {
  548. Clear_Socket_Error(UDPSocket);
  549. }
  550. break;
  551. }
  552. TransmitBuffers[TXBufferTail++].InUse = false;
  553. TXBufferTail &= WS_NUM_TX_BUFFERS-1;
  554. }
  555. return;
  556. }
  557. }
  558. /*
  559. ** Handle the asynchronous event callbacks
  560. */
  561. case WM_ASYNCEVENT:
  562. event = WSAGETSELECTEVENT(lParam);
  563. switch (event) {
  564. /*
  565. ** FD_CLOSE: the client has gone away. Remove the client from our system.
  566. */
  567. case FD_CLOSE:
  568. rc = WSAGETSELECTERROR(lParam);
  569. if (rc != 0 && rc != WSAECONNRESET) {
  570. ConnectStatus = CONNECTION_LOST;
  571. return;
  572. }
  573. if (Async != 0) {
  574. WSACancelAsyncRequest(Async);
  575. }
  576. WSAAsyncSelect (ConnectSocket, MainWindow, WM_ASYNCEVENT, 0);
  577. Close_Socket (ConnectSocket);
  578. ConnectSocket = INVALID_SOCKET;
  579. //Connected = FALSE;
  580. ConnectStatus = CONNECTION_LOST;
  581. break;
  582. /*
  583. ** FD_CONNECT: A connection was made, or an error occurred.
  584. */
  585. case FD_CONNECT:
  586. rc = WSAGETSELECTERROR(lParam);
  587. if (rc != 0) {
  588. ConnectStatus = UNABLE_TO_CONNECT;
  589. return;
  590. }
  591. ConnectStatus = CONNECTED_OK;
  592. Connected = TRUE;
  593. return;
  594. }
  595. }
  596. }
  597. /***********************************************************************************************
  598. * TMC::Copy_To_In_Buffer -- copy data from our winsock buffer to our internal buffer *
  599. * *
  600. * *
  601. * *
  602. * INPUT: bytes to copy *
  603. * *
  604. * OUTPUT: Nothing *
  605. * *
  606. * WARNINGS: None *
  607. * *
  608. * HISTORY: *
  609. * 3/20/96 3:17PM ST : Created *
  610. *=============================================================================================*/
  611. void TcpipManagerClass::Copy_To_In_Buffer(int bytes)
  612. {
  613. if (!ReceiveBuffers[RXBufferHead].InUse){
  614. memcpy (ReceiveBuffers[RXBufferHead].Buffer, ReceiveBuffer, MIN(bytes, WS_INTERNET_BUFFER_LEN));
  615. ReceiveBuffers[RXBufferHead].InUse = true;
  616. ReceiveBuffers[RXBufferHead++].DataLength = MIN(bytes, WS_INTERNET_BUFFER_LEN);
  617. RXBufferHead &= WS_NUM_RX_BUFFERS-1;
  618. }
  619. }
  620. /***********************************************************************************************
  621. * TMC::Set_Host_Address -- Set the address of the host game we want to connect to *
  622. * *
  623. * *
  624. * *
  625. * INPUT: ptr to address string *
  626. * *
  627. * OUTPUT: Nothing *
  628. * *
  629. * WARNINGS: None *
  630. * *
  631. * HISTORY: *
  632. * 3/20/96 3:19PM ST : Created *
  633. *=============================================================================================*/
  634. void TcpipManagerClass::Set_Host_Address(char *address)
  635. {
  636. strcpy(HostAddress, address);
  637. }
  638. /***********************************************************************************************
  639. * TMC::Start_Client -- Start trying to connect to a game host *
  640. * *
  641. * *
  642. * *
  643. * INPUT: Nothing *
  644. * *
  645. * OUTPUT: Nothing *
  646. * *
  647. * WARNINGS: None *
  648. * *
  649. * HISTORY: *
  650. * 3/20/96 3:19PM ST : Created *
  651. *=============================================================================================*/
  652. void TcpipManagerClass::Start_Client(void)
  653. {
  654. struct sockaddr_in addr;
  655. bool delay = true;
  656. int i;
  657. addr.sin_family = AF_INET;
  658. addr.sin_port = 0;
  659. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  660. /*
  661. ** Set up the incoming and outgoing data buffers head and tail pointers
  662. */
  663. TXBufferHead = 0;
  664. TXBufferTail = 0;
  665. RXBufferHead = 0;
  666. RXBufferTail = 0;
  667. for (i=0 ; i<WS_NUM_TX_BUFFERS ; i++){
  668. TransmitBuffers[i].InUse = false;
  669. }
  670. for (i=0 ; i<WS_NUM_RX_BUFFERS ; i++){
  671. ReceiveBuffers[i].InUse = false;
  672. }
  673. Connected = FALSE;
  674. /*
  675. ** Flag that we are the client side not the server
  676. */
  677. IsServer = FALSE;
  678. UseUDP = TRUE;
  679. /*
  680. ** Create our UDP socket
  681. */
  682. UDPSocket = socket(AF_INET, SOCK_DGRAM, 0);
  683. if (UDPSocket == INVALID_SOCKET) {
  684. Close_Socket(ConnectSocket);
  685. ConnectStatus = NOT_CONNECTING;
  686. return;
  687. }
  688. /*
  689. ** Bind our UDP socket to our UDP port number
  690. */
  691. addr.sin_family = AF_INET;
  692. addr.sin_port = htons(PlanetWestwoodPortNumber);
  693. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  694. if (bind(UDPSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==
  695. SOCKET_ERROR) {
  696. Close_Socket(UDPSocket);
  697. Close_Socket(ConnectSocket);
  698. ConnectStatus = NOT_CONNECTING;
  699. return;
  700. }
  701. /*
  702. ** Set options for the UDP socket
  703. */
  704. setsockopt (UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);
  705. setsockopt (UDPSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);
  706. /*
  707. ** Enable asynchronous events on the UDP socket
  708. */
  709. if (WSAAsyncSelect (UDPSocket, MainWindow, WM_UDPASYNCEVENT,
  710. FD_READ | FD_WRITE) == SOCKET_ERROR){
  711. WSACancelAsyncRequest(Async);
  712. Close_Socket (UDPSocket);
  713. Close_Socket (ConnectSocket);
  714. ConnectStatus = NOT_CONNECTING;
  715. return;
  716. }
  717. /*
  718. ** If the name is not a dot-decimal ip address then do a nameserver lookup
  719. */
  720. Server.Addr.s_addr = inet_addr(PlanetWestwoodIPAddress);
  721. memcpy(&UDPIPAddress, &Server.Addr.s_addr, 4);
  722. if (Server.Addr.s_addr == INADDR_NONE){
  723. strcpy (Server.Name, PlanetWestwoodIPAddress);
  724. Async = WSAAsyncGetHostByName(MainWindow, WM_HOSTBYNAME,
  725. Server.Name, HostBuff, MAXGETHOSTSTRUCT);
  726. ConnectStatus = RESOLVING_HOST_ADDRESS;
  727. }else{
  728. ConnectStatus = CONNECTED_OK;
  729. Connected = TRUE;
  730. }
  731. }
  732. /***********************************************************************************************
  733. * TMC::Close_Socket -- Close an opened Winsock socket. *
  734. * *
  735. * *
  736. * *
  737. * INPUT: Socket to close *
  738. * *
  739. * OUTPUT: Nothing *
  740. * *
  741. * WARNINGS: None *
  742. * *
  743. * HISTORY: *
  744. * 3/20/96 3:24PM ST : Created *
  745. *=============================================================================================*/
  746. void TcpipManagerClass::Close_Socket(SOCKET s)
  747. {
  748. LINGER ling;
  749. ling.l_onoff = 0; // linger off
  750. ling.l_linger = 0; // timeout in seconds (ie close now)
  751. setsockopt(s, SOL_SOCKET, SO_LINGER, (LPSTR)&ling, sizeof(ling));
  752. closesocket (s);
  753. }
  754. void TcpipManagerClass::Set_Protocol_UDP(BOOL state)
  755. {
  756. UseUDP = state;
  757. }
  758. void TcpipManagerClass::Clear_Socket_Error(SOCKET socket)
  759. {
  760. unsigned long error_code;
  761. int length = 4;
  762. getsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);
  763. error_code = 0;
  764. setsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, length);
  765. }
  766. #endif //WIN32