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 "HostCache.h"
00031 #include "Neighbours.h"
00032 #include "Security.h"
00033 #include "VendorCache.h"
00034 #include "G1Packet.h"
00035 #include "EDPacket.h"
00036 #include "Buffer.h"
00037
00038 #ifdef _DEBUG
00039 #undef THIS_FILE
00040 static char THIS_FILE[]=__FILE__;
00041 #define new DEBUG_NEW
00042 #endif
00043
00044 CHostCache HostCache;
00045
00046
00048
00049
00050 CHostCache::CHostCache() :
00051 Gnutella1( PROTOCOL_G1 ), Gnutella2( PROTOCOL_G2 ),
00052 eDonkey( PROTOCOL_ED2K )
00053 {
00054 m_pList.AddTail( &Gnutella1 );
00055 m_pList.AddTail( &Gnutella2 );
00056 m_pList.AddTail( &eDonkey );
00057 }
00058
00060
00061
00062 void CHostCache::Clear()
00063 {
00064 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00065 {
00066 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00067 pCache->Clear();
00068 }
00069 }
00070
00071 BOOL CHostCache::Load()
00072 {
00073 CSingleLock pLock( &Network.m_pSection, TRUE );
00074 CString strFile;
00075 CFile pFile;
00076
00077 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00078 {
00079 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00080 pCache->Clear();
00081 }
00082
00083 strFile.Format( _T("%s\\Data\\HostCache.dat"), (LPCTSTR)Settings.General.UserPath );
00084 if ( ! pFile.Open( strFile, CFile::modeRead ) ) return FALSE;
00085
00086 try
00087 {
00088 CArchive ar( &pFile, CArchive::load );
00089 Serialize( ar );
00090 ar.Close();
00091 }
00092 catch ( CException* pException )
00093 {
00094 pException->Delete();
00095 }
00096
00097 if ( eDonkey.GetNewest() == NULL ) eDonkey.Import( _T("C:\\Program Files\\eMule\\server.met") );
00098
00099 return TRUE;
00100 }
00101
00102 BOOL CHostCache::Save()
00103 {
00104 CSingleLock pLock( &Network.m_pSection, TRUE );
00105 CString strFile;
00106 CFile pFile;
00107
00108 strFile.Format( _T("%s\\Data\\HostCache.dat"), (LPCTSTR)Settings.General.UserPath );
00109
00110 if ( ! pFile.Open( strFile, CFile::modeWrite|CFile::modeCreate ) ) return FALSE;
00111
00112 CArchive ar( &pFile, CArchive::store );
00113 Serialize( ar );
00114 ar.Close();
00115
00116 return TRUE;
00117 }
00118
00119 void CHostCache::Serialize(CArchive& ar)
00120 {
00121 int nVersion = 10;
00122
00123 if ( ar.IsStoring() )
00124 {
00125 ar << nVersion;
00126 ar.WriteCount( m_pList.GetCount() );
00127
00128 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00129 {
00130 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00131 ar << pCache->m_nProtocol;
00132 pCache->Serialize( ar, nVersion );
00133 }
00134 }
00135 else
00136 {
00137 ar >> nVersion;
00138 if ( nVersion < 6 ) return;
00139
00140 for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
00141 {
00142 PROTOCOLID nProtocol;
00143 ar >> nProtocol;
00144
00145 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00146 {
00147 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00148 if ( pCache->m_nProtocol == nProtocol )
00149 {
00150 pCache->Serialize( ar, nVersion );
00151 break;
00152 }
00153 }
00154 }
00155 }
00156 }
00157
00159
00160
00161 CHostCacheHost* CHostCache::Find(IN_ADDR* pAddress) const
00162 {
00163 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00164 {
00165 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00166 if ( CHostCacheHost* pHost = pCache->Find( pAddress ) ) return pHost;
00167 }
00168 return NULL;
00169 }
00170
00171 BOOL CHostCache::Check(CHostCacheHost* pHost) const
00172 {
00173 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00174 {
00175 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00176 if ( pCache->Check( pHost ) ) return TRUE;
00177 }
00178 return FALSE;
00179 }
00180
00181 void CHostCache::Remove(CHostCacheHost* pHost)
00182 {
00183 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00184 {
00185 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00186 pCache->Remove( pHost );
00187 }
00188 }
00189
00190 void CHostCache::OnFailure(IN_ADDR* pAddress, WORD nPort)
00191 {
00192 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00193 {
00194 CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
00195 pCache->OnFailure( pAddress, nPort );
00196 }
00197 }
00198
00199
00201
00202
00203 CHostCacheList::CHostCacheList(PROTOCOLID nProtocol)
00204 {
00205 m_nProtocol = nProtocol;
00206 m_nBuffer = 0;
00207 m_pBuffer = NULL;
00208 m_nCookie = 0;
00209 }
00210
00211 CHostCacheList::~CHostCacheList()
00212 {
00213 Clear();
00214 if ( m_pBuffer ) delete [] m_pBuffer;
00215 }
00216
00218
00219
00220 void CHostCacheList::Clear()
00221 {
00222 if ( m_pBuffer == NULL )
00223 {
00224 m_nBuffer = Settings.Gnutella.HostCacheSize;
00225 m_pBuffer = new CHostCacheHost[ m_nBuffer ];
00226 }
00227
00228 CHostCacheHost* pHost = m_pBuffer;
00229
00230 for ( DWORD nPos = m_nBuffer ; nPos ; nPos--, pHost++ )
00231 {
00232 pHost->m_pNextHash = ( nPos == 1 ) ? NULL : pHost + 1;
00233 pHost->m_nProtocol = m_nProtocol;
00234 }
00235
00236 ZeroMemory( m_pHash, sizeof(CHostCacheHost*) * 256 );
00237
00238 m_pFree = m_pBuffer;
00239 m_pNewest = NULL;
00240 m_pOldest = NULL;
00241 m_nHosts = 0;
00242
00243 m_nCookie++;
00244 }
00245
00247
00248
00249 CHostCacheHost* CHostCacheList::Add(IN_ADDR* pAddress, WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
00250 {
00251
00252 if ( ! nPort )
00253 return NULL;
00254 if ( ! pAddress->S_un.S_un_b.s_b1 )
00255 return NULL;
00256
00257
00258 if ( Network.IsFirewalledAddress( &pAddress->S_un.S_addr, TRUE ) )
00259 return NULL;
00260
00261
00262 if ( ( Settings.Connection.IgnoreOwnIP ) && ( Network.m_pHost.sin_addr.S_un.S_addr == pAddress->S_un.S_addr ) )
00263 return NULL;
00264
00265
00266 if ( Security.IsDenied( pAddress ) )
00267 return NULL;
00268
00269
00270 return AddInternal( pAddress, nPort, tSeen, pszVendor );
00271 }
00272
00273 BOOL CHostCacheList::Add(LPCTSTR pszHost, DWORD tSeen, LPCTSTR pszVendor)
00274 {
00275 CString strHost( pszHost );
00276
00277 strHost.TrimLeft();
00278 strHost.TrimRight();
00279
00280 int nPos = strHost.ReverseFind( ' ' );
00281
00282 if ( nPos > 0 )
00283 {
00284 CString strTime = strHost.Mid( nPos + 1 );
00285 strHost = strHost.Left( nPos );
00286 strHost.TrimRight();
00287
00288 tSeen = TimeFromString( strTime );
00289 }
00290
00291 nPos = strHost.Find( ':' );
00292 if ( nPos < 0 ) return FALSE;
00293
00294 int nPort = GNUTELLA_DEFAULT_PORT;
00295 if ( _stscanf( strHost.Mid( nPos + 1 ), _T("%i"), &nPort ) != 1 ) return FALSE;
00296 strHost = strHost.Left( nPos );
00297
00298 USES_CONVERSION;
00299 DWORD nAddress = inet_addr( T2CA( (LPCTSTR)strHost ) );
00300
00301
00302 if ( ! nPort )
00303 return TRUE;
00304 if ( ! nAddress )
00305 return TRUE;
00306
00307
00308 if ( Network.IsFirewalledAddress( &nAddress, TRUE ) )
00309 return TRUE;
00310
00311
00312 if ( ( Settings.Connection.IgnoreOwnIP ) && ( Network.m_pHost.sin_addr.S_un.S_addr == nAddress ) )
00313 return TRUE;
00314
00315
00316 if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
00317 return TRUE;
00318
00319
00320 AddInternal( (IN_ADDR*)&nAddress, (WORD)nPort, tSeen, pszVendor );
00321
00322 return TRUE;
00323 }
00324
00325
00326
00327 CHostCacheHost* CHostCacheList::AddInternal(IN_ADDR* pAddress, WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
00328 {
00329
00330 BYTE nHash = pAddress->S_un.S_un_b.s_b1
00331 + pAddress->S_un.S_un_b.s_b2
00332 + pAddress->S_un.S_un_b.s_b3
00333 + pAddress->S_un.S_un_b.s_b4;
00334
00335 CHostCacheHost** pHash = m_pHash + nHash;
00336 CHostCacheHost* pHost = *pHash;
00337
00338 for ( ; pHost ; pHost = pHost->m_pNextHash )
00339 {
00340 if ( pHost->m_pAddress.S_un.S_addr == pAddress->S_un.S_addr ) break;
00341 }
00342
00343 BOOL bToNewest = TRUE;
00344
00345 if ( pHost == NULL )
00346 {
00347 if ( m_nHosts == m_nBuffer ) RemoveOldest();
00348 if ( m_nHosts == m_nBuffer || ! m_pFree ) return NULL;
00349
00350 pHost = m_pFree;
00351 m_pFree = m_pFree->m_pNextHash;
00352 m_nHosts++;
00353
00354 pHost->m_pNextHash = *pHash;
00355 *pHash = pHost;
00356
00357 pHost->Reset( pAddress );
00358 }
00359 else if ( time( NULL ) - pHost->m_tFailure >= 180 )
00360 {
00361 if ( pHost->m_pPrevTime )
00362 pHost->m_pPrevTime->m_pNextTime = pHost->m_pNextTime;
00363 else
00364 m_pOldest = pHost->m_pNextTime;
00365
00366 if ( pHost->m_pNextTime )
00367 pHost->m_pNextTime->m_pPrevTime = pHost->m_pPrevTime;
00368 else
00369 m_pNewest = pHost->m_pPrevTime;
00370 }
00371 else
00372 {
00373 bToNewest = FALSE;
00374 }
00375
00376 if ( bToNewest )
00377 {
00378 pHost->m_pNextTime = NULL;
00379 pHost->m_pPrevTime = m_pNewest;
00380
00381 if ( m_pNewest )
00382 m_pNewest->m_pNextTime = pHost;
00383 else
00384 m_pOldest = pHost;
00385
00386 m_pNewest = pHost;
00387 }
00388
00389 pHost->Update( nPort, tSeen, pszVendor );
00390 m_nCookie++;
00391
00392 return pHost;
00393 }
00394
00396
00397
00398 CHostCacheHost* CHostCacheList::Find(IN_ADDR* pAddress) const
00399 {
00400 if ( ! pAddress->S_un.S_un_b.s_b1 ) return NULL;
00401
00402 BYTE nHash = pAddress->S_un.S_un_b.s_b1
00403 + pAddress->S_un.S_un_b.s_b2
00404 + pAddress->S_un.S_un_b.s_b3
00405 + pAddress->S_un.S_un_b.s_b4;
00406
00407 CHostCacheHost** pHash = (class CHostCacheHost **)m_pHash + nHash;
00408 CHostCacheHost* pHost = *pHash;
00409
00410 for ( ; pHost ; pHost = pHost->m_pNextHash )
00411 {
00412 if ( pHost->m_pAddress.S_un.S_addr == pAddress->S_un.S_addr ) return pHost;
00413 }
00414
00415 return NULL;
00416 }
00417
00419
00420
00421 BOOL CHostCacheList::Check(CHostCacheHost* pHost) const
00422 {
00423 for ( CHostCacheHost* pTest = m_pOldest ; pTest ; pTest = pTest->m_pNextTime )
00424 {
00425 if ( pTest == pHost ) return TRUE;
00426 }
00427
00428 return FALSE;
00429 }
00430
00432
00433
00434 void CHostCacheList::Remove(CHostCacheHost* pHost)
00435 {
00436
00437
00438
00439 for ( CHostCacheHost* pTest = m_pOldest ; pTest ; pTest = pTest->m_pNextTime )
00440 {
00441 if ( pTest == pHost )
00442 {
00443 if ( pHost->m_pPrevTime )
00444 pHost->m_pPrevTime->m_pNextTime = pHost->m_pNextTime;
00445 else
00446 m_pOldest = pHost->m_pNextTime;
00447
00448 if ( pHost->m_pNextTime )
00449 pHost->m_pNextTime->m_pPrevTime = pHost->m_pPrevTime;
00450 else
00451 m_pNewest = pHost->m_pPrevTime;
00452
00453 BYTE nHash = pHost->m_pAddress.S_un.S_un_b.s_b1
00454 + pHost->m_pAddress.S_un.S_un_b.s_b2
00455 + pHost->m_pAddress.S_un.S_un_b.s_b3
00456 + pHost->m_pAddress.S_un.S_un_b.s_b4;
00457
00458 CHostCacheHost** pPrevious = m_pHash + nHash;
00459
00460 for ( pTest = *pPrevious ; pTest ; pTest = pTest->m_pNextHash )
00461 {
00462 if ( pTest == pHost )
00463 {
00464 *pPrevious = pHost->m_pNextHash;
00465 break;
00466 }
00467
00468 pPrevious = &pTest->m_pNextHash;
00469 }
00470
00471 pHost->m_pNextHash = m_pFree;
00472 m_pFree = pHost;
00473 m_nHosts--;
00474 m_nCookie++;
00475
00476 return;
00477 }
00478 }
00479 }
00480
00481 void CHostCacheList::RemoveOldest()
00482 {
00483 if ( m_pOldest ) Remove( m_pOldest );
00484 }
00485
00487
00488
00489 void CHostCacheList::OnFailure(IN_ADDR* pAddress, WORD nPort)
00490 {
00491 BYTE nHash = pAddress->S_un.S_un_b.s_b1
00492 + pAddress->S_un.S_un_b.s_b2
00493 + pAddress->S_un.S_un_b.s_b3
00494 + pAddress->S_un.S_un_b.s_b4;
00495
00496 CHostCacheHost** pHash = m_pHash + nHash;
00497
00498 for ( CHostCacheHost* pHost = *pHash ; pHost ; pHost = pHost->m_pNextHash )
00499 {
00500 if ( pHost->m_pAddress.S_un.S_addr == pAddress->S_un.S_addr &&
00501 ( ! nPort || pHost->m_nPort == nPort ) )
00502 {
00503 if ( pHost->m_bPriority ) return;
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 Remove( pHost );
00530
00531 break;
00532 }
00533 }
00534 }
00535
00537
00538
00539 DWORD CHostCacheList::CountHosts() const
00540 {
00541 DWORD nCount = 0;
00542
00543 for ( CHostCacheHost* pHost = GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
00544 nCount++;
00545
00546 return ( nCount );
00547 }
00548
00550
00551
00552 void CHostCacheList::PruneByQueryAck()
00553 {
00554 DWORD tNow = time( NULL );
00555
00556 for ( CHostCacheHost* pHost = m_pNewest ; pHost ; )
00557 {
00558 CHostCacheHost* pNext = pHost->m_pPrevTime;
00559
00560 if ( pHost->m_tAck )
00561 {
00562 if ( tNow - pHost->m_tAck > Settings.Gnutella2.QueryHostDeadline )
00563 {
00564 pHost->m_tAck = 0;
00565 if ( pHost->m_nFailures++ > 3 ) Remove( pHost );
00566 }
00567 }
00568
00569 pHost = pNext;
00570 }
00571 }
00572
00573
00575
00576
00577 void CHostCacheList::PruneOldHosts()
00578 {
00579 DWORD tNow = time( NULL );
00580
00581 for ( CHostCacheHost* pHost = m_pNewest ; pHost ; )
00582 {
00583 CHostCacheHost* pNext = pHost->m_pPrevTime;
00584
00585 DWORD nExpire;
00586
00587 if ( pHost->m_nProtocol == PROTOCOL_G1 )
00588 nExpire = Settings.Gnutella1.HostExpire;
00589 else if ( pHost->m_nProtocol == PROTOCOL_G2 )
00590 nExpire = Settings.Gnutella2.HostExpire;
00591 else
00592 nExpire = 0;
00593
00594 if ( ( nExpire ) && ( tNow - pHost->m_tSeen > nExpire ) )
00595 {
00596 Remove( pHost );
00597 }
00598
00599 pHost = pNext;
00600 }
00601 }
00602
00603
00605
00606
00607 void CHostCacheList::Serialize(CArchive& ar, int nVersion)
00608 {
00609 if ( ar.IsStoring() )
00610 {
00611 ar.WriteCount( m_nHosts );
00612
00613 for ( CHostCacheHost* pHost = m_pOldest ; pHost ; pHost = pHost->m_pNextTime )
00614 {
00615 pHost->Serialize( ar, nVersion );
00616 }
00617 }
00618 else
00619 {
00620 int nItem, nCount = ar.ReadCount();
00621
00622 for ( nItem = 0 ; nItem < nCount && m_pFree ; nItem++ )
00623 {
00624 CHostCacheHost* pHost = m_pFree;
00625 m_pFree = m_pFree->m_pNextHash;
00626 m_nHosts++;
00627
00628 pHost->Reset( NULL );
00629 pHost->Serialize( ar, nVersion );
00630
00631 if ( m_pOldest == NULL ) m_pOldest = pHost;
00632
00633 if ( m_pNewest )
00634 {
00635 m_pNewest->m_pNextTime = pHost;
00636 pHost->m_pPrevTime = m_pNewest;
00637 m_pNewest = pHost;
00638 }
00639 else m_pNewest = pHost;
00640
00641 BYTE nHash = pHost->m_pAddress.S_un.S_un_b.s_b1
00642 + pHost->m_pAddress.S_un.S_un_b.s_b2
00643 + pHost->m_pAddress.S_un.S_un_b.s_b3
00644 + pHost->m_pAddress.S_un.S_un_b.s_b4;
00645
00646 CHostCacheHost** pHash = m_pHash + nHash;
00647 pHost->m_pNextHash = *pHash;
00648 *pHash = pHost;
00649 }
00650 }
00651 }
00652
00654
00655
00656 int CHostCacheList::Import(LPCTSTR pszFile)
00657 {
00658 CFile pFile;
00659
00660 if ( ! pFile.Open( pszFile, CFile::modeRead ) ) return 0;
00661
00662 if ( _tcsistr( pszFile, _T(".met") ) != NULL )
00663 {
00664 return ImportMET( &pFile );
00665 }
00666 else
00667 {
00668 return 0;
00669 }
00670 }
00671
00673
00674
00675 int CHostCacheList::ImportMET(CFile* pFile)
00676 {
00677 CSingleLock pLock( &Network.m_pSection, TRUE );
00678
00679 BYTE nVersion = 0;
00680 pFile->Read( &nVersion, sizeof(nVersion) );
00681 if ( nVersion != 0xE0 && nVersion != 0x0E ) return FALSE;
00682
00683 int nServers = 0;
00684 UINT nCount = 0;
00685
00686 pFile->Read( &nCount, sizeof(nCount) );
00687
00688 while ( nCount-- > 0 )
00689 {
00690 IN_ADDR pAddress;
00691 WORD nPort;
00692 UINT nTags;
00693
00694 if ( pFile->Read( &pAddress, sizeof(pAddress) ) != sizeof(pAddress) ) break;
00695 if ( pFile->Read( &nPort, sizeof(nPort) ) != sizeof(nPort) ) break;
00696 if ( pFile->Read( &nTags, sizeof(nTags) ) != sizeof(nTags) ) break;
00697
00698 CHostCacheHost* pServer = Add( &pAddress, nPort );
00699
00700 while ( nTags-- > 0 )
00701 {
00702 CEDTag pTag;
00703 if ( ! pTag.Read( pFile ) ) break;
00704 if ( pServer == NULL ) continue;
00705
00706 if ( pTag.Check( ED2K_ST_SERVERNAME, ED2K_TAG_STRING ) )
00707 {
00708 pServer->m_sName = pTag.m_sValue;
00709 }
00710 else if ( pTag.Check( ED2K_ST_DESCRIPTION, ED2K_TAG_STRING ) )
00711 {
00712 pServer->m_sDescription = pTag.m_sValue;
00713 }
00714 else if ( pTag.Check( ED2K_ST_MAXUSERS, ED2K_TAG_INT ) )
00715 {
00716 pServer->m_nUserLimit = pTag.m_nValue;
00717 }
00718 else if ( pTag.Check( ED2K_ST_MAXFILES, ED2K_TAG_INT ) )
00719 {
00720 pServer->m_nFileLimit = pTag.m_nValue;
00721 }
00722 else if ( pTag.Check( ED2K_ST_UDPFLAGS, ED2K_TAG_INT ) )
00723 {
00724 pServer->m_nUDPFlags = pTag.m_nValue;
00725 }
00726 }
00727
00728 nServers++;
00729 }
00730
00731 return nServers;
00732 }
00733
00735
00736
00737 int CHostCacheList::LoadDefaultED2KServers()
00738 {
00739 CSingleLock pLock( &Network.m_pSection, TRUE );
00740
00741 CFile pFile;
00742 int nServers = 0;
00743 CString strFile = Settings.General.Path + _T("\\Data\\DefaultServers.dat");
00744
00745 if ( pFile.Open( strFile, CFile::modeRead ) )
00746 {
00747 theApp.Message( MSG_DEFAULT, _T("Loading default ED2K server list") );
00748
00749 try
00750 {
00751 CString strLine;
00752 CBuffer pBuffer;
00753 TCHAR cType;
00754
00755 pBuffer.EnsureBuffer( (DWORD)pFile.GetLength() );
00756 pBuffer.m_nLength = (DWORD)pFile.GetLength();
00757 pFile.Read( pBuffer.m_pBuffer, pBuffer.m_nLength );
00758 pFile.Close();
00759
00760 while ( pBuffer.ReadLine( strLine ) )
00761 {
00762 if ( strLine.GetLength() < 7 ) continue;
00763
00764 cType = strLine.GetAt( 0 );
00765
00766 if ( cType != '#' )
00767 {
00768 CString strServer = strLine.Right( strLine.GetLength() - 2 );
00769
00770 int nIP[4], nPort;
00771
00772 if ( _stscanf( strServer, _T("%i.%i.%i.%i:%i"), &nIP[0], &nIP[1], &nIP[2], &nIP[3], &nPort ) == 5 )
00773 {
00774 IN_ADDR pAddress;
00775 pAddress.S_un.S_un_b.s_b1 = nIP[0];
00776 pAddress.S_un.S_un_b.s_b2 = nIP[1];
00777 pAddress.S_un.S_un_b.s_b3 = nIP[2];
00778 pAddress.S_un.S_un_b.s_b4 = nIP[3];
00779
00780 CHostCacheHost* pServer = Add( &pAddress, nPort );
00781
00782 if ( cType == 'P' )
00783 pServer->m_bPriority = TRUE;
00784 else
00785 pServer->m_bPriority = FALSE;
00786
00787 nServers++;
00788 }
00789 }
00790 }
00791 }
00792 catch ( CException* pException )
00793 {
00794 if (pFile.m_hFile != CFile::hFileNull) pFile.Close();
00795 pException->Delete();
00796 }
00797 }
00798
00799 return nServers;
00800 }
00801
00802
00803
00805
00806
00807 CHostCacheHost::CHostCacheHost()
00808 {
00809 m_pNextHash = m_pPrevTime = m_pNextTime = NULL;
00810 }
00811
00813
00814
00815 void CHostCacheHost::Serialize(CArchive& ar, int nVersion)
00816 {
00817 if ( ar.IsStoring() )
00818 {
00819 ar.Write( &m_pAddress, sizeof(m_pAddress) );
00820 ar << m_nPort;
00821
00822 ar << m_tAdded;
00823 ar << m_tSeen;
00824 ar << m_tRetryAfter;
00825
00826 if ( m_pVendor != NULL && m_pVendor->m_sCode.GetLength() == 4 )
00827 {
00828 ar << (CHAR)m_pVendor->m_sCode.GetAt( 0 );
00829 ar << (CHAR)m_pVendor->m_sCode.GetAt( 1 );
00830 ar << (CHAR)m_pVendor->m_sCode.GetAt( 2 );
00831 ar << (CHAR)m_pVendor->m_sCode.GetAt( 3 );
00832 }
00833 else
00834 {
00835 CHAR cZero = 0;
00836 ar << cZero;
00837 }
00838
00839 ar << m_sName;
00840 if ( m_sName.GetLength() ) ar << m_sDescription;
00841
00842 ar << m_nUserCount;
00843 ar << m_nUserLimit;
00844 ar << m_bPriority;
00845
00846 ar << m_nFileLimit;
00847 ar << m_nTCPFlags;
00848 ar << m_nUDPFlags;
00849 ar << m_tStats;
00850
00851 ar << m_nKeyValue;
00852 if ( m_nKeyValue != 0 )
00853 {
00854 ar << m_tKeyTime;
00855 ar << m_nKeyHost;
00856 }
00857 }
00858 else
00859 {
00860 ar.Read( &m_pAddress, sizeof(m_pAddress) );
00861 ar >> m_nPort;
00862
00863 ar >> m_tAdded;
00864 ar >> m_tSeen;
00865 ar >> m_tRetryAfter;
00866
00867 CHAR szaVendor[4] = { 0, 0, 0, 0 };
00868 ar >> szaVendor[0];
00869
00870 if ( szaVendor[0] )
00871 {
00872 ar.Read( szaVendor + 1, 3 );
00873 TCHAR szVendor[5] = { szaVendor[0], szaVendor[1], szaVendor[2], szaVendor[3], 0 };
00874 m_pVendor = VendorCache.Lookup( szVendor );
00875 }
00876
00877 if ( nVersion >= 10 )
00878 {
00879 ar >> m_sName;
00880 if ( m_sName.GetLength() ) ar >> m_sDescription;
00881
00882 ar >> m_nUserCount;
00883 ar >> m_nUserLimit;
00884 ar >> m_bPriority;
00885
00886 ar >> m_nFileLimit;
00887 ar >> m_nTCPFlags;
00888 ar >> m_nUDPFlags;
00889 ar >> m_tStats;
00890 }
00891 else if ( nVersion >= 7 )
00892 {
00893 ar >> m_sName;
00894 if ( m_sName.GetLength() )
00895 {
00896 ar >> m_sDescription;
00897 ar >> m_nUserCount;
00898 if ( nVersion >= 8 ) ar >> m_nUserLimit;
00899 if ( nVersion >= 9 ) ar >> m_bPriority;
00900 if ( nVersion >= 10 )
00901 {
00902 ar >> m_nFileLimit;
00903 ar >> m_nTCPFlags;
00904 ar >> m_nUDPFlags;
00905 }
00906 }
00907 }
00908
00909 ar >> m_nKeyValue;
00910 if ( m_nKeyValue != 0 )
00911 {
00912 ar >> m_tKeyTime;
00913 ar >> m_nKeyHost;
00914 }
00915 }
00916 }
00917
00919
00920
00921 void CHostCacheHost::Reset(IN_ADDR* pAddress)
00922 {
00923 if ( pAddress ) m_pAddress = *pAddress;
00924
00925 m_pVendor = NULL;
00926 m_bPriority = FALSE;
00927 m_nUserCount = 0;
00928 m_nUserLimit = 0;
00929 m_nFileLimit = 0;
00930 m_sName.Empty();
00931 m_sDescription.Empty();
00932
00933 m_nUDPFlags = 0;
00934 m_nTCPFlags = 0;
00935
00936 m_tAdded = GetTickCount();
00937 m_tSeen = 0;
00938 m_tRetryAfter = 0;
00939 m_tConnect = 0;
00940 m_tQuery = 0;
00941 m_tAck = 0;
00942 m_tStats = 0;
00943 m_tFailure = 0;
00944 m_nFailures = 0;
00945
00946 m_tKeyTime = 0;
00947 m_nKeyValue = 0;
00948 m_nKeyHost = 0;
00949 }
00950
00952
00953
00954 void CHostCacheHost::Update(WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
00955 {
00956 m_nPort = nPort;
00957 m_tSeen = tSeen > 1 ? tSeen : time( NULL );
00958
00959 if ( pszVendor != NULL )
00960 {
00961 if ( m_pVendor == NULL || m_pVendor->m_sCode != pszVendor )
00962 {
00963 m_pVendor = VendorCache.Lookup( pszVendor );
00964 }
00965 }
00966 }
00967
00969
00970
00971 CNeighbour* CHostCacheHost::ConnectTo(BOOL bAutomatic)
00972 {
00973 m_tConnect = time( NULL );
00974 if ( bAutomatic && Network.IsFirewalledAddress( &m_pAddress, TRUE ) ) return NULL;
00975 return Neighbours.ConnectTo( &m_pAddress, m_nPort, m_nProtocol, bAutomatic );
00976 }
00977
00979
00980
00981 CG1Packet* CHostCacheHost::ToG1Ping(int nTTL, GGUID* pGUID)
00982 {
00983 CG1Packet* pPong = CG1Packet::New( G1_PACKET_PONG, nTTL, pGUID );
00984
00985 pPong->WriteShortLE( m_nPort );
00986 pPong->WriteLongLE( *(DWORD*)&m_pAddress );
00987 pPong->WriteLongLE( 0 );
00988 pPong->WriteLongLE( 0 );
00989
00990 return pPong;
00991 }
00992
00994
00995
00996 CString CHostCacheHost::ToString() const
00997 {
00998 struct tm* pTime = gmtime( (time_t*)&m_tSeen );
00999 CString str;
01000
01001 str.Format( _T("%s:%i %.4i-%.2i-%.2iT%.2i:%.2iZ"),
01002 (LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
01003 pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
01004 pTime->tm_hour, pTime->tm_min );
01005
01006 return str;
01007 }
01008
01010
01011
01012 BOOL CHostCacheHost::CanConnect(DWORD tNow) const
01013 {
01014 if ( ! m_tConnect ) return TRUE;
01015 if ( m_pAddress.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
01016 if ( ! tNow ) tNow = time( NULL );
01017 return tNow - m_tConnect >= Settings.Gnutella.ConnectThrottle;
01018 }
01019
01021
01022
01023 BOOL CHostCacheHost::CanQuote(DWORD tNow) const
01024 {
01025 if ( ! tNow ) tNow = time( NULL );
01026 return tNow - m_tSeen < Settings.Gnutella2.HostCurrent;
01027 }
01028
01030
01031
01032
01033 BOOL CHostCacheHost::CanQuery(DWORD tNow) const
01034 {
01035
01036 if ( m_nProtocol == PROTOCOL_ED2K )
01037 {
01038
01039 if ( ! Settings.eDonkey.EnableToday ) return FALSE;
01040 if ( ! Settings.eDonkey.ServerWalk ) return FALSE;
01041
01042
01043 if ( 0 == tNow ) tNow = time( NULL );
01044
01045
01046 if ( 0 != m_tRetryAfter && tNow < m_tRetryAfter ) return FALSE;
01047
01048
01049 if ( 0 == m_tQuery ) return TRUE;
01050
01051
01052 return ( tNow - m_tQuery ) >= max( Settings.eDonkey.QueryServerThrottle, DWORD(60) );
01053 }
01054 else if ( m_nProtocol == PROTOCOL_G2 )
01055 {
01056
01057 if ( ! Settings.Gnutella2.EnableToday ) return FALSE;
01058
01059
01060 if ( 0 != m_tAck ) return FALSE;
01061
01062
01063 if ( 0 == tNow ) tNow = time( NULL );
01064
01065
01066 if ( ( tNow - m_tSeen ) > Settings.Gnutella2.HostCurrent ) return FALSE;
01067
01068
01069 if ( 0 != m_tRetryAfter && tNow < m_tRetryAfter ) return FALSE;
01070
01071
01072 if ( 0 == m_tQuery ) return TRUE;
01073
01074
01075 return ( tNow - m_tQuery ) >= max( Settings.Gnutella2.QueryHostThrottle, DWORD(90) );
01076 }
01077
01078 return FALSE;
01079 }
01080
01082
01083
01084 void CHostCacheHost::SetKey(DWORD nKey, IN_ADDR* pHost)
01085 {
01086 m_tAck = 0;
01087 m_nFailures = 0;
01088 m_tKeyTime = nKey ? time( NULL ) : 0;
01089 m_nKeyValue = nKey;
01090 m_nKeyHost = pHost && nKey ? pHost->S_un.S_addr : Network.m_pHost.sin_addr.S_un.S_addr;
01091 }