Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

UploadTransferBT.cpp

Go to the documentation of this file.
00001 //
00002 // UploadTransferBT.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include <algorithm>
00024 #include "Shareaza.h"
00025 #include "Settings.h"
00026 #include "BTClient.h"
00027 #include "BTPacket.h"
00028 #include "Download.h"
00029 #include "DownloadTransferBT.h"
00030 #include "Uploads.h"
00031 #include "UploadFile.h"
00032 #include "UploadFiles.h"
00033 #include "UploadTransferBT.h"
00034 #include "FragmentedFile.h"
00035 #include "TransferFile.h"
00036 #include "Statistics.h"
00037 #include "Buffer.h"
00038 
00039 #ifdef _DEBUG
00040 #undef THIS_FILE
00041 static char THIS_FILE[]=__FILE__;
00042 #define new DEBUG_NEW
00043 #endif
00044 
00045 
00047 // CUploadTransferBT construction
00048 
00049 CUploadTransferBT::CUploadTransferBT(CBTClient* pClient, CDownload* pDownload) : CUploadTransfer( PROTOCOL_BT )
00050 {
00051         ASSERT( pClient != NULL );
00052         ASSERT( pDownload != NULL );
00053         
00054         m_pDownload                     = pDownload;
00055         m_pClient                       = pClient;
00056         m_pHost                         = pClient->m_pHost;
00057         m_sAddress                      = pClient->m_sAddress;
00058         m_sUserAgent            = _T("BitTorrent");
00059         
00060         m_nState                        = upsReady;
00061         m_bInterested           = FALSE;
00062         m_bChoked                       = TRUE;
00063         m_nRandomUnchoke        = 0;
00064         
00065         RequestPartial( m_pDownload );
00066         m_pDownload->AddUpload( this );
00067 }
00068 
00069 CUploadTransferBT::~CUploadTransferBT()
00070 {
00071         ASSERT( m_pClient == NULL );
00072         ASSERT( m_pDownload == NULL );
00073 }
00074 
00076 // CUploadTransferBT choking
00077 
00078 void CUploadTransferBT::SetChoke(BOOL bChoke)
00079 {
00080         // Sort transfers- keep active ones near the head (Top of the list in the uploads window)
00081         if ( ! bChoke ) UploadFiles.MoveToHead( this );
00082 
00083         // If we have not changed state, just return
00084         if ( m_bChoked == bChoke ) return;
00085 
00086         // Update state
00087         m_bChoked = bChoke;
00088         
00089         m_oRequested.clear();
00090         m_oServed.clear();
00091         
00092         if ( bChoke )
00093         {
00094                 m_nState = upsReady;
00095                 UploadFiles.MoveToTail( this );
00096         }
00097         
00098         m_pClient->Send( CBTPacket::New( bChoke ? BT_PACKET_CHOKE : BT_PACKET_UNCHOKE ) );
00099         
00100         theApp.Message( MSG_DEBUG, _T("%s upload to %s"),
00101                 bChoke ? _T("Choking") : _T("Unchoking"), (LPCTSTR)m_sAddress );
00102 }
00103 
00105 // CUploadTransferBT close
00106 
00107 void CUploadTransferBT::Close(BOOL bMessage)
00108 {
00109         if ( m_pClient != NULL )
00110         {
00111                 m_pClient->m_pUpload = NULL;
00112                 m_pClient->Close();
00113                 m_pClient = NULL;
00114         }
00115         
00116         if ( m_pDiskFile != NULL ) CloseFile();
00117         
00118         if ( m_pDownload != NULL ) m_pDownload->RemoveUpload( this );
00119         m_pDownload = NULL;
00120         
00121         m_oRequested.clear();
00122         m_oServed.clear();
00123         
00124         CUploadTransfer::Close( bMessage );
00125 }
00126 
00128 // CUploadTransferBT bandwidth
00129 
00130 DWORD CUploadTransferBT::GetMeasuredSpeed()
00131 {
00132         if ( m_pClient == NULL ) return 0;
00133         m_pClient->Measure();
00134         return m_pClient->m_mOutput.nMeasure;
00135 }
00136 
00138 // CUploadTransferBT connection event
00139 
00140 BOOL CUploadTransferBT::OnConnected()
00141 {
00142         m_pClient->m_mOutput.pLimit = &Uploads.m_nTorrentSpeed;
00143         return TRUE;
00144 }
00145 
00147 // CUploadTransferBT run event
00148 
00149 BOOL CUploadTransferBT::OnRun()
00150 {
00151         if ( m_nState >= upsRequest && ! m_bChoked ) return ServeRequests();
00152         return TRUE;
00153 }
00154 
00156 // CUploadTransferBT interest flag
00157 
00158 BOOL CUploadTransferBT::OnInterested(CBTPacket* pPacket)
00159 {
00160         if ( m_bInterested ) return TRUE;
00161         m_bInterested = TRUE;
00162         return TRUE;
00163 }
00164 
00165 BOOL CUploadTransferBT::OnUninterested(CBTPacket* pPacket)
00166 {
00167         if ( ! m_bInterested ) return TRUE;
00168         m_bInterested = FALSE;
00169         m_nState = upsReady;
00170         return TRUE;
00171 }
00172 
00174 // CUploadTransferBT request management
00175 
00176 BOOL CUploadTransferBT::OnRequest(CBTPacket* pPacket)
00177 {
00178         if ( pPacket->GetRemaining() < 4 * 3 ) return TRUE;
00179         if ( m_bChoked ) return TRUE;
00180         
00181         QWORD nIndex    = pPacket->ReadLongBE();
00182         QWORD nOffset   = pPacket->ReadLongBE();
00183         QWORD nLength   = pPacket->ReadLongBE();
00184         
00185         nOffset += nIndex * m_pDownload->m_pTorrent.m_nBlockSize;
00186         
00187         if ( nLength > Settings.BitTorrent.RequestLimit )
00188         {
00189                 // error
00190                 theApp.Message( MSG_DEBUG, _T("CUploadTransferBT::OnRequest(): Request size %I64i is too large"), nLength );
00191                 Close();
00192                 return FALSE;
00193         }
00194         
00195         if ( nOffset + nLength > m_nFileSize )
00196         {
00197                 // error
00198                 theApp.Message( MSG_DEBUG, _T("CUploadTransferBT::OnRequest(): Request through %I64i > %I64i"), nLength, m_nFileSize );
00199                 Close();
00200                 return FALSE;
00201         }
00202         
00203     if ( ::std::find_first_of( m_oRequested.begin(), m_oRequested.end(), m_oServed.begin(), m_oServed.end() )
00204         != m_oRequested.end() ) return TRUE;
00205         
00206     m_oRequested.pushBack( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00207         
00208         if ( m_nState == upsReady )
00209         {
00210                 m_nState = upsRequest;
00211                 AllocateBaseFile();
00212                 theApp.Message( MSG_SYSTEM, IDS_UPLOAD_FILE,
00213                         (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
00214         }
00215         
00216         return ServeRequests();
00217 }
00218 
00219 BOOL CUploadTransferBT::OnCancel(CBTPacket* pPacket)
00220 {
00221         if ( pPacket->GetRemaining() < 4 * 3 ) return TRUE;
00222         
00223         QWORD nIndex    = pPacket->ReadLongBE();
00224         QWORD nOffset   = pPacket->ReadLongBE();
00225         QWORD nLength   = pPacket->ReadLongBE();
00226         
00227         nOffset += nIndex * m_pDownload->m_pTorrent.m_nBlockSize;
00228         
00229     m_oRequested.erase( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00230         
00231         return TRUE;
00232 }
00233 
00235 // CUploadTransferBT file access
00236 
00237 BOOL CUploadTransferBT::OpenFile()
00238 {
00239         ASSERT( m_nState == upsRequest || m_nState == upsUploading );
00240         ASSERT( m_pBaseFile != NULL );
00241         
00242         if ( m_pDiskFile != NULL ) return TRUE;
00243         m_pDiskFile = TransferFiles.Open( m_sFilePath, FALSE, FALSE );
00244         if ( m_pDiskFile != NULL ) return TRUE;
00245         
00246         theApp.Message( MSG_ERROR, IDS_UPLOAD_CANTOPEN, (LPCTSTR)m_sFileName , (LPCTSTR)m_sAddress);
00247         
00248         Close();
00249         return FALSE;
00250 }
00251 
00253 // CUploadTransferBT serving
00254 
00255 BOOL CUploadTransferBT::ServeRequests()
00256 {
00257         ASSERT( m_nState == upsRequest || m_nState == upsUploading );
00258         ASSERT( m_pBaseFile != NULL );
00259         ASSERT( m_nLength == SIZE_UNKNOWN );
00260         
00261         if ( m_bChoked ) return TRUE;
00262         if ( m_pClient->m_pOutput->m_nLength > Settings.BitTorrent.RequestSize / 3 ) return TRUE;
00263         
00264         while ( !m_oRequested.empty() && m_nLength == SIZE_UNKNOWN )
00265         {
00266         if ( ::std::find( m_oServed.begin(), m_oServed.end(), *m_oRequested.begin() )
00267             == m_oServed.end()
00268             // This should be redundant (Camper)
00269             && m_oRequested.begin()->begin() < m_nFileSize
00270             && m_oRequested.begin()->end() <= m_nFileSize )
00271         {
00272             m_nOffset = m_oRequested.begin()->begin();
00273             m_nLength = m_oRequested.begin()->length();
00274             m_nPosition = 0;
00275         }
00276         m_oRequested.popFront();
00277         }
00278         
00279         if ( m_nLength < SIZE_UNKNOWN )
00280         {
00281                 if ( ! OpenFile() ) return FALSE;
00282                 
00283                 theApp.Message( MSG_DEBUG, IDS_UPLOAD_CONTENT,
00284                         m_nOffset, m_nOffset + m_nLength - 1,
00285                         (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress, _T("BT") );
00286                 
00287                 CBuffer* pBuffer = m_pClient->m_pOutput;
00288                 pBuffer->EnsureBuffer( sizeof(BT_PIECE_HEADER) + (DWORD)m_nLength );
00289                 
00290                 BT_PIECE_HEADER* pHeader = (BT_PIECE_HEADER*)( pBuffer->m_pBuffer + pBuffer->m_nLength );
00291                 
00292                 if ( ! m_pDiskFile->Read( m_nOffset + m_nPosition, &pHeader[1], m_nLength, &m_nLength ) ) return FALSE;
00293 
00294                 pHeader->nLength        = SWAP_LONG( 1 + 8 + (DWORD)m_nLength );
00295                 pHeader->nType          = BT_PACKET_PIECE;
00296                 pHeader->nPiece         = (DWORD)( m_nOffset / m_pDownload->m_pTorrent.m_nBlockSize );
00297                 pHeader->nOffset        = (DWORD)( m_nOffset % m_pDownload->m_pTorrent.m_nBlockSize );
00298                 pHeader->nPiece         = SWAP_LONG( pHeader->nPiece );
00299                 pHeader->nOffset        = SWAP_LONG( pHeader->nOffset );
00300                 
00301                 pBuffer->m_nLength += sizeof(BT_PIECE_HEADER) + (DWORD)m_nLength;
00302                 m_pClient->Send( NULL );
00303                 
00304                 m_nPosition += m_nLength;
00305                 m_nUploaded += m_nLength;
00306                 m_pDownload->m_nTorrentUploaded += m_nLength;
00307                 Statistics.Current.Uploads.Volume += ( m_nLength / 1024 );
00308                 
00309         m_oServed.pushBack( FF::SimpleFragment( m_nOffset, m_nOffset + m_nLength ) );
00310                 m_pBaseFile->AddFragment( m_nOffset, m_nLength );
00311 
00312                 m_nState        = upsUploading;
00313                 m_nLength       = SIZE_UNKNOWN;
00314         }
00315         else
00316         {
00317                 m_nState = upsRequest;
00318         }
00319         
00320         return TRUE;
00321 }
00322 

Generated on Thu Dec 15 10:39:50 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2