1 #include "automotivemanager.h"
2 #include "abstractdbusinterface.h"
3 #include "listplusplus.h"
5 static const gchar introspection_xml[] =
7 " <interface name='org.automotive.Manager'>"
8 " <method name='FindObject'>"
9 " <arg type='s' name='searchstring' direction='in'/>"
10 " <arg type='ao' name='response' direction='out'/>"
12 " <method name='FindObjectForZone'>"
13 " <arg type='s' name='searchstring' direction='in'/>"
14 " <arg type='i' name='zone' direction='in'/>"
15 " <arg type='o' name='response' direction='out'/>"
17 " <method name='FindObjectForSourceZone'>"
18 " <arg type='s' name='searchstring' direction='in'/>"
19 " <arg type='s' name='source' direction='in'/>"
20 " <arg type='i' name='zone' direction='in'/>"
21 " <arg type='o' name='response' direction='out'/>"
23 " <method name='List'>"
24 " <arg type='as' name='response' direction='out'/>"
26 " <method name='ZonesForObjectName'>"
27 " <arg type='s' name='searchstring' direction='in'/>"
28 " <arg type='ai' name='response' direction='out'/>"
30 " <method name='SourcesForObjectName'>"
31 " <arg type='s' name='searchstring' direction='in'/>"
32 " <arg type='as' name='response' direction='out'/>"
34 " <method name='SupportsProperty'>"
35 " <arg type='s' name='objectName' direction='in'/>"
36 " <arg type='s' name='propertyName' direction='in'/>"
37 " <arg type='b' name='response' direction='out'/>"
42 static void handleMethodCall(GDBusConnection *connection,
44 const gchar *object_path,
45 const gchar *interface_name,
46 const gchar *method_name,
48 GDBusMethodInvocation *invocation,
52 AutomotiveManager* manager = static_cast<AutomotiveManager*>(user_data);
54 std::string method = method_name;
56 uint pid = getPid(sender);
58 if(DebugOut::getDebugThreshhold() >= 6)
60 DebugOut(6)<<"DBus method call from: "<<sender<< " pid: " <<pid<< " interface: "<<interface_name<<" method: "<<method<<endl;
61 DebugOut(6)<<"DBus method call path: "<<object_path<<endl;
64 if(method == "FindObject")
68 g_variant_get(parameters,"(s)",&arg);
70 std::string objectToFind = arg;
72 if(objectToFind == "")
74 g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
78 std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(objectToFind);
80 if(!interfaces.size())
82 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Object not found");
86 GVariantBuilder params;
87 g_variant_builder_init(¶ms, G_VARIANT_TYPE_ARRAY);
89 bool hasItems = false;
91 for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
93 AbstractDBusInterface* t = *itr;
99 if(!t->isRegistered())
102 std::list<std::string> processes = manager->subscribedProcesses[t];
104 if(!contains(processes,sender))
106 DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
107 manager->subscribedProcesses[t].push_back(sender);
110 GVariant *newvar = g_variant_new("o",t->objectPath().c_str());
111 g_variant_builder_add_value(¶ms, newvar);
115 g_dbus_method_invocation_return_value(invocation, g_variant_new("(ao)",¶ms));
117 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
121 else if(method == "FindObjectForZone")
126 g_variant_get(parameters,"(si)", &arg, &zone);
128 std::string propertyToFind = arg;
130 if(propertyToFind == "")
132 g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
136 std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
138 if(!interfaces.size())
140 g_dbus_method_invocation_return_dbus_error(invocation, "org.automotive.Manager.ObjectNotFound", "Property not found");
146 for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
148 AbstractDBusInterface* t = *itr;
150 if(t->zone() == (Zone::Type)zone)
152 if(!t->isRegistered())
155 std::list<std::string> processes = manager->subscribedProcesses[t];
157 if(!contains(processes,sender))
159 DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
160 manager->subscribedProcesses[t].push_back(sender);
163 g_dbus_method_invocation_return_value(invocation,g_variant_new("(o)", t->objectPath().c_str()));
168 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.InvalidZone", "zone not found");
171 else if (method == "ZonesForObjectName")
175 g_variant_get(parameters,"(s)",&arg);
177 std::string propertyToFind = arg;
179 if(propertyToFind == "")
181 g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
185 std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
187 if(!interfaces.size())
189 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
193 GVariantBuilder params;
194 g_variant_builder_init(¶ms, G_VARIANT_TYPE_ARRAY);
196 for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
198 AbstractDBusInterface* t = *itr;
199 GVariant *newvar = g_variant_new("i",t->zone());
200 g_variant_builder_add_value(¶ms, newvar);
204 g_dbus_method_invocation_return_value(invocation,g_variant_new("(ai)",¶ms));
207 else if(method == "List")
209 std::vector<std::string> supportedProperties = AbstractDBusInterface::supportedInterfaces();
211 if(!supportedProperties.size())
213 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.Error", "No supported objects");
217 std::sort(supportedProperties.begin(), supportedProperties.end());
218 auto itr = std::unique(supportedProperties.begin(), supportedProperties.end());
220 supportedProperties.erase(itr, supportedProperties.end());
222 GVariantBuilder builder;
223 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
225 for(auto objectName : supportedProperties)
227 g_variant_builder_add(&builder, "s", objectName.c_str());
230 g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",&builder));
232 else if(method == "SourcesForObjectName")
236 g_variant_get(parameters,"(s)",&arg);
238 std::string propertyToFind = arg;
240 if(propertyToFind == "")
242 g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
246 std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
248 if(!interfaces.size())
250 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
254 GVariantBuilder params;
255 g_variant_builder_init(¶ms, G_VARIANT_TYPE_ARRAY);
257 for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
259 AbstractDBusInterface* t = *itr;
260 string source = t->source();
261 boost::algorithm::erase_all(source, "-");
262 GVariant *newvar = g_variant_new("s", source.c_str());
263 g_variant_builder_add_value(¶ms, newvar);
267 g_dbus_method_invocation_return_value(invocation,g_variant_new("(as)",¶ms));
269 else if(method == "FindObjectForSourceZone")
275 g_variant_get(parameters,"(ssi)", &arg, &arg2, &zone);
277 std::string propertyToFind = arg;
278 std::string source = arg2;
280 if(propertyToFind == "" || source == "")
282 g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR,G_DBUS_ERROR_INVALID_ARGS, "Invalid argument.");
286 std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(propertyToFind);
288 if(!interfaces.size())
290 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
294 for(auto itr = interfaces.begin(); itr != interfaces.end(); itr++)
296 AbstractDBusInterface* t = *itr;
297 string targetSource = t->source();
298 boost::algorithm::erase_all(targetSource, "-");
299 if(t->zone() == (Zone::Type)zone && source == targetSource)
301 if(!t->isRegistered())
304 std::list<std::string> processes = manager->subscribedProcesses[t];
306 if(!contains(processes,sender))
308 DebugOut()<<"Referencing "<<t->objectPath()<<" with sender: "<<sender<<endl;
309 manager->subscribedProcesses[t].push_back(sender);
312 g_dbus_method_invocation_return_value(invocation,g_variant_new("(o)", t->objectPath().c_str()));
317 g_dbus_method_invocation_return_dbus_error(invocation,"org.automotive.Manager.ObjectNotFound", "Property not found");
319 else if(method == "SupportsProperty")
322 gchar* propertyToFindStr;
324 g_variant_get(parameters,"(ss)",&objectName, &propertyToFindStr);
326 auto objectNamePtr = amb::make_super(objectName);
327 auto propertyToFindStrPtr = amb::make_super(propertyToFindStr);
329 DebugOut(6) << "Checking " << objectNamePtr.get() << " for member: " << propertyToFindStrPtr.get() << endl;
331 std::list<AbstractDBusInterface*> interfaces = AbstractDBusInterface::getObjectsForProperty(objectNamePtr.get());
333 for(auto i : interfaces)
335 if(i->hasPropertyDBus(propertyToFindStrPtr.get()))
337 DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was found!!" << endl;
338 g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", true));
342 DebugOut(6) << "member " << propertyToFindStrPtr.get() << " of " << objectNamePtr.get() << " was not found." << endl;
343 g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", false));
347 g_dbus_method_invocation_return_error(invocation,G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Unknown method.");
351 static void signalCallback( GDBusConnection *connection,
352 const gchar *sender_name,
353 const gchar *object_path,
354 const gchar *interface_name,
355 const gchar *signal_name,
356 GVariant *parameters,
359 AutomotiveManager* manager = static_cast<AutomotiveManager*>(user_data);
363 DebugOut(DebugOut::Error)<<"Bad user_data"<<endl;
368 gchar* newOwner=nullptr;
369 gchar* oldOwner = nullptr;
370 g_variant_get(parameters,"(sss)",&name, &oldOwner, &newOwner);
372 std::list<AbstractDBusInterface*> toRemove;
374 if(std::string(newOwner) == "")
376 for(auto &i : manager->subscribedProcesses)
378 AbstractDBusInterface* iface = i.first;
380 for(auto itr = i.second.begin(); itr != i.second.end(); itr++)
382 std::string n = *itr;
385 DebugOut()<<"unreferencing "<<n<<" from the subscription of "<<iface->objectPath()<<endl;
386 itr = manager->subscribedProcesses[iface].erase(itr);
387 DebugOut()<<"new ref count: "<<manager->subscribedProcesses[iface].size()<<endl;
391 if(manager->subscribedProcesses[iface].empty())
393 DebugOut()<<"No more subscribers. Unregistering: "<<iface->objectPath()<<endl;
394 ///Defer removal to not screw up the list
395 toRemove.push_back(iface);
396 iface->unregisterObject();
400 for(auto & i : toRemove)
402 manager->subscribedProcesses.erase(i);
411 static GVariant* getProperty(GDBusConnection* connection, const gchar* sender, const gchar* objectPath, const gchar* interfaceName, const gchar* propertyName, GError** error, gpointer userData)
416 static gboolean setProperty(GDBusConnection * connection, const gchar * sender, const gchar *objectPath,
417 const gchar *interfaceName, const gchar * propertyName, GVariant *value,
418 GError** error, gpointer userData)
423 static const GDBusInterfaceVTable interfaceVTable =
430 AutomotiveManager::AutomotiveManager(GDBusConnection *connection)
431 :mConnection(connection)
433 GError* error = NULL;
435 GDBusNodeInfo* introspection = g_dbus_node_info_new_for_xml(introspection_xml, &error);
436 GDBusInterfaceInfo* mInterfaceInfo = g_dbus_node_info_lookup_interface(introspection, "org.automotive.Manager");
438 regId = g_dbus_connection_register_object(mConnection, "/", mInterfaceInfo, &interfaceVTable, this, NULL, &error);
439 g_dbus_node_info_unref(introspection);
441 auto errorPtr = amb::make_super(error);
444 DebugOut(DebugOut::Error) << "registering dbus object: " << "'org.automotive.Manager' " << errorPtr->message << endl;
450 g_dbus_connection_signal_subscribe(mConnection, "org.freedesktop.DBus", "org.freedesktop.DBus",
451 "NameOwnerChanged", "/org/freedesktop/DBus", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
452 signalCallback, this, NULL);
455 AutomotiveManager::~AutomotiveManager()
457 g_dbus_connection_unregister_object(mConnection, regId);