📄 downloads.cpp
字号:
//
// 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 + -