diff options
author | Claudius 'keldu' Holeksa <mail@keldu.de> | 2024-10-18 13:14:09 +0200 |
---|---|---|
committer | Claudius 'keldu' Holeksa <mail@keldu.de> | 2024-10-18 13:14:09 +0200 |
commit | 1456fc7c9a42992c2a601dffd26e251ebab99c3f (patch) | |
tree | 9cf60cd2f0edef76f5d5592d4d11eb734106bd0c | |
parent | 225134d485ec3795e839ea9bbafdae214771f340 (diff) |
Fixing tls and writing a basic test for it
-rw-r--r-- | modules/io-tls/SConstruct | 1 | ||||
-rw-r--r-- | modules/io-tls/c++/tls.cpp | 306 | ||||
-rw-r--r-- | modules/io-tls/c++/tls.hpp | 20 | ||||
-rw-r--r-- | modules/io-tls/c++/tls.tmpl.hpp | 313 | ||||
-rw-r--r-- | modules/io-tls/examples/tls_client.cpp | 49 |
5 files changed, 381 insertions, 308 deletions
diff --git a/modules/io-tls/SConstruct b/modules/io-tls/SConstruct index e3a5648..909eadb 100644 --- a/modules/io-tls/SConstruct +++ b/modules/io-tls/SConstruct @@ -57,6 +57,7 @@ env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], LIBS=[ 'gnutls' ,'forstio-core' + ,'forstio-async' ,'forstio-io' ]) env.__class__.add_source_files = add_kel_source_files diff --git a/modules/io-tls/c++/tls.cpp b/modules/io-tls/c++/tls.cpp index 1c42215..e69de29 100644 --- a/modules/io-tls/c++/tls.cpp +++ b/modules/io-tls/c++/tls.cpp @@ -1,306 +0,0 @@ -#include "tls.hpp" - -#include <gnutls/gnutls.h> -#include <gnutls/x509.h> - -#include <forstio/io/io_helpers.hpp> - -#include <cassert> - -#include <iostream> - -namespace saw { - -class tls::impl { -public: - gnutls_certificate_credentials_t xcred; - -public: - impl() { - gnutls_global_init(); - gnutls_certificate_allocate_credentials(&xcred); - gnutls_certificate_set_x509_system_trust(xcred); - } - - ~impl() { - gnutls_certificate_free_credentials(xcred); - gnutls_global_deinit(); - } -}; - -static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data, - size_t size); -static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size); - -tls::tls() : impl_{heap<tls::impl>()} {} - -tls::~tls() {} - -tls::impl &tls::get_impl() { return *impl_; } - -template<typename T> -class tls_io_stream final : public io_stream<net::Tls<T>> { -private: - own<io_stream<T>> internal_; - gnutls_certificate_credentials_t xcred_; - gnutls_session_t session_handle_; - -public: - tls_io_stream(own<io_stream<T>> internal__, gnutls_certificate_credentials_t xcred__, gnutls_session_t session_handle__): - internal_{std::move(internal__)}, - xcred_{xcred__}, - session_handle_{session_handle__} - {} - - ~tls_io_stream() { gnutls_bye(session_handle_, GNUTLS_SHUT_RDWR); } - - error_or<size_t> read(void *buffer, size_t length) override { - ssize_t size = gnutls_record_recv(session_handle_, buffer, length); - if (size < 0) { - if(gnutls_error_is_fatal(size) == 0){ - return make_error<err::recoverable>("Recoverable error on read in gnutls. TODO better error msg handling"); - // Leaving proper message handling done in previous error framework - //return recoverable_error([size](){return std::string{"Read recoverable Error "}+std::string{gnutls_strerror(size)};}, "Error read r"); - }else{ - return make_error<err::critical>("Fatal error on read in gnutls. TODO better error msg handling"); - } - }else if(size == 0){ - return make_error<err::disconnected>(); - } - - return static_cast<size_t>(length); - } - - conveyor<void> read_ready() override { return internal_->read_ready(); } - - conveyor<void> on_read_disconnected() override { - return internal_->on_read_disconnected(); - } - - error_or<size_t> write(const void *buffer, size_t length) override { - ssize_t size = gnutls_record_send(session_handle_, buffer, length); - if(size < 0){ - if(gnutls_error_is_fatal(size) == 0){ - return make_error<err::recoverable>("Recoverable error on write in gnutls. TODO better error msg handling"); - }else{ - return make_error<err::critical>("Fatal error on write in gnutls. TODO better error msg handling"); - } - } - - return static_cast<size_t>(size); - } - - conveyor<void> write_ready() override { return internal_->write_ready(); } - - gnutls_session_t &session() { return session_handle_; } -}; - -template<typename T> -class tls_server final : public server<net::Tls<T>> { -private: - own<server<T>> internal_; - gnutls_certificate_credentials_t xcred_; - gnutls_session_t session_handle_; - -public: - tls_server(own<server<T>> internal__, gnutls_certificate_credentials_t xcred__): - internal_{std::move(internal__)} - {} - - ~tls_server() { - gnutls_bye(session_handle_, GNUTLS_SHUT_RDWR); - gnutls_certificate_free_credentials(xcred_); - } - - conveyor<own<io_stream<net::Tls<T>>>> accept() override; -}; - -template<typename T> -class tls_network final : public network<net::Tls<T>> { -private: - ref<tls> tls_; - ref<network<T>> internal_; -public: - tls_network(tls& tls_, network<T> &network_); - - conveyor<own<network_address<net::Tls<T>>>> resolve_address(const std::string &addr, uint16_t port = 0) override; - - own<server<net::Tls<T>>> listen(const network_address<net::Tls<T>>& address) override; - - conveyor<own<io_stream<net::Tls<T>>>> connect(const network_address<net::Tls<T>>& address) override; - - own<datagram<net::Tls<T>>> bind_datagram(const network_address<net::Tls<T>>& address) override; -}; - -template<typename T> -conveyor<own<io_stream<net::Tls<T>>>> tls_server<T>::accept() { - SAW_ASSERT(internal_) { return conveyor<own<io_stream<net::Tls<T>>>>{fix_void<own<io_stream<net::Tls<T>>>>{nullptr}}; } - return internal_->accept().then([](own<io_stream<T>> stream) -> own<io_stream<net::Tls<T>>> { - /// @todo handshake - - return heap<tls_io_stream<T>>(std::move(stream)); - }); -} - -namespace { -/* -* Small helper for setting up the nonblocking connection handshake -*/ -template<typename T> -struct tls_client_stream_helper { -public: - own<conveyor_feeder<own<io_stream<net::Tls<T>>>>> feeder; - conveyor_sink connection_sink; - conveyor_sink stream_reader; - conveyor_sink stream_writer; - - own<tls_io_stream<T>> stream = nullptr; -public: - tls_client_stream_helper(own<conveyor_feeder<own<io_stream<net::Tls<T>>>>> f): - feeder{std::move(f)} - {} - - void setupTurn(){ - SAW_ASSERT(stream){ - return; - } - - stream_reader = stream->read_ready().then([this](){ - turn(); - }).sink(); - - stream_writer = stream->write_ready().then([this](){ - turn(); - }).sink(); - } - - void turn(){ - if(stream){ - // Guarantee that the receiving end is already setup - SAW_ASSERT(feeder){ - return; - } - - auto &session = stream->session(); - - int ret; - do { - ret = gnutls_handshake(session); - } while ( (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) && gnutls_error_is_fatal(ret) == 0); - - if(gnutls_error_is_fatal(ret)){ - feeder->fail(make_error<err::critical>("Couldn't create Tls connection")); - stream = nullptr; - }else if(ret == GNUTLS_E_SUCCESS){ - feeder->feed(std::move(stream)); - } - } - } -}; -} - -template<typename T> -own<server<net::Tls<T>>> tls_network<T>::listen(const network_address<net::Tls<T>>& address) { - gnutls_certificate_credentials_t x509_cred; - gnutls_certificate_allocate_credentials(&x509_cred); - auto int_srv = internal_.listen(address); - - return heap<tls_server>(std::move(int_srv), x509_cred); -} - -template<typename T> -conveyor<own<io_stream<net::Tls<T>>>> tls_network<T>::connect(const network_address<net::Tls<T>>& address) { - // Helper setups - auto caf = new_conveyor_and_feeder<own<io_stream<net::Tls<T>>>>(); - own<tls_client_stream_helper<T>> helper = heap<tls_client_stream_helper<T>>(std::move(caf.feeder)); - tls_client_stream_helper<T>* hlp_ptr = helper.get(); - - // Conveyor entangled structure - auto prim_conv = internal_.connect(address).then([this, hlp_ptr, addr = address.address()]( - own<io_stream<T>> stream) -> error_or<void> { - io_stream<T>* inner_stream = stream.get(); - auto tls_stream = heap<tls_io_stream<T>>(std::move(stream)); - - auto &session = tls_stream->session(); - - gnutls_init(&session, GNUTLS_CLIENT); - - gnutls_server_name_set(session, GNUTLS_NAME_DNS, addr.c_str(), - addr.size()); - - gnutls_set_default_priority(session); - gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, - tls_().get_impl().xcred); - gnutls_session_set_verify_cert(session, addr.c_str(), 0); - - gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(inner_stream)); - gnutls_transport_set_push_function(session, forst_tls_push_func); - gnutls_transport_set_pull_function(session, forst_tls_pull_func); - - // gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); - - hlp_ptr->stream = std::move(tls_stream); - hlp_ptr->setupTurn(); - hlp_ptr->turn(); - - return void_t{}; - }); - - helper->connection_sink = prim_conv.sink(); - - return caf.conveyor.attach(std::move(helper)); -} - -template<typename T> -own<datagram<net::Tls<T>>> tls_network<T>::bind_datagram(const network_address<net::Tls<T>>& address){ - ///@unimplemented - return nullptr; -} - -template<typename T> -static ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data, - size_t size) { - io_stream<T> *stream = reinterpret_cast<io_stream<T>*>(p); - if (!stream) { - return -1; - } - - error_or<size_t> length = stream->write(data, size); - if (length.is_error() || !length.is_value()) { - return -1; - } - - return static_cast<ssize_t>(length.get_value()); -} - -template<typename T> -static ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size) { - io_stream<T> *stream = reinterpret_cast<io_stream<T>*>(p); - if (!stream) { - return -1; - } - - error_or<size_t> length = stream->read(data, size); - if (length.is_error() || !length.is_value()) { - return -1; - } - - return static_cast<ssize_t>(length.get_value()); -} - -template<typename T> -tls_network<T>::tls_network(tls& tls_, network<T> &network) : tls_{tls_},internal_{network} {} - -template<typename T> -conveyor<own<network_address<net::Tls<T>>>> tls_network<T>::resolve_address(const std::string &addr, - uint16_t port) { - /// @todo tls server name needed. Check validity. Won't matter later on, because gnutls should fail anyway. But - /// it's better to find the error source sooner rather than later - return internal_.resolve_address(addr, port); -} - -template<typename T> -error_or<own<network<net::Tls<T>>>> setup_tls_network(network<net::Tls<T>> &network) { - return make_error<err::not_implemented>(); -} -} // namespace saw diff --git a/modules/io-tls/c++/tls.hpp b/modules/io-tls/c++/tls.hpp index c5c3da1..5082ee9 100644 --- a/modules/io-tls/c++/tls.hpp +++ b/modules/io-tls/c++/tls.hpp @@ -43,6 +43,20 @@ private: }; template<typename T> +class network_address<net::Tls<T>> final { +private: + own<network_address<T>> internal_; +public: + network_address(own<network_address<T>> internal__): + internal_{std::move(internal__)} + {} + + network_address<T>& get_handle() { + return *internal_; + } +}; + +template<typename T> class network<net::Tls<T>> { public: virtual ~network() = default; @@ -63,15 +77,17 @@ public: /** * Set up a listener on this address */ - virtual error_or<own<server<T>>> listen(network_address<T> &bind_addr) = 0; + virtual error_or<own<server<net::Tls<T>>>> listen(network_address<net::Tls<T>> &bind_addr) = 0; /** * Connect to a remote address */ - virtual conveyor<own<io_stream<T>>> connect(network_address<T> &address) = 0; + virtual conveyor<own<io_stream<net::Tls<T>>>> connect(network_address<net::Tls<T>> &address) = 0; }; template<typename T = net::Os> error_or<own<network<net::Tls<T>>>> setup_tls_network(network<T> &network); } // namespace saw + +#include "tls.tmpl.hpp" diff --git a/modules/io-tls/c++/tls.tmpl.hpp b/modules/io-tls/c++/tls.tmpl.hpp new file mode 100644 index 0000000..bc3d2d2 --- /dev/null +++ b/modules/io-tls/c++/tls.tmpl.hpp @@ -0,0 +1,313 @@ +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> + +#include <forstio/io/io_helpers.hpp> + +#include <cassert> + +namespace saw { + +class tls::impl { +public: + gnutls_certificate_credentials_t xcred; + +public: + impl() { + gnutls_global_init(); + gnutls_certificate_allocate_credentials(&xcred); + gnutls_certificate_set_x509_system_trust(xcred); + } + + ~impl() { + gnutls_certificate_free_credentials(xcred); + gnutls_global_deinit(); + } +}; + +template<typename T> +ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data, + size_t size); +template<typename T> +ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size); + +tls::tls() : impl_{heap<tls::impl>()} {} + +tls::~tls() {} + +tls::impl &tls::get_impl() { return *impl_; } + +template<typename T> +class tls_io_stream final : public io_stream<net::Tls<T>> { +private: + own<io_stream<T>> internal_; + gnutls_certificate_credentials_t xcred_; + gnutls_session_t session_handle_; + +public: + /* + tls_io_stream(own<io_stream<T>> internal__, gnutls_certificate_credentials_t xcred__, gnutls_session_t session_handle__): + internal_{std::move(internal__)}, + xcred_{xcred__}, + session_handle_{session_handle__} + {} + */ + tls_io_stream(own<io_stream<T>> internal__): + internal_{std::move(internal__)}, + xcred_{}, + session_handle_{} + {} + + ~tls_io_stream() { gnutls_bye(session_handle_, GNUTLS_SHUT_RDWR); } + + error_or<size_t> read(void *buffer, size_t length) override { + ssize_t size = gnutls_record_recv(session_handle_, buffer, length); + if (size < 0) { + if(gnutls_error_is_fatal(size) == 0){ + return make_error<err::recoverable>("Recoverable error on read in gnutls. TODO better error msg handling"); + // Leaving proper message handling done in previous error framework + //return recoverable_error([size](){return std::string{"Read recoverable Error "}+std::string{gnutls_strerror(size)};}, "Error read r"); + }else{ + return make_error<err::critical>("Fatal error on read in gnutls. TODO better error msg handling"); + } + }else if(size == 0){ + return make_error<err::disconnected>(); + } + + return static_cast<size_t>(length); + } + + conveyor<void> read_ready() override { return internal_->read_ready(); } + + conveyor<void> on_read_disconnected() override { + return internal_->on_read_disconnected(); + } + + error_or<size_t> write(const void *buffer, size_t length) override { + ssize_t size = gnutls_record_send(session_handle_, buffer, length); + if(size < 0){ + if(gnutls_error_is_fatal(size) == 0){ + return make_error<err::recoverable>("Recoverable error on write in gnutls. TODO better error msg handling"); + }else{ + return make_error<err::critical>("Fatal error on write in gnutls. TODO better error msg handling"); + } + } + + return static_cast<size_t>(size); + } + + conveyor<void> write_ready() override { return internal_->write_ready(); } + + gnutls_session_t &session() { return session_handle_; } +}; + +template<typename T> +class tls_server final : public server<net::Tls<T>> { +private: + own<server<T>> internal_; + gnutls_certificate_credentials_t xcred_; + gnutls_session_t session_handle_; + +public: + tls_server(own<server<T>> internal__, gnutls_certificate_credentials_t xcred__): + internal_{std::move(internal__)} + {} + + ~tls_server() { + gnutls_bye(session_handle_, GNUTLS_SHUT_RDWR); + gnutls_certificate_free_credentials(xcred_); + } + + conveyor<own<io_stream<net::Tls<T>>>> accept() override; +}; + +template<typename T> +class tls_network final : public network<net::Tls<T>> { +private: + own<tls> tls_; + ref<network<T>> internal_; +public: + tls_network(own<tls> tls_, network<T> &network_); + + conveyor<own<network_address<net::Tls<T>>>> resolve_address(const std::string &addr, uint16_t port = 0) override; + error_or<own<network_address<net::Tls<T>>>> parse_address(const std::string &addr, uint16_t port = 0) override { + + return make_error<err::not_implemented>(); + } + + error_or<own<server<net::Tls<T>>>> listen(network_address<net::Tls<T>>& address) override; + + conveyor<own<io_stream<net::Tls<T>>>> connect(network_address<net::Tls<T>>& address) override; +}; + +template<typename T> +conveyor<own<io_stream<net::Tls<T>>>> tls_server<T>::accept() { + SAW_ASSERT(internal_) { return conveyor<own<io_stream<net::Tls<T>>>>{fix_void<own<io_stream<net::Tls<T>>>>{nullptr}}; } + return internal_->accept().then([](own<io_stream<T>> stream) -> error_or<own<io_stream<net::Tls<T>>>> { + /// @todo handshake + return make_error<err::not_implemented>(); + // auto foo = heap<tls_io_stream<T>>(std::move(stream)); + }); +} + +namespace { +/* +* Small helper for setting up the nonblocking connection handshake +*/ +template<typename T> +struct tls_client_stream_helper { +public: + own<conveyor_feeder<own<io_stream<net::Tls<T>>>>> feeder; + conveyor_sink connection_sink; + conveyor_sink stream_reader; + conveyor_sink stream_writer; + + own<tls_io_stream<T>> stream = nullptr; +public: + tls_client_stream_helper(own<conveyor_feeder<own<io_stream<net::Tls<T>>>>> f): + feeder{std::move(f)} + {} + + void setupTurn(){ + SAW_ASSERT(stream){ + return; + } + + stream_reader = stream->read_ready().then([this](){ + turn(); + }).sink(); + + stream_writer = stream->write_ready().then([this](){ + turn(); + }).sink(); + } + + void turn(){ + if(stream){ + // Guarantee that the receiving end is already setup + SAW_ASSERT(feeder){ + return; + } + + auto &session = stream->session(); + + int ret; + do { + ret = gnutls_handshake(session); + } while ( (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) && gnutls_error_is_fatal(ret) == 0); + + if(gnutls_error_is_fatal(ret)){ + feeder->fail(make_error<err::critical>("Couldn't create Tls connection")); + stream = nullptr; + }else if(ret == GNUTLS_E_SUCCESS){ + feeder->feed(std::move(stream)); + } + } + } +}; +} + +template<typename T> +error_or<own<server<net::Tls<T>>>> tls_network<T>::listen(network_address<net::Tls<T>>& address) { + gnutls_certificate_credentials_t x509_cred; + gnutls_certificate_allocate_credentials(&x509_cred); + auto int_srv = internal_().listen(address.get_handle()); + + own<server<net::Tls<T>>> tls_srv = heap<tls_server<T>>(std::move(int_srv), x509_cred); + return tls_srv; +} + +template<typename T> +conveyor<own<io_stream<net::Tls<T>>>> tls_network<T>::connect(network_address<net::Tls<T>>& address) { + // Helper setups + auto caf = new_conveyor_and_feeder<own<io_stream<net::Tls<T>>>>(); + own<tls_client_stream_helper<T>> helper = heap<tls_client_stream_helper<T>>(std::move(caf.feeder)); + tls_client_stream_helper<T>* hlp_ptr = helper.get(); + + // Conveyor entangled structure + auto prim_conv = internal_().connect(address.get_handle()).then([this, hlp_ptr, addr = address.get_handle().address()]( + own<io_stream<T>> stream) -> error_or<void> { + io_stream<T>* inner_stream = stream.get(); + auto tls_stream = heap<tls_io_stream<T>>(std::move(stream)); + + auto &session = tls_stream->session(); + + gnutls_init(&session, GNUTLS_CLIENT); + + gnutls_server_name_set(session, GNUTLS_NAME_DNS, addr.c_str(), + addr.size()); + + gnutls_set_default_priority(session); + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + tls_->get_impl().xcred); + gnutls_session_set_verify_cert(session, addr.c_str(), 0); + + gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(inner_stream)); + gnutls_transport_set_push_function(session, forst_tls_push_func<T>); + gnutls_transport_set_pull_function(session, forst_tls_pull_func<T>); + + // gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + hlp_ptr->stream = std::move(tls_stream); + hlp_ptr->setupTurn(); + hlp_ptr->turn(); + + return void_t{}; + }); + + helper->connection_sink = prim_conv.sink(); + + return caf.conveyor.attach(std::move(helper)); +} + +template<typename T> +ssize_t forst_tls_push_func(gnutls_transport_ptr_t p, const void *data, + size_t size) { + io_stream<T> *stream = reinterpret_cast<io_stream<T>*>(p); + if (!stream) { + return -1; + } + + error_or<size_t> length = stream->write(data, size); + if (length.is_error() || !length.is_value()) { + return -1; + } + + return static_cast<ssize_t>(length.get_value()); +} + +template<typename T> +ssize_t forst_tls_pull_func(gnutls_transport_ptr_t p, void *data, size_t size) { + io_stream<T> *stream = reinterpret_cast<io_stream<T>*>(p); + if (!stream) { + return -1; + } + + error_or<size_t> length = stream->read(data, size); + if (length.is_error() || !length.is_value()) { + return -1; + } + + return static_cast<ssize_t>(length.get_value()); +} + +template<typename T> +tls_network<T>::tls_network(own<tls> tls__, network<T> &network) : tls_{std::move(tls__)},internal_{network} {} + +template<typename T> +conveyor<own<network_address<net::Tls<T>>>> tls_network<T>::resolve_address(const std::string &addr, + uint16_t port) { + /// @todo tls server name needed. Check validity. Won't matter later on, because gnutls should fail anyway. But + /// it's better to find the error source sooner rather than later + return internal_().resolve_address(addr, port).then([](auto net_addr){ + return heap<network_address<net::Tls<T>>>(std::move(net_addr)); + }); +} + +template<typename T> +error_or<own<network<net::Tls<T>>>> setup_tls_network(network<T> &net) { + auto tls_ctx = heap<tls>(); + + own<network<net::Tls<T>>> tls_net = heap<tls_network<T>>(std::move(tls_ctx), net); + return tls_net; +} +} // namespace saw diff --git a/modules/io-tls/examples/tls_client.cpp b/modules/io-tls/examples/tls_client.cpp index e2ce4a5..d01e2bf 100644 --- a/modules/io-tls/examples/tls_client.cpp +++ b/modules/io-tls/examples/tls_client.cpp @@ -2,6 +2,8 @@ #include <iostream> +#include <forstio/buffer.hpp> + saw::error_or<void> real_main(){ using namespace saw; auto eo_aio = setup_async_io(); @@ -9,6 +11,7 @@ saw::error_or<void> real_main(){ return std::move(eo_aio.get_error()); } auto& aio = eo_aio.get_value(); + wait_scope wait{aio.event_loop}; auto eo_tls_net = setup_tls_network(aio.io->get_network()); if(eo_tls_net.is_error()){ @@ -16,6 +19,52 @@ saw::error_or<void> real_main(){ } auto& tls_net = eo_tls_net.get_value(); + auto eo_tls_addr = tls_net->resolve_address("keldu.de", 443).take(); + if(eo_tls_addr.is_error()){ + return std::move(eo_tls_addr.get_error()); + } + auto& tls_addr = eo_tls_addr.get_value(); + + ring_buffer buff{4096u * 4096u}; + + own<io_stream<net::Tls<net::Os>>> tls_io = nullptr; + + std::cout<<"Preparing to connect"<<std::endl; + tls_net->connect(*tls_addr).then([&](auto tls_io_str){ + tls_io = std::move(tls_io_str); + std::cout<<"Connected"<<std::endl; + std::string_view get_req{"GET / HTTP/1.1"}; + auto write_res = tls_io->write(&get_req[0], get_req.size()); + + std::cout<<"Sending: "<<get_req<<std::endl; + + }).detach(); + + wait.wait_for(1000u*1000u); + wait.wait_for(1000u*1000u); + wait.wait_for(1000u*1000u); + if(!tls_io){ + return make_error<invalid_state>("Never managed to connect"); + } + { + auto read_res = tls_io->read(&buff.write(), buff.write_segment_length()); + if(read_res.is_error()){ + std::cerr<<":("<<std::endl; + return; + } + auto& read_res_val = read_res.get_value(); + buff.write_advance(read_res_val); + + for(uint64_t i = 0u; i < buff.read_segment_length(); ++i){ + std::cout<<buff.read(i); + } + std::cout<<std::endl; + + } + wait.wait_for(1000u*1000u); + wait.wait_for(1000u*1000u); + wait.wait_for(1000u*1000u); + return make_void(); } |