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 "SearchManager.h"
00026 #include "ManagedSearch.h"
00027 #include "QuerySearch.h"
00028 #include "Network.h"
00029 #include "HostCache.h"
00030 #include "Neighbours.h"
00031 #include "Datagrams.h"
00032 #include "G1Neighbour.h"
00033 #include "G2Neighbour.h"
00034 #include "G1Packet.h"
00035 #include "G2Packet.h"
00036 #include "EDPacket.h"
00037 #include "EDNeighbour.h"
00038
00039 #ifdef _DEBUG
00040 #undef THIS_FILE
00041 static char THIS_FILE[]=__FILE__;
00042 #define new DEBUG_NEW
00043 #endif
00044
00045
00047
00048
00049 CManagedSearch::CManagedSearch(CQuerySearch* pSearch, int nPriority)
00050 {
00051 m_pSearch = pSearch ? pSearch : new CQuerySearch();
00052 m_nPriority = nPriority;
00053 m_bAllowG2 = TRUE;
00054 m_bAllowG1 = TRUE;
00055 m_bAllowED2K = TRUE;
00056
00057 m_bActive = FALSE;
00058 m_bReceive = TRUE;
00059 m_tStarted = 0;
00060 m_nHits = 0;
00061
00062 m_nHubs = 0;
00063 m_nLeaves = 0;
00064 m_nQueryCount = 0;
00065
00066 m_tLastG2 = 0;
00067 m_tLastED2K = 0;
00068 m_tMoreResults = 0;
00069 m_nEDServers = 0;
00070 m_nEDClients = 0;
00071
00072 }
00073
00074 CManagedSearch::~CManagedSearch()
00075 {
00076 Stop();
00077 if ( m_pSearch ) delete m_pSearch;
00078 }
00079
00081
00082
00083 void CManagedSearch::Serialize(CArchive& ar)
00084 {
00085 int nVersion = 3;
00086
00087 if ( ar.IsStoring() )
00088 {
00089 ar << nVersion;
00090
00091 m_pSearch->Serialize( ar );
00092 ar << m_nPriority;
00093 ar << m_bActive;
00094 ar << m_bReceive;
00095 ar << m_bAllowG2;
00096 ar << m_bAllowG1;
00097 ar << m_bAllowED2K;
00098 }
00099 else
00100 {
00101 ar >> nVersion;
00102 if ( nVersion < 2 ) AfxThrowUserException();
00103
00104 if ( m_pSearch ) delete m_pSearch;
00105 m_pSearch = new CQuerySearch();
00106 m_pSearch->Serialize( ar );
00107
00108 ar >> m_nPriority;
00109 ar >> m_bActive;
00110 ar >> m_bReceive;
00111
00112 m_bActive = m_bReceive = FALSE;
00113
00114 if ( nVersion >= 3 )
00115 {
00116 ar >> m_bAllowG2;
00117 ar >> m_bAllowG1;
00118 ar >> m_bAllowED2K;
00119 }
00120 }
00121 }
00122
00124
00125
00126 void CManagedSearch::Start()
00127 {
00128 if ( m_bActive ) return;
00129 m_bActive = TRUE;
00130
00131 CSingleLock pLock( &SearchManager.m_pSection );
00132 pLock.Lock( 1000 );
00133
00134 m_tStarted = time( NULL );
00135 m_tExecute = 0;
00136 m_tLastED2K = 0;
00137 m_tMoreResults = 0;
00138 m_nQueryCount = 0;
00139
00140 m_pNodes.RemoveAll();
00141
00142 SearchManager.Add( this );
00143 }
00144
00145 void CManagedSearch::Stop()
00146 {
00147 if ( m_bActive )
00148 {
00149 m_bActive = FALSE;
00150 Datagrams.PurgeToken( this );
00151 }
00152
00153 CSingleLock pLock( &SearchManager.m_pSection );
00154 pLock.Lock( 1000 );
00155 SearchManager.Remove( this );
00156 }
00157
00159
00160
00161 BOOL CManagedSearch::Execute()
00162 {
00163 if ( ! m_bActive || ! m_pSearch ) return FALSE;
00164
00165 DWORD tTicks = GetTickCount();
00166 DWORD tSecs = time( NULL );
00167
00168
00169 DWORD nThrottle = max( Settings.Search.GeneralThrottle, (DWORD)200 );
00170 if ( m_nPriority == spLowest ) nThrottle += 30000;
00171 else if ( m_nPriority == spMedium ) nThrottle += 800;
00172
00173 if ( tTicks - m_tExecute < nThrottle ) return FALSE;
00174 m_tExecute = tTicks;
00175
00176
00177 BOOL bSuccess = ExecuteNeighbours( tTicks, tSecs );
00178
00179
00180 if ( Settings.Gnutella2.EnableToday && m_bAllowG2 )
00181 {
00182 if ( tTicks > m_tLastG2 && tTicks - m_tLastG2 >= Settings.Gnutella2.QueryGlobalThrottle )
00183 {
00184 bSuccess |= ExecuteG2Mesh( tTicks, tSecs );
00185 m_tLastG2 = tTicks;
00186 }
00187 }
00188
00189
00190 if ( Settings.eDonkey.EnableToday && Settings.eDonkey.ServerWalk && m_bAllowED2K && Network.IsListening() )
00191 {
00192 if ( ( m_pSearch->m_bED2K ) || ( IsLastED2KSearch() ) )
00193 {
00194 if ( tTicks > m_tLastED2K && tTicks - m_tLastED2K >= Settings.eDonkey.QueryGlobalThrottle )
00195 {
00196 bSuccess |= ExecuteDonkeyMesh( tTicks, tSecs );
00197 m_tLastED2K = tTicks;
00198 }
00199 }
00200 }
00201
00202 if ( bSuccess ) m_nQueryCount++;
00203
00204 return bSuccess;
00205 }
00206
00208
00209
00210 BOOL CManagedSearch::ExecuteNeighbours(DWORD tTicks, DWORD tSecs)
00211 {
00212 BOOL bIsOld = ( tSecs - m_tStarted ) >= 5;
00213
00214 int nCount = 0;
00215
00216 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00217 {
00218 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00219 DWORD nPeriod;
00220
00221
00222
00223 if ( pNeighbour->m_nState != nrsConnected ) continue;
00224
00225
00226
00227 switch ( pNeighbour->m_nProtocol )
00228 {
00229 case PROTOCOL_G1:
00230 if ( ! m_bAllowG1 ) continue;
00231 break;
00232 case PROTOCOL_G2:
00233 if ( ! m_bAllowG2 ) continue;
00234 break;
00235 case PROTOCOL_ED2K:
00236 if ( ! m_bAllowED2K ) continue;
00237 break;
00238 }
00239
00240
00241
00242 nPeriod = bIsOld ? 15 : 5;
00243 if ( bIsOld && pNeighbour->m_nProtocol == PROTOCOL_G1 ) nPeriod += 120 + ( 15 * m_nPriority );
00244
00245 if ( tTicks - pNeighbour->m_tConnected < nPeriod * 1000 ) continue;
00246
00247
00248
00249 if ( bIsOld )
00250 {
00251 if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00252 {
00253 if ( tSecs - pNeighbour->m_tLastQuery <
00254 Settings.Gnutella1.QueryThrottle ) continue;
00255 }
00256 else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00257 {
00258 if ( tSecs - pNeighbour->m_tLastQuery <
00259 Settings.Gnutella2.QueryHostThrottle / 4 ) continue;
00260 }
00261 }
00262
00263
00264
00265 DWORD nAddress = pNeighbour->m_pHost.sin_addr.S_un.S_addr;
00266
00267 if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)nPeriod ) )
00268 {
00269 DWORD nFrequency = 0;
00270
00271 if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00272 {
00273 nFrequency = Settings.Gnutella1.RequeryDelay;
00274 nFrequency *= ( m_nPriority + 1 );
00275 }
00276 else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00277 {
00278 nFrequency = Settings.Gnutella2.RequeryDelay;
00279 nFrequency *= ( m_nPriority + 1 );
00280 }
00281 else if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
00282 nFrequency = 86400;
00283
00284 if ( tSecs - nPeriod < nFrequency )
00285 {
00286
00287 if ( ( pNeighbour->m_nProtocol == PROTOCOL_ED2K ) && ( pNeighbour->m_pMoreResultsGUID != NULL ) )
00288 {
00289 if ( ( m_pSearch->m_pGUID == *pNeighbour->m_pMoreResultsGUID ) &&
00290 ( m_tMoreResults + 10000 < tTicks ) )
00291 {
00292
00293 pNeighbour->Send( CEDPacket::New( ED2K_C2S_MORERESULTS ) );
00294 ((CEDNeighbour*)pNeighbour)->m_pQueries.AddTail( pNeighbour->m_pMoreResultsGUID );
00295
00296 pNeighbour->m_pMoreResultsGUID = NULL;
00297
00298 m_tMoreResults = tTicks;
00299
00300 theApp.Message( MSG_DEBUG, _T("Asking ed2k neighbour for additional search results") );
00301 }
00302 }
00303
00304
00305 continue;
00306 }
00307 }
00308
00309
00310
00311 m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00312
00313
00314
00315 CPacket* pPacket = NULL;
00316
00317 if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00318 {
00319 pPacket = m_pSearch->ToG1Packet();
00320 }
00321 else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00322 {
00323 m_pSearch->m_bAndG1 = ( Settings.Gnutella1.EnableToday && m_bAllowG1 );
00324 pPacket = m_pSearch->ToG2Packet( Datagrams.IsStable() ? &Network.m_pHost : NULL, 0 );
00325 }
00326 else if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
00327 {
00328 pPacket = m_pSearch->ToEDPacket( FALSE, ((CEDNeighbour*)pNeighbour)->m_nTCPFlags );
00329 }
00330 else
00331 {
00332 ASSERT( FALSE );
00333 }
00334
00335
00336
00337 if ( pPacket != NULL && pNeighbour->SendQuery( m_pSearch, pPacket, TRUE ) )
00338 {
00339
00340 if ( pNeighbour->m_pMoreResultsGUID != NULL )
00341 {
00342 delete pNeighbour->m_pMoreResultsGUID;
00343 pNeighbour->m_pMoreResultsGUID = NULL;
00344 }
00345 m_tMoreResults = 0;
00346
00347
00348 theApp.Message( MSG_DEFAULT, IDS_NETWORK_SEARCH_SENT,
00349 m_pSearch->m_sSearch.GetLength() ? (LPCTSTR)m_pSearch->m_sSearch : _T("URN"),
00350 (LPCTSTR)CString( inet_ntoa( pNeighbour->m_pHost.sin_addr ) ) );
00351
00352 if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
00353 {
00354
00355 m_nEDServers++;
00356 m_nEDClients += ((CEDNeighbour*)pNeighbour)->m_nUserCount;
00357
00358
00359 if ( ! m_pSearch->m_bED2K )
00360 {
00361 SearchManager.m_pLastED2KSearch = m_pSearch->m_pGUID;
00362 }
00363 }
00364 }
00365 pPacket->Release();
00366
00367 nCount++;
00368 }
00369
00370 return ( nCount > 0 );
00371 }
00372
00374
00375
00376 BOOL CManagedSearch::ExecuteG2Mesh(DWORD tTicks, DWORD tSecs)
00377 {
00378
00379
00380 for ( CHostCacheHost* pHost = HostCache.Gnutella2.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
00381 {
00382
00383
00384 ASSERT( pHost->m_nProtocol == PROTOCOL_G2 );
00385 if ( pHost->m_nProtocol != PROTOCOL_G2 ) continue;
00386
00387
00388
00389 if ( NULL != Neighbours.Get( &pHost->m_pAddress ) ) continue;
00390
00391
00392
00393 if ( ! pHost->CanQuery( tSecs ) ) continue;
00394
00395
00396
00397
00398 SOCKADDR_IN* pReceiver = NULL;
00399
00400 if ( pHost->m_nKeyValue == 0 )
00401 {
00402
00403 }
00404 else if ( Datagrams.IsStable() )
00405 {
00406
00407
00408
00409 if ( pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
00410 pReceiver = &Network.m_pHost;
00411 else
00412 pHost->m_nKeyValue = 0;
00413 }
00414 else
00415 {
00416
00417
00418
00419 if ( CNeighbour* pNeighbour = Neighbours.Get( (IN_ADDR*)&pHost->m_nKeyHost ) )
00420 {
00421 if ( m_pNodes.Lookup( (LPVOID)pHost->m_nKeyHost, (LPVOID&)pReceiver ) )
00422 pReceiver = &pNeighbour->m_pHost;
00423 else
00424 continue;
00425 }
00426 else
00427 {
00428 pHost->m_nKeyValue = 0;
00429 }
00430 }
00431
00432
00433
00434 if ( pHost->m_nKeyValue != 0 )
00435 {
00436 DWORD tLastQuery, nAddress = pHost->m_pAddress.S_un.S_addr;
00437 ASSERT( pReceiver != NULL );
00438
00439
00440
00441 if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)tLastQuery ) )
00442 {
00443
00444 DWORD nFrequency;
00445
00446 if ( m_nPriority >= spLowest )
00447 {
00448
00449 if ( m_pSearch->m_bSHA1 )
00450 nFrequency = 16 * 60 * 60;
00451 else
00452 nFrequency = 32 * 60 * 60;
00453 }
00454 else
00455 nFrequency = Settings.Gnutella2.RequeryDelay * ( m_nPriority + 1 );
00456 if ( tSecs - tLastQuery < nFrequency ) continue;
00457 }
00458
00459
00460
00461 m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00462
00463
00464
00465 pHost->m_tQuery = tSecs;
00466 if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00467
00468
00469
00470 m_pSearch->m_bAndG1 = ( Settings.Gnutella1.EnableToday && m_bAllowG1 );
00471 CPacket* pPacket = m_pSearch->ToG2Packet( pReceiver, pHost->m_nKeyValue );
00472
00473
00474
00475 if ( pPacket != NULL )
00476 {
00477 Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, this, TRUE );
00478
00479 theApp.Message( MSG_DEBUG, _T("Querying %s"),
00480 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00481
00482 return TRUE;
00483 }
00484 }
00485 else if ( tSecs - pHost->m_tKeyTime >= max( Settings.Gnutella2.QueryHostThrottle * 5, DWORD(5*60) ) )
00486 {
00487
00488
00489
00490 CNeighbour* pCacheHub = NULL;
00491 pReceiver = NULL;
00492
00493 if ( Datagrams.IsStable() )
00494 {
00495
00496 pReceiver = &Network.m_pHost;
00497 }
00498 else
00499 {
00500
00501
00502
00503 for ( POSITION pos = Neighbours.GetIterator() ; pos ; pCacheHub = NULL )
00504 {
00505 pCacheHub = Neighbours.GetNext( pos );
00506 LPVOID pTemp;
00507
00508 if ( m_pNodes.Lookup( (LPVOID)pCacheHub->m_pHost.sin_addr.S_un.S_addr, pTemp ) )
00509 {
00510 if ( pCacheHub->m_nProtocol == PROTOCOL_G2 &&
00511 pCacheHub->m_nNodeType == ntHub )
00512 {
00513 pReceiver = &pCacheHub->m_pHost;
00514 if ( ! ((CG2Neighbour*)pCacheHub)->m_bCachedKeys ) pCacheHub = NULL;
00515 break;
00516 }
00517 }
00518 }
00519 }
00520
00521
00522
00523 if ( pCacheHub != NULL )
00524 {
00525
00526
00527
00528 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
00529 pPacket->WritePacket( "QNA", 6 );
00530 pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );
00531 pPacket->WriteShortBE( pHost->m_nPort );
00532 pCacheHub->Send( pPacket );
00533
00534
00535
00536 CString strReceiver = CString( inet_ntoa( pReceiver->sin_addr ) );
00537 theApp.Message( MSG_DEBUG, _T("Requesting query key from %s through %s"),
00538 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)strReceiver );
00539
00540 if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00541 pHost->m_tKeyTime = tSecs;
00542 pHost->m_nKeyValue = 0;
00543
00544 return TRUE;
00545 }
00546 else if ( pReceiver != NULL )
00547 {
00548
00549
00550 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
00551
00552 if ( pReceiver == &Network.m_pHost )
00553 {
00554 theApp.Message( MSG_DEBUG, _T("Requesting query key from %s"),
00555 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00556 }
00557 else
00558 {
00559
00560 pPacket->WritePacket( "RNA", 6 );
00561 pPacket->WriteLongLE( pReceiver->sin_addr.S_un.S_addr );
00562 pPacket->WriteShortBE( ntohs( pReceiver->sin_port ) );
00563
00564 CString strReceiver = CString( inet_ntoa( pReceiver->sin_addr ) );
00565 theApp.Message( MSG_DEBUG, _T("Requesting query key from %s for %s"),
00566 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)strReceiver );
00567 }
00568
00569
00570
00571 Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, NULL, FALSE );
00572
00573 if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00574 pHost->m_tKeyTime = tSecs;
00575 pHost->m_nKeyValue = 0;
00576
00577 return TRUE;
00578 }
00579 }
00580 }
00581
00582 return FALSE;
00583 }
00584
00586
00587
00588 BOOL CManagedSearch::ExecuteDonkeyMesh(DWORD tTicks, DWORD tSecs)
00589 {
00590 for ( CHostCacheHost* pHost = HostCache.eDonkey.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
00591 {
00592 ASSERT( pHost->m_nProtocol == PROTOCOL_ED2K );
00593
00594
00595
00596 if ( Neighbours.Get( &pHost->m_pAddress ) ) continue;
00597
00598
00599
00600 if ( pHost->CanQuery( tSecs ) )
00601 {
00602 DWORD nAddress = pHost->m_pAddress.S_un.S_addr;
00603 DWORD tLastQuery;
00604
00605
00606
00607 if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)tLastQuery ) ) continue;
00608
00609
00610
00611 m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00612
00613
00614
00615 pHost->m_tQuery = tSecs;
00616 if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00617
00618
00619
00620 CPacket* pPacket = NULL;
00621
00622 if ( pHost->m_nProtocol == PROTOCOL_ED2K )
00623 {
00624 pPacket = m_pSearch->ToEDPacket( TRUE, pHost->m_nUDPFlags );
00625 }
00626 else
00627 {
00628 ASSERT( FALSE );
00629 }
00630
00631
00632
00633 if ( pPacket != NULL )
00634 {
00635 Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort + 4, pPacket, TRUE );
00636
00637 theApp.Message( MSG_DEBUG, _T("Sending UDP query to %s"),
00638 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00639
00640
00641 if ( pHost->m_nProtocol == PROTOCOL_ED2K )
00642 {
00643 m_nEDServers++;
00644 m_nEDClients += pHost->m_nUserCount;
00645 }
00646
00647 return TRUE;
00648 }
00649 }
00650 }
00651
00652 return FALSE;
00653 }
00654
00656
00657
00658 void CManagedSearch::OnHostAcknowledge(DWORD nAddress)
00659 {
00660 DWORD tSecs = time( NULL );
00661 m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00662 }
00663
00665
00666
00667 BOOL CManagedSearch::IsLastED2KSearch()
00668 {
00669 return ( m_pSearch->m_pGUID == SearchManager.m_pLastED2KSearch );
00670 }
00671