📄 downloadwithtiger.cpp
字号:
DWORD nTarget = 0xFFFFFFFF;
if ( m_pFile == NULL )
{
for ( TRISTATE nState = TS_UNKNOWN ; nState < TS_TRUE ; nState++ )
{
for ( DWORD nBlock = 0 ; nBlock < nBlockCount ; nBlock ++ )
{
if ( pBlockPtr[ nBlock ] == nState )
{
nTarget = nBlock;
break;
}
}
if ( nTarget != 0xFFFFFFFF ) break;
}
}
else
{
DWORD nRetry = 0xFFFFFFFF;
QWORD nPrevious = 0;
for ( CFileFragment* pFragment = m_pFile->GetFirstEmptyFragment() ; pFragment ; pFragment = pFragment->m_pNext )
{
if ( pFragment->m_nOffset - nPrevious >= nBlockSize )
{
DWORD nBlock = (DWORD)( ( nPrevious + nBlockSize - 1 ) / nBlockSize );
nPrevious = nBlockSize * (QWORD)nBlock + nBlockSize;
for ( ; nPrevious <= pFragment->m_nOffset ; nBlock ++, nPrevious += nBlockSize )
{
if ( pBlockPtr[ nBlock ] == TS_UNKNOWN )
{
nTarget = nBlock;
break;
}
else if ( pBlockPtr[ nBlock ] == TS_FALSE && nRetry == 0xFFFFFFFF )
{
nRetry = nBlock;
}
}
if ( nTarget != 0xFFFFFFFF ) break;
}
nPrevious = pFragment->m_nOffset + pFragment->m_nLength;
}
if ( m_nSize > nPrevious && nTarget == 0xFFFFFFFF )
{
DWORD nBlock = (DWORD)( ( nPrevious + nBlockSize - 1 ) / nBlockSize );
nPrevious = nBlockSize * (QWORD)nBlock;
for ( ; nPrevious < m_nSize ; nBlock ++, nPrevious += nBlockSize )
{
if ( pBlockPtr[ nBlock ] == TS_UNKNOWN )
{
nTarget = nBlock;
break;
}
else if ( pBlockPtr[ nBlock ] == TS_FALSE && nRetry == 0xFFFFFFFF )
{
nRetry = nBlock;
}
}
}
if ( nTarget == 0xFFFFFFFF ) nTarget = nRetry;
}
if ( nTarget != 0xFFFFFFFF )
{
m_nVerifyHash = nHash;
m_nVerifyBlock = nTarget;
m_nVerifyOffset = nTarget * nBlockSize;
m_nVerifyLength = min( nBlockSize, m_nSize - m_nVerifyOffset );
m_tVerifyLast = GetTickCount();
if ( m_nVerifyHash == HASH_TIGERTREE )
m_pTigerTree.BeginBlockTest();
else if ( m_nVerifyHash == HASH_ED2K )
m_pHashset.BeginBlockTest();
else if ( m_nVerifyHash == HASH_TORRENT )
m_pTorrent.BeginBlockTest();
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithTiger validation process
void CDownloadWithTiger::ContinueValidation()
{
ASSERT( m_nVerifyHash > HASH_NULL );
ASSERT( m_nVerifyBlock < 0xFFFFFFFF );
BOOL bDone = ( m_pFile == NULL ) || ( m_pFile->GetRemaining() == 0 );
HANDLE hComplete = INVALID_HANDLE_VALUE;
if ( m_pFile == NULL )
{
hComplete = CreateFile( m_sLocalName, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if ( hComplete == INVALID_HANDLE_VALUE ) return;
}
for ( int nRound = bDone ? 10 : 2 ; nRound > 0 && m_nVerifyLength > 0 ; nRound-- )
{
DWORD nChunk = (DWORD)min( m_nVerifyLength, Transfers.m_nBuffer );
LPBYTE pChunk = Transfers.m_pBuffer;
if ( m_pFile != NULL )
{
m_pFile->ReadRange( m_nVerifyOffset, pChunk, nChunk );
}
else
{
LONG nOffsetHigh = (LONG)( m_nVerifyOffset >> 32 );
SetFilePointer( hComplete, (DWORD)( m_nVerifyOffset & 0xFFFFFFFF ), &nOffsetHigh, FILE_BEGIN );
ReadFile( hComplete, pChunk, nChunk, &nChunk, NULL );
}
if ( m_nVerifyHash == HASH_TIGERTREE )
m_pTigerTree.AddToTest( pChunk, (DWORD)nChunk );
else if ( m_nVerifyHash == HASH_ED2K )
m_pHashset.AddToTest( pChunk, (DWORD)nChunk );
else if ( m_nVerifyHash == HASH_TORRENT )
m_pTorrent.AddToTest( pChunk, (DWORD)nChunk );
else
ASSERT( FALSE );
m_nVerifyOffset += nChunk;
m_nVerifyLength -= nChunk;
}
if ( hComplete != INVALID_HANDLE_VALUE ) CloseHandle( hComplete );
if ( m_nVerifyLength == 0 ) FinishValidation();
}
void CDownloadWithTiger::FinishValidation()
{
CFileFragment* pCorrupted = NULL;
if ( m_nVerifyHash == HASH_TIGERTREE )
{
if ( m_pTigerTree.FinishBlockTest( m_nVerifyBlock ) )
{
m_pTigerBlock[ m_nVerifyBlock ] = TS_TRUE;
m_nTigerSuccess ++;
}
else
{
m_pTigerBlock[ m_nVerifyBlock ] = TS_FALSE;
pCorrupted = CFileFragment::New();
pCorrupted->m_nOffset = m_nVerifyBlock * m_nTigerSize;
pCorrupted->m_nLength = min( m_nTigerSize, m_nSize - pCorrupted->m_nOffset );
}
}
else if ( m_nVerifyHash == HASH_ED2K )
{
if ( m_pHashset.FinishBlockTest( m_nVerifyBlock ) )
{
m_pHashsetBlock[ m_nVerifyBlock ] = TS_TRUE;
m_nHashsetSuccess ++;
}
else
{
m_pHashsetBlock[ m_nVerifyBlock ] = TS_FALSE;
pCorrupted = CFileFragment::New();
pCorrupted->m_nOffset = m_nVerifyBlock * ED2K_PART_SIZE;
pCorrupted->m_nLength = min( ED2K_PART_SIZE, m_nSize - pCorrupted->m_nOffset );
}
}
else if ( m_nVerifyHash == HASH_TORRENT )
{
if ( m_pTorrent.FinishBlockTest( m_nVerifyBlock ) )
{
m_pTorrentBlock[ m_nVerifyBlock ] = TS_TRUE;
m_nTorrentSuccess ++;
OnFinishedTorrentBlock( m_nVerifyBlock );
}
else
{
m_pTorrentBlock[ m_nVerifyBlock ] = TS_FALSE;
pCorrupted = CFileFragment::New();
pCorrupted->m_nOffset = m_nVerifyBlock * m_nTorrentSize;
pCorrupted->m_nLength = min( m_nTorrentSize, m_nSize - pCorrupted->m_nOffset );
}
}
if ( pCorrupted != NULL && m_pFile != NULL )
{
if ( m_pTigerBlock != NULL )
SubtractHelper( &pCorrupted, m_pTigerBlock, m_nTigerBlock, m_nTigerSize );
if ( m_pHashsetBlock != NULL )
SubtractHelper( &pCorrupted, m_pHashsetBlock, m_nHashsetBlock, ED2K_PART_SIZE );
if ( m_pTorrentBlock != NULL )
SubtractHelper( &pCorrupted, m_pTorrentBlock, m_nTorrentBlock, m_nTorrentSize );
for ( CFileFragment* pRange = pCorrupted ; pRange ; pRange = pRange->m_pNext )
{
m_pFile->InvalidateRange( pRange->m_nOffset, pRange->m_nLength );
RemoveOverlappingSources( pRange->m_nOffset, pRange->m_nLength );
}
pCorrupted->DeleteChain();
}
m_nVerifyHash = HASH_NULL;
m_nVerifyBlock = 0xFFFFFFFF;
m_nVerifyCookie++;
SetModified();
}
void CDownloadWithTiger::SubtractHelper(CFileFragment** ppCorrupted, BYTE* pBlock, QWORD nBlock, QWORD nSize)
{
QWORD nOffset = 0;
while ( nBlock-- && *ppCorrupted )
{
if ( *pBlock++ == TS_TRUE )
{
CFileFragment::Subtract( ppCorrupted, nOffset, nSize );
}
nOffset += nSize;
}
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithTiger available ranges override
CString CDownloadWithTiger::GetAvailableRanges() const
{
CString strRanges, strRange;
QWORD nOffset, nLength;
BOOL bSuccess;
for ( nOffset = 0 ; GetNextVerifyRange( nOffset, nLength, bSuccess ) ; )
{
if ( bSuccess )
{
if ( strRanges.IsEmpty() )
strRanges = _T("bytes ");
else
strRanges += ',';
strRange.Format( _T("%I64i-%I64i"), nOffset, nOffset + nLength - 1 );
strRanges += strRange;
}
nOffset += nLength;
}
if ( strRanges.IsEmpty() ) strRanges = CDownloadWithTorrent::GetAvailableRanges();
return strRanges;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithTiger clear data
void CDownloadWithTiger::ResetVerification()
{
if ( m_nVerifyHash == HASH_TIGERTREE )
{
m_pTigerTree.FinishBlockTest( m_nVerifyBlock );
}
else if ( m_nVerifyHash == HASH_ED2K )
{
m_pHashset.FinishBlockTest( m_nVerifyBlock );
}
else if ( m_nVerifyHash == HASH_TORRENT )
{
m_pTorrent.FinishBlockTest( m_nVerifyBlock );
}
if ( m_pTigerBlock != NULL ) ZeroMemory( m_pTigerBlock, m_nTigerBlock );
if ( m_pHashsetBlock != NULL ) ZeroMemory( m_pHashsetBlock, m_nHashsetBlock );
if ( m_pTorrentBlock != NULL ) ZeroMemory( m_pTorrentBlock, m_nTorrentBlock );
m_nTigerSuccess = 0;
m_nHashsetSuccess = 0;
m_nTorrentSuccess = 0;
m_nVerifyHash = HASH_NULL;
m_nVerifyBlock = 0xFFFFFFFF;
m_nVerifyCookie++;
SetModified();
}
void CDownloadWithTiger::ClearVerification()
{
ResetVerification();
if ( m_pTigerBlock != NULL ) delete [] m_pTigerBlock;
if ( m_pHashsetBlock != NULL ) delete [] m_pHashsetBlock;
m_pTigerBlock = NULL;
m_nTigerBlock = 0;
m_pHashsetBlock = NULL;
m_nHashsetBlock = 0;
m_pTigerTree.Clear();
m_pHashset.Clear();
m_nVerifyCookie++;
SetModified();
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithTiger serialize
void CDownloadWithTiger::Serialize(CArchive& ar, int nVersion)
{
CDownloadWithTorrent::Serialize( ar, nVersion );
m_pTigerTree.Serialize( ar );
if ( m_pTigerTree.IsAvailable() )
{
if ( ar.IsStoring() )
{
ar << m_nTigerBlock;
ar << m_nTigerSize;
ar << m_nTigerSuccess;
ar.Write( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
}
else
{
m_pTigerTree.SetupParameters( m_nSize );
ar >> m_nTigerBlock;
ar >> m_nTigerSize;
ar >> m_nTigerSuccess;
m_pTigerBlock = new BYTE[ m_nTigerBlock ];
ar.Read( m_pTigerBlock, sizeof(BYTE) * m_nTigerBlock );
}
}
if ( nVersion >= 19 )
{
m_pHashset.Serialize( ar );
if ( m_pHashset.IsAvailable() )
{
if ( ar.IsStoring() )
{
ar << m_nHashsetBlock;
ar << m_nHashsetSuccess;
ar.Write( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
}
else
{
ar >> m_nHashsetBlock;
ar >> m_nHashsetSuccess;
m_pHashsetBlock = new BYTE[ m_nHashsetBlock ];
ar.Read( m_pHashsetBlock, sizeof(BYTE) * m_nHashsetBlock );
}
}
}
if ( nVersion < 30 && m_bBTH )
{
ClearVerification();
m_bSHA1 = m_bTiger = m_bED2K = FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -