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   {
60     io_service& io = this->get_io_service();
61 
62     impl.open(io, address);
63   }
64 
65   void open(implementation_type& impl,
66       const int bus = bus::system)
67   {
68     io_service& io = this->get_io_service();
69 
70     impl.open(io, bus);
71   }
72 
73   message send(implementation_type& impl,
74       message& m)
75   {
76     error e;
77     message reply(dbus_connection_send_with_reply_and_block(impl,
78         m, -1, e));
79 
80     e.throw_if_set();
81     return reply;
82   }
83 
84   template <typename Duration>
85   message send(implementation_type& impl,
86       message& m,
87       const Duration& timeout)
88   {
89     //TODO generically convert timeout to milliseconds
90     if(timeout == Duration::zero()) {
91       //TODO this can return false if it failed
92       dbus_connection_send(impl, m, NULL);
93       return message();
94     } else {
95       error e;
96       message reply(dbus_connection_send_with_reply_and_block(impl,
97           m, chrono::milliseconds(timeout).count(), e));
98 
99       e.throw_if_set();
100       return reply;
101     }
102   }
103 
104   template<typename MessageHandler>
105   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
106       void(boost::system::error_code, message))
107   async_send(implementation_type& impl,
108       message& m,
109       BOOST_ASIO_MOVE_ARG(MessageHandler) handler)
110   {
111     // begin asynchronous operation
112     impl.start(this->get_io_service());
113 
114     boost::asio::detail::async_result_init<
115       MessageHandler, void(boost::system::error_code, message)> init(
116         BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
117 
118     detail::async_send_op<
119       BOOST_ASIO_HANDLER_TYPE(MessageHandler,
120         void(boost::system::error_code, message))>(
121           this->get_io_service(),
122             BOOST_ASIO_MOVE_CAST(MessageHandler)(init.handler)) (impl, m);
123 
124     return init.result.get();
125   }
126 
127   void new_match(implementation_type& impl,
128       match& m);
129 
130   void delete_match(implementation_type& impl,
131       match& m);
132 
133   void new_filter(implementation_type& impl,
134       filter& f);
135 
136   void delete_filter(implementation_type& impl,
137       filter& f);
138 
139 };
140 
141 io_service::id connection_service::id;
142 
143 
144 
145 
146 } // namespace dbus
147 
148 #endif // DBUS_CONNECTION_SERVICE_HPP
149