# DBus-C++

## Desktop Communication Bus System

libdbus-c-- Documentation 0.9.0

- Files
- Data Structures
- Globals
- Main Page

connection.cpp
Go to the documentation of this file.
1/*
2 *
3 * D-Bus++ - C++ bindings for D-Bus
4 *
5 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <dbus-c++/debug.h>
29#include <dbus-c++/connection.h>
30
31#include <dbus/dbus.h>
32#include <string>
33
34#include "internalerror.h"
35
36#include "connection_p.h"
37#include "dispatcher_p.h"
38#include "server_p.h"
39#include "message_p.h"
40#include "pendingcall_p.h"
41
42 using namespace DBus;
43
44 Connection::Private::Private(DBusConnection *c, Server::Private *s)
45 : conn(c) , dispatcher(NULL), server(s)
46{
47 init();
48}
49
50 Connection::Private::Private(DBusBusType type)
51 : dispatcher(NULL), server(NULL)
52{
53 InternalError e;
54
55 conn = dbus_bus_get_private(type, e);
56
57 if (e) throw Error(e);
58
59 init();
60}
61
62 Connection::Private::~Private()
63{
64 debug_log("terminating connection 0x%08x", conn);
65
66 detach_server();
67
68 if (dbus_connection_get_is_connected(conn))
69 {
70 std::vector<std::string>::iterator i = names.begin();
71
72 while (i != names.end())
73 {
74 debug_log("%s: releasing bus name %s", dbus_bus_get_unique_name(conn), i->c_str());
75 dbus_bus_release_name(conn, i->c_str(), NULL);
76 ++i;
77 }
78 dbus_connection_close(conn);
79 }
80 dbus_connection_unref(conn);
81}
82
83 void Connection::Private::init()
84{
85 dbus_connection_ref(conn);
86 dbus_connection_ref(conn); //todo: the library has to own another reference
87
88 disconn_filter = new Callback<Connection::Private, bool, const Message &>(
89 this, &Connection::Private::disconn_filter_function
90 );
91
92 dbus_connection_add_filter(conn, message_filter_stub, &disconn_filter, NULL); // TODO: some assert at least
93
94 dbus_connection_set_dispatch_status_function(conn, dispatch_status_stub, this, 0);
95 dbus_connection_set_exit_on_disconnect(conn, false); //why was this set to true??
96}
97
98 void Connection::Private::detach_server()
99{
100 /* Server::Private *tmp = server;
101
102 server = NULL;
103
104 if (tmp)
105 {
106 ConnectionList::iterator i;
107
108 for (i = tmp->connections.begin(); i != tmp->connections.end(); ++i)
109 {
110 if (i->_pvt.get() == this)
111 {
112 tmp->connections.erase(i);
113 break;
114 }
115 }
116 }*/
117}
118
119 bool Connection::Private::do_dispatch()
120{
121 debug_log("dispatching on %p", conn);
122
123 if (!dbus_connection_get_is_connected(conn))
124 {
125 debug_log("connection terminated");
126
127 detach_server();
128
129 return true;
130 }
131
132 return dbus_connection_dispatch(conn) != DBUS_DISPATCH_DATA_REMAINS;
133}
134
135 void Connection::Private::dispatch_status_stub(DBusConnection *dc, DBusDispatchStatus status, void *data)
136{
137 Private *p = static_cast<Private *>(data);
138
139 switch (status)
140 {
141 case DBUS_DISPATCH_DATA_REMAINS:
142 debug_log("some dispatching to do on %p", dc);
143 p->dispatcher->queue_connection(p);
144 break;
145
146 case DBUS_DISPATCH_COMPLETE:
147 debug_log("all dispatching done on %p", dc);
148 break;
149
150 case DBUS_DISPATCH_NEED_MEMORY: //uh oh...
151 debug_log("connection %p needs memory", dc);
152 break;
153 }
154}
155
156DBusHandlerResult Connection::Private::message_filter_stub(DBusConnection *conn, DBusMessage *dmsg, void *data)
157{
158 MessageSlot *slot = static_cast<MessageSlot *>(data);
159
160 Message msg = Message(new Message::Private(dmsg));
161
162 return slot && !slot->empty() && slot->call(msg)
163 ? DBUS_HANDLER_RESULT_HANDLED
164 : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
165}
166
167 bool Connection::Private::disconn_filter_function(const Message &msg)
168{
169 if (msg.is_signal(DBUS_INTERFACE_LOCAL, "Disconnected"))
170 {
171 debug_log("%p disconnected by local bus", conn);
172 dbus_connection_close(conn);
173
174 return true;
175 }
176 return false;
177}
178
179DBusDispatchStatus Connection::Private::dispatch_status()
180{
181 return dbus_connection_get_dispatch_status(conn);
182}
183
184 bool Connection::Private::has_something_to_dispatch()
185{
186 return dispatch_status() == DBUS_DISPATCH_DATA_REMAINS;
187}
188
189
190 Connection Connection::SystemBus()
191{
192 return Connection(new Private(DBUS_BUS_SYSTEM));
193}
194
195 Connection Connection::SessionBus()
196{
197 return Connection(new Private(DBUS_BUS_SESSION));
198}
199
200 Connection Connection::ActivationBus()
201{
202 return Connection(new Private(DBUS_BUS_STARTER));
203}
204
205 Connection::Connection(const char *address, bool priv)
206 : _timeout(-1)
207{
208 InternalError e;
209 DBusConnection *conn = priv
210 ? dbus_connection_open_private(address, e)
211 : dbus_connection_open(address, e);
212
213 if (e) throw Error(e);
214
215 _pvt = new Private(conn);
216
217 setup(default_dispatcher);
218
219 debug_log("connected to %s", address);
220}
221
222 Connection::Connection(Connection::Private *p)
223 : _pvt(p), _timeout(-1)
224{
225 setup(default_dispatcher);
226}
227
228 Connection::Connection(const Connection &c)
229 : _pvt(c._pvt), _timeout(c._timeout)
230{
231 dbus_connection_ref(_pvt->conn);
232}
233
234 Connection::~Connection()
235{
236 dbus_connection_unref(_pvt->conn);
237}
238
239 Dispatcher *Connection::setup(Dispatcher *dispatcher)
240{
241 debug_log("registering stubs for connection %p", _pvt->conn);
242
243 if (!dispatcher) dispatcher = default_dispatcher;
244
245 if (!dispatcher) throw ErrorFailed("no default dispatcher set for new connection");
246
247 Dispatcher *prev = _pvt->dispatcher;
248
249 _pvt->dispatcher = dispatcher;
250
251 dispatcher->queue_connection(_pvt.get());
252
253 dbus_connection_set_watch_functions(
254 _pvt->conn,
255 Dispatcher::Private::on_add_watch,
256 Dispatcher::Private::on_rem_watch,
257 Dispatcher::Private::on_toggle_watch,
258 dispatcher,
259 0
260 );
261
262 dbus_connection_set_timeout_functions(
263 _pvt->conn,
264 Dispatcher::Private::on_add_timeout,
265 Dispatcher::Private::on_rem_timeout,
266 Dispatcher::Private::on_toggle_timeout,
267 dispatcher,
268 0
269 );
270
271 return prev;
272}
273
274 bool Connection::operator == (const Connection &c) const
275{
276 return _pvt->conn == c._pvt->conn;
277}
278
279 bool Connection::register_bus()
280{
281 InternalError e;
282
283 bool r = dbus_bus_register(_pvt->conn, e);
284
285 if (e) throw(e);
286
287 return r;
288}
289
290 bool Connection::connected() const
291{
292 return dbus_connection_get_is_connected(_pvt->conn);
293}
294
295 void Connection::disconnect()
296{
297// dbus_connection_disconnect(_pvt->conn); // disappeared in 0.9x
298 dbus_connection_close(_pvt->conn);
299}
300
301 void Connection::exit_on_disconnect(bool exit)
302{
303 dbus_connection_set_exit_on_disconnect(_pvt->conn, exit);
304}
305
306 bool Connection::unique_name(const char *n)
307{
308 return dbus_bus_set_unique_name(_pvt->conn, n);
309}
310
311 const char *Connection::unique_name() const
312{
313 return dbus_bus_get_unique_name(_pvt->conn);
314}
315
316 void Connection::flush()
317{
318 dbus_connection_flush(_pvt->conn);
319}
320
321 void Connection::add_match(const char *rule)
322{
323 InternalError e;
324
325 dbus_bus_add_match(_pvt->conn, rule, e);
326
327 debug_log("%s: added match rule %s", unique_name(), rule);
328
329 if (e) throw Error(e);
330}
331
332 void Connection::remove_match(const char *rule,
333 bool throw_on_error)
334{
335 InternalError e;
336
337 dbus_bus_remove_match(_pvt->conn, rule, e);
338
339 debug_log("%s: removed match rule %s", unique_name(), rule);
340
341 if (e)
342 {
343 if (throw_on_error)
344 throw Error(e);
345 else
346 debug_log("DBus::Connection::remove_match: %s (%s).",
347 static_cast<DBusError *>(e)->message,
348 static_cast<DBusError *>(e)->name);
349 }
350}
351
352 bool Connection::add_filter(MessageSlot &s)
353{
354 debug_log("%s: adding filter", unique_name());
355 return dbus_connection_add_filter(_pvt->conn, Private::message_filter_stub, &s, NULL);
356}
357
358 void Connection::remove_filter(MessageSlot &s)
359{
360 debug_log("%s: removing filter", unique_name());
361 dbus_connection_remove_filter(_pvt->conn, Private::message_filter_stub, &s);
362}
363
364 bool Connection::send(const Message &msg, unsigned int *serial)
365{
366 return dbus_connection_send(_pvt->conn, msg._pvt->msg, serial);
367}
368
369 Message Connection::send_blocking(Message &msg, int timeout)
370{
371 DBusMessage *reply;
372 InternalError e;
373
374 if (this->_timeout != -1)
375 {
376 reply = dbus_connection_send_with_reply_and_block(_pvt->conn, msg._pvt->msg, this->_timeout, e);
377 }
378 else
379 {
380 reply = dbus_connection_send_with_reply_and_block(_pvt->conn, msg._pvt->msg, timeout, e);
381 }
382
383 if (e) throw Error(e);
384
385 return Message(new Message::Private(reply), false);
386}
387
388 PendingCall Connection::send_async(Message &msg, int timeout)
389{
390 DBusPendingCall *pending;
391
392 if (!dbus_connection_send_with_reply(_pvt->conn, msg._pvt->msg, &pending, timeout))
393 {
394 throw ErrorNoMemory("Unable to start asynchronous call");
395 }
396 return PendingCall(new PendingCall::Private(pending));
397}
398
399 void Connection::request_name(const char *name, int flags)
400{
401 InternalError e;
402
403 debug_log("%s: registering bus name %s", unique_name(), name);
404
405 /*
406 * TODO:
407 * Think about giving back the 'ret' value. Some people on the list
408 * requested about this...
409 */
410 int ret = dbus_bus_request_name(_pvt->conn, name, flags, e);
411
412 if (ret == -1)
413 {
414 if (e) throw Error(e);
415 }
416
417// this->remove_match("destination");
418
419 if (name)
420 {
421 _pvt->names.push_back(name);
422 std::string match = "destination='" + _pvt->names.back() + "'";
423 add_match(match.c_str());
424 }
425}
426
427 unsigned long Connection::sender_unix_uid(const char *sender)
428{
429 InternalError e;
430
431 unsigned long ul = dbus_bus_get_unix_user(_pvt->conn, sender, e);
432
433 if (e) throw Error(e);
434
435 return ul;
436}
437
438 bool Connection::has_name(const char *name)
439{
440 InternalError e;
441
442 bool b = dbus_bus_name_has_owner(_pvt->conn, name, e);
443
444 if (e) throw Error(e);
445
446 return b;
447}
448
449 const std::vector<std::string>& Connection::names()
450{
451 return _pvt->names;
452}
453
454 bool Connection::start_service(const char *name, unsigned long flags)
455{
456 InternalError e;
457
458 bool b = dbus_bus_start_service_by_name(_pvt->conn, name, flags, NULL, e);
459
460 if (e) throw Error(e);
461
462 return b;
463}
464
465 void Connection::set_timeout(int timeout)
466{
467 _timeout = timeout;
468}
469
470 int Connection::get_timeout()
471{
472 return _timeout;
473}
474
DBus::Callback
Definition util.h:272
DBus::Connection::connected
bool connected() const
Gets whether the connection is currently open.
Definition connection.cpp:290
DBus::Connection::exit_on_disconnect
void exit_on_disconnect(bool exit)
Set whether _exit() should be called when the connection receives a disconnect signal.
Definition connection.cpp:301
DBus::Connection::SystemBus
static Connection SystemBus()
Definition connection.cpp:190
DBus::Connection::remove_match
void remove_match(const char *rule, bool throw_on_error)
Removes a previously-added match rule "by value" (the most recently-added identical rule gets removed...
Definition connection.cpp:332
DBus::Connection::has_name
bool has_name(const char *name)
Asks the bus whether a certain name has an owner.
Definition connection.cpp:438
DBus::Connection::Connection
Connection(Private *)
Definition connection.cpp:222
DBus::Connection::flush
void flush()
Blocks until the outgoing message queue is empty.
Definition connection.cpp:316
DBus::Connection::request_name
void request_name(const char *name, int flags=0)
Definition connection.cpp:399
DBus::Connection::send_blocking
Message send_blocking(Message &msg, int timeout=-1)
Sends a message and blocks a certain time period while waiting for a reply.
Definition connection.cpp:369
DBus::Connection::~Connection
virtual ~Connection()
Definition connection.cpp:234
DBus::Connection::add_filter
bool add_filter(MessageSlot &s)
Adds a message filter.
Definition connection.cpp:352
DBus::Connection::setup
Dispatcher * setup(Dispatcher *)
Definition connection.cpp:239
DBus::Connection::start_service
bool start_service(const char *name, unsigned long flags)
Starts a service that will request ownership of the given name.
Definition connection.cpp:454
DBus::Connection::remove_filter
void remove_filter(MessageSlot &s)
Removes a previously-added message filter.
Definition connection.cpp:358
DBus::Connection::_timeout
int _timeout
Definition connection.h:462
DBus::Connection::add_match
void add_match(const char *rule)
Adds a match rule to match messages going through the message bus.
Definition connection.cpp:321
DBus::Connection::get_timeout
int get_timeout()
Definition connection.cpp:470
DBus::Connection::ActivationBus
static Connection ActivationBus()
Definition connection.cpp:200
DBus::Connection::send
bool send(const Message &msg, unsigned int *serial=NULL)
Adds a message to the outgoing message queue.
Definition connection.cpp:364
DBus::Connection::sender_unix_uid
unsigned long sender_unix_uid(const char *sender)
Definition connection.cpp:427
DBus::Connection::_pvt
RefPtrI< Private > _pvt
Definition connection.h:461
DBus::Connection::send_async
PendingCall send_async(Message &msg, int timeout=-1)
Queues a message to send, as with send(), but also returns a DBusPendingCall used to receive a reply ...
Definition connection.cpp:388
DBus::Connection::SessionBus
static Connection SessionBus()
Definition connection.cpp:195
DBus::Connection::register_bus
bool register_bus()
Registers a connection with the bus.
Definition connection.cpp:279
DBus::Connection::set_timeout
void set_timeout(int timeout)
Definition connection.cpp:465
DBus::Connection::operator==
bool operator==(const Connection &) const
Definition connection.cpp:274
DBus::Connection::disconnect
void disconnect()
Closes a private connection, so no further data can be sent or received.
Definition connection.cpp:295
DBus::Connection::names
const std::vector< std::string > & names()
Definition connection.cpp:449
DBus::Connection::unique_name
const char * unique_name() const
Gets the unique name of the connection as assigned by the message bus.
Definition connection.cpp:311
DBus::Dispatcher
Definition dispatcher.h:152
DBus::Dispatcher::queue_connection
void queue_connection(Connection::Private *)
Definition dispatcher.cpp:158
DBus::Error
Definition error.h:40
DBus::Message
Definition message.h:159
DBus::Message::_pvt
RefPtrI< Private > _pvt
Definition message.h:208
DBus::Message::is_signal
bool is_signal(const char *interface, const char *member) const
Definition message.cpp:468
DBus::PendingCall
Definition pendingcall.h:38
DBus::Slot::call
R call(P param) const
Definition util.h:248
DBus::Slot::empty
bool empty() const
Definition util.h:260
connection.h
connection_p.h
debug.h
dispatcher_p.h
internalerror.h
message_p.h
DBus
Definition connection_p.h:42
DBus::MessageSlot
Slot< bool, const Message & > MessageSlot
Definition connection.h:41
DBus::default_dispatcher
DXXAPI Dispatcher * default_dispatcher
Definition dispatcher.cpp:36
DBus::debug_log
DXXAPI LogFunction debug_log
Definition debug.cpp:55
pendingcall_p.h
server_p.h
DBus::Connection::Private
Definition connection_p.h:45
DBus::Connection::Private::names
std::vector< std::string > names
Definition connection_p.h:48
DBus::Connection::Private::dispatch_status
DBusDispatchStatus dispatch_status()
Definition connection.cpp:179
DBus::Connection::Private::dispatcher
Dispatcher * dispatcher
Definition connection_p.h:50
DBus::Connection::Private::do_dispatch
bool do_dispatch()
Definition connection.cpp:119
DBus::Connection::Private::dispatch_status_stub
static void dispatch_status_stub(DBusConnection *, DBusDispatchStatus, void *)
Definition connection.cpp:135
DBus::Connection::Private::~Private
~Private()
Definition connection.cpp:62
DBus::Connection::Private::message_filter_stub
static DBusHandlerResult message_filter_stub(DBusConnection *, DBusMessage *, void *)
Definition connection.cpp:156
DBus::Connection::Private::conn
DBusConnection * conn
Definition connection_p.h:46
DBus::Connection::Private::init
void init()
Definition connection.cpp:83
DBus::Connection::Private::disconn_filter
MessageSlot disconn_filter
Definition connection_p.h:53
DBus::Connection::Private::detach_server
void detach_server()
Definition connection.cpp:98
DBus::Connection::Private::Private
Private(DBusConnection *, Server::Private *=NULL)
Definition connection.cpp:44
DBus::Connection::Private::disconn_filter_function
bool disconn_filter_function(const Message &)
Definition connection.cpp:167
DBus::Connection::Private::has_something_to_dispatch
bool has_something_to_dispatch()
Definition connection.cpp:184
DBus::Connection::Private::server
Server::Private * server
Definition connection_p.h:56
DBus::Dispatcher::Private::on_rem_watch
static void on_rem_watch(DBusWatch *watch, void *data)
Definition dispatcher.cpp:115
DBus::Dispatcher::Private::on_add_timeout
static dbus_bool_t on_add_timeout(DBusTimeout *timeout, void *data)
Definition dispatcher.cpp:131
DBus::Dispatcher::Private::on_add_watch
static dbus_bool_t on_add_watch(DBusWatch *watch, void *data)
Definition dispatcher.cpp:104
DBus::Dispatcher::Private::on_toggle_timeout
static void on_toggle_timeout(DBusTimeout *timeout, void *data)
Definition dispatcher.cpp:151
DBus::Dispatcher::Private::on_toggle_watch
static void on_toggle_watch(DBusWatch *watch, void *data)
Definition dispatcher.cpp:124
DBus::Dispatcher::Private::on_rem_timeout
static void on_rem_timeout(DBusTimeout *timeout, void *data)
Definition dispatcher.cpp:142
DBus::ErrorFailed
Definition error.h:75
DBus::ErrorNoMemory
Definition error.h:82
DBus::InternalError
Definition internalerror.h:40
DBus::Message::Private
Definition message_p.h:41
DBus::PendingCall::Private
Definition pendingcall_p.h:41
DBus::Server::Private
Definition server_p.h:42
DBus::type
Definition types.h:145