mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
359
Code/wwnet/packetmgr.h
Normal file
359
Code/wwnet/packetmgr.h
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
** 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/wwnet/packetmgr.h $*
|
||||
* *
|
||||
* $Author:: Bhayes $*
|
||||
* *
|
||||
* $Modtime:: 2/18/02 10:48p $*
|
||||
* *
|
||||
* $Revision:: 16 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PACKETMGR_H
|
||||
#define _PACKETMGR_H
|
||||
|
||||
#include "mutex.h"
|
||||
#include "wwdebug.h"
|
||||
#include "vector.h"
|
||||
|
||||
#include <winsock.h> // for SOCKET
|
||||
|
||||
#ifdef WWASSERT
|
||||
#ifndef pm_assert
|
||||
#define pm_assert WWASSERT
|
||||
#endif //pm_assert
|
||||
#else //WWASSERT
|
||||
#define pm_assert assert
|
||||
#endif //WWASSERT
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
#define WRAPPER_CRC
|
||||
|
||||
|
||||
/*
|
||||
** Header used at the beginning of a packet to identify the number of packets packed in this packet IYSWIM.
|
||||
*/
|
||||
struct PacketPackHeaderStruct {
|
||||
/*
|
||||
** Number of same length packets in this block.
|
||||
*/
|
||||
unsigned short NumPackets : 5;
|
||||
|
||||
/*
|
||||
** Length of the packets.
|
||||
*/
|
||||
unsigned short PacketSize : 10;
|
||||
|
||||
/*
|
||||
** More packets of a different length after these ones?
|
||||
*/
|
||||
unsigned short MorePackets : 1;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Header used at the beginning of every delta packet.
|
||||
*/
|
||||
struct PacketDeltaHeaderStruct {
|
||||
/*
|
||||
** Chunk pack bits are present.
|
||||
*/
|
||||
unsigned char ChunkPack : 1;
|
||||
|
||||
/*
|
||||
** Byte pack bits are present.
|
||||
*/
|
||||
unsigned char BytePack : 1;
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
** Minimum MTU allowable on the internet is 576. IP Header is 20 bytes. UDP header is 8 bytes
|
||||
** So our max packet size is 576 - 28 = 548
|
||||
*/
|
||||
#ifdef WRAPPER_CRC
|
||||
#define PACKET_MANAGER_MTU 540
|
||||
#else
|
||||
#define PACKET_MANAGER_MTU 544
|
||||
#endif //WRAPPER_CRC
|
||||
#define PACKET_MANAGER_BUFFERS 256
|
||||
#define PACKET_MANAGER_BUFFERS_WHEN_SERVER (32 * 32)
|
||||
#define PACKET_MANAGER_RECEIVE_BUFFERS 128
|
||||
#define PACKET_MANAGER_RECEIVE_BUFFERS_AS_SERVER (64 * 32)
|
||||
#define PACKET_MANAGER_MAX_PACKETS 31
|
||||
#define UDP_HEADER_SIZE 28
|
||||
|
||||
|
||||
/*
|
||||
** This class intercepts packets at the lowest level and applies delta based compression and packet combining to reduce
|
||||
** low level bandwidth while being transparent to higher levels in the application.
|
||||
**
|
||||
** All packets are prefixed by a PacketHeaderStruct which is 2 bytes long. So sending a single packet incurs an extra
|
||||
** overhead of two bytes. Normally, however, multiple small packets can be combined into a single large one which saves
|
||||
** the IP and UDP overhead invlolved in sending the subsequent packets.
|
||||
**
|
||||
*/
|
||||
class PacketManagerClass;
|
||||
class PacketManagerClass
|
||||
{
|
||||
public:
|
||||
/*
|
||||
** Constructor.
|
||||
*/
|
||||
PacketManagerClass(void);
|
||||
~PacketManagerClass(void);
|
||||
|
||||
/*
|
||||
** Application interface.
|
||||
*/
|
||||
bool Take_Packet(unsigned char *packet, int packet_len, unsigned char *dest_ip, unsigned short dest_port, SOCKET socket);
|
||||
int Get_Packet(SOCKET socket, unsigned char *packet_buffer, int packet_buffer_size, unsigned char *ip_address, unsigned short &port);
|
||||
void Flush(bool forced = false);
|
||||
void Set_Is_Server(bool is_server);
|
||||
|
||||
/*
|
||||
** Bandwidth Management.
|
||||
*/
|
||||
void Reset_Stats(void);
|
||||
void Update_Stats(bool forced = false);
|
||||
unsigned long Get_Total_Raw_Bandwidth_In(void);
|
||||
unsigned long Get_Total_Raw_Bandwidth_Out(void);
|
||||
unsigned long Get_Total_Compressed_Bandwidth_In(void);
|
||||
unsigned long Get_Total_Compressed_Bandwidth_Out(void);
|
||||
|
||||
unsigned long Get_Raw_Bandwidth_In(SOCKADDR_IN *address);
|
||||
unsigned long Get_Raw_Bandwidth_Out(SOCKADDR_IN *address);
|
||||
unsigned long Get_Compressed_Bandwidth_In(SOCKADDR_IN *address);
|
||||
unsigned long Get_Compressed_Bandwidth_Out(SOCKADDR_IN *address);
|
||||
|
||||
unsigned long Get_Raw_Bytes_Out(SOCKADDR_IN *address);
|
||||
|
||||
void Set_Stats_Sampling_Frequency_Delay(unsigned long time_ms);
|
||||
unsigned long Get_Stats_Sampling_Frequency_Delay(void) {return(StatsFrequency);};
|
||||
|
||||
|
||||
/*
|
||||
** Class configuration.
|
||||
*/
|
||||
void Set_Flush_Frequency(unsigned long freq) {FlushFrequency = freq;};
|
||||
bool Toggle_Allow_Deltas(void) {
|
||||
AllowDeltas = AllowDeltas ? false : true;
|
||||
return(AllowDeltas);
|
||||
};
|
||||
|
||||
bool Toggle_Allow_Combos(void) {
|
||||
AllowCombos = AllowCombos ? false : true;
|
||||
return(AllowCombos);
|
||||
};
|
||||
|
||||
//
|
||||
// TSS added 09/25/01
|
||||
//
|
||||
unsigned long Get_Flush_Frequency(void) {return FlushFrequency;}
|
||||
bool Get_Allow_Deltas(void) {return AllowDeltas;}
|
||||
bool Get_Allow_Combos(void) {return AllowCombos;}
|
||||
void Disable_Optimizations(void);
|
||||
|
||||
enum ErrorStateEnum {
|
||||
STATE_OK,
|
||||
STATE_WS_BUFFERS_FULL,
|
||||
};
|
||||
ErrorStateEnum Get_Error_State(void);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
** Delta compression.
|
||||
*/
|
||||
static int Build_Delta_Packet_Patch(unsigned char *base_packet, unsigned char *add_packet, unsigned char *delta_packet, int base_packet_size, int add_packet_size);
|
||||
static int Reconstruct_From_Delta(unsigned char *base_packet, unsigned char *reconstructed_packet, unsigned char *delta_packet, int base_packet_size, int &delta_size);
|
||||
bool Break_Packet(unsigned char *packet, int packet_len, unsigned char *ip_address, unsigned short port);
|
||||
|
||||
/*
|
||||
** Bit packing.
|
||||
*/
|
||||
static inline int Add_Bit(bool bit, unsigned char * &bitstream, int &position);
|
||||
static inline unsigned char Get_Bit(unsigned char * &bitstream, int &position);
|
||||
|
||||
/*
|
||||
** Buffer allocation.
|
||||
*/
|
||||
int Get_Next_Free_Buffer_Index(void);
|
||||
|
||||
/*
|
||||
** Error handling.
|
||||
*/
|
||||
void Clear_Socket_Error(SOCKET socket);
|
||||
|
||||
/*
|
||||
** Stats management.
|
||||
*/
|
||||
struct BandwidthStatsStruct {
|
||||
unsigned long IPAddress;
|
||||
unsigned short Port;
|
||||
unsigned long UncompressedBytesIn;
|
||||
unsigned long UncompressedBytesOut;
|
||||
unsigned long CompressedBytesIn;
|
||||
unsigned long CompressedBytesOut;
|
||||
unsigned long UncompressedBandwidthIn;
|
||||
unsigned long UncompressedBandwidthOut;
|
||||
unsigned long CompressedBandwidthIn;
|
||||
unsigned long CompressedBandwidthOut;
|
||||
|
||||
bool operator == (BandwidthStatsStruct const &stats);
|
||||
bool operator != (BandwidthStatsStruct const &stats);
|
||||
};
|
||||
int Get_Stats_Index(unsigned long ip_address, unsigned short port, bool can_create = true);
|
||||
void Register_Packet_In(unsigned char *ip_address, unsigned short port, unsigned long compressed_size, unsigned long uncompressed_size);
|
||||
void Register_Packet_Out(unsigned char *ip_address, unsigned short port, unsigned long compressed_size, unsigned long uncompressed_size);
|
||||
|
||||
/*
|
||||
** Send buffers.
|
||||
*/
|
||||
typedef struct tPacketBufferType {
|
||||
unsigned char Buffer [600];
|
||||
} PacketBufferType;
|
||||
|
||||
class SendBufferClass {
|
||||
public:
|
||||
PacketBufferType *PacketBuffer;
|
||||
unsigned char IPAddress[4];
|
||||
unsigned short Port;
|
||||
int PacketLength;
|
||||
bool PacketReady;
|
||||
int PacketSendLength;
|
||||
SOCKET PacketSendSocket;
|
||||
|
||||
SendBufferClass(void) {
|
||||
PacketBuffer = new PacketBufferType;
|
||||
IPAddress[0] = 0;
|
||||
IPAddress[1] = 0;
|
||||
IPAddress[2] = 0;
|
||||
IPAddress[3] = 0;
|
||||
Port = 0;
|
||||
PacketLength = 0;
|
||||
PacketReady = false;
|
||||
PacketSendLength = 0;
|
||||
PacketSendSocket = INVALID_SOCKET;
|
||||
};
|
||||
|
||||
~SendBufferClass(void) {
|
||||
delete PacketBuffer;
|
||||
PacketBuffer = NULL;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
int NumSendBuffers;
|
||||
SendBufferClass *SendBuffers;
|
||||
|
||||
//unsigned char *PacketBuffers; //[PACKET_MANAGER_BUFFERS][600];
|
||||
//unsigned char *IPAddresses; //[PACKET_MANAGER_BUFFERS][4];
|
||||
//unsigned short *Ports; //[PACKET_MANAGER_BUFFERS];
|
||||
//int *PacketLengths //[PACKET_MANAGER_BUFFERS];
|
||||
//bool *PacketReady; //[PACKET_MANAGER_BUFFERS];
|
||||
//int *PacketSendLength; //[PACKET_MANAGER_BUFFERS];
|
||||
//SOCKET *PacketSendSockets; //[PACKET_MANAGER_BUFFERS];
|
||||
|
||||
int NextPacket;
|
||||
int NumPackets;
|
||||
|
||||
unsigned char BuildPacket[PACKET_MANAGER_MTU];
|
||||
unsigned char DeltaPacket[PACKET_MANAGER_MTU + 128];
|
||||
|
||||
/*
|
||||
** Receive buffers. Don't need so many since we only process one packet at a time.
|
||||
*/
|
||||
class ReceiveBufferClass {
|
||||
public:
|
||||
unsigned char ReceiveHoldingBuffer[600];
|
||||
unsigned long ReceivePacketLength;
|
||||
};
|
||||
|
||||
int NumReceiveBuffers;
|
||||
ReceiveBufferClass *ReceiveBuffers;
|
||||
|
||||
//unsigned char ReceiveHoldingBuffers[PACKET_MANAGER_RECEIVE_BUFFERS][600];
|
||||
//unsigned long ReceivePacketLengths[PACKET_MANAGER_RECEIVE_BUFFERS];
|
||||
unsigned char ReceiveIPAddress[4];
|
||||
unsigned short ReceivePort;
|
||||
int NumReceivePackets;
|
||||
int CurrentPacket;
|
||||
SOCKET ReceiveSocket;
|
||||
|
||||
/*
|
||||
** Send timing.
|
||||
*/
|
||||
unsigned long LastSendTime;
|
||||
unsigned long FlushFrequency;
|
||||
|
||||
/*
|
||||
** Bandwidth measurement.
|
||||
*/
|
||||
DynamicVectorClass<BandwidthStatsStruct> BandwidthList;
|
||||
unsigned long TotalCompressedBandwidthIn;
|
||||
unsigned long TotalCompressedBandwidthOut;
|
||||
unsigned long TotalUncompressedBandwidthIn;
|
||||
unsigned long TotalUncompressedBandwidthOut;
|
||||
unsigned long StatsFrequency;
|
||||
unsigned long LastStatsUpdate;
|
||||
bool ResetStatsIn;
|
||||
bool ResetStatsOut;
|
||||
|
||||
/*
|
||||
** Debug
|
||||
*/
|
||||
bool AllowDeltas;
|
||||
bool AllowCombos;
|
||||
|
||||
/*
|
||||
** Winsock error handling.
|
||||
*/
|
||||
ErrorStateEnum ErrorState;
|
||||
|
||||
/*
|
||||
** Thread safety
|
||||
*/
|
||||
CriticalSectionClass CriticalSection;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Single instance of the packet manager.
|
||||
*/
|
||||
extern PacketManagerClass PacketManager;
|
||||
|
||||
#endif //_PACKETMGR_H
|
||||
Reference in New Issue
Block a user