1 #pragma once 2 3 #include "async_resp.hpp" 4 #include "http_request.hpp" 5 #include "http_server.hpp" 6 #include "logging.hpp" 7 #include "privileges.hpp" 8 #include "routing.hpp" 9 #include "utility.hpp" 10 11 #include <boost/asio/io_context.hpp> 12 #include <boost/asio/ip/tcp.hpp> 13 #include <boost/asio/ssl/context.hpp> 14 #include <boost/beast/ssl/ssl_stream.hpp> 15 16 #include <chrono> 17 #include <cstdint> 18 #include <functional> 19 #include <future> 20 #include <memory> 21 #include <string> 22 #include <utility> 23 24 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros) 25 #define BMCWEB_ROUTE(app, url) \ 26 app.template route<crow::utility::getParameterTag(url)>(url) 27 28 namespace crow 29 { 30 class App 31 { 32 public: 33 using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>; 34 using ssl_server_t = Server<App, ssl_socket_t>; 35 using socket_t = boost::asio::ip::tcp::socket; 36 using server_t = Server<App, socket_t>; 37 38 explicit App(std::shared_ptr<boost::asio::io_context> ioIn = 39 std::make_shared<boost::asio::io_context>()) : 40 io(std::move(ioIn)) 41 {} 42 ~App() 43 { 44 stop(); 45 } 46 47 App(const App&) = delete; 48 App(App&&) = delete; 49 App& operator=(const App&) = delete; 50 App& operator=(const App&&) = delete; 51 52 template <typename Adaptor> 53 void handleUpgrade(Request& req, 54 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 55 Adaptor&& adaptor) 56 { 57 router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor)); 58 } 59 60 void handle(Request& req, 61 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 62 { 63 router.handle(req, asyncResp); 64 } 65 66 DynamicRule& routeDynamic(const std::string& rule) 67 { 68 return router.newRuleDynamic(rule); 69 } 70 71 template <uint64_t Tag> 72 auto& route(std::string&& rule) 73 { 74 return router.newRuleTagged<Tag>(std::move(rule)); 75 } 76 77 App& socket(int existingSocket) 78 { 79 socketFd = existingSocket; 80 return *this; 81 } 82 83 App& port(std::uint16_t port) 84 { 85 portUint = port; 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 98 if (-1 == socketFd) 99 { 100 sslServer = std::make_unique<ssl_server_t>(this, portUint, 101 sslContext, io); 102 } 103 else 104 { 105 sslServer = std::make_unique<ssl_server_t>(this, socketFd, 106 sslContext, io); 107 } 108 sslServer->run(); 109 110 #else 111 112 if (-1 == socketFd) 113 { 114 server = std::make_unique<server_t>(this, portUint, nullptr, io); 115 } 116 else 117 { 118 server = std::make_unique<server_t>(this, socketFd, nullptr, io); 119 } 120 server->run(); 121 122 #endif 123 } 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 { 138 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 } 145 146 App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx) 147 { 148 sslContext = std::move(ctx); 149 BMCWEB_LOG_INFO("app::ssl context use_count={}", 150 sslContext.use_count()); 151 return *this; 152 } 153 154 std::shared_ptr<boost::asio::ssl::context> sslContext = nullptr; 155 156 boost::asio::io_context& ioContext() 157 { 158 return *io; 159 } 160 161 private: 162 std::shared_ptr<boost::asio::io_context> io; 163 #ifdef BMCWEB_ENABLE_SSL 164 uint16_t portUint = 443; 165 #else 166 uint16_t portUint = 80; 167 #endif 168 int socketFd = -1; 169 Router router; 170 171 #ifdef BMCWEB_ENABLE_SSL 172 std::unique_ptr<ssl_server_t> sslServer; 173 #else 174 std::unique_ptr<server_t> server; 175 #endif 176 }; 177 } // namespace crow 178 using App = crow::App; 179