⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloadtransferhttp.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		{
			theApp.Message( MSG_ERROR, IDS_CONNECTION_TIMEOUT_CONNECT, (LPCTSTR)m_sAddress );
			if ( m_pSource != NULL ) m_pSource->PushRequest();
			Close( TS_UNKNOWN );
			return FALSE;
		}
		break;

	case dtsRequesting:
	case dtsHeaders:
		if ( tNow - m_tRequest > Settings.Connection.TimeoutHandshake )
		{
			theApp.Message( MSG_ERROR, IDS_DOWNLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
			Close( m_bBusyFault || m_bQueueFlag ? TS_TRUE : TS_UNKNOWN );
			return FALSE;
		}
		break;

	case dtsDownloading:
	case dtsFlushing:
	case dtsTiger:
	case dtsMetadata:
		if ( tNow - m_mInput.tLast > Settings.Connection.TimeoutTraffic * 2 )
		{
			theApp.Message( MSG_ERROR, IDS_DOWNLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
			Close( TS_TRUE );
			return FALSE;
		}
		break;

	case dtsBusy:
		if ( tNow - m_tRequest > 1000 )
		{
			theApp.Message( MSG_ERROR, IDS_DOWNLOAD_BUSY, (LPCTSTR)m_sAddress, Settings.Downloads.RetryDelay / 1000 );
			Close( TS_TRUE );
			return FALSE;
		}
		break;

	case dtsQueued:
		if ( tNow >= m_tRequest )
		{
			return StartNextFragment();
		}
		break;

	}

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read handler

BOOL CDownloadTransferHTTP::OnRead()
{
	CDownloadTransfer::OnRead();
	
	switch ( m_nState )
	{
	case dtsRequesting:
		if ( ! ReadResponseLine() ) return FALSE;
		if ( m_nState != dtsHeaders ) break;

	case dtsHeaders:
		if ( ! ReadHeaders() ) return FALSE;
		if ( m_nState != dtsDownloading ) break;

	case dtsDownloading:
		return ReadContent();

	case dtsTiger:
		return ReadTiger();

	case dtsMetadata:
		return ReadMetadata();

	case dtsFlushing:
		return ReadFlush();

	}

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read response line

BOOL CDownloadTransferHTTP::ReadResponseLine()
{
	CString strLine, strCode, strMessage;
	
	if ( ! m_pInput->ReadLine( strLine ) ) return TRUE;
	if ( strLine.IsEmpty() ) return TRUE;

	if ( strLine.GetLength() > 512 ) strLine = _T("#LINE_TOO_LONG#");
	
	theApp.Message( MSG_DEBUG, _T("%s: DOWNLOAD RESPONSE: %s"), (LPCTSTR)m_sAddress, (LPCTSTR)strLine );
	
	if ( strLine.GetLength() >= 12 && strLine.Left( 9 ) == _T("HTTP/1.1 ") )
	{
		strCode		= strLine.Mid( 9, 3 );
		strMessage	= strLine.Mid( 12 );
	}
	else if ( strLine.GetLength() >= 12 && strLine.Left( 9 ) == _T("HTTP/1.0 ") )
	{
		strCode		= strLine.Mid( 9, 3 );
		strMessage	= strLine.Mid( 12 );
	}
	else if ( strLine.GetLength() >= 8 && strLine.Left( 4 ) == _T("HTTP") )
	{
		strCode		= strLine.Mid( 5, 3 );
		strMessage	= strLine.Mid( 8 );
	}
	else
	{
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_NOHTTP, (LPCTSTR)m_sAddress );
		Close( TS_FALSE );
		return FALSE;
	}
	
	if ( strCode == _T("200") || strCode == _T("206") )
	{
		SetState( dtsHeaders );
	}
	else if ( strCode == _T("503") )
	{
		if ( _tcsistr( strMessage, _T("range") ) != NULL )
		{
			m_bRangeFault = TRUE;
		}
		else
		{
			m_bBusyFault = TRUE;
		}
		
		SetState( dtsHeaders );
	}
	else if ( strCode == _T("416") )
	{
		m_bRangeFault = TRUE;
		SetState( dtsHeaders );
	}
	else if ( FALSE && ( strCode == _T("301") || strCode == _T("302") ) )
	{
		// TODO: Read "Location:" header and re-request
	}
	else
	{
		strMessage.TrimLeft();
		if ( strMessage.GetLength() > 128 ) strMessage = _T("No Message");
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_HTTPCODE, (LPCTSTR)m_sAddress,
			(LPCTSTR)strCode, (LPCTSTR)strMessage );
		SetState( dtsHeaders );
		m_bBadResponse = TRUE;
	}
	
	m_pHeaderName.RemoveAll();
	m_pHeaderValue.RemoveAll();
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CDownloadTransferHTTP read header lines

BOOL CDownloadTransferHTTP::OnHeaderLine(CString& strHeader, CString& strValue)
{
	theApp.Message( MSG_DEBUG, _T("%s: DOWNLOAD HEADER: %s: %s"), (LPCTSTR)m_sAddress, (LPCTSTR)strHeader, (LPCTSTR)strValue );
	
	if ( strHeader.CompareNoCase( _T("Server") ) == 0 )
	{
		m_sUserAgent = strValue;
		
		if ( IsAgentBlocked() )
		{
			Close( TS_FALSE );
			return FALSE;
		}
		
		m_pSource->m_sServer = strValue;
		if ( strValue.GetLength() > 64 ) strValue = strValue.Left( 64 );
		
		if ( _tcsistr( m_sUserAgent, _T("shareaza") ) != NULL ) m_pSource->SetGnutella( 3 );
		if ( _tcsistr( m_sUserAgent, _T("trustyfiles") ) != NULL ) m_pSource->SetGnutella( 3 );
		if ( _tcsistr( m_sUserAgent, _T("gnucdna") ) != NULL ) m_pSource->SetGnutella( 3 );
		if ( _tcsistr( m_sUserAgent, _T("adagio") ) != NULL ) m_pSource->SetGnutella( 2 );
	}
	else if ( strHeader.CompareNoCase( _T("Connection") ) == 0 )
	{
		if ( strValue.CompareNoCase( _T("Keep-Alive") ) == 0 ) m_bKeepAlive = TRUE;
	}
	else if ( strHeader.CompareNoCase( _T("Content-Length") ) == 0 )
	{
		_stscanf( strValue, _T("%I64i"), &m_nContentLength );
	}
	else if ( strHeader.CompareNoCase( _T("Content-Range") ) == 0 )
	{
		QWORD nFirst = 0, nLast = 0, nTotal = 0;
		
		if ( _stscanf( strValue, _T("bytes %I64i-%I64i/%I64i"), &nFirst, &nLast, &nTotal ) != 3 )
			_stscanf( strValue, _T("bytes=%I64i-%I64i/%I64i"), &nFirst, &nLast, &nTotal );
		
		if ( m_pDownload->m_nSize == SIZE_UNKNOWN )
		{
			m_pDownload->m_nSize = nTotal;
		}
		else if ( m_bTigerFetch || m_bMetaFetch )
		{
			m_nOffset = nFirst;
			m_nLength = nLast + 1 - nFirst;
			if ( m_nContentLength == SIZE_UNKNOWN ) m_nContentLength = m_nLength;
			return TRUE;
		}
		else if ( m_pDownload->m_nSize != nTotal )
		{
			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;
		}
		
		BOOL bUseful = m_pDownload->IsPositionEmpty( nFirst );
		// BOOL bUseful = m_pDownload->IsRangeUseful( nFirst, nLast - nFirst + 1 );
		
		if ( nFirst == m_nOffset && nLast == m_nOffset + m_nLength - 1 && bUseful )
		{
			// Perfect match, good
		}
		else if ( nFirst >= m_nOffset && nFirst < m_nOffset + m_nLength && bUseful )
		{
			m_nOffset = nFirst;
			m_nLength = nLast - nFirst + 1;
			
			theApp.Message( MSG_DEFAULT, IDS_DOWNLOAD_USEFUL_RANGE, (LPCTSTR)m_sAddress,
				m_nOffset, m_nOffset + m_nLength - 1, (LPCTSTR)m_pDownload->GetDisplayName() );
		}
		else
		{
			theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_RANGE, (LPCTSTR)m_sAddress,
				(LPCTSTR)m_pDownload->GetDisplayName() );
			Close( TS_TRUE );
			
			return FALSE;
		}
		
		if ( m_nContentLength == SIZE_UNKNOWN ) m_nContentLength = m_nLength;
		m_bGotRange = TRUE;
	}
	else if ( strHeader.CompareNoCase( _T("Content-Type") ) == 0 )
	{
		m_sContentType = strValue;
	}
	else if ( strHeader.CompareNoCase( _T("Content-Encoding") ) == 0 )
	{
		if ( Settings.Downloads.AllowBackwards && _tcsistr( strValue, _T("backwards") ) ) m_bRecvBackwards = TRUE;
	}
	else if (	strHeader.CompareNoCase( _T("X-Gnutella-Content-URN") ) == 0 ||
				strHeader.CompareNoCase( _T("X-Content-URN") ) == 0 ||
				strHeader.CompareNoCase( _T("Content-URN") ) == 0 )
	{
		for ( CString strURNs = strValue + ',' ; ; )
		{
			int nPos = strURNs.Find( ',' );
			if ( nPos < 0 ) break;
			
			strValue	= strURNs.Left( nPos );
			strURNs		= strURNs.Mid( nPos + 1 );
			strValue.TrimLeft();
			
			SHA1 pSHA1;
			if ( CSHA::HashFromURN( strValue, &pSHA1 ) )
			{
				if ( m_pSource->CheckHash( &pSHA1 ) )
				{
					m_bHashMatch = TRUE;
				}
				else
				{
					theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress,
						(LPCTSTR)m_pDownload->GetDisplayName() );
					Close( TS_FALSE );
					return FALSE;
				}
			}
			
			// TODO: Remove " ! m_bHashMatch "
			
			TIGEROOT pTiger;
			if ( ! m_bHashMatch && CTigerNode::HashFromURN( strValue, &pTiger ) )
			{
				if ( m_pSource->CheckHash( &pTiger ) )
				{
					m_bHashMatch = TRUE;
				}
				else
				{
					theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress,
						(LPCTSTR)m_pDownload->GetDisplayName() );
					Close( TS_FALSE );
					return FALSE;
				}
			}
			
			MD4 pED2K;
			if ( CED2K::HashFromURN( strValue, &pED2K ) )
			{
				if ( m_pSource->CheckHash( &pED2K ) )
				{
					m_bHashMatch = TRUE;
				}
				else
				{
					theApp.Message( MSG_ERROR, IDS_DOWNLOAD_WRONG_HASH, (LPCTSTR)m_sAddress,
						(LPCTSTR)m_pDownload->GetDisplayName() );
					Close( TS_FALSE );
					return FALSE;
				}
			}
		}
		m_pSource->SetGnutella( 1 );
	}
	else if ( strHeader.CompareNoCase( _T("X-Metadata-Path") ) == 0 )
	{
		if ( ! m_bMetaIgnore && Settings.Downloads.Metadata ) m_sMetadata = strValue;
	}
	else if ( strHeader.CompareNoCase( _T("X-TigerTree-Path") ) == 0 )
	{
		if ( Settings.Downloads.VerifyTiger && ! m_bTigerIgnore && m_sTigerTree.IsEmpty() )
		{
			if ( strValue.Find( _T("tigertree/v1") ) < 0 &&
				 strValue.Find( _T("tigertree/v2") ) < 0 )
			{
				m_sTigerTree = strValue;
			}
		}
	}
	else if ( strHeader.CompareNoCase( _T("X-Thex-URI") ) == 0 )
	{
		if ( Settings.Downloads.VerifyTiger && ! m_bTigerIgnore )
		{
			if ( StartsWith( strValue, _T("/") ) )
			{
				m_sTigerTree = strValue.SpanExcluding( _T("; ") );
				Replace( m_sTigerTree, _T("ed2k=0"), _T("ed2k=1") );
			}
		}
		m_pSource->SetGnutella( 1 );
	}
	else if (	strHeader.CompareNoCase( _T("X-Gnutella-Alternate-Location") ) == 0 ||
				strHeader.CompareNoCase( _T("Alt-Location") ) == 0 ||
				strHeader.CompareNoCase( _T("X-Alt") ) == 0 )
	{
		if ( Settings.Library.SourceMesh )
		{
			if ( strValue.Find( _T("Zhttp://") ) < 0 )
			{
				m_pDownload->AddSourceURLs( strValue, m_bHashMatch );
			}
		}
		m_pSource->SetGnutella( 1 );
	}
	else if ( strHeader.CompareNoCase( _T("X-Available-Ranges") ) == 0 )
	{
		m_bGotRanges = TRUE;
		m_pSource->SetAvailableRanges( strValue );
		m_pSource->SetGnutella( 1 );
	}
	else if ( strHeader.CompareNoCase( _T("X-Queue") ) == 0 )
	{
		m_pSource->SetGnutella( 1 );
		
		m_bQueueFlag = TRUE;
		strValue.MakeLower();
		
		int nPos = strValue.Find( _T("position=") );
		if ( nPos >= 0 ) _stscanf( strValue.Mid( nPos + 9 ), _T("%i"), &m_nQueuePos );
		
		nPos = strValue.Find( _T("length=") );
		if ( nPos >= 0 ) _stscanf( strValue.Mid( nPos + 7 ), _T("%i"), &m_nQueueLen );
		
		DWORD nLimit;
		
		nPos = strValue.Find( _T("pollmin=") );
		if ( nPos >= 0 && _stscanf( strValue.Mid( nPos + 8 ), _T("%lu"), &nLimit ) == 1 )
		{
			m_nRetryDelay = max( m_nRetryDelay, nLimit * 1000 + 3000  );
		}
		
		nPos = strValue.Find( _T("pollmax=") );
		if ( nPos >= 0 && _stscanf( strValue.Mid( nPos + 8 ), _T("%lu"), &nLimit ) == 1 )
		{
			m_nRetryDelay = min( m_nRetryDelay, nLimit * 1000 - 8000 );
		}

		nPos = strValue.Find( _T("id=") );
		if ( nPos >= 0 )
		{
			m_sQueueName = strValue.Mid( nPos + 3 );
			m_sQueueName.TrimLeft();
			if ( m_sQueueName.Find( '\"' ) == 0 )
			{
				m_sQueueName = m_sQueueName.Mid( 1 ).SpanExcluding( _T("\"") );
			}
			else
			{
				m_sQueueName = m_sQueueName.SpanExcluding( _T("\" ") );
			}
			if ( m_sQueueName == _T("s") ) m_sQueueName = _T("Small Queue");
			else if ( m_sQueueName == _T("l") ) m_sQueueName = _T("Large Queue");
		}
	}
	else if (	strHeader.CompareNoCase( _T("X-PerHost") ) == 0 ||
				strHeader.CompareNoCase( _T("X-Gnutella-maxSlotsPerHost") ) == 0 )
	{
		int nLimit = 0;
		
		if ( _stscanf( strValue, _T("%lu"), &nLimit ) != 1 )
		{
			Downloads.SetPerHostLimit( &m_pHost.sin_addr, nLimit );
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -