Exemple #1
0
void AsioTcpSocket::Send(ptr<File> file, ptr<SendHandler> sendHandler)
{
	BEGIN_TRY();

	CriticalCode cc(cs);

	// если запланировано закрытие передачи, то больше в очередь добавлять ничего нельзя
	if(sendClosed)
		THROW("Sending closed");

	bool queueWasEmpty = sendQueue.empty();

	// добавить элемент в очередь
	sendQueue.push_back(SendItem(file, sendHandler));

	// сбросить количество переданных данных в первом элементе,
	// если очередь была пуста (то есть первый элемент как раз
	// был добавлен)
	// также, если очередь была пуста, начать отправку
	if(queueWasEmpty)
	{
		firstItemSent = 0;
		StartSending();
	}

	END_TRY("Can't send data to Asio TCP socket");
}
Exemple #2
0
void AsioTcpSocket::End()
{
	CriticalCode cc(cs);

	if(!sendClosed)
	{
		sendClosed = true;

		if(sendQueue.empty())
			StartSending();
	}
}
BOOL CUploadTransferDC::RequestTigerTree(CLibraryFile* pFile, QWORD nOffset, QWORD nLength)
{
	m_pXML.Clear();

	if ( ! RequestComplete( pFile ) )
	{
		ASSERT( FALSE );
		return FALSE;
	}

	theApp.Message( MSG_INFO, IDS_UPLOAD_TIGER_SEND, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress );

	CAutoPtr< CTigerTree > pTigerTree( pFile->GetTigerTree() );
	if ( ! pTigerTree )
		return FALSE;

	BYTE* pSerialTree = NULL;
	DWORD nSerialTree = 0;
	if ( ! pTigerTree->ToBytesLevel1( &pSerialTree, &nSerialTree ) )
		return FALSE;

	if ( nOffset >= nSerialTree )
		nLength = SIZE_UNKNOWN;
	else
		nLength = min( ( ( nLength == SIZE_UNKNOWN ) ? nSerialTree : nLength ), nSerialTree - nOffset );

	if ( nLength > nSerialTree || nOffset + nLength > nSerialTree )
	{
		GlobalFree( pSerialTree );
		return FALSE;
	}

	CString strAnswer;
	strAnswer.Format( _T("$ADCSND tthl TTH/%s %I64u %I64u|"),
		m_oTiger.toString(), nOffset, nLength );

	m_pClient->SendCommand( strAnswer );

	m_pClient->Write( pSerialTree + nOffset, nLength );

	// Start uploading
	m_nOffset = nOffset;
	m_nLength = nLength;
	m_nPosition = 0;

	StartSending( upsTigerTree );

	GlobalFree( pSerialTree );

	return TRUE;
}
BOOL CUploadTransferDC::SendFile()
{
	if ( ! OpenFile() )
	{
		theApp.Message( MSG_ERROR, IDS_UPLOAD_CANTOPEN, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress );

		m_pClient->SendCommand( FILE_NOT_AVAILABLE );

		return FALSE;
	}

	if ( m_bGet )
	{
		m_bGet = FALSE;
	}
	else
	{
		CString strAnswer;
		strAnswer.Format( _T("$ADCSND file TTH/%s %I64u %I64u|"), m_oTiger.toString(), m_nOffset, m_nLength );

		m_pClient->SendCommand( strAnswer );
	}

	StartSending( upsUploading );

	if ( m_pBaseFile->m_nRequests++ == 0 )
	{
		theApp.Message( MSG_NOTICE, IDS_UPLOAD_FILE, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress );

		//ASSERT( m_pBaseFile->m_sPath.GetLength() );
		PostMainWndMessage( WM_NOWUPLOADING, 0, (LPARAM)new CString( m_pBaseFile->m_sPath ) );
	}

	theApp.Message( MSG_INFO, IDS_UPLOAD_CONTENT, m_nOffset, m_nOffset + m_nLength - 1, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );

	return TRUE;
}
Exemple #5
0
void AsioTcpSocket::Sent(const boost::system::error_code& error, size_t transferred)
{
	// если произошла ошибка
	if(error)
	{
		ptr<Exception> exception = AsioService::ConvertError(error);

		// отправить её всем элементам в очереди, и очистить очередь

		// скопируем обработчики в вектор, чтобы вызывать их
		// вне блокировки, и обеспечить реентрантность
		std::vector<ptr<SendHandler> > handlers;
		{
			CriticalCode cc(cs);
			handlers.resize(sendQueue.size());
			size_t j = 0;
			for(std::deque<SendItem>::iterator i = sendQueue.begin(); i != sendQueue.end(); ++i)
				handlers[j++] = i->handler;
			sendQueue.clear();
		}

		for(size_t j = 0; j < handlers.size(); ++j)
			if(handlers[j])
				handlers[j]->FireError(exception);

		return;
	}
	// ошибки нет
	else
	{
		// уведомить все завершившиеся файлы, и удалить их из очереди

		// скопируем обработчики в вектор, чтобы вызывать их
		// вне блокировки, и обеспечить реентрантность
		std::vector<ptr<SendHandler> > handlers;
		{
			CriticalCode cc(cs);
			std::deque<SendItem>::iterator i;
			for(i = sendQueue.begin(); i != sendQueue.end(); ++i)
			{
				const SendItem& item = *i;
				// если элемент не передался полностью, закончить
				size_t itemDataSkip = i == sendQueue.begin() ? firstItemSent : 0;
				size_t itemSize = item.data->GetSize() - itemDataSkip;
				if(itemSize > transferred)
				{
					// этот элемент теперь будет первым, выставить новое смещение
					firstItemSent = itemDataSkip + transferred;
					break;
				}
				// иначе передался полностью
				transferred -= itemSize;
				// добавить обработчик в массив
				if(item.handler)
					handlers.push_back(item.handler);
			}
			// теперь i указывает на первый элемент, который ещё не передался
			// удалить всё, что до него
			sendQueue.erase(sendQueue.begin(), i);

			// если в очереди что-то есть, запустить отправку снова
			StartSending();
		}

		for(size_t j = 0; j < handlers.size(); ++j)
			handlers[j]->FireSuccess();
	}
}
BOOL CUploadTransferDC::RequestFileList(BOOL bFile, BOOL bZip, const std::string& strFilename, QWORD nOffset, QWORD nLength)
{
	m_pXML.Clear();

	theApp.Message( MSG_NOTICE, IDS_UPLOAD_BROWSE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );

	BOOL bBZip = bFile && ( strFilename == "files.xml.bz2" );
	m_sName = ( bFile ? "/" : strFilename.c_str() );

	// Create library file list
	CAutoPtr< CXMLElement > pXML( LibraryFolders.CreateXML( m_sName, TRUE, xmlDC ) );
	if ( ! pXML )
		return FALSE;	// Out of memory

	m_pXML.Print( pXML->ToString( TRUE, TRUE, TRUE, TRI_TRUE ), CP_UTF8 );

	// ToDo: Implement partial request of file list
	nOffset = 0;
	nLength = m_pXML.m_nLength;

	if ( bBZip )
	{
		// BZip it
		if ( ! m_pXML.BZip() )
			return FALSE;	// Out of memory

		bZip = FALSE;
		nLength = m_pXML.m_nLength;
	}

	if ( bZip )
	{
		// Zip it
		if ( ! m_pXML.Deflate() )
			return FALSE;	// Out of memory
	}

	m_nOffset = nOffset;
	m_nLength = m_pXML.m_nLength;
	m_nPosition = 0;

	if ( m_bGet )
	{
		CString strAnswer;
		strAnswer.Format( _T("$FileLength %I64u|"), nLength );

		m_pClient->SendCommand( strAnswer );

		return TRUE;
	}

	CString strAnswer;
	strAnswer.Format( _T("$ADCSND %hs %hs %I64u %I64u%hs|"),
		( bFile ? "file" : "list" ), strFilename.c_str(),
		nOffset, nLength, ( bZip ? " ZL1" : "") );

	m_pClient->SendCommand( strAnswer );

	StartSending( upsBrowse );

	m_pClient->Write( &m_pXML );

	m_pXML.Clear();

	return TRUE;
}
BOOL CUploadTransferDC::RequestFile(CLibraryFile* pFile, QWORD nOffset, QWORD nLength)
{
	m_pXML.Clear();

	if ( ! RequestComplete( pFile ) )
	{
		ASSERT( FALSE );
		return FALSE;
	}

	if ( ! UploadQueues.CanUpload( PROTOCOL_DC, pFile, FALSE ) )
	{
		theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sName );

		m_pClient->SendCommand( FILE_NOT_AVAILABLE );

		return TRUE;
	}

	m_nOffset = nOffset;
	if ( m_nOffset >= m_nSize )
		m_nLength = SIZE_UNKNOWN;
	else
		m_nLength = min( ( ( nLength == SIZE_UNKNOWN ) ? m_nSize : nLength ), m_nSize - m_nOffset );
	m_nPosition = 0;

	if ( m_nLength > m_nSize || m_nOffset + m_nLength > m_nSize )
	{
		theApp.Message( MSG_ERROR, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sName );

		m_pClient->SendCommand( FILE_NOT_AVAILABLE );

		return TRUE;
	}

	AllocateBaseFile();

	if ( m_bStopTransfer )
	{
		m_tRotateTime = 0;
		m_bStopTransfer = FALSE;

		CUploadQueue* pQueue = m_pQueue;
		if ( pQueue )
			pQueue->Dequeue( this );
	}

	int nPosition = UploadQueues.GetPosition( this, TRUE );
	if ( nPosition < 0 && UploadQueues.Enqueue( this ) )
	{
		nPosition = UploadQueues.GetPosition( this, TRUE );
	}

	if ( nPosition == 0 )
	{
		// Ready to send
		if ( m_bGet )
			return TRUE;	// Wait for $Send

		return SendFile();
	}
	else if ( nPosition > 0 )
	{
		// Queued
		theApp.Message( MSG_INFO, IDS_UPLOAD_QUEUED, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress, nPosition, m_pQueue->GetQueuedCount(), (LPCTSTR)m_pQueue->m_sName );

		CString strQueued;
		strQueued.Format( UPLOAD_QUEUE, nPosition );

		m_pClient->SendCommand( strQueued );

		StartSending( upsPreQueue );

		m_tRankingCheck = GetTickCount();

		return TRUE;
	}
	else
	{
		// Unable to queue anywhere
		UploadQueues.Dequeue( this );
		ASSERT( m_pQueue == NULL );

		theApp.Message( MSG_ERROR, IDS_UPLOAD_BUSY_QUEUE, (LPCTSTR)m_sName, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );

		m_pClient->SendCommand( UPLOAD_BUSY );

		return TRUE;
	}
}
BOOL CUploadTransferDC::OnUpload(const std::string& strType, const std::string& strFilename, QWORD nOffset, QWORD nLength, const std::string& strOptions)
{
	ASSERT( m_pClient );

	if ( m_nState >= upsUploading )
	{
		// Drop unsent data
		CLockedBuffer pOutput( m_pClient->GetOutput() );
		pOutput->Clear();

		m_nState = upsRequest;
	}

	ClearRequest();

	m_sUserAgent = m_pClient->GetUserAgent();
	m_pHost = m_pClient->m_pHost;
	m_sAddress = m_pClient->m_sAddress;
	UpdateCountry();

	m_pClient->m_mInput.pLimit  = &Settings.Bandwidth.Request;
	m_pClient->m_mOutput.pLimit = &m_nBandwidth;

	m_tRequest = GetTickCount();

	BOOL bZip = ( strOptions.find("ZL1") != std::string::npos );

	if ( strType == "tthl" )
	{
		m_bGet = FALSE;

		if ( strFilename.substr( 0, 4 ) == "TTH/" )
		{
			Hashes::TigerHash oTiger;
			if ( oTiger.fromString( CA2W( strFilename.substr( 4 ).c_str() ) ) )
			{
				CSingleLock oLock( &Library.m_pSection );
				if ( oLock.Lock( 1000 ) )
				{
					if ( CLibraryFile* pFile = LibraryMaps.LookupFileByTiger( oTiger, TRUE, TRUE ) )
					{
						if ( RequestTigerTree( pFile, nOffset, nLength ) )
							return TRUE;
					}
				}
			}
		}
	}
	else if ( strType == "file" || strType =="get" )
	{
		m_bGet = ( strType == "get" );

		if ( strFilename == "files.xml" || strFilename == "files.xml.bz2" )
		{
			if ( RequestFileList( TRUE, bZip, strFilename, nOffset, nLength ) )
				return TRUE;
		}
		else if ( strFilename.substr( 0, 4 ) == "TTH/" )
		{
			Hashes::TigerHash oTiger;
			if ( oTiger.fromString( CA2W( strFilename.substr( 4 ).c_str() ) ) )
			{
				CSingleLock oLock( &Library.m_pSection );
				if ( oLock.Lock( 1000 ) )
				{
					if ( CLibraryFile* pFile = LibraryMaps.LookupFileByTiger( oTiger, TRUE, TRUE ) )
					{
						if ( RequestFile( pFile, nOffset, nLength ) )
							return TRUE;
					}
				}
			}
		}
	}
	else if ( strType == "list" )
	{
		m_bGet = FALSE;

		if ( RequestFileList( FALSE, bZip, strFilename, nOffset, nLength ) )
			return TRUE;
	}
	else if ( strType == "send" )
	{
		if ( m_bGet )
		{
			if ( m_pXML.GetCount() )
			{
				// Send cached file list
				m_bGet = FALSE;

				StartSending( upsBrowse );

				m_pClient->Write( &m_pXML );

				m_pXML.Clear();

				return TRUE;
			}
			else if ( SendFile() )
			{
				// Send already requested file
				return TRUE;
			}
		}
		// else $Send without $Get
	}
	else
	{
		// Invalid request type
		theApp.Message( MSG_ERROR, _T("DC++ Invalid request type from %s"), (LPCTSTR)m_sAddress );
		return FALSE;
	}

	theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)CA2CT( strFilename.c_str() ) );

	m_pClient->SendCommand( FILE_NOT_AVAILABLE );

	return TRUE;
}