📄 downloads.cpp
字号:
m_pList.InsertBefore( posOther, pDownload );
else
m_pList.InsertAfter( posOther, pDownload );
m_pList.RemoveAt( posMe );
DownloadGroups.IncBaseCookie();
return TRUE;
}
BOOL CDownloads::Reorder(CDownload* pDownload, CDownload* pBefore)
{
CSingleLock pLock( &Transfers.m_pSection, TRUE );
POSITION pos1 = m_pList.Find( pDownload );
if ( pos1 == NULL ) return FALSE;
if ( pBefore != NULL )
{
POSITION pos2 = m_pList.Find( pBefore );
if ( pos2 == NULL || pos1 == pos2 ) return FALSE;
m_pList.RemoveAt( pos1 );
m_pList.InsertBefore( pos2, pDownload );
}
else
{
m_pList.RemoveAt( pos1 );
m_pList.AddTail( pDownload );
}
DownloadGroups.IncBaseCookie();
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloads bandwidth
DWORD CDownloads::GetBandwidth() const
{
DWORD nTotal = 0;
for ( POSITION pos = GetIterator() ; pos ; )
{
nTotal += GetNext( pos )->GetMeasuredSpeed();
}
return nTotal;
}
//////////////////////////////////////////////////////////////////////
// CDownloads limiting tests
void CDownloads::UpdateAllows(BOOL bNew)
{
int nDownloads = 0;
int nTransfers = 0;
if ( bNew ) m_tLastConnect = GetTickCount();
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownload* pDownload = GetNext( pos );
int nTemp = pDownload->GetTransferCount();
if ( nTemp )
{
nDownloads ++;
nTransfers += nTemp;
}
}
m_bAllowMoreDownloads = nDownloads < Settings.Downloads.MaxFiles;
m_bAllowMoreTransfers = nTransfers < Settings.Downloads.MaxTransfers;
}
BOOL CDownloads::AllowMoreDownloads() const
{
int nCount = 0;
for ( POSITION pos = GetIterator() ; pos ; )
{
if ( GetNext( pos )->GetTransferCount() ) nCount++;
}
return nCount < Settings.Downloads.MaxFiles;
}
BOOL CDownloads::AllowMoreTransfers(IN_ADDR* pAddress) const
{
int nCount = 0, nLimit = 0;
for ( POSITION pos = GetIterator() ; pos ; )
{
nCount += GetNext( pos )->GetTransferCount( dtsCountAll, pAddress );
}
if ( pAddress == NULL ) return nCount < Settings.Downloads.MaxTransfers;
if ( m_pHostLimits.Lookup( (LPVOID)pAddress->S_un.S_addr, (void*&)nLimit ) )
{
return ( nCount < nLimit );
}
else
{
return ( nCount == 0 );
}
}
void CDownloads::SetPerHostLimit(IN_ADDR* pAddress, int nLimit)
{
m_pHostLimits.SetAt( (LPVOID)pAddress->S_un.S_addr, (LPVOID)nLimit );
}
//////////////////////////////////////////////////////////////////////
// CDownloads disk space helper
BOOL CDownloads::IsSpaceAvailable(QWORD nVolume)
{
QWORD nMargin = 10485760;
if ( HINSTANCE hKernel = LoadLibrary( _T("KERNEL32.DLL") ) )
{
BOOL (WINAPI *pfnGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
(FARPROC&)pfnGetDiskFreeSpaceEx = GetProcAddress( hKernel, "GetDiskFreeSpaceExA" );
if ( pfnGetDiskFreeSpaceEx != NULL )
{
ULARGE_INTEGER nFree, nNull;
if ( (*pfnGetDiskFreeSpaceEx)( Settings.Downloads.IncompletePath, &nFree, &nNull, &nNull ) )
{
if ( nFree.QuadPart < nVolume + nMargin ) return FALSE;
if ( (*pfnGetDiskFreeSpaceEx)( Settings.Downloads.CompletePath, &nFree, &nNull, &nNull ) )
{
if ( nFree.QuadPart < nVolume + nMargin ) return FALSE;
}
return TRUE;
}
}
FreeLibrary( hKernel );
}
CString str = Settings.Downloads.IncompletePath.SpanExcluding( _T("\\") ) + '\\';
DWORD nSPC, nBPS, nFree, nTotal;
if ( GetDiskFreeSpace( str, &nSPC, &nBPS, &nFree, &nTotal ) )
{
QWORD nBytes = (QWORD)nSPC * (QWORD)nBPS * (QWORD)nFree;
if ( nBytes < nVolume + nMargin ) return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloads run callback (threaded)
void CDownloads::OnRun()
{
CSingleLock pLock( &Transfers.m_pSection );
DWORD nActiveDownloads = 0;
DWORD nActiveTransfers = 0;
DWORD nTotalTransfers = 0;
DWORD nTotalBandwidth = 0;
m_nValidation = 0;
m_nRunCookie ++;
while ( TRUE )
{
BOOL bWorked = FALSE;
pLock.Lock();
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownload* pDownload = GetNext( pos );
if ( pDownload->m_nRunCookie == m_nRunCookie ) continue;
pDownload->m_nRunCookie = m_nRunCookie;
pDownload->OnRun();
int nTemp = 0;
for ( CDownloadTransfer* pTransfer = pDownload->GetFirstTransfer() ; pTransfer ; pTransfer = pTransfer->m_pDlNext )
{
if ( pTransfer->m_nProtocol == PROTOCOL_ED2K )
{
CDownloadTransferED2K* pED2K = (CDownloadTransferED2K*)pTransfer;
if ( pED2K->m_pClient == NULL || pED2K->m_pClient->m_bConnected == FALSE ) continue;
if ( pTransfer->m_nState == dtsQueued ) continue;
}
else if ( pTransfer->m_nProtocol == PROTOCOL_BT )
{
CDownloadTransferBT* pBT = (CDownloadTransferBT*)pTransfer;
if ( pBT->m_nState == dtsTorrent && pBT->m_bChoked ) continue;
}
nTemp ++;
if ( pTransfer->m_nState == dtsDownloading )
{
nTotalBandwidth += pTransfer->GetMeasuredSpeed();
nActiveTransfers ++;
}
}
if ( nTemp )
{
nActiveDownloads ++;
nTotalTransfers += nTemp;
}
bWorked = TRUE;
break;
}
pLock.Unlock();
if ( ! bWorked ) break;
}
m_nTransfers = nActiveTransfers;
m_nBandwidth = nTotalBandwidth;
m_bAllowMoreDownloads = nActiveDownloads < (DWORD)Settings.Downloads.MaxFiles;
m_bAllowMoreTransfers = nTotalTransfers < (DWORD)Settings.Downloads.MaxTransfers;
if ( nActiveTransfers > 0 )
{
m_nLimitGeneric = Settings.Bandwidth.Downloads / nActiveTransfers;
m_nLimitDonkey = UploadQueues.GetDonkeyBandwidth();
if ( m_nLimitDonkey < 10240 )
m_nLimitDonkey = min( m_nLimitGeneric, m_nLimitDonkey * 3 / nActiveTransfers );
else
m_nLimitDonkey = m_nLimitGeneric;
}
else
{
m_nLimitGeneric = m_nLimitDonkey = Settings.Bandwidth.Downloads;
}
DownloadGroups.Save( FALSE );
}
//////////////////////////////////////////////////////////////////////
// CDownloads query hit handler
void CDownloads::OnQueryHits(CQueryHit* pHits)
{
CSingleLock pLock( &Transfers.m_pSection );
if ( ! pLock.Lock( 50 ) ) return;
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownload* pDownload = GetNext( pos );
if ( pDownload->IsMoving() == FALSE ) pDownload->OnQueryHits( pHits );
}
}
//////////////////////////////////////////////////////////////////////
// CDownloads push handler
BOOL CDownloads::OnPush(GGUID* pGUID, CConnection* pConnection)
{
CSingleLock pLock( &Transfers.m_pSection );
if ( ! pLock.Lock( 250 ) ) return FALSE;
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownload* pDownload = GetNext( pos );
if ( pDownload->OnAcceptPush( pGUID, pConnection ) ) return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDownloads eDonkey2000 callback handler
BOOL CDownloads::OnDonkeyCallback(CEDClient* pClient, CDownloadSource* pExcept)
{
CSingleLock pLock( &Transfers.m_pSection );
if ( ! pLock.Lock( 250 ) ) return FALSE;
if ( m_bClosing ) return FALSE;
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownload* pDownload = GetNext( pos );
if ( pDownload->OnDonkeyCallback( pClient, pExcept ) ) return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDownloads verification handler
void CDownloads::OnVerify(LPCTSTR pszPath, BOOL bVerified)
{
CSingleLock pLock( &Transfers.m_pSection );
if ( ! pLock.Lock( 500 ) ) return;
for ( POSITION pos = GetIterator() ; pos ; )
{
if ( GetNext( pos )->OnVerify( pszPath, bVerified ) ) break;
}
}
//////////////////////////////////////////////////////////////////////
// CDownloads load and save
void CDownloads::Load()
{
CSingleLock pLock( &Transfers.m_pSection, TRUE );
WIN32_FIND_DATA pFind;
CString strPath;
HANDLE hSearch;
PurgeDeletes();
PurgePreviews();
DownloadGroups.CreateDefault();
LoadFromCompoundFiles();
strPath = Settings.Downloads.IncompletePath + _T("\\*.sd");
hSearch = FindFirstFile( strPath, &pFind );
if ( hSearch != INVALID_HANDLE_VALUE )
{
do
{
CDownload* pDownload = new CDownload();
strPath.Format( _T("%s\\%s"), (LPCTSTR)Settings.Downloads.IncompletePath, pFind.cFileName );
if ( pDownload->Load( strPath ) )
{
m_pList.AddTail( pDownload );
}
else
{
delete pDownload;
}
}
while ( FindNextFile( hSearch, &pFind ) );
FindClose( hSearch );
}
Save( FALSE );
DownloadGroups.Load();
Transfers.StartThread();
}
void CDownloads::Save(BOOL bForce)
{
CSingleLock pLock( &Transfers.m_pSection, TRUE );
for ( POSITION pos = GetIterator() ; pos ; )
{
CDownload* pDownload = GetNext( pos );
if ( bForce || pDownload->m_nCookie != pDownload->m_nSaveCookie ) pDownload->Save( TRUE );
}
}
//////////////////////////////////////////////////////////////////////
// CDownloads load all the old compound file formats
void CDownloads::LoadFromCompoundFiles()
{
if ( LoadFromCompoundFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.dat") ) )
{
// Good
}
else if ( LoadFromCompoundFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.bak") ) )
{
// Good
}
else if ( LoadFromTimePair() )
{
// Good
}
DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.dat") );
DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.bak") );
DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza.dat") );
DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza1.dat") );
DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza2.dat") );
}
BOOL CDownloads::LoadFromCompoundFile(LPCTSTR pszFile)
{
CFile pFile;
if ( ! pFile.Open( pszFile, CFile::modeRead ) ) return FALSE;
CArchive ar( &pFile, CArchive::load );
try
{
SerializeCompound( ar );
}
catch ( CException* pException )
{
pException->Delete();
Clear();
return FALSE;
}
return TRUE;
}
BOOL CDownloads::LoadFromTimePair()
{
FILETIME pFileTime1 = { 0, 0 }, pFileTime2 = { 0, 0 };
CFile pFile1, pFile2;
BOOL bFile1, bFile2;
CString strFile;
strFile = Settings.Downloads.IncompletePath + _T("\\Shareaza");
bFile1 = pFile1.Open( strFile + _T("1.dat"), CFile::modeRead );
bFile2 = pFile2.Open( strFile + _T("2.dat"), CFile::modeRead );
if ( bFile1 || bFile2 )
{
if ( bFile1 ) bFile1 = pFile1.Read( &pFileTime1, sizeof(FILETIME) ) == sizeof(FILETIME);
if ( bFile2 ) bFile2 = pFile2.Read( &pFileTime2, sizeof(FILETIME) ) == sizeof(FILETIME);
}
else
{
if ( ! pFile1.Open( strFile + _T(".dat"), CFile::modeRead ) ) return FALSE;
pFileTime1.dwHighDateTime++;
}
CFile* pNewest = ( CompareFileTime( &pFileTime1, &pFileTime2 ) >= 0 ) ? &pFile1 : &pFile2;
try
{
CArchive ar( pNewest, CArchive::load );
SerializeCompound( ar );
ar.Close();
}
catch ( CException* pException )
{
pException->Delete();
Clear();
if ( pNewest == &pFile1 && bFile2 )
pNewest = &pFile2;
else if ( pNewest == &pFile2 && bFile1 )
pNewest = &pFile1;
else
pNewest = NULL;
if ( pNewest != NULL )
{
try
{
CArchive ar( pNewest, CArchive::load );
SerializeCompound( ar );
ar.Close();
}
catch ( CException* pException )
{
pException->Delete();
Clear();
return FALSE;
}
}
}
return TRUE;
}
void CDownloads::SerializeCompound(CArchive& ar)
{
ASSERT( ar.IsLoading() );
int nVersion;
ar >> nVersion;
if ( nVersion < 4 ) return;
for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
{
CDownload* pDownload = new CDownload();
m_pList.AddTail( pDownload );
pDownload->Serialize( ar, nVersion );
}
}
//////////////////////////////////////////////////////////////////////
// CDownloads left over file purge operations
void CDownloads::PurgeDeletes()
{
CStringList pRemove;
HKEY hKey = NULL;
if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_CURRENT_USER,
_T("Software\\Shareaza\\Shareaza\\Delete"), 0, KEY_ALL_ACCESS, &hKey ) ) return;
for ( DWORD nIndex = 0 ; nIndex < 1000 ; nIndex ++ )
{
DWORD nPath = MAX_PATH*2;
TCHAR szPath[MAX_PATH*2];
if ( ERROR_SUCCESS != RegEnumValue( hKey, nIndex, szPath, &nPath, NULL,
NULL, NULL, NULL ) ) break;
if ( GetFileAttributes( szPath ) == 0xFFFFFFFF || DeleteFile( szPath ) )
{
pRemove.AddTail( szPath );
}
}
while ( ! pRemove.IsEmpty() )
{
RegDeleteValue( hKey, pRemove.RemoveHead() );
}
RegCloseKey( hKey );
}
void CDownloads::PurgePreviews()
{
WIN32_FIND_DATA pFind;
HANDLE hSearch;
CString strPath;
strPath = Settings.Downloads.IncompletePath + _T("\\Preview of *.*");
hSearch = FindFirstFile( strPath, &pFind );
if ( hSearch == INVALID_HANDLE_VALUE ) return;
do
{
if ( _tcsnicmp( pFind.cFileName, _T("Preview of "), 11 ) == 0 )
{
strPath = Settings.Downloads.IncompletePath + '\\' + pFind.cFileName;
DeleteFile( strPath );
}
}
while ( FindNextFile( hSearch, &pFind ) );
FindClose( hSearch );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -