From f87bc2b1449a4fc73a7743183f104b240e5c3e03 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Tue, 7 Apr 2026 18:18:07 +0300 Subject: [PATCH] Add patch to fix Boost.Asio 1.90+ compatibility --- build-cmd.sh | 1 + patches/fix-boost-asio-1.90-compat.patch | 442 +++++++++++++++++++++++ 2 files changed, 443 insertions(+) create mode 100644 patches/fix-boost-asio-1.90-compat.patch diff --git a/build-cmd.sh b/build-cmd.sh index 070ea21..97bb5a7 100755 --- a/build-cmd.sh +++ b/build-cmd.sh @@ -48,3 +48,4 @@ popd # This only makes sense because this is a header-only library anyhow. patch --directory "$stage/include/" -p1 < "$top/patches/fix-cpp20-build.patch" patch --directory "$stage/include/" -p1 < "$top/patches/fix-server-handler-cpp20.patch" +patch --directory "$stage/include/" -p1 < "$top/patches/fix-boost-asio-1.90-compat.patch" diff --git a/patches/fix-boost-asio-1.90-compat.patch b/patches/fix-boost-asio-1.90-compat.patch new file mode 100644 index 0000000..68aa84a --- /dev/null +++ b/patches/fix-boost-asio-1.90-compat.patch @@ -0,0 +1,442 @@ +From 1479b4407df50c1f480b8c9faa1881d1cd3dbfdb Mon Sep 17 00:00:00 2001 +From: Andrey Lihatskiy +Date: Tue, 7 Apr 2026 17:49:50 +0300 +Subject: [PATCH] Fix Boost.Asio 1.90+ compatibility + +Boost 1.90 removed deprecated APIs that websocketpp 0.8.2 relied on: +- io_service -> io_context +- io_service::work -> executor_work_guard +- io_service::strand -> strand +- strand::wrap() -> bind_executor() +- timer::expires_from_now() -> (expiry() - now()) +- resolver::query + resolver::iterator -> resolve(host, port) + results_type +- socket_base::max_connections -> SOMAXCONN +--- + websocketpp/common/asio.hpp | 5 ++ + websocketpp/transport/asio/connection.hpp | 34 +++++------ + websocketpp/transport/asio/endpoint.hpp | 61 ++++++++++---------- + websocketpp/transport/asio/security/none.hpp | 4 +- + websocketpp/transport/asio/security/tls.hpp | 8 +-- + 5 files changed, 57 insertions(+), 55 deletions(-) + +diff --git a/websocketpp/common/asio.hpp b/websocketpp/common/asio.hpp +index 3c8fa13..a26dbc4 100644 +--- a/websocketpp/common/asio.hpp ++++ b/websocketpp/common/asio.hpp +@@ -93,6 +93,11 @@ namespace lib { + #else + namespace asio { + using namespace boost::asio; ++ ++ // Boost 1.90+ removed io_service entirely; provide a compatibility alias ++ #if BOOST_VERSION >= 109000 ++ typedef boost::asio::io_context io_service; ++ #endif + + // See note above about boost <1.49 compatibility + #if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48 +diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp +index 57dda74..d86a7a4 100644 +--- a/websocketpp/transport/asio/connection.hpp ++++ b/websocketpp/transport/asio/connection.hpp +@@ -86,9 +86,9 @@ public: + typedef typename response_type::ptr response_ptr; + + /// Type of a pointer to the Asio io_service being used +- typedef lib::asio::io_service * io_service_ptr; ++ typedef lib::asio::io_context * io_service_ptr; + /// Type of a pointer to the Asio io_service::strand being used +- typedef lib::shared_ptr strand_ptr; ++ typedef lib::shared_ptr> strand_ptr; + /// Type of a pointer to the Asio timer class + typedef lib::shared_ptr timer_ptr; + +@@ -318,7 +318,7 @@ public: + ); + + if (config::enable_multithreading) { +- new_timer->async_wait(m_strand->wrap(lib::bind( ++ new_timer->async_wait(lib::asio::bind_executor(*m_strand, lib::bind( + &type::handle_timer, get_shared(), + new_timer, + callback, +@@ -462,7 +462,7 @@ protected: + m_io_service = io_service; + + if (config::enable_multithreading) { +- m_strand.reset(new lib::asio::io_service::strand(*io_service)); ++ m_strand.reset(new lib::asio::strand(io_service->get_executor())); + } + + lib::error_code ec = socket_con_type::init_asio(io_service, m_strand, +@@ -573,7 +573,7 @@ protected: + lib::error_code const & ec) + { + if (ec == transport::error::operation_aborted || +- (post_timer && lib::asio::is_neg(post_timer->expires_from_now()))) ++ (post_timer && lib::asio::is_neg(post_timer->expiry() - lib::asio::steady_timer::clock_type::now()))) + { + m_alog->write(log::alevel::devel,"post_init cancelled"); + return; +@@ -629,7 +629,7 @@ protected: + lib::asio::async_write( + socket_con_type::get_next_layer(), + m_bufs, +- m_strand->wrap(lib::bind( ++ lib::asio::bind_executor(*m_strand, lib::bind( + &type::handle_proxy_write, get_shared(), + callback, + lib::placeholders::_1 +@@ -679,7 +679,7 @@ protected: + // Whatever aborted it will be issuing the callback so we are safe to + // return + if (ec == lib::asio::error::operation_aborted || +- lib::asio::is_neg(m_proxy_data->timer->expires_from_now())) ++ lib::asio::is_neg(m_proxy_data->timer->expiry() - lib::asio::steady_timer::clock_type::now())) + { + m_elog->write(log::elevel::devel,"write operation aborted"); + return; +@@ -713,7 +713,7 @@ protected: + socket_con_type::get_next_layer(), + m_proxy_data->read_buf, + "\r\n\r\n", +- m_strand->wrap(lib::bind( ++ lib::asio::bind_executor(*m_strand, lib::bind( + &type::handle_proxy_read, get_shared(), + callback, + lib::placeholders::_1, lib::placeholders::_2 +@@ -751,7 +751,7 @@ protected: + // Whatever aborted it will be issuing the callback so we are safe to + // return + if (ec == lib::asio::error::operation_aborted || +- lib::asio::is_neg(m_proxy_data->timer->expires_from_now())) ++ lib::asio::is_neg(m_proxy_data->timer->expiry() - lib::asio::steady_timer::clock_type::now())) + { + m_elog->write(log::elevel::devel,"read operation aborted"); + return; +@@ -841,7 +841,7 @@ protected: + socket_con_type::get_socket(), + lib::asio::buffer(buf,len), + lib::asio::transfer_at_least(num_bytes), +- m_strand->wrap(make_custom_alloc_handler( ++ lib::asio::bind_executor(*m_strand, make_custom_alloc_handler( + m_read_handler_allocator, + lib::bind( + &type::handle_async_read, get_shared(), +@@ -910,7 +910,7 @@ protected: + lib::asio::async_write( + socket_con_type::get_socket(), + m_bufs, +- m_strand->wrap(make_custom_alloc_handler( ++ lib::asio::bind_executor(*m_strand, make_custom_alloc_handler( + m_write_handler_allocator, + lib::bind( + &type::handle_async_write, get_shared(), +@@ -947,7 +947,7 @@ protected: + lib::asio::async_write( + socket_con_type::get_socket(), + m_bufs, +- m_strand->wrap(make_custom_alloc_handler( ++ lib::asio::bind_executor(*m_strand, make_custom_alloc_handler( + m_write_handler_allocator, + lib::bind( + &type::handle_async_write, get_shared(), +@@ -1012,18 +1012,18 @@ protected: + */ + lib::error_code interrupt(interrupt_handler handler) { + if (config::enable_multithreading) { +- m_io_service->post(m_strand->wrap(handler)); ++ lib::asio::post(*m_io_service, lib::asio::bind_executor(*m_strand, handler)); + } else { +- m_io_service->post(handler); ++ lib::asio::post(*m_io_service, handler); + } + return lib::error_code(); + } + + lib::error_code dispatch(dispatch_handler handler) { + if (config::enable_multithreading) { +- m_io_service->post(m_strand->wrap(handler)); ++ lib::asio::post(*m_io_service, lib::asio::bind_executor(*m_strand, handler)); + } else { +- m_io_service->post(handler); ++ lib::asio::post(*m_io_service, handler); + } + return lib::error_code(); + } +@@ -1095,7 +1095,7 @@ protected: + callback, lib::asio::error_code const & ec) + { + if (ec == lib::asio::error::operation_aborted || +- lib::asio::is_neg(shutdown_timer->expires_from_now())) ++ lib::asio::is_neg(shutdown_timer->expiry() - lib::asio::steady_timer::clock_type::now())) + { + m_alog->write(log::alevel::devel,"async_shutdown cancelled"); + return; +diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp +index 94509ad..e2b8ed7 100644 +--- a/websocketpp/transport/asio/endpoint.hpp ++++ b/websocketpp/transport/asio/endpoint.hpp +@@ -78,7 +78,7 @@ public: + typedef typename transport_con_type::ptr transport_con_ptr; + + /// Type of a pointer to the ASIO io_service being used +- typedef lib::asio::io_service * io_service_ptr; ++ typedef lib::asio::io_context * io_service_ptr; + /// Type of a shared pointer to the acceptor being used + typedef lib::shared_ptr acceptor_ptr; + /// Type of a shared pointer to the resolver being used +@@ -86,7 +86,7 @@ public: + /// Type of timer handle + typedef lib::shared_ptr timer_ptr; + /// Type of a shared pointer to an io_service work object +- typedef lib::shared_ptr work_ptr; ++ typedef lib::shared_ptr> work_ptr; + + /// Type of socket pre-bind handler + typedef lib::function tcp_pre_bind_handler; +@@ -95,7 +95,7 @@ public: + explicit endpoint() + : m_io_service(NULL) + , m_external_io_service(false) +- , m_listen_backlog(lib::asio::socket_base::max_connections) ++ , m_listen_backlog(SOMAXCONN) + , m_reuse_addr(false) + , m_state(UNINITIALIZED) + { +@@ -135,7 +135,7 @@ public: + , m_io_service(src.m_io_service) + , m_external_io_service(src.m_external_io_service) + , m_acceptor(src.m_acceptor) +- , m_listen_backlog(lib::asio::socket_base::max_connections) ++ , m_listen_backlog(SOMAXCONN) + , m_reuse_addr(src.m_reuse_addr) + , m_elog(src.m_elog) + , m_alog(src.m_alog) +@@ -159,7 +159,7 @@ public: + rhs.m_io_service = NULL; + rhs.m_external_io_service = false; + rhs.m_acceptor = NULL; +- rhs.m_listen_backlog = lib::asio::socket_base::max_connections; ++ rhs.m_listen_backlog = SOMAXCONN; + rhs.m_state = UNINITIALIZED; + + // TODO: this needs to be updated +@@ -230,9 +230,9 @@ public: + // TODO: remove the use of auto_ptr when C++98/03 support is no longer + // necessary. + #ifdef _WEBSOCKETPP_CPP11_MEMORY_ +- lib::unique_ptr service(new lib::asio::io_service()); ++ lib::unique_ptr service(new lib::asio::io_context()); + #else +- lib::auto_ptr service(new lib::asio::io_service()); ++ lib::auto_ptr service(new lib::asio::io_context()); + #endif + init_asio(service.get(), ec); + if( !ec ) service.release(); // Call was successful, transfer ownership +@@ -252,9 +252,9 @@ public: + // TODO: remove the use of auto_ptr when C++98/03 support is no longer + // necessary. + #ifdef _WEBSOCKETPP_CPP11_MEMORY_ +- lib::unique_ptr service(new lib::asio::io_service()); ++ lib::unique_ptr service(new lib::asio::io_context()); + #else +- lib::auto_ptr service(new lib::asio::io_service()); ++ lib::auto_ptr service(new lib::asio::io_context()); + #endif + init_asio( service.get() ); + // If control got this far without an exception, then ownership has successfully been taken +@@ -375,7 +375,7 @@ public: + * + * @return A reference to the endpoint's io_service + */ +- lib::asio::io_service & get_io_service() { ++ lib::asio::io_context & get_io_service() { + return *m_io_service; + } + +@@ -558,16 +558,14 @@ public: + { + using lib::asio::ip::tcp; + tcp::resolver r(*m_io_service); +- tcp::resolver::query query(host, service); +- tcp::resolver::iterator endpoint_iterator = r.resolve(query); +- tcp::resolver::iterator end; +- if (endpoint_iterator == end) { ++ auto results = r.resolve(host, service); ++ if (results.empty()) { + m_elog->write(log::elevel::library, + "asio::listen could not resolve the supplied host or service"); + ec = make_error_code(error::invalid_host_service); + return; + } +- listen(*endpoint_iterator,ec); ++ listen(*results.begin(),ec); + } + + /// Set up endpoint for listening on a host and service +@@ -666,7 +664,7 @@ public: + + /// wraps the reset method of the internal io_service object + void reset() { +- m_io_service->reset(); ++ m_io_service->restart(); + } + + /// wraps the stopped method of the internal io_service object +@@ -687,7 +685,7 @@ public: + * @since 0.3.0 + */ + void start_perpetual() { +- m_work.reset(new lib::asio::io_service::work(*m_io_service)); ++ m_work.reset(new lib::asio::executor_work_guard(m_io_service->get_executor())); + } + + /// Clears the endpoint's perpetual flag, allowing it to exit when empty +@@ -779,7 +777,7 @@ public: + if (config::enable_multithreading) { + m_acceptor->async_accept( + tcon->get_raw_socket(), +- tcon->get_strand()->wrap(lib::bind( ++ lib::asio::bind_executor(*tcon->get_strand(), lib::bind( + &type::handle_accept, + this, + callback, +@@ -883,8 +881,6 @@ protected: + port = pu->get_port_str(); + } + +- tcp::resolver::query query(host,port); +- + if (m_alog->static_test(log::alevel::devel)) { + m_alog->write(log::alevel::devel, + "starting async DNS resolve for "+host+":"+port); +@@ -905,8 +901,9 @@ protected: + + if (config::enable_multithreading) { + m_resolver->async_resolve( +- query, +- tcon->get_strand()->wrap(lib::bind( ++ host, ++ port, ++ lib::asio::bind_executor(*tcon->get_strand(), lib::bind( + &type::handle_resolve, + this, + tcon, +@@ -918,7 +915,8 @@ protected: + ); + } else { + m_resolver->async_resolve( +- query, ++ host, ++ port, + lib::bind( + &type::handle_resolve, + this, +@@ -966,10 +964,10 @@ protected: + + void handle_resolve(transport_con_ptr tcon, timer_ptr dns_timer, + connect_handler callback, lib::asio::error_code const & ec, +- lib::asio::ip::tcp::resolver::iterator iterator) ++ lib::asio::ip::tcp::resolver::results_type results) + { + if (ec == lib::asio::error::operation_aborted || +- lib::asio::is_neg(dns_timer->expires_from_now())) ++ lib::asio::is_neg(dns_timer->expiry() - lib::asio::steady_timer::clock_type::now())) + { + m_alog->write(log::alevel::devel,"async_resolve cancelled"); + return; +@@ -987,9 +985,8 @@ protected: + std::stringstream s; + s << "Async DNS resolve successful. Results: "; + +- lib::asio::ip::tcp::resolver::iterator it, end; +- for (it = iterator; it != end; ++it) { +- s << (*it).endpoint() << " "; ++ for (auto const & entry : results) { ++ s << entry.endpoint() << " "; + } + + m_alog->write(log::alevel::devel,s.str()); +@@ -1014,8 +1011,8 @@ protected: + if (config::enable_multithreading) { + lib::asio::async_connect( + tcon->get_raw_socket(), +- iterator, +- tcon->get_strand()->wrap(lib::bind( ++ results, ++ lib::asio::bind_executor(*tcon->get_strand(), lib::bind( + &type::handle_connect, + this, + tcon, +@@ -1027,7 +1024,7 @@ protected: + } else { + lib::asio::async_connect( + tcon->get_raw_socket(), +- iterator, ++ results, + lib::bind( + &type::handle_connect, + this, +@@ -1077,7 +1074,7 @@ protected: + connect_handler callback, lib::asio::error_code const & ec) + { + if (ec == lib::asio::error::operation_aborted || +- lib::asio::is_neg(con_timer->expires_from_now())) ++ lib::asio::is_neg(con_timer->expiry() - lib::asio::steady_timer::clock_type::now())) + { + m_alog->write(log::alevel::devel,"async_connect cancelled"); + return; +diff --git a/websocketpp/transport/asio/security/none.hpp b/websocketpp/transport/asio/security/none.hpp +index 6c7d352..c4e8d69 100644 +--- a/websocketpp/transport/asio/security/none.hpp ++++ b/websocketpp/transport/asio/security/none.hpp +@@ -63,9 +63,9 @@ public: + typedef lib::shared_ptr ptr; + + /// Type of a pointer to the Asio io_service being used +- typedef lib::asio::io_service* io_service_ptr; ++ typedef lib::asio::io_context* io_service_ptr; + /// Type of a pointer to the Asio io_service strand being used +- typedef lib::shared_ptr strand_ptr; ++ typedef lib::shared_ptr> strand_ptr; + /// Type of the ASIO socket being used + typedef lib::asio::ip::tcp::socket socket_type; + /// Type of a shared pointer to the socket being used. +diff --git a/websocketpp/transport/asio/security/tls.hpp b/websocketpp/transport/asio/security/tls.hpp +index 04ac379..965886d 100644 +--- a/websocketpp/transport/asio/security/tls.hpp ++++ b/websocketpp/transport/asio/security/tls.hpp +@@ -72,9 +72,9 @@ public: + /// Type of a shared pointer to the ASIO socket being used + typedef lib::shared_ptr socket_ptr; + /// Type of a pointer to the ASIO io_service being used +- typedef lib::asio::io_service * io_service_ptr; ++ typedef lib::asio::io_context * io_service_ptr; + /// Type of a pointer to the ASIO io_service strand being used +- typedef lib::shared_ptr strand_ptr; ++ typedef lib::shared_ptr> strand_ptr; + /// Type of a shared pointer to the ASIO TLS context being used + typedef lib::shared_ptr context_ptr; + +@@ -266,7 +266,7 @@ protected: + if (m_strand) { + m_socket->async_handshake( + get_handshake_type(), +- m_strand->wrap(lib::bind( ++ lib::asio::bind_executor(*m_strand, lib::bind( + &type::handle_init, get_shared(), + callback, + lib::placeholders::_1 +@@ -326,7 +326,7 @@ protected: + + void async_shutdown(socket::shutdown_handler callback) { + if (m_strand) { +- m_socket->async_shutdown(m_strand->wrap(callback)); ++ m_socket->async_shutdown(lib::asio::bind_executor(*m_strand, callback)); + } else { + m_socket->async_shutdown(callback); + } +-- +2.45.2.windows.1 +