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

📄 downloads.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Downloads.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 "Downloads.h"
#include "Download.h"
#include "Transfers.h"
#include "Transfer.h"
#include "DownloadGroups.h"
#include "DownloadTransfer.h"
#include "DownloadTransferED2K.h"
#include "DownloadTransferBT.h"
#include "UploadQueues.h"

#include "Buffer.h"
#include "EDClient.h"
#include "QueryHit.h"
#include "MatchObjects.h"
#include "ShareazaURL.h"

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

#include "WndMain.h"

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

CDownloads Downloads;


//////////////////////////////////////////////////////////////////////
// CDownloads construction

CDownloads::CDownloads()
{
	m_nLimitGeneric	= Settings.Bandwidth.Downloads;
	m_nLimitDonkey	= Settings.Bandwidth.Downloads;
	m_nTransfers	= 0;
	m_nBandwidth	= 0;
	m_nRunCookie	= 0;
	m_bClosing		= FALSE;
	m_tLastConnect	= 0;
}

CDownloads::~CDownloads()
{
}

//////////////////////////////////////////////////////////////////////
// CDownloads add an empty download (privilaged)

CDownload* CDownloads::Add()
{
	CDownload* pDownload = new CDownload();
	m_pList.AddTail( pDownload );
	return pDownload;
}

//////////////////////////////////////////////////////////////////////
// CDownloads add download from a hit or from a file

CDownload* CDownloads::Add(CQueryHit* pHit)
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	
	CDownload* pDownload = NULL;
	
	if ( pDownload == NULL && pHit->m_bSHA1 )
		pDownload = FindBySHA1( &pHit->m_pSHA1 );
	if ( pDownload == NULL && pHit->m_bTiger )
		pDownload = FindByTiger( &pHit->m_pTiger );
	if ( pDownload == NULL && pHit->m_bED2K )
		pDownload = FindByED2K( &pHit->m_pED2K );
	
	if ( pDownload != NULL )
	{
		theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ALREADY, (LPCTSTR)pHit->m_sName );
		
		pDownload->AddSourceHit( pHit );
		pDownload->Resume();
	}
	else
	{
		pDownload = new CDownload();
		pDownload->AddSourceHit( pHit, TRUE );
		m_pList.AddTail( pDownload );
		
		theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ADDED,
			(LPCTSTR)pDownload->GetDisplayName(), pDownload->GetSourceCount() );
	}
	
	pHit->m_bDownload = TRUE;
	
	DownloadGroups.Link( pDownload );
	Transfers.StartThread();
	
	return pDownload;
}

CDownload* CDownloads::Add(CMatchFile* pFile)
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	
	CDownload* pDownload = NULL;
	
	if ( pDownload == NULL && pFile->m_bSHA1 )
		pDownload = FindBySHA1( &pFile->m_pSHA1 );
	if ( pDownload == NULL && pFile->m_bTiger )
		pDownload = FindByTiger( &pFile->m_pTiger );
	if ( pDownload == NULL && pFile->m_bED2K )
		pDownload = FindByED2K( &pFile->m_pED2K );
	
	if ( pDownload != NULL )
	{
		theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ALREADY, (LPCTSTR)pFile->m_pHits->m_sName );
		
		for ( CQueryHit* pHit = pFile->m_pHits ; pHit ; pHit = pHit->m_pNext )
		{
			pDownload->AddSourceHit( pHit );
		}
		
		pDownload->Resume();
	}
	else
	{
		pDownload = new CDownload();
		m_pList.AddTail( pDownload );
		
		if ( pFile->m_pBest != NULL )
		{
			pDownload->AddSourceHit( pFile->m_pBest, TRUE );
		}
		
		for ( CQueryHit* pHit = pFile->m_pHits ; pHit ; pHit = pHit->m_pNext )
		{
			if ( pHit != pFile->m_pBest )
			{
				pDownload->AddSourceHit( pHit, TRUE );
			}
		}
		
		theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ADDED,
			(LPCTSTR)pDownload->GetDisplayName(), pDownload->GetSourceCount() );
	}
	
	pFile->m_bDownload = TRUE;
	
	DownloadGroups.Link( pDownload );
	Transfers.StartThread();
	
	if ( pDownload->GetSourceCount() == 0 ||
		 ( pDownload->m_bED2K && ! pDownload->m_bSHA1 ) )
	{
		pDownload->FindMoreSources();
	}
	
	return pDownload;
}

//////////////////////////////////////////////////////////////////////
// CDownloads add download from a URL

CDownload* CDownloads::Add(CShareazaURL* pURL)
{
	if ( pURL->m_nAction != CShareazaURL::uriDownload &&
		 pURL->m_nAction != CShareazaURL::uriSource ) return NULL;
	
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	CDownload* pDownload = NULL;
	
	if ( pDownload == NULL && pURL->m_bSHA1 )
		pDownload = FindBySHA1( &pURL->m_pSHA1 );
	if ( pDownload == NULL && pURL->m_bTiger )
		pDownload = FindByTiger( &pURL->m_pTiger );
	if ( pDownload == NULL && pURL->m_bED2K )
		pDownload = FindByED2K( &pURL->m_pED2K );
	if ( pDownload == NULL && pURL->m_bBTH )
		pDownload = FindByBTH( &pURL->m_pBTH );
	
	if ( pDownload != NULL )
	{
		theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ALREADY,
			(LPCTSTR)pDownload->GetDisplayName() );
		
		if ( pURL->m_sURL.GetLength() ) pDownload->AddSourceURLs( pURL->m_sURL, FALSE );
		
		return pDownload;
	}
	
	pDownload = new CDownload();
	
	if ( pURL->m_bSHA1 )
	{
		pDownload->m_bSHA1 = TRUE;
		pDownload->m_pSHA1 = pURL->m_pSHA1;
	}
	if ( pURL->m_bTiger )
	{
		pDownload->m_bTiger = TRUE;
		pDownload->m_pTiger = pURL->m_pTiger;
	}
	if ( pURL->m_bMD5 )
	{
		pDownload->m_bMD5 = TRUE;
		pDownload->m_pMD5 = pURL->m_pMD5;
	}
	if ( pURL->m_bED2K )
	{
		pDownload->m_bED2K = TRUE;
		pDownload->m_pED2K = pURL->m_pED2K;
		pDownload->Share( TRUE );
	}
	if ( pURL->m_bBTH )
	{
		pDownload->m_bBTH = TRUE;
		pDownload->m_pBTH = pURL->m_pBTH;
		pDownload->Share( TRUE );
	}
	
	if ( pURL->m_sName.GetLength() )
	{
		pDownload->m_sRemoteName = pURL->m_sName;
	}
	
	if ( pURL->m_bSize )
	{
		pDownload->m_nSize = pURL->m_nSize;
	}
	
	if ( pURL->m_sURL.GetLength() )
	{
		if ( ! pDownload->AddSourceURLs( pURL->m_sURL, FALSE ) )
		{
			if ( pURL->m_nAction == CShareazaURL::uriSource )
			{
				delete pDownload;
				return NULL;
			}
		}
	}
	
	pDownload->SetTorrent( pURL->m_pTorrent );
	
	m_pList.AddTail( pDownload );
	
	theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ADDED,
		(LPCTSTR)pDownload->GetDisplayName(), pDownload->GetSourceCount() );
	
	if ( pURL->m_nAction != CShareazaURL::uriSource )
		pDownload->FindMoreSources();
	
	DownloadGroups.Link( pDownload );
	Transfers.StartThread();
	
	return pDownload;
}

//////////////////////////////////////////////////////////////////////
// CDownloads commands

void CDownloads::PauseAll()
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		GetNext( pos )->Pause();
	}
}

void CDownloads::ClearCompleted()
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->IsCompleted() ) pDownload->Remove();
	}
}

void CDownloads::ClearPaused()
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );

	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->IsPaused() ) pDownload->Remove();
	}
}

void CDownloads::Clear(BOOL bShutdown)
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	m_bClosing = TRUE;
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		Remove( GetNext( pos ) );
	}
	
	m_pList.RemoveAll();
	m_bClosing = bShutdown;
}

void CDownloads::CloseTransfers()
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	
	m_bClosing = TRUE;
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		GetNext( pos )->CloseTransfers();
	}
	
	m_bClosing = FALSE;
	m_nTransfers = 0;
	m_nBandwidth = 0;
}

//////////////////////////////////////////////////////////////////////
// CDownloads list access

int CDownloads::GetCount(BOOL bActiveOnly) const
{
	if ( ! bActiveOnly ) return m_pList.GetCount();
	
	int nCount = 0;
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		
		if ( ! pDownload->IsMoving() && ! pDownload->IsPaused() &&
			 pDownload->GetSourceCount( TRUE ) > 0 )
				nCount++;
	}
	
	return nCount;
}

int CDownloads::GetTransferCount() const
{
	int nCount = 0;
	
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		nCount += GetNext( pos )->GetTransferCount();
	}
	
	return nCount;
}

void CDownloads::Remove(CDownload* pDownload)
{
	POSITION pos = m_pList.Find( pDownload );
	if ( pos != NULL ) m_pList.RemoveAt( pos );
	delete pDownload;
}

//////////////////////////////////////////////////////////////////////
// CDownloads find by pointer or hash

BOOL CDownloads::Check(CDownloadSource* pSource) const
{
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		if ( GetNext( pos )->CheckSource( pSource ) ) return TRUE;
	}
	return FALSE;
}

BOOL CDownloads::CheckActive(CDownload* pDownload, int nScope) const
{
	for ( POSITION pos = GetReverseIterator() ; pos && nScope > 0 ; )
	{
		CDownload* pTest = GetPrevious( pos );
		BOOL bActive = pTest->IsPaused() == FALSE && pTest->IsCompleted() == FALSE;
		
		if ( pDownload == pTest ) return bActive;
		if ( bActive ) nScope--;
	}
	
	return FALSE;
}

CDownload* CDownloads::FindByURN(LPCTSTR pszURN, BOOL bSharedOnly) const
{
	CDownload* pDownload;
	TIGEROOT pTiger;
	SHA1 pSHA1;
	MD4 pED2K;
	
	if ( CSHA::HashFromURN( pszURN, &pSHA1 ) )
	{
		if ( pDownload = FindBySHA1( &pSHA1, bSharedOnly ) ) return pDownload;
	}
	
	if ( CTigerNode::HashFromURN( pszURN, &pTiger ) )
	{
		if ( pDownload = FindByTiger( &pTiger, bSharedOnly ) ) return pDownload;
	}
	
	if ( CED2K::HashFromURN( pszURN, &pED2K ) )
	{
		if ( pDownload = FindByED2K( &pED2K, bSharedOnly ) ) return pDownload;
	}
	
	return NULL;
}

CDownload* CDownloads::FindBySHA1(const SHA1* pSHA1, BOOL bSharedOnly) const
{
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->m_bSHA1 && pDownload->m_pSHA1 == *pSHA1 )
		{
			if ( ! bSharedOnly || ( pDownload->IsShared() && pDownload->IsStarted() ) )
				return pDownload;
		}
	}
	
	return NULL;
}

CDownload* CDownloads::FindByTiger(const TIGEROOT* pTiger, BOOL bSharedOnly) const
{
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->m_bTiger && pDownload->m_pTiger == *pTiger )
		{
			if ( ! bSharedOnly || ( pDownload->IsShared() && pDownload->IsStarted() ) )
				return pDownload;
		}
	}
	
	return NULL;
}

CDownload* CDownloads::FindByED2K(const MD4* pED2K, BOOL bSharedOnly) const
{
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->m_bED2K && pDownload->m_pED2K == *pED2K )
		{
			if ( ! bSharedOnly || ( pDownload->IsShared() && pDownload->IsStarted() ) )
				return pDownload;
		}
	}
	
	return NULL;
}

CDownload* CDownloads::FindByBTH(const SHA1* pBTH, BOOL bSharedOnly) const
{
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->m_bBTH && pDownload->m_pBTH == *pBTH )
		{
			if ( ! bSharedOnly || ( pDownload->IsShared() ) )
				return pDownload;
		}
	}
	
	return NULL;
}

//////////////////////////////////////////////////////////////////////
// CDownloads serialization ID

CDownload* CDownloads::FindBySID(DWORD nSerID) const
{
	for ( POSITION pos = GetIterator() ; pos ; )
	{
		CDownload* pDownload = GetNext( pos );
		if ( pDownload->m_nSerID == nSerID ) return pDownload;
	}
	
	return NULL;
}

DWORD CDownloads::GetFreeSID()
{
	for ( ;; )
	{
		DWORD nSerID	= ( rand() & 0xFF ) + ( ( rand() & 0xFF ) << 8 )
						+ ( ( rand() & 0xFF ) << 16 ) + ( ( rand() & 0xFF ) << 24 );
		
		for ( POSITION pos = GetIterator() ; pos ; )
		{
			CDownload* pDownload = GetNext( pos );
			if ( pDownload->m_nSerID == nSerID ) { nSerID = 0; break; }
		}
		
		if ( nSerID ) return nSerID;
	}
	
	ASSERT( FALSE );
	return 0;
}

//////////////////////////////////////////////////////////////////////
// CDownloads ordering

BOOL CDownloads::Move(CDownload* pDownload, int nDelta)
{
	CSingleLock pLock( &Transfers.m_pSection, TRUE );
	
	POSITION posMe = m_pList.Find( pDownload );
	if ( posMe == NULL ) return FALSE;
	
	POSITION posOther = posMe;
	
	if ( nDelta < 0 )
		m_pList.GetPrev( posOther );
	else
		m_pList.GetNext( posOther );
	
	if ( posOther == NULL) return FALSE;
	
	if ( nDelta < 0 )

⌨️ 快捷键说明

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