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_HPP
7 #define DBUS_CONNECTION_HPP
8 
9 #include <dbus/connection_service.hpp>
10 #include <dbus/element.hpp>
11 #include <dbus/message.hpp>
12 #include <chrono>
13 #include <string>
14 #include <boost/asio.hpp>
15 
16 namespace dbus {
17 
18 class filter;
19 class match;
20 
21 /// Root D-Bus IO object
22 /**
23  * A connection to a bus, through which messages may be sent or received.
24  */
25 class connection : public boost::asio::basic_io_object<connection_service> {
26  public:
27   /// Open a connection to a specified address.
28   /**
29  * @param io_service The io_service object that the connection will use to
30  * wire D-Bus for asynchronous operation.
31  *
32  * @param address The address of the bus to connect to.
33  *
34  * @throws boost::system::system_error When opening the connection failed.
35  */
36   connection(boost::asio::io_service& io, const string& address)
37       : basic_io_object<connection_service>(io) {
38     this->get_service().open(this->get_implementation(), address);
39   }
40 
41   /// Open a connection to a well-known bus.
42   /**
43  * D-Bus connections are usually opened to well-known buses like the
44  * system or session bus.
45  *
46  * @param bus The well-known bus to connect to.
47  *
48  * @throws boost::system::system_error When opening the connection failed.
49  */
50   // TODO: change this unsigned to an enumeration
51   connection(boost::asio::io_service& io, const int bus)
52       : basic_io_object<connection_service>(io) {
53     this->get_service().open(this->get_implementation(), bus);
54   }
55 
56 
57   /// Request a name on the bus.
58   /**
59  * @param name The name requested on the bus
60  *
61  * @return
62  *
63  * @throws boost::system::system_error When the response timed out or
64  * there was some other error.
65  */
66   void request_name(const string& name) {
67       this->get_implementation().request_name(name);
68   }
69 
70   /// Reply to a message.
71   /**
72  * @param m The message from which to create the reply
73  *
74  * @return The new reply message
75  *
76  * @throws boost::system::system_error When the response timed out or
77  * there was some other error.
78  */
79   message reply(message& m) {
80     return this->get_implementation().new_method_return(m);
81   }
82 
83   /// Send a message.
84   /**
85  * @param m The message to send.
86  *
87  * @return The reply received.
88  *
89  * @throws boost::system::system_error When the response timed out or
90  * there was some other error.
91  */
92   message send(message& m) {
93     return this->get_service().send(this->get_implementation(), m);
94   }
95 
96   /// Send a message.
97   /**
98  * @param m The message to send.
99  *
100  * @param t Time to wait for a reply. Passing 0 as the timeout means
101  * that you wish to ignore the reply. (Or catch it later somehow...)
102  *
103  * @return The reply received.
104  *
105  * @throws boost::system::system_error When the response timed out (if
106  * timeout was not 0), or there was some other error.
107  */
108   template <typename Duration>
109   message send(message& m, const Duration& t) {
110     return this->get_service().send(this->get_implementation(), m, t);
111   }
112 
113   /// Send a message asynchronously.
114   /**
115  * @param m The message to send.
116  *
117  * @param handler Handler for the reply.
118  *
119  * @return Asynchronous result
120  */
121   template <typename MessageHandler>
122   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
123                                        void(boost::system::error_code, message))
124       async_send(message& m, BOOST_ASIO_MOVE_ARG(MessageHandler) handler) {
125     return this->get_service().async_send(
126         this->get_implementation(), m,
127         BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
128   }
129 
130   /// Create a new match.
131   void new_match(match& m) {
132     this->get_service().new_match(this->get_implementation(), m);
133   }
134 
135   /// Destroy a match.
136   void delete_match(match& m) {
137     this->get_service().delete_match(this->get_implementation(), m);
138   }
139 
140   /// Create a new filter.
141   void new_filter(filter& f) {
142     this->get_service().new_filter(this->get_implementation(), f);
143   }
144 
145   /// Destroy a filter.
146   void delete_filter(filter& f) {
147     this->get_service().delete_filter(this->get_implementation(), f);
148   }
149 
150   // FIXME the only way around this I see is to expose start() here, which seems
151   // ugly
152   friend class filter;
153 };
154 
155 }  // namespace dbus
156 
157 #endif  // DBUS_CONNECTION_HPP
158