PACKET.CPP 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /***************************************************************************
  15. * *
  16. * Project Name : Westwood Auto Registration App *
  17. * *
  18. * File Name : PACKET.CPP *
  19. * *
  20. * Programmer : Philip W. Gorrow *
  21. * *
  22. * Start Date : 04/22/96 *
  23. * *
  24. * Last Update : April 24, 1996 [PWG] *
  25. * *
  26. *-------------------------------------------------------------------------*
  27. * Functions: *
  28. * *PacketClass::Find_Field -- Finds a field if it exists in the packets *
  29. * Get_Field -- Find specified name and returns data *
  30. * PacketClass::~PacketClass -- destroys a packet class be freeing list *
  31. * PacketClass::Add_Field -- Adds a FieldClass entry to head of packet li*
  32. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  33. #if (0) //PG
  34. #include <stdlib.h>
  35. #include <mem.h>
  36. #include <string.h>
  37. enum {false=0,true=1};
  38. typedef int bool;
  39. #include "packet.h"
  40. /**************************************************************************
  41. * PACKETCLASS::~PACKETCLASS -- destroys a packet class be freeing list *
  42. * *
  43. * INPUT: none *
  44. * *
  45. * OUTPUT: none *
  46. * *
  47. * HISTORY: *
  48. * 04/24/1996 PWG : Created. *
  49. *========================================================================*/
  50. PacketClass::~PacketClass(void)
  51. {
  52. FieldClass *current;
  53. FieldClass *next;
  54. //
  55. // Loop through the entire field list and delete each entry.
  56. //
  57. for (current = Head; current; current = next) {
  58. next = current->Next;
  59. delete current;
  60. }
  61. }
  62. /**************************************************************************
  63. * PACKETCLASS::ADD_FIELD -- Adds a FieldClass entry to head of packet li *
  64. * *
  65. * INPUT: FieldClass * - a properly constructed field class entry. *
  66. * *
  67. * OUTPUT: none *
  68. * *
  69. * HISTORY: *
  70. * 04/24/1996 PWG : Created. *
  71. *========================================================================*/
  72. void PacketClass::Add_Field(FieldClass *field)
  73. {
  74. field->Next = Head;
  75. Head = field;
  76. }
  77. /**************************************************************************
  78. * PACKETCLASS::PACKETCLASS -- Creates a Packet object from a COMMS packe *
  79. * *
  80. * INPUT: *
  81. * *
  82. * OUTPUT: *
  83. * *
  84. * WARNINGS: *
  85. * *
  86. * HISTORY: *
  87. * 04/22/1996 PWG : Created. *
  88. *========================================================================*/
  89. PacketClass::PacketClass(char *curbuf)
  90. {
  91. int remaining_size;
  92. //
  93. // Pull the size and packet ID out of the linear packet stream.
  94. //
  95. Size = *(unsigned short *)curbuf;
  96. curbuf += sizeof (unsigned short);
  97. Size = ntohs(Size);
  98. ID = *(short *)curbuf;
  99. curbuf += sizeof (short);
  100. ID = ntohs(ID);
  101. Head = NULL;
  102. //
  103. // Calculate the remaining size so that we can loop through the
  104. // packets and extract them.
  105. //
  106. remaining_size = Size - 4;
  107. //
  108. // Loop through the linear packet until we run out of room and
  109. // create a field for each.
  110. //
  111. while (remaining_size > 0) {
  112. FieldClass *field = new FieldClass;
  113. //
  114. // Copy the adjusted header into the buffer and then advance the buffer
  115. //
  116. memcpy(field, curbuf, FIELD_HEADER_SIZE);
  117. curbuf += FIELD_HEADER_SIZE;
  118. remaining_size -= FIELD_HEADER_SIZE;
  119. //
  120. // Copy the data into the buffer
  121. //
  122. int size = ntohs(field->Size);
  123. field->Data = new char[size];
  124. memcpy(field->Data, curbuf, size);
  125. curbuf += size;
  126. remaining_size -= size;
  127. //
  128. // Make sure we allow for the pad bytes.
  129. //
  130. int pad = (4 - (ntohs(field->Size) & 3)) & 3;
  131. curbuf += pad;
  132. remaining_size -= pad;
  133. //
  134. // Convert the field back to the host format
  135. //
  136. field->Net_To_Host();
  137. //
  138. // Finally add the field to the field list in the packet
  139. // structure.
  140. //
  141. Add_Field(field);
  142. }
  143. }
  144. /**************************************************************************
  145. * CREATE_COMMS_PACKET -- Walks field list creating a packet *
  146. * *
  147. * INPUT: short - the id of the packet so the server can identify it *
  148. * unsigned short & - the size of the packet returned here *
  149. * *
  150. * OUTPUT: void * pointer to the linear packet data *
  151. * *
  152. * WARNINGS: This routine allocates memory that the user is responsible *
  153. * for freeing. *
  154. * *
  155. * HISTORY: *
  156. * 04/22/1996 PWG : Created. *
  157. *========================================================================*/
  158. char *PacketClass::Create_Comms_Packet(int &size)
  159. {
  160. FieldClass *current;
  161. //
  162. // Size starts at four because that is the size of the packet header.
  163. //
  164. size = 4;
  165. //
  166. // Take a quick spin through and calculate the size of the packet we
  167. // are building.
  168. //
  169. for (current = Head; current; current=current->Next) {
  170. size += (unsigned short)FIELD_HEADER_SIZE; // add in packet header size
  171. size += current->Size; // add in data size
  172. size += (4 - (size & 3)) & 3; // add in pad value to dword align next packet
  173. }
  174. //
  175. // Now that we know the size allocate a buffer big enough to hold the
  176. // packet.
  177. //
  178. char *retval = new char[size];
  179. char *curbuf = retval;
  180. //
  181. // write the size into the packet header
  182. //
  183. *(unsigned short *)curbuf = (unsigned short)htons((unsigned short)size);
  184. curbuf += sizeof (unsigned short);
  185. *(short *)curbuf = htons(ID);
  186. curbuf += sizeof (short);
  187. //
  188. // Ok now that the actual header information has been written we need to write out
  189. // field information.
  190. //
  191. for (current = Head; current; current = current->Next) {
  192. //
  193. // Temporarily convert the packet to net format (this saves alot of
  194. // effort, and seems safe...)
  195. //
  196. current->Host_To_Net();
  197. //
  198. // Copy the adjusted header into the buffer and then advance the buffer
  199. //
  200. memcpy(curbuf, current, FIELD_HEADER_SIZE);
  201. curbuf += FIELD_HEADER_SIZE;
  202. //
  203. // Copy the data into the buffer and then advance the buffer
  204. //
  205. memcpy(curbuf, current->Data, ntohs(current->Size));
  206. curbuf += ntohs(current->Size);
  207. //
  208. // Finally take care of any pad bytes by setting them to 0
  209. //
  210. int pad = (4 - (ntohs(current->Size) & 3)) & 3;
  211. //
  212. // If there is any pad left over, make sure you memset it
  213. // to zeros, so it looks like a pad.
  214. //
  215. if (pad) {
  216. memset(curbuf, 0, pad);
  217. curbuf += pad;
  218. }
  219. current->Net_To_Host();
  220. }
  221. return(retval);
  222. }
  223. /**************************************************************************
  224. * PACKETCLASS::FIND_FIELD -- Finds a field if it exists in the packets *
  225. * *
  226. * INPUT: char * - the id of the field we are looking for. *
  227. * *
  228. * OUTPUT: FieldClass * pointer to the field class *
  229. * *
  230. * HISTORY: *
  231. * 04/23/1996 PWG : Created. *
  232. *========================================================================*/
  233. FieldClass *PacketClass::Find_Field(char *id)
  234. {
  235. for (FieldClass *current = Head; current; current = current->Next) {
  236. if ( strncmp(id, current->ID, 4) == 0)
  237. return current;
  238. }
  239. return NULL;
  240. }
  241. /**************************************************************************
  242. * GET_FIELD -- Find specified name and returns data *
  243. * *
  244. * INPUT: char * - the id of the field that holds the data. *
  245. * char & - the reference to store the data into *
  246. * *
  247. * OUTPUT: true if the field was found, false if it was not. *
  248. * *
  249. * WARNINGS: The data reference is not changed if the field is not *
  250. * found. *
  251. * *
  252. * HISTORY: *
  253. * 04/23/1996 PWG : Created. *
  254. *========================================================================*/
  255. bool PacketClass::Get_Field(char *id, char &data)
  256. {
  257. FieldClass *field = Find_Field(id);
  258. if (field) {
  259. data = *((char *)field->Data);
  260. }
  261. return((field) ? true : false);
  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. * unsigned 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. bool PacketClass::Get_Field(char *id, unsigned char &data)
  278. {
  279. FieldClass *field = Find_Field(id);
  280. if (field) {
  281. data = *((unsigned 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. * short & - 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. bool PacketClass::Get_Field(char *id, short &data)
  300. {
  301. FieldClass *field = Find_Field(id);
  302. if (field) {
  303. data = *((short *)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. * unsigned 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. bool PacketClass::Get_Field(char *id, unsigned short &data)
  322. {
  323. FieldClass *field = Find_Field(id);
  324. if (field) {
  325. data = *((unsigned 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. * long & - 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. bool PacketClass::Get_Field(char *id, long &data)
  344. {
  345. FieldClass *field = Find_Field(id);
  346. if (field) {
  347. data = *((long *)field->Data);
  348. }
  349. return((field) ? true : false);
  350. }
  351. /**************************************************************************
  352. * GET_FIELD -- Find specified name and returns data as a string *
  353. * *
  354. * INPUT: char * - the id of the field that holds the data. *
  355. * char * - the string to store the data into *
  356. * *
  357. * OUTPUT: true if the field was found, false if it was not. *
  358. * *
  359. * WARNINGS: The string is not changed if the field is not found. It *
  360. * is assumed that the string variabled specified by the *
  361. * pointer is large enough to hold the data. *
  362. * *
  363. * HISTORY: *
  364. * 04/23/1996 PWG : Created. *
  365. *========================================================================*/
  366. bool PacketClass::Get_Field(char *id, char *data)
  367. {
  368. FieldClass *field = Find_Field(id);
  369. if (field) {
  370. strcpy(data, (char *)field->Data);
  371. }
  372. return((field) ? true : false);
  373. }
  374. /**************************************************************************
  375. * GET_FIELD -- Find specified name and returns data *
  376. * *
  377. * INPUT: char * - the id of the field that holds the data. *
  378. * unsigned long & - the reference to store the data into *
  379. * *
  380. * OUTPUT: true if the field was found, false if it was not. *
  381. * *
  382. * WARNINGS: The data reference is not changed if the field is not *
  383. * found. *
  384. * *
  385. * HISTORY: *
  386. * 04/23/1996 PWG : Created. *
  387. *========================================================================*/
  388. bool PacketClass::Get_Field(char *id, unsigned long &data)
  389. {
  390. FieldClass *field = Find_Field(id);
  391. if (field) {
  392. data = *((unsigned long *)field->Data);
  393. }
  394. return((field) ? true : false);
  395. }
  396. /**************************************************************************
  397. * GET_FIELD -- Find specified name and returns data *
  398. * *
  399. * INPUT: char * - the id of the field that holds the data. *
  400. * void * - the reference to store the data into *
  401. * int - the length of the buffer passed in *
  402. * *
  403. * OUTPUT: true if the field was found, false if it was not. *
  404. * *
  405. * WARNINGS: The data reference is not changed if the field is not *
  406. * found. *
  407. * *
  408. * HISTORY: *
  409. * 6/4/96 4:46PM ST : Created *
  410. *========================================================================*/
  411. bool PacketClass::Get_Field(char *id, void *data, int &length)
  412. {
  413. FieldClass *field = Find_Field(id);
  414. if (field) {
  415. memcpy (data, field->Data, min(field->Size, length));
  416. length = (int) field->Size;
  417. }
  418. return((field) ? true : false);
  419. }
  420. #endif