Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

G2Packet.cpp

Go to the documentation of this file.
00001 //
00002 // G2Packet.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "G2Packet.h"
00026 #include "G1Packet.h"
00027 #include "Buffer.h"
00028 
00029 #ifdef _DEBUG
00030 #undef THIS_FILE
00031 static char THIS_FILE[]=__FILE__;
00032 #define new DEBUG_NEW
00033 #endif
00034 
00035 CG2Packet::CG2PacketPool CG2Packet::POOL;
00036 
00037 
00039 // CG2Packet construction
00040 
00041 CG2Packet::CG2Packet() : CPacket( PROTOCOL_G2 )
00042 {
00043         m_sType[0]              = 0;
00044         m_bCompound             = FALSE;
00045         m_bBigEndian    = FALSE;
00046 }
00047 
00048 CG2Packet::~CG2Packet()
00049 {
00050 }
00051 
00053 // CG2Packet reset
00054 
00055 void CG2Packet::Reset()
00056 {
00057         CPacket::Reset();
00058 
00059         m_sType[0]              = 0;
00060         m_bCompound             = FALSE;
00061         m_bBigEndian    = FALSE;
00062 }
00063 
00065 // CG2Packet construct from byte source
00066 
00067 CG2Packet* CG2Packet::New(BYTE* pSource)
00068 {
00069         CG2Packet* pPacket = New();
00070 
00071         BYTE nInput             = *pSource++;
00072 
00073         BYTE nLenLen    = ( nInput & 0xC0 ) >> 6;
00074         BYTE nTypeLen   = ( nInput & 0x38 ) >> 3;
00075         BYTE nFlags             = ( nInput & 0x07 );
00076 
00077         pPacket->m_bCompound    = ( nFlags & G2_FLAG_COMPOUND ) ? TRUE : FALSE;
00078         pPacket->m_bBigEndian   = ( nFlags & G2_FLAG_BIG_ENDIAN ) ? TRUE : FALSE;
00079 
00080         DWORD nLength = 0;
00081 
00082         if ( pPacket->m_bBigEndian )
00083         {
00084                 for ( nLength = 0 ; nLenLen-- ; )
00085                 {
00086                         nLength <<= 8;
00087                         nLength |= *pSource++;
00088                 }
00089         }
00090         else
00091         {
00092                 BYTE* pLenOut = (BYTE*)&nLength;
00093                 while ( nLenLen-- ) *pLenOut++ = *pSource++;
00094         }
00095 
00096         nTypeLen++;
00097     LPSTR pszType = pPacket->m_sType;
00098         for ( ; nTypeLen-- ;  ) *pszType++ = (CHAR)*pSource++;
00099         *pszType++ = 0;
00100 
00101         pPacket->Write( pSource, nLength );
00102 
00103         return pPacket;
00104 }
00105 
00107 // CG2Packet construct wrapping G1 packet
00108 
00109 CG2Packet* CG2Packet::New(LPCSTR pszType, CG1Packet* pWrap, int nMinTTL)
00110 {
00111         CG2Packet* pPacket = New( pszType, FALSE );
00112 
00113         GNUTELLAPACKET pHeader;
00114 
00115         pHeader.m_pGUID         = pWrap->m_pGUID;
00116         pHeader.m_nType         = pWrap->m_nType;
00117         pHeader.m_nTTL          = min( pWrap->m_nTTL, BYTE(nMinTTL) );
00118         pHeader.m_nHops         = pWrap->m_nHops;
00119         pHeader.m_nLength       = (LONG)pWrap->m_nLength;
00120 
00121         pPacket->Write( &pHeader, sizeof(pHeader) );
00122         pPacket->Write( pWrap->m_pBuffer, pWrap->m_nLength );
00123 
00124         return pPacket;
00125 }
00126 
00128 // CG2Packet clone
00129 
00130 CG2Packet* CG2Packet::Clone() const
00131 {
00132         CG2Packet* pPacket = CG2Packet::New( m_sType, m_bCompound );
00133         pPacket->Write( m_pBuffer, m_nLength );
00134         return pPacket;
00135 }
00136 
00138 // CG2Packet sub-packet write
00139 
00140 void CG2Packet::WritePacket(CG2Packet* pPacket)
00141 {
00142         if ( pPacket == NULL ) return;
00143         WritePacket( pPacket->m_sType, pPacket->m_nLength, pPacket->m_bCompound );
00144         Write( pPacket->m_pBuffer, pPacket->m_nLength );
00145 }
00146 
00148 // CG2Packet sub-packet write
00149 
00150 void CG2Packet::WritePacket(LPCSTR pszType, DWORD nLength, BOOL bCompound)
00151 {
00152         ASSERT( strlen( pszType ) > 0 );
00153         ASSERT( nLength <= 0xFFFFFF );
00154 
00155         BYTE nTypeLen   = (BYTE)( strlen( pszType ) - 1 ) & 0x07;
00156         BYTE nLenLen    = 1;
00157 
00158         if ( nLength > 0xFF )
00159         {
00160                 nLenLen++;
00161                 if ( nLength > 0xFFFF ) nLenLen++;
00162         }
00163 
00164         BYTE nFlags = ( nLenLen << 6 ) + ( nTypeLen << 3 );
00165 
00166         if ( bCompound ) nFlags |= G2_FLAG_COMPOUND;
00167         if ( m_bBigEndian ) nFlags |= G2_FLAG_BIG_ENDIAN;
00168 
00169         WriteByte( nFlags );
00170 
00171         if ( m_bBigEndian )
00172         {
00173                 if ( nLenLen >= 3 ) WriteByte( (BYTE)( ( nLength >> 16 ) & 0xFF ) );
00174                 if ( nLenLen >= 2 ) WriteByte( (BYTE)( ( nLength >> 8 ) & 0xFF ) );
00175                 WriteByte( (BYTE)( nLength & 0xFF ) );
00176         }
00177         else
00178         {
00179                 Write( &nLength, nLenLen );
00180         }
00181 
00182         Write( pszType, nTypeLen + 1 );
00183 
00184         m_bCompound = TRUE;     // This must be compound now
00185 }
00186 
00188 // CG2Packet sub-packet read
00189 
00190 BOOL CG2Packet::ReadPacket(LPSTR pszType, DWORD& nLength, BOOL* pbCompound)
00191 {
00192         if ( GetRemaining() == 0 ) return FALSE;
00193 
00194         BYTE nInput = ReadByte();
00195         if ( nInput == 0 ) return FALSE;
00196 
00197         BYTE nLenLen    = ( nInput & 0xC0 ) >> 6;
00198         BYTE nTypeLen   = ( nInput & 0x38 ) >> 3;
00199         BYTE nFlags             = ( nInput & 0x07 );
00200 
00201         if ( GetRemaining() < nTypeLen + nLenLen + 1 ) AfxThrowUserException();
00202 
00203         if ( m_bBigEndian )
00204         {
00205                 for ( nLength = 0 ; nLenLen-- ; )
00206                 {
00207                         nLength <<= 8;
00208                         nLength |= ReadByte();
00209                 }
00210         }
00211         else
00212         {
00213                 nLength = 0;
00214                 Read( &nLength, nLenLen );
00215         }
00216 
00217         if ( GetRemaining() < (int)nLength + nTypeLen + 1 ) AfxThrowUserException();
00218 
00219         Read( pszType, nTypeLen + 1 );
00220         pszType[ nTypeLen + 1 ] = 0;
00221 
00222         if ( pbCompound )
00223         {
00224                 *pbCompound = ( nFlags & G2_FLAG_COMPOUND ) == G2_FLAG_COMPOUND;
00225         }
00226         else
00227         {
00228                 if ( nFlags & G2_FLAG_COMPOUND ) SkipCompound( nLength );
00229         }
00230 
00231         return TRUE;
00232 }
00233 
00235 // CG2Packet skip compound sub-packets
00236 
00237 BOOL CG2Packet::SkipCompound()
00238 {
00239         if ( m_bCompound )
00240         {
00241                 DWORD nLength = m_nLength;
00242                 if ( ! SkipCompound( nLength ) ) return FALSE;
00243         }
00244 
00245         return TRUE;
00246 }
00247 
00248 BOOL CG2Packet::SkipCompound(DWORD& nLength, DWORD nRemaining)
00249 {
00250         DWORD nStart    = m_nPosition;
00251         DWORD nEnd              = m_nPosition + nLength;
00252 
00253         while ( m_nPosition < nEnd )
00254         {
00255                 BYTE nInput = ReadByte();
00256                 if ( nInput == 0 ) break;
00257 
00258                 BYTE nLenLen    = ( nInput & 0xC0 ) >> 6;
00259                 BYTE nTypeLen   = ( nInput & 0x38 ) >> 3;
00260                 BYTE nFlags             = ( nInput & 0x07 );
00261 
00262                 if ( m_nPosition + nTypeLen + nLenLen + 1 > nEnd ) AfxThrowUserException();
00263 
00264                 DWORD nPacket = 0;
00265 
00266                 if ( m_bBigEndian )
00267                 {
00268                         for ( nPacket = 0 ; nLenLen-- ; )
00269                         {
00270                                 nPacket <<= 8;
00271                                 nPacket |= ReadByte();
00272                         }
00273                 }
00274                 else
00275                 {
00276                         Read( &nPacket, nLenLen );
00277                 }
00278 
00279                 if ( m_nPosition + nTypeLen + 1 + nPacket > nEnd ) AfxThrowUserException();
00280 
00281                 m_nPosition += nPacket + nTypeLen + 1;
00282         }
00283 
00284         nEnd = m_nPosition - nStart;
00285         if ( nEnd > nLength ) AfxThrowUserException();
00286         nLength -= nEnd;
00287 
00288         return nRemaining ? nLength >= nRemaining : TRUE;
00289 }
00290 
00292 // CG2Packet read a TO block
00293 
00294 BOOL CG2Packet::GetTo(GGUID* pGUID)
00295 {
00296         if ( m_bCompound == FALSE ) return FALSE;
00297         if ( GetRemaining() < 4 + 16 ) return FALSE;
00298 
00299         BYTE* pTest = m_pBuffer + m_nPosition;
00300 
00301         if ( pTest[0] != 0x48 ) return FALSE;
00302         if ( pTest[1] != 0x10 ) return FALSE;
00303         if ( pTest[2] != 'T' ) return FALSE;
00304         if ( pTest[3] != 'O' ) return FALSE;
00305 
00306         CopyMemory( pGUID, pTest + 4, 16 );
00307 
00308         return TRUE;
00309 }
00310 
00312 // CG2Packet seek to a wrapped packet (past compound)
00313 
00314 BOOL CG2Packet::SeekToWrapped()
00315 {
00316         m_nPosition = 0;
00317 
00318         if ( ! SkipCompound() ) return FALSE;
00319         if ( GetRemaining() < sizeof(GNUTELLAPACKET) ) return FALSE;
00320 
00321         GNUTELLAPACKET* pHead = (GNUTELLAPACKET*)( m_pBuffer + m_nPosition );
00322         return (DWORD)GetRemaining() >= sizeof(GNUTELLAPACKET) + pHead->m_nLength;
00323 }
00324 
00326 // CG2Packet strings with UTF-8 encoding
00327 
00328 CString CG2Packet::ReadString(DWORD nMaximum)
00329 {
00330         CString strString;
00331 
00332         nMaximum = min( nMaximum, m_nLength - m_nPosition );
00333         if ( ! nMaximum ) return strString;
00334 
00335         LPCSTR pszInput = (LPCSTR)m_pBuffer + m_nPosition;
00336         LPCSTR pszScan  = pszInput;
00337         BOOL bEncoded   = FALSE;
00338 
00339     DWORD nLength = 0;
00340         for ( ; nLength < nMaximum ; nLength++ )
00341         {
00342                 m_nPosition++;
00343                 if ( ! *pszScan ) break;
00344                 pszScan ++;
00345         }
00346 
00347         int nWide = MultiByteToWideChar( CP_UTF8, 0, pszInput, nLength, NULL, 0 );
00348         MultiByteToWideChar( CP_UTF8, 0, pszInput, nLength, strString.GetBuffer( nWide ), nWide );
00349         strString.ReleaseBuffer( nWide );
00350 
00351         return strString;
00352 }
00353 
00354 void CG2Packet::WriteString(LPCTSTR pszString, BOOL bNull)
00355 {
00356         if ( *pszString == NULL )
00357         {
00358                 if ( bNull ) WriteByte( 0 );
00359                 return;
00360         }
00361 
00362         int nWide               = _tcslen(pszString);
00363         int nByte               = WideCharToMultiByte( CP_UTF8, 0, pszString, nWide, NULL, 0, NULL, NULL );
00364         LPSTR pszByte   = ( nByte <= PACKET_BUF_SCHAR ) ? m_szSCHAR : new CHAR[ nByte + 1 ];
00365 
00366         WideCharToMultiByte( CP_UTF8, 0, pszString, nWide, pszByte, nByte, NULL, NULL );
00367 
00368         if ( bNull )
00369         {
00370                 pszByte[ nByte ] = 0;
00371                 Write( pszByte, nByte + 1 );
00372         }
00373         else
00374                 Write( pszByte, nByte );
00375 
00376         if ( pszByte != m_szSCHAR ) delete [] pszByte;
00377 }
00378 
00379 void CG2Packet::WriteString(LPCSTR pszString, BOOL bNull)
00380 {
00381         if ( *pszString == NULL )
00382         {
00383                 if ( bNull ) WriteByte( 0 );
00384                 return;
00385         }
00386 
00387         Write( pszString, strlen(pszString) + ( bNull ? 1 : 0 ) );
00388 }
00389 
00390 int CG2Packet::GetStringLen(LPCTSTR pszString) const
00391 {
00392         if ( *pszString == 0 ) return 0;
00393 
00394         LPCTSTR pszScan = pszString;
00395         BOOL bPlain = TRUE;
00396 
00397     int nLength = 0;
00398         for ( ; *pszScan ; nLength++ )
00399         {
00400                 if ( ( *pszScan++ ) & 0x80 ) bPlain = FALSE;
00401         }
00402 
00403         nLength = WideCharToMultiByte( CP_UTF8, 0, pszString, nLength, NULL, 0, NULL, NULL );
00404 
00405         return nLength;
00406 }
00407 
00409 // CG2Packet to buffer
00410 
00411 void CG2Packet::ToBuffer(CBuffer* pBuffer) const
00412 {
00413         ASSERT( strlen( m_sType ) > 0 );
00414 
00415         BYTE nLenLen    = 1;
00416         BYTE nTypeLen   = (BYTE)( strlen( m_sType ) - 1 ) & 0x07;
00417 
00418         if ( m_nLength > 0xFF )
00419         {
00420                 nLenLen++;
00421                 if ( m_nLength > 0xFFFF ) nLenLen++;
00422         }
00423 
00424         BYTE nFlags = ( nLenLen << 6 ) + ( nTypeLen << 3 );
00425 
00426         if ( m_bCompound ) nFlags |= G2_FLAG_COMPOUND;
00427         if ( m_bBigEndian ) nFlags |= G2_FLAG_BIG_ENDIAN;
00428 
00429         pBuffer->Add( &nFlags, 1 );
00430 
00431         if ( m_bBigEndian )
00432         {
00433                 pBuffer->EnsureBuffer( nLenLen );
00434                 BYTE* pOut = pBuffer->m_pBuffer + pBuffer->m_nLength;
00435                 pBuffer->m_nLength += nLenLen;
00436 
00437                 if ( nLenLen >= 3 ) *pOut++ = (BYTE)( ( m_nLength >> 16 ) & 0xFF );
00438                 if ( nLenLen >= 2 ) *pOut++ = (BYTE)( ( m_nLength >> 8 ) & 0xFF );
00439                 *pOut++ = (BYTE)( m_nLength & 0xFF );
00440         }
00441         else
00442         {
00443                 pBuffer->Add( &m_nLength, nLenLen );
00444         }
00445 
00446         pBuffer->Add( m_sType, nTypeLen + 1 );
00447 
00448         pBuffer->Add( m_pBuffer, m_nLength );
00449 }
00450 
00452 // CG2Packet buffer stream read
00453 
00454 CG2Packet* CG2Packet::ReadBuffer(CBuffer* pBuffer)
00455 {
00456         if ( pBuffer == NULL ) return NULL;
00457 
00458         if ( pBuffer->m_nLength == 0 ) return NULL;
00459         BYTE nInput = *(pBuffer->m_pBuffer);
00460 
00461         if ( nInput == 0 )
00462         {
00463                 pBuffer->Remove( 1 );
00464                 return NULL;
00465         }
00466 
00467         BYTE nLenLen    = ( nInput & 0xC0 ) >> 6;
00468         BYTE nTypeLen   = ( nInput & 0x38 ) >> 3;
00469         BYTE nFlags             = ( nInput & 0x07 );
00470 
00471         if ( (DWORD)pBuffer->m_nLength < (DWORD)nLenLen + nTypeLen + 2 ) return NULL;
00472 
00473         DWORD nLength = 0;
00474 
00475         if ( nFlags & G2_FLAG_BIG_ENDIAN )
00476         {
00477                 BYTE* pLenIn = pBuffer->m_pBuffer + 1;
00478 
00479                 for ( BYTE nIt = nLenLen ; nIt ; nIt-- )
00480                 {
00481                         nLength <<= 8;
00482                         nLength |= *pLenIn++;
00483                 }
00484         }
00485         else
00486         {
00487                 BYTE* pLenIn    = pBuffer->m_pBuffer + 1;
00488                 BYTE* pLenOut   = (BYTE*)&nLength;
00489                 for ( BYTE nLenCnt = nLenLen ; nLenCnt-- ; ) *pLenOut++ = *pLenIn++;
00490         }
00491 
00492         if ( (DWORD)pBuffer->m_nLength < (DWORD)nLength + nLenLen + nTypeLen + 2 )
00493                 return NULL;
00494 
00495         CG2Packet* pPacket = CG2Packet::New( pBuffer->m_pBuffer );
00496         pBuffer->Remove( nLength + nLenLen + nTypeLen + 2 );
00497 
00498         return pPacket;
00499 }
00500 
00502 // CG2Packet debug
00503 
00504 void CG2Packet::Debug(LPCTSTR pszReason) const
00505 {
00506 #ifdef _DEBUG
00507 
00508         CString strOutput;
00509         strOutput.Format( L"[G2]: '%s' %s %s", pszReason, GetType(), (LPCTSTR)ToASCII() );
00510         CPacket::Debug( strOutput );
00511 
00512 #endif
00513 }
00514 

Generated on Thu Dec 15 10:39:42 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2