1 #include <string> 2 #include <boost/asio.hpp> 3 #include "connection_service.hpp" 4 5 namespace dbus { 6 7 using std::string; 8 using namespace boost::asio; 9 10 /// Root D-Bus IO object 11 /** 12 * A connection to a bus, through which messages may be sent or received. 13 */ 14 class connection 15 : public basic_io_object<connection_service> 16 { 17 public: 18 19 /// Constructor. 20 /** 21 * @param io_service The io_service object that the connection will use to 22 * wire D-Bus for asynchronous operation. 23 */ 24 explicit connection(io_service& io) 25 : basic_io_object<connection_service>(io) 26 { 27 } 28 29 //TODO: should these be constructors...? 30 31 /// Open a connection to a specified address. 32 /** 33 * @note This function or open(unsigned) should be called only once to initialize 34 * a connection. 35 * 36 * @param address The address of the bus to connect to. 37 * 38 * @param shared Set false to open a private connection. 39 * 40 * @throws boost::system::system_error When opening the connection failed. 41 */ 42 void open(const string& address, bool shared=true) 43 { 44 this->get_service().open( 45 this->get_implementation(), 46 address, 47 shared); 48 } 49 50 /// Open a connection to a well-known bus. 51 /** 52 * D-Bus connections are usually opened to well-known buses like the 53 * system or session bus. 54 * 55 * @note This function or open(string) should be called only once to initialize 56 * a connection. 57 * 58 * @param bus_type The well-known bus to connect to. 59 * 60 * @param shared Set false to open a private connection. 61 * 62 * @throws boost::system::system_error When opening the connection failed. 63 */ 64 // TODO: change this unsigned to an enumeration 65 void open(const unsigned bus_type, bool shared=true) 66 { 67 this->get_service().open( 68 this->get_implementation(), 69 bus_type, 70 shared); 71 } 72 73 //TODO add error_code catchers to all these... 74 75 /// Send a message. 76 /** 77 * @param m The message to send. 78 * 79 * @param timeout Time to wait for a reply. Passing 0 as the timeout means 80 * that you wish to ignore the reply. (Or catch it later somehow...) 81 * 82 * @return The reply received. 83 * 84 * @throws boost::system::system_error When the response timed out, if 85 * timeout was not 0. 86 */ 87 template <typename Duration> 88 message send(message& m, 89 const Duration& timeout = timeout_default()) 90 { 91 return this->get_service().send( 92 this->get_implementation(), 93 m, 94 timeout); 95 } 96 97 /// Send a message asynchronously. 98 /** 99 * @param m The message to send. 100 * 101 * @param handler Handler for the reply. 102 * 103 * @return Asynchronous result 104 */ 105 template<typename MessageHandler> 106 inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler, 107 void(boost::system::error_code, message)) 108 async_send(message& m, 109 BOOST_ASIO_MOVE_ARG(MessageHandler) handler) 110 { 111 return this->get_service().async_send( 112 this->get_implementation(), 113 m, 114 BOOST_ASIO_MOVE_CAST(MessageHandler)(handler)); 115 } 116 117 //TODO figure out incomplete type knot without inlining class declaration. 118 //TODO use noncopyable 119 120 /// Simple placeholder object for a match rule. 121 /** 122 * A match rule determines what messages will be received by this application. 123 * 124 * Each rule will be represented by an instance of match. To remove that rule, 125 * dispose of the object. 126 */ 127 class match 128 { 129 connection& connection_; 130 std::string expression_; 131 132 match(connection& c, 133 BOOST_ASIO_MOVE_ARG(std::string) e) 134 : connection_(c), 135 expression_(BOOST_ASIO_MOVE_CAST(e)) 136 { 137 // dbus_bus_add_match 138 } 139 140 match() {} 141 142 public: 143 friend class connection; 144 145 ~match() 146 { 147 // dbus_bus_remove_match 148 } 149 150 }; 151 152 /// Create a new match. 153 match new_match( 154 BOOST_ASIO_MOVE_ARG(string) expression) 155 { 156 return this->get_service().new_match( 157 this->get_implementation(), 158 BOOST_ASIO_MOVE_CAST(string)(expression)); 159 } 160 161 /// Represents a filter of incoming messages. 162 /** 163 * Filters examine incoming messages, demuxing them to multiple queues. 164 */ 165 class filter 166 { 167 connection& connection_; 168 function<bool(message)> predicate_; 169 detail::queue<message> queue_; 170 171 template<typename MessagePredicate> 172 filter(connection& c, 173 BOOST_ASIO_MOVE_ARG(MessagePredicate) p) 174 : connection_(c), 175 predicate_(BOOST_ASIO_MOVE_CAST(MessagePredicate)(p)) 176 { 177 // dbus_connection_add_filter 178 } 179 180 filter() {} 181 182 public: 183 friend class connection; 184 185 ~filter() 186 { 187 // dbus_connection_remove_filter 188 } 189 190 template<typename MessageHandler> 191 inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler, 192 void(boost::system::error_code, message)) 193 async_dispatch( 194 BOOST_ASIO_MOVE_ARG(MessageHandler) handler) 195 { 196 return queue_.async_pop( 197 BOOST_ASIO_MOVE_CAST(MessageHandler)(handler)); 198 } 199 200 }; 201 202 /// Create a new filter. 203 template<typename MessagePredicate> 204 filter new_filter( 205 BOOST_ASIO_MOVE_ARG(MessagePredicate) p) 206 { 207 return this->get_service().new_match( 208 this->get_implementation(), 209 BOOST_ASIO_MOVE_CAST(MessagePredicate)(p)); 210 } 211 212 }; 213 214 } // namespace dbus 215