125 lines
3.4 KiB
C++
125 lines
3.4 KiB
C++
/*
|
|
* (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 <memory>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
#include <CivetServer.h>
|
|
|
|
#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<CivetServer>(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<CivetWebHandler>& handler) {
|
|
return handler->callbacks_running();
|
|
});
|
|
}
|
|
|
|
template <typename Handler>
|
|
void add_handler(Handler *handler)
|
|
{
|
|
handlers_.emplace_back(std::unique_ptr<CivetWebHandler>(
|
|
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 <typename Handler>
|
|
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<CivetWebSocketHandler *>(websocket_handler));
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<CivetServer> server_;
|
|
const ServerProperty& server_property_;
|
|
std::vector<std::unique_ptr<CivetWebHandler>> handlers_;
|
|
};
|
|
|
|
}}}} // namespace rti::apputils::http::server
|
|
|
|
#endif // HTTP_SERVER_HPP
|