blob: dfd530454390d83ac33ee17d45a04b8f360eecfa [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Gunnar Mills1214b7e2020-06-04 10:11:30 -05003#include "http_request.h"
4#include "http_server.h"
5#include "logging.h"
Gunnar Mills1214b7e2020-06-04 10:11:30 -05006#include "routing.h"
7#include "utility.h"
8
Tanousf00032d2018-11-05 01:18:10 -03009#include "privileges.hpp"
10
Ed Tanous7045c8d2017-04-03 10:04:37 -070011#include <chrono>
12#include <cstdint>
13#include <functional>
14#include <future>
15#include <memory>
16#include <string>
Ed Tanous911ac312017-08-15 09:37:42 -070017#include <utility>
Ed Tanous1abe55e2018-09-05 08:30:59 -070018
Ed Tanous1abe55e2018-09-05 08:30:59 -070019#define BMCWEB_ROUTE(app, url) \
20 app.template route<crow::black_magic::get_parameter_tag(url)>(url)
Ed Tanous7045c8d2017-04-03 10:04:37 -070021
Ed Tanous1abe55e2018-09-05 08:30:59 -070022namespace crow
23{
Ed Tanous55c7b7a2018-05-22 15:27:24 -070024#ifdef BMCWEB_ENABLE_SSL
Ed Tanous7045c8d2017-04-03 10:04:37 -070025using ssl_context_t = boost::asio::ssl::context;
26#endif
Ed Tanous52cc1122020-07-18 13:51:21 -070027class App
Ed Tanous1abe55e2018-09-05 08:30:59 -070028{
29 public:
Ed Tanous52cc1122020-07-18 13:51:21 -070030 using self_t = App;
Ed Tanous789a6a32018-11-29 15:17:22 -080031
Ed Tanous55c7b7a2018-05-22 15:27:24 -070032#ifdef BMCWEB_ENABLE_SSL
Ed Tanousceac6f72018-12-02 11:58:47 -080033 using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
Ed Tanous52cc1122020-07-18 13:51:21 -070034 using ssl_server_t = Server<App, ssl_socket_t>;
Ed Tanous789a6a32018-11-29 15:17:22 -080035#else
Ed Tanousceac6f72018-12-02 11:58:47 -080036 using socket_t = boost::asio::ip::tcp::socket;
Ed Tanous52cc1122020-07-18 13:51:21 -070037 using server_t = Server<App, socket_t>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070038#endif
Ed Tanousceac6f72018-12-02 11:58:47 -080039
Ed Tanous52cc1122020-07-18 13:51:21 -070040 explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
41 std::make_shared<boost::asio::io_context>()) :
Ed Tanous271584a2019-07-09 16:24:22 -070042 io(std::move(ioIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050043 {}
Ed Tanous52cc1122020-07-18 13:51:21 -070044 ~App()
Ed Tanous1abe55e2018-09-05 08:30:59 -070045 {
46 this->stop();
47 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070048
Ed Tanous1abe55e2018-09-05 08:30:59 -070049 template <typename Adaptor>
50 void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
51 {
Ed Tanousceac6f72018-12-02 11:58:47 -080052 router.handleUpgrade(req, res, std::move(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070054
RAJESWARAN THILLAIGOVINDAN61dbeef2019-12-13 04:26:54 -060055 void handle(Request& req, Response& res)
Ed Tanous1abe55e2018-09-05 08:30:59 -070056 {
57 router.handle(req, res);
58 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070059
Ed Tanous1abe55e2018-09-05 08:30:59 -070060 DynamicRule& routeDynamic(std::string&& rule)
61 {
62 return router.newRuleDynamic(rule);
63 }
64
Gunnar Mills1214b7e2020-06-04 10:11:30 -050065 template <uint64_t Tag>
66 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070067 {
68 return router.newRuleTagged<Tag>(std::move(rule));
69 }
70
71 self_t& socket(int existing_socket)
72 {
73 socketFd = existing_socket;
74 return *this;
75 }
76
77 self_t& port(std::uint16_t port)
78 {
79 portUint = port;
80 return *this;
81 }
82
83 self_t& bindaddr(std::string bindaddr)
84 {
85 bindaddrStr = bindaddr;
86 return *this;
87 }
88
89 void validate()
90 {
91 router.validate();
92 }
93
94 void run()
95 {
96 validate();
97#ifdef BMCWEB_ENABLE_SSL
Ed Tanous789a6a32018-11-29 15:17:22 -080098 if (-1 == socketFd)
Ed Tanous1abe55e2018-09-05 08:30:59 -070099 {
Ed Tanous789a6a32018-11-29 15:17:22 -0800100 sslServer = std::move(std::make_unique<ssl_server_t>(
Ed Tanous52cc1122020-07-18 13:51:21 -0700101 this, bindaddrStr, portUint, sslContext, io));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700102 }
103 else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700104 {
Ed Tanous52cc1122020-07-18 13:51:21 -0700105 sslServer = std::move(
106 std::make_unique<ssl_server_t>(this, socketFd, sslContext, io));
Ed Tanous1abe55e2018-09-05 08:30:59 -0700107 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800108 sslServer->setTickFunction(tickInterval, tickFunction);
109 sslServer->run();
110
111#else
112
113 if (-1 == socketFd)
114 {
115 server = std::move(std::make_unique<server_t>(
Ed Tanous52cc1122020-07-18 13:51:21 -0700116 this, bindaddrStr, portUint, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800117 }
118 else
119 {
Ed Tanous52cc1122020-07-18 13:51:21 -0700120 server = std::move(
121 std::make_unique<server_t>(this, socketFd, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800122 }
123 server->setTickFunction(tickInterval, tickFunction);
124 server->run();
125
126#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700127 }
128
129 void stop()
130 {
131 io->stop();
132 }
133
134 void debugPrint()
135 {
136 BMCWEB_LOG_DEBUG << "Routing:";
137 router.debugPrint();
138 }
139
140 std::vector<const std::string*> getRoutes()
141 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700142 const std::string root("");
143 return router.getRoutes(root);
144 }
145 std::vector<const std::string*> getRoutes(const std::string& parent)
146 {
147 return router.getRoutes(parent);
148 }
Ed Tanousb4a7bfa2017-04-04 17:23:00 -0700149
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700150#ifdef BMCWEB_ENABLE_SSL
Ed Tanous1abe55e2018-09-05 08:30:59 -0700151 self_t& sslFile(const std::string& crt_filename,
152 const std::string& key_filename)
153 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600154 sslContext = std::make_shared<ssl_context_t>(
155 boost::asio::ssl::context::tls_server);
156 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
157 sslContext->use_certificate_file(crt_filename, ssl_context_t::pem);
158 sslContext->use_private_key_file(key_filename, ssl_context_t::pem);
159 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
160 boost::asio::ssl::context::no_sslv2 |
161 boost::asio::ssl::context::no_sslv3 |
162 boost::asio::ssl::context::no_tlsv1 |
163 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 return *this;
165 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700166
Ed Tanous1abe55e2018-09-05 08:30:59 -0700167 self_t& sslFile(const std::string& pem_filename)
168 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600169 sslContext = std::make_shared<ssl_context_t>(
170 boost::asio::ssl::context::tls_server);
171 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
172 sslContext->load_verify_file(pem_filename);
173 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
174 boost::asio::ssl::context::no_sslv2 |
175 boost::asio::ssl::context::no_sslv3 |
176 boost::asio::ssl::context::no_tlsv1 |
177 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700178 return *this;
179 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700180
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600181 self_t& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700182 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700183 sslContext = std::move(ctx);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600184 BMCWEB_LOG_INFO << "app::ssl context use_count="
185 << sslContext.use_count();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700186 return *this;
187 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700188
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600189 std::shared_ptr<ssl_context_t> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700190
191#else
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500192 template <typename T, typename... Remain>
193 self_t& ssl_file(T&&, Remain&&...)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700194 {
195 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
196 // defined.
197 static_assert(
198 // make static_assert dependent to T; always false
199 std::is_base_of<T, void>::value,
200 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
201 return *this;
202 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700203
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500204 template <typename T>
205 self_t& ssl(T&&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 {
207 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
208 // defined.
209 static_assert(
210 // make static_assert dependent to T; always false
211 std::is_base_of<T, void>::value,
212 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
213 return *this;
214 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700215#endif
216
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500217 template <typename Duration, typename Func>
218 self_t& tick(Duration d, Func f)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700219 {
220 tickInterval = std::chrono::duration_cast<std::chrono::milliseconds>(d);
221 tickFunction = f;
222 return *this;
223 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700224
Ed Tanous1abe55e2018-09-05 08:30:59 -0700225 private:
Ed Tanous8f626352018-12-19 14:51:54 -0800226 std::shared_ptr<asio::io_context> io;
Ed Tanous789a6a32018-11-29 15:17:22 -0800227#ifdef BMCWEB_ENABLE_SSL
228 uint16_t portUint = 443;
229#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700230 uint16_t portUint = 80;
Ed Tanous789a6a32018-11-29 15:17:22 -0800231#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700232 std::string bindaddrStr = "::";
233 int socketFd = -1;
234 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700235
Ed Tanous1abe55e2018-09-05 08:30:59 -0700236 std::chrono::milliseconds tickInterval{};
237 std::function<void()> tickFunction;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700238
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700239#ifdef BMCWEB_ENABLE_SSL
Ed Tanous1abe55e2018-09-05 08:30:59 -0700240 std::unique_ptr<ssl_server_t> sslServer;
Ed Tanous789a6a32018-11-29 15:17:22 -0800241#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700242 std::unique_ptr<server_t> server;
Ed Tanous789a6a32018-11-29 15:17:22 -0800243#endif
Ed Tanous7045c8d2017-04-03 10:04:37 -0700244};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700245} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700246using App = crow::App;