# DBus-C++

## Desktop Communication Bus System

libdbus-c-- Documentation 0.9.0

- Files
- Data Structures
- Globals
- Main Page

object.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++/object.h>
30#include "internalerror.h"
31
32#include <cstring>
33#include <map>
34#include <dbus/dbus.h>
35
36#include "message_p.h"
37#include "server_p.h"
38#include "connection_p.h"
39
40 using namespace DBus;
41
42 Object::Object(Connection &conn, const Path &path, const char *service)
43 : _conn(conn), _path(path), _service(service ? service : ""), _default_timeout(-1)
44{
45}
46
47 Object::~Object()
48{
49}
50
51 void Object::set_timeout(int new_timeout)
52{
53 debug_log("%s: %d millies", __PRETTY_FUNCTION__, new_timeout);
54 if (new_timeout < 0 && new_timeout != -1)
55 throw ErrorInvalidArgs("Bad timeout, cannot set it");
56 _default_timeout = new_timeout;
57}
58
59 struct ObjectAdaptor::Private
60{
61 static void unregister_function_stub(DBusConnection *, void *);
62 static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *);
63};
64
65 static DBusObjectPathVTable _vtable =
66{
67 ObjectAdaptor::Private::unregister_function_stub,
68 ObjectAdaptor::Private::message_function_stub,
69 NULL, NULL, NULL, NULL
70};
71
72 void ObjectAdaptor::Private::unregister_function_stub(DBusConnection *conn, void *data)
73{
74 //TODO: what do we have to do here ?
75}
76
77DBusHandlerResult ObjectAdaptor::Private::message_function_stub(DBusConnection *, DBusMessage *dmsg, void *data)
78{
79 ObjectAdaptor *o = static_cast<ObjectAdaptor *>(data);
80
81 if (o)
82 {
83 Message msg(new Message::Private(dmsg));
84
85 debug_log("in object %s", o->path().c_str());
86 debug_log(" got message #%d from %s to %s",
87 msg.serial(),
88 msg.sender(),
89 msg.destination()
90 );
91
92 return o->handle_message(msg)
93 ? DBUS_HANDLER_RESULT_HANDLED
94 : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
95 }
96 else
97 {
98 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
99 }
100}
101
102 typedef std::map<Path, ObjectAdaptor *> ObjectAdaptorTable;
103 static ObjectAdaptorTable _adaptor_table;
104
105 ObjectAdaptor *ObjectAdaptor::from_path(const Path &path)
106{
107 ObjectAdaptorTable::iterator ati = _adaptor_table.find(path);
108
109 if (ati != _adaptor_table.end())
110 return ati->second;
111
112 return NULL;
113}
114
115 ObjectAdaptorPList ObjectAdaptor::from_path_prefix(const std::string &prefix)
116{
117 ObjectAdaptorPList ali;
118
119 ObjectAdaptorTable::iterator ati = _adaptor_table.begin();
120
121 size_t plen = prefix.length();
122
123 while (ati != _adaptor_table.end())
124 {
125 if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
126 ali.push_back(ati->second);
127
128 ++ati;
129 }
130
131 return ali;
132}
133
134 ObjectPathList ObjectAdaptor::child_nodes_from_prefix(const std::string &prefix)
135{
136 ObjectPathList ali;
137
138 ObjectAdaptorTable::iterator ati = _adaptor_table.begin();
139
140 size_t plen = prefix.length();
141
142 while (ati != _adaptor_table.end())
143 {
144 if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
145 {
146 std::string p = ati->second->path().substr(plen);
147 p = p.substr(0, p.find('/'));
148 ali.push_back(p);
149 }
150 ++ati;
151 }
152
153 ali.sort();
154 ali.unique();
155
156 return ali;
157}
158
159 ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path)
160 : Object(conn, path, conn.unique_name())
161{
162 register_obj();
163}
164
165 ObjectAdaptor::~ObjectAdaptor()
166{
167 unregister_obj(false);
168}
169
170 void ObjectAdaptor::register_obj()
171{
172 debug_log("registering local object %s", path().c_str());
173
174 if (!dbus_connection_register_object_path(conn()._pvt->conn, path().c_str(), &_vtable, this))
175 {
176 throw ErrorNoMemory("unable to register object path");
177 }
178
179 _adaptor_table[path()] = this;
180}
181
182 void ObjectAdaptor::unregister_obj(bool)
183{
184 _adaptor_table.erase(path());
185
186 debug_log("unregistering local object %s", path().c_str());
187
188 dbus_connection_unregister_object_path(conn()._pvt->conn, path().c_str());
189}
190
191 void ObjectAdaptor::_emit_signal(SignalMessage &sig)
192{
193 sig.path(path().c_str());
194
195 conn().send(sig);
196}
197
198 struct ReturnLaterError
199{
200 const Tag *tag;
201};
202
203 bool ObjectAdaptor::handle_message(const Message &msg)
204{
205 switch (msg.type())
206 {
207 case DBUS_MESSAGE_TYPE_METHOD_CALL:
208 {
209 const CallMessage &cmsg = reinterpret_cast<const CallMessage &>(msg);
210 const char *member = cmsg.member();
211 const char *interface = cmsg.interface();
212
213 debug_log(" invoking method %s.%s", interface, member);
214
215 InterfaceAdaptor *ii = find_interface(interface);
216 if (ii)
217 {
218 try
219 {
220 Message ret = ii->dispatch_method(cmsg);
221 conn().send(ret);
222 }
223 catch (Error &e)
224 {
225 ErrorMessage em(cmsg, e.name(), e.message());
226 conn().send(em);
227 }
228 catch (ReturnLaterError &rle)
229 {
230 _continuations[rle.tag] = new Continuation(conn(), cmsg, rle.tag);
231 }
232 return true;
233 }
234 else
235 {
236 return false;
237 }
238 }
239 default:
240 {
241 return false;
242 }
243 }
244}
245
246 void ObjectAdaptor::return_later(const Tag *tag)
247{
248 ReturnLaterError rle = { tag };
249 throw rle;
250}
251
252 void ObjectAdaptor::return_now(Continuation *ret)
253{
254 ret->_conn.send(ret->_return);
255
256 ContinuationMap::iterator di = _continuations.find(ret->_tag);
257
258 delete di->second;
259
260 _continuations.erase(di);
261}
262
263 void ObjectAdaptor::return_error(Continuation *ret, const Error error)
264{
265 ret->_conn.send(ErrorMessage(ret->_call, error.name(), error.message()));
266
267 ContinuationMap::iterator di = _continuations.find(ret->_tag);
268
269 delete di->second;
270
271 _continuations.erase(di);
272}
273
274 ObjectAdaptor::Continuation *ObjectAdaptor::find_continuation(const Tag *tag)
275{
276 ContinuationMap::iterator di = _continuations.find(tag);
277
278 return di != _continuations.end() ? di->second : NULL;
279}
280
281 ObjectAdaptor::Continuation::Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
282 : _conn(conn), _call(call), _return(_call), _tag(tag)
283{
284 _writer = _return.writer(); //todo: verify
285}
286
287/*
288*/
289
290 ObjectProxy::ObjectProxy(Connection &conn, const Path &path, const char *service)
291 : Object(conn, path, service)
292{
293 register_obj();
294}
295
296 ObjectProxy::~ObjectProxy()
297{
298 unregister_obj(false);
299}
300
301 void ObjectProxy::register_obj()
302{
303 debug_log("registering remote object %s", path().c_str());
304
305 _filtered = new Callback<ObjectProxy, bool, const Message &>(this, &ObjectProxy::handle_message);
306
307 conn().add_filter(_filtered);
308
309 InterfaceProxyTable::const_iterator ii = _interfaces.begin();
310 while (ii != _interfaces.end())
311 {
312 std::string im = "type='signal',interface='" + ii->first + "',path='" + path() + "'";
313 conn().add_match(im.c_str());
314 ++ii;
315 }
316}
317
318 void ObjectProxy::unregister_obj(bool throw_on_error)
319{
320 debug_log("unregistering remote object %s", path().c_str());
321
322 InterfaceProxyTable::const_iterator ii = _interfaces.begin();
323 while (ii != _interfaces.end())
324 {
325 std::string im = "type='signal',interface='" + ii->first + "',path='" + path() + "'";
326 conn().remove_match(im.c_str(), throw_on_error);
327 ++ii;
328 }
329 conn().remove_filter(_filtered);
330}
331
332 Message ObjectProxy::_invoke_method(CallMessage &call)
333{
334 if (call.path() == NULL)
335 call.path(path().c_str());
336
337 if (call.destination() == NULL)
338 call.destination(service().c_str());
339
340 return conn().send_blocking(call, get_timeout());
341}
342
343 bool ObjectProxy::_invoke_method_noreply(CallMessage &call)
344{
345 if (call.path() == NULL)
346 call.path(path().c_str());
347
348 if (call.destination() == NULL)
349 call.destination(service().c_str());
350
351 return conn().send(call);
352}
353
354 bool ObjectProxy::handle_message(const Message &msg)
355{
356 switch (msg.type())
357 {
358 case DBUS_MESSAGE_TYPE_SIGNAL:
359 {
360 const SignalMessage &smsg = reinterpret_cast<const SignalMessage &>(msg);
361 const char *interface = smsg.interface();
362 const char *member = smsg.member();
363 const char *objpath = smsg.path();
364
365 if (objpath != path()) return false;
366
367 debug_log("filtered signal %s(in %s) from %s to object %s",
368 member, interface, msg.sender(), objpath);
369
370 InterfaceProxy *ii = find_interface(interface);
371 if (ii)
372 {
373 return ii->dispatch_signal(smsg);
374 }
375 else
376 {
377 return false;
378 }
379 }
380 default:
381 {
382 return false;
383 }
384 }
385}
DBus::AdaptorBase::find_interface
InterfaceAdaptor * find_interface(const std::string &name)
Definition interface.cpp:42
DBus::CallMessage
Definition message.h:269
DBus::CallMessage::member
const char * member() const
Definition message.cpp:599
DBus::CallMessage::path
const char * path() const
Definition message.cpp:609
DBus::Callback
Definition util.h:272
DBus::Connection
Definition connection.h:49
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::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::add_filter
bool add_filter(MessageSlot &s)
Adds a message filter.
Definition connection.cpp:352
DBus::Connection::remove_filter
void remove_filter(MessageSlot &s)
Removes a previously-added message filter.
Definition connection.cpp:358
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::send
bool send(const Message &msg, unsigned int *serial=NULL)
Adds a message to the outgoing message queue.
Definition connection.cpp:364
DBus::ErrorMessage
Definition message.h:223
DBus::Error
Definition error.h:40
DBus::Error::name
const char * name() const
Definition error.cpp:65
DBus::Error::message
const char * message() const
Definition error.cpp:70
DBus::InterfaceAdaptor
Definition interface.h:134
DBus::InterfaceAdaptor::dispatch_method
Message dispatch_method(const CallMessage &)
Definition interface.cpp:57
DBus::InterfaceProxy
Definition interface.h:164
DBus::InterfaceProxy::dispatch_signal
bool dispatch_signal(const SignalMessage &)
Definition interface.cpp:131
DBus::Message
Definition message.h:159
DBus::Message::destination
const char * destination() const
Definition message.cpp:453
DBus::Message::sender
const char * sender() const
Definition message.cpp:443
DBus::Message::type
int type() const
Definition message.cpp:423
DBus::Message::serial
int serial() const
Definition message.cpp:428
DBus::ObjectAdaptor::Continuation
Definition object.h:137
DBus::ObjectAdaptor::Continuation::_writer
MessageIter _writer
Definition object.h:150
DBus::ObjectAdaptor::Continuation::_conn
Connection _conn
Definition object.h:148
DBus::ObjectAdaptor::Continuation::tag
Tag * tag()
Definition object.h:185
DBus::ObjectAdaptor::Continuation::_return
ReturnMessage _return
Definition object.h:151
DBus::ObjectAdaptor::Continuation::Continuation
Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
Definition object.cpp:281
DBus::ObjectAdaptor::Continuation::_tag
const Tag * _tag
Definition object.h:152
DBus::ObjectAdaptor::Continuation::_call
CallMessage _call
Definition object.h:149
DBus::ObjectAdaptor::from_path_prefix
static ObjectAdaptorPList from_path_prefix(const std::string &prefix)
Definition object.cpp:115
DBus::ObjectAdaptor::handle_message
bool handle_message(const Message &)
Definition object.cpp:203
DBus::ObjectAdaptor::child_nodes_from_prefix
static ObjectPathList child_nodes_from_prefix(const std::string &prefix)
Definition object.cpp:134
DBus::ObjectAdaptor::from_path
static ObjectAdaptor * from_path(const Path &path)
Definition object.cpp:105
DBus::ObjectAdaptor::register_obj
void register_obj()
Definition object.cpp:170
DBus::ObjectAdaptor::return_now
void return_now(Continuation *ret)
Definition object.cpp:252
DBus::ObjectAdaptor::unregister_obj
void unregister_obj(bool throw_on_error=true)
Definition object.cpp:182
DBus::ObjectAdaptor::_continuations
ContinuationMap _continuations
Definition object.h:175
DBus::ObjectAdaptor::return_later
void return_later(const Tag *tag)
Definition object.cpp:246
DBus::ObjectAdaptor::find_continuation
Continuation * find_continuation(const Tag *tag)
Definition object.cpp:274
DBus::ObjectAdaptor::ObjectAdaptor
ObjectAdaptor(Connection &conn, const Path &path)
Definition object.cpp:159
DBus::ObjectAdaptor::_emit_signal
void _emit_signal(SignalMessage &)
Definition object.cpp:191
DBus::ObjectAdaptor::~ObjectAdaptor
~ObjectAdaptor()
Definition object.cpp:165
DBus::ObjectAdaptor::return_error
void return_error(Continuation *ret, const Error error)
Definition object.cpp:263
DBus::ObjectProxy::_invoke_method_noreply
bool _invoke_method_noreply(CallMessage &call)
Definition object.cpp:343
DBus::ObjectProxy::_invoke_method
Message _invoke_method(CallMessage &)
Definition object.cpp:332
DBus::ObjectProxy::_filtered
MessageSlot _filtered
Definition object.h:225
DBus::ObjectProxy::handle_message
bool handle_message(const Message &)
Definition object.cpp:354
DBus::ObjectProxy::~ObjectProxy
~ObjectProxy()
Definition object.cpp:296
DBus::ObjectProxy::ObjectProxy
ObjectProxy(Connection &conn, const Path &path, const char *service="")
Definition object.cpp:290
DBus::ObjectProxy::unregister_obj
void unregister_obj(bool throw_on_error=true)
Definition object.cpp:318
DBus::ObjectProxy::register_obj
void register_obj()
Definition object.cpp:301
DBus::Object::_conn
Connection _conn
Definition object.h:68
DBus::Object::_default_timeout
int _default_timeout
Definition object.h:71
DBus::Object::path
const DBus::Path & path() const
Definition object.h:82
DBus::Object::Object
Object(Connection &conn, const Path &path, const char *service)
Definition object.cpp:42
DBus::Object::get_timeout
int get_timeout() const
Definition object.h:92
DBus::Object::service
const std::string & service() const
Definition object.h:87
DBus::Object::set_timeout
void set_timeout(int new_timeout=-1)
Definition object.cpp:51
DBus::Object::conn
Connection & conn()
Definition object.h:77
DBus::Object::_path
DBus::Path _path
Definition object.h:69
DBus::Object::_service
std::string _service
Definition object.h:70
DBus::Object::~Object
virtual ~Object()
Definition object.cpp:47
DBus::ProxyBase::find_interface
InterfaceProxy * find_interface(const std::string &name)
Definition interface.cpp:116
DBus::ProxyBase::_interfaces
InterfaceProxyTable _interfaces
Definition interface.h:102
DBus::SignalMessage
Definition message.h:241
DBus::SignalMessage::member
const char * member() const
Definition message.cpp:544
DBus::SignalMessage::path
const char * path() const
Definition message.cpp:554
DBus::Tag
Definition object.h:101
connection_p.h
debug.h
internalerror.h
message_p.h
DBus
Definition connection_p.h:42
DBus::ObjectAdaptorPList
std::list< ObjectAdaptor * > ObjectAdaptorPList
Definition object.h:113
DBus::debug_log
DXXAPI LogFunction debug_log
Definition debug.cpp:55
DBus::ObjectPathList
std::list< std::string > ObjectPathList
Definition object.h:114
_vtable
static DBusObjectPathVTable _vtable
Definition object.cpp:65
ObjectAdaptorTable
std::map< Path, ObjectAdaptor * > ObjectAdaptorTable
Definition object.cpp:102
_adaptor_table
static ObjectAdaptorTable _adaptor_table
Definition object.cpp:103
object.h
server_p.h
DBus::ErrorInvalidArgs
Definition error.h:187
DBus::ErrorNoMemory
Definition error.h:82
DBus::Message::Private
Definition message_p.h:41
DBus::Path
Definition types.h:42
DBus::ObjectAdaptor::Private
Definition object.cpp:60
DBus::ObjectAdaptor::Private::unregister_function_stub
static void unregister_function_stub(DBusConnection *, void *)
Definition object.cpp:72
DBus::ObjectAdaptor::Private::message_function_stub
static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *)
Definition object.cpp:77
ReturnLaterError
Definition object.cpp:199
ReturnLaterError::tag
const Tag * tag
Definition object.cpp:200