Esempio n. 1
0
void CTransferSocket::OnReceive()
{
	m_pControlSocket->LogMessage(::Debug_Debug, _T("CTransferSocket::OnReceive(), m_transferMode=%d"), m_transferMode);

	if (!m_pBackend)
	{
		m_pControlSocket->LogMessage(::Debug_Verbose, _T("Postponing receive, m_pBackend was false."));
		m_postponedReceive = true;
		return;
	}

	if (!m_bActive)
	{
		m_pControlSocket->LogMessage(::Debug_Verbose, _T("Postponing receive, m_bActive was false."));
		m_postponedReceive = true;
		return;
	}

	if (m_transferMode == list)
	{
		for (;;)
		{
			char *pBuffer = new char[4096];
			int error;
			int numread = m_pBackend->Read(pBuffer, 4096, error);
			if (numread < 0)
			{
				delete [] pBuffer;
				if (error != EAGAIN)
				{
					m_pControlSocket->LogMessage(::Error, _T("Could not read from transfer socket: %s"), CSocket::GetErrorDescription(error).c_str());
					TransferEnd(transfer_failure);
				}
				else if (m_onCloseCalled && !m_pBackend->IsWaiting(CRateLimiter::inbound))
					TransferEnd(successful);

				return;
			}

			if (numread > 0)
			{
				if (!m_pDirectoryListingParser->AddData(pBuffer, numread))
				{
					TransferEnd(transfer_failure);
					return;
				}

				m_pEngine->SetActive(CFileZillaEngine::recv);
				if (!m_madeProgress)
				{
					m_madeProgress = 2;
					m_pControlSocket->SetTransferStatusMadeProgress();
				}
				m_pControlSocket->UpdateTransferStatus(numread);
			}
			else
			{
				delete [] pBuffer;
				TransferEnd(successful);
				return;
			}
		}
	}
	else if (m_transferMode == download)
	{
		for (;;)
		{
			if (!CheckGetNextWriteBuffer())
				return;

			int error;
			int numread = m_pBackend->Read(m_pTransferBuffer, m_transferBufferLen, error);
			if (numread < 0)
			{
				if (error != EAGAIN)
				{
					m_pControlSocket->LogMessage(::Error, _T("Could not read from transfer socket: %s"), CSocket::GetErrorDescription(error).c_str());
					TransferEnd(transfer_failure);
				}
				else if (m_onCloseCalled && !m_pBackend->IsWaiting(CRateLimiter::inbound))
					TransferEnd(successful);
				return;
			}

			if (numread > 0)
			{
				m_pEngine->SetActive(CFileZillaEngine::recv);
				if (!m_madeProgress)
				{
					m_madeProgress = 2;
					m_pControlSocket->SetTransferStatusMadeProgress();
				}
				m_pControlSocket->UpdateTransferStatus(numread);

				m_pTransferBuffer += numread;
				m_transferBufferLen -= numread;

				if (!CheckGetNextWriteBuffer())
					return;
			}
			else //!numread
			{
				FinalizeWrite();
				break;
			}
		}
	}
	else if (m_transferMode == resumetest)
	{
		for (;;)
		{
			char buffer[2];
			int error;
			int numread = m_pBackend->Read(buffer, 2, error);
			if (numread < 0)
			{
				if (error != EAGAIN)
				{
					m_pControlSocket->LogMessage(::Error, _T("Could not read from transfer socket: %s"), CSocket::GetErrorDescription(error).c_str());
					TransferEnd(transfer_failure);
				}
				else if (m_onCloseCalled && !m_pBackend->IsWaiting(CRateLimiter::inbound))
				{
					if (m_transferBufferLen == 1)
						TransferEnd(successful);
					else
					{
						m_pControlSocket->LogMessage(::Debug_Warning, _T("Server incorrectly sent %d bytes"), m_transferBufferLen);
						TransferEnd(failed_resumetest);
					}
				}
				return;
			}

			if (!numread)
			{
				if (m_transferBufferLen == 1)
					TransferEnd(successful);
				else
				{
					m_pControlSocket->LogMessage(::Debug_Warning, _T("Server incorrectly sent %d bytes"), m_transferBufferLen);
					TransferEnd(failed_resumetest);
				}
				return;
			}
			m_transferBufferLen += numread;

			if (m_transferBufferLen > 1)
			{
				m_pControlSocket->LogMessage(::Debug_Warning, _T("Server incorrectly sent %d bytes"), m_transferBufferLen);
				TransferEnd(failed_resumetest);
				return;
			}
		}
	}
}
void CTransferSocket::OnReceive()
{
	controlSocket_.LogMessage(MessageType::Debug_Debug, _T("CTransferSocket::OnReceive(), m_transferMode=%d"), m_transferMode);

	if (!m_pBackend) {
		controlSocket_.LogMessage(MessageType::Debug_Verbose, _T("Postponing receive, m_pBackend was false."));
		m_postponedReceive = true;
		return;
	}

	if (!m_bActive) {
		controlSocket_.LogMessage(MessageType::Debug_Verbose, _T("Postponing receive, m_bActive was false."));
		m_postponedReceive = true;
		return;
	}

	if (m_transferMode == TransferMode::list) {
		for (;;) {
			char *pBuffer = new char[4096];
			int error;
			int numread = m_pBackend->Read(pBuffer, 4096, error);
			if (numread < 0) {
				delete [] pBuffer;
				if (error != EAGAIN) {
					controlSocket_.LogMessage(MessageType::Error, _T("Could not read from transfer socket: %s"), CSocket::GetErrorDescription(error));
					TransferEnd(TransferEndReason::transfer_failure);
				}
				else if (m_onCloseCalled && !m_pBackend->IsWaiting(CRateLimiter::inbound)) {
					TransferEnd(TransferEndReason::successful);
				}
				return;
			}

			if (numread > 0) {
				if (!m_pDirectoryListingParser->AddData(pBuffer, numread)) {
					TransferEnd(TransferEndReason::transfer_failure);
					return;
				}

				controlSocket_.SetActive(CFileZillaEngine::recv);
				if (!m_madeProgress) {
					m_madeProgress = 2;
					engine_.transfer_status_.SetMadeProgress();
				}
				engine_.transfer_status_.Update(numread);
			}
			else {
				delete [] pBuffer;
				TransferEnd(TransferEndReason::successful);
				return;
			}
		}
	}
	else if (m_transferMode == TransferMode::download) {
		int error;
		int numread;

		// Only do a certain number of iterations in one go to keep the event loop going.
		// Otherwise this behaves like a livelock on very large files written to a very fast
		// SSD downloaded from a very fast server.
		for (int i = 0; i < 100; ++i) {
			if (!CheckGetNextWriteBuffer()) {
				return;
			}

			numread = m_pBackend->Read(m_pTransferBuffer, m_transferBufferLen, error);
			if (numread <= 0) {
				break;
			}

			controlSocket_.SetActive(CFileZillaEngine::recv);
			if (!m_madeProgress) {
				m_madeProgress = 2;
				engine_.transfer_status_.SetMadeProgress();
			}
			engine_.transfer_status_.Update(numread);

			m_pTransferBuffer += numread;
			m_transferBufferLen -= numread;
		}

		if (numread < 0) {
			if (error != EAGAIN) {
				controlSocket_.LogMessage(MessageType::Error, _T("Could not read from transfer socket: %s"), CSocket::GetErrorDescription(error));
				TransferEnd(TransferEndReason::transfer_failure);
			}
			else if (m_onCloseCalled && !m_pBackend->IsWaiting(CRateLimiter::inbound)) {
				FinalizeWrite();
			}
		}
		else if (!numread) {
			FinalizeWrite();
		}
		else {
			send_event<CSocketEvent>(m_pBackend, SocketEventType::read, 0);
		}
	}
	else if (m_transferMode == TransferMode::resumetest) {
		for (;;) {
			char buffer[2];
			int error;
			int numread = m_pBackend->Read(buffer, 2, error);
			if (numread < 0) {
				if (error != EAGAIN) {
					controlSocket_.LogMessage(MessageType::Error, _T("Could not read from transfer socket: %s"), CSocket::GetErrorDescription(error));
					TransferEnd(TransferEndReason::transfer_failure);
				}
				else if (m_onCloseCalled && !m_pBackend->IsWaiting(CRateLimiter::inbound)) {
					if (m_transferBufferLen == 1) {
						TransferEnd(TransferEndReason::successful);
					}
					else {
						controlSocket_.LogMessage(MessageType::Debug_Warning, _T("Server incorrectly sent %d bytes"), m_transferBufferLen);
						TransferEnd(TransferEndReason::failed_resumetest);
					}
				}
				return;
			}

			if (!numread) {
				if (m_transferBufferLen == 1)
					TransferEnd(TransferEndReason::successful);
				else {
					controlSocket_.LogMessage(MessageType::Debug_Warning, _T("Server incorrectly sent %d bytes"), m_transferBufferLen);
					TransferEnd(TransferEndReason::failed_resumetest);
				}
				return;
			}
			m_transferBufferLen += numread;

			if (m_transferBufferLen > 1) {
				controlSocket_.LogMessage(MessageType::Debug_Warning, _T("Server incorrectly sent %d bytes"), m_transferBufferLen);
				TransferEnd(TransferEndReason::failed_resumetest);
				return;
			}
		}
	}
}