Chops Net IP
Loading...
Searching...
No Matches
chops::net::basic_io_interface< IOT > Class Template Reference

The basic_io_interface class template provides access to an underlying network IO handler (TCP or UDP IO handler), primarily for calling the start_io, stop_io, and make_io_output methods. More...

#include <basic_io_interface.hpp>

Public Types

using endpoint_type = typename IOT::endpoint_type
 

Public Member Functions

 basic_io_interface ()=default
 Default construct a basic_io_interface.
 
 basic_io_interface (const basic_io_interface &)=default
 
 basic_io_interface (basic_io_interface &&)=default
 
basic_io_interface< IOT > & operator= (const basic_io_interface &)=default
 
basic_io_interface< IOT > & operator= (basic_io_interface &&)=default
 
 basic_io_interface (std::weak_ptr< IOT > p) noexcept
 Construct with a shared weak pointer to an internal IO handler, this is an internal constructor only and not to be used by application code.
 
bool is_valid () const noexcept
 Query whether an IO handler is associated with this object.
 
auto make_io_output () const -> nonstd::expected< basic_io_output< IOT >, std::error_code >
 Make a basic_io_output object from the associated IO handler.
 
auto is_io_started () const -> nonstd::expected< bool, std::error_code >
 Query whether an IO handler is in a started state or not.
 
template<typename F >
auto visit_socket (F &&func) -> nonstd::expected< void, std::error_code >
 Provide an application supplied function object which will be called with a reference to the associated IO handler socket.
 
template<typename MH , typename MF >
auto start_io (std::size_t header_size, MH &&msg_handler, MF &&msg_frame) -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with message frame logic.
 
template<typename MH >
auto start_io (std::size_t header_size, MH &&msg_handler, hdr_decoder_func func) -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with simple variable length message frame logic.
 
template<typename MH >
auto start_io (std::string_view delimiter, MH &&msg_handler) -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with delimeter logic.
 
template<typename MH >
auto start_io (std::size_t read_size, MH &&msg_handler) -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with fixed or maximum buffer size logic.
 
template<typename MH >
auto start_io (const endpoint_type &endp, std::size_t max_size, MH &&msg_handler) -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with a maximum buffer size and a default destination endpoint.
 
auto start_io () -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with no incoming message handling.
 
auto start_io (const endpoint_type &endp) -> nonstd::expected< void, std::error_code >
 Enable IO processing for the associated network IO handler with no incoming message handling, but with a default destination endpoint.
 
auto stop_io () -> nonstd::expected< void, std::error_code >
 Stop IO processing and close the associated network IO handler.
 
bool operator== (const basic_io_interface< IOT > &rhs) const noexcept
 Compare two basic_io_interface objects for equality.
 
bool operator< (const basic_io_interface< IOT > &rhs) const noexcept
 Compare two basic_io_interface objects for ordering purposes.
 
const void * get_ptr () const noexcept
 Return a raw pointer to an associated IO handler.
 

Related Symbols

(Note that these are not member symbols.)

using tcp_io_interface = basic_io_interface<tcp_io>
 Using declaration for a TCP based basic_io_interface type.
 
using udp_io_interface = basic_io_interface<udp_io>
 Using declaration for a UDP based basic_io_interface type.
 
using hdr_decoder_func = std::size_t (*)(const std::byte* ptr, std::size_t sz)
 Signature for a variable length message header decoder function, used in one of the basic_io_interface start_io methods.
 

Detailed Description

template<typename IOT>
class chops::net::basic_io_interface< IOT >

The basic_io_interface class template provides access to an underlying network IO handler (TCP or UDP IO handler), primarily for calling the start_io, stop_io, and make_io_output methods.

The basic_io_interface class provides the primary application interface to start network IO processing, whether TCP or UDP. This class provides methods to start IO processing (i.e. start read processing and enable write processing), stop IO processing (if needed, typically doesn't need to be directly called), and access the IO handler socket (e.g. to retrieve or modify socket options). It also provides a method to create a basic_io_output object for sending data.

The start_io and stop_io methods are not a data flow toggle. In other words, once start_io is called, no other start_io methods can be called. If stop_io is called, connection teardown (or socket close) is initiated, and start_io will not be possible.

Calling stop_io is not necessary and is only needed if an application needs to close a connection or socket directly and not through other means (e.g. a net_entity close or a connection termination or a message handler false return).

This class is a lightweight value class, allowing basic_io_interface objects to be copied and used in multiple places in an application, all of them accessing the same network IO handler. Internally, a std::weak pointer is used to link the basic_io_interface object with a network IO handler.

A basic_io_interface object is provided for application use through a state change function object callback. This occurs when a net_entity creates the underlying network IO handler, or the network IO handler is being closed and destructed. The net_entity class documentation provides more detail.

A basic_io_interface object is either associated with a network IO handler (i.e. the std::weak pointer is good), or not. The is_valid method queries if the association is present. Note that even if the std::weak_pointer is valid, the network IO handler might be in the process of closing or being destructed.

Applications can default construct a basic_io_interface object, but it is not useful until a valid basic_io_interface object is assigned to it (typically this would be performed through the state change function object callback).

A basic_io_output object can be created from a basic_io_interface, allowing the sending of data to the underlying network IO handler.

The underlying network IO handler socket can be accessed through the visit_socket method. This allows socket options to be queried and set (or other useful socket methods to be called).

Appropriate comparison operators are provided to allow basic_io_interface objects to be used in associative or sequence containers.

All basic_io_interface methods can be called concurrently from multiple threads, but calling stop_io at the same time as start_io from multiple threads may result in undesired application behavior.

Error handling is provided by returning a nonstd::expected object on most methods.

Constructor & Destructor Documentation

◆ basic_io_interface()

template<typename IOT >
chops::net::basic_io_interface< IOT >::basic_io_interface ( )
default

Default construct a basic_io_interface.

A basic_io_interface is not useful until an active basic_io_interface is assigned into it.

Member Function Documentation

◆ get_ptr()

template<typename IOT >
const void * chops::net::basic_io_interface< IOT >::get_ptr ( ) const
inlinenoexcept

Return a raw pointer to an associated IO handler.

This method provides a raw pointer to an associated IO handler (or nullptr). This value can be used for logging or associative container lookup purposes. In particular, this value can be used to correlate multiple error messages from the same IO handler instantiation.

Returns
A pointer value, which may be a nullptr.

◆ is_io_started()

template<typename IOT >
auto chops::net::basic_io_interface< IOT >::is_io_started ( ) const -> nonstd::expected<bool, std::error_code>
inline

Query whether an IO handler is in a started state or not.

Returns
nonstd::expected - bool on success, specifying whether start_io on the IO handler has been called (if false, the IO handler has not been started or is in a stopped state); on error (if no associated IO handler), a std::error_code is returned.

◆ is_valid()

template<typename IOT >
bool chops::net::basic_io_interface< IOT >::is_valid ( ) const
inlinenoexcept

Query whether an IO handler is associated with this object.

If true, an IO handler (e.g. TCP or UDP IO handler) is associated. However, the IO handler may be closing down and may not allow further operations.

Returns
true if associated with an IO handler.

◆ make_io_output()

template<typename IOT >
auto chops::net::basic_io_interface< IOT >::make_io_output ( ) const -> nonstd::expected<basic_io_output<IOT>, std::error_code>
inline

Make a basic_io_output object from the associated IO handler.

A basic_io_output object is used for sending data. A basic_io_output object will be created even if start_io has not been called, and attempting to send data before start_io is called will result in discarded data.

Returns
nonstd::expected - basic_io_output on success, either a tcp_io_output or udp_io_output; on error (if no associated IO handler), a std::error_code is returned.

◆ operator<()

template<typename IOT >
bool chops::net::basic_io_interface< IOT >::operator< ( const basic_io_interface< IOT > & rhs) const
inlinenoexcept

Compare two basic_io_interface objects for ordering purposes.

The comparison is made through the std::shared_ptr operator< method. All invalid basic_io_interface objects are less than valid ones. When both are valid, the address ordering is returned.

Returns
As described in the comments.

◆ operator==()

template<typename IOT >
bool chops::net::basic_io_interface< IOT >::operator== ( const basic_io_interface< IOT > & rhs) const
inlinenoexcept

Compare two basic_io_interface objects for equality.

The comparison is made through the std::shared_ptr operator== method. The comparison is made on addresses if both basic_io_interface objects are valid. If both basic_io_interface objects are invalid, true is returned (this implies that all invalid basic_io_interface objects are equivalent). If one is valid and the other invalid, false is returned.

Returns
As described in the comments.

◆ start_io() [1/7]

template<typename IOT >
auto chops::net::basic_io_interface< IOT >::start_io ( ) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with no incoming message handling.

This method is implemented for both TCP and UDP IO handlers.

This method is used to enable IO processing where only sends are needed (and no incoming message handling).

For TCP IO handlers, a read will be started, but no data processed (typically if the read completes it is due to an error condition). For UDP IO handlers, no reads are started.

Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ start_io() [2/7]

template<typename IOT >
auto chops::net::basic_io_interface< IOT >::start_io ( const endpoint_type & endp) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with no incoming message handling, but with a default destination endpoint.

This method is not implemented for TCP IO handlers (only for UDP IO handlers).

This allows the send method without an endpoint to be called for UDP datagrams.

This method is used to enable IO processing where only sends are needed (and no incoming message handling).

Parameters
endpDefault destination asio::ip::udp::endpoint.
Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ start_io() [3/7]

template<typename IOT >
template<typename MH >
auto chops::net::basic_io_interface< IOT >::start_io ( const endpoint_type & endp,
std::size_t max_size,
MH && msg_handler ) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with a maximum buffer size and a default destination endpoint.

This method is not implemented for TCP IO handlers (only for UDP IO handlers).

This allows the send method without an endpoint to be called for UDP datagrams. The buffer will be sent to this destination endpoint.

The maximum size parameter is the same as the corresponding (without default destination endpoint) start_io method.

Sends (writes) are enabled after this call.

Parameters
endpDefault destination asio::ip::udp::endpoint.
max_sizeMaximum UDP datagram size.
msg_handlerA message handler function object callback. The signature of the callback is:
bool (asio::const_buffer,
chops::net::udp_io_output, // basic_io_output<udp_io>
asio::ip::udp::endpoint);

Returning false from the message handler callback causes the UDP socket to be closed.

The message handler function object is moved if possible, otherwise it is copied. State data should be movable or copyable.

Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ start_io() [4/7]

template<typename IOT >
template<typename MH >
auto chops::net::basic_io_interface< IOT >::start_io ( std::size_t header_size,
MH && msg_handler,
hdr_decoder_func func ) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with simple variable length message frame logic.

This method is not implemented for UDP IO handlers.

For TCP IO handlers, this starts read processing using a message handler function object callback and a simple variable length message header decoder function pointer. The message frame TCP processing is similar to the generalized message frame processing except that only simple variable length messages are supported. "Simple" means a fixed size header followed by one variable length body. The header must be able to be decoded with a simple function that returns the size (in bytes) of the body when given the full, fixed size header.

Parameters
header_sizeThe initial read size (in bytes) of each incoming message, which should match the header size of the header decoder function.
msg_handlerA message handler function object callback. The signature of the callback is:
bool (asio::const_buffer,
chops::net::tcp_io_output, // basic_io_output<tcp_io>
asio::ip::tcp::endpoint);

The buffer (first parameter) always references a full message. The basic_io_output can be used for sending a reply. The endpoint is the remote endpoint that sent the data (not used in the send method call, but may be useful for other purposes).

Returning false from the message handler callback causes the connection to be closed.

The message handler function object is moved if possible, otherwise it is copied. State data should be movable or copyable.

Parameters
funcA function that is of type hdr_decoder_func.
Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ start_io() [5/7]

template<typename IOT >
template<typename MH , typename MF >
auto chops::net::basic_io_interface< IOT >::start_io ( std::size_t header_size,
MH && msg_handler,
MF && msg_frame ) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with message frame logic.

This method is not implemented for UDP IO handlers.

For TCP IO handlers, this starts read processing using a message handler function object callback and a message frame function object callback. Sends (writes) are enabled after this call.

This method is used for message frame based TCP processing. The logic is "read header, process data to determine size of rest of message, read rest of message". The message frame function object callback implements this logic. Once a complete message has been read, the message handler function object callback is invoked. There may be multiple iterations of calling the message frame function object before the message frame determines the complete message has been read.

Parameters
header_sizeThe initial read size (in bytes) of each incoming message.
msg_handlerA message handler function object callback. The signature of the callback is:
bool (asio::const_buffer,
chops::net::tcp_io_output, // basic_io_output<tcp_io>
asio::ip::tcp::endpoint);

The buffer (first parameter) always references a full message. The basic_io_output can be used for sending a reply. The endpoint is the remote endpoint that sent the data (not used in the send method call, but may be useful for other purposes).

Returning false from the message handler callback causes the connection to be closed.

The message handler function object is moved if possible, otherwise it is copied. State data should be movable or copyable.

Parameters
msg_frameA message frame function object callback. The signature of the callback is:
std::size_t (asio::mutable_buffer);

Each time the message frame callback is called by the Chops Net IP IO handler, the next chunk of incoming bytes is passed through the buffer parameter.

The callback returns the size of the next read, or zero as a notification that the complete message has been called and the message handler is to be invoked.

If there is non-trivial processing that is performed in the message frame object and the application wishes to keep any resulting state (typically to use within the message handler), one option is to design a single class that provides two operator function call overloads and use the same object (via std::ref) for both the message handler and the message frame processing.

The message frame function object is moved if possible, otherwise it is copied. State data should be movable or copyable.

Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ start_io() [6/7]

template<typename IOT >
template<typename MH >
auto chops::net::basic_io_interface< IOT >::start_io ( std::size_t read_size,
MH && msg_handler ) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with fixed or maximum buffer size logic.

This method is implemented for both TCP and UDP IO handlers.

For TCP IO handlers, this reads a fixed size message which is then passed to the message handler function object.

For UDP IO handlers, this specifies the maximum size of the datagram. For IPv4 this value can be up to 65,507 (for IPv6 the maximum is larger). If the incoming datagram is larger than the specified size, data will be truncated or lost.

Sends (writes) are enabled after this call.

Parameters
read_sizeMaximum UDP datagram size or TCP fixed read size.
msg_handlerA message handler function object callback. The signature of the callback is:
// TCP io:
bool (asio::const_buffer,
chops::net::tcp_io_output, // basic_io_output<tcp_io>
asio::ip::tcp::endpoint);
// UDP io:
bool (asio::const_buffer,
chops::net::udp_io_output, // basic_io_output<udp_io>
asio::ip::udp::endpoint);

Returning false from the message handler callback causes the TCP connection or UDP socket to be closed.

The message handler function object is moved if possible, otherwise it is copied. State data should be movable or copyable.

Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ start_io() [7/7]

template<typename IOT >
template<typename MH >
auto chops::net::basic_io_interface< IOT >::start_io ( std::string_view delimiter,
MH && msg_handler ) -> nonstd::expected<void, std::error_code>
inline

Enable IO processing for the associated network IO handler with delimeter logic.

This method is not implemented for UDP IO handlers.

For TCP IO handlers, this starts read processing using a message handler function object callback. Sends (writes) are enabled after this call.

This method is used for delimiter based TCP processing (typically text based messages in TCP streams). The logic is "read data until the delimiter characters match" (which are usually "end-of-line" sequences). The message handler function object callback is then invoked.

Parameters
delimiterDelimiter characters denoting end of each message.
msg_handlerA message handler function object callback. The signature of the callback is:
bool (asio::const_buffer,
chops::net::tcp_io_output, // basic_io_output<tcp_io>
asio::ip::tcp::endpoint);

The buffer points to the complete message including the delimiter sequence. The basic_io_output can be used for sending a reply, and the endpoint is the remote endpoint that sent the data. Returning false from the message handler callback causes the connection to be closed.

The message handler function object is moved if possible, otherwise it is copied. State data should be movable or copyable.

Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ stop_io()

template<typename IOT >
auto chops::net::basic_io_interface< IOT >::stop_io ( ) -> nonstd::expected<void, std::error_code>
inline

Stop IO processing and close the associated network IO handler.

After this call, connection disconnect or socket close processing will occur, a state change function object callback will be invoked, and eventually the IO handler object will be destructed. start_io cannot be called after stop_io (in other words, start_io followed by stop_io followed by start_io, etc is not supported).

For TCP entities (connectors and acceptors), the TCP connection will be taken down, but the entity will remain active. For UDP entities stop_io is equivalent to calling stop on the net_entity.

Returns
nonstd::expected - IO is started on success; on error, a std::error_code is returned.

◆ visit_socket()

template<typename IOT >
template<typename F >
auto chops::net::basic_io_interface< IOT >::visit_socket ( F && func) -> nonstd::expected<void, std::error_code>
inline

Provide an application supplied function object which will be called with a reference to the associated IO handler socket.

The function object must have one of the following signatures, depending on the IO handler type:

void (asio::ip::tcp::socket&); // TCP IO
void (asio::ip::udp::socket&); // UDP IO

Within the function object socket options can be queried or modified.

Returns
nonstd::expected - socket has been visited on success; on error (if no associated IO handler), a std::error_code is returned.

Friends And Related Symbol Documentation

◆ hdr_decoder_func

template<typename IOT >
using hdr_decoder_func = std::size_t (*)(const std::byte* ptr, std::size_t sz)
related

Signature for a variable length message header decoder function, used in one of the basic_io_interface start_io methods.

Given a buffer of std::bytes corresponding to a header on a variable length message, decode the header and return the length in bytes of the message body. Specifically, only the size of the body should be returned, not the full message size (header plus body).

For example, a 14 byte header that contains a full message length would need to subtract 14 from the length before returning the value from this function.

This can only be a function pointer, not a function object. If state needs to be stored or more complex logic needed than can be provided by a simple function, then the start_io that takes a full message frame function object should be used.

Parameters
ptrA pointer to the beginning of the variable len message header.
szThe size of the header buffer, in bytes, which should be the same for every call and match the parameter given to the basic_io_interface start_io call.

The documentation for this class was generated from the following files: