Clone of UAS2 @ https://github.com/drudgedance/uas2

PacketPipe.h 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * This file is part of UAS2.
  3. *
  4. * UAS2 is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * UAS2 is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. * You should have received a copy of the GNU General Public License
  14. * along with UASv1; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. /**
  18. * @file PacketPipe.h
  19. */
  20. #ifndef __PACKETPIPE_H
  21. #define __PACKETPIPE_H
  22. #include <list>
  23. #include "Message.h"
  24. #include "CRC_Module.h"
  25. typedef struct cFragment {
  26. BYTE m_pbData[MAX_PACKET_SIZE];
  27. WORD m_wSize;
  28. DWORD m_dwSeed;
  29. cFragment( BYTE *pbData, WORD wSize )
  30. : m_wSize( wSize + 36 )
  31. {
  32. CopyMemory( &m_pbData[36], pbData, wSize );
  33. }
  34. cFragment( )
  35. : m_wSize( 0 )
  36. {
  37. }
  38. ~cFragment( ) {}
  39. } cFragment;
  40. typedef struct cIgnoreRequest
  41. {
  42. DWORD m_dwZero; //Sequence - Numeric identifier for the order in which this packet should be processed.
  43. DWORD m_dwEight; //Flags - Bitmask identifying what data follows the header.
  44. DWORD m_dwCRC; // CRC - Cyclic redundancy checksum verifying all data is authentic and undamaged.
  45. DWORD m_dwNum; // ?
  46. WORD m_wUnk1; // Server Logical ID - Recipient identifier (index < 400) distinguishing the connection host.
  47. WORD m_wUnk2; // Time - Half-seconds since connection establishment that you received a packet.
  48. WORD m_wSize; // Size - Number of bytes following the header.
  49. WORD m_wTable; // Table - Unknown. Might involve CRC. Should match for sent/received headers.
  50. cIgnoreRequest( )
  51. {
  52. m_dwZero = 0;
  53. m_dwEight = 8;
  54. m_wSize = 8;
  55. m_wTable = 2;
  56. }
  57. } cIgnoreRequest;
  58. template< class _Type >
  59. class cPacketPipe : public _Type
  60. {
  61. friend class cClient;
  62. friend class cMasterServer;
  63. public:
  64. cPacketPipe ( ) {}
  65. ~cPacketPipe( )
  66. {
  67. while ( !m_lstQueuedPackets.empty( ) )
  68. {
  69. SAFEDELETE( m_lstQueuedPackets.front( ) )
  70. m_lstQueuedPackets.pop_front( );
  71. }
  72. while ( !m_lstSentPackets.empty( ) )
  73. {
  74. SAFEDELETE( m_lstSentPackets.front( ) )
  75. m_lstSentPackets.pop_front( );
  76. }
  77. }
  78. /**
  79. * Set the initial values.
  80. */
  81. inline void Initialize( )
  82. {
  83. m_dwSendSequence = 1;
  84. m_dwRecvSequence = 1;
  85. m_dwMsgID = 1;
  86. m_wTime = 12;
  87. m_pdwSendCRC = m_lpdwSendCRC;
  88. m_pdwRecvCRC = m_lpdwRecvCRC;
  89. ResetCRCs( );
  90. }
  91. /**
  92. * Reset the values.
  93. */
  94. inline void Reset( )
  95. {
  96. m_dwSendSequence = 1;
  97. m_dwRecvSequence = 1;
  98. m_dwMsgID = 1;
  99. m_wTime = 12;
  100. ResetCRCs( );
  101. }
  102. inline void SetSendSequence( DWORD dwSendSequence )
  103. {
  104. m_dwSendSequence = dwSendSequence;
  105. }
  106. /**
  107. * Creates a general CRC.
  108. *
  109. * @param *pbSendBuffer -
  110. * @param iSize -
  111. *
  112. * @return (dwCrc1 + dwCrc2) -
  113. */
  114. static inline DWORD CalcCRC( BYTE *pbSendBuffer, int iSize )
  115. {
  116. DWORD dwCrc1, dwCrc2, *pdwCrc;
  117. pdwCrc = (DWORD *)&pbSendBuffer[8];
  118. *pdwCrc = 0xBADD70DD;
  119. dwCrc1 = GetMagicNumber( &pbSendBuffer[0x00], 0x14, TRUE );
  120. dwCrc2 = GetMagicNumber( &pbSendBuffer[0x14], iSize, FALSE );
  121. *pdwCrc = dwCrc1 + dwCrc2;
  122. return (dwCrc1 + dwCrc2);
  123. }
  124. private:
  125. /**
  126. * Creates the fragment headers and adds the packet to the client's send queue.
  127. *
  128. * @param *pbData - A pointer to the data to be sent.
  129. * @param wSize - The size of the data.
  130. * @param wGroup - The group to which the data belongs (used by AddFragmentHeader).
  131. */
  132. void AddPacket( BYTE *pbData, WORD wSize, WORD wGroup )
  133. {
  134. if ( !wSize || !pbData )
  135. return ;
  136. WORD wDataSize;
  137. cFragment *pcFragment;
  138. if ( FindSpaceInQueue( pbData, wSize, wGroup ) )
  139. return ;
  140. WORD wSizeLeft = wSize;
  141. WORD wFragmentCount = wSize / MAX_DATA_SIZE;
  142. WORD wFragmentIndex = 0;
  143. BYTE *pbCurData = pbData;
  144. if ( wSize % MAX_DATA_SIZE )
  145. ++wFragmentCount;
  146. wDataSize = wSizeLeft > MAX_DATA_SIZE ? MAX_DATA_SIZE : wSizeLeft;
  147. pcFragment = new cFragment( pbCurData, wDataSize );
  148. for ( ; wFragmentIndex < wFragmentCount; ++wFragmentIndex )
  149. {
  150. AddFragmentHeader( pcFragment->m_pbData + sizeof( cTransportHeader ), wDataSize, wFragmentIndex, wFragmentCount, wGroup );
  151. pbCurData = pbCurData + wDataSize;
  152. wSizeLeft -= wDataSize;
  153. wDataSize = wSizeLeft > MAX_DATA_SIZE ? MAX_DATA_SIZE : wSizeLeft;
  154. m_lstQueuedPackets.push_back( pcFragment );
  155. if ( wDataSize )
  156. pcFragment = new cFragment( pbCurData, wDataSize );
  157. }
  158. ++m_dwMsgID;
  159. }
  160. /**
  161. * Constructs the transport headers and sends the packets.
  162. *
  163. * @param saSockAddr - The client's SOCKADDR_IN struct value.
  164. */
  165. void SendQueuedPackets( SOCKADDR_IN& saSockAddr )
  166. {
  167. cTransportHeader *pcTH;
  168. cFragment *pcFragment;
  169. while ( !m_lstQueuedPackets.empty( ) )
  170. {
  171. pcFragment = m_lstQueuedPackets.front( );
  172. pcTH = reinterpret_cast< cTransportHeader * >( pcFragment->m_pbData );
  173. pcTH->m_dwSequence = ++m_dwSendSequence;
  174. pcTH->m_dwFlags = 0x0200;
  175. pcTH->m_wLogicalID = m_wLogicalID;
  176. pcTH->m_wTime = m_wTime;
  177. pcTH->m_wTotalSize = pcFragment->m_wSize - sizeof( cTransportHeader );
  178. pcTH->m_wTable = 0x0000;
  179. DWORD dwNewCRC, dwXorVal;
  180. //dwNewCRC = Calc200_CRC( pcFragment->m_pbData );
  181. //
  182. dwNewCRC = GetMagicNumber(pcFragment->m_pbData + sizeof(cTransportHeader),pcTH->m_wTotalSize,1);
  183. //
  184. dwXorVal = GetSendXORVal( m_pdwSendCRC );
  185. dwNewCRC ^= dwXorVal;
  186. //
  187. pcTH->m_dwCRC = 0xBADD70DD;
  188. //
  189. //dwNewCRC += CalcTransportCRC( (DWORD *)pcFragment->m_pbData );
  190. dwNewCRC += GetMagicNumber(pcFragment->m_pbData, sizeof(cTransportHeader),1);
  191. //
  192. pcTH->m_dwCRC = dwNewCRC;
  193. sendto( m_Socket, (char *)pcFragment->m_pbData, pcFragment->m_wSize, NULL, (sockaddr *)&saSockAddr, sizeof( SOCKADDR ) );
  194. pcFragment->m_dwSeed = dwXorVal;
  195. m_lstSentPackets.push_back( pcFragment );
  196. m_lstQueuedPackets.pop_front( );
  197. }
  198. }
  199. /**
  200. * Calculates the CRC for 0x0200 packets.
  201. *
  202. * @param *pbPacket -
  203. *
  204. * @return dwCrc -
  205. */
  206. static inline DWORD Calc200_CRC( BYTE *pbPacket )
  207. {
  208. BYTE *pbPacketEnd = pbPacket + reinterpret_cast< cTransportHeader * > ( pbPacket )->m_wTotalSize + sizeof ( cTransportHeader );
  209. DWORD dwCrc = 0;
  210. for ( BYTE *pbFragment = pbPacket + sizeof ( cTransportHeader ); pbFragment < pbPacketEnd; )
  211. {
  212. WORD wLength = reinterpret_cast< cFragmentHeader * > ( pbFragment )->m_wFragmentLength;
  213. dwCrc += GetMagicNumber ( pbFragment, sizeof ( cFragmentHeader ), 1 ) + GetMagicNumber ( pbFragment + sizeof ( cFragmentHeader ), wLength - sizeof ( cFragmentHeader ), TRUE );
  214. pbFragment += wLength;
  215. }
  216. return dwCrc;
  217. }
  218. /**
  219. * Calculates the CRC for the transport header.
  220. *
  221. * @param *pdwWoot -
  222. *
  223. * @return dwCrc -
  224. */
  225. static inline DWORD CalcTransportCRC( DWORD *pdwWoot )
  226. {
  227. DWORD dwOrg = pdwWoot[2];
  228. DWORD dwCrc = 0;
  229. pdwWoot[2] = 0xBADD70DD;
  230. dwCrc += GetMagicNumber( (BYTE *)pdwWoot, 20, TRUE );
  231. pdwWoot[2] = dwOrg;
  232. return dwCrc;
  233. }
  234. /**
  235. * Seeds the CRC.
  236. *
  237. * @param *pbBuf - A pointer to the data to use.
  238. * @param wSize - The size of the data.
  239. * @param fIncludeSize -
  240. *
  241. * @return dwCS -
  242. */
  243. static DWORD GetMagicNumber( BYTE *pbBuf, WORD wSize, BOOL fIncludeSize )
  244. {
  245. DWORD dwCS = 0;
  246. int i;
  247. if ( fIncludeSize )
  248. dwCS += wSize << 16;
  249. // sum up the DWORDs:
  250. for (i = 0; i < (wSize >> 2); ++i )
  251. dwCS += ((DWORD *)pbBuf)[i];
  252. // now any remaining bytes are summed in reverse endian
  253. int iShift = 3;
  254. for ( i = (i << 2); i < wSize; ++i )
  255. {
  256. dwCS += pbBuf[i] << (iShift * 8);
  257. --iShift;
  258. }
  259. return dwCS;
  260. }
  261. /**
  262. * Returns a ping packet.
  263. *
  264. * @param saSockAddr - The client's SOCKADDR_IN struct value.
  265. */
  266. void ReturnPing( SOCKADDR_IN& saSockAddr )
  267. {
  268. char szSendBuffer[0x40];
  269. DWORD *last = (DWORD *)&szSendBuffer[0x14];
  270. cTransportHeader *pcTH;
  271. pcTH = reinterpret_cast< cTransportHeader * >( szSendBuffer );
  272. pcTH->m_dwSequence = m_dwSendSequence;
  273. pcTH->m_dwFlags = 0x00000004;
  274. pcTH->m_wLogicalID = m_wLogicalID;
  275. pcTH->m_wTime = m_wTime;
  276. pcTH->m_wTotalSize = 4;
  277. pcTH->m_wTable = 0;
  278. *last = m_dwRecvSequence;
  279. CalcCRC( (BYTE *)szSendBuffer, 4 );
  280. sendto( m_Socket, (char *)szSendBuffer, 24, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
  281. }
  282. /**
  283. * Adds a packet to the queue.
  284. *
  285. * @param cmPacket - The address of the packet message to add.
  286. * @param wGroup - The group to which the packet belongs (used by AddFragmentHeader).
  287. */
  288. inline void AddPacket( cMessage& cmPacket, WORD wGroup )
  289. {
  290. WORD wSize = cmPacket.getSize( );
  291. BYTE *pbData = new BYTE[wSize];
  292. cmPacket.getData( 0, wSize, pbData );
  293. AddPacket( pbData, wSize, wGroup );
  294. SAFEDELETE_ARRAY( pbData )
  295. }
  296. /**
  297. * Checks to see if this packet can be crammed into another fragment.
  298. *
  299. * @param *pbData - A pointer to the data.
  300. * @param wSize - The size of the data.
  301. * @param wGroup - The group to which the data belongs (used by AddFragmentHeader).
  302. */
  303. BOOL FindSpaceInQueue( BYTE *pbData, WORD wSize, WORD wGroup )
  304. {
  305. cFragment *pcFragment;
  306. std::list< cFragment * >::iterator itFragment = m_lstQueuedPackets.begin( );
  307. for ( ; itFragment != m_lstQueuedPackets.end( ); ++itFragment )
  308. {
  309. pcFragment = *itFragment;
  310. if ( pcFragment->m_wSize + wSize + sizeof( cFragmentHeader ) <= MAX_PACKET_SIZE )
  311. {
  312. CopyMemory( &pcFragment->m_pbData[pcFragment->m_wSize + sizeof( cFragmentHeader )], pbData, wSize );
  313. AddFragmentHeader( &pcFragment->m_pbData[pcFragment->m_wSize], wSize, 0, 1, wGroup );
  314. pcFragment->m_wSize += wSize + sizeof( cFragmentHeader );
  315. return TRUE;
  316. }
  317. }
  318. return FALSE;
  319. }
  320. /**
  321. * Creates the fragment header.
  322. *
  323. * @param *pbStart -
  324. * @param wSize -
  325. * @param wFragmentIndex -
  326. * @param wFragmentCount -
  327. * @param wGroup -
  328. */
  329. inline void AddFragmentHeader( BYTE *pbStart, WORD wSize, WORD wFragmentIndex, WORD wFragmentCount, WORD wGroup )
  330. {
  331. cFragmentHeader *pcFH = reinterpret_cast< cFragmentHeader * >( pbStart );
  332. pcFH->m_dwSequence = m_dwMsgID;
  333. pcFH->m_dwObjectID = 0x80000000;
  334. pcFH->m_wFragmentIndex = wFragmentIndex;
  335. pcFH->m_wFragmentLength = wSize + sizeof( cFragmentHeader );
  336. pcFH->m_wFragmentCount = wFragmentCount;
  337. pcFH->m_wFragmentGroup = wGroup;
  338. }
  339. /**
  340. * Resends packets that the client needs.
  341. *
  342. * @param dwNumLostPackets - The number of packets lost.
  343. * @param *pdwMissingPackets - An array of the lost packets (of count dwNumLostPackets).
  344. * @param saSockAddr - The client's SOCKADDR_IN struct value.
  345. */
  346. void ProcessLostPackets( DWORD dwNumLostPackets, DWORD *pdwMissingPackets, SOCKADDR_IN& saSockAddr )
  347. {
  348. DWORD dwNumIgnored = 0;
  349. std::vector< DWORD > vIgnoreList;
  350. vIgnoreList.reserve( dwNumLostPackets );
  351. cFragment *pcFragment;
  352. for ( DWORD dwCurrentPacket = 0; dwCurrentPacket < dwNumLostPackets; ++dwCurrentPacket )
  353. {
  354. std::list< cFragment * >::iterator itFragment = m_lstSentPackets.begin( );
  355. for ( ; itFragment != m_lstSentPackets.end( ); ++itFragment )
  356. {
  357. pcFragment = *itFragment;
  358. if ( *((DWORD *)pcFragment->m_pbData) == pdwMissingPackets[dwCurrentPacket] )
  359. break;
  360. }
  361. if ( itFragment != m_lstSentPackets.end( ) )
  362. {
  363. cTransportHeader *pcTH = reinterpret_cast< cTransportHeader * >( pcFragment->m_pbData );
  364. pcTH->m_dwFlags = 0x00000201;
  365. pcTH->m_wTime = m_wTime;
  366. DWORD dwNewCRC;
  367. dwNewCRC = Calc200_CRC( pcFragment->m_pbData );
  368. dwNewCRC ^= pcFragment->m_dwSeed;
  369. dwNewCRC += CalcTransportCRC( (DWORD *)pcFragment->m_pbData );
  370. pcTH->m_dwCRC = dwNewCRC;
  371. sendto( m_Socket, (char *)pcFragment->m_pbData, pcFragment->m_wSize, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
  372. }
  373. else
  374. {
  375. vIgnoreList.push_back( pdwMissingPackets[dwCurrentPacket] );
  376. ++dwNumIgnored;
  377. }
  378. }
  379. if ( !vIgnoreList.empty( ) )
  380. {
  381. BYTE pbSendBuffer[0x1E4];
  382. cIgnoreRequest irOut;
  383. irOut.m_dwNum = dwNumIgnored;
  384. irOut.m_wUnk1 = m_wLogicalID;
  385. irOut.m_wUnk2 = m_wTime;
  386. irOut.m_wSize = 4 + dwNumIgnored * 4;
  387. CopyMemory( pbSendBuffer, &irOut, sizeof( cIgnoreRequest ) );
  388. std::vector< DWORD >::iterator itIgnore = vIgnoreList.begin( );
  389. for ( DWORD dwCount = 0; itIgnore != vIgnoreList.end( ); ++itIgnore, ++dwCount )
  390. CopyMemory( pbSendBuffer + sizeof( irOut ) + dwCount * 4, &itIgnore, sizeof( DWORD ) );
  391. irOut.m_dwCRC = CalcCRC( pbSendBuffer, 4 + dwNumIgnored * 4 );
  392. sendto( m_Socket, (char*)pbSendBuffer, sizeof( irOut ) + dwNumIgnored * 4, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
  393. vIgnoreList.clear( );
  394. }
  395. }
  396. /**
  397. * Removes packets from the m_lstSentPackets list.
  398. *
  399. * @param dwLastGoodSeq -
  400. */
  401. inline void ClearSentPackets( DWORD dwLastGoodSeq )
  402. {
  403. cFragment *pcFragment;
  404. while ( !m_lstSentPackets.empty( ) )
  405. {
  406. pcFragment = m_lstSentPackets.front( );
  407. if ( *((DWORD *)pcFragment->m_pbData) > dwLastGoodSeq )
  408. break;
  409. else
  410. {
  411. m_lstSentPackets.pop_front( );
  412. SAFEDELETE( pcFragment )
  413. }
  414. }
  415. }
  416. inline void ResetCRCs( )
  417. {
  418. GenerateCRCs( m_dwSendCRCSeed, m_dwRecvCRCSeed, m_pdwSendCRC, m_pdwRecvCRC );
  419. }
  420. DWORD m_lpdwSendCRC[3];
  421. DWORD m_lpdwRecvCRC[3];
  422. DWORD *m_pdwSendCRC;
  423. DWORD *m_pdwRecvCRC;
  424. DWORD m_dwSendSequence;
  425. DWORD m_dwRecvSequence;
  426. DWORD m_dwMsgID;
  427. WORD m_wTime;
  428. //SOCKADDR_IN m_saSockAddr;
  429. std::list< cFragment * > m_lstQueuedPackets;
  430. std::list< cFragment * > m_lstSentPackets;
  431. };
  432. #endif // #ifndef __PACKETPIPE_H