17f664254SPatrick Williams /* 27f664254SPatrick Williams // Copyright (c) 2018 Intel Corporation 37f664254SPatrick Williams // 47f664254SPatrick Williams // Licensed under the Apache License, Version 2.0 (the "License"); 57f664254SPatrick Williams // you may not use this file except in compliance with the License. 67f664254SPatrick Williams // You may obtain a copy of the License at 77f664254SPatrick Williams // 87f664254SPatrick Williams // http://www.apache.org/licenses/LICENSE-2.0 97f664254SPatrick Williams // 107f664254SPatrick Williams // Unless required by applicable law or agreed to in writing, software 117f664254SPatrick Williams // distributed under the License is distributed on an "AS IS" BASIS, 127f664254SPatrick Williams // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137f664254SPatrick Williams // See the License for the specific language governing permissions and 147f664254SPatrick Williams // limitations under the License. 157f664254SPatrick Williams */ 167f664254SPatrick Williams #pragma once 177f664254SPatrick Williams 187f664254SPatrick Williams #ifndef BOOST_COROUTINES_NO_DEPRECATION_WARNING 197f664254SPatrick Williams // users should define this if they directly include boost/asio/spawn.hpp, 207f664254SPatrick Williams // but by defining it here, warnings won't cause problems with a compile 217f664254SPatrick Williams #define BOOST_COROUTINES_NO_DEPRECATION_WARNING 227f664254SPatrick Williams #endif 237f664254SPatrick Williams 2438ab5ecfSEd Tanous #include <boost/asio/async_result.hpp> 2538ab5ecfSEd Tanous #include <boost/asio/io_context.hpp> 2638ab5ecfSEd Tanous #include <boost/asio/posix/stream_descriptor.hpp> 2738ab5ecfSEd Tanous #include <boost/asio/post.hpp> 28cd3bf08aSEd Tanous #include <boost/asio/steady_timer.hpp> 29cd3bf08aSEd Tanous 301778b12bSEd Tanous #ifndef SDBUSPLUS_DISABLE_BOOST_COROUTINES 317f664254SPatrick Williams #include <boost/asio/spawn.hpp> 321778b12bSEd Tanous #endif 337f664254SPatrick Williams #include <boost/callable_traits.hpp> 347f664254SPatrick Williams #include <sdbusplus/asio/detail/async_send_handler.hpp> 357f664254SPatrick Williams #include <sdbusplus/message.hpp> 367f664254SPatrick Williams #include <sdbusplus/utility/read_into_tuple.hpp> 377f664254SPatrick Williams #include <sdbusplus/utility/type_traits.hpp> 387f664254SPatrick Williams 397f664254SPatrick Williams #include <chrono> 4067cfca77SAlexander Hansen #include <functional> 417f664254SPatrick Williams #include <string> 427f664254SPatrick Williams #include <tuple> 437f664254SPatrick Williams 447f664254SPatrick Williams namespace sdbusplus 457f664254SPatrick Williams { 467f664254SPatrick Williams 477f664254SPatrick Williams namespace asio 487f664254SPatrick Williams { 497f664254SPatrick Williams 507f664254SPatrick Williams /// Root D-Bus IO object 517f664254SPatrick Williams /** 527f664254SPatrick Williams * A connection to a bus, through which messages may be sent or received. 537f664254SPatrick Williams */ 540f282c48SPatrick Williams class connection : public sdbusplus::bus_t 557f664254SPatrick Williams { 567f664254SPatrick Williams public: 57*17a3263cSPatrick Williams // default to default bus connection(boost::asio::io_context & io,sdbusplus::bus_t && bus=sdbusplus::bus::new_default ())58*17a3263cSPatrick Williams explicit connection( 59*17a3263cSPatrick Williams boost::asio::io_context& io, 60*17a3263cSPatrick Williams sdbusplus::bus_t&& bus = sdbusplus::bus::new_default()) : 61*17a3263cSPatrick Williams sdbusplus::bus_t(std::move(bus)), io_(io), 62cd3bf08aSEd Tanous socket(io_.get_executor(), get_fd()), timer(io_.get_executor()) 637f664254SPatrick Williams { 64894d6ca4SRahul Kapoor read_immediate(); 657f664254SPatrick Williams } connection(boost::asio::io_context & io,sd_bus * bus)667f664254SPatrick Williams connection(boost::asio::io_context& io, sd_bus* bus) : 67cd3bf08aSEd Tanous sdbusplus::bus_t(bus), io_(io), socket(io_.get_executor(), get_fd()), 68cd3bf08aSEd Tanous timer(io_.get_executor()) 697f664254SPatrick Williams { 70894d6ca4SRahul Kapoor read_immediate(); 717f664254SPatrick Williams } ~connection()727f664254SPatrick Williams ~connection() 737f664254SPatrick Williams { 747f664254SPatrick Williams // The FD will be closed by the socket object, so assign null to the 757f664254SPatrick Williams // sd_bus object to avoid a double close() Ignore return codes here, 767f664254SPatrick Williams // because there's nothing we can do about errors 777f664254SPatrick Williams socket.release(); 787f664254SPatrick Williams } 797f664254SPatrick Williams 807f664254SPatrick Williams /** @brief Perform an asynchronous send of a message, executing the handler 817f664254SPatrick Williams * upon return and return 827f664254SPatrick Williams * 837f664254SPatrick Williams * @param[in] m - A message ready to send 846c97486fSEd Tanous * @param[in] token - The completion token to execute upon completion; 85ddc57bdfSEd Tanous * @param[in] timeout - The timeout in microseconds 867f664254SPatrick Williams * 877f664254SPatrick Williams */ 8850fe983aSEd Tanous 8950fe983aSEd Tanous using callback_t = void(boost::system::error_code, message_t&); 9050fe983aSEd Tanous using send_function = std::move_only_function<callback_t>; async_send(message_t & m,send_function && callback,uint64_t timeout=0)9150fe983aSEd Tanous inline void async_send(message_t& m, send_function&& callback, 926c97486fSEd Tanous uint64_t timeout = 0) 937f664254SPatrick Williams { 9450fe983aSEd Tanous boost::asio::async_initiate<send_function, callback_t>( 9550fe983aSEd Tanous detail::async_send_handler(get(), m, timeout), callback); 9650fe983aSEd Tanous } 9750fe983aSEd Tanous #ifndef SDBUSPLUS_DISABLE_BOOST_COROUTINES async_send_yield(message_t & m,boost::asio::yield_context && token,uint64_t timeout=0)9850fe983aSEd Tanous inline auto async_send_yield(message_t& m, 9950fe983aSEd Tanous boost::asio::yield_context&& token, 10050fe983aSEd Tanous uint64_t timeout = 0) 10150fe983aSEd Tanous { 10250fe983aSEd Tanous using yield_callback_t = void(boost::system::error_code, message_t); 10350fe983aSEd Tanous return boost::asio::async_initiate<boost::asio::yield_context, 10450fe983aSEd Tanous yield_callback_t>( 1056c97486fSEd Tanous detail::async_send_handler(get(), m, timeout), token); 1067f664254SPatrick Williams } 10750fe983aSEd Tanous #endif 1087f664254SPatrick Williams 109668c56b0SEd Tanous template <typename MessageHandler> unpack(boost::system::error_code ec,message_t & r,MessageHandler && handler)110668c56b0SEd Tanous static void unpack(boost::system::error_code ec, message_t& r, 111668c56b0SEd Tanous MessageHandler&& handler) 112668c56b0SEd Tanous { 113668c56b0SEd Tanous using FunctionTuple = boost::callable_traits::args_t<MessageHandler>; 114668c56b0SEd Tanous using FunctionTupleType = utility::decay_tuple_t<FunctionTuple>; 115668c56b0SEd Tanous constexpr bool returnWithMsg = []() { 116668c56b0SEd Tanous if constexpr ((std::tuple_size_v<FunctionTupleType>) > 1) 117668c56b0SEd Tanous { 118668c56b0SEd Tanous return std::is_same_v< 119668c56b0SEd Tanous std::tuple_element_t<1, FunctionTupleType>, 120668c56b0SEd Tanous sdbusplus::message_t>; 121668c56b0SEd Tanous } 122668c56b0SEd Tanous return false; 123668c56b0SEd Tanous }(); 124668c56b0SEd Tanous using UnpackType = utility::strip_first_n_args_t<returnWithMsg ? 2 : 1, 125668c56b0SEd Tanous FunctionTupleType>; 126668c56b0SEd Tanous UnpackType responseData; 127668c56b0SEd Tanous if (!ec) 128668c56b0SEd Tanous { 129668c56b0SEd Tanous try 130668c56b0SEd Tanous { 131668c56b0SEd Tanous utility::read_into_tuple(responseData, r); 132668c56b0SEd Tanous } 133668c56b0SEd Tanous catch (const std::exception&) 134668c56b0SEd Tanous { 135668c56b0SEd Tanous // Set error code if not already set 136668c56b0SEd Tanous ec = boost::system::errc::make_error_code( 137668c56b0SEd Tanous boost::system::errc::invalid_argument); 138668c56b0SEd Tanous } 139668c56b0SEd Tanous } 140668c56b0SEd Tanous // Note. Callback is called whether or not the unpack was 141668c56b0SEd Tanous // successful to allow the user to implement their own 142668c56b0SEd Tanous // handling 143668c56b0SEd Tanous if constexpr (returnWithMsg) 144668c56b0SEd Tanous { 145668c56b0SEd Tanous auto response = 146668c56b0SEd Tanous std::tuple_cat(std::make_tuple(ec), std::forward_as_tuple(r), 147668c56b0SEd Tanous std::move(responseData)); 148668c56b0SEd Tanous std::apply(handler, response); 149668c56b0SEd Tanous } 150668c56b0SEd Tanous else 151668c56b0SEd Tanous { 152668c56b0SEd Tanous auto response = 153668c56b0SEd Tanous std::tuple_cat(std::make_tuple(ec), std::move(responseData)); 154668c56b0SEd Tanous std::apply(handler, response); 155668c56b0SEd Tanous } 156668c56b0SEd Tanous } 157668c56b0SEd Tanous 1587f664254SPatrick Williams /** @brief Perform an asynchronous method call, with input parameter packing 159da0b3f13SKonrad Sztyber * and return value unpacking. 1607f664254SPatrick Williams * 1617f664254SPatrick Williams * @param[in] handler - A function object that is to be called as a 1627f664254SPatrick Williams * continuation for the async dbus method call. The 1637f664254SPatrick Williams * arguments to parse on the return are deduced from 1647f664254SPatrick Williams * the handler's signature and then passed in along 16510d7aa12SPatrick Williams * with an error code and optional message_t 1667f664254SPatrick Williams * @param[in] service - The service to call. 1677f664254SPatrick Williams * @param[in] objpath - The object's path for the call. 1687f664254SPatrick Williams * @param[in] interf - The object's interface to call. 1697f664254SPatrick Williams * @param[in] method - The object's method to call. 170da0b3f13SKonrad Sztyber * @param[in] timeout - The timeout for the method call in usec (0 results 171da0b3f13SKonrad Sztyber * in using the default value). 172ddc57bdfSEd Tanous * @param[in] a - Optional parameters for the method call. 1737f664254SPatrick Williams * 1747f664254SPatrick Williams */ 1757f664254SPatrick Williams template <typename MessageHandler, typename... InputArgs> async_method_call_timed(MessageHandler && handler,const std::string & service,const std::string & objpath,const std::string & interf,const std::string & method,uint64_t timeout,const InputArgs &...a)17606f265f6SPatrick Williams void async_method_call_timed( 17706f265f6SPatrick Williams MessageHandler&& handler, const std::string& service, 17806f265f6SPatrick Williams const std::string& objpath, const std::string& interf, 17906f265f6SPatrick Williams const std::string& method, uint64_t timeout, const InputArgs&... a) 1807f664254SPatrick Williams { 181668c56b0SEd Tanous using callback_t = std::move_only_function<void( 182668c56b0SEd Tanous boost::system::error_code, message_t&)>; 183668c56b0SEd Tanous callback_t applyHandler = 18406f265f6SPatrick Williams [handler = std::forward<MessageHandler>( 18506f265f6SPatrick Williams handler)](boost::system::error_code ec, message_t& r) mutable { 186668c56b0SEd Tanous unpack(ec, r, std::move(handler)); 1877f664254SPatrick Williams }; 18810d7aa12SPatrick Williams message_t m; 1897f664254SPatrick Williams boost::system::error_code ec; 1907f664254SPatrick Williams try 1917f664254SPatrick Williams { 1927f664254SPatrick Williams m = new_method_call(service.c_str(), objpath.c_str(), 1937f664254SPatrick Williams interf.c_str(), method.c_str()); 1947f664254SPatrick Williams m.append(a...); 1957f664254SPatrick Williams } 1967f664254SPatrick Williams catch (const exception::SdBusError& e) 1977f664254SPatrick Williams { 1987f664254SPatrick Williams ec = boost::system::errc::make_error_code( 1997f664254SPatrick Williams static_cast<boost::system::errc::errc_t>(e.get_errno())); 2007f664254SPatrick Williams applyHandler(ec, m); 2017f664254SPatrick Williams return; 2027f664254SPatrick Williams } 203668c56b0SEd Tanous async_send(m, std::move(applyHandler), timeout); 204da0b3f13SKonrad Sztyber } 205da0b3f13SKonrad Sztyber 206da0b3f13SKonrad Sztyber /** @brief Perform an asynchronous method call, with input parameter packing 207da0b3f13SKonrad Sztyber * and return value unpacking. Uses the default timeout value. 208da0b3f13SKonrad Sztyber * 209da0b3f13SKonrad Sztyber * @param[in] handler - A function object that is to be called as a 210da0b3f13SKonrad Sztyber * continuation for the async dbus method call. The 211da0b3f13SKonrad Sztyber * arguments to parse on the return are deduced from 212da0b3f13SKonrad Sztyber * the handler's signature and then passed in along 21310d7aa12SPatrick Williams * with an error code and optional message_t 214da0b3f13SKonrad Sztyber * @param[in] service - The service to call. 215da0b3f13SKonrad Sztyber * @param[in] objpath - The object's path for the call. 216da0b3f13SKonrad Sztyber * @param[in] interf - The object's interface to call. 217da0b3f13SKonrad Sztyber * @param[in] method - The object's method to call. 218ddc57bdfSEd Tanous * @param[in] a - Optional parameters for the method call. 219da0b3f13SKonrad Sztyber * 220da0b3f13SKonrad Sztyber */ 221da0b3f13SKonrad Sztyber template <typename MessageHandler, typename... InputArgs> async_method_call(MessageHandler && handler,const std::string & service,const std::string & objpath,const std::string & interf,const std::string & method,InputArgs &&...a)222da0b3f13SKonrad Sztyber void async_method_call(MessageHandler&& handler, const std::string& service, 223da0b3f13SKonrad Sztyber const std::string& objpath, 224da0b3f13SKonrad Sztyber const std::string& interf, const std::string& method, 2255a6a9141SEd Tanous InputArgs&&... a) 226da0b3f13SKonrad Sztyber { 227da0b3f13SKonrad Sztyber async_method_call_timed(std::forward<MessageHandler>(handler), service, 2285a6a9141SEd Tanous objpath, interf, method, 0, 2295a6a9141SEd Tanous std::forward<InputArgs>(a)...); 2307f664254SPatrick Williams } 2317f664254SPatrick Williams 2321778b12bSEd Tanous #ifndef SDBUSPLUS_DISABLE_BOOST_COROUTINES 233dfbd9ddfSLei YU template <typename... RetTypes> default_ret_types()234dfbd9ddfSLei YU auto default_ret_types() 235dfbd9ddfSLei YU { 236dfbd9ddfSLei YU if constexpr (sizeof...(RetTypes) == 0) 237dfbd9ddfSLei YU { 238dfbd9ddfSLei YU return; 239dfbd9ddfSLei YU } 240dfbd9ddfSLei YU else if constexpr (sizeof...(RetTypes) == 1 && 241dfbd9ddfSLei YU std::is_void_v<std::tuple_element_t< 242dfbd9ddfSLei YU 0, std::tuple<RetTypes...>>>) 243dfbd9ddfSLei YU { 244dfbd9ddfSLei YU return; 245dfbd9ddfSLei YU } 246dfbd9ddfSLei YU else if constexpr (sizeof...(RetTypes) == 1) 247dfbd9ddfSLei YU { 248dfbd9ddfSLei YU return std::tuple_element_t<0, std::tuple<RetTypes...>>{}; 249dfbd9ddfSLei YU } 250dfbd9ddfSLei YU else 251dfbd9ddfSLei YU { 252dfbd9ddfSLei YU return std::tuple<RetTypes...>{}; 253dfbd9ddfSLei YU } 254dfbd9ddfSLei YU } 2557f664254SPatrick Williams /** @brief Perform a yielding asynchronous method call, with input 2567f664254SPatrick Williams * parameter packing and return value unpacking 2577f664254SPatrick Williams * 2587f664254SPatrick Williams * @param[in] yield - A yield context to async block upon. 2597f664254SPatrick Williams * @param[in] ec - an error code that will be set for any errors 2607f664254SPatrick Williams * @param[in] service - The service to call. 2617f664254SPatrick Williams * @param[in] objpath - The object's path for the call. 2627f664254SPatrick Williams * @param[in] interf - The object's interface to call. 2637f664254SPatrick Williams * @param[in] method - The object's method to call. 264ddc57bdfSEd Tanous * @param[in] a - Optional parameters for the method call. 2657f664254SPatrick Williams * 2667f664254SPatrick Williams * @return Unpacked value of RetType 2677f664254SPatrick Williams */ 2687f664254SPatrick Williams template <typename... RetTypes, typename... InputArgs> yield_method_call(boost::asio::yield_context yield,boost::system::error_code & ec,const std::string & service,const std::string & objpath,const std::string & interf,const std::string & method,const InputArgs &...a)26906f265f6SPatrick Williams auto yield_method_call( 27006f265f6SPatrick Williams boost::asio::yield_context yield, boost::system::error_code& ec, 27106f265f6SPatrick Williams const std::string& service, const std::string& objpath, 2727f664254SPatrick Williams const std::string& interf, const std::string& method, 2737f664254SPatrick Williams const InputArgs&... a) 2747f664254SPatrick Williams { 27510d7aa12SPatrick Williams message_t m; 2767f664254SPatrick Williams try 2777f664254SPatrick Williams { 2787f664254SPatrick Williams m = new_method_call(service.c_str(), objpath.c_str(), 2797f664254SPatrick Williams interf.c_str(), method.c_str()); 2807f664254SPatrick Williams m.append(a...); 2817f664254SPatrick Williams } 2827f664254SPatrick Williams catch (const exception::SdBusError& e) 2837f664254SPatrick Williams { 2847f664254SPatrick Williams ec = boost::system::errc::make_error_code( 2857f664254SPatrick Williams static_cast<boost::system::errc::errc_t>(e.get_errno())); 2867f664254SPatrick Williams } 2877f664254SPatrick Williams if (!ec) 2887f664254SPatrick Williams { 289dfbd9ddfSLei YU message_t r; 29050fe983aSEd Tanous r = async_send_yield(m, yield[ec]); 2917f664254SPatrick Williams try 2927f664254SPatrick Williams { 293dfbd9ddfSLei YU return r.unpack<RetTypes...>(); 2947f664254SPatrick Williams } 2955a6c7902SBrad Bishop catch (const std::exception&) 2967f664254SPatrick Williams { 2977f664254SPatrick Williams ec = boost::system::errc::make_error_code( 2987f664254SPatrick Williams boost::system::errc::invalid_argument); 2997f664254SPatrick Williams } 3007f664254SPatrick Williams } 301dfbd9ddfSLei YU return default_ret_types<RetTypes...>(); 3027f664254SPatrick Williams } 3031778b12bSEd Tanous #endif get_io_context()3047f664254SPatrick Williams boost::asio::io_context& get_io_context() 3057f664254SPatrick Williams { 3067f664254SPatrick Williams return io_; 3077f664254SPatrick Williams } 3087f664254SPatrick Williams 3097f664254SPatrick Williams private: 3107f664254SPatrick Williams boost::asio::io_context& io_; 3117f664254SPatrick Williams boost::asio::posix::stream_descriptor socket; 312cd3bf08aSEd Tanous boost::asio::steady_timer timer; 3137f664254SPatrick Williams process()314cd3bf08aSEd Tanous void process() 3157f664254SPatrick Williams { 316cd3bf08aSEd Tanous if (process_discard()) 317cd3bf08aSEd Tanous { 318cd3bf08aSEd Tanous read_immediate(); 319cd3bf08aSEd Tanous } 320cd3bf08aSEd Tanous else 321cd3bf08aSEd Tanous { 322cd3bf08aSEd Tanous read_wait(); 323cd3bf08aSEd Tanous } 324cd3bf08aSEd Tanous } 325cd3bf08aSEd Tanous on_fd_event(const boost::system::error_code & ec)326cd3bf08aSEd Tanous void on_fd_event(const boost::system::error_code& ec) 327cd3bf08aSEd Tanous { 328cd3bf08aSEd Tanous // This is expected if the timer expired before an fd event was 329cd3bf08aSEd Tanous // available 330cd3bf08aSEd Tanous if (ec == boost::asio::error::operation_aborted) 331cd3bf08aSEd Tanous { 332cd3bf08aSEd Tanous return; 333cd3bf08aSEd Tanous } 334cd3bf08aSEd Tanous timer.cancel(); 3350c76546fSVernon Mauery if (ec) 3360c76546fSVernon Mauery { 3370c76546fSVernon Mauery return; 3380c76546fSVernon Mauery } 339cd3bf08aSEd Tanous process(); 3407f664254SPatrick Williams } 341cd3bf08aSEd Tanous on_timer_event(const boost::system::error_code & ec)342cd3bf08aSEd Tanous void on_timer_event(const boost::system::error_code& ec) 3437f664254SPatrick Williams { 344cd3bf08aSEd Tanous if (ec == boost::asio::error::operation_aborted) 345cd3bf08aSEd Tanous { 346cd3bf08aSEd Tanous // This is expected if the fd was available before the timer expired 347cd3bf08aSEd Tanous return; 3487f664254SPatrick Williams } 349cd3bf08aSEd Tanous if (ec) 350cd3bf08aSEd Tanous { 351cd3bf08aSEd Tanous return; 352cd3bf08aSEd Tanous } 353cd3bf08aSEd Tanous // Abort existing operations on the socket 354cd3bf08aSEd Tanous socket.cancel(); 355cd3bf08aSEd Tanous process(); 356cd3bf08aSEd Tanous } 357cd3bf08aSEd Tanous read_wait()358cd3bf08aSEd Tanous void read_wait() 359cd3bf08aSEd Tanous { 360cd3bf08aSEd Tanous int fd = get_fd(); 361cd3bf08aSEd Tanous if (fd < 0) 362cd3bf08aSEd Tanous { 363cd3bf08aSEd Tanous return; 364cd3bf08aSEd Tanous } 365cd3bf08aSEd Tanous if (fd != socket.native_handle()) 366cd3bf08aSEd Tanous { 367cd3bf08aSEd Tanous socket.release(); 368cd3bf08aSEd Tanous socket.assign(fd); 369cd3bf08aSEd Tanous } 370cd3bf08aSEd Tanous int events = get_events(); 371cd3bf08aSEd Tanous if (events < 0) 372cd3bf08aSEd Tanous { 373cd3bf08aSEd Tanous return; 374cd3bf08aSEd Tanous } 375cd3bf08aSEd Tanous if (events & POLLIN) 376cd3bf08aSEd Tanous { 377cd3bf08aSEd Tanous socket.async_wait(boost::asio::posix::stream_descriptor::wait_read, 378cd3bf08aSEd Tanous std::bind_front(&connection::on_fd_event, this)); 379cd3bf08aSEd Tanous } 380cd3bf08aSEd Tanous if (events & POLLOUT) 381cd3bf08aSEd Tanous { 382cd3bf08aSEd Tanous socket.async_wait(boost::asio::posix::stream_descriptor::wait_write, 383cd3bf08aSEd Tanous std::bind_front(&connection::on_fd_event, this)); 384cd3bf08aSEd Tanous } 385cd3bf08aSEd Tanous if (events & POLLERR) 386cd3bf08aSEd Tanous { 387cd3bf08aSEd Tanous socket.async_wait(boost::asio::posix::stream_descriptor::wait_error, 388cd3bf08aSEd Tanous std::bind_front(&connection::on_fd_event, this)); 389cd3bf08aSEd Tanous } 390cd3bf08aSEd Tanous 391cd3bf08aSEd Tanous uint64_t timeout = 0; 392cd3bf08aSEd Tanous int timeret = get_timeout(&timeout); 393cd3bf08aSEd Tanous if (timeret < 0) 394cd3bf08aSEd Tanous { 395cd3bf08aSEd Tanous return; 396cd3bf08aSEd Tanous } 397cd3bf08aSEd Tanous using clock = std::chrono::steady_clock; 398cd3bf08aSEd Tanous 399cd3bf08aSEd Tanous using SdDuration = std::chrono::duration<uint64_t, std::micro>; 400cd3bf08aSEd Tanous SdDuration sdTimeout(timeout); 401cd3bf08aSEd Tanous // sd-bus always returns a 64 bit timeout regardless of architecture, 402cd3bf08aSEd Tanous // and per the documentation routinely returns UINT64_MAX 403cd3bf08aSEd Tanous if (sdTimeout > clock::duration::max()) 404cd3bf08aSEd Tanous { 405cd3bf08aSEd Tanous // No need to start the timer if the expiration is longer than 406cd3bf08aSEd Tanous // underlying timer can run. 407cd3bf08aSEd Tanous return; 408cd3bf08aSEd Tanous } 409cd3bf08aSEd Tanous auto nativeTimeout = std::chrono::floor<clock::duration>(sdTimeout); 410cd3bf08aSEd Tanous timer.expires_at(clock::time_point(nativeTimeout)); 411cd3bf08aSEd Tanous timer.async_wait(std::bind_front(&connection::on_timer_event, this)); 4127f664254SPatrick Williams } read_immediate()4137f664254SPatrick Williams void read_immediate() 4147f664254SPatrick Williams { 415cd3bf08aSEd Tanous boost::asio::post(io_, std::bind_front(&connection::process, this)); 4167f664254SPatrick Williams } 4177f664254SPatrick Williams }; 4187f664254SPatrick Williams 4197f664254SPatrick Williams } // namespace asio 4207f664254SPatrick Williams 4217f664254SPatrick Williams } // namespace sdbusplus 422