00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "BTClient.h"
00026 #include "BTClients.h"
00027 #include "BTPacket.h"
00028 #include "BENode.h"
00029 #include "Buffer.h"
00030 #include "SHA.h"
00031
00032 #include "Download.h"
00033 #include "Downloads.h"
00034 #include "DownloadSource.h"
00035 #include "DownloadTransferBT.h"
00036 #include "Uploads.h"
00037 #include "UploadTransferBT.h"
00038 #include "SourceURL.h"
00039 #include "GProfile.h"
00040
00041 #ifdef _DEBUG
00042 #undef THIS_FILE
00043 static char THIS_FILE[]=__FILE__;
00044 #define new DEBUG_NEW
00045 #endif
00046
00047
00049
00050
00051 CBTClient::CBTClient()
00052 {
00053 m_bExtended = FALSE;
00054 m_pUpload = NULL;
00055 m_pDownload = NULL;
00056 m_pDownloadTransfer = NULL;
00057
00058 m_bShake = FALSE;
00059 m_bOnline = FALSE;
00060 m_bClosing = FALSE;
00061 m_bExchange = FALSE;
00062
00063 m_sUserAgent = _T("BitTorrent");
00064 m_mInput.pLimit = m_mOutput.pLimit = &Settings.Bandwidth.Request;
00065
00066 BTClients.Add( this );
00067 }
00068
00069 CBTClient::~CBTClient()
00070 {
00071 ASSERT( m_hSocket == INVALID_SOCKET );
00072 ASSERT( m_pDownloadTransfer == NULL );
00073 ASSERT( m_pDownload == NULL );
00074 ASSERT( m_pUpload == NULL );
00075
00076 BTClients.Remove( this );
00077 }
00078
00080
00081
00082 BOOL CBTClient::Connect(CDownloadTransferBT* pDownloadTransfer)
00083 {
00084 ASSERT( m_hSocket == INVALID_SOCKET );
00085 ASSERT( m_pDownload == NULL );
00086
00087 CDownloadSource* pSource = pDownloadTransfer->m_pSource;
00088
00089 if ( ! CTransfer::ConnectTo( &pSource->m_pAddress, pSource->m_nPort ) ) return FALSE;
00090
00091 m_pDownload = pDownloadTransfer->m_pDownload;
00092 m_pDownloadTransfer = pDownloadTransfer;
00093
00094 theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_CONNECTING, (LPCTSTR)m_sAddress );
00095
00096 return TRUE;
00097 }
00098
00100
00101
00102 void CBTClient::AttachTo(CConnection* pConnection)
00103 {
00104 ASSERT( m_hSocket == INVALID_SOCKET );
00105 CTransfer::AttachTo( pConnection );
00106 theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_ACCEPTED, (LPCTSTR)m_sAddress );
00107 }
00108
00110
00111
00112 void CBTClient::Close()
00113 {
00114 ASSERT( this != NULL );
00115
00116 if ( m_bClosing ) return;
00117 m_bClosing = TRUE;
00118
00119 if ( m_pUpload != NULL ) m_pUpload->Close();
00120 ASSERT( m_pUpload == NULL );
00121
00122 if ( m_pDownloadTransfer != NULL )
00123 {
00124 if ( ( m_pDownload == NULL ) || ( m_pDownload->IsCompleted() ) )
00125 m_pDownloadTransfer->Close( TS_FALSE );
00126 else
00127 m_pDownloadTransfer->Close( TS_UNKNOWN );
00128 }
00129 ASSERT( m_pDownloadTransfer == NULL );
00130
00131 m_pDownload = NULL;
00132
00133 CTransfer::Close();
00134
00135 delete this;
00136 }
00137
00139
00140
00141 void CBTClient::Send(CBTPacket* pPacket, BOOL bRelease)
00142 {
00143 ASSERT( m_hSocket != INVALID_SOCKET );
00144 ASSERT( m_bOnline );
00145
00146 if ( pPacket != NULL )
00147 {
00148 ASSERT( pPacket->m_nProtocol == PROTOCOL_BT );
00149
00150 pPacket->ToBuffer( m_pOutput );
00151 if ( bRelease ) pPacket->Release();
00152 }
00153
00154 OnWrite();
00155 }
00156
00158
00159
00160 BOOL CBTClient::OnRun()
00161 {
00162 CTransfer::OnRun();
00163
00164 DWORD tNow = GetTickCount();
00165
00166 if ( ! m_bConnected )
00167 {
00168 if ( tNow - m_tConnected > Settings.Connection.TimeoutConnect )
00169 {
00170 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_CONNECT_TIMEOUT, (LPCTSTR)m_sAddress );
00171 Close();
00172 return FALSE;
00173 }
00174 }
00175 else if ( ! m_bOnline )
00176 {
00177 if ( tNow - m_tConnected > Settings.Connection.TimeoutHandshake )
00178 {
00179 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_HANDSHAKE_TIMEOUT, (LPCTSTR)m_sAddress );
00180 Close();
00181 return FALSE;
00182 }
00183 }
00184 else
00185 {
00186 if ( tNow - m_mInput.tLast > Settings.BitTorrent.LinkTimeout * 2 )
00187 {
00188 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_LOST, (LPCTSTR)m_sAddress );
00189 Close();
00190 return FALSE;
00191 }
00192 else if ( tNow - m_mOutput.tLast > Settings.BitTorrent.LinkPing / 2 && m_pOutput->m_nLength == 0 )
00193 {
00194 DWORD dwZero = 0;
00195 m_pOutput->Add( &dwZero, 4 );
00196 OnWrite();
00197 }
00198
00199
00200 ASSERT ( m_pUpload != NULL );
00201
00202 if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnRun() ) return FALSE;
00203 if ( m_pUpload == NULL || ! m_pUpload->OnRun() ) return FALSE;
00204 }
00205
00206 return TRUE;
00207 }
00208
00210
00211
00212 BOOL CBTClient::OnConnected()
00213 {
00214 theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_HANDSHAKING, (LPCTSTR)m_sAddress );
00215 SendHandshake( TRUE, TRUE );
00216 return TRUE;
00217 }
00218
00220
00221
00222 void CBTClient::OnDropped(BOOL bError)
00223 {
00224 if ( ! m_bConnected )
00225 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_DROP_CONNECTING, (LPCTSTR)m_sAddress );
00226 else if ( ! m_bOnline )
00227 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_DROP_HANDSHAKE, (LPCTSTR)m_sAddress );
00228 else
00229 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_DROP_CONNECTED, (LPCTSTR)m_sAddress );
00230
00231 Close();
00232 }
00233
00235
00236
00237 BOOL CBTClient::OnWrite()
00238 {
00239 CTransfer::OnWrite();
00240 return TRUE;
00241 }
00242
00244
00245
00246 BOOL CBTClient::OnRead()
00247 {
00248 BOOL bSuccess = TRUE;
00249
00250 CTransfer::OnRead();
00251
00252 if ( m_bOnline )
00253 {
00254 CBTPacket* pPacket;
00255
00256 while ( pPacket = CBTPacket::ReadBuffer( m_pInput ) )
00257 {
00258 try
00259 {
00260 bSuccess = OnPacket( pPacket );
00261 }
00262 catch ( CException* pException )
00263 {
00264 pException->Delete();
00265 if ( ! m_bOnline ) bSuccess = FALSE;
00266 }
00267
00268 pPacket->Release();
00269 if ( ! bSuccess ) break;
00270 }
00271 }
00272 else
00273 {
00274 if ( ! m_bShake && m_pInput->m_nLength >= BT_PROTOCOL_HEADER_LEN + 8 + sizeof(SHA1) )
00275 {
00276 bSuccess = OnHandshake1();
00277 }
00278
00279 if ( bSuccess && m_bShake && m_pInput->m_nLength >= sizeof(SHA1) )
00280 {
00281 bSuccess = OnHandshake2();
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 }
00293
00294 return bSuccess;
00295 }
00296
00298
00299
00300 void CBTClient::SendHandshake(BOOL bPart1, BOOL bPart2)
00301 {
00302 ASSERT( m_pDownload != NULL );
00303
00304 if ( bPart1 )
00305 {
00306 DWORD dwZero = 0;
00307 m_pOutput->Print( BT_PROTOCOL_HEADER );
00308 m_pOutput->Add( &dwZero, 4 );
00309 m_pOutput->Add( &dwZero, 4 );
00310 m_pOutput->Add( &m_pDownload->m_pBTH, sizeof(SHA1) );
00311 }
00312
00313 if ( bPart2 )
00314 {
00315 m_pOutput->Add( &m_pDownload->m_pPeerID, sizeof(SHA1) );
00316 }
00317
00318 OnWrite();
00319 }
00320
00321 BOOL CBTClient::OnHandshake1()
00322 {
00323 ASSERT( ! m_bOnline );
00324 ASSERT( ! m_bShake );
00325
00326 LPBYTE pIn = m_pInput->m_pBuffer;
00327
00328
00329 if ( memcmp( pIn, BT_PROTOCOL_HEADER, BT_PROTOCOL_HEADER_LEN ) != 0 )
00330 {
00331 ASSERT( FALSE );
00332 theApp.Message( MSG_ERROR, _T("BitTorrent coupling from %s had invalid header"), (LPCTSTR)m_sAddress );
00333 Close();
00334 return FALSE;
00335 }
00336
00337 pIn += BT_PROTOCOL_HEADER_LEN + 8;
00338
00339
00340 SHA1 pFileHash = *(SHA1*)pIn;
00341 pIn += sizeof(SHA1);
00342
00343 m_pInput->Remove( BT_PROTOCOL_HEADER_LEN + 8 + sizeof(SHA1) );
00344
00345 if ( m_bInitiated )
00346 {
00347 ASSERT( m_pDownload != NULL );
00348 ASSERT( m_pDownloadTransfer != NULL );
00349
00350 if ( pFileHash != m_pDownload->m_pBTH || m_pDownload->IsShared() == FALSE )
00351 {
00352 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_WRONG_FILE, (LPCTSTR)m_sAddress );
00353 Close();
00354 return FALSE;
00355 }
00356 else if ( ! m_pDownload->IsTrying() )
00357 {
00358 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_INACTIVE_FILE, (LPCTSTR)m_sAddress );
00359 Close();
00360 return FALSE;
00361 }
00362 }
00363 else
00364 {
00365 ASSERT( m_pDownload == NULL );
00366 ASSERT( m_pDownloadTransfer == NULL );
00367
00368
00369 m_pDownload = Downloads.FindByBTH( &pFileHash, TRUE );
00370
00371 if ( m_pDownload == NULL )
00372 {
00373 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_UNKNOWN_FILE, (LPCTSTR)m_sAddress );
00374 Close();
00375 return FALSE;
00376 }
00377 else if ( ! m_pDownload->IsTrying() )
00378 {
00379 m_pDownload = NULL;
00380 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_INACTIVE_FILE, (LPCTSTR)m_sAddress );
00381 Close();
00382 return FALSE;
00383 }
00384 else if ( m_pDownload->UploadExists( &m_pHost.sin_addr ) )
00385 {
00386 m_pDownload = NULL;
00387 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_DUPLICATE, (LPCTSTR)m_sAddress );
00388 Close();
00389 return FALSE;
00390 }
00391
00392
00393
00394 if ( ( m_pDownload->GetTransferCount( dtsCountTorrentAndActive ) ) > ( Settings.BitTorrent.DownloadConnections * 1.25 ) )
00395 {
00396 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_MAX_CONNECTIONS, (LPCTSTR)m_sAddress );
00397 Close();
00398 return FALSE;
00399 }
00400
00401 }
00402
00403
00404 ASSERT( m_pDownload != NULL );
00405 ASSERT( m_pDownload->m_pBTH == pFileHash );
00406
00407
00408 if ( ! m_bInitiated ) SendHandshake( TRUE, TRUE );
00409 m_bShake = TRUE;
00410
00411 return TRUE;
00412 }
00413
00414 BOOL CBTClient::OnHandshake2()
00415 {
00416 m_pGUID = *(SHA1*)m_pInput->m_pBuffer;
00417 m_pInput->Remove( sizeof(SHA1) );
00418
00419 for ( int nByte = 0 ; nByte < 20 ; nByte++ )
00420 {
00421 if ( nByte < 16 )
00422 {
00423 if ( m_pGUID.b[ nByte ] ) m_bExtended = TRUE;
00424 }
00425 else
00426 {
00427 if ( m_pGUID.b[ nByte ] != ( m_pGUID.b[ nByte % 16 ] ^ m_pGUID.b[ 15 - ( nByte % 16 ) ] ) )
00428 {
00429 m_bExtended = FALSE;
00430 break;
00431 }
00432 }
00433 }
00434
00435 ASSERT( m_pDownload != NULL );
00436
00437 if ( m_bInitiated )
00438 {
00439 ASSERT( m_pDownloadTransfer != NULL );
00440 CopyMemory( &m_pDownloadTransfer->m_pSource->m_pGUID, &m_pGUID, 16 );
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 }
00453 else
00454 {
00455 if ( m_pDownload->UploadExists( &m_pGUID ) )
00456 {
00457 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_DUPLICATE, (LPCTSTR)m_sAddress );
00458 Close();
00459 return FALSE;
00460 }
00461
00462 if ( ! m_pDownload->IsMoving() && ! m_pDownload->IsPaused() )
00463 {
00464 ASSERT( m_pDownloadTransfer == NULL );
00465
00466
00467 if ( m_pDownload->m_nStartTorrentDownloads != dtNever )
00468 {
00469
00470
00471 m_pDownloadTransfer = m_pDownload->CreateTorrentTransfer( this );
00472
00473 if ( m_pDownloadTransfer == NULL )
00474 {
00475 m_pDownload = NULL;
00476 theApp.Message( MSG_ERROR, IDS_BT_CLIENT_UNKNOWN_FILE, (LPCTSTR)m_sAddress );
00477 Close();
00478 return FALSE;
00479 }
00480 }
00481 }
00482 }
00483
00484 ASSERT( m_pUpload == NULL );
00485 m_pUpload = new CUploadTransferBT( this, m_pDownload );
00486
00487 m_bOnline = TRUE;
00488
00489 DetermineUserAgent();
00490 if ( m_bExtended ) m_sUserAgent = _T("Shareaza");
00491
00492 return OnOnline();
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00532
00533
00534 void CBTClient::DetermineUserAgent()
00535 {
00536 int nNickStart = 0, nNickEnd = 13;
00537 CString strVer, strNick;
00538
00539 if ( m_pGUID.b[0] == '-' && m_pGUID.b[7] == '-' )
00540 {
00541 if ( m_pGUID.b[1] == 'A' && m_pGUID.b[2] == 'R' )
00542 {
00543 m_sUserAgent = _T("Arctic");
00544 }
00545 else if ( m_pGUID.b[1] == 'A' && m_pGUID.b[2] == 'Z' )
00546 {
00547 m_sUserAgent = _T("Azureus");
00548 }
00549 else if ( m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'B' )
00550 {
00551 m_sUserAgent = _T("BitBuddy");
00552 }
00553 else if ( m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'C' )
00554 {
00555 m_sUserAgent = _T("BitComet");
00556 }
00557 else if ( m_pGUID.b[1] == 'b' && m_pGUID.b[2] == 'k' )
00558 {
00559 m_sUserAgent = _T("BitKitten");
00560 }
00561 else if ( m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'O' )
00562 {
00563
00564 m_sUserAgent = _T("BO");
00565 }
00566 else if ( m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'S' )
00567 {
00568 m_sUserAgent = _T("BTSlave");
00569 }
00570 else if ( m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'X' )
00571 {
00572 m_sUserAgent = _T("Bittorrent X");
00573 }
00574 else if ( m_pGUID.b[1] == 'C' && m_pGUID.b[2] == 'T' )
00575 {
00576 m_sUserAgent = _T("CTorrent");
00577 }
00578 else if ( ( m_pGUID.b[1] == 'L' && m_pGUID.b[2] == 'T' ) || ( m_pGUID.b[1] == 'l' && m_pGUID.b[2] == 't' ) )
00579 {
00580 m_sUserAgent = _T("libtorrent");
00581 }
00582 else if ( m_pGUID.b[1] == 'M' && m_pGUID.b[2] == 'P' )
00583 {
00584 m_sUserAgent = _T("MooPolice");
00585 }
00586 else if ( m_pGUID.b[1] == 'M' && m_pGUID.b[2] == 'T' )
00587 {
00588 m_sUserAgent = _T("MoonlightTorrent");
00589 }
00590 else if ( m_pGUID.b[1] == 'Q' && m_pGUID.b[2] == 'T' )
00591 {
00592 m_sUserAgent = _T("QT4");
00593 }
00594 else if ( m_pGUID.b[1] == 'S' && m_pGUID.b[2] == 'B' )
00595 {
00596 m_sUserAgent = _T("Swiftbit");
00597 }
00598 else if ( m_pGUID.b[1] == 'S' && m_pGUID.b[2] == 'N' )
00599 {
00600 m_sUserAgent = _T("ShareNET");
00601 }
00602 else if ( m_pGUID.b[1] == 'S' && m_pGUID.b[2] == 'S' )
00603 {
00604 m_sUserAgent = _T("Swarmscope");
00605 }
00606 else if ( m_pGUID.b[1] == 'S' && m_pGUID.b[2] == '~' )
00607 {
00608 m_sUserAgent = _T("Sbeta");
00609 }
00610 else if ( m_pGUID.b[1] == 'S' && m_pGUID.b[2] == 'Z' )
00611 {
00612
00613
00614 m_sUserAgent.Empty();
00615 }
00616 else if ( m_pGUID.b[1] == 'T' && m_pGUID.b[2] == 'N' )
00617 {
00618 m_sUserAgent = _T("TorrentDOTnet");
00619 }
00620 else if ( m_pGUID.b[1] == 'T' && m_pGUID.b[2] == 'S' )
00621 {
00622 m_sUserAgent = _T("Torrentstorm");
00623 }
00624 else if ( m_pGUID.b[1] == 'X' && m_pGUID.b[2] == 'T' )
00625 {
00626 m_sUserAgent = _T("XanTorrent");
00627 }
00628 else if ( m_pGUID.b[1] == 'Z' && m_pGUID.b[2] == 'T' )
00629 {
00630 m_sUserAgent = _T("ZipTorrent");
00631 }
00632 else
00633 {
00634 m_sUserAgent.Format( _T("%c%c"), m_pGUID.b[1], m_pGUID.b[2] );
00635 }
00636
00637 if ( m_sUserAgent.IsEmpty() )
00638 {
00639
00640 m_sUserAgent.Format( _T("BitTorrent (%c%c)"), m_pGUID.b[1], m_pGUID.b[2] );
00641 }
00642 else
00643 {
00644
00645 strVer.Format( _T(" %i.%i.%i.%i"),
00646 ( m_pGUID.b[3] - '0' ), ( m_pGUID.b[4] - '0' ),
00647 ( m_pGUID.b[5] - '0' ), ( m_pGUID.b[6] - '0' ) );
00648 m_sUserAgent += strVer;
00649 }
00650 }
00651 else if ( m_pGUID.b[4] == '-' && m_pGUID.b[5] == '-' && m_pGUID.b[6] == '-' && m_pGUID.b[7] == '-' )
00652 {
00653 switch ( m_pGUID.b[0] )
00654 {
00655 case 'A':
00656 m_sUserAgent = _T("ABC");
00657 break;
00658 case 'O':
00659 m_sUserAgent = _T("Osprey");
00660 break;
00661 case 'S':
00662 m_sUserAgent = _T("Shadow");
00663 break;
00664 case 'T':
00665 m_sUserAgent = _T("BitTornado");
00666 break;
00667 case 'U':
00668 m_sUserAgent = _T("UPnP NAT BT");
00669 break;
00670 default:
00671 m_sUserAgent.Format(_T("%c"), m_pGUID.b[0]);
00672 }
00673
00674 strVer.Format( _T(" %i.%i.%i"),
00675 ( m_pGUID.b[1] - '0' ), ( m_pGUID.b[2] - '0' ),
00676 ( m_pGUID.b[3] - '0' ) );
00677 m_sUserAgent += strVer;
00678 }
00679 else if ( m_pGUID.b[0] == 'M' && m_pGUID.b[2] == '-' && m_pGUID.b[4] == '-' && m_pGUID.b[6] == '-' )
00680 {
00681 m_sUserAgent.Format( _T("BitTorrent %i.%i.%i"), m_pGUID.b[1] - '0' , m_pGUID.b[3] - '0' , m_pGUID.b[5]- '0' );
00682 }
00683 else if ( m_pGUID.b[0] == 'P' && m_pGUID.b[1] == 'l' && m_pGUID.b[2] == 'u' && m_pGUID.b[3] == 's' )
00684 {
00685 m_sUserAgent.Format( _T("BitTorrent Plus %i.%i%i"), m_pGUID.b[4] - '0', m_pGUID.b[5] - '0', m_pGUID.b[6] - '0' );
00686 }
00687 else if ( m_pGUID.b[0] == 'e' && m_pGUID.b[1] == 'x' && m_pGUID.b[2] == 'b' && m_pGUID.b[3] == 'c' )
00688 {
00689
00690 if ( m_pGUID.b[6] == 'L' && m_pGUID.b[7] == 'O' && m_pGUID.b[8] == 'R' && m_pGUID.b[9] == 'D' )
00691 m_sUserAgent.Format( _T("BitLord %i.%02i"), m_pGUID.b[4], m_pGUID.b[5] );
00692
00693 else
00694 m_sUserAgent.Format( _T("BitComet %i.%02i"), m_pGUID.b[4], m_pGUID.b[5] );
00695 }
00696 else if ( ( m_pGUID.b[0] == 'B' && m_pGUID.b[1] == 'S' ) || ( m_pGUID.b[2] == 'B' && m_pGUID.b[3] == 'S' ) )
00697 {
00698 m_sUserAgent.Format( _T("BitSpirit") );
00699 }
00700 else if ( m_pGUID.b[0] == 'B' && m_pGUID.b[1] == 'T' && m_pGUID.b[2] == 'M' )
00701 {
00702 m_sUserAgent.Format( _T("BTuga Rv %i.%i"), m_pGUID.b[3] - '0', m_pGUID.b[4] - '0' );
00703 nNickStart = 5;
00704 }
00705 else if ( ( m_pGUID.b[0] == 'b' && m_pGUID.b[1] == 't' && m_pGUID.b[2] == 'u' && m_pGUID.b[3] == 'g' && m_pGUID.b[4] == 'a' ) || ( m_pGUID.b[0] == 'o' && m_pGUID.b[1] == 'e' && m_pGUID.b[2] == 'r' && m_pGUID.b[3] == 'n' && m_pGUID.b[4] == 'u' ) )
00706 {
00707 m_sUserAgent.Format( _T("BTugaXP") );
00708 }
00709 else if ( m_pGUID.b[0] == 'M' && m_pGUID.b[1] == 'b' && m_pGUID.b[2] == 'r' && m_pGUID.b[3] == 's' && m_pGUID.b[4] == 't' )
00710 {
00711 m_sUserAgent.Format( _T("Burst %i.%i.%i"), m_pGUID.b[5] - '0', m_pGUID.b[7] - '0', m_pGUID.b[9] - '0' );
00712 }
00713 else if ( m_pGUID.b[0] == 'e' && m_pGUID.b[1] == 'X' )
00714 {
00715 m_sUserAgent.Format( _T("eXeem") );
00716 nNickStart = 2;
00717 }
00718 else if ( m_pGUID.b[0] == '-' && m_pGUID.b[1] == 'G' && m_pGUID.b[2] == '3' )
00719 {
00720 m_sUserAgent.Format( _T("G3 Torrent") );
00721 nNickStart = 3;
00722 nNickEnd = 11;
00723 }
00724 else if ( m_pGUID.b[0] == '-' && m_pGUID.b[1] == 'M' && m_pGUID.b[2] == 'L' )
00725 {
00726 m_sUserAgent.Format( _T("MLdonkey %i.%i.%i"), m_pGUID.b[3] - '0' , m_pGUID.b[5] - '0' , m_pGUID.b[7] - '0' );
00727 }
00728 else if ( m_pGUID.b[0] == 'O' && m_pGUID.b[1] == 'P' )
00729 {
00730 m_sUserAgent.Format( _T("Opera %i%i%i%i"), m_pGUID.b[2] - '0', m_pGUID.b[3] - '0', m_pGUID.b[4] - '0', m_pGUID.b[5] - '0' );
00731 }
00732 else if ( ( m_pGUID.b[0] == 'a' && m_pGUID.b[1] == '0' && m_pGUID.b[2] == '0' && m_pGUID.b[3] == '-' && m_pGUID.b[4] == '-' && m_pGUID.b[5] == '-' && m_pGUID.b[6] == '0' ) || ( m_pGUID.b[0] == 'a' && m_pGUID.b[1] == '0' && m_pGUID.b[2] == '2' && m_pGUID.b[3] == '-' && m_pGUID.b[4] == '-' && m_pGUID.b[5] == '-' && m_pGUID.b[6] == '0' ) )
00733 {
00734 m_sUserAgent.Format( _T("Swarmy") );
00735 }
00736 else if ( m_pGUID.b[0] == 'X' && m_pGUID.b[1] == 'B' && m_pGUID.b[2] == 'T' )
00737 {
00738 m_sUserAgent.Format( _T("XBT %i.%i.%i"), m_pGUID.b[3] - '0', m_pGUID.b[4] - '0', m_pGUID.b[5] - '0' );
00739 }
00740 else if ( !m_pGUID.b[0] && !m_pGUID.b[1] && !m_pGUID.b[2] && !m_pGUID.b[3] && !m_pGUID.b[4] && !m_pGUID.b[5] && !m_pGUID.b[6] && !m_pGUID.b[7] && m_pGUID.b[8] && m_pGUID.b[9] && m_pGUID.b[10] && m_pGUID.b[11] && m_pGUID.b[12] && m_pGUID.b[13] && m_pGUID.b[14] && m_pGUID.b[15] && m_pGUID.b[16] == 'U' && m_pGUID.b[17] == 'D' && m_pGUID.b[18] == 'P' && m_pGUID.b[19] == '0' )
00741 {
00742 m_sUserAgent.Format( _T("BitSpirit") );
00743 }
00744 else
00745 {
00746 m_sUserAgent = _T("BitTorrent");
00747 }
00748
00749 if ( nNickStart > 0 )
00750 for ( int i = nNickStart; i <= nNickEnd; i++ )
00751 {
00752 if ( m_pGUID.b[i] == NULL ) break;
00753
00754 strNick.AppendFormat( _T("%c"), m_pGUID.b[i] );
00755 }
00756
00757 if ( m_pDownloadTransfer != NULL )
00758 {
00759 m_pDownloadTransfer->m_sUserAgent = m_sUserAgent;
00760 if ( m_pDownloadTransfer->m_pSource != NULL )
00761 {
00762 m_pDownloadTransfer->m_pSource->m_sServer = m_sUserAgent;
00763 if ( strNick.GetLength() ) m_pDownloadTransfer->m_pSource->m_sNick = strNick;
00764 m_pDownloadTransfer->m_pSource->m_bClientExtended = ( m_bExtended && ! m_pDownloadTransfer->m_pSource->m_bPushOnly);
00765 }
00766 }
00767
00768 if ( m_pUpload != NULL )
00769 {
00770 m_pUpload->m_sUserAgent = m_sUserAgent;
00771 if ( strNick.GetLength() ) m_pUpload->m_sNick = strNick;
00772 m_pUpload->m_bClientExtended = m_bExtended;
00773 }
00774 }
00775
00777
00778
00779 BOOL CBTClient::OnOnline()
00780 {
00781 ASSERT( m_bOnline );
00782 ASSERT( m_pDownload != NULL );
00783 ASSERT( m_pUpload != NULL );
00784
00785 theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_ONLINE, (LPCTSTR)m_sAddress,
00786 (LPCTSTR)m_pDownload->GetDisplayName() );
00787
00788 if ( m_bExtended ) SendBeHandshake();
00789
00790 if ( CBTPacket* pBitfield = m_pDownload->CreateBitfieldPacket() )
00791 Send( pBitfield );
00792
00793 if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnConnected() ) return FALSE;
00794 if ( ! m_pUpload->OnConnected() ) return FALSE;
00795
00796 return TRUE;
00797 }
00798
00800
00801
00802 BOOL CBTClient::OnPacket(CBTPacket* pPacket)
00803 {
00804 switch ( pPacket->m_nType )
00805 {
00806 case BT_PACKET_KEEPALIVE:
00807 break;
00808 case BT_PACKET_CHOKE:
00809 if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnChoked( pPacket ) ) return FALSE;
00810 m_pDownload->ChokeTorrent();
00811 break;
00812 case BT_PACKET_UNCHOKE:
00813 if ( m_pDownloadTransfer != NULL && ! m_pDownloadTransfer->OnUnchoked( pPacket ) ) return FALSE;
00814 m_pDownload->ChokeTorrent();
00815 break;
00816 case BT_PACKET_INTERESTED:
00817 if ( ! m_pUpload->OnInterested( pPacket ) ) return FALSE;
00818 m_pDownload->ChokeTorrent();
00819 break;
00820 case BT_PACKET_NOT_INTERESTED:
00821 if ( ! m_pUpload->OnUninterested( pPacket ) ) return FALSE;
00822 m_pDownload->ChokeTorrent();
00823 break;
00824 case BT_PACKET_HAVE:
00825 return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnHave( pPacket );
00826 case BT_PACKET_BITFIELD:
00827 return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnBitfield( pPacket );
00828 case BT_PACKET_REQUEST:
00829 return m_pUpload->OnRequest( pPacket );
00830 case BT_PACKET_PIECE:
00831 return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnPiece( pPacket );
00832 case BT_PACKET_CANCEL:
00833 return m_pUpload->OnCancel( pPacket );
00834
00835 case BT_PACKET_HANDSHAKE:
00836 if ( ! m_bExtended ) break;
00837 return OnBeHandshake( pPacket );
00838 case BT_PACKET_SOURCE_REQUEST:
00839 if ( ! m_bExchange ) break;
00840 return OnSourceRequest( pPacket );
00841 case BT_PACKET_SOURCE_RESPONSE:
00842 if ( ! m_bExchange ) break;
00843 return m_pDownloadTransfer == NULL || m_pDownloadTransfer->OnSourceResponse( pPacket );
00844 }
00845
00846 return TRUE;
00847 }
00848
00850
00851
00852 void CBTClient::SendBeHandshake()
00853 {
00854 CBENode pRoot;
00855
00856 CString strNick = MyProfile.GetNick().Left( 255 );
00857 if ( strNick.GetLength() ) pRoot.Add( "nickname" )->SetString( strNick );
00858
00859
00860 pRoot.Add( "source-exchange" )->SetInt( 2 );
00861 pRoot.Add( "user-agent" )->SetString( Settings.SmartAgent() );
00862
00863 CBuffer pOutput;
00864 pRoot.Encode( &pOutput );
00865
00866 CBTPacket* pPacket = CBTPacket::New( BT_PACKET_HANDSHAKE );
00867 pPacket->Write( pOutput.m_pBuffer, pOutput.m_nLength );
00868 Send( pPacket );
00869 }
00870
00871 BOOL CBTClient::OnBeHandshake(CBTPacket* pPacket)
00872 {
00873 if ( pPacket->GetRemaining() > 1024 ) return TRUE;
00874
00875 CBuffer pInput;
00876 pInput.Add( pPacket->m_pBuffer, pPacket->GetRemaining() );
00877
00878 CBENode* pRoot = CBENode::Decode( &pInput );
00879 if ( pRoot == NULL ) return TRUE;
00880
00881 CBENode* pAgent = pRoot->GetNode( "user-agent" );
00882
00883 if ( pAgent->IsType( CBENode::beString ) )
00884 {
00885 m_sUserAgent = pAgent->GetString();
00886
00887 if ( m_pDownloadTransfer != NULL )
00888 {
00889 m_pDownloadTransfer->m_sUserAgent = m_sUserAgent;
00890 if ( m_pDownloadTransfer->m_pSource != NULL )
00891 {
00892 m_pDownloadTransfer->m_pSource->m_sServer = m_sUserAgent;
00893 m_pDownloadTransfer->m_pSource->m_bClientExtended = TRUE;
00894 }
00895 }
00896
00897 if ( m_pUpload != NULL )
00898 {
00899 m_pUpload->m_sUserAgent = m_sUserAgent;
00900 m_pUpload->m_bClientExtended = TRUE;
00901 }
00902 }
00903
00904 CBENode* pNick = pRoot->GetNode( "nickname" );
00905
00906 if ( pNick->IsType( CBENode::beString ) )
00907 {
00908 if ( m_pDownloadTransfer != NULL )
00909 {
00910 m_pDownloadTransfer->m_pSource->m_sNick = pNick->GetString();
00911 }
00912 }
00913
00914 if ( CBENode* pExchange = pRoot->GetNode( "source-exchange" ) )
00915 {
00916 if ( pExchange->GetInt() >= 2 )
00917 {
00918 m_bExchange = TRUE;
00919
00920 if ( m_pDownloadTransfer != NULL )
00921 Send( CBTPacket::New( BT_PACKET_SOURCE_REQUEST ) );
00922 }
00923 }
00924
00925 delete pRoot;
00926
00927 theApp.Message( MSG_DEFAULT, IDS_BT_CLIENT_EXTENDED, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
00928
00929 return TRUE;
00930 }
00931
00933
00934
00935 BOOL CBTClient::OnSourceRequest(CBTPacket* pPacket)
00936 {
00937 if ( m_pDownload == NULL ) return TRUE;
00938
00939 CBENode pRoot;
00940 CBENode* pPeers = pRoot.Add( "peers" );
00941
00942 for ( CDownloadSource* pSource = m_pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00943 {
00944 if ( pSource->m_pTransfer == NULL ) continue;
00945 if ( pSource->m_pTransfer->m_nState < dtsRequesting ) continue;
00946
00947 if ( pSource->m_nProtocol == PROTOCOL_BT )
00948 {
00949 CBENode* pPeer = pPeers->Add();
00950 CSourceURL pURL;
00951
00952 if ( pURL.Parse( pSource->m_sURL ) && pURL.m_bBTC )
00953 {
00954 pPeer->Add( "peer id" )->SetString( &pURL.m_pBTC, sizeof(SHA1) );
00955 }
00956
00957 pPeer->Add( "ip" )->SetString( CString( inet_ntoa( pSource->m_pAddress ) ) );
00958 pPeer->Add( "port" )->SetInt( pSource->m_nPort );
00959 }
00960 else if ( pSource->m_nProtocol == PROTOCOL_HTTP &&
00961 pSource->m_bReadContent == TRUE &&
00962 pSource->m_bPushOnly == FALSE )
00963 {
00964 CBENode* pPeer = pPeers->Add();
00965 pPeer->Add( "url" )->SetString( pSource->m_sURL );
00966 }
00967 }
00968
00969 if ( pPeers->GetCount() == 0 ) return TRUE;
00970
00971 CBuffer pOutput;
00972 pRoot.Encode( &pOutput );
00973
00974 CBTPacket* pResponse = CBTPacket::New( BT_PACKET_SOURCE_RESPONSE );
00975 pResponse->Write( pOutput.m_pBuffer, pOutput.m_nLength );
00976 Send( pResponse );
00977
00978 return TRUE;
00979 }