123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002 |
- //
- // 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 *
- * *
- * File Name : TCPIP.CPP *
- * *
- * Programmer : Steve Tall *
- * *
- * Start Date : March 11th, 1996 *
- * *
- * Last Update : March 20th, 1996 [ST] *
- * *
- *-------------------------------------------------------------------------*
- * Overview: *
- * *
- * Member functions of the TcpipManagerClass which provides the Winsock *
- * interface for C&C *
- * *
- * *
- *-------------------------------------------------------------------------*
- * Functions: *
- * *
- * TMC::TcpipManagerClass -- constructor for the TcpipManagerClass *
- * TMC::~TcpipManagerClass -- destructor for the TcpipManagerClass *
- * TMC::Close -- restores any currently in use Winsock resources *
- * TMC::Init -- Initialised Winsock for use. *
- * TMC::Start_Server -- Initialise connection and start listening. *
- * TMC::Read -- read any pending input from the stream socket *
- * TMC::Write -- Send data via the Winsock streaming socket *
- * TMC::Add_Client -- A client has requested to connect. *
- * TMC::Message_Handler -- Message handler for Winsock. *
- * TMC::Set_Host_Address -- Set the address of the host *
- * TMC::Start_Client -- Start trying to connect to a game host *
- * TMC::Close_Socket -- Close an opened Winsock socket. *
- * TMC::Copy_To_In_Buffer -- copy data from our winsock buffer *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "tcpip.h"
- #ifdef FORCE_WINSOCK
- /*
- ** Nasty globals
- */
- bool Server; //Is this player acting as client or server
- TcpipManagerClass Winsock; //The object for interfacing with Winsock
- /***********************************************************************************************
- * TMC::TcpipManagerClass -- constructor for the TcpipManagerClass *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:51PM ST : Created *
- *=============================================================================================*/
- TcpipManagerClass::TcpipManagerClass(void)
- {
- WinsockInitialised = FALSE;
- Connected = FALSE;
- UseUDP = TRUE;
- SocketReceiveBuffer = 4096;
- SocketSendBuffer = 4096;
- }
- /***********************************************************************************************
- * TMC::~TcpipManagerClass -- destructor for the TcpipManagerClass *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:52PM ST : Created *
- *=============================================================================================*/
- TcpipManagerClass::~TcpipManagerClass(void)
- {
- Close();
- }
- /***********************************************************************************************
- * TMC::Close -- restores any currently in use Winsock resources *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:52PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Close(void)
- {
- /*
- ** If we never initialised the class in the first place then just return
- */
- if (!WinsockInitialised) return;
- /*
- ** Cancel any outstaning asyncronous events
- */
- if (Async){
- WSACancelAsyncRequest(Async);
- }
- /*
- ** Close any open sockets
- */
- if (ConnectSocket != INVALID_SOCKET){
- Close_Socket(ConnectSocket);
- ConnectSocket = INVALID_SOCKET;
- }
- if (ListenSocket != INVALID_SOCKET){
- Close_Socket(ListenSocket);
- ListenSocket = INVALID_SOCKET;
- }
- if (UDPSocket != INVALID_SOCKET){
- Close_Socket(ListenSocket);
- UDPSocket = INVALID_SOCKET;
- }
- /*
- ** Call the Winsock cleanup function to say we are finished using Winsock
- */
- WSACleanup();
- WinsockInitialised = FALSE;
- Connected = FALSE;
- }
- /***********************************************************************************************
- * TMC::Init -- Initialised Winsock for use. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: TRUE if Winsock is available and was initialised *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:54PM ST : Created *
- *=============================================================================================*/
- BOOL TcpipManagerClass::Init(void)
- {
- short version;
- int rc;
- /*
- ** Just return true if we are already set up
- */
- if (WinsockInitialised) return (TRUE);
- /*
- ** Initialise sockets to null
- */
- ListenSocket = INVALID_SOCKET;
- ConnectSocket =INVALID_SOCKET;
- UDPSocket = INVALID_SOCKET;
- /*
- ** Start WinSock, and fill in our WinSockData
- */
- version = (WINSOCK_MINOR_VER << 8) | WINSOCK_MAJOR_VER;
- rc = WSAStartup(version, &WinsockInfo);
- if (rc != 0) {
- return (FALSE);
- }
- /*
- ** Check the Winsock version number
- */
- if ((WinsockInfo.wVersion & 0x00ff) != (version & 0x00ff) ||
- (WinsockInfo.wVersion >> 8) != (version >> 8)) {
- return (FALSE);
- }
- /*
- ** Everything is OK so return success
- */
- WinsockInitialised = TRUE;
- return (TRUE);
- }
- /***********************************************************************************************
- * TMC::Start_Server -- initialise out connection as the server. Start listening for clients. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:56PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Start_Server(void)
- {
- int i;
- //struct sockaddr_in addr;
- Start_Client();
- /*
- ** Set up the incoming and outgoing data buffers head and tail pointers
- */
- //InBufferHead = 0;
- //InBufferTail = 0;
- //OutBufferHead= 0;
- //OutBufferTail= 0;
- TXBufferHead = 0;
- TXBufferTail = 0;
- RXBufferHead = 0;
- RXBufferTail = 0;
- for (i=0 ; i<WS_NUM_TX_BUFFERS ; i++){
- TransmitBuffers[i].InUse = false;
- }
- for (i=0 ; i<WS_NUM_RX_BUFFERS ; i++){
- ReceiveBuffers[i].InUse = false;
- }
- /*
- ** Flag that we are the server side not the client
- */
- IsServer = TRUE;
- UseUDP = TRUE;
- #if (0)
- /*
- ** Create our socket and bind it to our port number
- */
- ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (ListenSocket == INVALID_SOCKET) {
- ConnectStatus = NOT_CONNECTING;
- return ;
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PORTNUM);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(ListenSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==
- SOCKET_ERROR) {
- Close_Socket(ListenSocket);
- ConnectStatus = NOT_CONNECTING;
- return;
- }
- /*
- ** Start listening for connections on this socket
- */
- if (listen(ListenSocket, 1) == SOCKET_ERROR) {
- Close_Socket(ListenSocket);
- ConnectStatus = NOT_CONNECTING;
- return;
- }
- /*
- ** Select the asynchronous events we want to process
- */
- if (WSAAsyncSelect (ListenSocket, MainWindow, WM_ACCEPT, FD_ACCEPT) == SOCKET_ERROR) {
- Close_Socket(ListenSocket);
- ConnectStatus = NOT_CONNECTING;
- return;
- }
- #endif
- ConnectStatus = CONNECTING;
- }
- /***********************************************************************************************
- * TMC::Read -- read any pending input from the stream socket *
- * *
- * *
- * *
- * INPUT: ptr to buffer to receive input *
- * length of buffer *
- * *
- * OUTPUT: number of bytes transfered to buffer *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 2:58PM ST : Created *
- *=============================================================================================*/
- int TcpipManagerClass::Read(void *buffer, int buffer_len)
- {
- int bytes_copied = 0;
- char *dest_buf = (char*) buffer;
- /*
- ** Make sure the message loop gets called because all the Winsock notifications
- ** are done via messages.
- */
- Keyboard::Check();
- /*
- ** Copy any outstanding incoming data to the buffer provided
- */
- if (ReceiveBuffers[RXBufferTail].InUse){
- memcpy (buffer, ReceiveBuffers[RXBufferTail].Buffer,
- MIN(ReceiveBuffers[RXBufferTail].DataLength, buffer_len));
- ReceiveBuffers[RXBufferTail].InUse = false;
- bytes_copied = MIN(ReceiveBuffers[RXBufferTail++].DataLength, buffer_len);
- RXBufferTail &= WS_NUM_RX_BUFFERS-1;
- }
- return (bytes_copied);
- }
- /***********************************************************************************************
- * TMC::Write -- Send data via the Winsock UDP 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 TcpipManagerClass::Write(void *buffer, int buffer_len)
- {
- char *source_buf = (char*) buffer;
- /*
- ** Copy the data to one of the classes internal buffers
- */
- if (!TransmitBuffers[TXBufferHead].InUse){
- memcpy (TransmitBuffers[TXBufferHead].Buffer,
- buffer,
- MIN (buffer_len, WS_INTERNET_BUFFER_LEN));
- TransmitBuffers[TXBufferHead].InUse = true;
- TransmitBuffers[TXBufferHead++].DataLength = MIN(buffer_len, WS_INTERNET_BUFFER_LEN);
- TXBufferHead &= WS_NUM_TX_BUFFERS-1;
- }
- /*
- ** Send a message to ourselves to start off the event
- */
- if (UseUDP){
- SendMessage(MainWindow, WM_UDPASYNCEVENT, 0, (LONG)FD_WRITE);
- }else{
- SendMessage(MainWindow, WM_ASYNCEVENT, 0, (LONG)FD_WRITE);
- }
- Keyboard::Check();
- }
- /***********************************************************************************************
- * TMC::Add_Client -- a client has requested to connect. Make the connection *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: TRUE if client was successfully connected *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:02PM ST : Created *
- *=============================================================================================*/
- BOOL TcpipManagerClass::Add_Client(void)
- {
- struct sockaddr_in addr;
- int addrsize;
- bool delay = TRUE;
- /*
- ** Accept the connection. If there is an error then dont do anything else
- */
- addrsize = sizeof(addr);
- ConnectSocket = accept (ListenSocket, (LPSOCKADDR)&addr, &addrsize);
- if (ConnectSocket == INVALID_SOCKET) {
- //Show_Error("accept", WSAGetLastError());
- return(FALSE);
- }
- /*
- ** Set options for this socket
- */
- setsockopt (ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&delay, 4);
- setsockopt (ConnectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);
- setsockopt (ConnectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);
- /*
- ** Save the clients address
- */
- memcpy(&ClientIPAddress, &addr.sin_addr.s_addr,4);
- memcpy(&UDPIPAddress, &addr.sin_addr.s_addr,4);
- /*
- ** Initiate an asynchronous host lookup by address. Our window will receive notification
- ** when this is complete or when it times out.
- */
- Async = WSAAsyncGetHostByAddr (MainWindow, WM_HOSTBYADDRESS,
- (char const *)&addr.sin_addr, 4, PF_INET, &HostBuff[0],
- MAXGETHOSTSTRUCT);
- /*
- ** Enable asynchronous events on this socket
- */
- if (WSAAsyncSelect (ConnectSocket, MainWindow, WM_ASYNCEVENT,
- FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR){
- WSACancelAsyncRequest(Async);
- Close_Socket (ConnectSocket);
- return(FALSE);
- }
- /*
- ** Create our UDP socket
- */
- UDPSocket = socket(AF_INET, SOCK_DGRAM, 0);
- if (UDPSocket == INVALID_SOCKET) {
- return (FALSE);
- }
- /*
- ** Bind our UDP socket to our UDP port number
- */
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PlanetWestwoodPortNumber);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(UDPSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==
- SOCKET_ERROR) {
- Close_Socket(UDPSocket);
- ConnectStatus = NOT_CONNECTING;
- return(FALSE);
- }
- /*
- ** Set options for the UDP socket
- */
- setsockopt (UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);
- setsockopt (UDPSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);
- /*
- ** Enable asynchronous events on this socket
- */
- if (WSAAsyncSelect (UDPSocket, MainWindow, WM_UDPASYNCEVENT,
- FD_READ | FD_WRITE) == SOCKET_ERROR){
- WSACancelAsyncRequest(Async);
- Close_Socket (UDPSocket);
- Close_Socket (ConnectSocket);
- return(FALSE);
- }
- return (TRUE);
- }
- /***********************************************************************************************
- * TMC::Message_Handler -- Message handler function for Winsock related messages *
- * *
- * *
- * *
- * INPUT: Windows message handler stuff *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:05PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Message_Handler(HWND, UINT message, UINT , LONG lParam)
- {
- struct hostent *hentry;
- struct sockaddr_in addr;
- int event;
- int rc;
- int addr_len;
- switch (message){
- /*
- ** Handle the GetHostByAddress result
- */
- case WM_HOSTBYADDRESS:
- if (IsServer){
- /*
- ** We are the server
- */
- ConnectStatus = CONNECTING;
- if (WSAGETASYNCERROR(lParam)==0) {
- hentry = (struct hostent *)&HostBuff[0];
- strcpy (&ClientName[0], hentry->h_name);
- }
- Async = 0;
- return;
- }else{
- /*
- ** We are the client
- */
- ConnectStatus = CONTACTING_SERVER;
- if (WSAGETASYNCERROR(lParam)==0) {
- hentry = (struct hostent *)&HostBuff[0];
- strcpy (Server.Name, hentry->h_name);
- }
- else {
- Server.Name[0] = 0;
- }
- Async = 0;
- return;
- }
- /*
- ** Retrieve host by name: Start connecting now that we have the
- ** address.
- */
- case WM_HOSTBYNAME:
- if (WSAGETASYNCERROR(lParam)==0) {
- hentry = (struct hostent *)&HostBuff[0];
- memcpy (&(Server.Addr.s_addr), hentry->h_addr, 4);
- memcpy(&UDPIPAddress, hentry->h_addr, 4);
- strcpy (Server.DotAddr, inet_ntoa(Server.Addr));
- ConnectStatus = CONNECTED_OK;
- Connected = TRUE;
- }
- else {
- Server.Name[0] = 0;
- strcpy (Server.DotAddr, "????");
- ConnectStatus = SERVER_ADDRESS_LOOKUP_FAILED;
- }
- Async = 0;
- return;
- /*
- ** Connection is ready - accept the client
- */
- case WM_ACCEPT:
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0) {
- ConnectStatus = UNABLE_TO_ACCEPT_CLIENT;
- return;
- }
- if (Add_Client()) {
- ConnectStatus = CONNECTED_OK;
- Connected = TRUE;
- }
- else {
- ConnectStatus = UNABLE_TO_ACCEPT_CLIENT;
- }
- return;
- /*
- ** Handle UDP packet events
- */
- case WM_UDPASYNCEVENT:
- event = WSAGETSELECTEVENT(lParam);
- switch (event) {
- case FD_READ:
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0) {
- Clear_Socket_Error(UDPSocket);
- return;
- }
- addr_len = sizeof(addr);
- rc = recvfrom(UDPSocket, ReceiveBuffer, WS_RECEIVE_BUFFER_LEN, 0,
- (LPSOCKADDR)&addr, &addr_len);
- if (rc == SOCKET_ERROR) {
- Clear_Socket_Error(UDPSocket);
- return;
- }
- memcpy(&UDPIPAddress, &addr.sin_addr.s_addr, 4);
- Copy_To_In_Buffer(rc);
- return;
- case FD_WRITE:
- if (UseUDP){
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0) {
- Clear_Socket_Error(UDPSocket);
- return;
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PlanetWestwoodPortNumber);
- memcpy (&addr.sin_addr.s_addr, &UDPIPAddress, 4);
- /*
- ** Send as many bytes as there are in the buffer; if there's
- ** an error, just bail out. If we get a WOULDBLOCK error,
- ** WinSock will send us another message when the socket is
- ** available for another write.
- */
- while (TransmitBuffers[TXBufferTail].InUse){
- rc = sendto(UDPSocket,
- TransmitBuffers[TXBufferTail].Buffer,
- TransmitBuffers[TXBufferTail].DataLength,
- 0,
- (LPSOCKADDR)&addr,
- sizeof (addr));
- if (rc == SOCKET_ERROR){
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- Clear_Socket_Error(UDPSocket);
- }
- break;
- }
- TransmitBuffers[TXBufferTail++].InUse = false;
- TXBufferTail &= WS_NUM_TX_BUFFERS-1;
- }
- return;
- }
- }
- /*
- ** Handle the asynchronous event callbacks
- */
- case WM_ASYNCEVENT:
- event = WSAGETSELECTEVENT(lParam);
- switch (event) {
- /*
- ** FD_CLOSE: the client has gone away. Remove the client from our system.
- */
- case FD_CLOSE:
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0 && rc != WSAECONNRESET) {
- ConnectStatus = CONNECTION_LOST;
- return;
- }
- if (Async != 0) {
- WSACancelAsyncRequest(Async);
- }
- WSAAsyncSelect (ConnectSocket, MainWindow, WM_ASYNCEVENT, 0);
- Close_Socket (ConnectSocket);
- ConnectSocket = INVALID_SOCKET;
- //Connected = FALSE;
- ConnectStatus = CONNECTION_LOST;
- break;
- #if (0)
- /*
- ** FD_READ: Data is available on our socket. This message is sent every time
- ** data becomes available so we only have to do one read
- */
- case FD_READ:
- if (!UseUDP){
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0) {
- return;
- }
- rc = recv(ConnectSocket, ReceiveBuffer, WS_RECEIVE_BUFFER_LEN, 0);
- if (rc == SOCKET_ERROR) {
- Clear_Socket_Error(ConnectSocket);
- return;
- }
- Copy_To_In_Buffer(rc);
- return;
- }
- /*
- ** FD_WRITE: The socket is available for writing. We may actually have sent this
- ** message from elewhere in the class.
- */
- case FD_WRITE:
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0) {
- return;
- }
- /*
- ** Send as many bytes as there are in the buffer; if there's
- ** an error, just bail out. If we get a WOULDBLOCK error,
- ** WinSock will send us another message when the socket is
- ** available for another write.
- */
- while (OutBufferHead > OutBufferTail){
- rc = send(ConnectSocket, OutBuffer + OutBufferTail,
- OutBufferHead - OutBufferTail, 0);
- if (rc == SOCKET_ERROR){
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- Clear_Socket_Error(ConnectSocket);
- }
- break;
- }
- OutBufferTail+=rc;
- }
- if (OutBufferHead == OutBufferTail){
- OutBufferHead = OutBufferTail = 0;
- }
- return;
- #endif //(0)
- /*
- ** FD_CONNECT: A connection was made, or an error occurred.
- */
- case FD_CONNECT:
- rc = WSAGETSELECTERROR(lParam);
- if (rc != 0) {
- ConnectStatus = UNABLE_TO_CONNECT;
- return;
- }
- ConnectStatus = CONNECTED_OK;
- Connected = TRUE;
- return;
- }
- }
- }
- /***********************************************************************************************
- * TMC::Copy_To_In_Buffer -- copy data from our winsock buffer to our internal buffer *
- * *
- * *
- * *
- * INPUT: bytes to copy *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:17PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Copy_To_In_Buffer(int bytes)
- {
- if (!ReceiveBuffers[RXBufferHead].InUse){
- memcpy (ReceiveBuffers[RXBufferHead].Buffer, ReceiveBuffer, MIN(bytes, WS_INTERNET_BUFFER_LEN));
- ReceiveBuffers[RXBufferHead].InUse = true;
- ReceiveBuffers[RXBufferHead++].DataLength = MIN(bytes, WS_INTERNET_BUFFER_LEN);
- RXBufferHead &= WS_NUM_RX_BUFFERS-1;
- }
- }
- /***********************************************************************************************
- * TMC::Set_Host_Address -- Set the address of the host game we want to connect to *
- * *
- * *
- * *
- * INPUT: ptr to address string *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:19PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Set_Host_Address(char *address)
- {
- strcpy(HostAddress, address);
- }
- /***********************************************************************************************
- * TMC::Start_Client -- Start trying to connect to a game host *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:19PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Start_Client(void)
- {
- struct sockaddr_in addr;
- bool delay = true;
- int i;
- addr.sin_family = AF_INET;
- addr.sin_port = 0;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- /*
- ** Set up the incoming and outgoing data buffers head and tail pointers
- */
- // InBufferHead = 0;
- // InBufferTail = 0;
- // OutBufferHead= 0;
- // OutBufferTail= 0;
- TXBufferHead = 0;
- TXBufferTail = 0;
- RXBufferHead = 0;
- RXBufferTail = 0;
- for (i=0 ; i<WS_NUM_TX_BUFFERS ; i++){
- TransmitBuffers[i].InUse = false;
- }
- for (i=0 ; i<WS_NUM_RX_BUFFERS ; i++){
- ReceiveBuffers[i].InUse = false;
- }
- Connected = FALSE;
- /*
- ** Flag that we are the client side not the server
- */
- IsServer = FALSE;
- UseUDP = TRUE;
- /*
- ** Create our UDP socket
- */
- UDPSocket = socket(AF_INET, SOCK_DGRAM, 0);
- if (UDPSocket == INVALID_SOCKET) {
- Close_Socket(ConnectSocket);
- ConnectStatus = NOT_CONNECTING;
- return;
- }
- /*
- ** Bind our UDP socket to our UDP port number
- */
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PlanetWestwoodPortNumber);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(UDPSocket, (LPSOCKADDR)&addr, sizeof(addr)) ==
- SOCKET_ERROR) {
- Close_Socket(UDPSocket);
- Close_Socket(ConnectSocket);
- ConnectStatus = NOT_CONNECTING;
- return;
- }
- /*
- ** Set options for the UDP socket
- */
- setsockopt (UDPSocket, SOL_SOCKET, SO_RCVBUF, (char*)&SocketReceiveBuffer, 4);
- setsockopt (UDPSocket, SOL_SOCKET, SO_SNDBUF, (char*)&SocketSendBuffer, 4);
- /*
- ** Enable asynchronous events on the UDP socket
- */
- if (WSAAsyncSelect (UDPSocket, MainWindow, WM_UDPASYNCEVENT,
- FD_READ | FD_WRITE) == SOCKET_ERROR){
- WSACancelAsyncRequest(Async);
- Close_Socket (UDPSocket);
- Close_Socket (ConnectSocket);
- ConnectStatus = NOT_CONNECTING;
- return;
- }
- /*
- ** If the name is not a dot-decimal ip address then do a nameserver lookup
- */
- Server.Addr.s_addr = inet_addr(PlanetWestwoodIPAddress);
- memcpy(&UDPIPAddress, &Server.Addr.s_addr, 4);
- if (Server.Addr.s_addr == INADDR_NONE){
- strcpy (Server.Name, PlanetWestwoodIPAddress);
- Async = WSAAsyncGetHostByName(MainWindow, WM_HOSTBYNAME,
- Server.Name, HostBuff, MAXGETHOSTSTRUCT);
- ConnectStatus = RESOLVING_HOST_ADDRESS;
- }else{
- ConnectStatus = CONNECTED_OK;
- Connected = TRUE;
- }
- }
- /***********************************************************************************************
- * TMC::Close_Socket -- Close an opened Winsock socket. *
- * *
- * *
- * *
- * INPUT: Socket to close *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/20/96 3:24PM ST : Created *
- *=============================================================================================*/
- void TcpipManagerClass::Close_Socket(SOCKET s)
- {
- LINGER ling;
- ling.l_onoff = 0; // linger off
- ling.l_linger = 0; // timeout in seconds (ie close now)
- setsockopt(s, SOL_SOCKET, SO_LINGER, (LPSTR)&ling, sizeof(ling));
- closesocket (s);
- }
- void TcpipManagerClass::Set_Protocol_UDP(BOOL state)
- {
- UseUDP = state;
- }
- void TcpipManagerClass::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);
- }
- #endif //FORCE_WINSOCK
|