blob: 023eabbfc3ba1b0bae6487d904c63d858fc84a60 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Ed Tanous04e438c2020-10-03 08:06:26 -07003#include "http_request.hpp"
4#include "http_server.hpp"
5#include "logging.hpp"
Tanousf00032d2018-11-05 01:18:10 -03006#include "privileges.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -07007#include "routing.hpp"
8#include "utility.hpp"
Tanousf00032d2018-11-05 01:18:10 -03009
Ed Tanous7045c8d2017-04-03 10:04:37 -070010#include <chrono>
11#include <cstdint>
12#include <functional>
13#include <future>
14#include <memory>
15#include <string>
Ed Tanous911ac312017-08-15 09:37:42 -070016#include <utility>
Ed Tanous1abe55e2018-09-05 08:30:59 -070017
Ed Tanous1abe55e2018-09-05 08:30:59 -070018#define BMCWEB_ROUTE(app, url) \
Ed Tanous988403c2020-08-24 11:29:49 -070019 app.template route<crow::black_magic::getParameterTag(url)>(url)
Ed Tanous7045c8d2017-04-03 10:04:37 -070020
Ed Tanous1abe55e2018-09-05 08:30:59 -070021namespace crow
22{
Ed Tanous55c7b7a2018-05-22 15:27:24 -070023#ifdef BMCWEB_ENABLE_SSL
Ed Tanous7045c8d2017-04-03 10:04:37 -070024using ssl_context_t = boost::asio::ssl::context;
25#endif
Ed Tanous52cc1122020-07-18 13:51:21 -070026class App
Ed Tanous1abe55e2018-09-05 08:30:59 -070027{
28 public:
Ed Tanous55c7b7a2018-05-22 15:27:24 -070029#ifdef BMCWEB_ENABLE_SSL
Ed Tanousceac6f72018-12-02 11:58:47 -080030 using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
Ed Tanous52cc1122020-07-18 13:51:21 -070031 using ssl_server_t = Server<App, ssl_socket_t>;
Ed Tanous789a6a32018-11-29 15:17:22 -080032#else
Ed Tanousceac6f72018-12-02 11:58:47 -080033 using socket_t = boost::asio::ip::tcp::socket;
Ed Tanous52cc1122020-07-18 13:51:21 -070034 using server_t = Server<App, socket_t>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070035#endif
Ed Tanousceac6f72018-12-02 11:58:47 -080036
Ed Tanous52cc1122020-07-18 13:51:21 -070037 explicit App(std::shared_ptr<boost::asio::io_context> ioIn =
38 std::make_shared<boost::asio::io_context>()) :
Ed Tanous271584a2019-07-09 16:24:22 -070039 io(std::move(ioIn))
Gunnar Mills1214b7e2020-06-04 10:11:30 -050040 {}
Ed Tanous52cc1122020-07-18 13:51:21 -070041 ~App()
Ed Tanous1abe55e2018-09-05 08:30:59 -070042 {
43 this->stop();
44 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070045
Ed Tanous1abe55e2018-09-05 08:30:59 -070046 template <typename Adaptor>
47 void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
48 {
Ed Tanousceac6f72018-12-02 11:58:47 -080049 router.handleUpgrade(req, res, std::move(adaptor));
Ed Tanous1abe55e2018-09-05 08:30:59 -070050 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070051
RAJESWARAN THILLAIGOVINDAN61dbeef2019-12-13 04:26:54 -060052 void handle(Request& req, Response& res)
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 {
54 router.handle(req, res);
55 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070056
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 DynamicRule& routeDynamic(std::string&& rule)
58 {
59 return router.newRuleDynamic(rule);
60 }
61
Gunnar Mills1214b7e2020-06-04 10:11:30 -050062 template <uint64_t Tag>
63 auto& route(std::string&& rule)
Ed Tanous1abe55e2018-09-05 08:30:59 -070064 {
65 return router.newRuleTagged<Tag>(std::move(rule));
66 }
67
Ed Tanous81ce6092020-12-17 16:54:55 +000068 App& socket(int existingSocket)
Ed Tanous1abe55e2018-09-05 08:30:59 -070069 {
Ed Tanous81ce6092020-12-17 16:54:55 +000070 socketFd = existingSocket;
Ed Tanous1abe55e2018-09-05 08:30:59 -070071 return *this;
72 }
73
Ed Tanousb74e4402020-09-09 20:26:26 -070074 App& port(std::uint16_t port)
Ed Tanous1abe55e2018-09-05 08:30:59 -070075 {
76 portUint = port;
77 return *this;
78 }
79
Ed Tanousb74e4402020-09-09 20:26:26 -070080 App& bindaddr(std::string bindaddr)
Ed Tanous1abe55e2018-09-05 08:30:59 -070081 {
Ed Tanousb5a76932020-09-29 16:16:58 -070082 bindaddrStr = std::move(bindaddr);
Ed Tanous1abe55e2018-09-05 08:30:59 -070083 return *this;
84 }
85
86 void validate()
87 {
88 router.validate();
89 }
90
91 void run()
92 {
93 validate();
94#ifdef BMCWEB_ENABLE_SSL
Ed Tanous789a6a32018-11-29 15:17:22 -080095 if (-1 == socketFd)
Ed Tanous1abe55e2018-09-05 08:30:59 -070096 {
Ed Tanous23a21a12020-07-25 04:45:05 +000097 sslServer = std::make_unique<ssl_server_t>(
98 this, bindaddrStr, portUint, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -070099 }
100 else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700101 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000102 sslServer =
103 std::make_unique<ssl_server_t>(this, socketFd, sslContext, io);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700104 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800105 sslServer->run();
106
107#else
108
109 if (-1 == socketFd)
110 {
111 server = std::move(std::make_unique<server_t>(
Ed Tanous52cc1122020-07-18 13:51:21 -0700112 this, bindaddrStr, portUint, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800113 }
114 else
115 {
Ed Tanous52cc1122020-07-18 13:51:21 -0700116 server = std::move(
117 std::make_unique<server_t>(this, socketFd, nullptr, io));
Ed Tanous789a6a32018-11-29 15:17:22 -0800118 }
Ed Tanous789a6a32018-11-29 15:17:22 -0800119 server->run();
120
121#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700122 }
123
124 void stop()
125 {
126 io->stop();
127 }
128
129 void debugPrint()
130 {
131 BMCWEB_LOG_DEBUG << "Routing:";
132 router.debugPrint();
133 }
134
135 std::vector<const std::string*> getRoutes()
136 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700137 const std::string root("");
138 return router.getRoutes(root);
139 }
140 std::vector<const std::string*> getRoutes(const std::string& parent)
141 {
142 return router.getRoutes(parent);
143 }
Ed Tanousb4a7bfa2017-04-04 17:23:00 -0700144
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700145#ifdef BMCWEB_ENABLE_SSL
Ed Tanous81ce6092020-12-17 16:54:55 +0000146 App& sslFile(const std::string& crtFilename, const std::string& keyFilename)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700147 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600148 sslContext = std::make_shared<ssl_context_t>(
149 boost::asio::ssl::context::tls_server);
150 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
Ed Tanous81ce6092020-12-17 16:54:55 +0000151 sslContext->use_certificate_file(crtFilename, ssl_context_t::pem);
152 sslContext->use_private_key_file(keyFilename, ssl_context_t::pem);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600153 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
154 boost::asio::ssl::context::no_sslv2 |
155 boost::asio::ssl::context::no_sslv3 |
156 boost::asio::ssl::context::no_tlsv1 |
157 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700158 return *this;
159 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700160
Ed Tanous81ce6092020-12-17 16:54:55 +0000161 App& sslFile(const std::string& pemFilename)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700162 {
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600163 sslContext = std::make_shared<ssl_context_t>(
164 boost::asio::ssl::context::tls_server);
165 sslContext->set_verify_mode(boost::asio::ssl::verify_peer);
Ed Tanous81ce6092020-12-17 16:54:55 +0000166 sslContext->load_verify_file(pemFilename);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600167 sslContext->set_options(boost::asio::ssl::context::default_workarounds |
168 boost::asio::ssl::context::no_sslv2 |
169 boost::asio::ssl::context::no_sslv3 |
170 boost::asio::ssl::context::no_tlsv1 |
171 boost::asio::ssl::context::no_tlsv1_1);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700172 return *this;
173 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700174
Ed Tanousb74e4402020-09-09 20:26:26 -0700175 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700176 {
Ed Tanous1abe55e2018-09-05 08:30:59 -0700177 sslContext = std::move(ctx);
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600178 BMCWEB_LOG_INFO << "app::ssl context use_count="
179 << sslContext.use_count();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700180 return *this;
181 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700182
Marri Devender Rao5968cae2019-01-21 10:27:12 -0600183 std::shared_ptr<ssl_context_t> sslContext = nullptr;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700184
185#else
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500186 template <typename T, typename... Remain>
Ed Tanousb74e4402020-09-09 20:26:26 -0700187 App& ssl_file(T&&, Remain&&...)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700188 {
189 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
190 // defined.
191 static_assert(
192 // make static_assert dependent to T; always false
193 std::is_base_of<T, void>::value,
194 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
195 return *this;
196 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700197
Gunnar Mills1214b7e2020-06-04 10:11:30 -0500198 template <typename T>
Ed Tanousb74e4402020-09-09 20:26:26 -0700199 App& ssl(T&&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700200 {
201 // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
202 // defined.
203 static_assert(
204 // make static_assert dependent to T; always false
205 std::is_base_of<T, void>::value,
206 "Define BMCWEB_ENABLE_SSL to enable ssl support.");
207 return *this;
208 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700209#endif
210
Ed Tanous1abe55e2018-09-05 08:30:59 -0700211 private:
Ed Tanous23e64202020-09-15 19:21:30 -0700212 std::shared_ptr<boost::asio::io_context> io;
Ed Tanous789a6a32018-11-29 15:17:22 -0800213#ifdef BMCWEB_ENABLE_SSL
214 uint16_t portUint = 443;
215#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700216 uint16_t portUint = 80;
Ed Tanous789a6a32018-11-29 15:17:22 -0800217#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -0700218 std::string bindaddrStr = "::";
219 int socketFd = -1;
220 Router router;
Ed Tanous7045c8d2017-04-03 10:04:37 -0700221
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700222#ifdef BMCWEB_ENABLE_SSL
Ed Tanous1abe55e2018-09-05 08:30:59 -0700223 std::unique_ptr<ssl_server_t> sslServer;
Ed Tanous789a6a32018-11-29 15:17:22 -0800224#else
Ed Tanous1abe55e2018-09-05 08:30:59 -0700225 std::unique_ptr<server_t> server;
Ed Tanous789a6a32018-11-29 15:17:22 -0800226#endif
Ed Tanous7045c8d2017-04-03 10:04:37 -0700227};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700228} // namespace crow
Ed Tanous52cc1122020-07-18 13:51:21 -0700229using App = crow::App;