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 "DiscoveryServices.h"
00030 #include "Network.h"
00031 #include "HostCache.h"
00032 #include "Neighbours.h"
00033 #include "Neighbour.h"
00034 #include "Packet.h"
00035 #include "Buffer.h"
00036
00037 #ifdef _DEBUG
00038 #undef THIS_FILE
00039 static char THIS_FILE[]=__FILE__;
00040 #define new DEBUG_NEW
00041 #endif
00042
00043 CDiscoveryServices DiscoveryServices;
00044
00046
00047
00048 CDiscoveryServices::CDiscoveryServices()
00049 {
00050 m_hThread = NULL;
00051 m_hInternet = NULL;
00052 m_hRequest = NULL;
00053 m_pWebCache = NULL;
00054 m_nWebCache = 0;
00055 m_tQueried = 0;
00056 m_nLastQueryProtocol = PROTOCOL_NULL;
00057 m_tUpdated = 0;
00058 m_nLastUpdateProtocol = PROTOCOL_NULL;
00059 m_tExecute = 0;
00060 m_bFirstTime = TRUE;
00061 m_tMetQueried = 0;
00062 }
00063
00064 CDiscoveryServices::~CDiscoveryServices()
00065 {
00066 Clear();
00067 }
00068
00070
00071
00072 POSITION CDiscoveryServices::GetIterator() const
00073 {
00074 return m_pList.GetHeadPosition();
00075 }
00076
00077 CDiscoveryService* CDiscoveryServices::GetNext(POSITION& pos) const
00078 {
00079 return (CDiscoveryService*)m_pList.GetNext( pos );
00080 }
00081
00082 BOOL CDiscoveryServices::Check(CDiscoveryService* pService, int nType) const
00083 {
00084 if ( pService == NULL ) return FALSE;
00085 if ( m_pList.Find( pService ) == NULL ) return FALSE;
00086 return ( nType < 0 ) || ( pService->m_nType == nType );
00087 }
00088
00089 int CDiscoveryServices::GetCount(int nType, PROTOCOLID nProtocol) const
00090 {
00091 int nCount = 0;
00092 CDiscoveryService* ptr;
00093
00094 for ( POSITION pos = GetIterator() ; pos ; )
00095 {
00096 ptr = GetNext( pos );
00097 if ( ( nType == CDiscoveryService::dsNull ) || ( ptr->m_nType == nType ) )
00098 {
00099 if ( ( nProtocol == PROTOCOL_NULL ) ||
00100 ( ( nProtocol == PROTOCOL_G1 ) && ptr->m_bGnutella1 ) ||
00101 ( ( nProtocol == PROTOCOL_G2 ) && ptr->m_bGnutella2 ) ||
00102 ( ( nProtocol == PROTOCOL_ED2K ) && ptr->m_nType == CDiscoveryService::dsServerMet ) )
00103 {
00104 nCount++;
00105 }
00106 }
00107 }
00108 return nCount;
00109 }
00110
00112
00113
00114 CDiscoveryService* CDiscoveryServices::Add(LPCTSTR pszAddress, int nType, PROTOCOLID nProtocol)
00115 {
00116 CString strAddress( pszAddress );
00117
00118
00119 strAddress.TrimLeft();
00120 strAddress.TrimRight();
00121
00122
00123 while ( strAddress.GetLength() >= 8 )
00124 {
00125 if ( strAddress.Right( 2 ) == _T("//") )
00126 strAddress = strAddress.Left( strAddress.GetLength() - 1 );
00127 else if ( strAddress.Right( 2 ) == _T("./") )
00128 strAddress = strAddress.Left( strAddress.GetLength() - 2 );
00129 else if ( strAddress.GetAt( strAddress.GetLength() - 1 ) == '.' )
00130 strAddress = strAddress.Left( strAddress.GetLength() - 1 );
00131 else break;
00132
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 if ( strAddress.GetLength() < 8 ) return NULL;
00144
00145 CSingleLock pNetworkLock( &Network.m_pSection );
00146 if ( ! pNetworkLock.Lock( 250 ) ) return NULL;
00147
00148 if ( GetByAddress( strAddress ) != NULL ) return NULL;
00149
00150 CDiscoveryService* pService = NULL;
00151
00152 switch ( nType )
00153 {
00154 case CDiscoveryService::dsWebCache:
00155 if ( CheckWebCacheValid( pszAddress ) )
00156 pService = new CDiscoveryService( CDiscoveryService::dsWebCache, strAddress );
00157 break;
00158
00159 case CDiscoveryService::dsServerMet:
00160 if ( CheckWebCacheValid( pszAddress ) )
00161 pService = new CDiscoveryService( CDiscoveryService::dsServerMet, strAddress );
00162 break;
00163
00164 case CDiscoveryService::dsGnutella:
00165 if ( _tcschr( pszAddress, '.' ) != NULL )
00166 pService = new CDiscoveryService( CDiscoveryService::dsGnutella, strAddress );
00167 break;
00168
00169 case CDiscoveryService::dsBlocked:
00170 pService = new CDiscoveryService( CDiscoveryService::dsBlocked, strAddress );
00171 break;
00172 }
00173
00174 if ( pService == NULL ) return NULL;
00175
00176
00177 switch( nProtocol )
00178 {
00179 case PROTOCOL_ED2K:
00180 pService->m_bGnutella2 = FALSE;
00181 pService->m_bGnutella1 = FALSE;
00182 break;
00183 case PROTOCOL_G2:
00184 pService->m_bGnutella2 = TRUE;
00185 pService->m_bGnutella1 = FALSE;
00186 break;
00187 case PROTOCOL_G1:
00188 pService->m_bGnutella2 = FALSE;
00189 pService->m_bGnutella1 = TRUE;
00190 break;
00191 default:
00192 pService->m_bGnutella2 = TRUE;
00193 pService->m_bGnutella1 = TRUE;
00194 break;
00195 }
00196
00197 return Add( pService );
00198 }
00199
00200 CDiscoveryService* CDiscoveryServices::Add(CDiscoveryService* pService)
00201 {
00202 if ( pService == NULL ) return NULL;
00203
00204
00205 if ( ( pService->m_bGnutella2 == FALSE ) && ( pService->m_bGnutella1 == FALSE ) && ( pService->m_nType == CDiscoveryService::dsWebCache ) )
00206 {
00207 pService->m_bGnutella2 = TRUE;
00208 pService->m_bGnutella1 = TRUE;
00209 }
00210
00211
00212 if ( ( pService->m_bGnutella2 && ( GetCount( PROTOCOL_G2 ) >= Settings.Discovery.CacheCount ) ) ||
00213 ( pService->m_bGnutella1 && ( GetCount( PROTOCOL_G1 ) >= Settings.Discovery.CacheCount ) ) )
00214 {
00215
00216 if ( m_pList.Find( pService ) == NULL )
00217 {
00218
00219 theApp.Message( MSG_DEBUG, _T("Maximum discovery service count reached- %s not added"), pService->m_sAddress );
00220 delete pService;
00221 return NULL;
00222 }
00223 else
00224 {
00225
00226 return pService;
00227 }
00228 }
00229
00230
00231 if ( m_pList.Find( pService ) == NULL ) m_pList.AddTail( pService );
00232 return pService;
00233 }
00234
00235 void CDiscoveryServices::Remove(CDiscoveryService* pService, BOOL bCheck)
00236 {
00237 if ( POSITION pos = m_pList.Find( pService ) ) m_pList.RemoveAt( pos );
00238 delete pService;
00239
00240 if ( bCheck && ! EnoughServices() )
00241 {
00242 AddDefaults();
00243 }
00244 }
00245
00246
00247 BOOL CDiscoveryServices::CheckWebCacheValid(LPCTSTR pszAddress)
00248 {
00249
00250 if ( _tcsclen( pszAddress ) < 12 ) return FALSE;
00251
00252
00253 for ( POSITION pos = GetIterator() ; pos ; )
00254 {
00255 CDiscoveryService* pService = GetNext( pos );
00256
00257 if ( pService->m_nType == CDiscoveryService::dsBlocked )
00258 {
00259 if ( _tcsistr( pszAddress, pService->m_sAddress ) != NULL )
00260 return FALSE;
00261 }
00262 }
00263
00264
00265 if ( _tcsnicmp( pszAddress, _T("http://"), 7 ) == 0 )
00266 pszAddress += 7;
00267 else if ( _tcsnicmp( pszAddress, _T("https://"), 8 ) == 0 )
00268 pszAddress += 8;
00269 else
00270 return FALSE;
00271
00272
00273 pszAddress = _tcschr( pszAddress, '.' );
00274 if ( pszAddress == NULL ) return FALSE;
00275
00276
00277 pszAddress = _tcschr( pszAddress, '/' );
00278 if ( pszAddress == NULL ) return FALSE;
00279
00280
00281 return TRUE;
00282 }
00283
00284 BOOL CDiscoveryServices::CheckMinimumServices()
00285 {
00286
00287 if ( ! EnoughServices() )
00288 {
00289 AddDefaults();
00290 return FALSE;
00291 }
00292
00293 return TRUE;
00294 }
00295
00297
00298
00299
00300
00301
00302
00303 BOOL CDiscoveryServices::QueryForHosts( PROTOCOLID nProtocol )
00304 {
00305 CSingleLock pLock( &Network.m_pSection );
00306 if ( ! pLock.Lock( 250 ) ) return FALSE;
00307
00308 for ( int nLoop = 0 ; nLoop < 3 ; nLoop ++ )
00309 {
00310 if ( RequestRandomService( nProtocol ) )
00311 return TRUE;
00312 }
00313
00314 return FALSE;
00315 }
00316
00317 DWORD CDiscoveryServices::MetQueried() const
00318 {
00319 return m_tMetQueried;
00320 }
00321
00322 CDiscoveryService* CDiscoveryServices::GetByAddress(LPCTSTR pszAddress) const
00323 {
00324 for ( POSITION pos = GetIterator() ; pos ; )
00325 {
00326 CDiscoveryService* pService = GetNext( pos );
00327
00328 int nLen = pService->m_sAddress.GetLength();
00329 if ( nLen > 20 )
00330 {
00331
00332 if ( _tcsnicmp( pService->m_sAddress, pszAddress, nLen - 2 ) == 0 )
00333 return pService;
00334 }
00335 else
00336 {
00337 if ( pService->m_sAddress.CompareNoCase( pszAddress ) == 0 )
00338 return pService;
00339 }
00340 }
00341
00342 return NULL;
00343 }
00344
00345 void CDiscoveryServices::Clear()
00346 {
00347 Stop();
00348
00349 for ( POSITION pos = GetIterator() ; pos ; )
00350 {
00351 delete GetNext( pos );
00352 }
00353
00354 m_pList.RemoveAll();
00355 }
00356
00357 void CDiscoveryServices::Stop()
00358 {
00359 StopWebRequest();
00360 }
00361
00362
00364
00365
00366 BOOL CDiscoveryServices::Load()
00367 {
00368 CSingleLock pLock( &Network.m_pSection, TRUE );
00369 CFile pFile;
00370
00371 CString strFile = Settings.General.UserPath + _T("\\Data\\Discovery.dat");
00372
00373
00374 if ( ! pFile.Open( strFile, CFile::modeRead ) )
00375 {
00376 AddDefaults();
00377 Save();
00378 return FALSE;
00379 }
00380
00381 try
00382 {
00383 CArchive ar( &pFile, CArchive::load );
00384 Serialize( ar );
00385 ar.Close();
00386 }
00387 catch ( CException* pException )
00388 {
00389 pException->Delete();
00390 pFile.Close();
00391 Clear();
00392 AddDefaults();
00393 Save();
00394 return FALSE;
00395 }
00396
00397 pFile.Close();
00398
00399
00400 if ( ! EnoughServices() )
00401 {
00402 AddDefaults();
00403 Save();
00404 }
00405
00406 return TRUE;
00407 }
00408
00409 BOOL CDiscoveryServices::Save()
00410 {
00411 CSingleLock pLock( &Network.m_pSection, TRUE );
00412 CFile pFile;
00413
00414 CString strFile = Settings.General.UserPath + _T("\\Data\\Discovery.dat");
00415 if ( !pFile.Open( strFile, CFile::modeWrite|CFile::modeCreate ) )
00416 return FALSE;
00417
00418 CArchive ar( &pFile, CArchive::store );
00419 Serialize( ar );
00420 ar.Close();
00421
00422 return TRUE;
00423 }
00424
00426
00427
00428 void CDiscoveryServices::Serialize(CArchive& ar)
00429 {
00430 int nVersion = 6;
00431
00432 if ( ar.IsStoring() )
00433 {
00434 ar << nVersion;
00435
00436 ar.WriteCount( GetCount() );
00437
00438 for ( POSITION pos = GetIterator() ; pos ; )
00439 {
00440 GetNext( pos )->Serialize( ar, nVersion );
00441 }
00442 }
00443 else
00444 {
00445 Clear();
00446
00447 ar >> nVersion;
00448 if ( nVersion < 6 ) return;
00449
00450 for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
00451 {
00452 CDiscoveryService* pService = new CDiscoveryService();
00453 pService->Serialize( ar, nVersion );
00454 m_pList.AddTail( pService );
00455 }
00456 }
00457 }
00458
00460
00461
00462
00463 BOOL CDiscoveryServices::EnoughServices() const
00464 {
00465 int nWebCacheCount = 0, nServerMetCount = 0;
00466 int nG1Count = 0, nG2Count = 0;
00467
00468 for ( POSITION pos = GetIterator() ; pos ; )
00469 {
00470 CDiscoveryService* pService = GetNext( pos );
00471 if ( pService->m_nType == CDiscoveryService::dsWebCache )
00472 {
00473 nWebCacheCount++;
00474
00475 if ( pService->m_bGnutella1 ) nG1Count++;
00476 if ( pService->m_bGnutella2 ) nG2Count++;
00477 }
00478 else if ( pService->m_nType == CDiscoveryService::dsServerMet )
00479 {
00480 nServerMetCount ++;
00481 }
00482 }
00483
00484 return ( ( nWebCacheCount > 4 ) &&
00485 ( nG2Count > 2 ) &&
00486 ( nG1Count > 0 ) &&
00487 ( nServerMetCount > 0 ) );
00488 }
00489
00491
00492
00493 void CDiscoveryServices::AddDefaults()
00494 {
00495 CFile pFile;
00496 CString strFile = Settings.General.Path + _T("\\Data\\DefaultServices.dat");
00497
00498 if ( pFile.Open( strFile, CFile::modeRead ) )
00499 {
00500 theApp.Message( MSG_DEFAULT, _T("Loading default discovery service list") );
00501
00502 try
00503 {
00504 CString strService;
00505 CString strLine;
00506 CBuffer pBuffer;
00507 TCHAR cType;
00508
00509 pBuffer.EnsureBuffer( (DWORD)pFile.GetLength() );
00510 pBuffer.m_nLength = (DWORD)pFile.GetLength();
00511 pFile.Read( pBuffer.m_pBuffer, pBuffer.m_nLength );
00512 pFile.Close();
00513
00514 while ( pBuffer.ReadLine( strLine ) )
00515 {
00516 if ( strLine.GetLength() < 7 ) continue;
00517
00518 cType = strLine.GetAt( 0 );
00519 strService = strLine.Right( strLine.GetLength() - 2 );
00520
00521 switch( cType )
00522 {
00523 case '1': Add( strService, CDiscoveryService::dsWebCache, PROTOCOL_G1 );
00524 break;
00525 case '2': Add( strService, CDiscoveryService::dsWebCache, PROTOCOL_G2 );
00526 break;
00527 case 'M': Add( strService, CDiscoveryService::dsWebCache );
00528 break;
00529 case 'D': Add( strService, CDiscoveryService::dsServerMet, PROTOCOL_ED2K );
00530 break;
00531 case 'X': Add( strService, CDiscoveryService::dsBlocked );
00532 break;
00533 case '#':
00534 break;
00535 }
00536 }
00537 }
00538 catch ( CException* pException )
00539 {
00540 if (pFile.m_hFile != CFile::hFileNull) pFile.Close();
00541 pException->Delete();
00542 }
00543 }
00544
00545
00546 if ( ! EnoughServices() )
00547 {
00548 theApp.Message( MSG_ERROR, _T("Default discovery service load failed- using application defined list.") );
00549 CString strServices;
00550 strServices.LoadString( IDS_DISCOVERY_DEFAULTS );
00551
00552 for ( strServices += '\n' ; strServices.GetLength() ; )
00553 {
00554 CString strService = strServices.SpanExcluding( _T("\r\n") );
00555 strServices = strServices.Mid( strService.GetLength() + 1 );
00556
00557 if ( strService.GetLength() > 0 )
00558 {
00559 if ( _tcsistr( strService, _T("server.met") ) == NULL )
00560 Add( strService, CDiscoveryService::dsWebCache );
00561 else
00562 Add( strService, CDiscoveryService::dsServerMet, PROTOCOL_ED2K );
00563 }
00564 }
00565 }
00566 }
00567
00569
00570
00571 BOOL CDiscoveryServices::Update()
00572 {
00573 PROTOCOLID nProtocol;
00574 DWORD tNow = (DWORD)time( NULL );
00575
00576
00577 if ( tNow - m_tUpdated < Settings.Discovery.UpdatePeriod ) return FALSE;
00578
00579 if ( m_hInternet ) return FALSE;
00580 StopWebRequest();
00581
00582 CSingleLock pLock( &Network.m_pSection );
00583 if ( ! pLock.Lock( 250 ) ) return FALSE;
00584
00585
00586 if ( Network.GetStableTime() < 7200 ) return FALSE;
00587
00588
00589 if ( Neighbours.IsG2Hub() )
00590 {
00591 if ( Neighbours.IsG1Ultrapeer() )
00592 {
00593
00594 if ( m_nLastUpdateProtocol == PROTOCOL_G2 ) nProtocol = PROTOCOL_G1;
00595 else nProtocol = PROTOCOL_G2;
00596 }
00597 else
00598 nProtocol = PROTOCOL_G2;
00599 }
00600 else if ( Neighbours.IsG1Ultrapeer() )
00601 nProtocol = PROTOCOL_G1;
00602 else
00603 return FALSE;
00604
00605
00606
00607 ASSERT ( ( nProtocol == PROTOCOL_G1 ) || ( nProtocol == PROTOCOL_G2 ) );
00608
00609
00610 if ( Neighbours.GetCount( nProtocol, -1, ntNode ) < 4 ) return FALSE;
00611
00612
00613 CDiscoveryService* pService = GetRandomWebCache(nProtocol, TRUE, NULL, TRUE );
00614 if ( pService == NULL ) return FALSE;
00615
00616
00617 return RequestWebCache( pService, wcmUpdate, nProtocol );
00618
00619 }
00620
00622
00623
00624
00625
00626
00627
00628
00629 BOOL CDiscoveryServices::Execute(BOOL bSecondary)
00630 {
00631 CSingleLock pLock( &Network.m_pSection );
00632 if ( ! pLock.Lock( 250 ) ) return FALSE;
00633 DWORD tNow = time( NULL );
00634
00635 if ( bSecondary )
00636 {
00637 if ( m_hInternet ) return FALSE;
00638 if ( tNow - m_tQueried < 60 ) return FALSE;
00639 if ( tNow - m_tExecute < 10 ) return FALSE;
00640 }
00641 else
00642 {
00643 theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_BOOTSTRAP );
00644 }
00645
00646 m_tExecute = tNow;
00647 DWORD nG1Hosts = HostCache.Gnutella1.CountHosts();
00648 DWORD nG2Hosts = HostCache.Gnutella2.CountHosts();
00649 BOOL bG1Required = Settings.Gnutella1.EnableToday && ( nG1Hosts < 200 );
00650 BOOL bG2Required = Settings.Gnutella2.EnableToday && ( nG2Hosts < 800 );
00651
00652 if ( ! bSecondary )
00653 {
00654 ExecuteBootstraps( Settings.Discovery.BootstrapCount );
00655
00656 if ( ( bG2Required ) && ( nG2Hosts < 25 ) && RequestRandomService( PROTOCOL_G2 ) )
00657 return TRUE;
00658
00659 if ( ( bG1Required ) && ( nG1Hosts < 15 ) && RequestRandomService( PROTOCOL_G1 ) )
00660 return TRUE;
00661
00662
00663 if ( ( Settings.eDonkey.EnableToday ) && ( Settings.eDonkey.MetAutoQuery ) &&
00664 ( HostCache.eDonkey.CountHosts() < 3 ) && ( m_tMetQueried == 0 ) )
00665 {
00666 m_tMetQueried = tNow;
00667 if ( RequestRandomService( PROTOCOL_ED2K ) ) return TRUE;
00668 }
00669
00670 if ( ( bG1Required ) && ( m_nLastQueryProtocol == PROTOCOL_G2 ) )
00671 return RequestRandomService( PROTOCOL_G1 );
00672 else
00673 return RequestRandomService( PROTOCOL_G2 );
00674 }
00675
00676
00677
00678
00679 if ( bG1Required && bG2Required )
00680 {
00681
00682 if ( nG2Hosts < 25 )
00683 return RequestRandomService( PROTOCOL_G2 );
00684 else if ( nG1Hosts < 15 )
00685 return RequestRandomService( PROTOCOL_G1 );
00686 else if ( Neighbours.NeedMoreHubs( PROTOCOL_G2 ) || ( nG2Hosts <= nG1Hosts ) )
00687 return RequestRandomService( PROTOCOL_G2 );
00688 else
00689 return RequestRandomService( PROTOCOL_G1 );
00690 }
00691 else if ( bG2Required )
00692 {
00693 return RequestRandomService( PROTOCOL_G2 );
00694 }
00695 else if ( bG1Required )
00696 {
00697 return RequestRandomService( PROTOCOL_G1 );
00698 }
00699
00700 return FALSE;
00701 }
00702
00704
00705
00706 int CDiscoveryServices::ExecuteBootstraps(int nCount)
00707 {
00708 CPtrArray pRandom;
00709 int nSuccess;
00710
00711 if ( nCount < 1 ) return 0;
00712
00713 for ( POSITION pos = GetIterator() ; pos ; )
00714 {
00715 CDiscoveryService* pService = GetNext( pos );
00716 if ( pService->m_nType == CDiscoveryService::dsGnutella )
00717 pRandom.Add( pService );
00718 }
00719
00720 srand( GetTickCount() );
00721
00722 for ( nSuccess = 0 ; nCount > 0 && pRandom.GetSize() > 0 ; )
00723 {
00724 int nRandom = rand() % pRandom.GetSize();
00725 CDiscoveryService* pService = (CDiscoveryService*)pRandom.GetAt( nRandom );
00726 pRandom.RemoveAt( nRandom );
00727
00728 if ( pService->ResolveGnutella() )
00729 {
00730 nSuccess++;
00731 nCount--;
00732 }
00733 }
00734
00735 return nSuccess;
00736 }
00737
00738 void CDiscoveryServices::OnGnutellaAdded(IN_ADDR* pAddress, int nCount)
00739 {
00740
00741 }
00742
00743 void CDiscoveryServices::OnGnutellaFailed(IN_ADDR* pAddress)
00744 {
00745
00746 }
00747
00748
00750
00751
00752
00753
00754
00755 BOOL CDiscoveryServices::RequestRandomService(PROTOCOLID nProtocol)
00756 {
00757
00758
00759
00760 CDiscoveryService* pService = GetRandomService( nProtocol );
00761
00762 if ( pService )
00763 {
00764 if ( pService->m_nType == CDiscoveryService::dsServerMet )
00765 {
00766 if ( RequestWebCache( pService, wcmServerMet, nProtocol ) ) return TRUE;
00767 }
00768 else
00769 {
00770 if ( RequestWebCache( pService, wcmHosts, nProtocol ) ) return TRUE;
00771 }
00772 }
00773 return FALSE;
00774 }
00775
00777
00778
00779
00780
00781
00782 CDiscoveryService* CDiscoveryServices::GetRandomService(PROTOCOLID nProtocol)
00783 {
00784 CPtrArray pServices;
00785 DWORD tNow = time( NULL );
00786
00787
00788 for ( POSITION pos = GetIterator() ; pos ; )
00789 {
00790 CDiscoveryService* pService = GetNext( pos );
00791
00792
00793 if ( tNow - pService->m_tAccessed > pService->m_nAccessPeriod )
00794 {
00795
00796 switch ( nProtocol )
00797 {
00798 case PROTOCOL_G1:
00799 if ( ( pService->m_nType == CDiscoveryService::dsWebCache ) && ( pService->m_bGnutella1 ) )
00800 pServices.Add( pService );
00801 break;
00802 case PROTOCOL_G2:
00803 if ( ( pService->m_nType == CDiscoveryService::dsWebCache ) && ( pService->m_bGnutella2 ) )
00804 pServices.Add( pService );
00805 break;
00806 case PROTOCOL_ED2K:
00807 if ( pService->m_nType == CDiscoveryService::dsServerMet )
00808 pServices.Add( pService );
00809 break;
00810 default:
00811 break;
00812 }
00813 }
00814 }
00815
00816
00817 if ( pServices.GetSize() > 0 )
00818 {
00819
00820 srand( GetTickCount() );
00821 return (CDiscoveryService*)pServices.GetAt( rand() % pServices.GetSize() );
00822 }
00823 else
00824 {
00825
00826 return NULL;
00827 }
00828 }
00829
00831
00832
00833 CDiscoveryService* CDiscoveryServices::GetRandomWebCache(PROTOCOLID nProtocol, BOOL bWorkingOnly, CDiscoveryService* pExclude, BOOL bForUpdate)
00834 {
00835 CPtrArray pWebCaches;
00836 DWORD tNow = time( NULL );
00837
00838 for ( POSITION pos = GetIterator() ; pos ; )
00839 {
00840 CDiscoveryService* pService = GetNext( pos );
00841
00842 if ( pService->m_nType == CDiscoveryService::dsWebCache && pService != pExclude )
00843 {
00844 if ( ! bWorkingOnly || ( pService->m_nAccesses > 0 && pService->m_nFailures == 0 && pService->m_nHosts > 0 ) )
00845 {
00846 if ( tNow - pService->m_tAccessed > pService->m_nAccessPeriod )
00847 {
00848 if ( ! bForUpdate || tNow - pService->m_tUpdated > pService->m_nUpdatePeriod )
00849 {
00850 switch ( nProtocol )
00851 {
00852 case PROTOCOL_G1:
00853 if ( ( pService->m_nType == CDiscoveryService::dsWebCache ) && ( pService->m_bGnutella1 ) )
00854 pWebCaches.Add( pService );
00855 break;
00856 case PROTOCOL_G2:
00857 if ( ( pService->m_nType == CDiscoveryService::dsWebCache ) && ( pService->m_bGnutella2 ) )
00858 pWebCaches.Add( pService );
00859 break;
00860 default:
00861 theApp.Message( MSG_ERROR, _T("CDiscoveryServices::GetRandomWebCache() was passed an invalid protocol") );
00862 ASSERT( FALSE );
00863 return NULL;
00864 }
00865 }
00866 }
00867 }
00868 }
00869 }
00870
00871
00872 if ( pWebCaches.GetSize() > 0 )
00873 {
00874
00875 srand( GetTickCount() );
00876 return (CDiscoveryService*)pWebCaches.GetAt( rand() % pWebCaches.GetSize() );
00877 }
00878 else
00879 {
00880
00881 return NULL;
00882 }
00883 }
00884
00886
00887
00888 BOOL CDiscoveryServices::RequestWebCache(CDiscoveryService* pService, int nMode, PROTOCOLID nProtocol)
00889 {
00890 DWORD tNow = (DWORD)time( NULL );
00891 StopWebRequest();
00892
00893 if ( pService != NULL )
00894 {
00895 if ( time( NULL ) - pService->m_tAccessed < pService->m_nAccessPeriod ) return FALSE;
00896 }
00897
00898 switch ( nProtocol )
00899 {
00900 case PROTOCOL_G1:
00901 theApp.Message( MSG_DEBUG, _T("CDiscoveryServices::RequestWebCache() seeking gnutella hosts") );
00902 break;
00903 case PROTOCOL_G2:
00904 theApp.Message( MSG_DEBUG, _T("CDiscoveryServices::RequestWebCache() seeking G2 hosts") );
00905 break;
00906 case PROTOCOL_ED2K:
00907 theApp.Message( MSG_DEBUG, _T("CDiscoveryServices::RequestWebCache() seeking ed2k hosts") );
00908 break;
00909 default:
00910 theApp.Message( MSG_ERROR, _T("ERROR: CDiscoveryServices::RequestWebCache() was passed an invalid protocol") );
00911 return FALSE;
00912 }
00913
00914 m_pWebCache = pService;
00915 m_nWebCache = nMode;
00916 m_hRequest = NULL;
00917
00918 switch ( nMode )
00919 {
00920 case wcmHosts:
00921 case wcmCaches:
00922 if ( m_pWebCache != NULL )
00923 {
00924 theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_QUERY, (LPCTSTR)m_pWebCache->m_sAddress );
00925
00926 m_tQueried = tNow;
00927 m_nLastQueryProtocol = nProtocol;
00928 }
00929 break;
00930
00931 case wcmUpdate:
00932 m_pSubmit = GetRandomWebCache( nProtocol, TRUE, m_pWebCache, FALSE );
00933 if ( m_pWebCache != NULL )
00934 {
00935 theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_UPDATING, (LPCTSTR)m_pWebCache->m_sAddress );
00936
00937 m_tUpdated = tNow;
00938 m_nLastUpdateProtocol = nProtocol;
00939 }
00940 break;
00941
00942 case wcmSubmit:
00943 m_pSubmit = m_pWebCache;
00944 m_pWebCache = GetRandomWebCache( nProtocol, FALSE, m_pSubmit, TRUE );
00945 if ( m_pWebCache != NULL )
00946 {
00947 theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_SUBMIT, (LPCTSTR)m_pWebCache->m_sAddress );
00948
00949 m_tQueried = tNow;
00950 m_nLastQueryProtocol = nProtocol;
00951 }
00952 break;
00953
00954 case wcmServerMet:
00955 if ( nProtocol != PROTOCOL_ED2K )
00956 {
00957 theApp.Message( MSG_ERROR, _T("ERROR: CDiscoveryServices::RequestWebCache() was passed wcmServerMet with non-ed2k protocol") );
00958 ASSERT ( FALSE );
00959 return FALSE;
00960 }
00961 else if ( m_pWebCache != NULL )
00962 {
00963 theApp.Message( MSG_SYSTEM, IDS_DISCOVERY_QUERY, (LPCTSTR)m_pWebCache->m_sAddress );
00964
00965 m_tQueried = tNow;
00966 m_nLastQueryProtocol = nProtocol;
00967 }
00968 break;
00969 default:
00970 theApp.Message( MSG_ERROR, _T("ERROR: CDiscoveryServices::RequestWebCache() was passed an invalid mode") );
00971 ASSERT ( FALSE );
00972 return FALSE;
00973 }
00974
00975 if ( m_pWebCache == NULL ) return FALSE;
00976
00977 CString strAgent = Settings.SmartAgent();
00978
00979 m_hInternet = InternetOpen( strAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
00980 if ( ! m_hInternet ) return FALSE;
00981
00982 CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_NORMAL );
00983 m_hThread = pThread->m_hThread;
00984
00985 return TRUE;
00986 }
00987
00988 void CDiscoveryServices::StopWebRequest()
00989 {
00990 if ( m_hInternet ) InternetCloseHandle( m_hInternet );
00991 m_hInternet = NULL;
00992
00993 if ( m_hThread == NULL ) return;
00994
00995 int nAttempt = 10;
00996 for ( ; nAttempt > 0 ; nAttempt-- )
00997 {
00998 DWORD nCode;
00999
01000 if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
01001 if ( nCode != STILL_ACTIVE ) break;
01002 Sleep( 100 );
01003 }
01004
01005 if ( nAttempt == 0 )
01006 {
01007 TerminateThread( m_hThread, 0 );
01008 theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CDiscoveryServices thread.") );
01009 Sleep( 100 );
01010 }
01011
01012 m_hThread = NULL;
01013 }
01014
01016
01017
01018 UINT CDiscoveryServices::ThreadStart(LPVOID pParam)
01019 {
01020 CDiscoveryServices* pClass = (CDiscoveryServices*)pParam;
01021 pClass->OnRun();
01022 return 0;
01023 }
01024
01026
01027
01028 void CDiscoveryServices::OnRun()
01029 {
01030 BOOL bSuccess = TRUE;
01031
01032 if ( m_nWebCache == wcmServerMet )
01033 {
01034 bSuccess = RunServerMet();
01035 }
01036 else if ( m_nWebCache == wcmHosts )
01037 {
01038 bSuccess = RunWebCacheGet( FALSE );
01039
01040 if ( bSuccess && m_hInternet )
01041 {
01042 CSingleLock pLock( &Network.m_pSection, TRUE );
01043
01044 if ( m_bFirstTime || ( GetCount( CDiscoveryService::dsWebCache ) < (int)Settings.Discovery.Lowpoint ) )
01045 {
01046 m_bFirstTime = FALSE;
01047 pLock.Unlock();
01048 bSuccess = RunWebCacheGet( TRUE );
01049 }
01050 }
01051 }
01052 else if ( m_nWebCache == wcmCaches )
01053 {
01054 bSuccess = RunWebCacheGet( TRUE );
01055 }
01056 else if ( m_nWebCache == wcmUpdate )
01057 {
01058 bSuccess = RunWebCacheUpdate();
01059 }
01060 else if ( m_nWebCache == wcmSubmit )
01061 {
01062 bSuccess = RunWebCacheUpdate();
01063 }
01064
01065 if ( m_hInternet && ! bSuccess )
01066 {
01067 if ( m_nWebCache == wcmUpdate )
01068 {
01069 m_tUpdated = 0;
01070 m_nLastUpdateProtocol = PROTOCOL_NULL;
01071 }
01072 else
01073 {
01074 m_tQueried = 0;
01075 m_nLastQueryProtocol = PROTOCOL_NULL;
01076 }
01077
01078 CSingleLock pLock( &Network.m_pSection );
01079 if ( pLock.Lock( 250 ) && Check( m_pWebCache ) ) m_pWebCache->OnFailure();
01080 }
01081
01082 if ( m_hInternet != NULL )
01083 {
01084 if ( m_hRequest != NULL ) InternetCloseHandle( m_hRequest );
01085 InternetCloseHandle( m_hInternet );
01086 m_hInternet = NULL;
01087 m_hRequest = NULL;
01088 }
01089 }
01090
01092
01093
01094 BOOL CDiscoveryServices::RunWebCacheGet(BOOL bCaches)
01095 {
01096 CSingleLock pLock( &Network.m_pSection, TRUE );
01097 CString strURL, strOutput;
01098
01099 if ( ! Check( m_pWebCache ) ) return FALSE;
01100 m_pWebCache->OnAccess();
01101
01102 if ( bCaches )
01103 strURL = m_pWebCache->m_sAddress + _T("?get=1&urlfile=1");
01104 else
01105 strURL = m_pWebCache->m_sAddress + _T("?get=1&hostfile=1");
01106
01107 if ( m_nLastQueryProtocol == PROTOCOL_G2 ) strURL += _T("&net=gnutella2");
01108
01109 pLock.Unlock();
01110
01111 if ( ! SendWebCacheRequest( strURL, strOutput ) ) return FALSE;
01112 pLock.Lock();
01113
01114 if ( ! Check( m_pWebCache ) ) return FALSE;
01115
01116 BOOL bSuccess = FALSE;
01117 int nIP[4], nIPs = 0;
01118
01119 if ( _tcsistr( strOutput, _T("<html>") ) != NULL )
01120 {
01121
01122 return FALSE;
01123 }
01124 else if ( _tcsistr( strOutput, _T("<font>") ) != NULL )
01125 {
01126
01127 return FALSE;
01128 }
01129
01130
01131 for ( strOutput += '\n' ; strOutput.GetLength() ; )
01132 {
01133 CString strLine = strOutput.SpanExcluding( _T("\r\n") );
01134 strOutput = strOutput.Mid( strLine.GetLength() + 1 );
01135
01136 strLine.TrimLeft();
01137 strLine.TrimRight();
01138 if ( strLine.IsEmpty() ) continue;
01139
01140 theApp.Message( MSG_DEBUG, _T("GWebCache(get): %s"), (LPCTSTR)strLine );
01141
01142 if ( _tcsnicmp( strLine, _T("h|"), 2 ) == 0 )
01143 {
01144
01145
01146
01147 strLine = strLine.Mid( 2 );
01148 int nBreak = strLine.Find( '|' );
01149 DWORD tSeen = 0;
01150
01151 if ( nBreak > 0 )
01152 {
01153 int nSeconds = 0;
01154 _stscanf( strLine.Mid( nBreak + 1 ), _T("%i"), &nSeconds );
01155 nSeconds = max( 0, min( 18000, nSeconds ) );
01156 strLine = strLine.Left( nBreak );
01157 tSeen = time( NULL ) - nSeconds;
01158 }
01159
01160 if ( m_nLastQueryProtocol == PROTOCOL_G2 )
01161 HostCache.Gnutella2.Add( strLine, tSeen );
01162 else
01163 HostCache.Gnutella1.Add( strLine, tSeen );
01164
01165 m_pWebCache->OnHostAdd();
01166 bSuccess = TRUE;
01167 nIPs ++;
01168 }
01169 else if ( _tcsnicmp( strLine, _T("u|"), 2 ) == 0 )
01170 {
01171
01172
01173 Add( strLine.Mid( 2 ).SpanExcluding( _T("|") ), CDiscoveryService::dsWebCache, m_nLastQueryProtocol );
01174
01175 m_bFirstTime = FALSE;
01176 bSuccess = TRUE;
01177 }
01178 else if ( _tcsnicmp( strLine, _T("i|"), 2 ) == 0 )
01179 {
01180
01181
01182
01183
01184
01185 if ( _tcsnicmp( strLine, _T("i|access|period|"), 16 ) == 0 )
01186 {
01187 _stscanf( (LPCTSTR)strLine + 16, _T("%u"), &m_pWebCache->m_nAccessPeriod );
01188 }
01189 else if ( strLine == _T("i|force|remove") || _tcsnicmp( strLine, _T("i|update|warning|bad url"), 24 ) == 0 )
01190 {
01191 m_pWebCache->Remove();
01192 return FALSE;
01193 }
01194
01195 if ( _tcsistr( strLine, _T("ERROR: Network not supported") ) != NULL )
01196 {
01197
01198 if ( m_nLastQueryProtocol == PROTOCOL_G2 )
01199 {
01200 m_pWebCache->m_bGnutella1 = TRUE;
01201 m_pWebCache->m_bGnutella2 = FALSE;
01202 }
01203 else
01204 {
01205 m_pWebCache->m_bGnutella1 = FALSE;
01206 m_pWebCache->m_bGnutella2 = TRUE;
01207 }
01208
01209 return FALSE;
01210 }
01211 }
01212 else if ( _tcsistr( strLine, _T("ERROR: Network not supported") ) != NULL )
01213 {
01214
01215 if ( m_nLastQueryProtocol == PROTOCOL_G2 )
01216 {
01217 m_pWebCache->m_bGnutella1 = TRUE;
01218 m_pWebCache->m_bGnutella2 = FALSE;
01219 }
01220 else
01221 {
01222 m_pWebCache->m_bGnutella1 = FALSE;
01223 m_pWebCache->m_bGnutella2 = TRUE;
01224 }
01225
01226 return FALSE;
01227 }
01228 else if ( _tcsistr( strLine, _T("ERROR") ) != NULL )
01229 {
01230
01231 return FALSE;
01232 }
01233 else if ( _stscanf( strLine, _T("%i.%i.%i.%i"), &nIP[0], &nIP[1], &nIP[2], &nIP[3] ) == 4 )
01234 {
01235
01236 HostCache.Gnutella1.Add( strLine );
01237 m_pWebCache->OnHostAdd();
01238 m_pWebCache->m_bGnutella2 = FALSE;
01239 m_pWebCache->m_bGnutella1 = TRUE;
01240 bSuccess = TRUE;
01241 }
01242 else
01243 {
01244
01245 Add( strLine.SpanExcluding( _T(" ") ), CDiscoveryService::dsWebCache, PROTOCOL_G1 );
01246 m_pWebCache->m_bGnutella2 = FALSE;
01247 m_pWebCache->m_bGnutella1 = TRUE;
01248 m_bFirstTime = FALSE;
01249 }
01250 }
01251
01252 if ( bSuccess )
01253 {
01254 m_pWebCache->OnSuccess();
01255 if ( HostCache.Gnutella2.GetNewest() != NULL && nIPs > 0 ) m_tQueried = time( NULL );
01256 return TRUE;
01257 }
01258
01259 return FALSE;
01260 }
01261
01263
01264
01265 BOOL CDiscoveryServices::RunWebCacheUpdate()
01266 {
01267 CSingleLock pLock( &Network.m_pSection, TRUE );
01268 CString strURL, strOutput;
01269
01270 if ( ! Check( m_pWebCache, CDiscoveryService::dsWebCache ) ) return FALSE;
01271 m_pWebCache->OnAccess();
01272
01273 if ( m_nWebCache == wcmUpdate )
01274 {
01275 if ( ! Network.IsListening() ) return TRUE;
01276
01277 strURL.Format( _T("%s?update=1&ip=%s:%hu&x.leaves=%i"),
01278 (LPCTSTR)m_pWebCache->m_sAddress,
01279 (LPCTSTR)CString( inet_ntoa( Network.m_pHost.sin_addr ) ),
01280 htons( Network.m_pHost.sin_port ),
01281 Neighbours.GetCount( -1, -1, ntLeaf ) );
01282 }
01283
01284 if ( m_pSubmit != NULL && Check( m_pSubmit, CDiscoveryService::dsWebCache ) &&
01285 m_pWebCache->m_bGnutella2 == m_pSubmit->m_bGnutella2 )
01286 {
01287 if ( strURL.IsEmpty() )
01288 {
01289 strURL.Format( _T("%s?url="), (LPCTSTR)m_pWebCache->m_sAddress );
01290 }
01291 else
01292 {
01293 strURL += _T("&url=");
01294 }
01295
01296 CString strSubmit( m_pSubmit->m_sAddress );
01297
01298 for ( int nSubmit = 0 ; nSubmit < strSubmit.GetLength() ; nSubmit ++ )
01299 {
01300 if ( (WORD)strSubmit.GetAt( nSubmit ) > 127 )
01301 {
01302 strSubmit = strSubmit.Left( nSubmit );
01303 break;
01304 }
01305 }
01306
01307 strURL += CConnection::URLEncode( strSubmit );
01308 }
01309
01310 if ( m_nLastUpdateProtocol == PROTOCOL_G2 ) strURL += _T("&net=gnutella2");
01311
01312 pLock.Unlock();
01313
01314 if ( strURL.IsEmpty() ) return FALSE;
01315
01316 if ( ! SendWebCacheRequest( strURL, strOutput ) ) return FALSE;
01317
01318 pLock.Lock();
01319 if ( ! Check( m_pWebCache, CDiscoveryService::dsWebCache ) ) return FALSE;
01320
01321 for ( strOutput += '\n' ; strOutput.GetLength() ; )
01322 {
01323 CString strLine = strOutput.SpanExcluding( _T("\r\n") );
01324 strOutput = strOutput.Mid( strLine.GetLength() + 1 );
01325
01326 strLine.TrimLeft();
01327 strLine.TrimRight();
01328
01329 if ( strLine.IsEmpty() ) continue;
01330
01331 theApp.Message( MSG_DEBUG, _T("GWebCache(update): %s"), (LPCTSTR)strLine );
01332
01333 if ( _tcsstr( strLine, _T("OK") ) )
01334 {
01335 m_pWebCache->m_tUpdated = (DWORD)time( NULL );
01336 m_pWebCache->m_nUpdates++;
01337 m_pWebCache->OnSuccess();
01338 return TRUE;
01339 }
01340 else if ( _tcsstr( strLine, _T("ERROR") ) )
01341 {
01342 return FALSE;
01343 }
01344 else if ( _tcsnicmp( strLine, _T("i|access|period|"), 16 ) == 0 )
01345 {
01346 _stscanf( (LPCTSTR)strLine + 16, _T("%u"), &m_pWebCache->m_nAccessPeriod );
01347 }
01348 else if ( _tcsnicmp( strLine, _T("i|update|period|"), 16 ) == 0 )
01349 {
01350 _stscanf( (LPCTSTR)strLine + 16, _T("%u"), &m_pWebCache->m_nUpdatePeriod );
01351 }
01352 else if ( strLine == _T("i|force|remove") )
01353 {
01354 m_pWebCache->Remove();
01355 break;
01356 }
01357 }
01358
01359 return FALSE;
01360 }
01361
01363
01364
01365 BOOL CDiscoveryServices::SendWebCacheRequest(CString strURL, CString& strOutput)
01366 {
01367 strOutput.Empty();
01368
01369 strURL += _T("&client=RAZA&version=");
01370 strURL += theApp.m_sVersion;
01371
01372 theApp.Message( MSG_DEBUG, _T("DiscoveryService URL: %s"), (LPCTSTR)strURL );
01373
01374 if ( m_hRequest ) InternetCloseHandle( m_hRequest );
01375
01376 m_hRequest = InternetOpenUrl( m_hInternet, strURL, _T("Connection: close"), -1,
01377 INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_NO_COOKIES, 0 );
01378 if ( m_hRequest == NULL ) return FALSE;
01379
01380 DWORD nStatusCode = 0, nStatusLen = 32;
01381 TCHAR szStatusCode[32];
01382
01383 if ( ! HttpQueryInfo( m_hRequest, HTTP_QUERY_STATUS_CODE, szStatusCode,
01384 &nStatusLen, NULL ) ) return FALSE;
01385
01386 _stscanf( szStatusCode, _T("%u"), &nStatusCode );
01387 if ( nStatusCode < 200 || nStatusCode > 299 ) return FALSE;
01388
01389 DWORD nRemaining, nResponse = 0;
01390 LPBYTE pResponse = NULL;
01391
01392 while ( InternetQueryDataAvailable( m_hRequest, &nRemaining, 0, 0 ) && nRemaining > 0 )
01393 {
01394 pResponse = (LPBYTE)realloc( pResponse, nResponse + nRemaining );
01395 InternetReadFile( m_hRequest, pResponse + nResponse, nRemaining, &nRemaining );
01396 nResponse += nRemaining;
01397 }
01398
01399 if ( nRemaining )
01400 {
01401 free( pResponse );
01402 return FALSE;
01403 }
01404
01405 LPTSTR pszResponse = strOutput.GetBuffer( nResponse );
01406 for ( nStatusCode = 0 ; nStatusCode < nResponse ; nStatusCode++ )
01407 pszResponse[ nStatusCode ] = (TCHAR)pResponse[ nStatusCode ];
01408 strOutput.ReleaseBuffer( nResponse );
01409
01410 free( pResponse );
01411
01412 return TRUE;
01413 }
01414
01416
01417
01418 BOOL CDiscoveryServices::RunServerMet()
01419 {
01420 CSingleLock pLock( &Network.m_pSection, TRUE );
01421 CString strURL;
01422
01423 if ( ! Check( m_pWebCache, CDiscoveryService::dsServerMet ) ) return FALSE;
01424
01425 m_pWebCache->OnAccess();
01426 strURL = m_pWebCache->m_sAddress;
01427
01428 pLock.Unlock();
01429
01430 if ( m_hRequest != NULL ) InternetCloseHandle( m_hRequest );
01431
01432 m_hRequest = InternetOpenUrl( m_hInternet, strURL, NULL, 0,
01433 INTERNET_FLAG_RELOAD|INTERNET_FLAG_DONT_CACHE, 0 );
01434
01435 if ( m_hRequest == NULL ) return FALSE;
01436
01437 DWORD nRemaining = 0;
01438 BYTE pBuffer[1024];
01439 CMemFile pFile;
01440
01441 while ( InternetQueryDataAvailable( m_hRequest, &nRemaining, 0, 0 ) && nRemaining > 0 )
01442 {
01443 while ( nRemaining > 0 )
01444 {
01445 DWORD nBuffer = min( nRemaining, DWORD(1024) );
01446 InternetReadFile( m_hRequest, pBuffer, nBuffer, &nBuffer );
01447 pFile.Write( pBuffer, nBuffer );
01448 nRemaining -= nBuffer;
01449 }
01450 }
01451
01452 pFile.Seek( 0, CFile::begin );
01453
01454 pLock.Lock();
01455
01456 if ( ! Check( m_pWebCache, CDiscoveryService::dsServerMet ) ) return FALSE;
01457
01458 int nCount = HostCache.eDonkey.ImportMET( &pFile );
01459
01460 if ( ! nCount ) return FALSE;
01461
01462 HostCache.Save();
01463 m_pWebCache->OnHostAdd( nCount );
01464 m_pWebCache->OnSuccess();
01465
01466 return TRUE;
01467 }
01468
01469
01471
01472
01473 CDiscoveryService::CDiscoveryService(int nType, LPCTSTR pszAddress)
01474 {
01475 m_nType = nType;
01476 m_bGnutella2 = FALSE;
01477 m_bGnutella1 = FALSE;
01478 m_tCreated = (DWORD)time( NULL );
01479 m_tAccessed = 0;
01480 m_nAccesses = 0;
01481 m_tUpdated = 0;
01482 m_nUpdates = 0;
01483 m_nFailures = 0;
01484 m_nHosts = 0;
01485 m_nAccessPeriod = max( Settings.Discovery.UpdatePeriod, DWORD(1800) );
01486 m_nUpdatePeriod = Settings.Discovery.DefaultUpdate;
01487
01488 if ( pszAddress != NULL ) m_sAddress = pszAddress;
01489 }
01490
01491 CDiscoveryService::~CDiscoveryService()
01492 {
01493 }
01494
01496
01497
01498 void CDiscoveryService::Remove(BOOL bCheck)
01499 {
01500 DiscoveryServices.Remove( this, bCheck );
01501 }
01502
01504
01505
01506 void CDiscoveryService::Serialize(CArchive& ar, int nVersion)
01507 {
01508
01509 if ( ar.IsStoring() )
01510 {
01511 ar << m_nType;
01512 ar << m_sAddress;
01513 ar << m_bGnutella2;
01514 ar << m_bGnutella1;
01515 ar << m_tCreated;
01516 ar << m_tAccessed;
01517 ar << m_nAccesses;
01518 ar << m_tUpdated;
01519 ar << m_nUpdates;
01520 ar << m_nFailures;
01521 ar << m_nHosts;
01522 ar << m_nAccessPeriod;
01523 ar << m_nUpdatePeriod;
01524 }
01525 else
01526 {
01527 ar >> m_nType;
01528 ar >> m_sAddress;
01529 ar >> m_bGnutella2;
01530 ar >> m_bGnutella1;
01531 ar >> m_tCreated;
01532 ar >> m_tAccessed;
01533 ar >> m_nAccesses;
01534 ar >> m_tUpdated;
01535 ar >> m_nUpdates;
01536 ar >> m_nFailures;
01537 ar >> m_nHosts;
01538 ar >> m_nAccessPeriod;
01539 ar >> m_nUpdatePeriod;
01540 }
01541 }
01542
01544
01545
01546
01547 BOOL CDiscoveryService::Execute(int nMode)
01548 {
01549 CSingleLock pLock( &Network.m_pSection );
01550 if ( ! pLock.Lock( 250 ) ) return FALSE;
01551
01552 if ( m_nType == dsGnutella )
01553 {
01554 return ResolveGnutella();
01555 }
01556 else if ( m_nType == dsWebCache )
01557 {
01558 return DiscoveryServices.RequestWebCache( this, nMode, m_bGnutella2 ? PROTOCOL_G2 : PROTOCOL_G1 );
01559 }
01560 else if ( m_nType == dsServerMet )
01561 {
01562 return DiscoveryServices.RequestWebCache( this, CDiscoveryServices::wcmServerMet, PROTOCOL_ED2K );
01563 }
01564
01565 return FALSE;
01566 }
01567
01569
01570
01571 BOOL CDiscoveryService::ResolveGnutella()
01572 {
01573 CString strHost = m_sAddress;
01574 int nPort = GNUTELLA_DEFAULT_PORT;
01575 int nPos = strHost.Find( ':' );
01576
01577 if ( nPos >= 0 && _stscanf( strHost.Mid( nPos + 1 ), _T("%i"), &nPort ) == 1 )
01578 strHost = strHost.Left( nPos );
01579
01580 if ( ! Network.Connect( FALSE ) ) return FALSE;
01581
01582 if ( Network.AsyncResolve( strHost, (WORD)nPort, PROTOCOL_G1, 0 ) )
01583 {
01584 OnSuccess();
01585 return TRUE;
01586 }
01587
01588 OnFailure();
01589
01590 return FALSE;
01591 }
01592
01594
01595
01596 void CDiscoveryService::OnAccess()
01597 {
01598 m_tAccessed = (DWORD)time( NULL );
01599 m_nAccesses ++;
01600 }
01601
01602 void CDiscoveryService::OnHostAdd(int nCount)
01603 {
01604 m_nHosts += nCount;
01605 m_nFailures = 0;
01606 }
01607
01608 void CDiscoveryService::OnSuccess()
01609 {
01610 m_nFailures = 0;
01611
01612 if ( m_nType == dsWebCache || m_nType == dsServerMet )
01613 {
01614 theApp.Message( MSG_DEFAULT, IDS_DISCOVERY_WEB_SUCCESS,
01615 (LPCTSTR)m_sAddress );
01616 }
01617 }
01618
01619 void CDiscoveryService::OnFailure()
01620 {
01621 m_nFailures++;
01622
01623 theApp.Message( MSG_ERROR, IDS_DISCOVERY_FAILED,
01624 (LPCTSTR)m_sAddress, m_nFailures );
01625
01626 if ( m_nFailures >= Settings.Discovery.FailureLimit )
01627 {
01628 theApp.Message( MSG_ERROR, IDS_DISCOVERY_FAIL_REMOVE,
01629 (LPCTSTR)m_sAddress, m_nFailures );
01630 Remove();
01631 }
01632 }
01633