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