blob: b5f5c13f7bd16c350a1b93559e888e8db1eda40b [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 Tanous8db83742024-04-13 09:11:15 -070011#include <systemd/sd-daemon.h>
12
Nan Zhoucec58fe2022-06-14 20:45:45 +000013#include <boost/asio/io_context.hpp>
14#include <boost/asio/ip/tcp.hpp>
Nan Zhoucec58fe2022-06-14 20:45:45 +000015#include <boost/asio/ssl/context.hpp>
Ed Tanous003301a2024-04-16 09:59:19 -070016#include <boost/asio/ssl/stream.hpp>
Nan Zhoucec58fe2022-06-14 20:45:45 +000017
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 Tanous47488a92023-06-26 18:19:33 -070028 app.template route<crow::utility::getParameterTag(url)>(url)
Ed Tanous7045c8d2017-04-03 10:04:37 -070029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace crow
31{
Ed Tanous52cc1122020-07-18 13:51:21 -070032class App
Ed Tanous1abe55e2018-09-05 08:30:59 -070033{
34 public:
Ed Tanous003301a2024-04-16 09:59:19 -070035 using ssl_socket_t = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;
Ed Tanous8db83742024-04-13 09:11:15 -070036 using raw_socket_t = boost::asio::ip::tcp::socket;
37
Ed Tanous25b54db2024-04-17 15:40:31 -070038 using socket_type = std::conditional_t<BMCWEB_INSECURE_DISABLE_SSL,
39 raw_socket_t, ssl_socket_t>;
Ed Tanous8db83742024-04-13 09:11:15 -070040 using server_type = Server<App, socket_type>;
Ed Tanousceac6f72018-12-02 11:58:47 -080041
Ed Tanous52cc1122020-07-18 13:51:21 -070042 explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
43 std::make_shared<boost::asio::io_context>()) :
Ed Tanous271584a2019-07-09 16:24:22 -070044 io(std::move(ioIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050045 {}
Ed Tanous52cc1122020-07-18 13:51:21 -070046 ~App()
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 {
Ed Tanous21b4aba2023-06-05 11:42:43 -070048 stop();
Ed Tanous1abe55e2018-09-05 08:30:59 -070049 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070050
Ed Tanousecd6a3a2022-01-07 09:18:40 -080051 App(const App&) = delete;
52 App(App&&) = delete;
53 App& operator=(const App&) = delete;
54 App& operator=(const App&&) = delete;
55
Ed Tanous1abe55e2018-09-05 08:30:59 -070056 template <typename Adaptor>
Jonathan Doman102a4cd2024-04-15 16:56:23 -070057 void handleUpgrade(const std::shared_ptr<Request>& req,
P Dheeraj Srujan Kumara9f076e2021-10-18 22:45:37 +053058 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
59 Adaptor&& adaptor)
Ed Tanous1abe55e2018-09-05 08:30:59 -070060 {
P Dheeraj Srujan Kumara9f076e2021-10-18 22:45:37 +053061 router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070062 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070063
Jonathan Doman102a4cd2024-04-15 16:56:23 -070064 void handle(const std::shared_ptr<Request>& req,
zhanghch058d1b46d2021-04-01 11:18:24 +080065 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -070066 {
zhanghch058d1b46d2021-04-01 11:18:24 +080067 router.handle(req, asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -070068 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070069
Ed Tanous8cb2c022024-03-27 16:31:46 -070070 DynamicRule& routeDynamic(const std::string& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070071 {
72 return router.newRuleDynamic(rule);
73 }
74
Gunnar Mills1214b7e2020-06-04 10:11:30 -050075 template <uint64_t Tag>
76 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070077 {
78 return router.newRuleTagged<Tag>(std::move(rule));
79 }
80
Ed Tanous1abe55e2018-09-05 08:30:59 -070081 void validate()
82 {
83 router.validate();
84 }
85
Ed Tanous3281bcf2024-06-25 16:02:05 -070086 void loadCertificate()
87 {
88 BMCWEB_LOG_DEBUG("Loading certificate");
89 if (!server)
90 {
91 return;
92 }
93 server->loadCertificate();
94 }
95
Ed Tanous8db83742024-04-13 09:11:15 -070096 std::optional<boost::asio::ip::tcp::acceptor> setupSocket()
97 {
98 if (io == nullptr)
99 {
100 BMCWEB_LOG_CRITICAL("IO was nullptr?");
101 return std::nullopt;
102 }
103 constexpr int defaultPort = 18080;
104 int listenFd = sd_listen_fds(0);
105 if (listenFd == 1)
106 {
107 BMCWEB_LOG_INFO("attempting systemd socket activation");
108 if (sd_is_socket_inet(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_STREAM,
109 1, 0) != 0)
110 {
111 BMCWEB_LOG_INFO("Starting webserver on socket handle {}",
112 SD_LISTEN_FDS_START);
113 return boost::asio::ip::tcp::acceptor(
114 *io, boost::asio::ip::tcp::v6(), SD_LISTEN_FDS_START);
115 }
116 BMCWEB_LOG_ERROR(
117 "bad incoming socket, starting webserver on port {}",
118 defaultPort);
119 }
120 BMCWEB_LOG_INFO("Starting webserver on port {}", defaultPort);
121 return boost::asio::ip::tcp::acceptor(
122 *io, boost::asio::ip::tcp::endpoint(
123 boost::asio::ip::make_address("0.0.0.0"), defaultPort));
124 }
125
Ed Tanous1abe55e2018-09-05 08:30:59 -0700126 void run()
127 {
128 validate();
Ed Tanous789a6a32018-11-29 15:17:22 -0800129
Ed Tanous8db83742024-04-13 09:11:15 -0700130 std::optional<boost::asio::ip::tcp::acceptor> acceptor = setupSocket();
131 if (!acceptor)
Ed Tanous789a6a32018-11-29 15:17:22 -0800132 {
Ed Tanous8db83742024-04-13 09:11:15 -0700133 BMCWEB_LOG_CRITICAL("Couldn't start server");
134 return;
Ed Tanous789a6a32018-11-29 15:17:22 -0800135 }
Ed Tanous8db83742024-04-13 09:11:15 -0700136 server.emplace(this, std::move(*acceptor), sslContext, io);
Ed Tanous789a6a32018-11-29 15:17:22 -0800137 server->run();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700138 }
139
140 void stop()
141 {
142 io->stop();
143 }
144
145 void debugPrint()
146 {
Ed Tanous62598e32023-07-17 17:06:25 -0700147 BMCWEB_LOG_DEBUG("Routing:");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700148 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 Tanousb74e4402020-09-09 20:26:26 -0700161 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700162 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700163 sslContext = std::move(ctx);
Ed Tanous62598e32023-07-17 17:06:25 -0700164 BMCWEB_LOG_INFO("app::ssl context use_count={}",
165 sslContext.use_count());
Ed Tanous1abe55e2018-09-05 08:30:59 -0700166 return *this;
167 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700168
Ed Tanous4fa45df2023-09-01 14:20:50 -0700169 std::shared_ptr<boost::asio::ssl::context> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700170
Ed Tanousf8ca6d72022-06-28 12:12:03 -0700171 boost::asio::io_context& ioContext()
172 {
173 return *io;
174 }
175
Ed Tanous1abe55e2018-09-05 08:30:59 -0700176 private:
Ed Tanous23e64202020-09-15 19:21:30 -0700177 std::shared_ptr<boost::asio::io_context> io;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700178
Ed Tanous8db83742024-04-13 09:11:15 -0700179 std::optional<server_type> server;
180
181 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700182};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700183} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700184using App = crow::App;