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;
}
Пример #5
0
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;
}