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

📄 btclient.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		}
	}
	
	ASSERT( m_pDownload != NULL );
	ASSERT( m_pDownload->m_pBTH == pFileHash );
	
	if ( ! m_bInitiated ) SendHandshake( TRUE, FALSE );
	
	m_bShake = TRUE;
	
	return TRUE;
}

BOOL CBTClient::OnHandshake2()
{
	m_pGUID = *(SHA1*)m_pInput->m_pBuffer;
	m_pInput->Remove( sizeof(SHA1) );
	
	for ( int nByte = 0 ; nByte < 20 ; nByte++ )
	{
		if ( nByte < 16 )
		{
			if ( m_pGUID.b[ nByte ] ) m_bShareaza = TRUE;
		}
		else
		{
			if ( m_pGUID.b[ nByte ]	!= ( m_pGUID.b[ nByte % 16 ] ^ m_pGUID.b[ 15 - ( nByte % 16 ) ] ) )
			{
				m_bShareaza = FALSE;
				break;
			}
		}
	}
	
	ASSERT( m_pDownload != NULL );
	
	if ( m_bInitiated )
	{
		ASSERT( m_pDownloadTransfer != NULL );
		CopyMemory( &m_pDownloadTransfer->m_pSource->m_pGUID, &m_pGUID, 16 );
		
		/*
		if ( memcmp( &m_pGUID, &m_pDownloadTransfer->m_pSource->m_pGUID, 16 ) != 0 )
		{
			theApp.Message( MSG_ERROR, IDS_BT_CLIENT_WRONG_GUID, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
		*/
	}
	else if ( ! m_pDownload->IsMoving() && ! m_pDownload->IsPaused() )
	{
		ASSERT( m_pDownloadTransfer == NULL );
		
		m_pDownloadTransfer = m_pDownload->CreateTorrentTransfer( this );
		
		if ( m_pDownloadTransfer == NULL )
		{
			m_pDownload = NULL;
			theApp.Message( MSG_ERROR, IDS_BT_CLIENT_UNKNOWN_FILE, (LPCTSTR)m_sAddress );
			Close();
			return FALSE;
		}
	}
	
	ASSERT( m_pUpload == NULL );
	m_pUpload = new CUploadTransferBT( this, m_pDownload );
	
	m_bOnline = TRUE;
	
	DetermineUserAgent();
	
	if ( ! m_bInitiated ) SendHandshake( FALSE, TRUE );
	
	return OnOnline();
}

//////////////////////////////////////////////////////////////////////
// CBTClient online handler

void CBTClient::DetermineUserAgent()
{
	CString strVer;
	
	if ( m_pGUID.b[0] == '-' && m_pGUID.b[7] == '-' )
	{
		if ( m_pGUID.b[1] == 'A' && m_pGUID.b[2] == 'Z' )
		{
			m_sUserAgent = _T("Azureus");
		}
		else if ( m_pGUID.b[1] == 'M' && m_pGUID.b[2] == 'T' )
		{
			m_sUserAgent = _T("MoonlightTorrent");
		}
		else if ( m_pGUID.b[1] == 'L' && m_pGUID.b[2] == 'T' )
		{
			m_sUserAgent = _T("libtorrent");
		}
		else if ( m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'X' )
		{
			m_sUserAgent = _T("Bittorrent X");
		}
		else if ( m_pGUID.b[1] == 'T' && m_pGUID.b[2] == 'S' )
		{
			m_sUserAgent = _T("Torrentstorm");
		}
		else if ( m_pGUID.b[1] == 'S' && m_pGUID.b[2] == 'S' )
		{
			m_sUserAgent = _T("Swarmscope");
		}
		else if ( m_pGUID.b[1] == 'X' && m_pGUID.b[2] == 'T' )
		{
			m_sUserAgent = _T("XanTorrent");
		}
		
		strVer.Format( _T(" %i.%i.%i.%i"),
			( m_pGUID.b[3] - '0' ), ( m_pGUID.b[4] - '0' ),
			( m_pGUID.b[5] - '0' ), ( m_pGUID.b[6] - '0' ) );
		m_sUserAgent += strVer;
	}
	else if ( m_pGUID.b[4] == '-' && m_pGUID.b[5] == '-' && m_pGUID.b[6] == '-' && m_pGUID.b[7] == '-' )
	{
		switch ( m_pGUID.b[0] )
		{
		case 'S':
			m_sUserAgent = _T("Shadow");
			break;
		case 'U':
			m_sUserAgent = _T("UPnP NAT BT");
			break;
		case 'T':
			m_sUserAgent = _T("BitTornado");
			break;
		}
		
		strVer.Format( _T(" %i%i%i"),
			( m_pGUID.b[1] - '0' ), ( m_pGUID.b[2] - '0' ),
			( m_pGUID.b[3] - '0' ) );
		m_sUserAgent += strVer;
	}
	
	if ( m_pDownloadTransfer != NULL )
	{
		m_pDownloadTransfer->m_sUserAgent = m_sUserAgent;
		if ( m_pDownloadTransfer->m_pSource != NULL )
			m_pDownloadTransfer->m_pSource->m_sServer = m_sUserAgent;
	}
	
	if ( m_pUpload != NULL )
		m_pUpload->m_sUserAgent = m_sUserAgent;
}

//////////////////////////////////////////////////////////////////////
// CBTClient online handler

BOOL CBTClient::OnOnline()
{
	ASSERT( m_bOnline );
	ASSERT( m_pDownload != NULL );
	ASSERT( m_pUpload != NULL );
	
	theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_ONLINE, (LPCTSTR)m_sAddress,
		(LPCTSTR)m_pDownload->GetDisplayName() );
	
	if ( m_bShareaza ) SendBeHandshake();
	
	if ( CBTPacket* pBitfield = m_pDownload->CreateBitfieldPacket() )
		Send( pBitfield );
	
	if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnConnected() ) return FALSE;
	if ( ! m_pUpload->OnConnected() ) return FALSE;
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CBTClient packet switch

BOOL CBTClient::OnPacket(CBTPacket* pPacket)
{
	switch ( pPacket->m_nType )
	{
	case BT_PACKET_KEEPALIVE:
		break;
	case BT_PACKET_CHOKE:
		if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnChoked( pPacket ) ) return FALSE;
		m_pDownload->ChokeTorrent();
		break;
	case BT_PACKET_UNCHOKE:
		if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnUnchoked( pPacket ) ) return FALSE;
		m_pDownload->ChokeTorrent();
		break;
	case BT_PACKET_INTERESTED:
		if ( ! m_pUpload->OnInterested( pPacket ) ) return FALSE;
		m_pDownload->ChokeTorrent();
		break;
	case BT_PACKET_NOT_INTERESTED:
		if ( ! m_pUpload->OnUninterested( pPacket ) ) return FALSE;
		m_pDownload->ChokeTorrent();
		break;
	case BT_PACKET_HAVE:
		return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnHave( pPacket );
	case BT_PACKET_BITFIELD:
		return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnBitfield( pPacket );
	case BT_PACKET_REQUEST:
		return m_pUpload->OnRequest( pPacket );
	case BT_PACKET_PIECE:
		return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnPiece( pPacket );
	case BT_PACKET_CANCEL:
		return m_pUpload->OnCancel( pPacket );
	
	case BT_PACKET_HANDSHAKE:
		if ( ! m_bShareaza ) break;
		return OnBeHandshake( pPacket );
	case BT_PACKET_SOURCE_REQUEST:
		if ( ! m_bExchange ) break;
		return OnSourceRequest( pPacket );
	case BT_PACKET_SOURCE_RESPONSE:
		if ( ! m_bExchange ) break;
		return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnSourceResponse( pPacket );
	}
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CBTClient advanced handshake

void CBTClient::SendBeHandshake()
{
	CBENode pRoot;
	
	CString strNick = MyProfile.GetNick();
	if ( strNick.GetLength() ) pRoot.Add( "nickname" )->SetString( strNick );
	
	pRoot.Add( "source-exchange" )->SetInt( 2 );
	pRoot.Add( "user-agent" )->SetString( Settings.SmartAgent( Settings.General.UserAgent ) );
	
	CBuffer pOutput;
	pRoot.Encode( &pOutput );
	
	CBTPacket* pPacket = CBTPacket::New( BT_PACKET_HANDSHAKE );
	pPacket->Write( pOutput.m_pBuffer, pOutput.m_nLength );
	Send( pPacket );
}

BOOL CBTClient::OnBeHandshake(CBTPacket* pPacket)
{
	if ( pPacket->GetRemaining() > 1024 ) return TRUE;
	
	CBuffer pInput;
	pInput.Add( pPacket->m_pBuffer, pPacket->GetRemaining() );
	
	CBENode* pRoot = CBENode::Decode( &pInput );
	if ( pRoot == NULL ) return TRUE;
	
	CBENode* pAgent = pRoot->GetNode( "user-agent" );
	
	if ( pAgent->IsType( CBENode::beString ) )
	{
		m_sUserAgent = pAgent->GetString();
		
		if ( m_pDownloadTransfer != NULL )
		{
			m_pDownloadTransfer->m_sUserAgent = m_sUserAgent;
			if ( m_pDownloadTransfer->m_pSource != NULL )
				m_pDownloadTransfer->m_pSource->m_sServer = m_sUserAgent;
		}
		
		if ( m_pUpload != NULL ) m_pUpload->m_sUserAgent = m_sUserAgent;
	}
	
	CBENode* pNick = pRoot->GetNode( "nickname" );
	
	if ( pNick->IsType( CBENode::beString ) )
	{
		if ( m_pDownloadTransfer != NULL )
		{
			m_pDownloadTransfer->m_pSource->m_sNick = pNick->GetString();
		}
	}
	
	if ( CBENode* pExchange = pRoot->GetNode( "source-exchange" ) )
	{
		if ( pExchange->GetInt() >= 2 )
		{
			m_bExchange = TRUE;
			
			if ( m_pDownloadTransfer != NULL )
				Send( CBTPacket::New( BT_PACKET_SOURCE_REQUEST ) );
		}
	}
	
	delete pRoot;
	
	theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_EXTENDED, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CBTClient source request

BOOL CBTClient::OnSourceRequest(CBTPacket* pPacket)
{
	if ( m_pDownload == NULL ) return TRUE;
	
	CBENode pRoot;
	CBENode* pPeers = pRoot.Add( "peers" );
	
	for ( CDownloadSource* pSource = m_pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
	{
		if ( pSource->m_pTransfer == NULL ) continue;
		if ( pSource->m_pTransfer->m_nState < dtsRequesting ) continue;
		
		if ( pSource->m_nProtocol == PROTOCOL_BT )
		{
			CBENode* pPeer = pPeers->Add();
			CSourceURL pURL;
			
			if ( pURL.Parse( pSource->m_sURL ) && pURL.m_bBTC )
			{
				pPeer->Add( "peer id" )->SetString( &pURL.m_pBTC, sizeof(SHA1) );
			}
			
			pPeer->Add( "ip" )->SetString( CString( inet_ntoa( pSource->m_pAddress ) ) );
			pPeer->Add( "port" )->SetInt( pSource->m_nPort );
		}
		else if (	pSource->m_nProtocol == PROTOCOL_HTTP &&
					pSource->m_bReadContent == TRUE &&
					pSource->m_bPushOnly == FALSE )
		{
			CBENode* pPeer = pPeers->Add();
			pPeer->Add( "url" )->SetString( pSource->m_sURL );
		}
	}
	
	if ( pPeers->GetCount() == 0 ) return TRUE;
	
	CBuffer pOutput;
	pRoot.Encode( &pOutput );
	
	CBTPacket* pResponse = CBTPacket::New( BT_PACKET_SOURCE_RESPONSE );
	pResponse->Write( pOutput.m_pBuffer, pOutput.m_nLength );
	Send( pResponse );
	
	return TRUE;
}

⌨️ 快捷键说明

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