⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hostcache.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -