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 <boost/asio.hpp>
10 
11 #include <dbus/error.hpp>
12 #include <dbus/element.hpp>
13 #include <dbus/message.hpp>
14 #include <dbus/detail/async_send_op.hpp>
15 
16 #include <dbus/impl/connection.ipp>
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 namespace boost::asio;
27 
28 class filter;
29 class match;
30 
31 class connection_service
32   : public io_service::service
33 {
34 public:
35   static io_service::id id;
36 
37   typedef impl::connection implementation_type;
38 
39   explicit connection_service(io_service& io)
40     : service(io)
41   {
42   }
43 
44   void construct(implementation_type& impl)
45   {
46   }
47 
48   void destroy(implementation_type& impl)
49   {
50   }
51 
52   void shutdown_service()
53   {
54     //TODO is there anything that needs shutting down?
55   }
56 
57   void open(implementation_type& impl,
58       const string& address,
59       bool shared)
60   {
61     io_service& io = this->get_io_service();
62 
63     impl = implementation_type(io, address, shared);
64   }
65 
66   void open(implementation_type& impl,
67       const int bus = bus::system,
68       bool shared = true)
69   {
70     io_service& io = this->get_io_service();
71 
72     impl = implementation_type(io, bus, shared);
73   }
74 
75   message send(implementation_type& impl,
76       message& m)
77   {
78     error e;
79     message reply(dbus_connection_send_with_reply_and_block(impl,
80         m, -1, e));
81 
82     e.throw_if_set();
83     return reply;
84   }
85 
86   template <typename Duration>
87   message send(implementation_type& impl,
88       message& m,
89       const Duration& timeout)
90   {
91     //TODO generically convert timeout to milliseconds
92     if(timeout == Duration::zero()) {
93       //TODO this can return false if it failed
94       dbus_connection_send(impl, m, NULL);
95       return message();
96     } else {
97       error e;
98       message reply(dbus_connection_send_with_reply_and_block(impl,
99           m, chrono::milliseconds(timeout).count(), e));
100 
101       e.throw_if_set();
102       return reply;
103     }
104   }
105 
106   template<typename MessageHandler>
107   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
108       void(boost::system::error_code, message))
109   async_send(implementation_type& impl,
110       message& m,
111       BOOST_ASIO_MOVE_ARG(MessageHandler) handler)
112   {
113     boost::asio::detail::async_result_init<
114       MessageHandler, void(boost::system::error_code, message)> init(
115         BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
116 
117     detail::async_send_op<
118       BOOST_ASIO_HANDLER_TYPE(MessageHandler,
119         void(boost::system::error_code, message))>(
120           this->get_io_service(),
121             BOOST_ASIO_MOVE_CAST(MessageHandler)(init.handler)) (impl, m);
122 
123     return init.result.get();
124   }
125 
126   void new_match(implementation_type& impl,
127       match& m);
128 
129   void delete_match(implementation_type& impl,
130       match& m);
131 
132   void new_filter(implementation_type& impl,
133       filter& f);
134 
135   void delete_filter(implementation_type& impl,
136       filter& f);
137 
138 };
139 
140 io_service::id connection_service::id;
141 
142 
143 
144 
145 } // namespace dbus
146 
147 #endif // DBUS_CONNECTION_SERVICE_HPP
148