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

DownloadWithTiger.cpp

Go to the documentation of this file.
00001 //
00002 // DownloadWithTiger.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 "Downloads.h"
00026 #include "DownloadWithTiger.h"
00027 #include "FragmentedFile.h"
00028 
00029 #include "Neighbours.h"
00030 #include "Transfers.h"
00031 #include "Library.h"
00032 #include "SharedFile.h"
00033 #include "BTInfo.h"
00034 
00035 #ifdef _DEBUG
00036 #undef THIS_FILE
00037 static char THIS_FILE[]=__FILE__;
00038 #define new DEBUG_NEW
00039 #endif
00040 
00041 
00043 // CDownloadWithTiger construction
00044 
00045 CDownloadWithTiger::CDownloadWithTiger()
00046 {
00047         m_pTigerBlock           = NULL;
00048         m_nTigerBlock           = 0;
00049         m_nTigerSuccess         = 0;
00050 
00051         m_pHashsetBlock         = NULL;
00052         m_nHashsetBlock         = 0;
00053         m_nHashsetSuccess       = 0;
00054 
00055         m_nVerifyCookie         = 0;
00056         m_nVerifyHash           = HASH_NULL;
00057         m_nVerifyBlock          = 0xFFFFFFFF;
00058 }
00059 
00060 CDownloadWithTiger::~CDownloadWithTiger()
00061 {
00062         if ( m_pHashsetBlock != NULL ) delete [] m_pHashsetBlock;
00063         if ( m_pTigerBlock != NULL ) delete [] m_pTigerBlock;
00064 }
00065 
00067 // CDownloadWithTiger informational access
00068 
00069 DWORD CDownloadWithTiger::GetValidationCookie() const
00070 {
00071         return m_nVerifyCookie;
00072 }
00073 
00074 QWORD CDownloadWithTiger::GetVerifyLength(int nHash) const
00075 {
00076         if ( nHash == HASH_NULL )
00077         {
00078                 if ( m_pTorrentBlock != NULL ) return m_nTorrentSize;
00079                 else if ( m_pTigerBlock != NULL ) return m_nTigerSize;
00080                 else if ( m_pHashsetBlock != NULL ) return ED2K_PART_SIZE;
00081         }
00082         else if ( nHash == HASH_TIGERTREE && m_pTigerBlock != NULL )
00083         {
00084                 return m_nTigerSize;
00085         }
00086         else if ( nHash == HASH_ED2K && m_pHashsetBlock != NULL )
00087         {
00088                 return ED2K_PART_SIZE;
00089         }
00090         else if ( nHash == HASH_TORRENT && m_pTorrentBlock != NULL )
00091         {
00092                 return m_nTorrentSize;
00093         }
00094 
00095         return 0;
00096 }
00097 
00098 BOOL CDownloadWithTiger::GetNextVerifyRange(QWORD& nOffset, QWORD& nLength, BOOL& bSuccess, int nHash) const
00099 {
00100         if ( nOffset >= m_nSize ) return FALSE;
00101         if ( m_pTigerBlock == NULL && m_pHashsetBlock == NULL && m_pTorrentBlock == NULL ) return FALSE;
00102 
00103         if ( nHash == HASH_NULL )
00104         {
00105                 if ( m_pTorrentBlock != NULL ) nHash = HASH_TORRENT;
00106                 else if ( m_pTigerBlock != NULL ) nHash = HASH_TIGERTREE;
00107                 else if ( m_pHashsetBlock != NULL ) nHash = HASH_ED2K;
00108         }
00109 
00110         QWORD nBlockCount, nBlockSize;
00111         BYTE* pBlockPtr;
00112 
00113         switch ( nHash )
00114         {
00115         case HASH_TIGERTREE:
00116                 if ( m_pTigerBlock == NULL ) return FALSE;
00117                 pBlockPtr       = m_pTigerBlock;
00118                 nBlockCount     = m_nTigerBlock;
00119                 nBlockSize      = m_nTigerSize;
00120                 break;
00121         case HASH_ED2K:
00122                 if ( m_pHashsetBlock == NULL ) return FALSE;
00123                 pBlockPtr       = m_pHashsetBlock;
00124                 nBlockCount     = m_nHashsetBlock;
00125                 nBlockSize      = ED2K_PART_SIZE;
00126                 break;
00127         case HASH_TORRENT:
00128                 if ( m_pTorrentBlock == NULL ) return FALSE;
00129                 pBlockPtr       = m_pTorrentBlock;
00130                 nBlockCount     = m_nTorrentBlock;
00131                 nBlockSize      = m_nTorrentSize;
00132                 break;
00133         default:
00134                 return FALSE;
00135         }
00136 
00137         if ( nBlockSize == 0 ) return FALSE;
00138 
00139         for ( QWORD nBlock = nOffset / nBlockSize ; nBlock < nBlockCount ; nBlock++ )
00140         {
00141                 QWORD nThis = nBlock * nBlockSize;
00142 
00143                 if ( nThis >= nOffset && pBlockPtr[ nBlock ] )
00144                 {
00145                         TRISTATE nBase  = pBlockPtr[ nBlock ];
00146                         bSuccess                = nBase == TS_TRUE;
00147                         nOffset                 = nThis;
00148                         nLength                 = 0;
00149 
00150                         for ( ; nBlock < nBlockCount ; nBlock++ )
00151                         {
00152                                 if ( nBase != pBlockPtr[ nBlock ] ) break;
00153                                 nLength += nBlockSize;
00154                         }
00155 
00156                         return TRUE;
00157                 }
00158         }
00159 
00160         return FALSE;
00161 }
00162 
00163 BOOL CDownloadWithTiger::IsFullyVerified()
00164 {
00165         if ( m_nTorrentBlock > 0 && m_nTorrentSuccess >= m_nTorrentBlock ) return TRUE;
00166         if ( m_nTigerBlock > 0 && m_nTigerSuccess >= m_nTigerBlock ) return TRUE;
00167         if ( m_nHashsetBlock > 0 && m_nHashsetSuccess >= m_nHashsetBlock ) return TRUE;
00168         return FALSE;
00169 }
00170 
00172 // CDownloadWithTiger tiger-tree access
00173 
00174 BOOL CDownloadWithTiger::NeedTigerTree() const
00175 {
00176         return ( m_nSize < SIZE_UNKNOWN && m_pTigerTree.IsAvailable() == FALSE );
00177 }
00178 
00179 BOOL CDownloadWithTiger::SetTigerTree(BYTE* pTiger, DWORD nTiger)
00180 {
00181         if ( m_nSize == SIZE_UNKNOWN ) return FALSE;
00182         if ( m_pTigerTree.IsAvailable() ) return TRUE;
00183 
00184         if ( ! m_pTigerTree.FromBytes( pTiger, nTiger,
00185                         Settings.Library.TigerHeight, m_nSize ) )
00186         {
00187                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TIGER_CORRUPT,
00188                         (LPCTSTR)GetDisplayName() );
00189                 return FALSE;
00190         }
00191 
00192         TIGEROOT pRoot;
00193         m_pTigerTree.GetRoot( &pRoot );
00194 
00195         if ( m_bTiger && m_pTiger != pRoot )
00196         {
00197                 m_pTigerTree.Clear();
00198                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TIGER_MISMATCH,
00199                         (LPCTSTR)GetDisplayName() );
00200                 return FALSE;
00201         }
00202         else if ( ! m_bTiger )
00203         {
00204                 m_bTiger = TRUE;
00205                 m_pTiger = pRoot;
00206         }
00207 
00208         m_nTigerSize    = m_pTigerTree.GetBlockLength();
00209         m_nTigerBlock   = m_pTigerTree.GetBlockCount();
00210         m_pTigerBlock   = new BYTE[ m_nTigerBlock ];
00211 
00212         ZeroMemory( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
00213 
00214         SetModified();
00215 
00216         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_READY,
00217                 (LPCTSTR)GetDisplayName(), m_pTigerTree.GetHeight(),
00218                 (LPCTSTR)Settings.SmartVolume( m_nTigerSize, FALSE ) );
00219 
00220         return TRUE;
00221 }
00222 
00223 CTigerTree* CDownloadWithTiger::GetTigerTree()
00224 {
00225         return m_pTigerTree.IsAvailable() ? &m_pTigerTree : NULL;
00226 }
00227 
00229 // CDownloadWithTiger eDonkey2000 hashset access
00230 
00231 BOOL CDownloadWithTiger::NeedHashset() const
00232 {
00233         return ( m_nSize < SIZE_UNKNOWN && m_pHashset.IsAvailable() == FALSE );
00234 }
00235 
00236 BOOL CDownloadWithTiger::SetHashset(BYTE* pSource, DWORD nSource)
00237 {
00238         if ( m_nSize == SIZE_UNKNOWN ) return FALSE;
00239         if ( m_pHashset.IsAvailable() ) return TRUE;
00240 
00241         if ( nSource == 0 && m_bED2K )
00242         {
00243                 m_pHashset.FromRoot( &m_pED2K );
00244         }
00245         else if ( m_pHashset.FromBytes( pSource, nSource, m_nSize ) )
00246         {
00247                 MD4 pRoot;
00248                 m_pHashset.GetRoot( &pRoot );
00249 
00250                 if ( m_bED2K && m_pED2K != pRoot )
00251                 {
00252                         m_pHashset.Clear();
00253                         theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_CORRUPT,
00254                                 (LPCTSTR)GetDisplayName() );
00255                         return FALSE;
00256                 }
00257                 else if ( ! m_bED2K )
00258                 {
00259                         m_bED2K = TRUE;
00260                         m_pED2K = pRoot;
00261                 }
00262         }
00263         else
00264         {
00265                 theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HASHSET_CORRUPT,
00266                         (LPCTSTR)GetDisplayName() );
00267                 return FALSE;
00268         }
00269 
00270         m_nHashsetBlock = m_pHashset.GetBlockCount();
00271         m_pHashsetBlock = new BYTE[ m_nHashsetBlock ];
00272 
00273         ZeroMemory( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
00274 
00275         SetModified();
00276 
00277         theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_HASHSET_READY,
00278                 (LPCTSTR)GetDisplayName(),
00279                 (LPCTSTR)Settings.SmartVolume( ED2K_PART_SIZE, FALSE ) );
00280 
00281         Neighbours.SendDonkeyDownload( reinterpret_cast<CDownload*>( this ) );
00282 
00283         return TRUE;
00284 }
00285 
00286 CED2K* CDownloadWithTiger::GetHashset()
00287 {
00288         return m_pHashset.IsAvailable() ? &m_pHashset : NULL;
00289 }
00290 
00292 // CDownloadWithTiger test if the file can finish
00293 
00294 BOOL CDownloadWithTiger::ValidationCanFinish() const
00295 {
00296         BOOL bAvailable = FALSE;
00297 
00298         if ( m_pTorrentBlock != NULL )
00299         {
00300                 if ( m_nTorrentSuccess >= m_nTorrentBlock ) return TRUE;
00301                 bAvailable = TRUE;
00302         }
00303 
00304         if ( m_pTigerBlock != NULL && Settings.Downloads.VerifyTiger )
00305         {
00306                 if ( m_nTigerSuccess >= m_nTigerBlock ) return TRUE;
00307                 bAvailable = TRUE;
00308         }
00309 
00310         if ( m_pHashsetBlock != NULL && Settings.Downloads.VerifyED2K )
00311         {
00312                 if ( m_nHashsetSuccess >= m_nHashsetBlock ) return TRUE;
00313                 bAvailable = TRUE;
00314         }
00315 
00316         return ! bAvailable;
00317 }
00318 
00320 // CDownloadWithTiger run validation
00321 
00322 void CDownloadWithTiger::RunValidation(BOOL bSeeding)
00323 {
00324         if ( m_pTigerBlock == NULL && m_pHashsetBlock == NULL && m_pTorrentBlock == NULL ) return;
00325         if ( m_sLocalName.IsEmpty() ) return;
00326 
00327         if ( ! bSeeding )
00328         {
00329                 if ( m_pFile == NULL || ! OpenFile() ) return;
00330         }
00331 
00332         if ( m_nVerifyHash > HASH_NULL && m_nVerifyBlock < 0xFFFFFFFF )
00333         {
00334                 Downloads.m_nValidation ++;
00335                 ContinueValidation();
00336         }
00337         else
00338         {
00339                 if ( FindNewValidationBlock( HASH_TORRENT ) ||
00340                          FindNewValidationBlock( HASH_TIGERTREE ) ||
00341                          FindNewValidationBlock( HASH_ED2K ) )
00342                 {
00343                         Downloads.m_nValidation ++;
00344                         ContinueValidation();
00345                 }
00346         }
00347 }
00348 
00350 // CDownloadWithTiger validation setup
00351 
00352 BOOL CDownloadWithTiger::FindNewValidationBlock(int nHash)
00353 {
00354         if ( nHash == HASH_TIGERTREE && ! Settings.Downloads.VerifyTiger ) return FALSE;
00355         if ( nHash == HASH_ED2K && ! Settings.Downloads.VerifyED2K ) return FALSE;
00356 
00357         DWORD nBlockCount;
00358         QWORD nBlockSize;
00359         BYTE* pBlockPtr;
00360 
00361         switch ( nHash )
00362         {
00363         case HASH_TIGERTREE:
00364                 if ( m_pTigerBlock == NULL ) return FALSE;
00365                 pBlockPtr       = m_pTigerBlock;
00366                 nBlockCount     = m_nTigerBlock;
00367                 nBlockSize      = m_nTigerSize;
00368                 break;
00369         case HASH_ED2K:
00370                 if ( m_pHashsetBlock == NULL ) return FALSE;
00371                 pBlockPtr       = m_pHashsetBlock;
00372                 nBlockCount     = m_nHashsetBlock;
00373                 nBlockSize      = ED2K_PART_SIZE;
00374                 break;
00375         case HASH_TORRENT:
00376                 if ( m_pTorrentBlock == NULL ) return FALSE;
00377                 pBlockPtr       = m_pTorrentBlock;
00378                 nBlockCount     = m_nTorrentBlock;
00379                 nBlockSize      = m_nTorrentSize;
00380                 break;
00381         default:
00382                 return FALSE;
00383         }
00384 
00385         DWORD nTarget = 0xFFFFFFFF;
00386 
00387         if ( m_pFile == NULL )
00388         {
00389                 for ( TRISTATE nState = TS_UNKNOWN ; nState < TS_TRUE ; nState++ )
00390                 {
00391                         for ( DWORD nBlock = 0 ; nBlock < nBlockCount ; nBlock ++ )
00392                         {
00393                                 if ( pBlockPtr[ nBlock ] == nState )
00394                                 {
00395                                         nTarget = nBlock;
00396                                         break;
00397                                 }
00398                         }
00399 
00400                         if ( nTarget != 0xFFFFFFFF ) break;
00401                 }
00402         }
00403         else
00404         {
00405                 DWORD nRetry = 0xFFFFFFFF;
00406                 QWORD nPrevious = 0;
00407 
00408         for ( FF::SimpleFragmentList::ConstIterator pFragment
00409             = m_pFile->GetEmptyFragmentList().begin();
00410             pFragment != m_pFile->GetEmptyFragmentList().end();
00411             ++pFragment )
00412         {
00413                         if ( pFragment->begin() - nPrevious >= nBlockSize )
00414                         {
00415                                 DWORD nBlock = (DWORD)( ( nPrevious + nBlockSize - 1 ) / nBlockSize );
00416                                 nPrevious = nBlockSize * (QWORD)nBlock + nBlockSize;
00417 
00418                                 for ( ; nPrevious <= pFragment->begin() ; nBlock ++, nPrevious += nBlockSize )
00419                                 {
00420                                         if ( pBlockPtr[ nBlock ] == TS_UNKNOWN )
00421                                         {
00422                                                 nTarget = nBlock;
00423                                                 break;
00424                                         }
00425                                         else if ( pBlockPtr[ nBlock ] == TS_FALSE && nRetry == 0xFFFFFFFF )
00426                                         {
00427                                                 nRetry = nBlock;
00428                                         }
00429                                 }
00430 
00431                                 if ( nTarget != 0xFFFFFFFF ) break;
00432                         }
00433 
00434                         nPrevious = pFragment->end();
00435                 }
00436 
00437                 if ( m_nSize > nPrevious && nTarget == 0xFFFFFFFF )
00438                 {
00439                         DWORD nBlock = (DWORD)( ( nPrevious + nBlockSize - 1 ) / nBlockSize );
00440                         nPrevious = nBlockSize * (QWORD)nBlock;
00441 
00442                         for ( ; nPrevious < m_nSize ; nBlock ++, nPrevious += nBlockSize )
00443                         {
00444                                 if ( pBlockPtr[ nBlock ] == TS_UNKNOWN )
00445                                 {
00446                                         nTarget = nBlock;
00447                                         break;
00448                                 }
00449                                 else if ( pBlockPtr[ nBlock ] == TS_FALSE && nRetry == 0xFFFFFFFF )
00450                                 {
00451                                         nRetry = nBlock;
00452                                 }
00453                         }
00454                 }
00455 
00456                 if ( nTarget == 0xFFFFFFFF ) nTarget = nRetry;
00457         }
00458 
00459         if ( nTarget != 0xFFFFFFFF )
00460         {
00461                 m_nVerifyHash   = nHash;
00462                 m_nVerifyBlock  = nTarget;
00463                 m_nVerifyOffset = nTarget * nBlockSize;
00464                 m_nVerifyLength = min( nBlockSize, m_nSize - m_nVerifyOffset );
00465                 m_tVerifyLast   = GetTickCount();
00466 
00467                 if ( m_nVerifyHash == HASH_TIGERTREE )
00468                         m_pTigerTree.BeginBlockTest();
00469                 else if ( m_nVerifyHash == HASH_ED2K )
00470                         m_pHashset.BeginBlockTest();
00471                 else if ( m_nVerifyHash == HASH_TORRENT )
00472                         m_pTorrent.BeginBlockTest();
00473 
00474                 return TRUE;
00475         }
00476 
00477         return FALSE;
00478 }
00479 
00481 // CDownloadWithTiger validation process
00482 
00483 void CDownloadWithTiger::ContinueValidation()
00484 {
00485         ASSERT( m_nVerifyHash > HASH_NULL );
00486         ASSERT( m_nVerifyBlock < 0xFFFFFFFF );
00487 
00488         BOOL bDone = ( m_pFile == NULL ) || ( m_pFile->GetRemaining() == 0 );
00489         HANDLE hComplete = INVALID_HANDLE_VALUE;
00490 
00491         if ( m_pFile == NULL )
00492         {
00493                 hComplete = CreateFile( m_sLocalName, GENERIC_READ,
00494                         FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
00495                         FILE_ATTRIBUTE_NORMAL, NULL );
00496                 if ( hComplete == INVALID_HANDLE_VALUE ) return;
00497         }
00498 
00499         for ( int nRound = bDone ? 10 : 2 ; nRound > 0 && m_nVerifyLength > 0 ; nRound-- )
00500         {
00501                 DWORD nChunk    = (DWORD)min( DWORD(m_nVerifyLength), Transfers.m_nBuffer );
00502                 LPBYTE pChunk   = Transfers.m_pBuffer;
00503 
00504                 if ( m_pFile != NULL )
00505                 {
00506                         m_pFile->ReadRange( m_nVerifyOffset, pChunk, nChunk );
00507                 }
00508                 else
00509                 {
00510                         LONG nOffsetHigh = (LONG)( m_nVerifyOffset >> 32 );
00511                         SetFilePointer( hComplete, (DWORD)( m_nVerifyOffset & 0xFFFFFFFF ), &nOffsetHigh, FILE_BEGIN );
00512                         ReadFile( hComplete, pChunk, nChunk, &nChunk, NULL );
00513                 }
00514 
00515                 if ( m_nVerifyHash == HASH_TIGERTREE )
00516                         m_pTigerTree.AddToTest( pChunk, (DWORD)nChunk );
00517                 else if ( m_nVerifyHash == HASH_ED2K )
00518                         m_pHashset.AddToTest( pChunk, (DWORD)nChunk );
00519                 else if ( m_nVerifyHash == HASH_TORRENT )
00520                         m_pTorrent.AddToTest( pChunk, (DWORD)nChunk );
00521                 else
00522                         ASSERT( FALSE );
00523 
00524                 m_nVerifyOffset += nChunk;
00525                 m_nVerifyLength -= nChunk;
00526         }
00527 
00528         if ( hComplete != INVALID_HANDLE_VALUE ) CloseHandle( hComplete );
00529         if ( m_nVerifyLength == 0 ) FinishValidation();
00530 }
00531 
00532 void CDownloadWithTiger::FinishValidation()
00533 {
00534     FF::SimpleFragmentList oCorrupted( m_nSize );
00535 
00536         if ( m_nVerifyHash == HASH_TIGERTREE )
00537         {
00538                 if ( m_pTigerTree.FinishBlockTest( m_nVerifyBlock ) )
00539                 {
00540                         m_pTigerBlock[ m_nVerifyBlock ] = TS_TRUE;
00541                         m_nTigerSuccess ++;
00542                 }
00543                 else
00544                 {
00545                         m_pTigerBlock[ m_nVerifyBlock ] = TS_FALSE;
00546 
00547             QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(m_nTigerSize);
00548             oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset,
00549                 ::std::min( nOffset + m_nTigerSize, m_nSize ) ) );
00550                 }
00551         }
00552         else if ( m_nVerifyHash == HASH_ED2K )
00553         {
00554                 if ( m_pHashset.FinishBlockTest( m_nVerifyBlock ) )
00555                 {
00556                         m_pHashsetBlock[ m_nVerifyBlock ] = TS_TRUE;
00557                         m_nHashsetSuccess ++;
00558                 }
00559                 else
00560                 {
00561                         m_pHashsetBlock[ m_nVerifyBlock ] = TS_FALSE;
00562 
00563             QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(ED2K_PART_SIZE);
00564             oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset,
00565                 ::std::min( nOffset + ED2K_PART_SIZE, m_nSize ) ) );
00566                 }
00567         }
00568         else if ( m_nVerifyHash == HASH_TORRENT )
00569         {
00570                 if ( m_pTorrent.FinishBlockTest( m_nVerifyBlock ) )
00571                 {
00572                         m_pTorrentBlock[ m_nVerifyBlock ] = TS_TRUE;
00573                         m_nTorrentSuccess ++;
00574 
00575                         OnFinishedTorrentBlock( m_nVerifyBlock );
00576                 }
00577                 else
00578                 {
00579                         m_pTorrentBlock[ m_nVerifyBlock ] = TS_FALSE;
00580 
00581             QWORD nOffset = QWORD(m_nVerifyBlock) * QWORD(m_nTorrentSize);
00582             oCorrupted.insert( oCorrupted.end(), FF::SimpleFragment( nOffset,
00583                 ::std::min( nOffset + m_nTorrentSize, m_nSize ) ) );
00584                 }
00585         }
00586 
00587         if ( !oCorrupted.empty() && m_pFile != NULL )
00588         {
00589                 if ( m_pTigerBlock != NULL )
00590                         SubtractHelper( oCorrupted, m_pTigerBlock, m_nTigerBlock, m_nTigerSize );
00591                 if ( m_pHashsetBlock != NULL )
00592                         SubtractHelper( oCorrupted, m_pHashsetBlock, m_nHashsetBlock, ED2K_PART_SIZE );
00593                 if ( m_pTorrentBlock != NULL )
00594                         SubtractHelper( oCorrupted, m_pTorrentBlock, m_nTorrentBlock, m_nTorrentSize );
00595 
00596         for ( FF::SimpleFragmentList::ConstIterator pRange = oCorrupted.begin();
00597             pRange != oCorrupted.end(); ++pRange )
00598                 {
00599                         m_pFile->InvalidateRange( pRange->begin(), pRange->length() );
00600                         RemoveOverlappingSources( pRange->begin(), pRange->length() );
00601                 }
00602 
00603     }
00604         m_nVerifyHash   = HASH_NULL;
00605         m_nVerifyBlock  = 0xFFFFFFFF;
00606         m_nVerifyCookie++;
00607 
00608         SetModified();
00609 }
00610 
00611 void CDownloadWithTiger::SubtractHelper(FF::SimpleFragmentList& ppCorrupted, BYTE* pBlock, QWORD nBlock, QWORD nSize)
00612 {
00613         QWORD nOffset = 0;
00614 
00615         while ( nBlock-- && !ppCorrupted.empty() )
00616         {
00617                 if ( *pBlock++ == TS_TRUE )
00618                 {
00619             ppCorrupted.erase( FF::SimpleFragment( nOffset, ::std::min( nOffset + nSize, m_nSize ) ) );
00620                 }
00621 
00622                 nOffset += nSize;
00623         }
00624 }
00625 
00627 // CDownloadWithTiger available ranges override
00628 
00629 CString CDownloadWithTiger::GetAvailableRanges() const
00630 {
00631         CString strRanges, strRange;
00632         QWORD nOffset, nLength;
00633         BOOL bSuccess;
00634 
00635         for ( nOffset = 0 ; GetNextVerifyRange( nOffset, nLength, bSuccess ) ; )
00636         {
00637                 if ( bSuccess )
00638                 {
00639                         if ( strRanges.IsEmpty() )
00640                                 strRanges = _T("bytes ");
00641                         else
00642                                 strRanges += ',';
00643 
00644                         strRange.Format( _T("%I64i-%I64i"), nOffset, nOffset + nLength - 1 );
00645                         strRanges += strRange;
00646                 }
00647 
00648                 nOffset += nLength;
00649         }
00650 
00651         if ( strRanges.IsEmpty() ) strRanges = CDownloadWithTorrent::GetAvailableRanges();
00652 
00653         return strRanges;
00654 }
00655 
00657 // CDownloadWithTiger clear data
00658 
00659 void CDownloadWithTiger::ResetVerification()
00660 {
00661         if ( m_nVerifyHash == HASH_TIGERTREE )
00662         {
00663                 m_pTigerTree.FinishBlockTest( m_nVerifyBlock );
00664         }
00665         else if ( m_nVerifyHash == HASH_ED2K )
00666         {
00667                 m_pHashset.FinishBlockTest( m_nVerifyBlock );
00668         }
00669         else if ( m_nVerifyHash == HASH_TORRENT )
00670         {
00671                 m_pTorrent.FinishBlockTest( m_nVerifyBlock );
00672         }
00673 
00674         if ( m_pTigerBlock != NULL ) ZeroMemory( m_pTigerBlock, m_nTigerBlock );
00675         if ( m_pHashsetBlock != NULL ) ZeroMemory( m_pHashsetBlock, m_nHashsetBlock );
00676         if ( m_pTorrentBlock != NULL ) ZeroMemory( m_pTorrentBlock, m_nTorrentBlock );
00677 
00678         m_nTigerSuccess         = 0;
00679         m_nHashsetSuccess       = 0;
00680         m_nTorrentSuccess       = 0;
00681 
00682         m_nVerifyHash           = HASH_NULL;
00683         m_nVerifyBlock          = 0xFFFFFFFF;
00684 
00685         m_nVerifyCookie++;
00686         SetModified();
00687 }
00688 
00689 void CDownloadWithTiger::ClearVerification()
00690 {
00691         ResetVerification();
00692 
00693         if ( m_pTigerBlock != NULL ) delete [] m_pTigerBlock;
00694         if ( m_pHashsetBlock != NULL ) delete [] m_pHashsetBlock;
00695 
00696         m_pTigerBlock           = NULL;
00697         m_nTigerBlock           = 0;
00698         m_pHashsetBlock         = NULL;
00699         m_nHashsetBlock         = 0;
00700 
00701         m_pTigerTree.Clear();
00702         m_pHashset.Clear();
00703 
00704         m_nVerifyCookie++;
00705         SetModified();
00706 }
00707 
00709 // CDownloadWithTiger serialize
00710 
00711 void CDownloadWithTiger::Serialize(CArchive& ar, int nVersion)
00712 {
00713         CDownloadWithTorrent::Serialize( ar, nVersion );
00714 
00715         m_pTigerTree.Serialize( ar );
00716 
00717         if ( m_pTigerTree.IsAvailable() )
00718         {
00719                 if ( ar.IsStoring() )
00720                 {
00721                         ar << m_nTigerBlock;
00722                         ar << m_nTigerSize;
00723                         ar << m_nTigerSuccess;
00724                         ar.Write( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
00725                 }
00726                 else
00727                 {
00728                         m_pTigerTree.SetupParameters( m_nSize );
00729 
00730                         ar >> m_nTigerBlock;
00731                         ar >> m_nTigerSize;
00732                         ar >> m_nTigerSuccess;
00733 
00734                         m_pTigerBlock = new BYTE[ m_nTigerBlock ];
00735                         ar.Read( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
00736                 }
00737         }
00738 
00739         if ( nVersion >= 19 )
00740         {
00741                 m_pHashset.Serialize( ar );
00742 
00743                 if ( m_pHashset.IsAvailable() )
00744                 {
00745                         if ( ar.IsStoring() )
00746                         {
00747                                 ar << m_nHashsetBlock;
00748                                 ar << m_nHashsetSuccess;
00749                                 ar.Write( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
00750                         }
00751                         else
00752                         {
00753                                 ar >> m_nHashsetBlock;
00754                                 ar >> m_nHashsetSuccess;
00755 
00756                                 m_pHashsetBlock = new BYTE[ m_nHashsetBlock ];
00757                                 ar.Read( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
00758                         }
00759                 }
00760         }
00761 
00762         if ( nVersion < 30 && m_bBTH )
00763         {
00764                 ClearVerification();
00765                 m_bSHA1 = m_bTiger = m_bED2K = FALSE;
00766         }
00767 }

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