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 "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
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
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
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
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
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
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
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
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
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;
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
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 ) &&
00298 m_pQueue->m_bRotate && m_pQueue->IsActive( this ) && ! m_bStopTransfer )
00299 {
00300 DWORD tRotationLength = m_pQueue->m_nRotateTime * 1000;
00301
00302
00303 if ( ( m_pQueue->m_bRewardUploaders ) && ( m_nUserRating == urCredit ) )
00304 tRotationLength <<= 1;
00305
00306 pLock.Unlock();
00307
00308 if ( m_tRotateTime == 0 )
00309 {
00310 if ( m_nState == upsUploading ) m_tRotateTime = tNow;
00311 }
00312 else if ( tNow - m_tRotateTime >= tRotationLength )
00313 {
00314 m_bStopTransfer = TRUE;
00315 }
00316 }
00317 else
00318 {
00319 m_tRotateTime = 0;
00320 }
00321 }
00322
00324
00325
00326 void CUploadTransfer::CalculateRating(DWORD tNow)
00327 {
00328 if ( tNow > m_tRatingTime + 15000 )
00329 {
00330 QWORD nDownloaded = Downloads.GetAmountDownloadedFrom( &(m_pHost.sin_addr) );
00331 m_tRatingTime = tNow;
00332 if ( nDownloaded > 128 * 1024)
00333 {
00334 if ( nDownloaded > m_nUploaded )
00335 m_nUserRating = urCredit;
00336 else
00337 m_nUserRating = urSharing;
00338 }
00339 else
00340 {
00341 if ( m_nUploaded < 4*1024*1024 )
00342 m_nUserRating = urNew;
00343 else
00344 m_nUserRating = urNotSharing;
00345 }
00346 }
00347
00348
00349 }
00350
00352
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
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
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 }