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

DownloadTransfer.cpp

Go to the documentation of this file.
00001 //
00002 // DownloadTransfer.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 "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Download.h"
00026 #include "Downloads.h"
00027 #include "DownloadSource.h"
00028 #include "DownloadTransfer.h"
00029 #include "FragmentedFile.h"
00030 #include "Network.h"
00031 #include "Buffer.h"
00032 #include "SHA.h"
00033 #include "ED2K.h"
00034 #include "SourceURL.h"
00035 #include "XML.h"
00036 #include "DownloadTransferBT.h"
00037 
00038 #ifdef _DEBUG
00039 #undef THIS_FILE
00040 static char THIS_FILE[]=__FILE__;
00041 #define new DEBUG_NEW
00042 #endif
00043 
00044 
00046 // CDownloadTransfer construction
00047 
00048 CDownloadTransfer::CDownloadTransfer(CDownloadSource* pSource, PROTOCOLID nProtocol)
00049 {
00050         m_nProtocol             = nProtocol;
00051         m_pDownload             = pSource->m_pDownload;
00052         m_pDlPrev               = NULL;
00053         m_pDlNext               = NULL;
00054         m_pSource               = pSource;
00055 
00056         m_nState                = dtsNull;
00057 
00058         m_nQueuePos             = 0;
00059         m_nQueueLen             = 0;
00060 
00061         m_nOffset               = SIZE_UNKNOWN;
00062         m_nLength               = 0;
00063         m_nPosition             = 0;
00064         m_nDownloaded   = 0;
00065 
00066         m_bWantBackwards = m_bRecvBackwards = FALSE;
00067 
00068         m_pDownload->AddTransfer( this );
00069 }
00070 
00071 CDownloadTransfer::~CDownloadTransfer()
00072 {
00073         ASSERT( m_pSource == NULL );
00074 }
00075 
00077 // CDownloadTransfer close
00078 
00079 void CDownloadTransfer::Close(TRISTATE bKeepSource)
00080 {
00081         SetState( dtsNull );
00082 
00083         CTransfer::Close();
00084 
00085         if ( m_pSource != NULL )
00086         {
00087                 switch ( bKeepSource )
00088                 {
00089                 case TS_TRUE:
00090                         m_pSource->OnFailure( TRUE );
00091                         break;
00092                 case TS_UNKNOWN:
00093                         m_pSource->OnFailure( FALSE );
00094                         break;
00095                 case TS_FALSE:
00096                         m_pSource->Remove( FALSE, TRUE );
00097                         break;
00098                 }
00099 
00100                 m_pSource = NULL;
00101         }
00102 
00103         ASSERT( m_pDownload != NULL );
00104         m_pDownload->RemoveTransfer( this );
00105 }
00106 
00108 // CDownloadTransfer speed controls
00109 
00110 void CDownloadTransfer::Boost()
00111 {
00112         m_mInput.pLimit = m_mOutput.pLimit = NULL;
00113 }
00114 
00115 DWORD CDownloadTransfer::GetAverageSpeed()
00116 {
00117         return GetMeasuredSpeed();
00118 }
00119 
00120 DWORD CDownloadTransfer::GetMeasuredSpeed()
00121 {
00122         Measure();
00123         return m_mInput.nMeasure;
00124 }
00125 
00127 // CDownloadTransfer state
00128 
00129 CString CDownloadTransfer::GetStateText(BOOL bLong)
00130 {
00131         CString str, strQ, strQueued, strOf;
00132 
00133         switch ( m_nState )
00134         {
00135         case dtsConnecting:
00136                 LoadString( str, IDS_STATUS_CONNECTING );
00137                 break;
00138         case dtsRequesting:
00139                 LoadString( str, IDS_STATUS_REQUESTING );
00140                 break;
00141         case dtsHeaders:
00142         case dtsFlushing:
00143                 LoadString( str, IDS_STATUS_RESPONSE );
00144                 break;
00145         case dtsDownloading:
00146                 LoadString( str, IDS_STATUS_DOWNLOADING );
00147                 break;
00148         case dtsTiger:
00149                 LoadString( str, IDS_STATUS_TIGERTREE );
00150                 break;
00151         case dtsHashset:
00152                 LoadString( str, IDS_STATUS_HASHSET );
00153                 break;
00154         case dtsMetadata:
00155                 LoadString( str, IDS_STATUS_METADATA );
00156                 break;
00157         case dtsBusy:
00158                 LoadString( str, IDS_STATUS_BUSY );
00159                 break;
00160         case dtsEnqueue:
00161                 LoadString( str, IDS_STATUS_ENQUEUE );
00162                 break;
00163         case dtsQueued:
00164                 LoadString( strQ, IDS_STATUS_Q );
00165                 LoadString( strQueued, IDS_STATUS_QUEUED );
00166                 LoadString( strOf, IDS_GENERAL_OF );
00167                 if ( ! bLong )
00168                 {
00169                         str.Format( m_nQueueLen ? _T("%s %i %s %i") : _T("%s #%i"),
00170                                 strQ, m_nQueuePos, strOf, m_nQueueLen );
00171                 }
00172                 else if ( m_sQueueName.GetLength() )
00173                 {
00174                         str.Format( _T("%s: %s: %i %s %i"), strQueued,
00175                                 (LPCTSTR)m_sQueueName, m_nQueuePos, strOf, m_nQueueLen );
00176                 }
00177                 else
00178                 {
00179                         str.Format( m_nQueueLen ? _T("%s: %i %s %i") : _T("%s: #%i"), strQueued,
00180                                 m_nQueuePos, strOf, m_nQueueLen );
00181                 }
00182                 break;
00183         default:
00184                 LoadString( str, IDS_STATUS_UNKNOWN );
00185                 break;
00186         }
00187 
00188         return str;
00189 }
00190 
00192 // CDownloadTransfer run handler
00193 
00194 BOOL CDownloadTransfer::OnRun()
00195 {
00196         return CTransfer::OnRun();
00197 }
00198 
00200 // CDownloadTransfer state management
00201 
00202 void CDownloadTransfer::SetState(int nState)
00203 {
00204         if ( m_pDownload != NULL )
00205         {
00206                 if ( Settings.Downloads.SortSources )
00207                 {       //Proper sort
00208 
00209                         static BYTE StateSortOrder[13]={ 13 ,12 ,10 ,4 ,0 ,4 ,1 ,2 ,3 ,12 ,8 ,6 ,9};
00210                                 //dtsNull, dtsConnecting, dtsRequesting, dtsHeaders, dtsDownloading, dtsFlushing,
00211                                 //dtsTiger, dtsHashset, dtsMetadata, dtsBusy, dtsEnqueue, dtsQueued, dtsTorrent
00212 
00213 
00214                         //Assemble the sort order DWORD
00215                         m_pSource->m_nSortOrder = StateSortOrder[ min( nState, 13 ) ];          //Get state sort order
00216 
00217                         if ( m_pSource->m_nSortOrder >= 13 )
00218                         {       //Don't bother wasting CPU sorting 'dead' sources- Simply send to bottom.
00219                                 m_pDownload->SortSource( m_pSource, FALSE );
00220                                 m_pSource->m_nSortOrder = -1;
00221                         }
00222                         else
00223                         {       //All other sources should be properly sorted
00224 
00225                                 if( ( nState == dtsTorrent ) && ( m_pSource->m_pTransfer ) )    //Torrent states
00226                                 {       //Choked torrents after queued, requesting = requesting, uninterested near end
00227                                         CDownloadTransferBT* pBT = (CDownloadTransferBT*)m_pSource->m_pTransfer;
00228                                         if ( ! pBT->m_bInterested ) m_pSource->m_nSortOrder = 11;
00229                                         else if ( pBT->m_bChoked ) m_pSource->m_nSortOrder = 7;
00230                                         else m_pSource->m_nSortOrder = 10;
00231                                 }
00232                                 m_pSource->m_nSortOrder <<=  8;                                                                 //Sort by state
00233 
00234                                 if ( m_nProtocol != PROTOCOL_HTTP )
00235                                         m_pSource->m_nSortOrder += ( m_nProtocol & 0xFF );
00236                                 m_pSource->m_nSortOrder <<=  16;                                                                //Then protocol
00237 
00238                                 if ( nState == dtsQueued )                                                                              //Then queue postion
00239                                         m_pSource->m_nSortOrder += ( min( m_nQueuePos, 10000 ) & 0xFFFF );
00240                                 else                                                                                                                    // or IP
00241                                         m_pSource->m_nSortOrder += ( ( m_pSource->m_pAddress.S_un.S_un_b.s_b1 << 8 ) |
00242                                                                                                  ( m_pSource->m_pAddress.S_un.S_un_b.s_b2      ) );
00243 
00244                                 //Do the sort
00245                                 m_pDownload->SortSource( m_pSource );
00246                         }
00247                 }
00248                 else
00249                 {       //Simple sort.
00250                         if ( nState == dtsDownloading && m_nState != dtsDownloading )
00251                         {        //Downloading sources go to the top
00252                                 m_pDownload->SortSource( m_pSource, TRUE );
00253                         }
00254                         else if ( nState != dtsDownloading && m_nState == dtsDownloading )
00255                         {       //Sources that have stopped downloading go to the bottom.
00256                                 m_pDownload->SortSource( m_pSource, FALSE );
00257                         }
00258                 }
00259         }
00260 
00261         m_nState = nState;
00262 }
00263 
00265 // CDownloadTransfer fragment size management
00266 
00267 void CDownloadTransfer::ChunkifyRequest(QWORD* pnOffset, QWORD* pnLength, QWORD nChunk, BOOL bVerifyLock)
00268 {
00269         ASSERT( pnOffset != NULL && pnLength != NULL );
00270 
00271         if ( m_pSource->m_bCloseConn ) return;
00272 
00273         nChunk = min( nChunk, (QWORD)Settings.Downloads.ChunkSize );
00274 
00275         if ( bVerifyLock )
00276         {
00277                 if ( QWORD nVerify = m_pDownload->GetVerifyLength() )
00278                 {
00279                         nVerify = nVerify * 3 / 2;
00280                         nChunk = max( nChunk, nVerify );
00281                 }
00282 
00283                 if ( Settings.Downloads.ChunkStrap > 0 && m_nDownloaded == 0 )
00284                 {
00285                         nChunk = Settings.Downloads.ChunkStrap;
00286                 }
00287         }
00288 
00289         if ( nChunk == 0 || *pnLength <= nChunk ) return;
00290 
00291         if ( m_pDownload->GetVolumeComplete() == 0 || *pnOffset == 0 )
00292         {
00293                 *pnLength = nChunk;
00294         }
00295         else if ( m_bWantBackwards )
00296         {
00297                 *pnOffset = *pnOffset + *pnLength - nChunk;
00298                 *pnLength = nChunk;
00299         }
00300         else
00301         {
00302                 QWORD nCount = *pnLength / nChunk;
00303                 if ( *pnLength % nChunk ) nCount++;
00304                 nCount = rand() % nCount;
00305 
00306                 QWORD nStart = *pnOffset + nChunk * nCount;
00307                 *pnLength = min( nChunk, *pnOffset + *pnLength - nStart );
00308                 *pnOffset = nStart;
00309         }
00310 }

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