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 
71   std::string get_unique_name(){
72       return this->get_implementation().get_unique_name();
73   }
74 
75   /// Reply to a message.
76   /**
77  * @param m The message from which to create the reply
78  *
79  * @return The new reply message
80  *
81  * @throws boost::system::system_error When the response timed out or
82  * there was some other error.
83  */
84   message reply(message& m) {
85     return this->get_implementation().new_method_return(m);
86   }
87 
88   /// Send a message.
89   /**
90  * @param m The message to send.
91  *
92  * @return The reply received.
93  *
94  * @throws boost::system::system_error When the response timed out or
95  * there was some other error.
96  */
97   message send(message& m) {
98     return this->get_service().send(this->get_implementation(), m);
99   }
100 
101   /// Send a message.
102   /**
103  * @param m The message to send.
104  *
105  * @param t Time to wait for a reply. Passing 0 as the timeout means
106  * that you wish to ignore the reply. (Or catch it later somehow...)
107  *
108  * @return The reply received.
109  *
110  * @throws boost::system::system_error When the response timed out (if
111  * timeout was not 0), or there was some other error.
112  */
113   template <typename Duration>
114   message send(message& m, const Duration& t = std::chrono::seconds(0)) {
115     return this->get_service().send(this->get_implementation(), m, t);
116   }
117 
118   /// Send a message asynchronously.
119   /**
120  * @param m The message to send.
121  *
122  * @param handler Handler for the reply.
123  *
124  * @return Asynchronous result
125  */
126   template <typename MessageHandler>
127   inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
128                                        void(boost::system::error_code, message))
129       async_send(message& m, BOOST_ASIO_MOVE_ARG(MessageHandler) handler) {
130     return this->get_service().async_send(
131         this->get_implementation(), m,
132         BOOST_ASIO_MOVE_CAST(MessageHandler)(handler));
133   }
134 
135   /// Create a new match.
136   void new_match(match& m) {
137     this->get_service().new_match(this->get_implementation(), m);
138   }
139 
140   /// Destroy a match.
141   void delete_match(match& m) {
142     this->get_service().delete_match(this->get_implementation(), m);
143   }
144 
145   /// Create a new filter.
146   void new_filter(filter& f) {
147     this->get_service().new_filter(this->get_implementation(), f);
148   }
149 
150   /// Destroy a filter.
151   void delete_filter(filter& f) {
152     this->get_service().delete_filter(this->get_implementation(), f);
153   }
154 
155   // FIXME the only way around this I see is to expose start() here, which seems
156   // ugly
157   friend class filter;
158 };
159 
160 typedef std::shared_ptr<connection> connection_ptr;
161 
162 }  // namespace dbus
163 
164 #endif  // DBUS_CONNECTION_HPP
165