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

📄 queryhit.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// QueryHit.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 "QuerySearch.h"
#include "QueryHit.h"
#include "Network.h"
#include "G1Packet.h"
#include "G2Packet.h"
#include "EDPacket.h"
#include "Transfer.h"
#include "SchemaCache.h"
#include "Schema.h"
#include "ZLib.h"
#include "XML.h"
#include "GGEP.h"
#include "VendorCache.h"
#include "RouteCache.h"

#include "SHA.h"
#include "TigerTree.h"
#include "ED2K.h"

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


//////////////////////////////////////////////////////////////////////
// CQueryHit construction

CQueryHit::CQueryHit(PROTOCOLID nProtocol, GGUID* pSearchID)
{
	m_pNext = NULL;
	
	if ( pSearchID != NULL )
		m_pSearchID = *pSearchID;
	else
		m_pSearchID = (GGUID&)GUID_NULL;
	
	m_nProtocol		= nProtocol;
	m_pClientID		= (GGUID&)GUID_NULL;
	m_pAddress.S_un.S_addr = 0;
	m_nPort			= 0;
	m_nSpeed		= 0;
	m_pVendor		= VendorCache.m_pNull;
	
	m_bPush			= TS_UNKNOWN;
	m_bBusy			= TS_UNKNOWN;
	m_bStable		= TS_UNKNOWN;
	m_bMeasured		= TS_UNKNOWN;
	m_bChat			= FALSE;
	m_bBrowseHost	= FALSE;
	
	m_nGroup		= 0;
	m_bSHA1			= FALSE;
	m_bTiger		= FALSE;
	m_bED2K			= FALSE;
	m_bBTH			= FALSE;
	m_nIndex		= 0;
	m_bSize			= FALSE;
	m_nSize			= 0;
	m_nSources		= 0;
	m_nPartial		= 0;
	m_bPreview		= FALSE;
	m_nUpSlots		= 0;
	m_nUpQueue		= 0;	
	m_bCollection	= FALSE;
	
	m_pXML			= NULL;
	m_nRating		= 0;
	
	m_bBogus		= FALSE;
	m_bMatched		= FALSE;
	m_bFiltered		= FALSE;
	m_bDownload		= FALSE;
	m_bNew			= FALSE;
	m_bSelected		= FALSE;
	m_bResolveURL	= TRUE;
}

CQueryHit::~CQueryHit()
{
	if ( m_pXML ) delete m_pXML;
}

//////////////////////////////////////////////////////////////////////
// CQueryHit from G1 packet

CQueryHit* CQueryHit::FromPacket(CG1Packet* pPacket, int* pnHops)
{
	CQueryHit* pFirstHit	= NULL;
	CQueryHit* pLastHit		= NULL;
	CXMLElement* pXML		= NULL;
	GGUID pQueryID;
	
	if ( pPacket->m_nProtocol == PROTOCOL_G2 )
	{
		GNUTELLAPACKET pG1;
		if ( ! ((CG2Packet*)pPacket)->SeekToWrapped() ) return NULL;
		pPacket->Read( &pG1, sizeof(pG1) );
		
		pQueryID = pG1.m_pGUID;
		if ( pnHops ) *pnHops = pG1.m_nHops + 1;
	}
	else
	{
		pQueryID = pPacket->m_pGUID;
		if ( pnHops ) *pnHops = pPacket->m_nHops + 1;
	}
	
	try
	{
		BYTE	nCount		= pPacket->ReadByte();
		WORD	nPort		= pPacket->ReadShortLE();
		DWORD	nAddress	= pPacket->ReadLongLE();
		DWORD	nSpeed		= pPacket->ReadLongLE();
		
		if ( ! nCount ) AfxThrowUserException();
		
		while ( nCount-- )
		{
			CQueryHit* pHit = new CQueryHit( PROTOCOL_G1, &pQueryID );
			if ( pFirstHit ) pLastHit->m_pNext = pHit;
			else pFirstHit = pHit;
			pLastHit = pHit;
			
			pHit->m_pAddress	= (IN_ADDR&)nAddress;
			pHit->m_nPort		= nPort;
			pHit->m_nSpeed		= nSpeed;
			
			pHit->ReadG1Packet( pPacket );
		}

		CVendor*	pVendor		= VendorCache.m_pNull;
		BYTE		nPublicSize	= 0;
		BYTE		nFlags[2]	= { 0, 0 };
		WORD		nXMLSize	= 0;
		BOOL		bChat		= FALSE;
		BOOL		bBrowseHost	= FALSE;

		if ( pPacket->GetRemaining() >= 16 + 5 )
		{
			CHAR szaVendor[ 4 ];
			pPacket->Read( szaVendor, 4 );
			TCHAR szVendor[5] = { szaVendor[0], szaVendor[1], szaVendor[2], szaVendor[3], 0 };
			
			pVendor		= VendorCache.Lookup( szVendor );
			nPublicSize	= pPacket->ReadByte();
		}
		
		if ( pVendor->m_bHTMLBrowse ) bBrowseHost = TRUE;
		
		if ( nPublicSize > pPacket->GetRemaining() - 16 ) AfxThrowUserException();
		
		if ( nPublicSize >= 2 )
		{
			nFlags[0]	= pPacket->ReadByte();
			nFlags[1]	= pPacket->ReadByte();
			nPublicSize -= 2;
		}
		
		if ( nPublicSize >= 2 )
		{
			nXMLSize = pPacket->ReadShortLE();
			nPublicSize -= 2;
			if ( nPublicSize + nXMLSize > pPacket->GetRemaining() - 16 ) AfxThrowUserException();
		}
		
		while ( nPublicSize-- ) pPacket->ReadByte();
		
		if ( pVendor->m_bChatFlag && pPacket->GetRemaining() >= 16 + nXMLSize + 1 )
		{
			bChat = pPacket->PeekByte() == 1;
		}
		
		if ( pPacket->GetRemaining() < 16 + nXMLSize ) nXMLSize = 0;
		
		if ( ( nFlags[0] & G1_QHD_GGEP ) && ( nFlags[1] & G1_QHD_GGEP ) &&
			 Settings.Gnutella1.EnableGGEP )
		{
			ReadGGEP( pPacket, &bBrowseHost );
		}
		
		if ( nXMLSize > 0 )
		{
			pPacket->Seek( 16 + nXMLSize, CG1Packet::seekEnd );
			pXML = ReadXML( pPacket, nXMLSize );
		}
		
		if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) )
		{
			nFlags[0] |= G1_QHD_PUSH;
			nFlags[1] |= G1_QHD_PUSH;
		}
		
		GGUID pClientID;
		
		pPacket->Seek( 16, CG1Packet::seekEnd );
		pPacket->Read( &pClientID, sizeof(pClientID) );
		
		DWORD nIndex = 0;
		
		for ( pLastHit = pFirstHit ; pLastHit ; pLastHit = pLastHit->m_pNext, nIndex++ )
		{
			pLastHit->ParseAttributes( &pClientID, pVendor, nFlags, bChat, bBrowseHost );
			pLastHit->Resolve();
			if ( pXML ) pLastHit->ParseXML( pXML, nIndex );
		}
		
		CheckBogus( pFirstHit );
	}
	catch ( CException* pException )
	{
		pException->Delete();
		if ( pXML ) delete pXML;
		if ( pFirstHit ) pFirstHit->Delete();
		return NULL;
	}
	
	if ( pXML ) delete pXML;
	
	return pFirstHit;
}

//////////////////////////////////////////////////////////////////////
// CQueryHit from G2 packet

CQueryHit* CQueryHit::FromPacket(CG2Packet* pPacket, int* pnHops)
{
	if ( pPacket->IsType( G2_PACKET_HIT_WRAP ) )
	{
		return FromPacket( (CG1Packet*)pPacket );
	}
	
	if ( ! pPacket->m_bCompound ) return NULL;
	
	CQueryHit* pFirstHit	= NULL;
	CQueryHit* pLastHit		= NULL;
	CXMLElement* pXML		= NULL;
	
	GGUID		pSearchID;
	GGUID		pClientID, pIncrID;
	BOOL		bClientID	= FALSE;
	
	DWORD		nAddress	= 0;
	WORD		nPort		= 0;
	BOOL		bBusy		= FALSE;
	BOOL		bPush		= FALSE;
	BOOL		bStable		= TRUE;
	BOOL		bBrowseHost	= FALSE;
	BOOL		bPeerChat	= FALSE;
	CVendor*	pVendor		= VendorCache.m_pNull;
	
	CString		strNick;
	DWORD		nGroupState[8][4];
	
	ZeroMemory( nGroupState, sizeof(nGroupState) );
	
	try
	{
		BOOL bCompound;
		CHAR szType[9];
		DWORD nLength;
		
		while ( pPacket->ReadPacket( szType, nLength, &bCompound ) )
		{
			DWORD nSkip = pPacket->m_nPosition + nLength;
			
			if ( bCompound )
			{
				if ( strcmp( szType, "H" ) &&
					 strcmp( szType, "HG" ) &&
					 strcmp( szType, "UPRO" ) )
				{
					pPacket->SkipCompound( nLength );
				}
			}
			
			if ( strcmp( szType, "H" ) == 0 && bCompound )
			{
				CQueryHit* pHit = new CQueryHit( PROTOCOL_G2);
				
				if ( pFirstHit ) pLastHit->m_pNext = pHit;
				else pFirstHit = pHit;
				pLastHit = pHit;
				
				pHit->ReadG2Packet( pPacket, nLength );
			}
			else if ( strcmp( szType, "HG" ) == 0 && bCompound )
			{
				DWORD nQueued = 0, nUploads = 0, nSpeed = 0;
				CHAR szInner[9];
				DWORD nInner;
				
				while ( pPacket->m_nPosition < nSkip && pPacket->ReadPacket( szInner, nInner ) )
				{
					DWORD nSkipInner = pPacket->m_nPosition + nInner;
					
					if ( strcmp( szInner, "SS" ) == 0 && nInner >= 7 )
					{
						nQueued		= pPacket->ReadShortBE();
						nUploads	= pPacket->ReadByte();
						nSpeed		= pPacket->ReadLongBE();
					}
					
					pPacket->m_nPosition = nSkipInner;
				}
				
				if ( pPacket->m_nPosition < nSkip && nSpeed > 0 )
				{
					int nGroup = pPacket->ReadByte();
					
					if ( nGroup >= 0 && nGroup < 8 )
					{
						nGroupState[ nGroup ][0] = TRUE;
						nGroupState[ nGroup ][1] = nQueued;
						nGroupState[ nGroup ][2] = nUploads;
						nGroupState[ nGroup ][3] = nSpeed;
					}
				}
			}
			else if ( strcmp( szType, "NH" ) == 0 && nLength >= 6 )
			{
				SOCKADDR_IN pHub;
				
				pHub.sin_addr.S_un.S_addr	= pPacket->ReadLongLE();
				pHub.sin_port				= htons( pPacket->ReadShortBE() );
				
				pIncrID.n[15] ++;
				Network.NodeRoute->Add( &pIncrID, &pHub );
			}
			else if ( strcmp( szType, "GU" ) == 0 && nLength == 16 )
			{
				pPacket->Read( &pClientID, sizeof(GGUID) );
				bClientID	= TRUE;
				pIncrID		= pClientID;
			}
			else if ( ( strcmp( szType, "NA" ) == 0 || strcmp( szType, "NI" ) == 0 ) && nLength >= 6 )
			{
				nAddress	= pPacket->ReadLongLE();
				nPort		= pPacket->ReadShortBE();
			}
			else if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
			{
				CString strVendor = pPacket->ReadString( 4 );
				pVendor = VendorCache.Lookup( strVendor );
			}
			else if ( strcmp( szType, "MD" ) == 0 )
			{
				CString strXML	= pPacket->ReadString( nLength );
				LPCTSTR pszXML	= strXML;
				
				while ( pszXML && *pszXML )
				{
					CXMLElement* pPart = CXMLElement::FromString( pszXML, TRUE );
					if ( ! pPart ) break;
					
					if ( ! pXML ) pXML = new CXMLElement( NULL, _T("Metadata") );
					pXML->AddElement( pPart );
					
					pszXML = _tcsstr( pszXML + 1, _T("<?xml") );
				}
			}
			else if ( strcmp( szType, "UPRO" ) == 0 && bCompound )
			{
				CHAR szInner[9];
				DWORD nInner;
				
				while ( pPacket->m_nPosition < nSkip && pPacket->ReadPacket( szInner, nInner ) )
				{
					DWORD nSkipInner = pPacket->m_nPosition + nInner;
					if ( strcmp( szInner, "NICK" ) == 0 )
					{
						strNick = pPacket->ReadString( nInner );
					}
					pPacket->m_nPosition = nSkipInner;
				}
			}
			else if ( strcmp( szType, "BH" ) == 0 )
			{
				bBrowseHost |= 1;
			}
			else if ( strcmp( szType, "BUP" ) == 0 )
			{
				bBrowseHost |= 2;
			}
			else if ( strcmp( szType, "PCH" ) == 0 )
			{
				bPeerChat = TRUE;
			}
			else if ( strcmp( szType, "BUSY" ) == 0 )
			{
				bBusy = TRUE;
			}
			else if ( strcmp( szType, "UNSTA" ) == 0 )
			{
				bStable = FALSE;
			}
			else if ( strcmp( szType, "FW" ) == 0 )
			{
				bPush = TRUE;
			}
			else if ( strcmp( szType, "SS" ) == 0 && nLength > 0 )
			{
				BYTE nStatus = pPacket->ReadByte();
				
				bBusy	= ( nStatus & G2_SS_BUSY ) ? TRUE : FALSE;
				bPush	= ( nStatus & G2_SS_PUSH ) ? TRUE : FALSE;
				bStable	= ( nStatus & G2_SS_STABLE ) ? TRUE : FALSE;
				
				if ( nLength >= 1+4+2+1 )
				{
					nGroupState[0][0] = TRUE;
					nGroupState[0][3] = pPacket->ReadLongBE();
					nGroupState[0][1] = pPacket->ReadShortBE();
					nGroupState[0][2] = pPacket->ReadByte();
				}
			}
			
			pPacket->m_nPosition = nSkip;
		}
		
		if ( ! bClientID ) AfxThrowUserException();
		if ( pPacket->GetRemaining() < 17 ) AfxThrowUserException();
		
		BYTE nHops = pPacket->ReadByte() + 1;
		if ( pnHops ) *pnHops = nHops;
		
		pPacket->Read( &pSearchID, sizeof(GGUID) );
		
		if ( ! bPush ) bPush = ( nPort == 0 || Network.IsFirewalledAddress( &nAddress ) );
		
		DWORD nIndex = 0;
		
		for ( pLastHit = pFirstHit ; pLastHit ; pLastHit = pLastHit->m_pNext, nIndex++ )
		{
			if ( nGroupState[ pLastHit->m_nGroup ][0] == FALSE ) pLastHit->m_nGroup = 0;
			
			pLastHit->m_pSearchID	= pSearchID;
			pLastHit->m_pClientID	= pClientID;
			pLastHit->m_pAddress	= *(IN_ADDR*)&nAddress;
			pLastHit->m_nPort		= nPort;
			pLastHit->m_pVendor		= pVendor;
			pLastHit->m_nSpeed		= nGroupState[ pLastHit->m_nGroup ][3];
			pLastHit->m_bBusy		= bBusy   ? TS_TRUE : TS_FALSE;
			pLastHit->m_bPush		= bPush   ? TS_TRUE : TS_FALSE;

⌨️ 快捷键说明

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