packet.cpp 21 KB

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