LLFIO v2.00
Loading...
Searching...
No Matches
llfio_v2_xxx::tls_socket_source_registry Class Reference

A process-wide registry of tls_socket_source. More...

#include "tls_socket_handle.hpp"

Static Public Member Functions

static bool empty () noexcept
 True if there are no socket sources known to this registry.
 
static size_t size () noexcept
 The current total number of socket sources known to this registry.
 
static span< tls_socket_source_implementation_informationsources (span< tls_socket_source_implementation_information > tofill, tls_socket_source_implementation_features set=tls_socket_source_implementation_features::none, tls_socket_source_implementation_features mask=tls_socket_source_implementation_features::none) noexcept
 
static tls_socket_source_implementation_information default_source (tls_socket_source_implementation_features set=tls_socket_source_implementation_features::none, tls_socket_source_implementation_features mask=tls_socket_source_implementation_features::none) noexcept
 Convenience overload retrieving TLS socket sources, preferring system over third party implementations.
 
static result< void > register_source (tls_socket_source_implementation_information i) noexcept
 Registers a new source of byte sockets.
 
static void unregister_source (tls_socket_source_implementation_information i) noexcept
 Deregisters a new source of byte sockets.
 

Detailed Description

A process-wide registry of tls_socket_source.

Warning
This is deprecated and scheduled for removal in 2025.

Probably the most common use case for this will be fetching the default source of TLS secured sockets, so here is some example boilerplate:

Blocking:

++
Get a source able to manufacture TLS sockets
tls_socket_source_ptr secure_socket_source =
Get a new TLS socket able to connect
tls_socket_source_handle_ptr sock =
secure_socket_source->connecting_socket(ip::family::v6).value();
Resolve the name "host.org" and service "1234" into an IP address,
and connect to it over TLS. If the remote's TLS certificate is
not trusted by this system, or the remote certificate does not
match the host, this call will fail.
sock->connect("host.org", 1234).value();
Write "Hello" to the connected TLS socket
sock->write(0, {{(const byte *) "Hello", 5}}).value();
Blocking read the response
char buffer[5];
tls_socket_handle::buffer_type b((byte *) buffer, 5);
auto readed = sock->read({{&b, 1}, 0}).value();
if(string_view(buffer, b.size()) != "World") {
abort();
}
With TLS sockets it is important to perform a proper shutdown
rather than hard close
sock->shutdown_and_close().value();
static tls_socket_source_implementation_information default_source(tls_socket_source_implementation_features set=tls_socket_source_implementation_features::none, tls_socket_source_implementation_features mask=tls_socket_source_implementation_features::none) noexcept
Convenience overload retrieving TLS socket sources, preferring system over third party implementation...
Definition tls_socket_handle.hpp:571
std::unique_ptr< tls_socket_source, detail::tls_socket_source_deleter > tls_socket_source_ptr
A pointer to a TLS socket source.
Definition tls_socket_handle.hpp:421
result< tls_socket_source_ptr >(* instantiate)() noexcept
Create an instance of this TLS socket source. The instance may be shared or recycled or a singleton.
Definition tls_socket_handle.hpp:440

Non-blocking:

++
// Get a source able to manufacture TLS sockets
tls_socket_source_ptr secure_socket_source =
// Get a new TLS socket able to connect
tls_socket_source_handle_ptr sock =
secure_socket_source->multiplexable_connecting_socket(ip::family::v6).value();
// Resolve the name "host.org" and service "1234" into an IP address,
// and connect to it over TLS. If the remote's TLS certificate is
// not trusted by this system, or the remote certificate does not
// match the host, this call will fail.
//
// If the connection does not complete within three seconds, fail.
sock->connect("host.org", 1234, std::chrono::seconds(3)).value();
// Write "Hello" to the connected TLS socket
sock->write(0, {{(const byte *) "Hello", 5}}, std::chrono::seconds(3)).value();
// Blocking read the response, but only up to three seconds.
char buffer[5];
tls_socket_handle::buffer_type b((byte *) buffer, 5);
auto readed = sock->read({{&b, 1}, 0}, std::chrono::seconds(3)).value();
if(string_view(buffer, b.size()) != "World") {
abort();
}
// With TLS sockets it is important to perform a proper shutdown
// rather than hard close
sock->shutdown_and_close(std::chrono::seconds(3)).value();

Fuller fat example:

std::string host; // set to one of my network cards
// Get me a FIPS 140 compliant source of TLS sockets which uses kernel
// sockets, this call takes bits set and bits masked, so the implementation
// features bitfield is masked for the FIPS 140 bit, and only if that is set
// is the TLS socket source considered.
//
// The need for a kernel sockets based TLS implementation is so poll() will
// work, as it requires kernel sockets compatible input.
static constexpr auto required_features =
llfio::tls_socket_source_implementation_features::FIPS_140_2
| llfio::tls_socket_source_implementation_features::kernel_sockets;
llfio::tls_socket_source_registry::default_source(required_features,
required_features).instantiate().value();
// Create a listening TLS socket on any IP family.
->multiplexable_listening_socket(llfio::ip::family::any).value();
// The default is to NOT authenticate the TLS certificates of those connecting
// in with the system's TLS certificate store. If you wanted something
// different, you'd set that now using:
// serversocket->set_authentication_certificates_path()
// Bind the listening TLS socket to port 8989 on the NIC described by host
// ip::address incidentally is inspired by ASIO's class, it is very
// similar. I only made it more constexpr.
serversocket->bind(llfio::ip::make_address(host+":8989").value()).value();
// poll() works on three spans. We deliberately have separate poll_what
// storage so we can avoid having to reset topoll's contents per poll()
std::vector<llfio::pollable_handle *> pollable_handles;
std::vector<llfio::poll_what> topoll, whatchanged;
// We will want to know about new inbound connections to our listening
// socket
pollable_handles.push_back(serversocket.get());
topoll.push_back(llfio::poll_what::is_readable);
whatchanged.push_back(llfio::poll_what::none);
// Connected socket state
struct connected_socket {
// The connected socket
// The endpoint from which it connected
llfio::ip::address endpoint;
// The size of registered buffer actually allocated (we request system
// page size, the DMA controller may return that or more)
size_t rbuf_storage_length{llfio::utils::page_size()};
size_t wbuf_storage_length{llfio::utils::page_size()};
// These are shared ptrs to memory potentially registered with the NIC's
// DMA controller and therefore i/o using them would be true whole system
// zero copy
llfio::tls_socket_handle::registered_buffer_type rbuf_storage, wbuf_storage;
// These spans of byte and const byte index into buffer storage and get
// updated by each i/o operation to describe what was done
llfio::tls_socket_handle::buffer_type rbuf;
llfio::tls_socket_handle::const_buffer_type wbuf;
explicit connected_socket(std::pair<llfio::tls_socket_handle_ptr, llfio::ip::address> s)
: socket(std::move(s.first))
, endpoint(std::move(s.second))
, rbuf_storage(socket->allocate_registered_buffer(rbuf_storage_length).value())
, wbuf_storage(socket->allocate_registered_buffer(wbuf_storage_length).value())
, rbuf(*rbuf_storage) // fill this buffer
, wbuf(wbuf_storage->data(), 0) // nothing to write
{}
};
std::vector<connected_socket> connected_sockets;
// Begin the processing loop
for(;;) {
// We need to clear whatchanged before use, as it accumulates bits set.
std::fill(whatchanged.begin(), whatchanged.end(), llfio::poll_what::none);
// As with all LLFIO calls, you can set a deadline here so this call
// times out. The default as usual is wait until infinity.
size_t handles_changed
= llfio::poll(whatchanged, {pollable_handles}, topoll).value();
// Loop the polled handles looking for events changed.
for(size_t handleidx = 0;
handles_changed > 0 && handleidx < pollable_handles.size();
handleidx++) {
if(whatchanged[handleidx] == llfio::poll_what::none) {
continue;
}
if(0 == handleidx) {
// This is the listening socket, and there is a new connection to be
// read, as listening socket defines its read operation to be
// connected sockets and the endpoint they connected from.
std::pair<llfio::tls_socket_handle_ptr, llfio::ip::address> s;
serversocket->read({s}).value();
connected_sockets.emplace_back(std::move(s));
// Watch this connected socket going forth for data to read or failure
pollable_handles.push_back(connected_sockets.back().socket.get());
topoll.push_back(llfio::poll_what::is_readable|llfio::poll_what::is_errored);
whatchanged.push_back(llfio::poll_what::none);
handles_changed--;
continue;
}
// There has been an event on this socket
auto &sock = connected_sockets[handleidx - 1];
handles_changed--;
if(whatchanged[handleidx] & llfio::poll_what::is_errored) {
// Force it closed and ignore it from polling going forth
sock.socket->close().value();
sock.rbuf_storage.reset();
sock.wbuf_storage.reset();
pollable_handles[handleidx] = nullptr;
}
if(whatchanged[handleidx] & llfio::poll_what::is_readable) {
// Set up the buffer to fill. Note the scatter buffer list
// based API.
sock.rbuf = *sock.rbuf_storage;
sock.socket->read({{&sock.rbuf, 1}}).value();
// sock.rbuf has its size adjusted to bytes read
}
if(whatchanged[handleidx] & llfio::poll_what::is_writable) {
// If this was set in topoll, it means write buffers
// were full at some point, and we are now being told
// there is space to write some more
if(!sock.wbuf.empty()) {
// Take a copy of the buffer to write, as it will be
// modified in place with what was written
auto b(sock.wbuf);
sock.socket->write({{&b, 1}}).value();
// Adjust the buffer to yet to write
sock.wbuf = {sock.wbuf.data() + b.size(), sock.wbuf.size() - b.size() };
}
if(sock.wbuf.empty()) {
// Nothing more to write, so no longer poll for this
topoll[handleidx]&=uint8_t(~llfio::poll_what::is_writable);
}
}
// Process buffers read and written for this socket ...
}
}
A source of tls_socket_handle and listening_tls_socket_handle and possibly a byte_io_multiplexer to m...
Definition tls_socket_handle.hpp:345
result< listening_tls_socket_handle_ptr > multiplexable_listening_socket(ip::family family, byte_socket_handle::mode _mode=byte_socket_handle::mode::write, byte_socket_handle::caching _caching=byte_socket_handle::caching::all, byte_socket_handle::flag flags=byte_socket_handle::flag::multiplexable) noexcept
Convenience function defaulting flag::multiplexable set.
Definition tls_socket_handle.hpp:397
#define LLFIO_V2_NAMESPACE
The namespace of this LLFIO v2 which will be some unknown inline namespace starting with v2_ inside t...
Definition config.hpp:183
The LLFIO namespace.
Definition byte_io_handle.hpp:37
std::unique_ptr< listening_tls_socket_handle, detail::listening_tls_socket_handle_deleter > listening_tls_socket_handle_ptr
A pointer to a listening TLS socket handle returned by a TLS socket source.
Definition tls_socket_handle.hpp:307
result< size_t > poll(span< poll_what > out, span< pollable_handle * > handles, span< const poll_what > query, deadline d={}) noexcept
Polls a list of pollable handles awaiting a change in state.
std::unique_ptr< tls_socket_handle, detail::tls_socket_handle_deleter > tls_socket_handle_ptr
A pointer to a TLS socket handle returned by a TLS socket source.
Definition tls_socket_handle.hpp:198

Member Function Documentation

◆ default_source()

static tls_socket_source_implementation_information llfio_v2_xxx::tls_socket_source_registry::default_source ( tls_socket_source_implementation_features  set = tls_socket_source_implementation_features::none,
tls_socket_source_implementation_features  mask = tls_socket_source_implementation_features::none 
)
inlinestaticnoexcept

Convenience overload retrieving TLS socket sources, preferring system over third party implementations.

573 {
574 tls_socket_source_implementation_information ret{"no implementation available"};
575 set |= tls_socket_source_implementation_features::system_implementation;
576 mask |= tls_socket_source_implementation_features::system_implementation;
577 auto filled = sources({&ret, 1}, set, mask);
578 if(!filled.empty())
579 {
580 return ret;
581 }
582 set &= ~tls_socket_source_implementation_features::system_implementation;
583 mask &= ~tls_socket_source_implementation_features::system_implementation;
584 filled = sources({&ret, 1}, set, mask);
585 if(!filled.empty())
586 {
587 return ret;
588 }
589 return {};
590 }
static span< tls_socket_source_implementation_information > sources(span< tls_socket_source_implementation_information > tofill, tls_socket_source_implementation_features set=tls_socket_source_implementation_features::none, tls_socket_source_implementation_features mask=tls_socket_source_implementation_features::none) noexcept

◆ empty()

static bool llfio_v2_xxx::tls_socket_source_registry::empty ( )
inlinestaticnoexcept

True if there are no socket sources known to this registry.

558{ return size() == 0; }
static size_t size() noexcept
The current total number of socket sources known to this registry.

◆ sources()

static span< tls_socket_source_implementation_information > llfio_v2_xxx::tls_socket_source_registry::sources ( span< tls_socket_source_implementation_information tofill,
tls_socket_source_implementation_features  set = tls_socket_source_implementation_features::none,
tls_socket_source_implementation_features  mask = tls_socket_source_implementation_features::none 
)
staticnoexcept

Fills an array with implementation informations for the TLS socket sources in the registry with features matching set after being masked with mask. The default parameters fetch all sources.


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