Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

QueryHashTable.cpp

Go to the documentation of this file.
00001 //
00002 // QueryHashTable.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // CQueryHashTable construction
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 // CQueryHashTable create
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 // CQueryHashTable clear
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 // CQueryHashTable merge tables
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 // CQueryHashTable packet patch dispatch
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 // CQueryHashTable packet handler
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 // CQueryHashTable reset handler
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;     // Minimum size
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 // CQueryHashTable patch handler
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 // CQueryHashTable add phrases and words
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 // CQueryHashTable check phrases and words
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 // CQueryHashTable check query object
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 // CQueryHashTable hash functions
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 // CQueryHashTable calculate percent full
01043 
01044 int CQueryHashTable::GetPercent()
01045 {
01046         if ( ! m_pHash || ! m_nHash ) return 0;
01047         return m_nCount * 100 / m_nHash;
01048 }
01049 

Generated on Thu Dec 15 10:39:46 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2