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 7fc79e461SBenjamin Kietzman #include <dbus/message.hpp> 8fc79e461SBenjamin Kietzman #include <dbus/detail/watch_timeout.hpp> 9fc79e461SBenjamin Kietzman #include <dbus/detail/queue.hpp> 10fc79e461SBenjamin Kietzman 11d620effbSBenjamin Kietzman namespace dbus { 12d620effbSBenjamin Kietzman 13cd8b76a3SBenjamin Kietzman namespace bus { 14cd8b76a3SBenjamin Kietzman static const int session = DBUS_BUS_SESSION; 15cd8b76a3SBenjamin Kietzman static const int system = DBUS_BUS_SYSTEM; 16cd8b76a3SBenjamin Kietzman static const int starter = DBUS_BUS_STARTER; 17cd8b76a3SBenjamin Kietzman } // namespace bus 18cd8b76a3SBenjamin Kietzman 19fc79e461SBenjamin Kietzman using std::string; 20fc79e461SBenjamin Kietzman using namespace boost::asio; 21fc79e461SBenjamin Kietzman 22*17826fe7SBenjamin Kietzman class filter; 23*17826fe7SBenjamin Kietzman class match; 24*17826fe7SBenjamin Kietzman 25d620effbSBenjamin Kietzman class connection_service 26d620effbSBenjamin Kietzman : public io_service::service 27d620effbSBenjamin Kietzman { 28d620effbSBenjamin Kietzman public: 29d620effbSBenjamin Kietzman static io_service::id id; 30d620effbSBenjamin Kietzman 31d620effbSBenjamin Kietzman typedef DBusConnection *implementation_type; 32d620effbSBenjamin Kietzman 33d620effbSBenjamin Kietzman explicit connection_service(io_service& io) 34d620effbSBenjamin Kietzman : service(io) 35d620effbSBenjamin Kietzman { 36d620effbSBenjamin Kietzman } 37d620effbSBenjamin Kietzman 38d620effbSBenjamin Kietzman void construct(implementation_type& impl) 39d620effbSBenjamin Kietzman { 40d620effbSBenjamin Kietzman } 41d620effbSBenjamin Kietzman 42d620effbSBenjamin Kietzman void destroy(implementation_type& impl) 43d620effbSBenjamin Kietzman { 44d620effbSBenjamin Kietzman dbus_connection_unref(impl); 45d620effbSBenjamin Kietzman } 46d620effbSBenjamin Kietzman 47d620effbSBenjamin Kietzman void shutdown_service() 48d620effbSBenjamin Kietzman { 49cd8b76a3SBenjamin Kietzman //TODO is there anything that needs shutting down? 50d620effbSBenjamin Kietzman } 51d620effbSBenjamin Kietzman 52d620effbSBenjamin Kietzman void open(implementation_type& impl, 53d620effbSBenjamin Kietzman const string& address, bool shared=true) 54d620effbSBenjamin Kietzman { 55d620effbSBenjamin Kietzman io_service& io = this->get_io_service(); 56d620effbSBenjamin Kietzman 57d620effbSBenjamin Kietzman DBusError error; 58d620effbSBenjamin Kietzman dbus_error_init(&error); 59d620effbSBenjamin Kietzman impl = dbus_connection_open(address.c_str(), &error); 60d620effbSBenjamin Kietzman //TODO actually deal with that error 61d620effbSBenjamin Kietzman 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 71d620effbSBenjamin Kietzman DBusError error; 72d620effbSBenjamin Kietzman dbus_error_init(&error); 73cd8b76a3SBenjamin Kietzman impl = dbus_bus_get((DBusBusType)bus, &error); 74d620effbSBenjamin Kietzman //TODO actually deal with that error 75d620effbSBenjamin Kietzman 76cd8b76a3SBenjamin Kietzman detail::set_watch_timeout_dispatch_functions(impl, io); 77cd8b76a3SBenjamin Kietzman } 78d620effbSBenjamin Kietzman 79cd8b76a3SBenjamin Kietzman message send(implementation_type& impl, 80cd8b76a3SBenjamin Kietzman message& m) 81cd8b76a3SBenjamin Kietzman { 82cd8b76a3SBenjamin Kietzman DBusError error; 83cd8b76a3SBenjamin Kietzman dbus_error_init(&error); 84cd8b76a3SBenjamin Kietzman return message(dbus_connection_send_with_reply_and_block(impl, 85cd8b76a3SBenjamin Kietzman m, -1, &error)); 86cd8b76a3SBenjamin Kietzman //TODO deal with that error 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 { 100d620effbSBenjamin Kietzman DBusError error; 101d620effbSBenjamin Kietzman dbus_error_init(&error); 1020de54404SBenjamin Kietzman return message(dbus_connection_send_with_reply_and_block(impl, 103cd8b76a3SBenjamin Kietzman m, chrono::milliseconds(timeout).count(), &error)); 104d620effbSBenjamin Kietzman //TODO deal with that error 105d620effbSBenjamin Kietzman } 106d620effbSBenjamin Kietzman } 107d620effbSBenjamin Kietzman 108d620effbSBenjamin Kietzman template<typename MessageHandler> 109d620effbSBenjamin Kietzman inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler, 110d620effbSBenjamin Kietzman void(boost::system::error_code, message)) 111d620effbSBenjamin Kietzman async_send(implementation_type& impl, 112d620effbSBenjamin Kietzman message& m, 113d620effbSBenjamin Kietzman BOOST_ASIO_MOVE_ARG(MessageHandler) handler) 114d620effbSBenjamin Kietzman { 115d620effbSBenjamin Kietzman DBusPendingCall *p; 116d620effbSBenjamin Kietzman dbus_connection_send_with_reply(impl, 117d620effbSBenjamin Kietzman m, &p, -1); 118cd8b76a3SBenjamin Kietzman /* 119cd8b76a3SBenjamin Kietzman dbus_pending_call_set_notify(p, 120cd8b76a3SBenjamin Kietzman &pending_call_notify, &get_io_service(), NULL); 121cd8b76a3SBenjamin Kietzman 122cd8b76a3SBenjamin Kietzman //FIXME Race condition: another thread might have 123cd8b76a3SBenjamin Kietzman // processed the pending call's reply before a notify 124cd8b76a3SBenjamin Kietzman // function could be set. If so, the notify function 125cd8b76a3SBenjamin Kietzman // will never trigger, so it must be called manually: 126cd8b76a3SBenjamin Kietzman if(dbus_pending_call_get_completed(p)) 127cd8b76a3SBenjamin Kietzman { 128cd8b76a3SBenjamin Kietzman //TODO: does this work, or might it call the notify 129cd8b76a3SBenjamin Kietzman // function too many times? Might have to use steal_reply 130cd8b76a3SBenjamin Kietzman pending_call_notify(p, &get_io_service()); 131cd8b76a3SBenjamin Kietzman } 132cd8b76a3SBenjamin Kietzman */ 133d620effbSBenjamin Kietzman } 134d620effbSBenjamin Kietzman 135cd8b76a3SBenjamin Kietzman void new_match(implementation_type& impl, 136*17826fe7SBenjamin Kietzman match& m); 137cd8b76a3SBenjamin Kietzman 138cd8b76a3SBenjamin Kietzman void delete_match(implementation_type& impl, 139*17826fe7SBenjamin Kietzman match& m); 140cd8b76a3SBenjamin Kietzman 141*17826fe7SBenjamin Kietzman static DBusHandlerResult filter_callback( 142cd8b76a3SBenjamin Kietzman DBusConnection *c, 143cd8b76a3SBenjamin Kietzman DBusMessage *m, 144*17826fe7SBenjamin Kietzman void *userdata); 145cd8b76a3SBenjamin Kietzman 146cd8b76a3SBenjamin Kietzman void new_filter(implementation_type& impl, 147*17826fe7SBenjamin Kietzman filter& f); 148cd8b76a3SBenjamin Kietzman 149cd8b76a3SBenjamin Kietzman void delete_filter(implementation_type& impl, 150*17826fe7SBenjamin Kietzman filter& f); 151*17826fe7SBenjamin Kietzman 152d620effbSBenjamin Kietzman }; 153d620effbSBenjamin Kietzman 154d620effbSBenjamin Kietzman io_service::id connection_service::id; 155d620effbSBenjamin Kietzman 156cd8b76a3SBenjamin Kietzman 157cd8b76a3SBenjamin Kietzman 158cd8b76a3SBenjamin Kietzman 159d620effbSBenjamin Kietzman } // namespace dbus 160fc79e461SBenjamin Kietzman 161fc79e461SBenjamin Kietzman #endif // DBUS_CONNECTION_SERVICE_HPP 162