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