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; } } } }