CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

PACKET.CPP (20032B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /***************************************************************************
     17  *                                                                         *
     18  *                 Project Name : Westwood Auto Registration App           *
     19  *                                                                         *
     20  *                    File Name : PACKET.CPP                               *
     21  *                                                                         *
     22  *                   Programmer : Philip W. Gorrow                         *
     23  *                                                                         *
     24  *                   Start Date : 04/22/96                                 *
     25  *                                                                         *
     26  *                  Last Update : April 24, 1996 [PWG]                     *
     27  *                                                                         *
     28  *-------------------------------------------------------------------------*
     29  * Functions:                                                              *
     30  *   *PacketClass::Find_Field -- Finds a field if it exists in the packets *
     31  *   Get_Field -- Find specified name and returns data                     *
     32  *   PacketClass::~PacketClass -- destroys a packet class be freeing list  *
     33  *   PacketClass::Add_Field -- Adds a FieldClass entry to head of packet li*
     34  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     35 #include <stdlib.h>
     36 //#include <mem.h>
     37 #include <string.h>
     38 
     39 //enum {false=0,true=1};
     40 //typedef int bool;
     41 
     42 #include "packet.h"
     43 
     44 
     45 /**************************************************************************
     46  * PACKETCLASS::~PACKETCLASS -- destroys a packet class be freeing list   *
     47  *                                                                        *
     48  * INPUT:		none                                                       *
     49  *                                                                        *
     50  * OUTPUT:     none																		  *
     51  *                                                                        *
     52  * HISTORY:                                                               *
     53  *   04/24/1996 PWG : Created.                                            *
     54  *========================================================================*/
     55 PacketClass::~PacketClass(void)
     56 {
     57 	FieldClass *current;
     58 	FieldClass *next;
     59 	//
     60 	// Loop through the entire field list and delete each entry.
     61 	//
     62 	for (current = Head; current; current = next) {
     63 		next = current->Next;
     64 		delete current;
     65 	}
     66 }
     67 
     68 
     69 /**************************************************************************
     70  * PACKETCLASS::ADD_FIELD -- Adds a FieldClass entry to head of packet li *
     71  *                                                                        *
     72  * INPUT:		FieldClass * - a properly constructed field class entry.	  *
     73  *                                                                        *
     74  * OUTPUT:     none                                                       *
     75  *                                                                        *
     76  * HISTORY:                                                               *
     77  *   04/24/1996 PWG : Created.                                            *
     78  *========================================================================*/
     79 void PacketClass::Add_Field(FieldClass *field)
     80 {
     81 	field->Next = Head;
     82 	Head = field;
     83 }
     84 
     85 /**************************************************************************
     86  * PACKETCLASS::PACKETCLASS -- Creates a Packet object from a COMMS packe *
     87  *                                                                        *
     88  * INPUT:                                                                 *
     89  *                                                                        *
     90  * OUTPUT:                                                                *
     91  *                                                                        *
     92  * WARNINGS:                                                              *
     93  *                                                                        *
     94  * HISTORY:                                                               *
     95  *   04/22/1996 PWG : Created.                                            *
     96  *========================================================================*/
     97 PacketClass::PacketClass(char *curbuf)
     98 {
     99 	int remaining_size;
    100 	//
    101 	// Pull the size and packet ID out of the linear packet stream.
    102 	//
    103 	Size = *(unsigned short *)curbuf;
    104 	curbuf += sizeof (unsigned short);
    105 	Size = ntohs(Size);
    106 	ID	  = *(short *)curbuf;
    107 	curbuf += sizeof (short);
    108 	ID   = ntohs(ID);
    109 	Head = NULL;
    110 
    111 	//
    112 	// Calculate the remaining size so that we can loop through the
    113 	//   packets and extract them.
    114 	//
    115 	remaining_size = Size - 4;
    116 
    117 	//
    118 	// Loop through the linear packet until we run out of room and
    119 	// create a field for each.
    120 	//
    121 	while (remaining_size > 0) {
    122 		FieldClass *field = new FieldClass;
    123 
    124 		//
    125 		// Copy the adjusted header into the buffer and then advance the buffer
    126 		//
    127 		memcpy(field, curbuf, FIELD_HEADER_SIZE);
    128 		curbuf += FIELD_HEADER_SIZE;
    129 		remaining_size   -= FIELD_HEADER_SIZE;
    130 
    131 		//
    132 		// Copy the data into the buffer
    133 		//
    134 		int size			= ntohs(field->Size);
    135 		field->Data		= new char[size];
    136 		memcpy(field->Data, curbuf, size);
    137 		curbuf			+= size;
    138 		remaining_size	-= size;
    139 		//
    140 		// Make sure we allow for the pad bytes.
    141 		//
    142 		int pad = (4 - (ntohs(field->Size) & 3)) & 3;
    143 		curbuf += pad;
    144 		remaining_size   -= pad;
    145 
    146 		//
    147 		// Convert the field back to the host format
    148 		//
    149 		field->Net_To_Host();
    150 
    151 		//
    152 		// Finally add the field to the field list in the packet
    153 		// structure.
    154 		//
    155 		Add_Field(field);
    156 	}
    157 }
    158 
    159 /**************************************************************************
    160  * CREATE_COMMS_PACKET -- Walks field list creating a packet              *
    161  *                                                                        *
    162  * INPUT:		short - the id of the packet so the server can identify it *
    163  *					unsigned short & - the size of the packet returned here    *
    164  *                                                                        *
    165  * OUTPUT:     void * pointer to the linear packet data                   *
    166  *                                                                        *
    167  * WARNINGS: 	This routine allocates memory that the user is responsible *
    168  *  				for freeing.															  *
    169  *                                                                        *
    170  * HISTORY:                                                               *
    171  *   04/22/1996 PWG : Created.                                            *
    172  *========================================================================*/
    173 char *PacketClass::Create_Comms_Packet(int &size)
    174 {
    175 	FieldClass *current;
    176 
    177 	//
    178 	// Size starts at four because that is the size of the packet header.
    179 	//
    180 	size = 4;
    181 
    182 	//
    183 	// Take a quick spin through and calculate the size of the packet we
    184 	//   are building.
    185 	//
    186 	for (current = Head; current; current=current->Next) {
    187 		size += (unsigned short)FIELD_HEADER_SIZE;			// add in packet header size
    188 		size += current->Size;				// add in data size
    189 		size += (4 - (size & 3)) & 3; 	// add in pad value to dword align next packet
    190 	}
    191 
    192 	//
    193 	// Now that we know the size allocate a buffer big enough to hold the
    194 	// packet.
    195 	//
    196 	char *retval = new char[size];
    197 	char *curbuf = retval;
    198 
    199 	//
    200 	// write the size into the packet header
    201 	//
    202 	*(unsigned short *)curbuf = (unsigned short)htons((unsigned short)size);
    203 	curbuf += sizeof (unsigned short);
    204 	*(short *)curbuf = htons(ID);
    205 	curbuf += sizeof (short);
    206 
    207 	//
    208 	// Ok now that the actual header information has been written we need to write out
    209 	// field information.
    210 	//
    211 	for (current = Head; current; current = current->Next) {
    212 		//
    213 		// Temporarily convert the packet to net format (this saves alot of
    214 		//   effort, and seems safe...)
    215 		//
    216 		current->Host_To_Net();
    217 
    218 		//
    219 		// Copy the adjusted header into the buffer and then advance the buffer
    220 		//
    221 		memcpy(curbuf, current, FIELD_HEADER_SIZE);
    222 		curbuf += FIELD_HEADER_SIZE;
    223 
    224 		//
    225 		// Copy the data into the buffer and then advance the buffer
    226 		//
    227 		memcpy(curbuf, current->Data, ntohs(current->Size));
    228 		curbuf += ntohs(current->Size);
    229 
    230 		//
    231 		// Finally take care of any pad bytes by setting them to 0
    232 		//
    233 		int pad = (4 - (ntohs(current->Size) & 3)) & 3;
    234 
    235 		//
    236 		//	If there is any pad left over, make sure you memset it
    237 		// to zeros, so it looks like a pad.
    238 		//
    239 		if (pad) {
    240 			memset(curbuf, 0, pad);
    241 			curbuf += pad;
    242 		}
    243 
    244 		current->Net_To_Host();
    245 	}
    246 	return(retval);
    247 }
    248 
    249 
    250 /**************************************************************************
    251  * PACKETCLASS::FIND_FIELD -- Finds a field if it exists in the packets   *
    252  *                                                                        *
    253  * INPUT:		char *  - the id of the field we are looking for.			  *
    254  *                                                                        *
    255  * OUTPUT:     FieldClass * pointer to the field class                    *
    256  *                                                                        *
    257  * HISTORY:                                                               *
    258  *   04/23/1996 PWG : Created.                                            *
    259  *========================================================================*/
    260 FieldClass *PacketClass::Find_Field(char *id)
    261 {
    262 	for (FieldClass *current = Head; current; current = current->Next) {
    263 		if ( strncmp(id, current->ID, 4) == 0)
    264 			return current;
    265 	}
    266 	return NULL;
    267 }
    268 
    269 
    270 /**************************************************************************
    271  * GET_FIELD -- Find specified name and returns data                      *
    272  *                                                                        *
    273  * INPUT:		char *   - the id of the field that holds the data.		  *
    274  *					char &   - the reference to store the data into				  *
    275  *                                                                        *
    276  * OUTPUT:		true if the field was found, false if it was not.			  *
    277  *                                                                        *
    278  * WARNINGS:	The data reference is not changed if the field is not		  *
    279  *					found.																	  *
    280  *                                                                        *
    281  * HISTORY:                                                               *
    282  *   04/23/1996 PWG : Created.                                            *
    283  *========================================================================*/
    284 bool PacketClass::Get_Field(char *id, char &data)
    285 {
    286 	FieldClass *field = Find_Field(id);
    287 	if (field) {
    288 		data = *((char *)field->Data);
    289 	}
    290 	return((field) ? true : false);
    291 }
    292 
    293 
    294 /**************************************************************************
    295  * GET_FIELD -- Find specified name and returns data                      *
    296  *                                                                        *
    297  * INPUT:		char *   - the id of the field that holds the data.		  *
    298  *					unsigned char &   - the reference to store the data into	  *
    299  *                                                                        *
    300  * OUTPUT:		true if the field was found, false if it was not.			  *
    301  *                                                                        *
    302  * WARNINGS:	The data reference is not changed if the field is not		  *
    303  *					found.																	  *
    304  *                                                                        *
    305  * HISTORY:                                                               *
    306  *   04/23/1996 PWG : Created.                                            *
    307  *========================================================================*/
    308 bool PacketClass::Get_Field(char *id, unsigned char &data)
    309 {
    310 	FieldClass *field = Find_Field(id);
    311 	if (field) {
    312 		data = *((unsigned char *)field->Data);
    313 	}
    314 	return((field) ? true : false);
    315 }
    316 
    317 
    318 /**************************************************************************
    319  * GET_FIELD -- Find specified name and returns data                      *
    320  *                                                                        *
    321  * INPUT:		char *   - the id of the field that holds the data.		  *
    322  *					short &   - the reference to store the data into	        *
    323  *                                                                        *
    324  * OUTPUT:		true if the field was found, false if it was not.			  *
    325  *                                                                        *
    326  * WARNINGS:	The data reference is not changed if the field is not		  *
    327  *					found.																	  *
    328  *                                                                        *
    329  * HISTORY:                                                               *
    330  *   04/23/1996 PWG : Created.                                            *
    331  *========================================================================*/
    332 bool PacketClass::Get_Field(char *id, short &data)
    333 {
    334 	FieldClass *field = Find_Field(id);
    335 	if (field) {
    336 		data = *((short *)field->Data);
    337 	}
    338 	return((field) ? true : false);
    339 }
    340 
    341 
    342 /**************************************************************************
    343  * GET_FIELD -- Find specified name and returns data                      *
    344  *                                                                        *
    345  * INPUT:		char *   - the id of the field that holds the data.		  *
    346  *					unsigned short &   - the reference to store the data into  *
    347  *                                                                        *
    348  * OUTPUT:		true if the field was found, false if it was not.			  *
    349  *                                                                        *
    350  * WARNINGS:	The data reference is not changed if the field is not		  *
    351  *					found.																	  *
    352  *                                                                        *
    353  * HISTORY:                                                               *
    354  *   04/23/1996 PWG : Created.                                            *
    355  *========================================================================*/
    356 bool PacketClass::Get_Field(char *id, unsigned short &data)
    357 {
    358 	FieldClass *field = Find_Field(id);
    359 	if (field) {
    360 		data = *((unsigned short *)field->Data);
    361 	}
    362 	return((field) ? true : false);
    363 }
    364 
    365 
    366 /**************************************************************************
    367  * GET_FIELD -- Find specified name and returns data                      *
    368  *                                                                        *
    369  * INPUT:		char *   - the id of the field that holds the data.		  *
    370  *					long &   - the reference to store the data into  			  *
    371  *                                                                        *
    372  * OUTPUT:		true if the field was found, false if it was not.			  *
    373  *                                                                        *
    374  * WARNINGS:	The data reference is not changed if the field is not		  *
    375  *					found.																	  *
    376  *                                                                        *
    377  * HISTORY:                                                               *
    378  *   04/23/1996 PWG : Created.                                            *
    379  *========================================================================*/
    380 bool PacketClass::Get_Field(char *id, long &data)
    381 {
    382 	FieldClass *field = Find_Field(id);
    383 	if (field) {
    384 		data = *((long *)field->Data);
    385 	}
    386 	return((field) ? true : false);
    387 }
    388 
    389 /**************************************************************************
    390  * GET_FIELD -- Find specified name and returns data as a string          *
    391  *                                                                        *
    392  * INPUT:		char *   - the id of the field that holds the data.		  *
    393  *					char *   - the string to store the data into					  *
    394  *                                                                        *
    395  * OUTPUT:		true if the field was found, false if it was not.			  *
    396  *                                                                        *
    397  * WARNINGS:	The string is not changed if the field is not found.  It   *
    398  *					is assumed that the string variabled specified by the      *
    399  *					pointer is large enough to hold the data.						  *
    400  *                                                                        *
    401  * HISTORY:                                                               *
    402  *   04/23/1996 PWG : Created.                                            *
    403  *========================================================================*/
    404 #pragma warning(disable:4996)
    405 bool PacketClass::Get_Field(char *id, char *data)
    406 {
    407 	FieldClass *field = Find_Field(id);
    408 	if (field) {
    409 		strcpy(data, (char *)field->Data);
    410 	}
    411 	return((field) ? true : false);
    412 }
    413 
    414 /**************************************************************************
    415  * GET_FIELD -- Find specified name and returns data                      *
    416  *                                                                        *
    417  * INPUT:		char *   - the id of the field that holds the data.		  *
    418  *					unsigned long &   - the reference to store the data into   *
    419  *                                                                        *
    420  * OUTPUT:		true if the field was found, false if it was not.			  *
    421  *                                                                        *
    422  * WARNINGS:	The data reference is not changed if the field is not		  *
    423  *					found.																	  *
    424  *                                                                        *
    425  * HISTORY:                                                               *
    426  *   04/23/1996 PWG : Created.                                            *
    427  *========================================================================*/
    428 bool PacketClass::Get_Field(char *id, unsigned long &data)
    429 {
    430 	FieldClass *field = Find_Field(id);
    431 	if (field) {
    432 		data = *((unsigned long *)field->Data);
    433 	}
    434 	return((field) ? true : false);
    435 }
    436 
    437 
    438 /**************************************************************************
    439  * GET_FIELD -- Find specified name and returns data                      *
    440  *                                                                        *
    441  * INPUT:		char *   - the id of the field that holds the data.		    *
    442  *				void * - the reference to store the data into                *
    443  *           int    - the length of the buffer passed in                  *
    444  *                                                                        *
    445  * OUTPUT:		true if the field was found, false if it was not.			 *
    446  *                                                                        *
    447  * WARNINGS:	The data reference is not changed if the field is not		    *
    448  *					found.																	 *
    449  *                                                                        *
    450  * HISTORY:                                                               *
    451  *   6/4/96 4:46PM ST : Created                                           *
    452  *========================================================================*/
    453 bool PacketClass::Get_Field(char *id, void *data, int &length)
    454 {
    455 	FieldClass *field = Find_Field(id);
    456 	if (field) {
    457 		memcpy (data, field->Data, min(field->Size, length));
    458 		length = (int) field->Size;
    459 	}
    460 	return((field) ? true : false);
    461 }