1814 lines
No EOL
83 KiB
C++
1814 lines
No EOL
83 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/wwnet/packetmgr.cpp $*
|
|
* *
|
|
* $Author:: Steve_t $*
|
|
* *
|
|
* $Modtime:: 8/08/02 3:26p $*
|
|
* *
|
|
* $Revision:: 36 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
#include "packetmgr.h"
|
|
|
|
#include <always.h>
|
|
#include <memory.h>
|
|
//#include <winsock.h>
|
|
#include "systimer.h"
|
|
#include <malloc.h>
|
|
|
|
#include "netutil.h"
|
|
#include "wwmemlog.h"
|
|
#include "crc.h"
|
|
#include "wwprofile.h"
|
|
#include "connect.h"
|
|
|
|
/*
|
|
** Single instance of PacketManagerClass.
|
|
*/
|
|
PacketManagerClass PacketManager;
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Add_Bit -- Add a bit to a delta compressed packet stream *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Bit to add as a bool - true or false *
|
|
* Ptr to bitstream *
|
|
* Bit position at pointer *
|
|
* *
|
|
* OUTPUT: New bit position *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/24/2001 1:34PM ST : Created *
|
|
*=============================================================================================*/
|
|
inline int PacketManagerClass::Add_Bit(bool bit, unsigned char * &bitstream, int &position)
|
|
{
|
|
pm_assert(position < 8);
|
|
|
|
unsigned char whole = bit ? 1 : 0;
|
|
whole <<= position;
|
|
*bitstream |= whole;
|
|
|
|
position++;
|
|
|
|
if (position == 8) {
|
|
bitstream++;
|
|
*bitstream = 0;
|
|
position = 0;
|
|
}
|
|
|
|
return(position);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Get_Bit -- Get a bit from a delta compressed bitstream *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Ptr to bitstream *
|
|
* Bit position *
|
|
* *
|
|
* OUTPUT: 0 or 1 *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/24/2001 1:35PM ST : Created *
|
|
*=============================================================================================*/
|
|
inline unsigned char PacketManagerClass::Get_Bit(unsigned char * &bitstream, int &position)
|
|
{
|
|
pm_assert(position < 8);
|
|
|
|
unsigned char whole = *bitstream;
|
|
whole >>= position;
|
|
whole &= 1;
|
|
|
|
position++;
|
|
|
|
if (position == 8) {
|
|
bitstream++;
|
|
position = 0;
|
|
}
|
|
|
|
return(whole);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::PacketManagerClass -- Class constructor. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/24/2001 1:36PM ST : Created *
|
|
*=============================================================================================*/
|
|
PacketManagerClass::PacketManagerClass(void)
|
|
{
|
|
BandwidthList.Set_Growth_Step(128);
|
|
|
|
//memset(PacketLengths, 0, sizeof(PacketLengths));
|
|
NextPacket = 0;
|
|
NumPackets = 0;
|
|
NumReceivePackets = 0;
|
|
CurrentPacket = 0;
|
|
LastSendTime = 0;
|
|
FlushFrequency = 1000 / 10; // Default = 10 times per second.
|
|
AllowDeltas = true;
|
|
AllowCombos = true;
|
|
StatsFrequency = 10 * 1000;
|
|
LastStatsUpdate = TIMEGETTIME();
|
|
ErrorState = STATE_OK;
|
|
ResetStatsIn = true;
|
|
ResetStatsOut = true;
|
|
|
|
NumSendBuffers = PACKET_MANAGER_BUFFERS;
|
|
SendBuffers = new SendBufferClass[NumSendBuffers];
|
|
NumReceiveBuffers = PACKET_MANAGER_RECEIVE_BUFFERS;
|
|
ReceiveBuffers = new ReceiveBufferClass[NumReceiveBuffers];
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::~PacketManagerClass -- Class destructor *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/15/2001 11:24AM ST : Created *
|
|
*=============================================================================================*/
|
|
PacketManagerClass::~PacketManagerClass(void)
|
|
{
|
|
if (SendBuffers) {
|
|
delete [] SendBuffers;
|
|
SendBuffers = NULL;
|
|
}
|
|
if (ReceiveBuffers) {
|
|
delete [] ReceiveBuffers;
|
|
ReceiveBuffers = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Set_Is_Server -- Set whether to operate in server mode or not. *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: is_server - true if we are to be a server *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/15/2001 11:29AM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Set_Is_Server(bool is_server)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
WWMEMLOG(MEM_NETWORK);
|
|
bool reset = false;
|
|
|
|
if (is_server && NumSendBuffers != PACKET_MANAGER_BUFFERS_WHEN_SERVER) {
|
|
NumSendBuffers = PACKET_MANAGER_BUFFERS_WHEN_SERVER;
|
|
NumReceiveBuffers = PACKET_MANAGER_RECEIVE_BUFFERS_AS_SERVER;
|
|
reset = true;
|
|
} else {
|
|
if (!is_server && NumSendBuffers != PACKET_MANAGER_BUFFERS) {
|
|
NumSendBuffers = PACKET_MANAGER_BUFFERS;
|
|
NumReceiveBuffers = PACKET_MANAGER_RECEIVE_BUFFERS;
|
|
reset = true;
|
|
}
|
|
}
|
|
|
|
if (reset) {
|
|
NextPacket = 0;
|
|
NumPackets = 0;
|
|
NumReceivePackets = 0;
|
|
CurrentPacket = 0;
|
|
|
|
if (SendBuffers) {
|
|
delete [] SendBuffers;
|
|
}
|
|
SendBuffers = new SendBufferClass[NumSendBuffers];
|
|
|
|
if (ReceiveBuffers) {
|
|
delete [] ReceiveBuffers;
|
|
}
|
|
ReceiveBuffers = new ReceiveBufferClass[NumReceiveBuffers];
|
|
Reset_Stats();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Build_Delta_Packet_Patch -- Calc a delta between two packets *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Ptr to base packet *
|
|
* Ptr to packet to compare with base packet *
|
|
* Ptr to delta patch that describes differences between base and add packets *
|
|
* Size of base packet (packet sizes must match) *
|
|
* Size of add packet (must match base packets size) *
|
|
* *
|
|
* OUTPUT: Size of delta patch *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/24/2001 1:36PM ST : Created *
|
|
*=============================================================================================*/
|
|
int PacketManagerClass::Build_Delta_Packet_Patch(unsigned char *base_packet, unsigned char *add_packet, unsigned char *delta_packet, int base_packet_size, int add_packet_size)
|
|
{
|
|
|
|
/*
|
|
** Here's how this works.
|
|
**
|
|
** The source and delta packets are compared 8 bytes at a time and am equality bit is set in the output stream
|
|
** for each block of 8. Then, for each non-matching block, a per byte bit is set in the output stream to indicate
|
|
** whether a byte can be used from the base packet or if a patch byte is needed. Finally, patch bytes are added to
|
|
** the stream at the end starting at a byte boundry.
|
|
**
|
|
*/
|
|
|
|
|
|
/*
|
|
** Locals.
|
|
*/
|
|
int write_bit_pos = 0;
|
|
int read_bit_pos = 0;
|
|
int num_diff_bytes = 0;
|
|
unsigned char diff_bytes[1024];
|
|
|
|
/*
|
|
** Parameter asserts.
|
|
*/
|
|
pm_assert(base_packet != NULL);
|
|
pm_assert(add_packet != NULL);
|
|
pm_assert(delta_packet != NULL);
|
|
pm_assert(base_packet_size == add_packet_size);
|
|
pm_assert(base_packet_size < sizeof(diff_bytes));
|
|
|
|
/*
|
|
** dereference pointers to the packet header and the packet build pointer.
|
|
*/
|
|
PacketDeltaHeaderStruct *header = (PacketDeltaHeaderStruct*) delta_packet;
|
|
unsigned char *build_delta_ptr = delta_packet + sizeof(PacketDeltaHeaderStruct);
|
|
unsigned char *chunk_ptr = build_delta_ptr;
|
|
pm_assert(sizeof(PacketDeltaHeaderStruct) == 1);
|
|
*build_delta_ptr = 0;
|
|
|
|
header->BytePack = 0;
|
|
|
|
if (base_packet_size == add_packet_size) {
|
|
|
|
/*
|
|
** Break it up into 8 byte chunks and see whether any of the chunks are the same.
|
|
*/
|
|
bool chunks = false;
|
|
bool this_match = false;
|
|
|
|
for (int i=0 ; i<base_packet_size - 7 ; i+=8) {
|
|
|
|
this_match = false;
|
|
|
|
if (*((long*)&base_packet[i]) == *((long*)&add_packet[i])) {
|
|
if (*((long*)&base_packet[i+4]) == *((long*)&add_packet[i+4])) {
|
|
chunks = true;
|
|
this_match = true;
|
|
}
|
|
}
|
|
|
|
write_bit_pos = Add_Bit(this_match, build_delta_ptr, write_bit_pos);
|
|
}
|
|
|
|
/*
|
|
** Mark the tail end of the buffer as different.
|
|
*/
|
|
if ((base_packet_size & 7) != 0) {
|
|
if (chunks) {
|
|
write_bit_pos = Add_Bit(false, build_delta_ptr, write_bit_pos);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If none of the chunks were the same then this is a pointless endevour. Mark in the header that we don't have
|
|
** chunk info and move on to trying byte for byte.
|
|
*/
|
|
header->ChunkPack = chunks ? 1 : 0;
|
|
|
|
/*
|
|
** Lost the useless chunk info if none of the chunks matched anyway.
|
|
*/
|
|
if (!chunks) {
|
|
build_delta_ptr = chunk_ptr;
|
|
*build_delta_ptr = 0;
|
|
write_bit_pos = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
** Try a byte for byte check in the chunks that don't match. For any bytes that are different, save the changed value
|
|
** so we can add it to the end of the delta packet later.
|
|
*/
|
|
read_bit_pos = 0;
|
|
num_diff_bytes = 0;
|
|
for (i=0 ; i<base_packet_size ; i+= 8) {
|
|
|
|
/*
|
|
** If we have chunk info, then use it to skip matching chunks.
|
|
*/
|
|
if (chunks) {
|
|
if (Get_Bit(chunk_ptr, read_bit_pos)) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If this chunk didn't match then go through byte by byte and note differences.
|
|
*/
|
|
for (int j=i ; j<i+8 && j<base_packet_size ; j++) {
|
|
header->BytePack = 1;
|
|
this_match = (base_packet[j] == add_packet[j]) ? true : false;
|
|
write_bit_pos = Add_Bit(this_match, build_delta_ptr, write_bit_pos);
|
|
if (!this_match) {
|
|
diff_bytes[num_diff_bytes++] = add_packet[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** OK, now we have bitfields that mark the differences. A 1 in the bitfield means that the corresponding chunk or byte
|
|
** in the add packet is the same as in the base packet.
|
|
** Throw the non-matching bytes onto the end of the bitfield and we have a complete delta patch.
|
|
*/
|
|
unsigned char *delta_bytes_ptr = build_delta_ptr;
|
|
if (write_bit_pos != 0) {
|
|
delta_bytes_ptr++;
|
|
}
|
|
memcpy(delta_bytes_ptr, diff_bytes, num_diff_bytes);
|
|
|
|
/*
|
|
** Calculate the size of the whole delta patch.
|
|
*/
|
|
int patch_size = (delta_bytes_ptr - delta_packet) + num_diff_bytes;
|
|
|
|
return(patch_size);
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Reconstruct_From_Delta -- Rebuild a packet from a delta stream *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Base packet to copy same bytes from *
|
|
* Buffer to store reconstructed packet into *
|
|
* Ptr to delta packet stream. *
|
|
* Size of base packet *
|
|
* (out) bytes extracted from delta stream *
|
|
* *
|
|
* OUTPUT: Size of restored packet (should match size of base packet) *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/26/2001 2:14PM ST : Created *
|
|
*=============================================================================================*/
|
|
int PacketManagerClass::Reconstruct_From_Delta(unsigned char *base_packet, unsigned char *reconstructed_packet, unsigned char *delta_packet, int base_packet_size, int &delta_size)
|
|
{
|
|
if (base_packet == NULL) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Reconstruct_From_Delta -- Bad base packet\n"));
|
|
return(0);
|
|
}
|
|
|
|
if (reconstructed_packet == NULL) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Reconstruct_From_Delta -- Bad reconstructed packet\n"));
|
|
return(0);
|
|
}
|
|
|
|
if (delta_packet == NULL) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Reconstruct_From_Delta -- Bad delta packet\n"));
|
|
return(0);
|
|
}
|
|
|
|
if (base_packet_size > 500) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Reconstruct_From_Delta -- Bad base packet size\n"));
|
|
return(0);
|
|
}
|
|
|
|
|
|
pm_assert(base_packet != NULL);
|
|
pm_assert(reconstructed_packet != NULL);
|
|
pm_assert(delta_packet != NULL);
|
|
int patch_list[1024];
|
|
int num_patches = 0;
|
|
int read_bit_pos = 0;
|
|
int read_chunk_pos = 0;
|
|
int restored_bytes = 0;
|
|
|
|
PacketDeltaHeaderStruct *header = (PacketDeltaHeaderStruct*) delta_packet;
|
|
unsigned char *read_delta_ptr = delta_packet + sizeof(PacketDeltaHeaderStruct);
|
|
pm_assert(sizeof(PacketDeltaHeaderStruct) == 1);
|
|
unsigned char *chunk_ptr = read_delta_ptr;
|
|
|
|
/*
|
|
** If there is chunk info then extract that first. Use it to copy the approprate parts of the base packet into the add packet.
|
|
*/
|
|
if (header->ChunkPack) {
|
|
for (int i=0 ; i<base_packet_size - 7 ; i+=8) {
|
|
if (Get_Bit(read_delta_ptr, read_bit_pos)) {
|
|
memcpy(&reconstructed_packet[i], &base_packet[i], 8);
|
|
restored_bytes += 8;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If the packet isn't an even number of chunks long then pull out an extra bit and throw it away. It should always be 0.
|
|
*/
|
|
if ((base_packet_size & 7) != 0) {
|
|
//#ifdef WWDEBUG
|
|
unsigned char bitty =
|
|
//#endif //WWDEBUG
|
|
Get_Bit(read_delta_ptr, read_bit_pos);
|
|
if (bitty != 0) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Reconstruct_From_Delta -- Bad bitty\n"));
|
|
return(0);
|
|
}
|
|
pm_assert(bitty == 0);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Now use the per byte bitmask to restore the rest of the data.
|
|
*/
|
|
for (int i=0 ; i<base_packet_size ; i+= 8) {
|
|
|
|
/*
|
|
** If we have chunk info, then use it to skip matching chunks.
|
|
*/
|
|
if (header->ChunkPack) {
|
|
if (Get_Bit(chunk_ptr, read_chunk_pos)) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If this chunk didn't match then go through byte by byte and note differences.
|
|
*/
|
|
for (int j=i ; j<i+8 && j<base_packet_size ; j++) {
|
|
if (Get_Bit(read_delta_ptr, read_bit_pos)) {
|
|
reconstructed_packet[j] = base_packet[j];
|
|
restored_bytes++;
|
|
} else {
|
|
patch_list[num_patches++] = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Well, the patch bytes must be here somewhere.
|
|
*/
|
|
unsigned char *patch_bytes = read_delta_ptr;
|
|
if (read_bit_pos != 0) {
|
|
patch_bytes++;
|
|
}
|
|
|
|
/*
|
|
** Work out how many delta bytes we processed - it's needed for meta packet decoding.
|
|
*/
|
|
delta_size = (patch_bytes - delta_packet) + num_patches;
|
|
|
|
/*
|
|
** Copy the patch bytes into the correct positions.
|
|
*/
|
|
for (int p=0 ; p<num_patches ; p++) {
|
|
reconstructed_packet[patch_list[p]] = *patch_bytes++;
|
|
}
|
|
|
|
restored_bytes += num_patches;
|
|
//pm_assert(restored_bytes == base_packet_size);
|
|
|
|
return(restored_bytes);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Get_Next_Free_Buffer_Index -- Get next buffer to use for taking packets *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Buffer index (-1 if none free) *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/26/2001 2:17PM ST : Created *
|
|
*=============================================================================================*/
|
|
int PacketManagerClass::Get_Next_Free_Buffer_Index(void)
|
|
{
|
|
int return_index = -1;
|
|
for (int i=0 ; i<NumSendBuffers ; i++) {
|
|
NextPacket++;
|
|
if (NextPacket >= NumSendBuffers) {
|
|
NextPacket = 0;
|
|
}
|
|
if (SendBuffers[NextPacket].PacketLength == 0) {
|
|
return_index = NextPacket;
|
|
break;
|
|
}
|
|
}
|
|
return(return_index);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Take_Packet -- Intercept a packet before it's sent *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Ptr to packet *
|
|
* Length of packet *
|
|
* IP of packet recipient *
|
|
* Port of packet recipient *
|
|
* *
|
|
* OUTPUT: True if packet was accepted *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/18/2001 4:24PM ST : Created *
|
|
*=============================================================================================*/
|
|
bool PacketManagerClass::Take_Packet(unsigned char *packet, int packet_len, unsigned char *dest_ip, unsigned short dest_port, SOCKET source_socket)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
|
|
if (NumPackets < NumSendBuffers) {
|
|
if (packet_len > 0 && packet_len < (PACKET_MANAGER_MTU - sizeof(PacketPackHeaderStruct))) {
|
|
int index = Get_Next_Free_Buffer_Index();
|
|
if (index != -1) {
|
|
memcpy(SendBuffers[index].PacketBuffer, packet, packet_len);
|
|
SendBuffers[index].PacketLength = packet_len;
|
|
SendBuffers[index].Port = dest_port;
|
|
memcpy(&SendBuffers[index].IPAddress[0], dest_ip, 4);
|
|
SendBuffers[index].PacketSendSocket = source_socket;
|
|
NumPackets++;
|
|
//WWDEBUG_SAY(("NumPackets = %d (added packet at index %d)\n", NumPackets, index));
|
|
if (NumPackets > NumSendBuffers - 4) {
|
|
WWDEBUG_SAY(("***WARNING*** Outgoing packet buffer full - NumPackets = %d\n", NumPackets, index));
|
|
Flush(true);
|
|
WWDEBUG_SAY(("NumPackets = %d after flush\n", NumPackets, index));
|
|
}
|
|
Register_Packet_Out(dest_ip, dest_port, 0, packet_len + UDP_HEADER_SIZE);
|
|
return(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Flush -- Coalesce and send any pending packets *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Forced - set to true if packets should be sent even if it's not time *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/26/2001 2:19PM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Flush(bool forced)
|
|
{
|
|
{
|
|
WWPROFILE("PMgr Flush");
|
|
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
|
|
int base_index = -1;
|
|
int length = 0;
|
|
unsigned char *base_packet = NULL;
|
|
int new_length = 0;
|
|
PacketPackHeaderStruct *header = (PacketPackHeaderStruct*) BuildPacket;
|
|
unsigned char *next_packet_pos = NULL;
|
|
int index = 0;
|
|
int i;
|
|
SOCKET socket = INVALID_SOCKET;
|
|
|
|
/*
|
|
** If it's not time to send packets yet then just return.
|
|
*/
|
|
unsigned long time = TIMEGETTIME();
|
|
if (!forced && FlushFrequency != 0) {
|
|
if (time - LastSendTime < FlushFrequency) {
|
|
return;
|
|
}
|
|
}
|
|
LastSendTime = time;
|
|
|
|
//WWDEBUG_SAY(("NumPackets = %d\n", NumPackets));
|
|
|
|
/*
|
|
** Clear the array that indicates whether a packet is ready to be sent.
|
|
*/
|
|
for (i=0 ; i<NumSendBuffers ; i++) {
|
|
SendBuffers[i].PacketReady = false;
|
|
}
|
|
|
|
/*
|
|
** Loop until we process all packets.
|
|
*/
|
|
while (NumPackets) {
|
|
|
|
/*
|
|
** Get a packet to start with. Find the oldest packet first in each case.
|
|
*/
|
|
index = NextPacket + 1;
|
|
if (index >= NumSendBuffers) {
|
|
index = 0;
|
|
}
|
|
base_index = -1;
|
|
for (i=0 ; i<NumSendBuffers ; i++) {
|
|
if (SendBuffers[index].PacketLength != 0) {
|
|
base_index = index;
|
|
length = SendBuffers[index].PacketLength;
|
|
base_packet = (unsigned char *) SendBuffers[index].PacketBuffer;
|
|
//WWDEBUG_SAY(("Found base packet %d\n", base_index));
|
|
|
|
socket = SendBuffers[index].PacketSendSocket;
|
|
header->NumPackets = 1;
|
|
header->PacketSize = length;
|
|
header->MorePackets = 0;
|
|
pm_assert(header->NumPackets > 0 && header->NumPackets <= PACKET_MANAGER_MAX_PACKETS);
|
|
next_packet_pos = BuildPacket + sizeof(*header);
|
|
memcpy(next_packet_pos, base_packet, length);
|
|
next_packet_pos += length;
|
|
new_length = length + sizeof(*header);
|
|
//WWDEBUG_SAY(("Added base packet %d to metapacket - %d (+2) bytes\n", index, length));
|
|
index++;
|
|
if (index >= NumSendBuffers) {
|
|
index = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
index++;
|
|
if (index >= NumSendBuffers) {
|
|
index = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If we found a packet, see if there are more packets of the same size that we can package up with it.
|
|
*/
|
|
if (base_index != -1 && NumPackets > 1) {
|
|
if ((new_length + length + sizeof(PacketDeltaHeaderStruct)) < PACKET_MANAGER_MTU) {
|
|
|
|
for (int j=i ; j<NumSendBuffers ; j++) {
|
|
|
|
/*
|
|
** If we can't fit any more packets in this packet then break out of the loop and send it as is.
|
|
*/
|
|
if (header->NumPackets == PACKET_MANAGER_MAX_PACKETS) {
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** Is this packet the same length? If so, it might be suitable for coagulation.
|
|
*/
|
|
if (SendBuffers[index].PacketLength == length && SendBuffers[index].PacketSendSocket == socket) {
|
|
pm_assert(index != base_index);
|
|
|
|
/*
|
|
** Is this packet for the same recipient?
|
|
*/
|
|
if (SendBuffers[base_index].Port == SendBuffers[index].Port && (*(unsigned long*)(&SendBuffers[index].IPAddress[0])) == (*(unsigned long*)(&SendBuffers[base_index].IPAddress[0]))) {
|
|
|
|
//WWDEBUG_SAY(("Found secondary packet %d\n", index));
|
|
|
|
/*
|
|
** See if using a delta of the two packets would be smaller than including the whole packet.
|
|
*/
|
|
int bytes = Build_Delta_Packet_Patch(base_packet, SendBuffers[index].PacketBuffer->Buffer, DeltaPacket, length, length);
|
|
if (bytes < length && AllowDeltas) {
|
|
/*
|
|
** Yes, the delta is smaller so use that.
|
|
*/
|
|
memcpy(next_packet_pos, DeltaPacket, bytes);
|
|
next_packet_pos += bytes;
|
|
new_length += bytes;
|
|
//WWDEBUG_SAY(("Added delta packet %d to metapacket - %d bytes\n", index, bytes));
|
|
header->NumPackets++;
|
|
pm_assert(header->NumPackets > 0 && header->NumPackets <= PACKET_MANAGER_MAX_PACKETS);
|
|
} else {
|
|
/*
|
|
** The delta was no better than the original. Stick a 0 byte in to say it's not a delta and then
|
|
** Copy the whole thing.
|
|
*/
|
|
PacketDeltaHeaderStruct *delta_header = (PacketDeltaHeaderStruct*) next_packet_pos;
|
|
delta_header->ChunkPack = 0;
|
|
delta_header->BytePack = 0;
|
|
next_packet_pos += sizeof(PacketDeltaHeaderStruct);
|
|
new_length += sizeof(PacketDeltaHeaderStruct);
|
|
|
|
memcpy(next_packet_pos, SendBuffers[index].PacketBuffer, length);
|
|
next_packet_pos += length;
|
|
new_length += length;
|
|
//WWDEBUG_SAY(("Added secondary packet %d to metapacket - %d (+1) bytes\n", index, length));
|
|
header->NumPackets++;
|
|
pm_assert(header->NumPackets > 0 && header->NumPackets <= PACKET_MANAGER_MAX_PACKETS);
|
|
}
|
|
|
|
/*
|
|
** Discard the packet buffer now that we have added this packet to the current staging buffer area.
|
|
*/
|
|
SendBuffers[index].PacketLength = 0;
|
|
NumPackets--;
|
|
//WWDEBUG_SAY(("NumPackets = %d (discarding secondary packet index %d)\n", NumPackets, index));
|
|
|
|
pm_assert(header->NumPackets > 0 && header->NumPackets <= PACKET_MANAGER_MAX_PACKETS);
|
|
|
|
/*
|
|
** If there's no room for any more of these packets then bail out.
|
|
*/
|
|
if ((new_length + length + sizeof(PacketDeltaHeaderStruct)) >= PACKET_MANAGER_MTU) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
index++;
|
|
if (index >= NumSendBuffers) {
|
|
index = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pm_assert(header->NumPackets > 0 && header->NumPackets <= PACKET_MANAGER_MAX_PACKETS);
|
|
|
|
/*
|
|
** Allright, it's time to send this sucker.
|
|
*/
|
|
if (base_index != -1) {
|
|
|
|
/*
|
|
** Just copy it back into the base index for now and mark it as ready to go.
|
|
*/
|
|
memcpy(SendBuffers[base_index].PacketBuffer, BuildPacket, new_length);
|
|
SendBuffers[base_index].PacketReady = true;
|
|
SendBuffers[base_index].PacketSendLength = new_length;
|
|
SendBuffers[base_index].PacketLength = 0;
|
|
NumPackets--;
|
|
//WWDEBUG_SAY(("NumPackets = %d (discarding base packet %d)\n", NumPackets, base_index));
|
|
pm_assert(NumPackets >= 0);
|
|
}
|
|
pm_assert(header->NumPackets > 0 && header->NumPackets <= PACKET_MANAGER_MAX_PACKETS);
|
|
}
|
|
|
|
|
|
/*
|
|
** Merge ready buffers where possible. This is the step that adds runs of different sizeed packets into the same packet.
|
|
*/
|
|
if (AllowCombos) {
|
|
for (i=0 ; i<NumSendBuffers ; i++) {
|
|
if (SendBuffers[i].PacketReady) {
|
|
|
|
PacketPackHeaderStruct *current_header = (PacketPackHeaderStruct*) SendBuffers[i].PacketBuffer;
|
|
int current_len = SendBuffers[i].PacketSendLength;
|
|
socket = SendBuffers[i].PacketSendSocket;
|
|
|
|
|
|
/*
|
|
** See if we can find another packet for the same destination that will fit into the same buffer.
|
|
*/
|
|
#ifdef WWDEBUG
|
|
int num_sub_packets = 1;
|
|
#endif //WWDEBUG
|
|
for (int j=i+1 ; j<NumSendBuffers ; j++) {
|
|
if (SendBuffers[j].PacketReady && SendBuffers[j].PacketSendSocket == socket) {
|
|
if (SendBuffers[i].PacketSendLength + SendBuffers[j].PacketSendLength < PACKET_MANAGER_MTU) {
|
|
if (SendBuffers[i].Port == SendBuffers[j].Port && (*(unsigned long*)(&SendBuffers[i].IPAddress[0])) == (*(unsigned long*)(&SendBuffers[j].IPAddress[0]))) {
|
|
unsigned char *dest_ptr = &SendBuffers[i].PacketBuffer->Buffer[current_len];
|
|
memcpy(dest_ptr, SendBuffers[j].PacketBuffer, SendBuffers[j].PacketSendLength);
|
|
current_header->MorePackets = 1;
|
|
current_header = (PacketPackHeaderStruct*) dest_ptr;
|
|
current_len += SendBuffers[j].PacketSendLength;
|
|
SendBuffers[i].PacketSendLength = current_len;
|
|
SendBuffers[j].PacketReady = false;
|
|
#ifdef WWDEBUG
|
|
num_sub_packets++;
|
|
#endif //WWDEBUG
|
|
//WWDEBUG_SAY(("Added packet %d with %d sub packets to packet %d\n", j, ((PacketPackHeaderStruct*)&PacketBuffers[j][0])->NumPackets, i));
|
|
//WWDEBUG_SAY(("Packet %d has %d packets total\n", i, num_sub_packets));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Send any packets marked as ready.
|
|
*/
|
|
for (i=0 ; i<NumSendBuffers ; i++) {
|
|
if (SendBuffers[i].PacketReady) {
|
|
sockaddr_in addr;
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = SendBuffers[i].Port;
|
|
memcpy (&addr.sin_addr.s_addr, &SendBuffers[i].IPAddress[0], 4);
|
|
socket = SendBuffers[i].PacketSendSocket;
|
|
#ifdef WWDEBUG
|
|
int debug_num_packets = (int)(((PacketPackHeaderStruct*)SendBuffers[i].PacketBuffer)->NumPackets);
|
|
int debug_packet_size = (int)(((PacketPackHeaderStruct*)SendBuffers[i].PacketBuffer)->PacketSize);
|
|
pm_assert(debug_num_packets > 0);
|
|
pm_assert(debug_packet_size < PACKET_MANAGER_MTU);
|
|
pm_assert(SendBuffers[i].PacketSendLength < PACKET_MANAGER_MTU);
|
|
//WWDEBUG_SAY(("Sending packet %d (%d bytes) to %s. Packet has %d packets of %d bytes each\n", i, PacketSendLength[i], Addr_As_String(&addr), debug_num_packets, debug_packet_size));
|
|
#endif //WWDEBUG
|
|
|
|
|
|
#ifdef WRAPPER_CRC
|
|
|
|
unsigned long crc = CRC::Memory((unsigned char*)SendBuffers[i].PacketBuffer, SendBuffers[i].PacketSendLength);
|
|
#if (1)
|
|
/*
|
|
** Reverse byte order to prevent the demo from having the same CRC as the game.
|
|
*/
|
|
_asm {
|
|
push eax;
|
|
mov eax,crc;
|
|
bswap eax;
|
|
mov crc,eax;
|
|
pop eax;
|
|
};
|
|
#endif //(0)
|
|
char *crc_and_buffer = (char*)_alloca(SendBuffers[i].PacketSendLength + sizeof(crc));
|
|
*((unsigned long*) crc_and_buffer) = crc;
|
|
memcpy(crc_and_buffer + sizeof(crc), (const char*)SendBuffers[i].PacketBuffer, SendBuffers[i].PacketSendLength);
|
|
|
|
Register_Packet_Out(&SendBuffers[i].IPAddress[0], SendBuffers[i].Port, SendBuffers[i].PacketSendLength + UDP_HEADER_SIZE + sizeof(crc), 0);
|
|
int result = sendto(socket, crc_and_buffer, SendBuffers[i].PacketSendLength + sizeof(crc), 0, (LPSOCKADDR) &addr, sizeof(SOCKADDR_IN));
|
|
|
|
#else //WRAPPER_CRC
|
|
|
|
Register_Packet_Out(&SendBuffers[i].IPAddress[0], SendBuffers[i].Port, SendBuffers[i].PacketSendLength + UDP_HEADER_SIZE, 0);
|
|
int result = sendto(socket, (const char*)SendBuffers[i].PacketBuffer, SendBuffers[i].PacketSendLength, 0, (LPSOCKADDR) &addr, sizeof(SOCKADDR_IN));
|
|
|
|
#endif //WRAPPER_CRC
|
|
|
|
|
|
if (result == SOCKET_ERROR){
|
|
if (WSAGetLastError() != WSAEWOULDBLOCK) {
|
|
int error_code = 0;
|
|
error_code = WSAGetLastError();// avoid release build compiler warning
|
|
WWDEBUG_SAY(("PacketManagerClass - sendto returned error code %d - %s\n", error_code, cNetUtil::Winsock_Error_Text(error_code)));
|
|
Clear_Socket_Error(socket);
|
|
} else {
|
|
|
|
/*
|
|
** No more room for outgoing packets. Unfortunately, this means we lose the lot.
|
|
*/
|
|
WWDEBUG_SAY(("PacketManagerClass - sendto returned WSAEWOULDBLOCK\n"));
|
|
Sleep(0);
|
|
ErrorState = STATE_WS_BUFFERS_FULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Send some random garbage to see if we crash.
|
|
*/
|
|
//char garbage[640];
|
|
//for (int i=0 ; i<540 ; i++) {
|
|
// garbage[i] = rand();
|
|
//}
|
|
//sendto(socket, (const char*)garbage, 540, 0, (LPSOCKADDR) &addr, sizeof(SOCKADDR_IN));
|
|
|
|
}
|
|
}
|
|
Update_Stats();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Disable_Optimizations -- Disable all low level optimizations *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/26/2001 2:24PM TSS : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Disable_Optimizations(void)
|
|
{
|
|
FlushFrequency = 0;
|
|
AllowDeltas = false;
|
|
AllowCombos = false;
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Break_Packet -- Break up in incoming packet into it's original packets *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/26/2001 2:25PM ST : Created *
|
|
*=============================================================================================*/
|
|
bool PacketManagerClass::Break_Packet(unsigned char *packet, int original_packet_size, unsigned char *ip_address, unsigned short port)
|
|
{
|
|
/*
|
|
** Dereference a pointer to the packet header.
|
|
*/
|
|
PacketPackHeaderStruct *header = (PacketPackHeaderStruct*) packet;
|
|
|
|
/*
|
|
** Pull out the number of packets and the size of each.
|
|
*/
|
|
int num_packets = header->NumPackets;
|
|
int packet_size = header->PacketSize;
|
|
bool more_packets = header->MorePackets;
|
|
|
|
if (num_packets < 1 || packet_size > PACKET_MANAGER_MTU) {
|
|
WWDEBUG_SAY(("PacketManager - Packet decode error. num_packets = %d\n, packet_size = %d\n", num_packets, packet_size));
|
|
return(false);
|
|
}
|
|
pm_assert(num_packets >= 1);
|
|
pm_assert(packet_size <= PACKET_MANAGER_MTU);
|
|
|
|
/*
|
|
** Get the first packet. This is needed as a reference for other delta packets.
|
|
*/
|
|
unsigned char *packet_ptr = packet + sizeof(*header);
|
|
memcpy(&ReceiveBuffers[NumReceivePackets].ReceiveHoldingBuffer[0], packet_ptr, packet_size);
|
|
ReceiveBuffers[NumReceivePackets].ReceivePacketLength = packet_size;
|
|
Register_Packet_In(ip_address, port, 0, packet_size + UDP_HEADER_SIZE);
|
|
int delta_base_index = NumReceivePackets;
|
|
memcpy(ReceiveIPAddress, ip_address, 4);
|
|
ReceivePort = port;
|
|
NumReceivePackets++;
|
|
//WWDEBUG_SAY(("Extracted base packet from metapacket - %d bytes\n", packet_size));
|
|
|
|
packet_ptr += packet_size;
|
|
|
|
/*
|
|
** Get the rest of the packets.
|
|
*/
|
|
for (int i=0 ; i<num_packets-1 ; i++) {
|
|
PacketDeltaHeaderStruct * delta_header = (PacketDeltaHeaderStruct*) packet_ptr;
|
|
|
|
/*
|
|
** If this is a delta packet then we need to reconstruct it before copying it into the buffer.
|
|
*/
|
|
if (delta_header->ChunkPack || delta_header->BytePack) {
|
|
int delta_size = 0;
|
|
//#ifdef WWDEBUG
|
|
int bytes =
|
|
//#endif //WWDEBUG
|
|
Reconstruct_From_Delta(&ReceiveBuffers[delta_base_index].ReceiveHoldingBuffer[0], &ReceiveBuffers[NumReceivePackets].ReceiveHoldingBuffer[0], (unsigned char *)delta_header, packet_size, delta_size);
|
|
if (bytes != packet_size) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Break_Packet -- bytes != packet_size\n"));
|
|
return(false);
|
|
}
|
|
if (delta_size <= 0) {
|
|
WWDEBUG_SAY(("*** WARNING: MALFORMED PACKET - PacketManagerClass::Break_Packet -- delta_size <= 0\n"));
|
|
return(false);
|
|
}
|
|
pm_assert(bytes == packet_size);
|
|
pm_assert(delta_size > 0);
|
|
ReceiveBuffers[NumReceivePackets].ReceivePacketLength = packet_size;
|
|
NumReceivePackets++;
|
|
packet_ptr += delta_size;
|
|
Register_Packet_In(ip_address, port, 0, packet_size + UDP_HEADER_SIZE);
|
|
//WWDEBUG_SAY(("Extracted delta packet from metapacket - %d bytes (delta size = %d)\n", bytes, delta_size));
|
|
} else {
|
|
/*
|
|
** Not a delta, just copy the whole thing.
|
|
*/
|
|
packet_ptr += sizeof(*delta_header);
|
|
memcpy(&ReceiveBuffers[NumReceivePackets].ReceiveHoldingBuffer[0], packet_ptr, packet_size);
|
|
ReceiveBuffers[NumReceivePackets].ReceivePacketLength = packet_size;
|
|
packet_ptr += packet_size;
|
|
NumReceivePackets++;
|
|
Register_Packet_In(ip_address, port, 0, packet_size + UDP_HEADER_SIZE);
|
|
//WWDEBUG_SAY(("Extracted secondary packet from metapacket - %d (+1) bytes\n", PacketLength));
|
|
}
|
|
if (NumReceivePackets >= PACKET_MANAGER_RECEIVE_BUFFERS) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
int bytes_pulled_from_packet = packet_ptr - packet;
|
|
|
|
/*
|
|
** More packets in this buffer?
|
|
*/
|
|
if (more_packets && NumReceivePackets < PACKET_MANAGER_RECEIVE_BUFFERS) {
|
|
if (!Break_Packet(packet_ptr, original_packet_size - bytes_pulled_from_packet, ip_address, port)) {
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
//if (NumReceivePackets > 20) {
|
|
// WWDEBUG_SAY(("Sub packet broken into %d packets\n", NumReceivePackets));
|
|
//}
|
|
|
|
return(true);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Clear_Socket_Error -- Clear an error condition on a socket *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Socket *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/17/2001 12:19PM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Clear_Socket_Error(SOCKET socket)
|
|
{
|
|
unsigned long error_code;
|
|
int length = 4;
|
|
assert(socket != INVALID_SOCKET);
|
|
|
|
if (socket != INVALID_SOCKET) {
|
|
getsockopt (socket, SOL_SOCKET, SO_ERROR, (char*)&error_code, &length);
|
|
WWDEBUG_SAY(("Per socket error is %d - %s\n", error_code, cNetUtil::Winsock_Error_Text(error_code)));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Get_Packet -- Return the next incoming packet to the app *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Socket to use *
|
|
* Ptr to packet buffer *
|
|
* Size of packet buffer *
|
|
* (out) Ptr to ip_address *
|
|
* (out) Port number *
|
|
* *
|
|
* OUTPUT: Size of packet (0 = no packet, -1 = fatal socket error) *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 9/26/2001 2:28PM ST : Created *
|
|
*=============================================================================================*/
|
|
int PacketManagerClass::Get_Packet(SOCKET socket, unsigned char *packet_buffer, int packet_buffer_size, unsigned char *ip_address, unsigned short &port)
|
|
{
|
|
{
|
|
WWPROFILE("Pmgr Get");
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
|
|
if (NumReceivePackets == 0) {
|
|
int address_size = sizeof(sockaddr_in);
|
|
sockaddr_in addr;
|
|
memset(&addr, 0, sizeof(addr));
|
|
pm_assert(packet_buffer_size >= PACKET_MANAGER_MTU);
|
|
int bytes;
|
|
int result = ioctlsocket(socket, FIONREAD, (unsigned long *)&bytes);
|
|
if (result == 0 && bytes != 0) {
|
|
|
|
bytes = recvfrom(socket, (char*)packet_buffer, packet_buffer_size, 0, (LPSOCKADDR) &addr, &address_size);
|
|
if (bytes > 0) {
|
|
#ifndef WRAPPER_CRC
|
|
Register_Packet_In((unsigned char*) &addr.sin_addr.s_addr, addr.sin_port, bytes + UDP_HEADER_SIZE, 0);
|
|
#endif //WRAPPER_CRC
|
|
|
|
#ifdef WRAPPER_CRC
|
|
unsigned long crc = CRC::Memory((unsigned char*)packet_buffer + 4, bytes - sizeof(crc));
|
|
#if (1)
|
|
/*
|
|
** Reverse byte order to prevent the demo from having the same CRC as the game.
|
|
*/
|
|
_asm {
|
|
push eax;
|
|
mov eax,crc;
|
|
bswap eax;
|
|
mov crc,eax;
|
|
pop eax;
|
|
};
|
|
#endif //(0)
|
|
if (crc != *((unsigned long*)packet_buffer)) {
|
|
WWDEBUG_SAY(("PMC::Get_Packet: Socket %d, received packet %d bytes long from %s\n", socket, bytes, Addr_As_String(&addr)));
|
|
WWDEBUG_SAY(("PMC::Get_Packet: *** PACKET WRAPPER CRC ERROR ***"));
|
|
NumReceivePackets = 0;
|
|
} else {
|
|
Register_Packet_In((unsigned char*) &addr.sin_addr.s_addr, addr.sin_port, bytes + UDP_HEADER_SIZE, 0);
|
|
bytes -= sizeof(crc);
|
|
memmove(packet_buffer, packet_buffer + sizeof(crc), bytes);
|
|
#endif //WRAPPER_CRC
|
|
|
|
//WWDEBUG_SAY(("PMC::Get_Packet: Socket %d, received packet %d bytes long from %s\n", socket, bytes, Addr_As_String(&addr)));
|
|
ReceiveSocket = socket;
|
|
//WWDEBUG_SAY(("Breaking packet %d bytes long from %s\n", bytes, Addr_As_String(&addr)));
|
|
bool broken = Break_Packet(packet_buffer, bytes, (unsigned char*) &addr.sin_addr.s_addr, addr.sin_port);
|
|
if (!broken) {
|
|
WWDEBUG_SAY(("Failed to break packet %d bytes long from %s\n", bytes, Addr_As_String(&addr)));
|
|
WWDEBUG_SAY(("Discarding %d suspect packets due to decode failure\n", NumReceivePackets));
|
|
NumReceivePackets = 0;
|
|
} else {
|
|
//WWDEBUG_SAY(("PMC::Get_Packet: Packet broken into %d packets\n", NumReceivePackets));
|
|
}
|
|
CurrentPacket = 0;
|
|
#ifdef WRAPPER_CRC
|
|
}
|
|
#endif //WRAPPER_CRC
|
|
} else {
|
|
if (bytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
|
|
int error_code = 0;
|
|
error_code = WSAGetLastError();// avoid release build compiler warning
|
|
WWDEBUG_SAY(("PacketManagerClass - recvfrom failed with error %d - %s\n", error_code, cNetUtil::Winsock_Error_Text(error_code)));
|
|
Clear_Socket_Error(socket);
|
|
if (error_code == WSAECONNRESET) {
|
|
WWDEBUG_SAY(("PacketManagerClass - WSAECONNRESET from address %s\n", Addr_As_String(&addr)));
|
|
memcpy(ip_address, &addr.sin_addr.s_addr, 4);
|
|
port = addr.sin_port;
|
|
return(-1);
|
|
}
|
|
} else {
|
|
WWDEBUG_SAY(("PacketManagerClass - recvfrom failed with error WSAEWOULDBLOCK\n", WSAGetLastError()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CurrentPacket < NumReceivePackets && socket == ReceiveSocket) {
|
|
/*
|
|
** Copy the current packet into the return buffer. We have to zero out the rest of the buffer or the CRC won't come out
|
|
** right. Lordy. FIxed in CRC code now ST - 9/24/2001 3:36PM
|
|
*/
|
|
int size = (int)ReceiveBuffers[CurrentPacket].ReceivePacketLength;
|
|
memcpy(packet_buffer, &ReceiveBuffers[CurrentPacket].ReceiveHoldingBuffer[0], min(size, packet_buffer_size));
|
|
//if (size < packet_buffer_size) {
|
|
// memset(packet_buffer + size, 0, packet_buffer_size - size);
|
|
//}
|
|
memcpy(ip_address, ReceiveIPAddress, 4);
|
|
port = ReceivePort;
|
|
CurrentPacket++;
|
|
|
|
if (CurrentPacket >= NumReceivePackets) {
|
|
CurrentPacket = 0;
|
|
NumReceivePackets = 0;
|
|
}
|
|
|
|
return(size);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Reset_Stats -- Reset bandwidth stats *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:54AM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Reset_Stats(void)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
WWDEBUG_SAY(("PacketManagerClass Resetting stats\n"));
|
|
BandwidthList.Delete_All();
|
|
LastStatsUpdate = TIMEGETTIME();
|
|
ResetStatsIn = true;
|
|
ResetStatsOut = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Stats_Index -- Get stats struct index for ip/port pair *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: IP *
|
|
* Port *
|
|
* Can create - true if allowed to create an entry if one doesn't exist *
|
|
* *
|
|
* OUTPUT: Index of stats struct for this ip/port, -1 for not found *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:54AM ST : Created *
|
|
*=============================================================================================*/
|
|
int PacketManagerClass::Get_Stats_Index(unsigned long ip_address, unsigned short port, bool can_create)
|
|
{
|
|
/*
|
|
** Find the stats struct entry for this ip/port.
|
|
*/
|
|
for (int i=0 ; i<BandwidthList.Count() ; i++) {
|
|
if (ip_address == BandwidthList[i].IPAddress && port == BandwidthList[i].Port) {
|
|
return(i);
|
|
}
|
|
}
|
|
|
|
if (can_create) {
|
|
/*
|
|
** No entry found - create a new one.
|
|
*/
|
|
BandwidthStatsStruct stats;
|
|
stats.IPAddress = ip_address;
|
|
stats.Port = port;
|
|
stats.UncompressedBytesIn = 0;
|
|
stats.UncompressedBytesOut = 0;
|
|
stats.CompressedBytesIn = 0;
|
|
stats.CompressedBytesOut = 0;
|
|
stats.UncompressedBandwidthIn = 0;
|
|
stats.UncompressedBandwidthOut = 0;
|
|
stats.CompressedBandwidthIn = 0;
|
|
stats.CompressedBandwidthOut = 0;
|
|
BandwidthList.Add(stats);
|
|
return(BandwidthList.Count()-1);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Register_Packet_In -- Register an incoming packet for bandwidth stats *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: IP address packet came from *
|
|
* Port packet came from *
|
|
* Compressed size of packet (can be 0) *
|
|
* Uncompressed size of packet (can be 0) *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:56AM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Register_Packet_In(unsigned char *ip_address, unsigned short port, unsigned long compressed_size, unsigned long uncompressed_size)
|
|
{
|
|
static unsigned long _last_ip = 0;
|
|
static unsigned short _last_port = 0;
|
|
static int _last_stats = -1;
|
|
unsigned long long_ip = *((unsigned long*)ip_address);
|
|
|
|
if (ResetStatsIn) {
|
|
_last_ip = 0;
|
|
_last_port = 0;
|
|
_last_stats = -1;
|
|
ResetStatsIn = false;
|
|
}
|
|
|
|
if (_last_stats != -1 && _last_ip == long_ip && _last_port == port && BandwidthList.Count()) {
|
|
BandwidthList[_last_stats].UncompressedBytesIn += uncompressed_size;
|
|
BandwidthList[_last_stats].CompressedBytesIn += compressed_size;
|
|
} else {
|
|
|
|
int stats_index = Get_Stats_Index(long_ip, port);
|
|
assert(stats_index != -1);
|
|
|
|
if (stats_index != -1) {
|
|
BandwidthList[stats_index].UncompressedBytesIn += uncompressed_size;
|
|
BandwidthList[stats_index].CompressedBytesIn += compressed_size;
|
|
_last_stats = stats_index;
|
|
_last_ip = long_ip;
|
|
_last_port = port;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Register_Packet_Out -- Register an outgoing packet for bandwidth stats *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: IP address packet is going to *
|
|
* Port the packet is going to *
|
|
* Compressed size of packet (can be 0) *
|
|
* Uncompressed size of packet (can be 0) *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:56AM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Register_Packet_Out(unsigned char *ip_address, unsigned short port, unsigned long compressed_size, unsigned long uncompressed_size)
|
|
{
|
|
static unsigned long _last_ip = 0;
|
|
static unsigned short _last_port = 0;
|
|
static int _last_stats = -1;
|
|
unsigned long long_ip = *((unsigned long*)ip_address);
|
|
|
|
if (ResetStatsOut) {
|
|
_last_ip = 0;
|
|
_last_port = 0;
|
|
_last_stats = -1;
|
|
ResetStatsOut = false;
|
|
}
|
|
|
|
if (_last_stats != -1 && _last_ip == long_ip && _last_port == port && BandwidthList.Count()) {
|
|
BandwidthList[_last_stats].UncompressedBytesOut += uncompressed_size;
|
|
BandwidthList[_last_stats].CompressedBytesOut += compressed_size;
|
|
} else {
|
|
|
|
int stats_index = Get_Stats_Index(long_ip, port);
|
|
assert(stats_index != -1);
|
|
|
|
if (stats_index != -1) {
|
|
BandwidthList[stats_index].UncompressedBytesOut += uncompressed_size;
|
|
BandwidthList[stats_index].CompressedBytesOut += compressed_size;
|
|
_last_stats = stats_index;
|
|
_last_ip = long_ip;
|
|
_last_port = port;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Update_Stats -- Periodically update the bandwidth stats *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:57AM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Update_Stats(bool forced)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
unsigned long time = TIMEGETTIME();
|
|
|
|
/*
|
|
** Handle timer resetting.
|
|
*/
|
|
if (time < LastStatsUpdate) {
|
|
LastStatsUpdate = 0;
|
|
}
|
|
|
|
/*
|
|
** Only update every 'n' seconds.
|
|
*/
|
|
if (time - LastStatsUpdate > StatsFrequency || forced) {
|
|
|
|
LastStatsUpdate = time;
|
|
|
|
/*
|
|
** Reset the bandwidth totals.
|
|
*/
|
|
TotalCompressedBandwidthIn = 0;
|
|
TotalCompressedBandwidthOut = 0;
|
|
TotalUncompressedBandwidthIn = 0;
|
|
TotalUncompressedBandwidthOut = 0;
|
|
|
|
/*
|
|
** Go through the entry for each ip/port and work out the averages.
|
|
*/
|
|
for (int i=0 ; i<BandwidthList.Count() ; i++) {
|
|
BandwidthStatsStruct *stats = &BandwidthList[i];
|
|
|
|
if (stats->CompressedBytesOut) {
|
|
//stats->CompressedBandwidthOut = (stats->CompressedBytesOut * 8) / StatsFrequency;
|
|
stats->CompressedBandwidthOut = (int)((1000 * stats->CompressedBytesOut * 8) / (float) StatsFrequency);
|
|
stats->CompressedBytesOut = 0;
|
|
TotalCompressedBandwidthOut += stats->CompressedBandwidthOut;
|
|
}
|
|
|
|
if (stats->CompressedBytesIn) {
|
|
//stats->CompressedBandwidthIn = (stats->CompressedBytesIn * 8) / StatsFrequency;
|
|
stats->CompressedBandwidthIn = (int)((1000 * stats->CompressedBytesIn * 8) / (float) StatsFrequency);
|
|
stats->CompressedBytesIn = 0;
|
|
TotalCompressedBandwidthIn += stats->CompressedBandwidthIn;
|
|
}
|
|
|
|
if (stats->UncompressedBytesOut) {
|
|
//stats->UncompressedBandwidthOut = (stats->UncompressedBytesOut * 8) / StatsFrequency;
|
|
stats->UncompressedBandwidthOut = (int)((1000 * stats->UncompressedBytesOut * 8) / (float) StatsFrequency);
|
|
stats->UncompressedBytesOut = 0;
|
|
TotalUncompressedBandwidthOut += stats->UncompressedBandwidthOut;
|
|
}
|
|
|
|
if (stats->UncompressedBytesIn) {
|
|
//stats->UncompressedBandwidthIn = (stats->UncompressedBytesIn * 8) / StatsFrequency;
|
|
stats->UncompressedBandwidthIn = (int)((1000 * stats->UncompressedBytesIn * 8) / (float) StatsFrequency);
|
|
stats->UncompressedBytesIn = 0;
|
|
TotalUncompressedBandwidthIn += stats->UncompressedBandwidthIn;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Just debug output.
|
|
*/
|
|
//WWDEBUG_SAY(("TotalUncompressedBandwidthOut = %d bits per second\n", TotalUncompressedBandwidthOut));
|
|
//WWDEBUG_SAY(("TotalCompressedBandwidthOut = %d bits per second\n", TotalCompressedBandwidthOut));
|
|
//WWDEBUG_SAY(("TotalUncompressedBandwidthIn = %d bits per second\n", TotalUncompressedBandwidthIn));
|
|
//WWDEBUG_SAY(("TotalCompressedBandwidthIn = %d bits per second\n", TotalCompressedBandwidthIn));
|
|
//unsigned long comp_out = 100 - ((100 * TotalCompressedBandwidthOut) / TotalUncompressedBandwidthOut);
|
|
//unsigned long comp_in = 100 - ((100 * TotalCompressedBandwidthIn) / TotalUncompressedBandwidthIn);
|
|
//WWDEBUG_SAY(("Compression out = %d percent\n", comp_out));
|
|
//WWDEBUG_SAY(("Compression in = %d percent\n", comp_in));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Total_Raw_Bandwidth_In -- Get total uncompressed bandwidth in *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Total bandwidth before compression, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:59AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Total_Raw_Bandwidth_In(void)
|
|
{
|
|
return(TotalUncompressedBandwidthIn);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Total_Raw_Bandwidth_Out -- Get total uncompressed bandwidth out *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Total bandwidth before compression, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:59AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Total_Raw_Bandwidth_Out(void)
|
|
{
|
|
return(TotalUncompressedBandwidthOut);
|
|
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Total_Compressed_Bandwidth_In -- Get total compressed bandwidth in *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Total bandwidth after compression, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:59AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Total_Compressed_Bandwidth_In(void)
|
|
{
|
|
return(TotalCompressedBandwidthIn);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Total_Compressed_Bandwidth_Out -- Get total compressed bandwidth out *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Total bandwidth after compression, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 8:59AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Total_Compressed_Bandwidth_Out(void)
|
|
{
|
|
return(TotalCompressedBandwidthOut);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Raw_Bandwidth_In -- Get uncompressed bandwidth in from given address *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Address *
|
|
* *
|
|
* OUTPUT: Uncompressed bandwidth from address, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 9:01AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Raw_Bandwidth_In(SOCKADDR_IN *address)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
unsigned long ip = *((unsigned long*)&address->sin_addr.s_addr);
|
|
unsigned short port = address->sin_port;
|
|
int stats = Get_Stats_Index(ip, port, false);
|
|
|
|
unsigned long bw = 0;
|
|
if (stats != -1) {
|
|
bw = BandwidthList[stats].UncompressedBandwidthIn;
|
|
}
|
|
return(bw);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Raw_Bandwidth_Out -- Get uncompressed bandwidth to given address *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Address *
|
|
* *
|
|
* OUTPUT: Uncompressed bandwidth to address, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 9:01AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Raw_Bandwidth_Out(SOCKADDR_IN *address)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
unsigned long ip = *((unsigned long*)&address->sin_addr.s_addr);
|
|
unsigned short port = address->sin_port;
|
|
int stats = Get_Stats_Index(ip, port, false);
|
|
|
|
unsigned long bw = 0;
|
|
if (stats != -1) {
|
|
bw = BandwidthList[stats].UncompressedBandwidthOut;
|
|
}
|
|
return(bw);
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Raw_Bytes_Out -- Get uncompressed bytes to given address *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Address *
|
|
* *
|
|
* OUTPUT: Uncompressed bytes sent to address. *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 9:01AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Raw_Bytes_Out(SOCKADDR_IN *address)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
unsigned long ip = *((unsigned long*)&address->sin_addr.s_addr);
|
|
unsigned short port = address->sin_port;
|
|
int stats = Get_Stats_Index(ip, port, false);
|
|
|
|
unsigned long bytes = 0;
|
|
if (stats != -1) {
|
|
bytes = BandwidthList[stats].UncompressedBytesOut;
|
|
}
|
|
return(bytes);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Compressed_Bandwidth_In -- Get compressed bandwidth in from address *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Address *
|
|
* *
|
|
* OUTPUT: Compressed bandwidth in from address, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 9:01AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Compressed_Bandwidth_In(SOCKADDR_IN *address)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
unsigned long ip = *((unsigned long*)&address->sin_addr.s_addr);
|
|
unsigned short port = address->sin_port;
|
|
int stats = Get_Stats_Index(ip, port, false);
|
|
|
|
unsigned long bw = 0;
|
|
if (stats != -1) {
|
|
bw = BandwidthList[stats].CompressedBandwidthIn;
|
|
}
|
|
return(bw);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManager::Get_Compressed_Bandwidth_Out -- Get compressed bandwidth to address *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Address *
|
|
* *
|
|
* OUTPUT: Compressed bandwidth to address, in bits per second *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 9:01AM ST : Created *
|
|
*=============================================================================================*/
|
|
unsigned long PacketManagerClass::Get_Compressed_Bandwidth_Out(SOCKADDR_IN *address)
|
|
{
|
|
CriticalSectionClass::LockClass lock(CriticalSection);
|
|
unsigned long ip = *((unsigned long*)&address->sin_addr.s_addr);
|
|
unsigned short port = address->sin_port;
|
|
int stats = Get_Stats_Index(ip, port, false);
|
|
|
|
unsigned long bw = 0;
|
|
if (stats != -1) {
|
|
bw = BandwidthList[stats].CompressedBandwidthOut;
|
|
}
|
|
return(bw);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Set_Stats_Sampling_Frequency -- Set sample freq for stats *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: New frequency (delay in ms) *
|
|
* *
|
|
* OUTPUT: Nothing *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/9/2001 9:58AM ST : Created *
|
|
*=============================================================================================*/
|
|
void PacketManagerClass::Set_Stats_Sampling_Frequency_Delay(unsigned long time_ms)
|
|
{
|
|
assert(time_ms > 0);
|
|
StatsFrequency = time_ms;
|
|
Reset_Stats();
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PacketManagerClass::Get_Error_State -- Report and clear winsock error state *
|
|
* *
|
|
* *
|
|
* *
|
|
* INPUT: Nothing *
|
|
* *
|
|
* OUTPUT: Class error state *
|
|
* *
|
|
* WARNINGS: None *
|
|
* *
|
|
* HISTORY: *
|
|
* 10/24/2001 1:53PM ST : Created *
|
|
*=============================================================================================*/
|
|
PacketManagerClass::ErrorStateEnum PacketManagerClass::Get_Error_State(void)
|
|
{
|
|
ErrorStateEnum state = ErrorState;
|
|
ErrorState = STATE_OK;
|
|
return(state);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Operators required to allow us to add BandwidthStateStruct to a dynamic vector.
|
|
*/
|
|
bool PacketManagerClass::BandwidthStatsStruct::operator == (BandwidthStatsStruct const &stats) {
|
|
return((memcmp(this, &stats, sizeof(*this)) == 0) ? true : false);
|
|
}
|
|
|
|
bool PacketManagerClass::BandwidthStatsStruct::operator != (BandwidthStatsStruct const &stats) {
|
|
return((memcmp(this, &stats, sizeof(*this)) == 0) ? false : true);
|
|
} |