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

ManagedSearch.cpp

Go to the documentation of this file.
00001 //
00002 // ManagedSearch.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 "SearchManager.h"
00026 #include "ManagedSearch.h"
00027 #include "QuerySearch.h"
00028 #include "Network.h"
00029 #include "HostCache.h"
00030 #include "Neighbours.h"
00031 #include "Datagrams.h"
00032 #include "G1Neighbour.h"
00033 #include "G2Neighbour.h"
00034 #include "G1Packet.h"
00035 #include "G2Packet.h"
00036 #include "EDPacket.h"
00037 #include "EDNeighbour.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 // CManagedSearch construction
00048 
00049 CManagedSearch::CManagedSearch(CQuerySearch* pSearch, int nPriority)
00050 {
00051         m_pSearch               = pSearch ? pSearch : new CQuerySearch();
00052         m_nPriority             = nPriority;
00053         m_bAllowG2              = TRUE;
00054         m_bAllowG1              = TRUE;
00055         m_bAllowED2K    = TRUE;
00056         
00057         m_bActive               = FALSE;
00058         m_bReceive              = TRUE;
00059         m_tStarted              = 0;
00060         m_nHits                 = 0;
00061 
00062         m_nHubs                 = 0;
00063         m_nLeaves               = 0;
00064         m_nQueryCount   = 0;
00065 
00066         m_tLastG2               = 0;
00067         m_tLastED2K             = 0;
00068         m_tMoreResults  = 0;
00069         m_nEDServers    = 0;
00070         m_nEDClients    = 0;
00071 
00072 }
00073 
00074 CManagedSearch::~CManagedSearch()
00075 {
00076         Stop();
00077         if ( m_pSearch ) delete m_pSearch;
00078 }
00079 
00081 // CManagedSearch serialize
00082 
00083 void CManagedSearch::Serialize(CArchive& ar)
00084 {
00085         int nVersion = 3;
00086 
00087         if ( ar.IsStoring() )
00088         {
00089                 ar << nVersion;
00090 
00091                 m_pSearch->Serialize( ar );
00092                 ar << m_nPriority;
00093                 ar << m_bActive;
00094                 ar << m_bReceive;
00095                 ar << m_bAllowG2;
00096                 ar << m_bAllowG1;
00097                 ar << m_bAllowED2K;
00098         }
00099         else
00100         {
00101                 ar >> nVersion;
00102                 if ( nVersion < 2 ) AfxThrowUserException();
00103                 
00104                 if ( m_pSearch ) delete m_pSearch;
00105                 m_pSearch = new CQuerySearch();
00106                 m_pSearch->Serialize( ar );
00107                 
00108                 ar >> m_nPriority;
00109                 ar >> m_bActive;
00110                 ar >> m_bReceive;
00111                 
00112                 m_bActive = m_bReceive = FALSE;
00113                 
00114                 if ( nVersion >= 3 )
00115                 {
00116                         ar >> m_bAllowG2;
00117                         ar >> m_bAllowG1;
00118                         ar >> m_bAllowED2K;
00119                 }
00120         }
00121 }
00122 
00124 // CManagedSearch start and stop
00125 
00126 void CManagedSearch::Start()
00127 {
00128         if ( m_bActive ) return;
00129         m_bActive = TRUE;
00130         
00131         CSingleLock pLock( &SearchManager.m_pSection );
00132         pLock.Lock( 1000 );
00133         
00134         m_tStarted              = time( NULL );
00135         m_tExecute              = 0;
00136         m_tLastED2K             = 0;
00137         m_tMoreResults  = 0;
00138         m_nQueryCount   = 0;
00139         
00140         m_pNodes.RemoveAll();
00141         
00142         SearchManager.Add( this );
00143 }
00144 
00145 void CManagedSearch::Stop()
00146 {
00147         if ( m_bActive )
00148         {
00149                 m_bActive = FALSE;
00150             Datagrams.PurgeToken( this );
00151         }
00152         
00153         CSingleLock pLock( &SearchManager.m_pSection );
00154         pLock.Lock( 1000 );
00155         SearchManager.Remove( this );
00156 }
00157 
00159 // CManagedSearch execute
00160 
00161 BOOL CManagedSearch::Execute()
00162 {
00163         if ( ! m_bActive || ! m_pSearch ) return FALSE;
00164         
00165         DWORD tTicks    = GetTickCount();
00166         DWORD tSecs             = time( NULL );
00167         
00168         // Throttle this individual search (so it doesn't take up too many resources)
00169         DWORD nThrottle = max( Settings.Search.GeneralThrottle, (DWORD)200 );
00170         if ( m_nPriority == spLowest ) nThrottle += 30000;
00171         else if ( m_nPriority == spMedium ) nThrottle += 800;
00172 
00173         if ( tTicks - m_tExecute < nThrottle ) return FALSE;
00174         m_tExecute = tTicks;
00175         
00176         // Search local neighbours- hubs, servers and ultrapeers. (TCP) 
00177         BOOL bSuccess = ExecuteNeighbours( tTicks, tSecs );
00178 
00179         // G2 global search. (UDP)
00180         if ( Settings.Gnutella2.EnableToday && m_bAllowG2 )
00181         {
00182                 if ( tTicks > m_tLastG2 && tTicks - m_tLastG2 >= Settings.Gnutella2.QueryGlobalThrottle )
00183                 {
00184                         bSuccess |= ExecuteG2Mesh( tTicks, tSecs );
00185                         m_tLastG2 = tTicks;
00186                 }
00187         }
00188         
00189         // ED2K global search. (UDP)
00190         if ( Settings.eDonkey.EnableToday && Settings.eDonkey.ServerWalk && m_bAllowED2K && Network.IsListening() )
00191         {
00192                 if ( ( m_pSearch->m_bED2K ) || ( IsLastED2KSearch() ) )
00193                 {
00194                         if ( tTicks > m_tLastED2K && tTicks - m_tLastED2K >= Settings.eDonkey.QueryGlobalThrottle )
00195                         {
00196                                 bSuccess |= ExecuteDonkeyMesh( tTicks, tSecs );
00197                                 m_tLastED2K = tTicks;
00198                         }
00199                 }
00200         }
00201 
00202         if ( bSuccess ) m_nQueryCount++;
00203         
00204         return bSuccess;
00205 }
00206 
00208 // CManagedSearch execute the search on G1 / G2 / ED2K neighbours
00209 
00210 BOOL CManagedSearch::ExecuteNeighbours(DWORD tTicks, DWORD tSecs)
00211 {
00212         BOOL bIsOld = ( tSecs - m_tStarted ) >= 5;
00213         
00214         int nCount = 0;
00215         
00216         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00217         {
00218                 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00219                 DWORD nPeriod;
00220                 
00221                 // Must be connected
00222                 
00223                 if ( pNeighbour->m_nState != nrsConnected ) continue;
00224                 
00225                 // Check network flags
00226 
00227                 switch ( pNeighbour->m_nProtocol )
00228                 {
00229                 case PROTOCOL_G1:
00230                         if ( ! m_bAllowG1 ) continue;
00231                         break;
00232                 case PROTOCOL_G2:
00233                         if ( ! m_bAllowG2 ) continue;
00234                         break;
00235                 case PROTOCOL_ED2K:
00236                         if ( ! m_bAllowED2K ) continue;
00237                         break;
00238                 }
00239                 
00240                 // Must be stable for 15 seconds, or longer for G1 low priority searches
00241                 
00242                 nPeriod = bIsOld ? 15 : 5;
00243                 if ( bIsOld && pNeighbour->m_nProtocol == PROTOCOL_G1 ) nPeriod += 120 + ( 15 * m_nPriority );
00244                 
00245                 if ( tTicks - pNeighbour->m_tConnected < nPeriod * 1000 ) continue;
00246                 
00247                 // Do not hammer neighbours for search results
00248                 
00249                 if ( bIsOld )
00250                 {
00251                         if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00252                         {
00253                                 if ( tSecs - pNeighbour->m_tLastQuery <
00254                                          Settings.Gnutella1.QueryThrottle ) continue;
00255                         }
00256                         else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00257                         {
00258                                 if ( tSecs - pNeighbour->m_tLastQuery <
00259                                          Settings.Gnutella2.QueryHostThrottle / 4 ) continue;
00260                         }
00261                 }
00262                 
00263                 // Lookup the host
00264                 
00265                 DWORD nAddress = pNeighbour->m_pHost.sin_addr.S_un.S_addr;
00266                 
00267                 if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)nPeriod ) )
00268                 {
00269                         DWORD nFrequency = 0;
00270                         
00271                         if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00272                         {
00273                                 nFrequency = Settings.Gnutella1.RequeryDelay;
00274                                 nFrequency *= ( m_nPriority + 1 );
00275                         }
00276                         else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00277                         {
00278                                 nFrequency = Settings.Gnutella2.RequeryDelay;
00279                                 nFrequency *= ( m_nPriority + 1 );
00280                         }
00281                         else if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
00282                                 nFrequency = 86400;
00283                         
00284                         if ( tSecs - nPeriod < nFrequency ) // If we've queried this neighbour 'recently'
00285                         {
00286                                 // Request more ed2k results (if appropriate)
00287                                 if ( ( pNeighbour->m_nProtocol == PROTOCOL_ED2K ) && ( pNeighbour->m_pMoreResultsGUID != NULL ) ) // If it's an ed2k server and has more results
00288                                 {       
00289                                         if ( ( m_pSearch->m_pGUID == *pNeighbour->m_pMoreResultsGUID ) && // and this search is the one with results waiting
00290                                                 ( m_tMoreResults + 10000 < tTicks ) )           // and we've waited a little while (to ensure the search is still active)
00291                                         {
00292                                                 // Request more results
00293                                                 pNeighbour->Send( CEDPacket::New(  ED2K_C2S_MORERESULTS ) );
00294                                                 ((CEDNeighbour*)pNeighbour)->m_pQueries.AddTail( pNeighbour->m_pMoreResultsGUID );
00295                                                 // Reset "more results" indicator
00296                                                 pNeighbour->m_pMoreResultsGUID = NULL;
00297                                                 // Set timer
00298                                                 m_tMoreResults = tTicks;
00299                                                 // Display message in system window
00300                                                 theApp.Message( MSG_DEBUG, _T("Asking ed2k neighbour for additional search results") );
00301                                         }
00302                                 }
00303 
00304                                 // Don't search this neighbour again.
00305                                 continue; 
00306                         }
00307                 }
00308                 
00309                 // Set the last query time for this host for this search
00310                 
00311                 m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00312                 
00313                 // Create the appropriate packet type
00314                 
00315                 CPacket* pPacket = NULL;
00316                 
00317                 if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
00318                 {
00319                         pPacket = m_pSearch->ToG1Packet();
00320                 }
00321                 else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
00322                 {
00323                         m_pSearch->m_bAndG1 = ( Settings.Gnutella1.EnableToday && m_bAllowG1 );
00324                         pPacket = m_pSearch->ToG2Packet( Datagrams.IsStable() ? &Network.m_pHost : NULL, 0 );
00325                 }
00326                 else if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
00327                 {
00328                         pPacket = m_pSearch->ToEDPacket( FALSE, ((CEDNeighbour*)pNeighbour)->m_nTCPFlags );
00329                 }
00330                 else
00331                 {
00332                         ASSERT( FALSE );
00333                 }
00334                 
00335                 // Try to send the search
00336                 
00337                 if ( pPacket != NULL && pNeighbour->SendQuery( m_pSearch, pPacket, TRUE ) )
00338                 {
00339                         // Reset the last "search more" sent to this neighbour (if applicable)
00340                         if ( pNeighbour->m_pMoreResultsGUID != NULL )
00341                         {
00342                                 delete pNeighbour->m_pMoreResultsGUID;
00343                                 pNeighbour->m_pMoreResultsGUID = NULL;
00344                         }
00345                         m_tMoreResults = 0;
00346 
00347                         //Display message in system window
00348                         theApp.Message( MSG_DEFAULT, IDS_NETWORK_SEARCH_SENT,
00349                                 m_pSearch->m_sSearch.GetLength() ? (LPCTSTR)m_pSearch->m_sSearch : _T("URN"),
00350                                 (LPCTSTR)CString( inet_ntoa( pNeighbour->m_pHost.sin_addr ) ) );
00351                         
00352                         if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
00353                         {
00354                                 // Add to ED2K search counts
00355                                 m_nEDServers++;
00356                                 m_nEDClients += ((CEDNeighbour*)pNeighbour)->m_nUserCount;
00357 
00358                                 // Set the "last ED2K search" value if we sent a text search (to find the search later).
00359                                 if ( ! m_pSearch->m_bED2K )
00360                                 {
00361                                         SearchManager.m_pLastED2KSearch = m_pSearch->m_pGUID;
00362                                 }
00363                         }
00364                 }
00365                 pPacket->Release();
00366                 
00367                 nCount++;
00368         }
00369         
00370         return ( nCount > 0 );
00371 }
00372 
00374 // CManagedSearch execute the search on the G2 mesh
00375 
00376 BOOL CManagedSearch::ExecuteG2Mesh(DWORD tTicks, DWORD tSecs)
00377 {
00378         // Look at all known Gnutella2 hubs, newest first
00379         
00380         for ( CHostCacheHost* pHost = HostCache.Gnutella2.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
00381         {
00382                 // Must be Gnutella2
00383                 
00384                 ASSERT( pHost->m_nProtocol == PROTOCOL_G2 );
00385                 if ( pHost->m_nProtocol != PROTOCOL_G2 ) continue;
00386                 
00387                 // If this host is a neighbour, don't UDP to it
00388                 
00389                 if ( NULL != Neighbours.Get( &pHost->m_pAddress ) ) continue;
00390                 
00391                 // If this host can't be queried now, don't query it
00392                 
00393                 if ( ! pHost->CanQuery( tSecs ) ) continue;
00394                 
00395                 // Check if we have an appropriate query key for this host, and if so,
00396                 // record the receiver address
00397                 
00398                 SOCKADDR_IN* pReceiver = NULL;
00399                 
00400                 if ( pHost->m_nKeyValue == 0 )
00401                 {
00402                         // Well, we already know we don't have a key.. pretty simple
00403                 }
00404                 else if ( Datagrams.IsStable() )
00405                 {
00406                         // If we are "stable", we have to TX/RX our own UDP traffic,
00407                         // so we must have a query key for the local addess
00408                         
00409                         if ( pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
00410                                 pReceiver = &Network.m_pHost;
00411                         else
00412                                 pHost->m_nKeyValue = 0;
00413                 }
00414                 else
00415                 {
00416                         // Make sure we have a query key via one of our neighbours,
00417                         // and ensure we have queried this neighbour
00418                         
00419                         if ( CNeighbour* pNeighbour = Neighbours.Get( (IN_ADDR*)&pHost->m_nKeyHost ) )
00420                         {
00421                                 if ( m_pNodes.Lookup( (LPVOID)pHost->m_nKeyHost, (LPVOID&)pReceiver ) )
00422                                         pReceiver = &pNeighbour->m_pHost;
00423                                 else
00424                                         continue;
00425                         }
00426                         else
00427                         {
00428                                 pHost->m_nKeyValue = 0;
00429                         }
00430                 }
00431                 
00432                 // Now, if we still have a query key, send the query
00433                 
00434                 if ( pHost->m_nKeyValue != 0 )
00435                 {
00436                         DWORD tLastQuery, nAddress = pHost->m_pAddress.S_un.S_addr;
00437                         ASSERT( pReceiver != NULL );
00438                         
00439                         // Lookup the host
00440                         
00441                         if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)tLastQuery ) )
00442                         {
00443                                 // Check per-hub requery time
00444                                 DWORD nFrequency;
00445                                 
00446                                 if ( m_nPriority >=  spLowest )
00447                                 {
00448                                         // Low priority "auto find" sources
00449                                         if ( m_pSearch->m_bSHA1 )               // Has SHA1- probably exists on G2
00450                                                 nFrequency = 16 * 60 * 60;
00451                                         else                                                    // Reduce frequency if no SHA1.
00452                                                 nFrequency = 32 * 60 * 60;
00453                                 }
00454                                 else
00455                                         nFrequency = Settings.Gnutella2.RequeryDelay * ( m_nPriority + 1 );
00456                                 if ( tSecs - tLastQuery < nFrequency ) continue;
00457                         }
00458                         
00459                         // Set the last query time for this host for this search
00460                         
00461                         m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00462                         
00463                         // Record the query time on the host, for all searches
00464                         
00465                         pHost->m_tQuery = tSecs;
00466                         if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00467                         
00468                         // Try to create a packet
00469                         
00470                         m_pSearch->m_bAndG1 = ( Settings.Gnutella1.EnableToday && m_bAllowG1 );
00471                         CPacket* pPacket = m_pSearch->ToG2Packet( pReceiver, pHost->m_nKeyValue );
00472                         
00473                         // Send the packet if it was created
00474                         
00475                         if ( pPacket != NULL )
00476                         {
00477                                 Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, this, TRUE );
00478                                 
00479                                 theApp.Message( MSG_DEBUG, _T("Querying %s"),
00480                                         (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00481                                 
00482                                 return TRUE;
00483                         }
00484                 }
00485                 else if ( tSecs - pHost->m_tKeyTime >= max( Settings.Gnutella2.QueryHostThrottle * 5, DWORD(5*60) ) )
00486                 {
00487                         // Timing wise, we can request a query key now -- but first we must figure
00488                         // out who should be the receiver
00489                         
00490                         CNeighbour* pCacheHub = NULL;
00491                         pReceiver = NULL;
00492                         
00493                         if ( Datagrams.IsStable() )
00494                         {
00495                                 // If we are stable, we must be the receiver
00496                                 pReceiver = &Network.m_pHost;
00497                         }
00498                         else
00499                         {
00500                                 // Otherwise, we need to find a neighbour G2 hub who has acked
00501                                 // this query already
00502                                 
00503                                 for ( POSITION pos = Neighbours.GetIterator() ; pos ; pCacheHub = NULL )
00504                                 {
00505                                         pCacheHub = Neighbours.GetNext( pos );
00506                                         LPVOID pTemp;
00507                                         
00508                                         if ( m_pNodes.Lookup( (LPVOID)pCacheHub->m_pHost.sin_addr.S_un.S_addr, pTemp ) )
00509                                         {
00510                                                 if ( pCacheHub->m_nProtocol == PROTOCOL_G2 &&
00511                                                          pCacheHub->m_nNodeType == ntHub )
00512                                                 {
00513                                                         pReceiver = &pCacheHub->m_pHost;
00514                                                         if ( ! ((CG2Neighbour*)pCacheHub)->m_bCachedKeys ) pCacheHub = NULL;
00515                                                         break;
00516                                                 }
00517                                         }
00518                                 }
00519                         }
00520                         
00521                         // If we found a receiver, we can ask for the query key
00522                         
00523                         if ( pCacheHub != NULL )
00524                         {
00525                                 // The receiver is a cache-capable hub, so we ask it to return
00526                                 // a cached key, or fetch a fresh one
00527                                 
00528                                 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
00529                                 pPacket->WritePacket( "QNA", 6 );
00530                                 pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );
00531                                 pPacket->WriteShortBE( pHost->m_nPort );
00532                                 pCacheHub->Send( pPacket );
00533                                 
00534                                 // Report
00535                                 
00536                                 CString strReceiver = CString( inet_ntoa( pReceiver->sin_addr ) );
00537                                 theApp.Message( MSG_DEBUG, _T("Requesting query key from %s through %s"),
00538                                         (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)strReceiver );
00539                                 
00540                                 if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00541                                 pHost->m_tKeyTime = tSecs;
00542                                 pHost->m_nKeyValue = 0;
00543                                 
00544                                 return TRUE;
00545                         }
00546                         else if ( pReceiver != NULL )
00547                         {
00548                                 // We need to transmit directly to the remote query host
00549                                 
00550                                 CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
00551                                 
00552                                 if ( pReceiver == &Network.m_pHost )
00553                                 {
00554                                         theApp.Message( MSG_DEBUG, _T("Requesting query key from %s"),
00555                                                 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00556                                 }
00557                                 else
00558                                 {
00559                                         // We are not the receiver, so include receiver address
00560                                         pPacket->WritePacket( "RNA", 6 );
00561                                         pPacket->WriteLongLE( pReceiver->sin_addr.S_un.S_addr );
00562                                         pPacket->WriteShortBE( ntohs( pReceiver->sin_port ) );
00563                                         
00564                                         CString strReceiver = CString( inet_ntoa( pReceiver->sin_addr ) );
00565                                         theApp.Message( MSG_DEBUG, _T("Requesting query key from %s for %s"),
00566                                                 (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)strReceiver );
00567                                 }
00568                                 
00569                                 // Send
00570                                 
00571                                 Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, NULL, FALSE );
00572                                 
00573                                 if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00574                                 pHost->m_tKeyTime = tSecs;
00575                                 pHost->m_nKeyValue = 0;
00576                                 
00577                                 return TRUE;
00578                         }
00579                 }
00580         }
00581         
00582         return FALSE;
00583 }
00584 
00586 // CManagedSearch execute the search on eDonkey2000 servers
00587 
00588 BOOL CManagedSearch::ExecuteDonkeyMesh(DWORD tTicks, DWORD tSecs)
00589 {
00590         for ( CHostCacheHost* pHost = HostCache.eDonkey.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
00591         {
00592                 ASSERT( pHost->m_nProtocol == PROTOCOL_ED2K );
00593                 
00594                 // If this host is a neighbour, don't UDP to it
00595                 
00596                 if ( Neighbours.Get( &pHost->m_pAddress ) ) continue;
00597                 
00598                 // Make sure this host can be queried (now)
00599                 
00600                 if ( pHost->CanQuery( tSecs ) )
00601                 {
00602                         DWORD nAddress = pHost->m_pAddress.S_un.S_addr;
00603                         DWORD tLastQuery;
00604                         
00605                         // Never requery eDonkey2000 servers
00606                         
00607                         if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)tLastQuery ) ) continue;
00608                         
00609                         // Set the last query time for this host for this search
00610                         
00611                         m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00612                         
00613                         // Record the query time on the host, for all searches
00614                         
00615                         pHost->m_tQuery = tSecs;
00616                         if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
00617                         
00618                         // Create a packet in the appropriate format
00619                         
00620                         CPacket* pPacket = NULL;
00621                         
00622                         if ( pHost->m_nProtocol == PROTOCOL_ED2K )
00623                         {
00624                                 pPacket = m_pSearch->ToEDPacket( TRUE, pHost->m_nUDPFlags );
00625                         }
00626                         else
00627                         {
00628                                 ASSERT( FALSE );
00629                         }
00630                         
00631                         // Send the datagram if possible
00632                         
00633                         if ( pPacket != NULL ) 
00634                         {
00635                                 Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort + 4, pPacket, TRUE );
00636                                 
00637                                 theApp.Message( MSG_DEBUG, _T("Sending UDP query to %s"),
00638                                         (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00639 
00640                                 // Add to ED2K search counts
00641                                 if ( pHost->m_nProtocol == PROTOCOL_ED2K )
00642                                 {
00643                                         m_nEDServers++;
00644                                         m_nEDClients += pHost->m_nUserCount;
00645                                 }
00646                                 
00647                                 return TRUE;
00648                         }
00649                 }
00650         }
00651         
00652         return FALSE;
00653 }
00654 
00656 // CManagedSearch host acknowledgement
00657 
00658 void CManagedSearch::OnHostAcknowledge(DWORD nAddress)
00659 {
00660         DWORD tSecs = time( NULL );
00661         m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
00662 }
00663 
00665 // CManagedSearch check if we were the most recent ed2k text search. (Not find more sources)
00666 
00667 BOOL CManagedSearch::IsLastED2KSearch()
00668 {
00669         return ( m_pSearch->m_pGUID == SearchManager.m_pLastED2KSearch );
00670 }
00671 

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