xref: /openbmc/bmcweb/http/app.hpp (revision 2ae81db9)
1 #pragma once
2 
3 #include "async_resp.hpp"
4 #include "http_request.hpp"
5 #include "http_server.hpp"
6 #include "logging.hpp"
7 #include "privileges.hpp"
8 #include "routing.hpp"
9 #include "utility.hpp"
10 
11 #include <boost/asio/io_context.hpp>
12 #include <boost/asio/ip/tcp.hpp>
13 #include <boost/asio/ssl/context.hpp>
14 #include <boost/beast/ssl/ssl_stream.hpp>
15 
16 #include <chrono>
17 #include <cstdint>
18 #include <functional>
19 #include <future>
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)
25 #define BMCWEB_ROUTE(app, url)                                                 \
26     app.template route<crow::utility::getParameterTag(url)>(url)
27 
28 namespace crow
29 {
30 class App
31 {
32   public:
33     using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
34     using ssl_server_t = Server<App, ssl_socket_t>;
35     using socket_t = boost::asio::ip::tcp::socket;
36     using server_t = Server<App, socket_t>;
37 
38     explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
39                      std::make_shared<boost::asio::io_context>()) :
40         io(std::move(ioIn))
41     {}
42     ~App()
43     {
44         stop();
45     }
46 
47     App(const App&) = delete;
48     App(App&&) = delete;
49     App& operator=(const App&) = delete;
50     App& operator=(const App&&) = delete;
51 
52     template <typename Adaptor>
53     void handleUpgrade(Request& req,
54                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
55                        Adaptor&& adaptor)
56     {
57         router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor));
58     }
59 
60     void handle(Request& req,
61                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
62     {
63         router.handle(req, asyncResp);
64     }
65 
66     DynamicRule& routeDynamic(std::string&& rule)
67     {
68         return router.newRuleDynamic(rule);
69     }
70 
71     template <uint64_t Tag>
72     auto& route(std::string&& rule)
73     {
74         return router.newRuleTagged<Tag>(std::move(rule));
75     }
76 
77     App& socket(int existingSocket)
78     {
79         socketFd = existingSocket;
80         return *this;
81     }
82 
83     App& port(std::uint16_t port)
84     {
85         portUint = port;
86         return *this;
87     }
88 
89     void validate()
90     {
91         router.validate();
92     }
93 
94     void run()
95     {
96         validate();
97 #ifdef BMCWEB_ENABLE_SSL
98         if (-1 == socketFd)
99         {
100             sslServer = std::make_unique<ssl_server_t>(this, portUint,
101                                                        sslContext, io);
102         }
103         else
104         {
105             sslServer = std::make_unique<ssl_server_t>(this, socketFd,
106                                                        sslContext, io);
107         }
108         sslServer->run();
109 
110 #else
111 
112         if (-1 == socketFd)
113         {
114             server = std::make_unique<server_t>(this, portUint, nullptr, io);
115         }
116         else
117         {
118             server = std::make_unique<server_t>(this, socketFd, nullptr, io);
119         }
120         server->run();
121 
122 #endif
123     }
124 
125     void stop()
126     {
127         io->stop();
128     }
129 
130     void debugPrint()
131     {
132         BMCWEB_LOG_DEBUG("Routing:");
133         router.debugPrint();
134     }
135 
136     std::vector<const std::string*> getRoutes()
137     {
138         const std::string root;
139         return router.getRoutes(root);
140     }
141     std::vector<const std::string*> getRoutes(const std::string& parent)
142     {
143         return router.getRoutes(parent);
144     }
145 
146     App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
147     {
148         sslContext = std::move(ctx);
149         BMCWEB_LOG_INFO("app::ssl context use_count={}",
150                         sslContext.use_count());
151         return *this;
152     }
153 
154     std::shared_ptr<boost::asio::ssl::context> sslContext = nullptr;
155 
156     boost::asio::io_context& ioContext()
157     {
158         return *io;
159     }
160 
161   private:
162     std::shared_ptr<boost::asio::io_context> io;
163 #ifdef BMCWEB_ENABLE_SSL
164     uint16_t portUint = 443;
165 #else
166     uint16_t portUint = 80;
167 #endif
168     int socketFd = -1;
169     Router router;
170 
171 #ifdef BMCWEB_ENABLE_SSL
172     std::unique_ptr<ssl_server_t> sslServer;
173 #else
174     std::unique_ptr<server_t> server;
175 #endif
176 };
177 } // namespace crow
178 using App = crow::App;
179