PACKET.CPP 19 KB

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