blob: 6d725c9c0a21ca3a9b045864e42fe0ff3beb52d8 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Ed Tanous04e438c2020-10-03 08:06:26 -07003#include "http_connection.hpp"
4#include "logging.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08005#include "ssl_key_handler.hpp"
Manojkiran Eda44250442020-06-16 12:51:38 +05306
Ed Tanouse278c182019-03-13 16:23:37 -07007#include <boost/asio/ip/address.hpp>
Ed Tanous3112a142018-11-29 15:45:10 -08008#include <boost/asio/ip/tcp.hpp>
9#include <boost/asio/signal_set.hpp>
Ed Tanous2f1ebcd2019-02-13 19:39:07 -080010#include <boost/asio/ssl/context.hpp>
Ed Tanous003301a2024-04-16 09:59:19 -070011#include <boost/asio/ssl/stream.hpp>
Ed Tanous271584a2019-07-09 16:24:22 -070012#include <boost/asio/steady_timer.hpp>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050013
Manojkiran Eda44250442020-06-16 12:51:38 +053014#include <atomic>
Ed Tanous3dac7492017-08-02 13:46:20 -070015#include <chrono>
Ed Tanous911ac312017-08-15 09:37:42 -070016#include <cstdint>
Marri Devender Rao5968cae2019-01-21 10:27:12 -060017#include <filesystem>
Ed Tanous911ac312017-08-15 09:37:42 -070018#include <future>
19#include <memory>
Ed Tanous099225c2024-03-27 22:03:05 -070020#include <string>
Ed Tanous911ac312017-08-15 09:37:42 -070021#include <utility>
22#include <vector>
Ed Tanous1abe55e2018-09-05 08:30:59 -070023
Ed Tanous1abe55e2018-09-05 08:30:59 -070024namespace crow
25{
Ed Tanous7045c8d2017-04-03 10:04:37 -070026
Ed Tanous52cc1122020-07-18 13:51:21 -070027template <typename Handler, typename Adaptor = boost::asio::ip::tcp::socket>
Ed Tanous1abe55e2018-09-05 08:30:59 -070028class Server
29{
30 public:
Ed Tanous8db83742024-04-13 09:11:15 -070031 Server(Handler* handlerIn, boost::asio::ip::tcp::acceptor&& acceptorIn,
Ed Tanous8a592812022-06-04 09:06:59 -070032 std::shared_ptr<boost::asio::ssl::context> adaptorCtxIn,
Ed Tanous8db83742024-04-13 09:11:15 -070033 std::shared_ptr<boost::asio::io_context> io) :
Ed Tanous1abe55e2018-09-05 08:30:59 -070034 ioService(std::move(io)),
Ed Tanouscb13a392020-07-25 19:02:03 +000035 acceptor(std::move(acceptorIn)),
Ed Tanous5dfb5b22021-12-03 11:24:53 -080036 signals(*ioService, SIGINT, SIGTERM, SIGHUP), handler(handlerIn),
Ed Tanous8a592812022-06-04 09:06:59 -070037 adaptorCtx(std::move(adaptorCtxIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050038 {}
Ed Tanous7045c8d2017-04-03 10:04:37 -070039
Ed Tanous1abe55e2018-09-05 08:30:59 -070040 void updateDateStr()
41 {
Ed Tanous99131cd2019-10-24 11:12:47 -070042 time_t lastTimeT = time(nullptr);
Ed Tanous1abe55e2018-09-05 08:30:59 -070043 tm myTm{};
Ed Tanous7045c8d2017-04-03 10:04:37 -070044
Ed Tanous1abe55e2018-09-05 08:30:59 -070045 gmtime_r(&lastTimeT, &myTm);
Ed Tanous271584a2019-07-09 16:24:22 -070046
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 dateStr.resize(100);
Ed Tanous0f837072023-06-30 09:57:26 -070048 size_t dateStrSz = strftime(dateStr.data(), dateStr.size() - 1,
Patrick Williams89492a12023-05-10 07:51:34 -050049 "%a, %d %b %Y %H:%M:%S GMT", &myTm);
Ed Tanous1abe55e2018-09-05 08:30:59 -070050 dateStr.resize(dateStrSz);
Ed Tanous23a21a12020-07-25 04:45:05 +000051 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070052
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 void run()
54 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -060055 loadCertificate();
Ed Tanous1abe55e2018-09-05 08:30:59 -070056 updateDateStr();
Ed Tanous7045c8d2017-04-03 10:04:37 -070057
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 getCachedDateStr = [this]() -> std::string {
59 static std::chrono::time_point<std::chrono::steady_clock>
60 lastDateUpdate = std::chrono::steady_clock::now();
61 if (std::chrono::steady_clock::now() - lastDateUpdate >=
62 std::chrono::seconds(10))
63 {
64 lastDateUpdate = std::chrono::steady_clock::now();
65 updateDateStr();
66 }
Ed Tanous21b4aba2023-06-05 11:42:43 -070067 return dateStr;
Ed Tanous1abe55e2018-09-05 08:30:59 -070068 };
Ed Tanous9e6e1b22018-03-16 13:08:50 -070069
Ed Tanous62598e32023-07-17 17:06:25 -070070 BMCWEB_LOG_INFO("bmcweb server is running, local endpoint {}",
Ed Tanous8db83742024-04-13 09:11:15 -070071 acceptor.local_endpoint().address().to_string());
Marri Devender Rao5968cae2019-01-21 10:27:12 -060072 startAsyncWaitForSignal();
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 doAccept();
74 }
75
Marri Devender Rao5968cae2019-01-21 10:27:12 -060076 void loadCertificate()
77 {
Ed Tanous25b54db2024-04-17 15:40:31 -070078 if constexpr (BMCWEB_INSECURE_DISABLE_SSL)
Ed Tanous8db83742024-04-13 09:11:15 -070079 {
80 return;
81 }
Abhilash Rajud5fb5842024-06-03 11:40:17 -050082
83 auto sslContext = ensuressl::getSslServerContext();
84
Marri Devender Rao5968cae2019-01-21 10:27:12 -060085 adaptorCtx = sslContext;
86 handler->ssl(std::move(sslContext));
Marri Devender Rao5968cae2019-01-21 10:27:12 -060087 }
88
89 void startAsyncWaitForSignal()
90 {
Ed Tanous002d39b2022-05-31 08:59:27 -070091 signals.async_wait(
92 [this](const boost::system::error_code& ec, int signalNo) {
Marri Devender Rao5968cae2019-01-21 10:27:12 -060093 if (ec)
94 {
Ed Tanous62598e32023-07-17 17:06:25 -070095 BMCWEB_LOG_INFO("Error in signal handler{}", ec.message());
Marri Devender Rao5968cae2019-01-21 10:27:12 -060096 }
97 else
98 {
99 if (signalNo == SIGHUP)
100 {
Ed Tanous62598e32023-07-17 17:06:25 -0700101 BMCWEB_LOG_INFO("Receivied reload signal");
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600102 loadCertificate();
Ed Tanouscb13a392020-07-25 19:02:03 +0000103 boost::system::error_code ec2;
Ed Tanous8db83742024-04-13 09:11:15 -0700104 acceptor.cancel(ec2);
Ed Tanouscb13a392020-07-25 19:02:03 +0000105 if (ec2)
Zbigniew Lukwinski7d0120b2019-10-15 09:12:45 +0200106 {
Ed Tanous62598e32023-07-17 17:06:25 -0700107 BMCWEB_LOG_ERROR(
108 "Error while canceling async operations:{}",
109 ec2.message());
Zbigniew Lukwinski7d0120b2019-10-15 09:12:45 +0200110 }
Ed Tanous21b4aba2023-06-05 11:42:43 -0700111 startAsyncWaitForSignal();
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600112 }
113 else
114 {
115 stop();
116 }
117 }
118 });
119 }
120
Ed Tanous1abe55e2018-09-05 08:30:59 -0700121 void stop()
122 {
123 ioService->stop();
124 }
125
126 void doAccept()
127 {
Ed Tanous8db83742024-04-13 09:11:15 -0700128 if (ioService == nullptr)
129 {
130 BMCWEB_LOG_CRITICAL("IoService was null");
131 return;
132 }
Ed Tanous5dfb5b22021-12-03 11:24:53 -0800133 boost::asio::steady_timer timer(*ioService);
Ed Tanous88e16122021-12-06 14:14:43 -0800134 std::shared_ptr<Connection<Adaptor, Handler>> connection;
Ed Tanousceac6f72018-12-02 11:58:47 -0800135 if constexpr (std::is_same<Adaptor,
Ed Tanous003301a2024-04-16 09:59:19 -0700136 boost::asio::ssl::stream<
Ed Tanousceac6f72018-12-02 11:58:47 -0800137 boost::asio::ip::tcp::socket>>::value)
138 {
Ed Tanous8db83742024-04-13 09:11:15 -0700139 if (adaptorCtx == nullptr)
140 {
141 BMCWEB_LOG_CRITICAL(
Abhilash Rajud5fb5842024-06-03 11:40:17 -0500142 "Asked to launch TLS socket but no context available");
Ed Tanous8db83742024-04-13 09:11:15 -0700143 return;
144 }
Ed Tanous88e16122021-12-06 14:14:43 -0800145 connection = std::make_shared<Connection<Adaptor, Handler>>(
Ed Tanous5dfb5b22021-12-03 11:24:53 -0800146 handler, std::move(timer), getCachedDateStr,
Ed Tanous88e16122021-12-06 14:14:43 -0800147 Adaptor(*ioService, *adaptorCtx));
Ed Tanousceac6f72018-12-02 11:58:47 -0800148 }
149 else
150 {
Ed Tanous88e16122021-12-06 14:14:43 -0800151 connection = std::make_shared<Connection<Adaptor, Handler>>(
Ed Tanous5dfb5b22021-12-03 11:24:53 -0800152 handler, std::move(timer), getCachedDateStr,
Ed Tanous88e16122021-12-06 14:14:43 -0800153 Adaptor(*ioService));
Ed Tanousceac6f72018-12-02 11:58:47 -0800154 }
Ed Tanous8db83742024-04-13 09:11:15 -0700155 acceptor.async_accept(
Ed Tanous88e16122021-12-06 14:14:43 -0800156 boost::beast::get_lowest_layer(connection->socket()),
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800157 [this, connection](const boost::system::error_code& ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -0700158 if (!ec)
159 {
Ed Tanous21b4aba2023-06-05 11:42:43 -0700160 boost::asio::post(*ioService,
Ed Tanous002d39b2022-05-31 08:59:27 -0700161 [connection] { connection->start(); });
162 }
163 doAccept();
Patrick Williams5a39f772023-10-20 11:20:21 -0500164 });
Ed Tanous1abe55e2018-09-05 08:30:59 -0700165 }
166
167 private:
Ed Tanous23e64202020-09-15 19:21:30 -0700168 std::shared_ptr<boost::asio::io_context> ioService;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700169 std::function<std::string()> getCachedDateStr;
Ed Tanous8db83742024-04-13 09:11:15 -0700170 boost::asio::ip::tcp::acceptor acceptor;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700171 boost::asio::signal_set signals;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700172
173 std::string dateStr;
174
175 Handler* handler;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700176
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600177 std::shared_ptr<boost::asio::ssl::context> adaptorCtx;
Ed Tanous5dfb5b22021-12-03 11:24:53 -0800178};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700179} // namespace crow