packet.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /*
  2. ** Command & Conquer Renegade(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. #include <winsock.h>
  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()
  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(unsigned 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. {
  116. FieldClass *field = new FieldClass;
  117. //
  118. // Copy the adjusted header into the buffer and then advance the buffer
  119. //
  120. memcpy(field, curbuf, FIELD_HEADER_SIZE);
  121. curbuf += FIELD_HEADER_SIZE;
  122. remaining_size -= FIELD_HEADER_SIZE;
  123. //
  124. // Copy the data into the buffer
  125. //
  126. int size = ntohs(field->Size);
  127. field->Data = new char[size];
  128. memcpy(field->Data, curbuf, size);
  129. curbuf += size;
  130. remaining_size -= size;
  131. //
  132. // Make sure we allow for the pad bytes.
  133. //
  134. int pad = (4 - (ntohs(field->Size) & 3)) & 3;
  135. curbuf += pad;
  136. remaining_size -= pad;
  137. //
  138. // Convert the field back to the host format
  139. //
  140. field->Net_To_Host();
  141. //
  142. // Finally add the field to the field list in the packet
  143. // structure.
  144. //
  145. Add_Field(field);
  146. }
  147. }
  148. /**************************************************************************
  149. * CREATE_COMMS_PACKET -- Walks field list creating a packet *
  150. * *
  151. * INPUT: short - the id of the packet so the server can identify it *
  152. * unsigned short & - the size of the packet returned here *
  153. * *
  154. * OUTPUT: void * pointer to the linear packet data *
  155. * *
  156. * WARNINGS: This routine allocates memory that the user is responsible *
  157. * for freeing. *
  158. * *
  159. * HISTORY: *
  160. * 04/22/1996 PWG : Created. *
  161. *========================================================================*/
  162. char *PacketClass::Create_Comms_Packet(int &size)
  163. {
  164. FieldClass *current;
  165. //
  166. // Size starts at four because that is the size of the packet header.
  167. //
  168. size = 4;
  169. //
  170. // Take a quick spin through and calculate the size of the packet we
  171. // are building.
  172. //
  173. for (current = Head; current; current=current->Next)
  174. {
  175. size += (unsigned short)FIELD_HEADER_SIZE; // add in packet header size
  176. size += current->Size; // add in data size
  177. size += (4 - (size & 3)) & 3; // add in pad value to dword align next packet
  178. }
  179. //
  180. // Now that we know the size allocate a buffer big enough to hold the
  181. // packet.
  182. //
  183. char *retval = new char[size];
  184. char *curbuf = retval;
  185. //
  186. // write the size into the packet header
  187. //
  188. *((unsigned short *)curbuf) = (unsigned short)htons(size);
  189. curbuf += sizeof(unsigned short);
  190. *((short *)curbuf) = htons(ID);
  191. curbuf += sizeof(unsigned short);
  192. //
  193. // Ok now that the actual header information has been written we need to write out
  194. // field information.
  195. //
  196. for (current = Head; current; current = current->Next)
  197. {
  198. //
  199. // Temporarily convert the packet to net format (this saves alot of
  200. // effort, and seems safe...)
  201. //
  202. current->Host_To_Net();
  203. //
  204. // Copy the adjusted header into the buffer and then advance the buffer
  205. //
  206. memcpy(curbuf, current, FIELD_HEADER_SIZE);
  207. curbuf += FIELD_HEADER_SIZE;
  208. //
  209. // Copy the data into the buffer and then advance the buffer
  210. //
  211. memcpy(curbuf, current->Data, ntohs(current->Size));
  212. curbuf += ntohs(current->Size);
  213. //
  214. // Finally take care of any pad bytes by setting them to 0
  215. //
  216. int pad = (4 - (ntohs(current->Size) & 3)) & 3;
  217. curbuf += pad;
  218. current->Net_To_Host();
  219. }
  220. return(retval);
  221. }
  222. /**************************************************************************
  223. * PACKETCLASS::FIND_FIELD -- Finds a field if it exists in the packets *
  224. * *
  225. * INPUT: char * - the id of the field we are looking for. *
  226. * *
  227. * OUTPUT: FieldClass * pointer to the field class *
  228. * *
  229. * HISTORY: *
  230. * 04/23/1996 PWG : Created. *
  231. *========================================================================*/
  232. FieldClass *PacketClass::Find_Field(char *id)
  233. {
  234. for (FieldClass *current = Head; current; current = current->Next)
  235. {
  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. bit8 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. bit8 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. bit8 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. bit8 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. bit8 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. bit8 PacketClass::Get_Field(char *id, int &data)
  352. {
  353. FieldClass *field = Find_Field(id);
  354. if (field) {
  355. data = *((int *)field->Data);
  356. }
  357. return((field) ? true : false);
  358. }
  359. /**************************************************************************
  360. * GET_FIELD -- Find specified name and returns data as a string *
  361. * *
  362. * INPUT: char * - the id of the field that holds the data. *
  363. * char * - the string to store the data into *
  364. * *
  365. * OUTPUT: true if the field was found, false if it was not. *
  366. * *
  367. * WARNINGS: The string is not changed if the field is not found. It *
  368. * is assumed that the string variabled specified by the *
  369. * pointer is large enough to hold the data. *
  370. * *
  371. * HISTORY: *
  372. * 04/23/1996 PWG : Created. *
  373. *========================================================================*/
  374. bit8 PacketClass::Get_Field(char *id, char *data)
  375. {
  376. FieldClass *field = Find_Field(id);
  377. if (field) {
  378. strcpy(data, (char *)field->Data);
  379. }
  380. return((field) ? true : false);
  381. }
  382. /**************************************************************************
  383. * GET_FIELD -- Find specified name and returns data *
  384. * *
  385. * INPUT: char * - the id of the field that holds the data. *
  386. * unsigned long & - the reference to store the data into *
  387. * *
  388. * OUTPUT: true if the field was found, false if it was not. *
  389. * *
  390. * WARNINGS: The data reference is not changed if the field is not *
  391. * found. *
  392. * *
  393. * HISTORY: *
  394. * 04/23/1996 PWG : Created. *
  395. *========================================================================*/
  396. bit8 PacketClass::Get_Field(char *id, unsigned long &data)
  397. {
  398. FieldClass *field = Find_Field(id);
  399. if (field) {
  400. data = *((unsigned long *)field->Data);
  401. }
  402. return((field) ? true : false);
  403. }
  404. bit8 PacketClass::Get_Field(char *id, unsigned &data)
  405. {
  406. FieldClass *field = Find_Field(id);
  407. if (field) {
  408. data = *((unsigned *)field->Data);
  409. }
  410. return((field) ? true : false);
  411. }
  412. /**************************************************************************
  413. * GET_FIELD -- Find specified name and returns data *
  414. * *
  415. * INPUT: char * - the id of the field that holds the data. *
  416. * void * - the reference to store the data into *
  417. * int - the length of the buffer passed in *
  418. * *
  419. * OUTPUT: true if the field was found, false if it was not. *
  420. * *
  421. * WARNINGS: The data reference is not changed if the field is not *
  422. * found. *
  423. * *
  424. * HISTORY: *
  425. * 6/4/96 4:46PM ST : Created *
  426. *========================================================================*/
  427. bit8 PacketClass::Get_Field(char *id, void *data, int &length)
  428. {
  429. FieldClass *field = Find_Field(id);
  430. if (field) {
  431. memcpy (data, field->Data, MIN(field->Size, length));
  432. length = (int) field->Size;
  433. }
  434. return((field) ? true : false);
  435. }
  436. unsigned short PacketClass::Get_Field_Size(char* id)
  437. {
  438. FieldClass *field = Find_Field(id);
  439. if (field)
  440. return field->Get_Size();
  441. else
  442. return 0;
  443. }