void CDownloadWithSources::RemoveOverlappingSources(QWORD nOffset, QWORD nLength) { CQuickLock pLock( Transfers.m_pSection ); for ( POSITION posSource = GetIterator() ; posSource ; ) { CDownloadSource* pSource = GetNext( posSource ); if ( pSource->TouchedRange( nOffset, nLength ) ) { if ( GetTaskType() == dtaskMergeFile ) { // Merging process can produce corrupted blocks, retry connection after 30 seconds pSource->m_nFailures = 0; pSource->Close( 30 ); } else { theApp.Message( MSG_ERROR, IDS_DOWNLOAD_VERIFY_DROP, (LPCTSTR)CString( inet_ntoa( pSource->m_pAddress ) ), (LPCTSTR)pSource->m_sServer, (LPCTSTR)m_sName, nOffset, nOffset + nLength - 1 ); pSource->Remove( TRUE, FALSE ); } } } }
void CDownloadWithSources::RemoveOverlappingSources(QWORD nOffset, QWORD nLength) { for ( CDownloadSource* pSource = GetFirstSource() ; pSource ; ) { CDownloadSource* pNext = pSource->m_pNext; if ( pSource->TouchedRange( nOffset, nLength ) ) { theApp.Message( MSG_ERROR, IDS_DOWNLOAD_VERIFY_DROP, (LPCTSTR)CString( inet_ntoa( pSource->m_pAddress ) ), (LPCTSTR)pSource->m_sServer, (LPCTSTR)m_sRemoteName, nOffset, nOffset + nLength - 1 ); pSource->Remove( TRUE, TRUE ); } pSource = pNext; } }
void CDownloadWithSources::ClearSources() { CQuickLock pLock( Transfers.m_pSection ); for ( POSITION posSource = GetIterator() ; posSource ; ) { CDownloadSource* pSource = GetNext( posSource ); pSource->Remove(); } m_pSources.RemoveAll(); m_nG1SourceCount = 0; m_nG2SourceCount = 0; m_nEdSourceCount = 0; m_nHTTPSourceCount = 0; m_nBTSourceCount = 0; m_nFTPSourceCount = 0; m_nDCSourceCount = 0; SetModified(); }
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; }
void CRemote::PageDownloads() { if ( CheckCookie() ) return; m_nTab = tabDownloads; CString str; str.Format( L"%i", GetRandomNum( 0i32, _I32_MAX ) ); CSingleLock pLock( &DownloadGroups.m_pSection, TRUE ); Prepare(); // Header Add( L"random", str ); Output( L"downloadsHeader" ); BOOL bExclusive = ! GetKey( L"group_exclusive" ).IsEmpty(); BOOL bReveal = ! GetKey( L"group_reveal" ).IsEmpty(); for ( POSITION posGroup = DownloadGroups.GetIterator(); posGroup != NULL; ) { CDownloadGroup* pGroup = DownloadGroups.GetNext( posGroup ); CString strGroupID; strGroupID.Format( L"%p", pGroup ); Add( L"group_id", strGroupID ); if ( bExclusive ) pGroup->m_bRemoteSelected = ( GetKey( L"group_exclusive" ) == strGroupID ); else if ( bReveal ) pGroup->m_bRemoteSelected = TRUE; else if ( GetKey( L"group_select" ) == strGroupID ) pGroup->m_bRemoteSelected = TRUE; else if ( GetKey( L"group_deselect" ) == strGroupID ) pGroup->m_bRemoteSelected = FALSE; Add( L"group_caption", pGroup->m_sName ); if ( pGroup->m_bRemoteSelected ) Add( L"group_selected", L"true" ); Output( L"downloadsTab" ); Prepare( L"group_" ); } if ( ! GetKey( L"filter_set" ).IsEmpty() ) { Settings.Downloads.FilterMask &= ~( DLF_ACTIVE | DLF_PAUSED | DLF_QUEUED | DLF_SOURCES | DLF_SEED ); if ( GetKey( L"filter_active" ) == L"1" ) Settings.Downloads.FilterMask |= DLF_ACTIVE; if ( GetKey( L"filter_paused" ) == L"1" ) Settings.Downloads.FilterMask |= DLF_PAUSED; if ( GetKey( L"filter_queued" ) == L"1" ) Settings.Downloads.FilterMask |= DLF_QUEUED; if ( GetKey( L"filter_sources" ) == L"1" ) Settings.Downloads.FilterMask |= DLF_SOURCES; if ( GetKey( L"filter_seeds" ) == L"1" ) Settings.Downloads.FilterMask |= DLF_SEED; Settings.Downloads.ShowSources = ( GetKey( L"filter_show_all" ) == L"1" ); } Add( L"filter_active", ( Settings.Downloads.FilterMask & DLF_ACTIVE ) ? L"checked=\"checked\"" : L"" ); Add( L"filter_paused", ( Settings.Downloads.FilterMask & DLF_PAUSED ) ? L"checked=\"checked\"" : L"" ); Add( L"filter_queued", ( Settings.Downloads.FilterMask & DLF_QUEUED ) ? L"checked=\"checked\"" : L"" ); Add( L"filter_sources", ( Settings.Downloads.FilterMask & DLF_SOURCES ) ? L"checked=\"checked\"" : L"" ); Add( L"filter_seeds", ( Settings.Downloads.FilterMask & DLF_PAUSED ) ? L"checked=\"checked\"" : L"" ); Add( L"filter_show_all", Settings.Downloads.ShowSources ? L"checked=\"checked\"" : L"" ); Output( L"downloadsTop" ); for ( POSITION posDownload = Downloads.GetIterator(); posDownload != NULL; ) { CDownload* pDownload = Downloads.GetNext( posDownload ); CString strDownloadID; strDownloadID.Format( L"%p", pDownload ); if ( GetKey( L"modify_id" ) == strDownloadID ) { CString strAction = GetKey( L"modify_action" ); strAction.MakeLower(); if ( strAction == L"expand" ) { if ( CDownloadsCtrl::IsExpandable( pDownload ) ) pDownload->m_bExpanded = TRUE; } else if ( strAction == L"collapse" ) { if ( CDownloadsCtrl::IsExpandable( pDownload ) ) pDownload->m_bExpanded = FALSE; } else if ( strAction == L"resume" ) { pDownload->Resume(); } else if ( strAction == L"pause" ) { if ( ! pDownload->IsPaused() && ! pDownload->IsTasking() ) pDownload->Pause(); } else if ( strAction == L"cancel" ) { if ( ! pDownload->IsTasking() ) pDownload->Remove(); continue; } else if ( strAction == L"clear" ) { if ( pDownload->IsCompleted() && ! pDownload->IsPreviewVisible() ) { pDownload->Remove(); continue; } } else if ( strAction == L"more_sources" ) { // roo_koo_too improvement pDownload->FindMoreSources(); } } if ( CDownloadsCtrl::IsFiltered( pDownload ) ) continue; CDownloadGroup* pGroup = NULL; for ( POSITION posGroup = DownloadGroups.GetIterator(); posGroup != NULL; ) { pGroup = DownloadGroups.GetNext( posGroup ); if ( pGroup->m_bRemoteSelected && pGroup->Contains( pDownload ) ) break; pGroup = NULL; } if ( pGroup == NULL ) continue; Add( L"download_id", strDownloadID ); Add( L"download_filename", pDownload->GetDisplayName() ); Add( L"download_size", ( pDownload->m_nSize == SIZE_UNKNOWN ) ? LoadString( IDS_STATUS_UNKNOWN ) : Settings.SmartVolume( pDownload->m_nSize ) ); int nProgress = int( pDownload->GetProgress() ); str.Format( L"%i", nProgress ); Add( L"download_percent", str ); str.Format( L"%i", 100 - nProgress ); Add( L"download_percent_inverse", str ); Add( L"download_speed", Settings.SmartSpeed( pDownload->GetMeasuredSpeed() ) ); if ( CDownloadsCtrl::IsExpandable( pDownload ) ) { if ( pDownload->m_bExpanded ) Add( L"download_is_expanded", L"true" ); else Add( L"download_is_collapsed", L"true" ); } if ( pDownload->IsCompleted() ) Add( L"download_is_complete", L"true" ); else if ( pDownload->IsPaused() ) Add( L"download_is_paused", L"true" ); Add( L"download_status", pDownload->GetDownloadStatus() ); Add( L"download_sources", pDownload->GetDownloadSources() ); Output( L"downloadsDownload" ); if ( pDownload->m_bExpanded && CDownloadsCtrl::IsExpandable( pDownload ) ) { for ( POSITION posSource = pDownload->GetIterator(); posSource; ) { CDownloadSource* pSource = pDownload->GetNext( posSource ); ASSERT( pSource->m_pDownload == pDownload ); CString strSourceID; strSourceID.Format( L"%p", pSource ); if ( GetKey( L"modify_id" ) == strSourceID ) { CString strModifyAction = GetKey( L"modify_action" ); strModifyAction.MakeLower(); if ( strModifyAction == L"access" ) { // Only create a new Transfer if there isn't already one if ( pSource->IsIdle() && pSource->m_nProtocol != PROTOCOL_ED2K ) { if ( pDownload->IsPaused() ) pDownload->Resume(); // Workaround duplicate pDownload->Resume(); if ( pSource->m_bPushOnly ) pSource->PushRequest(); else if ( CDownloadTransfer* pTransfer = pSource->CreateTransfer() ) pTransfer->Initiate(); } } else if ( strModifyAction == L"forget" ) { pSource->Remove( TRUE, TRUE ); continue; } } if ( Settings.Downloads.ShowSources || pSource->IsConnected() ) { Add( L"source_id", strSourceID ); Add( L"source_agent", pSource->m_sServer ); Add( L"source_nick", pSource->m_sNick ); if ( ! pSource->IsIdle() ) { Add( L"source_status", pSource->GetState( FALSE ) ); Add( L"source_volume", Settings.SmartVolume( pSource->GetDownloaded() ) ); if ( DWORD nSpeed = pSource->GetMeasuredSpeed() ) Add( L"source_speed", Settings.SmartSpeed( nSpeed ) ); Add( L"source_address", pSource->GetAddress() ); Add( L"source_caption", pSource->GetAddress() + L" - " + pSource->m_sNick ); } else // No transfer { Add( L"source_address", CString( inet_ntoa( pSource->m_pAddress ) ) ); Add( L"source_caption", CString( inet_ntoa( pSource->m_pAddress ) ) + L" - " + pSource->m_sNick ); if ( pSource->m_tAttempt > 0 ) { DWORD tNow = GetTickCount(); if ( pSource->m_tAttempt >= tNow ) { tNow = ( pSource->m_tAttempt - tNow ) / 1000; CString strSourceStatus; strSourceStatus.Format( L"%.2u:%.2u", tNow / 60, tNow % 60 ); Add( L"source_status", strSourceStatus ); } } } Output( L"downloadsSource" ); Prepare( L"source_" ); } } } Prepare( L"download_" ); } // for POSITION loop Output( L"downloadsBottom" ); Output( L"downloadsFooter" ); }
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; }