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