/* ** Command & Conquer Renegade(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 . */ /*********************************************************************************************** *** 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:: /Commando/Code/Commando/natter.h $* * * * $Author:: Steve_t $* * * * $Modtime:: 3/01/02 2:27p $* * * * $Revision:: 18 $* * * * * *---------------------------------------------------------------------------------------------* * * * * *---------------------------------------------------------------------------------------------* * * * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #pragma once #ifndef NATTER_H #define NATTER_H #include "always.h" //#include "nat.h" #include "nataddr.h" /* ** Project specific includes. */ #include #include #include #include #include /* ** Commonly available components. */ #include #ifdef WWASSERT #ifndef fw_assert #define fw_assert WWASSERT #endif //fw_assert #else //WWASSERT #define fw_assert assert #endif //WWASSERT /* ** Size of temporary game options storage buffers. */ #define OPTIONS_STAGING_BUFFER_SIZE 512 #define PORT_BASE_MIN 1024 #define PORT_BASE_MAX 4095 #define PORT_POOL_MIN 4096 #define PORT_POOL_MAX 65535 /* ** Forward declarations. */ class SocketHandlerClass; class RegistryClass; /* ** This class performs the inevitable task of interfacing with whatever piece of code happens to be talking to WOLAPI. ** ** Will have to be completely replaced per project. ** */ class WOLNATInterfaceClass : public Observer, public Observer, public Observer, public Observer { public: /* ** Constructor, destructor. */ WOLNATInterfaceClass(void); ~WOLNATInterfaceClass(void); /* ** Startup, shutdown. */ void Init(void); void Shutdown(void); /* ** Service. */ void Service(void); void Set_Service_Socket_Handler(SocketHandlerClass *socket); void Service_Receive_Queue(SocketHandlerClass *socket); /* ** User event notification. */ void HandleNotification(WWOnline::UserEvent&); /* ** Game options notificaton. */ void HandleNotification(WWOnline::GameOptionsMessage&); /* ** Server connection notification. */ void HandleNotification(WWOnline::ConnectionStatus&); /* ** User IP event. */ void HandleNotification(WWOnline::UserIPEvent&); /* ** Server query. */ void Get_Current_Server_ConnData(char *buffer, int size); /* ** Private game options. */ void Send_Private_Game_Options(WOL::User *user, char *options); bool Get_Private_Game_Options(WOL::User *user, char *options, int option_buffer_len); /* ** Conversion. */ char *Get_Silly_String(WideStringClass *silly_string, char *buffer, int buffer_size); /* ** Game packet handling. */ bool Get_Packet(char *packet_buffer, int buffer_size, IPAddressClass &address); void Intercept_Game_Packet(cPacket &packet); bool Send_Game_Format_Packet_To(IPAddressClass *address, char *payload, int payload_size, SocketHandlerClass *socket_handler = NULL); /* ** General game helper functions. */ bool Get_My_Name(char *namebuf); bool Am_I_Server(void) {return(IsServer);}; void Set_Server(bool is_server); void Set_Server_Negotiated_Address(IPAddressClass *server_address); DynamicVectorClass Get_Mangler_Server_List(void); unsigned short Get_Mangler_Port_By_Index(int index); bool Get_Mangler_Name_By_Index(int index, char *mangler_name); int Get_Num_Mangler_Servers(void); unsigned long Get_Local_Address(void) { return(0);//return(FirewallHelper.Get_Local_Address()); }; void Tell_Server_That_Client_Is_In_Channel(void); bool Is_NAT_Thread_Busy(void); /* ** Game port management. */ unsigned short Get_Next_Client_Port(void); unsigned short Get_Port_As_Server(void); unsigned short Get_Port_As_Server_Client(void); unsigned short Get_Force_Port(void) {return(ForcePort);}; /* ** Config. */ void Get_Config(RegistryClass *reg, int &port_number, bool &send_delay); void Set_Config(RegistryClass *reg, int port_number, bool send_delay); void Save_Firewall_Info_To_Registry(void); unsigned long Get_Reg_External_IP(void) {return(RegExternalIP);} unsigned long Get_Reg_External_Port(void) {return(RegExternalPort);} void Get_Compact_Log(StringClass &log_string); unsigned long Get_Chat_External_IP(void) {return(ChatExternalIP);} /* ** Game options string types. */ enum { OPTION_ERROR = 'a', OPTION_INVITE_PORT_NEGOTIATION, OPTION_ACCEPT_PORT_NEGOTIATION_INVITATION, OPTION_PORT_NOTIFICATION, OPTION_CONNECTION_RESULT, OPTION_QUEUE_STATE, OPTION_ABORT_NEGOTIATION, OPTION_CLIENT_IN_CHANNEL }; /* ** Game options format for the firewall code only. All firewall options packets are prefixed with "NAT:" */ typedef struct tPrivateGameOptions { /* ** Option previx (Always "NAT:" for us. */ char NATOptionsPrefix[4]; /* ** Option type. See list above. */ char Option; /* ** Option payload union. Each type of option has a different payload. */ union tOptionData { /* ** Data for OPTION_INVITE_PORT_NEGOTIATION. */ struct InvitationStruct { char LocalIP[9]; // 00000000, char LocalPort[5]; // 0000, char ExternalIP[9]; // 00000000, char FirewallType[9]; // 00000000, char Queued[5]; // 0000(null) } Invitation; /* ** Data for OPTION_ACCEPT_PORT_NEGOTIATION_INVITATION. */ struct AcceptStruct { char LocalIP[9]; // 00000000, char LocalPort[5]; // 0000, char ExternalIP[9]; // 00000000, char FirewallType[9]; // 00000000(null) } Accept; /* ** Data for OPTION_PORT_NOTIFICATION. */ struct PortStruct { char MangledPort[5]; // 0000, char Name[64]; // "Players name......"(null) } Port; /* ** Data for OPTION_CONNECTION_RESULT. */ struct ConnectionResultStruct { char Result[2]; // n, char Port[5]; // 0000, char Name[64]; // "Players name......"(null) } ConnectionResult; /* ** Data for OPTION_QUEUE_STATE */ struct QueueStateStruct { char Position[3]; // 00(null) } QueueState; /* ** Data for OPTION_ABORT_NEGOTIATION */ struct QuitTalkingStruct { char Nothing; // 00 } QuitTalking; /* ** Data for OPTION_CLIENT_IN_CHANNEL */ struct ClientInChannelStruct { char Name[64]; // "Players name......"(null) } ClientInChannel; } OptionData; } PrivateGameOptionsStruct; private: /* ** PortBase is the start of the current port number range we are using. The range is added to the port base every time ** we start a new game so we are always using a fresh port. The server uses 2 ports per game and the client uses 1 port. */ unsigned short PortBase; /* ** Set this to non-zero to force it to be used as the local port. */ unsigned short ForcePort; /* ** External IP and port from the registry. */ unsigned long RegExternalIP; unsigned short RegExternalPort; /* ** Our IP according to westwood chat. */ unsigned long ChatExternalIP; /* ** Bloat pointer to the Session class. */ RefPtr SessionPtr; /* ** Address we used to send to the server. */ IPAddressClass ServerNegotiatedAddress; /* ** Holding area for incoming game packets. */ struct GamePacketStruct { IPAddressClass FromAddress; unsigned char Payload[512]; }; DynamicVectorClass IncomingPackets; /* ** This is the socket handler to use when sending or receiving game packets. It's only used on the client side since ** the server side has to use the games mechanisms to send and receive (the game already has a socket bound to the port ** we want to use in the server case). */ SocketHandlerClass *ServiceSocketHandler; /* ** Am I a game server? */ bool IsServer; /* ** Game options staging areas. */ typedef struct tGameOptionsStagingStruct { WOL::User User; char Options[OPTIONS_STAGING_BUFFER_SIZE]; } GameOptionsStagingStruct; DynamicVectorClass IncomingOptions; DynamicVectorClass OutgoingOptions; /* ** Mutex to serialise access to game options. */ HANDLE GameOptionsMutex; /* ** Thread safety for game options. */ class ThreadLockClass { public: /* ** Constructor. Grabs the mutex. */ inline ThreadLockClass(WOLNATInterfaceClass *wnptr) { WNPtr = wnptr; int deadlock = WaitForSingleObject(wnptr->GameOptionsMutex, 10 * 1000); if (deadlock == WAIT_TIMEOUT) { WWDEBUG_SAY(("FirewallHelper - Timeout waiting for firewall helper data mutex\n")); fw_assert(deadlock != WAIT_TIMEOUT); } }; WOLNATInterfaceClass *WNPtr; /* ** Destructor, releases the mutex. */ inline ~ThreadLockClass(void) { ReleaseMutex(WNPtr->GameOptionsMutex); }; }; friend ThreadLockClass; }; /* ** Extern for single instance of the WOLNATInterface. */ extern WOLNATInterfaceClass WOLNATInterface; #endif //NATTER_H