/* * (c) Copyright, Real-Time Innovations, 2019. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef HTTP_SERVER_HPP #define HTTP_SERVER_HPP #include #include #include #include #include "ServerProperty.hpp" #include "rti/apputils/http/server/detail/CivetWebHandler.hpp" namespace rti { namespace apputils { namespace http { namespace server { /** * @brief Server defines an interface to CivetWeb::CivetServer and allow us to * create handlers and close the server thought it. */ class Server { public: /** * @brief Constructor of the Server class. * * @param options CivetServer options * @param callbacks Callbacks methods */ Server(const ServerProperty& server_property, const CivetCallbacks *callbacks = nullptr) : server_(std::unique_ptr(new CivetServer( server_property.webserver_options(), callbacks))), server_property_(server_property), handlers_() { } ~Server() { close(); mg_exit_library(); } /** * @brief This method closes the server, i.e. calls CivetServer::close(). */ void close() { constexpr auto num_retries = 10u; for (auto i = 0u; !can_close() && i < num_retries; ++i) { std::this_thread::sleep_for(std::chrono::seconds(1)); } server_->close(); } /** * @brief Checks if the server has any callbacks still running so that it * can be closed. * * @return True if the server can be closed. False otherwise. */ bool can_close() { return std::none_of( handlers_.begin(), handlers_.end(), [](const std::unique_ptr& handler) { return handler->callbacks_running(); }); } template void add_handler(Handler *handler) { handlers_.emplace_back(std::unique_ptr( new CivetWebHandler(server_property_, *this, handler))); server_->addHandler(Handler::URI_PATTERN, handlers_.back().get()); } /** * @brief Adds a URI handler. Existing handlers will be overwritten. * * @param uri String with the URI * @param handler CivetServer pointer to the handler that to be added */ template void add_handler() { add_handler(new Handler()); } /** * @brief Adds a URI websocket handler. Existing websocket handlers will be * overwritten. * * @param uri String with the URI * @param websocket_handler CivetServer pointer to the handler that to be * added */ void add_websocket_handler(const std::string& uri, void *websocket_handler) { server_->addWebSocketHandler( uri, reinterpret_cast(websocket_handler)); } private: std::unique_ptr server_; const ServerProperty& server_property_; std::vector> handlers_; }; }}}} // namespace rti::apputils::http::server #endif // HTTP_SERVER_HPP