Probably the most common use case for this will be fetching the default source of TLS secured sockets, so here is some example boilerplate:
++
Get a source able to manufacture TLS sockets
Get a new TLS socket able to connect
tls_socket_source_handle_ptr sock =
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
std::string host;
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();
serversocket->bind(llfio::ip::make_address(host+":8989").value()).value();
std::vector<llfio::pollable_handle *> pollable_handles;
std::vector<llfio::poll_what> topoll, whatchanged;
pollable_handles.push_back(serversocket.get());
topoll.push_back(llfio::poll_what::is_readable);
whatchanged.push_back(llfio::poll_what::none);
struct connected_socket {
llfio::ip::address endpoint;
size_t rbuf_storage_length{llfio::utils::page_size()};
size_t wbuf_storage_length{llfio::utils::page_size()};
llfio::tls_socket_handle::registered_buffer_type rbuf_storage, wbuf_storage;
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)
, wbuf(wbuf_storage->data(), 0)
{}
};
std::vector<connected_socket> connected_sockets;
for(;;) {
std::fill(whatchanged.begin(), whatchanged.end(), llfio::poll_what::none);
size_t handles_changed
=
llfio::poll(whatchanged, {pollable_handles}, topoll).value();
for(size_t handleidx = 0;
handles_changed > 0 && handleidx < pollable_handles.size();
handleidx++) {
if(whatchanged[handleidx] == llfio::poll_what::none) {
continue;
}
if(0 == handleidx) {
std::pair<llfio::tls_socket_handle_ptr, llfio::ip::address> s;
serversocket->read({s}).value();
connected_sockets.emplace_back(std::move(s));
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;
}
auto &sock = connected_sockets[handleidx - 1];
handles_changed--;
if(whatchanged[handleidx] & llfio::poll_what::is_errored) {
sock.socket->close().value();
sock.rbuf_storage.reset();
sock.wbuf_storage.reset();
pollable_handles[handleidx] = nullptr;
}
if(whatchanged[handleidx] & llfio::poll_what::is_readable) {
sock.rbuf = *sock.rbuf_storage;
sock.socket->read({{&sock.rbuf, 1}}).value();
}
if(whatchanged[handleidx] & llfio::poll_what::is_writable) {
if(!sock.wbuf.empty()) {
auto b(sock.wbuf);
sock.socket->write({{&b, 1}}).value();
sock.wbuf = {sock.wbuf.data() + b.size(), sock.wbuf.size() - b.size() };
}
if(sock.wbuf.empty()) {
topoll[handleidx]&=uint8_t(~llfio::poll_what::is_writable);
}
}
}
}
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