blob: c1472e5ba3fa36677baa9c7e2ccd35bf9a43b6a8 [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
Ed Tanous7045c8d2017-04-03 10:04:37 -070011#include <chrono>
12#include <cstdint>
13#include <functional>
14#include <future>
15#include <memory>
16#include <string>
Ed Tanous911ac312017-08-15 09:37:42 -070017#include <utility>
Ed Tanous1abe55e2018-09-05 08:30:59 -070018
Ed Tanous600d2392022-01-07 09:32:03 -080019// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
Ed Tanous1abe55e2018-09-05 08:30:59 -070020#define BMCWEB_ROUTE(app, url) \
Ed Tanous988403c2020-08-24 11:29:49 -070021 app.template route<crow::black_magic::getParameterTag(url)>(url)
Ed Tanous7045c8d2017-04-03 10:04:37 -070022
Ed Tanous1abe55e2018-09-05 08:30:59 -070023namespace crow
24{
Ed Tanous55c7b7a2018-05-22 15:27:24 -070025#ifdef BMCWEB_ENABLE_SSL
Ed Tanous7045c8d2017-04-03 10:04:37 -070026using ssl_context_t = boost::asio::ssl::context;
27#endif
Ed Tanous52cc1122020-07-18 13:51:21 -070028class App
Ed Tanous1abe55e2018-09-05 08:30:59 -070029{
30 public:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070031#ifdef BMCWEB_ENABLE_SSL
Ed Tanousceac6f72018-12-02 11:58:47 -080032 using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
Ed Tanous52cc1122020-07-18 13:51:21 -070033 using ssl_server_t = Server<App, ssl_socket_t>;
Ed Tanous789a6a32018-11-29 15:17:22 -080034#else
Ed Tanousceac6f72018-12-02 11:58:47 -080035 using socket_t = boost::asio::ip::tcp::socket;
Ed Tanous52cc1122020-07-18 13:51:21 -070036 using server_t = Server<App, socket_t>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070037#endif
Ed Tanousceac6f72018-12-02 11:58:47 -080038
Ed Tanous52cc1122020-07-18 13:51:21 -070039 explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
40 std::make_shared<boost::asio::io_context>()) :
Ed Tanous271584a2019-07-09 16:24:22 -070041 io(std::move(ioIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050042 {}
Ed Tanous52cc1122020-07-18 13:51:21 -070043 ~App()
Ed Tanous1abe55e2018-09-05 08:30:59 -070044 {
45 this->stop();
46 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070047
Ed Tanousecd6a3a2022-01-07 09:18:40 -080048 App(const App&) = delete;
49 App(App&&) = delete;
50 App& operator=(const App&) = delete;
51 App& operator=(const App&&) = delete;
52
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 template <typename Adaptor>
54 void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
55 {
Ed Tanousf94c4ec2022-01-06 12:44:41 -080056 router.handleUpgrade(req, res, std::forward<Adaptor>(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070058
zhanghch058d1b46d2021-04-01 11:18:24 +080059 void handle(Request& req,
60 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -070061 {
zhanghch058d1b46d2021-04-01 11:18:24 +080062 router.handle(req, asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -070063 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070064
Ed Tanous1abe55e2018-09-05 08:30:59 -070065 DynamicRule& routeDynamic(std::string&& rule)
66 {
67 return router.newRuleDynamic(rule);
68 }
69
Gunnar Mills1214b7e2020-06-04 10:11:30 -050070 template <uint64_t Tag>
71 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070072 {
73 return router.newRuleTagged<Tag>(std::move(rule));
74 }
75
Ed Tanous81ce6092020-12-17 16:54:55 +000076 App& socket(int existingSocket)
Ed Tanous1abe55e2018-09-05 08:30:59 -070077 {
Ed Tanous81ce6092020-12-17 16:54:55 +000078 socketFd = existingSocket;
Ed Tanous1abe55e2018-09-05 08:30:59 -070079 return *this;
80 }
81
Ed Tanousb74e4402020-09-09 20:26:26 -070082 App& port(std::uint16_t port)
Ed Tanous1abe55e2018-09-05 08:30:59 -070083 {
84 portUint = port;
85 return *this;
86 }
87
Ed Tanousb74e4402020-09-09 20:26:26 -070088 App& bindaddr(std::string bindaddr)
Ed Tanous1abe55e2018-09-05 08:30:59 -070089 {
Ed Tanousb5a76932020-09-29 16:16:58 -070090 bindaddrStr = std::move(bindaddr);
Ed Tanous1abe55e2018-09-05 08:30:59 -070091 return *this;
92 }
93
94 void validate()
95 {
96 router.validate();
97 }
98
99 void run()
100 {
101 validate();
102#ifdef BMCWEB_ENABLE_SSL
Ed Tanous789a6a32018-11-29 15:17:22 -0800103 if (-1 == socketFd)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700104 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000105 sslServer = std::make_unique<ssl_server_t>(
106 this, bindaddrStr, portUint, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700107 }
108 else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700109 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000110 sslServer =
111 std::make_unique<ssl_server_t>(this, socketFd, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700112 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800113 sslServer->run();
114
115#else
116
117 if (-1 == socketFd)
118 {
119 server = std::move(std::make_unique<server_t>(
Ed Tanous52cc1122020-07-18 13:51:21 -0700120 this, bindaddrStr, portUint, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800121 }
122 else
123 {
Ed Tanous52cc1122020-07-18 13:51:21 -0700124 server = std::move(
125 std::make_unique<server_t>(this, socketFd, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800126 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800127 server->run();
128
129#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700130 }
131
132 void stop()
133 {
134 io->stop();
135 }
136
137 void debugPrint()
138 {
139 BMCWEB_LOG_DEBUG << "Routing:";
140 router.debugPrint();
141 }
142
143 std::vector<const std::string*> getRoutes()
144 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800145 const std::string root;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700146 return router.getRoutes(root);
147 }
148 std::vector<const std::string*> getRoutes(const std::string& parent)
149 {
150 return router.getRoutes(parent);
151 }
Ed Tanousb4a7bfa2017-04-04 17:23:00 -0700152
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700153#ifdef BMCWEB_ENABLE_SSL
Ed Tanous81ce6092020-12-17 16:54:55 +0000154 App& sslFile(const std::string& crtFilename, const std::string& keyFilename)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700155 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600156 sslContext = std::make_shared<ssl_context_t>(
157 boost::asio::ssl::context::tls_server);
158 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
Ed Tanous81ce6092020-12-17 16:54:55 +0000159 sslContext->use_certificate_file(crtFilename, ssl_context_t::pem);
160 sslContext->use_private_key_file(keyFilename, ssl_context_t::pem);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600161 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
162 boost::asio::ssl::context::no_sslv2 |
163 boost::asio::ssl::context::no_sslv3 |
164 boost::asio::ssl::context::no_tlsv1 |
165 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700166 return *this;
167 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700168
Ed Tanous81ce6092020-12-17 16:54:55 +0000169 App& sslFile(const std::string& pemFilename)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700170 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600171 sslContext = std::make_shared<ssl_context_t>(
172 boost::asio::ssl::context::tls_server);
173 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
Ed Tanous81ce6092020-12-17 16:54:55 +0000174 sslContext->load_verify_file(pemFilename);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600175 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
176 boost::asio::ssl::context::no_sslv2 |
177 boost::asio::ssl::context::no_sslv3 |
178 boost::asio::ssl::context::no_tlsv1 |
179 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700180 return *this;
181 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700182
Ed Tanousb74e4402020-09-09 20:26:26 -0700183 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700184 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700185 sslContext = std::move(ctx);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600186 BMCWEB_LOG_INFO << "app::ssl context use_count="
187 << sslContext.use_count();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700188 return *this;
189 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700190
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600191 std::shared_ptr<ssl_context_t> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700192
193#else
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500194 template <typename T, typename... Remain>
Ed Tanousb74e4402020-09-09 20:26:26 -0700195 App& ssl_file(T&&, Remain&&...)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700196 {
197 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
198 // defined.
199 static_assert(
200 // make static_assert dependent to T; always false
201 std::is_base_of<T, void>::value,
202 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
203 return *this;
204 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700205
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500206 template <typename T>
Ed Tanousb74e4402020-09-09 20:26:26 -0700207 App& ssl(T&&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208 {
209 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
210 // defined.
211 static_assert(
212 // make static_assert dependent to T; always false
213 std::is_base_of<T, void>::value,
214 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
215 return *this;
216 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700217#endif
218
Ed Tanous1abe55e2018-09-05 08:30:59 -0700219 private:
Ed Tanous23e64202020-09-15 19:21:30 -0700220 std::shared_ptr<boost::asio::io_context> io;
Ed Tanous789a6a32018-11-29 15:17:22 -0800221#ifdef BMCWEB_ENABLE_SSL
222 uint16_t portUint = 443;
223#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700224 uint16_t portUint = 80;
Ed Tanous789a6a32018-11-29 15:17:22 -0800225#endif
Ed Tanousc7b9cb32021-02-11 13:28:35 -0800226 std::string bindaddrStr = "0.0.0.0";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227 int socketFd = -1;
228 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700229
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700230#ifdef BMCWEB_ENABLE_SSL
Ed Tanous1abe55e2018-09-05 08:30:59 -0700231 std::unique_ptr<ssl_server_t> sslServer;
Ed Tanous789a6a32018-11-29 15:17:22 -0800232#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700233 std::unique_ptr<server_t> server;
Ed Tanous789a6a32018-11-29 15:17:22 -0800234#endif
Ed Tanous7045c8d2017-04-03 10:04:37 -0700235};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700236} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700237using App = crow::App;