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

LocalSearch.cpp

Go to the documentation of this file.
00001 //
00002 // LocalSearch.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 "LocalSearch.h"
00026 
00027 #include "Library.h"
00028 #include "LibraryFolders.h"
00029 #include "SharedFile.h"
00030 #include "SharedFolder.h"
00031 #include "AlbumFolder.h"
00032 
00033 #include "QuerySearch.h"
00034 #include "GProfile.h"
00035 #include "Network.h"
00036 #include "Neighbours.h"
00037 #include "Neighbour.h"
00038 #include "Datagrams.h"
00039 #include "G1Packet.h"
00040 #include "G2Packet.h"
00041 #include "Buffer.h"
00042 #include "ZLib.h"
00043 #include "GGEP.h"
00044 #include "BTClients.h"
00045 
00046 #include "Transfers.h"
00047 #include "Downloads.h"
00048 #include "Download.h"
00049 #include "Uploads.h"
00050 #include "UploadQueue.h"
00051 #include "UploadQueues.h"
00052 
00053 #include "XML.h"
00054 #include "Schema.h"
00055 #include "SchemaCache.h"
00056 
00057 #include "SHA.h"
00058 #include "TigerTree.h"
00059 #include "ED2K.h"
00060 
00061 #ifdef _DEBUG
00062 #undef THIS_FILE
00063 static char THIS_FILE[]=__FILE__;
00064 #define new DEBUG_NEW
00065 #endif
00066 
00067 
00069 // CLocalSearch construction
00070 
00071 CLocalSearch::CLocalSearch(CQuerySearch* pSearch, CNeighbour* pNeighbour, BOOL bWrapped)
00072 {
00073         m_pSearch               = pSearch;
00074         m_pNeighbour    = pNeighbour;
00075         m_pEndpoint             = NULL;
00076         m_pBuffer               = NULL;
00077         m_nTTL                  = Settings.Gnutella1.MaximumTTL - 3;
00078         m_nProtocol             = pNeighbour->m_nProtocol;
00079         m_bWrapped              = bWrapped;
00080         m_pPacket               = NULL;
00081 
00082         if ( m_bWrapped ) m_nProtocol = PROTOCOL_G1;
00083 }
00084 
00085 CLocalSearch::CLocalSearch(CQuerySearch* pSearch, SOCKADDR_IN* pEndpoint)
00086 {
00087         m_pSearch               = pSearch;
00088         m_pNeighbour    = NULL;
00089         m_pEndpoint             = pEndpoint;
00090         m_pBuffer               = NULL;
00091         m_nTTL                  = Settings.Gnutella1.MaximumTTL - 3;
00092         m_nProtocol             = PROTOCOL_G2;
00093         m_bWrapped              = FALSE;
00094         m_pPacket               = NULL;
00095 }
00096 
00097 CLocalSearch::CLocalSearch(CQuerySearch* pSearch, CBuffer* pBuffer, PROTOCOLID nProtocol)
00098 {
00099         m_pSearch               = pSearch;
00100         m_pNeighbour    = NULL;
00101         m_pEndpoint             = NULL;
00102         m_pBuffer               = pBuffer;
00103         m_nTTL                  = Settings.Gnutella1.MaximumTTL - 3;
00104         m_nProtocol             = nProtocol;
00105         m_bWrapped              = FALSE;
00106         m_pPacket               = NULL;
00107 }
00108 
00109 CLocalSearch::~CLocalSearch()
00110 {
00111         GetXMLString();
00112 }
00113 
00115 // CLocalSearch execute
00116 
00117 int CLocalSearch::Execute(int nMaximum)
00118 {
00119         if ( m_pBuffer == NULL )
00120         {
00121                 if ( UploadQueues.GetQueueRemaining() == 0 ) return 0;
00122         }
00123 
00124         if ( nMaximum < 0 ) nMaximum = Settings.Gnutella.MaxHits;
00125 
00126         if ( m_pSearch )
00127         {
00128                 m_pGUID = m_pSearch->m_pGUID;
00129         }
00130         else
00131         {
00132                 Network.CreateID( m_pGUID );
00133         }
00134 
00135         int nCount = ExecuteSharedFiles( nMaximum );
00136 
00137         if ( m_pSearch != NULL && m_pSearch->m_bWantPFS && m_nProtocol == PROTOCOL_G2 )
00138         {
00139                 if ( nMaximum == 0 || nCount < nMaximum )
00140                 {
00141                         nCount += ExecutePartialFiles( nMaximum ? nMaximum - nCount : 0 );
00142                 }
00143         }
00144 
00145         return nCount;
00146 }
00147 
00149 // CLocalSearch execute shared files
00150 
00151 int CLocalSearch::ExecuteSharedFiles(int nMaximum)
00152 {
00153         CQuickLock oLock( Library.m_pSection );
00154         CPtrList* pFiles = Library.Search( m_pSearch, nMaximum );
00155         if ( pFiles == NULL ) return 0;
00156 
00157         int nHits = pFiles->GetCount();
00158 
00159         while ( pFiles->GetCount() )
00160         {
00161                 int nInThisPacket = min( pFiles->GetCount(), (int)Settings.Gnutella.HitsPerPacket );
00162 
00163                 CreatePacket( nInThisPacket );
00164 
00165         int nHitB = 0;
00166                 for ( int nHitA = 0 ; nHitA < nInThisPacket ; nHitA++ )
00167                 {
00168                         CLibraryFile* pFile = (CLibraryFile*)pFiles->RemoveHead();
00169                         if ( AddHit( pFile, nHitB ) ) nHitB ++;
00170                 }
00171 
00172                 WriteTrailer();
00173                 if ( nHitB > 0 ) DispatchPacket(); else DestroyPacket();
00174         }
00175 
00176         delete pFiles;
00177 
00178         return nHits;
00179 }
00180 
00182 // CLocalSearch add file hit
00183 
00184 BOOL CLocalSearch::AddHit(CLibraryFile* pFile, int nIndex)
00185 {
00186         ASSERT( m_pPacket != NULL );
00187 
00188         if ( m_nProtocol == PROTOCOL_G1 )
00189         {
00190                 if ( ! Settings.Gnutella1.EnableToday ) 
00191                 {
00192                         theApp.Message( MSG_ERROR, _T("CLocalSearch::AddHit() dropping G1 hit G1- network not enabled ") );
00193                         return FALSE;
00194                 }
00195                 if ( ! AddHitG1( pFile, nIndex ) ) return FALSE;
00196         }
00197         else
00198         {
00199                 if ( ! AddHitG2( pFile, nIndex ) ) return FALSE;
00200         }
00201 
00202         return TRUE;
00203 }
00204 
00205 BOOL CLocalSearch::AddHitG1(CLibraryFile* pFile, int nIndex)
00206 {
00207         // Check that the file is actually available. (We must not return ghost hits to G1!)
00208         if ( ! pFile->IsAvailable() ) return FALSE;
00209 
00210         // Check that a queue that can upload this file exists, and isn't insanely long.
00211         if ( UploadQueues.QueueRank( PROTOCOL_HTTP, pFile ) > Settings.Gnutella1.HitQueueLimit ) return FALSE;
00212         // Normally this isn't a problem- the default queue length is 8 to 10, so this check (50) will
00213         // never be activated. However, sometimes users configure bad settings, such as a 2000 user HTTP
00214         // queue. Although the remote client could/should handle this by itself, we really should give
00215         // Gnutella some protection against 'extreme' settings (if only to reduce un-necessary traffic.)
00216 
00217         m_pPacket->WriteLongLE( pFile->m_nIndex );
00218         m_pPacket->WriteLongLE( (DWORD)min( pFile->GetSize(), QWORD(0xFFFFFFFF) ) );
00219         if ( Settings.Gnutella1.QueryHitUTF8 ) //Support UTF-8 Query
00220         {
00221                 m_pPacket->WriteStringUTF8( pFile->m_sName );
00222         }
00223         else
00224         {
00225                 m_pPacket->WriteString( pFile->m_sName );
00226         }
00227 
00228         if ( pFile->m_bSHA1 )
00229         {
00230                 CString strHash = CSHA::HashToString( &pFile->m_pSHA1, TRUE );
00231                 m_pPacket->WriteString( strHash );
00232 
00233                 /*
00234                 CGGEPBlock pBlock;
00235 
00236                 CGGEPItem* pItem = pBlock.Add( _T("H") );
00237                 pItem->WriteByte( 1 );
00238                 pItem->Write( &pFile->m_pSHA1, 20 );
00239 
00240                 pBlock.Write( m_pPacket );
00241                 m_pPacket->WriteByte( 0 );
00242                 */
00243         }
00244         else if ( pFile->m_bTiger )
00245         {
00246                 CString strHash = CTigerNode::HashToString( &pFile->m_pTiger, TRUE );
00247                 m_pPacket->WriteString( strHash );
00248         }
00249         else if ( pFile->m_bED2K )
00250         {
00251                 CString strHash = CED2K::HashToString( &pFile->m_pED2K, TRUE );
00252                 m_pPacket->WriteString( strHash );
00253         }
00254         else
00255         {
00256                 m_pPacket->WriteByte( 0 );
00257         }
00258 
00259         if ( pFile->m_pSchema != NULL && pFile->m_pMetadata != NULL && ( m_pSearch == NULL || m_pSearch->m_bWantXML ) )
00260         {
00261                 AddMetadata( pFile->m_pSchema, pFile->m_pMetadata, nIndex );
00262         }
00263 
00264         return TRUE;
00265 }
00266 
00267 BOOL CLocalSearch::AddHitG2(CLibraryFile* pFile, int nIndex)
00268 {
00269         CG2Packet* pPacket = (CG2Packet*)m_pPacket;
00270         CString strMetadata, strComment;
00271         BOOL bCollection = FALSE;
00272         BOOL bPreview = FALSE;
00273         DWORD nGroup = 0;
00274 
00275         // Pass 1: Calculate child group size
00276 
00277         if ( pFile->m_bTiger && pFile->m_bSHA1 )
00278         {
00279                 nGroup += 5 + 3 + sizeof(SHA1) + sizeof(TIGEROOT);
00280         }
00281         else if ( pFile->m_bTiger )
00282         {
00283                 nGroup += 5 + 4 + sizeof(TIGEROOT);
00284         }
00285         else if ( pFile->m_bSHA1 )
00286         {
00287                 nGroup += 5 + 5 + sizeof(SHA1);
00288         }
00289 
00290         if ( pFile->m_bED2K )
00291         {
00292                 nGroup += 5 + 5 + sizeof(MD4);
00293         }
00294 
00295         if ( m_pSearch == NULL || m_pSearch->m_bWantDN )
00296         {
00297                 if ( pFile->GetSize() <= 0xFFFFFFFF )
00298                 {
00299                         nGroup += 8 + pPacket->GetStringLen( pFile->m_sName );
00300                 }
00301                 else
00302                 {
00303                         nGroup += 4 + 8;
00304                         nGroup += 4 + pPacket->GetStringLen( pFile->m_sName );
00305                 }
00306 
00307                 if ( LPCTSTR pszType = _tcsrchr( pFile->m_sName, '.' ) )
00308                 {
00309                         if ( _tcsicmp( pszType, _T(".co") ) == 0 ||
00310                                  _tcsicmp( pszType, _T(".collection") ) == 0 )
00311                         {
00312                                 if ( ! pFile->m_bBogus )
00313                                 {
00314                                         nGroup += 2 + 7;
00315                                         bCollection = TRUE;
00316                                 }
00317                         }
00318                 }
00319         }
00320 
00321         if ( pFile->IsAvailable() && ( m_pSearch == NULL || m_pSearch->m_bWantURL ) )
00322         {
00323                 nGroup += 5;
00324                 if ( pFile->m_pSources.GetCount() ) nGroup += 7;
00325 
00326                 if ( Settings.Uploads.SharePreviews )
00327                 {
00328                         if (    pFile->m_bCachedPreview ||
00329                                         _tcsistr( pFile->m_sName, _T(".jpg") ) ||
00330                                         _tcsistr( pFile->m_sName, _T(".png") ) )
00331                         {
00332                                 bPreview = TRUE;
00333                         }
00334                 }
00335 
00336                 if ( bPreview ) nGroup += 5;
00337         }
00338 
00339         if ( pFile->m_pMetadata != NULL && ( m_pSearch == NULL || m_pSearch->m_bWantXML ) )
00340         {
00341                 strMetadata = pFile->m_pMetadata->ToString();
00342                 int nMetadata = pPacket->GetStringLen( strMetadata );
00343                 nGroup += 4 + nMetadata;
00344                 if ( nMetadata > 0xFF )
00345                 {
00346                         nGroup ++;
00347                         if ( nMetadata > 0xFFFF ) nGroup ++;
00348                 }
00349         }
00350 
00351         if ( m_pSearch == NULL || m_pSearch->m_bWantCOM )
00352         {
00353                 if ( pFile->m_nRating > 0 || pFile->m_sComments.GetLength() > 0 )
00354                 {
00355                         if ( pFile->m_nRating > 0 )
00356                         {
00357                                 strComment.Format( _T("<comment rating=\"%i\">"), pFile->m_nRating - 1 );
00358                                 CXMLNode::ValueToString( pFile->m_sComments, strComment );
00359                                 if ( strComment.GetLength() > 2048 ) strComment = strComment.Left( 2048 );
00360                                 strComment += _T("</comment>");
00361                         }
00362                         else
00363                         {
00364                                 strComment = _T("<comment>");
00365                                 CXMLNode::ValueToString( pFile->m_sComments, strComment );
00366                                 if ( strComment.GetLength() > 2048 ) strComment = strComment.Left( 2048 );
00367                                 strComment += _T("</comment>");
00368                         }
00369 
00370                         Replace( strComment, _T("\r\n"), _T("{n}") );
00371                         int nComment = pPacket->GetStringLen( strComment );
00372                         nGroup += 5 + nComment;
00373                         if ( nComment > 0xFF )
00374                         {
00375                                 nGroup ++;
00376                                 if ( nComment > 0xFFFF ) nGroup ++;
00377                         }
00378                 }
00379 
00380                 if ( pFile->m_bBogus ) nGroup += 7;
00381         }
00382         else
00383         {
00384                 if ( ! pFile->IsAvailable() ) return FALSE;
00385         }
00386 
00387         if ( m_pSearch == NULL ) nGroup += 8;
00388 
00389         nGroup += 4;
00390 
00391         // Pass 2: Write the child packet
00392 
00393         pPacket->WritePacket( "H", nGroup, TRUE );
00394 
00395         if ( pFile->m_bTiger && pFile->m_bSHA1 )
00396         {
00397                 pPacket->WritePacket( "URN", 3 + sizeof(SHA1) + sizeof(TIGEROOT) );
00398                 pPacket->WriteString( "bp" );
00399                 pPacket->Write( &pFile->m_pSHA1, sizeof(SHA1) );
00400                 pPacket->Write( &pFile->m_pTiger, sizeof(TIGEROOT) );
00401         }
00402         else if ( pFile->m_bTiger )
00403         {
00404                 pPacket->WritePacket( "URN", 4 + sizeof(TIGEROOT) );
00405                 pPacket->WriteString( "ttr" );
00406                 pPacket->Write( &pFile->m_pTiger, sizeof(TIGEROOT) );
00407         }
00408         else if ( pFile->m_bSHA1 )
00409         {
00410                 pPacket->WritePacket( "URN", 5 + sizeof(SHA1) );
00411                 pPacket->WriteString( "sha1" );
00412                 pPacket->Write( &pFile->m_pSHA1, sizeof(SHA1) );
00413         }
00414 
00415         if ( pFile->m_bED2K )
00416         {
00417                 pPacket->WritePacket( "URN", 5 + sizeof(MD4) );
00418                 pPacket->WriteString( "ed2k" );
00419                 pPacket->Write( &pFile->m_pED2K, sizeof(MD4) );
00420         }
00421 
00422         if ( m_pSearch == NULL || m_pSearch->m_bWantDN )
00423         {
00424                 if ( pFile->GetSize() <= 0xFFFFFFFF )
00425                 {
00426                         pPacket->WritePacket( "DN", pPacket->GetStringLen( pFile->m_sName ) + 4 );
00427                         pPacket->WriteLongBE( (DWORD)pFile->GetSize() );
00428                         pPacket->WriteString( pFile->m_sName, FALSE );
00429                 }
00430                 else
00431                 {
00432                         pPacket->WritePacket( "SZ", 8 );
00433                         pPacket->WriteInt64( pFile->GetSize() );
00434                         pPacket->WritePacket( "DN", pPacket->GetStringLen( pFile->m_sName ) );
00435                         pPacket->WriteString( pFile->m_sName, FALSE );
00436                 }
00437 
00438                 if ( bCollection ) pPacket->WritePacket( "COLLECT", 0 );
00439         }
00440 
00441         {
00442                 CSingleLock pQueueLock( &UploadQueues.m_pSection, TRUE );
00443 
00444                 CUploadQueue* pQueue = UploadQueues.SelectQueue( PROTOCOL_HTTP, pFile );
00445                 pPacket->WritePacket( "G", 1 );
00446                 pPacket->WriteByte( pQueue ? pQueue->m_nIndex + 1 : 0 );
00447         }
00448 
00449         if ( pFile->IsAvailable() && ( m_pSearch == NULL || m_pSearch->m_bWantURL ) )
00450         {
00451                 pPacket->WritePacket( "URL", 0 );
00452 
00453                 if ( int nCount = pFile->m_pSources.GetCount() )
00454                 {
00455                         pPacket->WritePacket( "CSC", 2 );
00456                         pPacket->WriteShortBE( (WORD)nCount );
00457                 }
00458 
00459                 if ( bPreview )
00460                 {
00461                         pPacket->WritePacket( "PVU", 0 );
00462                 }
00463         }
00464 
00465         if ( strMetadata.GetLength() )
00466         {
00467                 pPacket->WritePacket( "MD", pPacket->GetStringLen( strMetadata ) );
00468                 pPacket->WriteString( strMetadata, FALSE );
00469         }
00470 
00471         if ( m_pSearch == NULL || m_pSearch->m_bWantCOM )
00472         {
00473                 if ( strComment.GetLength() )
00474                 {
00475                         pPacket->WritePacket( "COM", pPacket->GetStringLen( strComment ) );
00476                         pPacket->WriteString( strComment, FALSE );
00477                 }
00478 
00479                 if ( pFile->m_bBogus ) pPacket->WritePacket( "BOGUS", 0 );
00480         }
00481 
00482         if ( m_pSearch == NULL )
00483         {
00484                 pPacket->WritePacket( "ID", 4 );
00485                 pPacket->WriteLongBE( pFile->m_nIndex );
00486         }
00487 
00488         return TRUE;
00489 }
00490 
00492 // CLocalSearch execute partial files
00493 
00494 int CLocalSearch::ExecutePartialFiles(int nMaximum)
00495 {
00496         ASSERT( m_nProtocol == PROTOCOL_G2 );
00497         ASSERT( m_pSearch != NULL );
00498 
00499         if ( m_pSearch->m_bTiger == FALSE && m_pSearch->m_bSHA1 == FALSE &&
00500                  m_pSearch->m_bED2K  == FALSE && m_pSearch->m_bBTH == FALSE ) return 0;
00501 
00502         CSingleLock pLock( &Transfers.m_pSection );
00503         if ( ! pLock.Lock( 50 ) ) return 0;
00504 
00505         int nCount = 0;
00506         m_pPacket = NULL;
00507 
00508         for ( POSITION pos = Downloads.GetIterator() ; pos ; )
00509         {
00510                 CDownload* pDownload = Downloads.GetNext( pos );
00511 
00512                 if ( ! pDownload->IsShared() ) continue;
00513 
00514                 if (    ( m_pSearch->m_bTiger && pDownload->m_bTiger && m_pSearch->m_pTiger == pDownload->m_pTiger )
00515                         ||      ( m_pSearch->m_bSHA1  && pDownload->m_bSHA1  && m_pSearch->m_pSHA1  == pDownload->m_pSHA1 )
00516                         ||      ( m_pSearch->m_bED2K  && pDownload->m_bED2K  && m_pSearch->m_pED2K  == pDownload->m_pED2K )
00517                         ||      ( m_pSearch->m_bBTH   && pDownload->m_bBTH   && m_pSearch->m_pBTH   == pDownload->m_pBTH ) )
00518                 {
00519                         if ( pDownload->m_bBTH || pDownload->IsStarted() )
00520                         {
00521                                 if ( m_pPacket == NULL ) CreatePacketG2();
00522                                 AddHit( pDownload, nCount++ );
00523                         }
00524                 }
00525         }
00526 
00527         if ( m_pPacket != NULL )
00528         {
00529                 WriteTrailerG2();
00530                 DispatchPacket();
00531         }
00532 
00533         return nCount;
00534 }
00535 
00537 // CLocalSearch add download hit
00538 
00539 void CLocalSearch::AddHit(CDownload* pDownload, int nIndex)
00540 {
00541         ASSERT( m_pPacket != NULL );
00542         CG2Packet* pPacket = (CG2Packet*)m_pPacket;
00543         DWORD nGroup = 2 + 4 + 4;
00544         CString strURL;
00545 
00546         if ( pDownload->m_bTiger && pDownload->m_bSHA1 )
00547         {
00548                 nGroup += 5 + 3 + sizeof(SHA1) + sizeof(TIGEROOT);
00549         }
00550         else if ( pDownload->m_bSHA1 )
00551         {
00552                 nGroup += 5 + 5 + sizeof(SHA1);
00553         }
00554         else if ( pDownload->m_bTiger )
00555         {
00556                 nGroup += 5 + 4 + sizeof(TIGEROOT);
00557         }
00558 
00559         if ( pDownload->m_bED2K )
00560         {
00561                 nGroup += 5 + 5 + sizeof(MD4);
00562         }
00563 
00564         if ( pDownload->m_bBTH )
00565         {
00566                 nGroup += 5 + 5 + sizeof(SHA1);
00567         }
00568 
00569         if ( m_pSearch->m_bWantDN )
00570         {
00571                 nGroup += 8 + pPacket->GetStringLen( pDownload->m_sRemoteName );
00572         }
00573 
00574         if ( m_pSearch->m_bWantURL )
00575         {
00576                 nGroup += 5;
00577 
00578                 // if ( m_pSearch->m_bBTH && pDownload->m_pTorrent.IsAvailable() && Network.IsListening() )
00579 
00580                 if ( m_pSearch->m_bBTH && pDownload->m_pTorrent.IsAvailable() && Network.m_pHost.sin_addr.S_un.S_addr != 0 )
00581                 {
00582                         strURL.Format( _T("btc://%s:%i/%s/%s/"),
00583                                 (LPCTSTR)CString( inet_ntoa( Network.m_pHost.sin_addr ) ),
00584                                 htons( Network.m_pHost.sin_port ),
00585                                 (LPCTSTR)CSHA::HashToString( &pDownload->m_pPeerID ),//(LPCTSTR)CSHA::HashToString( BTClients.GetGUID() ),
00586                                 (LPCTSTR)CSHA::HashToString( &pDownload->m_pBTH ) );
00587                         nGroup += pPacket->GetStringLen( strURL );
00588                 }
00589         }
00590 
00591         pPacket->WritePacket( "H", nGroup, TRUE );
00592 
00593         if ( pDownload->m_bTiger && pDownload->m_bSHA1 )
00594         {
00595                 pPacket->WritePacket( "URN", 3 + sizeof(SHA1) + sizeof(TIGEROOT) );
00596                 pPacket->WriteString( "bp" );
00597                 pPacket->Write( &pDownload->m_pSHA1, sizeof(SHA1) );
00598                 pPacket->Write( &pDownload->m_pTiger, sizeof(TIGEROOT) );
00599         }
00600         else if ( pDownload->m_bTiger )
00601         {
00602                 pPacket->WritePacket( "URN", 4 + sizeof(TIGEROOT) );
00603                 pPacket->WriteString( "ttr" );
00604                 pPacket->Write( &pDownload->m_pTiger, sizeof(TIGEROOT) );
00605         }
00606         else if ( pDownload->m_bSHA1 )
00607         {
00608                 pPacket->WritePacket( "URN", 5 + sizeof(SHA1) );
00609                 pPacket->WriteString( "sha1" );
00610                 pPacket->Write( &pDownload->m_pSHA1, sizeof(SHA1) );
00611         }
00612 
00613         if ( pDownload->m_bED2K )
00614         {
00615                 pPacket->WritePacket( "URN", 5 + sizeof(MD4) );
00616                 pPacket->WriteString( "ed2k" );
00617                 pPacket->Write( &pDownload->m_pED2K, sizeof(MD4) );
00618         }
00619 
00620         if ( pDownload->m_bBTH )
00621         {
00622                 pPacket->WritePacket( "URN", 5 + sizeof(SHA1) );
00623                 pPacket->WriteString( "btih" );
00624                 pPacket->Write( &pDownload->m_pBTH, sizeof(SHA1) );
00625         }
00626 
00627         if ( m_pSearch->m_bWantDN )
00628         {
00629                 if ( pDownload->m_nSize <= 0xFFFFFFFF )
00630                 {
00631                         pPacket->WritePacket( "DN", pPacket->GetStringLen( pDownload->m_sRemoteName ) + 4 );
00632                         pPacket->WriteLongBE( (DWORD)pDownload->m_nSize );
00633                         pPacket->WriteString( pDownload->m_sRemoteName, FALSE );
00634                 }
00635                 else
00636                 {
00637                         pPacket->WritePacket( "SZ", 8 );
00638                         pPacket->WriteInt64( pDownload->m_nSize );
00639                         pPacket->WritePacket( "DN", pPacket->GetStringLen( pDownload->m_sRemoteName ) );
00640                         pPacket->WriteString( pDownload->m_sRemoteName, FALSE );
00641                 }
00642         }
00643 
00644         if ( m_pSearch->m_bWantURL )
00645         {
00646                 if ( strURL.GetLength() > 0 )
00647                 {
00648                         pPacket->WritePacket( "URL", pPacket->GetStringLen( strURL ) );
00649                         pPacket->WriteString( strURL, FALSE );
00650                 }
00651                 else
00652                 {
00653                         pPacket->WritePacket( "URL", 0 );
00654                 }
00655         }
00656 
00657         QWORD nComplete = pDownload->GetVolumeComplete();
00658 
00659         if ( nComplete <= 0xFFFFFFFF )
00660         {
00661                 pPacket->WritePacket( "PART", 4 );
00662                 pPacket->WriteLongBE( (DWORD)nComplete );
00663         }
00664         else
00665         {
00666                 pPacket->WritePacket( "PART", 8 );
00667                 pPacket->WriteInt64( nComplete );
00668         }
00669 }
00670 
00672 // CLocalSearch create packet
00673 
00674 void CLocalSearch::CreatePacket(int nCount)
00675 {
00676         ASSERT( m_pPacket == NULL );
00677 
00678         if ( m_nProtocol == PROTOCOL_G1 )
00679                 CreatePacketG1( nCount );
00680         else
00681                 CreatePacketG2();
00682 
00683         if ( m_pSchemas.GetCount() ) GetXMLString();
00684 }
00685 
00686 void CLocalSearch::CreatePacketG1(int nCount)
00687 {
00688         m_pPacket = CG1Packet::New( G1_PACKET_HIT, m_nTTL, &m_pGUID );
00689 
00690         m_pPacket->WriteByte( nCount );
00691         m_pPacket->WriteShortLE( htons( Network.m_pHost.sin_port ) );
00692         m_pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00693 
00694         if ( Uploads.m_bStable )
00695         {
00696                 m_pPacket->WriteLongLE( Uploads.m_nBestSpeed * 8 / 1024 );
00697         }
00698         else
00699         {
00700                 m_pPacket->WriteLongLE( Settings.Connection.OutSpeed );
00701         }
00702 }
00703 
00704 void CLocalSearch::CreatePacketG2()
00705 {
00706         CG2Packet* pPacket = CG2Packet::New( G2_PACKET_HIT, TRUE );
00707         m_pPacket = pPacket;
00708 
00709         pPacket->WritePacket( "GU", 16 );
00710         GGUID tmp( MyProfile.GUID );
00711         pPacket->Write( &tmp, sizeof(GGUID) );
00712 
00713         if ( TRUE /* Network.IsListening() */ )
00714         {
00715                 pPacket->WritePacket( "NA", 6 );
00716                 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00717                 pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00718         }
00719 
00720         pPacket->WritePacket( "V", 4 );
00721         pPacket->WriteString( SHAREAZA_VENDOR_A, FALSE );
00722 
00723         if ( ! Network.IsStable() || ! Datagrams.IsStable() )
00724         {
00725                 pPacket->WritePacket( "FW", 0 );
00726         }
00727 
00728         {
00729                 CSingleLock pNetLock( &Network.m_pSection );
00730 
00731                 if ( pNetLock.Lock( 50 ) )
00732                 {
00733                         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00734                         {
00735                                 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00736 
00737                                 if ( pNeighbour->m_nNodeType != ntLeaf &&
00738                                          pNeighbour->m_nProtocol == PROTOCOL_G2 )
00739                                 {
00740                                         pPacket->WritePacket( "NH", 6 );
00741                                         pPacket->WriteLongLE( pNeighbour->m_pHost.sin_addr.S_un.S_addr );
00742                                         pPacket->WriteShortBE( htons( pNeighbour->m_pHost.sin_port ) );
00743                                 }
00744                         }
00745                 }
00746         }
00747 
00748         if ( ! Uploads.m_bStable ) pPacket->WritePacket( "UNSTA", 0 );
00749 
00750         CSingleLock pQueueLock( &UploadQueues.m_pSection );
00751         int nQueue = 1;
00752 
00753         if ( pQueueLock.Lock() )
00754         {
00755                 for ( POSITION pos = UploadQueues.GetIterator() ; pos ; nQueue++ )
00756                 {
00757                         CUploadQueue* pQueue = UploadQueues.GetNext( pos );
00758                         pPacket->WritePacket( "HG", ( 4 + 7 ) + 2, TRUE );
00759                         pPacket->WritePacket( "SS", 7 );
00760                         pPacket->WriteShortBE( pQueue->GetQueuedCount() + pQueue->GetTransferCount() );
00761                         pPacket->WriteByte( pQueue->GetTransferCount( TRUE ) );
00762                         pPacket->WriteLongBE( pQueue->GetPredictedBandwidth() * 8 / 1024 );
00763                         pPacket->WriteByte( 0 );
00764                         pPacket->WriteByte( nQueue );
00765                 }
00766 
00767                 pQueueLock.Unlock();
00768         }
00769 
00770         CString strNick = MyProfile.GetNick();
00771         if ( strNick.GetLength() > 32 ) strNick = strNick.Left( 32 );
00772 
00773         if ( strNick.GetLength() )
00774         {
00775                 int nNick = pPacket->GetStringLen( strNick );
00776                 pPacket->WritePacket( "UPRO", nNick + 6, TRUE );
00777                 pPacket->WritePacket( "NICK", nNick );
00778                 pPacket->WriteString( strNick, FALSE );
00779         }
00780 
00781         if ( Settings.Community.ServeProfile ) pPacket->WritePacket( "BUP", 0 );
00782         if ( Settings.Community.ServeFiles ) pPacket->WritePacket( "BH", 0 );
00783         if ( Settings.Community.ChatEnable ) pPacket->WritePacket( "PCH", 0 );
00784 }
00785 
00787 // CLocalSearch meta data
00788 
00789 void CLocalSearch::AddMetadata(CSchema* pSchema, CXMLElement* pXML, int nIndex)
00790 {
00791         ASSERT( pSchema != NULL );
00792         ASSERT( pXML != NULL );
00793         ASSERT( pXML->GetParent() == NULL );
00794 
00795         CXMLElement* pGroup;
00796 
00797         if ( ! m_pSchemas.Lookup( pSchema, (void*&)pGroup ) )
00798         {
00799                 pGroup = pSchema->Instantiate();
00800                 m_pSchemas.SetAt( pSchema, pGroup );
00801         }
00802 
00803         CString strIndex;
00804         strIndex.Format( _T("%lu"), nIndex );
00805 
00806         pXML->AddAttribute( _T("index"), strIndex );
00807         pGroup->AddElement( pXML );
00808 }
00809 
00811 // CLocalSearch XML to string
00812 
00813 CString CLocalSearch::GetXMLString()
00814 {
00815         CString strXML;
00816 
00817         for ( POSITION pos1 = m_pSchemas.GetStartPosition() ; pos1 ; )
00818         {
00819                 CXMLElement* pGroup;
00820                 CSchema* pSchema;
00821 
00822                 m_pSchemas.GetNextAssoc( pos1, (void*&)pSchema, (void*&)pGroup );
00823 
00824                 strXML += _T("<?xml version=\"1.0\"?>\r\n");
00825                 pGroup->ToString( strXML, TRUE );
00826 
00827                 for ( POSITION pos2 = pGroup->GetElementIterator() ; pos2 ; )
00828                 {
00829                         CXMLElement* pChild = pGroup->GetNextElement( pos2 );
00830                         pChild->DeleteAttribute( _T("index") );
00831                         pChild->Detach();
00832                 }
00833 
00834                 delete pGroup;
00835         }
00836 
00837         m_pSchemas.RemoveAll();
00838 
00839         return strXML;
00840 }
00841 
00843 // CLocalSearch core trailer
00844 
00845 void CLocalSearch::WriteTrailer()
00846 {
00847         ASSERT( m_pPacket != NULL );
00848 
00849         if ( m_nProtocol == PROTOCOL_G1 )
00850                 WriteTrailerG1();
00851         else
00852                 WriteTrailerG2();
00853 }
00854 
00855 void CLocalSearch::WriteTrailerG1()
00856 {
00857         m_pPacket->WriteString( SHAREAZA_VENDOR_T, FALSE );
00858 
00859         BYTE nFlags[2] = { 0, 0 };
00860 
00861         nFlags[0] |= G1_QHD_BUSY|G1_QHD_STABLE|G1_QHD_SPEED;
00862         nFlags[1] |= G1_QHD_PUSH;
00863 
00864         if ( ! Network.IsListening() ) nFlags[0] |= G1_QHD_PUSH;
00865         if ( Uploads.m_bStable ) nFlags[1] |= G1_QHD_STABLE;
00866         if ( Uploads.m_bStable ) nFlags[1] |= G1_QHD_SPEED;
00867         if ( ! UploadQueues.IsTransferAvailable() ) nFlags[1] |= G1_QHD_BUSY;
00868 
00869         if ( Settings.Community.ServeFiles && Settings.Gnutella1.EnableGGEP )
00870         {
00871                 nFlags[0] |= G1_QHD_GGEP;
00872                 nFlags[1] |= G1_QHD_GGEP;
00873         }
00874 
00875         CString strXML          = GetXMLString();
00876         DWORD nCompressed       = 0;
00877         BYTE* pCompressed       = NULL;
00878 
00879         m_pPacket->WriteByte( strXML.IsEmpty() ? 2 : 4 );
00880         m_pPacket->WriteByte( nFlags[0] );
00881         m_pPacket->WriteByte( nFlags[1] );
00882 
00883         LPSTR pszXML = NULL;
00884         int nXML = 0;
00885 
00886         if ( strXML.GetLength() > 0 )
00887         {
00888                 nXML = WideCharToMultiByte( CP_ACP, 0, strXML, -1, NULL, 0, NULL, NULL );
00889                 pszXML = new CHAR[ nXML ];
00890                 WideCharToMultiByte( CP_ACP, 0, strXML, -1, pszXML, nXML, NULL, NULL );
00891                 if ( nXML > 0 ) nXML --;
00892 
00893                 pCompressed = CZLib::Compress( pszXML, nXML, &nCompressed );
00894 
00895                 if ( nCompressed + 9 < (DWORD)nXML + 11 && pCompressed != NULL )
00896                 {
00897                         m_pPacket->WriteShortLE( (WORD)( nCompressed + 9 + 1 ) );
00898                 }
00899                 else
00900                 {
00901                         m_pPacket->WriteShortLE( nXML + 11 + 1 );
00902                         if ( pCompressed != NULL ) delete [] pCompressed;
00903                         pCompressed = NULL;
00904                 }
00905         }
00906 
00907         m_pPacket->WriteByte( Settings.Community.ChatEnable ? 1 : 0 );
00908 
00909         if ( Settings.Community.ServeFiles && Settings.Gnutella1.EnableGGEP )
00910         {
00911                 m_pPacket->WriteByte( GGEP_MAGIC );
00912                 m_pPacket->WriteByte( GGEP_HDR_LAST | 2 );
00913                 m_pPacket->WriteByte( 'B' );
00914                 m_pPacket->WriteByte( 'H' );
00915                 m_pPacket->WriteByte( GGEP_LEN_LAST );
00916         }
00917 
00918         if ( pCompressed != NULL )
00919         {
00920                 m_pPacket->Write( "{deflate}", 9 );
00921                 m_pPacket->Write( pCompressed, nCompressed );
00922                 m_pPacket->WriteByte( 0 );
00923                 delete [] pCompressed;
00924         }
00925         else if ( pszXML != NULL )
00926         {
00927                 m_pPacket->Write( "{plaintext}", 11 );
00928                 m_pPacket->Write( pszXML, nXML );
00929         }
00930 
00931         if ( pszXML != NULL ) delete [] pszXML;
00932 
00933         GGUID tmp( MyProfile.GUID );
00934         m_pPacket->Write( &tmp, sizeof(GGUID) );
00935 }
00936 
00937 void CLocalSearch::WriteTrailerG2()
00938 {
00939         CG2Packet* pPacket = (CG2Packet*)m_pPacket;
00940 
00941         pPacket->WriteByte( 0 );
00942         pPacket->WriteByte( 0 );
00943         pPacket->Write( &m_pGUID, sizeof(GGUID) );
00944 }
00945 
00947 // CLocalSearch dispatch packet
00948 
00949 void CLocalSearch::DispatchPacket()
00950 {
00951         ASSERT( m_pPacket != NULL );
00952 
00953         if ( m_pNeighbour != NULL )
00954         {
00955                 if ( m_bWrapped )
00956                 {
00957                         // ****Debug
00958                         theApp.Message( MSG_DEFAULT, _T("CLocalSearch::DispatchPacket() Wrapped query hit created") );
00959                         // ****
00960 
00961                         CG2Packet* pG2 = CG2Packet::New( G2_PACKET_HIT_WRAP, (CG1Packet*)m_pPacket );
00962                         m_pPacket->Release();
00963                         m_pPacket = pG2;
00964                 }
00965 
00966                 m_pNeighbour->Send( m_pPacket, FALSE, TRUE );
00967         }
00968 
00969         if ( m_pEndpoint != NULL )
00970         {
00971                 Datagrams.Send( m_pEndpoint, (CG2Packet*)m_pPacket, FALSE );
00972         }
00973 
00974         if ( m_pBuffer != NULL )
00975         {
00976                 m_pPacket->ToBuffer( m_pBuffer );
00977         }
00978 
00979         m_pPacket->Release();
00980         m_pPacket = NULL;
00981 }
00982 
00983 void CLocalSearch::DestroyPacket()
00984 {
00985         if ( m_pPacket != NULL )
00986         {
00987                 m_pPacket->Release();
00988                 m_pPacket = NULL;
00989         }
00990 }
00991 
00993 // CLocalSearch physical and virtual folder tree
00994 
00995 void CLocalSearch::WriteVirtualTree()
00996 {
00997         CSingleLock oLock( &Library.m_pSection );
00998         if ( oLock.Lock( 100 ) )
00999         {
01000                 m_pPacket = AlbumToPacket( Library.GetAlbumRoot() );
01001                 oLock.Unlock();
01002                 if ( m_pPacket != NULL ) DispatchPacket();
01003         }
01004 
01005         if ( oLock.Lock( 100 ) )
01006         {
01007                 m_pPacket = FoldersToPacket();
01008                 oLock.Unlock();
01009                 if ( m_pPacket != NULL ) DispatchPacket();
01010         }
01011 }
01012 
01013 CG2Packet* CLocalSearch::AlbumToPacket(CAlbumFolder* pFolder)
01014 {
01015         if ( pFolder == NULL ) return NULL;
01016 
01017         if ( pFolder->m_pSchema != NULL && pFolder->m_pSchema->m_bPrivate ) return NULL;
01018         if ( pFolder->GetSharedCount() == 0 ) return NULL;
01019 
01020         CG2Packet* pPacket = CG2Packet::New( "VF", TRUE );
01021 
01022         if ( pFolder->m_pSchema != NULL )
01023         {
01024                 CXMLElement* pXML = pFolder->m_pSchema->Instantiate( TRUE );
01025 
01026                 if ( pFolder->m_pXML != NULL )
01027                 {
01028                         pXML->AddElement( pFolder->m_pXML->Clone() );
01029                 }
01030                 else
01031                 {
01032                         CXMLElement* pBody = pXML->AddElement( pFolder->m_pSchema->m_sSingular );
01033                         pBody->AddAttribute( pFolder->m_pSchema->GetFirstMemberName(), pFolder->m_sName );
01034                 }
01035 
01036                 CString strXML = pXML->ToString();
01037                 delete pXML;
01038 
01039                 pPacket->WritePacket( "MD", pPacket->GetStringLen( strXML ) );
01040                 pPacket->WriteString( strXML, FALSE );
01041         }
01042 
01043         for ( POSITION pos = pFolder->GetFolderIterator() ; pos ; )
01044         {
01045                 if ( CG2Packet* pChild = AlbumToPacket( pFolder->GetNextFolder( pos ) ) )
01046                 {
01047                         pPacket->WritePacket( pChild );
01048                         pChild->Release();
01049                 }
01050         }
01051 
01052         pPacket->WritePacket( "FILES", pFolder->GetFileCount() * 4 );
01053 
01054         for ( POSITION pos = pFolder->GetFileIterator() ; pos ; )
01055         {
01056                 CLibraryFile* pFile = pFolder->GetNextFile( pos );
01057                 pPacket->WriteLongBE( pFile->m_nIndex );
01058         }
01059 
01060         return pPacket;
01061 }
01062 
01063 CG2Packet* CLocalSearch::FoldersToPacket()
01064 {
01065         CG2Packet* pPacket = CG2Packet::New( "PF", TRUE );
01066 
01067         for ( POSITION pos = LibraryFolders.GetFolderIterator() ; pos ; )
01068         {
01069                 if ( CG2Packet* pChild = FolderToPacket( LibraryFolders.GetNextFolder( pos ) ) )
01070                 {
01071                         pPacket->WritePacket( pChild );
01072                         pChild->Release();
01073                 }
01074         }
01075 
01076         return pPacket;
01077 }
01078 
01079 CG2Packet* CLocalSearch::FolderToPacket(CLibraryFolder* pFolder)
01080 {
01081         if ( pFolder == NULL ) return NULL;
01082 
01083         if ( pFolder->GetSharedCount() == 0 ) return NULL;
01084 
01085         CG2Packet* pPacket = CG2Packet::New( "PF", TRUE );
01086 
01087         pPacket->WritePacket( "DN", pPacket->GetStringLen( pFolder->m_sName ) );
01088         pPacket->WriteString( pFolder->m_sName, FALSE );
01089 
01090         for ( POSITION pos = pFolder->GetFolderIterator() ; pos ; )
01091         {
01092                 if ( CG2Packet* pChild = FolderToPacket( pFolder->GetNextFolder( pos ) ) )
01093                 {
01094                         pPacket->WritePacket( pChild );
01095                         pChild->Release();
01096                 }
01097         }
01098 
01099         pPacket->WritePacket( "FILES", pFolder->GetFileCount() * 4 );
01100 
01101         for ( POSITION pos = pFolder->GetFileIterator() ; pos ; )
01102         {
01103                 CLibraryFile* pFile = pFolder->GetNextFile( pos );
01104                 pPacket->WriteLongBE( pFile->m_nIndex );
01105         }
01106 
01107         return pPacket;
01108 }

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