1 // Copyright (c) Benjamin Kietzman (github.com/bkietz)
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef DBUS_CONNECTION_SERVICE_HPP
7 #define DBUS_CONNECTION_SERVICE_HPP
8 
9 #include <string>
10 #include <boost/asio.hpp>
11 
12 #include <dbus/error.hpp>
13 #include <dbus/message.hpp>
14 #include <dbus/detail/watch_timeout.hpp>
15 #include <dbus/detail/queue.hpp>
16 #include <dbus/detail/async_send_op.hpp>
17 
18 namespace dbus {
19 
20 namespace bus {
21   static const int session = DBUS_BUS_SESSION;
22   static const int system  = DBUS_BUS_SYSTEM;
23   static const int starter = DBUS_BUS_STARTER;
24 } // namespace bus
25 
26 using std::string;
27 using namespace boost::asio;
28 
29 class filter;
30 class match;
31 
32 class connection_service
33   : public io_service::service
34 {
35 public:
36   static io_service::id id;
37 
38   typedef DBusConnection *implementation_type;
39 
40   explicit connection_service(io_service& io)
41     :  service(io)
42   {
43   }
44 
45   void construct(implementation_type& impl)
46   {
47   }
48 
49   void destroy(implementation_type& impl)
50   {
51     dbus_connection_unref(impl);
52   }
53 
54   void shutdown_service()
55   {
56     //TODO is there anything that needs shutting down?
57   }
58 
59   void open(implementation_type& impl,
60       const string& address, bool shared=true)
61   {
62     io_service& io = this->get_io_service();
63 
64     error e;
65     impl = dbus_connection_open(address.c_str(), e);
66 
67     e.throw_if_set();
68     detail::set_watch_timeout_dispatch_functions(impl, io);
69   }
70 
71   void open(implementation_type& impl,
72       const int bus = (int) DBUS_BUS_SYSTEM,
73       bool shared=true)
74   {
75     io_service& io = this->get_io_service();
76 
77     error e;
78     impl = dbus_bus_get((DBusBusType)bus, e);
79 
80     e.throw_if_set();
81     detail::set_watch_timeout_dispatch_functions(impl, io);
82   }
83 
84   message send(implementation_type& impl,
85       message& m)
86   {
87     error e;
88     message reply(dbus_connection_send_with_reply_and_block(impl,
89         m, -1, e));
90 
91     e.throw_if_set();
92     return reply;
93   }
94 
95   template <typename Duration>
96   message send(implementation_type& impl,
97       message& m,
98       const Duration& timeout)
99   {
100     //TODO generically convert timeout to milliseconds
101     if(timeout == Duration::zero()) {
102       //TODO this can return false if it failed
103       dbus_connection_send(impl, m, &m.serial);
104       return message();
105     } else {
106       error e;
107       message reply(dbus_connection_send_with_reply_and_block(impl,
108           m, chrono::milliseconds(timeout).count(), e));
109 
110       e.throw_if_set();
111       return reply;
112     }
113   }
114 
115   template<typename MessageHandler>
116   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
117       void(boost::system::error_code, message))
118   async_send(implementation_type& impl,
119       message& m,
120       BOOST_ASIO_MOVE_ARG(MessageHandler) handler)
121   {
122     boost::asio::detail::async_result_init<
123       MessageHandler, void(boost::system::error_code, message)> init(
124         BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
125 
126     detail::async_send_op<
127       BOOST_ASIO_HANDLER_TYPE(MessageHandler,
128         void(boost::system::error_code, message))>(
129           this->get_io_service(),
130             BOOST_ASIO_MOVE_CAST(MessageHandler)(init.handler)) (impl, m);
131 
132     return init.result.get();
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