123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- /*
- * This file is part of UAS2.
- *
- * UAS2 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * UAS2 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with UASv1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- /**
- * @file PacketPipe.h
- */
-
- #ifndef __PACKETPIPE_H
- #define __PACKETPIPE_H
-
- #include <list>
-
- #include "Message.h"
- #include "CRC_Module.h"
-
-
- typedef struct cFragment {
- BYTE m_pbData[MAX_PACKET_SIZE];
- WORD m_wSize;
- DWORD m_dwSeed;
-
- cFragment( BYTE *pbData, WORD wSize )
- : m_wSize( wSize + 36 )
- {
- CopyMemory( &m_pbData[36], pbData, wSize );
- }
-
- cFragment( )
- : m_wSize( 0 )
- {
- }
-
- ~cFragment( ) {}
-
- } cFragment;
-
- typedef struct cIgnoreRequest
- {
- DWORD m_dwZero; //Sequence - Numeric identifier for the order in which this packet should be processed.
- DWORD m_dwEight; //Flags - Bitmask identifying what data follows the header.
- DWORD m_dwCRC; // CRC - Cyclic redundancy checksum verifying all data is authentic and undamaged.
- DWORD m_dwNum; // ?
- WORD m_wUnk1; // Server Logical ID - Recipient identifier (index < 400) distinguishing the connection host.
- WORD m_wUnk2; // Time - Half-seconds since connection establishment that you received a packet.
- WORD m_wSize; // Size - Number of bytes following the header.
- WORD m_wTable; // Table - Unknown. Might involve CRC. Should match for sent/received headers.
-
- cIgnoreRequest( )
- {
- m_dwZero = 0;
- m_dwEight = 8;
- m_wSize = 8;
- m_wTable = 2;
- }
- } cIgnoreRequest;
-
- template< class _Type >
- class cPacketPipe : public _Type
- {
- friend class cClient;
- friend class cMasterServer;
-
- public:
- cPacketPipe ( ) {}
- ~cPacketPipe( )
- {
- while ( !m_lstQueuedPackets.empty( ) )
- {
- SAFEDELETE( m_lstQueuedPackets.front( ) )
- m_lstQueuedPackets.pop_front( );
- }
-
- while ( !m_lstSentPackets.empty( ) )
- {
- SAFEDELETE( m_lstSentPackets.front( ) )
- m_lstSentPackets.pop_front( );
- }
- }
-
- /**
- * Set the initial values.
- */
- inline void Initialize( )
- {
- m_dwSendSequence = 1;
- m_dwRecvSequence = 1;
- m_dwMsgID = 1;
- m_wTime = 12;
- m_pdwSendCRC = m_lpdwSendCRC;
- m_pdwRecvCRC = m_lpdwRecvCRC;
-
- ResetCRCs( );
- }
- /**
- * Reset the values.
- */
- inline void Reset( )
- {
- m_dwSendSequence = 1;
- m_dwRecvSequence = 1;
- m_dwMsgID = 1;
- m_wTime = 12;
-
- ResetCRCs( );
- }
-
- inline void SetSendSequence( DWORD dwSendSequence )
- {
- m_dwSendSequence = dwSendSequence;
- }
-
- /**
- * Creates a general CRC.
- *
- * @param *pbSendBuffer -
- * @param iSize -
- *
- * @return (dwCrc1 + dwCrc2) -
- */
- static inline DWORD CalcCRC( BYTE *pbSendBuffer, int iSize )
- {
- DWORD dwCrc1, dwCrc2, *pdwCrc;
-
- pdwCrc = (DWORD *)&pbSendBuffer[8];
- *pdwCrc = 0xBADD70DD;
- dwCrc1 = GetMagicNumber( &pbSendBuffer[0x00], 0x14, TRUE );
- dwCrc2 = GetMagicNumber( &pbSendBuffer[0x14], iSize, FALSE );
- *pdwCrc = dwCrc1 + dwCrc2;
-
- return (dwCrc1 + dwCrc2);
- }
-
- private:
- /**
- * Creates the fragment headers and adds the packet to the client's send queue.
- *
- * @param *pbData - A pointer to the data to be sent.
- * @param wSize - The size of the data.
- * @param wGroup - The group to which the data belongs (used by AddFragmentHeader).
- */
- void AddPacket( BYTE *pbData, WORD wSize, WORD wGroup )
- {
- if ( !wSize || !pbData )
- return ;
-
- WORD wDataSize;
- cFragment *pcFragment;
-
- if ( FindSpaceInQueue( pbData, wSize, wGroup ) )
- return ;
-
- WORD wSizeLeft = wSize;
- WORD wFragmentCount = wSize / MAX_DATA_SIZE;
- WORD wFragmentIndex = 0;
- BYTE *pbCurData = pbData;
-
- if ( wSize % MAX_DATA_SIZE )
- ++wFragmentCount;
-
- wDataSize = wSizeLeft > MAX_DATA_SIZE ? MAX_DATA_SIZE : wSizeLeft;
- pcFragment = new cFragment( pbCurData, wDataSize );
-
- for ( ; wFragmentIndex < wFragmentCount; ++wFragmentIndex )
- {
- AddFragmentHeader( pcFragment->m_pbData + sizeof( cTransportHeader ), wDataSize, wFragmentIndex, wFragmentCount, wGroup );
-
- pbCurData = pbCurData + wDataSize;
- wSizeLeft -= wDataSize;
- wDataSize = wSizeLeft > MAX_DATA_SIZE ? MAX_DATA_SIZE : wSizeLeft;
-
- m_lstQueuedPackets.push_back( pcFragment );
-
- if ( wDataSize )
- pcFragment = new cFragment( pbCurData, wDataSize );
- }
-
- ++m_dwMsgID;
-
- }
- /**
- * Constructs the transport headers and sends the packets.
- *
- * @param saSockAddr - The client's SOCKADDR_IN struct value.
- */
- void SendQueuedPackets( SOCKADDR_IN& saSockAddr )
- {
- cTransportHeader *pcTH;
- cFragment *pcFragment;
-
- while ( !m_lstQueuedPackets.empty( ) )
- {
- pcFragment = m_lstQueuedPackets.front( );
-
- pcTH = reinterpret_cast< cTransportHeader * >( pcFragment->m_pbData );
-
- pcTH->m_dwSequence = ++m_dwSendSequence;
- pcTH->m_dwFlags = 0x0200;
- pcTH->m_wLogicalID = m_wLogicalID;
- pcTH->m_wTime = m_wTime;
- pcTH->m_wTotalSize = pcFragment->m_wSize - sizeof( cTransportHeader );
- pcTH->m_wTable = 0x0000;
-
- DWORD dwNewCRC, dwXorVal;
- //dwNewCRC = Calc200_CRC( pcFragment->m_pbData );
- //
- dwNewCRC = GetMagicNumber(pcFragment->m_pbData + sizeof(cTransportHeader),pcTH->m_wTotalSize,1);
- //
- dwXorVal = GetSendXORVal( m_pdwSendCRC );
- dwNewCRC ^= dwXorVal;
- //
- pcTH->m_dwCRC = 0xBADD70DD;
- //
- //dwNewCRC += CalcTransportCRC( (DWORD *)pcFragment->m_pbData );
-
- dwNewCRC += GetMagicNumber(pcFragment->m_pbData, sizeof(cTransportHeader),1);
- //
- pcTH->m_dwCRC = dwNewCRC;
-
- sendto( m_Socket, (char *)pcFragment->m_pbData, pcFragment->m_wSize, NULL, (sockaddr *)&saSockAddr, sizeof( SOCKADDR ) );
-
- pcFragment->m_dwSeed = dwXorVal;
-
- m_lstSentPackets.push_back( pcFragment );
- m_lstQueuedPackets.pop_front( );
- }
- }
- /**
- * Calculates the CRC for 0x0200 packets.
- *
- * @param *pbPacket -
- *
- * @return dwCrc -
- */
- static inline DWORD Calc200_CRC( BYTE *pbPacket )
- {
- BYTE *pbPacketEnd = pbPacket + reinterpret_cast< cTransportHeader * > ( pbPacket )->m_wTotalSize + sizeof ( cTransportHeader );
- DWORD dwCrc = 0;
-
- for ( BYTE *pbFragment = pbPacket + sizeof ( cTransportHeader ); pbFragment < pbPacketEnd; )
- {
- WORD wLength = reinterpret_cast< cFragmentHeader * > ( pbFragment )->m_wFragmentLength;
-
- dwCrc += GetMagicNumber ( pbFragment, sizeof ( cFragmentHeader ), 1 ) + GetMagicNumber ( pbFragment + sizeof ( cFragmentHeader ), wLength - sizeof ( cFragmentHeader ), TRUE );
- pbFragment += wLength;
- }
-
- return dwCrc;
- }
- /**
- * Calculates the CRC for the transport header.
- *
- * @param *pdwWoot -
- *
- * @return dwCrc -
- */
- static inline DWORD CalcTransportCRC( DWORD *pdwWoot )
- {
- DWORD dwOrg = pdwWoot[2];
- DWORD dwCrc = 0;
-
- pdwWoot[2] = 0xBADD70DD;
- dwCrc += GetMagicNumber( (BYTE *)pdwWoot, 20, TRUE );
- pdwWoot[2] = dwOrg;
-
- return dwCrc;
- }
- /**
- * Seeds the CRC.
- *
- * @param *pbBuf - A pointer to the data to use.
- * @param wSize - The size of the data.
- * @param fIncludeSize -
- *
- * @return dwCS -
- */
- static DWORD GetMagicNumber( BYTE *pbBuf, WORD wSize, BOOL fIncludeSize )
- {
- DWORD dwCS = 0;
- int i;
-
- if ( fIncludeSize )
- dwCS += wSize << 16;
-
- // sum up the DWORDs:
- for (i = 0; i < (wSize >> 2); ++i )
- dwCS += ((DWORD *)pbBuf)[i];
-
- // now any remaining bytes are summed in reverse endian
- int iShift = 3;
- for ( i = (i << 2); i < wSize; ++i )
- {
- dwCS += pbBuf[i] << (iShift * 8);
- --iShift;
- }
-
- return dwCS;
- }
- /**
- * Returns a ping packet.
- *
- * @param saSockAddr - The client's SOCKADDR_IN struct value.
- */
- void ReturnPing( SOCKADDR_IN& saSockAddr )
- {
- char szSendBuffer[0x40];
-
- DWORD *last = (DWORD *)&szSendBuffer[0x14];
-
- cTransportHeader *pcTH;
- pcTH = reinterpret_cast< cTransportHeader * >( szSendBuffer );
- pcTH->m_dwSequence = m_dwSendSequence;
- pcTH->m_dwFlags = 0x00000004;
- pcTH->m_wLogicalID = m_wLogicalID;
- pcTH->m_wTime = m_wTime;
- pcTH->m_wTotalSize = 4;
- pcTH->m_wTable = 0;
-
- *last = m_dwRecvSequence;
-
- CalcCRC( (BYTE *)szSendBuffer, 4 );
- sendto( m_Socket, (char *)szSendBuffer, 24, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
- }
- /**
- * Adds a packet to the queue.
- *
- * @param cmPacket - The address of the packet message to add.
- * @param wGroup - The group to which the packet belongs (used by AddFragmentHeader).
- */
- inline void AddPacket( cMessage& cmPacket, WORD wGroup )
- {
- WORD wSize = cmPacket.getSize( );
-
- BYTE *pbData = new BYTE[wSize];
- cmPacket.getData( 0, wSize, pbData );
-
- AddPacket( pbData, wSize, wGroup );
-
- SAFEDELETE_ARRAY( pbData )
- }
- /**
- * Checks to see if this packet can be crammed into another fragment.
- *
- * @param *pbData - A pointer to the data.
- * @param wSize - The size of the data.
- * @param wGroup - The group to which the data belongs (used by AddFragmentHeader).
- */
- BOOL FindSpaceInQueue( BYTE *pbData, WORD wSize, WORD wGroup )
- {
- cFragment *pcFragment;
-
- std::list< cFragment * >::iterator itFragment = m_lstQueuedPackets.begin( );
- for ( ; itFragment != m_lstQueuedPackets.end( ); ++itFragment )
- {
- pcFragment = *itFragment;
-
- if ( pcFragment->m_wSize + wSize + sizeof( cFragmentHeader ) <= MAX_PACKET_SIZE )
- {
- CopyMemory( &pcFragment->m_pbData[pcFragment->m_wSize + sizeof( cFragmentHeader )], pbData, wSize );
- AddFragmentHeader( &pcFragment->m_pbData[pcFragment->m_wSize], wSize, 0, 1, wGroup );
- pcFragment->m_wSize += wSize + sizeof( cFragmentHeader );
- return TRUE;
- }
- }
- return FALSE;
- }
- /**
- * Creates the fragment header.
- *
- * @param *pbStart -
- * @param wSize -
- * @param wFragmentIndex -
- * @param wFragmentCount -
- * @param wGroup -
- */
- inline void AddFragmentHeader( BYTE *pbStart, WORD wSize, WORD wFragmentIndex, WORD wFragmentCount, WORD wGroup )
- {
- cFragmentHeader *pcFH = reinterpret_cast< cFragmentHeader * >( pbStart );
-
- pcFH->m_dwSequence = m_dwMsgID;
- pcFH->m_dwObjectID = 0x80000000;
- pcFH->m_wFragmentIndex = wFragmentIndex;
- pcFH->m_wFragmentLength = wSize + sizeof( cFragmentHeader );
- pcFH->m_wFragmentCount = wFragmentCount;
- pcFH->m_wFragmentGroup = wGroup;
- }
- /**
- * Resends packets that the client needs.
- *
- * @param dwNumLostPackets - The number of packets lost.
- * @param *pdwMissingPackets - An array of the lost packets (of count dwNumLostPackets).
- * @param saSockAddr - The client's SOCKADDR_IN struct value.
- */
- void ProcessLostPackets( DWORD dwNumLostPackets, DWORD *pdwMissingPackets, SOCKADDR_IN& saSockAddr )
- {
-
- DWORD dwNumIgnored = 0;
-
- std::vector< DWORD > vIgnoreList;
- vIgnoreList.reserve( dwNumLostPackets );
-
- cFragment *pcFragment;
-
- for ( DWORD dwCurrentPacket = 0; dwCurrentPacket < dwNumLostPackets; ++dwCurrentPacket )
- {
- std::list< cFragment * >::iterator itFragment = m_lstSentPackets.begin( );
- for ( ; itFragment != m_lstSentPackets.end( ); ++itFragment )
- {
- pcFragment = *itFragment;
- if ( *((DWORD *)pcFragment->m_pbData) == pdwMissingPackets[dwCurrentPacket] )
- break;
- }
-
- if ( itFragment != m_lstSentPackets.end( ) )
- {
- cTransportHeader *pcTH = reinterpret_cast< cTransportHeader * >( pcFragment->m_pbData );
-
- pcTH->m_dwFlags = 0x00000201;
- pcTH->m_wTime = m_wTime;
-
- DWORD dwNewCRC;
- dwNewCRC = Calc200_CRC( pcFragment->m_pbData );
- dwNewCRC ^= pcFragment->m_dwSeed;
- dwNewCRC += CalcTransportCRC( (DWORD *)pcFragment->m_pbData );
-
- pcTH->m_dwCRC = dwNewCRC;
-
- sendto( m_Socket, (char *)pcFragment->m_pbData, pcFragment->m_wSize, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
- }
- else
- {
- vIgnoreList.push_back( pdwMissingPackets[dwCurrentPacket] );
- ++dwNumIgnored;
- }
- }
-
- if ( !vIgnoreList.empty( ) )
- {
- BYTE pbSendBuffer[0x1E4];
-
- cIgnoreRequest irOut;
- irOut.m_dwNum = dwNumIgnored;
- irOut.m_wUnk1 = m_wLogicalID;
- irOut.m_wUnk2 = m_wTime;
- irOut.m_wSize = 4 + dwNumIgnored * 4;
-
- CopyMemory( pbSendBuffer, &irOut, sizeof( cIgnoreRequest ) );
-
- std::vector< DWORD >::iterator itIgnore = vIgnoreList.begin( );
- for ( DWORD dwCount = 0; itIgnore != vIgnoreList.end( ); ++itIgnore, ++dwCount )
- CopyMemory( pbSendBuffer + sizeof( irOut ) + dwCount * 4, &itIgnore, sizeof( DWORD ) );
-
- irOut.m_dwCRC = CalcCRC( pbSendBuffer, 4 + dwNumIgnored * 4 );
-
- sendto( m_Socket, (char*)pbSendBuffer, sizeof( irOut ) + dwNumIgnored * 4, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
-
- vIgnoreList.clear( );
- }
-
- }
- /**
- * Removes packets from the m_lstSentPackets list.
- *
- * @param dwLastGoodSeq -
- */
- inline void ClearSentPackets( DWORD dwLastGoodSeq )
- {
- cFragment *pcFragment;
-
- while ( !m_lstSentPackets.empty( ) )
- {
- pcFragment = m_lstSentPackets.front( );
-
- if ( *((DWORD *)pcFragment->m_pbData) > dwLastGoodSeq )
- break;
- else
- {
- m_lstSentPackets.pop_front( );
- SAFEDELETE( pcFragment )
- }
- }
- }
- inline void ResetCRCs( )
- {
- GenerateCRCs( m_dwSendCRCSeed, m_dwRecvCRCSeed, m_pdwSendCRC, m_pdwRecvCRC );
- }
-
- DWORD m_lpdwSendCRC[3];
- DWORD m_lpdwRecvCRC[3];
- DWORD *m_pdwSendCRC;
- DWORD *m_pdwRecvCRC;
- DWORD m_dwSendSequence;
- DWORD m_dwRecvSequence;
- DWORD m_dwMsgID;
- WORD m_wTime;
- //SOCKADDR_IN m_saSockAddr;
-
- std::list< cFragment * > m_lstQueuedPackets;
- std::list< cFragment * > m_lstSentPackets;
- };
-
- #endif // #ifndef __PACKETPIPE_H
|