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 "Downloads.h"
00026 #include "Download.h"
00027 #include "Transfers.h"
00028 #include "Transfer.h"
00029 #include "DownloadGroups.h"
00030 #include "DownloadTransfer.h"
00031 #include "DownloadTransferED2K.h"
00032 #include "DownloadTransferBT.h"
00033 #include "UploadQueues.h"
00034
00035 #include "Buffer.h"
00036 #include "EDClient.h"
00037 #include "QueryHit.h"
00038 #include "MatchObjects.h"
00039 #include "ShareazaURL.h"
00040
00041 #include "SHA.h"
00042 #include "ED2K.h"
00043 #include "TigerTree.h"
00044
00045 #include "WndMain.h"
00046
00047 #ifdef _DEBUG
00048 #undef THIS_FILE
00049 static char THIS_FILE[]=__FILE__;
00050 #define new DEBUG_NEW
00051 #endif
00052
00053 CDownloads Downloads;
00054
00055
00057
00058
00059 CDownloads::CDownloads()
00060 {
00061 m_nLimitGeneric = Settings.Bandwidth.Downloads;
00062 m_nLimitDonkey = Settings.Bandwidth.Downloads;
00063 m_nTransfers = 0;
00064 m_nBandwidth = 0;
00065 m_nRunCookie = 0;
00066 m_bClosing = FALSE;
00067 m_tLastConnect = 0;
00068 }
00069
00070 CDownloads::~CDownloads()
00071 {
00072 }
00073
00075
00076
00077 CDownload* CDownloads::Add()
00078 {
00079 CDownload* pDownload = new CDownload();
00080 m_pList.AddTail( pDownload );
00081 return pDownload;
00082 }
00083
00085
00086
00087 CDownload* CDownloads::Add(CQueryHit* pHit, BOOL bAddToHead)
00088 {
00089 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00090
00091 CDownload* pDownload = NULL;
00092
00093 if ( pDownload == NULL && pHit->m_bSHA1 )
00094 pDownload = FindBySHA1( &pHit->m_pSHA1 );
00095 if ( pDownload == NULL && pHit->m_bTiger )
00096 pDownload = FindByTiger( &pHit->m_pTiger );
00097 if ( pDownload == NULL && pHit->m_bED2K )
00098 pDownload = FindByED2K( &pHit->m_pED2K );
00099
00100 if ( pDownload != NULL )
00101 {
00102 theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ALREADY, (LPCTSTR)pHit->m_sName );
00103
00104 pDownload->AddSourceHit( pHit );
00105 pDownload->Resume();
00106 }
00107 else
00108 {
00109 pDownload = new CDownload();
00110 pDownload->AddSourceHit( pHit, TRUE );
00111
00112 if ( bAddToHead ) m_pList.AddHead( pDownload );
00113 else m_pList.AddTail( pDownload );
00114
00115 theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ADDED,
00116 (LPCTSTR)pDownload->GetDisplayName(), pDownload->GetSourceCount() );
00117
00118 if( pDownload->m_bSHA1 ) pDownload->m_bSHA1Trusted = TRUE;
00119 else if( pDownload->m_bED2K ) pDownload->m_bED2KTrusted = TRUE;
00120 }
00121
00122 pHit->m_bDownload = TRUE;
00123
00124 DownloadGroups.Link( pDownload );
00125 Transfers.StartThread();
00126
00127 if ( ( (pDownload->GetSourceCount() == 0 ) || ( pDownload->m_bED2K && ! pDownload->m_bSHA1 ) )
00128 &&( (GetTryingCount() < Settings.Downloads.MaxFiles ) || ( bAddToHead ) ) )
00129 {
00130 pDownload->SetStartTimer();
00131 }
00132
00133
00134 return pDownload;
00135 }
00136
00137 CDownload* CDownloads::Add(CMatchFile* pFile, BOOL bAddToHead)
00138 {
00139 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00140
00141 CDownload* pDownload = NULL;
00142
00143 if ( pDownload == NULL && pFile->m_bSHA1 )
00144 pDownload = FindBySHA1( &pFile->m_pSHA1 );
00145 if ( pDownload == NULL && pFile->m_bTiger )
00146 pDownload = FindByTiger( &pFile->m_pTiger );
00147 if ( pDownload == NULL && pFile->m_bED2K )
00148 pDownload = FindByED2K( &pFile->m_pED2K );
00149
00150 if ( pDownload != NULL )
00151 {
00152 theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ALREADY, (LPCTSTR)pFile->m_pHits->m_sName );
00153
00154 for ( CQueryHit* pHit = pFile->m_pHits ; pHit ; pHit = pHit->m_pNext )
00155 {
00156 pDownload->AddSourceHit( pHit );
00157
00158
00159 if ( pHit->m_nRating || ! pHit->m_sComments.IsEmpty() )
00160 {
00161 pDownload->AddReview( &pHit->m_pAddress, 2, pHit->m_nRating, pHit->m_sNick, pHit->m_sComments );
00162 }
00163 }
00164
00165 pDownload->Resume();
00166 }
00167 else
00168 {
00169 pDownload = new CDownload();
00170 if ( bAddToHead ) m_pList.AddHead( pDownload );
00171 else m_pList.AddTail( pDownload );
00172
00173 if ( pFile->m_pBest != NULL )
00174 {
00175 pDownload->AddSourceHit( pFile->m_pBest, TRUE );
00176 }
00177
00178 for ( CQueryHit* pHit = pFile->m_pHits ; pHit ; pHit = pHit->m_pNext )
00179 {
00180 if ( pHit != pFile->m_pBest )
00181 {
00182 pDownload->AddSourceHit( pHit, TRUE );
00183 }
00184
00185
00186 if ( pHit->m_nRating || ! pHit->m_sComments.IsEmpty() )
00187 {
00188 pDownload->AddReview( &pHit->m_pAddress, 2, pHit->m_nRating, pHit->m_sNick, pHit->m_sComments );
00189 }
00190 }
00191
00192 theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ADDED,
00193 (LPCTSTR)pDownload->GetDisplayName(), pDownload->GetSourceCount() );
00194
00195 if( pDownload->m_bSHA1 ) pDownload->m_bSHA1Trusted = TRUE;
00196 else if( pDownload->m_bED2K ) pDownload->m_bED2KTrusted = TRUE;
00197 }
00198
00199 pFile->m_bDownload = TRUE;
00200
00201 DownloadGroups.Link( pDownload );
00202 Transfers.StartThread();
00203
00204 if ( ( (pDownload->GetSourceCount() == 0 ) ||
00205 ( pDownload->m_bED2K && ! pDownload->m_bSHA1 )) &&
00206 (GetTryingCount() < Settings.Downloads.MaxFiles ) )
00207 {
00208 pDownload->FindMoreSources();
00209 pDownload->SetStartTimer();
00210 }
00211
00212 return pDownload;
00213 }
00214
00216
00217
00218 CDownload* CDownloads::Add(CShareazaURL* pURL)
00219 {
00220 if ( pURL->m_nAction != CShareazaURL::uriDownload &&
00221 pURL->m_nAction != CShareazaURL::uriSource ) return NULL;
00222
00223 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00224 CDownload* pDownload = NULL;
00225
00226 if ( pDownload == NULL && pURL->m_bSHA1 )
00227 pDownload = FindBySHA1( &pURL->m_pSHA1 );
00228 if ( pDownload == NULL && pURL->m_bTiger )
00229 pDownload = FindByTiger( &pURL->m_pTiger );
00230 if ( pDownload == NULL && pURL->m_bED2K )
00231 pDownload = FindByED2K( &pURL->m_pED2K );
00232 if ( pDownload == NULL && pURL->m_bBTH )
00233 pDownload = FindByBTH( &pURL->m_pBTH );
00234
00235 if ( pDownload != NULL )
00236 {
00237 theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ALREADY,
00238 (LPCTSTR)pDownload->GetDisplayName() );
00239
00240 if ( pURL->m_sURL.GetLength() ) pDownload->AddSourceURLs( pURL->m_sURL, FALSE );
00241
00242 return pDownload;
00243 }
00244
00245 pDownload = new CDownload();
00246
00247 if ( pURL->m_bSHA1 )
00248 {
00249 pDownload->m_bSHA1 = TRUE;
00250 pDownload->m_pSHA1 = pURL->m_pSHA1;
00251 pDownload->m_bSHA1Trusted = TRUE;
00252 }
00253 if ( pURL->m_bTiger )
00254 {
00255 pDownload->m_bTiger = TRUE;
00256 pDownload->m_pTiger = pURL->m_pTiger;
00257 pDownload->m_bTigerTrusted = TRUE;
00258 }
00259 if ( pURL->m_bMD5 )
00260 {
00261 pDownload->m_bMD5 = TRUE;
00262 pDownload->m_pMD5 = pURL->m_pMD5;
00263 pDownload->m_bMD5Trusted = TRUE;
00264 }
00265 if ( pURL->m_bED2K )
00266 {
00267 pDownload->m_bED2K = TRUE;
00268 pDownload->m_pED2K = pURL->m_pED2K;
00269 pDownload->m_bED2KTrusted = TRUE;
00270 pDownload->Share( TRUE );
00271 }
00272 if ( pURL->m_bBTH )
00273 {
00274 pDownload->m_bBTH = TRUE;
00275 pDownload->m_pBTH = pURL->m_pBTH;
00276 pDownload->m_bBTHTrusted = TRUE;
00277 pDownload->Share( TRUE );
00278 }
00279
00280 if ( pURL->m_sName.GetLength() )
00281 {
00282 pDownload->m_sRemoteName = pURL->m_sName;
00283 }
00284
00285 if ( pURL->m_bSize )
00286 {
00287 pDownload->m_nSize = pURL->m_nSize;
00288 }
00289
00290 if ( pURL->m_sURL.GetLength() )
00291 {
00292 if ( ! pDownload->AddSourceURLs( pURL->m_sURL, FALSE ) )
00293 {
00294 if ( pURL->m_nAction == CShareazaURL::uriSource )
00295 {
00296 delete pDownload;
00297 return NULL;
00298 }
00299 }
00300 }
00301
00302 pDownload->SetTorrent( pURL->m_pTorrent );
00303
00304 m_pList.AddTail( pDownload );
00305
00306 theApp.Message( MSG_DOWNLOAD, IDS_DOWNLOAD_ADDED,
00307 (LPCTSTR)pDownload->GetDisplayName(), pDownload->GetSourceCount() );
00308
00309 if( ( pDownload->m_bBTH && ( GetTryingCount(TRUE) < Settings.BitTorrent.DownloadTorrents ) ) ||
00310 ( !pDownload->m_bBTH && ( GetTryingCount(FALSE) < Settings.Downloads.MaxFiles ) ) )
00311 {
00312 pDownload->SetStartTimer();
00313 if ( pURL->m_nAction != CShareazaURL::uriSource )
00314 pDownload->FindMoreSources();
00315 }
00316
00317 DownloadGroups.Link( pDownload );
00318 Transfers.StartThread();
00319
00320 return pDownload;
00321 }
00322
00324
00325
00326 void CDownloads::PauseAll()
00327 {
00328 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00329
00330 for ( POSITION pos = GetIterator() ; pos ; )
00331 {
00332 GetNext( pos )->Pause();
00333 }
00334 }
00335
00336 void CDownloads::ClearCompleted()
00337 {
00338 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00339
00340 for ( POSITION pos = GetIterator() ; pos ; )
00341 {
00342 CDownload* pDownload = GetNext( pos );
00343 if ( ( pDownload->IsCompleted() ) && ( !pDownload->IsSeeding() ) ) pDownload->Remove();
00344 }
00345 }
00346
00347 void CDownloads::ClearPaused()
00348 {
00349 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00350
00351 for ( POSITION pos = GetIterator() ; pos ; )
00352 {
00353 CDownload* pDownload = GetNext( pos );
00354 if ( pDownload->IsPaused() ) pDownload->Remove();
00355 }
00356 }
00357
00358 void CDownloads::Clear(BOOL bShutdown)
00359 {
00360 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00361 m_bClosing = TRUE;
00362
00363 for ( POSITION pos = GetIterator() ; pos ; )
00364 {
00365 Remove( GetNext( pos ) );
00366 }
00367
00368 m_pList.RemoveAll();
00369 m_bClosing = bShutdown;
00370 }
00371
00372 void CDownloads::CloseTransfers()
00373 {
00374 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00375
00376 m_bClosing = TRUE;
00377
00378 for ( POSITION pos = GetIterator() ; pos ; )
00379 {
00380 GetNext( pos )->CloseTransfers();
00381 }
00382
00383 m_bClosing = FALSE;
00384 m_nTransfers = 0;
00385 m_nBandwidth = 0;
00386 }
00387
00389
00390
00391 int CDownloads::GetSeedCount() const
00392 {
00393 int nCount = 0;
00394
00395 for ( POSITION pos = GetIterator() ; pos ; )
00396 {
00397 CDownload* pDownload = GetNext( pos );
00398
00399 if ( pDownload->IsSeeding() )
00400 nCount++;
00401 else if ( pDownload->IsCompleted() && pDownload->m_bBTH && pDownload->IsFullyVerified() )
00402 nCount++;
00403 }
00404
00405 return nCount;
00406 }
00407
00408 int CDownloads::GetActiveTorrentCount() const
00409 {
00410 int nCount = 0;
00411
00412 for ( POSITION pos = GetIterator() ; pos ; )
00413 {
00414 CDownload* pDownload = GetNext( pos );
00415
00416 if ( pDownload->IsDownloading() && pDownload->m_bBTH &&
00417 ! pDownload->IsSeeding() && ! pDownload->IsCompleted() &&
00418 ! pDownload->IsMoving() && ! pDownload->IsPaused() )
00419 nCount++;
00420 }
00421
00422 return nCount;
00423 }
00424
00425 int CDownloads::GetCount(BOOL bActiveOnly) const
00426 {
00427 if ( ! bActiveOnly ) return m_pList.GetCount();
00428
00429 int nCount = 0;
00430
00431 for ( POSITION pos = GetIterator() ; pos ; )
00432 {
00433 CDownload* pDownload = GetNext( pos );
00434
00435 if ( ! pDownload->IsMoving() && ! pDownload->IsPaused() &&
00436 pDownload->GetSourceCount( TRUE ) > 0 )
00437 nCount++;
00438 }
00439
00440 return nCount;
00441 }
00442
00443 int CDownloads::GetTransferCount() const
00444 {
00445 int nCount = 0;
00446
00447 for ( POSITION pos = GetIterator() ; pos ; )
00448 {
00449 nCount += GetNext( pos )->GetTransferCount();
00450 }
00451
00452 return nCount;
00453 }
00454
00455 int CDownloads::GetTryingCount(BOOL bTorrentsOnly) const
00456 {
00457 int nCount = 0;
00458
00459 for ( POSITION pos = GetIterator() ; pos ; )
00460 {
00461 CDownload* pDownload = GetNext( pos );
00462
00463 if ( ( pDownload->IsTrying() ) && ( ! pDownload->IsCompleted() ) && ( ! pDownload->IsPaused() ) )
00464 {
00465 if ( ( pDownload->m_bBTH ) || ( ! bTorrentsOnly ) )
00466 nCount++;
00467 }
00468 }
00469
00470 return nCount;
00471 }
00472
00473 int CDownloads::GetConnectingTransferCount() const
00474 {
00475 int nCount = 0;
00476
00477 for ( POSITION pos = GetIterator() ; pos ; )
00478 {
00479 CDownload* pDownload = GetNext( pos );
00480
00481 nCount += pDownload->GetTransferCount( dtsConnecting );
00482 }
00483
00484 return nCount;
00485 }
00486
00487 void CDownloads::Remove(CDownload* pDownload)
00488 {
00489 POSITION pos = m_pList.Find( pDownload );
00490 if ( pos != NULL ) m_pList.RemoveAt( pos );
00491 delete pDownload;
00492 }
00493
00495
00496
00497 BOOL CDownloads::Check(CDownloadSource* pSource) const
00498 {
00499 for ( POSITION pos = GetIterator() ; pos ; )
00500 {
00501 if ( GetNext( pos )->CheckSource( pSource ) ) return TRUE;
00502 }
00503 return FALSE;
00504 }
00505
00506 BOOL CDownloads::CheckActive(CDownload* pDownload, int nScope) const
00507 {
00508 for ( POSITION pos = GetReverseIterator() ; pos && nScope > 0 ; )
00509 {
00510 CDownload* pTest = GetPrevious( pos );
00511 BOOL bActive = pTest->IsPaused() == FALSE && pTest->IsCompleted() == FALSE;
00512
00513 if ( pDownload == pTest ) return bActive;
00514 if ( bActive ) nScope--;
00515 }
00516
00517 return FALSE;
00518 }
00519
00520 CDownload* CDownloads::FindByURN(LPCTSTR pszURN, BOOL bSharedOnly) const
00521 {
00522 CDownload* pDownload;
00523 TIGEROOT pTiger;
00524 SHA1 pSHA1;
00525 MD4 pED2K;
00526
00527 if ( CSHA::HashFromURN( pszURN, &pSHA1 ) )
00528 {
00529 if ( pDownload = FindBySHA1( &pSHA1, bSharedOnly ) ) return pDownload;
00530 }
00531
00532 if ( CTigerNode::HashFromURN( pszURN, &pTiger ) )
00533 {
00534 if ( pDownload = FindByTiger( &pTiger, bSharedOnly ) ) return pDownload;
00535 }
00536
00537 if ( CED2K::HashFromURN( pszURN, &pED2K ) )
00538 {
00539 if ( pDownload = FindByED2K( &pED2K, bSharedOnly ) ) return pDownload;
00540 }
00541
00542 return NULL;
00543 }
00544
00545 CDownload* CDownloads::FindBySHA1(const SHA1* pSHA1, BOOL bSharedOnly) const
00546 {
00547 for ( POSITION pos = GetIterator() ; pos ; )
00548 {
00549 CDownload* pDownload = GetNext( pos );
00550 if ( pDownload->m_bSHA1 && pDownload->m_pSHA1 == *pSHA1 )
00551 {
00552 if ( ! bSharedOnly || ( pDownload->IsShared() && pDownload->IsStarted() ) )
00553 return pDownload;
00554 }
00555 }
00556
00557 return NULL;
00558 }
00559
00560 CDownload* CDownloads::FindByTiger(const TIGEROOT* pTiger, BOOL bSharedOnly) const
00561 {
00562 for ( POSITION pos = GetIterator() ; pos ; )
00563 {
00564 CDownload* pDownload = GetNext( pos );
00565 if ( pDownload->m_bTiger && pDownload->m_pTiger == *pTiger )
00566 {
00567 if ( ! bSharedOnly || ( pDownload->IsShared() && pDownload->IsStarted() ) )
00568 return pDownload;
00569 }
00570 }
00571
00572 return NULL;
00573 }
00574
00575 CDownload* CDownloads::FindByED2K(const MD4* pED2K, BOOL bSharedOnly) const
00576 {
00577 for ( POSITION pos = GetIterator() ; pos ; )
00578 {
00579 CDownload* pDownload = GetNext( pos );
00580 if ( pDownload->m_bED2K && pDownload->m_pED2K == *pED2K )
00581 {
00582 if ( ! bSharedOnly || ( pDownload->IsShared() && pDownload->IsStarted() )
00583 && ( pDownload->m_nSize > ED2K_PART_SIZE || pDownload->IsCompleted() ) )
00584 return pDownload;
00585 }
00586 }
00587
00588 return NULL;
00589 }
00590
00591 CDownload* CDownloads::FindByBTH(const SHA1* pBTH, BOOL bSharedOnly) const
00592 {
00593 for ( POSITION pos = GetIterator() ; pos ; )
00594 {
00595 CDownload* pDownload = GetNext( pos );
00596 if ( pDownload->m_bBTH && pDownload->m_pBTH == *pBTH )
00597 {
00598 if ( ! bSharedOnly || ( pDownload->IsShared() ) )
00599 return pDownload;
00600 }
00601 }
00602
00603 return NULL;
00604 }
00605
00606
00608
00609
00610 CDownload* CDownloads::FindBySID(DWORD nSerID) const
00611 {
00612 for ( POSITION pos = GetIterator() ; pos ; )
00613 {
00614 CDownload* pDownload = GetNext( pos );
00615 if ( pDownload->m_nSerID == nSerID ) return pDownload;
00616 }
00617
00618 return NULL;
00619 }
00620
00621 DWORD CDownloads::GetFreeSID()
00622 {
00623 for ( ;; )
00624 {
00625 DWORD nSerID = ( rand() & 0xFF ) + ( ( rand() & 0xFF ) << 8 )
00626 + ( ( rand() & 0xFF ) << 16 ) + ( ( rand() & 0xFF ) << 24 );
00627
00628 for ( POSITION pos = GetIterator() ; pos ; )
00629 {
00630 CDownload* pDownload = GetNext( pos );
00631 if ( pDownload->m_nSerID == nSerID ) { nSerID = 0; break; }
00632 }
00633
00634 if ( nSerID ) return nSerID;
00635 }
00636
00637 ASSERT( FALSE );
00638 return 0;
00639 }
00640
00642
00643
00644 BOOL CDownloads::Move(CDownload* pDownload, int nDelta)
00645 {
00646 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00647
00648 POSITION posMe = m_pList.Find( pDownload );
00649 if ( posMe == NULL ) return FALSE;
00650
00651 POSITION posOther = posMe;
00652
00653 if ( nDelta < 0 )
00654 m_pList.GetPrev( posOther );
00655 else
00656 m_pList.GetNext( posOther );
00657
00658 if ( posOther == NULL) return FALSE;
00659
00660 if ( nDelta < 0 )
00661 m_pList.InsertBefore( posOther, pDownload );
00662 else
00663 m_pList.InsertAfter( posOther, pDownload );
00664 m_pList.RemoveAt( posMe );
00665
00666 DownloadGroups.IncBaseCookie();
00667
00668 return TRUE;
00669 }
00670
00671 BOOL CDownloads::Swap(CDownload* p1, CDownload*p2)
00672 {
00673 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00674
00675 POSITION pos1 = m_pList.Find( p1 );
00676 if (pos1 == NULL) return FALSE;
00677
00678 POSITION pos2 = m_pList.Find( p2 );
00679 if (pos2 == NULL) return FALSE;
00680
00681 m_pList.InsertAfter(pos2, p1 );
00682 m_pList.RemoveAt( pos2);
00683 m_pList.InsertAfter(pos1, p2 );
00684 m_pList.RemoveAt( pos1 );
00685 return TRUE;
00686 }
00687
00688 BOOL CDownloads::Reorder(CDownload* pDownload, CDownload* pBefore)
00689 {
00690 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00691
00692 POSITION pos1 = m_pList.Find( pDownload );
00693 if ( pos1 == NULL ) return FALSE;
00694
00695 if ( pBefore != NULL )
00696 {
00697 POSITION pos2 = m_pList.Find( pBefore );
00698 if ( pos2 == NULL || pos1 == pos2 ) return FALSE;
00699 m_pList.RemoveAt( pos1 );
00700 m_pList.InsertBefore( pos2, pDownload );
00701 }
00702 else
00703 {
00704 m_pList.RemoveAt( pos1 );
00705 m_pList.AddTail( pDownload );
00706 }
00707
00708 DownloadGroups.IncBaseCookie();
00709
00710 return TRUE;
00711 }
00712
00714
00715
00716 QWORD CDownloads::GetAmountDownloadedFrom(IN_ADDR* pAddress)
00717 {
00718 QWORD nTotal = 0;
00719
00720 if ( pAddress == NULL ) return 0;
00721
00722 for ( POSITION pos = GetIterator() ; pos ; )
00723 {
00724 CDownload* pDownload = GetNext( pos );
00725
00726 nTotal += pDownload->GetAmountDownloadedFrom(pAddress);
00727 }
00728 return nTotal;
00729 }
00730
00732
00733
00734 DWORD CDownloads::GetBandwidth() const
00735 {
00736 DWORD nTotal = 0;
00737 for ( POSITION pos = GetIterator() ; pos ; )
00738 {
00739 nTotal += GetNext( pos )->GetMeasuredSpeed();
00740 }
00741 return nTotal;
00742 }
00743
00745
00746
00747 void CDownloads::UpdateAllows(BOOL bNew)
00748 {
00749 int nDownloads = 0;
00750 int nTransfers = 0;
00751
00752 if ( bNew ) m_tLastConnect = GetTickCount();
00753
00754 for ( POSITION pos = GetIterator() ; pos ; )
00755 {
00756 CDownload* pDownload = GetNext( pos );
00757 int nTemp = pDownload->GetTransferCount();
00758
00759 if ( nTemp )
00760 {
00761 nDownloads ++;
00762 nTransfers += nTemp;
00763 }
00764 }
00765
00766 m_bAllowMoreDownloads = nDownloads < Settings.Downloads.MaxFiles;
00767 m_bAllowMoreTransfers = nTransfers < Settings.Downloads.MaxTransfers;
00768 }
00769
00770 BOOL CDownloads::AllowMoreDownloads() const
00771 {
00772 int nCount = 0;
00773
00774 for ( POSITION pos = GetIterator() ; pos ; )
00775 {
00776 if ( GetNext( pos )->GetTransferCount() ) nCount++;
00777 }
00778
00779 return nCount < Settings.Downloads.MaxFiles;
00780 }
00781
00782 BOOL CDownloads::AllowMoreTransfers(IN_ADDR* pAddress) const
00783 {
00784 int nCount = 0, nLimit = 0;
00785
00786 for ( POSITION pos = GetIterator() ; pos ; )
00787 {
00788 nCount += GetNext( pos )->GetTransferCount( dtsCountAll, pAddress );
00789 }
00790
00791 if ( pAddress == NULL ) return nCount < Settings.Downloads.MaxTransfers;
00792
00793 if ( m_pHostLimits.Lookup( (LPVOID)pAddress->S_un.S_addr, (void*&)nLimit ) )
00794 {
00795 return ( nCount < nLimit );
00796 }
00797 else
00798 {
00799 return ( nCount == 0 );
00800 }
00801 }
00802
00803 void CDownloads::SetPerHostLimit(IN_ADDR* pAddress, int nLimit)
00804 {
00805 m_pHostLimits.SetAt( (LPVOID)pAddress->S_un.S_addr, (LPVOID)nLimit );
00806 }
00807
00809
00810
00811 BOOL CDownloads::IsSpaceAvailable(QWORD nVolume, int nPath)
00812 {
00813 QWORD nMargin = 10485760;
00814
00815 if ( HINSTANCE hKernel = GetModuleHandle( _T("KERNEL32.DLL") ) )
00816 {
00817 BOOL (WINAPI *pfnGetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
00818 #ifdef UNICODE
00819 (FARPROC&)pfnGetDiskFreeSpaceEx = GetProcAddress( hKernel, "GetDiskFreeSpaceExW" );
00820 #else
00821 (FARPROC&)pfnGetDiskFreeSpaceEx = GetProcAddress( hKernel, "GetDiskFreeSpaceExA" );
00822 #endif
00823 if ( pfnGetDiskFreeSpaceEx != NULL )
00824 {
00825 ULARGE_INTEGER nFree, nNull;
00826
00827 if ( ( ! nPath || nPath == dlPathIncomplete ) && (*pfnGetDiskFreeSpaceEx)( Settings.Downloads.IncompletePath, &nFree, &nNull, &nNull ) )
00828 {
00829 if ( nFree.QuadPart < nVolume + nMargin ) return FALSE;
00830 }
00831
00832 if ( ( ! nPath || nPath == dlPathComplete ) && (*pfnGetDiskFreeSpaceEx)( Settings.Downloads.CompletePath, &nFree, &nNull, &nNull ) )
00833 {
00834 if ( nFree.QuadPart < nVolume + nMargin ) return FALSE;
00835 }
00836
00837 return TRUE;
00838 }
00839 }
00840
00841 DWORD nSPC, nBPS, nFree, nTotal;
00842 if ( ! nPath || nPath == dlPathIncomplete )
00843 {
00844 CString str = Settings.Downloads.IncompletePath.SpanExcluding( _T("\\") ) + '\\';
00845
00846 if ( GetDiskFreeSpace( str, &nSPC, &nBPS, &nFree, &nTotal ) )
00847 {
00848 QWORD nBytes = (QWORD)nSPC * (QWORD)nBPS * (QWORD)nFree;
00849 if ( nBytes < nVolume + nMargin ) return FALSE;
00850 }
00851 }
00852
00853 if ( ! nPath || nPath == dlPathComplete )
00854 {
00855 CString str = Settings.Downloads.CompletePath.SpanExcluding( _T("\\") ) + '\\';
00856
00857 if ( GetDiskFreeSpace( str, &nSPC, &nBPS, &nFree, &nTotal ) )
00858 {
00859 QWORD nBytes = (QWORD)nSPC * (QWORD)nBPS * (QWORD)nFree;
00860 if ( nBytes < nVolume + nMargin ) return FALSE;
00861 }
00862 }
00863
00864 return TRUE;
00865 }
00866
00868
00869
00870 void CDownloads::OnRun()
00871 {
00872 DWORD nActiveDownloads = 0;
00873 DWORD nActiveTransfers = 0;
00874 DWORD nTotalTransfers = 0;
00875 DWORD nTotalBandwidth = 0;
00876 DWORD nRunningTransfers = 0;
00877 DWORD nRunningED2KTransfers = 0;
00878 DWORD nTotalED2KBandwidth = 0;
00879
00880 {
00881 CTransfers::Lock oLock;
00882
00883 m_nValidation = 0;
00884 ++m_nRunCookie;
00885
00886 for ( POSITION pos = GetIterator(); pos; )
00887 {
00888 CDownload* pDownload = GetNext( pos );
00889 pDownload->m_nRunCookie = m_nRunCookie;
00890 pDownload->OnRun();
00891
00892 int nTemp = 0;
00893
00894 for ( CDownloadTransfer* pTransfer = pDownload->GetFirstTransfer() ; pTransfer ; pTransfer = pTransfer->m_pDlNext )
00895 {
00896 if ( pTransfer->m_nProtocol == PROTOCOL_ED2K )
00897 {
00898 CDownloadTransferED2K* pED2K = (CDownloadTransferED2K*)pTransfer;
00899 if ( pED2K->m_pClient == NULL || pED2K->m_pClient->m_bConnected == FALSE ) continue;
00900 if ( pTransfer->m_nState == dtsQueued ) continue;
00901 }
00902 else if ( pTransfer->m_nProtocol == PROTOCOL_BT )
00903 {
00904 CDownloadTransferBT* pBT = (CDownloadTransferBT*)pTransfer;
00905 if ( pBT->m_nState == dtsTorrent && pBT->m_bChoked ) continue;
00906 }
00907
00908 nTemp ++;
00909
00910 if ( pTransfer->m_nState == dtsDownloading )
00911 {
00912 DWORD nSpeed = pTransfer->GetMeasuredSpeed();
00913 nTotalBandwidth += nSpeed;
00914 nActiveTransfers ++;
00915 if ( nSpeed > 32 ) nRunningTransfers ++;
00916
00917 if ( pTransfer->m_nProtocol == PROTOCOL_ED2K )
00918 {
00919 nTotalED2KBandwidth += nSpeed;
00920 if ( nSpeed > 32 ) nRunningED2KTransfers ++;
00921 }
00922 }
00923 }
00924
00925 if ( nTemp )
00926 {
00927 nActiveDownloads ++;
00928 nTotalTransfers += nTemp;
00929 }
00930 }
00931 }
00932
00933 m_nTransfers = nActiveTransfers;
00934 m_nBandwidth = nTotalBandwidth;
00935
00936 m_bAllowMoreDownloads = nActiveDownloads < (DWORD)Settings.Downloads.MaxFiles;
00937 m_bAllowMoreTransfers = nTotalTransfers < (DWORD)Settings.Downloads.MaxTransfers;
00938
00939
00940 if ( nRunningTransfers > 0 )
00941 {
00942 m_nLimitGeneric = Settings.Bandwidth.Downloads / nRunningTransfers;
00943 m_nLimitDonkey = m_nLimitGeneric;
00944 if ( UploadQueues.IsDonkeyRatioActive() )
00945 {
00946
00947 DWORD nDonkeyLimit = max( UploadQueues.GetMinimumDonkeyBandwidth(), UploadQueues.GetCurrentDonkeyBandwidth() );
00948
00949 if ( nDonkeyLimit < 10240 )
00950 {
00951
00952 nDonkeyLimit *= 3;
00953
00954
00955 if ( nTotalED2KBandwidth > ( nDonkeyLimit / 2 ) )
00956 {
00957
00958
00959 if ( nRunningED2KTransfers > 0 )
00960 m_nLimitDonkey = nDonkeyLimit / nRunningED2KTransfers;
00961 else
00962 m_nLimitDonkey = nDonkeyLimit;
00963
00964 }
00965
00966
00967 if ( m_nLimitGeneric ) m_nLimitDonkey = min( m_nLimitGeneric, m_nLimitDonkey );
00968 }
00969 }
00970 }
00971 else
00972 {
00973 m_nLimitGeneric = m_nLimitDonkey = Settings.Bandwidth.Downloads;
00974 }
00975
00976 DownloadGroups.Save( FALSE );
00977 }
00978
00980
00981
00982 void CDownloads::OnQueryHits(CQueryHit* pHits)
00983 {
00984 CSingleLock pLock( &Transfers.m_pSection );
00985
00986 if ( ! pLock.Lock( 50 ) ) return;
00987
00988 for ( POSITION pos = GetIterator() ; pos ; )
00989 {
00990 CDownload* pDownload = GetNext( pos );
00991 if ( pDownload->IsMoving() == FALSE ) pDownload->OnQueryHits( pHits );
00992 }
00993 }
00994
00996
00997
00998 BOOL CDownloads::OnPush(GGUID* pGUID, CConnection* pConnection)
00999 {
01000 CSingleLock pLock( &Transfers.m_pSection );
01001 if ( ! pLock.Lock( 250 ) ) return FALSE;
01002
01003 for ( POSITION pos = GetIterator() ; pos ; )
01004 {
01005 CDownload* pDownload = GetNext( pos );
01006 if ( pDownload->OnAcceptPush( pGUID, pConnection ) ) return TRUE;
01007 }
01008
01009 return FALSE;
01010 }
01011
01013
01014
01015 BOOL CDownloads::OnDonkeyCallback(CEDClient* pClient, CDownloadSource* pExcept)
01016 {
01017 CSingleLock pLock( &Transfers.m_pSection );
01018 if ( ! pLock.Lock( 250 ) ) return FALSE;
01019
01020 if ( m_bClosing ) return FALSE;
01021
01022 for ( POSITION pos = GetIterator() ; pos ; )
01023 {
01024 CDownload* pDownload = GetNext( pos );
01025 if ( pDownload->OnDonkeyCallback( pClient, pExcept ) ) return TRUE;
01026 }
01027
01028 return FALSE;
01029 }
01030
01032
01033
01034 void CDownloads::OnVerify(LPCTSTR pszPath, BOOL bVerified)
01035 {
01036 CSingleLock pLock( &Transfers.m_pSection );
01037 if ( ! pLock.Lock( 500 ) ) return;
01038
01039 for ( POSITION pos = GetIterator() ; pos ; )
01040 {
01041 if ( GetNext( pos )->OnVerify( pszPath, bVerified ) ) break;
01042 }
01043 }
01044
01046
01047
01048 void CDownloads::Load()
01049 {
01050 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01051 WIN32_FIND_DATA pFind;
01052 CString strPath;
01053 HANDLE hSearch;
01054
01055 PurgeDeletes();
01056 PurgePreviews();
01057
01058 DownloadGroups.CreateDefault();
01059 LoadFromCompoundFiles();
01060
01061 strPath = Settings.Downloads.IncompletePath + _T("\\*.sd");
01062 hSearch = FindFirstFile( strPath, &pFind );
01063
01064 if ( hSearch != INVALID_HANDLE_VALUE )
01065 {
01066 do
01067 {
01068 CDownload* pDownload = new CDownload();
01069
01070 strPath.Format( _T("%s\\%s"), (LPCTSTR)Settings.Downloads.IncompletePath, pFind.cFileName );
01071
01072 if ( pDownload->Load( strPath ) )
01073 {
01074 m_pList.AddTail( pDownload );
01075 }
01076 else
01077 {
01078 theApp.Message( MSG_ERROR, _T("Error loading %s"), strPath );
01079 pDownload->ClearSources();
01080 delete pDownload;
01081 }
01082 }
01083 while ( FindNextFile( hSearch, &pFind ) );
01084
01085 FindClose( hSearch );
01086 }
01087
01088 Save( FALSE );
01089 DownloadGroups.Load();
01090 Transfers.StartThread();
01091 }
01092
01093 void CDownloads::Save(BOOL bForce)
01094 {
01095 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01096
01097 for ( POSITION pos = GetIterator() ; pos ; )
01098 {
01099 CDownload* pDownload = GetNext( pos );
01100 if ( bForce || pDownload->m_nCookie != pDownload->m_nSaveCookie ) pDownload->Save( TRUE );
01101 }
01102 }
01103
01105
01106
01107 void CDownloads::LoadFromCompoundFiles()
01108 {
01109 if ( LoadFromCompoundFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.dat") ) )
01110 {
01111
01112 }
01113 else if ( LoadFromCompoundFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.bak") ) )
01114 {
01115
01116 }
01117 else if ( LoadFromTimePair() )
01118 {
01119
01120 }
01121
01122 DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.dat") );
01123 DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza Downloads.bak") );
01124 DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza.dat") );
01125 DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza1.dat") );
01126 DeleteFile( Settings.Downloads.IncompletePath + _T("\\Shareaza2.dat") );
01127 }
01128
01129 BOOL CDownloads::LoadFromCompoundFile(LPCTSTR pszFile)
01130 {
01131 CFile pFile;
01132
01133 if ( ! pFile.Open( pszFile, CFile::modeRead ) ) return FALSE;
01134
01135 CArchive ar( &pFile, CArchive::load );
01136
01137 try
01138 {
01139 SerializeCompound( ar );
01140 }
01141 catch ( CException* pException )
01142 {
01143 pException->Delete();
01144 Clear();
01145 return FALSE;
01146 }
01147
01148 return TRUE;
01149 }
01150
01151 BOOL CDownloads::LoadFromTimePair()
01152 {
01153 FILETIME pFileTime1 = { 0, 0 }, pFileTime2 = { 0, 0 };
01154 CFile pFile1, pFile2;
01155 BOOL bFile1, bFile2;
01156 CString strFile;
01157
01158 strFile = Settings.Downloads.IncompletePath + _T("\\Shareaza");
01159 bFile1 = pFile1.Open( strFile + _T("1.dat"), CFile::modeRead );
01160 bFile2 = pFile2.Open( strFile + _T("2.dat"), CFile::modeRead );
01161
01162 if ( bFile1 || bFile2 )
01163 {
01164 if ( bFile1 ) bFile1 = pFile1.Read( &pFileTime1, sizeof(FILETIME) ) == sizeof(FILETIME);
01165 if ( bFile2 ) bFile2 = pFile2.Read( &pFileTime2, sizeof(FILETIME) ) == sizeof(FILETIME);
01166 }
01167 else
01168 {
01169 if ( ! pFile1.Open( strFile + _T(".dat"), CFile::modeRead ) ) return FALSE;
01170 pFileTime1.dwHighDateTime++;
01171 }
01172
01173 CFile* pNewest = ( CompareFileTime( &pFileTime1, &pFileTime2 ) >= 0 ) ? &pFile1 : &pFile2;
01174
01175 try
01176 {
01177 CArchive ar( pNewest, CArchive::load );
01178 SerializeCompound( ar );
01179 ar.Close();
01180 }
01181 catch ( CException* pException )
01182 {
01183 pException->Delete();
01184 Clear();
01185
01186 if ( pNewest == &pFile1 && bFile2 )
01187 pNewest = &pFile2;
01188 else if ( pNewest == &pFile2 && bFile1 )
01189 pNewest = &pFile1;
01190 else
01191 pNewest = NULL;
01192
01193 if ( pNewest != NULL )
01194 {
01195 try
01196 {
01197 CArchive ar( pNewest, CArchive::load );
01198 SerializeCompound( ar );
01199 ar.Close();
01200 }
01201 catch ( CException* pException )
01202 {
01203 pException->Delete();
01204 Clear();
01205 return FALSE;
01206 }
01207 }
01208 }
01209
01210 return TRUE;
01211 }
01212
01213 void CDownloads::SerializeCompound(CArchive& ar)
01214 {
01215 ASSERT( ar.IsLoading() );
01216
01217 int nVersion;
01218 ar >> nVersion;
01219 if ( nVersion < 4 ) return;
01220
01221 for ( int nCount = ar.ReadCount() ; nCount > 0 ; nCount-- )
01222 {
01223 CDownload* pDownload = new CDownload();
01224 m_pList.AddTail( pDownload );
01225 pDownload->Serialize( ar, nVersion );
01226 }
01227 }
01228
01230
01231
01232 void CDownloads::PurgeDeletes()
01233 {
01234 CStringList pRemove;
01235 HKEY hKey = NULL;
01236
01237 if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_CURRENT_USER,
01238 _T("Software\\Shareaza\\Shareaza\\Delete"), 0, KEY_ALL_ACCESS, &hKey ) ) return;
01239
01240 for ( DWORD nIndex = 0 ; nIndex < 1000 ; nIndex ++ )
01241 {
01242 DWORD nPath = MAX_PATH*2;
01243 TCHAR szPath[MAX_PATH*2];
01244
01245 if ( ERROR_SUCCESS != RegEnumValue( hKey, nIndex, szPath, &nPath, NULL,
01246 NULL, NULL, NULL ) ) break;
01247
01248 if ( GetFileAttributes( szPath ) == 0xFFFFFFFF || DeleteFile( szPath ) )
01249 {
01250 pRemove.AddTail( szPath );
01251 }
01252 }
01253
01254 while ( ! pRemove.IsEmpty() )
01255 {
01256 RegDeleteValue( hKey, pRemove.RemoveHead() );
01257 }
01258
01259 RegCloseKey( hKey );
01260 }
01261
01262 void CDownloads::PurgePreviews()
01263 {
01264 WIN32_FIND_DATA pFind;
01265 HANDLE hSearch;
01266 CString strPath;
01267
01268 strPath = Settings.Downloads.IncompletePath + _T("\\Preview of *.*");
01269 hSearch = FindFirstFile( strPath, &pFind );
01270 if ( hSearch == INVALID_HANDLE_VALUE ) return;
01271
01272 do
01273 {
01274 if ( _tcsnicmp( pFind.cFileName, _T("Preview of "), 11 ) == 0 )
01275 {
01276 strPath = Settings.Downloads.IncompletePath + '\\' + pFind.cFileName;
01277 DeleteFile( strPath );
01278 }
01279 }
01280 while ( FindNextFile( hSearch, &pFind ) );
01281
01282 FindClose( hSearch );
01283 }