1fc79e461SBenjamin Kietzman #ifndef DBUS_CONNECTION_SERVICE_HPP 2fc79e461SBenjamin Kietzman #define DBUS_CONNECTION_SERVICE_HPP 3fc79e461SBenjamin Kietzman 4fc79e461SBenjamin Kietzman #include <string> 5d620effbSBenjamin Kietzman #include <boost/asio.hpp> 6d620effbSBenjamin Kietzman 7*85860989SBenjamin Kietzman #include <dbus/error.hpp> 8fc79e461SBenjamin Kietzman #include <dbus/message.hpp> 9fc79e461SBenjamin Kietzman #include <dbus/detail/watch_timeout.hpp> 10fc79e461SBenjamin Kietzman #include <dbus/detail/queue.hpp> 11fc79e461SBenjamin Kietzman 12d620effbSBenjamin Kietzman namespace dbus { 13d620effbSBenjamin Kietzman 14cd8b76a3SBenjamin Kietzman namespace bus { 15cd8b76a3SBenjamin Kietzman static const int session = DBUS_BUS_SESSION; 16cd8b76a3SBenjamin Kietzman static const int system = DBUS_BUS_SYSTEM; 17cd8b76a3SBenjamin Kietzman static const int starter = DBUS_BUS_STARTER; 18cd8b76a3SBenjamin Kietzman } // namespace bus 19cd8b76a3SBenjamin Kietzman 20fc79e461SBenjamin Kietzman using std::string; 21fc79e461SBenjamin Kietzman using namespace boost::asio; 22fc79e461SBenjamin Kietzman 2317826fe7SBenjamin Kietzman class filter; 2417826fe7SBenjamin Kietzman class match; 2517826fe7SBenjamin Kietzman 26d620effbSBenjamin Kietzman class connection_service 27d620effbSBenjamin Kietzman : public io_service::service 28d620effbSBenjamin Kietzman { 29d620effbSBenjamin Kietzman public: 30d620effbSBenjamin Kietzman static io_service::id id; 31d620effbSBenjamin Kietzman 32d620effbSBenjamin Kietzman typedef DBusConnection *implementation_type; 33d620effbSBenjamin Kietzman 34d620effbSBenjamin Kietzman explicit connection_service(io_service& io) 35d620effbSBenjamin Kietzman : service(io) 36d620effbSBenjamin Kietzman { 37d620effbSBenjamin Kietzman } 38d620effbSBenjamin Kietzman 39d620effbSBenjamin Kietzman void construct(implementation_type& impl) 40d620effbSBenjamin Kietzman { 41d620effbSBenjamin Kietzman } 42d620effbSBenjamin Kietzman 43d620effbSBenjamin Kietzman void destroy(implementation_type& impl) 44d620effbSBenjamin Kietzman { 45d620effbSBenjamin Kietzman dbus_connection_unref(impl); 46d620effbSBenjamin Kietzman } 47d620effbSBenjamin Kietzman 48d620effbSBenjamin Kietzman void shutdown_service() 49d620effbSBenjamin Kietzman { 50cd8b76a3SBenjamin Kietzman //TODO is there anything that needs shutting down? 51d620effbSBenjamin Kietzman } 52d620effbSBenjamin Kietzman 53d620effbSBenjamin Kietzman void open(implementation_type& impl, 54d620effbSBenjamin Kietzman const string& address, bool shared=true) 55d620effbSBenjamin Kietzman { 56d620effbSBenjamin Kietzman io_service& io = this->get_io_service(); 57d620effbSBenjamin Kietzman 58*85860989SBenjamin Kietzman error e; 59*85860989SBenjamin Kietzman impl = dbus_connection_open(address.c_str(), e); 60d620effbSBenjamin Kietzman 61*85860989SBenjamin Kietzman e.throw_if_set(); 62cd8b76a3SBenjamin Kietzman detail::set_watch_timeout_dispatch_functions(impl, io); 63d620effbSBenjamin Kietzman } 64d620effbSBenjamin Kietzman 65d620effbSBenjamin Kietzman void open(implementation_type& impl, 66cd8b76a3SBenjamin Kietzman const int bus = (int) DBUS_BUS_SYSTEM, 67d620effbSBenjamin Kietzman bool shared=true) 68d620effbSBenjamin Kietzman { 69d620effbSBenjamin Kietzman io_service& io = this->get_io_service(); 70d620effbSBenjamin Kietzman 71*85860989SBenjamin Kietzman error e; 72*85860989SBenjamin Kietzman impl = dbus_bus_get((DBusBusType)bus, e); 73d620effbSBenjamin Kietzman 74*85860989SBenjamin Kietzman e.throw_if_set(); 75cd8b76a3SBenjamin Kietzman detail::set_watch_timeout_dispatch_functions(impl, io); 76cd8b76a3SBenjamin Kietzman } 77d620effbSBenjamin Kietzman 78cd8b76a3SBenjamin Kietzman message send(implementation_type& impl, 79cd8b76a3SBenjamin Kietzman message& m) 80cd8b76a3SBenjamin Kietzman { 81*85860989SBenjamin Kietzman error e; 82*85860989SBenjamin Kietzman message reply(dbus_connection_send_with_reply_and_block(impl, 83*85860989SBenjamin Kietzman m, -1, e)); 84*85860989SBenjamin Kietzman 85*85860989SBenjamin Kietzman e.throw_if_set(); 86*85860989SBenjamin Kietzman return reply; 87d620effbSBenjamin Kietzman } 88d620effbSBenjamin Kietzman 89d620effbSBenjamin Kietzman template <typename Duration> 90d620effbSBenjamin Kietzman message send(implementation_type& impl, 91d620effbSBenjamin Kietzman message& m, 92d620effbSBenjamin Kietzman const Duration& timeout) 93d620effbSBenjamin Kietzman { 94d620effbSBenjamin Kietzman //TODO generically convert timeout to milliseconds 95cd8b76a3SBenjamin Kietzman if(timeout == Duration::zero()) { 96d620effbSBenjamin Kietzman //TODO this can return false if it failed 97d620effbSBenjamin Kietzman dbus_connection_send(impl, m, &m.serial); 98d620effbSBenjamin Kietzman return message(); 99d620effbSBenjamin Kietzman } else { 100*85860989SBenjamin Kietzman error e; 101*85860989SBenjamin Kietzman message reply(dbus_connection_send_with_reply_and_block(impl, 102*85860989SBenjamin Kietzman m, chrono::milliseconds(timeout).count(), e)); 103*85860989SBenjamin Kietzman 104*85860989SBenjamin Kietzman e.throw_if_set(); 105*85860989SBenjamin Kietzman return reply; 106d620effbSBenjamin Kietzman } 107d620effbSBenjamin Kietzman } 108d620effbSBenjamin Kietzman 109d620effbSBenjamin Kietzman template<typename MessageHandler> 110d620effbSBenjamin Kietzman inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler, 111d620effbSBenjamin Kietzman void(boost::system::error_code, message)) 112d620effbSBenjamin Kietzman async_send(implementation_type& impl, 113d620effbSBenjamin Kietzman message& m, 114d620effbSBenjamin Kietzman BOOST_ASIO_MOVE_ARG(MessageHandler) handler) 115d620effbSBenjamin Kietzman { 116d620effbSBenjamin Kietzman DBusPendingCall *p; 117d620effbSBenjamin Kietzman dbus_connection_send_with_reply(impl, 118d620effbSBenjamin Kietzman m, &p, -1); 119cd8b76a3SBenjamin Kietzman /* 120cd8b76a3SBenjamin Kietzman dbus_pending_call_set_notify(p, 121cd8b76a3SBenjamin Kietzman &pending_call_notify, &get_io_service(), NULL); 122cd8b76a3SBenjamin Kietzman 123cd8b76a3SBenjamin Kietzman //FIXME Race condition: another thread might have 124cd8b76a3SBenjamin Kietzman // processed the pending call's reply before a notify 125cd8b76a3SBenjamin Kietzman // function could be set. If so, the notify function 126cd8b76a3SBenjamin Kietzman // will never trigger, so it must be called manually: 127cd8b76a3SBenjamin Kietzman if(dbus_pending_call_get_completed(p)) 128cd8b76a3SBenjamin Kietzman { 129cd8b76a3SBenjamin Kietzman //TODO: does this work, or might it call the notify 130cd8b76a3SBenjamin Kietzman // function too many times? Might have to use steal_reply 131cd8b76a3SBenjamin Kietzman pending_call_notify(p, &get_io_service()); 132cd8b76a3SBenjamin Kietzman } 133cd8b76a3SBenjamin Kietzman */ 134d620effbSBenjamin Kietzman } 135d620effbSBenjamin Kietzman 136cd8b76a3SBenjamin Kietzman void new_match(implementation_type& impl, 13717826fe7SBenjamin Kietzman match& m); 138cd8b76a3SBenjamin Kietzman 139cd8b76a3SBenjamin Kietzman void delete_match(implementation_type& impl, 14017826fe7SBenjamin Kietzman match& m); 141cd8b76a3SBenjamin Kietzman 14217826fe7SBenjamin Kietzman static DBusHandlerResult filter_callback( 143cd8b76a3SBenjamin Kietzman DBusConnection *c, 144cd8b76a3SBenjamin Kietzman DBusMessage *m, 14517826fe7SBenjamin Kietzman void *userdata); 146cd8b76a3SBenjamin Kietzman 147cd8b76a3SBenjamin Kietzman void new_filter(implementation_type& impl, 14817826fe7SBenjamin Kietzman filter& f); 149cd8b76a3SBenjamin Kietzman 150cd8b76a3SBenjamin Kietzman void delete_filter(implementation_type& impl, 15117826fe7SBenjamin Kietzman filter& f); 15217826fe7SBenjamin Kietzman 153d620effbSBenjamin Kietzman }; 154d620effbSBenjamin Kietzman 155d620effbSBenjamin Kietzman io_service::id connection_service::id; 156d620effbSBenjamin Kietzman 157cd8b76a3SBenjamin Kietzman 158cd8b76a3SBenjamin Kietzman 159cd8b76a3SBenjamin Kietzman 160d620effbSBenjamin Kietzman } // namespace dbus 161fc79e461SBenjamin Kietzman 162fc79e461SBenjamin Kietzman #endif // DBUS_CONNECTION_SERVICE_HPP 163