00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <dbus-c++/debug.h>
00029 #include <dbus-c++/object.h>
00030 #include "internalerror.h"
00031
00032 #include <cstring>
00033 #include <map>
00034 #include <dbus/dbus.h>
00035
00036 #include "message_p.h"
00037 #include "server_p.h"
00038 #include "connection_p.h"
00039
00040 using namespace DBus;
00041
00042 Object::Object(Connection &conn, const Path &path, const char *service)
00043 : _conn(conn), _path(path), _service(service ? service : ""), _default_timeout(-1)
00044 {
00045 }
00046
00047 Object::~Object()
00048 {
00049 }
00050
00051 void Object::set_timeout(int new_timeout)
00052 {
00053 debug_log("%s: %d millies", __PRETTY_FUNCTION__, new_timeout);
00054 if (new_timeout < 0 && new_timeout != -1)
00055 throw ErrorInvalidArgs("Bad timeout, cannot set it");
00056 _default_timeout = new_timeout;
00057 }
00058
00059 struct ObjectAdaptor::Private
00060 {
00061 static void unregister_function_stub(DBusConnection *, void *);
00062 static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *);
00063 };
00064
00065 static DBusObjectPathVTable _vtable =
00066 {
00067 ObjectAdaptor::Private::unregister_function_stub,
00068 ObjectAdaptor::Private::message_function_stub,
00069 NULL, NULL, NULL, NULL
00070 };
00071
00072 void ObjectAdaptor::Private::unregister_function_stub(DBusConnection *conn, void *data)
00073 {
00074
00075 }
00076
00077 DBusHandlerResult ObjectAdaptor::Private::message_function_stub(DBusConnection *, DBusMessage *dmsg, void *data)
00078 {
00079 ObjectAdaptor *o = static_cast<ObjectAdaptor *>(data);
00080
00081 if (o)
00082 {
00083 Message msg(new Message::Private(dmsg));
00084
00085 debug_log("in object %s", o->path().c_str());
00086 debug_log(" got message #%d from %s to %s",
00087 msg.serial(),
00088 msg.sender(),
00089 msg.destination()
00090 );
00091
00092 return o->handle_message(msg)
00093 ? DBUS_HANDLER_RESULT_HANDLED
00094 : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00095 }
00096 else
00097 {
00098 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00099 }
00100 }
00101
00102 typedef std::map<Path, ObjectAdaptor *> ObjectAdaptorTable;
00103 static ObjectAdaptorTable _adaptor_table;
00104
00105 ObjectAdaptor *ObjectAdaptor::from_path(const Path &path)
00106 {
00107 ObjectAdaptorTable::iterator ati = _adaptor_table.find(path);
00108
00109 if (ati != _adaptor_table.end())
00110 return ati->second;
00111
00112 return NULL;
00113 }
00114
00115 ObjectAdaptorPList ObjectAdaptor::from_path_prefix(const std::string &prefix)
00116 {
00117 ObjectAdaptorPList ali;
00118
00119 ObjectAdaptorTable::iterator ati = _adaptor_table.begin();
00120
00121 size_t plen = prefix.length();
00122
00123 while (ati != _adaptor_table.end())
00124 {
00125 if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
00126 ali.push_back(ati->second);
00127
00128 ++ati;
00129 }
00130
00131 return ali;
00132 }
00133
00134 ObjectPathList ObjectAdaptor::child_nodes_from_prefix(const std::string &prefix)
00135 {
00136 ObjectPathList ali;
00137
00138 ObjectAdaptorTable::iterator ati = _adaptor_table.begin();
00139
00140 size_t plen = prefix.length();
00141
00142 while (ati != _adaptor_table.end())
00143 {
00144 if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
00145 {
00146 std::string p = ati->second->path().substr(plen);
00147 p = p.substr(0, p.find('/'));
00148 ali.push_back(p);
00149 }
00150 ++ati;
00151 }
00152
00153 ali.sort();
00154 ali.unique();
00155
00156 return ali;
00157 }
00158
00159 ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path)
00160 : Object(conn, path, conn.unique_name())
00161 {
00162 register_obj();
00163 }
00164
00165 ObjectAdaptor::~ObjectAdaptor()
00166 {
00167 unregister_obj(false);
00168 }
00169
00170 void ObjectAdaptor::register_obj()
00171 {
00172 debug_log("registering local object %s", path().c_str());
00173
00174 if (!dbus_connection_register_object_path(conn()._pvt->conn, path().c_str(), &_vtable, this))
00175 {
00176 throw ErrorNoMemory("unable to register object path");
00177 }
00178
00179 _adaptor_table[path()] = this;
00180 }
00181
00182 void ObjectAdaptor::unregister_obj(bool)
00183 {
00184 _adaptor_table.erase(path());
00185
00186 debug_log("unregistering local object %s", path().c_str());
00187
00188 dbus_connection_unregister_object_path(conn()._pvt->conn, path().c_str());
00189 }
00190
00191 void ObjectAdaptor::_emit_signal(SignalMessage &sig)
00192 {
00193 sig.path(path().c_str());
00194
00195 conn().send(sig);
00196 }
00197
00198 struct ReturnLaterError
00199 {
00200 const Tag *tag;
00201 };
00202
00203 bool ObjectAdaptor::handle_message(const Message &msg)
00204 {
00205 switch (msg.type())
00206 {
00207 case DBUS_MESSAGE_TYPE_METHOD_CALL:
00208 {
00209 const CallMessage &cmsg = reinterpret_cast<const CallMessage &>(msg);
00210 const char *member = cmsg.member();
00211 const char *interface = cmsg.interface();
00212
00213 debug_log(" invoking method %s.%s", interface, member);
00214
00215 InterfaceAdaptor *ii = find_interface(interface);
00216 if (ii)
00217 {
00218 try
00219 {
00220 Message ret = ii->dispatch_method(cmsg);
00221 conn().send(ret);
00222 }
00223 catch (Error &e)
00224 {
00225 ErrorMessage em(cmsg, e.name(), e.message());
00226 conn().send(em);
00227 }
00228 catch (ReturnLaterError &rle)
00229 {
00230 _continuations[rle.tag] = new Continuation(conn(), cmsg, rle.tag);
00231 }
00232 return true;
00233 }
00234 else
00235 {
00236 return false;
00237 }
00238 }
00239 default:
00240 {
00241 return false;
00242 }
00243 }
00244 }
00245
00246 void ObjectAdaptor::return_later(const Tag *tag)
00247 {
00248 ReturnLaterError rle = { tag };
00249 throw rle;
00250 }
00251
00252 void ObjectAdaptor::return_now(Continuation *ret)
00253 {
00254 ret->_conn.send(ret->_return);
00255
00256 ContinuationMap::iterator di = _continuations.find(ret->_tag);
00257
00258 delete di->second;
00259
00260 _continuations.erase(di);
00261 }
00262
00263 void ObjectAdaptor::return_error(Continuation *ret, const Error error)
00264 {
00265 ret->_conn.send(ErrorMessage(ret->_call, error.name(), error.message()));
00266
00267 ContinuationMap::iterator di = _continuations.find(ret->_tag);
00268
00269 delete di->second;
00270
00271 _continuations.erase(di);
00272 }
00273
00274 ObjectAdaptor::Continuation *ObjectAdaptor::find_continuation(const Tag *tag)
00275 {
00276 ContinuationMap::iterator di = _continuations.find(tag);
00277
00278 return di != _continuations.end() ? di->second : NULL;
00279 }
00280
00281 ObjectAdaptor::Continuation::Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
00282 : _conn(conn), _call(call), _return(_call), _tag(tag)
00283 {
00284 _writer = _return.writer();
00285 }
00286
00287
00288
00289
00290 ObjectProxy::ObjectProxy(Connection &conn, const Path &path, const char *service)
00291 : Object(conn, path, service)
00292 {
00293 register_obj();
00294 }
00295
00296 ObjectProxy::~ObjectProxy()
00297 {
00298 unregister_obj(false);
00299 }
00300
00301 void ObjectProxy::register_obj()
00302 {
00303 debug_log("registering remote object %s", path().c_str());
00304
00305 _filtered = new Callback<ObjectProxy, bool, const Message &>(this, &ObjectProxy::handle_message);
00306
00307 conn().add_filter(_filtered);
00308
00309 InterfaceProxyTable::const_iterator ii = _interfaces.begin();
00310 while (ii != _interfaces.end())
00311 {
00312 std::string im = "type='signal',interface='" + ii->first + "',path='" + path() + "'";
00313 conn().add_match(im.c_str());
00314 ++ii;
00315 }
00316 }
00317
00318 void ObjectProxy::unregister_obj(bool throw_on_error)
00319 {
00320 debug_log("unregistering remote object %s", path().c_str());
00321
00322 InterfaceProxyTable::const_iterator ii = _interfaces.begin();
00323 while (ii != _interfaces.end())
00324 {
00325 std::string im = "type='signal',interface='" + ii->first + "',path='" + path() + "'";
00326 conn().remove_match(im.c_str(), throw_on_error);
00327 ++ii;
00328 }
00329 conn().remove_filter(_filtered);
00330 }
00331
00332 Message ObjectProxy::_invoke_method(CallMessage &call)
00333 {
00334 if (call.path() == NULL)
00335 call.path(path().c_str());
00336
00337 if (call.destination() == NULL)
00338 call.destination(service().c_str());
00339
00340 return conn().send_blocking(call, get_timeout());
00341 }
00342
00343 bool ObjectProxy::_invoke_method_noreply(CallMessage &call)
00344 {
00345 if (call.path() == NULL)
00346 call.path(path().c_str());
00347
00348 if (call.destination() == NULL)
00349 call.destination(service().c_str());
00350
00351 return conn().send(call);
00352 }
00353
00354 bool ObjectProxy::handle_message(const Message &msg)
00355 {
00356 switch (msg.type())
00357 {
00358 case DBUS_MESSAGE_TYPE_SIGNAL:
00359 {
00360 const SignalMessage &smsg = reinterpret_cast<const SignalMessage &>(msg);
00361 const char *interface = smsg.interface();
00362 const char *member = smsg.member();
00363 const char *objpath = smsg.path();
00364
00365 if (objpath != path()) return false;
00366
00367 debug_log("filtered signal %s(in %s) from %s to object %s",
00368 member, interface, msg.sender(), objpath);
00369
00370 InterfaceProxy *ii = find_interface(interface);
00371 if (ii)
00372 {
00373 return ii->dispatch_signal(smsg);
00374 }
00375 else
00376 {
00377 return false;
00378 }
00379 }
00380 default:
00381 {
00382 return false;
00383 }
00384 }
00385 }