⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloadtransfer.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// DownloadTransfer.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Download.h"
#include "Downloads.h"
#include "DownloadSource.h"
#include "DownloadTransfer.h"
#include "FragmentedFile.h"
#include "Network.h"
#include "Buffer.h"
#include "SHA.h"
#include "ED2K.h"
#include "SourceURL.h"
#include "XML.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////
// CDownloadTransfer construction

CDownloadTransfer::CDownloadTransfer(CDownloadSource* pSource, PROTOCOLID nProtocol)
{
	m_nProtocol		= nProtocol;
	m_pDownload		= pSource->m_pDownload;
	m_pDlPrev		= NULL;
	m_pDlNext		= NULL;
	m_pSource		= pSource;
	
	m_nState		= dtsNull;
	
	m_nQueuePos		= 0;
	m_nQueueLen		= 0;
	
	m_nOffset		= SIZE_UNKNOWN;
	m_nLength		= 0;
	m_nPosition		= 0;
	m_nDownloaded	= 0;
	
	m_bWantBackwards = m_bRecvBackwards = FALSE;
	
	m_pDownload->AddTransfer( this );
}

CDownloadTransfer::~CDownloadTransfer()
{
	ASSERT( m_pSource == NULL );
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransfer close

void CDownloadTransfer::Close(TRISTATE bKeepSource)
{
	CTransfer::Close();
	
	if ( m_pSource != NULL )
	{
		switch ( bKeepSource )
		{
		case TS_TRUE:
			m_pSource->OnFailure( TRUE );
			break;
		case TS_UNKNOWN:
			m_pSource->OnFailure( FALSE );
			break;
		case TS_FALSE:
			m_pSource->Remove( FALSE, TRUE );
			break;
		}
		
		m_pSource = NULL;
	}
	
	ASSERT( m_pDownload != NULL );
	m_pDownload->RemoveTransfer( this );
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransfer speed controls

void CDownloadTransfer::Boost()
{
	m_mInput.pLimit = m_mOutput.pLimit = NULL;
}

DWORD CDownloadTransfer::GetAverageSpeed()
{
	return GetMeasuredSpeed();
}

DWORD CDownloadTransfer::GetMeasuredSpeed()
{
	Measure();
	return m_mInput.nMeasure;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransfer state

CString CDownloadTransfer::GetStateText(BOOL bLong)
{
	CString str;
	
	switch ( m_nState )
	{
	case dtsConnecting:
		str = _T("Connecting");
		break;
	case dtsRequesting:
		str = _T("Requesting");
		break;
	case dtsHeaders:
	case dtsFlushing:
		str = _T("Response");
		break;
	case dtsDownloading:
		str = _T("Downloading");
		break;
	case dtsTiger:
		str = _T("TigerTree");
		break;
	case dtsHashset:
		str = _T("Hashset");
		break;
	case dtsMetadata:
		str = _T("Metadata");
		break;
	case dtsBusy:
		str = _T("Busy");
		break;
	case dtsEnqueue:
		str = _T("Enqueue");
		break;
	case dtsQueued:
		if ( ! bLong )
		{
			str.Format( m_nQueueLen ? _T("Q %i of %i") : _T("Q #%i"),
				m_nQueuePos, m_nQueueLen );
		}
		else if ( m_sQueueName.GetLength() )
		{
			str.Format( _T("Queued: %s: %i of %i"),
				(LPCTSTR)m_sQueueName, m_nQueuePos, m_nQueueLen );
		}
		else
		{
			str.Format( _T("Queued: %i of %i"),
				m_nQueuePos, m_nQueueLen );
		}
		break;
	default:
		str = _T("Unknown");
		break;
	}
	
	return str;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransfer run handler

BOOL CDownloadTransfer::OnRun()
{
	return CTransfer::OnRun();
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransfer state management

void CDownloadTransfer::SetState(int nState)
{
	if ( m_pDownload != NULL )
	{
		if ( nState == dtsDownloading && m_nState != dtsDownloading )
		{
			m_pDownload->SortSource( m_pSource, TRUE );
		}
		else if ( nState != dtsDownloading && m_nState == dtsDownloading )
		{
			m_pDownload->SortSource( m_pSource, FALSE );
		}
	}
	
	m_nState = nState;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransfer fragment size management

void CDownloadTransfer::ChunkifyRequest(QWORD* pnOffset, QWORD* pnLength, QWORD nChunk, BOOL bVerifyLock)
{
	ASSERT( pnOffset != NULL && pnLength != NULL );
	
	if ( m_pSource->m_bCloseConn ) return;
	
	nChunk = min( nChunk, (QWORD)Settings.Downloads.ChunkSize );
	
	if ( bVerifyLock )
	{
		if ( QWORD nVerify = m_pDownload->GetVerifyLength() )
		{
			nVerify = nVerify * 3 / 2;
			nChunk = max( nChunk, nVerify );
		}
		
		if ( Settings.Downloads.ChunkStrap > 0 && m_nDownloaded == 0 )
		{
			nChunk = Settings.Downloads.ChunkStrap;
		}
	}
	
	if ( nChunk == 0 || *pnLength <= nChunk ) return;
	
	if ( m_pDownload->GetVolumeComplete() == 0 || *pnOffset == 0 )
	{
		*pnLength = nChunk;
	}
	else if ( m_bWantBackwards )
	{
		*pnOffset = *pnOffset + *pnLength - nChunk;
		*pnLength = nChunk;
	}
	else
	{
		QWORD nCount = *pnLength / nChunk;
		if ( *pnLength % nChunk ) nCount++;
		nCount = rand() % nCount;
		
		QWORD nStart = *pnOffset + nChunk * nCount;
		*pnLength = min( nChunk, *pnOffset + *pnLength - nStart );
		*pnOffset = nStart;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -