00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
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
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
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;
00185 }
00186
00188
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
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
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
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
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
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
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
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