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