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 }