[gupnp] Add Connman based Context Manager



commit b4fd0681711438221db91eb631d8462b1ef0f1c5
Author: Ludovic Ferrandis <ludovic ferrandis linux intel com>
Date:   Tue Mar 6 10:51:40 2012 +0100

    Add Connman based Context Manager
    
    Initial implementation
    
    https://bugzilla.gnome.org/show_bug.cgi?id=672998

 configure.ac                     |   11 +-
 libgupnp/Makefile.am             |    8 +
 libgupnp/gupnp-connman-manager.c |  774 ++++++++++++++++++++++++++++++++++++++
 libgupnp/gupnp-connman-manager.h |   74 ++++
 libgupnp/gupnp-context-manager.c |    6 +
 5 files changed, 871 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 6a39c8b..717202d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,7 +47,7 @@ case "$target_os" in
         ;;
 esac
 
-PKG_CHECK_MODULES(LIBGUPNP, glib-2.0 >= 2.24.0 \
+PKG_CHECK_MODULES(LIBGUPNP, glib-2.0 >= 2.28.0 \
                             gio-2.0 \
                             gmodule-2.0 \
                             gssdp-1.0 >= 0.11.2 \
@@ -59,7 +59,7 @@ PKG_CHECK_MODULES(GTHREAD, gthread-2.0)
 
 AC_ARG_WITH([context_manager],
             AS_HELP_STRING(
-                        [--with-context-manager=@<:@network-manager/unix/linux@:>@],
+                        [--with-context-manager=@<:@network-manager/connman/unix/linux@:>@],
                         [Context Manager backend to use]),,
             [with_context_manager="unix"])
 
@@ -69,6 +69,13 @@ AC_MSG_RESULT([${with_context_manager}])
 AM_CONDITIONAL([USE_NETWORK_MANAGER],
                [test "x$with_context_manager" = "xnetwork-manager"])
 
+AM_CONDITIONAL([USE_CONNMAN],
+               [test "x$with_context_manager" = "xconnman"])
+
+if test "x$with_context_manager" = "xconnman"; then
+        PKG_CHECK_MODULES(CONNMAN, connman >= 0.80)
+fi
+
 USE_NETLINK=no
 if test "x$with_context_manager" = "xlinux"; then
        dnl check for netlink (Linux)
diff --git a/libgupnp/Makefile.am b/libgupnp/Makefile.am
index 2ae468c..24e04e0 100644
--- a/libgupnp/Makefile.am
+++ b/libgupnp/Makefile.am
@@ -6,6 +6,12 @@ if USE_NETWORK_MANAGER
 CONTEXT_MANAGER_IMPL += gupnp-network-manager.c  \
 		        gupnp-network-manager.h
 CONTEXT_MANAGER_CFLAGS = -DUSE_NETWORK_MANAGER
+else
+if USE_CONNMAN
+CONTEXT_MANAGER_IMPL += gupnp-connman-manager.c  \
+			gupnp-connman-manager.h
+CONTEXT_MANAGER_CFLAGS = -DUSE_CONNMAN
+endif
 endif
 
 if USE_NETLINK
@@ -96,6 +102,8 @@ libgupnp_1_0_la_LIBADD = $(LIBGUPNP_LIBS) $(DBUS_GLIB_LIBS) $(LIBCONIC_LIBS)
 EXTRA_DIST = gupnp-marshal.list 	   \
 	     gupnp-network-manager.c   	   \
 	     gupnp-network-manager.h       \
+	     gupnp-connman-manager.c   	   \
+	     gupnp-connman-manager.h       \
 	     gupnp-linux-context-manager.c \
 	     gupnp-linux-context-manager.h \
 	     gupnp-unix-context-manager.c  \
diff --git a/libgupnp/gupnp-connman-manager.c b/libgupnp/gupnp-connman-manager.c
new file mode 100644
index 0000000..8b9952f
--- /dev/null
+++ b/libgupnp/gupnp-connman-manager.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Author: Ludovic Ferrandis <ludovic ferrandis intel com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:gupnp-connman-manager
+ * @short_description: Connman-based implementation of
+ * #GUPnPContextManager.
+ *
+ */
+
+#include "gupnp-connman-manager.h"
+#include "gupnp-context.h"
+#include "gupnp-marshal.h"
+
+typedef enum
+{
+        CM_SERVICE_STATE_ACTIVE   = 1,
+        CM_SERVICE_STATE_INACTIVE = 2
+
+} CMServiceState;
+
+typedef struct {
+        GUPnPConnmanManager *manager;
+        GUPnPContext        *context;
+        GDBusProxy          *proxy;
+        CMServiceState      current;
+        guint               sig_prop_id;
+        guint               port;
+        gchar               *iface;
+        gchar               *name;
+
+} CMService;
+
+struct _GUPnPConnmanManagerPrivate {
+        GDBusProxy *manager_proxy;
+        GSource    *idle_context_creation_src;
+        GHashTable *cm_services;
+        guint      sig_change_id;
+};
+
+#define CM_DBUS_CONNMAN_NAME      "net.connman"
+#define CM_DBUS_MANAGER_PATH      "/"
+#define CM_DBUS_MANAGER_INTERFACE "net.connman.Manager"
+#define CM_DBUS_SERVICE_INTERFACE "net.connman.Service"
+
+#define DBUS_SERVICE_DBUS   "org.freedesktop.DBus"
+#define DBUS_PATH_DBUS      "/org/freedesktop/DBus"
+#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
+
+#define LOOPBACK_IFACE "lo"
+
+G_DEFINE_TYPE (GUPnPConnmanManager,
+               gupnp_connman_manager,
+               GUPNP_TYPE_CONTEXT_MANAGER);
+
+static gboolean
+loopback_context_create (gpointer data)
+{
+        GUPnPConnmanManager *manager;
+        GUPnPContext        *context;
+        GError              *error = NULL;
+        guint               port;
+
+        manager = GUPNP_CONNMAN_MANAGER (data);
+        manager->priv->idle_context_creation_src = NULL;
+
+        g_object_get (manager, "port", &port, NULL);
+
+        context = g_initable_new (GUPNP_TYPE_CONTEXT,
+                                  NULL,
+                                  &error,
+                                  "interface", LOOPBACK_IFACE,
+                                  "port", port,
+                                  NULL);
+
+        if (error != NULL) {
+                g_warning ("Error creating GUPnP context: %s", error->message);
+                g_error_free (error);
+
+                return FALSE;
+        }
+
+        g_signal_emit_by_name (manager, "context-available", context);
+        g_object_unref (context);
+
+        return FALSE;
+}
+
+static gboolean
+service_context_create (CMService *cm_service)
+{
+        GError  *error = NULL;
+
+        cm_service->context = g_initable_new (GUPNP_TYPE_CONTEXT,
+                                              NULL,
+                                              &error,
+                                              "interface", cm_service->iface,
+                                              "network", cm_service->name,
+                                              "port", cm_service->port,
+                                              NULL);
+
+        if (error != NULL) {
+                g_warning ("Error creating GUPnP context: %s", error->message);
+                g_error_free (error);
+
+                return FALSE;
+        }
+
+        g_signal_emit_by_name (cm_service->manager,
+                               "context-available",
+                               cm_service->context);
+
+        return TRUE;
+}
+
+static void
+service_context_delete (CMService *cm_service)
+{
+        // For other states we just destroy the context
+        g_signal_emit_by_name (cm_service->manager,
+                               "context-unavailable",
+                               cm_service->context);
+
+        g_object_unref (cm_service->context);
+        cm_service->context = NULL;
+}
+
+static void
+service_context_update (CMService *cm_service, CMServiceState new_state)
+{
+        if (cm_service->current != new_state) {
+                if (new_state == CM_SERVICE_STATE_ACTIVE) {
+                        if (service_context_create (cm_service) == FALSE)
+                                new_state = CM_SERVICE_STATE_INACTIVE;
+
+                } else if ((new_state == CM_SERVICE_STATE_INACTIVE) &&
+                           (cm_service->context != NULL)) {
+                                service_context_delete (cm_service);
+                }
+
+                cm_service->current = new_state;
+        }
+}
+
+static void
+on_service_property_signal (GDBusConnection *connection,
+                            const gchar     *sender_name,
+                            const gchar     *object_path,
+                            const gchar     *interface_name,
+                            const gchar     *signal_name,
+                            GVariant        *parameters,
+                            gpointer        user_data)
+{
+        CMService      *cm_service;
+        GVariant       *value;
+        gchar          *name;
+        const gchar    *state_str;
+        CMServiceState new_state;
+
+        cm_service = (CMService *) user_data;
+        g_variant_get (parameters, "(&sv)", &name, &value);
+
+        if (g_strcmp0 (name, "Name") == 0) {
+                g_free (cm_service->name);
+                g_variant_get (value, "s", &cm_service->name);
+
+                if (cm_service->context != NULL)
+                        g_object_set (G_OBJECT (cm_service->context),
+                                               "network",
+                                               cm_service->name,
+                                               NULL);
+
+        } else if (g_strcmp0 (name, "Ethernet") == 0) {
+                g_free (cm_service->iface);
+                g_variant_lookup (value, "Interface", "s", &cm_service->iface);
+
+                if (cm_service->context != NULL)
+                        g_object_set (G_OBJECT (cm_service->context),
+                                               "interface",
+                                               cm_service->iface,
+                                               NULL);
+
+        } else if (g_strcmp0 (name, "State") == 0) {
+                state_str = g_variant_get_string (value, 0);
+
+                if ((g_strcmp0 (state_str, "online") == 0) ||
+                    (g_strcmp0 (state_str, "ready") == 0))
+                        new_state = CM_SERVICE_STATE_ACTIVE;
+                else
+                        new_state = CM_SERVICE_STATE_INACTIVE;
+
+                service_context_update (cm_service, new_state);
+        }
+
+        g_variant_unref (value);
+}
+
+static CMService *
+cm_service_new (GUPnPConnmanManager *manager,
+                GDBusProxy          *service_proxy)
+{
+        CMService *cm_service;
+
+        cm_service = g_slice_new0 (CMService);
+
+        cm_service->manager = manager;
+        cm_service->proxy   = service_proxy;
+        cm_service->current = CM_SERVICE_STATE_INACTIVE;
+
+        return cm_service;
+}
+
+static void
+cm_service_free (CMService *cm_service)
+{
+        GDBusConnection *cnx;
+
+        cnx = g_dbus_proxy_get_connection (cm_service->proxy);
+
+        if (cm_service->sig_prop_id) {
+                g_dbus_connection_signal_unsubscribe (cnx,
+                                                      cm_service->sig_prop_id);
+                cm_service->sig_prop_id = 0;
+        }
+
+        g_object_unref (cm_service->proxy);
+
+        if (cm_service->context != NULL) {
+                g_signal_emit_by_name (cm_service->manager,
+                                       "context-unavailable",
+                                       cm_service->context);
+
+                g_object_unref (cm_service->context);
+        }
+
+        g_free (cm_service->iface);
+        g_free (cm_service->name);
+        g_slice_free (CMService, cm_service);
+}
+
+static void
+cm_service_use (GUPnPConnmanManager *manager,
+                CMService           *cm_service)
+{
+        GDBusConnection *connection;
+
+        connection = g_dbus_proxy_get_connection (cm_service->proxy);
+
+        cm_service->sig_prop_id = g_dbus_connection_signal_subscribe (
+                                connection,
+                                CM_DBUS_CONNMAN_NAME,
+                                CM_DBUS_SERVICE_INTERFACE,
+                                "PropertyChanged",
+                                g_dbus_proxy_get_object_path (cm_service->proxy),
+                                NULL,
+                                G_DBUS_SIGNAL_FLAGS_NONE,
+                                on_service_property_signal,
+                                cm_service,
+                                NULL);
+
+        if (cm_service->current == CM_SERVICE_STATE_ACTIVE)
+                if (service_context_create (cm_service) == FALSE)
+                        cm_service->current = CM_SERVICE_STATE_INACTIVE;
+}
+static void
+cm_service_update (CMService *cm_service, GVariant *dict, guint port)
+{
+        CMServiceState new_state;
+        GVariant       *eth;
+        gchar          *iface;
+        gchar          *name;
+        gchar          *state;
+        gboolean       is_name;
+        gboolean       is_iface;
+
+        is_iface = FALSE;
+        iface    = NULL;
+        name     = NULL;
+
+        is_name = g_variant_lookup (dict, "Name", "s", &name);
+
+        eth = g_variant_lookup_value (dict, "Ethernet", G_VARIANT_TYPE_VARDICT);
+
+        if (eth != NULL) {
+                is_iface = g_variant_lookup (eth, "Interface", "s", &iface);
+                g_variant_unref (eth);
+        }
+
+        new_state = CM_SERVICE_STATE_INACTIVE;
+
+        if (g_variant_lookup (dict, "State", "&s", &state) != FALSE)
+                if ((g_strcmp0 (state, "online") == 0) ||
+                    (g_strcmp0 (state, "ready") == 0))
+                        new_state = CM_SERVICE_STATE_ACTIVE;
+
+        if (is_name && (g_strcmp0 (cm_service->name, name) == 0)) {
+                g_free (cm_service->name);
+                cm_service->name = name;
+
+                if (cm_service->context != NULL)
+                        g_object_set (G_OBJECT (cm_service->context),
+                                      "network",
+                                      cm_service->name,
+                                      NULL);
+        }
+
+        if (is_iface && (g_strcmp0 (cm_service->iface, iface) == 0)) {
+                g_free (cm_service->iface);
+                cm_service->iface = iface;
+
+                if (cm_service->context != NULL)
+                        g_object_set (G_OBJECT (cm_service->context),
+                                      "interface",
+                                      cm_service->iface,
+                                      NULL);
+        }
+
+        cm_service->port = port;
+        service_context_update (cm_service, new_state);
+}
+
+static void
+service_proxy_new_cb (GObject      *source_object,
+                      GAsyncResult *res,
+                      gpointer     user_data)
+{
+        GUPnPConnmanManager *manager;
+        GDBusProxy          *service_proxy;
+        GError              *error = NULL;
+        CMService           *cm_service;
+        const gchar         *path;
+
+        service_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+        if (error != NULL) {
+                g_warning ("Failed to create D-Bus proxy: %s", error->message);
+                g_error_free (error);
+
+                return;
+        }
+
+        manager = GUPNP_CONNMAN_MANAGER (user_data);
+        path = g_dbus_proxy_get_object_path (service_proxy);
+        cm_service = g_hash_table_lookup (manager->priv->cm_services, path);
+
+        if (cm_service == NULL) {
+		g_object_unref (service_proxy);
+
+                return;
+	}
+
+        cm_service->proxy = service_proxy;
+        cm_service_use (manager, cm_service);
+}
+
+static void
+cm_service_add (GUPnPConnmanManager *manager,
+                GVariant            *dict,
+                gchar               *path,
+                guint               port)
+{
+        CMServiceState new_state;
+        CMService      *cm_service;
+        GVariant       *eth;
+        gchar          *iface;
+        gchar          *name;
+        gchar          *state;
+
+        iface   = NULL;
+        name    = NULL;
+
+        g_variant_lookup (dict, "Name", "s", &name);
+
+        eth = g_variant_lookup_value (dict, "Ethernet", G_VARIANT_TYPE_VARDICT);
+
+        if (eth != NULL) {
+                g_variant_lookup (eth, "Interface", "s", &iface);
+                g_variant_unref (eth);
+        }
+
+        new_state = CM_SERVICE_STATE_INACTIVE;
+
+        if (g_variant_lookup (dict, "State", "&s", &state) != FALSE)
+                if ((g_strcmp0 (state, "online") == 0) ||
+                    (g_strcmp0 (state, "ready") == 0))
+                        new_state = CM_SERVICE_STATE_ACTIVE;
+
+        cm_service = cm_service_new (manager, NULL);
+
+        cm_service->name    = name;
+        cm_service->iface   = iface;
+        cm_service->port    = port;
+        cm_service->current = new_state;
+
+        g_hash_table_insert (manager->priv->cm_services,
+                             g_strdup (path),
+                             cm_service);
+
+        g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+                                  G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+                                  G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                  NULL,
+                                  CM_DBUS_CONNMAN_NAME,
+                                  path,
+                                  CM_DBUS_SERVICE_INTERFACE,
+                                  NULL,
+                                  service_proxy_new_cb,
+                                  manager);
+}
+
+static void
+services_array_add (GUPnPConnmanManager *manager, GVariant *data)
+{
+        GVariant     *dict;
+        CMService    *cm_service;
+        gchar        *path;
+        GVariantIter iter;
+        GVariantIter dict_iter;
+        guint        port;
+
+        g_object_get (manager, "port", &port, NULL);
+        g_variant_iter_init (&iter, data);
+
+        while (g_variant_iter_loop (&iter, "(&o a{sv})", &path, &dict)) {
+
+                if (path == NULL)
+                        continue;
+
+                if (dict == NULL)
+                        continue;
+
+                if (g_variant_iter_init (&dict_iter, dict) == 0)
+                        continue;
+
+                cm_service = g_hash_table_lookup (manager->priv->cm_services,
+                                                  path);
+
+                if (cm_service == NULL)
+                        cm_service_add (manager, dict, path, port);
+                else
+                        cm_service_update (cm_service, dict, port);
+        }
+}
+
+static void
+services_array_remove (GUPnPConnmanManager *manager, GVariant *data)
+{
+        GUPnPConnmanManagerPrivate *priv;
+        CMService                  *cm_service;
+        char                       *path;
+        GVariantIter               iter;
+
+        priv = manager->priv;
+        g_variant_iter_init (&iter, data);
+
+        while (g_variant_iter_next (&iter, "&o", &path)) {
+                if (path == NULL)
+                        continue;
+
+                cm_service = g_hash_table_lookup (priv->cm_services, path);
+
+                if (cm_service == NULL)
+                        continue;
+
+                g_hash_table_remove (priv->cm_services, path);
+        }
+}
+
+static void
+on_manager_svc_changed_signal (GDBusConnection *connection,
+                               const gchar     *sender_name,
+                               const gchar     *object_path,
+                               const gchar     *interface_name,
+                               const gchar     *signal_name,
+                               GVariant        *parameters,
+                               gpointer        user_data)
+{
+        GUPnPConnmanManager *manager;
+        GVariant            *add_array;
+        GVariant            *remove_array;
+
+        manager = GUPNP_CONNMAN_MANAGER (user_data);
+
+        add_array = g_variant_get_child_value (parameters, 0);
+        remove_array = g_variant_get_child_value (parameters, 1);
+
+        if ((add_array != NULL) && (g_variant_n_children (add_array) > 0))
+                services_array_add (manager, add_array);
+
+        if ((remove_array != NULL) && (g_variant_n_children (remove_array) > 0))
+                services_array_remove (manager, remove_array);
+
+        g_variant_unref (add_array);
+        g_variant_unref (remove_array);
+}
+
+static void
+get_services_cb (GObject      *source_object,
+                 GAsyncResult *res,
+                 gpointer     user_data)
+{
+        GUPnPConnmanManager *manager;
+        GVariant            *ret;
+        GVariant            *services_array;
+        GError              *error = NULL;
+
+        ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+                                        res,
+                                        &error);
+
+        if (error != NULL) {
+                g_warning ("Error fetching service list: %s", error->message);
+                g_error_free (error);
+
+                return;
+        }
+
+        if (ret == NULL) {
+                g_warning ("Failed fetching list of services but no error");
+
+                return;
+        }
+
+        if (g_variant_is_container (ret) != TRUE)
+        {
+                g_warning ("Wrong format result");
+		g_variant_unref (ret);
+
+                return;
+        }
+
+        manager = GUPNP_CONNMAN_MANAGER (user_data);
+        services_array = g_variant_get_child_value (ret, 0);
+        services_array_add (manager, services_array);
+
+        g_variant_unref (services_array);
+        g_variant_unref (ret);
+}
+
+static void
+schedule_loopback_context_creation (GUPnPConnmanManager *manager)
+{
+        /* Create contexts in mainloop so that it happens after user has hooked
+         * to the "context-available" signal.
+         */
+        manager->priv->idle_context_creation_src = g_idle_source_new ();
+
+        g_source_attach (manager->priv->idle_context_creation_src,
+                         g_main_context_get_thread_default ());
+
+        g_source_set_callback (manager->priv->idle_context_creation_src,
+                               loopback_context_create,
+                               manager,
+                               NULL);
+
+        g_source_unref (manager->priv->idle_context_creation_src);
+}
+
+static void
+init_connman_manager (GUPnPConnmanManager *manager)
+{
+        GUPnPConnmanManagerPrivate *priv;
+        GError                     *error = NULL;
+        GDBusConnection            *connection;
+
+        priv = manager->priv;
+
+        priv->manager_proxy = g_dbus_proxy_new_for_bus_sync (
+                                G_BUS_TYPE_SYSTEM,
+                                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+                                G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                NULL,
+                                CM_DBUS_CONNMAN_NAME,
+                                CM_DBUS_MANAGER_PATH,
+                                CM_DBUS_MANAGER_INTERFACE,
+                                NULL,
+                                &error);
+
+        if (error != NULL) {
+                g_warning ("Failed to connect to Connman: %s", error->message);
+                g_error_free (error);
+
+                return;
+        }
+
+        connection = g_dbus_proxy_get_connection (priv->manager_proxy);
+
+        if (connection == NULL) {
+                g_warning ("Failed to get DBus Connection");
+                g_object_unref (priv->manager_proxy);
+                priv->manager_proxy = NULL;
+
+                return;
+        }
+
+        g_dbus_proxy_call (priv->manager_proxy,
+                           "GetServices",
+                           NULL,
+                           G_DBUS_CALL_FLAGS_NONE,
+                           -1,
+                           NULL,
+                           get_services_cb,
+                           manager);
+
+        priv->sig_change_id = g_dbus_connection_signal_subscribe (
+                                                connection,
+                                                CM_DBUS_CONNMAN_NAME,
+                                                CM_DBUS_MANAGER_INTERFACE,
+                                                "ServicesChanged",
+                                                CM_DBUS_MANAGER_PATH,
+                                                NULL,
+                                                G_DBUS_SIGNAL_FLAGS_NONE,
+                                                on_manager_svc_changed_signal,
+                                                manager,
+                                                NULL);
+}
+
+static void
+gupnp_connman_manager_dispose (GObject *object)
+{
+        GUPnPConnmanManager        *manager;
+        GUPnPConnmanManagerPrivate *priv;
+        GObjectClass               *object_class;
+        GDBusConnection            *cnx;
+
+        manager = GUPNP_CONNMAN_MANAGER (object);
+        priv = manager->priv;
+        cnx = g_dbus_proxy_get_connection (priv->manager_proxy);
+
+        if (priv->sig_change_id) {
+                g_dbus_connection_signal_unsubscribe (cnx, priv->sig_change_id);
+                priv->sig_change_id = 0;
+        }
+
+        if (priv->idle_context_creation_src) {
+                g_source_destroy (priv->idle_context_creation_src);
+                priv->idle_context_creation_src = NULL;
+        }
+
+        if (priv->manager_proxy != NULL) {
+                g_object_unref (priv->manager_proxy);
+                priv->manager_proxy = NULL;
+        }
+
+        if (priv->cm_services) {
+                g_hash_table_destroy (priv->cm_services);
+                priv->cm_services = NULL;
+        }
+
+        /* Call super */
+        object_class = G_OBJECT_CLASS (gupnp_connman_manager_parent_class);
+        object_class->dispose (object);
+}
+
+static void
+gupnp_connman_manager_constructed (GObject *object)
+{
+        GUPnPConnmanManager *manager;
+        GObjectClass        *object_class;
+
+        manager = GUPNP_CONNMAN_MANAGER (object);
+
+        init_connman_manager (manager);
+
+        schedule_loopback_context_creation (manager);
+
+        /* Call super */
+        object_class = G_OBJECT_CLASS (gupnp_connman_manager_parent_class);
+
+        if (object_class->constructed != NULL) {
+                object_class->constructed (object);
+        }
+}
+
+static void
+gupnp_connman_manager_init (GUPnPConnmanManager *manager)
+{
+        manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (
+                                                manager,
+                                                GUPNP_TYPE_CONNMAN_MANAGER,
+                                                GUPnPConnmanManagerPrivate);
+
+        manager->priv->cm_services = g_hash_table_new_full (
+                                        g_str_hash,
+                                        g_str_equal,
+                                        (GDestroyNotify) g_free,
+                                        (GDestroyNotify) cm_service_free);
+}
+
+static void
+gupnp_connman_manager_class_init (GUPnPConnmanManagerClass *klass)
+{
+        GObjectClass *object_class;
+
+        object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructed  = gupnp_connman_manager_constructed;
+        object_class->dispose      = gupnp_connman_manager_dispose;
+
+        g_type_class_add_private (klass, sizeof (GUPnPConnmanManagerPrivate));
+}
+
+gboolean
+gupnp_connman_manager_is_available (void)
+{
+        GDBusProxy *dbus_proxy;
+        GVariant   *ret_values;
+        GError     *error = NULL;
+        gboolean   ret = FALSE;
+
+        dbus_proxy = g_dbus_proxy_new_for_bus_sync (
+                        G_BUS_TYPE_SYSTEM,
+                        G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                        NULL,
+                        DBUS_SERVICE_DBUS,
+                        DBUS_PATH_DBUS,
+                        DBUS_INTERFACE_DBUS,
+                        NULL,
+                        &error);
+
+
+        if (error != NULL) {
+                g_warning ("Failed to connect to Connman: %s", error->message);
+                g_error_free (error);
+
+                return ret;
+        }
+
+        ret_values = g_dbus_proxy_call_sync (
+                                dbus_proxy,
+                                "NameHasOwner",
+                                g_variant_new ("(s)", CM_DBUS_CONNMAN_NAME),
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1,
+                                NULL,
+                                &error);
+
+        if (error != NULL) {
+                g_warning ("%s.NameHasOwner() failed: %s",
+                           DBUS_INTERFACE_DBUS,
+                           error->message);
+
+                g_error_free (error);
+
+        } else {
+                g_variant_get_child (ret_values, 0, "b", &ret);
+                g_variant_unref (ret_values);
+        }
+
+        g_object_unref (dbus_proxy);
+
+        return ret;
+}
diff --git a/libgupnp/gupnp-connman-manager.h b/libgupnp/gupnp-connman-manager.h
new file mode 100644
index 0000000..d5f972d
--- /dev/null
+++ b/libgupnp/gupnp-connman-manager.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Author: Ludovic Ferrandis <ludovic ferrandis intel com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GUPNP_CONNMAN_MANAGER_H__
+#define __GUPNP_CONNMAN_MANAGER_H__
+
+#include "gupnp-context-manager.h"
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL GType
+gupnp_connman_manager_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_CONNMAN_MANAGER \
+                (gupnp_connman_manager_get_type ())
+#define GUPNP_CONNMAN_MANAGER(obj) \
+                (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+                 GUPNP_TYPE_CONNMAN_MANAGER, \
+                 GUPnPConnmanManager))
+#define GUPNP_CONNMAN_MANAGER_CLASS(obj) \
+                (G_TYPE_CHECK_CLASS_CAST ((obj), \
+                 GUPNP_TYPE_CONNMAN_MANAGER, \
+                 GUPnPConnmanManagerClass))
+#define GUPNP_IS_CONNMAN_MANAGER(obj) \
+                (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+                 GUPNP_TYPE_CONNMAN_MANAGER))
+#define GUPNP_IS_CONNMAN_MANAGER_CLASS(obj) \
+                (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+                 GUPNP_TYPE_CONNMAN_MANAGER))
+#define GUPNP_CONNMAN_MANAGER_GET_CLASS(obj) \
+                (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                 GUPNP_TYPE_CONNMAN_MANAGER, \
+                 GUPnPConnmanManagerClass))
+
+typedef struct _GUPnPConnmanManagerPrivate GUPnPConnmanManagerPrivate;
+
+typedef struct {
+        GUPnPContextManager             parent;
+        GUPnPConnmanManagerPrivate      *priv;
+
+} GUPnPConnmanManager;
+
+typedef struct {
+        GUPnPContextManagerClass parent_class;
+
+} GUPnPConnmanManagerClass;
+
+G_GNUC_INTERNAL gboolean
+gupnp_connman_manager_is_available      (void);
+
+G_END_DECLS
+
+#endif /* __GUPNP_CONNMAN_MANAGER_H__ */
diff --git a/libgupnp/gupnp-context-manager.c b/libgupnp/gupnp-context-manager.c
index 95914ac..ff454c9 100644
--- a/libgupnp/gupnp-context-manager.c
+++ b/libgupnp/gupnp-context-manager.c
@@ -335,6 +335,12 @@ gupnp_context_manager_create (guint port)
 
         if (gupnp_network_manager_is_available ())
                 impl_type = GUPNP_TYPE_NETWORK_MANAGER;
+#elif USE_CONNMAN
+#include "gupnp-connman-manager.h"
+
+       if (gupnp_connman_manager_is_available ())
+                impl_type = GUPNP_TYPE_CONNMAN_MANAGER;
+
 #elif USE_NETLINK
 #include "gupnp-linux-context-manager.h"
         impl_type = GUPNP_TYPE_LINUX_CONTEXT_MANAGER;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]