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 "Network.h"
00026 #include "Security.h"
00027 #include "Statistics.h"
00028 #include "Neighbours.h"
00029 #include "G2Neighbour.h"
00030 #include "G2Packet.h"
00031 #include "G1Packet.h"
00032 #include "Buffer.h"
00033 #include "Handshakes.h"
00034 #include "Datagrams.h"
00035 #include "HostCache.h"
00036 #include "RouteCache.h"
00037 #include "VendorCache.h"
00038 #include "QuerySearch.h"
00039 #include "QueryHit.h"
00040 #include "Library.h"
00041 #include "LocalSearch.h"
00042 #include "SearchManager.h"
00043 #include "QueryHashTable.h"
00044 #include "HubHorizon.h"
00045 #include "GProfile.h"
00046 #include "Uploads.h"
00047 #include "XML.h"
00048
00049 #ifdef _DEBUG
00050 #undef THIS_FILE
00051 static char THIS_FILE[]=__FILE__;
00052 #define new DEBUG_NEW
00053 #endif
00054
00055
00057
00058
00059 CG2Neighbour::CG2Neighbour(CNeighbour* pBase) : CNeighbour( PROTOCOL_G2, pBase )
00060 {
00061 theApp.Message( MSG_DEFAULT, IDS_HANDSHAKE_ONLINE_G2, (LPCTSTR)m_sAddress,
00062 m_sUserAgent.IsEmpty() ? _T("Unknown") : (LPCTSTR)m_sUserAgent );
00063
00064 m_nLeafCount = 0;
00065 m_nLeafLimit = 0;
00066 m_bCachedKeys = FALSE;
00067
00068 m_pGUIDCache = new CRouteCache();
00069 m_pHubGroup = new CHubHorizonGroup();
00070
00071 m_tAdjust = 0;
00072 m_tLastPingIn = 0;
00073 m_tLastPingOut = 0;
00074 m_tLastPacket = GetTickCount();
00075 m_tWaitLNI = m_tLastPacket;
00076 m_tLastKHL = m_tLastPacket - Settings.Gnutella2.KHLPeriod + 1000;
00077 m_tLastHAW = m_tLastPacket;
00078
00079 m_nQueryLimiter = 40;
00080 m_tQueryTimer = 0;
00081 m_bBlacklisted = FALSE;
00082
00083 SendStartups();
00084 }
00085
00086 CG2Neighbour::~CG2Neighbour()
00087 {
00088 delete m_pHubGroup;
00089 delete m_pGUIDCache;
00090
00091 for ( POSITION pos = m_pOutbound.GetHeadPosition() ; pos ; )
00092 {
00093 CG2Packet* pOutbound = (CG2Packet*)m_pOutbound.GetNext( pos );
00094 pOutbound->Release();
00095 }
00096 }
00097
00099
00100
00101 BOOL CG2Neighbour::OnRead()
00102 {
00103 CNeighbour::OnRead();
00104 return ProcessPackets();
00105 }
00106
00107 BOOL CG2Neighbour::OnWrite()
00108 {
00109 CBuffer* pOutput = m_pZOutput ? m_pZOutput : m_pOutput;
00110
00111 while ( pOutput->m_nLength == 0 && m_nOutbound > 0 )
00112 {
00113 CG2Packet* pPacket = (CG2Packet*)m_pOutbound.RemoveHead();
00114 m_nOutbound--;
00115
00116 pPacket->ToBuffer( pOutput );
00117 pPacket->Release();
00118
00119 CNeighbour::OnWrite();
00120 }
00121
00122 CNeighbour::OnWrite();
00123
00124 return TRUE;
00125 }
00126
00128
00129
00130 BOOL CG2Neighbour::OnRun()
00131 {
00132 if ( ! CNeighbour::OnRun() ) return FALSE;
00133
00134 DWORD tNow = GetTickCount();
00135
00136 if ( m_tWaitLNI > 0 && tNow - m_tWaitLNI > Settings.Gnutella2.KHLPeriod * 3 )
00137 {
00138 Close( IDS_CONNECTION_TIMEOUT_TRAFFIC );
00139 return FALSE;
00140 }
00141 else if ( tNow - m_tLastPingOut >= Settings.Gnutella1.PingRate )
00142 {
00143 BOOL bNeedStable = Network.IsListening() && ! Datagrams.IsStable();
00144 CG2Packet* pPing = CG2Packet::New( G2_PACKET_PING, TRUE );
00145
00146 if ( bNeedStable )
00147 {
00148 pPing->WritePacket( "UDP", 6 );
00149 pPing->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00150 pPing->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00151 }
00152
00153 Send( pPing );
00154 Datagrams.Send( &m_pHost, CG2Packet::New( G2_PACKET_PING ) );
00155 m_tLastPingOut = tNow;
00156 }
00157
00158 if ( tNow - m_tLastKHL > Settings.Gnutella2.KHLPeriod )
00159 {
00160 SendLNI();
00161 SendKHL();
00162 }
00163 else if ( tNow - m_tLastHAW > Settings.Gnutella2.HAWPeriod )
00164 {
00165 SendHAW();
00166 }
00167
00168
00169 if ( m_nNodeType == ntLeaf )
00170 {
00171 if ( ( tNow - m_tQueryTimer ) > ( 5*60*1000 ) )
00172 {
00173 if ( m_nQueryLimiter < 60 ) m_nQueryLimiter ++;
00174 m_tQueryTimer = tNow;
00175 }
00176 }
00177 else
00178 {
00179 if ( ( tNow - m_tQueryTimer ) > ( 1000 ) )
00180 {
00181 if ( m_nQueryLimiter < 240 ) m_nQueryLimiter += 10;
00182 m_tQueryTimer = tNow;
00183 }
00184 }
00185
00186 return TRUE;
00187 }
00188
00190
00191
00192 BOOL CG2Neighbour::Send(CPacket* pPacket, BOOL bRelease, BOOL bBuffered)
00193 {
00194 BOOL bSuccess = FALSE;
00195
00196 if ( m_nState >= nrsConnected && pPacket->m_nProtocol == PROTOCOL_G2 )
00197 {
00198 m_nOutputCount++;
00199 Statistics.Current.Gnutella2.Outgoing++;
00200
00201 if ( bBuffered )
00202 {
00203 if ( m_nOutbound >= Settings.Gnutella1.PacketBufferSize )
00204 {
00205 CG2Packet* pRemove = (CG2Packet*)m_pOutbound.RemoveTail();
00206 pRemove->Release();
00207 m_nOutbound--;
00208 Statistics.Current.Gnutella2.Lost++;
00209 }
00210
00211 pPacket->AddRef();
00212 m_pOutbound.AddHead( pPacket );
00213 m_nOutbound++;
00214 }
00215 else
00216 {
00217 pPacket->ToBuffer( m_pZOutput ? m_pZOutput : m_pOutput );
00218 }
00219
00220 QueueRun();
00221
00222 pPacket->SmartDump( this, NULL, TRUE );
00223
00224 bSuccess = TRUE;
00225 }
00226
00227 if ( bRelease ) pPacket->Release();
00228
00229 return bSuccess;
00230 }
00231
00233
00234
00235 void CG2Neighbour::SendStartups()
00236 {
00237 CG2Packet* pPing = CG2Packet::New( G2_PACKET_PING, TRUE );
00238
00239 if ( Network.IsListening() )
00240 {
00241 pPing->WritePacket( "UDP", 6 );
00242 pPing->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00243 pPing->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00244 }
00245
00246 Send( pPing, TRUE, TRUE );
00247 m_tLastPingOut = GetTickCount();
00248
00249 Datagrams.Send( &m_pHost, CG2Packet::New( G2_PACKET_PING ) );
00250
00251 Send( CG2Packet::New( G2_PACKET_PROFILE_CHALLENGE ), TRUE, TRUE );
00252 }
00253
00255
00256
00257 BOOL CG2Neighbour::ProcessPackets()
00258 {
00259 CBuffer* pInput = m_pZInput ? m_pZInput : m_pInput;
00260
00261 BOOL bSuccess = TRUE;
00262 for ( ; bSuccess && pInput->m_nLength ; )
00263 {
00264 BYTE nInput = *(pInput->m_pBuffer);
00265
00266 if ( nInput == 0 )
00267 {
00268 pInput->Remove( 1 );
00269 continue;
00270 }
00271
00272 BYTE nLenLen = ( nInput & 0xC0 ) >> 6;
00273 BYTE nTypeLen = ( nInput & 0x38 ) >> 3;
00274 BYTE nFlags = ( nInput & 0x07 );
00275
00276 if ( (DWORD)pInput->m_nLength < (DWORD)nLenLen + nTypeLen + 2 ) break;
00277
00278 DWORD nLength = 0;
00279
00280 if ( nFlags & G2_FLAG_BIG_ENDIAN )
00281 {
00282 BYTE* pLenIn = pInput->m_pBuffer + 1;
00283
00284 for ( BYTE nIt = nLenLen ; nIt ; nIt-- )
00285 {
00286 nLength <<= 8;
00287 nLength |= *pLenIn++;
00288 }
00289 }
00290 else
00291 {
00292 BYTE* pLenIn = pInput->m_pBuffer + 1;
00293 BYTE* pLenOut = (BYTE*)&nLength;
00294 for ( BYTE nLenCnt = nLenLen ; nLenCnt-- ; ) *pLenOut++ = *pLenIn++;
00295 }
00296
00297 if ( nLength >= Settings.Gnutella1.MaximumPacket )
00298 {
00299 Close( IDS_PROTOCOL_TOO_LARGE );
00300 return FALSE;
00301 }
00302
00303 if ( (DWORD)pInput->m_nLength < (DWORD)nLength + nLenLen + nTypeLen + 2 ) break;
00304
00305 CG2Packet* pPacket = CG2Packet::New( pInput->m_pBuffer );
00306
00307 try
00308 {
00309 bSuccess = OnPacket( pPacket );
00310 }
00311 catch ( CException* pException )
00312 {
00313 pException->Delete();
00314
00315 bSuccess = TRUE;
00316 }
00317
00318 pPacket->Release();
00319
00320 pInput->Remove( nLength + nLenLen + nTypeLen + 2 );
00321 }
00322
00323 if ( bSuccess ) return TRUE;
00324
00325 Close( 0 );
00326 return FALSE;
00327 }
00328
00330
00331
00332 BOOL CG2Neighbour::OnPacket(CG2Packet* pPacket)
00333 {
00334 m_nInputCount++;
00335 m_tLastPacket = GetTickCount();
00336 Statistics.Current.Gnutella2.Incoming++;
00337
00338 pPacket->SmartDump( this, NULL, FALSE );
00339
00340 if ( Network.RoutePacket( pPacket ) ) return TRUE;
00341
00342 if ( pPacket->IsType( G2_PACKET_PING ) )
00343 {
00344 return OnPing( pPacket );
00345 }
00346 else if ( pPacket->IsType( G2_PACKET_LNI ) )
00347 {
00348 return OnLNI( pPacket );
00349 }
00350 else if ( pPacket->IsType( G2_PACKET_KHL ) )
00351 {
00352 return OnKHL( pPacket );
00353 }
00354 else if ( pPacket->IsType( G2_PACKET_HAW ) )
00355 {
00356 return OnHAW( pPacket );
00357 }
00358 else if ( pPacket->IsType( G2_PACKET_QUERY ) )
00359 {
00360 return OnQuery( pPacket );
00361 }
00362 else if ( pPacket->IsType( G2_PACKET_QUERY_WRAP ) )
00363 {
00364
00365 theApp.Message( MSG_DEBUG, _T("CG2Neighbour::OnPacket Ignoring wrapped query packet") );
00366 }
00367 else if ( pPacket->IsType( G2_PACKET_HIT_WRAP ) )
00368 {
00369 return OnCommonHit( pPacket );
00370 }
00371 else if ( pPacket->IsType( G2_PACKET_HIT ) )
00372 {
00373 return OnCommonHit( pPacket );
00374 }
00375 else if ( pPacket->IsType( G2_PACKET_QUERY_ACK ) )
00376 {
00377 return OnQueryAck( pPacket );
00378 }
00379 else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_REQ ) )
00380 {
00381 return OnQueryKeyReq( pPacket );
00382 }
00383 else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_ANS ) )
00384 {
00385 return OnQueryKeyAns( pPacket );
00386 }
00387 else if ( pPacket->IsType( G2_PACKET_QHT ) )
00388 {
00389 return OnCommonQueryHash( pPacket );
00390 }
00391 else if ( pPacket->IsType( G2_PACKET_PUSH ) )
00392 {
00393 return OnPush( pPacket );
00394 }
00395 else if ( pPacket->IsType( G2_PACKET_PROFILE_CHALLENGE ) )
00396 {
00397 return OnProfileChallenge( pPacket );
00398 }
00399 else if ( pPacket->IsType( G2_PACKET_PROFILE_DELIVERY ) )
00400 {
00401 return OnProfileDelivery( pPacket );
00402 }
00403
00404 return TRUE;
00405 }
00406
00408
00409
00410 BOOL CG2Neighbour::OnPing(CG2Packet* pPacket)
00411 {
00412 Send( CG2Packet::New( G2_PACKET_PONG ) );
00413
00414 if ( ! pPacket->m_bCompound ) return TRUE;
00415
00416 BOOL bRelay = FALSE;
00417 DWORD nAddress = 0;
00418 WORD nPort = 0;
00419 CHAR szType[9];
00420 DWORD nLength;
00421
00422 while ( pPacket->ReadPacket( szType, nLength ) )
00423 {
00424 DWORD nNext = pPacket->m_nPosition + nLength;
00425
00426 if ( strcmp( szType, "UDP" ) == 0 && nLength >= 6 )
00427 {
00428 nAddress = pPacket->ReadLongLE();
00429 nPort = pPacket->ReadShortBE();
00430 }
00431 else if ( strcmp( szType, "RELAY" ) == 0 )
00432 {
00433 bRelay = TRUE;
00434 }
00435
00436 pPacket->m_nPosition = nNext;
00437 }
00438
00439 if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) ) return TRUE;
00440
00441 if ( bRelay )
00442 {
00443 CG2Packet* pPong = CG2Packet::New( G2_PACKET_PONG, TRUE );
00444 pPong->WritePacket( "RELAY", 0 );
00445 Datagrams.Send( (IN_ADDR*)&nAddress, nPort, pPong );
00446 }
00447 else
00448 {
00449 DWORD tNow = GetTickCount();
00450 if ( tNow - m_tLastPingIn < Settings.Gnutella1.PingFlood ) return TRUE;
00451 m_tLastPingIn = tNow;
00452
00453 BYTE* pRelay = pPacket->WriteGetPointer( 7, 0 );
00454 *pRelay++ = 0x60;
00455 *pRelay++ = 0;
00456 *pRelay++ = 'R'; *pRelay++ = 'E'; *pRelay++ = 'L';
00457 *pRelay++ = 'A'; *pRelay++ = 'Y';
00458
00459 CPtrArray pG2Nodes;
00460
00461 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00462 {
00463 CG2Neighbour* pNeighbour = (CG2Neighbour*)Neighbours.GetNext( pos );
00464
00465 if ( pNeighbour->m_nState == nrsConnected &&
00466 pNeighbour->m_nProtocol == PROTOCOL_G2 &&
00467 pNeighbour != this)
00468 {
00469 pG2Nodes.Add( pNeighbour );
00470 }
00471 }
00472
00473 int nRelayTo = Settings.Gnutella2.PingRelayLimit;
00474
00475 int nCount = pG2Nodes.GetCount();
00476
00477 for ( int nCur = 0; (nCur < nCount && nCur < nRelayTo); nCur++ )
00478 {
00479 int nRand = rand() % pG2Nodes.GetCount();
00480
00481 CG2Neighbour* pNeighbour = (CG2Neighbour*)pG2Nodes.GetAt( nRand );
00482
00483 theApp.Message( MSG_DEBUG, _T("Ping Relay iteration %i picked random index %i as %s"),
00484 nCur, nRand, (LPCTSTR)pNeighbour->m_sAddress );
00485
00486 pNeighbour->Send( pPacket, FALSE );
00487 pG2Nodes.RemoveAt( nRand );
00488 }
00489 }
00490
00491 return TRUE;
00492 }
00493
00495
00496
00497 void CG2Neighbour::SendLNI()
00498 {
00499 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_LNI, TRUE );
00500
00501 QWORD nMyVolume = 0;
00502 DWORD nMyFiles = 0;
00503 LibraryMaps.GetStatistics( &nMyFiles, &nMyVolume );
00504
00505 WORD nLeafs = 0;
00506
00507 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00508 {
00509 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00510
00511 if ( pNeighbour != this &&
00512 pNeighbour->m_nState == nrsConnected &&
00513 pNeighbour->m_nNodeType == ntLeaf )
00514 {
00515 nMyFiles += pNeighbour->m_nFileCount;
00516 nMyVolume += pNeighbour->m_nFileVolume;
00517 nLeafs++;
00518 }
00519 }
00520
00521 pPacket->WritePacket( "NA", 6 );
00522 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00523 pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00524
00525 pPacket->WritePacket( "GU", 16 );
00526 GGUID tmp( MyProfile.GUID );
00527 pPacket->Write( &tmp, 16 );
00528
00529 pPacket->WritePacket( "V", 4 );
00530 pPacket->WriteString( SHAREAZA_VENDOR_A, FALSE );
00531
00532 pPacket->WritePacket( "LS", 8 );
00533 pPacket->WriteLongBE( (DWORD)nMyFiles );
00534 pPacket->WriteLongBE( (DWORD)nMyVolume );
00535
00536 if ( ! Neighbours.IsG2Leaf() )
00537 {
00538 pPacket->WritePacket( "HS", 4 );
00539 pPacket->WriteShortBE( nLeafs );
00540 pPacket->WriteShortBE( Settings.Gnutella2.NumLeafs );
00541
00542 pPacket->WritePacket( "QK", 0 );
00543 }
00544
00545 Send( pPacket, TRUE, FALSE );
00546 }
00547
00549
00550
00551 BOOL CG2Neighbour::OnLNI(CG2Packet* pPacket)
00552 {
00553 if ( ! pPacket->m_bCompound ) return TRUE;
00554
00555 DWORD tNow = time( NULL );
00556 CHAR szType[9];
00557 DWORD nLength;
00558
00559 m_nLeafCount = 0;
00560
00561 while ( pPacket->ReadPacket( szType, nLength ) )
00562 {
00563 DWORD nNext = pPacket->m_nPosition + nLength;
00564
00565 if ( strcmp( szType, "NA" ) == 0 && nLength >= 6 )
00566 {
00567 m_pHost.sin_addr.S_un.S_addr = pPacket->ReadLongLE();
00568 m_pHost.sin_port = htons( pPacket->ReadShortBE() );
00569 }
00570 else if ( strcmp( szType, "GU" ) == 0 && nLength >= 16 )
00571 {
00572 pPacket->Read( &m_pGUID, sizeof(GGUID) );
00573 m_bGUID = TRUE;
00574 }
00575 else if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
00576 {
00577 CHAR szVendor[5] = { 0, 0, 0, 0, 0 };
00578 pPacket->Read( szVendor, 4 );
00579 m_pVendor = VendorCache.Lookup( szVendor );
00580 }
00581 else if ( strcmp( szType, "LS" ) == 0 && nLength >= 8 )
00582 {
00583 m_nFileCount = pPacket->ReadLongBE();
00584 m_nFileVolume = pPacket->ReadLongBE();
00585 }
00586 else if ( strcmp( szType, "HS" ) == 0 && nLength >= 2 )
00587 {
00588 m_nLeafCount = pPacket->ReadShortBE();
00589 m_nLeafLimit = pPacket->ReadShortBE();
00590 }
00591 else if ( strcmp( szType, "QK" ) == 0 )
00592 {
00593 m_bCachedKeys = TRUE;
00594 }
00595
00596 pPacket->m_nPosition = nNext;
00597 }
00598
00599 if ( ! Network.IsFirewalledAddress( &m_pHost.sin_addr, TRUE ) &&
00600 m_pVendor != NULL && m_nNodeType != ntLeaf )
00601 {
00602 HostCache.Gnutella2.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ),
00603 0, m_pVendor->m_sCode );
00604 }
00605
00606 m_tWaitLNI = 0;
00607
00608 return TRUE;
00609 }
00610
00612
00613
00614 void CG2Neighbour::SendKHL()
00615 {
00616 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_KHL, TRUE );
00617
00618 DWORD nBase = pPacket->m_nPosition;
00619
00620 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00621 {
00622 CG2Neighbour* pNeighbour = (CG2Neighbour*)Neighbours.GetNext( pos );
00623
00624 if ( pNeighbour != this &&
00625 pNeighbour->m_nProtocol == PROTOCOL_G2 &&
00626 pNeighbour->m_nState == nrsConnected &&
00627 pNeighbour->m_nNodeType != ntLeaf &&
00628 pNeighbour->m_pHost.sin_addr.S_un.S_addr != Network.m_pHost.sin_addr.S_un.S_addr )
00629 {
00630 if ( pNeighbour->m_pVendor && pNeighbour->m_pVendor->m_sCode.GetLength() == 4 )
00631 {
00632 pPacket->WritePacket( "NH", 14 + 6, TRUE );
00633 pPacket->WritePacket( "HS", 2 );
00634 pPacket->WriteShortBE( (WORD)pNeighbour->m_nLeafCount );
00635 pPacket->WritePacket( "V", 4 );
00636 pPacket->WriteString( pNeighbour->m_pVendor->m_sCode );
00637 }
00638 else
00639 {
00640 pPacket->WritePacket( "NH", 7 + 6, TRUE );
00641 pPacket->WritePacket( "HS", 2 );
00642 pPacket->WriteShortBE( (WORD)pNeighbour->m_nLeafCount );
00643 pPacket->WriteByte( 0 );
00644 }
00645
00646 pPacket->WriteLongLE( pNeighbour->m_pHost.sin_addr.S_un.S_addr );
00647 pPacket->WriteShortBE( htons( pNeighbour->m_pHost.sin_port ) );
00648 }
00649 }
00650
00651 int nCount = Settings.Gnutella2.KHLHubCount;
00652 DWORD tNow = time( NULL );
00653
00654 pPacket->WritePacket( "TS", 4 );
00655 pPacket->WriteLongBE( time( NULL ) );
00656
00657 for ( CHostCacheHost* pHost = HostCache.Gnutella2.GetNewest() ; pHost && nCount > 0 ; pHost = pHost->m_pPrevTime )
00658 {
00659 if ( pHost->CanQuote( tNow ) &&
00660 Neighbours.Get( &pHost->m_pAddress ) == NULL &&
00661 pHost->m_pAddress.S_un.S_addr != Network.m_pHost.sin_addr.S_un.S_addr )
00662 {
00663 int nLength = 10;
00664
00665 if ( pHost->m_pVendor && pHost->m_pVendor->m_sCode.GetLength() == 4 )
00666 nLength += 7;
00667 if ( m_nNodeType == ntLeaf && pHost->m_nKeyValue != 0 && pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
00668 nLength += 8;
00669 if ( nLength > 10 )
00670 nLength ++;
00671
00672 pPacket->WritePacket( "CH", nLength, nLength > 10 );
00673
00674 if ( pHost->m_pVendor && pHost->m_pVendor->m_sCode.GetLength() == 4 )
00675 {
00676 pPacket->WritePacket( "V", 4 );
00677 pPacket->WriteString( pHost->m_pVendor->m_sCode, FALSE );
00678 }
00679
00680 if ( m_nNodeType == ntLeaf && pHost->m_nKeyValue != 0 && pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
00681 {
00682 pPacket->WritePacket( "QK", 4 );
00683 pPacket->WriteLongBE( pHost->m_nKeyValue );
00684 }
00685
00686 if ( nLength > 10 ) pPacket->WriteByte( 0 );
00687
00688 pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );
00689 pPacket->WriteShortBE( pHost->m_nPort );
00690 pPacket->WriteLongBE( pHost->m_tSeen );
00691
00692 nCount--;
00693 }
00694 }
00695
00696 Send( pPacket, TRUE, TRUE );
00697
00698 m_tLastKHL = GetTickCount();
00699 }
00700
00702
00703
00704 BOOL CG2Neighbour::OnKHL(CG2Packet* pPacket)
00705 {
00706 if ( ! pPacket->m_bCompound ) return TRUE;
00707
00708 CHAR szType[9], szInner[9];
00709 DWORD nLength, nInner;
00710 BOOL bCompound;
00711
00712 DWORD tNow = time( NULL );
00713
00714 m_pHubGroup->Clear();
00715
00716 while ( pPacket->ReadPacket( szType, nLength, &bCompound ) )
00717 {
00718 DWORD nNext = pPacket->m_nPosition + nLength;
00719
00720 if ( strcmp( szType, "NH" ) == 0 ||
00721 strcmp( szType, "CH" ) == 0 )
00722 {
00723 DWORD nAddress = 0, nKey = 0, tSeen = tNow;
00724 WORD nPort = 0, nLeafs = 0;
00725 CString strVendor;
00726
00727 if ( bCompound || 0 == strcmp( szType, "NH" ) )
00728 {
00729 while ( pPacket->m_nPosition < nNext && pPacket->ReadPacket( szInner, nInner ) )
00730 {
00731 DWORD nNextX = pPacket->m_nPosition + nInner;
00732
00733 if ( strcmp( szInner, "NA" ) == 0 && nInner >= 6 )
00734 {
00735 nAddress = pPacket->ReadLongLE();
00736 nPort = pPacket->ReadShortBE();
00737 }
00738 else if ( strcmp( szInner, "V" ) == 0 && nInner >= 4 )
00739 {
00740 strVendor = pPacket->ReadString( 4 );
00741 }
00742 else if ( strcmp( szInner, "QK" ) == 0 && nInner >= 4 )
00743 {
00744 nKey = pPacket->ReadLongBE();
00745 m_bCachedKeys = TRUE;
00746 }
00747 else if ( strcmp( szInner, "TS" ) == 0 && nInner >= 4 )
00748 {
00749 tSeen = pPacket->ReadLongBE() + m_tAdjust;
00750 }
00751
00752 pPacket->m_nPosition = nNextX;
00753 }
00754
00755 nLength = nNext - pPacket->m_nPosition;
00756 }
00757
00758 if ( nLength >= 6 )
00759 {
00760 nAddress = pPacket->ReadLongLE();
00761 nPort = pPacket->ReadShortBE();
00762 if ( nLength >= 10 ) tSeen = pPacket->ReadLongBE() + m_tAdjust;
00763 }
00764
00765 if ( FALSE == Network.IsFirewalledAddress( &nAddress, TRUE ) )
00766 {
00767 CHostCacheHost* pCached = HostCache.Gnutella2.Add(
00768 (IN_ADDR*)&nAddress, nPort, tSeen, strVendor );
00769
00770 if ( pCached != NULL && m_nNodeType == ntHub )
00771 {
00772 if ( pCached->m_nKeyValue == 0 ||
00773 pCached->m_nKeyHost != Network.m_pHost.sin_addr.S_un.S_addr )
00774 {
00775 pCached->SetKey( nKey, &m_pHost.sin_addr );
00776 }
00777 }
00778
00779 if ( strcmp( szType, "NH" ) == 0 )
00780 {
00781 m_pHubGroup->Add( (IN_ADDR*)&nAddress, nPort );
00782 }
00783 }
00784 }
00785 else if ( strcmp( szType, "TS" ) == 0 && nLength >= 4 )
00786 {
00787 m_tAdjust = (LONG)tNow - (LONG)pPacket->ReadLongBE();
00788 }
00789
00790 pPacket->m_nPosition = nNext;
00791 }
00792
00793 return TRUE;
00794 }
00795
00797
00798
00799 void CG2Neighbour::SendHAW()
00800 {
00801 m_tLastHAW = GetTickCount();
00802
00803 if ( m_nNodeType == ntLeaf || Neighbours.IsG2Leaf() ) return;
00804
00805 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_HAW, TRUE );
00806
00807 WORD nLeafs = 0;
00808 GGUID pGUID;
00809
00810 Network.CreateID( pGUID );
00811
00812 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00813 {
00814 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00815
00816 if ( pNeighbour != this &&
00817 pNeighbour->m_nState == nrsConnected &&
00818 pNeighbour->m_nNodeType == ntLeaf )
00819 {
00820 nLeafs++;
00821 }
00822 }
00823
00824 pPacket->WritePacket( "NA", 6 );
00825 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00826 pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00827
00828 pPacket->WritePacket( "HS", 2 );
00829 pPacket->WriteShortBE( nLeafs );
00830
00831 pPacket->WritePacket( "V", 4 );
00832 pPacket->WriteString( SHAREAZA_VENDOR_A );
00833
00834 pPacket->WriteByte( 100 );
00835 pPacket->WriteByte( 0 );
00836 pPacket->Write( &pGUID, sizeof(GGUID) );
00837
00838 Send( pPacket, TRUE, TRUE );
00839
00840 m_pGUIDCache->Add( &pGUID, this );
00841 }
00842
00844
00845
00846 BOOL CG2Neighbour::OnHAW(CG2Packet* pPacket)
00847 {
00848 if ( ! pPacket->m_bCompound ) return TRUE;
00849
00850 CString strVendor;
00851 CHAR szType[9];
00852 DWORD nLength;
00853
00854 DWORD nAddress = 0;
00855 WORD nPort = 0;
00856
00857 while ( pPacket->ReadPacket( szType, nLength ) )
00858 {
00859 DWORD nNext = pPacket->m_nPosition + nLength;
00860
00861 if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
00862 {
00863 strVendor = pPacket->ReadString( 4 );
00864 }
00865 else if ( strcmp( szType, "NA" ) == 0 && nLength >= 6 )
00866 {
00867 nAddress = pPacket->ReadLongLE();
00868 nPort = pPacket->ReadShortBE();
00869 }
00870
00871 pPacket->m_nPosition = nNext;
00872 }
00873
00874 if ( pPacket->GetRemaining() < 2 + 16 ) return TRUE;
00875 if ( nAddress == 0 || nPort == 0 ) return TRUE;
00876 if ( Network.IsFirewalledAddress( &nAddress, TRUE ) ) return TRUE;
00877
00878 BYTE* pPtr = pPacket->m_pBuffer + pPacket->m_nPosition;
00879 BYTE nTTL = pPacket->ReadByte();
00880 BYTE nHops = pPacket->ReadByte();
00881
00882 GGUID pGUID;
00883 pPacket->Read( &pGUID, sizeof(GGUID) );
00884
00885 HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, 0, strVendor );
00886
00887 if ( nTTL > 0 && nHops < 255 )
00888 {
00889 m_pGUIDCache->Add( &pGUID, this );
00890
00891 pPtr[0] = nTTL - 1;
00892 pPtr[1] = nHops + 1;
00893
00894 if ( CG2Neighbour* pNeighbour = Neighbours.GetRandomHub( this, &pGUID ) )
00895 {
00896 pNeighbour->Send( pPacket, FALSE, TRUE );
00897 }
00898 }
00899
00900 return TRUE;
00901 }
00902
00904
00905
00906 BOOL CG2Neighbour::SendQuery(CQuerySearch* pSearch, CPacket* pPacket, BOOL bLocal)
00907 {
00908 if ( m_nState != nrsConnected )
00909 {
00910 return FALSE;
00911 }
00912 else if ( pPacket == NULL || pPacket->m_nProtocol != PROTOCOL_G2 )
00913 {
00914 return FALSE;
00915 }
00916 else if ( m_nNodeType == ntHub && ! bLocal )
00917 {
00918 return FALSE;
00919 }
00920 else if ( m_pQueryTableRemote != NULL && m_pQueryTableRemote->m_bLive && ( m_nNodeType == ntLeaf || pSearch->m_bUDP ) )
00921 {
00922 if ( ! m_pQueryTableRemote->Check( pSearch ) ) return FALSE;
00923 }
00924 else if ( m_nNodeType == ntLeaf && ! bLocal )
00925 {
00926 return FALSE;
00927 }
00928
00929 Send( pPacket, FALSE, ! bLocal );
00930
00931 return TRUE;
00932 }
00933
00934 BOOL CG2Neighbour::OnQuery(CG2Packet* pPacket)
00935 {
00936 CQuerySearch* pSearch = CQuerySearch::FromPacket( pPacket );
00937
00938
00939 if ( pSearch == NULL )
00940 {
00941 theApp.Message( MSG_DEFAULT, IDS_PROTOCOL_BAD_QUERY, (LPCTSTR)m_sAddress );
00942 Statistics.Current.Gnutella2.Dropped++;
00943 m_nDropCount++;
00944 return TRUE;
00945 }
00946
00947
00948 if ( ( pSearch->m_bSHA1 ) || ( pSearch->m_bBTH ) || ( pSearch->m_bED2K ) )
00949 {
00950
00951
00952 if ( m_nQueryLimiter > -60 )
00953 {
00954 m_nQueryLimiter--;
00955 }
00956 else if ( ! m_bBlacklisted && ( m_nNodeType == ntLeaf ) )
00957 {
00958
00959 m_bBlacklisted = TRUE;
00960 theApp.Message( MSG_SYSTEM, _T("Blacklisting %s due to excess traffic"), (LPCTSTR)m_sAddress );
00961
00962
00963 }
00964
00965 if ( ( m_bBlacklisted ) || ( m_nQueryLimiter < 0 ) )
00966 {
00967
00968 if ( ! m_bBlacklisted )
00969 theApp.Message( MSG_DEBUG, _T("Dropping excess query traffic from %s"), (LPCTSTR)m_sAddress );
00970
00971 delete pSearch;
00972 Statistics.Current.Gnutella2.Dropped++;
00973 m_nDropCount++;
00974 return TRUE;
00975 }
00976 }
00977
00978
00979 if ( pPacket->IsType( G2_PACKET_QUERY_WRAP ) )
00980 {
00981 theApp.Message( MSG_DEBUG, _T("CG2Neighbour::OnQuery Ignoring wrapped query packet") );
00982 delete pSearch;
00983 Statistics.Current.Gnutella2.Dropped++;
00984 m_nDropCount++;
00985 return TRUE;
00986 }
00987
00988 if ( m_nNodeType == ntLeaf && pSearch->m_bUDP &&
00989 pSearch->m_pEndpoint.sin_addr.S_un.S_addr != m_pHost.sin_addr.S_un.S_addr )
00990 {
00991 delete pSearch;
00992 Statistics.Current.Gnutella2.Dropped++;
00993 m_nDropCount++;
00994 return TRUE;
00995 }
00996
00997 if ( ! Network.QueryRoute->Add( &pSearch->m_pGUID, this ) )
00998 {
00999 delete pSearch;
01000 Statistics.Current.Gnutella2.Dropped++;
01001 m_nDropCount++;
01002 return TRUE;
01003 }
01004
01005 if ( m_nNodeType != ntHub )
01006 {
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025 Neighbours.RouteQuery( pSearch, pPacket, this, m_nNodeType == ntLeaf );
01026 }
01027
01028 Network.OnQuerySearch( pSearch );
01029
01030 if ( pSearch->m_bUDP &&
01031 pSearch->m_pEndpoint.sin_addr.S_un.S_addr != m_pHost.sin_addr.S_un.S_addr )
01032 {
01033 CLocalSearch pLocal( pSearch, &pSearch->m_pEndpoint );
01034 pLocal.Execute();
01035 }
01036 else
01037 {
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 CLocalSearch pLocal( pSearch, this, FALSE );
01048 pLocal.Execute();
01049 }
01050
01051 if ( m_nNodeType == ntLeaf ) Send( Neighbours.CreateQueryWeb( &pSearch->m_pGUID, this ), TRUE, FALSE );
01052
01053 delete pSearch;
01054 Statistics.Current.Gnutella2.Queries++;
01055
01056 return TRUE;
01057 }
01058
01059 BOOL CG2Neighbour::OnQueryAck(CG2Packet* pPacket)
01060 {
01061 HostCache.Gnutella2.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
01062 SearchManager.OnQueryAck( pPacket, &m_pHost, NULL );
01063 return TRUE;
01064 }
01065
01067
01068
01069 BOOL CG2Neighbour::OnQueryKeyReq(CG2Packet* pPacket)
01070 {
01071 if ( ! pPacket->m_bCompound ) return TRUE;
01072 if ( m_nNodeType != ntLeaf ) return TRUE;
01073
01074 DWORD nLength, nAddress = 0;
01075 BOOL bCacheOkay = TRUE;
01076 CHAR szType[9];
01077 WORD nPort = 0;
01078
01079 while ( pPacket->ReadPacket( szType, nLength ) )
01080 {
01081 DWORD nOffset = pPacket->m_nPosition + nLength;
01082
01083 if ( strcmp( szType, "QNA" ) == 0 && nLength >= 6 )
01084 {
01085 nAddress = pPacket->ReadLongLE();
01086 nPort = pPacket->ReadShortBE();
01087 }
01088 else if ( strcmp( szType, "REF" ) == 0 )
01089 {
01090 bCacheOkay = FALSE;
01091 }
01092
01093 pPacket->m_nPosition = nOffset;
01094 }
01095
01096 if ( Network.IsFirewalledAddress( &nAddress, TRUE ) || 0 == nPort ) return TRUE;
01097
01098 CHostCacheHost* pCached = bCacheOkay ? HostCache.Gnutella2.Find( (IN_ADDR*)&nAddress ) : NULL;
01099
01100 if ( pCached != NULL && pCached->m_nKeyValue != 0 &&
01101 pCached->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
01102 {
01103 CG2Packet* pAnswer = CG2Packet::New( G2_PACKET_QUERY_KEY_ANS, TRUE );
01104 pAnswer->WritePacket( "QNA", 6 );
01105 pAnswer->WriteLongLE( nAddress );
01106 pAnswer->WriteShortBE( nPort );
01107 pAnswer->WritePacket( "QK", 4 );
01108 pAnswer->WriteLongBE( pCached->m_nKeyValue );
01109 pAnswer->WritePacket( "CACHED", 0 );
01110 Send( pAnswer );
01111 }
01112 else
01113 {
01114 CG2Packet* pRequest = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
01115 pRequest->WritePacket( "SNA", 4 );
01116 pRequest->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
01117 Datagrams.Send( (IN_ADDR*)&nAddress, nPort, pRequest, TRUE, NULL, FALSE );
01118 }
01119
01120 return TRUE;
01121 }
01122
01124
01125
01126 BOOL CG2Neighbour::OnQueryKeyAns(CG2Packet* pPacket)
01127 {
01128 if ( ! pPacket->m_bCompound ) return TRUE;
01129 if ( m_nNodeType != ntHub ) return TRUE;
01130
01131 DWORD nKey = 0, nAddress = 0;
01132 WORD nPort = 0;
01133
01134 CHAR szType[9];
01135 DWORD nLength;
01136
01137 while ( pPacket->ReadPacket( szType, nLength ) )
01138 {
01139 DWORD nOffset = pPacket->m_nPosition + nLength;
01140
01141 if ( strcmp( szType, "QK" ) == 0 && nLength >= 4 )
01142 {
01143 nKey = pPacket->ReadLongBE();
01144 }
01145 else if ( strcmp( szType, "QNA" ) == 0 && nLength >= 6 )
01146 {
01147 nAddress = pPacket->ReadLongLE();
01148 nPort = pPacket->ReadShortBE();
01149 }
01150 else if ( strcmp( szType, "CACHED" ) == 0 )
01151 {
01152 m_bCachedKeys = TRUE;
01153 }
01154
01155 pPacket->m_nPosition = nOffset;
01156 }
01157
01158 theApp.Message( MSG_DEBUG, _T("Got a query key for %s:%i via neighbour %s: 0x%x"),
01159 (LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ), nPort, (LPCTSTR)m_sAddress, nKey );
01160
01161 if ( Network.IsFirewalledAddress( &nAddress ) || 0 == nPort ) return TRUE;
01162
01163 CHostCacheHost* pCache = HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort );
01164 if ( pCache != NULL ) pCache->SetKey( nKey, &m_pHost.sin_addr );
01165
01166 return TRUE;
01167 }
01168
01170
01171
01172 BOOL CG2Neighbour::OnPush(CG2Packet* pPacket)
01173 {
01174 if ( ! pPacket->m_bCompound ) return TRUE;
01175
01176 DWORD nLength = pPacket->GetRemaining();
01177
01178 if ( ! pPacket->SkipCompound( nLength, 6 ) )
01179 {
01180 pPacket->Debug( _T("BadPush") );
01181 Statistics.Current.Gnutella2.Dropped++;
01182 return TRUE;
01183 }
01184
01185 DWORD nAddress = pPacket->ReadLongLE();
01186 WORD nPort = pPacket->ReadShortBE();
01187
01188 if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
01189 {
01190 Statistics.Current.Gnutella2.Dropped++;
01191 m_nDropCount++;
01192 return TRUE;
01193 }
01194 else if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) )
01195 {
01196 theApp.Message( MSG_ERROR, IDS_PROTOCOL_ZERO_PUSH, (LPCTSTR)m_sAddress );
01197 Statistics.Current.Gnutella2.Dropped++;
01198 m_nDropCount++;
01199 return TRUE;
01200 }
01201
01202 Handshakes.PushTo( (IN_ADDR*)&nAddress, nPort );
01203
01204 return TRUE;
01205 }
01206
01208
01209
01210 BOOL CG2Neighbour::OnProfileChallenge(CG2Packet* pPacket)
01211 {
01212 if ( ! MyProfile.IsValid() ) return TRUE;
01213
01214 CG2Packet* pProfile = CG2Packet::New( G2_PACKET_PROFILE_DELIVERY, TRUE );
01215
01216 CString strXML = MyProfile.GetXML( NULL, TRUE )->ToString( TRUE );
01217
01218 pProfile->WritePacket( "XML", pProfile->GetStringLen( strXML ) );
01219 pProfile->WriteString( strXML, FALSE );
01220
01221 Send( pProfile, TRUE, TRUE );
01222
01223 return TRUE;
01224 }
01225
01227
01228
01229 BOOL CG2Neighbour::OnProfileDelivery(CG2Packet* pPacket)
01230 {
01231 if ( ! pPacket->m_bCompound ) return TRUE;
01232
01233 CHAR szType[9];
01234 DWORD nLength;
01235
01236 while ( pPacket->ReadPacket( szType, nLength ) )
01237 {
01238 DWORD nOffset = pPacket->m_nPosition + nLength;
01239
01240 if ( strcmp( szType, "XML" ) == 0 )
01241 {
01242 CXMLElement* pXML = CXMLElement::FromString( pPacket->ReadString( nLength ), TRUE );
01243
01244 if ( pXML )
01245 {
01246 if ( m_pProfile == NULL ) m_pProfile = new CGProfile();
01247 if ( ! m_pProfile->FromXML( pXML ) ) delete pXML;
01248 }
01249 }
01250
01251 pPacket->m_nPosition = nOffset;
01252 }
01253
01254 return TRUE;
01255 }