diff --git a/example/https-client/https_client.cpp b/example/https-client/https_client.cpp index b64adc6..cde4932 100644 --- a/example/https-client/https_client.cpp +++ b/example/https-client/https_client.cpp @@ -63,8 +63,14 @@ run_client( // Connect to the server (throws on error) (co_await s.connect(corosio::endpoint(addr, port))).value(); + // Configure TLS context + corosio::tls::context ctx; + ctx.set_hostname(hostname); + ctx.set_default_verify_paths().value(); + ctx.set_verify_mode(corosio::tls::verify_mode::peer).value(); + // Wrap socket in TLS stream - corosio::wolfssl_stream secure(s); + corosio::wolfssl_stream secure(s, ctx); // Perform TLS handshake (co_await secure.handshake(corosio::wolfssl_stream::client)).value(); diff --git a/include/boost/corosio/signal_set.hpp b/include/boost/corosio/signal_set.hpp index a4a3b9b..fbf1413 100644 --- a/include/boost/corosio/signal_set.hpp +++ b/include/boost/corosio/signal_set.hpp @@ -20,7 +20,9 @@ #include #include #include +#include +#include #include #include @@ -73,15 +75,6 @@ class BOOST_COROSIO_DECL signal_set : public io_object return {ec_, signal_number_}; } - template - auto await_suspend( - std::coroutine_handle<> h, - Ex const& ex) -> std::coroutine_handle<> - { - s_.get().wait(h, ex, token_, &ec_, &signal_number_); - return std::noop_coroutine(); - } - template auto await_suspend( std::coroutine_handle<> h, @@ -104,61 +97,42 @@ class BOOST_COROSIO_DECL signal_set : public io_object system::error_code*, int*) = 0; - virtual system::error_code add(int signal_number) = 0; - virtual system::error_code remove(int signal_number) = 0; - virtual system::error_code clear() = 0; + virtual system::result add(int signal_number) = 0; + virtual system::result remove(int signal_number) = 0; + virtual system::result clear() = 0; virtual void cancel() = 0; }; -public: /** Destructor. Cancels any pending operations and releases signal resources. */ ~signal_set(); - /** Construct a signal set without adding any signals. + /** Construct an empty signal set. @param ctx The execution context that will own this signal set. */ explicit signal_set(capy::execution_context& ctx); - /** Construct a signal set and add one signal. - - @param ctx The execution context that will own this signal set. - @param signal_number_1 The signal number to be added. - - @throws boost::system::system_error Thrown on failure. - */ - signal_set(capy::execution_context& ctx, int signal_number_1); - - /** Construct a signal set and add two signals. + /** Construct a signal set with initial signals. @param ctx The execution context that will own this signal set. - @param signal_number_1 The first signal number to be added. - @param signal_number_2 The second signal number to be added. + @param signal First signal number to add. + @param signals Additional signal numbers to add. @throws boost::system::system_error Thrown on failure. */ + template... Signals> signal_set( capy::execution_context& ctx, - int signal_number_1, - int signal_number_2); - - /** Construct a signal set and add three signals. - - @param ctx The execution context that will own this signal set. - @param signal_number_1 The first signal number to be added. - @param signal_number_2 The second signal number to be added. - @param signal_number_3 The third signal number to be added. - - @throws boost::system::system_error Thrown on failure. - */ - signal_set( - capy::execution_context& ctx, - int signal_number_1, - int signal_number_2, - int signal_number_3); + int signal, + Signals... signals) + : signal_set(ctx) + { + add(signal).value(); + (add(signals).value(), ...); + } /** Move constructor. @@ -192,19 +166,9 @@ class BOOST_COROSIO_DECL signal_set : public io_object @param signal_number The signal to be added to the set. - @throws boost::system::system_error Thrown on failure. + @return Success, or an error if the signal could not be added. */ - void add(int signal_number); - - /** Add a signal to the signal set. - - This function adds the specified signal to the set. It has no - effect if the signal is already in the set. - - @param signal_number The signal to be added to the set. - @param ec Set to indicate what error occurred, if any. - */ - void add(int signal_number, system::error_code& ec); + system::result add(int signal_number); /** Remove a signal from the signal set. @@ -213,37 +177,18 @@ class BOOST_COROSIO_DECL signal_set : public io_object @param signal_number The signal to be removed from the set. - @throws boost::system::system_error Thrown on failure. - */ - void remove(int signal_number); - - /** Remove a signal from the signal set. - - This function removes the specified signal from the set. It has - no effect if the signal is not in the set. - - @param signal_number The signal to be removed from the set. - @param ec Set to indicate what error occurred, if any. - */ - void remove(int signal_number, system::error_code& ec); - - /** Remove all signals from the signal set. - - This function removes all signals from the set. It has no effect - if the set is already empty. - - @throws boost::system::system_error Thrown on failure. + @return Success, or an error if the signal could not be removed. */ - void clear(); + system::result remove(int signal_number); /** Remove all signals from the signal set. This function removes all signals from the set. It has no effect if the set is already empty. - @param ec Set to indicate what error occurred, if any. + @return Success, or an error if resetting any signal handler fails. */ - void clear(system::error_code& ec); + system::result clear(); /** Cancel all operations associated with the signal set. diff --git a/src/corosio/src/detail/posix/signals.cpp b/src/corosio/src/detail/posix/signals.cpp index 59bcb6a..8a4d853 100644 --- a/src/corosio/src/detail/posix/signals.cpp +++ b/src/corosio/src/detail/posix/signals.cpp @@ -16,9 +16,6 @@ #include #include -#include - -#include #include #include @@ -78,7 +75,7 @@ operator()() auto* service = svc; svc = nullptr; - d.post(capy::any_coro{h}); + d.post(h); // Balance the on_work_started() from start_wait if (service) @@ -134,28 +131,28 @@ wait( *ec = make_error_code(capy::error::canceled); if (signal_out) *signal_out = 0; - d.post(capy::any_coro{h}); + d.post(h); return; } svc_.start_wait(*this, &pending_op_); } -system::error_code +system::result posix_signal_impl:: add(int signal_number) { return svc_.add_signal(*this, signal_number); } -system::error_code +system::result posix_signal_impl:: remove(int signal_number) { return svc_.remove_signal(*this, signal_number); } -system::error_code +system::result posix_signal_impl:: clear() { @@ -237,13 +234,13 @@ destroy_impl(posix_signal_impl& impl) delete &impl; } -system::error_code +system::result posix_signals:: add_signal( posix_signal_impl& impl, int signal_number) { - if (signal_number < 1 || signal_number >= max_signal_number) + if (signal_number < 0 || signal_number >= max_signal_number) return make_error_code(system::errc::invalid_argument); signal_state* state = get_signal_state(); @@ -292,13 +289,13 @@ add_signal( return {}; } -system::error_code +system::result posix_signals:: remove_signal( posix_signal_impl& impl, int signal_number) { - if (signal_number < 1 || signal_number >= max_signal_number) + if (signal_number < 0 || signal_number >= max_signal_number) return make_error_code(system::errc::invalid_argument); signal_state* state = get_signal_state(); @@ -318,7 +315,10 @@ remove_signal( // Restore default handler on last global unregistration if (state->registration_count[signal_number] == 1) - ::signal(signal_number, SIG_DFL); + { + if (::signal(signal_number, SIG_DFL) == SIG_ERR) + return make_error_code(system::errc::invalid_argument); + } *deletion_point = reg->next_in_set; @@ -336,7 +336,7 @@ remove_signal( return {}; } -system::error_code +system::result posix_signals:: clear_signals(posix_signal_impl& impl) { @@ -344,12 +344,17 @@ clear_signals(posix_signal_impl& impl) std::lock_guard state_lock(state->mutex); std::lock_guard lock(mutex_); + system::error_code first_error; + while (signal_registration* reg = impl.signals_) { int signal_number = reg->signal_number; if (state->registration_count[signal_number] == 1) - ::signal(signal_number, SIG_DFL); + { + if (::signal(signal_number, SIG_DFL) == SIG_ERR && !first_error) + first_error = make_error_code(system::errc::invalid_argument); + } impl.signals_ = reg->next_in_set; @@ -366,6 +371,8 @@ clear_signals(posix_signal_impl& impl) delete reg; } + if (first_error) + return first_error; return {}; } @@ -392,7 +399,7 @@ cancel_wait(posix_signal_impl& impl) *op->ec_out = make_error_code(capy::error::canceled); if (op->signal_out) *op->signal_out = 0; - op->d.post(capy::any_coro{op->h}); + op->d.post(op->h); sched_.on_work_finished(); } } @@ -430,7 +437,7 @@ void posix_signals:: deliver_signal(int signal_number) { - if (signal_number < 1 || signal_number >= max_signal_number) + if (signal_number < 0 || signal_number >= max_signal_number) return; signal_state* state = get_signal_state(); @@ -541,40 +548,6 @@ signal_set(capy::execution_context& ctx) impl_ = &ctx.use_service().create_impl(); } -signal_set:: -signal_set(capy::execution_context& ctx, int signal_number_1) - : io_object(ctx) -{ - impl_ = &ctx.use_service().create_impl(); - add(signal_number_1); -} - -signal_set:: -signal_set( - capy::execution_context& ctx, - int signal_number_1, - int signal_number_2) - : io_object(ctx) -{ - impl_ = &ctx.use_service().create_impl(); - add(signal_number_1); - add(signal_number_2); -} - -signal_set:: -signal_set( - capy::execution_context& ctx, - int signal_number_1, - int signal_number_2, - int signal_number_3) - : io_object(ctx) -{ - impl_ = &ctx.use_service().create_impl(); - add(signal_number_1); - add(signal_number_2); - add(signal_number_3); -} - signal_set:: signal_set(signal_set&& other) noexcept : io_object(std::move(other)) @@ -601,52 +574,25 @@ operator=(signal_set&& other) return *this; } -void +system::result signal_set:: add(int signal_number) { - system::error_code ec = get().add(signal_number); - if (ec) - detail::throw_system_error(ec, "signal_set::add"); + return get().add(signal_number); } -void -signal_set:: -add(int signal_number, system::error_code& ec) -{ - ec = get().add(signal_number); -} - -void +system::result signal_set:: remove(int signal_number) { - system::error_code ec = get().remove(signal_number); - if (ec) - detail::throw_system_error(ec, "signal_set::remove"); + return get().remove(signal_number); } -void -signal_set:: -remove(int signal_number, system::error_code& ec) -{ - ec = get().remove(signal_number); -} - -void +system::result signal_set:: clear() { - system::error_code ec = get().clear(); - if (ec) - detail::throw_system_error(ec, "signal_set::clear"); -} - -void -signal_set:: -clear(system::error_code& ec) -{ - ec = get().clear(); + return get().clear(); } void diff --git a/src/corosio/src/detail/posix/signals.hpp b/src/corosio/src/detail/posix/signals.hpp index 93b599f..3e60f7f 100644 --- a/src/corosio/src/detail/posix/signals.hpp +++ b/src/corosio/src/detail/posix/signals.hpp @@ -16,10 +16,12 @@ #include #include +#include #include #include #include #include +#include #include "src/detail/scheduler_op.hpp" @@ -46,7 +48,7 @@ enum { max_signal_number = 64 }; /** Signal wait operation state. */ struct signal_op : scheduler_op { - std::coroutine_handle<> h; + capy::any_coro h; capy::any_executor_ref d; system::error_code* ec_out = nullptr; int* signal_out = nullptr; @@ -102,9 +104,9 @@ class posix_signal_impl system::error_code*, int*) override; - system::error_code add(int signal_number) override; - system::error_code remove(int signal_number) override; - system::error_code clear() override; + system::result add(int signal_number) override; + system::result remove(int signal_number) override; + system::result clear() override; void cancel() override; }; @@ -153,9 +155,9 @@ class posix_signals : public capy::execution_context::service @param impl The signal implementation to modify. @param signal_number The signal to register. - @return Error code, or success. + @return Success, or an error. */ - system::error_code add_signal( + system::result add_signal( posix_signal_impl& impl, int signal_number); @@ -163,18 +165,18 @@ class posix_signals : public capy::execution_context::service @param impl The signal implementation to modify. @param signal_number The signal to unregister. - @return Error code, or success. + @return Success, or an error. */ - system::error_code remove_signal( + system::result remove_signal( posix_signal_impl& impl, int signal_number); /** Remove all signals from a signal set. @param impl The signal implementation to clear. - @return Error code, or success. + @return Success, or an error. */ - system::error_code clear_signals(posix_signal_impl& impl); + system::result clear_signals(posix_signal_impl& impl); /** Cancel pending wait operations. diff --git a/src/corosio/src/detail/win/signals.cpp b/src/corosio/src/detail/win/signals.cpp index 377e36c..a58e217 100644 --- a/src/corosio/src/detail/win/signals.cpp +++ b/src/corosio/src/detail/win/signals.cpp @@ -215,21 +215,21 @@ wait( svc_.start_wait(*this, &pending_op_); } -system::error_code +system::result win_signal_impl:: add(int signal_number) { return svc_.add_signal(*this, signal_number); } -system::error_code +system::result win_signal_impl:: remove(int signal_number) { return svc_.remove_signal(*this, signal_number); } -system::error_code +system::result win_signal_impl:: clear() { @@ -310,7 +310,7 @@ destroy_impl(win_signal_impl& impl) delete &impl; } -system::error_code +system::result win_signals:: add_signal( win_signal_impl& impl, @@ -367,7 +367,7 @@ add_signal( return {}; } -system::error_code +system::result win_signals:: remove_signal( win_signal_impl& impl, @@ -416,7 +416,7 @@ remove_signal( return {}; } -system::error_code +system::result win_signals:: clear_signals(win_signal_impl& impl) { @@ -424,13 +424,18 @@ clear_signals(win_signal_impl& impl) std::lock_guard state_lock(state->mutex); std::lock_guard lock(mutex_); + system::error_code first_error; + while (signal_registration* reg = impl.signals_) { int signal_number = reg->signal_number; // Restore default handler if last registration if (state->registration_count[signal_number] == 1) - ::signal(signal_number, SIG_DFL); + { + if (::signal(signal_number, SIG_DFL) == SIG_ERR && !first_error) + first_error = make_error_code(system::errc::invalid_argument); + } // Remove from set's list impl.signals_ = reg->next_in_set; @@ -448,6 +453,8 @@ clear_signals(win_signal_impl& impl) delete reg; } + if (first_error) + return first_error; return {}; } @@ -633,40 +640,6 @@ signal_set(capy::execution_context& ctx) impl_ = &ctx.use_service().create_impl(); } -signal_set:: -signal_set(capy::execution_context& ctx, int signal_number_1) - : io_object(ctx) -{ - impl_ = &ctx.use_service().create_impl(); - add(signal_number_1); -} - -signal_set:: -signal_set( - capy::execution_context& ctx, - int signal_number_1, - int signal_number_2) - : io_object(ctx) -{ - impl_ = &ctx.use_service().create_impl(); - add(signal_number_1); - add(signal_number_2); -} - -signal_set:: -signal_set( - capy::execution_context& ctx, - int signal_number_1, - int signal_number_2, - int signal_number_3) - : io_object(ctx) -{ - impl_ = &ctx.use_service().create_impl(); - add(signal_number_1); - add(signal_number_2); - add(signal_number_3); -} - signal_set:: signal_set(signal_set&& other) noexcept : io_object(std::move(other)) @@ -693,52 +666,25 @@ operator=(signal_set&& other) return *this; } -void +system::result signal_set:: add(int signal_number) { - system::error_code ec = get().add(signal_number); - if (ec) - detail::throw_system_error(ec, "signal_set::add"); -} - -void -signal_set:: -add(int signal_number, system::error_code& ec) -{ - ec = get().add(signal_number); + return get().add(signal_number); } -void +system::result signal_set:: remove(int signal_number) { - system::error_code ec = get().remove(signal_number); - if (ec) - detail::throw_system_error(ec, "signal_set::remove"); + return get().remove(signal_number); } -void -signal_set:: -remove(int signal_number, system::error_code& ec) -{ - ec = get().remove(signal_number); -} - -void +system::result signal_set:: clear() { - system::error_code ec = get().clear(); - if (ec) - detail::throw_system_error(ec, "signal_set::clear"); -} - -void -signal_set:: -clear(system::error_code& ec) -{ - ec = get().clear(); + return get().clear(); } void diff --git a/src/corosio/src/detail/win/signals.hpp b/src/corosio/src/detail/win/signals.hpp index 6803bec..e163982 100644 --- a/src/corosio/src/detail/win/signals.hpp +++ b/src/corosio/src/detail/win/signals.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "src/detail/iocp/mutex.hpp" #include "src/detail/scheduler_op.hpp" @@ -105,9 +106,9 @@ class win_signal_impl system::error_code*, int*) override; - system::error_code add(int signal_number) override; - system::error_code remove(int signal_number) override; - system::error_code clear() override; + system::result add(int signal_number) override; + system::result remove(int signal_number) override; + system::result clear() override; void cancel() override; }; @@ -158,9 +159,9 @@ class win_signals : public capy::execution_context::service @param impl The signal implementation to modify. @param signal_number The signal to register. - @return Error code, or success. + @return Success, or an error. */ - system::error_code add_signal( + system::result add_signal( win_signal_impl& impl, int signal_number); @@ -168,18 +169,18 @@ class win_signals : public capy::execution_context::service @param impl The signal implementation to modify. @param signal_number The signal to unregister. - @return Error code, or success. + @return Success, or an error. */ - system::error_code remove_signal( + system::result remove_signal( win_signal_impl& impl, int signal_number); /** Remove all signals from a signal set. @param impl The signal implementation to clear. - @return Error code, or success. + @return Success, or an error. */ - system::error_code clear_signals(win_signal_impl& impl); + system::result clear_signals(win_signal_impl& impl); /** Cancel pending wait operations. diff --git a/test/unit/signal_set.cpp b/test/unit/signal_set.cpp index 3263647..29dc71b 100644 --- a/test/unit/signal_set.cpp +++ b/test/unit/signal_set.cpp @@ -113,19 +113,8 @@ struct signal_set_test io_context ioc; signal_set s(ioc); - s.add(SIGINT); - BOOST_TEST_PASS(); - } - - void - testAddWithErrorCode() - { - io_context ioc; - signal_set s(ioc); - - system::error_code ec; - s.add(SIGINT, ec); - BOOST_TEST(!ec); + auto result = s.add(SIGINT); + BOOST_TEST(result.has_value()); } void @@ -134,9 +123,9 @@ struct signal_set_test io_context ioc; signal_set s(ioc); - s.add(SIGINT); - s.add(SIGINT); // Should be no-op - BOOST_TEST_PASS(); + BOOST_TEST(s.add(SIGINT).has_value()); + auto result = s.add(SIGINT); // Should be no-op + BOOST_TEST(result.has_value()); } void @@ -145,9 +134,8 @@ struct signal_set_test io_context ioc; signal_set s(ioc); - system::error_code ec; - s.add(-1, ec); - BOOST_TEST(ec); + auto result = s.add(-1); + BOOST_TEST(result.has_error()); } void @@ -156,21 +144,9 @@ struct signal_set_test io_context ioc; signal_set s(ioc); - s.add(SIGINT); - s.remove(SIGINT); - BOOST_TEST_PASS(); - } - - void - testRemoveWithErrorCode() - { - io_context ioc; - signal_set s(ioc); - - s.add(SIGINT); - system::error_code ec; - s.remove(SIGINT, ec); - BOOST_TEST(!ec); + BOOST_TEST(s.add(SIGINT).has_value()); + auto result = s.remove(SIGINT); + BOOST_TEST(result.has_value()); } void @@ -180,8 +156,8 @@ struct signal_set_test signal_set s(ioc); // Removing signal not in set should be a no-op - s.remove(SIGINT); - BOOST_TEST_PASS(); + auto result = s.remove(SIGINT); + BOOST_TEST(result.has_value()); } void @@ -190,22 +166,9 @@ struct signal_set_test io_context ioc; signal_set s(ioc); - s.add(SIGINT); - s.add(SIGTERM); - s.clear(); - BOOST_TEST_PASS(); - } - - void - testClearWithErrorCode() - { - io_context ioc; - signal_set s(ioc); - - s.add(SIGINT); - system::error_code ec; - s.clear(ec); - BOOST_TEST(!ec); + BOOST_TEST(s.add(SIGINT).has_value()); + BOOST_TEST(s.add(SIGTERM).has_value()); + BOOST_TEST(s.clear().has_value()); } void @@ -214,8 +177,7 @@ struct signal_set_test io_context ioc; signal_set s(ioc); - s.clear(); // Should be no-op - BOOST_TEST_PASS(); + BOOST_TEST(s.clear().has_value()); // Should be no-op } //-------------------------------------------- @@ -593,14 +555,11 @@ struct signal_set_test // Add/remove/clear tests testAdd(); - testAddWithErrorCode(); testAddDuplicate(); testAddInvalidSignal(); testRemove(); - testRemoveWithErrorCode(); testRemoveNotPresent(); testClear(); - testClearWithErrorCode(); testClearEmpty(); // Async wait tests