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