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

📄 searchmanager.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// SearchManager.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 "SearchManager.h"
#include "ManagedSearch.h"
#include "QuerySearch.h"
#include "QueryHit.h"
#include "HostCache.h"
#include "G2Packet.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

CSearchManager SearchManager;


//////////////////////////////////////////////////////////////////////
// CSearchManager construction

CSearchManager::CSearchManager()
{
	m_tLastTick = 0;

	m_nPriorityClass = 0;
	m_nPriorityCount = 0;
}

CSearchManager::~CSearchManager()
{
}

//////////////////////////////////////////////////////////////////////
// CSearchManager add and remove

void CSearchManager::Add(CManagedSearch* pSearch)
{
	POSITION pos = m_pList.Find( pSearch );
	if ( pos == NULL ) m_pList.AddHead( pSearch );
}

void CSearchManager::Remove(CManagedSearch* pSearch)
{
	POSITION pos = m_pList.Find( pSearch );
	if ( pos != NULL ) m_pList.RemoveAt( pos );
}

//////////////////////////////////////////////////////////////////////
// CSearchManager list access

POSITION CSearchManager::GetIterator() const
{
	return m_pList.GetHeadPosition();
}

CManagedSearch* CSearchManager::GetNext(POSITION& pos) const
{
	return (CManagedSearch*)m_pList.GetNext( pos );
}

int CSearchManager::GetCount() const
{
	return m_pList.GetCount();
}

CManagedSearch* CSearchManager::Find(GGUID* pGUID)
{
	for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
	{
		CManagedSearch* pSearch = (CManagedSearch*)m_pList.GetNext( pos );
		if ( pSearch->m_pSearch->m_pGUID == *pGUID ) return pSearch;
	}
	
	return NULL;
}

//////////////////////////////////////////////////////////////////////
// CSearchManager run event (FROM CNetwork THREAD)

void CSearchManager::OnRun()
{
	DWORD tNow = GetTickCount();
	if ( tNow - m_tLastTick < Settings.Gnutella2.QueryGlobalThrottle ) return;
	m_tLastTick = tNow;

	if ( ! Network.IsWellConnected() ) return;
	
	HostCache.Gnutella2.PruneByQueryAck();
	
	CSingleLock pLock( &m_pSection );
	if ( ! pLock.Lock( 100 ) ) return;

	static int nPriorityFactor[ 3 ] = { 8, 4, 1 };
	
	if ( m_nPriorityCount >= nPriorityFactor[ m_nPriorityClass ] )
	{
		m_nPriorityCount = 0;
		m_nPriorityClass = ( m_nPriorityClass + 1 ) % CManagedSearch::spMax;
	}

	for ( int nClass = 0 ; nClass <= CManagedSearch::spMax ; nClass++ )
	{
		for ( POSITION pos = GetIterator() ; pos ; )
		{
			POSITION posCur = pos;
			CManagedSearch* pSearch = GetNext( pos );
			
			if ( pSearch->m_nPriority == m_nPriorityClass && pSearch->Execute() )
			{
				m_pList.RemoveAt( posCur );
				m_pList.AddTail( pSearch );
				m_nPriorityCount++;
				return;
			}
		}

		m_nPriorityCount = 0;
		m_nPriorityClass = ( m_nPriorityClass + 1 ) % CManagedSearch::spMax;
	}
}

//////////////////////////////////////////////////////////////////////
// CSearchManager query acknowledgement

BOOL CSearchManager::OnQueryAck(CG2Packet* pPacket, SOCKADDR_IN* pHost, GGUID* ppGUID)
{
	if ( ! pPacket->m_bCompound ) return FALSE;
	
	DWORD nFromIP = pHost->sin_addr.S_un.S_addr;
	DWORD tAdjust = 0, tNow = time( NULL );
	DWORD nHubs = 0, nLeaves = 0;
	CDWordArray pDone;
	
	CHAR szType[9];
	DWORD nLength;
	
	theApp.Message( MSG_DEBUG, _T("Processing query acknowledge from %s:"),
		(LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
	
	while ( pPacket->ReadPacket( szType, nLength ) )
	{
		DWORD nOffset = pPacket->m_nPosition + nLength;
		
		if ( strcmp( szType, "D" ) == 0 && nLength >= 4 )
		{
			DWORD nAddress = pPacket->ReadLongLE();
			pDone.Add( nAddress );
			
			if ( nLength >= 6 )
			{
				WORD nPort = pPacket->ReadShortBE();
				
				if ( ! Network.IsFirewalledAddress( &nAddress, TRUE ) && nPort )
				{
					HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, tNow );
				}
			}
			
			if ( nLength >= 8 ) nLeaves += pPacket->ReadShortBE();
			nHubs ++;
			
			theApp.Message( MSG_DEBUG, _T("  Done %s"),
				(LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ) );
		}
		else if ( strcmp( szType, "S" ) == 0 && nLength >= 6 )
		{
			DWORD nAddress	= pPacket->ReadLongLE();
			WORD nPort		= pPacket->ReadShortBE();
			DWORD tSeen		= ( nLength >= 10 ) ? pPacket->ReadLongBE() + tAdjust : tNow;
			
			theApp.Message( MSG_DEBUG, _T("  Try %s:%lu"),
				(LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ), nPort );
			
			if ( ! Network.IsFirewalledAddress( &nAddress, TRUE ) && nPort )
			{
				HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, min( tNow, tSeen ) );
			}
		}
		else if ( strcmp( szType, "TS" ) == 0 && nLength == 4 )
		{
			tAdjust = (LONG)tNow - (LONG)pPacket->ReadLongBE();
		}
		else if ( strcmp( szType, "RA" ) == 0 && nLength >= 2 )
		{
			DWORD nRetryAfter = 0;
			
			if ( nLength >= 4 )
			{
				nRetryAfter = pPacket->ReadLongBE();
			}
			else if ( nLength >= 2 )
			{
				nRetryAfter = pPacket->ReadShortBE();
			}
			
			if ( CHostCacheHost* pHost = HostCache.Gnutella2.Find( (IN_ADDR*)&nFromIP ) )
			{
				pHost->m_tRetryAfter = tNow + nRetryAfter;
			}
		}
		else if ( strcmp( szType, "FR" ) == 0 && nLength >= 4 )
		{
			nFromIP = pPacket->ReadLongLE();
		}
		
		pPacket->m_nPosition = nOffset;
	}
	
	if ( pPacket->GetRemaining() < 16 ) return FALSE;
	
	GGUID pGUID;
	pPacket->Read( &pGUID, sizeof(GGUID) );
	if ( ppGUID ) *ppGUID = pGUID;
	
	CSingleLock pLock( &m_pSection );
	
	if ( pLock.Lock( 100 ) )
	{
		if ( CManagedSearch* pSearch = Find( &pGUID ) )
		{
			pSearch->m_nHubs += nHubs;
			pSearch->m_nLeaves += nLeaves;
			
			// (technically not required, but..)
			pSearch->OnHostAcknowledge( nFromIP );
			
			for ( int nItem = 0 ; nItem < pDone.GetSize() ; nItem++ )
			{
				DWORD nAddress = pDone.GetAt( nItem );
				pSearch->OnHostAcknowledge( nAddress );
			}
			
			return FALSE;
		}
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CSearchManager query hits

BOOL CSearchManager::OnQueryHits(CQueryHit* pHits)
{
	CSingleLock pLock( &m_pSection );
	if ( ! pLock.Lock( 100 ) ) return TRUE;
	
	CManagedSearch* pSearch = Find( &pHits->m_pSearchID );
	if ( pSearch == NULL ) return TRUE;
	
	pSearch->OnHostAcknowledge( *(DWORD*)&pHits->m_pAddress );
	
	while ( pHits != NULL )
	{
		pSearch->m_nHits ++;
		pHits = pHits->m_pNext;
	}
	
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// CSearchManager query status request

WORD CSearchManager::OnQueryStatusRequest(GGUID* pGUID)
{
	CSingleLock pLock( &m_pSection );
	if ( ! pLock.Lock( 100 ) ) return 0xFFFF;
	
	CManagedSearch* pSearch = Find( pGUID );
	if ( pSearch == NULL ) return 0xFFFF;
	
	return (WORD)min( 0xFFFE, pSearch->m_nHits );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -