blob: 9ee082feec504a1817243dac1299cbd732ad4430 [file] [log] [blame] [edit]
#pragma once
#include "app_interface.h"
#include "async_resp.hpp"
#include "http_request.hpp"
#include "smart_router.h"
#include "utility.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#ifdef BMCWEB_ENABLE_SSL
#include <boost/asio/ssl/context.hpp>
#include <boost/beast/ssl/ssl_stream.hpp>
#endif
#include <array>
#include <chrono>
#include <cstdint>
#include <functional>
#include <future>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define BMCWEB_ROUTE(app, url) \
app.template route<crow::black_magic::getParameterTag(url)>(url)
#ifdef BMCWEB_ENABLE_SSL
using ssl_context_t = boost::asio::ssl::context;
using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
#else
using socket_t = boost::asio::ip::tcp::socket;
#endif
namespace crow
{
class App
{
public:
explicit App(bool allowSessionEmpty,
std::shared_ptr<boost::asio::io_context> ioIn =
std::make_shared<boost::asio::io_context>(),
AppInterface* tlbmc_app = nullptr) :
io(std::move(ioIn)),
router(allowSessionEmpty, tlbmc_app)
{}
~App()
{
this->stop();
}
App(const App&) = delete;
App(App&&) = delete;
App& operator=(const App&) = delete;
App& operator=(const App&&) = delete;
template <typename Adaptor>
void handleUpgrade(Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Adaptor&& adaptor)
{
router.HandleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor));
}
void handle(Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);
DynamicRule& routeDynamic(std::string&& rule)
{
return router.NewRuleDynamic(std::move(rule));
}
template <uint64_t Tag>
auto& route(std::string&& rule)
{
return router.NewRuleTagged<Tag>(std::move(rule));
}
App& socket(int existingSocket)
{
socketFd = existingSocket;
return *this;
}
App& port(std::uint16_t port)
{
portUint = port;
return *this;
}
App& bindaddr(std::string bindaddr)
{
bindaddrStr = std::move(bindaddr);
return *this;
}
void validate()
{
router.Validate();
}
void run();
void stop()
{
io->stop();
}
void debugPrint();
std::vector<const std::string*> getRoutes()
{
const std::string root;
return router.GetRoutes(root);
}
std::vector<const std::string*> getRoutes(const std::string& parent)
{
return router.GetRoutes(parent);
}
template <uint64_t Tag, typename Func, size_t N>
void addHandler(std::string_view url, boost::beast::http::verb verb,
const std::array<redfish::Privileges, N>& p, Func&& func)
{
router.NewRuleTagged<Tag>(url).methods(verb).privileges(p)(func);
}
template <uint64_t Tag, typename Func>
void replaceHandler(std::string_view url, boost::beast::http::verb verb,
Func&& func)
{
router.ReplaceHandler<Tag>(url, verb, func);
}
template <uint64_t Tag>
void removeHandler(std::string_view url, boost::beast::http::verb verb)
{
router.RemoveHandler<Tag>(url, verb);
}
template <uint64_t Tag, typename Func>
void appendHandler(std::string_view url, boost::beast::http::verb verb,
Func&& func)
{
router.AppendHandler<Tag>(url, verb, func);
}
#ifdef BMCWEB_ENABLE_SSL
App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
{
sslContext = std::move(ctx);
BMCWEB_LOG_INFO << "app::ssl context use_count="
<< sslContext.use_count();
return *this;
}
std::shared_ptr<ssl_context_t> sslContext = nullptr;
#else
template <typename T>
App& ssl(T&& /*unused*/)
{
// We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
// defined.
static_assert(
// make static_assert dependent to T; always false
std::is_base_of<T, void>::value,
"Define BMCWEB_ENABLE_SSL to enable ssl support.");
return *this;
}
#endif
private:
std::shared_ptr<boost::asio::io_context> io;
#ifdef BMCWEB_ENABLE_SSL
uint16_t portUint = 443;
#else
uint16_t portUint = 80;
#endif
std::string bindaddrStr = "0.0.0.0";
int socketFd = -1;
SmartRouter router;
};
} // namespace crow
using App = crow::App;