blob: b2e8cc062e209ad2def69be5f7fbb234c2a6f2d5 [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
Ed Tanous796ba932020-08-02 04:29:21 +00007#include "http_connect_types.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -07008#include "http_connection.hpp"
Ed Tanous796ba932020-08-02 04:29:21 +00009#include "io_context_singleton.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -070010#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080011#include "ssl_key_handler.hpp"
Manojkiran Eda44250442020-06-16 12:51:38 +053012
Ed Tanouse278c182019-03-13 16:23:37 -070013#include <boost/asio/ip/address.hpp>
Ed Tanous3112a142018-11-29 15:45:10 -080014#include <boost/asio/ip/tcp.hpp>
15#include <boost/asio/signal_set.hpp>
Ed Tanous2f1ebcd2019-02-13 19:39:07 -080016#include <boost/asio/ssl/context.hpp>
Ed Tanous003301a2024-04-16 09:59:19 -070017#include <boost/asio/ssl/stream.hpp>
Ed Tanous271584a2019-07-09 16:24:22 -070018#include <boost/asio/steady_timer.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050019
Ed Tanous3dac7492017-08-02 13:46:20 -070020#include <chrono>
Ed Tanousd7857202025-01-28 15:32:26 -080021#include <csignal>
22#include <cstddef>
23#include <ctime>
24#include <functional>
Ed Tanous911ac312017-08-15 09:37:42 -070025#include <memory>
Ed Tanous099225c2024-03-27 22:03:05 -070026#include <string>
Ed Tanous911ac312017-08-15 09:37:42 -070027#include <utility>
Ed Tanous796ba932020-08-02 04:29:21 +000028#include <vector>
Ed Tanous1abe55e2018-09-05 08:30:59 -070029
Ed Tanous1abe55e2018-09-05 08:30:59 -070030namespace crow
31{
Ed Tanous7045c8d2017-04-03 10:04:37 -070032
Ed Tanous796ba932020-08-02 04:29:21 +000033struct Acceptor
34{
35 boost::asio::ip::tcp::acceptor acceptor;
36 HttpType httpType;
37};
38
Ed Tanous52cc1122020-07-18 13:51:21 -070039template <typename Handler, typename Adaptor = boost::asio::ip::tcp::socket>
Ed Tanous1abe55e2018-09-05 08:30:59 -070040class Server
41{
Ed Tanous3281bcf2024-06-25 16:02:05 -070042 using self_t = Server<Handler, Adaptor>;
43
Ed Tanous1abe55e2018-09-05 08:30:59 -070044 public:
Ed Tanous796ba932020-08-02 04:29:21 +000045 Server(Handler* handlerIn, std::vector<Acceptor>&& acceptorsIn) :
46 acceptors(std::move(acceptorsIn)),
47
Ed Tanousd7857202025-01-28 15:32:26 -080048 // NOLINTNEXTLINE(misc-include-cleaner)
Ed Tanous796ba932020-08-02 04:29:21 +000049 signals(getIoContext(), SIGINT, SIGTERM, SIGHUP), handler(handlerIn)
Gunnar Mills1214b7e2020-06-04 10:11:30 -050050 {}
Ed Tanous7045c8d2017-04-03 10:04:37 -070051
Ed Tanous1abe55e2018-09-05 08:30:59 -070052 void updateDateStr()
53 {
Ed Tanous99131cd2019-10-24 11:12:47 -070054 time_t lastTimeT = time(nullptr);
Ed Tanous1abe55e2018-09-05 08:30:59 -070055 tm myTm{};
Ed Tanous7045c8d2017-04-03 10:04:37 -070056
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 gmtime_r(&lastTimeT, &myTm);
Ed Tanous271584a2019-07-09 16:24:22 -070058
Ed Tanous1abe55e2018-09-05 08:30:59 -070059 dateStr.resize(100);
Ed Tanous0f837072023-06-30 09:57:26 -070060 size_t dateStrSz = strftime(dateStr.data(), dateStr.size() - 1,
Patrick Williams89492a12023-05-10 07:51:34 -050061 "%a, %d %b %Y %H:%M:%S GMT", &myTm);
Ed Tanous1abe55e2018-09-05 08:30:59 -070062 dateStr.resize(dateStrSz);
Ed Tanous23a21a12020-07-25 04:45:05 +000063 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070064
Ed Tanous1abe55e2018-09-05 08:30:59 -070065 void run()
66 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -060067 loadCertificate();
Ed Tanous1abe55e2018-09-05 08:30:59 -070068 updateDateStr();
Ed Tanous7045c8d2017-04-03 10:04:37 -070069
Ed Tanous1abe55e2018-09-05 08:30:59 -070070 getCachedDateStr = [this]() -> std::string {
71 static std::chrono::time_point<std::chrono::steady_clock>
72 lastDateUpdate = std::chrono::steady_clock::now();
73 if (std::chrono::steady_clock::now() - lastDateUpdate >=
74 std::chrono::seconds(10))
75 {
76 lastDateUpdate = std::chrono::steady_clock::now();
77 updateDateStr();
78 }
Ed Tanous21b4aba2023-06-05 11:42:43 -070079 return dateStr;
Ed Tanous1abe55e2018-09-05 08:30:59 -070080 };
Ed Tanous9e6e1b22018-03-16 13:08:50 -070081
Ed Tanous796ba932020-08-02 04:29:21 +000082 for (const Acceptor& accept : acceptors)
83 {
84 BMCWEB_LOG_INFO(
85 "bmcweb server is running, local endpoint {}",
86 accept.acceptor.local_endpoint().address().to_string());
87 }
Marri Devender Rao5968cae2019-01-21 10:27:12 -060088 startAsyncWaitForSignal();
Ed Tanous1abe55e2018-09-05 08:30:59 -070089 doAccept();
90 }
91
Marri Devender Rao5968cae2019-01-21 10:27:12 -060092 void loadCertificate()
93 {
Ed Tanous25b54db2024-04-17 15:40:31 -070094 if constexpr (BMCWEB_INSECURE_DISABLE_SSL)
Ed Tanous8db83742024-04-13 09:11:15 -070095 {
96 return;
97 }
Abhilash Rajud5fb5842024-06-03 11:40:17 -050098
Ed Tanous796ba932020-08-02 04:29:21 +000099 adaptorCtx = ensuressl::getSslServerContext();
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600100 }
101
102 void startAsyncWaitForSignal()
103 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700104 signals.async_wait(
105 [this](const boost::system::error_code& ec, int signalNo) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400106 if (ec)
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600107 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400108 BMCWEB_LOG_INFO("Error in signal handler{}", ec.message());
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600109 }
110 else
111 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400112 if (signalNo == SIGHUP)
113 {
114 BMCWEB_LOG_INFO("Receivied reload signal");
115 loadCertificate();
116 startAsyncWaitForSignal();
117 }
118 else
119 {
Ed Tanous796ba932020-08-02 04:29:21 +0000120 getIoContext().stop();
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400121 }
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600122 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400123 });
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600124 }
125
Ed Tanous796ba932020-08-02 04:29:21 +0000126 using SocketPtr = std::unique_ptr<Adaptor>;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700127
Ed Tanous796ba932020-08-02 04:29:21 +0000128 void afterAccept(SocketPtr socket, HttpType httpType,
129 const boost::system::error_code& ec)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700130 {
Ed Tanous3281bcf2024-06-25 16:02:05 -0700131 if (ec)
Ed Tanous8db83742024-04-13 09:11:15 -0700132 {
Ed Tanous3281bcf2024-06-25 16:02:05 -0700133 BMCWEB_LOG_ERROR("Failed to accept socket {}", ec);
Ed Tanous8db83742024-04-13 09:11:15 -0700134 return;
135 }
Ed Tanous3281bcf2024-06-25 16:02:05 -0700136
Ed Tanous796ba932020-08-02 04:29:21 +0000137 boost::asio::steady_timer timer(getIoContext());
138 if (adaptorCtx == nullptr)
Ed Tanousceac6f72018-12-02 11:58:47 -0800139 {
Ed Tanous796ba932020-08-02 04:29:21 +0000140 adaptorCtx = std::make_shared<boost::asio::ssl::context>(
141 boost::asio::ssl::context::tls_server);
Ed Tanousceac6f72018-12-02 11:58:47 -0800142 }
Ed Tanous3281bcf2024-06-25 16:02:05 -0700143
Ed Tanous796ba932020-08-02 04:29:21 +0000144 boost::asio::ssl::stream<Adaptor> stream(std::move(*socket),
145 *adaptorCtx);
146 using ConnectionType = Connection<Adaptor, Handler>;
147 auto connection = std::make_shared<ConnectionType>(
148 handler, httpType, std::move(timer), getCachedDateStr,
149 std::move(stream));
150
151 boost::asio::post(getIoContext(),
152 [connection] { connection->start(); });
Ed Tanous3281bcf2024-06-25 16:02:05 -0700153
154 doAccept();
155 }
156
157 void doAccept()
158 {
Ed Tanous796ba932020-08-02 04:29:21 +0000159 SocketPtr socket = std::make_unique<Adaptor>(getIoContext());
Ed Tanous3281bcf2024-06-25 16:02:05 -0700160 // Keep a raw pointer so when the socket is moved, the pointer is still
161 // valid
Ed Tanous796ba932020-08-02 04:29:21 +0000162 Adaptor* socketPtr = socket.get();
163 for (Acceptor& accept : acceptors)
164 {
165 accept.acceptor.async_accept(
166 *socketPtr,
167 std::bind_front(&self_t::afterAccept, this, std::move(socket),
168 accept.httpType));
169 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700170 }
171
172 private:
Ed Tanous1abe55e2018-09-05 08:30:59 -0700173 std::function<std::string()> getCachedDateStr;
Ed Tanous796ba932020-08-02 04:29:21 +0000174 std::vector<Acceptor> acceptors;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700175 boost::asio::signal_set signals;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700176
177 std::string dateStr;
178
179 Handler* handler;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700180
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600181 std::shared_ptr<boost::asio::ssl::context> adaptorCtx;
Ed Tanous5dfb5b22021-12-03 11:24:53 -0800182};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700183} // namespace crow