Browse Source

[master] Merge branch 'trac5260'

Marcin Siodelski 8 years ago
parent
commit
43394f76ef
3 changed files with 52 additions and 24 deletions
  1. 24 8
      src/lib/http/connection.cc
  2. 0 6
      src/lib/http/connection.h
  3. 28 10
      src/lib/http/tests/listener_unittests.cc

+ 24 - 8
src/lib/http/connection.cc

@@ -34,10 +34,6 @@ HttpConnection:: HttpConnection(asiolink::IOService& io_service,
     : request_timer_(io_service),
       request_timeout_(request_timeout),
       socket_(io_service),
-      socket_callback_(boost::bind(&HttpConnection::socketReadCallback, this,
-                                   _1, _2)),
-      socket_write_callback_(boost::bind(&HttpConnection::socketWriteCallback,
-                                         this, _1, _2)),
       acceptor_(acceptor),
       connection_pool_(connection_pool),
       response_creator_(response_creator),
@@ -54,6 +50,7 @@ HttpConnection::~HttpConnection() {
 
 void
 HttpConnection::close() {
+    request_timer_.cancel();
     socket_.close();
 }
 
@@ -71,8 +68,12 @@ HttpConnection::stopThisConnection() {
 
 void
 HttpConnection::asyncAccept() {
+    // Create instance of the callback. It is safe to pass the local instance
+    // of the callback, because the underlying boost functions make copies
+    // as needed.
     HttpAcceptorCallback cb = boost::bind(&HttpConnection::acceptorCallback,
-                                          this, _1);
+                                          shared_from_this(),
+                                          boost::asio::placeholders::error);
     try {
         acceptor_.asyncAccept(socket_, cb);
 
@@ -86,8 +87,15 @@ void
 HttpConnection::doRead() {
     try {
         TCPEndpoint endpoint;
+        // Create instance of the callback. It is safe to pass the local instance
+        // of the callback, because the underlying boost functions make copies
+        // as needed.
+        SocketCallback cb(boost::bind(&HttpConnection::socketReadCallback,
+                                      shared_from_this(),
+                                      boost::asio::placeholders::error,
+                                      boost::asio::placeholders::bytes_transferred));
         socket_.asyncReceive(static_cast<void*>(buf_.data()), buf_.size(),
-                             0, &endpoint, socket_callback_);
+                             0, &endpoint, cb);
 
     } catch (const std::exception& ex) {
         stopThisConnection();
@@ -98,9 +106,16 @@ void
 HttpConnection::doWrite() {
     try {
         if (!output_buf_.empty()) {
+            // Create instance of the callback. It is safe to pass the local instance
+            // of the callback, because the underlying boost functions make copies
+            // as needed.
+            SocketCallback cb(boost::bind(&HttpConnection::socketWriteCallback,
+                                          shared_from_this(),
+                                          boost::asio::placeholders::error,
+                                          boost::asio::placeholders::bytes_transferred));
             socket_.asyncSend(output_buf_.data(),
                               output_buf_.length(),
-                              socket_write_callback_);
+                              cb);
         } else {
             stopThisConnection();
         }
@@ -133,7 +148,8 @@ HttpConnection::acceptorCallback(const boost::system::error_code& ec) {
                   HTTP_REQUEST_RECEIVE_START)
             .arg(getRemoteEndpointAddressAsText())
             .arg(static_cast<unsigned>(request_timeout_/1000));
-        request_timer_.setup(boost::bind(&HttpConnection::requestTimeoutCallback, this),
+        request_timer_.setup(boost::bind(&HttpConnection::requestTimeoutCallback,
+                                         shared_from_this()),
                              request_timeout_, IntervalTimer::ONE_SHOT);
         doRead();
     }

+ 0 - 6
src/lib/http/connection.h

@@ -187,12 +187,6 @@ private:
     /// @brief Socket used by this connection.
     asiolink::TCPSocket<SocketCallback> socket_;
 
-    /// @brief Callback invoked when data received over the socket.
-    SocketCallback socket_callback_;
-
-    /// @brief Callback invoked when data sent over the socket.
-    SocketCallback socket_write_callback_;
-
     /// @brief Reference to the TCP acceptor used to accept new connections.
     HttpAcceptor& acceptor_;
 

+ 28 - 10
src/lib/http/tests/listener_unittests.cc

@@ -168,10 +168,21 @@ public:
                            [this, request](const boost::system::error_code& ec,
                                            std::size_t bytes_transferred) mutable {
             if (ec) {
-                ADD_FAILURE() << "error occurred while connecting: "
-                              << ec.message();
-                io_service_.stop();
-                return;
+                if (ec.value() == boost::asio::error::operation_aborted) {
+                    return;
+
+                } else if ((ec.value() == boost::asio::error::try_again) ||
+                           (ec.value() == boost::asio::error::would_block)) {
+                    // If we should try again make sure there is no garbage in the
+                    // bytes_transferred.
+                    bytes_transferred = 0;
+
+                } else {
+                    ADD_FAILURE() << "error occurred while connecting: "
+                                  << ec.message();
+                    io_service_.stop();
+                    return;
+                }
             }
 
             // Remove the part of the request which has been sent.
@@ -199,14 +210,21 @@ public:
                                        std::size_t bytes_transferred) {
             if (ec) {
                 // IO service stopped so simply return.
-                if (ec == boost::asio::error::operation_aborted) {
+                if (ec.value() == boost::asio::error::operation_aborted) {
                     return;
-                }
 
-                // Error occurred, bail...
-                ADD_FAILURE() << "error occurred while receiving HTTP"
-                    " response from the server: " << ec.message();
-                io_service_.stop();
+                } else if ((ec.value() == boost::asio::error::try_again) ||
+                           (ec.value() == boost::asio::error::would_block)) {
+                    // If we should try again, make sure that there is no garbage
+                    // in the bytes_transferred.
+                    bytes_transferred = 0;
+
+                } else {
+                    // Error occurred, bail...
+                    ADD_FAILURE() << "error occurred while receiving HTTP"
+                        " response from the server: " << ec.message();
+                    io_service_.stop();
+                }
             }
 
             if (bytes_transferred > 0) {