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

UploadTransfer.cpp

Go to the documentation of this file.
00001 //
00002 // UploadTransfer.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 "Uploads.h"
00026 #include "UploadFile.h"
00027 #include "UploadFiles.h"
00028 #include "UploadQueue.h"
00029 #include "UploadQueues.h"
00030 #include "TransferFile.h"
00031 #include "UploadTransfer.h"
00032 #include "UploadTransferHTTP.h"
00033 
00034 #include "SharedFile.h"
00035 #include "Download.h"
00036 #include "Downloads.h"
00037 
00038 #include "TigerTree.h"
00039 #include "SHA.h"
00040 #include "ED2K.h"
00041 
00042 #ifdef _DEBUG
00043 #undef THIS_FILE
00044 static char THIS_FILE[]=__FILE__;
00045 #define new DEBUG_NEW
00046 #endif
00047 
00048 
00050 // CUploadTransfer construction
00051 
00052 CUploadTransfer::CUploadTransfer(PROTOCOLID nProtocol)
00053 {
00054         ClearRequest();
00055 
00056         m_nProtocol             = nProtocol;
00057         m_nState                = upsNull;
00058         m_pQueue                = NULL;
00059         m_pBaseFile             = NULL;
00060         m_pDiskFile             = NULL;
00061         m_nBandwidth    = Settings.Bandwidth.Request;
00062 
00063         m_bLive                 = TRUE;
00064         m_nRequests             = 0;
00065         m_nUploaded             = 0;
00066         m_nUserRating   = urNew;
00067         m_bClientExtended= FALSE;
00068 
00069         m_bStopTransfer = FALSE;
00070         m_tRotateTime   = 0;
00071         m_tAverageTime  = 0;
00072         m_nAveragePos   = 0;
00073         ZeroMemory( m_nAverageRate, sizeof(m_nAverageRate) );
00074         m_tRatingTime   = 0;
00075 
00076         Uploads.Add( this );
00077 }
00078 
00079 CUploadTransfer::~CUploadTransfer()
00080 {
00081         Close( FALSE );
00082         UploadFiles.Remove( this );
00083         Uploads.Remove( this );
00084 }
00085 
00087 // CUploadTransfer remove record
00088 
00089 void CUploadTransfer::Remove(BOOL bMessage)
00090 {
00091         ASSERT( this != NULL );
00092 
00093         if ( bMessage && m_sFileName.GetLength() > 0 )
00094         {
00095                 theApp.Message( MSG_SYSTEM, IDS_UPLOAD_REMOVE,
00096                         (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
00097         }
00098 
00099         m_nUploaded = 1;
00100         Close( FALSE );
00101 
00102         delete this;
00103 }
00104 
00106 // CUploadTransfer close connection
00107 
00108 void CUploadTransfer::Close(BOOL bMessage)
00109 {
00110         if ( m_nState == upsNull ) return;
00111         m_nState = upsNull;
00112 
00113         CTransfer::Close();
00114         UploadQueues.Dequeue( this );
00115         CloseFile();
00116 
00117         if ( bMessage ) theApp.Message( MSG_SYSTEM, IDS_UPLOAD_DROPPED, (LPCTSTR)m_sAddress );
00118         if ( m_nUploaded == 0 ) Remove( FALSE );
00119 }
00120 
00122 // CUploadTransfer promotion
00123 
00124 BOOL CUploadTransfer::Promote()
00125 {
00126         if ( m_nState != upsQueued ) return FALSE;
00127         UploadQueues.Dequeue( this );
00128         return UploadQueues.Enqueue( this, true );
00129 }
00130 
00132 // CUploadTransfer rename handler
00133 
00134 BOOL CUploadTransfer::OnRename(LPCTSTR pszSource, LPCTSTR pszTarget)
00135 {
00136         if ( m_nState != upsUploading || _tcsicmp( m_sFilePath, pszSource ) ) return FALSE;
00137 
00138         if ( pszTarget == NULL )
00139         {
00140                 theApp.Message( MSG_ERROR, IDS_UPLOAD_DELETED, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
00141                 Close();
00142                 return TRUE;
00143         }
00144 
00145         if ( pszTarget == (LPCTSTR)1 )
00146         {
00147                 if ( m_pDiskFile != NULL )
00148                 {
00149                         m_pDiskFile->Release( FALSE );
00150                         m_pDiskFile = NULL;
00151                 }
00152         }
00153         else if ( m_pDiskFile == NULL )
00154         {
00155                 m_sFilePath = pszTarget;
00156                 m_pDiskFile = TransferFiles.Open( m_sFilePath, FALSE, FALSE );
00157 
00158                 if ( m_pDiskFile == NULL )
00159                 {
00160                         theApp.Message( MSG_ERROR, IDS_UPLOAD_DELETED, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
00161                         Close();
00162                 }
00163         }
00164 
00165         return TRUE;
00166 }
00167 
00169 // CUploadTransfer statistics
00170 
00171 float CUploadTransfer::GetProgress()
00172 {
00173         if ( m_nState != upsUploading || m_nLength == 0 || m_nLength == SIZE_UNKNOWN ) return 0;
00174         return (float)m_nPosition / (float)m_nLength;
00175 }
00176 
00177 DWORD CUploadTransfer::GetAverageSpeed()
00178 {
00179         if ( m_nState != upsUploading || m_nLength == 0 || m_nLength == SIZE_UNKNOWN ) return GetMeasuredSpeed();
00180         DWORD nTime = ( GetTickCount() - m_tContent ) / 1000;
00181         return nTime ? (DWORD)( m_nPosition / nTime ) : 0;
00182 }
00183 
00184 DWORD CUploadTransfer::GetMeasuredSpeed()
00185 {
00186         Measure();
00187         return m_mOutput.nMeasure;
00188 }
00189 
00190 void CUploadTransfer::SetSpeedLimit(DWORD nLimit)
00191 {
00192         ZeroMemory( m_nAverageRate, sizeof(DWORD) * ULA_SLOTS );
00193         m_nBandwidth    = nLimit;
00194         m_tAverageTime  = 0;
00195         m_nAveragePos   = 0;
00196 }
00197 
00199 // CUploadTransfer run handler
00200 
00201 BOOL CUploadTransfer::OnRun()
00202 {
00203         DWORD tNow = GetTickCount();
00204 
00205         LongTermAverage( tNow );
00206         RotatingQueue( tNow );
00207         CalculateRating( tNow );
00208         return CTransfer::OnRun();
00209 }
00210 
00212 // CUploadTransfer read and write handlers
00213 
00214 BOOL CUploadTransfer::OnRead()
00215 {
00216         DWORD tLastRead = m_mInput.tLast;
00217 
00218         if ( ! CTransfer::OnRead() ) return FALSE;
00219 
00220         if ( m_mInput.tLast != tLastRead && ! m_bLive )
00221         {
00222                 m_bLive = TRUE;
00223                 Uploads.EnforcePerHostLimit( this );
00224         }
00225 
00226         return TRUE;
00227 }
00228 
00229 BOOL CUploadTransfer::OnWrite()
00230 {
00231         DWORD tLastSend = m_mOutput.tLast;
00232 
00233         if ( ! CTransfer::OnWrite() ) return FALSE;
00234 
00235         if ( m_mOutput.tLast != tLastSend && ! m_bLive )
00236         {
00237                 m_bLive = TRUE;
00238                 Uploads.EnforcePerHostLimit( this );
00239         }
00240 
00241         return TRUE;
00242 }
00243 
00245 // CUploadTransfer long term averaging
00246 
00247 void CUploadTransfer::LongTermAverage(DWORD tNow)
00248 {
00249         if ( m_nState != upsUploading || m_nLength == 0 || m_nLength == SIZE_UNKNOWN ) return;
00250 
00251         DWORD nSpeed = GetMeasuredSpeed();
00252 
00253         if ( Settings.Live.BandwidthScale < 100 )
00254         {
00255                 nSpeed = nSpeed * 100 / max( DWORD(1), Settings.Live.BandwidthScale );
00256         }
00257 
00258         m_nAverageRate[ m_nAveragePos ] = max( m_nAverageRate[ m_nAveragePos ], nSpeed );
00259 
00260         if ( tNow - m_tAverageTime < 2000 || m_nAverageRate[ m_nAveragePos ] == 0 ) return;
00261 
00262         m_tAverageTime = tNow;
00263         m_nAveragePos = ( m_nAveragePos + 1 ) % ULA_SLOTS;
00264 
00265         DWORD nAverage = 0;
00266 
00267         for ( int nPos = 0 ; nPos < ULA_SLOTS ; nPos++ )
00268         {
00269                 if ( m_nAverageRate[ nPos ] == 0 ) return;
00270                 nAverage += m_nAverageRate[ nPos ];
00271         }
00272 
00273         m_nAverageRate[ m_nAveragePos ] = 0;
00274         nAverage = nAverage / ULA_SLOTS * 9 / 8;
00275         nAverage = max( nAverage, Settings.Uploads.ClampdownFloor );
00276 
00277         if ( nAverage < m_nBandwidth * ( 100 - Settings.Uploads.ClampdownFactor ) / 100 )
00278         {
00279                 DWORD nOld = m_nBandwidth;      // Save
00280 
00281                 m_nBandwidth = min( nAverage, m_nBandwidth );
00282 
00283                 theApp.Message( MSG_DEBUG, _T("Changing upload throttle on %s from %s to %s"),
00284                         (LPCTSTR)m_sAddress,
00285                         (LPCTSTR)Settings.SmartVolume( nOld * 8, FALSE, TRUE ),
00286                         (LPCTSTR)Settings.SmartVolume( m_nBandwidth * 8, FALSE, TRUE ) );
00287         }
00288 }
00289 
00291 // CUploadTransfer rotating queue
00292 
00293 void CUploadTransfer::RotatingQueue(DWORD tNow)
00294 {
00295         CSingleLock pLock( &UploadQueues.m_pSection, TRUE );
00296 
00297         if ( m_pQueue != NULL && UploadQueues.Check( m_pQueue ) &&      //Is this queue able to rotate?
00298                  m_pQueue->m_bRotate && m_pQueue->IsActive( this ) && ! m_bStopTransfer )
00299         {
00300                 DWORD tRotationLength = m_pQueue->m_nRotateTime * 1000;
00301 
00302                 // High ranked users can get a longer rotate time
00303                 if ( ( m_pQueue->m_bRewardUploaders ) && ( m_nUserRating == urCredit ) )
00304                         tRotationLength <<= 1;
00305 
00306                 pLock.Unlock();
00307 
00308                 if ( m_tRotateTime == 0 )                                                                       //If the upload hasn't started yet
00309                 {
00310                         if ( m_nState == upsUploading ) m_tRotateTime = tNow;   //Set the upload as having started
00311                 }
00312                 else if ( tNow - m_tRotateTime >= tRotationLength )                     //Otherwise check if it should rotate
00313                 {
00314                         m_bStopTransfer = TRUE;
00315                 }
00316         }
00317         else
00318         {
00319                 m_tRotateTime = 0;
00320         }
00321 }
00322 
00324 // CUploadTransfer calculate rating
00325 
00326 void CUploadTransfer::CalculateRating(DWORD tNow)
00327 {       //calculate a download rating for this transfer / user
00328         if ( tNow > m_tRatingTime + 15000 ) //Recalculate rating every 15 seconds
00329         {
00330                 QWORD nDownloaded = Downloads.GetAmountDownloadedFrom( &(m_pHost.sin_addr) );
00331                 m_tRatingTime = tNow;
00332                 if ( nDownloaded > 128 * 1024)  //They have uploaded to us. (Transfers < 128k are ignored)
00333                 {
00334                         if ( nDownloaded > m_nUploaded ) //If they have sent more to us than we have to them
00335                                 m_nUserRating = urCredit;                       //They get the highest rating
00336                         else
00337                                 m_nUserRating = urSharing;                      //Otherwise, #2. (still known sharer)
00338                 }
00339                 else                                                    //They have not uploaded to us.
00340                 {
00341                         if ( m_nUploaded < 4*1024*1024 ) //If they have not gotten at least 4MB
00342                                 m_nUserRating = urNew;                  //They are a new user- give uncertain rating
00343                         else
00344                                 m_nUserRating = urNotSharing;   //Else, probably not uploading to us.
00345                 }
00346         }
00347 
00348         //ToDo: Maybe add a 'remote client' class to retain transfer stats for an hour or so?
00349 }
00350 
00352 // CUploadTransfer hash utilities
00353 
00354 void CUploadTransfer::ClearHashes()
00355 {
00356         m_bSHA1 = m_bTiger = m_bED2K = FALSE;
00357 }
00358 
00359 BOOL CUploadTransfer::HashesFromURN(LPCTSTR pszURN)
00360 {
00361         m_bSHA1         |= CSHA::HashFromURN( pszURN, &m_pSHA1 );
00362         m_bTiger        |= CTigerNode::HashFromURN( pszURN, &m_pTiger );
00363         m_bED2K         |= CED2K::HashFromURN( pszURN, &m_pED2K );
00364         return TRUE;
00365 }
00366 
00368 // CUploadTransfer request utilities
00369 
00370 void CUploadTransfer::ClearRequest()
00371 {
00372         m_sFileName.Empty();
00373         m_sFilePath.Empty();
00374         m_sFileTags.Empty();
00375 
00376         m_nFileBase             = 0;
00377         m_nFileSize             = 0;
00378         m_bFilePartial  = FALSE;
00379 
00380         m_nOffset               = 0;
00381         m_nLength               = SIZE_UNKNOWN;
00382         m_nPosition             = 0;
00383         m_nRequests ++;
00384 
00385         ClearHashes();
00386         ClearHeaders();
00387 }
00388 
00389 BOOL CUploadTransfer::RequestComplete(CLibraryFile* pFile)
00390 {
00391         ASSERT( pFile != NULL );
00392 
00393         if ( m_bSHA1 && pFile->m_bSHA1 && m_pSHA1 != pFile->m_pSHA1 ) return FALSE;
00394         if ( m_bTiger && pFile->m_bTiger && m_pTiger != pFile->m_pTiger ) return FALSE;
00395         if ( m_bED2K && pFile->m_bED2K && m_pED2K != pFile->m_pED2K ) return FALSE;
00396 
00397         m_sFileName     = pFile->m_sName;
00398         m_sFilePath     = pFile->GetPath();
00399         m_nFileBase     = pFile->m_nVirtualSize > 0 ? pFile->m_nVirtualBase : 0;
00400         m_nFileSize     = pFile->m_nVirtualSize > 0 ? pFile->m_nVirtualSize : pFile->m_nSize;
00401         m_sFileTags     = pFile->m_sShareTags;
00402         m_bFilePartial = FALSE;
00403 
00404         if ( m_bSHA1 = pFile->m_bSHA1 ) m_pSHA1 = pFile->m_pSHA1;
00405         if ( m_bTiger = pFile->m_bTiger ) m_pTiger = pFile->m_pTiger;
00406         if ( m_bED2K = pFile->m_bED2K ) m_pED2K = pFile->m_pED2K;
00407 
00408         return TRUE;
00409 }
00410 
00411 BOOL CUploadTransfer::RequestPartial(CDownload* pFile)
00412 {
00413         ASSERT( pFile != NULL );
00414 
00415         if ( m_bSHA1 && pFile->m_bSHA1 && m_pSHA1 != pFile->m_pSHA1 ) return FALSE;
00416         if ( m_bTiger && pFile->m_bTiger && m_pTiger != pFile->m_pTiger ) return FALSE;
00417         if ( m_bED2K && pFile->m_bED2K && m_pED2K != pFile->m_pED2K ) return FALSE;
00418 
00419         m_sFileName     = pFile->m_sRemoteName;
00420         m_sFilePath     = pFile->m_sLocalName;
00421         m_nFileBase     = 0;
00422         m_nFileSize     = pFile->m_nSize;
00423         m_bFilePartial = TRUE;
00424         m_sFileTags.Empty();
00425 
00426         if ( m_bSHA1 && ! pFile->m_bSHA1 )
00427         {
00428                 pFile->m_bSHA1 = TRUE;
00429                 pFile->m_pSHA1 = m_pSHA1;
00430         }
00431         else if ( m_bSHA1 = pFile->m_bSHA1 )
00432         {
00433                 m_pSHA1 = pFile->m_pSHA1;
00434         }
00435 
00436         if ( m_bTiger && ! pFile->m_bTiger )
00437         {
00438                 pFile->m_bTiger = TRUE;
00439                 pFile->m_pTiger = m_pTiger;
00440         }
00441         else if ( m_bTiger = pFile->m_bTiger )
00442         {
00443                 m_pTiger = pFile->m_pTiger;
00444         }
00445 
00446         if ( m_bED2K && ! pFile->m_bED2K )
00447         {
00448                 pFile->m_bED2K = TRUE;
00449                 pFile->m_pED2K = m_pED2K;
00450         }
00451         else if ( m_bED2K = pFile->m_bED2K )
00452         {
00453                 m_pED2K = pFile->m_pED2K;
00454         }
00455 
00456         return TRUE;
00457 }
00458 
00460 // CUploadTransfer file utilities
00461 
00462 void CUploadTransfer::StartSending(int nState)
00463 {
00464         m_nState        = nState;
00465         m_nPosition     = 0;
00466         m_tContent      = m_mOutput.tLast = GetTickCount();
00467         CTransfer::OnWrite();
00468 }
00469 
00470 void CUploadTransfer::AllocateBaseFile()
00471 {
00472         m_pBaseFile =   UploadFiles.GetFile( this, m_bSHA1 ? &m_pSHA1 : NULL,
00473                                         m_sFileName, m_sFilePath, m_nFileSize );
00474 }
00475 
00476 void CUploadTransfer::CloseFile()
00477 {
00478         if ( m_pDiskFile != NULL )
00479         {
00480                 m_pDiskFile->Release( FALSE );
00481                 m_pDiskFile = NULL;
00482         }
00483 }

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