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; }
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; }