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_IPP 7#define DBUS_CONNECTION_IPP 8 9#include <dbus/dbus.h> 10#include <dbus/detail/watch_timeout.hpp> 11 12#include <boost/atomic.hpp> 13 14namespace dbus { 15namespace impl { 16 17class connection { 18 public: 19 boost::atomic<bool> is_paused; 20 DBusConnection* conn; 21 22 connection() : is_paused(true), conn(NULL) {} 23 24 void open(boost::asio::io_service& io, int bus) { 25 error e; 26 conn = dbus_bus_get_private((DBusBusType)bus, e); 27 e.throw_if_set(); 28 29 dbus_connection_set_exit_on_disconnect(conn, false); 30 31 detail::set_watch_timeout_dispatch_functions(conn, io); 32 } 33 34 void open(boost::asio::io_service& io, const string& address) { 35 error e; 36 conn = dbus_connection_open_private(address.c_str(), e); 37 e.throw_if_set(); 38 39 dbus_bus_register(conn, e); 40 e.throw_if_set(); 41 42 dbus_connection_set_exit_on_disconnect(conn, false); 43 44 detail::set_watch_timeout_dispatch_functions(conn, io); 45 } 46 47 void request_name(const string& name) { 48 error e; 49 dbus_bus_request_name(conn, name.c_str(), 50 DBUS_NAME_FLAG_DO_NOT_QUEUE | DBUS_NAME_FLAG_REPLACE_EXISTING, e); 51 e.throw_if_set(); 52 } 53 54 std::string get_unique_name() { 55 error e; 56 auto name = dbus_bus_get_unique_name (conn); 57 e.throw_if_set(); 58 return std::string(name); 59 } 60 61 ~connection() { 62 if (conn != NULL) { 63 dbus_connection_close(conn); 64 dbus_connection_unref(conn); 65 } 66 } 67 68 message new_method_return(message &m) { 69 return dbus_message_new_method_return(m); 70 } 71 72 operator DBusConnection*() { return conn; } 73 operator const DBusConnection*() const { return conn; } 74 75 message send_with_reply_and_block(message& m, 76 int timeout_in_milliseconds = -1) { 77 error e; 78 DBusMessage* out = dbus_connection_send_with_reply_and_block( 79 conn, m, timeout_in_milliseconds, e); 80 e.throw_if_set(); 81 message reply(out); 82 83 return reply; 84 } 85 86 void send(message& m) { 87 // ignoring message serial for now 88 dbus_connection_send(conn, m, NULL); 89 } 90 91 void send_with_reply(message& m, DBusPendingCall** p, 92 int timeout_in_milliseconds = -1) { 93 dbus_connection_send_with_reply(conn, m, p, timeout_in_milliseconds); 94 } 95 96 // begin asynchronous operation 97 // FIXME should not get io from an argument 98 void start(boost::asio::io_service& io) { 99 bool old_value(true); 100 if (is_paused.compare_exchange_strong(old_value, false)) { 101 // If two threads call connection::async_send() 102 // simultaneously on a paused connection, then 103 // only one will pass the CAS instruction and 104 // only one dispatch_handler will be injected. 105 io.post(detail::dispatch_handler(io, conn)); 106 } 107 } 108 109 void cancel(boost::asio::io_service& io) { 110 bool old_value(false); 111 if (is_paused.compare_exchange_strong(old_value, true)) { 112 // TODO 113 } 114 } 115}; 116 117} // namespace impl 118} // namespace dbus 119 120#endif // DBUS_CONNECTION_IPP 121