| Ed Tanous | 40e9b92 | 2024-09-10 13:50:16 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: Apache-2.0 | 
|  | 2 | // SPDX-FileCopyrightText: Copyright OpenBMC Authors | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 3 | #pragma once | 
|  | 4 |  | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 5 | #include "async_resp.hpp" | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 6 | #include "http_connect_types.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 7 | #include "http_request.hpp" | 
|  | 8 | #include "http_server.hpp" | 
| Ed Tanous | 9838eb2 | 2025-01-29 16:24:42 -0800 | [diff] [blame] | 9 | #include "io_context_singleton.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 10 | #include "logging.hpp" | 
| Ed Tanous | 04e438c | 2020-10-03 08:06:26 -0700 | [diff] [blame] | 11 | #include "routing.hpp" | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 12 | #include "routing/dynamicrule.hpp" | 
| Ed Tanous | 46f780f | 2025-02-09 09:35:23 -0800 | [diff] [blame] | 13 | #include "str_utility.hpp" | 
| Tanous | f00032d | 2018-11-05 01:18:10 -0300 | [diff] [blame] | 14 |  | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 15 | #include <sys/socket.h> | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 16 | #include <systemd/sd-daemon.h> | 
|  | 17 |  | 
| Nan Zhou | cec58fe | 2022-06-14 20:45:45 +0000 | [diff] [blame] | 18 | #include <boost/asio/ip/tcp.hpp> | 
| Nan Zhou | cec58fe | 2022-06-14 20:45:45 +0000 | [diff] [blame] | 19 |  | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 20 | #include <cstddef> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 21 | #include <cstdint> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 22 | #include <memory> | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 23 | #include <optional> | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 24 | #include <span> | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 25 | #include <string> | 
| Ed Tanous | 46f780f | 2025-02-09 09:35:23 -0800 | [diff] [blame] | 26 | #include <string_view> | 
| Ed Tanous | 911ac31 | 2017-08-15 09:37:42 -0700 | [diff] [blame] | 27 | #include <utility> | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 28 | #include <vector> | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 29 |  | 
| Patrick Williams | a232343 | 2023-05-12 10:06:35 -0500 | [diff] [blame] | 30 | // NOLINTNEXTLINE(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 31 | #define BMCWEB_ROUTE(app, url)                                                 \ | 
| Ed Tanous | 47488a9 | 2023-06-26 18:19:33 -0700 | [diff] [blame] | 32 | app.template route<crow::utility::getParameterTag(url)>(url) | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 33 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 34 | namespace crow | 
|  | 35 | { | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 36 | class App | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 37 | { | 
|  | 38 | public: | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 39 | using raw_socket_t = boost::asio::ip::tcp::socket; | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 40 | using server_type = Server<App, raw_socket_t>; | 
| Ed Tanous | ceac6f7 | 2018-12-02 11:58:47 -0800 | [diff] [blame] | 41 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 42 | template <typename Adaptor> | 
| Jonathan Doman | 102a4cd | 2024-04-15 16:56:23 -0700 | [diff] [blame] | 43 | void handleUpgrade(const std::shared_ptr<Request>& req, | 
| P Dheeraj Srujan Kumar | a9f076e | 2021-10-18 22:45:37 +0530 | [diff] [blame] | 44 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, | 
|  | 45 | Adaptor&& adaptor) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 46 | { | 
| P Dheeraj Srujan Kumar | a9f076e | 2021-10-18 22:45:37 +0530 | [diff] [blame] | 47 | router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor)); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 48 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 49 |  | 
| Jonathan Doman | 102a4cd | 2024-04-15 16:56:23 -0700 | [diff] [blame] | 50 | void handle(const std::shared_ptr<Request>& req, | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 51 | const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 52 | { | 
| zhanghch05 | 8d1b46d | 2021-04-01 11:18:24 +0800 | [diff] [blame] | 53 | router.handle(req, asyncResp); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 54 | } | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 55 |  | 
| Ed Tanous | 8cb2c02 | 2024-03-27 16:31:46 -0700 | [diff] [blame] | 56 | DynamicRule& routeDynamic(const std::string& rule) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 57 | { | 
|  | 58 | return router.newRuleDynamic(rule); | 
|  | 59 | } | 
|  | 60 |  | 
| Gunnar Mills | 1214b7e | 2020-06-04 10:11:30 -0500 | [diff] [blame] | 61 | template <uint64_t Tag> | 
|  | 62 | auto& route(std::string&& rule) | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 63 | { | 
|  | 64 | return router.newRuleTagged<Tag>(std::move(rule)); | 
|  | 65 | } | 
|  | 66 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 67 | void validate() | 
|  | 68 | { | 
|  | 69 | router.validate(); | 
|  | 70 | } | 
|  | 71 |  | 
| Ed Tanous | 3281bcf | 2024-06-25 16:02:05 -0700 | [diff] [blame] | 72 | void loadCertificate() | 
|  | 73 | { | 
|  | 74 | BMCWEB_LOG_DEBUG("Loading certificate"); | 
|  | 75 | if (!server) | 
|  | 76 | { | 
|  | 77 | return; | 
|  | 78 | } | 
|  | 79 | server->loadCertificate(); | 
|  | 80 | } | 
|  | 81 |  | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 82 | static HttpType getHttpType(std::string_view socketTypeString) | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 83 | { | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 84 | if (socketTypeString == "http") | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 85 | { | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 86 | BMCWEB_LOG_DEBUG("Got http socket"); | 
|  | 87 | return HttpType::HTTP; | 
|  | 88 | } | 
|  | 89 | if (socketTypeString == "https") | 
|  | 90 | { | 
|  | 91 | BMCWEB_LOG_DEBUG("Got https socket"); | 
|  | 92 | return HttpType::HTTPS; | 
|  | 93 | } | 
|  | 94 | if (socketTypeString == "both") | 
|  | 95 | { | 
|  | 96 | BMCWEB_LOG_DEBUG("Got hybrid socket"); | 
|  | 97 | return HttpType::BOTH; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | // all other types https | 
|  | 101 | BMCWEB_LOG_ERROR("Unknown http type={} assuming HTTPS only", | 
|  | 102 | socketTypeString); | 
|  | 103 | return HttpType::HTTPS; | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | static std::vector<Acceptor> setupSocket() | 
|  | 107 | { | 
|  | 108 | std::vector<Acceptor> acceptors; | 
|  | 109 | char** names = nullptr; | 
|  | 110 | int listenFdCount = sd_listen_fds_with_names(0, &names); | 
|  | 111 | BMCWEB_LOG_DEBUG("Got {} sockets to open", listenFdCount); | 
|  | 112 |  | 
|  | 113 | if (listenFdCount < 0) | 
|  | 114 | { | 
|  | 115 | BMCWEB_LOG_CRITICAL("Failed to read socket files"); | 
|  | 116 | return acceptors; | 
|  | 117 | } | 
|  | 118 | int socketIndex = 0; | 
|  | 119 | for (char* name : | 
|  | 120 | std::span<char*>(names, static_cast<size_t>(listenFdCount))) | 
|  | 121 | { | 
|  | 122 | if (name == nullptr) | 
|  | 123 | { | 
|  | 124 | continue; | 
|  | 125 | } | 
|  | 126 | // name looks like bmcweb_443_https_auth | 
|  | 127 | // Assume HTTPS as default | 
|  | 128 | std::string socketName(name); | 
|  | 129 |  | 
|  | 130 | std::vector<std::string> socknameComponents; | 
|  | 131 | bmcweb::split(socknameComponents, socketName, '_'); | 
|  | 132 | HttpType httpType = getHttpType(socknameComponents[2]); | 
|  | 133 |  | 
|  | 134 | int listenFd = socketIndex + SD_LISTEN_FDS_START; | 
|  | 135 | if (sd_is_socket_inet(listenFd, AF_UNSPEC, SOCK_STREAM, 1, 0) > 0) | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 136 | { | 
|  | 137 | BMCWEB_LOG_INFO("Starting webserver on socket handle {}", | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 138 | listenFd); | 
|  | 139 | acceptors.emplace_back(Acceptor{ | 
|  | 140 | boost::asio::ip::tcp::acceptor( | 
|  | 141 | getIoContext(), boost::asio::ip::tcp::v6(), listenFd), | 
|  | 142 | httpType}); | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 143 | } | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 144 | socketIndex++; | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 145 | } | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 146 |  | 
| Janet Adkins | 58d3aab | 2025-02-19 14:45:43 -0600 | [diff] [blame] | 147 | if (acceptors.empty()) | 
|  | 148 | { | 
|  | 149 | constexpr int defaultPort = 18080; | 
|  | 150 | BMCWEB_LOG_INFO("Starting webserver on port {}", defaultPort); | 
|  | 151 | using boost::asio::ip::tcp; | 
|  | 152 | tcp::endpoint end(tcp::v6(), defaultPort); | 
|  | 153 | tcp::acceptor acc(getIoContext(), end); | 
|  | 154 | acceptors.emplace_back(std::move(acc), HttpType::HTTPS); | 
|  | 155 | } | 
|  | 156 |  | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 157 | return acceptors; | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 158 | } | 
|  | 159 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 160 | void run() | 
|  | 161 | { | 
|  | 162 | validate(); | 
| Ed Tanous | 789a6a3 | 2018-11-29 15:17:22 -0800 | [diff] [blame] | 163 |  | 
| Ed Tanous | 796ba93 | 2020-08-02 04:29:21 +0000 | [diff] [blame] | 164 | std::vector<Acceptor> acceptors = setupSocket(); | 
|  | 165 |  | 
|  | 166 | server.emplace(this, std::move(acceptors)); | 
| Ed Tanous | 789a6a3 | 2018-11-29 15:17:22 -0800 | [diff] [blame] | 167 | server->run(); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 168 | } | 
|  | 169 |  | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 170 | void debugPrint() | 
|  | 171 | { | 
| Ed Tanous | 62598e3 | 2023-07-17 17:06:25 -0700 | [diff] [blame] | 172 | BMCWEB_LOG_DEBUG("Routing:"); | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 173 | router.debugPrint(); | 
|  | 174 | } | 
|  | 175 |  | 
|  | 176 | std::vector<const std::string*> getRoutes() | 
|  | 177 | { | 
| Ed Tanous | e05aec5 | 2022-01-25 10:28:56 -0800 | [diff] [blame] | 178 | const std::string root; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 179 | return router.getRoutes(root); | 
|  | 180 | } | 
|  | 181 | std::vector<const std::string*> getRoutes(const std::string& parent) | 
|  | 182 | { | 
|  | 183 | return router.getRoutes(parent); | 
|  | 184 | } | 
| Ed Tanous | b4a7bfa | 2017-04-04 17:23:00 -0700 | [diff] [blame] | 185 |  | 
| Ed Tanous | 8db8374 | 2024-04-13 09:11:15 -0700 | [diff] [blame] | 186 | std::optional<server_type> server; | 
|  | 187 |  | 
|  | 188 | Router router; | 
| Ed Tanous | 7045c8d | 2017-04-03 10:04:37 -0700 | [diff] [blame] | 189 | }; | 
| Ed Tanous | 1abe55e | 2018-09-05 08:30:59 -0700 | [diff] [blame] | 190 | } // namespace crow | 
| Ed Tanous | 52cc112 | 2020-07-18 13:51:21 -0700 | [diff] [blame] | 191 | using App = crow::App; |