Delete socket adapters

Boost beast, ASIO, and networking TS already have mechanisms for
injecting unit tests, using template parameters.  We already use this to
some extent, although we pass through socket_adapters.  Now that we have
constexpr if, we have the ability to simplify this code quite a bit.

Tested by:
Pulled down phosphor-webui, ran redfish service validator.  Observed no
errors.

Change-Id: Ib8734aeb4c9139b56705060f6196e8ae16458fe9
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
diff --git a/CMakeLists.txt.in b/CMakeLists.txt.in
index edba792..0aed5d5 100644
--- a/CMakeLists.txt.in
+++ b/CMakeLists.txt.in
@@ -36,8 +36,8 @@
 
 externalproject_add (
     Boost URL
-    https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz
-    URL_MD5 d275cd85b00022313c171f602db59fc5 SOURCE_DIR
+    https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.gz
+    URL_MD5 5d8b4503582fffa9eefdb9045359c239 SOURCE_DIR
     "${CMAKE_BINARY_DIR}/boost-src" BINARY_DIR "${CMAKE_BINARY_DIR}/boost-build"
     CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND mkdir -p
     "${CMAKE_BINARY_DIR}/prefix/include/" && cp -R
diff --git a/crow/include/crow.h b/crow/include/crow.h
index 7e31cf3..7fe640a 100644
--- a/crow/include/crow.h
+++ b/crow/include/crow.h
@@ -11,7 +11,6 @@
 #include "crow/middleware_context.h"
 #include "crow/query_string.h"
 #include "crow/routing.h"
-#include "crow/socket_adaptors.h"
 #include "crow/timer_queue.h"
 #include "crow/utility.h"
 #include "crow/websocket.h"
diff --git a/crow/include/crow/app.h b/crow/include/crow/app.h
index 9a2281a..9ce2f8b 100644
--- a/crow/include/crow/app.h
+++ b/crow/include/crow/app.h
@@ -29,13 +29,13 @@
     using self_t = Crow;
 
 #ifdef BMCWEB_ENABLE_SSL
-    using ssl_socket_t = SSLAdaptor;
+    using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
     using ssl_server_t = Server<Crow, ssl_socket_t, Middlewares...>;
 #else
-    using socket_t = SocketAdaptor;
+    using socket_t = boost::asio::ip::tcp::socket;
     using server_t = Server<Crow, socket_t, Middlewares...>;
-
 #endif
+
     explicit Crow(std::shared_ptr<boost::asio::io_context> io =
                       std::make_shared<boost::asio::io_context>()) :
         io(std::move(io))
@@ -49,7 +49,7 @@
     template <typename Adaptor>
     void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
     {
-        router.handleUpgrade(req, res, adaptor);
+        router.handleUpgrade(req, res, std::move(adaptor));
     }
 
     void handle(const Request& req, Response& res)
diff --git a/crow/include/crow/http_connection.h b/crow/include/crow/http_connection.h
index 297648e..6f1dafd 100644
--- a/crow/include/crow/http_connection.h
+++ b/crow/include/crow/http_connection.h
@@ -15,12 +15,12 @@
 #include "crow/http_response.h"
 #include "crow/logging.h"
 #include "crow/middleware_context.h"
-#include "crow/socket_adaptors.h"
 #include "crow/timer_queue.h"
 #include "crow/utility.h"
 
 #ifdef BMCWEB_ENABLE_SSL
-#include <boost/asio/ssl/stream.hpp>
+#include <boost/asio/ssl.hpp>
+#include <boost/beast/experimental/core/ssl_stream.hpp>
 #endif
 
 namespace crow
@@ -251,9 +251,8 @@
                const std::string& server_name,
                std::tuple<Middlewares...>* middlewares,
                std::function<std::string()>& get_cached_date_str_f,
-               detail::TimerQueue& timerQueue,
-               typename Adaptor::context* adaptorCtx) :
-        adaptor(ioService, adaptorCtx),
+               detail::TimerQueue& timerQueue, Adaptor adaptorIn) :
+        adaptor(std::move(adaptorIn)),
         handler(handler), serverName(server_name), middlewares(middlewares),
         getCachedDateStr(get_cached_date_str_f), timerQueue(timerQueue)
     {
@@ -280,25 +279,36 @@
 #endif
     }
 
-    decltype(std::declval<Adaptor>().rawSocket())& socket()
+    Adaptor& socket()
     {
-        return adaptor.rawSocket();
+        return adaptor;
     }
 
     void start()
     {
-        adaptor.start([this](const boost::system::error_code& ec) {
-            if (!ec)
-            {
-                startDeadline();
 
-                doReadHeaders();
-            }
-            else
-            {
-                checkDestroy();
-            }
-        });
+        startDeadline();
+        // TODO(ed) Abstract this to a more clever class with the idea of an
+        // asynchronous "start"
+        if constexpr (std::is_same_v<Adaptor,
+                                     boost::beast::ssl_stream<
+                                         boost::asio::ip::tcp::socket>>)
+        {
+            adaptor.async_handshake(
+                boost::asio::ssl::stream_base::server,
+                [this](const boost::system::error_code& ec) {
+                    if (ec)
+                    {
+                        checkDestroy();
+                        return;
+                    }
+                    doReadHeaders();
+                });
+        }
+        else
+        {
+            doReadHeaders();
+        }
     }
 
     void handle()
@@ -318,21 +328,30 @@
             }
         }
 
-        BMCWEB_LOG_INFO << "Request: " << adaptor.remoteEndpoint() << " "
-                        << this << " HTTP/" << req->version() / 10 << "."
-                        << req->version() % 10 << ' ' << req->methodString()
-                        << " " << req->target();
+        std::string epName;
+        boost::system::error_code ec;
+        tcp::endpoint ep = adaptor.lowest_layer().remote_endpoint(ec);
+        if (!ec)
+        {
+            epName = boost::lexical_cast<std::string>(ep);
+        }
+
+        BMCWEB_LOG_INFO << "Request: " << epName << " " << this << " HTTP/"
+                        << req->version() / 10 << "." << req->version() % 10
+                        << ' ' << req->methodString() << " " << req->target();
 
         needToCallAfterHandlers = false;
 
         if (!isInvalidRequest)
         {
             res.completeRequestHandler = [] {};
-            res.isAliveHelper = [this]() -> bool { return adaptor.isOpen(); };
+            res.isAliveHelper = [this]() -> bool {
+                return adaptor.lowest_layer().is_open();
+            };
 
             ctx = detail::Context<Middlewares...>();
             req->middlewareContext = (void*)&ctx;
-            req->ioService = &adaptor.getIoService();
+            req->ioService = &adaptor.get_executor().context();
             detail::middlewareCallHelper<
                 0, decltype(ctx), decltype(*middlewares), Middlewares...>(
                 *middlewares, *req, res, ctx);
@@ -352,10 +371,6 @@
                 };
                 needToCallAfterHandlers = true;
                 handler->handle(*req, res);
-                if (req->keepAlive())
-                {
-                    res.addHeader("connection", "Keep-Alive");
-                }
             }
             else
             {
@@ -385,9 +400,9 @@
         }
 
         // auto self = this->shared_from_this();
-        res.completeRequestHandler = nullptr;
+        res.completeRequestHandler = res.completeRequestHandler = [] {};
 
-        if (!adaptor.isOpen())
+        if (!adaptor.lowest_layer().is_open())
         {
             // BMCWEB_LOG_DEBUG << this << " delete (socket is closed) " <<
             // isReading
@@ -429,7 +444,7 @@
 
         // Clean up any previous Connection.
         boost::beast::http::async_read_header(
-            adaptor.socket(), buffer, *parser,
+            adaptor, buffer, *parser,
             [this](const boost::system::error_code& ec,
                    std::size_t bytes_transferred) {
                 isReading = false;
@@ -446,7 +461,7 @@
                 {
                     // if the adaptor isn't open anymore, and wasn't handed to a
                     // websocket, treat as an error
-                    if (!adaptor.isOpen() && !req->isUpgrade())
+                    if (!adaptor.lowest_layer().is_open() && !req->isUpgrade())
                     {
                         errorWhileReading = true;
                     }
@@ -455,7 +470,7 @@
                 if (errorWhileReading)
                 {
                     cancelDeadlineTimer();
-                    adaptor.close();
+                    adaptor.lowest_layer().close();
                     BMCWEB_LOG_DEBUG << this << " from read(1)";
                     checkDestroy();
                     return;
@@ -480,7 +495,7 @@
         BMCWEB_LOG_DEBUG << this << " doRead";
 
         boost::beast::http::async_read(
-            adaptor.socket(), buffer, *parser,
+            adaptor, buffer, *parser,
             [this](const boost::system::error_code& ec,
                    std::size_t bytes_transferred) {
                 BMCWEB_LOG_ERROR << this << " async_read " << bytes_transferred
@@ -495,7 +510,7 @@
                 }
                 else
                 {
-                    if (!adaptor.isOpen())
+                    if (!adaptor.lowest_layer().is_open())
                     {
                         errorWhileReading = true;
                     }
@@ -503,7 +518,7 @@
                 if (errorWhileReading)
                 {
                     cancelDeadlineTimer();
-                    adaptor.close();
+                    adaptor.lowest_layer().close();
                     BMCWEB_LOG_DEBUG << this << " from read(1)";
                     checkDestroy();
                     return;
@@ -520,7 +535,7 @@
         res.preparePayload();
         serializer.emplace(*res.stringResponse);
         boost::beast::http::async_write(
-            adaptor.socket(), *serializer,
+            adaptor, *serializer,
             [&](const boost::system::error_code& ec,
                 std::size_t bytes_transferred) {
                 isWriting = false;
@@ -533,9 +548,9 @@
                     checkDestroy();
                     return;
                 }
-                if (!req->keepAlive())
+                if (!res.keepAlive())
                 {
-                    adaptor.close();
+                    adaptor.lowest_layer().close();
                     BMCWEB_LOG_DEBUG << this << " from write(1)";
                     checkDestroy();
                     return;
@@ -577,11 +592,11 @@
         cancelDeadlineTimer();
 
         timerCancelKey = timerQueue.add([this] {
-            if (!adaptor.isOpen())
+            if (!adaptor.lowest_layer().is_open())
             {
                 return;
             }
-            adaptor.close();
+            adaptor.lowest_layer().close();
         });
         BMCWEB_LOG_DEBUG << this << " timer added: " << &timerQueue << ' '
                          << timerCancelKey;
@@ -614,7 +629,6 @@
     bool isWriting{};
     bool needToCallAfterHandlers{};
     bool needToStartReadAfterComplete{};
-    bool addKeepAlive{};
 
     std::tuple<Middlewares...>* middlewares;
     detail::Context<Middlewares...> ctx;
diff --git a/crow/include/crow/http_response.h b/crow/include/crow/http_response.h
index 6090a5b..1deae34 100644
--- a/crow/include/crow/http_response.h
+++ b/crow/include/crow/http_response.h
@@ -114,6 +114,11 @@
         stringResponse->keep_alive(k);
     }
 
+    bool keepAlive()
+    {
+        return stringResponse->keep_alive();
+    }
+
     void preparePayload()
     {
         stringResponse->prepare_payload();
diff --git a/crow/include/crow/http_server.h b/crow/include/crow/http_server.h
index ebf5570..e8cb762 100644
--- a/crow/include/crow/http_server.h
+++ b/crow/include/crow/http_server.h
@@ -17,6 +17,7 @@
 #include "crow/timer_queue.h"
 #ifdef BMCWEB_ENABLE_SSL
 #include <boost/asio/ssl/context.hpp>
+#include <boost/beast/experimental/core/ssl_stream.hpp>
 #endif
 
 namespace crow
@@ -24,14 +25,14 @@
 using namespace boost;
 using tcp = asio::ip::tcp;
 
-template <typename Handler, typename Adaptor = SocketAdaptor,
+template <typename Handler, typename Adaptor = boost::asio::ip::tcp::socket,
           typename... Middlewares>
 class Server
 {
   public:
     Server(Handler* handler, std::unique_ptr<tcp::acceptor>&& acceptor,
            std::tuple<Middlewares...>* middlewares = nullptr,
-           typename Adaptor::context* adaptor_ctx = nullptr,
+           boost::asio::ssl::context* adaptor_ctx = nullptr,
            std::shared_ptr<boost::asio::io_context> io =
                std::make_shared<boost::asio::io_context>()) :
         ioService(std::move(io)),
@@ -43,7 +44,7 @@
 
     Server(Handler* handler, const std::string& bindaddr, uint16_t port,
            std::tuple<Middlewares...>* middlewares = nullptr,
-           typename Adaptor::context* adaptor_ctx = nullptr,
+           boost::asio::ssl::context* adaptor_ctx = nullptr,
            std::shared_ptr<boost::asio::io_context> io =
                std::make_shared<boost::asio::io_context>()) :
         Server(handler,
@@ -57,7 +58,7 @@
 
     Server(Handler* handler, int existing_socket,
            std::tuple<Middlewares...>* middlewares = nullptr,
-           typename Adaptor::context* adaptor_ctx = nullptr,
+           boost::asio::ssl::context* adaptor_ctx = nullptr,
            std::shared_ptr<boost::asio::io_context> io =
                std::make_shared<boost::asio::io_context>()) :
         Server(handler,
@@ -163,21 +164,36 @@
 
     void doAccept()
     {
-        auto p = new Connection<Adaptor, Handler, Middlewares...>(
-            *ioService, handler, serverName, middlewares, getCachedDateStr,
-            timerQueue, adaptorCtx);
-        acceptor->async_accept(
-            p->socket(), [this, p](boost::system::error_code ec) {
-                if (!ec)
-                {
-                    this->ioService->post([p] { p->start(); });
-                }
-                else
-                {
-                    delete p;
-                }
-                doAccept();
-            });
+        std::optional<Adaptor> adaptorTemp;
+        if constexpr (std::is_same<Adaptor,
+                                   boost::beast::ssl_stream<
+                                       boost::asio::ip::tcp::socket>>::value)
+        {
+            adaptorTemp = Adaptor(*ioService, *adaptorCtx);
+        }
+        else
+        {
+            adaptorTemp = Adaptor(*ioService);
+        }
+
+        Connection<Adaptor, Handler, Middlewares...>* p =
+            new Connection<Adaptor, Handler, Middlewares...>(
+                *ioService, handler, serverName, middlewares, getCachedDateStr,
+                timerQueue, std::move(adaptorTemp.value()));
+
+        acceptor->async_accept(p->socket().lowest_layer(),
+                               [this, p](boost::system::error_code ec) {
+                                   if (!ec)
+                                   {
+                                       this->ioService->post(
+                                           [p] { p->start(); });
+                                   }
+                                   else
+                                   {
+                                       delete p;
+                                   }
+                                   doAccept();
+                               });
     }
 
   private:
@@ -200,8 +216,7 @@
 
 #ifdef BMCWEB_ENABLE_SSL
     bool useSsl{false};
-    boost::asio::ssl::context sslContext{boost::asio::ssl::context::sslv23};
 #endif
-    typename Adaptor::context* adaptorCtx;
+    boost::asio::ssl::context* adaptorCtx;
 }; // namespace crow
 } // namespace crow
diff --git a/crow/include/crow/routing.h b/crow/include/crow/routing.h
index 945f361..7ba5171 100644
--- a/crow/include/crow/routing.h
+++ b/crow/include/crow/routing.h
@@ -41,13 +41,16 @@
     }
 
     virtual void handle(const Request&, Response&, const RoutingParams&) = 0;
-    virtual void handleUpgrade(const Request&, Response& res, SocketAdaptor&&)
+    virtual void handleUpgrade(const Request&, Response& res,
+                               boost::asio::ip::tcp::socket&&)
     {
         res = Response(boost::beast::http::status::not_found);
         res.end();
     }
 #ifdef BMCWEB_ENABLE_SSL
-    virtual void handleUpgrade(const Request&, Response& res, SSLAdaptor&&)
+    virtual void
+        handleUpgrade(const Request&, Response& res,
+                      boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&&)
     {
         res = Response(boost::beast::http::status::not_found);
         res.end();
@@ -300,21 +303,23 @@
     }
 
     void handleUpgrade(const Request& req, Response&,
-                       SocketAdaptor&& adaptor) override
+                       boost::asio::ip::tcp::socket&& adaptor) override
     {
-        new crow::websocket::ConnectionImpl<SocketAdaptor>(
+        new crow::websocket::ConnectionImpl<boost::asio::ip::tcp::socket>(
             req, std::move(adaptor), openHandler, messageHandler, closeHandler,
             errorHandler);
     }
 #ifdef BMCWEB_ENABLE_SSL
     void handleUpgrade(const Request& req, Response&,
-                       SSLAdaptor&& adaptor) override
+                       boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&&
+                           adaptor) override
     {
-        std::shared_ptr<crow::websocket::ConnectionImpl<SSLAdaptor>>
-            myConnection =
-                std::make_shared<crow::websocket::ConnectionImpl<SSLAdaptor>>(
-                    req, std::move(adaptor), openHandler, messageHandler,
-                    closeHandler, errorHandler);
+        std::shared_ptr<crow::websocket::ConnectionImpl<
+            boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>
+            myConnection = std::make_shared<crow::websocket::ConnectionImpl<
+                boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>(
+                req, std::move(adaptor), openHandler, messageHandler,
+                closeHandler, errorHandler);
         myConnection->start();
     }
 #endif
diff --git a/crow/include/crow/socket_adaptors.h b/crow/include/crow/socket_adaptors.h
deleted file mode 100644
index 16ebe1f..0000000
--- a/crow/include/crow/socket_adaptors.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#pragma once
-#include <boost/asio.hpp>
-#include <boost/lexical_cast.hpp>
-
-#include "crow/logging.h"
-
-#ifdef BMCWEB_ENABLE_SSL
-#include <boost/asio/ssl.hpp>
-#endif
-namespace crow
-{
-using namespace boost;
-using tcp = asio::ip::tcp;
-
-struct SocketAdaptor
-{
-    using streamType = tcp::socket;
-    using secure = std::false_type;
-    using context = void;
-    SocketAdaptor(boost::asio::io_context& ioService, context* /*unused*/) :
-        socketCls(ioService)
-    {
-    }
-
-    boost::asio::io_context& getIoService()
-    {
-        return socketCls.get_io_context();
-    }
-
-    tcp::socket& rawSocket()
-    {
-        return socketCls;
-    }
-
-    tcp::socket& socket()
-    {
-        return socketCls;
-    }
-
-    std::string remoteEndpoint()
-    {
-        boost::system::error_code ec;
-        tcp::endpoint ep = socketCls.remote_endpoint(ec);
-        if (ec)
-        {
-            return "";
-        }
-        return boost::lexical_cast<std::string>(ep);
-    }
-
-    bool isOpen()
-    {
-        return socketCls.is_open();
-    }
-
-    void close()
-    {
-        socketCls.close();
-    }
-
-    template <typename F> void start(F f)
-    {
-        boost::system::error_code ec;
-        f(ec);
-    }
-
-    tcp::socket socketCls;
-};
-
-struct TestSocketAdaptor
-{
-    using secure = std::false_type;
-    using context = void;
-    TestSocketAdaptor(boost::asio::io_context& ioService, context* /*unused*/) :
-        socketCls(ioService)
-    {
-    }
-
-    boost::asio::io_context& getIoService()
-    {
-        return socketCls.get_io_context();
-    }
-
-    tcp::socket& rawSocket()
-    {
-        return socketCls;
-    }
-
-    tcp::socket& socket()
-    {
-        return socketCls;
-    }
-
-    std::string remoteEndpoint()
-    {
-        return "Testhost";
-    }
-
-    bool isOpen()
-    {
-        return socketCls.is_open();
-    }
-
-    void close()
-    {
-        socketCls.close();
-    }
-
-    template <typename F> void start(F f)
-    {
-        f(boost::system::error_code());
-    }
-
-    tcp::socket socketCls;
-};
-
-#ifdef BMCWEB_ENABLE_SSL
-struct SSLAdaptor
-{
-    using streamType = boost::asio::ssl::stream<tcp::socket>;
-    using secure = std::true_type;
-    using context = boost::asio::ssl::context;
-    using ssl_socket_t = boost::asio::ssl::stream<tcp::socket>;
-    SSLAdaptor(boost::asio::io_context& ioService, context* ctx) :
-        sslSocket(new ssl_socket_t(ioService, *ctx))
-    {
-    }
-
-    boost::asio::ssl::stream<tcp::socket>& socket()
-    {
-        return *sslSocket;
-    }
-
-    tcp::socket::lowest_layer_type& rawSocket()
-    {
-        return sslSocket->lowest_layer();
-    }
-
-    std::string remoteEndpoint()
-    {
-        boost::system::error_code ec;
-        tcp::endpoint ep = rawSocket().remote_endpoint(ec);
-        if (ec)
-        {
-            return "";
-        }
-        return boost::lexical_cast<std::string>(ep);
-    }
-
-    bool isOpen()
-    {
-        /*TODO(ed) this is a bit of a cheat.
-         There are cases  when running a websocket where sslSocket might have
-        std::move() called on it (to transfer ownership to
-        websocket::Connection) and be empty.  This (and the check on close()) is
-        a cheat to do something sane in this scenario. the correct fix would
-        likely involve changing the http parser to return a specific code
-        meaning "has been upgraded" so that the doRead function knows not to try
-        to close the Connection which would fail, because the adapter is gone.
-        As is, doRead believes the parse failed, because isOpen now returns
-        False (which could also mean the client disconnected during parse)
-        UPdate: The parser does in fact have an "isUpgrade" method that is
-        intended for exactly this purpose.  Todo is now to make doRead obey the
-        flag appropriately so this code can be changed back.
-        */
-        if (sslSocket != nullptr)
-        {
-            return sslSocket->lowest_layer().is_open();
-        }
-        return false;
-    }
-
-    void close()
-    {
-        if (sslSocket == nullptr)
-        {
-            return;
-        }
-        boost::system::error_code ec;
-
-        // Shut it down
-        this->sslSocket->lowest_layer().close();
-    }
-
-    boost::asio::io_context& getIoService()
-    {
-        return rawSocket().get_io_context();
-    }
-
-    template <typename F> void start(F f)
-    {
-        sslSocket->async_handshake(
-            boost::asio::ssl::stream_base::server,
-            [f](const boost::system::error_code& ec) { f(ec); });
-    }
-
-    std::unique_ptr<boost::asio::ssl::stream<tcp::socket>> sslSocket;
-};
-#endif
-} // namespace crow
diff --git a/crow/include/crow/websocket.h b/crow/include/crow/websocket.h
index c435d33..b545b5a 100644
--- a/crow/include/crow/websocket.h
+++ b/crow/include/crow/websocket.h
@@ -6,7 +6,6 @@
 #include <functional>
 
 #include "crow/http_request.h"
-#include "crow/socket_adaptors.h"
 
 #ifdef BMCWEB_ENABLE_SSL
 #include <boost/beast/websocket/ssl.hpp>
@@ -27,7 +26,7 @@
     virtual void sendText(const boost::beast::string_view msg) = 0;
     virtual void sendText(std::string&& msg) = 0;
     virtual void close(const boost::beast::string_view msg = "quit") = 0;
-    virtual boost::asio::io_context& getIoService() = 0;
+    virtual boost::asio::io_context& get_io_context() = 0;
     virtual ~Connection() = default;
 
     void userdata(void* u)
@@ -49,15 +48,15 @@
 {
   public:
     ConnectionImpl(
-        const crow::Request& req, Adaptor&& adaptorIn,
+        const crow::Request& req, Adaptor adaptorIn,
         std::function<void(Connection&)> open_handler,
         std::function<void(Connection&, const std::string&, bool)>
             message_handler,
         std::function<void(Connection&, const std::string&)> close_handler,
         std::function<void(Connection&)> error_handler) :
-        adaptor(std::move(adaptorIn)),
-        inString(), inBuffer(inString, 4096), ws(adaptor.socket()),
-        Connection(req), openHandler(std::move(open_handler)),
+        inString(),
+        inBuffer(inString, 4096), ws(std::move(adaptorIn)), Connection(req),
+        openHandler(std::move(open_handler)),
         messageHandler(std::move(message_handler)),
         closeHandler(std::move(close_handler)),
         errorHandler(std::move(error_handler))
@@ -65,9 +64,9 @@
         BMCWEB_LOG_DEBUG << "Creating new connection " << this;
     }
 
-    boost::asio::io_context& getIoService() override
+    boost::asio::io_context& get_io_context() override
     {
-        return adaptor.getIoService();
+        return ws.get_executor().context();
     }
 
     void start()
@@ -131,12 +130,15 @@
         ws.async_close(
             boost::beast::websocket::close_code::normal,
             [this, self(shared_from_this())](boost::system::error_code ec) {
+                if (ec == boost::asio::error::operation_aborted)
+                {
+                    return;
+                }
                 if (ec)
                 {
                     BMCWEB_LOG_ERROR << "Error closing websocket " << ec;
                     return;
                 }
-                adaptor.close();
             });
     }
 
@@ -217,11 +219,7 @@
     }
 
   private:
-    Adaptor adaptor;
-
-    boost::beast::websocket::stream<
-        std::add_lvalue_reference_t<typename Adaptor::streamType>>
-        ws;
+    boost::beast::websocket::stream<Adaptor> ws;
 
     std::string inString;
     boost::asio::dynamic_string_buffer<std::string::value_type,
diff --git a/include/obmc_console.hpp b/include/obmc_console.hpp
index 436f6c6..5797613 100644
--- a/include/obmc_console.hpp
+++ b/include/obmc_console.hpp
@@ -116,7 +116,7 @@
 
                 host_socket = std::make_unique<
                     boost::asio::local::stream_protocol::socket>(
-                    conn.getIoService());
+                    conn.get_io_context());
                 host_socket->async_connect(ep, connectHandler);
             }
         })
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 3b2aae5..f746d43 100644
--- a/redfish-core/lib/service_root.hpp
+++ b/redfish-core/lib/service_root.hpp
@@ -41,7 +41,7 @@
                const std::vector<std::string>& params) override
     {
         res.jsonValue["@odata.type"] = "#ServiceRoot.v1_1_1.ServiceRoot";
-        res.jsonValue["@odata.id"] = "/redfish/v1/";
+        res.jsonValue["@odata.id"] = "/redfish/v1";
         res.jsonValue["@odata.context"] =
             "/redfish/v1/$metadata#ServiceRoot.ServiceRoot";
         res.jsonValue["Id"] = "RootService";
@@ -57,6 +57,7 @@
         res.jsonValue["Managers"] = {{"@odata.id", "/redfish/v1/Managers"}};
         res.jsonValue["SessionService"] = {
             {"@odata.id", "/redfish/v1/SessionService"}};
+        res.jsonValue["Managers"] = {{"@odata.id", "/redfish/v1/Managers"}};
         res.jsonValue["Systems"] = {{"@odata.id", "/redfish/v1/Systems"}};
         res.jsonValue["Registries"] = {{"@odata.id", "/redfish/v1/Registries"}};