00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "StdAfx.h"
00027 #include "Shareaza.h"
00028 #include "Settings.h"
00029 #include "Network.h"
00030 #include "Buffer.h"
00031 #include "Statistics.h"
00032 #include "Neighbours.h"
00033 #include "Handshakes.h"
00034 #include "G1Neighbour.h"
00035 #include "G1Packet.h"
00036 #include "G2Packet.h"
00037 #include "HostCache.h"
00038 #include "RouteCache.h"
00039 #include "PacketBuffer.h"
00040 #include "Security.h"
00041 #include "GProfile.h"
00042 #include "PongCache.h"
00043 #include "VendorCache.h"
00044 #include "QuerySearch.h"
00045 #include "QueryHit.h"
00046 #include "QueryHashTable.h"
00047 #include "LocalSearch.h"
00048 #include "SearchManager.h"
00049 #include "DiscoveryServices.h"
00050 #include "Downloads.h"
00051 #include "Uploads.h"
00052 #include "Library.h"
00053 #include "SHA.h"
00054 #include "WndMain.h"
00055 #include "WndChild.h"
00056 #include "WndSearchMonitor.h"
00057
00058
00059 #ifdef _DEBUG
00060 #undef THIS_FILE
00061 static char THIS_FILE[]=__FILE__;
00062 #define new DEBUG_NEW
00063 #endif
00064
00066
00067
00068
00069
00070 CG1Neighbour::CG1Neighbour(CNeighbour* pBase) : CNeighbour( PROTOCOL_G1, pBase )
00071 {
00072
00073 ZeroMemory( m_nPongNeeded, PONG_NEEDED_BUFFER );
00074
00075
00076 m_tLastOutPing = m_tLastPacket;
00077
00078
00079 m_nHopsFlow = 0xFF;
00080
00081
00082 m_pOutbound = new CG1PacketBuffer( m_pZOutput ? m_pZOutput : m_pOutput );
00083
00084
00085 theApp.Message( MSG_DEFAULT, IDS_HANDSHAKE_ONLINE, (LPCTSTR)m_sAddress, 0, 6, m_sUserAgent.IsEmpty() ? _T("Unknown") : (LPCTSTR)m_sUserAgent );
00086
00087
00088 Send( CG1Packet::New( G1_PACKET_PING ) );
00089
00090
00091 if ( Settings.Gnutella1.VendorMsg && m_bVendorMsg )
00092 {
00093
00094 CG1Packet* pVendor = CG1Packet::New( G1_PACKET_VENDOR, 1 );
00095
00096
00097 pVendor->WriteLongLE( 0 );
00098 pVendor->WriteShortLE( 0 );
00099 pVendor->WriteShortLE( 0 );
00100 pVendor->WriteShortLE( 6 );
00101 pVendor->WriteLongLE( 'RAEB' );
00102 pVendor->WriteShortLE( 0x0004 );
00103 pVendor->WriteShortLE( 1 );
00104 pVendor->WriteLongLE( 'RAEB' );
00105 pVendor->WriteShortLE( 0x000B );
00106 pVendor->WriteShortLE( 1 );
00107 pVendor->WriteLongLE( 'RAEB' );
00108 pVendor->WriteShortLE( 0x000C );
00109 pVendor->WriteShortLE( 1 );
00110 pVendor->WriteLongLE( 'AZAR' );
00111 pVendor->WriteShortLE( 0x0001 );
00112 pVendor->WriteShortLE( 1 );
00113 pVendor->WriteLongLE( 'AZAR' );
00114 pVendor->WriteShortLE( 0x0002 );
00115 pVendor->WriteShortLE( 1 );
00116 pVendor->WriteLongLE( 'AZAR' );
00117 pVendor->WriteShortLE( 0x0003 );
00118 pVendor->WriteShortLE( 1 );
00119
00120
00121 Send( pVendor );
00122 }
00123 }
00124
00125
00126 CG1Neighbour::~CG1Neighbour()
00127 {
00128
00129 if ( m_pOutbound ) delete m_pOutbound;
00130 }
00131
00133
00134
00135
00136
00137 BOOL CG1Neighbour::OnRead()
00138 {
00139
00140 CNeighbour::OnRead();
00141
00142
00143 return ProcessPackets();
00144 }
00145
00146
00147
00148 BOOL CG1Neighbour::OnWrite()
00149 {
00150
00151 CBuffer* pOutput = m_pZOutput ? m_pZOutput : m_pOutput;
00152
00153
00154 DWORD nExpire = GetTickCount();
00155
00156
00157 CNeighbour::OnWrite();
00158
00159
00160 while ( pOutput->m_nLength == 0 && m_pOutbound->m_nTotal > 0 )
00161 {
00162
00163 CG1Packet* pPacket = m_pOutbound->GetPacketToSend( nExpire );
00164 if ( ! pPacket ) break;
00165
00166
00167 pPacket->ToBuffer( pOutput );
00168 pPacket->Release();
00169
00170
00171 m_pOutbound->m_nTotal--;
00172
00173
00174 CNeighbour::OnWrite();
00175 }
00176
00177
00178 m_nOutbound = m_pOutbound->m_nTotal;
00179 m_nLostCount = m_pOutbound->m_nDropped;
00180
00181
00182 return TRUE;
00183 }
00184
00186
00187
00188
00189
00190
00191 BOOL CG1Neighbour::OnRun()
00192 {
00193
00194 if ( ! CNeighbour::OnRun() ) return FALSE;
00195
00196
00197 DWORD tNow = GetTickCount();
00198 SendPing( tNow, NULL );
00199
00200
00201 return TRUE;
00202 }
00203
00205
00206
00207
00208
00209 BOOL CG1Neighbour::Send(CPacket* pPacket, BOOL bRelease, BOOL bBuffered)
00210 {
00211
00212 CG1Packet* pPacketG1 = (CG1Packet*)pPacket;
00213
00214
00215 BOOL bSuccess = FALSE;
00216
00217
00218 if ( m_nState >= nrsConnected && pPacket->m_nProtocol == PROTOCOL_G1 && pPacketG1->m_nTTL )
00219 {
00220
00221 m_nOutputCount++;
00222 Statistics.Current.Gnutella1.Outgoing++;
00223
00224
00225 m_pOutbound->Add( pPacketG1, bBuffered );
00226 QueueRun();
00227
00228
00229 pPacketG1->SmartDump( this, NULL, TRUE );
00230
00231
00232 bSuccess = TRUE;
00233 }
00234
00235
00236 if ( bRelease ) pPacket->Release();
00237
00238
00239 return bSuccess;
00240 }
00241
00243
00244
00245
00246
00247 BOOL CG1Neighbour::ProcessPackets()
00248 {
00249
00250 CBuffer* pInput = m_pZInput ? m_pZInput : m_pInput;
00251
00252
00253 BOOL bSuccess = TRUE;
00254 for ( ; bSuccess ; )
00255 {
00256
00257 GNUTELLAPACKET* pPacket = (GNUTELLAPACKET*)pInput->m_pBuffer;
00258 if ( pInput->m_nLength < sizeof(*pPacket) ) break;
00259
00260
00261 DWORD nLength =
00262 sizeof(*pPacket) +
00263 pPacket->m_nLength;
00264
00265
00266 if ( pPacket->m_nLength < 0 || nLength >= Settings.Gnutella1.MaximumPacket )
00267 {
00268
00269 Close( IDS_PROTOCOL_TOO_LARGE );
00270 return FALSE;
00271 }
00272
00273
00274 if ( pInput->m_nLength < nLength ) break;
00275
00276
00277 CG1Packet* pPacketObject = CG1Packet::New( pPacket );
00278 bSuccess = OnPacket( pPacketObject );
00279 pPacketObject->Release();
00280
00281
00282 pInput->Remove( nLength );
00283 }
00284
00285
00286 if ( bSuccess ) return TRUE;
00287
00288
00289 Close( 0 );
00290 return FALSE;
00291 }
00292
00294
00295
00296
00297
00298
00299 BOOL CG1Neighbour::OnPacket(CG1Packet* pPacket)
00300 {
00301
00302 m_nInputCount++;
00303 m_tLastPacket = GetTickCount();
00304 Statistics.Current.Gnutella1.Incoming++;
00305
00306
00307 if (
00308
00309
00310 pPacket->m_nTTL != 0 &&
00311
00312
00313 (DWORD)pPacket->m_nTTL + pPacket->m_nHops > Settings.Gnutella1.MaximumTTL &&
00314
00315
00316 pPacket->m_nType != G1_PACKET_PUSH && pPacket->m_nType != G1_PACKET_HIT )
00317 {
00318
00319 theApp.Message( MSG_ERROR, IDS_PROTOCOL_HIGH_TTL, (LPCTSTR)m_sAddress, pPacket->m_nTTL, pPacket->m_nHops );
00320 pPacket->m_nTTL = 1;
00321 }
00322
00323
00324 pPacket->SmartDump( this, NULL, FALSE );
00325
00326
00327 switch ( pPacket->m_nType )
00328 {
00329 case G1_PACKET_PING: return OnPing( pPacket );
00330 case G1_PACKET_PONG: return OnPong( pPacket );
00331 case G1_PACKET_BYE: return OnBye( pPacket );
00332 case G1_PACKET_QUERY_ROUTE: return OnCommonQueryHash( pPacket );
00333 case G1_PACKET_VENDOR:
00334 case G1_PACKET_VENDOR_APP: return OnVendor( pPacket );
00335 case G1_PACKET_PUSH: return OnPush( pPacket );
00336 case G1_PACKET_QUERY: return OnQuery( pPacket );
00337 case G1_PACKET_HIT: return OnHit( pPacket );
00338 }
00339
00340
00341 theApp.Message( MSG_ERROR, IDS_PROTOCOL_UNKNOWN, (LPCTSTR)m_sAddress, pPacket->m_nType );
00342
00343
00344 return ! Settings.Gnutella1.StrictPackets;
00345 }
00346
00348
00349
00350
00351
00352
00353 BOOL CG1Neighbour::SendPing(DWORD dwNow, GGUID* pGUID)
00354 {
00355
00356 if ( m_nNodeType == ntLeaf && pGUID != NULL ) return FALSE;
00357
00358
00359 BOOL bNeedPeers = Neighbours.NeedMoreHubs( PROTOCOL_G1 ) || Neighbours.NeedMoreLeafs( PROTOCOL_G1 );
00360
00361
00362 if ( ! dwNow ) dwNow = GetTickCount();
00363
00364
00365 if ( dwNow - m_tLastOutPing < Settings.Gnutella1.PingRate * 2 ) return FALSE;
00366
00367
00368 m_tLastOutPing = dwNow;
00369
00370
00371 Send( CG1Packet::New( G1_PACKET_PING, ( pGUID || bNeedPeers ) ? 0 : 1, pGUID ), TRUE, TRUE );
00372 return TRUE;
00373 }
00374
00375
00376
00377
00378 BOOL CG1Neighbour::OnPing(CG1Packet* pPacket)
00379 {
00380
00381 if ( ! Neighbours.m_pPingRoute->Add( &pPacket->m_pGUID, this ) )
00382 {
00383
00384 Statistics.Current.Gnutella1.Dropped++;
00385 m_nDropCount++;
00386 return TRUE;
00387 }
00388
00389
00390 if ( pPacket->m_nLength != 0 && Settings.Gnutella1.StrictPackets )
00391 {
00392
00393 theApp.Message( MSG_ERROR, IDS_PROTOCOL_SIZE_PING, (LPCTSTR)m_sAddress );
00394 Statistics.Current.Gnutella1.Dropped++;
00395 m_nDropCount++;
00396 return TRUE;
00397
00398 }
00399 else if ( pPacket->m_nLength > Settings.Gnutella1.MaximumQuery )
00400 {
00401
00402 theApp.Message( MSG_ERROR, IDS_PROTOCOL_TOO_LARGE, (LPCTSTR)m_sAddress );
00403 Statistics.Current.Gnutella1.Dropped++;
00404 m_nDropCount++;
00405 return TRUE;
00406 }
00407
00408
00409 BOOL bIsKeepAlive = ( pPacket->m_nTTL == 1 && pPacket->m_nHops == 0 );
00410
00411
00412 DWORD dwNow = GetTickCount();
00413 if ( dwNow - m_tLastInPing < Settings.Gnutella1.PingFlood && ! bIsKeepAlive )
00414 {
00415
00416 Statistics.Current.Gnutella1.Dropped++;
00417 m_nDropCount++;
00418 return TRUE;
00419 }
00420
00421
00422 if ( pPacket->m_nLength && m_bGGEP )
00423 {
00424
00425 if ( pPacket->ReadByte() != GGEP_MAGIC )
00426 {
00427
00428 theApp.Message( MSG_ERROR, IDS_PROTOCOL_GGEP_REQUIRED, (LPCTSTR)m_sAddress );
00429 Statistics.Current.Gnutella1.Dropped++;
00430 m_nDropCount++;
00431 return TRUE;
00432
00433 }
00434 else if ( pPacket->Hop() )
00435 {
00436
00437 if ( Neighbours.Broadcast( pPacket, this, TRUE ) ) Statistics.Current.Gnutella1.Routed++;
00438
00439
00440 pPacket->m_nHops--;
00441 pPacket->m_nTTL++;
00442 }
00443 }
00444
00445
00446 m_tLastInPing = dwNow;
00447 m_nLastPingHops = pPacket->m_nHops + 1;
00448 m_pLastPingID = pPacket->m_pGUID;
00449
00450
00451 if ( pPacket->m_nTTL == 2 && pPacket->m_nHops == 0 )
00452 {
00453
00454 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00455 {
00456
00457 CNeighbour* pConnection = Neighbours.GetNext( pos );
00458 if ( pConnection->m_nState != nrsConnected ) continue;
00459
00460
00461 CG1Packet* pPong = CG1Packet::New(
00462 G1_PACKET_PONG,
00463 m_nLastPingHops,
00464 &m_pLastPingID );
00465
00466
00467 pPong->WriteShortLE( htons( pConnection->m_pHost.sin_port ) );
00468 pPong->WriteLongLE( pConnection->m_pHost.sin_addr.S_un.S_addr );
00469 pPong->WriteLongLE( 0 );
00470 pPong->WriteLongLE( 0 );
00471
00472
00473 Send( pPong );
00474 }
00475
00476
00477 return TRUE;
00478 }
00479
00480
00481 if ( bIsKeepAlive ||
00482 ( Network.IsListening() && ! Neighbours.IsG1Leaf() ) )
00483 {
00484
00485 CG1Packet* pPong = CG1Packet::New(
00486 G1_PACKET_PONG,
00487 m_nLastPingHops,
00488 &m_pLastPingID );
00489
00490
00491 QWORD nMyVolume;
00492 DWORD nMyFiles;
00493 LibraryMaps.GetStatistics( &nMyFiles, &nMyVolume );
00494
00495
00496 pPong->WriteShortLE( htons( Network.m_pHost.sin_port ) );
00497 pPong->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00498
00499
00500 pPong->WriteLongLE( nMyFiles );
00501 pPong->WriteLongLE( (DWORD)nMyVolume );
00502
00503
00504 Send( pPong );
00505 }
00506
00507
00508 if ( bIsKeepAlive ||
00509 m_nNodeType == ntHub ||
00510 ! pPacket->Hop() )
00511
00512
00513 return TRUE;
00514
00515
00516 Neighbours.OnG1Ping();
00517
00518
00519 CPtrList pIgnore;
00520
00521
00522 ZeroMemory( m_nPongNeeded, PONG_NEEDED_BUFFER );
00523
00524
00525 for ( BYTE nHops = 1 ; nHops <= pPacket->m_nTTL ; nHops++ )
00526 {
00527
00528 m_nPongNeeded[ nHops ] =
00529 Settings.Gnutella1.PongCount /
00530 pPacket->m_nTTL;
00531
00532
00533 CPongItem* pCache = NULL;
00534 while ( ( m_nPongNeeded[ nHops ] > 0 ) &&
00535 ( pCache = Neighbours.m_pPongCache->Lookup( this, nHops, &pIgnore ) ) )
00536 {
00537
00538 Send( pCache->ToPacket( m_nLastPingHops, &m_pLastPingID ) );
00539
00540
00541 pIgnore.AddTail( pCache );
00542 m_nPongNeeded[ nHops ]--;
00543 }
00544 }
00545
00546
00547 return TRUE;
00548 }
00549
00551
00552
00553
00554
00555
00556 BOOL CG1Neighbour::OnPong(CG1Packet* pPacket)
00557 {
00558
00559 if ( pPacket->m_nLength < 14 || ( pPacket->m_nLength > 14 && Settings.Gnutella1.StrictPackets ) )
00560 {
00561
00562 theApp.Message( MSG_ERROR, IDS_PROTOCOL_SIZE_PONG, (LPCTSTR)m_sAddress );
00563 Statistics.Current.Gnutella1.Dropped++;
00564 m_nDropCount++;
00565 return TRUE;
00566 }
00567
00568
00569 WORD nPort = pPacket->ReadShortLE();
00570 DWORD nAddress = pPacket->ReadLongLE();
00571 DWORD nFiles = pPacket->ReadLongLE();
00572 DWORD nVolume = pPacket->ReadLongLE();
00573
00574
00575 if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
00576 {
00577
00578 Statistics.Current.Gnutella1.Dropped++;
00579 m_nDropCount++;
00580 return TRUE;
00581 }
00582
00583
00584 if ( pPacket->m_nLength > 14 && m_bGGEP )
00585 {
00586
00587 if ( pPacket->ReadByte() != GGEP_MAGIC )
00588 {
00589
00590 theApp.Message( MSG_ERROR, IDS_PROTOCOL_GGEP_REQUIRED, (LPCTSTR)m_sAddress );
00591 Statistics.Current.Gnutella1.Dropped++;
00592 m_nDropCount++;
00593 return TRUE;
00594
00595 }
00596 else if ( pPacket->Hop() )
00597 {
00598
00599 CG1Neighbour* pOrigin;
00600 Neighbours.m_pPingRoute->Lookup( &pPacket->m_pGUID, (CNeighbour**)&pOrigin );
00601
00602
00603 if ( pOrigin && pOrigin->m_bGGEP )
00604 {
00605
00606 Statistics.Current.Gnutella1.Routed++;
00607 pOrigin->Send( pPacket, FALSE, TRUE );
00608 }
00609
00610
00611 pPacket->m_nHops--;
00612 }
00613 }
00614
00615
00616 BOOL bLocal =
00617 ! nPort ||
00618 Network.IsFirewalledAddress( &nAddress );
00619
00620
00621 if ( pPacket->m_nHops != 0 && bLocal )
00622 {
00623
00624 if ( pPacket->m_nHops ) theApp.Message( MSG_DEBUG, IDS_PROTOCOL_ZERO_PONG, (LPCTSTR)m_sAddress );
00625 Statistics.Current.Gnutella1.Dropped++;
00626 m_nDropCount++;
00627 return TRUE;
00628 }
00629
00630
00631 if ( ! bLocal && ! Network.IsFirewalledAddress( &nAddress, TRUE ) )
00632 {
00633
00634 if ( pPacket->m_nHops == 0 && nAddress == m_pHost.sin_addr.S_un.S_addr )
00635 {
00636
00637 m_nFileCount = nFiles;
00638 m_nFileVolume = nVolume;
00639
00640
00641 HostCache.Gnutella1.Add( (IN_ADDR*)&nAddress, nPort, 0, m_bShareaza ? SHAREAZA_VENDOR_T : NULL );
00642
00643 }
00644 else
00645 {
00646
00647 HostCache.Gnutella1.Add( (IN_ADDR*)&nAddress, nPort );
00648 }
00649 }
00650
00651
00652 BYTE nHops = pPacket->m_nHops + 1;
00653 nHops = min( nHops, BYTE(PONG_NEEDED_BUFFER - 1) );
00654 if ( ! bLocal ) Neighbours.OnG1Pong( this, (IN_ADDR*)&nAddress, nPort, nHops + 1, nFiles, nVolume );
00655
00656
00657 return TRUE;
00658 }
00659
00660
00661
00662
00663 void CG1Neighbour::OnNewPong(CPongItem* pPong)
00664 {
00665
00666 if ( m_nPongNeeded[ pPong->m_nHops ] > 0 )
00667 {
00668
00669 Send( pPong->ToPacket( m_nLastPingHops, &m_pLastPingID ) );
00670
00671
00672 m_nPongNeeded[ pPong->m_nHops ]--;
00673 }
00674 }
00675
00677
00678
00679
00680
00681
00682 BOOL CG1Neighbour::OnBye(CG1Packet* pPacket)
00683 {
00684
00685 CString strReason;
00686 WORD nReason = 0;
00687
00688
00689 if ( pPacket->m_nLength >= 3 )
00690 {
00691
00692 nReason = pPacket->ReadShortLE();
00693 strReason = pPacket->ReadString();
00694 }
00695
00696
00697 for ( int nChar = 0 ; nChar < strReason.GetLength() ; nChar++ )
00698 {
00699
00700 if ( strReason[nChar] < 32 )
00701 {
00702
00703 strReason = strReason.Left( nChar );
00704 break;
00705 }
00706 }
00707
00708
00709 if ( strReason.IsEmpty() || strReason.GetLength() > 128 ) strReason = _T("No Message");
00710
00711
00712 theApp.Message( MSG_ERROR, IDS_CONNECTION_BYE, (LPCTSTR)m_sAddress, nReason, (LPCTSTR)strReason );
00713
00714
00715 return FALSE;
00716 }
00717
00719
00720
00721
00722
00723
00724 BOOL CG1Neighbour::OnVendor(CG1Packet* pPacket)
00725 {
00726
00727 if ( pPacket->m_nLength < 8 || ! Settings.Gnutella1.VendorMsg )
00728 {
00729
00730 Statistics.Current.Gnutella1.Dropped++;
00731 m_nDropCount++;
00732 return TRUE;
00733 }
00734
00735
00736 DWORD nVendor = pPacket->ReadLongLE();
00737 WORD nFunction = pPacket->ReadShortLE();
00738 WORD nVersion = pPacket->ReadShortLE();
00739
00740
00741 if ( nVendor == 0 && nFunction == 0 )
00742 {
00743
00744
00745 }
00746 else if ( nFunction == 0xFFFF )
00747 {
00748
00749 if ( nVendor == 0 )
00750 {
00751
00752 CG1Packet* pReply = CG1Packet::New( pPacket->m_nType, 1, &pPacket->m_pGUID );
00753 pReply->WriteLongLE( 0 );
00754 pReply->WriteShortLE( 0xFFFE );
00755 pReply->WriteShortLE( 1 );
00756 pReply->WriteLongLE( 'AZAR' );
00757 pReply->WriteLongLE( 'RAEB' );
00758 Send( pReply );
00759
00760 }
00761 else if ( nVendor == 'AZAR' )
00762 {
00763
00764 CG1Packet* pReply = CG1Packet::New( pPacket->m_nType, 1, &pPacket->m_pGUID );
00765 pReply->WriteLongLE( 'AZAR' );
00766 pReply->WriteShortLE( 0xFFFE );
00767 pReply->WriteShortLE( 1 );
00768 pReply->WriteShortLE( 0x0001 );
00769 pReply->WriteShortLE( 1 );
00770 pReply->WriteShortLE( 0x0002 );
00771 pReply->WriteShortLE( 1 );
00772 pReply->WriteShortLE( 0x0003 );
00773 pReply->WriteShortLE( 1 );
00774 Send( pReply );
00775
00776 }
00777 else if ( nVendor == 'RAEB' )
00778 {
00779
00780 CG1Packet* pReply = CG1Packet::New( pPacket->m_nType, 1, &pPacket->m_pGUID );
00781 pReply->WriteLongLE( 'RAEB' );
00782 pReply->WriteShortLE( 0xFFFE );
00783 pReply->WriteShortLE( 1 );
00784 pReply->WriteShortLE( 0x0004 );
00785 pReply->WriteShortLE( 1 );
00786 pReply->WriteShortLE( 0x000B );
00787 pReply->WriteShortLE( 1 );
00788 pReply->WriteShortLE( 0x000C );
00789 pReply->WriteShortLE( 1 );
00790 Send( pReply );
00791 }
00792
00793 }
00794 else if ( nVendor == 'AZAR' )
00795 {
00796
00797 switch ( nFunction )
00798 {
00799
00800
00801 case 0x0001:
00802
00803
00804 if ( nVersion <= 1 )
00805 {
00806
00807 CG1Packet* pReply = CG1Packet::New( pPacket->m_nType, 1, &pPacket->m_pGUID );
00808 pReply->WriteLongLE( 'AZAR' );
00809 pReply->WriteShortLE( 0x0002 );
00810 pReply->WriteShortLE( 1 );
00811 pReply->WriteShortLE( theApp.m_nVersion[0] );
00812 pReply->WriteShortLE( theApp.m_nVersion[1] );
00813 pReply->WriteShortLE( theApp.m_nVersion[2] );
00814 pReply->WriteShortLE( theApp.m_nVersion[3] );
00815 Send( pReply );
00816 }
00817
00818 break;
00819
00820
00821 case 0x0002:
00822
00823
00824 if ( nVersion <= 1 && pPacket->GetRemaining() >= 8 )
00825 {
00826
00827 WORD nVersion[4];
00828 nVersion[0] = pPacket->ReadShortLE();
00829 nVersion[1] = pPacket->ReadShortLE();
00830 nVersion[2] = pPacket->ReadShortLE();
00831 nVersion[3] = pPacket->ReadShortLE();
00832 }
00833
00834 break;
00835
00836
00837 case 0x0003:
00838
00839
00840 if ( nVersion <= 1 && pPacket->GetRemaining() >= 28 )
00841 {
00842
00843 OnClusterAdvisor( pPacket );
00844 }
00845
00846 break;
00847 }
00848
00849 }
00850 else if ( nVendor == 'RAEB' )
00851 {
00852
00853 switch ( nFunction )
00854 {
00855
00856
00857 case 0x0001:
00858
00859 break;
00860
00861
00862 case 0x0003:
00863
00864 break;
00865
00866
00867 case 0x0004:
00868
00869 if ( nVersion <= 1 && pPacket->GetRemaining() >= 1 )
00870 {
00871 m_nHopsFlow = pPacket->ReadByte();
00872 }
00873
00874 break;
00875
00876
00877 case 0x0005:
00878
00879 break;
00880
00881
00882 case 0x0006:
00883
00884 break;
00885
00886
00887 case 0x000B:
00888
00889
00890 if ( nVersion <= 1 )
00891 {
00892
00893 CG1Packet* pReply = CG1Packet::New( pPacket->m_nType, 1, &pPacket->m_pGUID );
00894 pReply->WriteLongLE( 'RAEB' );
00895 pReply->WriteShortLE( 0x000C );
00896 pReply->WriteShortLE( 1 );
00897 pReply->WriteShortLE( SearchManager.OnQueryStatusRequest( &pPacket->m_pGUID ) );
00898 Send( pReply );
00899 }
00900
00901 break;
00902
00903
00904 case 0x000C:
00905
00906 break;
00907 }
00908 }
00909
00910
00911 return TRUE;
00912 }
00913
00915
00916
00917
00918 void CG1Neighbour::SendClusterAdvisor()
00919 {
00920
00921 if ( ! m_bShareaza || ! Settings.Gnutella1.VendorMsg ) return;
00922
00923
00924 DWORD tNow = time( NULL );
00925 CG1Packet* pPacket = NULL;
00926 WORD nCount = 0;
00927
00928
00929 for ( CHostCacheHost* pHost = HostCache.Gnutella1.GetNewest();
00930 pHost && nCount < 20;
00931 pHost = pHost->m_pPrevTime )
00932 {
00933
00934 if ( pHost->m_pVendor == VendorCache.m_pShareaza &&
00935 pHost->m_tAdded > m_tClusterHost &&
00936 pHost->CanConnect( tNow ) )
00937 {
00938
00939 if ( ! pPacket )
00940 {
00941
00942 pPacket = CG1Packet::New( G1_PACKET_VENDOR, 1 );
00943 pPacket->WriteLongLE( 'AZAR' );
00944 pPacket->WriteShortLE( 0x0003 );
00945 pPacket->WriteShortLE( 1 );
00946 pPacket->WriteShortLE( 0 );
00947 }
00948
00949
00950 pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );
00951 pPacket->WriteShortLE( pHost->m_nPort );
00952
00953
00954 nCount++;
00955 }
00956 }
00957
00958
00959 m_tClusterHost = GetTickCount();
00960
00961
00962 if ( pPacket && nCount )
00963 {
00964
00965 m_tClusterSent = m_tClusterHost;
00966 ((WORD*)pPacket->m_pBuffer)[4] = nCount;
00967 pPacket->RazaSign();
00968 Send( pPacket, TRUE, TRUE );
00969 }
00970 }
00971
00972
00973
00974
00975 BOOL CG1Neighbour::OnClusterAdvisor(CG1Packet* pPacket)
00976 {
00977
00978 if ( ! pPacket->RazaVerify() ) return FALSE;
00979
00980
00981 WORD nCount = pPacket->ReadShortLE();
00982 if ( pPacket->GetRemaining() < nCount * 6 + 20 ) return FALSE;
00983
00984
00985 SendClusterAdvisor();
00986
00987
00988 while ( nCount-- )
00989 {
00990
00991 DWORD nAddress = pPacket->ReadLongLE();
00992 WORD nPort = pPacket->ReadShortLE();
00993 HostCache.Gnutella1.Add( (IN_ADDR*)&nAddress, nPort, 0, SHAREAZA_VENDOR_T );
00994 }
00995
00996
00997 m_tClusterHost = GetTickCount();
00998
00999
01000 return TRUE;
01001 }
01002
01004
01005
01006
01007
01008
01009 BOOL CG1Neighbour::OnPush(CG1Packet* pPacket)
01010 {
01011
01012 if ( pPacket->m_nLength < 26 || ( pPacket->m_nLength > 26 && Settings.Gnutella1.StrictPackets ) )
01013 {
01014
01015 theApp.Message( MSG_ERROR, IDS_PROTOCOL_SIZE_PUSH, (LPCTSTR)m_sAddress );
01016 Statistics.Current.Gnutella1.Dropped++;
01017 m_nDropCount++;
01018 return TRUE;
01019 }
01020
01021
01022 GGUID pClientID;
01023 pPacket->Read( &pClientID, 16 );
01024
01025
01026 DWORD nFileIndex = pPacket->ReadLongLE();
01027 DWORD nAddress = pPacket->ReadLongLE();
01028 WORD nPort = pPacket->ReadShortLE();
01029
01030
01031 BOOL bGGEP = FALSE;
01032
01033
01034 if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
01035 {
01036
01037 Statistics.Current.Gnutella1.Dropped++;
01038 m_nDropCount++;
01039 return TRUE;
01040 }
01041
01042
01043 if ( pPacket->m_nLength > 26 && m_bGGEP )
01044 {
01045
01046 if ( pPacket->ReadByte() != GGEP_MAGIC )
01047 {
01048
01049 theApp.Message( MSG_ERROR, IDS_PROTOCOL_GGEP_REQUIRED, (LPCTSTR)m_sAddress );
01050 Statistics.Current.Gnutella1.Dropped++;
01051 m_nDropCount++;
01052 return TRUE;
01053 }
01054
01055
01056 bGGEP = TRUE;
01057 }
01058
01059
01060 if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) )
01061 {
01062
01063 theApp.Message( MSG_ERROR, IDS_PROTOCOL_ZERO_PUSH, (LPCTSTR)m_sAddress );
01064 Statistics.Current.Gnutella1.Dropped++;
01065 m_nDropCount++;
01066 return TRUE;
01067 }
01068
01069
01070 if ( pClientID == MyProfile.GUID )
01071 {
01072
01073 Handshakes.PushTo( (IN_ADDR*)&nAddress, nPort, nFileIndex );
01074 return TRUE;
01075 }
01076
01077
01078 CNeighbour* pOrigin;
01079 Network.NodeRoute->Lookup( &pClientID, (CNeighbour**)&pOrigin );
01080
01081
01082 if ( pOrigin && pPacket->Hop() )
01083 {
01084
01085 if ( pOrigin->m_nProtocol == PROTOCOL_G1 )
01086 {
01087
01088 if ( bGGEP && ! pOrigin->m_bGGEP ) pPacket->Shorten( 26 );
01089
01090
01091 pOrigin->Send( pPacket, FALSE, TRUE );
01092
01093 }
01094 else if ( pOrigin->m_nProtocol == PROTOCOL_G2 )
01095 {
01096
01097 CG2Packet* pWrap = CG2Packet::New( G2_PACKET_PUSH, TRUE );
01098 pWrap->WritePacket( "TO", 16 );
01099 pWrap->Write( &pClientID, 16 );
01100 pWrap->WriteByte( 0 );
01101 pWrap->WriteLongLE( nAddress );
01102 pWrap->WriteShortLE( nPort );
01103 pOrigin->Send( pWrap, TRUE, TRUE );
01104 }
01105
01106
01107 Statistics.Current.Gnutella1.Routed++;
01108 }
01109
01110
01111 return TRUE;
01112 }
01113
01114
01115
01116
01117 void CG1Neighbour::SendG2Push(GGUID* pGUID, CPacket* pPacket)
01118 {
01119
01120 if ( pPacket->GetRemaining() < 6 ) return;
01121
01122
01123 DWORD nAddress = pPacket->ReadLongLE();
01124 WORD nPort = pPacket->ReadShortLE();
01125
01126
01127 pPacket = CG1Packet::New( G1_PACKET_PUSH, Settings.Gnutella1.MaximumTTL - 1 );
01128 pPacket->Write( pGUID, 16 );
01129 pPacket->WriteLongLE( 0 );
01130 pPacket->WriteLongLE( nAddress );
01131 pPacket->WriteShortLE( nPort );
01132 Send( pPacket, TRUE, TRUE );
01133 }
01134
01136
01137
01138
01139
01140
01141 BOOL CG1Neighbour::OnQuery(CG1Packet* pPacket)
01142 {
01143
01144 if ( pPacket->m_nLength <= 5 )
01145 {
01146
01147 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_QUERY, (LPCTSTR)m_sAddress );
01148 Statistics.Current.Gnutella1.Dropped++;
01149 m_nDropCount++;
01150 return TRUE;
01151
01152 }
01153 else if ( pPacket->m_nLength > Settings.Gnutella1.MaximumQuery )
01154 {
01155
01156 theApp.Message( MSG_ERROR, IDS_PROTOCOL_TOO_LARGE, (LPCTSTR)m_sAddress );
01157 Statistics.Current.Gnutella1.Dropped++;
01158 m_nDropCount++;
01159 return FALSE;
01160 }
01161
01162
01163 if ( m_nNodeType == ntLeaf && pPacket->m_nHops > 0 )
01164 {
01165
01166 theApp.Message( MSG_ERROR, IDS_PROTOCOL_LEAF_FORWARD, (LPCTSTR)m_sAddress );
01167 Statistics.Current.Gnutella1.Dropped++;
01168 m_nDropCount++;
01169 return FALSE;
01170 }
01171
01172
01173 if ( ! Network.QueryRoute->Add( &pPacket->m_pGUID, this ) )
01174 {
01175
01176 Statistics.Current.Gnutella1.Dropped++;
01177 m_nDropCount++;
01178 return TRUE;
01179 }
01180
01181
01182 CQuerySearch* pSearch = CQuerySearch::FromPacket( pPacket );
01183 if ( pSearch == NULL )
01184 {
01185
01186 pPacket->Debug( _T("BadQuery") );
01187 theApp.Message( MSG_DEBUG, IDS_PROTOCOL_BAD_QUERY, (LPCTSTR)m_sAddress );
01188 Statistics.Current.Gnutella1.Dropped++;
01189 m_nDropCount++;
01190 return TRUE;
01191 }
01192
01193
01194 CLocalSearch pLocalSearch( pSearch, this );
01195
01196
01197 if ( m_nNodeType != ntHub && pPacket->Hop() )
01198 {
01199
01200 Neighbours.RouteQuery( pSearch, pPacket, this, TRUE );
01201 }
01202
01203
01204 Network.OnQuerySearch( pSearch );
01205
01206
01207 if ( ! pSearch->m_bFirewall || Network.IsListening() ) pLocalSearch.Execute();
01208
01209
01210 delete pSearch;
01211 Statistics.Current.Gnutella1.Queries++;
01212 return TRUE;
01213 }
01214
01215
01216
01217
01218 BOOL CG1Neighbour::SendQuery(CQuerySearch* pSearch, CPacket* pPacket, BOOL bLocal)
01219 {
01220
01221 if ( m_nState != nrsConnected ) return FALSE;
01222
01223
01224 if ( pPacket == NULL || pPacket->m_nProtocol != PROTOCOL_G1 ) return FALSE;
01225
01226
01227 CG1Packet* pG1 = (CG1Packet*)pPacket;
01228
01229
01230 if ( pG1->m_nHops > m_nHopsFlow )
01231 {
01232
01233 return FALSE;
01234
01235 }
01236 else if ( m_nNodeType == ntHub && ! bLocal )
01237 {
01238
01239 return FALSE;
01240
01241 }
01242 else if ( ! pSearch->m_bAndG1 )
01243 {
01244
01245 return FALSE;
01246
01247 }
01248 else if ( m_pQueryTableRemote != NULL && m_pQueryTableRemote->m_bLive )
01249 {
01250
01251 if ( ! m_pQueryTableRemote->Check( pSearch ) ) return FALSE;
01252
01253 }
01254 else if ( m_nNodeType == ntLeaf && ! bLocal )
01255 {
01256
01257 return FALSE;
01258 }
01259
01260
01261 if ( bLocal ) m_tLastQuery = time( NULL );
01262
01263
01264 Send( pPacket, FALSE, ! bLocal );
01265 return TRUE;
01266 }
01267
01269
01270
01271
01272
01273
01274 BOOL CG1Neighbour::OnHit(CG1Packet* pPacket)
01275 {
01276
01277 if ( pPacket->m_nLength <= 27 )
01278 {
01279
01280 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_HIT, (LPCTSTR)m_sAddress );
01281 Statistics.Current.Gnutella1.Dropped++;
01282 m_nDropCount++;
01283 return TRUE;
01284 }
01285
01286
01287 return OnCommonHit( pPacket );
01288 }