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

DownloadSource.cpp

Go to the documentation of this file.
00001 //
00002 // DownloadSource.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 "DownloadTransferHTTP.h"
00029 #include "DownloadTransferFTP.h"
00030 #include "DownloadTransferED2K.h"
00031 #include "DownloadTransferBT.h"
00032 #include "FragmentedFile.h"
00033 
00034 #include "Neighbours.h"
00035 #include "QueryHit.h"
00036 #include "Network.h"
00037 #include "VendorCache.h"
00038 #include "EDClients.h"
00039 #include "EDClient.h"
00040 #include "EDPacket.h"
00041 #include "SourceURL.h"
00042 #include "SHA.h"
00043 
00044 #ifdef _DEBUG
00045 #undef THIS_FILE
00046 static char THIS_FILE[]=__FILE__;
00047 #define new DEBUG_NEW
00048 #endif
00049 
00050 
00052 // CDownloadSource construction
00053 
00054 CDownloadSource::CDownloadSource(CDownload* pDownload)
00055 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00056 {
00057         Construct( pDownload );
00058 }
00059 
00060 void CDownloadSource::Construct(CDownload* pDownload)
00061 {
00062         ASSERT( pDownload != NULL );
00063         
00064         m_pDownload             = pDownload;
00065         m_pPrev                 = NULL;
00066         m_pNext                 = NULL;
00067         m_pTransfer             = NULL;
00068         m_bSelected             = FALSE;
00069         
00070         m_nProtocol             = PROTOCOL_NULL;
00071         m_bGUID                 = FALSE;
00072         m_nPort                 = 0;
00073         m_nServerPort   = 0;
00074         
00075         m_nIndex                = 0;
00076         m_bHashAuth             = FALSE;
00077         m_bSHA1                 = FALSE;
00078         m_bTiger                = FALSE;
00079         m_bED2K                 = FALSE;
00080         
00081         m_nSpeed                = 0;
00082         m_bPushOnly             = FALSE;
00083         m_bCloseConn    = FALSE;
00084         m_bReadContent  = FALSE;
00085         m_nGnutella             = 0;
00086         m_bClientExtended=FALSE;
00087         
00088         m_nSortOrder    = 0xFFFFFFFF;
00089         m_nColour               = -1;
00090         m_tAttempt              = 0;
00091         m_nFailures             = 0;
00092 
00093         SYSTEMTIME pTime;
00094         GetSystemTime( &pTime );
00095         SystemTimeToFileTime( &pTime, &m_tLastSeen );
00096 }
00097 
00098 CDownloadSource::~CDownloadSource()
00099 {
00100 //      m_pPastFragment->DeleteChain();
00101 //      m_pAvailable->DeleteChain();
00102 }
00103 
00105 // CDownloadSource construction from a query hit
00106 
00107 CDownloadSource::CDownloadSource(CDownload* pDownload, CQueryHit* pHit)
00108 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00109 {
00110         Construct( pDownload );
00111         
00112         m_bPushOnly     = pHit->m_bPush == TS_TRUE ? TRUE : FALSE;
00113         
00114         m_sURL          = pHit->m_sURL;
00115         m_pAddress      = pHit->m_pAddress;     // Not needed?
00116         m_nPort         = pHit->m_nPort;        // Not needed?
00117         m_nSpeed        = pHit->m_bMeasured == TS_TRUE ? ( pHit->m_nSpeed * 128 ) : 0;
00118         m_sServer       = pHit->m_pVendor->m_sName;
00119         m_sName         = pHit->m_sName;
00120         m_nIndex        = pHit->m_nIndex;
00121         m_bSHA1         = pHit->m_bSHA1;
00122         m_bTiger        = pHit->m_bTiger;
00123         m_bED2K         = pHit->m_bED2K;
00124         
00125         if ( pHit->m_nProtocol == PROTOCOL_G1 || pHit->m_nProtocol == PROTOCOL_G2 )
00126         {
00127                 m_bGUID = TRUE;
00128                 m_pGUID = pHit->m_pClientID;
00129                 m_bClientExtended = TRUE;
00130         }
00131         else if ( pHit->m_nProtocol == PROTOCOL_ED2K )
00132         {
00133                 if ( ( m_sURL.Right( 3 ) == _T("/0/") ) && ( pDownload->m_nSize ) )
00134                 {       //Add the size if it was missing.
00135                         CString strTemp =  m_sURL.Left( m_sURL.GetLength() - 2 );
00136                         m_sURL.Format( _T("%s%I64i/"), strTemp, pDownload->m_nSize );
00137                 }
00138         }
00139         
00140         ResolveURL();
00141 }
00142 
00144 // CDownloadSource construction from eDonkey source transfer
00145 
00146 CDownloadSource::CDownloadSource(CDownload* pDownload, DWORD nClientID, WORD nClientPort, DWORD nServerIP, WORD nServerPort, GGUID* pGUID)
00147 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00148 {
00149         Construct( pDownload );
00150         
00151         if ( m_bPushOnly = CEDPacket::IsLowID( nClientID ) )
00152         {
00153                 m_sURL.Format( _T("ed2kftp://%lu@%s:%i/%s/%I64i/"),
00154                         nClientID,
00155                         (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)nServerIP ) ), nServerPort,
00156                         (LPCTSTR)CED2K::HashToString( &m_pDownload->m_pED2K ), m_pDownload->m_nSize );
00157         }
00158         else
00159         {
00160                 m_sURL.Format( _T("ed2kftp://%s:%i/%s/%I64i/"),
00161                         (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)nClientID ) ), nClientPort,
00162                         (LPCTSTR)CED2K::HashToString( &m_pDownload->m_pED2K ), m_pDownload->m_nSize );
00163         }
00164         
00165         if ( m_bGUID = ( pGUID != NULL ) ) m_pGUID = *pGUID;
00166         
00167         m_bED2K         = TRUE;
00168         m_sServer       = _T("eDonkey2000");
00169         
00170         ResolveURL();
00171 }
00172 
00174 // CDownloadSource construction from BitTorrent
00175 
00176 CDownloadSource::CDownloadSource(CDownload* pDownload, SHA1* pGUID, IN_ADDR* pAddress, WORD nPort)
00177 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00178 {
00179         Construct( pDownload );
00180         
00181         if ( pGUID != NULL )
00182         {
00183                 m_sURL.Format( _T("btc://%s:%i/%s/%s/"),
00184                         (LPCTSTR)CString( inet_ntoa( *pAddress ) ), nPort,
00185                         (LPCTSTR)CSHA::HashToString( pGUID ),
00186                         (LPCTSTR)CSHA::HashToString( &pDownload->m_pBTH ) );
00187         }
00188         else
00189         {
00190                 m_sURL.Format( _T("btc://%s:%i//%s/"),
00191                         (LPCTSTR)CString( inet_ntoa( *pAddress ) ), nPort,
00192                         (LPCTSTR)CSHA::HashToString( &pDownload->m_pBTH ) );
00193         }
00194         
00195         m_bGUID         = pGUID != NULL;
00196         m_sServer       = _T("BitTorrent");
00197         
00198         ResolveURL();
00199 }
00200 
00202 // CDownloadSource construction from URL
00203 
00204 CDownloadSource::CDownloadSource(CDownload* pDownload, LPCTSTR pszURL, BOOL bSHA1, BOOL bHashAuth, FILETIME* pLastSeen)
00205 : m_oAvailable( pDownload->m_nSize ), m_oPastFragments( pDownload->m_nSize )
00206 {
00207         Construct( pDownload );
00208         
00209         ASSERT( pszURL != NULL );
00210         m_sURL = pszURL;
00211         
00212         if ( ! ResolveURL() ) return;
00213         
00214         //m_bSHA1                       = bSHA1; //Done in ResolveURL now
00215         m_bHashAuth             = bHashAuth;
00216         
00217         if ( pLastSeen != NULL )
00218         {
00219                 FILETIME tNow = m_tLastSeen;
00220                 (LONGLONG&)tNow += 10000000;
00221                 if ( CompareFileTime( pLastSeen, &tNow ) <= 0 ) m_tLastSeen = *pLastSeen;
00222         }
00223 }
00224 
00226 // CDownloadSource URL resolver
00227 
00228 BOOL CDownloadSource::ResolveURL()
00229 {
00230         CSourceURL pURL;
00231         
00232         if ( ! pURL.Parse( m_sURL ) )
00233         {
00234                 theApp.Message( MSG_ERROR, _T("Unable to parse URL: %s"), (LPCTSTR)m_sURL );
00235                 return FALSE;
00236         }
00237         
00238         m_bSHA1         |= pURL.m_bSHA1;
00239         m_bED2K         |= pURL.m_bED2K;
00240 
00241         m_nProtocol     = pURL.m_nProtocol;
00242         m_pAddress      = pURL.m_pAddress;
00243         m_nPort         = pURL.m_nPort;
00244         
00245         if ( m_nProtocol == PROTOCOL_ED2K )
00246         {
00247                 m_pServerAddress        = pURL.m_pServerAddress;
00248                 m_nServerPort           = pURL.m_nServerPort;
00249                 if ( m_nServerPort ) m_bPushOnly = TRUE;
00250         }
00251         else if ( m_nProtocol == PROTOCOL_BT )
00252         {
00253                 if ( m_bGUID = pURL.m_bBTC ) CopyMemory( &m_pGUID, &pURL.m_pBTC, 16 );
00254         }
00255         
00256         return TRUE;
00257 }
00258 
00260 // CDownloadSource serialize
00261 
00262 void CDownloadSource::Serialize(CArchive& ar, int nVersion)
00263 {
00264         if ( ar.IsStoring() )
00265         {
00266                 ar << m_sURL;
00267                 ar << m_nProtocol;
00268                 
00269                 ar << m_bGUID;
00270                 if ( m_bGUID ) ar.Write( &m_pGUID, sizeof(GGUID) );
00271                 
00272                 ar << m_nPort;
00273                 if ( m_nPort ) ar.Write( &m_pAddress, sizeof(m_pAddress) );
00274                 ar << m_nServerPort;
00275                 if ( m_nServerPort ) ar.Write( &m_pServerAddress, sizeof(m_pServerAddress) );
00276                 
00277                 ar << m_sName;
00278                 ar << m_nIndex;
00279                 ar << m_bHashAuth;
00280                 ar << m_bSHA1;
00281                 ar << m_bTiger;
00282                 ar << m_bED2K;
00283                 
00284                 ar << m_sServer;
00285                 ar << m_sNick;
00286                 ar << m_nSpeed;
00287                 ar << m_bPushOnly;
00288                 ar << m_bCloseConn;
00289                 ar << m_bReadContent;
00290                 ar.Write( &m_tLastSeen, sizeof(FILETIME) );
00291                 
00292         SerializeOut2( ar, m_oPastFragments );
00293         }
00294         else if ( nVersion >= 21 )
00295         {
00296                 ar >> m_sURL;
00297                 ar >> m_nProtocol;
00298                 
00299                 ar >> m_bGUID;
00300                 if ( m_bGUID ) ar.Read( &m_pGUID, sizeof(GGUID) );
00301                 
00302                 ar >> m_nPort;
00303                 if ( m_nPort ) ar.Read( &m_pAddress, sizeof(m_pAddress) );
00304                 ar >> m_nServerPort;
00305                 if ( m_nServerPort ) ar.Read( &m_pServerAddress, sizeof(m_pServerAddress) );
00306                 
00307                 ar >> m_sName;
00308                 ar >> m_nIndex;
00309                 ar >> m_bHashAuth;
00310                 ar >> m_bSHA1;
00311                 ar >> m_bTiger;
00312                 ar >> m_bED2K;
00313                 
00314                 ar >> m_sServer;
00315                 if ( nVersion >= 24 ) ar >> m_sNick;
00316                 ar >> m_nSpeed;
00317                 ar >> m_bPushOnly;
00318                 ar >> m_bCloseConn;
00319                 ar >> m_bReadContent;
00320                 ar.Read( &m_tLastSeen, sizeof(FILETIME) );
00321                 
00322         SerializeIn2( ar, m_oPastFragments, nVersion );
00323 
00324                 // Should probably save this instead...
00325                 if ( _tcsncmp( m_sServer, _T("Shareaza"), 8 ) == 0 )
00326                         m_bClientExtended = TRUE;
00327                 if ( _tcsncmp( m_sServer, _T("RAZA"), 4 ) == 0 )
00328                         m_bClientExtended = TRUE;
00329                 //
00330         }
00331         else
00332         {
00333                 DWORD nIndex;
00334                 ar.Read( &m_pAddress, sizeof(m_pAddress) );
00335                 ar >> m_nPort;
00336                 ar >> m_nSpeed;
00337                 ar >> nIndex;
00338                 ar >> m_sName;
00339                 if ( nVersion >= 4 ) ar >> m_sURL;
00340                 if ( nVersion >= 21 ) ar >> m_nProtocol;
00341                 ar >> m_bSHA1;
00342                 if ( nVersion >= 13 ) ar >> m_bTiger;
00343                 if ( nVersion >= 13 ) ar >> m_bED2K;
00344                 if ( nVersion >= 10 ) ar >> m_bHashAuth;
00345                 
00346                 if ( nVersion == 8 )
00347                 {
00348                         DWORD nV;
00349                         ar >> nV;
00350                         m_sServer.Format( _T("%c%c%c%c"), nV & 0xFF, ( nV >> 8 ) & 0xFF, ( nV >> 16 ) & 0xFF, nV >> 24 );
00351                 }
00352                 else if ( nVersion >= 9 )
00353                 {
00354                         ar >> m_sServer;
00355                 }
00356                 
00357                 ar >> m_bPushOnly;
00358                 ar >> m_bReadContent;
00359                 if ( nVersion >= 7 ) ar >> m_bCloseConn;
00360                 if ( nVersion >= 12 ) ar.Read( &m_tLastSeen, sizeof(FILETIME) );
00361                 
00362                 ar.Read( &m_pGUID, sizeof(GGUID) );
00363                 ar.Read( &m_pGUID, sizeof(GGUID) );
00364                 m_bGUID = m_pGUID != (GGUID&)GUID_NULL;
00365                 
00366         SerializeIn2( ar, m_oPastFragments, nVersion );
00367                 
00368                 ResolveURL();
00369         }
00370 }
00371 
00373 // CDownloadSource create transfer
00374 
00375 CDownloadTransfer* CDownloadSource::CreateTransfer()
00376 {
00377         ASSERT( m_pTransfer == NULL );
00378         
00379         switch ( m_nProtocol )
00380         {
00381         case PROTOCOL_G1:       return ( m_pTransfer = new CDownloadTransferHTTP( this ) );
00382         case PROTOCOL_G2:       return ( m_pTransfer = new CDownloadTransferHTTP( this ) );
00383         case PROTOCOL_ED2K:     return ( m_pTransfer = new CDownloadTransferED2K( this ) );
00384         case PROTOCOL_HTTP:     return ( m_pTransfer = new CDownloadTransferHTTP( this ) );
00385         case PROTOCOL_FTP:      return ( m_pTransfer = new CDownloadTransferFTP( this ) );
00386         case PROTOCOL_BT:       return ( m_pTransfer = new CDownloadTransferBT( this, NULL ) );
00387         default:                        theApp.Message( MSG_ERROR, _T("Invalid protocol in CDownloadSource::CreateTransfer()") );
00388                                                 return ( NULL );
00389         }
00390 }
00391 
00393 // CDownloadSource remove
00394 
00395 void CDownloadSource::Remove(BOOL bCloseTransfer, BOOL bBan)
00396 {
00397         if ( m_pTransfer != NULL )
00398         {
00399                 if ( bCloseTransfer )
00400                 {
00401                         m_pTransfer->Close( TS_TRUE );
00402                         ASSERT( m_pTransfer == NULL );
00403                 }
00404                 else
00405                 {
00406                         m_pTransfer->m_pSource = NULL;
00407                         m_pTransfer = NULL;
00408                 }
00409         }
00410         
00411         m_pDownload->RemoveSource( this, bBan );
00412 }
00413 
00415 // CDownloadSource failure handler
00416 
00417 void CDownloadSource::OnFailure(BOOL bNondestructive)
00418 {
00419         if ( m_pTransfer != NULL )
00420         {
00421                 m_pTransfer->SetState(dtsNull);
00422                 m_pTransfer->m_pSource = NULL;
00423                 m_pTransfer = NULL;
00424         }
00425         
00426         DWORD nDelay = Settings.Downloads.RetryDelay * (DWORD)pow( 2, m_nFailures );
00427         
00428         if ( m_nFailures < 20 )
00429         {
00430                 if ( nDelay > 3600000 ) nDelay = 3600000;
00431         }
00432         else
00433         {
00434                 if ( nDelay > 86400000 ) nDelay = 86400000;
00435         }
00436         
00437         nDelay += GetTickCount();
00438         
00439         int nMaxFailures = ( m_bReadContent ? 40 : 3 );
00440         if ( nMaxFailures < 20 && m_pDownload->GetSourceCount() > 20 ) nMaxFailures = 0;
00441         
00442         m_pDownload->SetModified();
00443         
00444         if ( bNondestructive || ( ++m_nFailures < nMaxFailures ) )
00445         {
00446                 m_tAttempt = max( m_tAttempt, nDelay );
00447         }
00448         else
00449         {
00450                 if ( Settings.Downloads.NeverDrop )
00451                 {
00452                         m_tAttempt = nDelay;
00453                 }
00454                 else
00455                 {
00456                         m_pDownload->RemoveSource( this, TRUE );
00457                 }
00458         }
00459 }
00460 
00462 // CDownloadSource resume handler
00463 
00464 void CDownloadSource::OnResume()
00465 {
00466         m_tAttempt = 0;
00467 }
00468 
00470 // CDownloadSource status
00471 
00472 void CDownloadSource::SetValid()
00473 {
00474         m_bReadContent = TRUE;
00475         m_nFailures = 0;
00476         m_pDownload->SetModified();
00477 }
00478 
00479 void CDownloadSource::SetLastSeen()
00480 {
00481         SYSTEMTIME pTime;
00482         GetSystemTime( &pTime );
00483         SystemTimeToFileTime( &pTime, &m_tLastSeen );
00484         m_pDownload->SetModified();
00485 }
00486 
00487 void CDownloadSource::SetGnutella(int nGnutella)
00488 {
00489         m_nGnutella |= nGnutella;
00490         m_pDownload->SetModified();
00491 }
00492 
00494 // CDownloadSource hash check and learn
00495 
00496 BOOL CDownloadSource::CheckHash(const SHA1* pSHA1)
00497 {
00498         if ( m_pDownload->m_bSHA1 && ! m_bHashAuth )
00499         {
00500                 if ( m_pDownload->m_pSHA1 != *pSHA1 ) return FALSE;
00501         }
00502         else
00503         {
00504                 if ( m_pDownload->m_pTorrent.IsAvailable() ) return TRUE;
00505                 
00506                 m_pDownload->m_bSHA1 = TRUE;
00507                 m_pDownload->m_pSHA1 = *pSHA1;
00508         }
00509         
00510         m_bSHA1 = TRUE;
00511         m_pDownload->SetModified();
00512         
00513         return TRUE;
00514 }
00515 
00516 BOOL CDownloadSource::CheckHash(const TIGEROOT* pTiger)
00517 {
00518         if ( m_pDownload->m_bTiger && ! m_bHashAuth )
00519         {
00520                 if ( m_pDownload->m_pTiger != *pTiger ) return FALSE;
00521         }
00522         else
00523         {
00524                 if ( m_pDownload->m_pTorrent.IsAvailable() ) return TRUE;
00525                 
00526                 m_pDownload->m_bTiger = TRUE;
00527                 m_pDownload->m_pTiger = *pTiger;
00528         }
00529         
00530         m_bTiger = TRUE;
00531         m_pDownload->SetModified();
00532         
00533         return TRUE;
00534 }
00535 
00536 BOOL CDownloadSource::CheckHash(const MD4* pED2K)
00537 {
00538         if ( m_pDownload->m_bED2K && ! m_bHashAuth )
00539         {
00540                 if ( memcmp( &m_pDownload->m_pED2K, pED2K, sizeof(MD4) ) ) return FALSE;
00541         }
00542         else
00543         {
00544                 if ( m_pDownload->m_pTorrent.IsAvailable() ) return TRUE;
00545                 
00546                 m_pDownload->m_bED2K = TRUE;
00547                 m_pDownload->m_pED2K = *pED2K;
00548         }
00549         
00550         m_bED2K = TRUE;
00551         m_pDownload->SetModified();
00552         
00553         return TRUE;
00554 }
00555 
00557 // CDownloadSource push request
00558 
00559 BOOL CDownloadSource::PushRequest()
00560 {
00561         if ( m_nProtocol == PROTOCOL_BT )
00562         {
00563                 return FALSE;
00564         }
00565         else if ( m_nProtocol == PROTOCOL_ED2K )
00566         {
00567                 if ( m_nServerPort == 0 ) return FALSE;
00568                 if ( EDClients.IsFull() ) return TRUE;
00569                 
00570                 CEDClient* pClient = EDClients.Connect( m_pAddress.S_un.S_addr, m_nPort,
00571                         &m_pServerAddress, m_nServerPort, m_bGUID ? &m_pGUID : NULL );
00572                 
00573                 if ( pClient != NULL && pClient->m_bConnected )
00574                 {
00575                         pClient->SeekNewDownload();
00576                         return TRUE;
00577                 }
00578                 
00579                 if ( Neighbours.PushDonkey( m_pAddress.S_un.S_addr, &m_pServerAddress, m_nServerPort ) )
00580                 {
00581                         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_PUSH_SENT, (LPCTSTR)m_pDownload->m_sRemoteName );
00582                         m_tAttempt = GetTickCount() + Settings.Downloads.PushTimeout;
00583                         return TRUE;
00584                 }
00585         }
00586         else
00587         {
00588                 if ( ! m_bGUID ) return FALSE;
00589                 
00590                 if ( Network.SendPush( &m_pGUID, m_nIndex ) )
00591                 {
00592                         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_PUSH_SENT, (LPCTSTR)m_pDownload->m_sRemoteName );
00593                         m_tAttempt = GetTickCount() + Settings.Downloads.PushTimeout;
00594                         return TRUE;
00595                 }
00596         }
00597         
00598         return FALSE;
00599 }
00600 
00601 BOOL CDownloadSource::CheckPush(GGUID* pClientID)
00602 {
00603         return m_bGUID && ( m_pGUID == *pClientID );
00604 }
00605 
00606 BOOL CDownloadSource::CheckDonkey(CEDClient* pClient)
00607 {
00608         if ( m_nProtocol != PROTOCOL_ED2K ) return FALSE;
00609         
00610         if ( m_bGUID && pClient->m_bGUID ) return m_pGUID == pClient->m_pGUID;
00611         
00612         if ( m_bPushOnly )
00613         {
00614                 return  m_pServerAddress.S_un.S_addr == pClient->m_pServer.sin_addr.S_un.S_addr &&
00615                                 m_pAddress.S_un.S_addr == pClient->m_nClientID;
00616         }
00617         else
00618         {
00619                 return m_pAddress.S_un.S_addr == pClient->m_pHost.sin_addr.S_un.S_addr;
00620         }
00621 }
00622 
00624 // CDownloadSource past fragments
00625 
00626 void CDownloadSource::AddFragment(QWORD nOffset, QWORD nLength, BOOL bMerge)
00627 {
00628         m_bReadContent = TRUE;
00629     m_oPastFragments.insert( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00630         m_pDownload->SetModified();
00631 }
00632 
00634 // CDownloadSource available ranges
00635 
00636 void CDownloadSource::SetAvailableRanges(LPCTSTR pszRanges)
00637 {
00638     m_oAvailable.clear();
00639         
00640         if ( ! pszRanges || ! *pszRanges ) return;
00641         if ( _tcsnicmp( pszRanges, _T("bytes"), 5 ) ) return;
00642         
00643         CString strRanges( pszRanges + 6 );
00644         
00645         for ( strRanges += ',' ; strRanges.GetLength() ; )
00646         {
00647                 CString strRange = strRanges.SpanExcluding( _T(", \t") );
00648                 strRanges = strRanges.Mid( strRange.GetLength() + 1 );
00649                 
00650                 strRange.TrimLeft();
00651                 strRange.TrimRight();
00652                 if ( strRange.Find( '-' ) < 0 ) continue;
00653                 
00654                 QWORD nFirst = 0, nLast = 0;
00655                 
00656         // ??????????????? nLast == nFirst has special meaning ?
00657                 if ( _stscanf( strRange, _T("%I64i-%I64i"), &nFirst, &nLast ) == 2 && nLast > nFirst )
00658                 {
00659             if( nFirst < m_oAvailable.limit() ) // Sanity check
00660             {
00661                                 // perhaps the file size we expect is incorrect or the source is erronous
00662                                 // in either case we make sure the range fits - so we chop off the end if necessary
00663                 m_oAvailable.insert( FF::SimpleFragment( nFirst, min( nLast + 1, m_oAvailable.limit() ) ) );
00664             }
00665                 }
00666         }
00667         
00668         m_pDownload->SetModified();
00669 }
00670 
00672 // CDownloadSource range intersection test
00673 
00674 BOOL CDownloadSource::HasUsefulRanges() const
00675 {
00676         if ( m_oAvailable.empty() )
00677     {
00678         return m_pDownload->IsRangeUseful( 0, m_pDownload->m_nSize );
00679     }
00680     return m_pDownload->AreRangesUseful( m_oAvailable );
00681 }
00682 
00684 // CDownloadSource range intersection
00685 
00686 BOOL CDownloadSource::TouchedRange(QWORD nOffset, QWORD nLength) const
00687 {
00688         if ( m_pTransfer != NULL && m_pTransfer->m_nState == dtsDownloading )
00689         {
00690                 if ( m_pTransfer->m_nOffset + m_pTransfer->m_nLength > nOffset &&
00691                          m_pTransfer->m_nOffset < nOffset + nLength )
00692                 {
00693                         return TRUE;
00694                 }
00695         }
00696         
00697     return overlaps( m_oPastFragments,
00698         FF::SimpleFragment( nOffset, nOffset + nLength ) );
00699 }
00700 
00702 // CDownloadSource colour
00703 
00704 int CDownloadSource::GetColour()
00705 {
00706         if ( m_nColour >= 0 ) return m_nColour;
00707         m_nColour = m_pDownload->GetSourceColour();
00708         return m_nColour;
00709 }

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