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