ソースを参照

2008-09-10 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	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
Tatsuhiro Tsujikawa 17 年 前
コミット
1b2a76706f
4 ファイル変更74 行追加15 行削除
  1. 8 0
      ChangeLog
  2. 29 14
      src/FtpConnection.cc
  3. 2 1
      src/FtpConnection.h
  4. 35 0
      test/FtpConnectionTest.cc

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+2008-09-10  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	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  <tujikawa at rednoah dot com>
 
 	Merged from stable-0.15

+ 29 - 14
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<unsigned int, std::string>& 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.

+ 2 - 1
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<unsigned int, std::string>& response);
 
   static const std::string A;

+ 35 - 0
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();