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