]> granicus.if.org Git - icinga2/commitdiff
HttpServerConnection: re-add automatic disconnect
authorAlexander A. Klimov <alexander.klimov@icinga.com>
Wed, 20 Feb 2019 14:27:15 +0000 (15:27 +0100)
committerAlexander A. Klimov <alexander.klimov@icinga.com>
Mon, 1 Apr 2019 11:31:16 +0000 (13:31 +0200)
lib/remote/httpserverconnection.cpp
lib/remote/httpserverconnection.hpp

index 2419eb59540b07c54fd08c7154eec5cf1daab81c..198a472b96b78fc6bc400f57aed6fb844d0e2088 100644 (file)
@@ -17,6 +17,7 @@
 #include "base/timer.hpp"
 #include "base/tlsstream.hpp"
 #include "base/utility.hpp"
+#include <limits>
 #include <memory>
 #include <stdexcept>
 #include <boost/asio/spawn.hpp>
@@ -30,7 +31,7 @@ using namespace icinga;
 auto const l_ServerHeader ("Icinga/" + Application::GetAppVersion());
 
 HttpServerConnection::HttpServerConnection(const String& identity, bool authenticated, const std::shared_ptr<AsioTlsStream>& stream)
-       : m_Stream(stream), m_IoStrand(stream->get_io_service()), m_ShuttingDown(false)
+       : m_Stream(stream), m_Seen(Utility::GetTime()), m_IoStrand(stream->get_io_service()), m_ShuttingDown(false)
 {
        if (authenticated) {
                m_ApiUser = ApiUser::GetByClientCN(identity);
@@ -53,6 +54,7 @@ void HttpServerConnection::Start()
        HttpServerConnection::Ptr preventGc (this);
 
        asio::spawn(m_IoStrand, [this, preventGc](asio::yield_context yc) { ProcessMessages(yc); });
+       asio::spawn(m_IoStrand, [this, preventGc](asio::yield_context yc) { CheckLiveness(yc); });
 }
 
 void HttpServerConnection::Disconnect()
@@ -351,6 +353,7 @@ bool ProcessRequest(
        boost::beast::http::request<boost::beast::http::string_body>& request,
        ApiUser::Ptr& authenticatedUser,
        boost::beast::http::response<boost::beast::http::string_body>& response,
+       double& seen,
        boost::asio::yield_context& yc
 )
 {
@@ -361,6 +364,8 @@ bool ProcessRequest(
        try {
                CpuBoundWork handlingRequest (yc);
 
+               Defer updateSeen ([&seen]() { seen = Utility::GetTime(); });
+
                HttpHandler::ProcessRequest(stream, authenticatedUser, request, response, yc, hasStartedStreaming);
        } catch (const std::exception& ex) {
                if (hasStartedStreaming) {
@@ -409,6 +414,8 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
                                break;
                        }
 
+                       m_Seen = Utility::GetTime();
+
                        auto& request (parser.get());
 
                        {
@@ -450,7 +457,9 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
                                break;
                        }
 
-                       if (!ProcessRequest(*m_Stream, request, authenticatedUser, response, yc)) {
+                       m_Seen = std::numeric_limits<decltype(m_Seen)>::max();
+
+                       if (!ProcessRequest(*m_Stream, request, authenticatedUser, response, m_Seen, yc)) {
                                break;
                        }
 
@@ -465,3 +474,25 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
                }
        }
 }
+
+void HttpServerConnection::CheckLiveness(boost::asio::yield_context yc)
+{
+       boost::asio::deadline_timer timer (m_Stream->get_io_service());
+
+       for (;;) {
+               timer.expires_from_now(boost::posix_time::seconds(5));
+               timer.async_wait(yc);
+
+               if (m_ShuttingDown) {
+                       break;
+               }
+
+               if (m_Seen < Utility::GetTime() - 10) {
+                       Log(LogInformation, "HttpServerConnection")
+                               <<  "No messages for HTTP connection have been received in the last 10 seconds.";
+
+                       Disconnect();
+                       break;
+               }
+       }
+}
index bb329199129c058f31b92cb0bca7e52cd82bc2aa..7db97ed68207c5105e1d15981c861b8a80350143 100644 (file)
@@ -31,11 +31,13 @@ public:
 private:
        ApiUser::Ptr m_ApiUser;
        std::shared_ptr<AsioTlsStream> m_Stream;
+       double m_Seen;
        String m_PeerAddress;
        boost::asio::io_service::strand m_IoStrand;
        bool m_ShuttingDown;
 
        void ProcessMessages(boost::asio::yield_context yc);
+       void CheckLiveness(boost::asio::yield_context yc);
 };
 
 }