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