- Main Page
- Classes
- Files

- File List
- File Members

# E:/uas2/Server/PacketPipe.h

Go to the documentation of this file.

    00001 /*
    00002 * This file is part of UAS2.
    00003 *
    00004 * UAS2 is free software; you can redistribute it and/or modify
    00005 * it under the terms of the GNU General Public License as published by
    00006 * the Free Software Foundation; either version 2 of the License, or
    00007 * (at your option) any later version.
    00008 *
    00009 * UAS2 is distributed in the hope that it will be useful,
    00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012 * GNU General Public License for more details.
    00013
    00014 * You should have received a copy of the GNU General Public License
    00015 * along with UASv1; if not, write to the Free Software
    00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00017 */
    00018
    00023 #ifndef __PACKETPIPE_H
    00024 #define __PACKETPIPE_H
    00025
    00026 #include <list>
    00027
    00028 #include "Message.h"
    00029 #include "CRC_Module.h"
    00030
    00031
    00032 typedef struct cFragment {
    00033         BYTE            m_pbData[MAX_PACKET_SIZE];
    00034         WORD            m_wSize;
    00035         DWORD           m_dwSeed;
    00036
    00037         cFragment( BYTE *pbData, WORD wSize )
    00038                 :       m_wSize( wSize + 36 )
    00039         {
    00040                 CopyMemory( &m_pbData[36], pbData, wSize );
    00041         }
    00042
    00043         cFragment( )
    00044                 :       m_wSize( 0 )
    00045         {
    00046         }
    00047
    00048         ~cFragment( ) {}
    00049
    00050 } cFragment;
    00051
    00052 typedef struct cIgnoreRequest
    00053 {
    00054         DWORD   m_dwZero;       //Sequence - Numeric identifier for the order in which this packet should be processed.
    00055         DWORD   m_dwEight;      //Flags - Bitmask identifying what data follows the header.
    00056         DWORD   m_dwCRC;        // CRC - Cyclic redundancy checksum verifying all data is authentic and undamaged.
    00057         DWORD   m_dwNum;        // ?
    00058         WORD    m_wUnk1;        // Server Logical ID - Recipient identifier (index < 400) distinguishing the connection host.
    00059         WORD    m_wUnk2;        // Time - Half-seconds since connection establishment that you received a packet.
    00060         WORD    m_wSize;        // Size - Number of bytes following the header.
    00061         WORD    m_wTable;       // Table - Unknown. Might involve CRC. Should match for sent/received headers.
    00062
    00063         cIgnoreRequest( )
    00064         {
    00065                 m_dwZero        = 0;
    00066                 m_dwEight       = 8;
    00067                 m_wSize         = 8;
    00068                 m_wTable        = 2;
    00069         }
    00070 } cIgnoreRequest;
    00071
    00072 template< class _Type >
    00073 class cPacketPipe : public _Type
    00074 {
    00075         friend class cClient;
    00076         friend class cMasterServer;
    00077
    00078 public:
    00079         cPacketPipe     ( )     {}
    00080         ~cPacketPipe( )
    00081         {
    00082                 while ( !m_lstQueuedPackets.empty( ) )
    00083                 {
    00084                         SAFEDELETE( m_lstQueuedPackets.front( ) )
    00085                         m_lstQueuedPackets.pop_front( );
    00086                 }
    00087
    00088                 while ( !m_lstSentPackets.empty( ) )
    00089                 {
    00090                         SAFEDELETE( m_lstSentPackets.front( ) )
    00091                         m_lstSentPackets.pop_front( );
    00092                 }
    00093         }
    00094
    00098         inline void Initialize( )
    00099         {
    00100                 m_dwSendSequence        = 1;
    00101                 m_dwRecvSequence        = 1;
    00102                 m_dwMsgID                       = 1;
    00103                 m_wTime                         = 12;
    00104                 m_pdwSendCRC            = m_lpdwSendCRC;
    00105                 m_pdwRecvCRC            = m_lpdwRecvCRC;
    00106
    00107                 ResetCRCs( );
    00108         }
    00112         inline void Reset( )
    00113         {
    00114                 m_dwSendSequence        = 1;
    00115                 m_dwRecvSequence        = 1;
    00116                 m_dwMsgID                       = 1;
    00117                 m_wTime                         = 12;
    00118
    00119                 ResetCRCs( );
    00120         }
    00121
    00122         inline void SetSendSequence( DWORD dwSendSequence )
    00123         {
    00124                 m_dwSendSequence = dwSendSequence;
    00125         }
    00126
    00135         static inline DWORD CalcCRC( BYTE *pbSendBuffer, int iSize )
    00136         {
    00137                 DWORD dwCrc1, dwCrc2, *pdwCrc;
    00138
    00139                 pdwCrc  = (DWORD *)&pbSendBuffer[8];
    00140                 *pdwCrc = 0xBADD70DD;
    00141                 dwCrc1  = GetMagicNumber( &pbSendBuffer[0x00], 0x14, TRUE );
    00142                 dwCrc2  = GetMagicNumber( &pbSendBuffer[0x14], iSize, FALSE );
    00143                 *pdwCrc = dwCrc1 + dwCrc2;
    00144
    00145                 return (dwCrc1 + dwCrc2);
    00146         }
    00147
    00148 private:
    00156         void AddPacket( BYTE *pbData, WORD wSize, WORD wGroup )
    00157         {
    00158                 if ( !wSize || !pbData )
    00159                         return ;
    00160
    00161                 WORD                    wDataSize;
    00162                 cFragment               *pcFragment;
    00163
    00164                 if ( FindSpaceInQueue( pbData, wSize, wGroup ) )
    00165                         return ;
    00166
    00167                 WORD wSizeLeft          = wSize;
    00168                 WORD wFragmentCount     = wSize / MAX_DATA_SIZE;
    00169                 WORD wFragmentIndex     = 0;
    00170                 BYTE *pbCurData         = pbData;
    00171
    00172                 if ( wSize % MAX_DATA_SIZE )
    00173                         ++wFragmentCount;
    00174
    00175                 wDataSize       = wSizeLeft > MAX_DATA_SIZE ? MAX_DATA_SIZE : wSizeLeft;
    00176                 pcFragment      = new cFragment( pbCurData, wDataSize );
    00177
    00178                 for ( ; wFragmentIndex < wFragmentCount; ++wFragmentIndex )
    00179                 {
    00180                         AddFragmentHeader( pcFragment->m_pbData + sizeof( cTransportHeader ), wDataSize, wFragmentIndex, wFragmentCount, wGroup );
    00181
    00182                         pbCurData       = pbCurData + wDataSize;
    00183                         wSizeLeft       -= wDataSize;
    00184                         wDataSize       = wSizeLeft > MAX_DATA_SIZE ? MAX_DATA_SIZE : wSizeLeft;
    00185
    00186                         m_lstQueuedPackets.push_back( pcFragment );
    00187
    00188                         if ( wDataSize )
    00189                                 pcFragment = new cFragment( pbCurData, wDataSize );
    00190                 }
    00191
    00192                 ++m_dwMsgID;
    00193
    00194         }
    00200         void SendQueuedPackets( SOCKADDR_IN& saSockAddr )
    00201         {
    00202                 cTransportHeader *pcTH;
    00203                 cFragment *pcFragment;
    00204
    00205                 while ( !m_lstQueuedPackets.empty( ) )
    00206                 {
    00207                         pcFragment = m_lstQueuedPackets.front( );
    00208
    00209                         pcTH = reinterpret_cast< cTransportHeader * >( pcFragment->m_pbData );
    00210
    00211                         pcTH->m_dwSequence      = ++m_dwSendSequence;
    00212                         pcTH->m_dwFlags         = 0x0200;
    00213                         pcTH->m_wLogicalID      = m_wLogicalID;
    00214                         pcTH->m_wTime           = m_wTime;
    00215                         pcTH->m_wTotalSize      = pcFragment->m_wSize - sizeof( cTransportHeader );
    00216                         pcTH->m_wTable          = 0x0000;
    00217
    00218                         DWORD dwNewCRC, dwXorVal;
    00219                         //dwNewCRC = Calc200_CRC( pcFragment->m_pbData );
    00220 //
    00221                         dwNewCRC = GetMagicNumber(pcFragment->m_pbData + sizeof(cTransportHeader),pcTH->m_wTotalSize,1);
    00222 //
    00223                         dwXorVal = GetSendXORVal( m_pdwSendCRC );
    00224                         dwNewCRC ^= dwXorVal;
    00225 //
    00226                         pcTH->m_dwCRC = 0xBADD70DD;
    00227 //
    00228                         //dwNewCRC += CalcTransportCRC( (DWORD *)pcFragment->m_pbData );
    00229
    00230                         dwNewCRC += GetMagicNumber(pcFragment->m_pbData, sizeof(cTransportHeader),1);
    00231 //
    00232                         pcTH->m_dwCRC = dwNewCRC;
    00233
    00234                         sendto( m_Socket, (char *)pcFragment->m_pbData, pcFragment->m_wSize, NULL, (sockaddr *)&saSockAddr, sizeof( SOCKADDR ) );
    00235
    00236                         pcFragment->m_dwSeed = dwXorVal;
    00237
    00238                         m_lstSentPackets.push_back( pcFragment );
    00239                         m_lstQueuedPackets.pop_front( );
    00240                 }
    00241         }
    00249         static inline DWORD Calc200_CRC( BYTE *pbPacket )
    00250         {
    00251                 BYTE *pbPacketEnd = pbPacket + reinterpret_cast< cTransportHeader * > ( pbPacket )->m_wTotalSize + sizeof ( cTransportHeader );
    00252                 DWORD dwCrc = 0;
    00253
    00254                 for ( BYTE *pbFragment = pbPacket + sizeof ( cTransportHeader ); pbFragment < pbPacketEnd; )
    00255                 {
    00256                         WORD wLength = reinterpret_cast< cFragmentHeader * > ( pbFragment )->m_wFragmentLength;
    00257
    00258                         dwCrc += GetMagicNumber ( pbFragment, sizeof ( cFragmentHeader ), 1 ) + GetMagicNumber ( pbFragment + sizeof ( cFragmentHeader ), wLength - sizeof ( cFragmentHeader ), TRUE );
    00259                         pbFragment += wLength;
    00260                 }
    00261
    00262                 return dwCrc;
    00263         }
    00271         static inline DWORD CalcTransportCRC( DWORD *pdwWoot )
    00272         {
    00273                 DWORD dwOrg = pdwWoot[2];
    00274                 DWORD dwCrc     = 0;
    00275
    00276                 pdwWoot[2]      = 0xBADD70DD;
    00277                 dwCrc           += GetMagicNumber( (BYTE *)pdwWoot, 20, TRUE );
    00278                 pdwWoot[2]      = dwOrg;
    00279
    00280                 return dwCrc;
    00281         }
    00291         static DWORD GetMagicNumber( BYTE *pbBuf, WORD wSize, BOOL fIncludeSize )
    00292         {
    00293                 DWORD dwCS = 0;
    00294                 int i;
    00295
    00296                 if ( fIncludeSize )
    00297                         dwCS += wSize << 16;
    00298
    00299                 // sum up the DWORDs:
    00300                 for (i = 0; i < (wSize >> 2); ++i )
    00301                         dwCS += ((DWORD *)pbBuf)[i];
    00302
    00303                 // now any remaining bytes are summed in reverse endian
    00304                 int iShift = 3;
    00305                 for ( i = (i << 2); i < wSize; ++i )
    00306                 {
    00307                         dwCS += pbBuf[i] << (iShift * 8);
    00308                         --iShift;
    00309                 }
    00310
    00311                 return dwCS;
    00312         }
    00318         void ReturnPing( SOCKADDR_IN& saSockAddr )
    00319         {
    00320                 char szSendBuffer[0x40];
    00321
    00322                 DWORD *last = (DWORD *)&szSendBuffer[0x14];
    00323
    00324                 cTransportHeader *pcTH;
    00325                 pcTH = reinterpret_cast< cTransportHeader * >( szSendBuffer );
    00326                 pcTH->m_dwSequence      = m_dwSendSequence;
    00327                 pcTH->m_dwFlags         = 0x00000004;
    00328                 pcTH->m_wLogicalID      = m_wLogicalID;
    00329                 pcTH->m_wTime           = m_wTime;
    00330                 pcTH->m_wTotalSize      = 4;
    00331                 pcTH->m_wTable          = 0;
    00332
    00333                 *last = m_dwRecvSequence;
    00334
    00335                 CalcCRC( (BYTE *)szSendBuffer, 4 );
    00336                 sendto( m_Socket, (char *)szSendBuffer, 24, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
    00337         }
    00344         inline void AddPacket( cMessage& cmPacket, WORD wGroup )
    00345         {
    00346                 WORD wSize = cmPacket.getSize( );
    00347
    00348                 BYTE *pbData = new BYTE[wSize];
    00349                 cmPacket.getData( 0, wSize, pbData );
    00350
    00351                 AddPacket( pbData, wSize, wGroup );
    00352
    00353                 SAFEDELETE_ARRAY( pbData )
    00354         }
    00362         BOOL FindSpaceInQueue( BYTE *pbData, WORD wSize, WORD wGroup )
    00363         {
    00364                 cFragment *pcFragment;
    00365
    00366                 std::list< cFragment * >::iterator itFragment = m_lstQueuedPackets.begin( );
    00367                 for ( ; itFragment != m_lstQueuedPackets.end( ); ++itFragment )
    00368                 {
    00369                         pcFragment = *itFragment;
    00370
    00371                         if ( pcFragment->m_wSize + wSize + sizeof( cFragmentHeader ) <= MAX_PACKET_SIZE )
    00372                         {
    00373                                 CopyMemory( &pcFragment->m_pbData[pcFragment->m_wSize + sizeof( cFragmentHeader )], pbData, wSize );
    00374                                 AddFragmentHeader( &pcFragment->m_pbData[pcFragment->m_wSize], wSize, 0, 1, wGroup );
    00375                                 pcFragment->m_wSize += wSize + sizeof( cFragmentHeader );
    00376                                 return TRUE;
    00377                         }
    00378                 }
    00379                 return FALSE;
    00380         }
    00390         inline void AddFragmentHeader( BYTE *pbStart, WORD wSize, WORD wFragmentIndex, WORD wFragmentCount, WORD wGroup )
    00391         {
    00392                 cFragmentHeader *pcFH = reinterpret_cast< cFragmentHeader * >( pbStart );
    00393
    00394                 pcFH->m_dwSequence              = m_dwMsgID;
    00395                 pcFH->m_dwObjectID              = 0x80000000;
    00396                 pcFH->m_wFragmentIndex  = wFragmentIndex;
    00397                 pcFH->m_wFragmentLength = wSize + sizeof( cFragmentHeader );
    00398                 pcFH->m_wFragmentCount  = wFragmentCount;
    00399                 pcFH->m_wFragmentGroup  = wGroup;
    00400         }
    00408         void ProcessLostPackets( DWORD dwNumLostPackets, DWORD *pdwMissingPackets, SOCKADDR_IN& saSockAddr )
    00409         {
    00410
    00411                 DWORD dwNumIgnored = 0;
    00412
    00413                 std::vector< DWORD > vIgnoreList;
    00414                 vIgnoreList.reserve( dwNumLostPackets );
    00415
    00416                 cFragment *pcFragment;
    00417
    00418                 for ( DWORD dwCurrentPacket = 0; dwCurrentPacket < dwNumLostPackets; ++dwCurrentPacket )
    00419                 {
    00420                         std::list< cFragment * >::iterator itFragment = m_lstSentPackets.begin( );
    00421                         for ( ; itFragment != m_lstSentPackets.end( ); ++itFragment )
    00422                         {
    00423                                 pcFragment = *itFragment;
    00424                                 if ( *((DWORD *)pcFragment->m_pbData) == pdwMissingPackets[dwCurrentPacket] )
    00425                                         break;
    00426                         }
    00427
    00428                         if ( itFragment != m_lstSentPackets.end( ) )
    00429                         {
    00430                                 cTransportHeader *pcTH = reinterpret_cast< cTransportHeader * >( pcFragment->m_pbData );
    00431
    00432                                 pcTH->m_dwFlags = 0x00000201;
    00433                                 pcTH->m_wTime   = m_wTime;
    00434
    00435                                 DWORD dwNewCRC;
    00436                                 dwNewCRC = Calc200_CRC( pcFragment->m_pbData );
    00437                                 dwNewCRC ^= pcFragment->m_dwSeed;
    00438                                 dwNewCRC += CalcTransportCRC( (DWORD *)pcFragment->m_pbData );
    00439
    00440                                 pcTH->m_dwCRC = dwNewCRC;
    00441
    00442                                 sendto( m_Socket, (char *)pcFragment->m_pbData, pcFragment->m_wSize, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
    00443                         }
    00444                         else
    00445                         {
    00446                                 vIgnoreList.push_back( pdwMissingPackets[dwCurrentPacket] );
    00447                                 ++dwNumIgnored;
    00448                         }
    00449                 }
    00450
    00451                 if ( !vIgnoreList.empty( ) )
    00452                 {
    00453                         BYTE pbSendBuffer[0x1E4];
    00454
    00455                         cIgnoreRequest irOut;
    00456                         irOut.m_dwNum   = dwNumIgnored;
    00457                         irOut.m_wUnk1   = m_wLogicalID;
    00458                         irOut.m_wUnk2   = m_wTime;
    00459                         irOut.m_wSize   = 4 + dwNumIgnored * 4;
    00460
    00461                         CopyMemory( pbSendBuffer, &irOut, sizeof( cIgnoreRequest ) );
    00462
    00463                         std::vector< DWORD >::iterator itIgnore = vIgnoreList.begin( );
    00464                         for ( DWORD dwCount = 0; itIgnore != vIgnoreList.end( ); ++itIgnore, ++dwCount )
    00465                                 CopyMemory( pbSendBuffer + sizeof( irOut ) + dwCount * 4, &itIgnore, sizeof( DWORD ) );
    00466
    00467                         irOut.m_dwCRC = CalcCRC( pbSendBuffer, 4 + dwNumIgnored * 4 );
    00468
    00469                         sendto( m_Socket, (char*)pbSendBuffer, sizeof( irOut ) + dwNumIgnored * 4, NULL, (SOCKADDR *)&saSockAddr, sizeof( SOCKADDR ) );
    00470
    00471                         vIgnoreList.clear( );
    00472                 }
    00473
    00474         }
    00480         inline void ClearSentPackets( DWORD dwLastGoodSeq )
    00481         {
    00482                 cFragment *pcFragment;
    00483
    00484                 while ( !m_lstSentPackets.empty( ) )
    00485                 {
    00486                         pcFragment = m_lstSentPackets.front( );
    00487
    00488                         if ( *((DWORD *)pcFragment->m_pbData) > dwLastGoodSeq )
    00489                                 break;
    00490                         else
    00491                         {
    00492                                 m_lstSentPackets.pop_front( );
    00493                                 SAFEDELETE( pcFragment )
    00494                         }
    00495                 }
    00496         }
    00497         inline void ResetCRCs( )
    00498         {
    00499                 GenerateCRCs( m_dwSendCRCSeed, m_dwRecvCRCSeed, m_pdwSendCRC, m_pdwRecvCRC );
    00500         }
    00501
    00502         DWORD           m_lpdwSendCRC[3];
    00503         DWORD           m_lpdwRecvCRC[3];
    00504         DWORD           *m_pdwSendCRC;
    00505         DWORD           *m_pdwRecvCRC;
    00506         DWORD           m_dwSendSequence;
    00507         DWORD           m_dwRecvSequence;
    00508         DWORD           m_dwMsgID;
    00509         WORD            m_wTime;
    00510         //SOCKADDR_IN m_saSockAddr;
    00511
    00512         std::list< cFragment * > m_lstQueuedPackets;
    00513         std::list< cFragment * > m_lstSentPackets;
    00514 };
    00515
    00516 #endif  // #ifndef __PACKETPIPE_H