📄 hostcache.cpp
字号:
CHostCacheHost** pHash = m_pHash + nHash;
for ( CHostCacheHost* pHost = *pHash ; pHost ; pHost = pHost->m_pNextHash )
{
if ( pHost->m_pAddress.S_un.S_addr == pAddress->S_un.S_addr &&
( ! nPort || pHost->m_nPort == nPort ) )
{
if ( pHost->m_bPriority ) return;
/*
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;
pHost->m_pPrevTime = NULL;
pHost->m_pNextTime = m_pOldest;
if ( m_pOldest )
m_pOldest->m_pPrevTime = pHost;
else
m_pNewest = pHost;
m_pOldest = pHost;
pHost->m_tFailure = time( NULL );
*/
Remove( pHost );
break;
}
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList query acknowledgement prune
void CHostCacheList::PruneByQueryAck()
{
DWORD tNow = time( NULL );
for ( CHostCacheHost* pHost = m_pNewest ; pHost ; )
{
CHostCacheHost* pNext = pHost->m_pPrevTime;
if ( pHost->m_tAck )
{
if ( tNow - pHost->m_tAck > Settings.Gnutella2.QueryHostDeadline )
{
pHost->m_tAck = 0;
if ( pHost->m_nFailures++ > 3 ) Remove( pHost );
}
}
pHost = pNext;
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList serialize
void CHostCacheList::Serialize(CArchive& ar, int nVersion)
{
if ( ar.IsStoring() )
{
ar.WriteCount( m_nHosts );
for ( CHostCacheHost* pHost = m_pOldest ; pHost ; pHost = pHost->m_pNextTime )
{
pHost->Serialize( ar, nVersion );
}
}
else
{
int nItem, nCount = ar.ReadCount();
for ( nItem = 0 ; nItem < nCount && m_pFree ; nItem++ )
{
CHostCacheHost* pHost = m_pFree;
m_pFree = m_pFree->m_pNextHash;
m_nHosts++;
pHost->Reset( NULL );
pHost->Serialize( ar, nVersion );
if ( m_pOldest == NULL ) m_pOldest = pHost;
if ( m_pNewest )
{
m_pNewest->m_pNextTime = pHost;
pHost->m_pPrevTime = m_pNewest;
m_pNewest = pHost;
}
else m_pNewest = pHost;
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** pHash = m_pHash + nHash;
pHost->m_pNextHash = *pHash;
*pHash = pHost;
}
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList root import
int CHostCacheList::Import(LPCTSTR pszFile)
{
CFile pFile;
if ( ! pFile.Open( pszFile, CFile::modeRead ) ) return 0;
if ( _tcsistr( pszFile, _T(".met") ) != NULL )
{
return ImportMET( &pFile );
}
else
{
return 0;
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheList MET import
int CHostCacheList::ImportMET(CFile* pFile)
{
CSingleLock pLock( &Network.m_pSection, TRUE );
BYTE nVersion = 0;
pFile->Read( &nVersion, sizeof(nVersion) );
if ( nVersion != 0xE0 && nVersion != 0x0E ) return FALSE;
int nServers = 0;
UINT nCount = 0;
pFile->Read( &nCount, sizeof(nCount) );
while ( nCount-- > 0 )
{
IN_ADDR pAddress;
WORD nPort;
UINT nTags;
if ( pFile->Read( &pAddress, sizeof(pAddress) ) != sizeof(pAddress) ) break;
if ( pFile->Read( &nPort, sizeof(nPort) ) != sizeof(nPort) ) break;
if ( pFile->Read( &nTags, sizeof(nTags) ) != sizeof(nTags) ) break;
CHostCacheHost* pServer = Add( &pAddress, nPort );
while ( nTags-- > 0 )
{
CEDTag pTag;
if ( ! pTag.Read( pFile ) ) break;
if ( pServer == NULL ) continue;
if ( pTag.Check( ED2K_ST_SERVERNAME, ED2K_TAG_STRING ) )
{
pServer->m_sName = pTag.m_sValue;
}
else if ( pTag.Check( ED2K_ST_DESCRIPTION, ED2K_TAG_STRING ) )
{
pServer->m_sDescription = pTag.m_sValue;
}
else if ( pTag.Check( ED2K_ST_MAXUSERS, ED2K_TAG_INT ) )
{
pServer->m_nUserLimit = pTag.m_nValue;
}
}
nServers++;
}
return nServers;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost construction
CHostCacheHost::CHostCacheHost()
{
m_pNextHash = m_pPrevTime = m_pNextTime = NULL;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost serialize
void CHostCacheHost::Serialize(CArchive& ar, int nVersion)
{
if ( ar.IsStoring() )
{
ar.Write( &m_pAddress, sizeof(m_pAddress) );
ar << m_nPort;
ar << m_tAdded;
ar << m_tSeen;
ar << m_tRetryAfter;
if ( m_pVendor != NULL && m_pVendor->m_sCode.GetLength() == 4 )
{
ar << (CHAR)m_pVendor->m_sCode.GetAt( 0 );
ar << (CHAR)m_pVendor->m_sCode.GetAt( 1 );
ar << (CHAR)m_pVendor->m_sCode.GetAt( 2 );
ar << (CHAR)m_pVendor->m_sCode.GetAt( 3 );
}
else
{
CHAR cZero = 0;
ar << cZero;
}
ar << m_sName;
if ( m_sName.GetLength() )
{
ar << m_sDescription;
ar << m_nUserCount;
ar << m_nUserLimit;
ar << m_bPriority;
}
ar << m_nKeyValue;
if ( m_nKeyValue != 0 )
{
ar << m_tKeyTime;
ar << m_nKeyHost;
}
}
else
{
ar.Read( &m_pAddress, sizeof(m_pAddress) );
ar >> m_nPort;
ar >> m_tAdded;
ar >> m_tSeen;
ar >> m_tRetryAfter;
CHAR szaVendor[4] = { 0, 0, 0, 0 };
ar >> szaVendor[0];
if ( szaVendor[0] )
{
ar.Read( szaVendor + 1, 3 );
TCHAR szVendor[5] = { szaVendor[0], szaVendor[1], szaVendor[2], szaVendor[3], 0 };
m_pVendor = VendorCache.Lookup( szVendor );
}
if ( nVersion >= 7 )
{
ar >> m_sName;
if ( m_sName.GetLength() )
{
ar >> m_sDescription;
ar >> m_nUserCount;
if ( nVersion >= 8 ) ar >> m_nUserLimit;
if ( nVersion >= 9 ) ar >> m_bPriority;
}
}
ar >> m_nKeyValue;
if ( m_nKeyValue != 0 )
{
ar >> m_tKeyTime;
ar >> m_nKeyHost;
}
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost reset
void CHostCacheHost::Reset(IN_ADDR* pAddress)
{
if ( pAddress ) m_pAddress = *pAddress;
m_pVendor = NULL;
m_bPriority = FALSE;
m_nUserCount = 0;
m_nUserLimit = 0;
m_sName.Empty();
m_sDescription.Empty();
m_tAdded = GetTickCount();
m_tSeen = 0;
m_tRetryAfter = 0;
m_tConnect = 0;
m_tQuery = 0;
m_tAck = 0;
m_tFailure = 0;
m_nFailures = 0;
m_tKeyTime = 0;
m_nKeyValue = 0;
m_nKeyHost = 0;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost update
void CHostCacheHost::Update(WORD nPort, DWORD tSeen, LPCTSTR pszVendor)
{
m_nPort = nPort;
m_tSeen = tSeen > 1 ? tSeen : time( NULL );
if ( pszVendor != NULL )
{
if ( m_pVendor == NULL || m_pVendor->m_sCode != pszVendor )
{
m_pVendor = VendorCache.Lookup( pszVendor );
}
}
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost connection setup
CNeighbour* CHostCacheHost::ConnectTo(BOOL bAutomatic)
{
m_tConnect = time( NULL );
if ( bAutomatic && Network.IsFirewalledAddress( &m_pAddress, TRUE ) ) return NULL;
return Neighbours.ConnectTo( &m_pAddress, m_nPort, m_nProtocol, bAutomatic );
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost packet conversion
CG1Packet* CHostCacheHost::ToG1Ping(int nTTL, GGUID* pGUID)
{
CG1Packet* pPong = CG1Packet::New( G1_PACKET_PONG, nTTL, pGUID );
pPong->WriteShortLE( m_nPort );
pPong->WriteLongLE( *(DWORD*)&m_pAddress );
pPong->WriteLongLE( 0 );
pPong->WriteLongLE( 0 );
return pPong;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost string
CString CHostCacheHost::ToString() const
{
struct tm* pTime = gmtime( (time_t*)&m_tSeen );
CString str; // 2002-04-30T08:30Z
str.Format( _T("%s:%i %.4i-%.2i-%.2iT%.2i:%.2iZ"),
(LPCTSTR)CString( inet_ntoa( m_pAddress ) ), m_nPort,
pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
pTime->tm_hour, pTime->tm_min );
return str;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost connection test
BOOL CHostCacheHost::CanConnect(DWORD tNow) const
{
if ( ! m_tConnect ) return TRUE;
if ( m_pAddress.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
if ( ! tNow ) tNow = time( NULL );
return tNow - m_tConnect >= Settings.Gnutella.ConnectThrottle;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost quote test
BOOL CHostCacheHost::CanQuote(DWORD tNow) const
{
if ( ! tNow ) tNow = time( NULL );
return tNow - m_tSeen < Settings.Gnutella.HostCacheExpire;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost query test
BOOL CHostCacheHost::CanQuery(DWORD tNow) const
{
// eDonkey2000 server
if ( m_nProtocol == PROTOCOL_ED2K )
{
// Must support ED2K
if ( ! Settings.eDonkey.EnableToday ) return FALSE;
if ( ! Settings.eDonkey.ServerWalk ) return FALSE;
// Get the time if not supplied
if ( 0 == tNow ) tNow = time( NULL );
// Retry After
if ( 0 != m_tRetryAfter && tNow < m_tRetryAfter ) return FALSE;
// If haven't queried yet, its ok
if ( 0 == m_tQuery ) return TRUE;
// Don't query too fast
return ( tNow - m_tQuery ) >= Settings.eDonkey.QueryServerThrottle;
}
else if ( m_nProtocol == PROTOCOL_G2 )
{
// Must support G2
if ( ! Settings.Gnutella2.EnableToday ) return FALSE;
// Must not be waiting for an ack
if ( 0 != m_tAck ) return FALSE;
// Get the time if not supplied
if ( 0 == tNow ) tNow = time( NULL );
// Must not have expired from host cache
if ( ( tNow - m_tSeen ) > Settings.Gnutella.HostCacheExpire ) return FALSE;
// Retry After
if ( 0 != m_tRetryAfter && tNow < m_tRetryAfter ) return FALSE;
// If haven't queried yet, its ok
if ( 0 == m_tQuery ) return TRUE;
// Don't query too fast
return ( tNow - m_tQuery ) >= max( Settings.Gnutella2.QueryHostThrottle, 60 );
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CHostCacheHost query key submission
void CHostCacheHost::SetKey(DWORD nKey, IN_ADDR* pHost)
{
m_tAck = 0;
m_nFailures = 0;
m_tKeyTime = nKey ? time( NULL ) : 0;
m_nKeyValue = nKey;
m_nKeyHost = pHost && nKey ? pHost->S_un.S_addr : Network.m_pHost.sin_addr.S_un.S_addr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -