13#include <http_parser.h>
131 result = std::make_unique< chunked_input_info_t >(
150template<
typename Http_Methods >
151inline http_parser_settings
154 http_parser_settings parser_settings;
155 http_parser_settings_init( &parser_settings );
157 parser_settings.on_url =
158 []( http_parser * parser,
const char * at,
size_t length ) ->
int {
162 parser_settings.on_header_field =
163 []( http_parser * parser,
const char * at,
size_t length ) ->
int {
167 parser_settings.on_header_value =
168 []( http_parser * parser,
const char * at,
size_t length ) ->
int {
172 parser_settings.on_headers_complete =
173 []( http_parser * parser ) ->
int {
177 parser_settings.on_body =
178 []( http_parser * parser,
const char * at,
size_t length ) ->
int {
182 parser_settings.on_chunk_header =
183 []( http_parser * parser ) ->
int {
187 parser_settings.on_chunk_complete =
188 []( http_parser * parser ) ->
int {
192 parser_settings.on_message_complete =
193 []( http_parser * parser ) ->
int {
194 return restinio_message_complete_cb< Http_Methods >( parser );
197 return parser_settings;
228 std::size_t buffer_size,
231 ,
m_buf{ buffer_size }
255 http_parser_init( &
m_parser, HTTP_REQUEST);
263template <
typename Connection,
typename Start_Read_CB,
typename Failed_CB >
266 asio_ns::ip::tcp::socket & ,
268 Start_Read_CB start_read_cb,
278 asio_ns::ip::tcp::socket & )
noexcept
302template <
typename Traits >
349 "[connection:{}] start connection with {}",
366 "[connection:{}] destructor called",
379 m_settings->call_state_listener( [
this]()
noexcept {
397 [ & ](
const asio_ns::error_code & ec ){
400 "[connection:{}] prepare connection error: {}",
413 "[connection:{}] start waiting for request",
480 "[connection:{}] continue reading request",
488 asio_ns::bind_executor(
490 [
this, ctx = shared_from_this()]
492 (
const asio_ns::error_code & ec,
493 std::size_t length )
noexcept {
502 "[connection:{}] skip read operation: already running",
510 after_read(
const asio_ns::error_code & ec, std::size_t length )
noexcept
521 "[connection:{}] received {} bytes",
530 catch(
const std::exception & x )
534 "[connection:{}] unexpected exception during the "
535 "handling of incoming data: {}",
550 "[connection:{}] read socket error: {}; "
565 "[connection:{}] EOF and no request, "
597 if( HPE_OK != parser.http_errno &&
598 HPE_PAUSED != parser.http_errno )
601 auto err = HTTP_PARSER_ERRNO( &parser );
606 "[connection:{}] parser error {}: {}",
608 http_errno_name( err ),
609 http_errno_description( err ) );
652 "[connection:{}] request received (#{}): {} {}",
656 static_cast<http_method
>( parser.method ) ),
657 parser_ctx.m_header.request_target() );
666 const auto handling_result =
668 std::make_shared< generic_request_t >(
672 parser_ctx.make_chunked_input_info_if_necessary(),
673 shared_from_concrete< connection_base_t >(),
677 switch( handling_result )
705 const std::string default_value{};
708 "[connection:{}] upgrade request received: {} {}; "
712 static_cast<http_method
>( parser.method ) ),
713 parser_ctx.m_header.request_target(),
714 parser_ctx.m_header.get_field_or(
731 "[connection:{}] upgrade request happened to be a pipelined one, "
732 "and will be handled after previous requests are handled",
741 catch(
const std::exception & ex )
745 "[connection:{}] error while handling request: {}",
770 "[connection:{}] handle upgrade request (#{}): {} {}",
774 static_cast<http_method
>( parser.method ) ),
775 parser_ctx.m_header.request_target() );
787 std::make_shared< generic_request_t >(
791 parser_ctx.make_chunked_input_info_if_necessary(),
792 shared_from_concrete< connection_base_t >(),
795 switch( handling_result )
819 "[connection:{}] upgrade request handler rejects "
820 "request, but socket was moved out from connection",
859 response_output_flags,
861 ctx = shared_from_this() ]
869 response_output_flags,
872 catch(
const std::exception & ex )
876 "[connection:{}] unable to handle response: {}",
894 auto invoke_after_write_cb_with_error = [&]{
901 catch(
const std::exception & ex )
905 "[connection:{}] notificator error: {}",
935 "[connection:{}] append response (#{}), "
936 "flags: {}, write group size: {}",
939 response_output_flags,
945 response_output_flags,
954 "[connection:{}] receive response parts for "
955 "request (#{}), but response with connection-close "
956 "attribute happened before",
960 invoke_after_write_cb_with_error();
967 "[connection:{}] try to write response, "
968 "while socket is closed",
971 invoke_after_write_cb_with_error();
996 const bool response_coordinator_full_before =
1001 if( next_write_group )
1005 "[connection:{}] start next write group for response (#{}), "
1008 next_write_group->second,
1009 next_write_group->first.items_count() );
1013 const bool response_coordinator_full_after =
1018 response_coordinator_full_before &&
1019 !response_coordinator_full_after;
1021 if( 0 < next_write_group->first.status_line_size() )
1026 next_write_group->first.items().front().write_type() );
1032 asio_ns::buffer_cast< const char * >(
1033 next_write_group->first.items().front().buf() ),
1034 next_write_group->first.status_line_size() };
1038 "[connection:{}] start response (#{}): {}",
1040 next_write_group->second,
1082 if( holds_alternative< trivial_write_operation_t >( wo ) )
1086 else if( holds_alternative< file_write_operation_t >( wo ) )
1092 assert( holds_alternative< none_write_operation_t >( wo ) );
1096 catch(
const std::exception & ex )
1100 "[connection:{}] handle_current_write_ctx failed: {}",
1118 "[connection:{}] sending resp data with "
1119 "connection-close attribute "
1128 asio_ns::error_code ignored_ec;
1135 "[connection:{}] sending resp data, "
1144 asio_ns::async_write(
1147 asio_ns::bind_executor(
1149 [
this, ctx = shared_from_this()]
1151 (
const asio_ns::error_code & ec, std::size_t written )
noexcept
1158 "[connection:{}] outgoing data was sent: {} bytes",
1178 "[connection:{}] sending resp file data with "
1179 "connection-close attribute, "
1186 asio_ns::error_code ignored_ec;
1193 "[connection:{}] sending resp file data, total size: {}",
1206 asio_ns::bind_executor(
1208 [
this, ctx = shared_from_this(),
1212 (
const asio_ns::error_code & ec,
file_size_t written )
mutable noexcept
1229 "[connection:{}] file data was sent: {} bytes",
1239 "[connection:{}] send file data error: {} ({}) bytes",
1257 "[connection:{}] finishing current write group",
1268 "[connection:{}] should keep alive",
1328 "[connection:{}] last sent response was marked "
1369 "[connection:{}] unable to write: {}",
1380 catch(
const std::exception & ex )
1385 "[connection:{}] notificator error: {}",
1403 "[connection:{}] close",
1411 "connection.socket.shutdown",
1413 asio_ns::error_code ignored_ec;
1415 asio_ns::ip::tcp::socket::shutdown_both,
1420 "connection.socket.close",
1428 "[connection:{}] close: close socket",
1438 "[connection:{}] close: timer canceled",
1447 "[connection:{}] close: reset responses data",
1452 m_settings->call_state_listener_suppressing_exceptions(
1467 template<
typename Message_Builder >
1526 conn_object.check_timeout_impl();
1528 catch(
const std::exception & x )
1530 conn_object.trigger_error_and_close( [&] {
1531 return fmt::format(
"[connection: {}] unexpected "
1532 "error during timeout handling: {}",
1533 conn_object.connection_id(),
1586 std::chrono::steady_clock::time_point timeout_after,
1595 std::chrono::steady_clock::duration timeout,
1599 std::chrono::steady_clock::now() + timeout,
1608 "[connection:{}] {} timed out",
1629 m_settings->m_read_next_http_message_timelimit,
1677 timelimit =
m_settings->m_write_http_response_timelimit;
1707template <
typename Traits >
1718 std::unique_ptr< socket_options_setter_t > socket_options_setter )
1738 (*m_socket_options_setter)( options );
1741 return std::make_shared< connection_type_t >(
A simple implementation of at_scope_exit concept.
Helper type for controlling the lifetime of the connection.
Type of object that tells that new connection has been accepted.
Type of object that tells that the connection has been closed.
An object with info about connection to be passed to state listener.
std::unique_ptr< socket_options_setter_t > m_socket_options_setter
connection_factory_t(connection_settings_handle_t< Traits > connection_settings, std::unique_ptr< socket_options_setter_t > socket_options_setter)
typename Traits::logger_t logger_t
connection_settings_handle_t< Traits > m_connection_settings
auto create_new_connection(stream_socket_t socket, endpoint_t remote_endpoint, lifetime_monitor_t lifetime_monitor)
typename Traits::stream_socket_t stream_socket_t
connection_id_t m_connection_id_counter
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
Context for handling http connections.
virtual void check_timeout(tcp_connection_ctx_handle_t &self) override
Schedules real timedout operations check on the executer of a connection.
connection_t & operator=(const connection_t &)=delete
typename Traits::strand_t strand_t
void handle_upgrade_request()
Calls handler for upgrade request.
void init_write_if_necessary()
tcp_connection_ctx_weak_handle_t m_prepared_weak_ctx
A prepared weak handle for passing it to timer guard.
void on_request_message_complete()
Handle a given request message.
void handle_request_handling_timeout()
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
virtual void write_response_parts(request_id_t request_id, response_output_flags_t response_output_flags, write_group_t wg) override
Write parts for specified request.
void handle_xxx_timeout(const char *operation_name)
void guard_write_operation()
Start guard write operation if necessary.
void finish_handling_current_write_ctx()
Do post write actions for current write group.
const endpoint_t m_remote_endpoint
Remote endpoint for this connection.
lifetime_monitor_t m_lifetime_monitor
Monitor of the connection lifetime.
stream_socket_t m_socket
Connection.
connection_input_t m_input
Input routine.
void schedule_operation_timeout_callback(std::chrono::steady_clock::time_point timeout_after, timout_cb_t timout_cb)
Helper function to work with timer guard.
void guard_sendfile_operation(std::chrono::steady_clock::duration timelimit)
request_handler_t & m_request_handler
Request handler.
void handle_trivial_write_operation(const trivial_write_operation_t &op)
Run trivial buffers write operation.
void handle_nothing_to_write()
void handle_file_write_operation(file_write_operation_t &op)
Run sendfile write operation.
timout_cb_t m_current_timeout_cb
Callback to all if timeout happened.
void wait_for_http_message()
Start reading next htttp-message.
void after_read(const asio_ns::error_code &ec, std::size_t length) noexcept
Handle read operation result.
logger_t & m_logger
Logger for operation.
std::chrono::steady_clock::time_point m_current_timeout_after
Timeout point of a current guarded operation.
void init_write()
Initiate write operation.
typename Traits::timer_manager_t timer_manager_t
upgrade_internals_t move_upgrade_internals()
Move socket out of connection.
void cancel_timeout_checking() noexcept
Stop timout guarding.
static connection_t & cast_to_self(tcp_connection_ctx_base_t &base)
Timer to controll operations.
connection_t(const connection_t &)=delete
void handle_current_write_ctx() noexcept
Start/continue/continue handling output data of current write group.
void(connection_t::*)(void) timout_cb_t
Callback type for timedout operations.
connection_t(connection_id_t conn_id, stream_socket_t &&socket, connection_settings_handle_t< Traits > settings, endpoint_t remote_endpoint, lifetime_monitor_t lifetime_monitor)
void close() noexcept
Close connection functions.
void handle_write_response_timeout()
typename Traits::logger_t logger_t
void after_write(const asio_ns::error_code &ec) noexcept
Handle write response finished.
void trigger_error_and_close(Message_Builder msg_builder) noexcept
Trigger an error.
response_coordinator_t m_response_coordinator
Response coordinator.
void guard_request_handling_operation()
Start guard request handling operation if necessary.
typename timer_manager_t::timer_guard_t timer_guard_t
request_handler_type_from_traits_t< Traits > request_handler_t
void init_next_timeout_checking()
Schedule next timeout checking.
void consume_data(const char *data, std::size_t length)
Parse some data.
void consume_message()
Start (continue) a chain of read-parse-read-... operations.
timer_guard_t m_timer_guard
Timer guard.
typename Traits::stream_socket_t stream_socket_t
void check_timeout_impl()
Check timed out operation.
connection_settings_handle_t< Traits > m_settings
Common paramaters of a connection.
void handle_sendfile_timeout()
void guard_read_operation()
Statr guard read operation if necessary.
void write_response_parts_impl(request_id_t request_id, response_output_flags_t response_output_flags, write_group_t wg)
Write parts for specified request.
connection_t(connection_t &&)=delete
void schedule_operation_timeout_callback(std::chrono::steady_clock::duration timeout, timout_cb_t timout_cb)
bool m_init_read_after_this_write
void handle_read_timeout()
write_group_output_ctx_t m_write_output_ctx
Write to socket operation context.
Wrapper for an executor (strand) used by connections.
Traits::strand_t & get_executor() noexcept
An executor for callbacks on async operations.
Helper class for reading bytes and feeding them to parser.
std::size_t length() const noexcept
How many unconsumed bytes are there in buffer.
void consumed_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
void obtained_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
auto make_asio_buffer() noexcept
Make asio buffer for reading bytes from socket.
const char * bytes() const noexcept
Get pointer to unconsumed bytes.
Coordinator for process of sending responses with respect to http pipeline technique and chunk transf...
void reset() noexcept
Remove all contexts.
request_id_t register_new_request()
Create a new request and reserve context for its response.
bool is_able_to_get_more_messages() const noexcept
Check if it is possible to accept more requests.
bool is_full() const noexcept
bool empty() const noexcept
optional_t< std::pair< write_group_t, request_id_t > > pop_ready_buffers()
Extract a portion of data available for write.
bool closed() const noexcept
void append_response(request_id_t req_id, response_output_flags_t response_output_flags, write_group_t wg)
Add outgoing data for specified request.
Socket adapter for asio::ssl::stream< asio::ip::tcp::socket >.
Write operaton using sendfile.
auto timelimit() const noexcept
Get the timelimit on this sendfile operation.
void start_sendfile_operation(default_asio_executor executor, Socket &socket, After_Write_CB after_sendfile_cb)
Start a sendfile operation.
auto size() const noexcept
Get the size of sendfile operation.
auto size() const noexcept
The size of data within this operation.
const std::vector< asio_ns::const_buffer > & get_trivial_bufs() const noexcept
Get buffer "iovec" for performing gather write.
Helper class for writting response data.
void fail_write_group(const asio_ns::error_code &ec)
Handle current group write process failed.
solid_write_operation_variant_t extract_next_write_operation()
et an object with next write operation to perform.
void finish_write_group()
Finish writing group normally.
void start_next_write_group(optional_t< write_group_t > next_wg) noexcept
Start handlong next write group.
bool transmitting() const noexcept
Check if data is trunsmitting now.
A type of holder of limits related to an incoming HTTP message.
An adapter for setting acceptor options before running server.
connection_id_t connection_id() const noexcept
Get connection id.
Group of writable items transported to the context of underlying connection as one solid piece.
void invoke_after_write_notificator_if_exists(const asio_ns::error_code &ec)
Get after write notificator.
auto items_count() const noexcept
Get the count of stored items.
#define RESTINIO_ENSURE_NOEXCEPT_CALL(expr)
A wrapper around static_assert for checking that an expression is noexcept and execution of that expr...
#define RESTINIO_NODISCARD
Stuff related to limits of active parallel connections.
A special wrapper around fmtlib include files.
constexpr underlying_uint_t zero
The minimal allowed value for a qvalue.
tls_socket_t * make_tls_socket_pointer_for_state_listener(asio_ns::ip::tcp::socket &) noexcept
std::shared_ptr< connection_settings_t< Traits > > connection_settings_handle_t
http_parser_settings create_parser_settings() noexcept
Include parser callbacks.
auto create_not_implemented_resp()
void prepare_connection_and_start_read(asio_ns::ip::tcp::socket &, Connection &, Start_Read_CB start_read_cb, Failed_CB)
connection_upgrade_stage_t
Enum for a flag specifying that connection is going to upgrade or not.
@ wait_for_upgrade_handling_result_or_nothing
Handler for request with connection-upgrade header was called so any response data comming is for tha...
@ none
No connection request in progress.
@ pending_upgrade_handling
Request with connection-upgrade header came and waits for request handler to be called in non pipelin...
void suppress_exceptions(Logger &&logger, const char *block_description, Lambda &&lambda) noexcept
Helper function for execution a block of code with suppression of any exceptions raised inside that b...
scope_exit_details::at_exit_t< L > at_scope_exit(L &&l)
Helper function for creation action to be performed at scope exit.
void log_error_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
void log_trace_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
ws_handle_t upgrade(generic_request_type_from_traits_t< Traits > &req, activation_t activation_flag, http_header_fields_t upgrade_response_header_fields, WS_Message_Handler ws_message_handler)
Upgrade http-connection of a current request to a websocket connection.
std::shared_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_handle_t
Alias for http connection handle.
std::uint64_t file_size_t
std::unique_ptr< chunked_input_info_t > chunked_input_info_unique_ptr_t
Alias of unique_ptr for chunked_input_info.
std::weak_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_weak_handle_t
Alias for http connection weak handle.
nonstd::string_view string_view_t
unsigned int request_id_t
Request id in scope of single connection.
@ trivial_write_operation
Item is a buffer and must be written trivially.
bool error_is_operation_aborted(const asio_ns::error_code &ec) noexcept
@ accepted
Request accepted for handling.
@ not_handled
The request wasn't handled. If there is another handler to be tried it should be tried....
@ rejected
Request wasn't accepted for handling.
typename details::actual_request_handler_type_detector< typename Traits::request_handler_t, typename Traits::extra_data_factory_t >::request_handler_t request_handler_type_from_traits_t
A metafunction for extraction a request-handler type from server's traits.
@ write_was_not_executed
After write notificator error: data was not sent, connection closed (or aborted) before a given piece...
bool error_is_eof(const asio_ns::error_code &ec) noexcept
asio_ns::ip::tcp::endpoint endpoint_t
An alias for endpoint type from Asio.
@ connection_close
This response says to close connection.
asio_ns::error_code make_asio_compaible_error(asio_convertible_error_t err) noexcept
Make restinio error_code compatible with asio_ns::error_code.
@ final_parts
Final parts (response ands with these parts).
std::uint64_t connection_id_t
Type for ID of connection.
int restinio_url_cb(http_parser *parser, const char *at, size_t length)
int restinio_header_value_cb(http_parser *parser, const char *at, size_t length)
int restinio_body_cb(http_parser *parser, const char *at, size_t length)
int restinio_chunk_complete_cb(http_parser *)
int restinio_headers_complete_cb(http_parser *parser)
int restinio_header_field_cb(http_parser *parser, const char *at, size_t length)
int restinio_chunk_header_cb(http_parser *parser)
Helpers for safe truncation of unsigned integers.
Internals that are necessary for upgrade.
lifetime_monitor_t m_lifetime_monitor
connection_settings_handle_t< Traits > m_settings
upgrade_internals_t(connection_settings_handle_t< Traits > settings, stream_socket_t socket, lifetime_monitor_t lifetime_monitor)
upgrade_internals_t(upgrade_internals_t &&)=default
Parsing result context for using in parser callbacks.
void reset()
Prepare context to handle new request.
RESTINIO_NODISCARD chunked_input_info_unique_ptr_t make_chunked_input_info_if_necessary()
Creates an instance of chunked_input_info if there is an info about chunks in the body.
bool m_leading_headers_completed
http_request_header_t m_header
Request data.
std::size_t m_total_field_count
Total number of parsed HTTP-fields.
bool m_message_complete
Flag: is http message parsed completely.
const incoming_http_msg_limits_t m_limits
Limits for the incoming message.
chunked_input_info_block_t m_chunked_info_block
std::string m_current_field_name
Parser context temp values and flags.
http_parser_ctx_t(incoming_http_msg_limits_t limits)
The main constructor.
std::size_t m_last_value_total_size
Response output flags for buffers commited to response-coordinator.