📄 managedsearch.cpp
字号:
// Try to send the search
if ( pPacket != NULL && pNeighbour->SendQuery( m_pSearch, pPacket, TRUE ) )
{
theApp.Message( MSG_DEFAULT, IDS_NETWORK_SEARCH_SENT,
m_pSearch->m_sSearch.GetLength()
? (LPCTSTR)m_pSearch->m_sSearch
: _T("URN"),
(LPCTSTR)CString( inet_ntoa( pNeighbour->m_pHost.sin_addr ) ) );
}
pPacket->Release();
nCount++;
}
return ( nCount > 0 );
}
//////////////////////////////////////////////////////////////////////
// CManagedSearch execute the search on the G2 mesh
BOOL CManagedSearch::ExecuteG2Mesh(DWORD tTicks, DWORD tSecs)
{
// Look at all known Gnutella2 hubs, newest first
for ( CHostCacheHost* pHost = HostCache.Gnutella2.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
{
// Must be Gnutella2
ASSERT( pHost->m_nProtocol == PROTOCOL_G2 );
if ( pHost->m_nProtocol != PROTOCOL_G2 ) continue;
// If this host is a neighbour, don't UDP to it
if ( NULL != Neighbours.Get( &pHost->m_pAddress ) ) continue;
// If this host can't be queried now, don't query it
if ( ! pHost->CanQuery( tSecs ) ) continue;
// Check if we have an appropriate query key for this host, and if so,
// record the receiver address
SOCKADDR_IN* pReceiver = NULL;
if ( pHost->m_nKeyValue == 0 )
{
// Well, we already know we don't have a key.. pretty simple
}
else if ( Datagrams.IsStable() )
{
// If we are "stable", we have to TX/RX our own UDP traffic,
// so we must have a query key for the local addess
if ( pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
pReceiver = &Network.m_pHost;
else
pHost->m_nKeyValue = 0;
}
else
{
// Make sure we have a query key via one of our neighbours,
// and ensure we have queried this neighbour
if ( CNeighbour* pNeighbour = Neighbours.Get( (IN_ADDR*)&pHost->m_nKeyHost ) )
{
if ( m_pNodes.Lookup( (LPVOID)pHost->m_nKeyHost, (LPVOID&)pReceiver ) )
pReceiver = &pNeighbour->m_pHost;
else
continue;
}
else
{
pHost->m_nKeyValue = 0;
}
}
// Now, if we still have a query key, send the query
if ( pHost->m_nKeyValue != 0 )
{
DWORD tLastQuery, nAddress = pHost->m_pAddress.S_un.S_addr;
ASSERT( pReceiver != NULL );
// Lookup the host
if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)tLastQuery ) )
{
// Check per-hub requery time
DWORD nFrequency = Settings.Gnutella2.RequeryDelay;
nFrequency *= ( m_nPriority + 1 );
if ( tSecs - tLastQuery < nFrequency ) continue;
}
// Set the last query time for this host for this search
m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
// Record the query time on the host, for all searches
pHost->m_tQuery = tSecs;
if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
// Try to create a packet
m_pSearch->m_bAndG1 = ( Settings.Gnutella1.EnableToday && m_bAllowG1 );
CPacket* pPacket = m_pSearch->ToG2Packet( pReceiver, pHost->m_nKeyValue );
// Send the packet if it was created
if ( pPacket != NULL )
{
Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, this, TRUE );
theApp.Message( MSG_DEBUG, _T("Querying %s"),
(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
return TRUE;
}
}
else if ( tSecs - pHost->m_tKeyTime >= max( Settings.Gnutella2.QueryHostThrottle * 5, 5*60 ) )
{
// Timing wise, we can request a query key now -- but first we must figure
// out who should be the receiver
CNeighbour* pCacheHub = NULL;
pReceiver = NULL;
if ( Datagrams.IsStable() )
{
// If we are stable, we must be the receiver
pReceiver = &Network.m_pHost;
}
else
{
// Otherwise, we need to find a neighbour G2 hub who has acked
// this query already
for ( POSITION pos = Neighbours.GetIterator() ; pos ; pCacheHub = NULL )
{
pCacheHub = Neighbours.GetNext( pos );
LPVOID pTemp;
if ( m_pNodes.Lookup( (LPVOID)pCacheHub->m_pHost.sin_addr.S_un.S_addr, pTemp ) )
{
if ( pCacheHub->m_nProtocol == PROTOCOL_G2 &&
pCacheHub->m_nNodeType == ntHub )
{
pReceiver = &pCacheHub->m_pHost;
if ( ! ((CG2Neighbour*)pCacheHub)->m_bCachedKeys ) pCacheHub = NULL;
break;
}
}
}
}
// If we found a receiver, we can ask for the query key
if ( pCacheHub != NULL )
{
// The receiver is a cache-capable hub, so we ask it to return
// a cached key, or fetch a fresh one
CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
pPacket->WritePacket( "QNA", 6 );
pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );
pPacket->WriteShortBE( pHost->m_nPort );
pCacheHub->Send( pPacket );
// Report
CString strReceiver = CString( inet_ntoa( pReceiver->sin_addr ) );
theApp.Message( MSG_DEBUG, _T("Requesting query key from %s through %s"),
(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)strReceiver );
if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
pHost->m_tKeyTime = tSecs;
pHost->m_nKeyValue = 0;
return TRUE;
}
else if ( pReceiver != NULL )
{
// We need to transmit directly to the remote query host
CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
if ( pReceiver == &Network.m_pHost )
{
theApp.Message( MSG_DEBUG, _T("Requesting query key from %s"),
(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
}
else
{
// We are not the receiver, so include receiver address
pPacket->WritePacket( "RNA", 6 );
pPacket->WriteLongLE( pReceiver->sin_addr.S_un.S_addr );
pPacket->WriteShortBE( ntohs( pReceiver->sin_port ) );
CString strReceiver = CString( inet_ntoa( pReceiver->sin_addr ) );
theApp.Message( MSG_DEBUG, _T("Requesting query key from %s for %s"),
(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)strReceiver );
}
// Send
Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, NULL, FALSE );
if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
pHost->m_tKeyTime = tSecs;
pHost->m_nKeyValue = 0;
return TRUE;
}
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CManagedSearch execute the search on eDonkey2000 servers
BOOL CManagedSearch::ExecuteDonkeyMesh(DWORD tTicks, DWORD tSecs)
{
for ( CHostCacheHost* pHost = HostCache.eDonkey.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
{
ASSERT( pHost->m_nProtocol == PROTOCOL_ED2K );
// If this host is a neighbour, don't UDP to it
if ( Neighbours.Get( &pHost->m_pAddress ) ) continue;
// Make sure this host can be queried (now)
if ( pHost->CanQuery( tSecs ) )
{
DWORD nAddress = pHost->m_pAddress.S_un.S_addr;
DWORD tLastQuery;
// Never requery eDonkey2000 servers
if ( m_pNodes.Lookup( (LPVOID)nAddress, (LPVOID&)tLastQuery ) ) continue;
// Set the last query time for this host for this search
m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
// Record the query time on the host, for all searches
pHost->m_tQuery = tSecs;
if ( pHost->m_tAck == 0 ) pHost->m_tAck = tSecs;
// Create a packet in the appropriate format
CPacket* pPacket = NULL;
if ( pHost->m_nProtocol == PROTOCOL_ED2K )
{
pPacket = m_pSearch->ToEDPacket( TRUE );
}
else
{
ASSERT( FALSE );
}
// Send the datagram if possible
if ( pPacket != NULL )
{
Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort + 4, pPacket, TRUE );
theApp.Message( MSG_DEBUG, _T("Sending query to %s"),
(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
return TRUE;
}
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CManagedSearch host acknowledgement
void CManagedSearch::OnHostAcknowledge(DWORD nAddress)
{
DWORD tSecs = time( NULL );
m_pNodes.SetAt( (LPVOID)nAddress, (LPVOID)tSecs );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -