📄 downloadtransfered2k.cpp
字号:
//
// DownloadTransferED2K.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 "Download.h"
#include "Downloads.h"
#include "DownloadSource.h"
#include "DownloadTransfer.h"
#include "DownloadTransferED2K.h"
#include "FragmentedFile.h"
#include "Datagrams.h"
#include "EDClients.h"
#include "EDClient.h"
#include "EDPacket.h"
#include "Network.h"
#include "Buffer.h"
#include "ED2K.h"
#include <zlib.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define BUFFER_SIZE 8192
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K construction
CDownloadTransferED2K::CDownloadTransferED2K(CDownloadSource* pSource) : CDownloadTransfer( pSource, PROTOCOL_ED2K )
{
m_pClient = NULL;
m_bHashset = FALSE;
m_tRequest = 0;
m_tRanking = 0;
m_pAvailable = NULL;
m_pRequested = NULL;
m_nRequested = 0;
m_bUDP = FALSE;
m_pInflatePtr = NULL;
m_pInflateBuffer = new CBuffer();
ASSERT( m_pDownload->m_bED2K );
}
CDownloadTransferED2K::~CDownloadTransferED2K()
{
ClearRequests();
delete m_pInflateBuffer;
if ( m_pAvailable != NULL ) delete [] m_pAvailable;
#ifdef _DEBUG
ASSERT( m_pClient == NULL );
for ( CEDClient* pClient = EDClients.GetFirst() ; pClient ; pClient = pClient->m_pEdNext )
{
ASSERT( pClient->m_pDownload != this );
}
#endif
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K initiate
BOOL CDownloadTransferED2K::Initiate()
{
ASSERT( m_pClient == NULL );
ASSERT( m_nState == dtsNull );
if ( ! m_pDownload->m_bED2K || m_pDownload->m_nSize == SIZE_UNKNOWN )
{
Close( TS_FALSE );
return FALSE;
}
m_pClient = EDClients.Connect(
m_pSource->m_pAddress.S_un.S_addr,
m_pSource->m_nPort,
m_pSource->m_nServerPort ? &m_pSource->m_pServerAddress : NULL,
m_pSource->m_nServerPort,
m_pSource->m_bGUID ? &m_pSource->m_pGUID : NULL );
if ( m_pClient == NULL )
{
Close( EDClients.IsFull() ? TS_TRUE : TS_FALSE );
return FALSE;
}
SetState( dtsConnecting );
m_tConnected = GetTickCount();
if ( ! m_pClient->AttachDownload( this ) )
{
SetState( dtsNull );
m_pClient = NULL;
Close( TS_TRUE );
return FALSE;
}
m_pHost = m_pClient->m_pHost;
m_sAddress = m_pClient->m_sAddress;
m_pClient->m_mInput.pLimit = &Downloads.m_nLimitDonkey;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K close
void CDownloadTransferED2K::Close(TRISTATE bKeepSource)
{
if ( m_pClient != NULL )
{
m_pClient->OnDownloadClose();
m_pClient = NULL;
}
CDownloadTransfer::Close( bKeepSource );
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K bandwidth control
void CDownloadTransferED2K::Boost()
{
if ( m_pClient == NULL ) return;
m_pClient->m_mInput.pLimit = NULL;
}
DWORD CDownloadTransferED2K::GetAverageSpeed()
{
return m_pSource->m_nSpeed = GetMeasuredSpeed();
}
DWORD CDownloadTransferED2K::GetMeasuredSpeed()
{
if ( m_pClient == NULL ) return 0;
m_pClient->Measure();
return m_pClient->m_mInput.nMeasure;
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K run event
BOOL CDownloadTransferED2K::OnRun()
{
return OnRunEx( GetTickCount() );
}
BOOL CDownloadTransferED2K::OnRunEx(DWORD tNow)
{
switch ( m_nState )
{
case dtsRequesting:
case dtsEnqueue:
if ( tNow > m_tRequest && tNow - m_tRequest > Settings.Connection.TimeoutHandshake * 2 )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
Close( TS_UNKNOWN );
return FALSE;
}
break;
case dtsQueued:
return RunQueued( tNow );
case dtsDownloading:
case dtsHashset:
if ( tNow > m_pClient->m_mInput.tLast &&
tNow - m_pClient->m_mInput.tLast > Settings.Connection.TimeoutTraffic * 2 )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
Close( TS_TRUE );
return FALSE;
}
break;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K connection established event
BOOL CDownloadTransferED2K::OnConnected()
{
ASSERT( m_pClient != NULL );
ASSERT( m_pSource != NULL );
m_pHost = m_pClient->m_pHost;
m_sAddress = m_pClient->m_sAddress;
m_pSource->m_bGUID = TRUE;
m_pSource->m_pGUID = m_pClient->m_pGUID;
m_pSource->m_sServer = m_sUserAgent = m_pClient->m_sUserAgent;
m_pSource->m_sNick = m_pClient->m_sNick;
m_pSource->SetLastSeen();
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONNECTED, (LPCTSTR)m_sAddress );
return SendPrimaryRequest();
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K connection dropped event
void CDownloadTransferED2K::OnDropped(BOOL bError)
{
if ( m_nState == dtsQueued )
{
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_QUEUE_DROP,
(LPCTSTR)m_pDownload->GetDisplayName() );
}
else
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DROPPED, (LPCTSTR)m_sAddress );
Close( TS_UNKNOWN );
}
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferED2K packet handlers
BOOL CDownloadTransferED2K::OnFileReqAnswer(CEDPacket* pPacket)
{
// Not really interested
return TRUE;
}
BOOL CDownloadTransferED2K::OnFileNotFound(CEDPacket* pPacket)
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILENOTFOUND,
(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName() );
Close( TS_FALSE );
return FALSE;
}
BOOL CDownloadTransferED2K::OnFileStatus(CEDPacket* pPacket)
{
if ( m_nState <= dtsConnecting ) return TRUE;
if ( pPacket->GetRemaining() < sizeof(MD4) + 2 )
{
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() );
return TRUE;
}
DWORD nBlocks = pPacket->ReadShortLE();
if ( nBlocks == (DWORD)( ( m_pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE ) )
{
m_pSource->m_pAvailable->DeleteChain();
m_pSource->m_pAvailable = NULL;
if ( m_pAvailable != NULL ) delete [] m_pAvailable;
m_pAvailable = new BYTE[ nBlocks ];
ZeroMemory( m_pAvailable, nBlocks );
for ( DWORD nBlock = 0 ; nBlock < nBlocks && pPacket->GetRemaining() ; )
{
BYTE nByte = pPacket->ReadByte();
for ( int nBit = 0 ; nBit < 8 && nBlock < nBlocks ; nBit++, nBlock++ )
{
if ( nByte & ( 1 << nBit ) )
{
QWORD nFrom = ED2K_PART_SIZE * nBlock;
QWORD nTo = nFrom + ED2K_PART_SIZE;
nTo = min( nTo, m_pDownload->m_nSize );
CFileFragment::AddMerge( &m_pSource->m_pAvailable, nFrom, nTo - nFrom );
m_pAvailable[ nBlock ] = TRUE;
}
}
}
}
else if ( nBlocks == 0 )
{
m_pSource->m_pAvailable->DeleteChain();
m_pSource->m_pAvailable = NULL;
if ( m_pAvailable != NULL ) delete [] m_pAvailable;
m_pAvailable = NULL;
}
else
{
theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
Close( TS_FALSE );
return FALSE;
}
SendSecondaryRequest();
return TRUE;
}
BOOL CDownloadTransferED2K::OnHashsetAnswer(CEDPacket* pPacket)
{
if ( m_nState != dtsHashset ) return TRUE;
if ( pPacket->GetRemaining() < sizeof(MD4) + 2 )
{
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 )
{
return TRUE; // Hack
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_ERROR, (LPCTSTR)m_sAddress );
Close( TS_FALSE );
return FALSE;
}
m_bHashset = TRUE;
DWORD nBlocks = pPacket->ReadShortLE();
if ( nBlocks == 0 ) nBlocks = 1;
if ( nBlocks != (DWORD)( ( m_pDownload->m_nSize + ED2K_PART_SIZE - 1 ) / ED2K_PART_SIZE ) )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_ERROR, (LPCTSTR)m_sAddress );
}
else if ( m_pDownload->SetHashset( pPacket->m_pBuffer + pPacket->m_nPosition,
pPacket->GetRemaining() ) )
{
return SendSecondaryRequest();
}
Close( TS_FALSE );
return FALSE;
}
BOOL CDownloadTransferED2K::OnQueueRank(CEDPacket* pPacket)
{
if ( m_nState <= dtsConnecting ) return TRUE;
if ( pPacket->GetRemaining() < 4 )
{
theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
Close( TS_FALSE );
return FALSE;
}
m_nQueuePos = pPacket->ReadLongLE();
if ( m_nQueuePos > 0 )
{
SetQueueRank( m_nQueuePos );
}
else
{
m_pSource->m_tAttempt = GetTickCount() + Settings.eDonkey.ReAskTime * 1000;
Close( TS_UNKNOWN );
}
return TRUE;
}
BOOL CDownloadTransferED2K::OnRankingInfo(CEDPacket* pPacket)
{
if ( m_nState <= dtsConnecting ) return TRUE;
if ( pPacket->GetRemaining() < 12 )
{
theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
Close( TS_FALSE );
return FALSE;
}
m_nQueuePos = pPacket->ReadShortLE();
m_nQueueLen = pPacket->ReadShortLE();
SetQueueRank( m_nQueuePos );
return TRUE;
}
BOOL CDownloadTransferED2K::OnStartUpload(CEDPacket* pPacket)
{
SetState( dtsDownloading );
m_pClient->m_mInput.tLast = GetTickCount();
ClearRequests();
return SendFragmentRequests();
}
BOOL CDownloadTransferED2K::OnFinishUpload(CEDPacket* pPacket)
{
return SendPrimaryRequest();
}
BOOL CDownloadTransferED2K::OnSendingPart(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 nOffset = pPacket->ReadLongLE();
QWORD nLength = pPacket->ReadLongLE();
if ( nLength <= nOffset )
{
if ( nLength == nOffset ) return TRUE;
theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_BAD_PACKET, (LPCTSTR)m_sAddress, pPacket->m_nType );
Close( TS_FALSE );
return FALSE;
}
nLength -= nOffset;
if ( nLength > (QWORD)pPacket->GetRemaining() )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -