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 
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 
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 {
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 
77 DBusHandlerResult 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;
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 
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 
291  : Object(conn, path, service)
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 
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  }
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 }
const char * destination() const
Definition: message.cpp:452
const char * sender() const
Definition: message.cpp:442
void remove_filter(MessageSlot &s)
Removes a previously-added message filter.
Definition: connection.cpp:359
void register_obj()
Definition: object.cpp:301
void return_error(Continuation *ret, const Error error)
Definition: object.cpp:263
Message _invoke_method(CallMessage &)
Definition: object.cpp:332
const char * name() const
Definition: error.cpp:65
InterfaceAdaptor * find_interface(const std::string &name)
Definition: interface.cpp:42
void unregister_obj(bool throw_on_error=true)
Definition: object.cpp:318
static DBusObjectPathVTable _vtable
Definition: object.cpp:65
void add_match(const char *rule)
Adds a match rule to match messages going through the message bus.
Definition: connection.cpp:322
void return_now(Continuation *ret)
Definition: object.cpp:252
Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
Definition: object.cpp:281
const char * path() const
Definition: message.cpp:608
bool handle_message(const Message &)
Definition: object.cpp:203
void set_timeout(int new_timeout=-1)
Definition: object.cpp:51
Object(Connection &conn, const Path &path, const char *service)
Definition: object.cpp:42
ContinuationMap _continuations
Definition: object.h:175
Connection & conn()
Definition: object.h:77
void return_later(const Tag *tag)
Definition: object.cpp:246
int type() const
Definition: message.cpp:422
bool add_filter(MessageSlot &s)
Adds a message filter.
Definition: connection.cpp:353
static void unregister_function_stub(DBusConnection *, void *)
Definition: object.cpp:72
void _emit_signal(SignalMessage &)
Definition: object.cpp:191
const Tag * tag
Definition: object.cpp:200
virtual ~Object()
Definition: object.cpp:47
int get_timeout() const
Definition: object.h:92
int serial() const
Definition: message.cpp:427
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:333
bool dispatch_signal(const SignalMessage &)
Definition: interface.cpp:131
static ObjectAdaptorTable _adaptor_table
Definition: object.cpp:103
bool _invoke_method_noreply(CallMessage &call)
Definition: object.cpp:343
static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *)
Definition: object.cpp:77
Continuation * find_continuation(const Tag *tag)
Definition: object.cpp:274
const char * member() const
Definition: message.cpp:598
InterfaceProxy * find_interface(const std::string &name)
Definition: interface.cpp:116
std::map< Path, ObjectAdaptor * > ObjectAdaptorTable
Definition: object.cpp:102
DXXAPI LogFunction debug_log
Definition: debug.cpp:55
MessageSlot _filtered
Definition: object.h:225
bool handle_message(const Message &)
Definition: object.cpp:354
const char * member() const
Definition: message.cpp:543
DBusConnection * conn
Definition: connection_p.h:46
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:370
const std::string & service() const
Definition: object.h:87
MessageIter writer()
Definition: message.cpp:472
std::list< std::string > ObjectPathList
Definition: object.h:114
InterfaceProxyTable _interfaces
Definition: interface.h:102
const DBus::Path & path() const
Definition: object.h:82
Message dispatch_method(const CallMessage &)
Definition: interface.cpp:57
int _default_timeout
Definition: object.h:71
bool send(const Message &msg, unsigned int *serial=NULL)
Adds a message to the outgoing message queue.
Definition: connection.cpp:365
void unregister_obj(bool throw_on_error=true)
Definition: object.cpp:182
const char * path() const
Definition: message.cpp:553
const char * message() const
Definition: error.cpp:70
std::list< ObjectAdaptor * > ObjectAdaptorPList
Definition: object.h:111
ObjectProxy(Connection &conn, const Path &path, const char *service="")
Definition: object.cpp:290