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
46
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
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
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
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
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
160 : Object(conn, path, conn.unique_name())
161{
162 register_obj();
163}
164
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 InterfaceAdaptor *ii = NULL;
213
214 debug_log(" invoking method %s.%s", interface, member);
215
216 if (interface)
217 ii = find_interface(interface);
218 else
219 ii = NULL;
220
221 if (ii)
222 {
223 try
224 {
225 Message ret = ii->dispatch_method(cmsg);
226 conn().send(ret);
227 }
228 catch (Error &e)
229 {
230 ErrorMessage em(cmsg, e.name(), e.message());
231 conn().send(em);
232 }
233 catch (ReturnLaterError &rle)
234 {
235 _continuations[rle.tag] = new Continuation(conn(), cmsg, rle.tag);
236 }
237 return true;
238 }
239 else
240 {
241 return false;
242 }
243 }
244 default:
245 {
246 return false;
247 }
248 }
249}
250
252{
253 ReturnLaterError rle = { tag };
254 throw rle;
255}
256
258{
259 ret->_conn.send(ret->_return);
260
261 ContinuationMap::iterator di = _continuations.find(ret->_tag);
262
263 delete di->second;
264
265 _continuations.erase(di);
266}
267
269{
270 ret->_conn.send(ErrorMessage(ret->_call, error.name(), error.message()));
271
272 ContinuationMap::iterator di = _continuations.find(ret->_tag);
273
274 delete di->second;
275
276 _continuations.erase(di);
277}
278
280{
281 ContinuationMap::iterator di = _continuations.find(tag);
282
283 return di != _continuations.end() ? di->second : NULL;
284}
285
287 : _conn(conn), _call(call), _return(_call), _tag(tag)
288{
289 _writer = _return.writer(); //todo: verify
290}
291
292/*
293*/
294
297{
298 register_obj();
299}
300
305
307{
308 debug_log("registering remote object %s", path().c_str());
309
311
313
314 InterfaceProxyTable::const_iterator ii = _interfaces.begin();
315 while (ii != _interfaces.end())
316 {
317 std::string im = "type='signal',interface='" + ii->first + "',path='" + path() + "'";
318 conn().add_match(im.c_str());
319 ++ii;
320 }
321}
322
323void ObjectProxy::unregister_obj(bool throw_on_error)
324{
325 debug_log("unregistering remote object %s", path().c_str());
326
327 InterfaceProxyTable::const_iterator ii = _interfaces.begin();
328 while (ii != _interfaces.end())
329 {
330 std::string im = "type='signal',interface='" + ii->first + "',path='" + path() + "'";
331 conn().remove_match(im.c_str(), throw_on_error);
332 ++ii;
333 }
335}
336
338{
339 if (call.path() == NULL)
340 call.path(path().c_str());
341
342 if (call.destination() == NULL)
343 call.destination(service().c_str());
344
345 return conn().send_blocking(call, get_timeout());
346}
347
349{
350 if (call.path() == NULL)
351 call.path(path().c_str());
352
353 if (call.destination() == NULL)
354 call.destination(service().c_str());
355
356 return conn().send(call);
357}
358
360{
361 switch (msg.type())
362 {
363 case DBUS_MESSAGE_TYPE_SIGNAL:
364 {
365 const SignalMessage &smsg = reinterpret_cast<const SignalMessage &>(msg);
366 const char *interface = smsg.interface();
367 const char *member = smsg.member();
368 const char *objpath = smsg.path();
369
370 if (objpath != path()) return false;
371
372 debug_log("filtered signal %s(in %s) from %s to object %s",
373 member, interface, msg.sender(), objpath);
374
375 InterfaceProxy *ii = find_interface(interface);
376 if (ii)
377 {
378 return ii->dispatch_signal(smsg);
379 }
380 else
381 {
382 return false;
383 }
384 }
385 default:
386 {
387 return false;
388 }
389 }
390}
InterfaceAdaptor * find_interface(const std::string &name)
Definition interface.cpp:42
const char * member() const
Definition message.cpp:602
const char * path() const
Definition message.cpp:612
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...
Message send_blocking(Message &msg, int timeout=-1)
Sends a message and blocks a certain time period while waiting for a reply.
bool add_filter(MessageSlot &s)
Adds a message filter.
void remove_filter(MessageSlot &s)
Removes a previously-added message filter.
void add_match(const char *rule)
Adds a match rule to match messages going through the message bus.
bool send(const Message &msg, unsigned int *serial=NULL)
Adds a message to the outgoing message queue.
const char * name() const
Definition error.cpp:65
const char * message() const
Definition error.cpp:70
bool dispatch_signal(const SignalMessage &)
const char * destination() const
Definition message.cpp:456
const char * sender() const
Definition message.cpp:446
int type() const
Definition message.cpp:426
int serial() const
Definition message.cpp:431
Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
Definition object.cpp:286
static ObjectAdaptorPList from_path_prefix(const std::string &prefix)
Definition object.cpp:115
bool handle_message(const Message &)
Definition object.cpp:203
static ObjectPathList child_nodes_from_prefix(const std::string &prefix)
Definition object.cpp:134
static ObjectAdaptor * from_path(const Path &path)
Definition object.cpp:105
void return_now(Continuation *ret)
Definition object.cpp:257
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:251
Continuation * find_continuation(const Tag *tag)
Definition object.cpp:279
ObjectAdaptor(Connection &conn, const Path &path)
Definition object.cpp:159
void _emit_signal(SignalMessage &)
Definition object.cpp:191
void return_error(Continuation *ret, const Error error)
Definition object.cpp:268
bool _invoke_method_noreply(CallMessage &call)
Definition object.cpp:348
Message _invoke_method(CallMessage &)
Definition object.cpp:337
MessageSlot _filtered
Definition object.h:225
bool handle_message(const Message &)
Definition object.cpp:359
ObjectProxy(Connection &conn, const Path &path, const char *service="")
Definition object.cpp:295
void unregister_obj(bool throw_on_error=true)
Definition object.cpp:323
void register_obj()
Definition object.cpp:306
Connection _conn
Definition object.h:68
int _default_timeout
Definition object.h:71
const DBus::Path & path() const
Definition object.h:82
Object(Connection &conn, const Path &path, const char *service)
Definition object.cpp:42
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
DBus::Path _path
Definition object.h:69
std::string _service
Definition object.h:70
virtual ~Object()
Definition object.cpp:47
InterfaceProxy * find_interface(const std::string &name)
InterfaceProxyTable _interfaces
Definition interface.h:102
const char * member() const
Definition message.cpp:547
const char * path() const
Definition message.cpp:557
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
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