示例#1
0
BOOL CNetwork::SendPush(GGUID* pGUID, DWORD nIndex)
{
	CSingleLock pLock( &Network.m_pSection );
	if ( ! pLock.Lock( 250 ) ) return TRUE;

	if ( ! IsListening() ) return FALSE;
	
	GGUID pGUID2 = *pGUID;
	SOCKADDR_IN pEndpoint;
	CNeighbour* pOrigin;
	int nCount = 0;
	
	while ( GetNodeRoute( &pGUID2, &pOrigin, &pEndpoint ) )
	{
		if ( pOrigin != NULL && pOrigin->m_nProtocol == PROTOCOL_G1 )
		{
			CG1Packet* pPacket = CG1Packet::New( G1_PACKET_PUSH,
				Settings.Gnutella1.MaximumTTL - 1 );
			
			pPacket->Write( pGUID, 16 );
			pPacket->WriteLongLE( nIndex );
			pPacket->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
			pPacket->WriteShortLE( htons( m_pHost.sin_port ) );
			
			pOrigin->Send( pPacket );
		}
		else
		{
			CG2Packet* pPacket = CG2Packet::New( G2_PACKET_PUSH, TRUE );
			
			pPacket->WritePacket( G2_PACKET_TO, 16 );
			pPacket->Write( pGUID, 16 );
			
			pPacket->WriteByte( 0 );
			pPacket->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
			pPacket->WriteShortBE( htons( m_pHost.sin_port ) );
			
			if ( pOrigin != NULL )
			{
				pOrigin->Send( pPacket );
			}
			else
			{
				Datagrams.Send( &pEndpoint, pPacket );
			}
		}
		
		pGUID2.n[15] ++;
		nCount++;
	}
	
	return nCount > 0;
}
示例#2
0
BOOL CNetwork::RoutePacket(CG2Packet* pPacket)
{
	GGUID pGUID;
	
	if ( ! pPacket->GetTo( &pGUID ) || pGUID == MyProfile.GUID ) return FALSE;
	
	CNeighbour* pOrigin = NULL;
	SOCKADDR_IN pEndpoint;
	
	if ( GetNodeRoute( &pGUID, &pOrigin, &pEndpoint ) )
	{
		if ( pOrigin != NULL )
		{
			if ( pOrigin->m_nProtocol == PROTOCOL_G1 &&
				 pPacket->IsType( G2_PACKET_PUSH ) )
			{
				CG1Neighbour* pG1 = (CG1Neighbour*)pOrigin;
				pPacket->SkipCompound();
				pG1->SendG2Push( &pGUID, pPacket );
			}
			else
			{
				pOrigin->Send( pPacket, FALSE, TRUE );
			}
		}
		else
		{
			Datagrams.Send( &pEndpoint, pPacket, FALSE );
		}
		
		Statistics.Current.Gnutella2.Routed++;
	}
	
	return TRUE;
}
示例#3
0
BOOL CNetwork::RouteHits(CQueryHit* pHits, CPacket* pPacket)
{
	SOCKADDR_IN pEndpoint;
	CNeighbour* pOrigin;
	
	if ( ! QueryRoute->Lookup( &pHits->m_pSearchID, &pOrigin, &pEndpoint ) ) return FALSE;
	
	BOOL bWrapped = FALSE;
	
	if ( pPacket->m_nProtocol == PROTOCOL_G1 )
	{
		CG1Packet* pG1 = (CG1Packet*)pPacket;
		if ( ! pG1->Hop() ) return FALSE;
	}
	else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
	{
		CG2Packet* pG2 = (CG2Packet*)pPacket;

		if ( pG2->IsType( G2_PACKET_HIT ) && pG2->m_nLength > 17 )
		{
			BYTE* pHops = pG2->m_pBuffer + pG2->m_nLength - 17;
			if ( *pHops > Settings.Gnutella1.MaximumTTL ) return FALSE;
			(*pHops) ++;
		}
		else if ( pG2->IsType( G2_PACKET_HIT_WRAP ) )
		{
			if ( ! pG2->SeekToWrapped() ) return FALSE;
			GNUTELLAPACKET* pG1 = (GNUTELLAPACKET*)( pPacket->m_pBuffer + pPacket->m_nPosition );
			if ( pG1->m_nTTL == 0 ) return FALSE;
			pG1->m_nTTL --;
			pG1->m_nHops ++;
			bWrapped = TRUE;
		}
	}
	
	if ( pOrigin != NULL )
	{
		if ( pOrigin->m_nProtocol == pPacket->m_nProtocol )
		{
			pOrigin->Send( pPacket, FALSE, FALSE );	// Dont buffer
		}
		else if ( pOrigin->m_nProtocol == PROTOCOL_G1 && pPacket->m_nProtocol == PROTOCOL_G2 )
		{
			if ( ! bWrapped ) return FALSE;
			pPacket = CG1Packet::New( (GNUTELLAPACKET*)( pPacket->m_pBuffer + pPacket->m_nPosition ) );
			pOrigin->Send( pPacket, TRUE, TRUE );
		}
		else if ( pOrigin->m_nProtocol == PROTOCOL_G2 && pPacket->m_nProtocol == PROTOCOL_G1 )
		{
			pPacket = CG2Packet::New( G2_PACKET_HIT_WRAP, (CG1Packet*)pPacket );
			pOrigin->Send( pPacket, TRUE, FALSE );	// Dont buffer
		}
		else
		{
			// Should not happen either (logic flaw)
			return FALSE;
		}
	}
	else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
	{
		if ( pEndpoint.sin_addr.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
		Datagrams.Send( &pEndpoint, (CG2Packet*)pPacket, FALSE );
	}
	else
	{
		if ( pEndpoint.sin_addr.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
		pPacket = CG2Packet::New( G2_PACKET_HIT_WRAP, (CG1Packet*)pPacket );
		Datagrams.Send( &pEndpoint, (CG2Packet*)pPacket, TRUE );
	}
	
	if ( pPacket->m_nProtocol == PROTOCOL_G1 )
		Statistics.Current.Gnutella1.Routed++;
	else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
		Statistics.Current.Gnutella2.Routed++;
	
	return TRUE;
}
示例#4
0
BOOL CManagedSearch::ExecuteG2Mesh(const DWORD /*tTicks*/, const DWORD tSecs)
{
	ASSUME_LOCK( SearchManager.m_pSection );

	// Look at all known Gnutella2 hubs, newest first

	CQuickLock oLock( HostCache.Gnutella2.m_pSection );

	for ( CHostCacheIterator i = HostCache.Gnutella2.Begin() ;
		i != HostCache.Gnutella2.End() ; ++i )
	{
		CHostCacheHostPtr pHost = (*i);

		// Must be Gnutella2
		ASSERT( pHost->m_nProtocol == PROTOCOL_G2 );

		// If this host is a neighbour, don't UDP to it
		if ( 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 )
		{
			// We already know we don't have a key, pretty simple
		}
		else if ( ! Network.IsFirewalled(CHECK_UDP) )
		{
			// 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 ) )
			{
				DWORD nTemp;
				if ( m_pNodes.Lookup( pHost->m_nKeyHost, nTemp ) )
					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;
			ASSERT( pReceiver != NULL );

			// Lookup the host
			if ( m_pNodes.Lookup( pHost->m_pAddress.s_addr, tLastQuery ) )
			{
				// Check per-hub re-query time
				DWORD nFrequency;

				if ( m_nPriority >= spLowest )
				{
					// Low priority "auto find" sources
					if ( m_pSearch->m_oSHA1 )		// Has SHA1- probably exists on G2
						nFrequency = 16 * 60 * 60;
					else							// Reduce frequency if no SHA1.
						nFrequency = 32 * 60 * 60;
				}
				else
					nFrequency = Settings.Gnutella2.RequeryDelay * ( m_nPriority + 1 );

				if ( tSecs - tLastQuery < nFrequency )
					continue;
			}

			// Set the last query time for this host for this search
			m_pNodes.SetAt( pHost->m_pAddress.s_addr, 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.Enabled && m_bAllowG1 );

			if ( CPacket* pPacket = m_pSearch->ToG2Packet( pReceiver, pHost->m_nKeyValue ) )
			{
				if ( Datagrams.Send( &pHost->m_pAddress, pHost->m_nPort, pPacket, TRUE, this, TRUE ) )
				{
					theApp.Message( MSG_DEBUG | MSG_FACILITY_SEARCH, _T("Querying %s"), (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
					return TRUE;
				}
			}
		}
		else if ( tSecs - pHost->m_tKeyTime >= max( Settings.Gnutella2.QueryThrottle * 5ul, 5ul * 60ul ) )
		{
			// 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 ( ! Network.IsFirewalled( CHECK_UDP ) )
			{
				// 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 );
					DWORD nTemp;

					if ( m_pNodes.Lookup( pCacheHub->m_pHost.sin_addr.s_addr, nTemp ) )
					{
						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
				if ( CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE ) )
				{
					pPacket->WritePacket( G2_PACKET_QUERY_ADDRESS, 6 );
					pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );
					pPacket->WriteShortBE( pHost->m_nPort );

					if ( pCacheHub->Send( pPacket ) )
					{
						if ( pHost->m_tAck == 0 )
							pHost->m_tAck = tSecs;
						pHost->m_tKeyTime = tSecs;
						pHost->m_nKeyValue = 0;

						theApp.Message( MSG_DEBUG | MSG_FACILITY_SEARCH, _T("Requesting query key from %s through %s"),
							(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)CString( inet_ntoa( pReceiver->sin_addr ) ) );
						return TRUE;
					}
				}
			}
			else if ( pReceiver != NULL )
			{
				// We need to transmit directly to the remote query host
				if ( CG2Packet* pPacket = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE ) )
				{
					if ( pReceiver != &Network.m_pHost )
					{
						// We are not the receiver, so include receiver address
						pPacket->WritePacket( G2_PACKET_REQUEST_ADDRESS, 6 );
						pPacket->WriteLongLE( pReceiver->sin_addr.S_un.S_addr );
						pPacket->WriteShortBE( ntohs( pReceiver->sin_port ) );
					}

					if ( 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;

						if ( pReceiver == &Network.m_pHost )
						{
							theApp.Message( MSG_DEBUG | MSG_FACILITY_SEARCH, _T("Requesting query key from %s"),
								(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
						}
						else
						{
							theApp.Message( MSG_DEBUG | MSG_FACILITY_SEARCH, _T("Requesting query key from %s for %s"),
								(LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ), (LPCTSTR)CString( inet_ntoa( pReceiver->sin_addr ) ) );
						}
						return TRUE;
					}
				}
			}
		}
	}

	return FALSE;
}
示例#5
0
BOOL CManagedSearch::ExecuteNeighbours(const DWORD tTicks, const DWORD tSecs)
{
	ASSUME_LOCK( SearchManager.m_pSection );

	int nCount = 0;
	for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
	{
		CNeighbour* pNeighbour = Neighbours.GetNext( pos );
		const DWORD& nAddress = pNeighbour->m_pHost.sin_addr.S_un.S_addr;

		// Must be connected
		if ( pNeighbour->m_nState != nrsConnected )
			continue;

		// Must be stable for 15 seconds
		if ( tTicks < pNeighbour->m_tConnected + 15000 )
			continue;

		// Request more ed2k results (if appropriate)
			 // If we've queried this neighbour 'recently'
			 // and it's an ed2k server and has more results
			 // and this search is the one with results waiting
			 // and we've waited a little while to ensure search is still active
		if ( m_bAllowED2K &&
			 pNeighbour->m_nProtocol == PROTOCOL_ED2K &&
			 tSecs - pNeighbour->m_tLastQuery < 86400 &&	// 1 day
			 pNeighbour->m_oMoreResultsGUID &&
			 IsEqualGUID( pNeighbour->m_oMoreResultsGUID ) &&
			 m_tMoreResults + 10000 < tTicks )
		{
			// Request more results
			pNeighbour->Send( CEDPacket::New( ED2K_C2S_MORERESULTS ) );
			((CEDNeighbour*)pNeighbour)->m_pQueries.AddTail( pNeighbour->m_oMoreResultsGUID );
			// Reset "more results" indicator
			pNeighbour->m_oMoreResultsGUID.clear();
			// Set timer
			m_tMoreResults = tTicks;
			m_pNodes.SetAt( nAddress, tSecs );

			theApp.Message( MSG_DEBUG | MSG_FACILITY_SEARCH, _T("Asking ed2k neighbour for additional search results") );
			continue;
		}

		// Check enabled networks, and do not hammer neighbours for search results
		switch ( pNeighbour->m_nProtocol )
		{
		case PROTOCOL_G2:
			if ( ! m_bAllowG2 ||
				tSecs < pNeighbour->m_tLastQuery + Settings.Gnutella2.QueryThrottle )
				continue;
			break;
		case PROTOCOL_G1:
			if ( ! m_bAllowG1 ||
				tSecs < pNeighbour->m_tLastQuery + Settings.Gnutella1.QueryThrottle )
				continue;
			break;
		case PROTOCOL_ED2K:
			if ( ! m_bAllowED2K ||
				tSecs < pNeighbour->m_tLastQuery + Settings.eDonkey.QueryThrottle )
				continue;
			break;
		case PROTOCOL_DC:
			if ( ! m_bAllowDC ||
				( ! m_pSearch->m_oTiger && m_pSearch->m_sSearch.IsEmpty() ) ||
				tSecs < pNeighbour->m_tLastQuery + Settings.DC.QueryThrottle )
				continue;
			break;
		default:
			continue;
		}

		// Create the appropriate packet type
		CPacket* pPacket = NULL;
		if ( pNeighbour->m_nProtocol == PROTOCOL_G1 )
		{
			DWORD nTTL;
			BOOL bKnownHost = m_pG1Nodes.Lookup( nAddress, nTTL );
			if ( pNeighbour->m_bExtProbes )
			{
				// Neighbour supports X-Ext-Probes
				if ( bKnownHost )
				{
					if ( nTTL >= pNeighbour->GetMaxTTL() )
						continue;	// X-Max-TTL reached
					if ( m_nHits >= Settings.Gnutella.MaxResults )
						continue;	// Maximum hits reached
					nTTL++;
				}
				else	// It's the first step
				{
					nTTL = 1;
				}
			}
			else
			{
				if ( bKnownHost )
					continue;	// We under pledge of X-Requeries

				nTTL = pNeighbour->GetMaxTTL();		// Single query with max available TTL
			}

			m_pG1Nodes.SetAt( nAddress, nTTL );
			pPacket = m_pSearch->ToG1Packet( nTTL );
		}
		else if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
		{
			m_pSearch->m_bAndG1 = ( Settings.Gnutella1.Enabled && m_bAllowG1 );
			pPacket = m_pSearch->ToG2Packet( ! Network.IsFirewalled(CHECK_UDP) ? &Network.m_pHost : NULL, 0 );
		}
		else if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
		{
			CEDNeighbour* pEDNeighbour = static_cast< CEDNeighbour* >( pNeighbour );
			pPacket = m_pSearch->ToEDPacket( FALSE, pEDNeighbour->m_nTCPFlags );
		}
		else if ( pNeighbour->m_nProtocol == PROTOCOL_DC )
		{
			CDCNeighbour* pDCNeighbour = static_cast< CDCNeighbour* >( pNeighbour );
			m_pSearch->m_pMyHub = pDCNeighbour->m_pHost;
			m_pSearch->m_sMyHub = pDCNeighbour->m_sServerName;
			m_pSearch->m_sMyNick = pDCNeighbour->m_sNick;
			pPacket = m_pSearch->ToDCPacket();
		}

		// Try to send the search
		if ( pPacket != NULL )
		{
			// Set the last query time for this host for this search
			m_pNodes.SetAt( nAddress, tSecs );

			if ( pNeighbour->SendQuery( m_pSearch, pPacket, TRUE ) )
			{
				// Reset the last "search more" sent to this neighbour (if applicable)
				pNeighbour->m_oMoreResultsGUID.clear();
				m_tMoreResults = 0;

				// Display message in system window
				theApp.Message( MSG_INFO, 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 ) ) );

				// Save GUID of latest text search if needed
				if ( pNeighbour->m_nProtocol == PROTOCOL_ED2K )
				{
					// Set the "last ED2K search" value if we sent a text search (to find the search later).
					if ( ! m_pSearch->m_oED2K )
						SearchManager.m_oLastSearch = m_pSearch->m_oGUID;
				}
				else if ( pNeighbour->m_nProtocol == PROTOCOL_DC )
				{
					SearchManager.m_oLastSearch = m_pSearch->m_oGUID;
				}
			}
			pPacket->Release();
		}

		nCount++;
	}

	return ( nCount > 0 );
}