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

📄 downloadtransfered2k.cpp

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