Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

HostCache.cpp

Go to the documentation of this file.
00001 //
00002 // HostCache.cpp
00003 //
00004 //      Date:                   "$Date: 2005/07/16 14:43:11 $"
00005 //      Revision:               "$Revision: 1.16 $"
00006 //  Last change by:     "$Author: mogthecat $"
00007 //
00008 // Copyright (c) Shareaza Development Team, 2002-2005.
00009 // This file is part of SHAREAZA (www.shareaza.com)
00010 //
00011 // Shareaza is free software; you can redistribute it
00012 // and/or modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Shareaza is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with Shareaza; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // CHostCache construction
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 // CHostCache core operations
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 // CHostCache forwarding operations
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 // CHostCacheList construction
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 // CHostCacheList clear
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 // CHostCacheList host add
00248 
00249 CHostCacheHost* CHostCacheList::Add(IN_ADDR* pAddress, WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
00250 {
00251         // Don't add invalid addresses
00252         if ( ! nPort ) 
00253                 return NULL;
00254         if ( ! pAddress->S_un.S_un_b.s_b1 ) 
00255                 return NULL;
00256 
00257         // Don't add own firewalled IPs
00258         if ( Network.IsFirewalledAddress( &pAddress->S_un.S_addr, TRUE ) ) 
00259                 return NULL;
00260 
00261         // Don't add own IP if set not to. (Above check may not run if not ignoring local IPs)
00262         if ( ( Settings.Connection.IgnoreOwnIP ) && ( Network.m_pHost.sin_addr.S_un.S_addr == pAddress->S_un.S_addr ) )
00263                 return NULL;
00264 
00265         // Check security settings, don't add blocked IPs
00266         if ( Security.IsDenied( pAddress ) )
00267                 return NULL;
00268 
00269         // Try adding it to the cache. (duplicates will be rejected)
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         // Don't add invalid addresses
00302         if ( ! nPort ) 
00303                  return TRUE;
00304         if ( ! nAddress ) 
00305                  return TRUE;
00306         
00307         // Don't add own firewalled IPs
00308         if ( Network.IsFirewalledAddress( &nAddress, TRUE ) ) 
00309                 return TRUE;
00310 
00311         // Don't add own IP if set not to. (Above check may not run if not ignoring local IPs)
00312         if ( ( Settings.Connection.IgnoreOwnIP ) && ( Network.m_pHost.sin_addr.S_un.S_addr == nAddress ) )
00313                  return TRUE;
00314 
00315         // Check security settings, don't add blocked IPs
00316         if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
00317                  return TRUE;
00318 
00319         // Try adding it to the cache. (duplicates will be rejected)
00320         AddInternal( (IN_ADDR*)&nAddress, (WORD)nPort, tSeen, pszVendor );
00321         
00322         return TRUE;
00323 }
00324 
00325 // This function actually add the remote client to the host cache. Private, but used by the public 
00326 // functions. No security checking, etc.
00327 CHostCacheHost* CHostCacheList::AddInternal(IN_ADDR* pAddress, WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
00328 {
00329         // Check if we already have the host
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 // CHostCacheList find
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 // CHostCacheList check host
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 // CHostCacheList host remove
00433 
00434 void CHostCacheList::Remove(CHostCacheHost* pHost)
00435 {
00436         // NOTE: OPTIMIZE: Why the hell am I searching the list if I already have
00437         // the object pointer?
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 // CHostCacheList failure processor
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                         if ( pHost->m_pPrevTime )
00507                                 pHost->m_pPrevTime->m_pNextTime = pHost->m_pNextTime;
00508                         else
00509                                 m_pOldest = pHost->m_pNextTime;
00510                         
00511                         if ( pHost->m_pNextTime )
00512                                 pHost->m_pNextTime->m_pPrevTime = pHost->m_pPrevTime;
00513                         else
00514                                 m_pNewest = pHost->m_pPrevTime;
00515                         
00516                         pHost->m_pPrevTime = NULL;
00517                         pHost->m_pNextTime = m_pOldest;
00518                         
00519                         if ( m_pOldest )
00520                                 m_pOldest->m_pPrevTime = pHost;
00521                         else
00522                                 m_pNewest = pHost;
00523                         
00524                         m_pOldest = pHost;
00525                         
00526                         pHost->m_tFailure = time( NULL );
00527                         */
00528                         
00529                         Remove( pHost );
00530                         
00531                         break;
00532                 }
00533         }
00534 }
00535 
00537 // CHostCacheList count
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 // CHostCacheList query acknowledgement prune (G2)
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 // CHostCacheList prune old hosts (To remove old hosts when trying to connect to G1)
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 // ed2k
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 // CHostCacheList serialize
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 // CHostCacheList root import
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 // CHostCacheList MET import
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 // CHostCacheList MET import
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 ) )                  // Load default list from file if possible
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; // Blank comment line
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(); // Check if file is still open, if yes close
00795                         pException->Delete();
00796                 }
00797         }
00798 
00799         return nServers;
00800 }
00801 
00802 
00803 
00805 // CHostCacheHost construction
00806 
00807 CHostCacheHost::CHostCacheHost()
00808 {
00809         m_pNextHash = m_pPrevTime = m_pNextTime = NULL;
00810 }
00811 
00813 // CHostCacheHost serialize
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 // CHostCacheHost reset
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 // CHostCacheHost update
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 // CHostCacheHost connection setup
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 // CHostCacheHost packet conversion
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 // CHostCacheHost string
00995 
00996 CString CHostCacheHost::ToString() const
00997 {
00998         struct tm* pTime = gmtime( (time_t*)&m_tSeen );
00999         CString str; // 2002-04-30T08:30Z
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 // CHostCacheHost connection test
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 // CHostCacheHost quote test
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 // CHostCacheHost query test
01031 
01032 // Can we UDP query this host? (G2/ed2k)
01033 BOOL CHostCacheHost::CanQuery(DWORD tNow) const
01034 {
01035         // eDonkey2000 server
01036         if ( m_nProtocol == PROTOCOL_ED2K )
01037         {
01038                 // Must support ED2K
01039                 if ( ! Settings.eDonkey.EnableToday ) return FALSE;
01040                 if ( ! Settings.eDonkey.ServerWalk ) return FALSE;
01041                 
01042                 // Get the time if not supplied
01043                 if ( 0 == tNow ) tNow = time( NULL );
01044                 
01045                 // Retry After
01046                 if ( 0 != m_tRetryAfter && tNow < m_tRetryAfter ) return FALSE;
01047                 
01048                 // If haven't queried yet, its ok
01049                 if ( 0 == m_tQuery ) return TRUE;
01050                 
01051                 // Don't query too fast
01052                 return ( tNow - m_tQuery ) >= max( Settings.eDonkey.QueryServerThrottle, DWORD(60) );
01053         }
01054         else if ( m_nProtocol == PROTOCOL_G2 )
01055         {
01056                 // Must support G2
01057                 if ( ! Settings.Gnutella2.EnableToday ) return FALSE;
01058                 
01059                 // Must not be waiting for an ack
01060                 if ( 0 != m_tAck ) return FALSE;
01061                 
01062                 // Get the time if not supplied
01063                 if ( 0 == tNow ) tNow = time( NULL );
01064                 
01065                 // Must be a recently seen (current) host
01066                 if ( ( tNow - m_tSeen ) > Settings.Gnutella2.HostCurrent ) return FALSE;
01067                 
01068                 // Retry After
01069                 if ( 0 != m_tRetryAfter && tNow < m_tRetryAfter ) return FALSE;
01070                 
01071                 // If haven't queried yet, its ok
01072                 if ( 0 == m_tQuery ) return TRUE;
01073                 
01074                 // Don't query too fast
01075                 return ( tNow - m_tQuery ) >= max( Settings.Gnutella2.QueryHostThrottle, DWORD(90) );
01076         }
01077         
01078         return FALSE;
01079 }
01080 
01082 // CHostCacheHost query key submission
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 }

Generated on Thu Dec 15 10:39:43 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2