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

📄 downloadtransfered2k.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		Close( TS_FALSE );
		return FALSE;
	}
	
	BOOL bUseful = m_pDownload->SubmitData( nOffset,
		pPacket->m_pBuffer + pPacket->m_nPosition, nLength );
	
	CFileFragment::Subtract( &m_pRequested, nOffset, nLength );
	m_nRequested = m_pRequested->GetCount();
	
	m_pSource->AddFragment( nOffset, nLength,
		( nOffset % ED2K_PART_SIZE ) ? TRUE : FALSE );
	
	m_nDownloaded += nLength;
	
	m_pSource->SetValid();
	
	return SendFragmentRequests();
}

BOOL CDownloadTransferED2K::OnCompressedPart(CEDPacket* pPacket)
{
	if ( m_nState != dtsDownloading ) return TRUE;
	
	if ( pPacket->GetRemaining() <= sizeof(MD4) + 8 )
	{
		theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
		Close( TS_FALSE );
		return FALSE;
	}
	
	MD4 pMD4;
	pPacket->Read( &pMD4, sizeof(MD4) );
	
	if ( pMD4 != m_pDownload->m_pED2K )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH,
			(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
		// Close( TS_FALSE );
		// return FALSE;
		return TRUE;
	}
	
	QWORD nBaseOffset = pPacket->ReadLongLE();
	QWORD nBaseLength = pPacket->ReadLongLE();
	
	z_streamp pStream = (z_streamp)m_pInflatePtr;
	
	if ( m_pInflatePtr == NULL || m_nInflateOffset != nBaseOffset || m_nInflateLength != nBaseLength )
	{
		if ( pStream != NULL )
		{
			inflateEnd( pStream );
			delete pStream;
		}
		
		m_nInflateOffset	= nBaseOffset;
		m_nInflateLength	= nBaseLength;
		m_nInflateRead		= 0;
		m_nInflateWritten	= 0;
		m_pInflateBuffer->Clear();
		
		m_pInflatePtr = new z_stream;
		pStream = (z_streamp)m_pInflatePtr;
		ZeroMemory( pStream, sizeof(z_stream) );
		
		if ( inflateInit( pStream ) != Z_OK )
		{
			delete pStream;
			m_pInflatePtr = NULL;
			
			theApp.Message( MSG_ERROR, IDS_DOWNLOAD_INFLATE_ERROR,
				(LPCTSTR)m_pDownload->GetDisplayName() );
			
			Close( TS_FALSE );
			return FALSE;
		}
	}
	
	m_pInflateBuffer->Add( pPacket->m_pBuffer + pPacket->m_nPosition, pPacket->GetRemaining() );
	
	BYTE pBuffer[ BUFFER_SIZE ];
	
	if ( m_pInflateBuffer->m_nLength > 0 && m_nInflateRead < m_nInflateLength )
	{
		pStream->next_in	= m_pInflateBuffer->m_pBuffer;
		pStream->avail_in	= m_pInflateBuffer->m_nLength;
		
		do
		{
			pStream->next_out	= pBuffer;
			pStream->avail_out	= BUFFER_SIZE;
			
			inflate( pStream, Z_SYNC_FLUSH );
			
			if ( pStream->avail_out < BUFFER_SIZE )
			{
				QWORD nOffset = m_nInflateOffset + m_nInflateWritten;
				QWORD nLength = BUFFER_SIZE - pStream->avail_out;
				
				BOOL bUseful = m_pDownload->SubmitData( nOffset, pBuffer, nLength );
				
				CFileFragment::Subtract( &m_pRequested, nOffset, nLength );
				m_nRequested = m_pRequested->GetCount();
				
				m_pSource->AddFragment( nOffset, nLength,
					( nOffset % ED2K_PART_SIZE ) ? TRUE : FALSE );
				
				m_nDownloaded += nLength;
				m_nInflateWritten += nLength;
			}
		}
		while ( pStream->avail_out == 0 );
		
		if ( pStream->avail_in >= 0 && pStream->avail_in < m_pInflateBuffer->m_nLength )
		{
			m_nInflateRead += ( m_pInflateBuffer->m_nLength - pStream->avail_in );
			m_pInflateBuffer->Remove( m_pInflateBuffer->m_nLength - pStream->avail_in );
		}
	}
	
	if ( m_nInflateRead >= m_nInflateLength )
	{
		inflateEnd( pStream );
		delete pStream;
		m_pInflatePtr = NULL;
		m_pInflateBuffer->Clear();
	}
	
	m_pSource->SetValid();
	
	return SendFragmentRequests();
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K send

void CDownloadTransferED2K::Send(CEDPacket* pPacket, BOOL bRelease)
{
	ASSERT( m_nState > dtsConnecting );
	ASSERT( m_pClient != NULL );
	m_pClient->Send( pPacket, bRelease );
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K file requestors

BOOL CDownloadTransferED2K::SendPrimaryRequest()
{
	ASSERT( m_pClient != NULL );
	
	/*
	if ( m_pDownload->GetVolumeRemaining() == 0 )
	{
		theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
		Close( TS_TRUE );
		return FALSE;
	}
	*/
	
	SetState( dtsRequesting );
	m_tRequest	= GetTickCount();
	ClearRequests();
	
	CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_FILEREQUEST );
	pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
	if ( Settings.eDonkey.ExtendedRequest && m_pClient->m_bEmRequest >= 1 ) m_pClient->WritePartStatus( pPacket, m_pDownload );
	Send( pPacket );
	
	pPacket = CEDPacket::New( ED2K_C2C_FILESTATUSREQUEST );
	pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
	Send( pPacket );
	
	if ( m_pDownload->GetSourceCount() < 500 && m_pClient->m_bEmule && Network.IsListening() )
	{
		pPacket = CEDPacket::New( ED2K_C2C_REQUESTSOURCES, ED2K_PROTOCOL_EMULE );
		pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
		Send( pPacket );
	}
	
	return TRUE;
}

BOOL CDownloadTransferED2K::SendSecondaryRequest()
{
	ASSERT( m_pClient != NULL );
	ASSERT( m_nState > dtsConnecting );
	// ASSERT( m_nState == dtsRequesting || m_nState == dtsHashset );
	
	if ( ! m_pDownload->PrepareFile() )
	{
		Close( TS_TRUE );
		return FALSE;
	}
	
	if ( m_bHashset == FALSE && m_pDownload->NeedHashset() )
	{
		CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_HASHSETREQUEST );
		pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
		Send( pPacket );
		
		SetState( dtsHashset );
		m_pClient->m_mInput.tLast = GetTickCount();
	}
	else if ( m_pSource->HasUsefulRanges() )
	{
		CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_QUEUEREQUEST );
		pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
		Send( pPacket );
		
		SetState( dtsEnqueue );
		m_tRequest = GetTickCount();
	}
	else
	{
		m_pSource->m_tAttempt = GetTickCount() + Settings.eDonkey.ReAskTime * 500;
		m_pSource->SetAvailableRanges( NULL );
		theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
		Close( TS_TRUE );
		return FALSE;
	}
	
	ClearRequests();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K fragment request manager

BOOL CDownloadTransferED2K::SendFragmentRequests()
{
	ASSERT( m_nState == dtsDownloading );
	ASSERT( m_pClient != NULL );
	
	if ( m_nRequested >= (int)Settings.eDonkey.RequestPipe ) return TRUE;
	
	CFileFragment* pPossible = m_pDownload->GetFirstEmptyFragment()->CreateCopy();
	
	for ( CDownloadTransfer* pTransfer = m_pDownload->GetFirstTransfer() ; pTransfer && pPossible ; pTransfer = pTransfer->m_pDlNext )
	{
		pTransfer->SubtractRequested( &pPossible );
	}
	
	while ( m_nRequested < (int)Settings.eDonkey.RequestPipe )
	{
		QWORD nOffset, nLength;
		
		if ( SelectFragment( pPossible, &nOffset, &nLength ) )
		{
			ChunkifyRequest( &nOffset, &nLength, Settings.eDonkey.RequestSize, FALSE );
			
			CFileFragment::Subtract( &pPossible, nOffset, nLength );
			
			CFileFragment* pRequest = CFileFragment::New( NULL, m_pRequested, nOffset, nLength );
			if ( m_pRequested != NULL ) m_pRequested->m_pPrevious = pRequest;
			m_pRequested = pRequest;
			m_nRequested ++;
			
			CEDPacket* pPacket = CEDPacket::New( ED2K_C2C_REQUESTPARTS );
			pPacket->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
			pPacket->WriteLongLE( (DWORD)nOffset );
			pPacket->WriteLongLE( 0 );
			pPacket->WriteLongLE( 0 );
			pPacket->WriteLongLE( (DWORD)( nOffset + nLength ) );
			pPacket->WriteLongLE( 0 );
			pPacket->WriteLongLE( 0 );
			Send( pPacket );
			
			int nType = ( m_nDownloaded == 0 || ( nOffset % ED2K_PART_SIZE ) == 0 )
				? MSG_DEFAULT : MSG_DEBUG;
			
			theApp.Message( nType, IDS_DOWNLOAD_FRAGMENT_REQUEST,
				nOffset, nOffset + nLength - 1,
				(LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress );
		}
		else
		{
			break;
		}
	}
	
	pPossible->DeleteChain();
	
	if ( m_nRequested > 0 ) return TRUE;
	
	Send( CEDPacket::New( ED2K_C2C_QUEUERELEASE ) );
	
	theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_END, (LPCTSTR)m_sAddress );
	Close( TS_TRUE );
	
	return FALSE;
}

void CDownloadTransferED2K::ClearRequests()
{
	m_pRequested->DeleteChain();
	m_pRequested = NULL;
	m_nRequested = 0;
	
	if ( z_streamp pStream = (z_streamp)m_pInflatePtr )
	{
		inflateEnd( pStream );
		delete pStream;
		m_pInflatePtr = NULL;
		m_pInflateBuffer->Clear();
	}
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K fragment selector

BOOL CDownloadTransferED2K::SelectFragment(CFileFragment* pPossible, QWORD* pnOffset, QWORD* pnLength)
{
	ASSERT( pnOffset != NULL && pnLength != NULL );
	
	if ( pPossible == NULL ) return FALSE;
	
	CFileFragment* pComplete = NULL;
	DWORD nBlock;
	
	for ( ; pPossible ; pPossible = pPossible->m_pNext )
	{
		if ( pPossible->m_nOffset % ED2K_PART_SIZE )
		{
			// the start of a block is complete, but part is missing
			
			nBlock = (DWORD)( pPossible->m_nOffset / ED2K_PART_SIZE );
			
			if ( m_pAvailable == NULL || m_pAvailable[ nBlock ] )
			{
				*pnOffset = pPossible->m_nOffset;
				*pnLength = ED2K_PART_SIZE * (QWORD)nBlock + ED2K_PART_SIZE - *pnOffset;
				*pnLength = min( *pnLength, pPossible->m_nLength );
				ASSERT( *pnLength <= ED2K_PART_SIZE );
				
				pComplete->DeleteChain();
				return TRUE;
			}
		}
		else if (	( pPossible->m_nLength % ED2K_PART_SIZE ) &&
					( pPossible->m_nOffset + pPossible->m_nLength < m_pDownload->m_nSize ) )
		{
			// the end of a block is complete, but part is missing
			
			nBlock = (DWORD)( ( pPossible->m_nOffset + pPossible->m_nLength ) / ED2K_PART_SIZE );
			
			if ( m_pAvailable == NULL || m_pAvailable[ nBlock ] )
			{
				*pnOffset = ED2K_PART_SIZE * (QWORD)nBlock;
				*pnLength = pPossible->m_nOffset + pPossible->m_nLength - *pnOffset;
				ASSERT( *pnLength <= ED2K_PART_SIZE );
				
				pComplete->DeleteChain();
				return TRUE;
			}
		}
		else
		{
			// this fragment contains one or more aligned empty blocks
			
			nBlock = (DWORD)( pPossible->m_nOffset / ED2K_PART_SIZE );
			*pnLength = pPossible->m_nLength;
			ASSERT( *pnLength != 0 );
			
			for ( ; ; nBlock ++, *pnLength -= ED2K_PART_SIZE )
			{
				if ( m_pAvailable == NULL || m_pAvailable[ nBlock ] )
				{
					pComplete = CFileFragment::New( NULL, pComplete, (QWORD)nBlock, 0 );
				}
				
				if ( *pnLength <= ED2K_PART_SIZE ) break;
			}
		}
	}
	
	if ( CFileFragment* pRandom = pComplete->GetRandom() )
	{
		*pnOffset = pRandom->m_nOffset * ED2K_PART_SIZE;
		*pnLength = ED2K_PART_SIZE;
		*pnLength = min( *pnLength, m_pDownload->m_nSize - *pnOffset );
		ASSERT( *pnLength <= ED2K_PART_SIZE );
		
		pComplete->DeleteChain();
		return TRUE;
	}
	else
	{
		ASSERT( pComplete == NULL );
		return FALSE;
	}
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K subtract requested fragments

BOOL CDownloadTransferED2K::SubtractRequested(CFileFragment** ppFragments)
{
	if ( m_nState == dtsDownloading )
	{
		if ( m_nRequested != 0 ) CFileFragment::Subtract( ppFragments, m_pRequested );
		return TRUE;
	}
	
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K run queued state

BOOL CDownloadTransferED2K::RunQueued(DWORD tNow)
{
	ASSERT( m_pClient != NULL );
	ASSERT( m_nState == dtsQueued );
	
	if ( Settings.Downloads.QueueLimit > 0 && m_nQueuePos > Settings.Downloads.QueueLimit )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_HUGE,
			(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName(), m_nQueuePos );
		Close( TS_FALSE );
		return FALSE;
	}
	else if ( m_pClient->m_bConnected == FALSE && tNow > m_tRanking && tNow - m_tRanking > Settings.eDonkey.ReAskTime * 1000 + 20000 )
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_TIMEOUT,
			(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
		Close( TS_UNKNOWN );
		return FALSE;
	}
	else if ( m_pClient->m_nUDP > 0 && ! m_bUDP && tNow > m_tRequest && tNow - m_tRequest > Settings.eDonkey.ReAskTime * 1000 - 20000 )
	{
		CEDPacket* pPing = CEDPacket::New( ED2K_C2C_UDP_REASKFILEPING, ED2K_PROTOCOL_EMULE );
		pPing->Write( &m_pDownload->m_pED2K, sizeof(MD4) );
		Datagrams.Send( &m_pClient->m_pHost.sin_addr, m_pClient->m_nUDP, pPing );
		m_bUDP = TRUE;
	}
	else if ( tNow > m_tRequest && tNow - m_tRequest > Settings.eDonkey.ReAskTime * 1000 )
	{
		m_tRequest = GetTickCount();
		
		if ( m_pClient->IsOnline() )
		{
			return OnConnected();
		}
		else
		{
			m_pClient->Connect();
		}
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K queue rank update

void CDownloadTransferED2K::SetQueueRank(int nRank)
{
	SetState( dtsQueued );

	m_tRequest	= m_tRanking = GetTickCount();
	m_nQueuePos	= nRank;
	m_bUDP		= FALSE;
	
	ClearRequests();
	
	theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_QUEUED,
		(LPCTSTR)m_sAddress, m_nQueuePos, m_nQueueLen, _T("eDonkey2000") );
}

⌨️ 快捷键说明

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