00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Network.h"
00026 #include "SearchManager.h"
00027 #include "ManagedSearch.h"
00028 #include "QuerySearch.h"
00029 #include "QueryHit.h"
00030 #include "HostCache.h"
00031 #include "G2Packet.h"
00032
00033 #ifdef _DEBUG
00034 #undef THIS_FILE
00035 static char THIS_FILE[]=__FILE__;
00036 #define new DEBUG_NEW
00037 #endif
00038
00039 CSearchManager SearchManager;
00040
00041
00043
00044
00045 CSearchManager::CSearchManager()
00046 {
00047 m_tLastTick = 0;
00048
00049 m_nPriorityClass = 0;
00050 m_nPriorityCount = 0;
00051
00052 m_pLastED2KSearch = (GGUID&)GUID_NULL;
00053 }
00054
00055 CSearchManager::~CSearchManager()
00056 {
00057 }
00058
00060
00061
00062 void CSearchManager::Add(CManagedSearch* pSearch)
00063 {
00064 POSITION pos = m_pList.Find( pSearch );
00065 if ( pos == NULL ) m_pList.AddHead( pSearch );
00066 }
00067
00068 void CSearchManager::Remove(CManagedSearch* pSearch)
00069 {
00070 POSITION pos = m_pList.Find( pSearch );
00071 if ( pos != NULL ) m_pList.RemoveAt( pos );
00072 }
00073
00075
00076
00077 POSITION CSearchManager::GetIterator() const
00078 {
00079 return m_pList.GetHeadPosition();
00080 }
00081
00082 CManagedSearch* CSearchManager::GetNext(POSITION& pos) const
00083 {
00084 return (CManagedSearch*)m_pList.GetNext( pos );
00085 }
00086
00087 int CSearchManager::GetCount() const
00088 {
00089 return m_pList.GetCount();
00090 }
00091
00092 CManagedSearch* CSearchManager::Find(GGUID* pGUID)
00093 {
00094 for ( POSITION pos = m_pList.GetHeadPosition() ; pos ; )
00095 {
00096 CManagedSearch* pSearch = (CManagedSearch*)m_pList.GetNext( pos );
00097 if ( pSearch->m_pSearch->m_pGUID == *pGUID ) return pSearch;
00098 }
00099
00100 return NULL;
00101 }
00102
00104
00105
00106 void CSearchManager::OnRun()
00107 {
00108
00109 DWORD tNow = GetTickCount();
00110 if ( ( tNow - m_tLastTick ) < 125 ) return;
00111 m_tLastTick = tNow;
00112
00113
00114 if ( ! Network.IsWellConnected() ) return;
00115
00116 HostCache.Gnutella2.PruneByQueryAck();
00117
00118 CSingleLock pLock( &m_pSection );
00119 if ( ! pLock.Lock( 100 ) ) return;
00120
00121 static int nPriorityFactor[ 3 ] = { 8, 4, 1 };
00122
00123 if ( m_nPriorityCount >= nPriorityFactor[ m_nPriorityClass ] )
00124 {
00125 m_nPriorityCount = 0;
00126 m_nPriorityClass = ( m_nPriorityClass + 1 ) % CManagedSearch::spMax;
00127 }
00128
00129 for ( int nClass = 0 ; nClass <= CManagedSearch::spMax ; nClass++ )
00130 {
00131 for ( POSITION pos = GetIterator() ; pos ; )
00132 {
00133 POSITION posCur = pos;
00134 CManagedSearch* pSearch = GetNext( pos );
00135
00136 if ( pSearch->m_nPriority == m_nPriorityClass && pSearch->Execute() )
00137 {
00138 m_pList.RemoveAt( posCur );
00139 m_pList.AddTail( pSearch );
00140 m_nPriorityCount++;
00141 return;
00142 }
00143 }
00144
00145 m_nPriorityCount = 0;
00146 m_nPriorityClass = ( m_nPriorityClass + 1 ) % CManagedSearch::spMax;
00147 }
00148 }
00149
00151
00152
00153 BOOL CSearchManager::OnQueryAck(CG2Packet* pPacket, SOCKADDR_IN* pHost, GGUID* ppGUID)
00154 {
00155 if ( ! pPacket->m_bCompound ) return FALSE;
00156
00157 DWORD nFromIP = pHost->sin_addr.S_un.S_addr;
00158 DWORD tAdjust = 0, tNow = time( NULL );
00159 DWORD nHubs = 0, nLeaves = 0;
00160 CDWordArray pDone;
00161
00162 CHAR szType[9];
00163 DWORD nLength;
00164
00165 theApp.Message( MSG_DEBUG, _T("Processing query acknowledge from %s:"),
00166 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
00167
00168 while ( pPacket->ReadPacket( szType, nLength ) )
00169 {
00170 DWORD nOffset = pPacket->m_nPosition + nLength;
00171
00172 if ( strcmp( szType, "D" ) == 0 && nLength >= 4 )
00173 {
00174 DWORD nAddress = pPacket->ReadLongLE();
00175 pDone.Add( nAddress );
00176
00177 if ( nLength >= 6 )
00178 {
00179 WORD nPort = pPacket->ReadShortBE();
00180
00181 if ( ! Network.IsFirewalledAddress( &nAddress, TRUE ) && nPort )
00182 {
00183 HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, tNow );
00184 }
00185 }
00186
00187 if ( nLength >= 8 ) nLeaves += pPacket->ReadShortBE();
00188 nHubs ++;
00189
00190 theApp.Message( MSG_DEBUG, _T(" Done %s"),
00191 (LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ) );
00192 }
00193 else if ( strcmp( szType, "S" ) == 0 && nLength >= 6 )
00194 {
00195 DWORD nAddress = pPacket->ReadLongLE();
00196 WORD nPort = pPacket->ReadShortBE();
00197 DWORD tSeen = ( nLength >= 10 ) ? pPacket->ReadLongBE() + tAdjust : tNow;
00198
00199 theApp.Message( MSG_DEBUG, _T(" Try %s:%lu"),
00200 (LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ), nPort );
00201
00202 if ( ! Network.IsFirewalledAddress( &nAddress, TRUE ) && nPort )
00203 {
00204 HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, min( tNow, tSeen ) );
00205 }
00206 }
00207 else if ( strcmp( szType, "TS" ) == 0 && nLength == 4 )
00208 {
00209 tAdjust = (LONG)tNow - (LONG)pPacket->ReadLongBE();
00210 }
00211 else if ( strcmp( szType, "RA" ) == 0 && nLength >= 2 )
00212 {
00213 DWORD nRetryAfter = 0;
00214
00215 if ( nLength >= 4 )
00216 {
00217 nRetryAfter = pPacket->ReadLongBE();
00218 }
00219 else if ( nLength >= 2 )
00220 {
00221 nRetryAfter = pPacket->ReadShortBE();
00222 }
00223
00224 if ( CHostCacheHost* pHost = HostCache.Gnutella2.Find( (IN_ADDR*)&nFromIP ) )
00225 {
00226 pHost->m_tRetryAfter = tNow + nRetryAfter;
00227 }
00228 }
00229 else if ( strcmp( szType, "FR" ) == 0 && nLength >= 4 )
00230 {
00231 nFromIP = pPacket->ReadLongLE();
00232 }
00233
00234 pPacket->m_nPosition = nOffset;
00235 }
00236
00237 if ( pPacket->GetRemaining() < 16 ) return FALSE;
00238
00239 GGUID pGUID;
00240 pPacket->Read( &pGUID, sizeof(GGUID) );
00241 if ( ppGUID ) *ppGUID = pGUID;
00242
00243 CSingleLock pLock( &m_pSection );
00244
00245 if ( pLock.Lock( 100 ) )
00246 {
00247 if ( CManagedSearch* pSearch = Find( &pGUID ) )
00248 {
00249 pSearch->m_nHubs += nHubs;
00250 pSearch->m_nLeaves += nLeaves;
00251
00252
00253 pSearch->OnHostAcknowledge( nFromIP );
00254
00255 for ( int nItem = 0 ; nItem < pDone.GetSize() ; nItem++ )
00256 {
00257 DWORD nAddress = pDone.GetAt( nItem );
00258 pSearch->OnHostAcknowledge( nAddress );
00259 }
00260
00261 return FALSE;
00262 }
00263 }
00264
00265 return TRUE;
00266 }
00267
00269
00270
00271 BOOL CSearchManager::OnQueryHits(CQueryHit* pHits)
00272 {
00273 CSingleLock pLock( &m_pSection );
00274 if ( ! pLock.Lock( 100 ) ) return TRUE;
00275
00276 CManagedSearch* pSearch = Find( &pHits->m_pSearchID );
00277 if ( pSearch == NULL ) return TRUE;
00278
00279 pSearch->OnHostAcknowledge( *(DWORD*)&pHits->m_pAddress );
00280
00281 while ( pHits != NULL )
00282 {
00283 pSearch->m_nHits ++;
00284 pHits = pHits->m_pNext;
00285 }
00286
00287 return FALSE;
00288 }
00289
00291
00292
00293 WORD CSearchManager::OnQueryStatusRequest(GGUID* pGUID)
00294 {
00295 CSingleLock pLock( &m_pSection );
00296 if ( ! pLock.Lock( 100 ) ) return 0xFFFF;
00297
00298 CManagedSearch* pSearch = Find( pGUID );
00299 if ( pSearch == NULL ) return 0xFFFF;
00300
00301 return (WORD)min( DWORD(0xFFFE), pSearch->m_nHits );
00302 }