| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004 |
- /*
- ** Command & Conquer(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program 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.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***************************************************************************
- ** 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
|