blob: b983beca3be612524ab15838b37825ff1ef6eae5 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
zhanghch058d1b46d2021-04-01 11:18:24 +08003#include "async_resp.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -07004#include "http_request.hpp"
5#include "http_server.hpp"
6#include "logging.hpp"
Tanousf00032d2018-11-05 01:18:10 -03007#include "privileges.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -07008#include "routing.hpp"
9#include "utility.hpp"
Tanousf00032d2018-11-05 01:18:10 -030010
Nan Zhoucec58fe2022-06-14 20:45:45 +000011#include <boost/asio/io_context.hpp>
12#include <boost/asio/ip/tcp.hpp>
13#ifdef BMCWEB_ENABLE_SSL
14#include <boost/asio/ssl/context.hpp>
15#include <boost/beast/ssl/ssl_stream.hpp>
16#endif
17
Ed Tanous7045c8d2017-04-03 10:04:37 -070018#include <chrono>
19#include <cstdint>
20#include <functional>
21#include <future>
22#include <memory>
23#include <string>
Ed Tanous911ac312017-08-15 09:37:42 -070024#include <utility>
Ed Tanous1abe55e2018-09-05 08:30:59 -070025
Patrick Williamsa2323432023-05-12 10:06:35 -050026// NOLINTNEXTLINE(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)
Ed Tanous1abe55e2018-09-05 08:30:59 -070027#define BMCWEB_ROUTE(app, url) \
Ed Tanous988403c2020-08-24 11:29:49 -070028 app.template route<crow::black_magic::getParameterTag(url)>(url)
Ed Tanous7045c8d2017-04-03 10:04:37 -070029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace crow
31{
Ed Tanous55c7b7a2018-05-22 15:27:24 -070032#ifdef BMCWEB_ENABLE_SSL
Ed Tanous7045c8d2017-04-03 10:04:37 -070033using ssl_context_t = boost::asio::ssl::context;
34#endif
Ed Tanous52cc1122020-07-18 13:51:21 -070035class App
Ed Tanous1abe55e2018-09-05 08:30:59 -070036{
37 public:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070038#ifdef BMCWEB_ENABLE_SSL
Ed Tanousceac6f72018-12-02 11:58:47 -080039 using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
Ed Tanous52cc1122020-07-18 13:51:21 -070040 using ssl_server_t = Server<App, ssl_socket_t>;
Ed Tanous789a6a32018-11-29 15:17:22 -080041#else
Ed Tanousceac6f72018-12-02 11:58:47 -080042 using socket_t = boost::asio::ip::tcp::socket;
Ed Tanous52cc1122020-07-18 13:51:21 -070043 using server_t = Server<App, socket_t>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070044#endif
Ed Tanousceac6f72018-12-02 11:58:47 -080045
Ed Tanous52cc1122020-07-18 13:51:21 -070046 explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
47 std::make_shared<boost::asio::io_context>()) :
Ed Tanous271584a2019-07-09 16:24:22 -070048 io(std::move(ioIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050049 {}
Ed Tanous52cc1122020-07-18 13:51:21 -070050 ~App()
Ed Tanous1abe55e2018-09-05 08:30:59 -070051 {
Ed Tanous21b4aba2023-06-05 11:42:43 -070052 stop();
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070054
Ed Tanousecd6a3a2022-01-07 09:18:40 -080055 App(const App&) = delete;
56 App(App&&) = delete;
57 App& operator=(const App&) = delete;
58 App& operator=(const App&&) = delete;
59
Ed Tanous1abe55e2018-09-05 08:30:59 -070060 template <typename Adaptor>
P Dheeraj Srujan Kumar7e9093e2021-09-18 01:19:04 +053061 void handleUpgrade(Request& req,
P Dheeraj Srujan Kumara9f076e2021-10-18 22:45:37 +053062 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
63 Adaptor&& adaptor)
Ed Tanous1abe55e2018-09-05 08:30:59 -070064 {
P Dheeraj Srujan Kumara9f076e2021-10-18 22:45:37 +053065 router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070066 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070067
zhanghch058d1b46d2021-04-01 11:18:24 +080068 void handle(Request& req,
69 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -070070 {
zhanghch058d1b46d2021-04-01 11:18:24 +080071 router.handle(req, asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -070072 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070073
Ed Tanous1abe55e2018-09-05 08:30:59 -070074 DynamicRule& routeDynamic(std::string&& rule)
75 {
76 return router.newRuleDynamic(rule);
77 }
78
Gunnar Mills1214b7e2020-06-04 10:11:30 -050079 template <uint64_t Tag>
80 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070081 {
82 return router.newRuleTagged<Tag>(std::move(rule));
83 }
84
Ed Tanous81ce6092020-12-17 16:54:55 +000085 App& socket(int existingSocket)
Ed Tanous1abe55e2018-09-05 08:30:59 -070086 {
Ed Tanous81ce6092020-12-17 16:54:55 +000087 socketFd = existingSocket;
Ed Tanous1abe55e2018-09-05 08:30:59 -070088 return *this;
89 }
90
Ed Tanousb74e4402020-09-09 20:26:26 -070091 App& port(std::uint16_t port)
Ed Tanous1abe55e2018-09-05 08:30:59 -070092 {
93 portUint = port;
94 return *this;
95 }
96
Ed Tanousb74e4402020-09-09 20:26:26 -070097 App& bindaddr(std::string bindaddr)
Ed Tanous1abe55e2018-09-05 08:30:59 -070098 {
Ed Tanousb5a76932020-09-29 16:16:58 -070099 bindaddrStr = std::move(bindaddr);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700100 return *this;
101 }
102
103 void validate()
104 {
105 router.validate();
106 }
107
108 void run()
109 {
110 validate();
111#ifdef BMCWEB_ENABLE_SSL
Ed Tanous789a6a32018-11-29 15:17:22 -0800112 if (-1 == socketFd)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700113 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000114 sslServer = std::make_unique<ssl_server_t>(
115 this, bindaddrStr, portUint, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700116 }
117 else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700118 {
Patrick Williams89492a12023-05-10 07:51:34 -0500119 sslServer = std::make_unique<ssl_server_t>(this, socketFd,
120 sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700121 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800122 sslServer->run();
123
124#else
125
126 if (-1 == socketFd)
127 {
Nan Zhoud9049df2022-08-02 18:38:18 +0000128 server = std::make_unique<server_t>(this, bindaddrStr, portUint,
129 nullptr, io);
Ed Tanous789a6a32018-11-29 15:17:22 -0800130 }
131 else
132 {
Nan Zhoud9049df2022-08-02 18:38:18 +0000133 server = std::make_unique<server_t>(this, socketFd, nullptr, io);
Ed Tanous789a6a32018-11-29 15:17:22 -0800134 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800135 server->run();
136
137#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700138 }
139
140 void stop()
141 {
142 io->stop();
143 }
144
145 void debugPrint()
146 {
147 BMCWEB_LOG_DEBUG << "Routing:";
148 router.debugPrint();
149 }
150
151 std::vector<const std::string*> getRoutes()
152 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800153 const std::string root;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700154 return router.getRoutes(root);
155 }
156 std::vector<const std::string*> getRoutes(const std::string& parent)
157 {
158 return router.getRoutes(parent);
159 }
Ed Tanousb4a7bfa2017-04-04 17:23:00 -0700160
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700161#ifdef BMCWEB_ENABLE_SSL
Ed Tanousb74e4402020-09-09 20:26:26 -0700162 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700163 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 sslContext = std::move(ctx);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600165 BMCWEB_LOG_INFO << "app::ssl context use_count="
166 << sslContext.use_count();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700167 return *this;
168 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700169
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600170 std::shared_ptr<ssl_context_t> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700171
172#else
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500173 template <typename T>
Ed Tanousb74e4402020-09-09 20:26:26 -0700174 App& ssl(T&&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700175 {
176 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
177 // defined.
178 static_assert(
179 // make static_assert dependent to T; always false
180 std::is_base_of<T, void>::value,
181 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
182 return *this;
183 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700184#endif
185
Ed Tanousf8ca6d72022-06-28 12:12:03 -0700186 boost::asio::io_context& ioContext()
187 {
188 return *io;
189 }
190
Ed Tanous1abe55e2018-09-05 08:30:59 -0700191 private:
Ed Tanous23e64202020-09-15 19:21:30 -0700192 std::shared_ptr<boost::asio::io_context> io;
Ed Tanous789a6a32018-11-29 15:17:22 -0800193#ifdef BMCWEB_ENABLE_SSL
194 uint16_t portUint = 443;
195#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700196 uint16_t portUint = 80;
Ed Tanous789a6a32018-11-29 15:17:22 -0800197#endif
Ed Tanousc7b9cb32021-02-11 13:28:35 -0800198 std::string bindaddrStr = "0.0.0.0";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700199 int socketFd = -1;
200 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700201
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700202#ifdef BMCWEB_ENABLE_SSL
Ed Tanous1abe55e2018-09-05 08:30:59 -0700203 std::unique_ptr<ssl_server_t> sslServer;
Ed Tanous789a6a32018-11-29 15:17:22 -0800204#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700205 std::unique_ptr<server_t> server;
Ed Tanous789a6a32018-11-29 15:17:22 -0800206#endif
Ed Tanous7045c8d2017-04-03 10:04:37 -0700207};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700209using App = crow::App;