📄 uploadtransferhttp.cpp
字号:
}
}
else if ( StartsWith( m_sRequest, _T("/gnutella/preview/v1?urn:") ) && Settings.Uploads.SharePreviews )
{
LPCTSTR pszURN = (LPCTSTR)m_sRequest + 21;
CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE, TRUE );
if ( pShared != NULL ) return RequestPreview( pShared );
}
else if ( StartsWith( m_sRequest, _T("/uri-res/N2R?urn:") ) )
{
LPCTSTR pszURN = (LPCTSTR)m_sRequest + 13;
if ( CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE, TRUE ) )
{
return RequestSharedFile( pShared );
}
CDownload* pDownload = Downloads.FindByURN( pszURN );
if ( pDownload != NULL && pDownload->IsShared() && pDownload->IsStarted() )
{
return RequestPartialFile( pDownload );
}
}
else if ( StartsWith( m_sRequest, _T("/get/") ) )
{
DWORD nIndex = 0;
CString strFile = m_sRequest.Mid( 5 );
int nChar = strFile.Find( '/' );
if ( _stscanf( strFile, _T("%lu/"), &nIndex ) == 1 && nChar > 0 && nChar < strFile.GetLength() - 1 )
{
strFile = strFile.Mid( nChar + 1 );
CLibraryFile* pFile = Library.LookupFile( nIndex, TRUE, TRUE, TRUE );
if ( pFile != NULL && pFile->m_sName.CompareNoCase( strFile ) )
{
Library.Unlock();
pFile = NULL;
}
if ( pFile == NULL )
{
pFile = LibraryMaps.LookupFileByName( strFile, TRUE, TRUE, TRUE );
}
if ( pFile != NULL ) return RequestSharedFile( pFile );
}
else
{
strFile = strFile.Mid( nChar + 1 );
CLibraryFile* pFile = LibraryMaps.LookupFileByName( strFile, TRUE, TRUE, TRUE );
if ( pFile != NULL ) return RequestSharedFile( pFile );
}
}
else
{
CString strFile = m_sRequest.Mid( 1 );
CLibraryFile* pFile = LibraryMaps.LookupFileByName( strFile, TRUE, TRUE, TRUE );
if ( pFile != NULL ) return RequestSharedFile( pFile );
}
if ( m_sFileName.IsEmpty() )
{
if ( m_bSHA1 ) m_sFileName = CSHA::HashToString( &m_pSHA1, TRUE );
}
SendResponse( IDR_HTML_FILENOTFOUND );
theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
return TRUE;
}
BOOL CUploadTransferHTTP::IsNetworkDisabled()
{
if ( Settings.Connection.RequireForTransfers == FALSE ) return FALSE;
if ( m_nGnutella == 2 )
{
if ( ! Settings.Gnutella2.EnableToday ) return TRUE;
}
else if ( m_nGnutella == 1 )
{
if ( ! Settings.Gnutella1.EnableToday ) return TRUE;
}
else
{
if ( ! Settings.Gnutella1.EnableToday &&
! Settings.Gnutella2.EnableToday ) return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CUploadTransferHTTP request a shared file
BOOL CUploadTransferHTTP::RequestSharedFile(CLibraryFile* pFile)
{
ASSERT( pFile != NULL );
if ( ! RequestComplete( pFile ) )
{
Library.Unlock();
SendResponse( IDR_HTML_HASHMISMATCH );
theApp.Message( MSG_ERROR, IDS_UPLOAD_HASH_MISMATCH, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
return TRUE;
}
m_bTigerTree = m_bTiger;
m_bMetadata = ( pFile->m_pMetadata != NULL && ( pFile->m_bMetadataAuto == FALSE || pFile->m_nVirtualSize > 0 ) );
if ( ! m_bSHA1 && ! m_bTiger && ! m_bED2K ) m_sLocations.Empty();
if ( m_nLength == SIZE_UNKNOWN ) m_nLength = m_nFileSize - m_nOffset;
if ( m_nOffset >= m_nFileSize || m_nOffset + m_nLength > m_nFileSize )
{
Library.Unlock();
SendResponse( IDR_HTML_BADRANGE );
theApp.Message( MSG_ERROR, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
return TRUE;
}
CString strLocations;
if ( Settings.Library.SourceMesh ) strLocations = pFile->GetAlternateSources( &m_pSourcesSent, 15, TRUE );
if ( m_sLocations.GetLength() ) pFile->AddAlternateSources( m_sLocations );
m_sLocations = strLocations;
Library.Unlock();
return QueueRequest();
}
//////////////////////////////////////////////////////////////////////
// CUploadTransferHTTP request a partial file
BOOL CUploadTransferHTTP::RequestPartialFile(CDownload* pDownload)
{
ASSERT( pDownload != NULL );
ASSERT( pDownload->IsStarted() );
if ( ! RequestPartial( pDownload ) )
{
SendResponse( IDR_HTML_HASHMISMATCH );
theApp.Message( MSG_ERROR, IDS_UPLOAD_HASH_MISMATCH, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
return TRUE;
}
ASSERT( m_nFileBase == 0 );
m_bTigerTree = ( m_bTiger && pDownload->GetTigerTree() != NULL );
m_bMetadata = ( pDownload->m_pXML != NULL );
if ( m_sLocations.GetLength() ) pDownload->AddSourceURLs( m_sLocations, TRUE );
if ( Settings.Library.SourceMesh ) m_sLocations = pDownload->GetSourceURLs( &m_pSourcesSent, 15, TRUE, NULL );
m_sRanges = pDownload->GetAvailableRanges();
if ( m_bRange && m_nOffset == 0 && m_nLength == SIZE_UNKNOWN )
{
pDownload->GetRandomRange( m_nOffset, m_nLength );
}
if ( m_nLength == SIZE_UNKNOWN ) m_nLength = m_nFileSize - m_nOffset;
if ( pDownload->ClipUploadRange( m_nOffset, m_nLength ) )
{
return QueueRequest();
}
if ( pDownload->IsMoving() )
{
if ( GetTickCount() - pDownload->m_tCompleted < 30000 )
{
m_pOutput->Print( "HTTP/1.1 503 Range Temporarily Unavailable\r\n" );
}
else
{
SendResponse( IDR_HTML_FILENOTFOUND );
theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
return TRUE;
}
}
else if ( pDownload->GetTransferCount() )
{
m_pOutput->Print( "HTTP/1.1 503 Range Temporarily Unavailable\r\n" );
}
else
{
m_pOutput->Print( "HTTP/1.1 416 Requested Range Unavailable\r\n" );
}
SendDefaultHeaders();
SendFileHeaders();
m_pOutput->Print( "Content-Length: 0\r\n" );
m_pOutput->Print( "\r\n" );
StartSending( upsResponse );
theApp.Message( MSG_DEFAULT, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CUploadTransferHTTP queue the request if necessary
BOOL CUploadTransferHTTP::QueueRequest()
{
if ( m_bHead ) return OpenFileSendHeaders();
AllocateBaseFile();
UINT nError = 0;
int nPosition = 0;
if ( Uploads.AllowMoreTo( &m_pHost.sin_addr ) )
{
if ( ( nPosition = UploadQueues.GetPosition( this, TRUE ) ) >= 0 )
{
ASSERT( m_pQueue != NULL );
ASSERT( m_pQueue->CanAccept( m_nProtocol, m_sFileName, m_nFileSize, m_bFilePartial, m_sFileTags ) );
if ( nPosition == 0 )
{
// Queued, and ready to send
return OpenFileSendHeaders();
}
else
{
// Queued, but must wait
}
}
else if ( UploadQueues.Enqueue( this ) )
{
ASSERT( m_pQueue != NULL );
ASSERT( m_pQueue->CanAccept( m_nProtocol, m_sFileName, m_nFileSize, m_bFilePartial, m_sFileTags ) );
nPosition = UploadQueues.GetPosition( this, TRUE );
ASSERT( nPosition >= 0 );
if ( nPosition == 0 )
{
// Queued, and ready to send
return OpenFileSendHeaders();
}
else if ( m_bQueueMe )
{
// Queued, but must wait
}
else
{
// Client can't queue, so dequeue and return busy
UploadQueues.Dequeue( this );
ASSERT( m_pQueue == NULL );
}
}
else
{
// Unable to queue anywhere
}
}
else
{
// Too many from this host
UploadQueues.Dequeue( this );
ASSERT( m_pQueue == NULL );
nError = IDS_UPLOAD_BUSY_HOST;
}
if ( m_pQueue != NULL )
{
CString strHeader, strName;
m_pOutput->Print( "HTTP/1.1 503 Busy Queued\r\n" );
SendDefaultHeaders();
SendFileHeaders();
DWORD nTimeScale = ( nPosition <= 2 ) ? 2000 : 1000;
CSingleLock pLock( &UploadQueues.m_pSection, TRUE );
if ( UploadQueues.Check( m_pQueue ) )
{
strName = m_pQueue->m_sName;
Replace( strName, _T("\""), _T("'") );
strHeader.Format( _T("X-Queue: position=%i,length=%i,limit=%i,pollMin=%lu,pollMax=%lu,id=\"%s\"\r\n"),
nPosition,
m_pQueue->GetQueuedCount(),
m_pQueue->GetTransferCount( TRUE ),
Settings.Uploads.QueuePollMin / nTimeScale,
Settings.Uploads.QueuePollMax / nTimeScale,
(LPCTSTR)strName );
theApp.Message( MSG_DEFAULT, IDS_UPLOAD_QUEUED, (LPCTSTR)m_sFileName,
(LPCTSTR)m_sAddress, nPosition, m_pQueue->GetQueuedCount(),
(LPCTSTR)strName );
}
pLock.Unlock();
m_pOutput->Print( strHeader );
m_pOutput->Print( "Content-Length: 0\r\n" );
m_pOutput->Print( "\r\n" );
StartSending( upsPreQueue );
}
else
{
SendResponse( IDR_HTML_BUSY, TRUE );
if ( ! nError ) nError = m_bQueueMe ? IDS_UPLOAD_BUSY_QUEUE : IDS_UPLOAD_BUSY_OLD;
theApp.Message( MSG_ERROR, nError, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CUploadTransferHTTP default response headers
void CUploadTransferHTTP::SendDefaultHeaders()
{
CString strLine = Settings.SmartAgent( Settings.General.UserAgent );
if ( strLine.GetLength() )
{
strLine = _T("Server: ") + strLine + _T("\r\n");
m_pOutput->Print( strLine );
}
if ( ! m_bInitiated )
{
strLine.Format( _T("Remote-IP: %s\r\n"),
(LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ) );
m_pOutput->Print( strLine );
}
if ( m_bKeepAlive )
{
m_pOutput->Print( "Connection: Keep-Alive\r\n" );
}
else
{
m_pOutput->Print( "Connection: Close\r\n" );
}
m_pOutput->Print( "Accept-Ranges: bytes\r\n" );
if ( m_nRequests <= 1 )
{
if ( m_bInitiated ) SendMyAddress();
strLine.Format( _T("X-PerHost: %lu\r\n"), Settings.Uploads.MaxPerHost );
m_pOutput->Print( strLine );
strLine = MyProfile.GetNick();
if ( strLine.GetLength() > 0 )
{
strLine = _T("X-Nick: ") + URLEncode( strLine ) + _T("\r\n");
m_pOutput->Print( strLine );
}
}
}
//////////////////////////////////////////////////////////////////////
// CUploadTransferHTTP file response headers
void CUploadTransferHTTP::SendFileHeaders()
{
CString strHeader;
if ( m_bSHA1 )
{
if ( m_bTiger )
{
strHeader = _T("X-Content-URN: urn:bitprint:")
+ CSHA::HashToString( &m_pSHA1, FALSE ) + '.'
+ CTigerNode::HashToString( &m_pTiger, FALSE ) + _T("\r\n");
}
else
{
strHeader = _T("X-Content-URN: ") + CSHA::HashToString( &m_pSHA1, TRUE ) + _T("\r\n");
}
m_pOutput->Print( strHeader );
}
else if ( m_bTiger )
{
strHeader = _T("X-Content-URN: ") + CTigerNode::HashToString( &m_pTiger, TRUE ) + _T("\r\n");
m_pOutput->Print( strHeader );
}
if ( m_bED2K )
{
strHeader = _T("X-Content-URN: ") + CED2K::HashToString( &m_pED2K, TRUE ) + _T("\r\n");
m_pOutput->Print( strHeader );
}
if ( m_bTigerTree && Settings.Uploads.ShareTiger )
{
strHeader = _T("X-Thex-URI: /gnutella/thex/v1?")
+ CTigerNode::HashToString( &m_pTiger, TRUE )
+ _T("&depth=9&ed2k=0\r\n");
m_pOutput->Print( strHeader );
}
if ( m_bMetadata )
{
strHeader = _T("X-Metadata-Path: /gnutella/metadata/v1?")
+ CTigerNode::HashToString( &m_pTiger, TRUE )
+ _T("\r\n");
m_pOutput->Print( strHeader );
}
if ( m_sRanges.GetLength() )
{
strHeader = _T("X-Available-Ranges: ") + m_sRanges + _T("\r\n");
m_pOutput->Print( strHeader );
}
if ( m_sLocations.GetLength() )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -