145 result = std::make_unique< chunked_input_info_t >(
164template<
typename Http_Methods >
165inline llhttp_settings_t
168 llhttp_settings_t parser_settings;
169 llhttp_settings_init( &parser_settings );
171 parser_settings.on_url =
172 []( llhttp_t * parser,
const char * at,
size_t length ) ->
int {
176 parser_settings.on_header_field =
177 []( llhttp_t * parser,
const char * at,
size_t length ) ->
int {
181 parser_settings.on_header_field_complete =
182 []( llhttp_t * parser ) ->
int {
186 parser_settings.on_header_value =
187 []( llhttp_t * parser,
const char * at,
size_t length ) ->
int {
191 parser_settings.on_header_value_complete =
192 []( llhttp_t * parser ) ->
int {
196 parser_settings.on_headers_complete =
197 []( llhttp_t * parser ) ->
int {
201 parser_settings.on_body =
202 []( llhttp_t * parser,
const char * at,
size_t length ) ->
int {
206 parser_settings.on_chunk_header =
207 []( llhttp_t * parser ) ->
int {
211 parser_settings.on_chunk_complete =
212 []( llhttp_t * parser ) ->
int {
216 parser_settings.on_message_complete =
217 []( llhttp_t * parser ) ->
int {
221 parser_settings.on_chunk_extension_name =
222 []( llhttp_t * parser,
const char * at,
size_t length ) ->
int {
226 parser_settings.on_chunk_extension_value =
227 []( llhttp_t * parser,
const char * at,
size_t length ) ->
int {
231 parser_settings.on_chunk_extension_name_complete =
232 []( llhttp_t * parser ) ->
int {
236 parser_settings.on_chunk_extension_value_complete =
237 []( llhttp_t * parser ) ->
int {
241 return parser_settings;
272 std::size_t buffer_size,
274 const llhttp_settings_t* settings )
276 ,
m_buf{ buffer_size }
278 llhttp_init( &
m_parser, llhttp_type_t::HTTP_REQUEST, settings );
310template <
typename Connection,
typename Start_Read_CB,
typename Failed_CB >
313 asio_ns::ip::tcp::socket & ,
315 Start_Read_CB start_read_cb,
325 asio_ns::ip::tcp::socket & )
noexcept
349template <
typename Traits >
398 "[connection:{}] start connection with {}" ),
416 "[connection:{}] destructor called" ),
429 m_settings->call_state_listener( [
this]()
noexcept {
447 [ & ](
const asio_ns::error_code & ec ){
451 "[connection:{}] prepare connection error: {}" ),
465 "[connection:{}] start waiting for request" ),
477 if( 0 !=
m_input.m_buf.length() )
528 if( !
m_input.m_read_operation_is_running )
533 "[connection:{}] continue reading request" ),
538 m_input.m_read_operation_is_running =
true;
540 m_input.m_buf.make_asio_buffer(),
541 asio_ns::bind_executor(
542 this->get_executor(),
543 [
this, ctx = shared_from_this()]
545 (
const asio_ns::error_code & ec,
546 std::size_t length )
noexcept {
547 m_input.m_read_operation_is_running =
false;
556 "[connection:{}] skip read operation: already running" ),
564 after_read(
const asio_ns::error_code & ec, std::size_t length )
noexcept
576 "[connection:{}] received {} bytes" ),
581 m_input.m_buf.obtained_bytes( length );
585 catch(
const std::exception & x )
590 "[connection:{}] unexpected exception during the "
591 "handling of incoming data: {}" ),
607 "[connection:{}] read socket error: {}; "
608 "parsed bytes: {}" ),
611 m_input.m_parser_ctx.m_bytes_parsed );
623 "[connection:{}] EOF and no request, "
624 "close connection" ),
639 auto * parser = &
m_input.m_parser;
641 const auto parse_err =
642 llhttp_execute( parser, data, length );
644 const auto nparsed = [&]{
645 if( !parser->error_pos )
647 return static_cast< std::size_t
>( parser->error_pos - data );
650 if( nparsed > length )
657 "[connection:{}] unexpected parser behavior: "
658 "llhttp_execute() reports parsed bytes number ({}) "
659 "is greater than the size of a buffer ({})"
660 "that was fed to the parser" ),
668 m_input.m_parser_ctx.m_bytes_parsed += nparsed;
675 m_input.m_buf.consumed_bytes( nparsed );
677 if( HPE_OK != parse_err &&
678 HPE_PAUSED != parse_err &&
679 HPE_PAUSED_UPGRADE != parse_err )
688 assert( llhttp_errno::HPE_OK <= parse_err &&
689 llhttp_errno::HPE_CB_RESET >= parse_err );
695 "[connection:{}] parser error {}: {}" ),
697 llhttp_errno_name( parse_err ),
698 llhttp_get_error_reason( parser ) );
705 if(
m_input.m_parser_ctx.m_message_complete )
719 auto & parser =
m_input.m_parser;
720 auto & parser_ctx =
m_input.m_parser_ctx;
729 m_input.m_connection_upgrade_stage =
734 m_input.m_connection_upgrade_stage )
742 "[connection:{}] request received (#{}): {} {}" ),
746 static_cast<llhttp_method
>( parser.method ) ),
747 parser_ctx.m_header.request_target() );
756 const auto handling_result =
758 std::make_shared< generic_request_t >(
760 std::move( parser_ctx.m_header ),
761 std::move( parser_ctx.m_body ),
762 parser_ctx.make_chunked_input_info_if_necessary(),
767 switch( handling_result )
795 const std::string default_value{};
799 "[connection:{}] upgrade request received: {} {}; "
803 static_cast<llhttp_method
>( parser.method ) ),
804 parser_ctx.m_header.request_target(),
805 parser_ctx.m_header.get_field_or(
806 http_field::upgrade, default_value ) );
823 "[connection:{}] upgrade request happened to "
824 "be a pipelined one, "
825 "and will be handled after previous requests "
835 catch(
const std::exception & ex )
840 "[connection:{}] error while handling request: {}" ),
854 auto & parser =
m_input.m_parser;
855 auto & parser_ctx =
m_input.m_parser_ctx;
866 "[connection:{}] handle upgrade request (#{}): {} {}" ),
870 static_cast<llhttp_method
>( parser.method ) ),
871 parser_ctx.m_header.request_target() );
879 m_input.m_connection_upgrade_stage =
883 std::make_shared< generic_request_t >(
885 std::move( parser_ctx.m_header ),
886 std::move( parser_ctx.m_body ),
887 parser_ctx.make_chunked_input_info_if_necessary(),
891 switch( handling_result )
916 "[connection:{}] upgrade request handler rejects "
917 "request, but socket was moved out from connection" ),
956 response_output_flags,
957 actual_wg = std::move( wg ),
958 ctx = shared_from_this() ]
966 response_output_flags,
967 std::move( actual_wg ) );
969 catch(
const std::exception & ex )
974 "[connection:{}] unable to handle response: {}" ),
992 auto invoke_after_write_cb_with_error = [&]{
999 catch(
const std::exception & ex )
1004 "[connection:{}] notificator error: {}" ),
1015 m_input.m_connection_upgrade_stage )
1035 "[connection:{}] append response (#{}), "
1036 "flags: {}, write group size: {}" ),
1045 response_output_flags,
1055 "[connection:{}] receive response parts for "
1056 "request (#{}), but response with connection-close "
1057 "attribute happened before" ),
1061 invoke_after_write_cb_with_error();
1069 "[connection:{}] try to write response, "
1070 "while socket is closed" ),
1073 invoke_after_write_cb_with_error();
1098 const bool response_coordinator_full_before =
1103 if( next_write_group )
1108 "[connection:{}] start next write group for response (#{}), "
1111 next_write_group->second,
1112 next_write_group->first.items_count() );
1116 const bool response_coordinator_full_after =
1121 response_coordinator_full_before &&
1122 !response_coordinator_full_after;
1124 if( 0 < next_write_group->first.status_line_size() )
1129 next_write_group->first.items().front().write_type() );
1134 asio_ns::buffer_cast< const char * >(
1135 next_write_group->first.items().front().buf() ),
1136 next_write_group->first.status_line_size() };
1140 "[connection:{}] start response (#{}): {}" ),
1142 next_write_group->second,
1149 std::move( next_write_group->first ) );
1184 if( std::holds_alternative< trivial_write_operation_t >( wo ) )
1188 else if( std::holds_alternative< file_write_operation_t >( wo ) )
1194 assert( std::holds_alternative< none_write_operation_t >( wo ) );
1198 catch(
const std::exception & ex )
1203 "[connection:{}] handle_current_write_ctx failed: {}" ),
1222 "[connection:{}] sending resp data with "
1223 "connection-close attribute "
1232 asio_ns::error_code ignored_ec;
1240 "[connection:{}] sending resp data, "
1249 asio_ns::async_write(
1252 asio_ns::bind_executor(
1254 [
this, ctx = shared_from_this()]
1256 (
const asio_ns::error_code & ec, std::size_t written )
noexcept
1264 "[connection:{}] outgoing data was "
1286 "[connection:{}] sending resp file data with "
1287 "connection-close attribute, "
1294 asio_ns::error_code ignored_ec;
1302 "[connection:{}] sending resp file data, total size: {}" ),
1315 asio_ns::bind_executor(
1317 [
this, ctx = shared_from_this(),
1321 (
const asio_ns::error_code & ec,
file_size_t written )
mutable noexcept
1339 "[connection:{}] file data was sent: "
1351 "[connection:{}] send file data error: "
1371 "[connection:{}] finishing current write group" ),
1383 "[connection:{}] should keep alive" ),
1388 m_input.m_connection_upgrade_stage )
1444 "[connection:{}] last sent response was marked "
1486 "[connection:{}] unable to write: {}" ),
1497 catch(
const std::exception & ex )
1503 "[connection:{}] notificator error: {}" ),
1529 "connection.socket.shutdown",
1531 asio_ns::error_code ignored_ec;
1533 asio_ns::ip::tcp::socket::shutdown_both,
1538 "connection.socket.close",
1547 "[connection:{}] close: close socket" ),
1558 "[connection:{}] close: timer canceled" ),
1568 "[connection:{}] close: reset responses data" ),
1573 m_settings->call_state_listener_suppressing_exceptions(
1588 template<
typename Message_Builder >
1595 m_logger, std::move(msg_builder) );
1639 [ ctx = std::move( self ) ]
1647 conn_object.check_timeout_impl();
1649 catch(
const std::exception & x )
1651 conn_object.trigger_error_and_close( [&] {
1654 "[connection: {}] unexpected "
1655 "error during timeout handling: {}" ),
1656 conn_object.connection_id(),
1709 std::chrono::steady_clock::time_point timeout_after,
1718 std::chrono::steady_clock::duration timeout,
1722 std::chrono::steady_clock::now() + timeout,
1752 m_settings->m_read_next_http_message_timelimit,
1799 if( std::chrono::steady_clock::duration::zero() == timelimit )
1800 timelimit =
m_settings->m_write_http_response_timelimit;
1830template <
typename Traits >
1841 std::unique_ptr< socket_options_setter_t > socket_options_setter )
1861 (*m_socket_options_setter)( options );
1864 return std::make_shared< connection_type_t >(
1866 std::move( socket ),
1868 std::move( remote_endpoint ),
1869 std::move( lifetime_monitor ) );
A simple implementation of at_scope_exit concept.
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.
connection_base_t(connection_id_t id)
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()
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
write_group_output_ctx_t::file_write_operation_t file_write_operation_t
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()
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.
write_group_output_ctx_t::none_write_operation_t none_write_operation_t
executor_wrapper_t< typename Traits::strand_t > executor_wrapper_base_t
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.
write_group_output_ctx_t::trivial_write_operation_t trivial_write_operation_t
generic_request_type_from_traits_t< Traits > generic_request_t
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.
Traits::strand_t & get_executor() noexcept
executor_wrapper_t(Init_Executor &&init_executor)
Helper class for reading bytes and feeding them to parser.
Coordinator for process of sending responses with respect to http pipeline technique and chunk transf...
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.
A type of holder of limits related to an incoming HTTP message.
An adapter for setting acceptor options before running server.
tcp_connection_ctx_base_t(connection_id_t id)
connection_id_t connection_id() const noexcept
Get connection id.
std::shared_ptr< Derived > shared_from_concrete()
Cast self to derived class.
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...
Stuff related to limits of active parallel connections.
A special wrapper around fmtlib include files.
#define RESTINIO_FMT_FORMAT_STRING(s)
int restinio_chunk_header_cb(llhttp_t *parser)
llhttp_settings_t create_parser_settings() noexcept
Helper for setting parser settings.
tls_socket_t * make_tls_socket_pointer_for_state_listener(asio_ns::ip::tcp::socket &) noexcept
int restinio_header_value_cb(llhttp_t *parser, const char *at, size_t length)
int restinio_chunk_extension_value_cb(llhttp_t *parser, const char *at, size_t length)
int restinio_chunk_extension_name_cb(llhttp_t *parser, const char *at, size_t length)
int restinio_header_value_complete_cb(llhttp_t *parser)
int restinio_chunk_complete_cb(llhttp_t *)
int restinio_body_cb(llhttp_t *parser, const char *at, size_t length)
int restinio_url_cb(llhttp_t *parser, const char *at, size_t length)
int restinio_headers_complete_cb(llhttp_t *parser)
auto create_not_implemented_resp()
int restinio_header_field_complete_cb(llhttp_t *parser)
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...
std::shared_ptr< connection_settings_t< Traits > > connection_settings_handle_t
int restinio_header_field_cb(llhttp_t *parser, const char *at, size_t length)
int restinio_chunk_extension_value_complete_cb(llhttp_t *)
int restinio_message_complete_cb(llhttp_t *parser)
int restinio_chunk_extension_name_complete_cb(llhttp_t *parser)
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
asio_ns::ip::tcp::endpoint endpoint_t
An alias for endpoint type from Asio.
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.
unsigned int request_id_t
Request id in scope of single connection.
std::string_view string_view_t
@ trivial_write_operation
Item is a buffer and must be written trivially.
generic_request_t< typename Traits::extra_data_factory_t::data_t > generic_request_type_from_traits_t
A metafunction for the detection of actual type of request-object from server's traits.
bool error_is_operation_aborted(const asio_ns::error_code &ec) noexcept
std::weak_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_weak_handle_t
Alias for http connection weak handle.
std::unique_ptr< chunk_ext_params_t > chunk_ext_params_unique_ptr_t
@ 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.
@ write_was_not_executed
After write notificator error: data was not sent, connection closed (or aborted) before a given piece...
impl::tls_socket_t tls_socket_t
A public alias for the actual implementation of TLS-socket.
std::unique_ptr< chunked_input_info_t > chunked_input_info_unique_ptr_t
Alias of unique_ptr for chunked_input_info.
bool error_is_eof(const asio_ns::error_code &ec) noexcept
std::uint64_t connection_id_t
Type for ID of connection.
@ 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.
std::uint64_t file_size_t
std::shared_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_handle_t
Alias for http connection handle.
@ final_parts
Final parts (response ands with these parts).
Helpers for safe truncation of unsigned integers.
connection_count_limits::connection_lifetime_monitor_t< limiter_t > lifetime_monitor_t
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.
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
chunk_ext_params_unique_ptr_t m_chunk_ext_params
Chunk extnsion's params if any.
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
std::size_t m_bytes_parsed
How many bytes were parsed for current request.
Response output flags for buffers commited to response-coordinator.