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

📄 queryhashtable.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// QueryHashTable.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 "QueryHashTable.h"
#include "QueryHashGroup.h"
#include "QueryHashMaster.h"

#include "QuerySearch.h"
#include "Neighbour.h"
#include "Buffer.h"
#include "G1Packet.h"
#include "G2Packet.h"
#include "XML.h"
#include "ZLib.h"
#include "SHA.h"
#include "ED2K.h"

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


//////////////////////////////////////////////////////////////////////
// CQueryHashTable construction

CQueryHashTable::CQueryHashTable()
{
	m_bLive		= FALSE;
	m_nCookie	= 0;
	m_pHash		= NULL;
	m_nHash		= 0;
	m_nBits		= 0;
	m_nInfinity	= 1;
	m_nCount	= 0;
	m_pBuffer	= new CBuffer();
	m_pGroup	= NULL;
}

CQueryHashTable::~CQueryHashTable()
{
	if ( m_pGroup ) QueryHashMaster.Remove( this );
	if ( m_pHash ) delete [] m_pHash;
	delete m_pBuffer;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable create

void CQueryHashTable::Create()
{
	BOOL bGrouped = m_pGroup != NULL;
	if ( bGrouped ) QueryHashMaster.Remove( this );
	
	if ( m_pHash ) delete [] m_pHash;
	
	m_bLive		= TRUE;
	m_nCookie	= GetTickCount();
	m_nBits		= Settings.Library.QueryRouteSize;
	m_nHash		= (int)pow( 2, m_nBits );
	m_pHash		= new BYTE[ ( m_nHash >> 3 ) + 1 ];
	m_nCount	= 0;
	
	FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
	
	if ( bGrouped ) QueryHashMaster.Add( this );
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable clear

void CQueryHashTable::Clear()
{
	if ( ! m_pHash ) return;
	
	BOOL bGrouped = m_pGroup != NULL;
	if ( bGrouped ) QueryHashMaster.Remove( this );
	
	m_nCookie	= GetTickCount();
	m_nCount	= 0;
	
	FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
	
	if ( bGrouped ) QueryHashMaster.Add( this );
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable merge tables

BOOL CQueryHashTable::Merge(CQueryHashTable* pSource)
{
	if ( m_pHash == NULL || pSource->m_pHash == NULL ) return FALSE;
	
	if ( m_nHash == pSource->m_nHash )
	{
		LPBYTE pSourcePtr	= pSource->m_pHash;
		LPBYTE pDestPtr		= m_pHash;
		
		for ( DWORD nPosition = m_nHash >> 3 ; nPosition ; nPosition-- )
		{
			register BYTE nSourceByte = *pSourcePtr;
			register BYTE nDestByte = *pDestPtr;
			
#define DO_MERGE(MASKVAL) \
			if ( ! ( nSourceByte & MASKVAL ) && ( nDestByte & MASKVAL ) ) \
			{ \
				*pDestPtr &= ~ MASKVAL; \
				m_nCount++; \
			}
			
			DO_MERGE(0x01); DO_MERGE(0x02); DO_MERGE(0x04); DO_MERGE(0x08);
			DO_MERGE(0x10); DO_MERGE(0x20); DO_MERGE(0x40); DO_MERGE(0x80);
#undef DO_MERGE
			
			pSourcePtr ++;
			pDestPtr ++;
		}
	}
	else
	{
		int nDestScale		= 1;
		int nSourceScale	= 1;
		
		if ( m_nHash > pSource->m_nHash )
		{
			for ( DWORD nIterate = pSource->m_nHash ; nIterate < m_nHash ; nIterate *= 2 ) nDestScale++;
			if ( nIterate != m_nHash ) return FALSE;
		}
		else if ( m_nHash < pSource->m_nHash )
		{
			for ( DWORD nIterate = m_nHash ; nIterate < pSource->m_nHash ; nIterate *= 2 ) nSourceScale++;
			if ( nIterate != pSource->m_nHash ) return FALSE;
		}
		
		LPBYTE pSourcePtr	= pSource->m_pHash;
		LPBYTE pDestPtr		= m_pHash;
		BYTE nSourceMask	= 0x01;
		BYTE nDestMask		= 0x01;
		
		for ( DWORD nDest = 0, nSource = 0 ; nDest < m_nHash && nSource < pSource->m_nHash ; )
		{
			BOOL bValue = TRUE;
			
			for ( int nSample = 0 ; nSample < nSourceScale ; nSample++, nSource++ )
			{
				if ( ( *pSourcePtr & nSourceMask ) == 0 ) bValue = FALSE;
				
				if ( nSourceMask == 0x80 )
				{
					nSourceMask = 0x01;
					pSourcePtr ++;
				}
				else
				{
					nSourceMask <<= 1;
				}
			}
			
			for ( nSample = 0 ; nSample < nDestScale ; nSample++, nDest++ )
			{
				if ( ! bValue && ( *pDestPtr & nDestMask ) )
				{
					*pDestPtr &= ~nDestMask;
					m_nCount++;
				}
				
				if ( nDestMask == 0x80 )
				{
					nDestMask = 0x01;
					pDestPtr ++;
				}
				else
				{
					nDestMask <<= 1;
				}
			}
		}
	}
	
	m_nCookie = GetTickCount();
	
	return TRUE;
}

BOOL CQueryHashTable::Merge(CQueryHashGroup* pSource)
{
	if ( m_pHash == NULL || pSource->m_pHash == NULL ) return FALSE;
	
	if ( m_nHash == pSource->m_nHash )
	{
		LPBYTE pSourcePtr	= pSource->m_pHash;
		LPBYTE pDestPtr		= m_pHash;
		
		for ( DWORD nPosition = m_nHash >> 3 ; nPosition ; nPosition-- )
		{
			register BYTE nDestByte = *pDestPtr;
			
#define DO_MERGE(MASKVAL) \
			if ( *pSourcePtr++ && ( nDestByte & MASKVAL ) ) \
			{ \
				*pDestPtr &= ~ MASKVAL; \
				m_nCount++; \
			}
			
			DO_MERGE(0x01); DO_MERGE(0x02); DO_MERGE(0x04); DO_MERGE(0x08);
			DO_MERGE(0x10); DO_MERGE(0x20); DO_MERGE(0x40); DO_MERGE(0x80);
#undef DO_MERGE
			
			pDestPtr++;
		}
	}
	else
	{
		int nDestScale		= 1;
		int nSourceScale	= 1;
		
		if ( m_nHash > pSource->m_nHash )
		{
			for ( DWORD nIterate = pSource->m_nHash ; nIterate < m_nHash ; nIterate *= 2 ) nDestScale++;
			if ( nIterate != m_nHash ) return FALSE;
		}
		else if ( m_nHash < pSource->m_nHash )
		{
			for ( DWORD nIterate = m_nHash ; nIterate < pSource->m_nHash ; nIterate *= 2 ) nSourceScale++;
			if ( nIterate != pSource->m_nHash ) return FALSE;
		}
		
		LPBYTE pSourcePtr	= pSource->m_pHash;
		LPBYTE pDestPtr		= m_pHash;
		BYTE nDestMask		= 0x01;
		
		for ( DWORD nDest = 0, nSource = 0 ; nDest < m_nHash && nSource < pSource->m_nHash ; )
		{
			BOOL bValue = TRUE;
			
			for ( int nSample = 0 ; nSample < nSourceScale ; nSample++, nSource++ )
			{
				if ( *pSourcePtr++ ) bValue = FALSE;
			}
			
			for ( nSample = 0 ; nSample < nDestScale ; nSample++, nDest++ )
			{
				if ( ! bValue && ( *pDestPtr & nDestMask ) )
				{
					*pDestPtr &= ~nDestMask;
					m_nCount++;
				}
				
				if ( nDestMask == 0x80 )
				{
					nDestMask = 0x01;
					pDestPtr ++;
				}
				else
				{
					nDestMask <<= 1;
				}
			}
		}
	}
	
	m_nCookie = GetTickCount();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CQueryHashTable packet patch dispatch

BOOL CQueryHashTable::PatchTo(CQueryHashTable* pTarget, CNeighbour* pNeighbour)
{
	if ( pTarget->m_pHash == NULL ) return FALSE;
	if ( m_nCookie == pTarget->m_nCookie ) return FALSE;
	
	m_nCookie	= pTarget->m_nCookie;
	m_nCount	= pTarget->m_nCount;
	
	BOOL bChanged = FALSE;
	
	if ( m_pHash == NULL || m_nHash != pTarget->m_nHash )
	{
		if ( m_pHash ) delete [] m_pHash;
		m_pHash = NULL;
		
		m_nBits		= pTarget->m_nBits;
		m_nHash		= pTarget->m_nHash;
		m_pHash		= new BYTE[ ( m_nHash >> 3 ) + 1 ];
		
		FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
		
		if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
		{
			CG1Packet* pReset = CG1Packet::New( G1_PACKET_QUERY_ROUTE, 1 );
			pReset->WriteByte( 0 );
			pReset->WriteLongLE( m_nHash );
			pReset->WriteByte( 2 );
			pNeighbour->Send( pReset );
		}
		else
		{
			CG2Packet* pReset = CG2Packet::New( G2_PACKET_QHT );
			pReset->WriteByte( 0 );
			pReset->WriteLongBE( m_nHash );
			pReset->WriteByte( 1 );
			pNeighbour->Send( pReset );
		}
		
		bChanged = TRUE;
	}
	
	BYTE nBits = 4;
	
	if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
	{
		nBits = 1;
	}
	else if ( pNeighbour->m_sUserAgent.Find( _T("Shareaza") ) == 0 )
	{
		LPCTSTR pszAgent = pNeighbour->m_sUserAgent;
		
		if (	_tcsstr( pszAgent, _T(" 1.3") ) ||
				_tcsstr( pszAgent, _T(" 1.2") ) ||
				_tcsstr( pszAgent, _T(" 1.1") ) ||
				_tcsstr( pszAgent, _T(" 1.0") ) )
		{
			return PatchToOldShareaza( pTarget, pNeighbour );
		}
		
		if (	_tcsstr( pszAgent, _T(" 1.4") ) == NULL &&
				_tcsstr( pszAgent, _T(" 1.5") ) == NULL &&
				_tcsstr( pszAgent, _T(" 1.6.0") ) == NULL )
		{
			nBits = 1;
		}
	}
	
	BYTE* pBuffer	= new BYTE[ m_nHash / ( 8 / nBits ) ];
	BYTE* pHashT	= pTarget->m_pHash;
	BYTE* pHashS	= m_pHash;
	BYTE  nMask		= 1;
	
	if ( nBits == 4 )
	{
		for ( DWORD nPosition = 0 ; nPosition < m_nHash ; nPosition++ )
		{
			BYTE nPatch = 0;
			
			if ( ( *pHashT & nMask ) == ( *pHashS & nMask ) )
			{
			}
			else if ( ( *pHashT & nMask ) )
			{
				nPatch = 1;
				*pHashS = ( *pHashS & ~nMask ) | ( *pHashT & nMask );
			}
			else
			{
				nPatch = 15;
				*pHashS = ( *pHashS & ~nMask ) | ( *pHashT & nMask );
			}
			
			if ( nPosition & 1 )
				pBuffer[ nPosition >> 1 ] |= nPatch;
			else
				pBuffer[ nPosition >> 1 ] = nPatch << 4;
			
			if ( nMask == 0x80 )
			{
				pHashS++;
				pHashT++;
				nMask = 1;
			}
			else
			{
				nMask <<= 1;
			}
			
			if ( nPatch ) bChanged = TRUE;
		}
	}
	else
	{
		ZeroMemory( pBuffer, m_nHash >> 3 );
		BYTE* pOutput = pBuffer;
		
		for ( DWORD nPosition = m_nHash ; nPosition ; nPosition-- )
		{
			if ( ( *pHashT & nMask ) != ( *pHashS & nMask ) )
			{
				*pOutput |= nMask;
				bChanged = TRUE;
			}
			
			*pHashS = ( *pHashS & ~nMask ) | ( *pHashT & nMask );
			
			if ( nMask == 0x80 )
			{
				pOutput++;
				pHashS++;
				pHashT++;
				nMask = 1;
			}
			else
			{
				nMask <<= 1;
			}
		}
	}
	
	if ( bChanged == FALSE && m_bLive )
	{
		delete [] pBuffer;
		return FALSE;
	}
	
	DWORD nCompress = 0;
	BYTE* pCompress = CZLib::Compress( pBuffer, m_nHash / ( 8 / nBits ), &nCompress );
	
	delete [] pBuffer;
	
	if ( pCompress == NULL ) return FALSE;
	
	DWORD nPacketSize	= 1024;
	BYTE nSequenceMax	= (BYTE)( nCompress / nPacketSize );
	if ( nCompress % nPacketSize ) nSequenceMax++;

	pBuffer = pCompress;

	for ( BYTE nSequence = 1 ; nSequence <= nSequenceMax ; nSequence++ )
	{
		CPacket* pPatch = NULL;

		if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
			pPatch = CG1Packet::New( G1_PACKET_QUERY_ROUTE, 1 );
		else
			pPatch = CG2Packet::New( G2_PACKET_QHT );

		pPatch->WriteByte( 1 );
		pPatch->WriteByte( nSequence );
		pPatch->WriteByte( nSequenceMax );
		pPatch->WriteByte( 1 );
		pPatch->WriteByte( nBits );

		DWORD nPacket = min( nCompress, nPacketSize );

		pPatch->Write( pBuffer, nPacket );

		pBuffer += nPacket;
		nCompress -= nPacket;

		pNeighbour->Send( pPatch );
	}
	
	delete [] pCompress;
	m_bLive = TRUE;
	
	return TRUE;
}

BOOL CQueryHashTable::PatchToOldShareaza(CQueryHashTable* pTarget, CNeighbour* pNeighbour)
{ 
	DWORD nPacketSize = 4096;

	BYTE* pBuffer	= new BYTE[ nPacketSize ];
	BYTE* pHashT	= pTarget->m_pHash;
	BYTE* pHashS	= m_pHash;
	DWORD nPosition	= 0;

	for ( BYTE nSequence = 1 ; nPosition < m_nHash ; nSequence++ )
	{
		CG1Packet* pPatch = CG1Packet::New( G1_PACKET_QUERY_ROUTE, 1 );

		pPatch->WriteByte( 1 );
		pPatch->WriteByte( nSequence );
		pPatch->WriteByte( (BYTE)( m_nHash / nPacketSize ) );
		pPatch->WriteByte( 1 );
		pPatch->WriteByte( 4 );

		BYTE nMask = 1;

		for ( DWORD nCount = 0 ; nCount < nPacketSize ; nCount++, nPosition++ )
		{
			BYTE nPatch = ( *pHashT & nMask ) != ( *pHashS & nMask ) ? 7 : 0;

			*pHashS = ( *pHashS & ~nMask ) | ( *pHashT & nMask );

⌨️ 快捷键说明

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