xref: /openbmc/boost-dbus/include/dbus/connection_service.hpp (revision cd8b76a30dfdc21e93912f0421b599f635d6f08b)
1fc79e461SBenjamin Kietzman #ifndef DBUS_CONNECTION_SERVICE_HPP
2fc79e461SBenjamin Kietzman #define DBUS_CONNECTION_SERVICE_HPP
3fc79e461SBenjamin Kietzman 
4fc79e461SBenjamin Kietzman #include <string>
5d620effbSBenjamin Kietzman #include <boost/asio.hpp>
6d620effbSBenjamin Kietzman 
7fc79e461SBenjamin Kietzman #include <dbus/message.hpp>
8fc79e461SBenjamin Kietzman #include <dbus/detail/watch_timeout.hpp>
9fc79e461SBenjamin Kietzman #include <dbus/detail/queue.hpp>
10*cd8b76a3SBenjamin Kietzman #include <dbus/match.hpp>
11fc79e461SBenjamin Kietzman 
12d620effbSBenjamin Kietzman namespace dbus {
13d620effbSBenjamin Kietzman 
14*cd8b76a3SBenjamin Kietzman namespace bus {
15*cd8b76a3SBenjamin Kietzman   static const int session = DBUS_BUS_SESSION;
16*cd8b76a3SBenjamin Kietzman   static const int system  = DBUS_BUS_SYSTEM;
17*cd8b76a3SBenjamin Kietzman   static const int starter = DBUS_BUS_STARTER;
18*cd8b76a3SBenjamin Kietzman } // namespace bus
19*cd8b76a3SBenjamin Kietzman 
20fc79e461SBenjamin Kietzman using std::string;
21fc79e461SBenjamin Kietzman using namespace boost::asio;
22fc79e461SBenjamin Kietzman 
23d620effbSBenjamin Kietzman class connection_service
24d620effbSBenjamin Kietzman   : public io_service::service
25d620effbSBenjamin Kietzman {
26d620effbSBenjamin Kietzman public:
27d620effbSBenjamin Kietzman   static io_service::id id;
28d620effbSBenjamin Kietzman 
29d620effbSBenjamin Kietzman   typedef DBusConnection *implementation_type;
30d620effbSBenjamin Kietzman 
31d620effbSBenjamin Kietzman   explicit connection_service(io_service& io)
32d620effbSBenjamin Kietzman     :  service(io)
33d620effbSBenjamin Kietzman   {
34d620effbSBenjamin Kietzman   }
35d620effbSBenjamin Kietzman 
36d620effbSBenjamin Kietzman   void construct(implementation_type& impl)
37d620effbSBenjamin Kietzman   {
38d620effbSBenjamin Kietzman   }
39d620effbSBenjamin Kietzman 
40d620effbSBenjamin Kietzman   void destroy(implementation_type& impl)
41d620effbSBenjamin Kietzman   {
42d620effbSBenjamin Kietzman     dbus_connection_unref(impl);
43d620effbSBenjamin Kietzman   }
44d620effbSBenjamin Kietzman 
45d620effbSBenjamin Kietzman   void shutdown_service()
46d620effbSBenjamin Kietzman   {
47*cd8b76a3SBenjamin Kietzman     //TODO is there anything that needs shutting down?
48d620effbSBenjamin Kietzman   }
49d620effbSBenjamin Kietzman 
50d620effbSBenjamin Kietzman   void open(implementation_type& impl,
51d620effbSBenjamin Kietzman       const string& address, bool shared=true)
52d620effbSBenjamin Kietzman   {
53d620effbSBenjamin Kietzman     io_service& io = this->get_io_service();
54d620effbSBenjamin Kietzman 
55d620effbSBenjamin Kietzman     DBusError error;
56d620effbSBenjamin Kietzman     dbus_error_init(&error);
57d620effbSBenjamin Kietzman     impl = dbus_connection_open(address.c_str(), &error);
58d620effbSBenjamin Kietzman     //TODO actually deal with that error
59d620effbSBenjamin Kietzman 
60*cd8b76a3SBenjamin Kietzman     detail::set_watch_timeout_dispatch_functions(impl, io);
61d620effbSBenjamin Kietzman   }
62d620effbSBenjamin Kietzman 
63d620effbSBenjamin Kietzman   void open(implementation_type& impl,
64*cd8b76a3SBenjamin Kietzman       const int bus = (int) DBUS_BUS_SYSTEM,
65d620effbSBenjamin Kietzman       bool shared=true)
66d620effbSBenjamin Kietzman   {
67d620effbSBenjamin Kietzman     io_service& io = this->get_io_service();
68d620effbSBenjamin Kietzman 
69d620effbSBenjamin Kietzman     DBusError error;
70d620effbSBenjamin Kietzman     dbus_error_init(&error);
71*cd8b76a3SBenjamin Kietzman     impl = dbus_bus_get((DBusBusType)bus, &error);
72d620effbSBenjamin Kietzman     //TODO actually deal with that error
73d620effbSBenjamin Kietzman 
74*cd8b76a3SBenjamin Kietzman     detail::set_watch_timeout_dispatch_functions(impl, io);
75*cd8b76a3SBenjamin Kietzman   }
76d620effbSBenjamin Kietzman 
77*cd8b76a3SBenjamin Kietzman   message send(implementation_type& impl,
78*cd8b76a3SBenjamin Kietzman       message& m)
79*cd8b76a3SBenjamin Kietzman   {
80*cd8b76a3SBenjamin Kietzman     DBusError error;
81*cd8b76a3SBenjamin Kietzman     dbus_error_init(&error);
82*cd8b76a3SBenjamin Kietzman     return message(dbus_connection_send_with_reply_and_block(impl,
83*cd8b76a3SBenjamin Kietzman         m, -1, &error));
84*cd8b76a3SBenjamin Kietzman         //TODO deal with that error
85d620effbSBenjamin Kietzman   }
86d620effbSBenjamin Kietzman 
87d620effbSBenjamin Kietzman   template <typename Duration>
88d620effbSBenjamin Kietzman   message send(implementation_type& impl,
89d620effbSBenjamin Kietzman       message& m,
90d620effbSBenjamin Kietzman       const Duration& timeout)
91d620effbSBenjamin Kietzman   {
92d620effbSBenjamin Kietzman     //TODO generically convert timeout to milliseconds
93*cd8b76a3SBenjamin Kietzman     if(timeout == Duration::zero()) {
94d620effbSBenjamin Kietzman       //TODO this can return false if it failed
95d620effbSBenjamin Kietzman       dbus_connection_send(impl, m, &m.serial);
96d620effbSBenjamin Kietzman       return message();
97d620effbSBenjamin Kietzman     } else {
98d620effbSBenjamin Kietzman       DBusError error;
99d620effbSBenjamin Kietzman       dbus_error_init(&error);
1000de54404SBenjamin Kietzman       return message(dbus_connection_send_with_reply_and_block(impl,
101*cd8b76a3SBenjamin Kietzman           m, chrono::milliseconds(timeout).count(), &error));
102d620effbSBenjamin Kietzman           //TODO deal with that error
103d620effbSBenjamin Kietzman     }
104d620effbSBenjamin Kietzman   }
105d620effbSBenjamin Kietzman 
106d620effbSBenjamin Kietzman   template<typename MessageHandler>
107d620effbSBenjamin Kietzman   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
108d620effbSBenjamin Kietzman       void(boost::system::error_code, message))
109d620effbSBenjamin Kietzman   async_send(implementation_type& impl,
110d620effbSBenjamin Kietzman       message& m,
111d620effbSBenjamin Kietzman       BOOST_ASIO_MOVE_ARG(MessageHandler) handler)
112d620effbSBenjamin Kietzman   {
113d620effbSBenjamin Kietzman     DBusPendingCall *p;
114d620effbSBenjamin Kietzman     dbus_connection_send_with_reply(impl,
115d620effbSBenjamin Kietzman         m, &p, -1);
116*cd8b76a3SBenjamin Kietzman     /*
117*cd8b76a3SBenjamin Kietzman     dbus_pending_call_set_notify(p,
118*cd8b76a3SBenjamin Kietzman         &pending_call_notify, &get_io_service(), NULL);
119*cd8b76a3SBenjamin Kietzman 
120*cd8b76a3SBenjamin Kietzman     //FIXME Race condition: another thread might have
121*cd8b76a3SBenjamin Kietzman     // processed the pending call's reply before a notify
122*cd8b76a3SBenjamin Kietzman     // function could be set. If so, the notify function
123*cd8b76a3SBenjamin Kietzman     // will never trigger, so it must be called manually:
124*cd8b76a3SBenjamin Kietzman     if(dbus_pending_call_get_completed(p))
125*cd8b76a3SBenjamin Kietzman     {
126*cd8b76a3SBenjamin Kietzman       //TODO: does this work, or might it call the notify
127*cd8b76a3SBenjamin Kietzman       // function too many times? Might have to use steal_reply
128*cd8b76a3SBenjamin Kietzman       pending_call_notify(p, &get_io_service());
129*cd8b76a3SBenjamin Kietzman     }
130*cd8b76a3SBenjamin Kietzman     */
131d620effbSBenjamin Kietzman   }
132d620effbSBenjamin Kietzman 
133*cd8b76a3SBenjamin Kietzman   void new_match(implementation_type& impl,
134*cd8b76a3SBenjamin Kietzman       match& m)
135*cd8b76a3SBenjamin Kietzman   {
136*cd8b76a3SBenjamin Kietzman     DBusError err;
137*cd8b76a3SBenjamin Kietzman     dbus_error_init(&err);
138*cd8b76a3SBenjamin Kietzman     dbus_bus_add_match(impl, m.get_expression().c_str(), &err);
139*cd8b76a3SBenjamin Kietzman     //TODO deal with that error
140*cd8b76a3SBenjamin Kietzman     // eventually, for complete asynchronicity, this should connect to
141*cd8b76a3SBenjamin Kietzman     // org.freedesktop.DBus and call org.freedesktop.DBus.AddMatch
142*cd8b76a3SBenjamin Kietzman   }
143*cd8b76a3SBenjamin Kietzman 
144*cd8b76a3SBenjamin Kietzman   void delete_match(implementation_type& impl,
145*cd8b76a3SBenjamin Kietzman       match& m)
146*cd8b76a3SBenjamin Kietzman   {
147*cd8b76a3SBenjamin Kietzman     DBusError err;
148*cd8b76a3SBenjamin Kietzman     dbus_error_init(&err);
149*cd8b76a3SBenjamin Kietzman     dbus_bus_remove_match(impl, m.get_expression().c_str(), &err);
150*cd8b76a3SBenjamin Kietzman   }
151*cd8b76a3SBenjamin Kietzman 
152*cd8b76a3SBenjamin Kietzman   static DBusHandlerResult filter_wrap(
153*cd8b76a3SBenjamin Kietzman       DBusConnection *c,
154*cd8b76a3SBenjamin Kietzman       DBusMessage *m,
155*cd8b76a3SBenjamin Kietzman       void *userdata)
156*cd8b76a3SBenjamin Kietzman   {
157*cd8b76a3SBenjamin Kietzman     try
158*cd8b76a3SBenjamin Kietzman     {
159*cd8b76a3SBenjamin Kietzman       filter& f = *static_cast<filter *>(userdata);
160*cd8b76a3SBenjamin Kietzman       if(f.offer(message(m)))
161*cd8b76a3SBenjamin Kietzman       {
162*cd8b76a3SBenjamin Kietzman         return DBUS_HANDLER_RESULT_HANDLED;
163*cd8b76a3SBenjamin Kietzman       }
164*cd8b76a3SBenjamin Kietzman     } catch(...) {
165*cd8b76a3SBenjamin Kietzman       // do not throw in C callbacks. Just don't.
166*cd8b76a3SBenjamin Kietzman     }
167*cd8b76a3SBenjamin Kietzman 
168*cd8b76a3SBenjamin Kietzman     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
169*cd8b76a3SBenjamin Kietzman   }
170*cd8b76a3SBenjamin Kietzman 
171*cd8b76a3SBenjamin Kietzman   void new_filter(implementation_type& impl,
172*cd8b76a3SBenjamin Kietzman       filter& f)
173*cd8b76a3SBenjamin Kietzman   {
174*cd8b76a3SBenjamin Kietzman     dbus_connection_add_filter(impl,
175*cd8b76a3SBenjamin Kietzman         &filter_wrap, &f, NULL);
176*cd8b76a3SBenjamin Kietzman   }
177*cd8b76a3SBenjamin Kietzman 
178*cd8b76a3SBenjamin Kietzman   void delete_filter(implementation_type& impl,
179*cd8b76a3SBenjamin Kietzman       filter& f)
180*cd8b76a3SBenjamin Kietzman   {
181*cd8b76a3SBenjamin Kietzman     dbus_connection_remove_filter(impl,
182*cd8b76a3SBenjamin Kietzman         &filter_wrap, &f);
183*cd8b76a3SBenjamin Kietzman   }
184d620effbSBenjamin Kietzman };
185d620effbSBenjamin Kietzman 
186d620effbSBenjamin Kietzman io_service::id connection_service::id;
187d620effbSBenjamin Kietzman 
188*cd8b76a3SBenjamin Kietzman 
189*cd8b76a3SBenjamin Kietzman 
190*cd8b76a3SBenjamin Kietzman 
191d620effbSBenjamin Kietzman } // namespace dbus
192fc79e461SBenjamin Kietzman 
193fc79e461SBenjamin Kietzman #endif // DBUS_CONNECTION_SERVICE_HPP
194