From 1b2a76706f5138e65e8ad0136671101287f5fa43 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 9 Sep 2008 15:22:32 +0000 Subject: [PATCH] 2008-09-10 Tatsuhiro Tsujikawa Fixed the bug that bulkReceiveResponse() reads all received data as a response even if more than one response is in it. * src/FtpConnection.cc * src/FtpConnection.h * test/FtpConnectionTest.cc --- ChangeLog | 8 ++++++++ src/FtpConnection.cc | 43 ++++++++++++++++++++++++++------------- src/FtpConnection.h | 3 ++- test/FtpConnectionTest.cc | 35 +++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index d764b094..03e2be5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-09-10 Tatsuhiro Tsujikawa + + Fixed the bug that bulkReceiveResponse() reads all received data as a + response even if more than one response is in it. + * src/FtpConnection.cc + * src/FtpConnection.h + * test/FtpConnectionTest.cc + 2008-09-09 Tatsuhiro Tsujikawa Merged from stable-0.15 diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 648e5e55..a008291e 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -176,24 +176,38 @@ unsigned int FtpConnection::getStatus(const std::string& response) const } } -bool FtpConnection::isEndOfResponse(unsigned int status, const std::string& response) const +// Returns the length of the reponse if the whole response has been received. +// The length includes \r\n. +// If the whole response has not been recieved, then returns std::string::npos. +std::string::size_type +FtpConnection::findEndOfResponse(unsigned int status, + const std::string& buf) const { - if(response.size() <= 4) { - return false; + if(buf.size() <= 4) { + return std::string::npos; } // if 4th character of buf is '-', then multi line response is expected. - if(response.at(3) == '-') { + if(buf.at(3) == '-') { // multi line response std::string::size_type p; - p = response.find("\r\n"+Util::uitos(status)+" "); + p = buf.find(A2STR::CRLF+Util::uitos(status)+" "); if(p == std::string::npos) { - return false; + return std::string::npos; + } + p = buf.find(A2STR::CRLF, p+6); + if(p == std::string::npos) { + return std::string::npos; + } else { + return p+2; } - } - if(Util::endsWith(response, A2STR::CRLF)) { - return true; } else { - return false; + // single line response + std::string::size_type p = buf.find(A2STR::CRLF); + if(p == std::string::npos) { + return std::string::npos; + } else { + return p+2; + } } } @@ -218,11 +232,12 @@ bool FtpConnection::bulkReceiveResponse(std::pair& re } else { return false; } - if(isEndOfResponse(status, strbuf)) { - logger->info(MSG_RECEIVE_RESPONSE, cuid, strbuf.c_str()); + std::string::size_type length; + if((length = findEndOfResponse(status, strbuf)) != std::string::npos) { response.first = status; - response.second = strbuf; - strbuf.erase(); + response.second = strbuf.substr(0, length); + logger->info(MSG_RECEIVE_RESPONSE, cuid, response.second.c_str()); + strbuf.erase(0, length); return true; } else { // didn't receive response fully. diff --git a/src/FtpConnection.h b/src/FtpConnection.h index 80a0a195..299489a7 100644 --- a/src/FtpConnection.h +++ b/src/FtpConnection.h @@ -60,7 +60,8 @@ private: std::string strbuf; unsigned int getStatus(const std::string& response) const; - bool isEndOfResponse(unsigned int status, const std::string& response) const; + std::string::size_type findEndOfResponse(unsigned int status, + const std::string& buf) const; bool bulkReceiveResponse(std::pair& response); static const std::string A; diff --git a/test/FtpConnectionTest.cc b/test/FtpConnectionTest.cc index 7095819c..2cf9056e 100644 --- a/test/FtpConnectionTest.cc +++ b/test/FtpConnectionTest.cc @@ -12,6 +12,7 @@ namespace aria2 { class FtpConnectionTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(FtpConnectionTest); + CPPUNIT_TEST(testReceiveResponse); CPPUNIT_TEST(testSendMdtm); CPPUNIT_TEST(testReceiveMdtmResponse); CPPUNIT_TEST_SUITE_END(); @@ -48,11 +49,45 @@ public: void testSendMdtm(); void testReceiveMdtmResponse(); + void testReceiveResponse(); }; CPPUNIT_TEST_SUITE_REGISTRATION(FtpConnectionTest); +void FtpConnectionTest::testReceiveResponse() +{ + _serverSocket->writeData("100"); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + _serverSocket->writeData(" single line response"); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + _serverSocket->writeData("\r\n"); + CPPUNIT_ASSERT_EQUAL((unsigned int)100, _ftp->receiveResponse()); + // 2 responses in the buffer + _serverSocket->writeData("101 single1\r\n" + "102 single2\r\n"); + CPPUNIT_ASSERT_EQUAL((unsigned int)101, _ftp->receiveResponse()); + CPPUNIT_ASSERT_EQUAL((unsigned int)102, _ftp->receiveResponse()); + + _serverSocket->writeData("103-multi line response\r\n"); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + _serverSocket->writeData("103-line2\r\n"); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + _serverSocket->writeData("103"); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + _serverSocket->writeData(" "); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, _ftp->receiveResponse()); + _serverSocket->writeData("last\r\n"); + CPPUNIT_ASSERT_EQUAL((unsigned int)103, _ftp->receiveResponse()); + + _serverSocket->writeData("104-multi\r\n" + "104 \r\n" + "105-multi\r\n" + "105 \r\n"); + CPPUNIT_ASSERT_EQUAL((unsigned int)104, _ftp->receiveResponse()); + CPPUNIT_ASSERT_EQUAL((unsigned int)105, _ftp->receiveResponse()); +} + void FtpConnectionTest::testSendMdtm() { _ftp->sendMdtm();