| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814 |
- /*
- ** 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);
- }
|