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

📄 uploadtransfer.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
字号:
//
// UploadTransfer.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 "Uploads.h"
#include "UploadFile.h"
#include "UploadFiles.h"
#include "UploadQueue.h"
#include "UploadQueues.h"
#include "TransferFile.h"
#include "UploadTransfer.h"
#include "UploadTransferHTTP.h"

#include "SharedFile.h"
#include "Download.h"

#include "TigerTree.h"
#include "SHA.h"
#include "ED2K.h"

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


//////////////////////////////////////////////////////////////////////
// CUploadTransfer construction

CUploadTransfer::CUploadTransfer(PROTOCOLID nProtocol)
{
	ClearRequest();
	
	m_nProtocol		= nProtocol;
	m_nState		= upsNull;
	m_pQueue		= NULL;
	m_pBaseFile		= NULL;
	m_pDiskFile		= NULL;
	m_nBandwidth	= Settings.Bandwidth.Request;
	
	m_bLive			= TRUE;
	m_nRequests		= 0;
	m_nUploaded		= 0;
	
	m_tRotateTime	= 0;
	m_tAverageTime	= 0;
	m_nAveragePos	= 0;
	ZeroMemory( m_nAverageRate, sizeof(m_nAverageRate) );
	
	Uploads.Add( this );
}

CUploadTransfer::~CUploadTransfer()
{
	Close( FALSE );
	UploadFiles.Remove( this );
	Uploads.Remove( this );
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer remove record

void CUploadTransfer::Remove(BOOL bMessage)
{
	ASSERT( this != NULL );
	
	if ( bMessage && m_sFileName.GetLength() > 0 )
	{
		theApp.Message( MSG_SYSTEM, IDS_UPLOAD_REMOVE,
			(LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
	}
	
	m_nUploaded = 1;
	Close( FALSE );
	
	delete this;
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer close connection

void CUploadTransfer::Close(BOOL bMessage)
{
	if ( m_nState == upsNull ) return;
	m_nState = upsNull;
	
	CTransfer::Close();
	UploadQueues.Dequeue( this );
	CloseFile();
	
	if ( bMessage ) theApp.Message( MSG_SYSTEM, IDS_UPLOAD_DROPPED, (LPCTSTR)m_sAddress );
	if ( m_nUploaded == 0 ) Remove( FALSE );
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer promotion

BOOL CUploadTransfer::Promote()
{
	if ( m_nState != upsQueued ) return FALSE;
	UploadQueues.Dequeue( this );
	return UploadQueues.Enqueue( this, true );
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer rename handler

BOOL CUploadTransfer::OnRename(LPCTSTR pszSource, LPCTSTR pszTarget)
{
	if ( m_nState != upsUploading || _tcsicmp( m_sFilePath, pszSource ) ) return FALSE;
	
	if ( pszTarget == NULL )
	{
		theApp.Message( MSG_ERROR, IDS_UPLOAD_DELETED, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
		Close();
		return TRUE;
	}
	
	if ( pszTarget == (LPCTSTR)1 )
	{
		if ( m_pDiskFile != NULL )
		{
			m_pDiskFile->Release( FALSE );
			m_pDiskFile = NULL;
		}
	}
	else if ( m_pDiskFile == NULL )
	{
		m_sFilePath = pszTarget;
		m_pDiskFile = TransferFiles.Open( m_sFilePath, FALSE, FALSE );
		
		if ( m_pDiskFile == NULL )
		{
			theApp.Message( MSG_ERROR, IDS_UPLOAD_DELETED, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
			Close();
		}
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer statistics

float CUploadTransfer::GetProgress()
{
	if ( m_nState != upsUploading || m_nLength == 0 || m_nLength == SIZE_UNKNOWN ) return 0;
	return (float)m_nPosition / (float)m_nLength;
}

DWORD CUploadTransfer::GetAverageSpeed()
{
	if ( m_nState != upsUploading || m_nLength == 0 || m_nLength == SIZE_UNKNOWN ) return GetMeasuredSpeed();
	DWORD nTime = ( GetTickCount() - m_tContent ) / 1000;
	return nTime ? (DWORD)( m_nPosition / nTime ) : 0;
}

DWORD CUploadTransfer::GetMeasuredSpeed()
{
	Measure();
	return m_mOutput.nMeasure;
}

void CUploadTransfer::SetSpeedLimit(DWORD nLimit)
{
	ZeroMemory( m_nAverageRate, sizeof(DWORD) * ULA_SLOTS );
	m_nBandwidth	= nLimit;
	m_tAverageTime	= 0;
	m_nAveragePos	= 0;
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer run handler

BOOL CUploadTransfer::OnRun()
{
	DWORD tNow = GetTickCount();
	LongTermAverage( tNow );
	RotatingQueue( tNow );
	return CTransfer::OnRun();
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer read and write handlers

BOOL CUploadTransfer::OnRead()
{
	DWORD tLastRead = m_mInput.tLast;
	
	if ( ! CTransfer::OnRead() ) return FALSE;
	
	if ( m_mInput.tLast != tLastRead && ! m_bLive )
	{
		m_bLive = TRUE;
		Uploads.EnforcePerHostLimit( this );
	}
	
	return TRUE;
}

BOOL CUploadTransfer::OnWrite()
{
	DWORD tLastSend = m_mOutput.tLast;
	
	if ( ! CTransfer::OnWrite() ) return FALSE;
	
	if ( m_mOutput.tLast != tLastSend && ! m_bLive )
	{
		m_bLive = TRUE;
		Uploads.EnforcePerHostLimit( this );
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer long term averaging

void CUploadTransfer::LongTermAverage(DWORD tNow)
{
	if ( m_nState != upsUploading || m_nLength == 0 || m_nLength == SIZE_UNKNOWN ) return;
	
	DWORD nSpeed = GetMeasuredSpeed();
	
	if ( Settings.Live.BandwidthScale < 100 )
	{
		nSpeed = nSpeed * 100 / max( 1, Settings.Live.BandwidthScale );
	}
	
	m_nAverageRate[ m_nAveragePos ] = max( m_nAverageRate[ m_nAveragePos ], nSpeed );
	
	if ( tNow - m_tAverageTime < 2000 || m_nAverageRate[ m_nAveragePos ] == 0 ) return;
	
	m_tAverageTime = tNow;
	m_nAveragePos = ( m_nAveragePos + 1 ) % ULA_SLOTS;
	
	DWORD nAverage = 0;
	
	for ( int nPos = 0 ; nPos < ULA_SLOTS ; nPos++ )
	{
		if ( m_nAverageRate[ nPos ] == 0 ) return;
		nAverage += m_nAverageRate[ nPos ];
	}
	
	m_nAverageRate[ m_nAveragePos ] = 0;
	nAverage = nAverage / ULA_SLOTS * 9 / 8;
	nAverage = max( nAverage, Settings.Uploads.ClampdownFloor );
	
	if ( nAverage < m_nBandwidth * ( 100 - Settings.Uploads.ClampdownFactor ) / 100 )
	{
		DWORD nOld = m_nBandwidth;	// Save
		
		m_nBandwidth = min( nAverage, m_nBandwidth );
		
		theApp.Message( MSG_DEBUG, _T("Changing upload throttle on %s from %s to %s"),
			(LPCTSTR)m_sAddress,
			(LPCTSTR)Settings.SmartVolume( nOld * 8, FALSE, TRUE ),
			(LPCTSTR)Settings.SmartVolume( m_nBandwidth * 8, FALSE, TRUE ) );
	}
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer rotating queue

void CUploadTransfer::RotatingQueue(DWORD tNow)
{
	CSingleLock pLock( &UploadQueues.m_pSection, TRUE );
	
	if ( m_pQueue != NULL && UploadQueues.Check( m_pQueue ) &&
		 m_pQueue->m_bRotate && m_pQueue->IsActive( this ) )
	{
		if ( m_tRotateTime == 0 )
		{
			if ( m_nState == upsUploading ) m_tRotateTime = tNow;
		}
		else if ( tNow - m_tRotateTime >= m_pQueue->m_nRotateTime * 1000 )
		{
			m_tRotateTime = 0;
			
			CUploadQueue* pQueue = m_pQueue;
			pQueue->Dequeue( this );
			pQueue->Enqueue( this, TRUE, FALSE );
			
			pLock.Unlock();
			OnQueueKick();
		}
	}
	else
	{
		m_tRotateTime = 0;
	}
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer hash utilities

void CUploadTransfer::ClearHashes()
{
	m_bSHA1 = m_bTiger = m_bED2K = FALSE;
}

BOOL CUploadTransfer::HashesFromURN(LPCTSTR pszURN)
{
	m_bSHA1		|= CSHA::HashFromURN( pszURN, &m_pSHA1 );
	m_bTiger	|= CTigerNode::HashFromURN( pszURN, &m_pTiger );
	m_bED2K		|= CED2K::HashFromURN( pszURN, &m_pED2K );
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer request utilities

void CUploadTransfer::ClearRequest()
{
	m_sFileName.Empty();
	m_sFilePath.Empty();
	m_sFileTags.Empty();
	
	m_nFileBase		= 0;
	m_nFileSize		= 0;
	m_bFilePartial	= FALSE;
	
	m_nOffset		= 0;
	m_nLength		= SIZE_UNKNOWN;
	m_nPosition		= 0;
	m_nRequests ++;
	
	ClearHashes();
	ClearHeaders();
}

BOOL CUploadTransfer::RequestComplete(CLibraryFile* pFile)
{
	ASSERT( pFile != NULL );
	
	if ( m_bSHA1 && pFile->m_bSHA1 && m_pSHA1 != pFile->m_pSHA1 ) return FALSE;
	if ( m_bTiger && pFile->m_bTiger && m_pTiger != pFile->m_pTiger ) return FALSE;
	if ( m_bED2K && pFile->m_bED2K && m_pED2K != pFile->m_pED2K ) return FALSE;
	
	m_sFileName	= pFile->m_sName;
	m_sFilePath	= pFile->GetPath();
	m_nFileBase	= pFile->m_nVirtualSize > 0 ? pFile->m_nVirtualBase : 0;
	m_nFileSize	= pFile->m_nVirtualSize > 0 ? pFile->m_nVirtualSize : pFile->m_nSize;
	m_sFileTags	= pFile->m_sShareTags;
	m_bFilePartial = FALSE;
	
	if ( m_bSHA1 = pFile->m_bSHA1 ) m_pSHA1 = pFile->m_pSHA1;
	if ( m_bTiger = pFile->m_bTiger ) m_pTiger = pFile->m_pTiger;
	if ( m_bED2K = pFile->m_bED2K ) m_pED2K = pFile->m_pED2K;
	
	return TRUE;
}

BOOL CUploadTransfer::RequestPartial(CDownload* pFile)
{
	ASSERT( pFile != NULL );
	
	if ( m_bSHA1 && pFile->m_bSHA1 && m_pSHA1 != pFile->m_pSHA1 ) return FALSE;
	if ( m_bTiger && pFile->m_bTiger && m_pTiger != pFile->m_pTiger ) return FALSE;
	if ( m_bED2K && pFile->m_bED2K && m_pED2K != pFile->m_pED2K ) return FALSE;
	
	m_sFileName	= pFile->m_sRemoteName;
	m_sFilePath	= pFile->m_sLocalName;
	m_nFileBase	= 0;
	m_nFileSize	= pFile->m_nSize;
	m_bFilePartial = TRUE;
	m_sFileTags.Empty();
	
	if ( m_bSHA1 && ! pFile->m_bSHA1 )
	{
		pFile->m_bSHA1 = TRUE;
		pFile->m_pSHA1 = m_pSHA1;
	}
	else if ( m_bSHA1 = pFile->m_bSHA1 )
	{
		m_pSHA1 = pFile->m_pSHA1;
	}
	
	if ( m_bTiger && ! pFile->m_bTiger )
	{
		pFile->m_bTiger = TRUE;
		pFile->m_pTiger = m_pTiger;
	}
	else if ( m_bTiger = pFile->m_bTiger )
	{
		m_pTiger = pFile->m_pTiger;
	}
	
	if ( m_bED2K && ! pFile->m_bED2K )
	{
		pFile->m_bED2K = TRUE;
		pFile->m_pED2K = m_pED2K;
	}
	else if ( m_bED2K = pFile->m_bED2K )
	{
		m_pED2K = pFile->m_pED2K;
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CUploadTransfer file utilities

void CUploadTransfer::StartSending(int nState)
{
	m_nState	= nState;
	m_nPosition	= 0;
	m_tContent	= m_mOutput.tLast = GetTickCount();
	CTransfer::OnWrite();
}

void CUploadTransfer::AllocateBaseFile()
{
	m_pBaseFile =	UploadFiles.GetFile( this, m_bSHA1 ? &m_pSHA1 : NULL,
					m_sFileName, m_sFilePath, m_nFileSize );
}

void CUploadTransfer::CloseFile()
{
	if ( m_pDiskFile != NULL )
	{
		m_pDiskFile->Release( FALSE );
		m_pDiskFile = NULL;
	}
}

⌨️ 快捷键说明

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