randolf.ca  1.00
Randolf's C++ classes
randolf::rsocket Class Reference

This rsocket class provides an easy-to-use and thoroughy-implemented object-oriented socket I/O interface for C++, intended to make socket I/O programming (with or without TLS encryption) easier and more enjoyable. More...

+ Collaboration diagram for randolf::rsocket:

Public Types

enum  TIMEOUT_BEHAVIOUR : bool {
  TIMEOUT_EXCEPTION = true ,
  TIMEOUT_EMPTY = false ,
  TIMEOUT_NULL = false ,
  TIMEOUT_ZERO = false
}
 Optional flags used with various methods to determine whether they will throw an randolf::rex::xETIMEDOUT exception or merely return a nullptr, an empty set, or a 0 (zero) when a timeout duration elapses. More...
 
enum  TLS_FLAGS : int {
  TLS_DEFAULT = 0 ,
  TLS_EXCLUSIVE = 1 ,
  TLS_NO_INGRESS = 2 ,
  TLS_NO_EGRESS = 4 ,
  TLS_CLIENT = 0 ,
  TLS_SERVER = 8
}
 Optional flags used with rsocket's tls() and tls_ctx() methods to specify relevant policies/semantics. More...
 

Public Member Functions

 rsocket () noexcept
 Instantiate an empty rsocket without opening said socket, and without throwing any exceptions. More...
 
 rsocket (const int family, const int type=SOCK_STREAM, const int protocol=PF_UNSPEC)
 Instantiate an rsocket with IP/host address and [optional] port number. More...
 
 rsocket (const rsocket *rtemplate, const bool flag_create_socket=true)
 Instantiate an rsocket based on a minimal subset of the settings in the specified rsocket (using it as a template), without actually opening a socket, and therefore also without throwing any exceptions. More...
 
 ~rsocket () noexcept
 Destructor, which closes any underlying sockets, frees any TLS structures that were allocated by OpenSSL, and performs any other necessary clean-up before finally copying the I/O statistics to a designated structure (if one was specified with the net_io_final() method). More...
 
rsocketaccept ()
 Accept new [inbound] socket connetions. (This is typically used in a loop.) More...
 
rsocketaccept4 (const int flags=0)
 Accept new [inbound] socket connetions, with socket flags specified. (This is typically used in a loop.) More...
 
std::shared_ptr< rsocketaccept4_sp (const int flags=0)
 Accept new [inbound] socket connetions, with socket flags specified. (This is typically used in a loop.) More...
 
std::shared_ptr< rsocketaccept_sp ()
 Accept new [inbound] socket connetions. (This is typically used in a loop.) More...
 
int backlog () noexcept
 Find out what this rsocket's default listen backlog is. More...
 
rsocketbacklog (int backlog=0) noexcept
 Override the default listen backlog for this rsocket. More...
 
rsocketbind (const std::string address, const int port=0)
 Bind this socket to the specified network address (and port number if the address family utilizes port numbers {e.g., TCP or UDP}). This is mostly used for server deamons, but can also be used to control the address from which the local host will make an outbound connection via the connect() method (this bound address is address from which the endpoint will recieve your connection). More...
 
rsocketbind (const struct sockaddr *addr, const socklen_t addrlen=sizeof(sockaddr))
 Bind this socket to the specified network address (and port number if the address family utilizes port numbers {e.g., TCP or UDP}). This is mostly used for server deamons, but can also be used to control the address from which the local host will make an outbound connection via the connect() method (this bound address is the address from which the endpoint will recieve your connection). More...
 
const int buffer_size () noexcept
 Find out what buffer size is used by the various recv() methods. More...
 
rsocketbuffer_size (const size_t nbytes) noexcept
 Override the default buffer size (typically 1024) used by the various recv() methods. More...
 
rsocketbuffer_size_reset () noexcept
 Reset the default buffer size (typically 1024) used by the various recv() methods. More...
 
rsocketclose ()
 Close this rsocket. (If this rsocket was already closed, then calling this method additional times will have no effect, and will not cause exceptions to be thrown.) More...
 
int close_passive () noexcept
 Close this rsocket without throwing any exceptions (an error code is returned instead, which is useful while calling close_passive() from within a destructor). More...
 
rsocketconnect (const std::string address, const int port=0)
 Connect this socket to a specific endpoint (which may differ from this rsocket's address that was previously configured by the bind() method). More...
 
const bool debug () noexcept
 Find out whether debug mode is enabled. More...
 
const int debug (const bool debug_flag, std::FILE *fd=stderr) noexcept
 Debug mode. When debug mode is enabled, output is sent to stderr by default, unless a second parameter specifies a different file handle (e.g., stdout, or even a socket). More...
 
const int debug (const char *msg) noexcept
 Send the specified message as debug output (as long as debug mode is enabled; if disabled, no debug output will be sent). More...
 
const int debug (const std::string msg) noexcept
 Send the specified message as debug output (as long as debug mode is enabled; if disabled, no debug output will be sent). More...
 
const std::FILE * debug_fd () noexcept
 Find out which file descriptor/handle is used for debug output. More...
 
const int debug_fd (std::FILE *fd) noexcept
 Specify a different file descriptor/handle to use for debug output. More...
 
const std::string eol () noexcept
 Find out what the current EoL (End of Line) sequence is set to. More...
 
rsocketeol (const char *eol) noexcept
 Set EoL (End of Line) sequence. This sequence is used by recvline(), sendline(), and related functions, and it defaults to an empty string which means that the EoL sequence will be automatically detected on-the-fly. More...
 
rsocketeol (const std::string eol) noexcept
 Set EoL (End of Line) sequence. This sequence is used by recvline(), sendline(), and related functions, and it defaults to an empty string which means that the EoL sequence will be automatically detected on-the-fly. More...
 
rsocketeol_adoption (const bool flag) noexcept
 Configure EoL adoption policy for the recvline() method. By default, rsocket is configured with the EoL adoption policy enabled alongside an empty eol() sequence, which results in the default operation being that the EoL sequence automatically gets detected and updated internally upon the first use of the recvline() method. More...
 
rsocketeol_fix_printf (const bool flag) noexcept
 Configure EoL substitution policy for the printf(), printfline(), vprintf(), and vprintfline() methods. By default, rsocket substitutes printf's \n sequence with the EoL sequence (if defined), and this method can be used to disable this behaviour. More...
 
const int eol_index (const std::string buffer, int *with_eol_size) noexcept
 Finds the first instance of the EoL sequence and returns its offset (which is effectively the same as the size of the text, not including the characters that the EoL sequence is comprised of). More...
 
const bool eos (const int timeout=0)
 Find out if the stream is at its end and that this rsocket's internal buffer (if one had been set up by the recvline() method) is empty. This doesn't necessarily mean that the stream is closed; but rather that the endpoint just hasn't sent any more data (yet). More...
 
const std::shared_ptr< sockaddr_storage > getpeername ()
 Get peer name returns the address of the socket as a sockaddr_storage structure. More...
 
const std::string getpeername_ntop ()
 Get peer name returns the address of the socket as a std::string object. More...
 
const std::shared_ptr< sockaddr_storage > getsockname ()
 Get socket name returns the address of the socket as a "sockaddr_storage" structure. More...
 
const std::string getsockname_ntop ()
 Get socket name returns the name of the socket as a std::string object. More...
 
std::shared_ptr< group_req > getsockopt_group_req (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< group_source_req > getsockopt_group_source_req (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< icmp6_filter > getsockopt_icmp6_filter (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< in_addr > getsockopt_in_addr (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
int getsockopt_int (const int level, const int option)
 Get socket option details in the form of an integer. More...
 
std::shared_ptr< ip6_mtuinfo > getsockopt_ip6_mtuinfo (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< ip_mreq > getsockopt_ip_mreq (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< ip_mreq_source > getsockopt_ip_mreq_source (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< ipv6_mreq > getsockopt_ipv6_mreq (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< linger > getsockopt_linger (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
template<class T >
std::shared_ptr< T > getsockopt_other (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< sockaddr_in6 > getsockopt_sockaddr_in6 (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
std::shared_ptr< timeval > getsockopt_timeval (const int level, const int option)
 Get socket option details in the form of a structure. More...
 
u_char getsockopt_u_char (const int level, const int option)
 Get socket option details in the form of an unsigned character. More...
 
u_int getsockopt_u_int (const int level, const int option)
 Get socket option details in the form of an unsigned integer. More...
 
const std::string inet_ntop ()
 Get underlying socket's address as a std::string, for sockets in one of the supported families: More...
 
const bool is_buffered () noexcept
 Find out whether an internal read buffer was allocated (this is most likely triggered by an attempt to read a line of text). More...
 
const bool is_closed () noexcept
 Find out whether the underlying socket is not open (which may not be the same as specifically "closed" since a newly instantiated empty socket begins in a "not open" state despite the underlying socket not having been closed). More...
 
const bool is_connected () noexcept
 Find out whether the underlying socket is connected with/to an endpoint. More...
 
const bool is_endian_lsb () noexcept
 Find out whether the default byte order for this host is LSB (small endian). More...
 
const bool is_endian_msb () noexcept
 Find out whether the default byte order for this host is MSB (big endian). More...
 
const bool is_eol_adoption () noexcept
 Find out if the EoL adoption policy is enabled for the recvline() method (see the eol_adoption method to find out how the dynamically-detected EoL sequence gets adopted, and under what conditions). More...
 
const bool is_eol_fix_printf () noexcept
 Find out if the EoL substitution policy is enabled for the printf(), printfline(), vprintf(), and vprintfline() methods. More...
 
const bool is_open () noexcept
 Find out whether the underlying socket is open. More...
 
const bool is_tls () noexcept
 Find out whether encrypted communications is enabled or disabled. More...
 
const bool is_tls_client_mode () noexcept
 Find out whether TLS context is in TLS_CLIENT mode. More...
 
const bool is_tls_egress_okay () noexcept
 Find out whether egress from encryption (to unencrypted mode) is allowed. More...
 
const bool is_tls_exclusive () noexcept
 Find out whether encrypted communications is exclusive. More...
 
const bool is_tls_ingress_okay () noexcept
 Find out whether ingress to encryption (from unencrypted mode) is allowed. More...
 
const bool is_tls_server_mode () noexcept
 Find out whether TLS context is in TLS_SERVER mode. More...
 
const bool is_tls_sni () noexcept
 Find out whether SNI (Server Name Identifier) is enabled (configured, which implies that an internal callback function was also set up). More...
 
const bool is_tls_sni_match () noexcept
 Find out whether SNI (Server Name Identifier) was matched, which means that we're using one of the supplementary TLS certificates that are included in the associated rsocket_sni object as separate TLS contexts. More...
 
rsocketlisten (int backlog=0)
 Enable listening mode for this rsocket to prepare it to accept() new inbound connections. More...
 
std::string name () noexcept
 Find out what this rsocket's name is. More...
 
rsocketname (const std::string name) noexcept
 Specify a name for this rsocket. More...
 
std::string name_sni () noexcept
 Find out what this rsocket's actual TLS SNI hostname is. More...
 
std::shared_ptr< rsocket_ionet_io () noexcept
 Get socket I/O statistics from internally-tracked socket I/O counters. More...
 
std::string net_io (const char *format, size_t len=0, rsocket_io *addr=nullptr) noexcept
 Get socket I/O statistics from internally-tracked socket I/O counters as a pre-formatted std::string object. More...
 
rsocketnet_io_final (rsocket_io *addr) noexcept
 Where the destructor should save final I/O statistics before this rsocket's resources are completely freed/deallocated. More...
 
rsocketnet_io_update (rsocket_io *addr) noexcept
 Where the destructor should save current I/O statistics. More...
 
short poll (const short events=POLLIN, const int timeout=0, const bool timeout_behaviour=TIMEOUT_EXCEPTION)
 Poll the underlying socket using the poll() method for data that's ready for receiving (default), etc. More...
 
const uint16_t port () noexcept
 Get port number associated with underlying socket descriptor/handle. More...
 
short ppoll (const short events=POLLIN, const int tv_sec=0, const long tv_nsec=0, const sigset_t *sigmask=nullptr, const bool timeout_behaviour=TIMEOUT_EXCEPTION)
 Poll the underlying socket using the ppoll() method for data that's ready for receiving (default), etc. More...
 
short ppoll (const short events=POLLIN, const struct timespec *tmo_p=nullptr, const sigset_t *sigmask=nullptr, const bool timeout_behaviour=TIMEOUT_EXCEPTION)
 Poll the underlying socket using the ppoll() method for data that's ready for receiving (default), etc. More...
 
rsocketprintf (const char *format,...)
 Send a formatted string to the rsocket endpoint. More...
 
rsocketprintfline (const char *format,...)
 Send a formatted string to the rsocket endpoint, and append an EoL sequence. More...
 
std::vector< char > recv (const size_t nbytes=0, const int flags=0)
 Receive data from the endpoint into a std::vector<char> that is allocated on-the-fly. More...
 
std::vector< char > recv (std::vector< char > buf, const int flags=0)
 Receive data from the endpoint into the std::vector object supplied in the buf parameter. More...
 
char * recv_asciiz (const size_t nbytes=0, const int flags=0)
 Receive an ASCIIZ string from the endpoint, including the NULL terminator. More...
 
char recv_byte (const int flags=0)
 Receive one byte of data from the endpoint. More...
 
template<typename T >
recv_struct (const int flags=0)
 Receive a data structure from the endpoint. More...
 
uint16_t recv_uint16_lsb (const int flags=0)
 Receive one 16-bit unsigned integer of data in LSB (little endian) order from the endpoint. More...
 
uint16_t recv_uint16_msb (const int flags=0)
 Receive one 16-bit unsigned integer of data in MSB (big endian) order from the endpoint. More...
 
uint32_t recv_uint32_lsb (const int flags=0)
 Receive one 32-bit unsigned integer of data in LSB (little endian) order from the endpoint. More...
 
uint32_t recv_uint32_msb (const int flags=0)
 Receive one 32-bit unsigned integer of data in MSB (big endian) order from the endpoint. More...
 
uint64_t recv_uint64_lsb (const int flags=0)
 Receive one 64-bit unsigned integer of data in LSB (little endian) order from the endpoint. More...
 
uint64_t recv_uint64_msb (const int flags=0)
 Receive one 64-bit unsigned integer of data in MSB (big endian) order from the endpoint. More...
 
std::vector< char > recvfrom (const size_t nbytes, const int flags, struct sockaddr *from, socklen_t fromlen=sizeof(sockaddr))
 Receive data from a specific endpoint. More...
 
std::string recvline (const size_t nbytes=0, const int flags=0, long timeout=0)
 Receive a line of data from the endpoint, with the EoL character(s) removed. This is meant for binary data that isn't expected to always be plain text. More...
 
mmsghdr * recvmmsg (struct mmsghdr *mmsg, const unsigned int vlen=sizeof(mmsghdr), const int flags=0, struct timespec *timeout={0})
 Receive data in the form of an "mmsghdr" structure. More...
 
msghdr * recvmsg (msghdr *msg, const int flags=0)
 Receive data in the form of a "msghdr" structure. More...
 
std::vector< char > recvz (const size_t nbytes=0, const int flags=0)
 Receive data from the endpoint, and add a 0 (null) onto the end. This is useful when using the resulting std::vector<char> as an ASCIIZ string. More...
 
rsocketsend (const char *msg, size_t len=0, const int flags=0)
 Send data in the form of a C-string to the endpoint. More...
 
rsocketsend (const std::string msg, const int flags=0)
 Send data in the form of a std::string to the endpoint. More...
 
rsocketsend (const std::vector< char > msg, const int flags=0)
 Send data in the form of a std::vector<char> to the endpoint. More...
 
rsocketsend_asciiz (const char *msg, const int flags=0)
 Send data in the form of an ASCIIZ string to the endpoint, including the terminating NULL character. More...
 
rsocketsend_byte (const char value, const int flags=0)
 Send one byte of data to the endpoint. More...
 
rsocketsend_eol (const int flags=0)
 Send the EoL sequence to the endpoint. More...
 
template<typename T >
rsocketsend_struct (const T value, const int flags=0)
 Send one byte of data to the endpoint. More...
 
rsocketsend_uint16_lsb (const uint16_t value, const int flags=0)
 Send one 16-bit unsigned integer of data in LSB (little endian) order to the endpoint. More...
 
rsocketsend_uint16_msb (const uint16_t value, const int flags=0)
 Send one 16-bit integer of data in MSB (big endian) order to the endpoint. More...
 
rsocketsend_uint32_lsb (const uint32_t value, const int flags=0)
 Send one 32-bit unsigned integer of data in LSB (little endian) order to the endpoint. More...
 
rsocketsend_uint32_msb (const uint32_t value, const int flags=0)
 Send one 32-bit unsigned integer of data in MSB (big endian) order to the endpoint. More...
 
rsocketsend_uint64_lsb (const uint64_t value, const int flags=0)
 Send one 64-bit unsigned integer of data in LSB (little endian) order to the endpoint. More...
 
rsocketsend_uint64_msb (const uint64_t value, const int flags=0)
 Send one 64-bit unsigned integer of data in MSB (big endian) order to the endpoint. More...
 
rsocketsendline (const std::string msg=std::string(), const int flags=0)
 Send data in the form of a std::string to the endpoint, with an EoL sequence appended. More...
 
rsocketsendmmsg (struct mmsghdr *mmsg, const unsigned int vlen=sizeof(mmsghdr), const int flags=0)
 Send data in the form of a "mmsghdr" structure to a specific endpoint. More...
 
rsocketsendmsg (const struct msghdr *msg, const int flags=0)
 Send data in the form of a "msghdr" structure to a specific endpoint. More...
 
rsocketsendto (const char *msg, const size_t len, const int flags, const struct sockaddr *to, socklen_t tolen=sizeof(sockaddr))
 Send data in the form of a C-string to a specific endpoint. More...
 
rsocketsendto (const std::string msg, const int flags, const struct sockaddr *to, socklen_t tolen=sizeof(sockaddr))
 Send data in the form of a std::string to a specific endpoint. More...
 
rsocketsendz (const char *msg, const int flags=0)
 Send data in the form of an ASCIIZ string to the endpoint. The terminating NULL character won't be transmitted. More...
 
rsocketsendzto (const char *msg, const int flags, const struct sockaddr *to, socklen_t tolen=sizeof(sockaddr))
 Send data in the form of an ASCIIZ string to a specific endpoint. The terminating NULL character won't be transmitted. More...
 
rsocketsetsockopt (const int level, const int option, const group_req &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const group_source_req &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const icmp6_filter &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const in_addr &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const int value)
 Set socket option to the specific integer. More...
 
rsocketsetsockopt (const int level, const int option, const ip6_mtuinfo &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const ip_mreq &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const ip_mreq_source &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const ipv6_mreq &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const linger &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const sockaddr_in6 &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const timeval &value)
 Set socket option to the specific structure. More...
 
rsocketsetsockopt (const int level, const int option, const u_char value)
 Set socket option to the specific unsigned character. More...
 
rsocketsetsockopt (const int level, const int option, const u_int value)
 Set socket option to the specific unsigned integer. More...
 
rsocketshutdown (const int how=SHUT_RDWR)
 Shut down the underlying socket, partially or fully. More...
 
const bool sockatmark ()
 Find out whether the underlying socket is at the out-of-band (OOB) mark. More...
 
rsocketsocket (const int family, const int type=SOCK_STREAM, const int protocol=PF_UNSPEC)
 Complete the configuration of an rsocket that was previously initialized without any parameters (a.k.a., an "empty rsocket"). More...
 
const int socket_family () noexcept
 Get underlying socket family/domain constant (SO_DOMAIN). More...
 
const int socket_fd () noexcept
 Get underlying socket descriptor/handle. More...
 
rsocketsocket_fd (const int new_socket_fd)
 Set underlying socket descriptor/handle (to one that is presumed to be open). More...
 
const int socket_protocol () noexcept
 Get underlying socket protocol constant (SO_PROTOCOL). More...
 
const int socket_type () noexcept
 Get underlying socket type constant (SO_TYPE). More...
 
std::shared_ptr< timeval > timeout ()
 Find out what the read timeout is set to on the current socket. More...
 
rsockettimeout (const int tv_sec=0, const long tv_usec=0)
 Set the recv timeout on the current socket. More...
 
rsockettimeout (const struct timeval tv)
 Set the recv timeout on the current socket. More...
 
long timeout_recvline ()
 Find out what the read timeout is set to when using the recvline() method. More...
 
rsockettimeout_recvline (const long timeout)
 Set the read timeout for the recvline() method when that method's timeout parameter is set to 0. More...
 
rsockettls (const bool status=true, const int flags=TLS_FLAGS::TLS_DEFAULT)
 Enable or disable encrypted communications (from the OpenSSL library). More...
 
SSL_CTX * tls_ctx () noexcept
 Return the current TLS context (multiple TLS contexts are supported, although typically needed to support SNI with inbound connections). More...
 
rsockettls_ctx (rsocket *rtemplate, const int flags=TLS_FLAGS::TLS_DEFAULT)
 Copy the source rsocket's TLS context map and add it to this rsocket's collection; or, if the source doesn't have any TLS contexts and this rsocket doesn't have any TLS contexts in its collection, then initialize TLS and instantiate a new TLS context. In either scenario, the source rsocket will be treated as a template as all TLS flags duplicated to enable encrypted socket I/O for use in this rsocket(). More...
 
rsockettls_ctx (SSL_CTX *ctx, const int flags=TLS_FLAGS::TLS_DEFAULT)
 Initialize TLS and instantiate a TLS context, and add it to this rsocket's current collection of TLS contexts, and set it as the currently active TLS context (so that a certificate chain and private key may be added to it). More...
 
rsockettls_ctx_check_privatekey ()
 Check the private key it to ensure it's consistent with the corresponding TLS certificate chain. More...
 
rsockettls_ctx_use_certificate_chain_and_privatekey_files (const char *chain_file, const char *key_file)
 Load a TLS certificate chain and private key in PEM format from text files and use them in the TLS context. More...
 
rsockettls_ctx_use_certificate_chain_and_privatekey_files (const std::string chain_file, const std::string key_file)
 Load a TLS certificate chain and private key in PEM format from text files and use them in the TLS context. More...
 
rsockettls_ctx_use_certificate_chain_and_privatekey_pems (const char *cert_pem_data, const char *key_pem_data, size_t cert_len=0, size_t key_len=0, const bool random_fill=true)
 Load a TLS certificate chain and a TLS private key in PEM format from memory and use them in the TLS context. More...
 
rsockettls_ctx_use_certificate_chain_file (const char *file)
 Load a TLS certificate chain in PEM format from a text file and use it in the TLS context. More...
 
rsockettls_ctx_use_certificate_chain_file (const std::string file)
 Load a TLS certificate chain in PEM format from a text file and use it in the TLS context. More...
 
rsockettls_ctx_use_certificate_chain_pem (const char *pem_data, size_t len=0, const bool random_fill=true)
 Load a TLS certificate chain in PEM format from memory and use it in the TLS context. More...
 
rsockettls_ctx_use_privatekey_file (const char *file)
 Load a TLS private key in PEM format from a text file and use it in the TLS context. More...
 
rsockettls_ctx_use_privatekey_file (const std::string file)
 Load a TLS private key in PEM format from a text file and use it in the TLS context. More...
 
rsockettls_ctx_use_privatekey_pem (const char *pem_data, size_t len=0, const bool random_fill=true)
 Load a TLS private key in PEM format from memory and use it in the TLS context. More...
 
rsockettls_do_handshake ()
 Initiate the TLS handshake with the endpoint (which is presumed to be a server). This method makes it easier to support application-level commands such as STARTTLS (which are implemented in protocols like SMTP, POP3, and IMAP4). More...
 
const SSL * tls_fd () noexcept
 Get OpenSSL's TLS structure. More...
 
rsocket_snitls_sni () noexcept
 Return the current rsocket_sni object that this rsocket will use when accepting incoming encrypted connections. More...
 
rsockettls_sni (rsocket_sni *sni) noexcept
 Set the current rsocket_sni object that this rsocket will use when accepting incoming encrypted connections. More...
 
rsocketvprintf (const char *format, va_list args)
 Send a formatted string to the rsocket endpoint. More...
 
rsocketvprintfline (const char *format, va_list args)
 Send a formatted string to the rsocket endpoint, and append an EoL sequence. More...
 

Static Public Member Functions

static int family (const std::string address, const int preferred_family=AF_UNSPEC)
 Find out what the specified IP address string's family (SO_DOMAIN) is. More...
 
static sockaddr * getsockaddr (const sockaddr_storage *sa)
 Get specified "sockaddr_storage" structure's address as a "sockaddr" structure, for sockets in one of the supported families: More...
 
static const std::string inet_ntop (sockaddr_storage *sa)
 Get specified "sockaddr_storage" structure's address as a std::string, for sockets in one of the supported families: More...
 
static std::shared_ptr< sockaddr_storage > mk_sockaddr_storage (const char *node_name, const char *service_name=nullptr, const addrinfo *hints=nullptr)
 Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure. More...
 
static std::shared_ptr< sockaddr_storage > mk_sockaddr_storage (const char *node_name, const u_int16_t service_name, const addrinfo *hints=nullptr)
 Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure. More...
 
static std::shared_ptr< sockaddr_storage > mk_sockaddr_storage (const std::string node_name, const std::string service_name, const addrinfo *hints=nullptr)
 Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure. More...
 
static std::shared_ptr< sockaddr_storage > mk_sockaddr_storage (const std::string node_name, const u_int16_t service_name, const addrinfo *hints=nullptr)
 Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure. More...
 
static std::string to_mac (const void *addr) noexcept
 Convert a 48-bit integer to a machine address in the form of xx:xx:xx:xx:xx:xx where every instance of xx is a hexadecimal representation of each respective 8-bit byte portion. More...
 
static std::string to_node (const void *addr) noexcept
 Convert a 48-bit integer to a node address in the form of xxxx:xxxx:xxxx where every instance of xxxx is a hexadecimal representation of each respective 16-bit word portion. More...
 

Friends

class rsocket_group
 

Detailed Description

This rsocket class provides an easy-to-use and thoroughy-implemented object-oriented socket I/O interface for C++, intended to make socket I/O programming (with or without TLS encryption) easier and more enjoyable.

Here's a short list of benefits that are helpful in developing high quality code that's consistent-and-reliable, and improves overall productivity:

  • eliminating the need to repeatedly write blocks of code that check for errors, by throwing exceptions instead (see randolf::rex::rex class for details and the long list of exceptions that are supported)
  • eliminating the need to track socket descriptors
  • eliminating the need to handle encrypted I/O separately (most functions)
  • eliminating the need to manage memory for many common structures used to interface with socket options, etc.
  • eliminating the need to record socket I/O statistics with every call to underlying socket I/O functions (see randolf::rsocket_io for details)
  • text-line reading/writing with an adapative approach (invented by Randolf Richardson in the 1980s for a custom BBS software project) to automatically detect EoL (End-of-Line) character sequences (unless the developer provides a specific sequence via an eol method) that can determine whether an endpoint is sending Linux/UNIX (standard), MacOS, DOS CR/LF, or even broken LF/CR (reverse of DOS) EoL sequences
  • transparent support for encryption with many additional features, including STARTTLS, ingress/egress policy enforcement, and SNI
  • eliminating the complexity of handling events with poll(), select(), and related functions (see the randolf::rsocket_mux class for details)
  • providing a variety of other useful features that make it easier to communicate with socket endpoints, such as receiving/sending an entire structure via a single call to the new-and-specialized recv_struct or send_struct methods, respectively

An rsocket is either the endpoint that our underlying socket will connect to, or it's the server daemon that our underying socket will listen() to and accept() [inbound] connections from.

Getting started with a few simple examples

This is an example of connecting to an HTTP server, using the "GET" command to request the home page (using HTTP/1.0), then receiving-and-displaying the resulting web page's contents via STDOUT (or sending an error message to STDERR). Finally, we exit with an EXIT_SUCCESS (or EXIT_FAILURE) code.

#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_INET, SOCK_STREAM, IPPROTO_TCP);
r.connect("www.example.com", 80);
r.sendline("GET / HTTP/1.0");
r.sendline("Host: www.example.com");
r.sendline("Connection: close");
r.send_eol();
while (r.opened()) {
std::cout << r.recvline(0, MSG_WAITALL) << std::endl;
} // -x- while data -x-
r.close();
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
const char * what() const noexcept
Find out what the reason (usually the error code, e.g., EAGAIN) was for this exception to be thrown.
Definition: rex:286
Exception group that can be used to catch exceptions thrown for errors returned from POSIX fuctions (...
Definition: rex:295
This rsocket class provides an easy-to-use and thoroughy-implemented object-oriented socket I/O inter...
Definition: rsocket:365

Parameter stacking is supported (with methods that return rsocket*); in this example, notice that semicolons (";") and "r." references are omittted (when compared with the above):

#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_INET, SOCK_STREAM, IPPROTO_TCP);
r.connect("www.example.com", 80)
->sendline("GET / HTTP/1.0")
->sendline("Host: www.example.com")
->sendline("Connection: close")
->send_eol();
while (r.opened()) {
std::cout << r.recvline(0, MSG_WAITALL) << std::endl;
} // -x- while data -x-
r.close();
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
Features

This is meant to be a comprehensive socket class for C++, which is intended to make socket I/O coding easier for developers with some key features:

  • easy conversion from C-style POSIX sockets due to API consistency
  • transparent TLS support (OpenSSL dependency)
    • keys and certificate chains can also be loaded from memory
    • SNI support (see the rsocket_sni class for more information)
  • underlying socket handle is accessible (via the socket_fd() method)
  • socket options are easier to get and to set
    • sensible support for future or unknown socket options
  • errors are presented as ~100 separate exception classes: rex::rex
    • one parent exception class makes it easier to catch all socket errors
    • a few exceptions groups are also provided to catch groups of errors
  • new buffers are returned as std::shared_ptr's to eliminate memory leaks
  • constructors with sensible defaults help to simplify coding
  • documentation includes code samples (with #include lines as needed)
  • debug output with helpful output (and option to set output file handle)
  • low-overhead is considered (this is why there's a bit more overloading)
  • thread-safety is noted where it is absolutely available (or where some caution is warranted)
  • can send ASCIIZ (C-strings) without needing to specify string length
  • can send std::string (which tracks its own string length)
  • each socket can optionally have a name

Additional features that are not part of the typical POSIX standard, but deserve special mention because they are needed so often:

  • easy access to internal I/O counters (see rsocket_io for details)
    • your rsocket_io structure can be updated automatically by rsocket's destructor after underlying socket is closed (see net_io_final() method for details)
  • printf() // Formatted strings (with automatic EoL sequence substitution)
  • recvline(), sendline() // ASCII text line I/O operations
    • class-wide configurable newline sequence (defaults to autodetect)
  • recv_asciiz(), send_asciiz() // ASCIIZ string I/O operations
  • recv_byte() , send_byte() // 8-bit byte operations (LSB/MSB is N/A)
  • recv_struct(), send_struct() // Multi-byte operations
  • recv_uint16(), send_uint16() // 16-bit operations with LSB/MSB variants
  • recv_uint32(), send_uint32() // 32-bit operations with LSB/MSB variants
  • recv_uint64(), send_uint64() // 64-bit operations with LSB/MSB variants

Some advanced features are planned that exceed what the basic socket I/O functions provide, but are also needed:

  • rsocket_group class for grouping rsockets (and automatic inclusion by accept() and accept4() methods; this may be a different group from whichever group the parent rsocket is in, if it's even in one)
    • option to send data to all rsocket objects in the rsocket_group
    • with support from the rsocket_mux class
    • automatic naming policies (possibly like net_io() formatting style)
  • recv_uint128()/send_uint128() // 128-bit operations w/ LSB/MSB variants
  • recv_uint(n)/send_uint(n) where "n" specifies the number of bits (which must be a multiple of 8), with LSB/MSB variants
  • auto-detection of inbound TLS connection (this is turned off by default)
    • This is not the same as STARTTLS (an application-level command, for which the tls_do_handshake() method will likely be used)
  • simple timing tracking options using timing_start() and timing_stop() methods, the results of which can be retrieved with timing_get() or a similarly-named group of methods

Other features that are not a high priority:

  • internal support for portability to MS-Windows (this is a big headache that I know will be time-consuming because Windows Sockets is not the same as the standard POSIX sockets APIs that are used by Linux, UNIX, MacOS, and pretty much all other Operating Systems. This means that this really isn't a high priority for me without sufficient demand and sufficient funding so I can commit my time without missing mortgage payments, student loan payments {for my kids}, living expenses, etc.)
Use case

Using the C interface, the programming must check for errors by testing the response codes (most of which are consistent, with a few subtle outliers), which leads to a lot of additional error-checking code with the potential for unintended errors (a.k.a., bugs). This style is necessary in C, but with C++ the way to handle errors is with exceptions, so I created this rsocket class to handle all these tedious details behind-the-scenes and, for any socket errors, to generate exceptions so that source code can be greatly simplified (and, as a result, also easier to read and review).

Pre-allocating buffers is also handled internally, which is particularly useful when making repeated calls to recv() and related methods. These methods return std::shared_ptr<structure > (a C++ smart pointer that aids in the prevention of resource leaks) or std::vector<char> (resized to the actual number of bytes received) as appropriate which eliminates the need to track size_t separately.

Conventions
Lower-case letter "r" is regularly used in partial example code to represent an instantiated rsocket object.

An ASCIIZ string is a C-string (char* array) that includes a terminating null (0) character at the end.

Notes

I use the term "ASCIIZ string" to indicate an array of characters that's terminated by a 0 (a.k.a., null). Although this is very much the same as a C-string, the difference is that in many API functions a C-string must often be accompanied by its length value. When referring to an ASCIIZ string, I'm intentionally indicating that the length of the string is not needed because the string is null-terminated. (This term was also commonly used in assembly language programming in the 1970s, 1980s, and 1990s, and as far as I know is still used by machine language programmers today.)

UTF-8 works without any problems as it is backward-compatible to 8-bit ASCII, and because std::string uses 8-bit bytes to store strings internally. Just keep in mind that the manipulation of UTF-8 substrings will require working with UTF-8 codepoints that may consume one or more bytes, which is beyond the scope of the impartial (to UTF-8 and ASCII) functionality that this rsocket class provides.

UTF-8 newline codepoints NEL (c2 85), LS (e2 80 a8), and PS (e2 80 a9) garner no special handling at this time - unlike CR/LF (0d/0a) - and are merely treated as non-newline codepoints at this time. There is a possibility of adding support for this in the future, but additional research and careful planning are required to make sure this works properly. What is most likely is that some UTF-8 flags will be added to support each of these (which will probably be disabled by default) that will be integrated into the readline() methods. This also depends on how widely used these particular codepoints are used, and pending further research to determine whether these really are supposed to be used functionally as newlines...

Examples of two UTF-8 codepoints that are not functional, but which a few people have mistakenly assumed are functional:

  • CR = superscript "C" with subscript "R" (e2 90 9d)
  • NL = superscript "N" with subscript "L" (e2 90 a4)

The above are designed as special characters to represent the Carriage-Return and New-Line respectively on ASCII character reference charts, which were used primarily by IBM in the 1970s and 1980s for instruction manuals and other documentation, and on some keyboard overlays.

Background

I created this class to make it easier to write internet server daemons. I started out using C-style socket functions (because C++ doesn't come with a socket class), but I found that I didn't enjoy mixing something as important and detailed as socket I/O in a procedural way into the object-oriented paradigm that C++ provides.

After looking for existing solutions (none of which served as comprehensive replacements for socket I/O), I embarked on creating the rsocket class, and then I began to understand why this probably hadn't been done – it's a massive untertaking, primarily because there are a lot of functions that are needed to handle socket I/O. Further, [at the time of this writing] the sockaddr_storage structure wasn't as widely used as it should be, and so information about it tended to be scarce, incomplete, or incorrect (further research was required to understand this properly, which was worthwhile).

Moving error codes into exceptions is also a major effort because they are so diverse and plentiful, and there are so many ways that things can go wrong at various stages. There are a few outlier functions that require slightly different approaches to error handling due to subtly different rules for handling their errors, and so even the exception-generation wasn't as straight-forward as one might optimistically expect it to be, but this is one of the many benefits of the object-oriented programming pardigm because a consistent interface can be provided due to handling edge cases internally.

So, I dedicated time to make this work, and with the intention of making it an open source project once I got it into a state that's ready for the general public. This required putting my other C++ projects on hold, which was fine because they didn't have strict deadlines and using this socket class in them will speed up development in the long-term anyway, so it's clearly worth the effort to me.

My background in programming began when I was a young child, teaching myself BASIC and then machine language (when I found BASIC to be too limited) before moving on to other languages like Perl and Java many years later. Eventually I circled around to C (which I chose to learn the hard way by writing some PostgreSQL extensions) and then C++ a few years after that. I have a lot of experience with socket communications, including fully-featured DNS resolver library code in machine language for Novell's NetWare that used C calling conventions and supported varargs, which worked well for the few developers who needed or wanted it.

History
  • 2022-Nov-09 v1.00 Initial version
  • 2022-Nov-26 v1.00 Moved exception handling to a separate class
  • 2022-Nov-28 v1.00 Completed readline/send functionality
  • 2022-Dec-03 v1.00 Added endianness transparency
  • 2022-Dec-04 v1.00 Added printf() support
  • 2022-Dec-24 v1.00 Added socket MUXing
  • 2023-Feb-22 v1.00 Added TLS/SSL support
  • 2023-Mar-10 v1.00 Added TLS-SNI support
  • 2023-Apr-19 v1.00 Added TLS certificate loading from memory
  • 2023-May-24 v1.00 Added support for clang++ compilation
  • 2023-Jun-09 v1.00 Improvements to dynamic internal read buffering
  • 2023-Oct-31 v1.00 Improvements to various classes
  • 2024-Feb-21 v1.00 Added is_buffered() method
  • 2024-Mar-31 v1.00 Completed recvline (implemented a work-around for a subtle SSL_peek failure to extract additional data when a user at an end-point is communicating with "icanon" mode enabled)
Version
1.00
Author
Randolf Richardson

Member Enumeration Documentation

◆ TIMEOUT_BEHAVIOUR

Optional flags used with various methods to determine whether they will throw an randolf::rex::xETIMEDOUT exception or merely return a nullptr, an empty set, or a 0 (zero) when a timeout duration elapses.

Note
You'll know when this is an option because the method will support this.
Enumerator
TIMEOUT_EXCEPTION 

Indicate that an randolf::rex::xETIMEDOUT exception should be thrown when the timeout duration elapses.

TIMEOUT_EMPTY 

Indicate that a nullptr, an empty set, or a 0 (zero) should be returned when the timeout duration elapses.

TIMEOUT_NULL 

Indicate that a nullptr, an empty set, or a 0 (zero) should be returned when the timeout duration elapses.

TIMEOUT_ZERO 

Indicate that a nullptr, an empty set, or a 0 (zero) should be returned when the timeout duration elapses.

◆ TLS_FLAGS

Optional flags used with rsocket's tls() and tls_ctx() methods to specify relevant policies/semantics.

Enumerator
TLS_DEFAULT 

The TLS_DEFAULT flag isn't necessary, but it's included here for completeness as it accomodates programming styles that prefer to emphasize when defaults are being relied upon.

TLS_EXCLUSIVE 

Only encrypted connections are permitted, initially, and all attempts to begin with unencrypted connections will consistently fail.

Encrypted connections must begin with a cryptographic handshake packet, or else the connection will be rejected as due to being reasonably assumed to be "not encrypted."

Postcondition
If this flag isn't set, an application-level mechanism can be used to upgrade to TLS encryption (this is common with connections that begin unencrypted, and issue a proprietary command {such as the STARTTLS command in SMTP} to upgrade to TLS later on {of which the tls() method is used to affect an ingress; see the TLS_NO_INGRESS flag for additional information}).
Note
Creating an exclusively unencrypted connection is accomplished by not initializing TLS.
See also
tls()
TLS_NO_EGRESS to prevent support for application-level downgrades to unencrypted connections
TLS_NO_INGRESS 

Mid-stream upgrades to encrypted connections are not permitted (e.g., via application-level initiations like the STARTTLS command as seen in SMTP), which will also cause calls to the tls() method to fail fast after plain non-encrypted data has already been sent or received.

Precondition
This flag is not necessary when the TLS_EXCLUSIVE flag is set.
See also
is_tls_ingress_okay()
tls_do_handshake()
TLS_NO_EGRESS
TLS_NO_EGRESS 

Mid-stream downgrades to unencrypted connections are not permitted (e.g., via application-level initiations like a hypothetical STOPTLS command as seen in FTPS), which will also cause calls to the tls() method to fail fast after encrypted data has already been sent or received.

Precondition
This flag may be combined with the TLS_EXCLUSIVE flag to prevent a connection from being downgraded programatically.
Note
Although egress to an unencrypted connection doesn't occur automatically (since egress can only be affected programatically to support commands at the application level), this flag is useful to prevent third-party code from downgrading an encrypted rsocket to unencrypted.
Warning
Supporting unencrypted communications is strongly discouraged over public networks (e.g., the internet) because unencrypted streams are trivially susceptible to man-in-the-middle attacks that can alter the contents of the data in both directions (which is a particularly dangerous prospect for sending/receiving sensitive information).
See also
is_tls_egress_okay()
TLS_NO_INGRESS
TLS_CLIENT 

This is a convenience flag that provides an option for developers to be more clear in their use of the tls() and tls_ctx() methods to indicate intent to rely on what is already the default.

See also
tls_do_handshake()
TLS_SERVER
TLS_SERVER 

Indicates that this rsocket will be for a server daemon, and to initialize a new TLS context (when one isn't being provided) using OpenSSL's TLS_server_method() function instead of OpenSSL's TLS_client_method() function (the latter is the default because most code is anticipated to be client-oriented).

Attention
Setting the CLIENT/SERVER flag incorrectly will typically cause the following error that's difficult to track down, which is usually triggered by calling accept, accept4(), or connect(), and so I hope that including this information here in this documentation will be helpful:
error:140C5042:SSL routines:ssl_undefined_function:called a function you should not call

The absence of this flag has the same effect as specifying the TLS_CLIENT flag.

See also
TLS_CLIENT

Constructor & Destructor Documentation

◆ rsocket() [1/3]

randolf::rsocket::rsocket ( )
inlinenoexcept

Instantiate an empty rsocket without opening said socket, and without throwing any exceptions.

Instantiating an empty rsocket is particularly useful for header-file definitions since exceptions can't be handled outside of subroutines, and it's also useful for enabling debug() mode before setting the socket's configuration with one of the socket() methods; for example:

randolf::rsocket r; // Empty rsocket (empty / incomplete initialization)
r.debug(true); // Enable debug mode
r.socket(...); // Required to complete rsocket initialization
const bool debug() noexcept
Find out whether debug mode is enabled.
Definition: rsocket:1971
rsocket * socket(const int family, const int type=SOCK_STREAM, const int protocol=PF_UNSPEC)
Complete the configuration of an rsocket that was previously initialized without any parameters (a....
Definition: rsocket:6889
Notes

The built-in defaults, when not provided, are as follows ("family" is also known as the "communication domain"):

  • family = AF_INET
  • type = SOCK_STREAM
  • protocol = PF_UNSPEC

You will need to use one of the socket(...) methods to specify socket details after defining rsocket objects with empty constructors so that you can catch runtime exceptions. (This also provides you with an option to enable debug mode during runtime prior to attempting to open an rsocket.)

Examples
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
randolf::rsocket r; // <-- Empty rsocket initialization (no exceptions)
int main(int argc, char *argv[]) {
try {
r.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // <-- Required to complete rsocket initialization
r.setsockopt(SOL_SOCKET, SO_REUSEADDR, true);
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
rsocket * setsockopt(const int level, const int option, const int value)
Set socket option to the specific integer.
Definition: rsocket:6607
rsocket * close()
Close this rsocket. (If this rsocket was already closed, then calling this method additional times wi...
Definition: rsocket:1866
See also
rsocket()
socket()
socket_family()
socket_fd()
socket_protocol()
socket_type()

◆ rsocket() [2/3]

randolf::rsocket::rsocket ( const rsocket rtemplate,
const bool  flag_create_socket = true 
)
inline

Instantiate an rsocket based on a minimal subset of the settings in the specified rsocket (using it as a template), without actually opening a socket, and therefore also without throwing any exceptions.

Note
This constructor does not suffice as a full clone()-like operation, and is minimal because it's used internally by the accept() and accept4() methods.

Details that are absorbed from the template/source rsocket (which eliminates the need to assign, set, and configure various parameters (TLS and TLS SNI parameters will be copied in a passive way by default):

  • Socket family (SO_DOMAIN)
  • Socket type (SO_TYPE)
  • Socket protocol (SO_PROTOCOL)
  • TLS details (status, context {which includes loaded certificates}, policies specified with TLS_FLAGS, etc.)
  • EoL details
  • TLS context (you'll still need to call tls_ctx(r->tls_ctx()))
  • TLS SNI map (you'll still need to call tls_sni(r->tls_sni()))
Postcondition
The TLS Context will not be initialized because it needs a real socket to draw from. If using TLS, you'll need to use the tls() method after the underlying socket has been initiated.

When flag_create_socket is set to FALSE, no exceptions will be thrown.

See also
rsocket()
socket()
socket_family()
socket_fd()
socket_protocol()
socket_type()
Parameters
rtemplateSource rsocket object to use as a template to absorb settings from
flag_create_socketTRUE = create a new socket handle (default)
FALSE = don't create a new socket because a new one will be assigned or created later (all variants of the accept() methods do this)

◆ rsocket() [3/3]

randolf::rsocket::rsocket ( const int  family,
const int  type = SOCK_STREAM,
const int  protocol = PF_UNSPEC 
)
inline

Instantiate an rsocket with IP/host address and [optional] port number.

This is either the endpoint that our underlying socket will be connecting to, or it's the local address of the server daemon that our socket will listen() to and accept() inbound connections from.

Notes

The built-in defaults, when not provided, are as follows ("family" is also known as the "communication domain"):

  • family = AF_INET
  • type = SOCK_STREAM
  • protocol = PF_UNSPEC

The socket() methods do the same work as the constructors with matching arguments, and are provided as convenience methods intended to augment empty rsocket constructors used in header files, but do require an address to be specified (for protocols that need port numbers, such as TCP or UDP, a "port" number also needs to be specified since the default port 0 will result in the dynamic allocation of a port number by the system).

For UNIX domain sockets use family AF_UNIX, type SOCK_STREAM, and protocol IPPROTO_IP when instantiating or opening an rsocket.

Examples
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_INET, SOCK_STREAM, IPPROTO_TCP); // <-- Same as socket() method
r.setsockopt(SOL_SOCKET, SO_REUSEADDR, true);
r.bind("127.0.0.1", 32768);
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
Exceptions
randolf::rex::xEACCESElevated access is needed to open this socket
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xEINVALProtocal family invalid or not available
randolf::rex::xEINVALInvalid flags in type
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENFILESystem-wide maximum open files limit reached
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xEPROTONOSUPPORTSpecified type or protocol is not supported within the specified family (a.k.a., communication domain)
See also
rsocket()
socket()
Parameters
familyCommunication domain; usually one of:
AF_INET (IPv4)
AF_INET6 (IPv6)
AF_UNIX (UNIX domain sockets)
typeCommunication semantics; usually one of:
SOCK_STREAM (common for TCP)
SOCK_DGRAM (common for UDP)
protocolNetwork protocol; usually one of:
IPPROTO_TCP
IPPROTO_UDP
IPPROTO_IP
PF_UNSPEC (auto-detect)

◆ ~rsocket()

randolf::rsocket::~rsocket ( )
inlinenoexcept

Destructor, which closes any underlying sockets, frees any TLS structures that were allocated by OpenSSL, and performs any other necessary clean-up before finally copying the I/O statistics to a designated structure (if one was specified with the net_io_final() method).

Attention
Developers should take care to check that the rsocket_io::is_final flag is set to TRUE prior to relying on the results of the rsocket_io data since there's no guarantee that the destructor will necessarily be executed in a timely manner (this flag is set last, after all other statistics are copied into the structure while in a mutex-locked state).
See also
net_io_final()

Member Function Documentation

◆ accept()

rsocket* randolf::rsocket::accept ( )
inline

Accept new [inbound] socket connetions. (This is typically used in a loop.)

Precondition
The resulting rsocket object is created before the actual call to the accept() function.
Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Postcondition
To prevent resource leaks, the resulting rsocket needs to be deleted after it's no longer needed.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNABORTEDThe connection was aborted
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEHOSTDOWNHost is down or its network is disconnected
randolf::rex::xEHOSTUNREACHNo route to host
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALSocket is not in listen() mode or the length of the address is invalid
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENETDOWNNetwork is disconnected or router is down
randolf::rex::xENETUNREACHNo route to network
randolf::rex::xENFILESystem-wide maximum open files limit reached
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENONETRequested host is not reachable on the network
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOSRSystem ran out of stream resources
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPERMConnection forbidden/denied by firewall rules
randolf::rex::xEPROTOProtocol error
randolf::rex::xEPROTONOSUPPORTSpecified type or protocol is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xERESTARTSYSUsed in back-end tracing to indicate that a system call is restartable and can be intercepted-and-redirected (there is no need to catch this exception unless you are an advanced developer, in which case you likely still won't need to catch it in code at this level)
randolf::rex::xESOCKTNOSUPPORTSpecified socket type is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xETIMEDOUTTimeout period elapsed
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and no inbound connections are waiting
Returns
Newly-created rsocket object representing the connection received
See also
accept_sp()
accept4()
accept4_sp()
listen

◆ accept_sp()

std::shared_ptr<rsocket> randolf::rsocket::accept_sp ( )
inline

Accept new [inbound] socket connetions. (This is typically used in a loop.)

Precondition
The resulting rsocket object is created before the actual call to the accept() function.
Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Postcondition
The resulting rsocket is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNABORTEDThe connection was aborted
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEHOSTDOWNHost is down or its network is disconnected
randolf::rex::xEHOSTUNREACHNo route to host
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALSocket is not in listen() mode or the length of the address is invalid
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENETDOWNNetwork is disconnected or router is down
randolf::rex::xENETUNREACHNo route to network
randolf::rex::xENFILESystem-wide maximum open files limit reached
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENONETRequested host is not reachable on the network
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOSRSystem ran out of stream resources
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPERMConnection forbidden/denied by firewall rules
randolf::rex::xEPROTOProtocol error
randolf::rex::xEPROTONOSUPPORTSpecified type or protocol is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xERESTARTSYSUsed in back-end tracing to indicate that a system call is restartable and can be intercepted-and-redirected (there is no need to catch this exception unless you are an advanced developer, in which case you likely still won't need to catch it in code at this level)
randolf::rex::xESOCKTNOSUPPORTSpecified socket type is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xETIMEDOUTTimeout period elapsed
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and no inbound connections are waiting
Returns
Newly-created rsocket object representing the connection received, wrapped in std::shared_ptr (a C++ smart pointer)
See also
accept()
accept4()
accept4_sp()
listen

◆ accept4()

rsocket* randolf::rsocket::accept4 ( const int  flags = 0)
inline

Accept new [inbound] socket connetions, with socket flags specified. (This is typically used in a loop.)

Precondition
The resulting rsocket object is created before the actual call to the accept4() function.
Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Postcondition
To prevent resource leaks, the resulting rsocket needs to be deleted after it's no longer needed.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNABORTEDThe connection was aborted
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEHOSTDOWNHost is down or its network is disconnected
randolf::rex::xEHOSTUNREACHNo route to host
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALSocket is not in listen() mode or the length of the address is invalid
randolf::rex::xEINVALInvalid value in flags
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENETDOWNNetwork is disconnected or router is down
randolf::rex::xENETUNREACHNo route to network
randolf::rex::xENFILESystem-wide maximum open files limit reached
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENONETRequested host is not reachable on the network
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOSRSystem ran out of stream resources
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPERMConnection forbidden/denied by firewall rules
randolf::rex::xEPROTOProtocol error
randolf::rex::xEPROTONOSUPPORTSpecified type or protocol is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xERESTARTSYSUsed in back-end tracing to indicate that a system call is restartable and can be intercepted-and-redirected (there is no need to catch this exception unless you are an advanced developer, in which case you likely still won't need to catch it in code at this level)
randolf::rex::xESOCKTNOSUPPORTSpecified socket type is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xETIMEDOUTTimeout period elapsed
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and no inbound connections are waiting
Returns
Newly-created rsocket object representing the connection received
See also
accept()
accept_sp()
accept4_sp()
listen
Parameters
flagsSOCK_NONBLOCK
SOCK_CLOEXEC

◆ accept4_sp()

std::shared_ptr<rsocket> randolf::rsocket::accept4_sp ( const int  flags = 0)
inline

Accept new [inbound] socket connetions, with socket flags specified. (This is typically used in a loop.)

Precondition
The resulting rsocket object is created before the actual call to the accept4() function.
Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Postcondition
The resulting rsocket is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNABORTEDThe connection was aborted
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEHOSTDOWNHost is down or its network is disconnected
randolf::rex::xEHOSTUNREACHNo route to host
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALSocket is not in listen() mode or the length of the address is invalid
randolf::rex::xEINVALInvalid value in flags
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENETDOWNNetwork is disconnected or router is down
randolf::rex::xENETUNREACHNo route to network
randolf::rex::xENFILESystem-wide maximum open files limit reached
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENONETRequested host is not reachable on the network
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOSRSystem ran out of stream resources
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPERMConnection forbidden/denied by firewall rules
randolf::rex::xEPROTOProtocol error
randolf::rex::xEPROTONOSUPPORTSpecified type or protocol is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xERESTARTSYSUsed in back-end tracing to indicate that a system call is restartable and can be intercepted-and-redirected (there is no need to catch this exception unless you are an advanced developer, in which case you likely still won't need to catch it in code at this level)
randolf::rex::xESOCKTNOSUPPORTSpecified socket type is not supported within the specified family (a.k.a., communication domain)
randolf::rex::xETIMEDOUTTimeout period elapsed
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and no inbound connections are waiting
Returns
Newly-created rsocket object representing the connection received, wrapped in std::shared_ptr (a C++ smart pointer)
See also
accept()
accept_sp()
accept4()
listen
Parameters
flagsSOCK_NONBLOCK
SOCK_CLOEXEC

◆ backlog() [1/2]

rsocket* randolf::rsocket::backlog ( int  backlog = 0)
inlinenoexcept

Override the default listen backlog for this rsocket.

Note
The default backlog is 4096 (SOMAXCONN) on Linux, and 128 on older systems.
Returns
The same rsocket object so as to facilitate stacking
See also
listen
Parameters
backlogBacklog queue size (0 = use SOMAXCONN, which is the system default of 4096 on Linux, or 128 on older systems.

◆ backlog() [2/2]

int randolf::rsocket::backlog ( )
inlinenoexcept

Find out what this rsocket's default listen backlog is.

Returns
The default listen backlog
See also
listen

◆ bind() [1/2]

rsocket* randolf::rsocket::bind ( const struct sockaddr *  addr,
const socklen_t  addrlen = sizeof(sockaddr) 
)
inline

Bind this socket to the specified network address (and port number if the address family utilizes port numbers {e.g., TCP or UDP}). This is mostly used for server deamons, but can also be used to control the address from which the local host will make an outbound connection via the connect() method (this bound address is the address from which the endpoint will recieve your connection).

Exceptions
randolf::rex::xEACCESIf the port number is below or equal to 1024 (or 1023 on some Operating Systems that test only for below 1024) in the absence of elevated access or the absence of a capability flag having been set
randolf::rex::xEACCESIf binding to an interface on systems that require elevated access for direct interface binding in absence of said elevated access
randolf::rex::xEADDRINUSEAddress and/or port number already in use
randolf::rex::xEADDRNOTAVAILThe interface doesn't exist or the address is not available on any local interface
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALSocket is already bound
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket

The following exceptions are specific to AF_UNIX family sockets...
randolf::rex::xEACCESWrite permission or search permission denied on a component of the path prefix (AF_UNIX family)
randolf::rex::xELOOPToo many symbolic links encountered while resolving address (AF_UNIX family)
randolf::rex::xENAMETOOLONGAddress is too long (AF_UNIX family)
randolf::rex::xENOENTOne of the path's directory components doesn't exist (AF_UNIX family)
randolf::rex::xENOTDIROne of the path's diretory components is not a directory (AF_UNIX family)
randolf::rex::xEROFSRead-only file system (AF_UNIX family)
Returns
The same rsocket object so as to facilitate stacking
See also
bind(std::string, int)
connect
listen
Parameters
addrSocket address structure
addrlenLength of socket structure

◆ bind() [2/2]

rsocket* randolf::rsocket::bind ( const std::string  address,
const int  port = 0 
)
inline

Bind this socket to the specified network address (and port number if the address family utilizes port numbers {e.g., TCP or UDP}). This is mostly used for server deamons, but can also be used to control the address from which the local host will make an outbound connection via the connect() method (this bound address is address from which the endpoint will recieve your connection).

In addition to the standard IPv4 (AF_INET family) and IPv6 (AF_INET6 family) support, rsocket also supports a few other binding options in a manner that makes it easy to utilize, without having to handle special implementation details (because they're handled behind-the-scenese by this rsocket class).

The address string supports a number of different notations and formats, which are documented, hereunder, with examples:

  • IPv4 addresses
  • IPv6 addresses
  • Network interfaces
  • UNIX domain sockets

IPv4 address notations (address family AF_INET)
Takes the form of x.x.x.x where each "x" represents an octet in the range of 0 through 255 (e.g., 127.0.0.1).

Under a proper implenetation of TCP/IP, an IPv4 address can be abbreviated to fewer octets. The following examples demonstrate this (an unabbreviated IPv4 address is included for completeness):

  • 0.0.0.1 may be abbreviated to 1
  • 4.0.0.1 may be abbrevaited to 4.1
  • 4.3.0.1 may be abbreviated to 4.3.1
  • 4.3.2.1 is not abbreviated (this is the most common usage)
Example of binding to IPv4 localhost
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_INET, SOCK_STREAM, IPPROTO_TCP);
r.bind("127.0.0.1", 32768); // <-- You are here
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xEACCES e) {
std::cerr << "Socket bind-access exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
Exception for error: EACCES.
Definition: rex:299
Note
Specifying the IP address of 0.0.0.0 will bind to all IPv4 addresses that are assigned to all of the host machine's network interfaces with IPv4 bindings.

Specifying the IP address of 127.0.0.1 (localhost) is useful for serving only those applications that are running on the local host and use an IPv4 socket to communicate.

IPv6 address notations (address family AF_INET6)
Takes the form of x:x:x:x:x:x:x:x where each "x" represents a segment in the range of 0 through ffff in hexadecimal (e.g., 0:0:0:0:0:0:0:1), or x:x:x:x:x:x:y.y.y.y where y.y.y.y represents an [unabbreviated] IPv4 address (which merely replaces the last two IPv6 segments).

Under a proper implenetation of TCP/IP, an IPv6 address can be abbreviated to fewer segments by using a sequence of two colons (::) to indicate that the undefined segments are 0 (this abbreviation can only be used once, and may represent segments at the beginning or end, or anywhere in between). The following examples demonstrate this (an unabbreviated IPv6 address is included for completeness):

  • 0:0:0:0:0:0:0:1 may be abbreviated to ::1
  • 0:0:0:0:0:0:2:1 may be abbreviated to ::2:1
  • 8:0:0:0:0:0:2:1 may be abbreviated to 8::2:1
  • 8:7:0:0:0:0:2:1 may be abbreviated to 8:7::2:1
  • 8:7:0:0:0:0:0:0 may be abbreviated to 8:7::
  • 8:0:0:0:0:0:0:0 may be abbreviated to 8::
  • 8:7:6:5:4:3:2:1 is not abbreviated
Example of binding to IPv6 localhost
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
r.bind("::1", 32768); // <-- You are here
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xEACCES e) {
std::cerr << "Socket bind-access exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
Note
Specifying the IP address of :: will bind to all IPv6 addresses that are assigned to all of the host machine's network interfaces with IPv6 bindings.

Specifying the IP address of ::1 (localhost) is useful for serving only those applications that are running on the local host and use an IPv6 socket to communicate.

Interface address notation (address families AF_INET and AF_INET6)
Takes the form of if=name where "name" represents the name of a local network interface.

Interface binding is useful when binding to interfaces that aren't configured with a static IP address because they were dymamically configured via the Dynamic Host Configuration Protocol (DHCP) or Stateless Address Configuration (SLAAC), or the configuration was changed manually by an administrator and you don't want your software to handle such changes gracefully, even if the new IP address is within the scope of an entirely different CIDR. (Changing between the IPv4 and IPv6 addresses is not supported, however, due to the fundamental differences between these two address families that includes differences beyond that of IP address format, although under a proper implementation of TCP/IP the binding should survive such changes when the IP address is reverted to the initial IP address family of the bound interface.)

Examples of interfaces include:

  • if=lo typical for localhost virtual network adapter
  • if=bond0 typical for the first bonded virtual network adapter (used in failover and load-balancing network configurations)
  • if=br0 typical for the first bridge virtual network adapter
  • if=eth0 typical for the first ethernet network adapter
  • if=tap0 typical for the first virtual layer 2 ethernet switch (used by VPNs to extend a remote network into the local network stack)
  • if=tun0 typical for the first virtual layer 3 ethernet tunnel (used by VPNs to provide access to a remote network)
  • if=wlo1 typical for the first wireless network adapter
Example of binding to interface localhost
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_INET, SOCK_STREAM, IPPROTO_TCP);
r.bind("if=lo", 32768); // <-- You are here
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xEACCES e) {
std::cerr << "Socket bind-access exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
Note
This is not a standard feature of the POSIX bind() function. This rsocket class uses the setsockopt() function behind-the-scenes to configure (enable) the SO_BINDTODEVICE option, and then the bind() function is called with the IPv4 address 0.0.0.0 if the underlying socket was initialized to the AF_INET family, or the IPv6 address :: if the underlying socket was initialized to the AF_INET6 family.

Specifying the interface address of if=lo (localhost) is useful for serving only those applications that are running on the local host and use an IPv4 or IPv6 socket to communicate.

UNIX Domain Sockets address-notation (address family AF_UNIX)
Takes the form of /path where "/path" represents an absolute path on the local file system (the path can also be relative, in which case it doesn't begin with a slash (/) character, but extra care is needed to ensure that the path will actually be at its expected location).
Example of binding to UNIX domain sockets
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
int main(int argc, char *argv[]) {
try {
randolf::rsocket r(AF_UNIX, SOCK_STREAM);
r.bind("/var/run/rsocket-test-socket.tmp"); // <-- You are here
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xEACCES e) {
std::cerr << "Socket bind-access exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
Note
Normal socket I/O functionality is used to exchange data with another process that can open the same UNIX domain socket (normally on the same host, although it may not be outside the realm of possibility for future Linux kernels to support UNIX domain sockets on remote hosts).

Exceptions
randolf::rex::xEACCESIf the port number is below or equal to 1024 (or 1023 on some Operating Systems that test only for below 1024) in the absence of elevated access or the absence of a capability flag having been set
randolf::rex::xEACCESIf binding to an interface on systems that require elevated access for direct interface binding in absence of said elevated access
randolf::rex::xEADDRINUSEAddress and/or port number already in use
randolf::rex::xEADDRNOTAVAILThe interface doesn't exist or the address is not available on any local interface
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALSocket is already bound
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket

The following exceptions are specific to AF_UNIX family sockets...
randolf::rex::xEACCESWrite permission or search permission denied on a component of the path prefix (AF_UNIX family)
randolf::rex::xELOOPToo many symbolic links encountered while resolving address (AF_UNIX family)
randolf::rex::xENAMETOOLONGAddress is too long (AF_UNIX family)
randolf::rex::xENOENTOne of the path's directory components doesn't exist (AF_UNIX family)
randolf::rex::xENOTDIROne of the path's diretory components is not a directory (AF_UNIX family)
randolf::rex::xEROFSRead-only file system (AF_UNIX family)
Returns
The same rsocket object so as to facilitate stacking
See also
bind(const struct sockaddr*, const socklen_t)
connect
listen
Parameters
addressIPv4 address, IPv6 address, hostname, UNIX domain sockets path, or specialized variant (see notes, above)
portTCP or UDP port number ranging 1-65535 (0 = ephemeral port; a.k.a., automatic assignment)

◆ buffer_size() [1/2]

const int randolf::rsocket::buffer_size ( )
inlinenoexcept

Find out what buffer size is used by the various recv() methods.

Returns
Buffer size (in bytes)
See also
buffer_size(const size_t nbytes)
is_buffered

◆ buffer_size() [2/2]

rsocket* randolf::rsocket::buffer_size ( const size_t  nbytes)
inlinenoexcept

Override the default buffer size (typically 1024) used by the various recv() methods.

If resetting to the compiled-in default, use the buffer_size_reset() method instead of setting the value directly. This ensures that future versions, with a different compiled-in default, will be reset to the compiled-in value.

Returns
The same rsocket object so as to facilitate stacking
See also
buffer_size
buffer_size_reset
Parameters
nbytesSize of the new buffer (in bytes)

◆ buffer_size_reset()

rsocket* randolf::rsocket::buffer_size_reset ( )
inlinenoexcept

Reset the default buffer size (typically 1024) used by the various recv() methods.

This method is preferred for resetting to the compiled-in default instead of setting the value directly. This ensures that future versions, with a different compiled-in default, will be reset to the compiled-in value.

Returns
The same rsocket object so as to facilitate stacking
See also
buffer_size(const size_t nbytes)

◆ close()

rsocket* randolf::rsocket::close ( )
inline

Close this rsocket. (If this rsocket was already closed, then calling this method additional times will have no effect, and will not cause exceptions to be thrown.)

Warning
This method may throw exceptions in some circumstances, which is extremely rare. If you prefer to close without having to contend with any exceptions (e.g., while calling close() from within a destructor), the close_passive() method will return an integer indicating success/failure instead of throwing an exception, and then you'll have to handle errno manually (which is useful in destructors because any error can merely be handled procedurally).
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEIOAn I/O error occurred
Returns
The same rsocket object so as to facilitate stacking
See also
is_closed()

◆ close_passive()

int randolf::rsocket::close_passive ( )
inlinenoexcept

Close this rsocket without throwing any exceptions (an error code is returned instead, which is useful while calling close_passive() from within a destructor).

Returns
0 = success
-1 = error (errno will be set accordingly)
See also
is_closed()

◆ connect()

rsocket* randolf::rsocket::connect ( const std::string  address,
const int  port = 0 
)
inline

Connect this socket to a specific endpoint (which may differ from this rsocket's address that was previously configured by the bind() method).

Exceptions
randolf::rex::xEADDRINUSEAddress and/or port number already in use
randolf::rex::xEADDRNOTAVAILNo ephemeral ports are available for assignment to unbound socket
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xEAGAINInsufficient entries in the routing cache
randolf::rex::xEALREADYPrevious connection attempt not completed on nonblocking socket
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINPROGRESSConnection cannot be completed immediately on nonblocking socket (AF_UNIX family fails with xEAGAIN instead)
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEISCONNSocket is already connected
randolf::rex::xENETUNREACHNo route to network
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEPERMConnection forbidden/denied by firewall rules
randolf::rex::xEPERMCan't connect to a broadcast address when the socket's broadcast flag isn't enabled
randolf::rex::xEPROTOTYPESocket type doesn't support the requested communications protocol (e.g., connecting a UNIX domain socket of type SOCK_STREAM to an endpoint expecting type SOCK_DGRAM)
randolf::rex::xETIMEDOUTTimeout period elapsed

The following exceptions are specific to AF_UNIX family sockets...
randolf::rex::xEACCESWrite permission or search permission denied on a component of the path prefix (AF_UNIX family)
randolf::rex::xEAGAINConnection cannot be completed immediately on nonblocking socket (AF_UNIX family)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_do_handshake()
Parameters
addressIPv4 address, IPv6 address, hostname, or UNIX domain sockets path
portTCP or UDP port number ranging 1-65535 (0 = ephemeral port; a.k.a., automatic assignment)

◆ debug() [1/4]

const bool randolf::rsocket::debug ( )
inlinenoexcept

Find out whether debug mode is enabled.

Threads
This method is threadsafe.
Returns
TRUE = enabled
FALSE = not enabled

◆ debug() [2/4]

const int randolf::rsocket::debug ( const bool  debug_flag,
std::FILE *  fd = stderr 
)
inlinenoexcept

Debug mode. When debug mode is enabled, output is sent to stderr by default, unless a second parameter specifies a different file handle (e.g., stdout, or even a socket).

debug(...) returns -1 if fd can't be written to (errno will be set in accordance with std::fprintf's behaviour since std::fprintf is used for writing debug output). Normally we'd throw an exception for such errors, but with debug is a special case because debugging needs to be as quick and convenient as possible for developers.

debug(...) returns -2 if writing to stderr failed when attempting to announce that fd can't be written to (as described above).

debug(...) returns -3 if some other error occurs (e.g., internal formatting error {which should not happen} or memory allocation failed, in which case there's a more serious problem that will be causing other problems elsewhere anyway).

Developers may add their own debug messages by using debug(std::string), which will only be written out if debug mode is enabled. This same method is used internally, so messages will be indistinguishable from developer's messages.

Threads
This method is thread-safe.
Returns
0 = success
-1 = error writing to stream (errno will be set accordingly)
-2 = error writing to stderr (errno will be set accordingly)
-3 = error (errno will be set accordingly)
Parameters
debug_flagTRUE = enable debug mode
FALSE = disable debug mode (does not close any file handles)
fdFile descriptor/handle to use for debug output

◆ debug() [3/4]

const int randolf::rsocket::debug ( const char *  msg)
inlinenoexcept

Send the specified message as debug output (as long as debug mode is enabled; if disabled, no debug output will be sent).

Returns
0 = success
-1 = error writing to stream (errno will be set accordingly)
-2 = error writing to stderr (errno will be set accordingly)
-3 = error (errno will be set accordingly)
Parameters
msgDebug message as an ASCIIZ string

◆ debug() [4/4]

const int randolf::rsocket::debug ( const std::string  msg)
inlinenoexcept

Send the specified message as debug output (as long as debug mode is enabled; if disabled, no debug output will be sent).

Returns
0 = success
-1 = error writing to stream (errno will be set accordingly)
-2 = error writing to stderr (errno will be set accordingly)
-3 = error (errno will be set accordingly)
Parameters
msgDebug message as an std::string object

◆ debug_fd() [1/2]

const std::FILE* randolf::rsocket::debug_fd ( )
inlinenoexcept

Find out which file descriptor/handle is used for debug output.

Returns
file handle/descriptor currently used for debug output

◆ debug_fd() [2/2]

const int randolf::rsocket::debug_fd ( std::FILE *  fd)
inlinenoexcept

Specify a different file descriptor/handle to use for debug output.

Returns
0 = success
-1 = error writing to stream (errno will be set accordingly)
-2 = error writing to stderr (errno will be set accordingly)
-3 = error (errno will be set accordingly)
Parameters
fdFile descriptor/handle to use for debug output

◆ eol() [1/3]

const std::string randolf::rsocket::eol ( )
inlinenoexcept

Find out what the current EoL (End of Line) sequence is set to.

Warning
To send an EoL sequence do not use send(r.eol()) because it may not be initialized yet and the endpoint you're sending to may seem unresponsive or other unexpected behaviour may occur.
To send an EoL sequence properly, use sendline() (no parameters is more efficient than specifying an empty string with ""), or use the specialized send_eol() method (which is the most efficient option).
Attention
An empty EoL sequence means that CRLF will be sent by sendline(), and recvline() will automatically detect from one of CR, CRLF, LF, and LFCR.
Returns
Current EoL sequence
See also
eol_adoption
eol_fix_printf
printfline
recvline
sendline
send_eol
vprintfline

◆ eol() [2/3]

rsocket* randolf::rsocket::eol ( const char *  eol)
inlinenoexcept

Set EoL (End of Line) sequence. This sequence is used by recvline(), sendline(), and related functions, and it defaults to an empty string which means that the EoL sequence will be automatically detected on-the-fly.

  • "" (empty string) = automatically detect on-the-fly (default)
  • \r\n (CRLF) = Carriage Return + Linefeed (typical for DOS)
  • \r (CR) = Carriage Return (typical for MacOS)
  • \n (LF) = Linefeed (typical for UNIX/Linux)
Note
CRLF (\r\n) is used by most internet protocols (e.g., HTTP, SMTP, POP3, IMAP4, FINGER, NICNAME/WHOIS, etc.).
Returns
The same rsocket object so as to facilitate stacking
See also
eol_adoption
eol_fix_printf
printfline
vprintfline
sendline
send_eol
Parameters
eolEoL sequence as an ASCIIZ string

◆ eol() [3/3]

rsocket* randolf::rsocket::eol ( const std::string  eol)
inlinenoexcept

Set EoL (End of Line) sequence. This sequence is used by recvline(), sendline(), and related functions, and it defaults to an empty string which means that the EoL sequence will be automatically detected on-the-fly.

  • "" (empty string) = automatically detect on-the-fly (default)
  • \r\n (CRLF) = Carriage Return + Linefeed (typical for DOS)
  • \r (CR) = Carriage Return (typical for MacOS)
  • \n (LF) = Linefeed (typical for UNIX/Linux)
Note
CRLF (\r\n) is used by most internet protocols (e.g., HTTP, SMTP, POP3, IMAP4, FINGER, NICNAME/WHOIS, etc.).
Returns
The same rsocket object so as to facilitate stacking
See also
eol_fix_printf
printfline
vprintfline
sendline
send_eol
Parameters
eolEoL sequence as an std::string object

◆ eol_adoption()

rsocket* randolf::rsocket::eol_adoption ( const bool  flag)
inlinenoexcept

Configure EoL adoption policy for the recvline() method. By default, rsocket is configured with the EoL adoption policy enabled alongside an empty eol() sequence, which results in the default operation being that the EoL sequence automatically gets detected and updated internally upon the first use of the recvline() method.

The EoL adoption policy is only effective when the eol() sequence is not defined (which is indicated by an empty EoL sequence string).

The EoL sequence is updated only when the EoL sequence string is empty, and when this EoL adoption policy is enabled.

Returns
The same rsocket object so as to facilitate stacking
See also
eol
eol_index
is_eol_adoption
recvline
sendline
send_eol
Parameters
flagTRUE = enable EoL adoption (default)
FALSE = disable EoL adoption

◆ eol_fix_printf()

rsocket* randolf::rsocket::eol_fix_printf ( const bool  flag)
inlinenoexcept

Configure EoL substitution policy for the printf(), printfline(), vprintf(), and vprintfline() methods. By default, rsocket substitutes printf's \n sequence with the EoL sequence (if defined), and this method can be used to disable this behaviour.

Note
The \n sequence used in the printf format string normally coincides with the local Operating System's newline standard, which is very likely different from the rsocket endpoint's newline standard, and/or the newline standard of the protocol being implemented. This policy setting makes it possible to control whether to use the configured EoL sequence when sending a formatted string to the endpoint.
Returns
The same rsocket object so as to facilitate stacking
See also
eol
is_eol_fix_printf
printf
printfline
vprintf
vprintfline
Parameters
flagTRUE = enable EoL substitution (default)
FALSE = disable EoL substitution

◆ eol_index()

const int randolf::rsocket::eol_index ( const std::string  buffer,
int *  with_eol_size 
)
inlinenoexcept

Finds the first instance of the EoL sequence and returns its offset (which is effectively the same as the size of the text, not including the characters that the EoL sequence is comprised of).

Note
This method is specialized primarily for internal use by the recvline() method.
Returns
Size of EoL sequence
-1 if EoL sequence wasn't found
See also
eol
eol_adoption
Parameters
bufferBuffer that probably contains at least one EoL sequence
with_eol_sizeSize of string with EoL character sequence included (will be updated by this method)

◆ eos()

const bool randolf::rsocket::eos ( const int  timeout = 0)
inline

Find out if the stream is at its end and that this rsocket's internal buffer (if one had been set up by the recvline() method) is empty. This doesn't necessarily mean that the stream is closed; but rather that the endpoint just hasn't sent any more data (yet).

If the stream isn't open, then this method will always return true to implicitly indicate that there's no more data.

Precondition
For this method to work properly, you need to specify a timeout either with the timeout parameter, or by setting the timeout() for this rsocket (you can still override this rsocket's timeout by specifying a timeout here).

It's better (more efficient) to use this method instead of the MSG_PEEK flag (with the various recv methods) to determine whether any data is waiting on the stream (e.g., data that's received by the sockets, but not by any recv methods yet) because this method is specialized in handling this particular condition and responds with an easy-to-use boolean flag.

Note
EoS is an acronym for: End of Stream
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xETIMEDOUTTimeout period elapsed (even if the TIMEOUT_BEHAVIOUR flag is not set to TIMEOUT_EXCEPTION, there is a highly improbable chance that a timeout could still occur if the data is read by another thread before the recv(..., MSG_PEEK) call)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
TRUE = End of Stream (no data, or the stream is_closed())
FALSE = More data is ready to be received
See also
is_closed
is_open
Parameters
timeoutNumber of milliseconds to wait

◆ family()

static int randolf::rsocket::family ( const std::string  address,
const int  preferred_family = AF_UNSPEC 
)
inlinestatic

Find out what the specified IP address string's family (SO_DOMAIN) is.

Exceptions
randolf::rex::xEADDRNOTAVAILThe interface doesn't exist or the address is not available on any local interface
randolf::rex::xEAI_NONAMEIf address is an empty string
Returns
AF_UNSPEC (if family couldn't be determined)
AF_INET (IPv4 address)
AF_INET6 (IPv6 address)
AF_UNIX (UNIX Domain address)
...or other family as applicable
Parameters
addressAddress, similar to bind() addressing, including non-standard "if=" variant that names a network interface
preferred_familyPreferred family to return first (used only with interface mode where the network interface is specified after the "if=" prefix); the default value of AF_UNSPEC will return the first family interface found

◆ getpeername()

const std::shared_ptr<sockaddr_storage> randolf::rsocket::getpeername ( )
inline

Get peer name returns the address of the socket as a sockaddr_storage structure.

The resulting structure is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
sockaddr_storage structure

◆ getpeername_ntop()

const std::string randolf::rsocket::getpeername_ntop ( )
inline

Get peer name returns the address of the socket as a std::string object.

Exceptions
randolf::rex::xEAI_ADDRFAMILYif the address can't be determined (e.g., because the family doesn't utilize or support an address {or the format isn't known}
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOSPCResulting address string exceeds maximum size
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
string representation of peer name

◆ getsockaddr()

static sockaddr* randolf::rsocket::getsockaddr ( const sockaddr_storage *  sa)
inlinestatic

Get specified "sockaddr_storage" structure's address as a "sockaddr" structure, for sockets in one of the supported families:

  • AF_INET (IPv4)
  • AF_INET6 (IPv6)
  • AF_UNIX (Domain socket path)
  • AF_PACKET (Ethernet node/mac. address)
Exceptions
randolf::rex::xEAI_ADDRFAMILYif the address can't be determined (e.g., because the family doesn't utilize or support an address {or the format isn't known}
Returns
pointer to sockaddr structure within provided sockaddr_storage
Parameters
saThe sockaddr_storage structure wherein sockaddr will be referenced from

◆ getsockname()

const std::shared_ptr<sockaddr_storage> randolf::rsocket::getsockname ( )
inline

Get socket name returns the address of the socket as a "sockaddr_storage" structure.

The resulting structure is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
sockaddr_storage structure

◆ getsockname_ntop()

const std::string randolf::rsocket::getsockname_ntop ( )
inline

Get socket name returns the name of the socket as a std::string object.

Exceptions
randolf::rex::xEAI_ADDRFAMILYif the address can't be determined (e.g., because the family doesn't utilize or support an address {or the format isn't known}
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOSPCResulting address string exceeds maximum size
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
string representation of socket name

◆ getsockopt_int()

int randolf::rsocket::getsockopt_int ( const int  level,
const int  option 
)
inline

Get socket option details in the form of an integer.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_u_int()

u_int randolf::rsocket::getsockopt_u_int ( const int  level,
const int  option 
)
inline

Get socket option details in the form of an unsigned integer.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option value
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_u_char()

u_char randolf::rsocket::getsockopt_u_char ( const int  level,
const int  option 
)
inline

Get socket option details in the form of an unsigned character.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option value
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_linger()

std::shared_ptr<linger> randolf::rsocket::getsockopt_linger ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_timeval()

std::shared_ptr<timeval> randolf::rsocket::getsockopt_timeval ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_in_addr()

std::shared_ptr<in_addr> randolf::rsocket::getsockopt_in_addr ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_ip_mreq()

std::shared_ptr<ip_mreq> randolf::rsocket::getsockopt_ip_mreq ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_ip_mreq_source()

std::shared_ptr<ip_mreq_source> randolf::rsocket::getsockopt_ip_mreq_source ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_icmp6_filter()

std::shared_ptr<icmp6_filter> randolf::rsocket::getsockopt_icmp6_filter ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_sockaddr_in6()

std::shared_ptr<sockaddr_in6> randolf::rsocket::getsockopt_sockaddr_in6 ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_ip6_mtuinfo()

std::shared_ptr<ip6_mtuinfo> randolf::rsocket::getsockopt_ip6_mtuinfo ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_ipv6_mreq()

std::shared_ptr<ipv6_mreq> randolf::rsocket::getsockopt_ipv6_mreq ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_group_req()

std::shared_ptr<group_req> randolf::rsocket::getsockopt_group_req ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_group_source_req()

std::shared_ptr<group_source_req> randolf::rsocket::getsockopt_group_source_req ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ getsockopt_other()

template<class T >
std::shared_ptr<T> randolf::rsocket::getsockopt_other ( const int  level,
const int  option 
)
inline

Get socket option details in the form of a structure.

Most options return an integer, with the remaining options returning a pointer to a structure wrapped in a std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks); the primitive types int, u_int, and u_char are not wrapped in C++ smart pointers because returning them by value is more efficient since allocating memory for an entire structure isn't needed.

Postcondition
It is up to the developer to know which return type is needed according to the socket option, otherwise an exception will likely be thrown – in some cases where the wrong type will seem to work, this is due to the wrong type providing a minimally sufficient amount of memory for the storage of the resulting structure.
Notes
The returned values/structures are not marked as "const" because they may need to be modified for unforseen purposes. Modifying the returend values or structures is fine because they are intended to be independent and are expected to have no direct impact on the rsocket's internal variables and structures.

Templates in C++ aren't used here because they don't work properly for our needs due to neccesity to handle both fundamental types and structures; it turns out that mixing these is impossible when using the same function name, so this just doesn't work as well as we'd like it to. (We may try to work on this again in the future as time permits to provide an additional method for obtaining socket options, but with the intention of never removing this current set of methods so as to ensure backward compatibility in the future.)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
socket option value
socket option structure wrapped in std::shared_ptr
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.

◆ inet_ntop() [1/2]

const std::string randolf::rsocket::inet_ntop ( )
inline

Get underlying socket's address as a std::string, for sockets in one of the supported families:

  • AF_INET (IPv4)
  • AF_INET6 (IPv6)
  • AF_UNIX (Domain socket path)
  • AF_PACKET (Ethernet node/mac. address)
Exceptions
randolf::rex::xEAI_ADDRFAMILYif the address can't be determined (e.g., because the family doesn't utilize or support an address {or the format isn't known}
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xENOSPCResulting address string exceeds maximum size
Returns
string representation of underlying socket's address
See also
inet_ntop(sockaddr_storage*) static method

◆ inet_ntop() [2/2]

static const std::string randolf::rsocket::inet_ntop ( sockaddr_storage *  sa)
inlinestatic

Get specified "sockaddr_storage" structure's address as a std::string, for sockets in one of the supported families:

  • AF_INET (IPv4)
  • AF_INET6 (IPv6)
  • AF_UNIX (Domain socket path)
  • AF_PACKET (Ethernet node/mac. address)
Exceptions
randolf::rex::xEAI_ADDRFAMILYif the address can't be determined (e.g., because the family doesn't utilize or support an address {or the format isn't known}
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xENOSPCResulting address string exceeds maximum size
Returns
string representation of underlying socket's address
See also
inet_ntop() non-static method
Parameters
saSource structure that [should] contain address data

◆ is_buffered()

const bool randolf::rsocket::is_buffered ( )
inlinenoexcept

Find out whether an internal read buffer was allocated (this is most likely triggered by an attempt to read a line of text).

Note
The buffer_size() methods report on how much memory was allocated for the internal read buffer or to set its size (in bytes).
Returns
TRUE = an internal read buffer was allocated
FALSE = an internal read buffer was not allocated
See also
buffer_size
buffer_size(const size_t nbytes)

◆ is_closed()

const bool randolf::rsocket::is_closed ( )
inlinenoexcept

Find out whether the underlying socket is not open (which may not be the same as specifically "closed" since a newly instantiated empty socket begins in a "not open" state despite the underlying socket not having been closed).

Returns
TRUE = not open
FALSE = open
See also
is_open()

◆ is_connected()

const bool randolf::rsocket::is_connected ( )
inlinenoexcept

Find out whether the underlying socket is connected with/to an endpoint.

Returns
TRUE = open
FALSE = not open

◆ is_endian_lsb()

const bool randolf::rsocket::is_endian_lsb ( )
inlinenoexcept

Find out whether the default byte order for this host is LSB (small endian).

Note
If you're trying to choose which endian type to use when designing a new internet protocol, then big endian is normally the better option. However, if your new protocol will only be used by hardware that all share the same endianness, then that endianness is probably the more optimal option since it will translate to an overall lesser consumption of CPU cycles by reducing or eliminating endianness conversions.
Returns
TRUE = LSB (little endian)
FALSE = MSB (big endian / network byte order)

◆ is_endian_msb()

const bool randolf::rsocket::is_endian_msb ( )
inlinenoexcept

Find out whether the default byte order for this host is MSB (big endian).

Note
Big endian is the standard known as "network byte order" that's also used in various header fields in internet packets.

If you're trying to choose which endian type to use when designing a new internet protocol, then big endian is normally the better option. However, if your new protocol will only be used by hardware that all share the same endianness, then that endianness is probably the more optimal option since it will translate to an overall lesser consumption of CPU cycles by reducing or eliminating endianness conversions.
Returns
TRUE = MSB (big endian / network byte order)
FALSE = LSB (little endian)

◆ is_eol_adoption()

const bool randolf::rsocket::is_eol_adoption ( )
inlinenoexcept

Find out if the EoL adoption policy is enabled for the recvline() method (see the eol_adoption method to find out how the dynamically-detected EoL sequence gets adopted, and under what conditions).

Returns
TRUE = EoL adoption is enabled
FALSE = EoL adoption is disabled
See also
eol
eol_adoption
eol_index
recvline
sendline
send_eol

◆ is_eol_fix_printf()

const bool randolf::rsocket::is_eol_fix_printf ( )
inlinenoexcept

Find out if the EoL substitution policy is enabled for the printf(), printfline(), vprintf(), and vprintfline() methods.

Returns
TRUE = EoL substitution is enabled
FALSE = EoL substitution is disabled
See also
eol
eol_fix_printf
printf
printfline
sendline
send_eol
vprintf
vprintfline

◆ is_open()

const bool randolf::rsocket::is_open ( )
inlinenoexcept

Find out whether the underlying socket is open.

Returns
TRUE = open
FALSE = not open
See also
is_closed()

◆ is_tls()

const bool randolf::rsocket::is_tls ( )
inlinenoexcept

Find out whether encrypted communications is enabled or disabled.

Returns
TRUE = encrypted communications is enabled
FALSE = encrypted communications is disabled
See also
tls(bool, TLS_FLAGS)

◆ is_tls_client_mode()

const bool randolf::rsocket::is_tls_client_mode ( )
inlinenoexcept

Find out whether TLS context is in TLS_CLIENT mode.

Returns
TRUE = TLS context is in TLS_CLIENT mode
FALSE = TLS context is in TLS_SERVER mode
See also
TLS_CLIENT
tls()

◆ is_tls_egress_okay()

const bool randolf::rsocket::is_tls_egress_okay ( )
inlinenoexcept

Find out whether egress from encryption (to unencrypted mode) is allowed.

Returns
TRUE = egress from encrypted communications is allowed
FALSE = egress from encrypted communications is not allowed
See also
TLS_NO_EGRESS
tls()

◆ is_tls_exclusive()

const bool randolf::rsocket::is_tls_exclusive ( )
inlinenoexcept

Find out whether encrypted communications is exclusive.

Returns
TRUE = encrypted communications is exclusive
FALSE = encrypted communications is not exclusive
See also
tls()

◆ is_tls_ingress_okay()

const bool randolf::rsocket::is_tls_ingress_okay ( )
inlinenoexcept

Find out whether ingress to encryption (from unencrypted mode) is allowed.

Returns
TRUE = ingress to encrypted communications is allowed
FALSE = ingress to encrypted communications is not allowed
See also
TLS_NO_INGRESS
tls()

◆ is_tls_server_mode()

const bool randolf::rsocket::is_tls_server_mode ( )
inlinenoexcept

Find out whether TLS context is in TLS_SERVER mode.

Returns
TRUE = TLS context is in TLS_SERVER mode
FALSE = TLS context is in TLS_CLIENT mode
See also
TLS_SERVER
tls()

◆ is_tls_sni()

const bool randolf::rsocket::is_tls_sni ( )
inlinenoexcept

Find out whether SNI (Server Name Identifier) is enabled (configured, which implies that an internal callback function was also set up).

Returns
TRUE = SNI is enabled
FALSE = SNI is disabled
See also
tls_sni()

◆ is_tls_sni_match()

const bool randolf::rsocket::is_tls_sni_match ( )
inlinenoexcept

Find out whether SNI (Server Name Identifier) was matched, which means that we're using one of the supplementary TLS certificates that are included in the associated rsocket_sni object as separate TLS contexts.

When this method returns TRUE, it means the OpenSSL callback (which occurs during the TLS handshake process) completed the TLS handshake with one of the TLS certificates that's included in this rsocket's rsocket_sni object instead of the primary TLS certificate assigned to this rsocket, and this rsocket is using the respective TLS context instead of the primary (default) one.

Returns
TRUE = SNI was matched
FALSE = SNI wasn't matched
See also
name_sni
tls_sni

◆ listen()

rsocket* randolf::rsocket::listen ( int  backlog = 0)
inline

Enable listening mode for this rsocket to prepare it to accept() new inbound connections.

The backlog defaults to SOMAXCONN (4096 on Linux, and 128 on older systems), which is common on most systems. If a higher value is supplied that exceeds kern.somaxconn, the kernel will automatically override the backlog with the value stored in kern.somaxconn without generating any errors or warnings.

Exceptions
randolf::rex::xEADDRINUSEAddress and/or port number already in use
randolf::rex::xEADDRINUSENo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
Returns
The same rsocket object so as to facilitate stacking
See also
accept()
accept_sp()
accept4()
accept4_sp()
backlog()
bind()
Parameters
backlogBacklog queue size (0 = uses rsocket's default; see backlog for more details about this); specifying a non-zero backlog also updates rocket's internal default (SOMAXCONN is 4096 on Linux, and 128 on older systems)

◆ mk_sockaddr_storage() [1/4]

static std::shared_ptr<sockaddr_storage> randolf::rsocket::mk_sockaddr_storage ( const char *  node_name,
const char *  service_name = nullptr,
const addrinfo *  hints = nullptr 
)
inlinestatic

Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure.

If service_name is an absolute path (that begins with a "/" charcter) and the family is set to AF_UNSPEC (the default), then the resulting family will be set to AF_UNIX.

Notes
This method utilizes the results of getaddrinfo().

Other families like AF_LINK and AF_PACKET should work, but haven't been tested thoroughly. The additional support we provide for IPv4 and IPv6 addresses is to copy the port number into the resulting structure (as a convenience).

Postcondition
The resulting sockaddr_storage structure is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).
Threads
This method is thread-safe.
Exceptions
randolf::rex::xEAI_ADDRFAMILYIf specified network host doesn't have any addresses in the specified address family
randolf::rex::xEAI_AGAINTemporary failure code from DNS server (try again later)
randolf::rex::xEAI_BADFLAGSInvalid flags in hints.ai_flags (or hints.ai_flags included AI_CANONNAME with nullptr as name)
randolf::rex::xEAI_FAILPermanent failure code from DNS server
randolf::rex::xEAI_FAMILYThe specified family is not supported
randolf::rex::xEAI_MEMORYOut of memory
randolf::rex::xEAI_NONAMEIf node_name is nullptr or an empty string
randolf::rex::xEAI_SERVICEThe specified service is not available for the specified socket type
randolf::rex::xEAI_SOCKTYPEThe specified socket type is not supported
randolf::rex::xEAI_SYSTEMOther system error (use errno to determine what the error is, then run use randolf::rex::rex::mk_exception to throw the correct exception)
Returns
sockaddr_storage structure
Parameters
node_nameIP address or UNIX domain socket address to convert
service_namePort number (or service name used by some other families)
hintsOptional pointer to a helpful addrinfo structure

◆ mk_sockaddr_storage() [2/4]

static std::shared_ptr<sockaddr_storage> randolf::rsocket::mk_sockaddr_storage ( const char *  node_name,
const u_int16_t  service_name,
const addrinfo *  hints = nullptr 
)
inlinestatic

Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure.

If service_name is an absolute path (that begins with a "/" charcter) and the family is set to AF_UNSPEC (the default), then the resulting family will be set to AF_UNIX.

Notes
This method utilizes the results of getaddrinfo().

Other families like AF_LINK and AF_PACKET should work, but haven't been tested thoroughly. The additional support we provide for IPv4 and IPv6 addresses is to copy the port number into the resulting structure (as a convenience).

Postcondition
The resulting sockaddr_storage structure is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).
Threads
This method is thread-safe.
Exceptions
randolf::rex::xEAI_ADDRFAMILYIf specified network host doesn't have any addresses in the specified address family
randolf::rex::xEAI_AGAINTemporary failure code from DNS server (try again later)
randolf::rex::xEAI_BADFLAGSInvalid flags in hints.ai_flags (or hints.ai_flags included AI_CANONNAME with nullptr as name)
randolf::rex::xEAI_FAILPermanent failure code from DNS server
randolf::rex::xEAI_FAMILYThe specified family is not supported
randolf::rex::xEAI_MEMORYOut of memory
randolf::rex::xEAI_NONAMEIf node_name is nullptr or an empty string
randolf::rex::xEAI_SERVICEThe specified service is not available for the specified socket type
randolf::rex::xEAI_SOCKTYPEThe specified socket type is not supported
randolf::rex::xEAI_SYSTEMOther system error (use errno to determine what the error is, then run use randolf::rex::rex::mk_exception to throw the correct exception)
Returns
sockaddr_storage structure
Parameters
node_nameIP address or UNIX domain socket address to convert
service_namePort number
hintsOptional pointer to a helpful addrinfo structure

◆ mk_sockaddr_storage() [3/4]

static std::shared_ptr<sockaddr_storage> randolf::rsocket::mk_sockaddr_storage ( const std::string  node_name,
const u_int16_t  service_name,
const addrinfo *  hints = nullptr 
)
inlinestatic

Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure.

If service_name is an absolute path (that begins with a "/" charcter) and the family is set to AF_UNSPEC (the default), then the resulting family will be set to AF_UNIX.

Notes
This method utilizes the results of getaddrinfo().

Other families like AF_LINK and AF_PACKET should work, but haven't been tested thoroughly. The additional support we provide for IPv4 and IPv6 addresses is to copy the port number into the resulting structure (as a convenience).

Postcondition
The resulting sockaddr_storage structure is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).
Threads
This method is thread-safe.
Exceptions
randolf::rex::xEAI_ADDRFAMILYIf specified network host doesn't have any addresses in the specified address family
randolf::rex::xEAI_AGAINTemporary failure code from DNS server (try again later)
randolf::rex::xEAI_BADFLAGSInvalid flags in hints.ai_flags (or hints.ai_flags included AI_CANONNAME with nullptr as name)
randolf::rex::xEAI_FAILPermanent failure code from DNS server
randolf::rex::xEAI_FAMILYThe specified family is not supported
randolf::rex::xEAI_MEMORYOut of memory
randolf::rex::xEAI_NONAMEIf node_name is nullptr or an empty string
randolf::rex::xEAI_SERVICEThe specified service is not available for the specified socket type
randolf::rex::xEAI_SOCKTYPEThe specified socket type is not supported
randolf::rex::xEAI_SYSTEMOther system error (use errno to determine what the error is, then run use randolf::rex::rex::mk_exception to throw the correct exception)
Returns
sockaddr_storage structure
Parameters
node_nameIP address or UNIX domain socket address to convert
service_namePort number
hintsOptional pointer to a helpful addrinfo structure

◆ mk_sockaddr_storage() [4/4]

static std::shared_ptr<sockaddr_storage> randolf::rsocket::mk_sockaddr_storage ( const std::string  node_name,
const std::string  service_name,
const addrinfo *  hints = nullptr 
)
inlinestatic

Convert an IPv4 address, IPv6 address, ethernet packet, or UNIX domain socket to a sockaddr_storage structure.

If service_name is an absolute path (that begins with a "/" charcter) and the family is set to AF_UNSPEC (the default), then the resulting family will be set to AF_UNIX.

Notes
This method utilizes the results of getaddrinfo().

Other families like AF_LINK and AF_PACKET should work, but haven't been tested thoroughly. The additional support we provide for IPv4 and IPv6 addresses is to copy the port number into the resulting structure (as a convenience).

Postcondition
The resulting sockaddr_storage structure is wrapped in std::shared_ptr (a C++ smart pointer that aids in the prevention of resource leaks).
Threads
This method is thread-safe.
Exceptions
randolf::rex::xEAI_ADDRFAMILYIf specified network host doesn't have any addresses in the specified address family
randolf::rex::xEAI_AGAINTemporary failure code from DNS server (try again later)
randolf::rex::xEAI_BADFLAGSInvalid flags in hints.ai_flags (or hints.ai_flags included AI_CANONNAME with nullptr as name)
randolf::rex::xEAI_FAILPermanent failure code from DNS server
randolf::rex::xEAI_FAMILYThe specified family is not supported
randolf::rex::xEAI_MEMORYOut of memory
randolf::rex::xEAI_NONAMEIf node_name is nullptr or an empty string
randolf::rex::xEAI_SERVICEThe specified service is not available for the specified socket type
randolf::rex::xEAI_SOCKTYPEThe specified socket type is not supported
randolf::rex::xEAI_SYSTEMOther system error (use errno to determine what the error is, then run use randolf::rex::rex::mk_exception to throw the correct exception)
Returns
sockaddr_storage structure
Parameters
node_nameIP address or UNIX domain socket address to convert
service_namePort number (or server name used by some other families)
hintsOptional pointer to a helpful addrinfo structure

◆ name() [1/2]

rsocket* randolf::rsocket::name ( const std::string  name)
inlinenoexcept

Specify a name for this rsocket.

This is an arbitrary name that is entirely optional, and should be regarded as similar to the naming of threads.

Returns
The same rsocket object so as to facilitate stacking
Parameters
nameName to assign to this rsocket

◆ name() [2/2]

std::string randolf::rsocket::name ( )
inlinenoexcept

Find out what this rsocket's name is.

The built-in SNI mechanism will overwrite this data to indicate the hostname that was specified by the TLS-encrypted endpoint that triggered an internal SNI callback – use the name_sni() method to find out which hostname is actually being used by TLS.

Returns
The name of this rsocket (or an empty std::string if this rsocket doesn't have a name)
See also
name_sni
tls_sni

◆ name_sni()

std::string randolf::rsocket::name_sni ( )
inlinenoexcept

Find out what this rsocket's actual TLS SNI hostname is.

This is the exact - or closest-matching (in the case of wildcards) - hostname associated with an actual TLS certificate that was provided in the configured rsocket_sni object.

Returns
The hostname associated with the TLS certificate selected with SNI
See also
name
tls_sni

◆ net_io() [1/2]

std::shared_ptr<rsocket_io> randolf::rsocket::net_io ( )
inlinenoexcept

Get socket I/O statistics from internally-tracked socket I/O counters.

The number of bytes transmitted and received is tracked internally, so that the information can be used later in logging. These statistics are available at all times, but for logging purposes it makes the most sense to copy this information after the rsocket is closed, at which time the final statistics will continue to be available until the rsocket's destructor takes over.

Threads
This method is threadsafe.
Returns
rsocket_io wrapped in a std::shared_ptr object to help ease memory management efforts
See also
net_io_final
net_io_update
printf

◆ net_io() [2/2]

std::string randolf::rsocket::net_io ( const char *  format,
size_t  len = 0,
rsocket_io addr = nullptr 
)
inlinenoexcept

Get socket I/O statistics from internally-tracked socket I/O counters as a pre-formatted std::string object.

The number of bytes transmitted and received is tracked internally, so that the information can be used later in logging. These statistics are available at all times, but for logging purposes it makes the most sense to copy this information after the rsocket is closed, at which time the final statistics will continue to be available until the rsocket's destructor takes over.

Formatting
The format string may contain any characters, with only instances of the following case-sensitive command sequences to be interpolated accordingly (invalid commands will be ignored and will remain in place, unmodified):
CommandReplacement textData source (rsocket_io)
$$One dollar sign ("$")N/A
$aRTotal (all) bytes receivedbytes_rx + crypt_rx
$aTTotal (all) bytes transmittedbytes_tx + crypt_tx
$bRUnencrypted bytes receivedbytes_rx
$bTUnencrypted bytes transmittedbytes_tx
$cREncrypted bytes receviedcrypt_rx
$cTEncrypted bytes transmittedcrypt_tx
CommandReplacement textData source (rsocket_io)

Why do we use dollar signs instead of percent symbols, like other formatting functions like printf() does? So that the format string won't be in conflict with any percent-prefixed commands in printf() and similar funcions. This means that a printf() format string can be put through a first pass here to get the needed statistics interpolated into the needed positions.

Threads
This method is threadsafe.
Returns
An interpolated format string as an std::string object.
See also
net_io_final
net_io_update
printf
Parameters
formatFormat string
lenLength of format string (in bytes), or 0 to auto-detect length if format string is an ASCIIZ string
addrPointer to an rsocket_io structure to read the statistics from (nullptr = use internal copy of current statistics)

◆ net_io_final()

rsocket* randolf::rsocket::net_io_final ( rsocket_io addr)
inlinenoexcept

Where the destructor should save final I/O statistics before this rsocket's resources are completely freed/deallocated.

Attention
Developers should take care to check that the rsocket_io::is_final flag is set to TRUE prior to relying on the results of the rsocket_io data since there's no guarantee that the destructor will necessarily be executed in a timely manner (this flag is set last, after all other statistics are copied into the structure while in a mutex-locked state).
Returns
The same rsocket object so as to facilitate stacking
See also
~rsocket
net_io
net_io_update
printf
Parameters
addrPointer to rsocket_io structure (nullptr = disabled)

◆ net_io_update()

rsocket* randolf::rsocket::net_io_update ( rsocket_io addr)
inlinenoexcept

Where the destructor should save current I/O statistics.

Attention
Statistics are copied into the structure while in a mutex-locked state, but the copy itself is not an overall atomic snapshot of the I/O statistics even though each statistic is copied atomically. This means that the actual statistics could be slightly different if updates occur independently (e.g., due to activities in a different thread), but this likely won't matter since the anticipated use for these statistics is to display or otherwise present general statistical information to a user at regular intervals.
Returns
The same rsocket object so as to facilitate stacking
See also
~rsocket
net_io
net_io_final
printf
Parameters
addrPointer to rsocket_io structure (nullptr = do nothing)

◆ poll()

short randolf::rsocket::poll ( const short  events = POLLIN,
const int  timeout = 0,
const bool  timeout_behaviour = TIMEOUT_EXCEPTION 
)
inline

Poll the underlying socket using the poll() method for data that's ready for receiving (default), etc.

Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Exceptions
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xETIMEDOUTTimeout period elapsed (even if the TIMEOUT_BEHAVIOUR flag is not set to TIMEOUT_EXCEPTION, there is a highly improbable chance that a timeout could still occur if the data is read by another thread before the recv(..., MSG_PEEK) call)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
The resulting (short)pollfd.revents bitfield
0 if timeout_behaviour is set to TIMEOUT_ZERO
Parameters
eventsEvents bitfield (e.g., POLLIN, POLLOUT, and POLLERR)
timeoutNumber of milliseconds to wait
timeout_behaviourTimeout behaviour (see TIMEOUT_BEHAVIOUR for details)

◆ port()

const uint16_t randolf::rsocket::port ( )
inlinenoexcept

Get port number associated with underlying socket descriptor/handle.

Returns 0 if:

  • an emphemeral port number assignment (dynamic) is intended
  • the underlying socket details are not defined (e.g., in the case of an empty rsocket instantiation)
  • port numbers are not supported/utilized by the current family (e.g., not AF_INET {IPv4} or AF_INET6 {IPv6})

The port number can be set in most constructors, or via one of the socket() or bind() methods.

Returns
Port number (typically TCP and UDP, although some other families such as SCTP and DCCP also utilize port numbers)
See also
socket_family()
socket_protocol()
socket_type()

◆ ppoll() [1/2]

short randolf::rsocket::ppoll ( const short  events = POLLIN,
const struct timespec *  tmo_p = nullptr,
const sigset_t *  sigmask = nullptr,
const bool  timeout_behaviour = TIMEOUT_EXCEPTION 
)
inline

Poll the underlying socket using the ppoll() method for data that's ready for receiving (default), etc.

Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Exceptions
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xETIMEDOUTTimeout period elapsed (even if the TIMEOUT_BEHAVIOUR flag is not set to TIMEOUT_EXCEPTION, there is a highly improbable chance that a timeout could still occur if the data is read by another thread before the recv(..., MSG_PEEK) call)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
The resulting (short)pollfd.revents bitfield
Parameters
eventsEvents bitfield (e.g., POLLIN, POLLOUT, and POLLERR)
tmo_pTimeout
sigmaskSignal mask
timeout_behaviourTimeout behaviour (see TIMEOUT_BEHAVIOUR for details)

◆ ppoll() [2/2]

short randolf::rsocket::ppoll ( const short  events = POLLIN,
const int  tv_sec = 0,
const long  tv_nsec = 0,
const sigset_t *  sigmask = nullptr,
const bool  timeout_behaviour = TIMEOUT_EXCEPTION 
)
inline

Poll the underlying socket using the ppoll() method for data that's ready for receiving (default), etc.

Note
The rsocket_mux class provides methods that support poll(), ppoll(), select(), and accept()/accept4() when using multiple sockets.
Exceptions
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xETIMEDOUTTimeout period elapsed (even if the TIMEOUT_BEHAVIOUR flag is not set to TIMEOUT_EXCEPTION, there is a highly improbable chance that a timeout could still occur if the data is read by another thread before the recv(..., MSG_PEEK) call)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
The resulting (short)pollfd.revents bitfield
Parameters
eventsEvents bitfield (e.g., POLLIN, POLLOUT, and POLLERR)
tv_secTimeout in seconds
tv_nsecTimeout in nanoseconds
sigmaskSignal mask
timeout_behaviourTimeout behaviour (see TIMEOUT_BEHAVIOUR for details)

◆ printf()

rsocket* randolf::rsocket::printf ( const char *  format,
  ... 
)
inline

Send a formatted string to the rsocket endpoint.

The format is described in the documentation for the POSIX or Standard C Library printf() function.

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEILSEQAn invalid wide-character code was detected
randolf::rex::xEOVERFLOWThe value returned is greater than {INT_MAX}
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENOMEMInsufficient memory
Returns
The same rsocket object so as to facilitate stacking
See also
eol_fix_printf
is_eol_fix_printf
net_io
printfline
vprintf
vprintfline
Parameters
formatFormat string to use
...Variadic arguments

◆ printfline()

rsocket* randolf::rsocket::printfline ( const char *  format,
  ... 
)
inline

Send a formatted string to the rsocket endpoint, and append an EoL sequence.

The format is described in the documentation for the POSIX or Standard C Library printf() function.

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEILSEQAn invalid wide-character code was detected
randolf::rex::xEOVERFLOWThe value returned is greater than {INT_MAX}
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENOMEMInsufficient memory
Returns
The same rsocket object so as to facilitate stacking
See also
eol
eol_fix_printf
is_eol_fix_printf
net_io
printf
sendline
vprintf
vprintfline
Parameters
formatFormat string to use
...Variadic arguments

◆ recv() [1/2]

std::vector<char> randolf::rsocket::recv ( const size_t  nbytes = 0,
const int  flags = 0 
)
inline

Receive data from the endpoint into a std::vector<char> that is allocated on-the-fly.

If nbytes is 0, then the internal buffer_size() will be used as the default, which can also be changed from its compiled-in default of 1024 by using one of the buffer_size() methods.

Notes
The MSG_WAITALL flag is particularly useful for preventing premature data reception, but it's important to note that it does implement temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
appropriately-sized vector of characters
See also
recv(std::vector<char>, const int)
recvz(const size_t, const int)
Parameters
nbytesMaximum number of bytes to receive
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv() [2/2]

std::vector<char> randolf::rsocket::recv ( std::vector< char >  buf,
const int  flags = 0 
)
inline

Receive data from the endpoint into the std::vector object supplied in the buf parameter.

The maximum number of bytes that can be received won't exceed the number of bytes that the supplied std::vector<char> was initialized or resized to.

Precondition
For std::vector it's important that the resize() method is used to pre-allocate the underlying char[] array, instead of the unfortunately-named reserve() method that doesn't pre-allocate, to avoid causing segmentation faults or other undefined behaviours.
Notes
The MSG_WAITALL flag is particularly useful for preventing premature data reception, but it's important to note that it does implement temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
The same array that was specified in the buf parameter
See also
recv(const size_t, const int)
recvz(const size_t, const int)
Parameters
bufTarget std::vector<char> to receive data into
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_asciiz()

char* randolf::rsocket::recv_asciiz ( const size_t  nbytes = 0,
const int  flags = 0 
)
inline

Receive an ASCIIZ string from the endpoint, including the NULL terminator.

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xERANGEif no NULL terminator is detected (this may occur before the underlying ASCIIZ string char* array is allocated)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
Pointer to ASCIIZ string (will need to be deleted by caller)
See also
send_asciiz(const char*, const int)
Parameters
nbytesMaximum number of bytes to receive
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_byte()

char randolf::rsocket::recv_byte ( const int  flags = 0)
inline

Receive one byte of data from the endpoint.

Notes
The MSG_WAITALL flag is particularly useful for preventing premature data reception, but it's important to note that it does implement temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
appropriately-sized vector of characters
See also
recv(std::vector<char>, const int)
recvz(const size_t, const int)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_struct()

template<typename T >
T randolf::rsocket::recv_struct ( const int  flags = 0)
inline

Receive a data structure from the endpoint.

Postcondition
MSB/LSB considerations are important for any integers within your structure, so be sure to sanitize them with htons(), ntohs(), and related methods prior to sending, and then after receiving. This way, your data will be protected against corruption resulting from byte order differences when communicating between hardware architectures that differ in MSB and LSB byte ordering.
Notes
The MSG_WAITALL flag is particularly useful for preventing premature data reception, but it's important to note that it does implement temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
Data structure
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_uint16_lsb()

uint16_t randolf::rsocket::recv_uint16_lsb ( const int  flags = 0)
inline

Receive one 16-bit unsigned integer of data in LSB (little endian) order from the endpoint.

Notes
The MSG_WAITALL flag is used behind-the-scenes to prevent premature data reception, which implements temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
uint16_t (converted to local endianness)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_uint16_msb()

uint16_t randolf::rsocket::recv_uint16_msb ( const int  flags = 0)
inline

Receive one 16-bit unsigned integer of data in MSB (big endian) order from the endpoint.

Notes
The MSG_WAITALL flag is used behind-the-scenes to prevent premature data reception, which implements temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
uint16_t (converted to local endianness)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_uint32_lsb()

uint32_t randolf::rsocket::recv_uint32_lsb ( const int  flags = 0)
inline

Receive one 32-bit unsigned integer of data in LSB (little endian) order from the endpoint.

Notes
The MSG_WAITALL flag is used behind-the-scenes to prevent premature data reception, which implements temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
uint32_t (converted to local endianness)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_uint32_msb()

uint32_t randolf::rsocket::recv_uint32_msb ( const int  flags = 0)
inline

Receive one 32-bit unsigned integer of data in MSB (big endian) order from the endpoint.

Notes
The MSG_WAITALL flag is used behind-the-scenes to prevent premature data reception, which implements temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
uint32_t (converted to local endianness)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_uint64_lsb()

uint64_t randolf::rsocket::recv_uint64_lsb ( const int  flags = 0)
inline

Receive one 64-bit unsigned integer of data in LSB (little endian) order from the endpoint.

Notes
The MSG_WAITALL flag is used behind-the-scenes to prevent premature data reception, which implements temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
uint64_t (converted to local endianness)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recv_uint64_msb()

uint64_t randolf::rsocket::recv_uint64_msb ( const int  flags = 0)
inline

Receive one 64-bit unsigned integer of data in MSB (big endian) order from the endpoint.

Notes
The MSG_WAITALL flag is used behind-the-scenes to prevent premature data reception, which implements temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
uint64_t (converted to local endianness)
Parameters
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recvfrom()

std::vector<char> randolf::rsocket::recvfrom ( const size_t  nbytes,
const int  flags,
struct sockaddr *  from,
socklen_t  fromlen = sizeof(sockaddr) 
)
inline

Receive data from a specific endpoint.

Notes
The MSG_WAITALL flag is particularly useful for preventing premature data reception, but it's important to note that it does implement temporary blocking while waiting for data.
Warning
This method is not compatible with TLS.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
Appropriately-sized vector of characters
Parameters
nbytesMaximum number of bytes to receive
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC
fromTarget endpoint address structure
fromlenSize of target endpoint structure

◆ recvline()

std::string randolf::rsocket::recvline ( const size_t  nbytes = 0,
const int  flags = 0,
long  timeout = 0 
)
inline

Receive a line of data from the endpoint, with the EoL character(s) removed. This is meant for binary data that isn't expected to always be plain text.

If nbytes is 0, then the internal buffer_size will be used as the default, which can also be changed from its compiled-in default of 1024 by using one of the buffer_size() methods.

Internally, the length of the eol() sequence is added to the buffer size so that the maximum line length without EoL characters matches the maximum that was specified with buffer_size() or with the nbytes parameter.

Notes
If you're searching for a readline() method for socket I/O, then this is most likely what you're wanting/needing.
Precondition
When setting the recvline timeout (either with the timeout parameter with this method, or by using the timeout_recvline(long) method), you may also need to set the socket timeout beforehand using the timeout() method, because recvline doesn't do this...

timeout_recvline sets the overall total timeout for an entire line to be entered
timeout sets the timeout between individual characters received (such as keystrokes from a live end-user)


If your socket timeout is longer than then recvline timeout, this will have the effect of rendering the recvling timeout as ineffective.
Exceptions
randolf::rex::xEAGAINif timeout occurs before EoL
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xERANGEif the timeout parameter is below 0
randolf::rex::xEOVERFLOWif no EoL character sequence is detected after recvline's buffer became full (whatever data is waiting may still be received using any of the recv_ methods with or without the MSG_PEEK flag set, including recvline() with a larger buffer size specified with the nbytes parameter)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
One line of text as a std::string object.
See also
eol()
sendline(const std::string, const int)
timeout
timeout_recvline
Parameters
nbytesMaximum number of bytes to receive
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC
timeoutTotal overall timeout (in seconds) for receiving a line
0 = whatever timeout_recvline() is configured to (the unconfigured default is 0, which effectively means no timeout)

◆ recvmsg()

msghdr* randolf::rsocket::recvmsg ( msghdr *  msg,
const int  flags = 0 
)
inline

Receive data in the form of a "msghdr" structure.

Warning
This method is not compatible with TLS.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
pointer to "msghdr" structure
Parameters
msgPointer to "msghdr" structure (or nullptr for automatic allocation)
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ recvmmsg()

mmsghdr* randolf::rsocket::recvmmsg ( struct mmsghdr *  mmsg,
const unsigned int  vlen = sizeof(mmsghdr),
const int  flags = 0,
struct timespec *  timeout = {0} 
)
inline

Receive data in the form of an "mmsghdr" structure.

Warning
This method is not compatible with TLS.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
pointer to "mmsghdr" structure
Parameters
mmsgPointer to "mmsghdr" structure (or nullptr for automatic allocation)
vlenSize of target endpoint structure
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB
timeoutTimeout

◆ recvz()

std::vector<char> randolf::rsocket::recvz ( const size_t  nbytes = 0,
const int  flags = 0 
)
inline

Receive data from the endpoint, and add a 0 (null) onto the end. This is useful when using the resulting std::vector<char> as an ASCIIZ string.

If nbytes is 0, then the internal buffer_size will be used as the default, which can also be changed from its compiled-in default of 1024 by using one of the buffer_size() methods.

Postcondition
The resulting std::vector size is always inflated by 1. This means that relying on a comparison against 0 will result in an infinite loop:
for (std::vector<char> v = r.recvz(); v.size > 0; v = recvz()) { ... }
std::vector< char > recvz(const size_t nbytes=0, const int flags=0)
Receive data from the endpoint, and add a 0 (null) onto the end. This is useful when using the result...
Definition: rsocket:5283
So, you'll need to compare against 1 instead of 0 to compensate fot the inflated size due to the addition of null character 0:
for (std::vector<char> v = r.recvz(); v.size > 1; v = recvz()) { ... }
Warning
The resulting size of std::vector<char> will be nbytes + 1 which ensures that any string processing functions or presentation libraries - such as printf() - expecting an ASCIIZ string buffer will stop at null (0), and will reliably output no more than the maximum size specified.

The way to think of this is that nbytes specifies the maximum number of bytes (a.k.a., characters) to recieve over the underlying socket, and the final 0 (null) being added is not included in the maximum specified by the nbytes parameter.
Notes
The MSG_WAITALL flag is particularly useful for preventing premature data reception, but it's important to note that it does implement temporary blocking while waiting for data.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNREFUSEDRemote address is not listening for new connections
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
Returns
appropriately-sized vector of characters + 1 (includes additional null terminator character 0)
See also
recv(const size_t, const int)
recv(std::vector<char>, const int)
Parameters
nbytesMaximum number of bytes to receive
flagsMSG_OOB
MSG_PEEK
MSG_WAITALL
MSG_DONTWAIT
MSG_CMSG_CLOEXEC

◆ send() [1/3]

rsocket* randolf::rsocket::send ( const std::string  msg,
const int  flags = 0 
)
inline

Send data in the form of a std::string to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send() [2/3]

rsocket* randolf::rsocket::send ( const std::vector< char >  msg,
const int  flags = 0 
)
inline

Send data in the form of a std::vector<char> to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send() [3/3]

rsocket* randolf::rsocket::send ( const char *  msg,
size_t  len = 0,
const int  flags = 0 
)
inline

Send data in the form of a C-string to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgPointer to data to send
lenNumber of bytes to send, or 0 to auto-detect length if message is an ASCIIZ string
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_asciiz()

rsocket* randolf::rsocket::send_asciiz ( const char *  msg,
const int  flags = 0 
)
inline

Send data in the form of an ASCIIZ string to the endpoint, including the terminating NULL character.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
See also
recv_asciiz(const size_t, const int)
sendz(const char*, const int) which doesn't transmit the terminating NULL character
Parameters
msgPointer to data to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_byte()

rsocket* randolf::rsocket::send_byte ( const char  value,
const int  flags = 0 
)
inline

Send one byte of data to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_eol()

rsocket* randolf::rsocket::send_eol ( const int  flags = 0)
inline

Send the EoL sequence to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_struct()

template<typename T >
rsocket* randolf::rsocket::send_struct ( const T  value,
const int  flags = 0 
)
inline

Send one byte of data to the endpoint.

Precondition
MSB/LSB considerations are important for any integers within your structure, so be sure to sanitize them with htons(), ntohs(), and related methods prior to sending, and then after receiving. This way, your data will be protected against corruption resulting from byte order differences when communicating between hardware architectures that differ in MSB and LSB byte ordering.
Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_uint16_lsb()

rsocket* randolf::rsocket::send_uint16_lsb ( const uint16_t  value,
const int  flags = 0 
)
inline

Send one 16-bit unsigned integer of data in LSB (little endian) order to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_uint16_msb()

rsocket* randolf::rsocket::send_uint16_msb ( const uint16_t  value,
const int  flags = 0 
)
inline

Send one 16-bit integer of data in MSB (big endian) order to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_uint32_lsb()

rsocket* randolf::rsocket::send_uint32_lsb ( const uint32_t  value,
const int  flags = 0 
)
inline

Send one 32-bit unsigned integer of data in LSB (little endian) order to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_uint32_msb()

rsocket* randolf::rsocket::send_uint32_msb ( const uint32_t  value,
const int  flags = 0 
)
inline

Send one 32-bit unsigned integer of data in MSB (big endian) order to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_uint64_lsb()

rsocket* randolf::rsocket::send_uint64_lsb ( const uint64_t  value,
const int  flags = 0 
)
inline

Send one 64-bit unsigned integer of data in LSB (little endian) order to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ send_uint64_msb()

rsocket* randolf::rsocket::send_uint64_msb ( const uint64_t  value,
const int  flags = 0 
)
inline

Send one 64-bit unsigned integer of data in MSB (big endian) order to the endpoint.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
valueData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ sendline()

rsocket* randolf::rsocket::sendline ( const std::string  msg = std::string(),
const int  flags = 0 
)
inline

Send data in the form of a std::string to the endpoint, with an EoL sequence appended.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
See also
eol
printfline
recvline(const size_t, const int)
vprintfline
Parameters
msgData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ sendmsg()

rsocket* randolf::rsocket::sendmsg ( const struct msghdr *  msg,
const int  flags = 0 
)
inline

Send data in the form of a "msghdr" structure to a specific endpoint.

Warning
This method is not compatible with TLS.
Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgPointer to data to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ sendmmsg()

rsocket* randolf::rsocket::sendmmsg ( struct mmsghdr *  mmsg,
const unsigned int  vlen = sizeof(mmsghdr),
const int  flags = 0 
)
inline

Send data in the form of a "mmsghdr" structure to a specific endpoint.

Warning
This method is not compatible with TLS.
Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
mmsgPointer to data to send
vlenSize of target endpoint structure
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ sendto() [1/2]

rsocket* randolf::rsocket::sendto ( const std::string  msg,
const int  flags,
const struct sockaddr *  to,
socklen_t  tolen = sizeof(sockaddr) 
)
inline

Send data in the form of a std::string to a specific endpoint.

Warning
This method is not compatible with TLS.
Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgData to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB
toTarget endpoint address structure
tolenSize of target endpoint structure

◆ sendto() [2/2]

rsocket* randolf::rsocket::sendto ( const char *  msg,
const size_t  len,
const int  flags,
const struct sockaddr *  to,
socklen_t  tolen = sizeof(sockaddr) 
)
inline

Send data in the form of a C-string to a specific endpoint.

Warning
This method is not compatible with TLS.
Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgPointer to data to send
lenNumber of bytes to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB
toTarget endpoint address structure
tolenSize of target endpoint structure

◆ sendz()

rsocket* randolf::rsocket::sendz ( const char *  msg,
const int  flags = 0 
)
inline

Send data in the form of an ASCIIZ string to the endpoint. The terminating NULL character won't be transmitted.

Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
See also
recvz(const size_t, const int)
send_asciiz(const char*, const int) which also transmits the terminating NULL character
Parameters
msgPointer to data to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB

◆ sendzto()

rsocket* randolf::rsocket::sendzto ( const char *  msg,
const int  flags,
const struct sockaddr *  to,
socklen_t  tolen = sizeof(sockaddr) 
)
inline

Send data in the form of an ASCIIZ string to a specific endpoint. The terminating NULL character won't be transmitted.

Warning
This method is not compatible with TLS.
Threads
This method is threadsafe.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xECONNRESETConnect reset by peer
randolf::rex::xEDESTADDRREQSocket is not connected to an endpoint
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINTRInterrupted by a signal
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xEISCONNSocket is already connected (this shouldn't occur, but the POSIX sockets documentation lists it as one of the errors that can be returned, perhaps because some incorrectly implemented TCP/IP stacks return this error?)
randolf::rex::xEMSGSIZEMessage data exceeds the maximum size to be sent atomically (the maximum size is typically 65,507 bytes for IPv4 and 65,527 bytes for IPv6)
randolf::rex::xENOBUFSOutput queue is full, mostly likely due to network congestion (or, less commonly, insufficient memory)
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
randolf::rex::xEOPNOTSUPPUnderlying socket is no of type SOCK_STREAM
randolf::rex::xEPIPEConnection-oriented socket was shut down on the local end (and SIGPIPE will also be received if MSG_NOSIGNAL isn't set)
randolf::rex::xEWOULDBLOCKThe underlying socket is non-blocking and there's no new data
randolf::rex::xEWOULDBLOCKNo ephemeral ports are available for assignment to unbound socket (should be randolf::rex::xEADDRNOTAVAIL, but it really isn't)
Returns
The same rsocket object so as to facilitate stacking
Parameters
msgPointer to data to send
flagsMSG_DONTROUTE
MSG_DONTWAIT
MSG_EOR
MSG_NOSIGNAL
MSG_OOB
toTarget endpoint address structure
tolenSize of target endpoint structure

◆ setsockopt() [1/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const int  value 
)
inline

Set socket option to the specific integer.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe value that this socket option will be set to

◆ setsockopt() [2/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const u_int  value 
)
inline

Set socket option to the specific unsigned integer.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Precondition
For any values that require a u_int, you'll need to explicitly cast this type when specifying the value directly; for example: (u_int)32768
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe value that this socket option will be set to

◆ setsockopt() [3/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const u_char  value 
)
inline

Set socket option to the specific unsigned character.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe value that this socket option will be set to

◆ setsockopt() [4/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const linger &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [5/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const timeval &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [6/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const in_addr &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [7/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const ip_mreq &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [8/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const ip_mreq_source &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [9/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const icmp6_filter &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [10/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const sockaddr_in6 &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [11/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const ip6_mtuinfo &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [12/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const ipv6_mreq &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [13/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const group_req &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ setsockopt() [14/14]

rsocket* randolf::rsocket::setsockopt ( const int  level,
const int  option,
const group_source_req &  value 
)
inline

Set socket option to the specific structure.

Notes
These setsockopt() methods take an integer or character value directly, or a pointer to a structure, and then rsocket handles the remaining tedious technical details behind-the-scenes for you when calling the underlying socket's setsockopt() function.
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
levelThe level at which the option resides; typically SOL_SOCKET
optionThe name of the option, such as SO_REUSEADDR, SO_LINGER, etc.
valueThe structure that this socket option will be set to

◆ shutdown()

rsocket* randolf::rsocket::shutdown ( const int  how = SHUT_RDWR)
inline

Shut down the underlying socket, partially or fully.

SHUT_RD: Further receives will be disallowed SHUT_WR: Further sends will be disallowed (this may cause actions specific to the protocol family of the socket to occur) SHUT_RDWR: Further sends and receives will be disallowed (default)

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEINVALInvalid argument passed
randolf::rex::xENOTCONNUnderlying socket is not connected
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
howSHUT_RD
SHUT_RW
SHUT_RDWR

◆ socket()

rsocket* randolf::rsocket::socket ( const int  family,
const int  type = SOCK_STREAM,
const int  protocol = PF_UNSPEC 
)
inline

Complete the configuration of an rsocket that was previously initialized without any parameters (a.k.a., an "empty rsocket").

Instantiating an empty rsocket is particularly useful for header-file definitions since exceptions can't be handled outside of subroutines, and it's also useful for enabling debug() mode before setting the socket's configuration with one of the socket() methods; for example:

randolf::rsocket r; // Empty rsocket (empty / incomplete initialization)
r.debug(true); // Enable debug mode
r.socket(...); // Required to complete rsocket initialization
Notes

The built-in defaults, when not provided, are as follows ("family" is also known as the "communication domain"):

  • family = AF_INET
  • type = SOCK_STREAM
  • protocol = PF_UNSPEC

You will need to use one of the socket(...) methods to specify socket details after defining rsocket objects with empty constructors so that you can catch runtime exceptions. (This also provides you with an option to enable debug mode during runtime prior to attempting to open an rsocket.)

Examples
#include <iostream> // std::cout, std::cerr, std::endl, etc.
#include <randolf/rex>
#include <randolf/rsocket>
randolf::rsocket r; // <-- Empty rsocket initialization (no exceptions)
int main(int argc, char *argv[]) {
try {
r.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // <-- Required to complete rsocket initialization
r.setsockopt(SOL_SOCKET, SO_REUSEADDR, true);
// ... other socket I/O operations
r.close();
} catch (const randolf::rex::xALL e) {
std::cerr << "Socket exception: " << e.what() << std::endl;
return EXIT_FAILURE;
} catch (const std::exception e) {
std::cerr << "Other exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} // -x- int main -x-
See also
rsocket()
socket()
socket_family()
socket_fd()
socket_protocol()
socket_type()
Exceptions
randolf::rex::xEACCESElevated access is needed to open this socket
randolf::rex::xEAFNOSUPPORTAddress family not implemented/supported
randolf::rex::xEALREADYIf this socket() method was already used, or it was used after rsocket() initialized with at least one parameter
randolf::rex::xEINVALProtocal family invalid or not available
randolf::rex::xEINVALInvalid flags in type
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENFILESystem-wide maximum open files limit reached
randolf::rex::xENOBUFSInsufficient memory
randolf::rex::xENOMEMInsufficient memory
randolf::rex::xEPROTONOSUPPORTSpecified type or protocol is not supported within the specified family (a.k.a., communication domain)
Returns
The same rsocket object so as to facilitate stacking
See also
rsocket()
socket_family()
socket_fd()
socket_protocol()
socket_type()
Parameters
familyCommunication domain; usually one of:
AF_INET (IPv4)
AF_INET6 (IPv6)
AF_UNIX (UNIX domain sockets)
typeCommunication semantics; usually one of:
SOCK_STREAM (common for TCP)
SOCK_DGRAM (common for UDP)
protocolNetwork protocol; usually one of:
IPPROTO_TCP
IPPROTO_UDP
IPPROTO_IP
PF_UNSPEC (auto-detect)

◆ socket_family()

const int randolf::rsocket::socket_family ( )
inlinenoexcept

Get underlying socket family/domain constant (SO_DOMAIN).

Returns
socket family/domain constant
See also
port()
socket()
socket_fd()
socket_protocol()
socket_type()

◆ socket_fd() [1/2]

const int randolf::rsocket::socket_fd ( )
inlinenoexcept

Get underlying socket descriptor/handle.

Returns
socket descriptor/handle
0 = socket not yet allocated
See also
port()
socket()
socket_family()
socket_protocol()
socket_type()

◆ socket_fd() [2/2]

rsocket* randolf::rsocket::socket_fd ( const int  new_socket_fd)
inline

Set underlying socket descriptor/handle (to one that is presumed to be open).

Note
This method is only available while an underlying socket has not been created or previously assigned, such as after an empty rsocket instantiation.
Exceptions
randolf::rex::xEALREADYIf this socket_fd() method was already used, or it was used after socket() initialized it, or if rsocket() had initialized with at least one parameter that resulted in the creation of an underlying socket
Returns
The same rsocket object so as to facilitate stacking
See also
socket()
socket_family()
socket_protocol()
socket_type()
Parameters
new_socket_fdNew socket descriptor/handle

◆ socket_protocol()

const int randolf::rsocket::socket_protocol ( )
inlinenoexcept

Get underlying socket protocol constant (SO_PROTOCOL).

Returns
socket protocol constant
See also
port()
socket()
socket_family()
socket_fd()
socket_type()

◆ socket_type()

const int randolf::rsocket::socket_type ( )
inlinenoexcept

Get underlying socket type constant (SO_TYPE).

Returns
socket type constant
See also
port()
socket()
socket_family()
socket_fd()
socket_protocol()

◆ sockatmark()

const bool randolf::rsocket::sockatmark ( )
inline

Find out whether the underlying socket is at the out-of-band (OOB) mark.

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEINVALThe underlying socket file descriptor is not a type to which sockatmark() can be applied
Returns
TRUE = at OOB mark
FALSE = not at OOB mark

◆ timeout() [1/3]

std::shared_ptr<timeval> randolf::rsocket::timeout ( )
inline

Find out what the read timeout is set to on the current socket.

Since getting the read timeout is such a common operation, this specialized method was created to ease software development efforts; internally we're just calling getsockopt_timeval(SOL_SOCKET, SO_RCVTIMEO).

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
timeval socket option structure wrapped in std::shared_ptr

◆ timeout() [2/3]

rsocket* randolf::rsocket::timeout ( const struct timeval  tv)
inline

Set the recv timeout on the current socket.

Since setting the read timeout is such a common operation, this specialized method was created to ease software development efforts; internally we're just calling setsockopt(SOL_SOCKET, SO_RCVTIMEO, timeval).

Attention
Although a timeout of 100,000 microseconds (1/10 of a one second) may suffice in healthy and efficient networks, a more conservative setting of 1 second tends to minimally yield more reliable results. Many end-user applications use defaults of 3 to 5 seconds to cover a wider variety of unpredictable network connections (such as over shared wireless connections that are slow), and this setting should ultimately be configurable by users/administrators.
Note
The default timeout for new sockets is normally 0 (no timeout).
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
tvtimeval structure

◆ timeout() [3/3]

rsocket* randolf::rsocket::timeout ( const int  tv_sec = 0,
const long  tv_usec = 0 
)
inline

Set the recv timeout on the current socket.

Since setting the read timeout is such a common operation, this specialized method was created to ease software development efforts; internally we're just calling setsockopt(SOL_SOCKET, SO_RCVTIMEO, timeval).

Attention
Although a timeout of 100,000 microseconds (1/10 of a one second) may suffice in healthy and efficient networks, a more conservative setting of 1 second tends to minimally yield more reliable results. Many end-user applications use defaults of 3 to 5 seconds to cover a wider variety of unpredictable network connections (such as over shared wireless connections that are slow), and this setting should ultimately be configurable by users/administrators.
Note
The default timeout for new sockets is normally 0 (no timeout).
Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEFAULTAddress structure/memory is not in a writable part of the user address space
randolf::rex::xEINVALAddress length is incorrect, or address is not valid for this socket's family (a.k.a., communication domain)
randolf::rex::xENOPROTOOPTEither the level or the specified optname is not supported
randolf::rex::xENOTSOCKUnderlying socket file descriptor (handle) doesn't refer to a socket
Returns
The same rsocket object so as to facilitate stacking
Parameters
tv_secTimeout in seconds
tv_usecTimeout in microseconds

◆ timeout_recvline() [1/2]

long randolf::rsocket::timeout_recvline ( )
inline

Find out what the read timeout is set to when using the recvline() method.

Returns
long value (0 = unlimited)

◆ timeout_recvline() [2/2]

rsocket* randolf::rsocket::timeout_recvline ( const long  timeout)
inline

Set the read timeout for the recvline() method when that method's timeout parameter is set to 0.

Note
The default timeout for this recvline_timeout setting is 0 (no timeout).
Exceptions
randolf::rex::xERANGEif the timeout parameter is below 0
Returns
The same rsocket object so as to facilitate stacking
Parameters
timeouttimeval structure

◆ tls()

rsocket* randolf::rsocket::tls ( const bool  status = true,
const int  flags = TLS_FLAGS::TLS_DEFAULT 
)
inline

Enable or disable encrypted communications (from the OpenSSL library).

Warning
TLS cannot be enabled before a non-encrypted rsocket is open (an rsocket is typically opened with the socket() method, the connect() method, or one of the accept() methods). If calling tls(true) on an rsocket that isn't open, an exception will be thrown.

If needed, a new TLS context will be instantiated and TLS will be initialized (if this hasn't already been done). TLS instantiation can be done first by calling the tls_ctx() method (regardless of whether encryption is being enabled or disabled). If the default TLS_FLAGS aren't sufficient for the needs of your application, then the tls_ctx() method facilitates this regardless of wehther rsocket is open.

Note
The reason a TLS context is instantiated and TLS is initialized even when the status is being set to FALSE is to facilitate TLS ingress from an unencrypted connection later in the session (see the TLS_NO_INGRESS flag for more information).
Postcondition
If a client attempts to upgrade a TLS connection to TLS (e.g., by using a command such as STARTTLS, which is commonly transmitted unencrypted form, like telnet-ssl does – using telnet-ssl -z ssl prevents this condition), the following error that's difficult to track down may be triggered when calling any of the recv methods (I hope that including this information here in this documentation will be helpful):
SSL_ERROR_UNKNOWN: error:0A00010B:SSL routines::wrong version number
This is most likely not a programming error, but rather a problem with how users may attempt to mis-use a connection based on a misunderstanding of the communications requirements (e.g., connecting unencrypted and attempting to upgrade to TLS over a connection that's expecting only TLS encrypted data).
Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
is_tls
tls_ctx
Parameters
statusTRUE = Enable encrypted communications
FALSE = Disable encrypted communications
flagsConfiguration parameters

◆ tls_ctx() [1/3]

SSL_CTX* randolf::rsocket::tls_ctx ( )
inlinenoexcept

Return the current TLS context (multiple TLS contexts are supported, although typically needed to support SNI with inbound connections).

Returns
Pointer to OpenSSL's context (normally labelled SSL_CTX* in the documentation for OpenSSL), or nullptr if this context was never assigned to (or created by) this rsocket
See also
tls_ctx

◆ tls_ctx() [2/3]

rsocket* randolf::rsocket::tls_ctx ( rsocket rtemplate,
const int  flags = TLS_FLAGS::TLS_DEFAULT 
)
inline

Copy the source rsocket's TLS context map and add it to this rsocket's collection; or, if the source doesn't have any TLS contexts and this rsocket doesn't have any TLS contexts in its collection, then initialize TLS and instantiate a new TLS context. In either scenario, the source rsocket will be treated as a template as all TLS flags duplicated to enable encrypted socket I/O for use in this rsocket().

Note
At least one TLS context is needed to enable encrypted socket I/O for use in this rsocket().
Postcondition
Encrypted socket I/O is only possible after a TLS context has been initialized (this is not a global setting as it has per-rsocket specificity).
Note
The only TLS_FLAGS flag that doesn't get transferred is TLS_SERVER when no flags are specified. Specifying any flag(s) will cause this method to ignore the source rsocket's TLS flags so as to defer to this override.
Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_sni
Parameters
rtemplateOpenSSL's TLS context to use (if not provided, a new context will be created automatically using OpenSSL's defaults)
flagsConfiguration parameters

◆ tls_ctx() [3/3]

rsocket* randolf::rsocket::tls_ctx ( SSL_CTX *  ctx,
const int  flags = TLS_FLAGS::TLS_DEFAULT 
)
inline

Initialize TLS and instantiate a TLS context, and add it to this rsocket's current collection of TLS contexts, and set it as the currently active TLS context (so that a certificate chain and private key may be added to it).

Note
At least one TLS context is needed to enable encrypted socket I/O for use in this rsocket().
Postcondition
Encrypted socket I/O is only possible after a TLS context has been initialized (this is not a global setting as it has per-rsocket specificity).
Note
This is the default TLS context for this rsocket, which will also be used for non-SNI handshakes.
Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_sni
Parameters
ctxOpenSSL's TLS context to use (if not provided, a new context will be created using OpenSSL's defaults)
flagsConfiguration parameters

◆ tls_ctx_check_privatekey()

rsocket* randolf::rsocket::tls_ctx_check_privatekey ( )
inline

Check the private key it to ensure it's consistent with the corresponding TLS certificate chain.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_privatekey_file
tls_ctx_use_privatekey_pem

◆ tls_ctx_use_certificate_chain_and_privatekey_files() [1/2]

rsocket* randolf::rsocket::tls_ctx_use_certificate_chain_and_privatekey_files ( const char *  chain_file,
const char *  key_file 
)
inline

Load a TLS certificate chain and private key in PEM format from text files and use them in the TLS context.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_certificate_chain_and_privatekey_pems
tls_ctx_use_certificate_chain_file
tls_ctx_use_certificate_chain_pem
tls_ctx_use_privatekey_file
tls_ctx_use_privatekey_pem
tls_ctx_check_privatekey
Parameters
chain_filePointer to ASCIIZ path and filename to certificate chain file (nullptr will simply be ignored)
key_filePointer to ASCIIZ path and filename to private key file (nullptr will simply be ignored)

◆ tls_ctx_use_certificate_chain_and_privatekey_files() [2/2]

rsocket* randolf::rsocket::tls_ctx_use_certificate_chain_and_privatekey_files ( const std::string  chain_file,
const std::string  key_file 
)
inline

Load a TLS certificate chain and private key in PEM format from text files and use them in the TLS context.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_certificate_chain_and_privatekey_pems
tls_ctx_use_certificate_chain_file
tls_ctx_use_certificate_chain_pem
tls_ctx_use_privatekey_file
tls_ctx_use_privatekey_pem
tls_ctx_check_privatekey
Parameters
chain_filePointer to ASCIIZ path and filename to certificate chain file (an empty string will simply be ignored)
key_filePointer to ASCIIZ path and filename to private key file (an empty string will simply be ignored)

◆ tls_ctx_use_certificate_chain_and_privatekey_pems()

rsocket* randolf::rsocket::tls_ctx_use_certificate_chain_and_privatekey_pems ( const char *  cert_pem_data,
const char *  key_pem_data,
size_t  cert_len = 0,
size_t  key_len = 0,
const bool  random_fill = true 
)
inline

Load a TLS certificate chain and a TLS private key in PEM format from memory and use them in the TLS context.

Although this functionality doesn't exist in OpenSSL (at the time of writing this method), it's provided here in a manner that has exactly the same effect as the tls_ctx_use_certificate_chain_and_privatekey_files() methods, but without needing the PEM-formatted certificate chain stored in files beforehand.

Note
The cert_pem_data and key_pem_data parameters are pointers to the memory locations that holds the PEM formatted certificate chain data and private key data, respectively. If the corresponding lengths of each of these data aren't specified or are set to zero (default), then they will be treated as multiline ASCIIZ strings.

Behind the scenes, we're just writing the cert_pem_data and key_pem_data memory to temporary files with severely-limited permissions (), then optionally overwriting those temporary files with random data prior to deleting them (this is the default, since better security practices should be the default, but on a secured system it may not be necessary and so this option can also be disabled to save CPU cycles and reduce overall disk-write I/O operations).

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_certificate_chain_and_privatekey_files
tls_ctx_use_certificate_chain_file
tls_ctx_use_certificate_chain_pem
tls_ctx_use_privatekey_file
tls_ctx_use_privatekey_pem
tls_ctx_check_privatekey
Parameters
cert_pem_dataPointer to certificate chain data in PEM format
key_pem_dataPointer to private key data in PEM format
cert_lenLength of cert_pem_data (in bytes), or 0 to auto-detect length if cert_pem_data is an ASCIIZ string
key_lenLength of key_pem_data (in bytes), or 0 to auto-detect length if key_pem_data is an ASCIIZ string
random_fillWhether to overwrite the temporary files with random data before deleting them

◆ tls_ctx_use_certificate_chain_file() [1/2]

rsocket* randolf::rsocket::tls_ctx_use_certificate_chain_file ( const char *  file)
inline

Load a TLS certificate chain in PEM format from a text file and use it in the TLS context.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_certificate_chain_file
tls_ctx_use_certificate_chain_pem
tls_ctx_check_privatekey
Parameters
filePointer to ASCIIZ path and filename to certificate chain file

◆ tls_ctx_use_certificate_chain_file() [2/2]

rsocket* randolf::rsocket::tls_ctx_use_certificate_chain_file ( const std::string  file)
inline

Load a TLS certificate chain in PEM format from a text file and use it in the TLS context.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_certificate_chain_file
tls_ctx_use_certificate_chain_pem
tls_ctx_check_privatekey
Parameters
filePath and filename to certificate chain file

◆ tls_ctx_use_certificate_chain_pem()

rsocket* randolf::rsocket::tls_ctx_use_certificate_chain_pem ( const char *  pem_data,
size_t  len = 0,
const bool  random_fill = true 
)
inline

Load a TLS certificate chain in PEM format from memory and use it in the TLS context.

Although this functionality doesn't exist in OpenSSL (at the time of writing this method), it's provided here in a manner that has exactly the same effect as the tls_ctx_use_certificate_chain_file() methods, but without needing the PEM-formatted certificate chain stored in a file beforehand.

Note
The pem_data parameter is a pointer to the memory location that holds the PEM formatted certificate chain data. If the length of this data isn't specified or is set to zero (default), then it will be treated as a multiline ASCIIZ string.

Behind the scenes, we're just writing the pem_data memory to a temporary file with severely-limited permissions (), then optionally overwriting that temporary file with random data prior to deleting it (this is the default, since better security practices should be the default, but on a secured system it may not be necessary and so this option can also be disabled to save CPU cycles and reduce overall disk-write I/O operations).

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_certificate_chain_file
tls_ctx_check_privatekey
Parameters
pem_dataPointer to certificate chain data in PEM format
lenLength of pem_data (in bytes), or 0 to auto-detect length if pem_data is an ASCIIZ string
random_fillWhether to overwrite the temporary file with random data before deleting it

◆ tls_ctx_use_privatekey_file() [1/2]

rsocket* randolf::rsocket::tls_ctx_use_privatekey_file ( const char *  file)
inline

Load a TLS private key in PEM format from a text file and use it in the TLS context.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_privatekey_file
tls_ctx_use_privatekey_pem
tls_ctx_check_privatekey
Parameters
filePointer to ASCIIZ path-and-filename of private key file

◆ tls_ctx_use_privatekey_file() [2/2]

rsocket* randolf::rsocket::tls_ctx_use_privatekey_file ( const std::string  file)
inline

Load a TLS private key in PEM format from a text file and use it in the TLS context.

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_privatekey_file
tls_ctx_use_privatekey_pem
tls_ctx_check_privatekey
Parameters
filePath and filename to private key file

◆ tls_ctx_use_privatekey_pem()

rsocket* randolf::rsocket::tls_ctx_use_privatekey_pem ( const char *  pem_data,
size_t  len = 0,
const bool  random_fill = true 
)
inline

Load a TLS private key in PEM format from memory and use it in the TLS context.

Although this functionality doesn't exist in OpenSSL (at the time of writing this method), it's provided here in a manner that has exactly the same effect as the tls_ctx_use_privatekey_file() methods, but without needing the PEM-formatted private key stored in a file beforehand.

Note
The pem_data parameter is a pointer to the memory location that holds the PEM formatted private key data. If the length of this data isn't specified or is set to zero (default), then it will be treated as a multiline ASCIIZ string.

Behind the scenes, we're just writing the pem_data memory to a temporary file (with severely-limited permissions), then optionally overwriting that temporary file with random data prior to deleting it (this is the default, since better security practices should be the default, but on a secured system it may not be necessary and so this option can also be disabled to save CPU cycles and reduce overall disk-write I/O operations).

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
tls_ctx_use_privatekey_file
tls_ctx_check_privatekey
Parameters
pem_dataPointer to private key data in PEM format
lenLength of pem_data (in bytes), or 0 to auto-detect length if pem_data is an ASCIIZ string
random_fillWhether to overwrite the temporary file with random data before deleting it

◆ tls_do_handshake()

rsocket* randolf::rsocket::tls_do_handshake ( )
inline

Initiate the TLS handshake with the endpoint (which is presumed to be a server). This method makes it easier to support application-level commands such as STARTTLS (which are implemented in protocols like SMTP, POP3, and IMAP4).

Exceptions
randolf::rex::xALLCatch this exception for now (at this time, the OpenSSL library doesn't document which errors may be returned)
Returns
The same rsocket object so as to facilitate stacking
See also
connect()
connect(std::string, int)
TLS_NO_INGRESS

◆ tls_fd()

const SSL* randolf::rsocket::tls_fd ( )
inlinenoexcept

Get OpenSSL's TLS structure.

Returns
TLS structure
nullptr = TLS structure not yet allocated

◆ tls_sni() [1/2]

rsocket_sni* randolf::rsocket::tls_sni ( )
inlinenoexcept

Return the current rsocket_sni object that this rsocket will use when accepting incoming encrypted connections.

Returns
Pointer to rsocket_sni object
nullptr = SNI is not assigned
See also
name_sni
tls_sni(rsocket_sni*)

◆ tls_sni() [2/2]

rsocket* randolf::rsocket::tls_sni ( rsocket_sni sni)
inlinenoexcept

Set the current rsocket_sni object that this rsocket will use when accepting incoming encrypted connections.

Use the name() method to find out which server name was supplied by the endpoint that triggered the SNI callback, regardless of whether it matches any of the TLS certificates used with this rsocket object or the rsocket_sni object that's associated with this rsocket object. If an SNI callback wasn't triggered, or if the endpoint didn't provide a server name, then it will remain unaffected (and the default {empty string} will remain unchanged).

Returns
The same rsocket object so as to facilitate stacking
See also
name_sni
tls_sni
is_tls_sni_match
Parameters
sniPointer to the rsocket_sni object to use, or specify nullptr to remove SNI support from this rsocket object

◆ to_mac()

static std::string randolf::rsocket::to_mac ( const void *  addr)
inlinestaticnoexcept

Convert a 48-bit integer to a machine address in the form of xx:xx:xx:xx:xx:xx where every instance of xx is a hexadecimal representation of each respective 8-bit byte portion.

This method is needed because we don't want to bring in the heavy fmt::format class as a dependency.

Returns
Mac address as 17-character in the typical format expected by system administrators
Parameters
addrPointer to 48-bit integer

◆ to_node()

static std::string randolf::rsocket::to_node ( const void *  addr)
inlinestaticnoexcept

Convert a 48-bit integer to a node address in the form of xxxx:xxxx:xxxx where every instance of xxxx is a hexadecimal representation of each respective 16-bit word portion.

This method is needed because we don't want to bring in the heavy fmt::format class as a dependency.

Returns
Node address as 14-character in the typical format expected by network administrators
Parameters
addrPointer to 48-bit integer

◆ vprintf()

rsocket* randolf::rsocket::vprintf ( const char *  format,
va_list  args 
)
inline

Send a formatted string to the rsocket endpoint.

The format is described in the documentation for the POSIX or Standard C Library printf() function.

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEILSEQAn invalid wide-character code was detected
randolf::rex::xEOVERFLOWThe value returned is greater than {INT_MAX}
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENOMEMInsufficient memory
Returns
The same rsocket object so as to facilitate stacking
See also
eol_fix_printf
is_eol_fix_printf
net_io
printf
printfline
vprintfline
Parameters
formatFormat string to use
argsVariadic arguments in va_list format

◆ vprintfline()

rsocket* randolf::rsocket::vprintfline ( const char *  format,
va_list  args 
)
inline

Send a formatted string to the rsocket endpoint, and append an EoL sequence.

The format is described in the documentation for the POSIX or Standard C Library printf() function.

Exceptions
randolf::rex::xEBADFThe underlying socket is not open
randolf::rex::xEILSEQAn invalid wide-character code was detected
randolf::rex::xEOVERFLOWThe value returned is greater than {INT_MAX}
randolf::rex::xEMFILEPer-process maximum open files limit reached
randolf::rex::xENOMEMInsufficient memory
Returns
The same rsocket object so as to facilitate stacking
See also
eol
eol_fix_printf
is_eol_fix_printf
net_io
printf
printfline
sendline
vprintf
Parameters
formatFormat string to use
argsVariadic arguments in va_list format

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