| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /Sun/WSProto.cpp $*
- * *
- * $Author:: Joe_b $*
- * *
- * $Modtime:: 8/20/97 10:54a $*
- * *
- * $Revision:: 5 $*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * WSProto.CPP WinsockInterfaceClass to provide an interface to Winsock protocols *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * Functions: *
- * *
- * WIC::WinsockInterfaceClass -- constructor for the WinsockInterfaceClass *
- * WIC::~WinsockInterfaceClass -- destructor for the WinsockInterfaceClass *
- * WIC::Close -- Releases any currently in use Winsock resources. *
- * WIC::Close_Socket -- Close the communication socket if its open *
- * WIC::Start_Listening -- Enable callbacks for read/write events on our socket *
- * WIC::Stop_Listening -- Disable the winsock event callback *
- * WIC::Discard_In_Buffers -- Discard any packets in our incoming packet holding buffers *
- * WIC::Discard_In_Buffers -- Discard any packets in our outgoing packet holding buffers *
- * WIC::Init -- Initialised Winsock and this class for use. *
- * WIC::Read -- read any pending input from the communications socket *
- * WIC::WriteTo -- Send data via the Winsock socket *
- * WIC::Broadcast -- Send data via the Winsock socket *
- * WIC::Clear_Socket_Error -- Clear any outstanding erros on the socket *
- * WIC::Set_Socket_Options -- Sets default socket options for Winsock buffer sizes *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "WSProto.h"
- #include <stdio.h>
- /***********************************************************************************************
- * WIC::WinsockInterfaceClass -- constructor for the WinsockInterfaceClass *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:51PM ST : Created *
- *=============================================================================================*/
- WinsockInterfaceClass::WinsockInterfaceClass(void)
- {
- WinsockInitialised = false;
- ASync = INVALID_HANDLE_VALUE;
- Socket = INVALID_SOCKET;
- }
- /***********************************************************************************************
- * WIC::~WinsockInterfaceClass -- destructor for the WinsockInterfaceClass *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:52PM ST : Created *
- *=============================================================================================*/
- WinsockInterfaceClass::~WinsockInterfaceClass(void)
- {
- Close();
- }
- /***********************************************************************************************
- * WIC::Close -- Releases any currently in use Winsock resources. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:52PM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Close(void)
- {
- /*
- ** If we never initialised the class in the first place then just return
- */
- if (!WinsockInitialised) return;
- /*
- ** Cancel any outstaning asyncronous events
- */
- Stop_Listening();
- /*
- ** Close any open sockets
- */
- Close_Socket();
- /*
- ** Call the Winsock cleanup function to say we are finished using Winsock
- */
- WSACleanup();
- WinsockInitialised = false;
- }
- /***********************************************************************************************
- * WIC::Close_Socket -- Close the communication socket if its open *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 11:53AM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Close_Socket (void)
- {
- if ( Socket != INVALID_SOCKET ) {
- closesocket (Socket);
- Socket = INVALID_SOCKET;
- }
- }
- /***********************************************************************************************
- * WIC::Start_Listening -- Enable callbacks for read/write events on our socket *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 11:54AM ST : Created *
- *=============================================================================================*/
- bool WinsockInterfaceClass::Start_Listening (void)
- {
- /*
- ** Enable asynchronous events on the socket
- */
- if ( WSAAsyncSelect ( Socket, MainWindow, Protocol_Event_Message(), FD_READ | FD_WRITE) == SOCKET_ERROR ){
- WWDebugString ( "TS: Async select failed.\n" );
- assert (false);
- WSACancelAsyncRequest(ASync);
- ASync = INVALID_HANDLE_VALUE;
- return (false);
- }
- return (true);
- }
- /***********************************************************************************************
- * WIC::Stop_Listening -- Disable the winsock event callback *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 12:06PM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Stop_Listening (void)
- {
- if ( ASync != INVALID_HANDLE_VALUE ) {
- WSACancelAsyncRequest ( ASync );
- ASync = INVALID_HANDLE_VALUE;
- }
- }
- /***********************************************************************************************
- * WIC::Discard_In_Buffers -- Discard any packets in our incoming packet holding buffers *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 11:55AM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Discard_In_Buffers (void)
- {
- WinsockBufferType *packet;
- while ( InBuffers.Count() ) {
- packet = InBuffers [ 0 ];
- delete packet;
- InBuffers.Delete (0);
- }
- }
- /***********************************************************************************************
- * WIC::Discard_In_Buffers -- Discard any packets in our outgoing packet holding buffers *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 11:55AM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Discard_Out_Buffers (void)
- {
- WinsockBufferType *packet;
- while ( OutBuffers.Count() ) {
- packet = OutBuffers [ 0 ];
- delete packet;
- OutBuffers.Delete (0);
- }
- }
- /***********************************************************************************************
- * WIC::Init -- Initialised Winsock and this class for use. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: true if Winsock is available and was initialised *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:54PM ST : Created *
- *=============================================================================================*/
- bool WinsockInterfaceClass::Init(void)
- {
- short version;
- int rc;
- /*
- ** Just return true if we are already set up
- */
- if (WinsockInitialised) return (true);
- /*
- ** Create a buffer much larger than the sizeof (WSADATA) would indicate since Bounds Checker
- ** says that a buffer of that size gets overrun.
- */
- char *buffer = new char [sizeof (WSADATA) + 1024];
- WSADATA *winsock_info = (WSADATA*) (&buffer[0]);
- /*
- ** Initialise socket and event handle to null
- */
- Socket =INVALID_SOCKET;
- ASync = INVALID_HANDLE_VALUE;
- Discard_In_Buffers();
- Discard_Out_Buffers();
- /*
- ** Start WinSock, and fill in our Winsock info structure
- */
- version = (WINSOCK_MINOR_VER << 8) | WINSOCK_MAJOR_VER;
- rc = WSAStartup(version, winsock_info);
- if (rc != 0) {
- char out[128];
- sprintf (out, "TS: Winsock failed to initialise - error code %d.\n", GetLastError() );
- OutputDebugString (out);
- delete [] buffer;
- return (false);
- }
- /*
- ** Check the Winsock version number
- */
- if ((winsock_info->wVersion & 0x00ff) != (version & 0x00ff) ||
- (winsock_info->wVersion >> 8) != (version >> 8)) {
- OutputDebugString ("TS: Winsock version is less than 1.1\n" );
- delete [] buffer;
- return (false);
- }
- /*
- ** Everything is OK so return success
- */
- WinsockInitialised = true;
- delete [] buffer;
- return (true);
- }
- /***********************************************************************************************
- * WIC::Read -- read any pending input from the communications socket *
- * *
- * *
- * *
- * INPUT: ptr to buffer to receive input *
- * length of buffer *
- * ptr to address to fill with address that packet was sent from *
- * length of address buffer *
- * *
- * OUTPUT: number of bytes transfered to buffer *
- * *
- * WARNINGS: The format of the address is dependent on the protocol in use. *
- * *
- * *
- * HISTORY: *
- * 3/20/96 2:58PM ST : Created *
- *=============================================================================================*/
- int WinsockInterfaceClass::Read(void *buffer, int &buffer_len, void *address, int &address_len)
- {
- address_len = address_len;
- /*
- ** Call the message loop in case there are any outstanding winsock READ messages.
- */
- Keyboard->Check();
- /*
- ** If there are no available packets then return 0
- */
- if ( InBuffers.Count() == 0 ) return (0);
- /*
- ** Get the oldest packet for reading
- */
- int packetnum = 0;
- WinsockBufferType *packet = InBuffers [packetnum];
- assert ( buffer_len >= packet->BufferLen );
- assert ( address_len >= sizeof (packet->Address) );
- /*
- ** Copy the data and the address it came from into the supplied buffers.
- */
- memcpy ( buffer, packet->Buffer, packet->BufferLen );
- memcpy ( address, packet->Address, sizeof (packet->Address) );
- /*
- ** Return the length of the packet in buffer_len.
- */
- buffer_len = packet->BufferLen;
- /*
- ** Delete the temporary storage for the packet now that it is being passed to the game.
- */
- InBuffers.Delete ( packetnum );
- delete packet;
- return ( buffer_len );
- }
- /***********************************************************************************************
- * WIC::WriteTo -- Send data via the Winsock socket *
- * *
- * *
- * *
- * INPUT: ptr to buffer containing data to send *
- * length of data to send *
- * address to send data to. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: The format of the address is dependent on the protocol in use. *
- * *
- * HISTORY: *
- * 3/20/96 3:00PM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::WriteTo(void *buffer, int buffer_len, void *address)
- {
- /*
- ** Create a temporary holding area for the packet.
- */
- WinsockBufferType *packet = new WinsockBufferType;
- /*
- ** Copy the packet into the holding buffer.
- */
- memcpy ( packet->Buffer, buffer, buffer_len );
- packet->BufferLen = buffer_len;
- packet->IsBroadcast = false;
- // memcpy ( packet->Address, address, sizeof (packet->Address) );
- memcpy ( packet->Address, address, sizeof( IPXAddressClass ) ); // Steve Tall has revised WriteTo due to this bug.
- /*
- ** Add it to our out list.
- */
- OutBuffers.Add ( packet );
- /*
- ** Send a message to ourselves so that we can initiate a write if Winsock is idle.
- */
- SendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );
- /*
- ** Make sure the message loop gets called.
- */
- Keyboard->Check();
- }
- /***********************************************************************************************
- * WIC::Broadcast -- Send data via the Winsock socket *
- * *
- * *
- * *
- * INPUT: ptr to buffer containing data to send *
- * length of data to send *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:00PM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Broadcast (void *buffer, int buffer_len)
- {
- /*
- ** Create a temporary holding area for the packet.
- */
- WinsockBufferType *packet = new WinsockBufferType;
- /*
- ** Copy the packet into the holding buffer.
- */
- memcpy ( packet->Buffer, buffer, buffer_len );
- packet->BufferLen = buffer_len;
- /*
- ** Indicate that this packet should be broadcast.
- */
- packet->IsBroadcast = true;
- /*
- ** Add it to our out list.
- */
- OutBuffers.Add ( packet );
- /*
- ** Send a message to ourselves so that we can initiate a write if Winsock is idle.
- */
- SendMessage ( MainWindow, Protocol_Event_Message(), 0, (LONG)FD_WRITE );
- /*
- ** Make sure the message loop gets called.
- */
- Keyboard->Check();
- }
- /***********************************************************************************************
- * WIC::Clear_Socket_Error -- Clear any outstanding erros on the socket *
- * *
- * *
- * *
- * INPUT: Socket *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 12:05PM ST : Created *
- *=============================================================================================*/
- void WinsockInterfaceClass::Clear_Socket_Error(SOCKET socket)
- {
- unsigned long error_code;
- int length = 4;
- getsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);
- error_code = 0;
- setsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, length);
- }
- /***********************************************************************************************
- * WIC::Set_Socket_Options -- Sets default socket options for Winsock buffer sizes *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 8/5/97 12:07PM ST : Created *
- *=============================================================================================*/
- bool WinsockInterfaceClass::Set_Socket_Options ( void )
- {
- static int socket_transmit_buffer_size = SOCKET_BUFFER_SIZE;
- static int socket_receive_buffer_size = SOCKET_BUFFER_SIZE;
- /*
- ** Specify the size of the receive buffer.
- */
- int err = setsockopt ( Socket, SOL_SOCKET, SO_RCVBUF, (char*)&socket_receive_buffer_size, 4);
- if ( err == INVALID_SOCKET ) {
- char out[128];
- sprintf (out, "TS: Failed to set IPX socket option SO_RCVBUF - error code %d.\n", GetLastError() );
- OutputDebugString (out);
- assert ( err != INVALID_SOCKET );
- }
- /*
- ** Specify the size of the send buffer.
- */
- err = setsockopt ( Socket, SOL_SOCKET, SO_SNDBUF, (char*)&socket_transmit_buffer_size, 4);
- if ( err == INVALID_SOCKET ) {
- char out[128];
- sprintf (out, "TS: Failed to set IPX socket option SO_SNDBUF - error code %d.\n", GetLastError() );
- OutputDebugString (out);
- assert ( err != INVALID_SOCKET );
- }
- return ( true );
- }
|