📄 downloadtransferhttp.cpp
字号:
}
else if ( strHeader.CompareNoCase( _T("X-Delete-Source") ) == 0 )
{
m_bBadResponse = TRUE;
}
else if ( strHeader.CompareNoCase( _T("X-Nick") ) == 0 ||
strHeader.CompareNoCase( _T("X-Name") ) == 0 ||
strHeader.CompareNoCase( _T("X-UserName") ) == 0 )
{
m_pSource->m_sNick = URLDecode( strValue );
}
else if ( strHeader.CompareNoCase( _T("X-Features") ) == 0 )
{
if ( _tcsistr( strValue, _T("g2/") ) != NULL ) m_pSource->SetGnutella( 2 );
if ( _tcsistr( strValue, _T("gnet2/") ) != NULL ) m_pSource->SetGnutella( 2 );
if ( _tcsistr( strValue, _T("gnutella2/") ) != NULL ) m_pSource->SetGnutella( 2 );
m_pSource->SetGnutella( 1 );
}
return CTransfer::OnHeaderLine( strHeader, strValue );
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP end of headers
BOOL CDownloadTransferHTTP::OnHeadersComplete()
{
if ( m_bBadResponse )
{
Close( TS_FALSE );
return FALSE;
}
else if ( ! m_pSource->CanInitiate( TRUE, TRUE ) )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DISABLED,
(LPCTSTR)m_pDownload->GetDisplayName(), (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
Close( TS_FALSE );
return FALSE;
}
else if ( m_bBusyFault )
{
m_nOffset = SIZE_UNKNOWN;
if ( Settings.Downloads.QueueLimit > 0 && m_nQueuePos > Settings.Downloads.QueueLimit )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUE_HUGE,
(LPCTSTR)m_sAddress, (LPCTSTR)m_pDownload->GetDisplayName(), m_nQueuePos );
Close( TS_FALSE );
return FALSE;
}
else if ( m_bQueueFlag && m_nRetryDelay >= 600000 )
{
m_pSource->m_tAttempt = GetTickCount() + m_nRetryDelay;
m_bQueueFlag = FALSE;
}
if ( m_bQueueFlag )
{
SetState( dtsFlushing );
m_tContent = m_mInput.tLast = GetTickCount();
return ReadFlush();
}
else
{
SetState( dtsBusy );
m_tRequest = GetTickCount();
return TRUE;
}
}
else if ( ! m_bGotRanges && ! m_bTigerFetch && ! m_bMetaFetch )
{
m_pSource->SetAvailableRanges( NULL );
}
if ( m_bRangeFault )
{
if ( m_pHost.sin_addr.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr )
{
Close( TS_FALSE );
return FALSE;
}
m_nOffset = SIZE_UNKNOWN;
SetState( dtsFlushing );
m_tContent = m_mInput.tLast = GetTickCount();
return ReadFlush();
}
else if ( m_nContentLength == SIZE_UNKNOWN )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE, (LPCTSTR)m_sAddress,
(LPCTSTR)m_pDownload->GetDisplayName() );
Close( TS_FALSE );
return FALSE;
}
else if ( m_bTigerFetch )
{
if ( ! m_bGotRange )
{
m_nOffset = 0;
m_nLength = m_nContentLength;
}
else if ( m_nOffset > 0 )
{
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_RANGE, (LPCTSTR)m_sAddress );
Close( TS_FALSE );
return FALSE;
}
if ( m_sContentType.CompareNoCase( _T("application/tigertree-breadthfirst") ) &&
m_sContentType.CompareNoCase( _T("application/dime") ) )
{
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_RANGE, (LPCTSTR)m_sAddress );
Close( TS_FALSE );
return FALSE;
}
SetState( dtsTiger );
m_tContent = m_mInput.tLast = GetTickCount();
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_TIGER_RECV, (LPCTSTR)m_sAddress,
(LPCTSTR)m_pSource->m_sServer );
return ReadTiger();
}
else if ( m_bMetaFetch )
{
if ( ! m_bGotRange )
{
m_nOffset = 0;
m_nLength = m_nContentLength;
}
SetState( dtsMetadata );
m_tContent = m_mInput.tLast = GetTickCount();
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_METADATA_RECV,
(LPCTSTR)m_sAddress, (LPCTSTR)m_pSource->m_sServer );
return ReadMetadata();
}
else if ( ! m_bGotRange )
{
if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
{
m_pDownload->m_nSize = m_nContentLength;
}
else if ( m_pDownload->m_nSize != m_nContentLength )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_SIZE, (LPCTSTR)m_sAddress,
(LPCTSTR)m_pDownload->GetDisplayName() );
Close( TS_FALSE );
return FALSE;
}
if ( m_nOffset == SIZE_UNKNOWN && ! m_pDownload->GetFragment( this ) )
{
Close( TS_TRUE );
return FALSE;
}
if ( ! m_pDownload->IsPositionEmpty( 0 ) )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_RANGE, (LPCTSTR)m_sAddress,
(LPCTSTR)m_pDownload->GetDisplayName() );
Close( TS_TRUE );
return FALSE;
}
m_nOffset = 0;
m_nLength = m_nContentLength;
}
if ( m_nContentLength != m_nLength )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_RANGE, (LPCTSTR)m_sAddress,
(LPCTSTR)m_pDownload->GetDisplayName() );
Close( TS_FALSE );
return FALSE;
}
if ( ! m_bKeepAlive ) m_pSource->m_bCloseConn = TRUE;
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_CONTENT, (LPCTSTR)m_sAddress,
(LPCTSTR)m_pSource->m_sServer );
SetState( dtsDownloading );
m_nPosition = 0;
m_tContent = m_mInput.tLast = GetTickCount();
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read content
BOOL CDownloadTransferHTTP::ReadContent()
{
if ( m_pInput->m_nLength > 0 )
{
m_pSource->SetValid();
DWORD nLength = (DWORD)min( (QWORD)m_pInput->m_nLength, m_nLength - m_nPosition );
BOOL bSubmit = FALSE;
if ( m_bRecvBackwards )
{
BYTE* pBuffer = new BYTE[ nLength ];
CBuffer::ReverseBuffer( m_pInput->m_pBuffer, pBuffer, nLength );
bSubmit = m_pDownload->SubmitData(
m_nOffset + m_nLength - m_nPosition - nLength, pBuffer, nLength );
delete [] pBuffer;
}
else
{
bSubmit = m_pDownload->SubmitData(
m_nOffset + m_nPosition, m_pInput->m_pBuffer, nLength );
}
m_pInput->Clear(); // Clear the buffer, we don't want any crap
m_nPosition += nLength;
m_nDownloaded += nLength;
if ( ! bSubmit && m_pDownload->GetProgress() < 0.95f )
{
BOOL bUseful = FALSE;
if ( m_bRecvBackwards )
{
bUseful = m_pDownload->IsRangeUseful( m_nOffset, m_nLength - m_nPosition );
}
else
{
bUseful = m_pDownload->IsRangeUseful( m_nOffset + m_nPosition, m_nLength - m_nPosition );
}
if ( /* m_bInitiated || */ ! bUseful )
{
theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_FRAGMENT_OVERLAP, (LPCTSTR)m_sAddress );
Close( TS_TRUE );
return FALSE;
}
}
}
if ( m_nPosition >= m_nLength )
{
m_pSource->AddFragment( m_nOffset, m_nLength );
return StartNextFragment();
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read Metadata
BOOL CDownloadTransferHTTP::ReadMetadata()
{
if ( m_pInput->m_nLength < m_nLength ) return TRUE;
CString strXML = m_pInput->ReadString( (DWORD)m_nLength, CP_UTF8 );
if ( CXMLElement* pXML = CXMLElement::FromString( strXML, TRUE ) )
{
if ( m_pDownload->m_pXML == NULL )
{
m_pDownload->m_pXML = pXML;
}
else
{
delete pXML;
}
}
m_pInput->Remove( (DWORD)m_nLength );
return StartNextFragment();
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read tiger tree
BOOL CDownloadTransferHTTP::ReadTiger()
{
if ( m_pInput->m_nLength < m_nLength ) return TRUE;
if ( m_sContentType.CompareNoCase( _T("application/tigertree-breadthfirst") ) == 0 )
{
m_pDownload->SetTigerTree( m_pInput->m_pBuffer, (DWORD)m_nLength );
m_pInput->Remove( (DWORD)m_nLength );
}
else if ( m_sContentType.CompareNoCase( _T("application/dime") ) == 0 )
{
CString strID, strType, strUUID = _T("x");
DWORD nFlags, nBody;
while ( m_pInput->ReadDIME( &nFlags, &strID, &strType, &nBody ) )
{
theApp.Message( MSG_DEBUG, _T("THEX DIME: %i, '%s', '%s', %i"),
nFlags, (LPCTSTR)strID, (LPCTSTR)strType, nBody );
if ( ( nFlags & 1 ) && strType.CompareNoCase( _T("text/xml") ) == 0 && nBody < 1024*1024 )
{
BOOL bSize = FALSE, bDigest = FALSE, bEncoding = FALSE;
CString strXML;
strXML = m_pInput->ReadString( nBody, CP_UTF8 );
if ( CXMLElement* pXML = CXMLElement::FromString( strXML ) )
{
if ( pXML->IsNamed( _T("hashtree") ) )
{
if ( CXMLElement* pxFile = pXML->GetElementByName( _T("file") ) )
{
QWORD nSize = 0;
_stscanf( pxFile->GetAttributeValue( _T("size") ), _T("%I64i"), &nSize );
bSize = ( nSize == m_pDownload->m_nSize );
}
if ( CXMLElement* pxDigest = pXML->GetElementByName( _T("digest") ) )
{
if ( pxDigest->GetAttributeValue( _T("algorithm") ).CompareNoCase( _T("http://open-content.net/spec/digest/tiger") ) == 0 )
{
bDigest = ( pxDigest->GetAttributeValue( _T("outputsize") ) == _T("24") );
}
}
if ( CXMLElement* pxTree = pXML->GetElementByName( _T("serializedtree") ) )
{
bEncoding = ( pxTree->GetAttributeValue( _T("type") ).CompareNoCase( _T("http://open-content.net/spec/thex/breadthfirst") ) == 0 );
strUUID = pxTree->GetAttributeValue( _T("uri") );
}
}
delete pXML;
}
theApp.Message( MSG_DEBUG, _T("THEX XML: size=%i, digest=%i, encoding=%i"),
bSize, bDigest, bEncoding );
if ( ! bSize || ! bDigest || ! bEncoding ) break;
}
else if ( strID == strUUID && strType.CompareNoCase( _T("http://open-content.net/spec/thex/breadthfirst") ) == 0 )
{
m_pDownload->SetTigerTree( m_pInput->m_pBuffer, nBody );
}
else if ( strType.CompareNoCase( _T("http://edonkey2000.com/spec/md4-hashset") ) == 0 )
{
m_pDownload->SetHashset( m_pInput->m_pBuffer, nBody );
}
m_pInput->Remove( ( nBody + 3 ) & ~3 );
if ( nFlags & 2 ) break;
}
m_pInput->Clear();
}
return StartNextFragment();
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read flushing
BOOL CDownloadTransferHTTP::ReadFlush()
{
if ( m_nContentLength == SIZE_UNKNOWN ) m_nContentLength = 0;
DWORD nRemove = min( m_pInput->m_nLength, (DWORD)m_nContentLength );
m_nContentLength -= nRemove;
m_pInput->Remove( nRemove );
if ( m_nContentLength == 0 )
{
if ( m_bQueueFlag )
{
SetState( dtsQueued );
m_tRequest = GetTickCount() + m_nRetryDelay;
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_QUEUED,
(LPCTSTR)m_sAddress, m_nQueuePos, m_nQueueLen,
(LPCTSTR)m_sQueueName );
}
else
{
return StartNextFragment();
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP dropped connection handler
void CDownloadTransferHTTP::OnDropped(BOOL bError)
{
if ( m_nState == dtsConnecting )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_CONNECT_ERROR, (LPCTSTR)m_sAddress );
if ( m_pSource != NULL ) m_pSource->PushRequest();
Close( TS_UNKNOWN );
}
else if ( m_nState == dtsBusy )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
Close( TS_TRUE );
}
else
{
// if ( m_nState == dtsDownloading && m_nLength && m_pSource )
// m_pSource->m_bCloseConn = TRUE;
if ( m_bBusyFault || m_bQueueFlag )
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
Close( TS_TRUE );
}
else
{
theApp.Message( MSG_ERROR, IDS_DOWNLOAD_DROPPED, (LPCTSTR)m_sAddress );
Close( m_nState >= dtsDownloading ? TS_TRUE : TS_UNKNOWN );
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -