418 lines
No EOL
11 KiB
C++
418 lines
No EOL
11 KiB
C++
/*
|
|
** 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 <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 *
|
|
* *
|
|
* $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 <Notify.h>
|
|
#include <wwonline\wolsession.h>
|
|
#include <wwonline\woluser.h>
|
|
#include <combat\combat.h>
|
|
#include <wwnet\wwpacket.h>
|
|
|
|
|
|
/*
|
|
** Commonly available components.
|
|
*/
|
|
#include <wwlib\vector.h>
|
|
|
|
|
|
#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<WWOnline::UserEvent>,
|
|
public Observer<WWOnline::GameOptionsMessage>,
|
|
public Observer<WWOnline::ConnectionStatus>,
|
|
public Observer<WWOnline::UserIPEvent>
|
|
{
|
|
|
|
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<WOL::Server*> 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<WWOnline::Session> 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<GamePacketStruct*> 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<GameOptionsStagingStruct*> IncomingOptions;
|
|
DynamicVectorClass<GameOptionsStagingStruct*> 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
|