Fixed FTP directory listing blocking forever if both expected responses are read from the command socket in a single call. (#1025)

This commit is contained in:
binary1248 2016-05-08 22:15:14 +02:00 committed by Lukas Dürrenberger
parent 556371ea10
commit c15172e3fd
2 changed files with 17 additions and 3 deletions

View File

@ -529,7 +529,8 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
TcpSocket m_commandSocket; ///< Socket holding the control connection with the server TcpSocket m_commandSocket; ///< Socket holding the control connection with the server
std::string m_receiveBuffer; ///< Received command data that is yet to be processed
}; };
} // namespace sf } // namespace sf

View File

@ -395,8 +395,18 @@ Ftp::Response Ftp::getResponse()
// Receive the response from the server // Receive the response from the server
char buffer[1024]; char buffer[1024];
std::size_t length; std::size_t length;
if (m_commandSocket.receive(buffer, sizeof(buffer), length) != Socket::Done)
return Response(Response::ConnectionClosed); if (m_receiveBuffer.empty())
{
if (m_commandSocket.receive(buffer, sizeof(buffer), length) != Socket::Done)
return Response(Response::ConnectionClosed);
}
else
{
std::copy(m_receiveBuffer.begin(), m_receiveBuffer.end(), buffer);
length = m_receiveBuffer.size();
m_receiveBuffer.clear();
}
// There can be several lines inside the received buffer, extract them all // There can be several lines inside the received buffer, extract them all
std::istringstream in(std::string(buffer, length), std::ios_base::binary); std::istringstream in(std::string(buffer, length), std::ios_base::binary);
@ -452,6 +462,9 @@ Ftp::Response Ftp::getResponse()
message = separator + line; message = separator + line;
} }
// Save the remaining data for the next time getResponse() is called
m_receiveBuffer.assign(buffer + in.tellg(), length - in.tellg());
// Return the response code and message // Return the response code and message
return Response(static_cast<Response::Status>(code), message); return Response(static_cast<Response::Status>(code), message);
} }