Loading...
Searching...
No Matches
ws_connection.hpp
Go to the documentation of this file.
/*
restinio
*/
#pragma once
#include <queue>
#include <restinio/asio_include.hpp>
#include <http_parser.h>
#include <restinio/impl/include_fmtlib.hpp>
#include <restinio/all.hpp>
#include <restinio/impl/executor_wrapper.hpp>
#include <restinio/impl/write_group_output_ctx.hpp>
#include <restinio/websocket/message.hpp>
#include <restinio/websocket/impl/ws_parser.hpp>
#include <restinio/websocket/impl/ws_protocol_validator.hpp>
#include <restinio/utils/impl/safe_uint_truncate.hpp>
#include <restinio/compiler_features.hpp>
namespace restinio
{
namespace websocket
{
namespace basic
{
namespace impl
{
using write_groups_queue_t = std::queue< write_group_t >;
constexpr size_t
websocket_header_max_size()
{
return 14;
}
//
// ws_outgoing_data_t
//
class ws_outgoing_data_t
{
public:
void
append( write_group_t wg )
{
m_awaiting_write_groups.emplace( std::move( wg ) );
}
optional_t< write_group_t >
pop_ready_buffers()
{
optional_t< write_group_t > result;
if( !m_awaiting_write_groups.empty() )
{
result = std::move( m_awaiting_write_groups.front() );
m_awaiting_write_groups.pop();
}
return result;
}
private:
write_groups_queue_t m_awaiting_write_groups;
};
//
// connection_input_t
//
struct connection_input_t
{
connection_input_t( std::size_t buffer_size )
: m_buf{ buffer_size }
{}
ws_parser_t m_parser;
restinio::impl::fixed_buffer_t m_buf;
std::string m_payload;
void
reset_parser_and_payload()
{
m_parser.reset();
m_payload.clear();
}
};
//
// ws_connection_t
//
template <
typename Traits,
typename WS_Message_Handler >
class ws_connection_t final
: public ws_connection_base_t
, public restinio::impl::executor_wrapper_t< typename Traits::strand_t >
{
using executor_wrapper_base_t = restinio::impl::executor_wrapper_t< typename Traits::strand_t >;
public:
using message_handler_t = WS_Message_Handler;
using timer_manager_t = typename Traits::timer_manager_t;
using timer_manager_handle_t = std::shared_ptr< timer_manager_t >;
using timer_guard_t = typename timer_manager_t::timer_guard_t;
using logger_t = typename Traits::logger_t;
using strand_t = typename Traits::strand_t;
using stream_socket_t = typename Traits::stream_socket_t;
using lifetime_monitor_t =
typename connection_count_limit_types<Traits>::lifetime_monitor_t;
using ws_weak_handle_t = std::weak_ptr< ws_t >;
ws_connection_t(
connection_id_t conn_id,
restinio::impl::connection_settings_handle_t< Traits > settings,
stream_socket_t socket,
lifetime_monitor_t lifetime_monitor,
message_handler_t msg_handler )
: ws_connection_base_t{ conn_id }
, executor_wrapper_base_t{ socket.get_executor() }
, m_settings{ std::move( settings ) }
, m_socket{ std::move( socket ) }
, m_lifetime_monitor{ std::move( lifetime_monitor ) }
, m_timer_guard{ m_settings->create_timer_guard() }
, m_input{ websocket_header_max_size() }
, m_msg_handler{ std::move( msg_handler ) }
, m_logger{ *( m_settings->m_logger ) }
{
// Notify of a new connection instance.
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[connection:{}] move socket to [ws_connection:{}]" ),
connection_id(),
connection_id() );
} );
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] start connection with {}" ),
connection_id(),
fmtlib_tools::streamed( m_socket.remote_endpoint() ) );
} );
// Inform state listener if it used.
m_settings->call_state_listener( [this]() noexcept {
return connection_state::notice_t {
connection_id(),
m_socket.remote_endpoint(),
connection_state::upgraded_to_websocket_t{}
};
} );
}
ws_connection_t( const ws_connection_t & ) = delete;
ws_connection_t( ws_connection_t && ) = delete;
ws_connection_t & operator = ( const ws_connection_t & ) = delete;
ws_connection_t & operator = ( ws_connection_t && ) = delete;
~ws_connection_t() override
{
try
{
// Notify of a new connection instance.
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] destructor called" ),
connection_id() );
} );
}
catch( ... )
{}
}
virtual void
shutdown() override
{
asio_ns::dispatch(
this->get_executor(),
[ this, ctx = shared_from_this() ]
// NOTE: this lambda is noexcept since v.0.6.0.
() noexcept {
try
{
// An exception from logger shouldn't prevent
// main shutdown actions.
restinio::utils::log_trace_noexcept( m_logger,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] shutdown" ),
connection_id() );
} );
m_close_frame_to_user.disable();
graceful_close();
}
catch( const std::exception & ex )
{
restinio::utils::log_error_noexcept( m_logger,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] shutdown operation error: {}" ),
connection_id(),
ex.what() );
} );
}
} );
}
virtual void
kill() override
{
asio_ns::dispatch(
this->get_executor(),
[ this, ctx = shared_from_this() ]
// NOTE: this lambda is noexcept since v.0.6.0.
() noexcept
{
try
{
// An exception from logger shouldn't prevent
// main kill actions.
restinio::utils::log_trace_noexcept( m_logger,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] kill" ),
connection_id() );
} );
m_close_frame_to_user.disable();
m_close_frame_to_peer.disable();
close_impl();
}
catch( const std::exception & ex )
{
restinio::utils::log_error_noexcept( m_logger,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] kill operation error: {}" ),
connection_id(),
ex.what() );
} );
}
} );
}
void
init_read( ws_handle_t wsh ) override
{
ws_weak_handle_t wswh{ wsh };
// Run write message on io_context loop (direct invocation if possible).
asio_ns::dispatch(
this->get_executor(),
[ this, ctx = shared_from_this(), wswh = std::move( wswh ) ]
// NOTE: this lambda is noexcept since v.0.6.0.
() noexcept
{
try
{
// Start timeout checking.
m_prepared_weak_ctx = shared_from_this();
init_next_timeout_checking();
m_websocket_weak_handle = std::move( wswh );
m_read_state = read_state_t::read_any_frame;
start_read_header();
}
catch( const std::exception & ex )
{
trigger_error_and_close(
status_code_t::unexpected_condition,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] unable to init read: {}" ),
connection_id(),
ex.what() );
} );
}
} );
}
virtual void
write_data(
write_group_t wg,
bool is_close_frame ) override
{
asio_ns::dispatch(
this->get_executor(),
[ this,
actual_wg = std::move( wg ),
ctx = shared_from_this(),
is_close_frame ]
// NOTE: this lambda is noexcept since v.0.6.0.
() mutable noexcept
{
try
{
if( write_state_t::write_enabled == m_write_state )
write_data_impl(
std::move( actual_wg ),
is_close_frame );
else
{
m_logger.warn( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] cannot write to websocket: "
"write operations disabled" ),
connection_id() );
} );
}
}
catch( const std::exception & ex )
{
trigger_error_and_close(
status_code_t::unexpected_condition,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] unable to write data: {}" ),
connection_id(),
ex.what() );
} );
}
} );
}
private:
void
close_impl() noexcept
{
m_close_impl.run_if_first(
[&]() noexcept {
restinio::utils::log_trace_noexcept( m_logger,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] close socket" ),
connection_id() );
} );
// This actions can throw and because of that we have
// to wrap them...
restinio::utils::suppress_exceptions(
m_logger,
"ws_connection.close_impl.socket.shutdown",
[&] {
asio_ns::error_code ignored_ec;
m_socket.shutdown(
asio_ns::ip::tcp::socket::shutdown_both,
ignored_ec );
} );
restinio::utils::suppress_exceptions(
m_logger,
"ws_connection.close_impl.socket.close",
[&] {
m_socket.close();
} );
} );
}
void
start_waiting_close_frame_only()
{
m_read_state = read_state_t::read_only_close_frame;
guard_close_frame_from_peer_operation();
}
void
graceful_close()
{
m_close_frame_to_peer.run_if_first(
[&]{
send_close_frame_to_peer( status_code_t::normal_closure );
start_waiting_close_frame_only();
} );
}
void
send_close_frame_to_peer( std::string payload )
{
writable_items_container_t bufs;
bufs.reserve( 2 );
bufs.emplace_back(
impl::write_message_details(
final_frame,
opcode_t::connection_close_frame,
payload.size() ) );
bufs.emplace_back( std::move( payload ) );
m_outgoing_data.append( write_group_t{ std::move( bufs ) } );
init_write_if_necessary();
// No more data must be written.
m_write_state = write_state_t::write_disabled;
}
void
send_close_frame_to_peer(
status_code_t code,
std::string desc = std::string{} )
{
send_close_frame_to_peer( std::string{ status_code_to_bin( code ) + desc } );
}
template< typename MSG_BUILDER >
void
trigger_error_and_close(
status_code_t status,
MSG_BUILDER msg_builder ) noexcept
{
// An exception in logger shouldn't prevent the main actions.
restinio::utils::log_error_noexcept(
m_logger, std::move( msg_builder ) );
// This can throw but we have to suppress any exceptions.
restinio::utils::suppress_exceptions(
m_logger, "ws_connection.call_close_handler_if_necessary",
[this, status] {
call_close_handler_if_necessary( status );
} );
RESTINIO_ENSURE_NOEXCEPT_CALL( close_impl() );
}
void
start_read_header()
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] start reading header" ),
connection_id() );
} );
// Prepare parser for consuming new message.
m_input.reset_parser_and_payload();
if( 0 == m_input.m_buf.length() )
{
consume_header_from_socket();
}
else
{
// Has something to read from m_input.m_buf.
consume_header_from_buffer(
m_input.m_buf.bytes(), m_input.m_buf.length() );
}
}
void
consume_header_from_socket()
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] continue reading message" ),
connection_id() );
} );
m_socket.async_read_some(
m_input.m_buf.make_asio_buffer(),
asio_ns::bind_executor(
this->get_executor(),
[ this, ctx = shared_from_this() ]
// NOTE: this lambda is noexcept since v.0.6.0.
( const asio_ns::error_code & ec, std::size_t length ) noexcept
{
try
{
after_read_header( ec, length );
}
catch( const std::exception & ex )
{
trigger_error_and_close(
status_code_t::unexpected_condition,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] after read header "
"callback error: {}" ),
connection_id(),
ex.what() );
} );
}
} ) );
}
void
handle_read_error( const char * desc, const asio_ns::error_code & ec )
{
// Assume that connection is lost.
trigger_error_and_close(
status_code_t::connection_lost,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING( "[ws_connection:{}] {}: {}" ),
connection_id(),
desc,
ec.message() );
} );
}
void
after_read_header(
const asio_ns::error_code & ec,
std::size_t length )
{
if( !ec )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] received {} bytes" ),
this->connection_id(),
length );
} );
m_input.m_buf.obtained_bytes( length );
consume_header_from_buffer( m_input.m_buf.bytes(), length );
}
else
{
handle_read_error( "reading message header error", ec );
}
}
void
consume_header_from_buffer( const char * data, std::size_t length )
{
const auto nparsed = m_input.m_parser.parser_execute( data, length );
m_input.m_buf.consumed_bytes( nparsed );
if( m_input.m_parser.header_parsed() )
{
handle_parsed_header( m_input.m_parser.current_message() );
}
else
{
assert( nparsed == length );
consume_header_from_socket();
}
}
void
handle_parsed_header( const message_details_t & md )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] start handling {} ({:#x})" ),
connection_id(),
opcode_to_string( md.m_opcode ),
static_cast<std::uint16_t>(md.m_opcode) );
} );
const auto validation_result =
m_protocol_validator.process_new_frame( md );
if( validation_state_t::frame_header_is_valid != validation_result )
{
m_logger.error( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] invalid header" ),
connection_id() );
} );
if( read_state_t::read_any_frame == m_read_state )
{
m_close_frame_to_peer.run_if_first(
[&]{
send_close_frame_to_peer( status_code_t::protocol_error );
// Do not wait anything in return, because
// protocol is violated.
} );
call_close_handler_if_necessary( status_code_t::protocol_error );
}
else if( read_state_t::read_only_close_frame == m_read_state )
{
// Wait for close frame cannot be done.
close_impl();
}
return;
}
handle_parsed_and_valid_header( md );
}
void
handle_parsed_and_valid_header( const message_details_t & md )
{
const auto payload_length =
restinio::utils::impl::uint64_to_size_t(md.payload_len());
m_input.m_payload.resize( payload_length );
if( payload_length == 0 )
{
// Callback for message with 0-size payload.
call_handler_on_current_message();
}
else
{
const auto payload_part_size =
std::min( m_input.m_buf.length(), payload_length );
std::memcpy(
&m_input.m_payload.front(),
m_input.m_buf.bytes(),
payload_part_size );
m_input.m_buf.consumed_bytes( payload_part_size );
const std::size_t length_remaining =
payload_length - payload_part_size;
if( validate_payload_part(
&m_input.m_payload.front(),
payload_part_size,
length_remaining ) )
{
if( 0 == length_remaining )
{
// All message is obtained.
call_handler_on_current_message();
}
else
{
// Read the rest of payload:
start_read_payload(
&m_input.m_payload.front() + payload_part_size,
length_remaining );
}
}
// Else payload is invalid and validate_payload_part()
// has handled the case so do nothing.
}
}
void
start_read_payload(
char * payload_data,
std::size_t length_remaining,
bool do_validate_payload_and_call_msg_handler = true )
{
m_socket.async_read_some(
asio_ns::buffer( payload_data, length_remaining ),
asio_ns::bind_executor(
this->get_executor(),
[ this,
ctx = shared_from_this(),
payload_data,
length_remaining,
do_validate_payload_and_call_msg_handler ]
// NOTE: this lambda is noexcept since v.0.6.0.
( const asio_ns::error_code & ec, std::size_t length ) noexcept
{
try
{
after_read_payload(
payload_data,
length_remaining,
ec,
length,
do_validate_payload_and_call_msg_handler );
}
catch( const std::exception & ex )
{
trigger_error_and_close(
status_code_t::unexpected_condition,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] after read payload "
"callback error: {}" ),
connection_id(),
ex.what() );
} );
}
} ) );
}
void
after_read_payload(
char * payload_data,
std::size_t length_remaining,
const asio_ns::error_code & ec,
std::size_t length,
bool do_validate_payload_and_call_msg_handler = true )
{
if( !ec )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] received {} bytes" ),
this->connection_id(),
length );
} );
assert( length <= length_remaining );
const std::size_t next_length_remaining =
length_remaining - length;
if( do_validate_payload_and_call_msg_handler )
{
if( validate_payload_part( payload_data, length, next_length_remaining ) )
{
if( 0 == next_length_remaining )
{
// Here: all the payload is ready.
// All message is obtained.
call_handler_on_current_message();
}
else
{
//Here: not all payload is obtained,
// so inintiate read once again:
start_read_payload(
payload_data + length,
next_length_remaining,
do_validate_payload_and_call_msg_handler );
}
}
// Else payload is invalid and validate_payload_part()
// has handled the case so do nothing.
}
else
{
if( 0 == next_length_remaining )
{
start_read_header();
}
else
{
start_read_payload(
payload_data + length,
length_remaining - length,
do_validate_payload_and_call_msg_handler );
}
}
}
else
{
handle_read_error( "reading message payload error", ec );
}
}
void
call_message_handler( message_handle_t close_frame )
{
if( auto wsh = m_websocket_weak_handle.lock() )
{
try
{
m_msg_handler(
std::move( wsh ),
std::move( close_frame ) );
}
catch( const std::exception & ex )
{
m_logger.error( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] execute handler error: {}" ),
connection_id(),
ex.what() );
} );
}
}
}
bool
validate_payload_part(
char * payload_data,
std::size_t length,
std::size_t next_length_remaining )
{
const auto validation_result =
m_protocol_validator.process_and_unmask_next_payload_part( payload_data, length );
if( validation_state_t::payload_part_is_valid != validation_result )
{
handle_invalid_payload( validation_result );
if( validation_state_t::incorrect_utf8_data == validation_result )
{
// Can skip this payload because it was not a bad close frame.
// It is the case we are expecting close frame
// so validator must be ready to receive more headers
// and payloads after this frame.
m_protocol_validator.reset();
if( 0 == next_length_remaining )
{
start_read_header();
}
else
{
// Skip checking payload for this frame:
const bool do_validate_payload_and_call_msg_handler = false;
start_read_payload(
payload_data + length,
next_length_remaining,
do_validate_payload_and_call_msg_handler );
}
}
return false;
}
return true;
}
void
handle_invalid_payload( validation_state_t validation_result )
{
m_logger.error( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] invalid paload" ),
connection_id() );
} );
if( validation_state_t::invalid_close_code == validation_result )
{
// A corner case: invalid payload in close frame.
if( read_state_t::read_any_frame == m_read_state )
{
// Case: close frame was not expected.
// This actually must be executed:
m_close_frame_to_peer.run_if_first(
[&]{
send_close_frame_to_peer( status_code_t::protocol_error );
// Do not wait anything in return, because
// protocol is violated.
} );
// Notify user of a close but use a correct close code.
call_close_handler_if_necessary( status_code_t::protocol_error );
}
else if( read_state_t::read_only_close_frame == m_read_state )
{
// Case: close frame was expected.
// We got a close frame but it is incorrect,
// so just close (there is not too much we can do).
close_impl();
}
}
else
{
if( read_state_t::read_any_frame == m_read_state )
{
m_close_frame_to_peer.run_if_first(
[&]{
send_close_frame_to_peer( status_code_t::invalid_message_data );
start_waiting_close_frame_only();
} );
call_close_handler_if_necessary( status_code_t::invalid_message_data );
}
}
}
void
call_handler_on_current_message()
{
auto & md = m_input.m_parser.current_message();
const auto validation_result = m_protocol_validator.finish_frame();
if( validation_state_t::frame_is_valid == validation_result )
{
if( read_state_t::read_any_frame == m_read_state )
{
if( opcode_t::connection_close_frame == md.m_opcode )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] got close frame from "
"peer, status: {}" ),
connection_id(),
static_cast<std::uint16_t>(
status_code_from_bin( m_input.m_payload )) );
} );
m_close_frame_to_user.disable();
m_close_frame_to_peer.run_if_first(
[&]{
send_close_frame_to_peer( m_input.m_payload );
} );
m_read_state = read_state_t::read_nothing;
}
call_message_handler(
std::make_shared< message_t >(
md.m_final_flag ? final_frame : not_final_frame,
md.m_opcode,
std::move( m_input.m_payload ) ) );
if( read_state_t::read_nothing != m_read_state )
start_read_header();
}
else
{
assert( read_state_t::read_only_close_frame == m_read_state );
if( opcode_t::connection_close_frame == md.m_opcode )
{
// Got it!
m_timer_guard.cancel();
close_impl();
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] expected close frame came" ),
connection_id() );
} );
}
else
{
// Wait for next frame.
start_read_header();
}
}
}
else
{
handle_invalid_payload( validation_result );
}
}
void
call_close_handler_if_necessary( status_code_t status )
{
m_close_frame_to_user.run_if_first(
[&]{
call_message_handler(
std::make_shared< message_t >(
final_frame,
opcode_t::connection_close_frame,
status_code_to_bin( status ) ) );
} );
}
void
write_data_impl( write_group_t wg, bool is_close_frame )
{
if( m_socket.is_open() )
{
if( is_close_frame )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] user sends close frame" ),
connection_id() );
} );
m_close_frame_to_peer.disable(); // It is formed and sent by user
m_close_frame_to_user.disable(); // And user knows that websocket is closed.
// No more writes.
m_write_state = write_state_t::write_disabled;
// Start waiting only close-frame.
start_waiting_close_frame_only();
}
// Push write_group to queue.
m_outgoing_data.append( std::move( wg ) );
init_write_if_necessary();
}
else
{
m_logger.warn( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] try to write while "
"socket is closed" ),
connection_id() );
} );
try
{
wg.invoke_after_write_notificator_if_exists(
make_asio_compaible_error(
asio_convertible_error_t::write_was_not_executed ) );
}
catch( ... )
{}
}
}
void
init_write_if_necessary()
{
if( !m_write_output_ctx.transmitting() )
{
init_write();
}
}
void
init_write()
{
// Here: not writing anything to socket, so
// write operation can be initiated.
auto next_write_group = m_outgoing_data.pop_ready_buffers();
if( next_write_group )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] start next write group, "
"size: {}" ),
this->connection_id(),
next_write_group->items_count() );
} );
// Initialize write context with a new write group.
m_write_output_ctx.start_next_write_group(
std::move( next_write_group ) );
// Start the loop of sending data from current write group.
handle_current_write_ctx();
}
}
// Use aliases for shorter names.
using none_write_operation_t = ::restinio::impl::write_group_output_ctx_t::none_write_operation_t;
using trivial_write_operation_t = ::restinio::impl::write_group_output_ctx_t::trivial_write_operation_t;
using file_write_operation_t = ::restinio::impl::write_group_output_ctx_t::file_write_operation_t;
void
handle_current_write_ctx()
{
try
{
auto wo = m_write_output_ctx.extract_next_write_operation();
if( holds_alternative< trivial_write_operation_t >( wo ) )
{
handle_trivial_write_operation( get< trivial_write_operation_t >( wo ) );
}
else if( holds_alternative< none_write_operation_t >( wo ) )
{
finish_handling_current_write_ctx();
}
else
{
assert( holds_alternative< file_write_operation_t >( wo ) );
throw exception_t{ "sendfile write operation not implemented" };
}
}
catch( const std::exception & ex )
{
trigger_error_and_close(
status_code_t::unexpected_condition,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] handle_current_write_ctx failed: {}" ),
connection_id(),
ex.what() );
} );
}
}
void
handle_trivial_write_operation( const trivial_write_operation_t & op )
{
// Asio buffers (param for async write):
auto & bufs = op.get_trivial_bufs();
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] sending data with "
"buf count: {}, "
"total size: {}" ),
connection_id(),
bufs.size(),
op.size() ); } );
guard_write_operation();
// There is somethig to write.
asio_ns::async_write(
m_socket,
bufs,
asio_ns::bind_executor(
this->get_executor(),
[ this,
ctx = shared_from_this() ]
// NOTE: this lambda is noexcept since v.0.6.0.
( const asio_ns::error_code & ec, std::size_t written ) noexcept
{
try
{
if( !ec )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] outgoing data was "
"sent: {} bytes" ),
connection_id(),
written );
} );
}
after_write( ec );
}
catch( const std::exception & ex )
{
trigger_error_and_close(
status_code_t::unexpected_condition,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] after write "
"callback error: {}" ),
connection_id(),
ex.what() );
} );
}
} ) );
}
void
finish_handling_current_write_ctx()
{
// Finishing writing this group.
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] finishing current write group" ),
this->connection_id() );
} );
// Group notificators are called from here (if exist):
m_write_output_ctx.finish_write_group();
// Start another write opertion
// if there is something to send.
init_write_if_necessary();
}
void
after_write( const asio_ns::error_code & ec )
{
if( !ec )
{
handle_current_write_ctx();
}
else
{
trigger_error_and_close(
status_code_t::connection_lost,
[&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] unable to write: {}" ),
connection_id(),
ec.message() );
} );
try
{
m_write_output_ctx.fail_write_group( ec );
}
catch( const std::exception & ex )
{
m_logger.error( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[ws_connection:{}] notificator error: {}" ),
connection_id(),
ex.what() );
} );
}
}
}
restinio::impl::connection_settings_handle_t< Traits > m_settings;
stream_socket_t m_socket;
lifetime_monitor_t m_lifetime_monitor;
static ws_connection_t &
cast_to_self( tcp_connection_ctx_base_t & base )
{
return static_cast< ws_connection_t & >( base );
}
virtual void
check_timeout( tcp_connection_ctx_handle_t & self ) override
{
asio_ns::dispatch(
this->get_executor(),
[ ctx = std::move( self ) ]
// NOTE: this lambda is noexcept since v.0.6.0.
() noexcept
{
auto & conn_object = cast_to_self( *ctx );
// If an exception will be thrown we can only
// close the connection.
try
{
conn_object.check_timeout_impl();
}
catch( const std::exception & x )
{
conn_object.trigger_error_and_close(
status_code_t::unexpected_condition,
[&] {
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[connection: {}] unexpected "
"error during timeout handling: {}" ),
conn_object.connection_id(),
x.what() );
} );
}
} );
}
std::chrono::steady_clock::time_point m_write_operation_timeout_after;
std::chrono::steady_clock::time_point m_close_frame_from_peer_timeout_after =
std::chrono::steady_clock::time_point::max();
tcp_connection_ctx_weak_handle_t m_prepared_weak_ctx;
timer_guard_t m_timer_guard;
void
check_timeout_impl()
{
const auto now = std::chrono::steady_clock::now();
if( m_write_output_ctx.transmitting() && now > m_write_operation_timeout_after )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[wd_connection:{}] write operation timed out" ),
connection_id() );
} );
m_close_frame_to_peer.disable();
call_close_handler_if_necessary( status_code_t::unexpected_condition );
close_impl();
}
else if( now > m_close_frame_from_peer_timeout_after )
{
m_logger.trace( [&]{
return fmt::format(
RESTINIO_FMT_FORMAT_STRING(
"[wd_connection:{}] waiting for close-frame "
"from peer timed out" ),
connection_id() );
} );
close_impl();
}
else
{
init_next_timeout_checking();
}
}
void
init_next_timeout_checking()
{
m_timer_guard.schedule( m_prepared_weak_ctx );
}
void
guard_write_operation()
{
m_write_operation_timeout_after =
std::chrono::steady_clock::now() + m_settings->m_write_http_response_timelimit;
}
void
guard_close_frame_from_peer_operation()
{
m_close_frame_from_peer_timeout_after =
std::chrono::steady_clock::now() + m_settings->m_read_next_http_message_timelimit;
}
connection_input_t m_input;
ws_protocol_validator_t m_protocol_validator{ true };
message_handler_t m_msg_handler;
logger_t & m_logger;
restinio::impl::write_group_output_ctx_t m_write_output_ctx;
ws_outgoing_data_t m_outgoing_data;
ws_weak_handle_t m_websocket_weak_handle;
enum class write_state_t
{
write_enabled,
write_disabled
};
write_state_t m_write_state = write_state_t::write_enabled;
enum class read_state_t
{
read_any_frame,
read_only_close_frame,
read_nothing
};
read_state_t m_read_state = read_state_t::read_nothing;
class one_shot_action_t
{
public:
template < typename Action >
void
run_if_first( Action && action ) noexcept(noexcept(action()))
{
if( m_not_executed_yet )
{
m_not_executed_yet = false;
action();
}
}
void
disable()
{
m_not_executed_yet = false;
}
private:
bool m_not_executed_yet{ true };
};
one_shot_action_t m_close_frame_to_user;
one_shot_action_t m_close_frame_to_peer;
one_shot_action_t m_close_impl;
};
} /* namespace impl */
} /* namespace basic */
} /* namespace websocket */
} /* namespace restinio */
all.hpp
asio_include.hpp
nonstd::optional_lite::optional
class optional
Definition: optional.hpp:932
restinio::connection_count_limits::connection_lifetime_monitor_t
Helper type for controlling the lifetime of the connection.
Definition: connection_count_limiter.hpp:375
restinio::connection_state::notice_t
An object with info about connection to be passed to state listener.
Definition: connection_state_listener.hpp:225
restinio::connection_state::upgraded_to_websocket_t
Type of object that tells that the connection has been upgraded to WebSocket.
Definition: connection_state_listener.hpp:196
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::impl::executor_wrapper_t
Wrapper for an executor (strand) used by connections.
Definition: executor_wrapper.hpp:25
restinio::impl::executor_wrapper_t< Traits::strand_t >::get_executor
Traits::strand_t & get_executor() noexcept
An executor for callbacks on async operations.
Definition: executor_wrapper.hpp:35
restinio::impl::fixed_buffer_t
Helper class for reading bytes and feeding them to parser.
Definition: fixed_buffer.hpp:27
restinio::impl::fixed_buffer_t::length
std::size_t length() const noexcept
How many unconsumed bytes are there in buffer.
Definition: fixed_buffer.hpp:63
restinio::impl::fixed_buffer_t::consumed_bytes
void consumed_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
Definition: fixed_buffer.hpp:56
restinio::impl::fixed_buffer_t::obtained_bytes
void obtained_bytes(std::size_t length) noexcept
Mark how many bytes were obtained.
Definition: fixed_buffer.hpp:48
restinio::impl::fixed_buffer_t::make_asio_buffer
auto make_asio_buffer() noexcept
Make asio buffer for reading bytes from socket.
Definition: fixed_buffer.hpp:41
restinio::impl::fixed_buffer_t::bytes
const char * bytes() const noexcept
Get pointer to unconsumed bytes.
Definition: fixed_buffer.hpp:69
restinio::impl::write_group_output_ctx_t::file_write_operation_t
Write operaton using sendfile.
Definition: write_group_output_ctx.hpp:142
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t
Trivial write operaton.
Definition: write_group_output_ctx.hpp:106
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::size
auto size() const noexcept
The size of data within this operation.
Definition: write_group_output_ctx.hpp:133
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::get_trivial_bufs
const std::vector< asio_ns::const_buffer > & get_trivial_bufs() const noexcept
Get buffer "iovec" for performing gather write.
Definition: write_group_output_ctx.hpp:127
restinio::impl::write_group_output_ctx_t
Helper class for writting response data.
Definition: write_group_output_ctx.hpp:80
restinio::impl::write_group_output_ctx_t::fail_write_group
void fail_write_group(const asio_ns::error_code &ec)
Handle current group write process failed.
Definition: write_group_output_ctx.hpp:283
restinio::impl::write_group_output_ctx_t::extract_next_write_operation
solid_write_operation_variant_t extract_next_write_operation()
et an object with next write operation to perform.
Definition: write_group_output_ctx.hpp:253
restinio::impl::write_group_output_ctx_t::finish_write_group
void finish_write_group()
Finish writing group normally.
Definition: write_group_output_ctx.hpp:294
restinio::impl::write_group_output_ctx_t::start_next_write_group
void start_next_write_group(optional_t< write_group_t > next_wg) noexcept
Start handlong next write group.
Definition: write_group_output_ctx.hpp:239
restinio::impl::write_group_output_ctx_t::transmitting
bool transmitting() const noexcept
Check if data is trunsmitting now.
Definition: write_group_output_ctx.hpp:235
restinio::tcp_connection_ctx_base_t
TCP connection base.
Definition: tcp_connection_ctx_base.hpp:29
restinio::tcp_connection_ctx_base_t::connection_id
connection_id_t connection_id() const noexcept
Get connection id.
Definition: tcp_connection_ctx_base.hpp:38
restinio::websocket::basic::impl::message_details_t
Websocket message class with more detailed protocol information.
Definition: ws_parser.hpp:63
restinio::websocket::basic::impl::message_details_t::payload_len
std::uint64_t payload_len() const
Get payload len.
Definition: ws_parser.hpp:92
restinio::websocket::basic::impl::message_details_t::m_opcode
opcode_t m_opcode
Opcode.
Definition: ws_parser.hpp:117
restinio::websocket::basic::impl::ws_connection_base_t
WebSocket connection base.
Definition: ws_connection_base.hpp:39
restinio::websocket::basic::impl::ws_connection_t::one_shot_action_t
A helper class for running exclusive action. Only a first action will run.
Definition: ws_connection.hpp:1453
restinio::websocket::basic::impl::ws_connection_t::one_shot_action_t::run_if_first
void run_if_first(Action &&action) noexcept(noexcept(action()))
Definition: ws_connection.hpp:1457
restinio::websocket::basic::impl::ws_connection_t::one_shot_action_t::disable
void disable()
Disable ation: action will not be executed even on a first shot.
Definition: ws_connection.hpp:1468
restinio::websocket::basic::impl::ws_connection_t::one_shot_action_t::m_not_executed_yet
bool m_not_executed_yet
Definition: ws_connection.hpp:1474
restinio::websocket::basic::impl::ws_connection_t
Context for handling websocket connections.
Definition: ws_connection.hpp:125
restinio::websocket::basic::impl::ws_connection_t::m_timer_guard
timer_guard_t m_timer_guard
Definition: ws_connection.hpp:1345
restinio::websocket::basic::impl::ws_connection_t::finish_handling_current_write_ctx
void finish_handling_current_write_ctx()
Do post write actions for current write group.
Definition: ws_connection.hpp:1233
restinio::websocket::basic::impl::ws_connection_t::after_read_header
void after_read_header(const asio_ns::error_code &ec, std::size_t length)
Handle read operation result, when reading header.
Definition: ws_connection.hpp:577
restinio::websocket::basic::impl::ws_connection_t::m_settings
restinio::impl::connection_settings_handle_t< Traits > m_settings
Common paramaters of a connection.
Definition: ws_connection.hpp:1289
restinio::websocket::basic::impl::ws_connection_t::consume_header_from_socket
void consume_header_from_socket()
Initiate read operation on socket to receive bytes for header.
Definition: ws_connection.hpp:522
restinio::websocket::basic::impl::ws_connection_t::m_msg_handler
message_handler_t m_msg_handler
Websocket message handler provided by user.
Definition: ws_connection.hpp:1410
restinio::websocket::basic::impl::ws_connection_t::handle_parsed_header
void handle_parsed_header(const message_details_t &md)
Handle parsed header.
Definition: ws_connection.hpp:621
restinio::websocket::basic::impl::ws_connection_t::message_handler_t
WS_Message_Handler message_handler_t
Definition: ws_connection.hpp:129
restinio::websocket::basic::impl::ws_connection_t::validate_payload_part
bool validate_payload_part(char *payload_data, std::size_t length, std::size_t next_length_remaining)
Validates a part of received payload.
Definition: ws_connection.hpp:862
restinio::websocket::basic::impl::ws_connection_t::m_websocket_weak_handle
ws_weak_handle_t m_websocket_weak_handle
A waek handler for owning ws_t to use it when call message handler.
Definition: ws_connection.hpp:1422
restinio::websocket::basic::impl::ws_connection_t::shutdown
virtual void shutdown() override
Shutdown websocket.
Definition: ws_connection.hpp:212
restinio::websocket::basic::impl::ws_connection_t::lifetime_monitor_t
typename connection_count_limit_types< Traits >::lifetime_monitor_t lifetime_monitor_t
Definition: ws_connection.hpp:138
restinio::websocket::basic::impl::ws_connection_t::send_close_frame_to_peer
void send_close_frame_to_peer(std::string payload)
Send close frame to peer.
Definition: ws_connection.hpp:435
restinio::websocket::basic::impl::ws_connection_t::write_data_impl
void write_data_impl(write_group_t wg, bool is_close_frame)
Implementation of writing data performed on the asio_ns::io_context.
Definition: ws_connection.hpp:1043
restinio::websocket::basic::impl::ws_connection_t::read_state_t
read_state_t
Websocket input states.
Definition: ws_connection.hpp:1438
restinio::websocket::basic::impl::ws_connection_t::read_state_t::read_only_close_frame
@ read_only_close_frame
Reads only close frame: skip all frames until close-frame.
restinio::websocket::basic::impl::ws_connection_t::read_state_t::read_nothing
@ read_nothing
Do not read anything (before activation).
restinio::websocket::basic::impl::ws_connection_t::read_state_t::read_any_frame
@ read_any_frame
Reads any type of frame and serve it to user.
restinio::websocket::basic::impl::ws_connection_t::ws_weak_handle_t
std::weak_ptr< ws_t > ws_weak_handle_t
Definition: ws_connection.hpp:140
restinio::websocket::basic::impl::ws_connection_t::check_timeout_impl
void check_timeout_impl()
Definition: ws_connection.hpp:1348
restinio::websocket::basic::impl::ws_connection_t::logger_t
typename Traits::logger_t logger_t
Definition: ws_connection.hpp:134
restinio::websocket::basic::impl::ws_connection_t::write_state_t
write_state_t
Websocket output states.
Definition: ws_connection.hpp:1426
restinio::websocket::basic::impl::ws_connection_t::write_state_t::write_enabled
@ write_enabled
Able to append outgoing data.
restinio::websocket::basic::impl::ws_connection_t::write_state_t::write_disabled
@ write_disabled
No more outgoing data can be added (e.g. close-frame was sent).
restinio::websocket::basic::impl::ws_connection_t::guard_close_frame_from_peer_operation
void guard_close_frame_from_peer_operation()
Definition: ws_connection.hpp:1396
restinio::websocket::basic::impl::ws_connection_t::m_close_frame_from_peer_timeout_after
std::chrono::steady_clock::time_point m_close_frame_from_peer_timeout_after
Definition: ws_connection.hpp:1342
restinio::websocket::basic::impl::ws_connection_t::timer_guard_t
typename timer_manager_t::timer_guard_t timer_guard_t
Definition: ws_connection.hpp:133
restinio::websocket::basic::impl::ws_connection_t::m_close_impl
one_shot_action_t m_close_impl
Definition: ws_connection.hpp:1479
restinio::websocket::basic::impl::ws_connection_t::init_write_if_necessary
void init_write_if_necessary()
Checks if there is something to write, and if so starts write operation.
Definition: ws_connection.hpp:1094
restinio::websocket::basic::impl::ws_connection_t::trigger_error_and_close
void trigger_error_and_close(status_code_t status, MSG_BUILDER msg_builder) noexcept
Trigger an error.
Definition: ws_connection.hpp:475
restinio::websocket::basic::impl::ws_connection_t::start_read_header
void start_read_header()
Start the process of reading ws messages from socket.
Definition: ws_connection.hpp:496
restinio::websocket::basic::impl::ws_connection_t::start_read_payload
void start_read_payload(char *payload_data, std::size_t length_remaining, bool do_validate_payload_and_call_msg_handler=true)
Start reading message payload.
Definition: ws_connection.hpp:721
restinio::websocket::basic::impl::ws_connection_t::m_logger
logger_t & m_logger
Logger for operation.
Definition: ws_connection.hpp:1413
restinio::websocket::basic::impl::ws_connection_t::m_close_frame_to_peer
one_shot_action_t m_close_frame_to_peer
Definition: ws_connection.hpp:1478
restinio::websocket::basic::impl::ws_connection_t::m_close_frame_to_user
one_shot_action_t m_close_frame_to_user
Definition: ws_connection.hpp:1477
restinio::websocket::basic::impl::ws_connection_t::m_prepared_weak_ctx
tcp_connection_ctx_weak_handle_t m_prepared_weak_ctx
Definition: ws_connection.hpp:1344
restinio::websocket::basic::impl::ws_connection_t::handle_trivial_write_operation
void handle_trivial_write_operation(const trivial_write_operation_t &op)
Definition: ws_connection.hpp:1171
restinio::websocket::basic::impl::ws_connection_t::init_next_timeout_checking
void init_next_timeout_checking()
schedule next timeout checking.
Definition: ws_connection.hpp:1382
restinio::websocket::basic::impl::ws_connection_t::handle_invalid_payload
void handle_invalid_payload(validation_state_t validation_result)
Handle payload errors.
Definition: ws_connection.hpp:905
restinio::websocket::basic::impl::ws_connection_t::handle_current_write_ctx
void handle_current_write_ctx()
Definition: ws_connection.hpp:1136
restinio::websocket::basic::impl::ws_connection_t::after_read_payload
void after_read_payload(char *payload_data, std::size_t length_remaining, const asio_ns::error_code &ec, std::size_t length, bool do_validate_payload_and_call_msg_handler=true)
Handle read operation result, when reading payload.
Definition: ws_connection.hpp:768
restinio::websocket::basic::impl::ws_connection_t::call_close_handler_if_necessary
void call_close_handler_if_necessary(status_code_t status)
Definition: ws_connection.hpp:1029
restinio::websocket::basic::impl::ws_connection_t::consume_header_from_buffer
void consume_header_from_buffer(const char *data, std::size_t length)
Parse header from internal buffer.
Definition: ws_connection.hpp:602
restinio::websocket::basic::impl::ws_connection_t::send_close_frame_to_peer
void send_close_frame_to_peer(status_code_t code, std::string desc=std::string{})
Send close frame to peer.
Definition: ws_connection.hpp:457
restinio::websocket::basic::impl::ws_connection_t::ws_connection_t
ws_connection_t(const ws_connection_t &)=delete
restinio::websocket::basic::impl::ws_connection_t::check_timeout
virtual void check_timeout(tcp_connection_ctx_handle_t &self) override
Definition: ws_connection.hpp:1310
restinio::websocket::basic::impl::ws_connection_t::m_input
connection_input_t m_input
Input routine.
Definition: ws_connection.hpp:1404
restinio::websocket::basic::impl::ws_connection_t::handle_read_error
void handle_read_error(const char *desc, const asio_ns::error_code &ec)
Handle read error (reading header or payload)
Definition: ws_connection.hpp:561
restinio::websocket::basic::impl::ws_connection_t::call_handler_on_current_message
void call_handler_on_current_message()
Definition: ws_connection.hpp:958
restinio::websocket::basic::impl::ws_connection_t::m_write_state
write_state_t m_write_state
A state of a websocket output.
Definition: ws_connection.hpp:1434
restinio::websocket::basic::impl::ws_connection_t::m_protocol_validator
ws_protocol_validator_t m_protocol_validator
Helper for validating protocol.
Definition: ws_connection.hpp:1407
restinio::websocket::basic::impl::ws_connection_t::handle_parsed_and_valid_header
void handle_parsed_and_valid_header(const message_details_t &md)
Handle parsed and valid header.
Definition: ws_connection.hpp:669
restinio::websocket::basic::impl::ws_connection_t::operator=
ws_connection_t & operator=(const ws_connection_t &)=delete
restinio::websocket::basic::impl::ws_connection_t::ws_connection_t
ws_connection_t(ws_connection_t &&)=delete
restinio::websocket::basic::impl::ws_connection_t::start_waiting_close_frame_only
void start_waiting_close_frame_only()
Start waiting for close-frame.
Definition: ws_connection.hpp:416
restinio::websocket::basic::impl::ws_connection_t::m_write_operation_timeout_after
std::chrono::steady_clock::time_point m_write_operation_timeout_after
Definition: ws_connection.hpp:1341
restinio::websocket::basic::impl::ws_connection_t::strand_t
typename Traits::strand_t strand_t
Definition: ws_connection.hpp:135
restinio::websocket::basic::impl::ws_connection_t::kill
virtual void kill() override
Kill websocket.
Definition: ws_connection.hpp:250
restinio::websocket::basic::impl::ws_connection_t::guard_write_operation
void guard_write_operation()
Start guard write operation if necessary.
Definition: ws_connection.hpp:1389
restinio::websocket::basic::impl::ws_connection_t::~ws_connection_t
~ws_connection_t() override
Definition: ws_connection.hpp:194
restinio::websocket::basic::impl::ws_connection_t::m_outgoing_data
ws_outgoing_data_t m_outgoing_data
Output buffers queue.
Definition: ws_connection.hpp:1419
restinio::websocket::basic::impl::ws_connection_t::init_read
void init_read(ws_handle_t wsh) override
Start reading ws-messages.
Definition: ws_connection.hpp:291
restinio::websocket::basic::impl::ws_connection_t::timer_manager_handle_t
std::shared_ptr< timer_manager_t > timer_manager_handle_t
Definition: ws_connection.hpp:132
restinio::websocket::basic::impl::ws_connection_t::call_message_handler
void call_message_handler(message_handle_t close_frame)
Call user message handler with current message.
Definition: ws_connection.hpp:837
restinio::websocket::basic::impl::ws_connection_t::cast_to_self
static ws_connection_t & cast_to_self(tcp_connection_ctx_base_t &base)
Timers.
Definition: ws_connection.hpp:1304
restinio::websocket::basic::impl::ws_connection_t::init_write
void init_write()
Initiate write operation.
Definition: ws_connection.hpp:1104
restinio::websocket::basic::impl::ws_connection_t::m_lifetime_monitor
lifetime_monitor_t m_lifetime_monitor
Monitor of the connection lifetime.
Definition: ws_connection.hpp:1299
restinio::websocket::basic::impl::ws_connection_t::after_write
void after_write(const asio_ns::error_code &ec)
Handle write response finished.
Definition: ws_connection.hpp:1253
restinio::websocket::basic::impl::ws_connection_t::m_write_output_ctx
restinio::impl::write_group_output_ctx_t m_write_output_ctx
Write to socket operation context.
Definition: ws_connection.hpp:1416
restinio::websocket::basic::impl::ws_connection_t::close_impl
void close_impl() noexcept
Standard close routine.
Definition: ws_connection.hpp:381
restinio::websocket::basic::impl::ws_connection_t::stream_socket_t
typename Traits::stream_socket_t stream_socket_t
Definition: ws_connection.hpp:136
restinio::websocket::basic::impl::ws_connection_t::write_data
virtual void write_data(write_group_t wg, bool is_close_frame) override
Write pieces of outgoing data.
Definition: ws_connection.hpp:329
restinio::websocket::basic::impl::ws_connection_t::m_socket
stream_socket_t m_socket
Connection.
Definition: ws_connection.hpp:1292
restinio::websocket::basic::impl::ws_connection_t::graceful_close
void graceful_close()
Close WebSocket connection in a graceful manner.
Definition: ws_connection.hpp:424
restinio::websocket::basic::impl::ws_connection_t::m_read_state
read_state_t m_read_state
A state of a websocket input.
Definition: ws_connection.hpp:1448
restinio::websocket::basic::impl::ws_connection_t::timer_manager_t
typename Traits::timer_manager_t timer_manager_t
Definition: ws_connection.hpp:131
restinio::websocket::basic::impl::ws_outgoing_data_t
A queue for outgoing buffers.
Definition: ws_connection.hpp:57
restinio::websocket::basic::impl::ws_outgoing_data_t::pop_ready_buffers
optional_t< write_group_t > pop_ready_buffers()
Definition: ws_connection.hpp:67
restinio::websocket::basic::impl::ws_outgoing_data_t::m_awaiting_write_groups
write_groups_queue_t m_awaiting_write_groups
A queue of buffers.
Definition: ws_connection.hpp:82
restinio::websocket::basic::impl::ws_outgoing_data_t::append
void append(write_group_t wg)
Add buffers to queue.
Definition: ws_connection.hpp:61
restinio::websocket::basic::impl::ws_parser_t
Websocket parser.
Definition: ws_parser.hpp:260
restinio::websocket::basic::impl::ws_parser_t::reset
void reset()
Reset internal state.
Definition: ws_parser.hpp:294
restinio::websocket::basic::impl::ws_parser_t::current_message
const message_details_t & current_message() const
Get current mesasge details.
Definition: ws_parser.hpp:303
restinio::websocket::basic::impl::ws_parser_t::parser_execute
size_t parser_execute(const char *data, size_t size)
Parse piece of data from buffer.
Definition: ws_parser.hpp:265
restinio::websocket::basic::impl::ws_parser_t::header_parsed
bool header_parsed() const
Check header of current websocket message is parsed.
Definition: ws_parser.hpp:284
restinio::websocket::basic::impl::ws_protocol_validator_t
Class for websocket protocol validations.
Definition: ws_protocol_validator.hpp:195
restinio::websocket::basic::impl::ws_protocol_validator_t::process_and_unmask_next_payload_part
validation_state_t process_and_unmask_next_payload_part(char *data, size_t size)
Validate next part of current frame and reset source part to unmasked data.
Definition: ws_protocol_validator.hpp:278
restinio::websocket::basic::impl::ws_protocol_validator_t::process_new_frame
validation_state_t process_new_frame(const message_details_t &frame)
Start work with new frame.
Definition: ws_protocol_validator.hpp:211
restinio::websocket::basic::impl::ws_protocol_validator_t::finish_frame
validation_state_t finish_frame()
Make final checks of payload if it is necessary and reset state.
Definition: ws_protocol_validator.hpp:303
restinio::websocket::basic::impl::ws_protocol_validator_t::reset
void reset()
Reset to initial state.
Definition: ws_protocol_validator.hpp:341
restinio::write_group_t
Group of writable items transported to the context of underlying connection as one solid piece.
Definition: buffers.hpp:729
restinio::write_group_t::invoke_after_write_notificator_if_exists
void invoke_after_write_notificator_if_exists(const asio_ns::error_code &ec)
Get after write notificator.
Definition: buffers.hpp:852
compiler_features.hpp
Detection of compiler version and absence of various features.
RESTINIO_ENSURE_NOEXCEPT_CALL
#define RESTINIO_ENSURE_NOEXCEPT_CALL(expr)
A wrapper around static_assert for checking that an expression is noexcept and execution of that expr...
Definition: compiler_features.hpp:70
executor_wrapper.hpp
include_fmtlib.hpp
A special wrapper around fmtlib include files.
RESTINIO_FMT_FORMAT_STRING
#define RESTINIO_FMT_FORMAT_STRING(s)
Definition: include_fmtlib.hpp:92
message.hpp
restinio::fmtlib_tools::streamed
decltype(auto) streamed(T &&v) noexcept
Definition: include_fmtlib.hpp:63
restinio::impl::connection_settings_handle_t
std::shared_ptr< connection_settings_t< Traits > > connection_settings_handle_t
Definition: connection_settings.hpp:235
restinio::utils::impl::uint64_to_size_t
std::size_t uint64_to_size_t(std::uint64_t v)
Helper function for truncating uint64 to std::size_t with exception if that truncation will lead to d...
Definition: safe_uint_truncate.hpp:59
restinio::utils::suppress_exceptions
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...
Definition: suppress_exceptions.hpp:94
restinio::utils::log_error_noexcept
void log_error_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
Definition: suppress_exceptions.hpp:71
restinio::utils::log_trace_noexcept
void log_trace_noexcept(Logger &&logger, Message_Builder &&builder) noexcept
Definition: suppress_exceptions.hpp:32
restinio::websocket::basic::impl::write_message_details
raw_data_t write_message_details(const message_details_t &message)
Serialize websocket message details into bytes buffer.
Definition: ws_parser.hpp:515
restinio::websocket::basic::impl::websocket_header_max_size
constexpr size_t websocket_header_max_size()
Max possible size of websocket frame header (a part before payload).
Definition: ws_connection.hpp:46
restinio::websocket::basic::impl::write_groups_queue_t
std::queue< write_group_t > write_groups_queue_t
Definition: ws_connection.hpp:42
restinio::websocket::basic::impl::validation_state_t
validation_state_t
States of validated frame.
Definition: ws_protocol_validator.hpp:29
restinio::websocket::basic::impl::validation_state_t::payload_part_is_valid
@ payload_part_is_valid
restinio::websocket::basic::impl::validation_state_t::frame_header_is_valid
@ frame_header_is_valid
restinio::websocket::basic::impl::validation_state_t::incorrect_utf8_data
@ incorrect_utf8_data
restinio::websocket::basic::impl::validation_state_t::invalid_close_code
@ invalid_close_code
restinio::websocket::basic::impl::validation_state_t::frame_is_valid
@ frame_is_valid
restinio::websocket::basic::status_code_t
status_code_t
Definition: message.hpp:86
restinio::websocket::basic::status_code_t::unexpected_condition
@ unexpected_condition
restinio::websocket::basic::status_code_t::connection_lost
@ connection_lost
restinio::websocket::basic::status_code_t::invalid_message_data
@ invalid_message_data
restinio::websocket::basic::status_code_t::protocol_error
@ protocol_error
restinio::websocket::basic::status_code_t::normal_closure
@ normal_closure
restinio::websocket::basic::message_handle_t
std::shared_ptr< message_t > message_handle_t
Request handler, that is the type for calling request handlers.
Definition: message.hpp:227
restinio::websocket::basic::final_frame
constexpr final_frame_flag_t final_frame
Definition: message.hpp:135
restinio::websocket::basic::not_final_frame
constexpr final_frame_flag_t not_final_frame
Definition: message.hpp:136
restinio::websocket::basic::opcode_to_string
const char * opcode_to_string(opcode_t opcode)
Helper sunction to get method string name.
Definition: message.hpp:46
restinio::websocket::basic::status_code_from_bin
status_code_t status_code_from_bin(string_view_t data)
Definition: message.hpp:112
restinio::websocket::basic::status_code_to_bin
std::string status_code_to_bin(status_code_t code)
Definition: message.hpp:101
restinio::websocket::basic::ws_handle_t
std::shared_ptr< ws_t > ws_handle_t
Alias for ws_t handle.
Definition: ws_connection_base.hpp:27
restinio
Definition: asio_include.hpp:21
restinio::tcp_connection_ctx_handle_t
std::shared_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_handle_t
Alias for http connection handle.
Definition: tcp_connection_ctx_base.hpp:62
restinio::writable_items_container_t
std::vector< writable_item_t > writable_items_container_t
Definition: buffers.hpp:705
restinio::tcp_connection_ctx_weak_handle_t
std::weak_ptr< tcp_connection_ctx_base_t > tcp_connection_ctx_weak_handle_t
Alias for http connection weak handle.
Definition: tcp_connection_ctx_base.hpp:65
restinio::asio_convertible_error_t::write_was_not_executed
@ write_was_not_executed
After write notificator error: data was not sent, connection closed (or aborted) before a given piece...
restinio::make_asio_compaible_error
asio_ns::error_code make_asio_compaible_error(asio_convertible_error_t err) noexcept
Make restinio error_code compatible with asio_ns::error_code.
Definition: asio_include.hpp:210
restinio::connection_id_t
std::uint64_t connection_id_t
Type for ID of connection.
Definition: common_types.hpp:174
std
STL namespace.
safe_uint_truncate.hpp
Helpers for safe truncation of unsigned integers.
code
Definition: inftrees.h:24
restinio::impl::write_group_output_ctx_t::none_write_operation_t
None write operation.
Definition: write_group_output_ctx.hpp:232
restinio::websocket::basic::impl::connection_input_t
Websocket input stuff.
Definition: ws_connection.hpp:91
restinio::websocket::basic::impl::connection_input_t::m_parser
ws_parser_t m_parser
websocket parser.
Definition: ws_connection.hpp:97
restinio::websocket::basic::impl::connection_input_t::m_buf
restinio::impl::fixed_buffer_t m_buf
Input buffer.
Definition: ws_connection.hpp:100
restinio::websocket::basic::impl::connection_input_t::reset_parser_and_payload
void reset_parser_and_payload()
Prepare parser for reading new http-message.
Definition: ws_connection.hpp:107
restinio::websocket::basic::impl::connection_input_t::connection_input_t
connection_input_t(std::size_t buffer_size)
Definition: ws_connection.hpp:92
restinio::websocket::basic::impl::connection_input_t::m_payload
std::string m_payload
Current payload.
Definition: ws_connection.hpp:103
write_group_output_ctx.hpp
ws_parser.hpp
ws_protocol_validator.hpp