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

📄 downloads.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -