blob: f8d4d97416249789fdf0ed3e3af76543d24f7a29 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanous7045c8d2017-04-03 10:04:37 -07003#pragma once
4
Ed Tanousd7857202025-01-28 15:32:26 -08005#include "bmcweb_config.h"
6
zhanghch058d1b46d2021-04-01 11:18:24 +08007#include "async_resp.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -07008#include "http_request.hpp"
9#include "http_server.hpp"
Ed Tanous9838eb22025-01-29 16:24:42 -080010#include "io_context_singleton.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -070011#include "logging.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -070012#include "routing.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080013#include "routing/dynamicrule.hpp"
Tanousf00032d2018-11-05 01:18:10 -030014
Ed Tanousd7857202025-01-28 15:32:26 -080015#include <sys/socket.h>
Ed Tanous8db83742024-04-13 09:11:15 -070016#include <systemd/sd-daemon.h>
17
Ed Tanousd7857202025-01-28 15:32:26 -080018#include <boost/asio/ip/address.hpp>
Nan Zhoucec58fe2022-06-14 20:45:45 +000019#include <boost/asio/ip/tcp.hpp>
Nan Zhoucec58fe2022-06-14 20:45:45 +000020#include <boost/asio/ssl/context.hpp>
Ed Tanous003301a2024-04-16 09:59:19 -070021#include <boost/asio/ssl/stream.hpp>
Nan Zhoucec58fe2022-06-14 20:45:45 +000022
Ed Tanous7045c8d2017-04-03 10:04:37 -070023#include <cstdint>
Ed Tanous7045c8d2017-04-03 10:04:37 -070024#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080025#include <optional>
Ed Tanous7045c8d2017-04-03 10:04:37 -070026#include <string>
Ed Tanousd7857202025-01-28 15:32:26 -080027#include <type_traits>
Ed Tanous911ac312017-08-15 09:37:42 -070028#include <utility>
Ed Tanousd7857202025-01-28 15:32:26 -080029#include <vector>
Ed Tanous1abe55e2018-09-05 08:30:59 -070030
Patrick Williamsa2323432023-05-12 10:06:35 -050031// NOLINTNEXTLINE(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)
Ed Tanous1abe55e2018-09-05 08:30:59 -070032#define BMCWEB_ROUTE(app, url) \
Ed Tanous47488a92023-06-26 18:19:33 -070033 app.template route<crow::utility::getParameterTag(url)>(url)
Ed Tanous7045c8d2017-04-03 10:04:37 -070034
Ed Tanous1abe55e2018-09-05 08:30:59 -070035namespace crow
36{
Ed Tanous52cc1122020-07-18 13:51:21 -070037class App
Ed Tanous1abe55e2018-09-05 08:30:59 -070038{
39 public:
Ed Tanous003301a2024-04-16 09:59:19 -070040 using ssl_socket_t = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;
Ed Tanous8db83742024-04-13 09:11:15 -070041 using raw_socket_t = boost::asio::ip::tcp::socket;
42
Ed Tanous25b54db2024-04-17 15:40:31 -070043 using socket_type = std::conditional_t<BMCWEB_INSECURE_DISABLE_SSL,
44 raw_socket_t, ssl_socket_t>;
Ed Tanous8db83742024-04-13 09:11:15 -070045 using server_type = Server<App, socket_type>;
Ed Tanousceac6f72018-12-02 11:58:47 -080046
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 template <typename Adaptor>
Jonathan Doman102a4cd2024-04-15 16:56:23 -070048 void handleUpgrade(const std::shared_ptr<Request>& req,
P Dheeraj Srujan Kumara9f076e2021-10-18 22:45:37 +053049 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
50 Adaptor&& adaptor)
Ed Tanous1abe55e2018-09-05 08:30:59 -070051 {
P Dheeraj Srujan Kumara9f076e2021-10-18 22:45:37 +053052 router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070054
Jonathan Doman102a4cd2024-04-15 16:56:23 -070055 void handle(const std::shared_ptr<Request>& req,
zhanghch058d1b46d2021-04-01 11:18:24 +080056 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 {
zhanghch058d1b46d2021-04-01 11:18:24 +080058 router.handle(req, asyncResp);
Ed Tanous1abe55e2018-09-05 08:30:59 -070059 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070060
Ed Tanous8cb2c022024-03-27 16:31:46 -070061 DynamicRule& routeDynamic(const std::string& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070062 {
63 return router.newRuleDynamic(rule);
64 }
65
Gunnar Mills1214b7e2020-06-04 10:11:30 -050066 template <uint64_t Tag>
67 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070068 {
69 return router.newRuleTagged<Tag>(std::move(rule));
70 }
71
Ed Tanous1abe55e2018-09-05 08:30:59 -070072 void validate()
73 {
74 router.validate();
75 }
76
Ed Tanous3281bcf2024-06-25 16:02:05 -070077 void loadCertificate()
78 {
79 BMCWEB_LOG_DEBUG("Loading certificate");
80 if (!server)
81 {
82 return;
83 }
84 server->loadCertificate();
85 }
86
Ed Tanous9838eb22025-01-29 16:24:42 -080087 static std::optional<boost::asio::ip::tcp::acceptor> setupSocket()
Ed Tanous8db83742024-04-13 09:11:15 -070088 {
Ed Tanous8db83742024-04-13 09:11:15 -070089 constexpr int defaultPort = 18080;
Ed Tanous38afdb92024-12-11 23:57:53 -080090 if (sd_listen_fds(0) == 1)
Ed Tanous8db83742024-04-13 09:11:15 -070091 {
92 BMCWEB_LOG_INFO("attempting systemd socket activation");
93 if (sd_is_socket_inet(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_STREAM,
94 1, 0) != 0)
95 {
96 BMCWEB_LOG_INFO("Starting webserver on socket handle {}",
97 SD_LISTEN_FDS_START);
98 return boost::asio::ip::tcp::acceptor(
Ed Tanous9838eb22025-01-29 16:24:42 -080099 getIoContext(), boost::asio::ip::tcp::v6(),
100 SD_LISTEN_FDS_START);
Ed Tanous8db83742024-04-13 09:11:15 -0700101 }
102 BMCWEB_LOG_ERROR(
103 "bad incoming socket, starting webserver on port {}",
104 defaultPort);
105 }
106 BMCWEB_LOG_INFO("Starting webserver on port {}", defaultPort);
107 return boost::asio::ip::tcp::acceptor(
Ed Tanous9838eb22025-01-29 16:24:42 -0800108 getIoContext(),
109 boost::asio::ip::tcp::endpoint(
110 boost::asio::ip::make_address("0.0.0.0"), defaultPort));
Ed Tanous8db83742024-04-13 09:11:15 -0700111 }
112
Ed Tanous1abe55e2018-09-05 08:30:59 -0700113 void run()
114 {
115 validate();
Ed Tanous789a6a32018-11-29 15:17:22 -0800116
Ed Tanous8db83742024-04-13 09:11:15 -0700117 std::optional<boost::asio::ip::tcp::acceptor> acceptor = setupSocket();
118 if (!acceptor)
Ed Tanous789a6a32018-11-29 15:17:22 -0800119 {
Ed Tanous8db83742024-04-13 09:11:15 -0700120 BMCWEB_LOG_CRITICAL("Couldn't start server");
121 return;
Ed Tanous789a6a32018-11-29 15:17:22 -0800122 }
Ed Tanous9838eb22025-01-29 16:24:42 -0800123 server.emplace(this, std::move(*acceptor), sslContext, getIoContext());
Ed Tanous789a6a32018-11-29 15:17:22 -0800124 server->run();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700125 }
126
Ed Tanous1abe55e2018-09-05 08:30:59 -0700127 void debugPrint()
128 {
Ed Tanous62598e32023-07-17 17:06:25 -0700129 BMCWEB_LOG_DEBUG("Routing:");
Ed Tanous1abe55e2018-09-05 08:30:59 -0700130 router.debugPrint();
131 }
132
133 std::vector<const std::string*> getRoutes()
134 {
Ed Tanouse05aec52022-01-25 10:28:56 -0800135 const std::string root;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700136 return router.getRoutes(root);
137 }
138 std::vector<const std::string*> getRoutes(const std::string& parent)
139 {
140 return router.getRoutes(parent);
141 }
Ed Tanousb4a7bfa2017-04-04 17:23:00 -0700142
Ed Tanousb74e4402020-09-09 20:26:26 -0700143 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700144 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700145 sslContext = std::move(ctx);
Ed Tanous62598e32023-07-17 17:06:25 -0700146 BMCWEB_LOG_INFO("app::ssl context use_count={}",
147 sslContext.use_count());
Ed Tanous1abe55e2018-09-05 08:30:59 -0700148 return *this;
149 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700150
Ed Tanous4fa45df2023-09-01 14:20:50 -0700151 std::shared_ptr<boost::asio::ssl::context> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700152
Ed Tanous8db83742024-04-13 09:11:15 -0700153 std::optional<server_type> server;
154
155 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700156};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700157} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700158using App = crow::App;