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
40using namespace DBus;
41
42Object::Object(Connection &conn, const Path &path, const char *service)
43 : _conn(conn), _path(path), _service(service ? service : ""), _default_timeout(-1)
44{
45}
46
48{
49}
50
51void 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
60{
61 static void unregister_function_stub(DBusConnection *, void *);
62 static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *);
63};
64
65static DBusObjectPathVTable _vtable =
66{
69 NULL, NULL, NULL, NULL
70};
71
72void 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
102typedef std::map<Path, ObjectAdaptor *> ObjectAdaptorTable;
104
105ObjectAdaptor *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
115ObjectAdaptorPList ObjectAdaptor::from_path_prefix(const std::string &prefix)
116{
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
134ObjectPathList 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
159ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path)
160 : Object(conn, path, conn.unique_name())
161{
162 register_obj();
163}
164
166{
167 unregister_obj(false);
168}
169
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
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
192{
193 sig.path(path().c_str());
194
195 conn().send(sig);
196}
197
199{
200 const Tag *tag;
201};
202
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
247{
248 ReturnLaterError rle = { tag };
249 throw rle;
250}
251
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
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
275{
276 ContinuationMap::iterator di = _continuations.find(tag);
277
278 return di != _continuations.end() ? di->second : NULL;
279}
280
282 : _conn(conn), _call(call), _return(_call), _tag(tag)
283{
284 _writer = _return.writer(); //todo: verify
285}
286
287/*
288*/
289
292{
293 register_obj();
294}
295
297{
298 unregister_obj(false);
299}
300
302{
303 debug_log("registering remote object %s", path().c_str());
304
306
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
318void 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 }
330}
331
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
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
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}
InterfaceAdaptor * find_interface(const std::string &name)
Definition: interface.cpp:42
const char * member() const
Definition: message.cpp:599
const char * path() const
Definition: message.cpp:609
const char * name() const
Definition: error.cpp:65
const char * message() const
Definition: error.cpp:70
Message dispatch_method(const CallMessage &)
Definition: interface.cpp:57
bool dispatch_signal(const SignalMessage &)
Definition: interface.cpp:131
Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
Definition: object.cpp:281
bool handle_message(const Message &)
Definition: object.cpp:203
void return_now(Continuation *ret)
Definition: object.cpp:252
void unregister_obj(bool throw_on_error=true)
Definition: object.cpp:182
ContinuationMap _continuations
Definition: object.h:175
void return_later(const Tag *tag)
Definition: object.cpp:246
Continuation * find_continuation(const Tag *tag)
Definition: object.cpp:274
void _emit_signal(SignalMessage &)
Definition: object.cpp:191
void return_error(Continuation *ret, const Error error)
Definition: object.cpp:263
bool _invoke_method_noreply(CallMessage &call)
Definition: object.cpp:343
Message _invoke_method(CallMessage &)
Definition: object.cpp:332
MessageSlot _filtered
Definition: object.h:225
bool handle_message(const Message &)
Definition: object.cpp:354
ObjectProxy(Connection &conn, const Path &path, const char *service="")
Definition: object.cpp:290
void unregister_obj(bool throw_on_error=true)
Definition: object.cpp:318
void register_obj()
Definition: object.cpp:301
int _default_timeout
Definition: object.h:71
const DBus::Path & path() const
Definition: object.h:82
int get_timeout() const
Definition: object.h:92
const std::string & service() const
Definition: object.h:87
void set_timeout(int new_timeout=-1)
Definition: object.cpp:51
Connection & conn()
Definition: object.h:77
virtual ~Object()
Definition: object.cpp:47
InterfaceProxy * find_interface(const std::string &name)
Definition: interface.cpp:116
InterfaceProxyTable _interfaces
Definition: interface.h:102
const char * member() const
Definition: message.cpp:544
const char * path() const
Definition: message.cpp:554
std::list< ObjectAdaptor * > ObjectAdaptorPList
Definition: object.h:113
DXXAPI LogFunction debug_log
Definition: debug.cpp:55
std::list< std::string > ObjectPathList
Definition: object.h:114
static DBusObjectPathVTable _vtable
Definition: object.cpp:65
std::map< Path, ObjectAdaptor * > ObjectAdaptorTable
Definition: object.cpp:102
static ObjectAdaptorTable _adaptor_table
Definition: object.cpp:103
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
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
bool add_filter(MessageSlot &s)
Adds a message filter.
Definition: connection.cpp:352
void remove_filter(MessageSlot &s)
Removes a previously-added message filter.
Definition: connection.cpp:358
void add_match(const char *rule)
Adds a match rule to match messages going through the message bus.
Definition: connection.cpp:321
bool send(const Message &msg, unsigned int *serial=NULL)
Adds a message to the outgoing message queue.
Definition: connection.cpp:364
DBusConnection * conn
Definition: connection_p.h:46
MessageIter writer()
Definition: message.cpp:473
const char * destination() const
Definition: message.cpp:453
const char * sender() const
Definition: message.cpp:443
int type() const
Definition: message.cpp:423
int serial() const
Definition: message.cpp:428
static void unregister_function_stub(DBusConnection *, void *)
Definition: object.cpp:72
static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *)
Definition: object.cpp:77
const Tag * tag
Definition: object.cpp:200