📄 hostcache.cpp
字号:
//
// HostCache.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Network.h"
#include "HostCache.h"
#include "Neighbours.h"
#include "Security.h"
#include "VendorCache.h"
#include "G1Packet.h"
#include "EDPacket.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CHostCache HostCache;
//////////////////////////////////////////////////////////////////////
// CHostCache construction
CHostCache::CHostCache() :
Gnutella1( PROTOCOL_G1 ), Gnutella2( PROTOCOL_G2 ),
eDonkey( PROTOCOL_ED2K )
{
m_pList.AddTail( &Gnutella1 );
m_pList.AddTail( &Gnutella2 );
m_pList.AddTail( &eDonkey );
}
//////////////////////////////////////////////////////////////////////
// CHostCache core operations
void CHostCache::Clear()
{
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
pCache->Clear();
}
}
BOOL CHostCache::Load()
{
CSingleLock pLock( &Network.m_pSection, TRUE );
CString strFile;
CFile pFile;
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
pCache->Clear();
}
strFile.Format( _T("%s\\Data\\HostCache.dat"), (LPCTSTR)Settings.General.Path );
if ( ! pFile.Open( strFile, CFile::modeRead ) ) return FALSE;
try
{
CArchive ar( &pFile, CArchive::load );
Serialize( ar );
ar.Close();
}
catch ( CException* pException )
{
pException->Delete();
}
if ( eDonkey.GetNewest() == NULL ) eDonkey.Import( _T("C:\\Program Files\\eMule\\server.met") );
return TRUE;
}
BOOL CHostCache::Save()
{
CSingleLock pLock( &Network.m_pSection, TRUE );
CString strFile;
CFile pFile;
strFile.Format( _T("%s\\Data\\HostCache.dat"), (LPCTSTR)Settings.General.Path );
if ( ! pFile.Open( strFile, CFile::modeWrite|CFile::modeCreate ) ) return FALSE;
CArchive ar( &pFile, CArchive::store );
Serialize( ar );
ar.Close();
return TRUE;
}
void CHostCache::Serialize(CArchive& ar)
{
int nVersion = 9;
if ( ar.IsStoring() )
{
ar << nVersion;
ar.WriteCount( m_pList.GetCount() );
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
ar << pCache->m_nProtocol;
pCache->Serialize( ar, nVersion );
}
}
else
{
ar >> nVersion;
if ( nVersion < 6 ) return;
for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
{
PROTOCOLID nProtocol;
ar >> nProtocol;
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
if ( pCache->m_nProtocol == nProtocol )
{
pCache->Serialize( ar, nVersion );
break;
}
}
}
}
}
//////////////////////////////////////////////////////////////////////
// CHostCache forwarding operations
CHostCacheHost* CHostCache::Find(IN_ADDR* pAddress) const
{
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
if ( CHostCacheHost* pHost = pCache->Find( pAddress ) ) return pHost;
}
return NULL;
}
BOOL CHostCache::Check(CHostCacheHost* pHost) const
{
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
if ( pCache->Check( pHost ) ) return TRUE;
}
return FALSE;
}
void CHostCache::Remove(CHostCacheHost* pHost)
{
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
pCache->Remove( pHost );
}
}
void CHostCache::OnFailure(IN_ADDR* pAddress, WORD nPort)
{
for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
{
CHostCacheList* pCache = (CHostCacheList*)m_pList.GetNext( pos );
pCache->OnFailure( pAddress, nPort );
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList construction
CHostCacheList::CHostCacheList(PROTOCOLID nProtocol)
{
m_nProtocol = nProtocol;
m_nBuffer = 0;
m_pBuffer = NULL;
m_nCookie = 0;
}
CHostCacheList::~CHostCacheList()
{
Clear();
if ( m_pBuffer ) delete [] m_pBuffer;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList clear
void CHostCacheList::Clear()
{
if ( m_pBuffer == NULL )
{
m_nBuffer = Settings.Gnutella.HostCacheSize;
m_pBuffer = new CHostCacheHost[ m_nBuffer ];
}
CHostCacheHost* pHost = m_pBuffer;
for ( DWORD nPos = m_nBuffer ; nPos ; nPos--, pHost++ )
{
pHost->m_pNextHash = ( nPos == 1 ) ? NULL : pHost + 1;
pHost->m_nProtocol = m_nProtocol;
}
ZeroMemory( m_pHash, sizeof(CHostCacheHost*) * 256 );
m_pFree = m_pBuffer;
m_pNewest = NULL;
m_pOldest = NULL;
m_nHosts = 0;
m_nCookie++;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList host add
CHostCacheHost* CHostCacheList::Add(IN_ADDR* pAddress, WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
{
if ( ! nPort ) return NULL;
if ( ! pAddress->S_un.S_un_b.s_b1 ) return NULL;
BYTE nHash = pAddress->S_un.S_un_b.s_b1
+ pAddress->S_un.S_un_b.s_b2
+ pAddress->S_un.S_un_b.s_b3
+ pAddress->S_un.S_un_b.s_b4;
CHostCacheHost** pHash = m_pHash + nHash;
CHostCacheHost* pHost = *pHash;
for ( ; pHost ; pHost = pHost->m_pNextHash )
{
if ( pHost->m_pAddress.S_un.S_addr == pAddress->S_un.S_addr ) break;
}
BOOL bToNewest = TRUE;
if ( pHost == NULL )
{
if ( m_nHosts == m_nBuffer ) RemoveOldest();
if ( m_nHosts == m_nBuffer || ! m_pFree ) return NULL;
pHost = m_pFree;
m_pFree = m_pFree->m_pNextHash;
m_nHosts++;
pHost->m_pNextHash = *pHash;
*pHash = pHost;
pHost->Reset( pAddress );
}
else if ( time( NULL ) - pHost->m_tFailure >= 180 )
{
if ( pHost->m_pPrevTime )
pHost->m_pPrevTime->m_pNextTime = pHost->m_pNextTime;
else
m_pOldest = pHost->m_pNextTime;
if ( pHost->m_pNextTime )
pHost->m_pNextTime->m_pPrevTime = pHost->m_pPrevTime;
else
m_pNewest = pHost->m_pPrevTime;
}
else
{
bToNewest = FALSE;
}
if ( bToNewest )
{
pHost->m_pNextTime = NULL;
pHost->m_pPrevTime = m_pNewest;
if ( m_pNewest )
m_pNewest->m_pNextTime = pHost;
else
m_pOldest = pHost;
m_pNewest = pHost;
}
pHost->Update( nPort, tSeen, pszVendor );
m_nCookie++;
return pHost;
}
BOOL CHostCacheList::Add(LPCTSTR pszHost, DWORD tSeen, LPCTSTR pszVendor)
{
CString strHost( pszHost );
strHost.TrimLeft();
strHost.TrimRight();
int nPos = strHost.ReverseFind( ' ' );
if ( nPos > 0 )
{
CString strTime = strHost.Mid( nPos + 1 );
strHost = strHost.Left( nPos );
strHost.TrimRight();
tSeen = TimeFromString( strTime );
}
nPos = strHost.Find( ':' );
if ( nPos < 0 ) return FALSE;
int nPort = GNUTELLA_DEFAULT_PORT;
if ( _stscanf( strHost.Mid( nPos + 1 ), _T("%i"), &nPort ) != 1 ) return FALSE;
strHost = strHost.Left( nPos );
USES_CONVERSION;
DWORD nAddress = inet_addr( T2CA( (LPCTSTR)strHost ) );
if ( Security.IsDenied( (IN_ADDR*)&nAddress ) ) return TRUE;
if ( Network.IsFirewalledAddress( &nAddress, TRUE ) ) return TRUE;
Add( (IN_ADDR*)&nAddress, (WORD)nPort, tSeen, pszVendor );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList find
CHostCacheHost* CHostCacheList::Find(IN_ADDR* pAddress) const
{
if ( ! pAddress->S_un.S_un_b.s_b1 ) return NULL;
BYTE nHash = pAddress->S_un.S_un_b.s_b1
+ pAddress->S_un.S_un_b.s_b2
+ pAddress->S_un.S_un_b.s_b3
+ pAddress->S_un.S_un_b.s_b4;
CHostCacheHost** pHash = (class CHostCacheHost **)m_pHash + nHash;
CHostCacheHost* pHost = *pHash;
for ( ; pHost ; pHost = pHost->m_pNextHash )
{
if ( pHost->m_pAddress.S_un.S_addr == pAddress->S_un.S_addr ) return pHost;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList check host
BOOL CHostCacheList::Check(CHostCacheHost* pHost) const
{
for ( CHostCacheHost* pTest = m_pOldest ; pTest ; pTest = pTest->m_pNextTime )
{
if ( pTest == pHost ) return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList host remove
void CHostCacheList::Remove(CHostCacheHost* pHost)
{
// NOTE: OPTIMIZE: Why the hell am I searching the list if I already have
// the object pointer?
for ( CHostCacheHost* pTest = m_pOldest ; pTest ; pTest = pTest->m_pNextTime )
{
if ( pTest == pHost )
{
if ( pHost->m_pPrevTime )
pHost->m_pPrevTime->m_pNextTime = pHost->m_pNextTime;
else
m_pOldest = pHost->m_pNextTime;
if ( pHost->m_pNextTime )
pHost->m_pNextTime->m_pPrevTime = pHost->m_pPrevTime;
else
m_pNewest = pHost->m_pPrevTime;
BYTE nHash = pHost->m_pAddress.S_un.S_un_b.s_b1
+ pHost->m_pAddress.S_un.S_un_b.s_b2
+ pHost->m_pAddress.S_un.S_un_b.s_b3
+ pHost->m_pAddress.S_un.S_un_b.s_b4;
CHostCacheHost** pPrevious = m_pHash + nHash;
for ( pTest = *pPrevious ; pTest ; pTest = pTest->m_pNextHash )
{
if ( pTest == pHost )
{
*pPrevious = pHost->m_pNextHash;
break;
}
pPrevious = &pTest->m_pNextHash;
}
pHost->m_pNextHash = m_pFree;
m_pFree = pHost;
m_nHosts--;
m_nCookie++;
return;
}
}
}
void CHostCacheList::RemoveOldest()
{
if ( m_pOldest ) Remove( m_pOldest );
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList failure processor
void CHostCacheList::OnFailure(IN_ADDR* pAddress, WORD nPort)
{
BYTE nHash = pAddress->S_un.S_un_b.s_b1
+ pAddress->S_un.S_un_b.s_b2
+ pAddress->S_un.S_un_b.s_b3
+ pAddress->S_un.S_un_b.s_b4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -