Seafire-Server/seafire/server/transaction.hxx
2025-03-07 22:15:36 +01:00

218 lines
4.5 KiB
C++

#ifndef seafire__server__transaction_hxx_
#define seafire__server__transaction_hxx_
#include <seafire/common/allocator.hxx>
#include <seafire/common/diagnostics.hxx>
#include <seafire/common/extension-context.hxx>
#include <seafire/common/io/buffer.hxx>
#include <seafire/server/error-handler.hxx>
#include <seafire/server/request-handler.hxx>
#include <seafire/server/request.hxx>
#include <seafire/server/response.hxx>
#include <seafire/protocol/connection.hxx>
#include <asio.hpp>
#include <chrono>
#include <iostream>
#include <memory>
#include <mutex>
namespace seafire::server
{
class transaction_t
: public std::enable_shared_from_this<transaction_t>,
request_t,
response_t
{
public:
struct configuration_t;
/// The result of this transaction.
///
enum result_t
{
/// Indicates a completed transation.
///
complete,
/// Indicates a completed transation and that the
/// underlying connection should be closed.
complete_closed
};
/// Completion handler type.
///
using completion_handler_t = std::function<void(std::error_code, result_t)>;
virtual
~transaction_t() noexcept(false);
error_handler_t&
get_error_handler();
protocol::connection_t&
connection();
asio::any_io_executor const&
get_executor();
void
start();
void
cancel();
// =================
// Common interface.
//
common::allocator_t&
memory() override;
// ==================
// Request interface.
//
// fixme: make these private.
//
protocol::request_t const&
get_request() const override;
std::istream&
get_request_content() override;
common::extension_context_t&
get_request_extensions() override;
// ===================
// Response interface.
//
// fixme: make these private.
//
void
register_finalizer(finalizer_t* f) override;
void
deregister_finalizer(finalizer_t* f) override;
protocol::response_t&
get_response() override;
protocol::response_t const&
get_response() const override;
common::extension_context_t&
get_response_extensions() override;
void
do_send_response(protocol::status_code_t,
common::io::const_buffers_t const&) override;
void
do_send_error(common_error_t error) override;
protected:
template<typename... Args>
friend
std::shared_ptr<transaction_t>
make_transaction(Args&&...);
protected:
/// fixme: replace request_timeout with a configuration_t object.
///
transaction_t(common::diagnostics_t&,
std::chrono::seconds request_timeout,
error_handler_t&,
protocol::connection_t&,
request_handler_t&,
completion_handler_t);
private:
common::diagnostics_t::proxy_t
trace();
bool
keep_alive();
void
init_read();
void
on_read_timeout(std::error_code const&);
void
on_read(std::error_code const&);
void
prepare_response();
void
init_dispatch();
void
invoke_finalizers();
void
finalize_response(protocol::status_code_t const&,
std::size_t);
void
init_write(common::io::const_buffers_t const&);
void
on_write(std::error_code const&);
std::recursive_mutex protector_;
common::diagnostics_t& diagnostics_;
std::chrono::seconds request_timeout_;
error_handler_t& error_handler_;
common::allocator_t allocator_;
common::extension_context_t request_extensions_;
common::extension_context_t response_extensions_;
protocol::connection_t& connection_;
request_handler_t& handler_;
completion_handler_t on_completion_;
asio::steady_timer request_timeout_timer_;
protocol::request_t request_;
asio::streambuf request_content_;
std::istream request_content_stream_;
protocol::response_t response_;
std::vector<finalizer_t*> finalizers_;
};
/// Holds transaction configuration parameters.
///
struct transaction_t::configuration_t
{
/// Holds the request timeout (in seconds).
///
/// Request timeout is completely disabled if this is 0.
///
std::chrono::seconds request_timeout;
};
template<typename... Args>
std::shared_ptr<transaction_t>
make_transaction(Args&&... args)
{
return std::shared_ptr<transaction_t>{
new transaction_t{
std::forward<Args>(args)...
}
};
}
} // namespace seafire::server
#endif