📄 queryhashtable.cpp
字号:
//
// 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 + -