00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "QueryHashTable.h"
00026 #include "QueryHashGroup.h"
00027 #include "QueryHashMaster.h"
00028
00029 #include "QuerySearch.h"
00030 #include "Neighbour.h"
00031 #include "Buffer.h"
00032 #include "G1Packet.h"
00033 #include "G2Packet.h"
00034 #include "XML.h"
00035 #include "ZLib.h"
00036 #include "SHA.h"
00037 #include "ED2K.h"
00038
00039 #ifdef _DEBUG
00040 #undef THIS_FILE
00041 static char THIS_FILE[]=__FILE__;
00042 #define new DEBUG_NEW
00043 #endif
00044
00045
00047
00048
00049 CQueryHashTable::CQueryHashTable()
00050 {
00051 m_bLive = FALSE;
00052 m_nCookie = 0;
00053 m_pHash = NULL;
00054 m_nHash = 0;
00055 m_nBits = 0;
00056 m_nInfinity = 1;
00057 m_nCount = 0;
00058 m_pBuffer = new CBuffer();
00059 m_pGroup = NULL;
00060 }
00061
00062 CQueryHashTable::~CQueryHashTable()
00063 {
00064 if ( m_pGroup ) QueryHashMaster.Remove( this );
00065 if ( m_pHash ) delete [] m_pHash;
00066 delete m_pBuffer;
00067 }
00068
00070
00071
00072 void CQueryHashTable::Create()
00073 {
00074 BOOL bGrouped = m_pGroup != NULL;
00075 if ( bGrouped ) QueryHashMaster.Remove( this );
00076
00077 if ( m_pHash ) delete [] m_pHash;
00078
00079 m_bLive = TRUE;
00080 m_nCookie = GetTickCount();
00081 m_nBits = Settings.Library.QueryRouteSize;
00082 m_nHash = (int)pow( 2, m_nBits );
00083 m_pHash = new BYTE[ ( m_nHash >> 3 ) + 1 ];
00084 m_nCount = 0;
00085
00086 FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
00087
00088 if ( bGrouped ) QueryHashMaster.Add( this );
00089 }
00090
00092
00093
00094 void CQueryHashTable::Clear()
00095 {
00096 if ( ! m_pHash ) return;
00097
00098 BOOL bGrouped = m_pGroup != NULL;
00099 if ( bGrouped ) QueryHashMaster.Remove( this );
00100
00101 m_nCookie = GetTickCount();
00102 m_nCount = 0;
00103
00104 FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
00105
00106 if ( bGrouped ) QueryHashMaster.Add( this );
00107 }
00108
00110
00111
00112 BOOL CQueryHashTable::Merge(CQueryHashTable* pSource)
00113 {
00114 if ( m_pHash == NULL || pSource->m_pHash == NULL ) return FALSE;
00115
00116 if ( m_nHash == pSource->m_nHash )
00117 {
00118 LPBYTE pSourcePtr = pSource->m_pHash;
00119 LPBYTE pDestPtr = m_pHash;
00120
00121 for ( DWORD nPosition = m_nHash >> 3 ; nPosition ; nPosition-- )
00122 {
00123 register BYTE nSourceByte = *pSourcePtr;
00124 register BYTE nDestByte = *pDestPtr;
00125
00126 #define DO_MERGE(MASKVAL) \
00127 if ( ! ( nSourceByte & MASKVAL ) && ( nDestByte & MASKVAL ) ) \
00128 { \
00129 *pDestPtr &= ~ MASKVAL; \
00130 m_nCount++; \
00131 }
00132
00133 DO_MERGE(0x01); DO_MERGE(0x02); DO_MERGE(0x04); DO_MERGE(0x08);
00134 DO_MERGE(0x10); DO_MERGE(0x20); DO_MERGE(0x40); DO_MERGE(0x80);
00135 #undef DO_MERGE
00136
00137 pSourcePtr ++;
00138 pDestPtr ++;
00139 }
00140 }
00141 else
00142 {
00143 int nDestScale = 1;
00144 int nSourceScale = 1;
00145
00146 if ( m_nHash > pSource->m_nHash )
00147 {
00148 DWORD nIterate = pSource->m_nHash;
00149 for ( ; nIterate < m_nHash ; nIterate *= 2 ) nDestScale++;
00150 if ( nIterate != m_nHash ) return FALSE;
00151 }
00152 else if ( m_nHash < pSource->m_nHash )
00153 {
00154 DWORD nIterate = m_nHash;
00155 for ( ; nIterate < pSource->m_nHash ; nIterate *= 2 ) nSourceScale++;
00156 if ( nIterate != pSource->m_nHash ) return FALSE;
00157 }
00158
00159 LPBYTE pSourcePtr = pSource->m_pHash;
00160 LPBYTE pDestPtr = m_pHash;
00161 BYTE nSourceMask = 0x01;
00162 BYTE nDestMask = 0x01;
00163
00164 for ( DWORD nDest = 0, nSource = 0 ; nDest < m_nHash && nSource < pSource->m_nHash ; )
00165 {
00166 BOOL bValue = TRUE;
00167
00168 for ( int nSample = 0 ; nSample < nSourceScale ; nSample++, nSource++ )
00169 {
00170 if ( ( *pSourcePtr & nSourceMask ) == 0 ) bValue = FALSE;
00171
00172 if ( nSourceMask == 0x80 )
00173 {
00174 nSourceMask = 0x01;
00175 pSourcePtr ++;
00176 }
00177 else
00178 {
00179 nSourceMask <<= 1;
00180 }
00181 }
00182
00183 for ( int nSample = 0 ; nSample < nDestScale ; nSample++, nDest++ )
00184 {
00185 if ( ! bValue && ( *pDestPtr & nDestMask ) )
00186 {
00187 *pDestPtr &= ~nDestMask;
00188 m_nCount++;
00189 }
00190
00191 if ( nDestMask == 0x80 )
00192 {
00193 nDestMask = 0x01;
00194 pDestPtr ++;
00195 }
00196 else
00197 {
00198 nDestMask <<= 1;
00199 }
00200 }
00201 }
00202 }
00203
00204 m_nCookie = GetTickCount();
00205
00206 return TRUE;
00207 }
00208
00209 BOOL CQueryHashTable::Merge(CQueryHashGroup* pSource)
00210 {
00211 if ( m_pHash == NULL || pSource->m_pHash == NULL ) return FALSE;
00212
00213 if ( m_nHash == pSource->m_nHash )
00214 {
00215 LPBYTE pSourcePtr = pSource->m_pHash;
00216 LPBYTE pDestPtr = m_pHash;
00217
00218 for ( DWORD nPosition = m_nHash >> 3 ; nPosition ; nPosition-- )
00219 {
00220 register BYTE nDestByte = *pDestPtr;
00221
00222 #define DO_MERGE(MASKVAL) \
00223 if ( *pSourcePtr++ && ( nDestByte & MASKVAL ) ) \
00224 { \
00225 *pDestPtr &= ~ MASKVAL; \
00226 m_nCount++; \
00227 }
00228
00229 DO_MERGE(0x01); DO_MERGE(0x02); DO_MERGE(0x04); DO_MERGE(0x08);
00230 DO_MERGE(0x10); DO_MERGE(0x20); DO_MERGE(0x40); DO_MERGE(0x80);
00231 #undef DO_MERGE
00232
00233 pDestPtr++;
00234 }
00235 }
00236 else
00237 {
00238 int nDestScale = 1;
00239 int nSourceScale = 1;
00240
00241 if ( m_nHash > pSource->m_nHash )
00242 {
00243 DWORD nIterate = pSource->m_nHash;
00244 for ( ; nIterate < m_nHash ; nIterate *= 2 ) nDestScale++;
00245 if ( nIterate != m_nHash ) return FALSE;
00246 }
00247 else if ( m_nHash < pSource->m_nHash )
00248 {
00249 DWORD nIterate = m_nHash;
00250 for ( ; nIterate < pSource->m_nHash ; nIterate *= 2 ) nSourceScale++;
00251 if ( nIterate != pSource->m_nHash ) return FALSE;
00252 }
00253
00254 LPBYTE pSourcePtr = pSource->m_pHash;
00255 LPBYTE pDestPtr = m_pHash;
00256 BYTE nDestMask = 0x01;
00257
00258 for ( DWORD nDest = 0, nSource = 0 ; nDest < m_nHash && nSource < pSource->m_nHash ; )
00259 {
00260 BOOL bValue = TRUE;
00261
00262 for ( int nSample = 0 ; nSample < nSourceScale ; nSample++, nSource++ )
00263 {
00264 if ( *pSourcePtr++ ) bValue = FALSE;
00265 }
00266
00267 for ( int nSample = 0 ; nSample < nDestScale ; nSample++, nDest++ )
00268 {
00269 if ( ! bValue && ( *pDestPtr & nDestMask ) )
00270 {
00271 *pDestPtr &= ~nDestMask;
00272 m_nCount++;
00273 }
00274
00275 if ( nDestMask == 0x80 )
00276 {
00277 nDestMask = 0x01;
00278 pDestPtr ++;
00279 }
00280 else
00281 {
00282 nDestMask <<= 1;
00283 }
00284 }
00285 }
00286 }
00287
00288 m_nCookie = GetTickCount();
00289
00290 return TRUE;
00291 }
00292
00294
00295
00296 BOOL CQueryHashTable::PatchTo(CQueryHashTable* pTarget, CNeighbour* pNeighbour)
00297 {
00298 if ( pTarget->m_pHash == NULL ) return FALSE;
00299 if ( m_nCookie == pTarget->m_nCookie ) return FALSE;
00300
00301 m_nCookie = pTarget->m_nCookie;
00302 m_nCount = pTarget->m_nCount;
00303
00304 BOOL bChanged = FALSE;
00305
00306 if ( m_pHash == NULL || m_nHash != pTarget->m_nHash )
00307 {
00308 if ( m_pHash ) delete [] m_pHash;
00309 m_pHash = NULL;
00310
00311 m_nBits = pTarget->m_nBits;
00312 m_nHash = pTarget->m_nHash;
00313 m_pHash = new BYTE[ ( m_nHash + 31 ) / 8 ];
00314
00315 FillMemory( m_pHash, ( m_nHash + 31 ) / 8, 0xFF );
00316
00317 if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00318 {
00319 CG1Packet* pReset = CG1Packet::New( G1_PACKET_QUERY_ROUTE, 1 );
00320 pReset->WriteByte( 0 );
00321 pReset->WriteLongLE( m_nHash );
00322 pReset->WriteByte( 2 );
00323 pNeighbour->Send( pReset );
00324 }
00325 else
00326 {
00327 CG2Packet* pReset = CG2Packet::New( G2_PACKET_QHT );
00328 pReset->WriteByte( 0 );
00329 pReset->WriteLongBE( m_nHash );
00330 pReset->WriteByte( 1 );
00331 pNeighbour->Send( pReset );
00332 }
00333
00334 bChanged = TRUE;
00335 }
00336
00337 BYTE nBits = 4;
00338
00339 if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00340 {
00341 nBits = 1;
00342 }
00343 else if ( pNeighbour->m_sUserAgent.Find( _T("Shareaza") ) == 0 )
00344 {
00345 LPCTSTR pszAgent = pNeighbour->m_sUserAgent;
00346
00347 if ( _tcsstr( pszAgent, _T(" 1.3") ) ||
00348 _tcsstr( pszAgent, _T(" 1.2") ) ||
00349 _tcsstr( pszAgent, _T(" 1.1") ) ||
00350 _tcsstr( pszAgent, _T(" 1.0") ) )
00351 {
00352 return PatchToOldShareaza( pTarget, pNeighbour );
00353 }
00354
00355 if ( _tcsstr( pszAgent, _T(" 1.4") ) == NULL &&
00356 _tcsstr( pszAgent, _T(" 1.5") ) == NULL &&
00357 _tcsstr( pszAgent, _T(" 1.6.0") ) == NULL )
00358 {
00359 nBits = 1;
00360 }
00361 }
00362
00363 BYTE* pBuffer = new BYTE[ ( m_nHash + 31 ) / ( 8 / nBits ) ];
00364 BYTE* pHashT = pTarget->m_pHash;
00365 BYTE* pHashS = m_pHash;
00366 BYTE nMask = 1;
00367
00368 if ( nBits == 4 )
00369 {
00370 static const DWORD changed[ 256 ] =
00371 {
00372 0x00000000,0x000000f0,0x0000000f,0x000000ff,0x0000f000,0x0000f0f0,0x0000f00f,0x0000f0ff,
00373 0x00000f00,0x00000ff0,0x00000f0f,0x00000fff,0x0000ff00,0x0000fff0,0x0000ff0f,0x0000ffff,
00374 0x00f00000,0x00f000f0,0x00f0000f,0x00f000ff,0x00f0f000,0x00f0f0f0,0x00f0f00f,0x00f0f0ff,
00375 0x00f00f00,0x00f00ff0,0x00f00f0f,0x00f00fff,0x00f0ff00,0x00f0fff0,0x00f0ff0f,0x00f0ffff,
00376 0x000f0000,0x000f00f0,0x000f000f,0x000f00ff,0x000ff000,0x000ff0f0,0x000ff00f,0x000ff0ff,
00377 0x000f0f00,0x000f0ff0,0x000f0f0f,0x000f0fff,0x000fff00,0x000ffff0,0x000fff0f,0x000fffff,
00378 0x00ff0000,0x00ff00f0,0x00ff000f,0x00ff00ff,0x00fff000,0x00fff0f0,0x00fff00f,0x00fff0ff,
00379 0x00ff0f00,0x00ff0ff0,0x00ff0f0f,0x00ff0fff,0x00ffff00,0x00fffff0,0x00ffff0f,0x00ffffff,
00380 0xf0000000,0xf00000f0,0xf000000f,0xf00000ff,0xf000f000,0xf000f0f0,0xf000f00f,0xf000f0ff,
00381 0xf0000f00,0xf0000ff0,0xf0000f0f,0xf0000fff,0xf000ff00,0xf000fff0,0xf000ff0f,0xf000ffff,
00382 0xf0f00000,0xf0f000f0,0xf0f0000f,0xf0f000ff,0xf0f0f000,0xf0f0f0f0,0xf0f0f00f,0xf0f0f0ff,
00383 0xf0f00f00,0xf0f00ff0,0xf0f00f0f,0xf0f00fff,0xf0f0ff00,0xf0f0fff0,0xf0f0ff0f,0xf0f0ffff,
00384 0xf00f0000,0xf00f00f0,0xf00f000f,0xf00f00ff,0xf00ff000,0xf00ff0f0,0xf00ff00f,0xf00ff0ff,
00385 0xf00f0f00,0xf00f0ff0,0xf00f0f0f,0xf00f0fff,0xf00fff00,0xf00ffff0,0xf00fff0f,0xf00fffff,
00386 0xf0ff0000,0xf0ff00f0,0xf0ff000f,0xf0ff00ff,0xf0fff000,0xf0fff0f0,0xf0fff00f,0xf0fff0ff,
00387 0xf0ff0f00,0xf0ff0ff0,0xf0ff0f0f,0xf0ff0fff,0xf0ffff00,0xf0fffff0,0xf0ffff0f,0xf0ffffff,
00388 0x0f000000,0x0f0000f0,0x0f00000f,0x0f0000ff,0x0f00f000,0x0f00f0f0,0x0f00f00f,0x0f00f0ff,
00389 0x0f000f00,0x0f000ff0,0x0f000f0f,0x0f000fff,0x0f00ff00,0x0f00fff0,0x0f00ff0f,0x0f00ffff,
00390 0x0ff00000,0x0ff000f0,0x0ff0000f,0x0ff000ff,0x0ff0f000,0x0ff0f0f0,0x0ff0f00f,0x0ff0f0ff,
00391 0x0ff00f00,0x0ff00ff0,0x0ff00f0f,0x0ff00fff,0x0ff0ff00,0x0ff0fff0,0x0ff0ff0f,0x0ff0ffff,
00392 0x0f0f0000,0x0f0f00f0,0x0f0f000f,0x0f0f00ff,0x0f0ff000,0x0f0ff0f0,0x0f0ff00f,0x0f0ff0ff,
00393 0x0f0f0f00,0x0f0f0ff0,0x0f0f0f0f,0x0f0f0fff,0x0f0fff00,0x0f0ffff0,0x0f0fff0f,0x0f0fffff,
00394 0x0fff0000,0x0fff00f0,0x0fff000f,0x0fff00ff,0x0ffff000,0x0ffff0f0,0x0ffff00f,0x0ffff0ff,
00395 0x0fff0f00,0x0fff0ff0,0x0fff0f0f,0x0fff0fff,0x0fffff00,0x0ffffff0,0x0fffff0f,0x0fffffff,
00396 0xff000000,0xff0000f0,0xff00000f,0xff0000ff,0xff00f000,0xff00f0f0,0xff00f00f,0xff00f0ff,
00397 0xff000f00,0xff000ff0,0xff000f0f,0xff000fff,0xff00ff00,0xff00fff0,0xff00ff0f,0xff00ffff,
00398 0xfff00000,0xfff000f0,0xfff0000f,0xfff000ff,0xfff0f000,0xfff0f0f0,0xfff0f00f,0xfff0f0ff,
00399 0xfff00f00,0xfff00ff0,0xfff00f0f,0xfff00fff,0xfff0ff00,0xfff0fff0,0xfff0ff0f,0xfff0ffff,
00400 0xff0f0000,0xff0f00f0,0xff0f000f,0xff0f00ff,0xff0ff000,0xff0ff0f0,0xff0ff00f,0xff0ff0ff,
00401 0xff0f0f00,0xff0f0ff0,0xff0f0f0f,0xff0f0fff,0xff0fff00,0xff0ffff0,0xff0fff0f,0xff0fffff,
00402 0xffff0000,0xffff00f0,0xffff000f,0xffff00ff,0xfffff000,0xfffff0f0,0xfffff00f,0xfffff0ff,
00403 0xffff0f00,0xffff0ff0,0xffff0f0f,0xffff0fff,0xffffff00,0xfffffff0,0xffffff0f,0xffffffff
00404 };
00405 static const DWORD changeFlag[ 256 ] =
00406 {
00407 0x11111111,0x111111f1,0x1111111f,0x111111ff,0x1111f111,0x1111f1f1,0x1111f11f,0x1111f1ff,
00408 0x11111f11,0x11111ff1,0x11111f1f,0x11111fff,0x1111ff11,0x1111fff1,0x1111ff1f,0x1111ffff,
00409 0x11f11111,0x11f111f1,0x11f1111f,0x11f111ff,0x11f1f111,0x11f1f1f1,0x11f1f11f,0x11f1f1ff,
00410 0x11f11f11,0x11f11ff1,0x11f11f1f,0x11f11fff,0x11f1ff11,0x11f1fff1,0x11f1ff1f,0x11f1ffff,
00411 0x111f1111,0x111f11f1,0x111f111f,0x111f11ff,0x111ff111,0x111ff1f1,0x111ff11f,0x111ff1ff,
00412 0x111f1f11,0x111f1ff1,0x111f1f1f,0x111f1fff,0x111fff11,0x111ffff1,0x111fff1f,0x111fffff,
00413 0x11ff1111,0x11ff11f1,0x11ff111f,0x11ff11ff,0x11fff111,0x11fff1f1,0x11fff11f,0x11fff1ff,
00414 0x11ff1f11,0x11ff1ff1,0x11ff1f1f,0x11ff1fff,0x11ffff11,0x11fffff1,0x11ffff1f,0x11ffffff,
00415 0xf1111111,0xf11111f1,0xf111111f,0xf11111ff,0xf111f111,0xf111f1f1,0xf111f11f,0xf111f1ff,
00416 0xf1111f11,0xf1111ff1,0xf1111f1f,0xf1111fff,0xf111ff11,0xf111fff1,0xf111ff1f,0xf111ffff,
00417 0xf1f11111,0xf1f111f1,0xf1f1111f,0xf1f111ff,0xf1f1f111,0xf1f1f1f1,0xf1f1f11f,0xf1f1f1ff,
00418 0xf1f11f11,0xf1f11ff1,0xf1f11f1f,0xf1f11fff,0xf1f1ff11,0xf1f1fff1,0xf1f1ff1f,0xf1f1ffff,
00419 0xf11f1111,0xf11f11f1,0xf11f111f,0xf11f11ff,0xf11ff111,0xf11ff1f1,0xf11ff11f,0xf11ff1ff,
00420 0xf11f1f11,0xf11f1ff1,0xf11f1f1f,0xf11f1fff,0xf11fff11,0xf11ffff1,0xf11fff1f,0xf11fffff,
00421 0xf1ff1111,0xf1ff11f1,0xf1ff111f,0xf1ff11ff,0xf1fff111,0xf1fff1f1,0xf1fff11f,0xf1fff1ff,
00422 0xf1ff1f11,0xf1ff1ff1,0xf1ff1f1f,0xf1ff1fff,0xf1ffff11,0xf1fffff1,0xf1ffff1f,0xf1ffffff,
00423 0x1f111111,0x1f1111f1,0x1f11111f,0x1f1111ff,0x1f11f111,0x1f11f1f1,0x1f11f11f,0x1f11f1ff,
00424 0x1f111f11,0x1f111ff1,0x1f111f1f,0x1f111fff,0x1f11ff11,0x1f11fff1,0x1f11ff1f,0x1f11ffff,
00425 0x1ff11111,0x1ff111f1,0x1ff1111f,0x1ff111ff,0x1ff1f111,0x1ff1f1f1,0x1ff1f11f,0x1ff1f1ff,
00426 0x1ff11f11,0x1ff11ff1,0x1ff11f1f,0x1ff11fff,0x1ff1ff11,0x1ff1fff1,0x1ff1ff1f,0x1ff1ffff,
00427 0x1f1f1111,0x1f1f11f1,0x1f1f111f,0x1f1f11ff,0x1f1ff111,0x1f1ff1f1,0x1f1ff11f,0x1f1ff1ff,
00428 0x1f1f1f11,0x1f1f1ff1,0x1f1f1f1f,0x1f1f1fff,0x1f1fff11,0x1f1ffff1,0x1f1fff1f,0x1f1fffff,
00429 0x1fff1111,0x1fff11f1,0x1fff111f,0x1fff11ff,0x1ffff111,0x1ffff1f1,0x1ffff11f,0x1ffff1ff,
00430 0x1fff1f11,0x1fff1ff1,0x1fff1f1f,0x1fff1fff,0x1fffff11,0x1ffffff1,0x1fffff1f,0x1fffffff,
00431 0xff111111,0xff1111f1,0xff11111f,0xff1111ff,0xff11f111,0xff11f1f1,0xff11f11f,0xff11f1ff,
00432 0xff111f11,0xff111ff1,0xff111f1f,0xff111fff,0xff11ff11,0xff11fff1,0xff11ff1f,0xff11ffff,
00433 0xfff11111,0xfff111f1,0xfff1111f,0xfff111ff,0xfff1f111,0xfff1f1f1,0xfff1f11f,0xfff1f1ff,
00434 0xfff11f11,0xfff11ff1,0xfff11f1f,0xfff11fff,0xfff1ff11,0xfff1fff1,0xfff1ff1f,0xfff1ffff,
00435 0xff1f1111,0xff1f11f1,0xff1f111f,0xff1f11ff,0xff1ff111,0xff1ff1f1,0xff1ff11f,0xff1ff1ff,
00436 0xff1f1f11,0xff1f1ff1,0xff1f1f1f,0xff1f1fff,0xff1fff11,0xff1ffff1,0xff1fff1f,0xff1fffff,
00437 0xffff1111,0xffff11f1,0xffff111f,0xffff11ff,0xfffff111,0xfffff1f1,0xfffff11f,0xfffff1ff,
00438 0xffff1f11,0xffff1ff1,0xffff1f1f,0xffff1fff,0xffffff11,0xfffffff1,0xffffff1f,0xffffffff
00439 };
00440 DWORD* const pDwordBuffer = reinterpret_cast< DWORD* >( pBuffer );
00441 const DWORD nEnd = ( m_nHash + 7 ) / 8;
00442 for ( DWORD nPosition = 0 ; nPosition < nEnd ; ++nPosition )
00443 {
00444 if ( pDwordBuffer[ nPosition ] = changeFlag[ pHashS[ nPosition ] ]
00445 & changed[ pHashT[ nPosition ] ^ pHashS[ nPosition ] ] ) bChanged = TRUE;
00446 }
00447 if ( bChanged ) memcpy( pHashS, pHashT, nEnd );
00448 }
00449 else
00450 {
00451 const DWORD nEnd = ( m_nHash + 31 ) / 32;
00452 DWORD* const pDwordBuffer = reinterpret_cast< DWORD* >( pBuffer );
00453 const DWORD* const pDwordHashS = reinterpret_cast< DWORD* >( pHashS );
00454 const DWORD* const pDwordHashT = reinterpret_cast< DWORD* >( pHashT );
00455 for ( DWORD nPosition = 0; nPosition < nEnd; ++nPosition )
00456 {
00457 if ( pDwordBuffer[ nPosition ]
00458 = pDwordHashS[ nPosition ] ^ pDwordHashT[ nPosition ] ) bChanged = TRUE;
00459 }
00460 if ( bChanged ) memcpy( pHashS, pHashT, ( m_nHash + 31 ) / 8 );
00461 }
00462
00463 if ( bChanged == FALSE && m_bLive )
00464 {
00465 delete [] pBuffer;
00466 return FALSE;
00467 }
00468
00469 DWORD nCompress = 0;
00470 BYTE* pCompress = CZLib::Compress( pBuffer, m_nHash / ( 8 / nBits ), &nCompress );
00471
00472 delete [] pBuffer;
00473
00474 if ( pCompress == NULL ) return FALSE;
00475
00476 DWORD nPacketSize = 1024;
00477 BYTE nSequenceMax = (BYTE)( nCompress / nPacketSize );
00478 if ( nCompress % nPacketSize ) nSequenceMax++;
00479
00480 pBuffer = pCompress;
00481
00482 for ( BYTE nSequence = 1 ; nSequence <= nSequenceMax ; nSequence++ )
00483 {
00484 CPacket* pPatch = NULL;
00485
00486 if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00487 pPatch = CG1Packet::New( G1_PACKET_QUERY_ROUTE, 1 );
00488 else
00489 pPatch = CG2Packet::New( G2_PACKET_QHT );
00490
00491 pPatch->WriteByte( 1 );
00492 pPatch->WriteByte( nSequence );
00493 pPatch->WriteByte( nSequenceMax );
00494 pPatch->WriteByte( 1 );
00495 pPatch->WriteByte( nBits );
00496
00497 DWORD nPacket = min( nCompress, nPacketSize );
00498
00499 pPatch->Write( pBuffer, nPacket );
00500
00501 pBuffer += nPacket;
00502 nCompress -= nPacket;
00503
00504 pNeighbour->Send( pPatch );
00505 }
00506
00507 delete [] pCompress;
00508 m_bLive = TRUE;
00509
00510 return TRUE;
00511 }
00512
00513 BOOL CQueryHashTable::PatchToOldShareaza(CQueryHashTable* pTarget, CNeighbour* pNeighbour)
00514 {
00515 DWORD nPacketSize = 4096;
00516
00517 BYTE* pBuffer = new BYTE[ nPacketSize ];
00518 BYTE* pHashT = pTarget->m_pHash;
00519 BYTE* pHashS = m_pHash;
00520 DWORD nPosition = 0;
00521
00522 for ( BYTE nSequence = 1 ; nPosition < m_nHash ; nSequence++ )
00523 {
00524 CG1Packet* pPatch = CG1Packet::New( G1_PACKET_QUERY_ROUTE, 1 );
00525
00526 pPatch->WriteByte( 1 );
00527 pPatch->WriteByte( nSequence );
00528 pPatch->WriteByte( (BYTE)( m_nHash / nPacketSize ) );
00529 pPatch->WriteByte( 1 );
00530 pPatch->WriteByte( 4 );
00531
00532 BYTE nMask = 1;
00533
00534 DWORD nCount = 0;
00535 for ( ; nCount < nPacketSize ; nCount++, nPosition++ )
00536 {
00537 BYTE nPatch = ( *pHashT & nMask ) != ( *pHashS & nMask ) ? 7 : 0;
00538
00539 *pHashS = ( *pHashS & ~nMask ) | ( *pHashT & nMask );
00540
00541 if ( nCount & 1 )
00542 pBuffer[ nCount >> 1 ] |= nPatch;
00543 else
00544 pBuffer[ nCount >> 1 ] = nPatch << 4;
00545
00546 if ( nMask == 0x80 )
00547 {
00548 nMask = 1;
00549 pHashT ++;
00550 pHashS ++;
00551 }
00552 else
00553 {
00554 nMask <<= 1;
00555 }
00556 }
00557
00558 pPatch->WriteZLib( pBuffer, nCount / 2 );
00559 pNeighbour->Send( pPatch );
00560 }
00561
00562 delete [] pBuffer;
00563 m_bLive = TRUE;
00564
00565 return TRUE;
00566 }
00567
00569
00570
00571 BOOL CQueryHashTable::OnPacket(CPacket* pPacket)
00572 {
00573 if ( pPacket->m_nLength < 1 ) return FALSE;
00574
00575 if ( pPacket->m_nProtocol == PROTOCOL_G1 )
00576 {
00577 CG1Packet* pG1 = (CG1Packet*)pPacket;
00578 if ( pG1->m_nTTL != 1 ) return FALSE;
00579 if ( pG1->m_nHops != 0 ) return FALSE;
00580 }
00581 else
00582 {
00583 CG2Packet* pG2 = (CG2Packet*)pPacket;
00584 DWORD nLength = pG2->m_nLength;
00585 if ( pG2->m_bCompound ) pG2->SkipCompound( nLength );
00586 }
00587
00588 BYTE nVariant = pPacket->ReadByte();
00589
00590 if ( nVariant == 0 )
00591 {
00592 return OnReset( pPacket );
00593 }
00594 else if ( nVariant == 1 )
00595 {
00596 return OnPatch( pPacket );
00597 }
00598
00599 return FALSE;
00600 }
00601
00603
00604
00605 BOOL CQueryHashTable::OnReset(CPacket* pPacket)
00606 {
00607 if ( pPacket->m_nLength != 6 ) return FALSE;
00608
00609 DWORD nHashSize = 0;
00610
00611 BOOL bGrouped = m_pGroup != NULL;
00612 if ( bGrouped ) QueryHashMaster.Remove( this );
00613
00614 if ( pPacket->m_nProtocol == PROTOCOL_G1 )
00615 {
00616 nHashSize = pPacket->ReadLongLE();
00617 m_nInfinity = pPacket->ReadByte();
00618 }
00619 else
00620 {
00621 nHashSize = pPacket->ReadLongBE();
00622 m_nInfinity = pPacket->ReadByte();
00623 }
00624
00625 if ( nHashSize < 64 ) return FALSE;
00626
00627 if ( nHashSize != m_nHash || m_pHash == NULL )
00628 {
00629 if ( m_pHash ) delete [] m_pHash;
00630 m_pHash = NULL;
00631
00632 for ( m_nHash = 1, m_nBits = 0 ; m_nHash < nHashSize ; m_nBits++ ) m_nHash *= 2;
00633 if ( m_nHash != nHashSize ) return FALSE;
00634 if ( m_nBits > 24 ) return FALSE;
00635
00636 m_pHash = new BYTE[ ( m_nHash >> 3 ) + 1 ];
00637 }
00638
00639 FillMemory( m_pHash, ( m_nHash >> 3 ) + 1, 0xFF );
00640
00641 if ( bGrouped ) QueryHashMaster.Add( this );
00642
00643 m_bLive = FALSE;
00644 m_nCookie = GetTickCount();
00645 m_nCount = 0;
00646
00647 m_pBuffer->Clear();
00648
00649 return TRUE;
00650 }
00651
00653
00654
00655 BOOL CQueryHashTable::OnPatch(CPacket* pPacket)
00656 {
00657 if ( pPacket->m_nLength < 5 ) return FALSE;
00658 if ( m_pHash == NULL ) return FALSE;
00659 if ( m_pBuffer == NULL ) return FALSE;
00660
00661 BYTE nSequence = pPacket->ReadByte();
00662 BYTE nMaximum = pPacket->ReadByte();
00663 BYTE nCompression = pPacket->ReadByte();
00664 BYTE nBits = pPacket->ReadByte();
00665
00666 if ( nBits != 1 && nBits != 4 && nBits != 8 ) return FALSE;
00667 if ( nSequence < 1 || nSequence > nMaximum ) return FALSE;
00668 if ( nCompression > 1 ) return FALSE;
00669
00670 if ( nSequence == 1 ) m_pBuffer->Clear();
00671
00672 m_pBuffer->Add( pPacket->m_pBuffer + pPacket->m_nPosition,
00673 pPacket->m_nLength - pPacket->m_nPosition );
00674
00675 if ( nSequence < nMaximum ) return TRUE;
00676
00677 if ( nCompression == 1 )
00678 {
00679 if ( ! m_pBuffer->Inflate( m_nHash + 4 ) )
00680 {
00681 m_pBuffer->Clear();
00682 return FALSE;
00683 }
00684 }
00685
00686 if ( m_pBuffer->m_nLength != m_nHash / ( 8 / nBits ) )
00687 {
00688 m_pBuffer->Clear();
00689 return FALSE;
00690 }
00691
00692 BYTE* pData = m_pBuffer->m_pBuffer;
00693 BYTE* pHash = m_pHash;
00694
00695 BOOL bGroup = ( m_pGroup != NULL && m_pGroup->m_nHash == m_nHash );
00696 BYTE* pGroup = bGroup ? m_pGroup->m_pHash : NULL;
00697
00698 if ( nBits == 1 )
00699 {
00700 for ( DWORD nPosition = ( m_nHash >> 3 ) ; nPosition ; nPosition--, pHash++, pData++ )
00701 {
00702 for ( BYTE nMask = 1 ; ; nMask <<= 1 )
00703 {
00704 if ( *pData & nMask )
00705 {
00706 if ( *pHash & nMask )
00707 {
00708 m_nCount ++;
00709 *pHash &= ~nMask;
00710 if ( bGroup )
00711 {
00712 #ifdef _DEBUG
00713 ASSERT( *pGroup < 255 );
00714 if ( *pGroup == 0 ) m_pGroup->m_nCount++;
00715 #endif
00716 (*pGroup) ++;
00717 }
00718 }
00719 else
00720 {
00721 m_nCount --;
00722 *pHash |= nMask;
00723
00724 if ( bGroup )
00725 {
00726 #ifdef _DEBUG
00727 ASSERT( *pGroup );
00728 if ( *pGroup == 1 ) m_pGroup->m_nCount--;
00729 #endif
00730 (*pGroup) --;
00731 }
00732 }
00733 }
00734
00735 pGroup++;
00736 if ( nMask == 0x80 ) break;
00737 }
00738 }
00739 }
00740 else
00741 {
00742 BYTE nMask = 1;
00743
00744 for ( DWORD nPosition = 0 ; nPosition < m_nHash ; nPosition++, pData++, pGroup++ )
00745 {
00746 if ( nBits == 8 )
00747 {
00748 if ( *pData )
00749 {
00750 if ( *pHash & nMask )
00751 {
00752 m_nCount++;
00753 *pHash &= ~nMask;
00754 if ( bGroup ) (*pGroup) ++;
00755 }
00756 else
00757 {
00758 m_nCount--;
00759 *pHash |= nMask;
00760 if ( bGroup ) (*pGroup) --;
00761 }
00762 }
00763 }
00764 else
00765 {
00766 if ( *pData & 0xF0 )
00767 {
00768 if ( *pHash & nMask )
00769 {
00770 m_nCount++;
00771 *pHash &= ~nMask;
00772 if ( bGroup ) (*pGroup) ++;
00773 }
00774 else
00775 {
00776 m_nCount--;
00777 *pHash |= nMask;
00778 if ( bGroup ) (*pGroup) --;
00779 }
00780 }
00781
00782 if ( ++nPosition >= m_nHash ) return FALSE;
00783 pGroup ++;
00784 nMask <<= 1;
00785
00786 if ( *pData & 0x0F )
00787 {
00788 if ( *pHash & nMask )
00789 {
00790 m_nCount++;
00791 *pHash &= ~nMask;
00792 if ( bGroup ) *pGroup ++;
00793 }
00794 else
00795 {
00796 m_nCount--;
00797 *pHash |= nMask;
00798 if ( bGroup ) *pGroup --;
00799 }
00800 }
00801 }
00802
00803 if ( nMask == 0x80 )
00804 {
00805 pHash++;
00806 nMask = 1;
00807 }
00808 else
00809 {
00810 nMask <<= 1;
00811 }
00812 }
00813 }
00814
00815 m_bLive = TRUE;
00816 m_nCookie = GetTickCount();
00817
00818 if ( bGroup ) QueryHashMaster.Invalidate();
00819
00820 return TRUE;
00821 }
00822
00824
00825
00826 int CQueryHashTable::AddPhrase(LPCTSTR pszPhrase)
00827 {
00828 if ( m_pHash == NULL ) return 0;
00829
00830 LPCTSTR pszPtr = pszPhrase;
00831 int nCount = 0;
00832
00833 int nStart = 0, nPos = 0;
00834 for ( ; *pszPtr ; nPos++, pszPtr++ )
00835 {
00836 if ( ! IsCharacter( *pszPtr ) )
00837 {
00838 if ( nStart < nPos )
00839 {
00840 nCount += Add( pszPhrase, nStart, nPos - nStart );
00841 }
00842
00843 nStart = nPos + 1;
00844 }
00845 }
00846
00847 if ( nStart < nPos )
00848 {
00849 nCount += Add( pszPhrase, nStart, nPos - nStart );
00850 }
00851
00852 return nCount;
00853 }
00854
00855 int CQueryHashTable::AddString(LPCTSTR pszString)
00856 {
00857 if ( m_pHash == NULL ) return 0;
00858 return Add( pszString, 0, _tcslen( pszString ) );
00859 }
00860
00861 int CQueryHashTable::Add(LPCTSTR pszString, int nStart, int nLength)
00862 {
00863 if ( ! nLength || ! IsWord( pszString, nStart, nLength ) ) return 0;
00864
00865 m_nCookie = GetTickCount();
00866
00867 DWORD nHash = HashWord( pszString, nStart, nLength, m_nBits );
00868 BYTE* pHash = m_pHash + ( nHash >> 3 );
00869 BYTE nMask = 1 << ( nHash & 7 );
00870
00871 if ( *pHash & nMask )
00872 {
00873 m_nCount++;
00874 *pHash &= ~nMask;
00875 }
00876
00877 if ( nLength >= 5 )
00878 {
00879 nHash = HashWord( pszString, nStart, nLength - 1, m_nBits );
00880 pHash = m_pHash + ( nHash >> 3 );
00881 nMask = 1 << ( nHash & 7 );
00882
00883 if ( *pHash & nMask )
00884 {
00885 m_nCount++;
00886 *pHash &= ~nMask;
00887 }
00888
00889 nHash = HashWord( pszString, nStart, nLength - 2, m_nBits );
00890 pHash = m_pHash + ( nHash >> 3 );
00891 nMask = 1 << ( nHash & 7 );
00892
00893 if ( *pHash & nMask )
00894 {
00895 m_nCount++;
00896 *pHash &= ~nMask;
00897 }
00898
00899 return 3;
00900 }
00901
00902 return 1;
00903 }
00904
00906
00907
00908 BOOL CQueryHashTable::CheckPhrase(LPCTSTR pszPhrase)
00909 {
00910 if ( ! m_bLive || m_pHash == NULL || ! *pszPhrase ) return TRUE;
00911
00912 int nWordCount = 0;
00913 int nWordHits = 0;
00914
00915 LPCTSTR pszPtr = pszPhrase;
00916 BOOL bNegate = FALSE;
00917 BOOL bSpace = TRUE;
00918
00919 int nStart = 0, nPos = 0;
00920 for ( ; *pszPtr ; nPos++, pszPtr++ )
00921 {
00922 if ( IsCharacter( *pszPtr ) )
00923 {
00924 bSpace = FALSE;
00925 }
00926 else
00927 {
00928 if ( nStart < nPos && ! bNegate && IsWord( pszPhrase, nStart, nPos - nStart ) )
00929 {
00930 nWordCount++;
00931 DWORD nHash = HashWord( pszPhrase, nStart, nPos - nStart, m_nBits );
00932 BYTE* pHash = m_pHash + ( nHash >> 3 );
00933 BYTE nMask = 1 << ( nHash & 7 );
00934 if ( ! ( *pHash & nMask ) ) nWordHits++;
00935 }
00936
00937 nStart = nPos + 1;
00938 bNegate = bSpace && ( *pszPtr == '-' );
00939 bSpace = ( *pszPtr == ' ' );
00940 }
00941 }
00942
00943 if ( nStart < nPos && ! bNegate && IsWord( pszPhrase, nStart, nPos - nStart ) )
00944 {
00945 nWordCount++;
00946 DWORD nHash = HashWord( pszPhrase, nStart, nPos - nStart, m_nBits );
00947 BYTE* pHash = m_pHash + ( nHash >> 3 );
00948 BYTE nMask = 1 << ( nHash & 7 );
00949 if ( ! ( *pHash & nMask ) ) nWordHits++;
00950 }
00951
00952 return ( nWordCount >= 3 ) ? ( nWordHits * 3 / nWordCount >= 2 ) : ( nWordHits == nWordCount );
00953 }
00954
00955 BOOL CQueryHashTable::CheckString(LPCTSTR pszString)
00956 {
00957 if ( ! m_bLive || m_pHash == NULL || ! *pszString ) return TRUE;
00958
00959 DWORD nHash = HashWord( pszString, 0, _tcslen( pszString ), m_nBits );
00960 BYTE* pHash = m_pHash + ( nHash >> 3 );
00961 BYTE nMask = 1 << ( nHash & 7 );
00962
00963 return ! ( *pHash & nMask );
00964 }
00965
00967
00968
00969 BOOL CQueryHashTable::Check(CQuerySearch* pSearch)
00970 {
00971 if ( ! m_bLive || m_pHash == NULL ) return TRUE;
00972
00973 if ( pSearch->m_bSHA1 || pSearch->m_bED2K || pSearch->m_bBTH )
00974 {
00975 if ( pSearch->m_bSHA1 )
00976 {
00977 if ( CheckString( CSHA::HashToString( &pSearch->m_pSHA1, TRUE ) ) ) return TRUE;
00978 }
00979
00980 if ( pSearch->m_bED2K )
00981 {
00982 if ( CheckString( CED2K::HashToString( &pSearch->m_pED2K, TRUE ) ) ) return TRUE;
00983 }
00984
00985 if ( pSearch->m_bBTH )
00986 {
00987 if ( CheckString( _T("urn:btih:") + CSHA::HashToString( &pSearch->m_pBTH, FALSE ) ) ) return TRUE;
00988 }
00989
00990 return FALSE;
00991 }
00992
00993 LPCTSTR* pWordPtr = pSearch->m_pWordPtr;
00994 DWORD* pWordLen = pSearch->m_pWordLen;
00995 DWORD nWordHits = 0;
00996
00997 for ( int nWord = pSearch->m_nWords ; nWord > 0 ; nWord--, pWordPtr++, pWordLen++ )
00998 {
00999 if ( **pWordPtr == '-' ) continue;
01000
01001 DWORD nHash = HashWord( *pWordPtr, 0, *pWordLen, m_nBits );
01002 BYTE* pHash = m_pHash + ( nHash >> 3 );
01003 BYTE nMask = 1 << ( nHash & 7 );
01004 if ( ! ( *pHash & nMask ) ) nWordHits++;
01005 }
01006
01007 return ( pSearch->m_nWords >= 3 ) ? ( nWordHits * 3 / pSearch->m_nWords >= 2 ) : ( nWordHits == pSearch->m_nWords );
01008 }
01009
01011
01012
01013 DWORD CQueryHashTable::HashWord(LPCTSTR pszString, int nStart, int nLength, int nBits)
01014 {
01015 DWORD nNumber = 0;
01016 int nByte = 0;
01017
01018 pszString += nStart;
01019
01020 for ( int nChar = 0 ; nChar < nLength ; nChar++, pszString++ )
01021 {
01022 int nValue = tolower( *pszString ) & 0xFF;
01023
01024 nValue = nValue << ( nByte * 8 );
01025 nByte = ( nByte + 1 ) & 3;
01026
01027 nNumber = nNumber ^ nValue;
01028 }
01029
01030 return HashNumber( nNumber, nBits );
01031 }
01032
01033 DWORD CQueryHashTable::HashNumber(DWORD nNumber, int nBits)
01034 {
01035 unsigned __int64 nProduct = (unsigned __int64)nNumber * (unsigned __int64)0x4F1BBCDC;
01036 unsigned __int64 nHash = nProduct << 32;
01037 nHash = nHash >> ( 32 + ( 32 - nBits ) );
01038 return (DWORD)nHash;
01039 }
01040
01042
01043
01044 int CQueryHashTable::GetPercent()
01045 {
01046 if ( ! m_pHash || ! m_nHash ) return 0;
01047 return m_nCount * 100 / m_nHash;
01048 }
01049