CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

WSPROTO.CPP (31153B)


      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  ***              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               ***
     18  ***********************************************************************************************
     19  *                                                                                             *
     20  *                 Project Name : Command & Conquer                                            *
     21  *                                                                                             *
     22  *                     $Archive:: /Sun/WSProto.cpp                                            $*
     23  *                                                                                             *
     24  *                      $Author:: Joe_b                                                       $*
     25  *                                                                                             *
     26  *                     $Modtime:: 8/20/97 10:54a                                              $*
     27  *                                                                                             *
     28  *                    $Revision:: 5                                                           $*
     29  *                                                                                             *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  *                                                                                             *
     33  *  WSProto.CPP WinsockInterfaceClass to provide an interface to Winsock protocols             *
     34  *                                                                                             *
     35  *---------------------------------------------------------------------------------------------*
     36  *                                                                                             *
     37  * Functions:                                                                                  *
     38  *                                                                                             *
     39  * WIC::WinsockInterfaceClass -- constructor for the WinsockInterfaceClass                     *
     40  * WIC::~WinsockInterfaceClass -- destructor for the WinsockInterfaceClass                     *
     41  * WIC::Close -- Releases any currently in use Winsock resources.                              *
     42  * WIC::Close_Socket -- Close the communication socket if its open                             *
     43  * WIC::Start_Listening -- Enable callbacks for read/write events on our socket                *
     44  * WIC::Stop_Listening -- Disable the winsock event callback                                   *
     45  * WIC::Discard_In_Buffers -- Discard any packets in our incoming packet holding buffers       *
     46  * WIC::Discard_In_Buffers -- Discard any packets in our outgoing packet holding buffers       *
     47  * WIC::Init -- Initialised Winsock and this class for use.                                    *
     48  * WIC::Read -- read any pending input from the communications socket                          *
     49  * WIC::WriteTo -- Send data via the Winsock socket                                            *
     50  * WIC::Broadcast -- Send data via the Winsock socket                                          *
     51  * WIC::Clear_Socket_Error -- Clear any outstanding erros on the socket                        *
     52  * WIC::Set_Socket_Options -- Sets default socket options for Winsock buffer sizes             *
     53  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     54 
     55 #include	"function.h"
     56 #include	"WSProto.h"
     57 
     58 #include	<stdio.h>
     59 
     60 
     61 /***********************************************************************************************
     62  * WIC::WinsockInterfaceClass -- constructor for the WinsockInterfaceClass                     *
     63  *                                                                                             *
     64  *                                                                                             *
     65  *                                                                                             *
     66  * INPUT:    Nothing                                                                           *
     67  *                                                                                             *
     68  * OUTPUT:   Nothing                                                                           *
     69  *                                                                                             *
     70  * WARNINGS: None                                                                              *
     71  *                                                                                             *
     72  * HISTORY:                                                                                    *
     73  *    3/20/96 2:51PM ST : Created                                                              *
     74  *=============================================================================================*/
     75 WinsockInterfaceClass::WinsockInterfaceClass(void)
     76 {
     77 	WinsockInitialised = false;
     78 	ASync = INVALID_HANDLE_VALUE;
     79 	Socket = INVALID_SOCKET;
     80 }
     81 
     82 
     83 /***********************************************************************************************
     84  * WIC::~WinsockInterfaceClass -- destructor for the WinsockInterfaceClass                     *
     85  *                                                                                             *
     86  *                                                                                             *
     87  *                                                                                             *
     88  * INPUT:    Nothing                                                                           *
     89  *                                                                                             *
     90  * OUTPUT:   Nothing                                                                           *
     91  *                                                                                             *
     92  * WARNINGS: None                                                                              *
     93  *                                                                                             *
     94  * HISTORY:                                                                                    *
     95  *    3/20/96 2:52PM ST : Created                                                              *
     96  *=============================================================================================*/
     97 WinsockInterfaceClass::~WinsockInterfaceClass(void)
     98 {
     99 	Close();
    100 }
    101 
    102 
    103 /***********************************************************************************************
    104  * WIC::Close -- Releases any currently in use Winsock resources.                              *
    105  *                                                                                             *
    106  *                                                                                             *
    107  *                                                                                             *
    108  * INPUT:    Nothing                                                                           *
    109  *                                                                                             *
    110  * OUTPUT:   Nothing                                                                           *
    111  *                                                                                             *
    112  * WARNINGS: None                                                                              *
    113  *                                                                                             *
    114  * HISTORY:                                                                                    *
    115  *    3/20/96 2:52PM ST : Created                                                              *
    116  *=============================================================================================*/
    117 void WinsockInterfaceClass::Close(void)
    118 {
    119 	/*
    120 	** If we never initialised the class in the first place then just return
    121 	*/
    122 	if (!WinsockInitialised) return;
    123 
    124 	/*
    125 	** Cancel any outstaning asyncronous events
    126 	*/
    127 	Stop_Listening();
    128 
    129 	/*
    130 	** Close any open sockets
    131 	*/
    132 	Close_Socket();
    133 
    134 	/*
    135 	** Call the Winsock cleanup function to say we are finished using Winsock
    136 	*/
    137 	WSACleanup();
    138 
    139 	WinsockInitialised = false;
    140 }
    141 
    142 
    143 
    144 /***********************************************************************************************
    145  * WIC::Close_Socket -- Close the communication socket if its open                             *
    146  *                                                                                             *
    147  *                                                                                             *
    148  *                                                                                             *
    149  * INPUT:    Nothing                                                                           *
    150  *                                                                                             *
    151  * OUTPUT:   Nothing                                                                           *
    152  *                                                                                             *
    153  * WARNINGS: None                                                                              *
    154  *                                                                                             *
    155  * HISTORY:                                                                                    *
    156  *    8/5/97 11:53AM ST : Created                                                              *
    157  *=============================================================================================*/
    158 void WinsockInterfaceClass::Close_Socket (void)
    159 {
    160 	if ( Socket != INVALID_SOCKET ) {
    161 		closesocket (Socket);
    162 		Socket = INVALID_SOCKET;
    163 	}
    164 }
    165 
    166 
    167 
    168 /***********************************************************************************************
    169  * WIC::Start_Listening -- Enable callbacks for read/write events on our socket                *
    170  *                                                                                             *
    171  *                                                                                             *
    172  *                                                                                             *
    173  * INPUT:    Nothing                                                                           *
    174  *                                                                                             *
    175  * OUTPUT:   Nothing                                                                           *
    176  *                                                                                             *
    177  * WARNINGS: None                                                                              *
    178  *                                                                                             *
    179  * HISTORY:                                                                                    *
    180  *    8/5/97 11:54AM ST : Created                                                              *
    181  *=============================================================================================*/
    182 bool WinsockInterfaceClass::Start_Listening (void)
    183 {
    184 	/*
    185 	** Enable asynchronous events on the socket
    186 	*/
    187 	if ( WSAAsyncSelect ( Socket, MainWindow, Protocol_Event_Message(), FD_READ | FD_WRITE) == SOCKET_ERROR ){
    188 		WWDebugString ( "TS: Async select failed.\n" );
    189 		assert (false);
    190 		WSACancelAsyncRequest(ASync);
    191 		ASync = INVALID_HANDLE_VALUE;
    192 		return (false);
    193 	}
    194 	return (true);
    195 }
    196 
    197 
    198 /***********************************************************************************************
    199  * WIC::Stop_Listening -- Disable the winsock event callback                                   *
    200  *                                                                                             *
    201  *                                                                                             *
    202  *                                                                                             *
    203  * INPUT:    Nothing                                                                           *
    204  *                                                                                             *
    205  * OUTPUT:   Nothing                                                                           *
    206  *                                                                                             *
    207  * WARNINGS: None                                                                              *
    208  *                                                                                             *
    209  * HISTORY:                                                                                    *
    210  *    8/5/97 12:06PM ST : Created                                                              *
    211  *=============================================================================================*/
    212 void WinsockInterfaceClass::Stop_Listening (void)
    213 {
    214 	if ( ASync != INVALID_HANDLE_VALUE ) {
    215 		WSACancelAsyncRequest ( ASync );
    216 		ASync = INVALID_HANDLE_VALUE;
    217 	}
    218 }
    219 
    220 
    221 
    222 
    223 /***********************************************************************************************
    224  * WIC::Discard_In_Buffers -- Discard any packets in our incoming packet holding buffers       *
    225  *                                                                                             *
    226  *                                                                                             *
    227  *                                                                                             *
    228  * INPUT:    Nothing                                                                           *
    229  *                                                                                             *
    230  * OUTPUT:   Nothing                                                                           *
    231  *                                                                                             *
    232  * WARNINGS: None                                                                              *
    233  *                                                                                             *
    234  * HISTORY:                                                                                    *
    235  *    8/5/97 11:55AM ST : Created                                                              *
    236  *=============================================================================================*/
    237 void WinsockInterfaceClass::Discard_In_Buffers (void)
    238 {
    239 	WinsockBufferType *packet;
    240 
    241 	while ( InBuffers.Count() ) {
    242 		packet = InBuffers [ 0 ];
    243 		delete packet;
    244 		InBuffers.Delete (0);
    245 	}
    246 }
    247 
    248 
    249 /***********************************************************************************************
    250  * WIC::Discard_In_Buffers -- Discard any packets in our outgoing packet holding buffers       *
    251  *                                                                                             *
    252  *                                                                                             *
    253  *                                                                                             *
    254  * INPUT:    Nothing                                                                           *
    255  *                                                                                             *
    256  * OUTPUT:   Nothing                                                                           *
    257  *                                                                                             *
    258  * WARNINGS: None                                                                              *
    259  *                                                                                             *
    260  * HISTORY:                                                                                    *
    261  *    8/5/97 11:55AM ST : Created                                                              *
    262  *=============================================================================================*/
    263 void WinsockInterfaceClass::Discard_Out_Buffers (void)
    264 {
    265 	WinsockBufferType *packet;
    266 
    267 	while ( OutBuffers.Count() ) {
    268 		packet = OutBuffers [ 0 ];
    269 		delete packet;
    270 		OutBuffers.Delete (0);
    271 	}
    272 }
    273 
    274 
    275 /***********************************************************************************************
    276  * WIC::Init -- Initialised Winsock and this class for use.                                    *
    277  *                                                                                             *
    278  *                                                                                             *
    279  *                                                                                             *
    280  * INPUT:    Nothing                                                                           *
    281  *                                                                                             *
    282  * OUTPUT:   true if Winsock is available and was initialised                                  *
    283  *                                                                                             *
    284  * WARNINGS: None                                                                              *
    285  *                                                                                             *
    286  * HISTORY:                                                                                    *
    287  *    3/20/96 2:54PM ST : Created                                                              *
    288  *=============================================================================================*/
    289 bool WinsockInterfaceClass::Init(void)
    290 {
    291 	short version;
    292 	int 	rc;
    293 
    294 	/*
    295 	** Just return true if we are already set up
    296 	*/
    297 	if (WinsockInitialised) return (true);
    298 
    299 	/*
    300 	** Create a buffer much larger than the sizeof (WSADATA) would indicate since Bounds Checker
    301 	** says that a buffer of that size gets overrun.
    302 	*/
    303 	char	*buffer = new char [sizeof (WSADATA) + 1024];
    304 	WSADATA *winsock_info = (WSADATA*) (&buffer[0]);
    305 
    306 	/*
    307 	** Initialise socket and event handle to null
    308 	*/
    309 	Socket =INVALID_SOCKET;
    310 	ASync = INVALID_HANDLE_VALUE;
    311 	Discard_In_Buffers();
    312 	Discard_Out_Buffers();
    313 
    314 	/*
    315 	** Start WinSock, and fill in our Winsock info structure
    316 	*/
    317 	version = (WINSOCK_MINOR_VER << 8) | WINSOCK_MAJOR_VER;
    318 	rc = WSAStartup(version, winsock_info);
    319 	if (rc != 0) {
    320 		char out[128];
    321 		sprintf (out, "TS: Winsock failed to initialise - error code %d.\n", GetLastError() );
    322 		OutputDebugString (out);
    323 		delete [] buffer;
    324 		return (false);
    325 	}
    326 
    327 	/*
    328 	** Check the Winsock version number
    329 	*/
    330 	if ((winsock_info->wVersion & 0x00ff) != (version & 0x00ff) ||
    331 		(winsock_info->wVersion >> 8) != (version >> 8)) {
    332 		OutputDebugString ("TS: Winsock version is less than 1.1\n" );
    333 		delete [] buffer;
    334 		return (false);
    335 	}
    336 
    337 	/*
    338 	** Everything is OK so return success
    339 	*/
    340 	WinsockInitialised = true;
    341 
    342 	delete [] buffer;
    343 	return (true);
    344 
    345 }
    346 
    347 
    348 
    349 
    350 /***********************************************************************************************
    351  * WIC::Read -- read any pending input from the communications socket                          *
    352  *                                                                                             *
    353  *                                                                                             *
    354  *                                                                                             *
    355  * INPUT:    ptr to buffer to receive input                                                    *
    356  *           length of buffer                                                                  *
    357  *           ptr to address to fill with address that packet was sent from                     *
    358  *           length of address buffer                                                          *
    359  *                                                                                             *
    360  * OUTPUT:   number of bytes transfered to buffer                                              *
    361  *                                                                                             *
    362  * WARNINGS: The format of the address is dependent on the protocol in use.                    *
    363  *                                                                                             *
    364  *                                                                                             *
    365  * HISTORY:                                                                                    *
    366  *    3/20/96 2:58PM ST : Created                                                              *
    367  *=============================================================================================*/
    368 int WinsockInterfaceClass::Read(void *buffer, int &buffer_len, void *address, int &address_len)
    369 {
    370 	address_len = address_len;
    371 	/*
    372 	** Call the message loop in case there are any outstanding winsock READ messages.
    373 	*/
    374 	Keyboard->Check();
    375 
    376 	/*
    377 	** If there are no available packets then return 0
    378 	*/
    379 	if ( InBuffers.Count() == 0 ) return (0);
    380 
    381 	/*
    382 	** Get the oldest packet for reading
    383 	*/
    384 	int packetnum = 0;
    385 	WinsockBufferType *packet = InBuffers [packetnum];
    386 
    387 	assert ( buffer_len >= packet->BufferLen );
    388 	assert ( address_len >= sizeof (packet->Address) );
    389 
    390 	/*
    391 	** Copy the data and the address it came from into the supplied buffers.
    392 	*/
    393 	memcpy ( buffer, packet->Buffer, packet->BufferLen );
    394 	memcpy ( address, packet->Address, sizeof (packet->Address) );
    395 
    396 	/*
    397 	** Return the length of the packet in buffer_len.
    398 	*/
    399 	buffer_len = packet->BufferLen;
    400 
    401 	/*
    402 	** Delete the temporary storage for the packet now that it is being passed to the game.
    403 	*/
    404 	InBuffers.Delete ( packetnum );
    405 	delete packet;
    406 
    407 	return ( buffer_len );
    408 }
    409 
    410 
    411 
    412 
    413 /***********************************************************************************************
    414  * WIC::WriteTo -- Send data via the Winsock socket                                            *
    415  *                                                                                             *
    416  *                                                                                             *
    417  *                                                                                             *
    418  * INPUT:    ptr to buffer containing data to send                                             *
    419  *           length of data to send                                                            *
    420  *           address to send data to.                                                          *
    421  *                                                                                             *
    422  * OUTPUT:   Nothing                                                                           *
    423  *                                                                                             *
    424  * WARNINGS: The format of the address is dependent on the protocol in use.                    *
    425  *                                                                                             *
    426  * HISTORY:                                                                                    *
    427  *    3/20/96 3:00PM ST : Created                                                              *
    428  *=============================================================================================*/
    429 void WinsockInterfaceClass::WriteTo(void *buffer, int buffer_len, void *address)
    430 {
    431 	/*
    432 	** Create a temporary holding area for the packet.
    433 	*/
    434 	WinsockBufferType *packet = new WinsockBufferType;
    435 
    436 	/*
    437 	** Copy the packet into the holding buffer.
    438 	*/
    439 	memcpy ( packet->Buffer, buffer, buffer_len );
    440 	packet->BufferLen = buffer_len;
    441 	packet->IsBroadcast = false;
    442 //	memcpy ( packet->Address, address, sizeof (packet->Address) );
    443 	memcpy ( packet->Address, address, sizeof( IPXAddressClass ) );		// Steve Tall has revised WriteTo due to this bug.
    444 
    445 	/*
    446 	** Add it to our out list.
    447 	*/
    448 	OutBuffers.Add ( packet );
    449 
    450 	/*
    451 	** Send a message to ourselves so that we can initiate a write if Winsock is idle.
    452 	*/
    453 	SendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );
    454 
    455 	/*
    456 	** Make sure the message loop gets called.
    457 	*/
    458 	Keyboard->Check();
    459 }
    460 
    461 
    462 
    463 
    464 /***********************************************************************************************
    465  * WIC::Broadcast -- Send data via the Winsock socket                                          *
    466  *                                                                                             *
    467  *                                                                                             *
    468  *                                                                                             *
    469  * INPUT:    ptr to buffer containing data to send                                             *
    470  *           length of data to send                                                            *
    471  *                                                                                             *
    472  * OUTPUT:   Nothing                                                                           *
    473  *                                                                                             *
    474  * WARNINGS: None                                                                              *
    475  *                                                                                             *
    476  * HISTORY:                                                                                    *
    477  *    3/20/96 3:00PM ST : Created                                                              *
    478  *=============================================================================================*/
    479 void WinsockInterfaceClass::Broadcast (void *buffer, int buffer_len)
    480 {
    481 
    482 	/*
    483 	** Create a temporary holding area for the packet.
    484 	*/
    485 	WinsockBufferType *packet = new WinsockBufferType;
    486 
    487 	/*
    488 	** Copy the packet into the holding buffer.
    489 	*/
    490 	memcpy ( packet->Buffer, buffer, buffer_len );
    491 	packet->BufferLen = buffer_len;
    492 
    493 	/*
    494 	** Indicate that this packet should be broadcast.
    495 	*/
    496 	packet->IsBroadcast = true;
    497 
    498 	/*
    499 	** Add it to our out list.
    500 	*/
    501 	OutBuffers.Add ( packet );
    502 
    503 	/*
    504 	** Send a message to ourselves so that we can initiate a write if Winsock is idle.
    505 	*/
    506 	SendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );
    507 
    508 	/*
    509 	** Make sure the message loop gets called.
    510 	*/
    511 	Keyboard->Check();
    512 }
    513 
    514 
    515 
    516 
    517 /***********************************************************************************************
    518  * WIC::Clear_Socket_Error -- Clear any outstanding erros on the socket                        *
    519  *                                                                                             *
    520  *                                                                                             *
    521  *                                                                                             *
    522  * INPUT:    Socket                                                                            *
    523  *                                                                                             *
    524  * OUTPUT:   Nothing                                                                           *
    525  *                                                                                             *
    526  * WARNINGS: None                                                                              *
    527  *                                                                                             *
    528  * HISTORY:                                                                                    *
    529  *    8/5/97 12:05PM ST : Created                                                              *
    530  *=============================================================================================*/
    531 void WinsockInterfaceClass::Clear_Socket_Error(SOCKET socket)
    532 {
    533 	unsigned long error_code;
    534 	int length = 4;
    535 
    536 	getsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);
    537 	error_code = 0;
    538 	setsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, length);
    539 }
    540 
    541 
    542 
    543 
    544 
    545 
    546 
    547 /***********************************************************************************************
    548  * WIC::Set_Socket_Options -- Sets default socket options for Winsock buffer sizes             *
    549  *                                                                                             *
    550  *                                                                                             *
    551  *                                                                                             *
    552  * INPUT:    Nothing                                                                           *
    553  *                                                                                             *
    554  * OUTPUT:   Nothing                                                                           *
    555  *                                                                                             *
    556  * WARNINGS: None                                                                              *
    557  *                                                                                             *
    558  * HISTORY:                                                                                    *
    559  *    8/5/97 12:07PM ST : Created                                                              *
    560  *=============================================================================================*/
    561 bool WinsockInterfaceClass::Set_Socket_Options ( void )
    562 {
    563 	static int		socket_transmit_buffer_size = SOCKET_BUFFER_SIZE;
    564 	static int		socket_receive_buffer_size = SOCKET_BUFFER_SIZE;
    565 
    566 	/*
    567 	** Specify the size of the receive buffer.
    568 	*/
    569 	int err = setsockopt ( Socket, SOL_SOCKET, SO_RCVBUF, (char*)&socket_receive_buffer_size, 4);
    570 	if ( err == INVALID_SOCKET ) {
    571 		char out[128];
    572 		sprintf (out, "TS: Failed to set IPX socket option SO_RCVBUF - error code %d.\n", GetLastError() );
    573 		OutputDebugString (out);
    574 		assert ( err != INVALID_SOCKET );
    575 	}
    576 
    577 	/*
    578 	** Specify the size of the send buffer.
    579 	*/
    580 	err = setsockopt ( Socket, SOL_SOCKET, SO_SNDBUF, (char*)&socket_transmit_buffer_size, 4);
    581 	if ( err == INVALID_SOCKET ) {
    582 		char out[128];
    583 		sprintf (out, "TS: Failed to set IPX socket option SO_SNDBUF - error code %d.\n", GetLastError() );
    584 		OutputDebugString (out);
    585 		assert ( err != INVALID_SOCKET );
    586 	}
    587 
    588 	return ( true );
    589 }
    590 
    591