blob: ff8642d6d15a91c878331a06ccbc0598feeb69c2 [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 Tanous55c7b7a2018-05-22 15:27:24 -070030#ifdef BMCWEB_ENABLE_SSL
Ed Tanousceac6f72018-12-02 11:58:47 -080031 using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
Ed Tanous52cc1122020-07-18 13:51:21 -070032 using ssl_server_t = Server<App, ssl_socket_t>;
Ed Tanous789a6a32018-11-29 15:17:22 -080033#else
Ed Tanousceac6f72018-12-02 11:58:47 -080034 using socket_t = boost::asio::ip::tcp::socket;
Ed Tanous52cc1122020-07-18 13:51:21 -070035 using server_t = Server<App, socket_t>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070036#endif
Ed Tanousceac6f72018-12-02 11:58:47 -080037
Ed Tanous52cc1122020-07-18 13:51:21 -070038 explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
39 std::make_shared<boost::asio::io_context>()) :
Ed Tanous271584a2019-07-09 16:24:22 -070040 io(std::move(ioIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050041 {}
Ed Tanous52cc1122020-07-18 13:51:21 -070042 ~App()
Ed Tanous1abe55e2018-09-05 08:30:59 -070043 {
44 this->stop();
45 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070046
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 template <typename Adaptor>
48 void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
49 {
Ed Tanousceac6f72018-12-02 11:58:47 -080050 router.handleUpgrade(req, res, std::move(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070051 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070052
RAJESWARAN THILLAIGOVINDAN61dbeef2019-12-13 04:26:54 -060053 void handle(Request& req, Response& res)
Ed Tanous1abe55e2018-09-05 08:30:59 -070054 {
55 router.handle(req, res);
56 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070057
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 DynamicRule& routeDynamic(std::string&& rule)
59 {
60 return router.newRuleDynamic(rule);
61 }
62
Gunnar Mills1214b7e2020-06-04 10:11:30 -050063 template <uint64_t Tag>
64 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070065 {
66 return router.newRuleTagged<Tag>(std::move(rule));
67 }
68
Ed Tanousb74e4402020-09-09 20:26:26 -070069 App& socket(int existing_socket)
Ed Tanous1abe55e2018-09-05 08:30:59 -070070 {
71 socketFd = existing_socket;
72 return *this;
73 }
74
Ed Tanousb74e4402020-09-09 20:26:26 -070075 App& port(std::uint16_t port)
Ed Tanous1abe55e2018-09-05 08:30:59 -070076 {
77 portUint = port;
78 return *this;
79 }
80
Ed Tanousb74e4402020-09-09 20:26:26 -070081 App& bindaddr(std::string bindaddr)
Ed Tanous1abe55e2018-09-05 08:30:59 -070082 {
83 bindaddrStr = bindaddr;
84 return *this;
85 }
86
87 void validate()
88 {
89 router.validate();
90 }
91
92 void run()
93 {
94 validate();
95#ifdef BMCWEB_ENABLE_SSL
Ed Tanous789a6a32018-11-29 15:17:22 -080096 if (-1 == socketFd)
Ed Tanous1abe55e2018-09-05 08:30:59 -070097 {
Ed Tanous23a21a12020-07-25 04:45:05 +000098 sslServer = std::make_unique<ssl_server_t>(
99 this, bindaddrStr, portUint, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700100 }
101 else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700102 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000103 sslServer =
104 std::make_unique<ssl_server_t>(this, socketFd, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700105 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800106 sslServer->run();
107
108#else
109
110 if (-1 == socketFd)
111 {
112 server = std::move(std::make_unique<server_t>(
Ed Tanous52cc1122020-07-18 13:51:21 -0700113 this, bindaddrStr, portUint, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800114 }
115 else
116 {
Ed Tanous52cc1122020-07-18 13:51:21 -0700117 server = std::move(
118 std::make_unique<server_t>(this, socketFd, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800119 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800120 server->run();
121
122#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700123 }
124
125 void stop()
126 {
127 io->stop();
128 }
129
130 void debugPrint()
131 {
132 BMCWEB_LOG_DEBUG << "Routing:";
133 router.debugPrint();
134 }
135
136 std::vector<const std::string*> getRoutes()
137 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700138 const std::string root("");
139 return router.getRoutes(root);
140 }
141 std::vector<const std::string*> getRoutes(const std::string& parent)
142 {
143 return router.getRoutes(parent);
144 }
Ed Tanousb4a7bfa2017-04-04 17:23:00 -0700145
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700146#ifdef BMCWEB_ENABLE_SSL
Ed Tanousb74e4402020-09-09 20:26:26 -0700147 App& sslFile(const std::string& crt_filename,
148 const std::string& key_filename)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700149 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600150 sslContext = std::make_shared<ssl_context_t>(
151 boost::asio::ssl::context::tls_server);
152 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
153 sslContext->use_certificate_file(crt_filename, ssl_context_t::pem);
154 sslContext->use_private_key_file(key_filename, ssl_context_t::pem);
155 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
156 boost::asio::ssl::context::no_sslv2 |
157 boost::asio::ssl::context::no_sslv3 |
158 boost::asio::ssl::context::no_tlsv1 |
159 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700160 return *this;
161 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700162
Ed Tanousb74e4402020-09-09 20:26:26 -0700163 App& sslFile(const std::string& pem_filename)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700164 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600165 sslContext = std::make_shared<ssl_context_t>(
166 boost::asio::ssl::context::tls_server);
167 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
168 sslContext->load_verify_file(pem_filename);
169 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
170 boost::asio::ssl::context::no_sslv2 |
171 boost::asio::ssl::context::no_sslv3 |
172 boost::asio::ssl::context::no_tlsv1 |
173 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700174 return *this;
175 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700176
Ed Tanousb74e4402020-09-09 20:26:26 -0700177 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700178 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700179 sslContext = std::move(ctx);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600180 BMCWEB_LOG_INFO << "app::ssl context use_count="
181 << sslContext.use_count();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700182 return *this;
183 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700184
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600185 std::shared_ptr<ssl_context_t> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700186
187#else
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500188 template <typename T, typename... Remain>
Ed Tanousb74e4402020-09-09 20:26:26 -0700189 App& ssl_file(T&&, Remain&&...)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700190 {
191 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
192 // defined.
193 static_assert(
194 // make static_assert dependent to T; always false
195 std::is_base_of<T, void>::value,
196 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
197 return *this;
198 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700199
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500200 template <typename T>
Ed Tanousb74e4402020-09-09 20:26:26 -0700201 App& ssl(T&&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202 {
203 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
204 // defined.
205 static_assert(
206 // make static_assert dependent to T; always false
207 std::is_base_of<T, void>::value,
208 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
209 return *this;
210 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700211#endif
212
Ed Tanous1abe55e2018-09-05 08:30:59 -0700213 private:
Ed Tanous23e64202020-09-15 19:21:30 -0700214 std::shared_ptr<boost::asio::io_context> io;
Ed Tanous789a6a32018-11-29 15:17:22 -0800215#ifdef BMCWEB_ENABLE_SSL
216 uint16_t portUint = 443;
217#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700218 uint16_t portUint = 80;
Ed Tanous789a6a32018-11-29 15:17:22 -0800219#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700220 std::string bindaddrStr = "::";
221 int socketFd = -1;
222 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700223
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700224#ifdef BMCWEB_ENABLE_SSL
Ed Tanous1abe55e2018-09-05 08:30:59 -0700225 std::unique_ptr<ssl_server_t> sslServer;
Ed Tanous789a6a32018-11-29 15:17:22 -0800226#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700227 std::unique_ptr<server_t> server;
Ed Tanous789a6a32018-11-29 15:17:22 -0800228#endif
Ed Tanous7045c8d2017-04-03 10:04:37 -0700229};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700230} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700231using App = crow::App;