BOOL CDownloadWithSources::AddSourceInternal(CDownloadSource* pSource)
{
	// Check/Reject if source is invalid
	if ( ! pSource->m_bPushOnly )
	{
		// Reject invalid IPs (Sometimes ed2k sends invalid 0.x.x.x sources)
		if ( pSource->m_pAddress.S_un.S_un_b.s_b1 == 0 )
		{
			delete pSource;
			return FALSE;
		}

		// Reject if source is the local IP/port
		if ( Network.m_pHost.sin_addr.S_un.S_addr == pSource->m_pAddress.S_un.S_addr )
		{
			if ( ( ( pSource->m_nServerPort == 0 ) && (Settings.Connection.InPort == pSource->m_nPort ) )
				|| ( Settings.Connection.IgnoreOwnIP ) )
			{	
				delete pSource;
				return FALSE;
			}
		}
	}
	else if ( pSource->m_nProtocol == PROTOCOL_ED2K )
	{
		// Reject invalid server IPs (Sometimes ed2k sends invalid 0.x.x.x sources)
		if ( pSource->m_pServerAddress.S_un.S_un_b.s_b1 == 0 )
		{
			delete pSource;
			return FALSE;
		}
	}

	// Check if GUID is valid (MLDonkey source exchange bug)
	if ( pSource->m_bGUID )
	{
		if ( ( pSource->m_pGUID.w[0] == 0 ) && ( pSource->m_pGUID.w[1] == 0 ) && 
			 ( pSource->m_pGUID.w[2] == 0 ) && ( pSource->m_pGUID.w[3] == 0 ) )
		{
			// GUID appear to be null, so invalidate it to prevent duplicate sources
			pSource->m_bGUID = FALSE;
		}
	}

	for ( CDownloadSource* pExisting = m_pSourceFirst ; pExisting ; pExisting = pExisting->m_pNext )
	{	
		if ( pExisting->Equals( pSource ) )
		{
			if ( pExisting->m_pTransfer != NULL ||
				 ( pExisting->m_nProtocol == PROTOCOL_HTTP && pSource->m_nProtocol != PROTOCOL_HTTP ) )
			{
				delete pSource;
				return FALSE;
			}
			else
			{
				pSource->m_tAttempt = pExisting->m_tAttempt;
				pExisting->Remove( TRUE, FALSE );
				break;
			}
		}
	}
	
	m_nSourceCount ++;

	pSource->m_pPrev = m_pSourceLast;
	pSource->m_pNext = NULL;
		
	if ( m_pSourceLast != NULL )
	{
		m_pSourceLast->m_pNext = pSource;
		m_pSourceLast = pSource;
	}
	else
	{
		m_pSourceFirst = m_pSourceLast = pSource;
	}
	
	SetModified();
	
	return TRUE;
}
Ejemplo n.º 2
0
BOOL CDownloadWithSources::AddSourceInternal(CDownloadSource* pSource)
{
	if ( ! pSource )
		return FALSE;	// Out of memory

	if ( GetEffectiveSourceCount() > Settings.Downloads.SourcesWanted )
	{
		delete pSource;
		return FALSE;	// Too many sources
	}

	// Check/Reject if source is invalid
	if ( ! pSource->m_bPushOnly )
	{
		// Reject invalid IPs (Sometimes ed2k sends invalid 0.x.x.x sources)
		if ( pSource->m_pAddress.S_un.S_un_b.s_b1 == 0 || pSource->m_nPort == 0 )
		{
			delete pSource;
			return FALSE;
		}

		// Reject if source is the local IP/port
		if ( Network.IsSelfIP( pSource->m_pAddress ) )
		{
			if ( Settings.Connection.IgnoreOwnIP ||
				( pSource->m_nServerPort == 0 &&
				Settings.Connection.InPort == pSource->m_nPort ) )
			{
				delete pSource;
				return FALSE;
			}
		}
	}
	else if ( pSource->m_nProtocol == PROTOCOL_ED2K )
	{
		// Reject invalid server IPs (Sometimes ed2k sends invalid 0.x.x.x sources)
		if ( pSource->m_pServerAddress.S_un.S_un_b.s_b1 == 0 )
		{
			delete pSource;
			return FALSE;
		}
	}

	CQuickLock pLock( Transfers.m_pSection );

	if ( pSource->m_nRedirectionCount == 0 )	// Don't check for existing sources if source is a redirection
	{
		bool bDeleteSource = false;
		bool bHTTPSource = pSource->IsHTTPSource();
		bool bNeedHTTPSource = ! bHTTPSource &&
			Settings.Gnutella2.Enabled &&
			VendorCache.IsExtended( pSource->m_sServer );

		// Remove unneeded sources
		for ( POSITION posSource = GetIterator() ; posSource ; )
		{
			CDownloadSource* pExisting = GetNext( posSource );

			ASSERT( pSource != pExisting );
			if ( pExisting->Equals( pSource ) ) 	// IPs and ports are equal
			{
				bool bExistingHTTPSource = pExisting->IsHTTPSource();

				if ( bNeedHTTPSource && bExistingHTTPSource )
					bNeedHTTPSource = false;

				if ( ( pExisting->m_nProtocol == pSource->m_nProtocol ) ||
					 ( bExistingHTTPSource && bHTTPSource ) )
				{
					bDeleteSource = true;			// Same protocol
				}
				else if ( ! pExisting->IsIdle() )
				{
					// Already downloading so we can remove new non-HTTP source
					if ( bExistingHTTPSource && ! bHTTPSource )
						bDeleteSource = true;
				}
				else // We are not downloading
				{
					// ...So we can replace non-HTTP source with a new one
					if ( ! bExistingHTTPSource && bHTTPSource )
					{
						// Set connection delay the same as for the old source
						pSource->m_tAttempt = pExisting->m_tAttempt;
						pExisting->Remove( TRUE, FALSE );
					}
				}
			}
		}

		if ( bDeleteSource )
		{
			delete pSource;

			SetModified();

			return FALSE;
		}

		// Make additional G2 source from the existing non-HTTP PeerProject source
		if ( bNeedHTTPSource )
		{
			CString strURL = GetURL( pSource->m_pAddress, pSource->m_nPort );
			if ( ! strURL.IsEmpty() )
			{
				if ( CDownloadSource* pG2Source = new CDownloadSource( (CDownload*)this, strURL ) )
				{
					pG2Source->m_sServer = pSource->m_sServer;		// Copy user-agent
					pG2Source->m_tAttempt = pSource->m_tAttempt;	// Set the same connection delay
					pG2Source->m_nProtocol = PROTOCOL_HTTP;

					AddSourceInternal( pG2Source );
				}
			}
		}
	}

	InternalAdd( pSource );

	SetModified();

	return TRUE;
}