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