diff --git a/build/scripts/bootstrap.sh b/build/scripts/bootstrap.sh index 3e2d41fa..6a81ce04 100755 --- a/build/scripts/bootstrap.sh +++ b/build/scripts/bootstrap.sh @@ -79,9 +79,9 @@ function installBuildDependencies pushd /tmp/gtest if [[ ($DISTRO == "ubuntu" && ($VER == "20.04" || $VER == "22.04" || $VER == "24.04")) - || ($DISTRO == "debian" && ($VER == "10" || $VER == "11" || $VER == "12")) ]]; + || ($DISTRO == "debian" && ($VER == "10" || $VER == "11" || $VER == "12" || $VER == "13")) ]]; then - if [[ $VER == "22.04" || $VER == "24.04" || $VER == "12" ]]; then release="v1.13.0"; else release="release-1.10.0"; fi; + if [[ $VER == "22.04" || $VER == "24.04" || $VER == "12" || $VER == "13" ]]; then release="v1.13.0"; else release="release-1.10.0"; fi; # The latest native-version of gtest on the latest versions of ubuntu and debian currently has a bug where # CMakeLists doesn't declare an install target, causing 'make install' to fail. @@ -168,8 +168,8 @@ function installAll function isSupportedLinux() { - if [[ ($DISTRO == "ubuntu" && ($VER == "18.04" || $VER == "20.04" || $VER == "22.04" || $VER == "24.04")) - || ($DISTRO == "debian" && ($VER == "10" || $VER == "11" || $VER == "12")) ]]; + if [[ ($DISTRO == "ubuntu" && ($VER == "20.04" || $VER == "22.04" || $VER == "24.04")) + || ($DISTRO == "debian" && ($VER == "10" || $VER == "11" || $VER == "12" || $VER == "13")) ]]; then return 0 else diff --git a/client-lite/src/exe/docs.cpp b/client-lite/src/exe/docs.cpp index 8360ce00..d3f61b6f 100644 --- a/client-lite/src/exe/docs.cpp +++ b/client-lite/src/exe/docs.cpp @@ -112,14 +112,14 @@ class BoostAsioService _workerThread.join(); } - boost::asio::io_service& IoService() + boost::asio::io_context& IoContext() { return _io; } private: - boost::asio::io_service _io; - boost::asio::io_service::work _work { _io }; + boost::asio::io_context _io; + boost::asio::executor_work_guard _work{_io.get_executor()}; std::thread _workerThread; }; @@ -134,7 +134,7 @@ HRESULT Run() try auto downloadManager = std::make_shared(clientConfigs); RestHttpController controller(clientConfigs, downloadManager); - controller.Start(asioService.IoService()); + controller.Start(asioService.IoContext()); DoLogInfo("HTTP controller listening at: %s", controller.ServerEndpoint().data()); RestPortAdvertiser portAdvertiser(controller.Port()); diff --git a/client-lite/src/ipc/rest_http_controller.cpp b/client-lite/src/ipc/rest_http_controller.cpp index 2268410b..2ba493dc 100644 --- a/client-lite/src/ipc/rest_http_controller.cpp +++ b/client-lite/src/ipc/rest_http_controller.cpp @@ -28,9 +28,9 @@ RestHttpController::~RestHttpController() (void)_callTracker.Wait(); } -void RestHttpController::Start(boost::asio::io_service& ioService) +void RestHttpController::Start(boost::asio::io_context& ioContext) { - _listener.Start(ioService, std::bind(&RestHttpController::_HttpListenerCallback, this, std::placeholders::_1, std::placeholders::_2)); + _listener.Start(ioContext, std::bind(&RestHttpController::_HttpListenerCallback, this, std::placeholders::_1, std::placeholders::_2)); } std::string RestHttpController::ServerEndpoint() const diff --git a/client-lite/src/ipc/rest_http_controller.h b/client-lite/src/ipc/rest_http_controller.h index 87ab1d1a..dddd56d5 100644 --- a/client-lite/src/ipc/rest_http_controller.h +++ b/client-lite/src/ipc/rest_http_controller.h @@ -19,7 +19,7 @@ class RestHttpController RestHttpController(ConfigManager& config, std::shared_ptr downloadManager); ~RestHttpController(); - void Start(boost::asio::io_service& ioService); + void Start(boost::asio::io_context& ioContext); std::string ServerEndpoint() const; uint16_t Port() const; diff --git a/client-lite/src/ipc/rest_http_listener.cpp b/client-lite/src/ipc/rest_http_listener.cpp index 498f3ceb..14ce5d49 100644 --- a/client-lite/src/ipc/rest_http_listener.cpp +++ b/client-lite/src/ipc/rest_http_listener.cpp @@ -6,9 +6,9 @@ using boost_tcp_t = boost::asio::ip::tcp; -void RestHttpListener::Start(boost::asio::io_service& ioService, const http_listener_callback_t& requestHandler) +void RestHttpListener::Start(boost::asio::io_context& ioContext, const http_listener_callback_t& requestHandler) { - _io = &ioService; + _io = &ioContext; _requestHandler = requestHandler; // IANA suggests ephemeral ports can be in range [49125, 65535]. @@ -16,9 +16,9 @@ void RestHttpListener::Start(boost::asio::io_service& ioService, const http_list // We just choose a range that lies within all three implementations. uint16_t restPort = 50000; constexpr uint16_t restPortLimit = 60999; - const auto addr = boost::asio::ip::address_v4::from_string("127.0.0.1"); + const auto addr = boost::asio::ip::make_address_v4("127.0.0.1"); boost_tcp_t::endpoint endpoint(addr, restPort); - boost_tcp_t::acceptor tmpListener{ioService, endpoint.protocol()}; + boost_tcp_t::acceptor tmpListener{ioContext, endpoint.protocol()}; while (true) { endpoint.port(restPort); diff --git a/client-lite/src/ipc/rest_http_listener.h b/client-lite/src/ipc/rest_http_listener.h index bfcbfdf3..30be3394 100644 --- a/client-lite/src/ipc/rest_http_listener.h +++ b/client-lite/src/ipc/rest_http_listener.h @@ -10,7 +10,7 @@ class RestHttpListener { public: - void Start(boost::asio::io_service& ioService, const http_listener_callback_t& requestHandler); + void Start(boost::asio::io_context& ioContext, const http_listener_callback_t& requestHandler); void Stop(); std::string Endpoint() const; uint16_t Port() const; @@ -21,7 +21,7 @@ class RestHttpListener std::unique_ptr _listener; http_listener_callback_t _requestHandler; - boost::asio::io_service* _io { nullptr }; + boost::asio::io_context* _io { nullptr }; std::atomic _numConnections { 0 }; }; diff --git a/client-lite/src/ipc/rest_http_listener_conn.cpp b/client-lite/src/ipc/rest_http_listener_conn.cpp index 07291e6a..65f57f74 100644 --- a/client-lite/src/ipc/rest_http_listener_conn.cpp +++ b/client-lite/src/ipc/rest_http_listener_conn.cpp @@ -10,9 +10,9 @@ using boost_tcp_t = boost::asio::ip::tcp; namespace msdod = microsoft::deliveryoptimization::details; -HttpListenerConnection::HttpListenerConnection(boost::asio::io_service& ioService, std::shared_ptr socket) : +HttpListenerConnection::HttpListenerConnection(boost::asio::io_context& ioContext, std::shared_ptr socket) : _socket(std::move(socket)), - _io(ioService) + _io(ioContext) { _recvBuf.resize(2048); } @@ -29,10 +29,10 @@ HttpListenerConnection::~HttpListenerConnection() } } -std::shared_ptr HttpListenerConnection::Make(boost::asio::io_service& ioService, +std::shared_ptr HttpListenerConnection::Make(boost::asio::io_context& ioContext, std::shared_ptr socket) { - return std::make_shared(ioService, std::move(socket)); + return std::make_shared(ioContext, std::move(socket)); } void HttpListenerConnection::Receive(http_listener_callback_t& callback) @@ -130,7 +130,7 @@ void HttpListenerConnection::_OnData(const boost::system::error_code& ec, size_t if (_httpParser.Done()) { - _io.post([this, lifetime = shared_from_this(), parsedData = _httpParser.ParsedData(), &callback]() + boost::asio::post(_io, [this, lifetime = shared_from_this(), parsedData = _httpParser.ParsedData(), &callback]() { callback(parsedData, *this); }); diff --git a/client-lite/src/ipc/rest_http_listener_conn.h b/client-lite/src/ipc/rest_http_listener_conn.h index 5fa02fd8..4ac1dbd0 100644 --- a/client-lite/src/ipc/rest_http_listener_conn.h +++ b/client-lite/src/ipc/rest_http_listener_conn.h @@ -14,10 +14,10 @@ using http_listener_callback_t = std::function { public: - HttpListenerConnection(boost::asio::io_service& ioService, std::shared_ptr socket); + HttpListenerConnection(boost::asio::io_context& ioContext, std::shared_ptr socket); ~HttpListenerConnection(); - static std::shared_ptr Make(boost::asio::io_service& ioService, + static std::shared_ptr Make(boost::asio::io_context& ioContext, std::shared_ptr socket); void Receive(http_listener_callback_t& callback); @@ -30,7 +30,7 @@ class HttpListenerConnection : public std::enable_shared_from_this _socket; - boost::asio::io_service& _io; + boost::asio::io_context& _io; std::vector _recvBuf; microsoft::deliveryoptimization::details::HttpParser _httpParser; diff --git a/client-lite/test/mcc_manager.tests.cpp b/client-lite/test/mcc_manager.tests.cpp index c9523a2e..a9ade933 100644 --- a/client-lite/test/mcc_manager.tests.cpp +++ b/client-lite/test/mcc_manager.tests.cpp @@ -254,8 +254,7 @@ TEST_F(MCCManagerTests, BoostResolverGoodQuery) { dotest::util::BoostAsioWorker asioService; - btcp_t::resolver::query goodQuery("dl.delivery.mp.microsoft.com", "80"); - const auto spEndpoint = asioService.ResolveDnsQuery(goodQuery); + const auto spEndpoint = asioService.ResolveDnsQuery("dl.delivery.mp.microsoft.com", "80"); ASSERT_TRUE(spEndpoint) << "Found at least one address"; } @@ -264,13 +263,11 @@ TEST_F(MCCManagerTests, BoostResolverQuery) dotest::util::BoostAsioWorker asioService; std::cout << "Issuing the bad query\n"; - btcp_t::resolver::query badQuery("ahdkhkasdhaksd", "80"); - auto spEndpoint = asioService.ResolveDnsQuery(badQuery); + auto spEndpoint = asioService.ResolveDnsQuery("ahdkhkasdhaksd", "80"); ASSERT_FALSE(spEndpoint) << "Found no addresses for the bad query"; std::cout << "\nIssuing the good query in 5 seconds\n"; std::this_thread::sleep_for(std::chrono::seconds(5)); - btcp_t::resolver::query goodQuery("dl.delivery.mp.microsoft.com", "80"); - spEndpoint = asioService.ResolveDnsQuery(goodQuery); + spEndpoint = asioService.ResolveDnsQuery("dl.delivery.mp.microsoft.com", "80"); ASSERT_TRUE(spEndpoint) << "Found at least one address for the good query"; } diff --git a/client-lite/test/rest_http_listener_tests.cpp b/client-lite/test/rest_http_listener_tests.cpp index 592e49ac..4ea6b0d8 100644 --- a/client-lite/test/rest_http_listener_tests.cpp +++ b/client-lite/test/rest_http_listener_tests.cpp @@ -23,7 +23,7 @@ TEST(RestListenerTests, ManyPortsInUse) { try { - bsock_t sock(asioWorker.Service()); + bsock_t sock(asioWorker.Context()); sock.open(btcp_t::v4()); sock.bind(btcp_t::endpoint(btcp_t::v4(), port)); sockets.push_back(std::move(sock)); @@ -60,7 +60,7 @@ TEST(RestListenerTests, ManyPortsInUse) RestHttpListener listener; const auto before = std::chrono::steady_clock::now(); - listener.Start(asioWorker.Service(), http_listener_callback_t{}); + listener.Start(asioWorker.Context(), http_listener_callback_t{}); const auto after = std::chrono::steady_clock::now(); std::cout << "Listener started at: " << listener.Endpoint() << "\n"; const auto elapsedMsecs = std::chrono::duration_cast(after - before).count(); diff --git a/common/lib-dotestutil/do_test_helpers.cpp b/common/lib-dotestutil/do_test_helpers.cpp index 3bd42fb5..cc977c88 100644 --- a/common/lib-dotestutil/do_test_helpers.cpp +++ b/common/lib-dotestutil/do_test_helpers.cpp @@ -40,32 +40,36 @@ BoostAsioWorker::~BoostAsioWorker() } // Returns nullptr if no address was found for the DNS query -std::unique_ptr BoostAsioWorker::ResolveDnsQuery(const btcp_t::resolver::query& resolverQuery, +std::unique_ptr BoostAsioWorker::ResolveDnsQuery(const std::string& host, const std::string& port, const boost::asio::ip::tcp::resolver::protocol_type* prot) { std::promise> epPromise; auto fut = epPromise.get_future(); - auto fnResolveHandler = [&epPromise, prot](const boost::system::error_code& ec, btcp_t::resolver::iterator endpoints) -> void + auto fnResolveHandler = [&epPromise, prot](const boost::system::error_code& ec, btcp_t::resolver::results_type endpoints) -> void { std::unique_ptr spFoundEp; if (ec) { std::cout << FormatString("Error resolving address: %d, %s\n", ec.value(), ec.message().c_str()); } - else if (endpoints == btcp_t::resolver::iterator()) + else if (endpoints.empty()) { std::cout << "Failed to resolve address to any endpoints\n"; } else { std::cout << "Resolved endpoints:\n"; - while (endpoints != btcp_t::resolver::iterator()) + + for (const auto& ep : endpoints) { - const auto& ep = *endpoints++; - std::cout << FormatString("Host: %s, IP: %s\n", ep.host_name().data(), ep.endpoint().address().to_string().c_str()); + std::cout << FormatString( + "Host: %s, IP: %s\n", + ep.host_name().data(), + ep.endpoint().address().to_string().c_str()); + if ((prot == nullptr) || (ep.endpoint().protocol() == *prot)) { - spFoundEp = std::make_unique(ep); + spFoundEp = std::make_unique(ep.endpoint()); } } } @@ -77,8 +81,8 @@ std::unique_ptr BoostAsioWorker::ResolveDnsQuery(const btcp_t: }; btcp_t::resolver queryResolver(_io); - std::cout << "Issuing query: " << resolverQuery.host_name() << ":" << resolverQuery.service_name() << '\n'; - queryResolver.async_resolve(resolverQuery, fnResolveHandler); + std::cout << "Issuing query: " << host << ":" << port << '\n'; + queryResolver.async_resolve(host, port, fnResolveHandler); std::cout << "Waiting...\n"; if (fut.wait_for(std::chrono::seconds(30)) == std::future_status::timeout) { diff --git a/common/lib-dotestutil/do_test_helpers.h b/common/lib-dotestutil/do_test_helpers.h index 0e55ddd9..af9bc290 100644 --- a/common/lib-dotestutil/do_test_helpers.h +++ b/common/lib-dotestutil/do_test_helpers.h @@ -35,14 +35,14 @@ class BoostAsioWorker public: ~BoostAsioWorker(); - std::unique_ptr ResolveDnsQuery(const boost::asio::ip::tcp::resolver::query& resolverQuery, + std::unique_ptr ResolveDnsQuery(const std::string& host, const std::string& port, const boost::asio::ip::tcp::resolver::protocol_type* prot = nullptr); - boost::asio::io_service& Service() { return _io; } + boost::asio::io_context& Context() { return _io; } private: - boost::asio::io_service _io; - boost::asio::io_service::work _work { _io }; + boost::asio::io_context _io; + boost::asio::executor_work_guard _work{_io.get_executor()}; std::thread _myThread { [this](){ _io.run(); } }; }; #endif // DO_PLATFORM_LINUX diff --git a/sdk-cpp/src/internal/rest/util/do_http_client.cpp b/sdk-cpp/src/internal/rest/util/do_http_client.cpp index f044f2a4..fd52b4af 100644 --- a/sdk-cpp/src/internal/rest/util/do_http_client.cpp +++ b/sdk-cpp/src/internal/rest/util/do_http_client.cpp @@ -2,10 +2,7 @@ #include #include -// Debian10 uses 1.67 while Ubuntu18.04 has 1.65.1. -// Starting in 1.66, boost::asio::io_service changed to io_context and retained io_service as a typedef. -// Include this header explicitly to get it regardless of which boost version is installed. -#include +#include #include #include @@ -40,7 +37,7 @@ class CHttpClientImpl boost::system::error_code Connect(ushort port) { tcp::resolver resolver{_ioc}; - const auto endpoints = resolver.resolve({ "127.0.0.1", std::to_string(port) }); + const auto endpoints = resolver.resolve("127.0.0.1", std::to_string(port)); boost::system::error_code ec; boost::asio::connect(_socket, endpoints, ec); return ec; @@ -58,7 +55,7 @@ class CHttpClientImpl } private: - net::io_service _ioc; + net::io_context _ioc; net::ip::tcp::socket _socket{_ioc}; }; diff --git a/sdk-cpp/tests/rest/rest_interface_tests.cpp b/sdk-cpp/tests/rest/rest_interface_tests.cpp index 42856ca9..3df0fc7f 100644 --- a/sdk-cpp/tests/rest/rest_interface_tests.cpp +++ b/sdk-cpp/tests/rest/rest_interface_tests.cpp @@ -41,12 +41,12 @@ void VerifyRestInterfaceWithLocalEndpoint(const btcp_t::endpoint& localEndpoint, { std::cout << "Will bind to local address: " << localEndpoint << std::endl; - auto sock = btcp_t::socket(asioService.Service(), btcp_t::v4()); + auto sock = btcp_t::socket(asioService.Context(), btcp_t::v4()); boost::system::error_code ec; sock.bind(localEndpoint, ec); ASSERT_FALSE(ec) << "Expect no bind failure but got: " << ec.message(); - auto addr = boost::asio::ip::address::from_string("127.0.0.1"); + auto addr = boost::asio::ip::make_address_v4("127.0.0.1"); const auto restPortStr = microsoft::deliveryoptimization::details::CPortFinder::GetDOPort(); ASSERT_TRUE(!restPortStr.empty()); @@ -79,10 +79,9 @@ TEST_F(RestInterfaceTests, RestInterfaceUseLocalHostForLocalSocket) { dotest::util::BoostAsioWorker asioService; - const auto localHostname = boost::asio::ip::host_name(); - btcp_t::resolver::query query(localHostname, ""); + const std::string localHostname = boost::asio::ip::host_name(); auto prot = btcp_t::v4(); - auto spLocalEp = asioService.ResolveDnsQuery(query, &prot); + auto spLocalEp = asioService.ResolveDnsQuery(localHostname, "", &prot); ASSERT_TRUE(spLocalEp) << "Found at least one address for the local hostname query"; // Hostname can resolve to either a loopback address or private address depending on machine/network config @@ -95,7 +94,7 @@ TEST_F(RestInterfaceTests, RestInterfaceUseLoopbackForLocalSocket) { dotest::util::BoostAsioWorker asioService; - auto loopbackIpAddr = boost::asio::ip::address::from_string("127.0.1.5"); + auto loopbackIpAddr = boost::asio::ip::make_address_v4("127.0.1.5"); auto loopbackEp = btcp_t::endpoint(loopbackIpAddr, 0); VerifyRestInterfaceWithLocalEndpoint(loopbackEp, "200 OK", asioService); } @@ -105,7 +104,7 @@ TEST_F(RestInterfaceTests, RestInterfaceUsePrivateIPForLocalSocket) { dotest::util::BoostAsioWorker asioService; - auto privateIpAddr = boost::asio::ip::address::from_string(TestHelpers::GetLocalIPv4Address()); + auto privateIpAddr = boost::asio::ip::make_address_v4(TestHelpers::GetLocalIPv4Address()); ASSERT_TRUE(!privateIpAddr.is_loopback()); auto privateEp = btcp_t::endpoint(privateIpAddr, 0); VerifyRestInterfaceWithLocalEndpoint(privateEp, "400 BadRequest", asioService);