Add gobject introspection
[profile/ivi/GUPnP.git] / libgupnp / gupnp-network-manager.c
1 /*
2  * Copyright (C) 2009 Nokia Corporation.
3  *
4  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
5  *                               <zeeshan.ali@nokia.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:gupnp-network-manager
25  * @short_description: NetworkManager-based implementation of
26  * #GUPnPContextManager.
27  *
28  */
29
30 #include <config.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <gio/gio.h>
36
37 #include "gupnp-network-manager.h"
38 #include "gupnp-context.h"
39 #include "gupnp-marshal.h"
40
41 #define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH \
42         (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
43
44 #define DBUS_SERVICE_NM "org.freedesktop.NetworkManager"
45 #define MANAGER_PATH "/org/freedesktop/NetworkManager"
46 #define MANAGER_INTERFACE "org.freedesktop.NetworkManager"
47 #define AP_INTERFACE "org.freedesktop.NetworkManager.AccessPoint"
48 #define DEVICE_INTERFACE "org.freedesktop.NetworkManager.Device"
49 #define WIFI_INTERFACE "org.freedesktop.NetworkManager.Device.Wireless"
50
51 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
52 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
53 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
54
55 G_DEFINE_TYPE (GUPnPNetworkManager,
56                gupnp_network_manager,
57                GUPNP_TYPE_CONTEXT_MANAGER);
58
59 typedef enum
60 {
61         NM_DEVICE_STATE_UNKNOWN = 0,
62         NM_OLD_DEVICE_STATE_UNMANAGED = 1,
63         NM_OLD_DEVICE_STATE_UNAVAILABLE = 2,
64         NM_OLD_DEVICE_STATE_DISCONNECTED = 3,
65         NM_OLD_DEVICE_STATE_PREPARE = 4,
66         NM_OLD_DEVICE_STATE_CONFIG = 5,
67         NM_OLD_DEVICE_STATE_NEED_AUTH = 6,
68         NM_OLD_DEVICE_STATE_IP_CONFIG = 7,
69         NM_OLD_DEVICE_STATE_ACTIVATED = 8,
70         NM_OLD_DEVICE_STATE_FAILED = 9,
71         NM_DEVICE_STATE_UNMANAGED = 10,
72         NM_DEVICE_STATE_UNAVAILABLE = 20,
73         NM_DEVICE_STATE_DISCONNECTED = 30,
74         NM_DEVICE_STATE_PREPARE = 40,
75         NM_DEVICE_STATE_CONFIG = 50,
76         NM_DEVICE_STATE_NEED_AUTH = 60,
77         NM_DEVICE_STATE_IP_CONFIG = 70,
78         NM_DEVICE_STATE_IP_CHECK = 80,
79         NM_DEVICE_STATE_SECONDARIES = 90,
80         NM_DEVICE_STATE_ACTIVATED = 100,
81         NM_DEVICE_STATE_DEACTIVATING = 110,
82         NM_DEVICE_STATE_FAILED = 120
83 } NMDeviceState;
84
85 typedef enum
86 {
87         NM_DEVICE_TYPE_UNKNOWN,
88         NM_DEVICE_TYPE_ETHERNET,
89         NM_DEVICE_TYPE_WIFI,
90         NM_OLD_DEVICE_TYPE_GSM,
91         NM_OLD_DEVICE_TYPE_CDMA,
92         NM_DEVICE_TYPE_BT,
93         NM_DEVICE_TYPE_OLPC_MESH,
94         NM_DEVICE_TYPE_WIMAX,
95         NM_DEVICE_TYPE_MODEM
96 } NMDeviceType;
97
98 typedef struct
99 {
100         gint ref_count;
101
102         GUPnPNetworkManager *manager;
103
104         GUPnPContext *context;
105
106         GDBusProxy *proxy;
107         GDBusProxy *wifi_proxy;
108         GDBusProxy *ap_proxy;
109 } NMDevice;
110
111 struct _GUPnPNetworkManagerPrivate {
112         GDBusProxy *manager_proxy;
113
114         GSource *idle_context_creation_src;
115
116         GList *nm_devices;
117
118         GCancellable *cancellable;
119
120         GDBusConnection *system_bus;
121 };
122
123 static NMDevice *
124 nm_device_new (GUPnPNetworkManager *manager,
125                GDBusProxy          *device_proxy)
126 {
127         NMDevice *nm_device;
128
129         nm_device = g_slice_new0 (NMDevice);
130
131         g_atomic_int_set (&nm_device->ref_count, 1);
132         nm_device->manager = g_object_ref (manager);
133         nm_device->proxy = g_object_ref (device_proxy);
134
135         return nm_device;
136 }
137
138 static NMDevice *
139 nm_device_ref (NMDevice *nm_device)
140 {
141         g_atomic_int_inc (&nm_device->ref_count);
142
143         return nm_device;
144 }
145
146 static void
147 nm_device_unref (NMDevice *nm_device)
148 {
149        if (!g_atomic_int_dec_and_test (&nm_device->ref_count))
150           return;
151
152         g_object_unref (nm_device->proxy);
153         if (nm_device->wifi_proxy != NULL)
154                 g_object_unref (nm_device->wifi_proxy);
155         if (nm_device->ap_proxy != NULL)
156                 g_object_unref (nm_device->ap_proxy);
157
158         if (nm_device->context != NULL) {
159                 g_signal_emit_by_name (nm_device->manager,
160                                        "context-unavailable",
161                                        nm_device->context);
162
163                 g_object_unref (nm_device->context);
164         }
165
166         g_object_unref (nm_device->proxy);
167         g_object_unref (nm_device->manager);
168
169         g_slice_free (NMDevice, nm_device);
170 }
171
172 #define LOOPBACK_IFACE "lo"
173
174 static gboolean
175 create_loopback_context (gpointer data)
176 {
177         GUPnPNetworkManager *manager = (GUPnPNetworkManager *) data;
178         GUPnPContext *context;
179         guint port;
180         GError *error = NULL;
181
182         manager->priv->idle_context_creation_src = NULL;
183
184         g_object_get (manager,
185                       "port", &port,
186                       NULL);
187
188         context = g_initable_new (GUPNP_TYPE_CONTEXT,
189                                   NULL,
190                                   &error,
191                                   "interface", LOOPBACK_IFACE,
192                                   "port", port,
193                                   NULL);
194         if (error) {
195                 g_warning ("Error creating GUPnP context: %s\n",
196                            error->message);
197
198                 g_error_free (error);
199                 return FALSE;
200         }
201
202         g_signal_emit_by_name (manager, "context-available", context);
203
204         g_object_unref (context);
205
206         return FALSE;
207 }
208
209 static void
210 create_context_for_device (NMDevice *nm_device)
211 {
212         GError *error = NULL;
213         guint port;
214         GVariant *value;
215         char *iface;
216         char *ssid = NULL;
217
218         g_object_get (nm_device->manager,
219                       "port", &port,
220                       NULL);
221
222         value = g_dbus_proxy_get_cached_property (nm_device->proxy,
223                                                   "Interface");
224         if (G_UNLIKELY (value == NULL))
225                 return;
226
227         if (G_UNLIKELY (!g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))) {
228                 g_variant_unref (value);
229
230                 return;
231         }
232
233         iface = g_variant_dup_string (value, NULL);
234         g_variant_unref (value);
235
236         if (nm_device->ap_proxy != NULL) {
237                 value = g_dbus_proxy_get_cached_property (nm_device->ap_proxy,
238                                                           "Ssid");
239                 if (G_LIKELY (value != NULL)) {
240                         ssid = g_strndup (g_variant_get_data (value),
241                                           g_variant_get_size (value));
242                         g_variant_unref (value);
243                 }
244         }
245
246         nm_device->context = g_initable_new (GUPNP_TYPE_CONTEXT,
247                                              NULL,
248                                              &error,
249                                              "interface", iface,
250                                              "network", ssid,
251                                              "port", port,
252                                              NULL);
253         g_free (iface);
254         g_free (ssid);
255
256         if (error) {
257                 g_warning ("Error creating GUPnP context: %s\n",
258                            error->message);
259
260                 g_error_free (error);
261
262                 return;
263         }
264
265         g_signal_emit_by_name (nm_device->manager,
266                                "context-available",
267                                nm_device->context);
268 }
269
270 static void
271 ap_proxy_new_cb (GObject      *source_object,
272                  GAsyncResult *res,
273                  gpointer      user_data)
274 {
275         NMDevice *nm_device;
276         GError *error;
277
278         nm_device = (NMDevice *) user_data;
279         error = NULL;
280
281         nm_device->ap_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
282         if (G_UNLIKELY (error != NULL)) {
283                 g_message ("Failed to create D-Bus proxy: %s", error->message);
284                 g_error_free (error);
285                 goto done;
286         }
287
288         create_context_for_device (nm_device);
289
290 done:
291         nm_device_unref (nm_device);
292 }
293
294 static void
295 on_wifi_device_activated (NMDevice *nm_device)
296 {
297         GVariant *value;
298         const char *ap_path;
299
300         value = g_dbus_proxy_get_cached_property (nm_device->wifi_proxy,
301                                                   "ActiveAccessPoint");
302         if (G_UNLIKELY (value == NULL))
303                 return;
304
305         if (G_UNLIKELY (!g_variant_is_of_type (value,
306                                                G_VARIANT_TYPE_OBJECT_PATH))) {
307                 g_variant_unref (value);
308
309                 return;
310         }
311
312         ap_path = g_variant_get_string (value, NULL);
313         if (G_UNLIKELY (ap_path == NULL))
314                 create_context_for_device (nm_device);
315         else {
316                 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
317                                           G_DBUS_PROXY_FLAGS_NONE,
318                                           NULL,
319                                           DBUS_SERVICE_NM,
320                                           ap_path,
321                                           AP_INTERFACE,
322                                           nm_device->manager->priv->cancellable,
323                                           ap_proxy_new_cb,
324                                           nm_device_ref (nm_device));
325         }
326
327         g_variant_unref (value);
328 }
329
330 static void
331 on_device_activated (NMDevice *nm_device)
332 {
333         if (nm_device->wifi_proxy != NULL)
334                 on_wifi_device_activated (nm_device);
335         else
336                 create_context_for_device (nm_device);
337 }
338
339 static void
340 on_device_signal (GDBusProxy *proxy,
341                   char       *sender_name,
342                   char       *signal_name,
343                   GVariant   *parameters,
344                   gpointer    user_data)
345 {
346         NMDevice *nm_device;
347         unsigned int new_state;
348
349         if (g_strcmp0 (signal_name, "StateChanged") != 0)
350                 return;
351
352         nm_device = (NMDevice *) user_data;
353         g_variant_get_child (parameters, 0, "u", &new_state);
354
355         if (new_state == NM_OLD_DEVICE_STATE_ACTIVATED ||
356             new_state == NM_DEVICE_STATE_ACTIVATED)
357                 on_device_activated (nm_device);
358         else if (nm_device->context != NULL) {
359                 /* For all other states we just destroy the context */
360                 g_signal_emit_by_name (nm_device->manager,
361                                        "context-unavailable",
362                                        nm_device->context);
363
364                 g_object_unref (nm_device->context);
365                 nm_device->context = NULL;
366
367                 if (nm_device->ap_proxy != NULL) {
368                         g_object_unref (nm_device->ap_proxy);
369                         nm_device->ap_proxy = NULL;
370                 }
371         }
372 }
373
374 static void
375 use_new_device (GUPnPNetworkManager *manager,
376                 NMDevice            *nm_device)
377 {
378         NMDeviceState state;
379         GVariant *value;
380
381         manager->priv->nm_devices = g_list_append (manager->priv->nm_devices,
382                                                    nm_device);
383
384         g_signal_connect (nm_device->proxy,
385                           "g-signal",
386                           G_CALLBACK (on_device_signal),
387                           nm_device);
388
389         value = g_dbus_proxy_get_cached_property (nm_device->proxy, "State");
390         if (G_UNLIKELY (value == NULL))
391                 return;
392
393         if (G_UNLIKELY (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))) {
394                 g_variant_unref (value);
395
396                 return;
397         }
398
399         state = g_variant_get_uint32 (value);
400         g_variant_unref (value);
401
402         if (state == NM_OLD_DEVICE_STATE_ACTIVATED ||
403             state == NM_DEVICE_STATE_ACTIVATED)
404                 on_device_activated (nm_device);
405 }
406
407 static void
408 wifi_proxy_new_cb (GObject      *source_object,
409                    GAsyncResult *res,
410                    gpointer      user_data) {
411         NMDevice *nm_device;
412         GError *error;
413
414         nm_device = (NMDevice *) user_data;
415         error = NULL;
416
417         nm_device->wifi_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
418         if (G_UNLIKELY (error != NULL)) {
419                 g_message ("Failed to create D-Bus proxy: %s", error->message);
420                 g_error_free (error);
421                 goto done;
422         }
423
424         use_new_device (nm_device->manager, nm_device);
425
426 done:
427         nm_device_unref (nm_device);
428 }
429
430 static void
431 device_proxy_new_cb (GObject      *source_object,
432                      GAsyncResult *res,
433                      gpointer      user_data) {
434         GUPnPNetworkManager *manager;
435         GDBusProxy *device_proxy;
436         NMDevice *nm_device;
437         NMDeviceType type;
438         GVariant *value;
439         GError *error;
440
441         manager = GUPNP_NETWORK_MANAGER (user_data);
442         error = NULL;
443
444         device_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
445         if (G_UNLIKELY (error != NULL)) {
446                 g_message ("Failed to create D-Bus proxy: %s", error->message);
447                 g_error_free (error);
448
449                 goto done;
450         }
451
452         value = g_dbus_proxy_get_cached_property (device_proxy, "DeviceType");
453         if (G_UNLIKELY (value == NULL)) {
454                 g_object_unref (device_proxy);
455
456                 goto done;
457         }
458
459         if (G_UNLIKELY (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))) {
460                 g_variant_unref (value);
461                 g_object_unref (device_proxy);
462
463                 goto done;
464         }
465
466         type = g_variant_get_uint32 (value);
467         g_variant_unref (value);
468
469         nm_device = nm_device_new (manager, device_proxy);
470
471         if (type == NM_DEVICE_TYPE_WIFI) {
472                 const char *path;
473
474                 path = g_dbus_proxy_get_object_path (nm_device->proxy);
475                 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
476                                           G_DBUS_PROXY_FLAGS_NONE,
477                                           NULL,
478                                           DBUS_SERVICE_NM,
479                                           path,
480                                           WIFI_INTERFACE,
481                                           manager->priv->cancellable,
482                                           wifi_proxy_new_cb,
483                                           nm_device_ref (nm_device));
484         } else
485                 use_new_device (manager, nm_device);
486
487 done:
488         g_object_unref (manager);
489 }
490
491 static int
492 compare_device_path (NMDevice *nm_device, char *device_path)
493 {
494      const char *path;
495
496      path = g_dbus_proxy_get_object_path (nm_device->proxy);
497      if (G_UNLIKELY (path == NULL))
498              return -1;
499
500      return strcmp (path, device_path);
501 }
502
503 static void
504 on_manager_signal (GDBusProxy *proxy,
505                    char       *sender_name,
506                    char       *signal_name,
507                    GVariant   *parameters,
508                    gpointer    user_data)
509 {
510         GUPnPNetworkManager *manager;
511
512         manager = GUPNP_NETWORK_MANAGER (user_data);
513
514         if (g_strcmp0 (signal_name, "DeviceAdded") == 0) {
515                 char *device_path = NULL;
516
517                 g_variant_get_child (parameters, 0, "o", &device_path);
518                 if (G_UNLIKELY (device_path == NULL))
519                         return;
520
521
522                 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
523                                           G_DBUS_PROXY_FLAGS_NONE,
524                                           NULL,
525                                           DBUS_SERVICE_NM,
526                                           device_path,
527                                           DEVICE_INTERFACE,
528                                           manager->priv->cancellable,
529                                           device_proxy_new_cb,
530                                           g_object_ref (manager));
531                 g_free (device_path);
532         } else if (g_strcmp0 (signal_name, "DeviceRemoved") == 0) {
533                 GList *device_node;
534                 NMDevice *nm_device;
535                 GUPnPNetworkManagerPrivate *priv;
536                 char *device_path = NULL;
537
538                 g_variant_get_child (parameters, 0, "o", &device_path);
539                 if (G_UNLIKELY (device_path == NULL))
540                         return;
541
542                 priv = manager->priv;
543
544                 device_node = g_list_find_custom (
545                                 priv->nm_devices,
546                                 device_path,
547                                 (GCompareFunc) compare_device_path);
548                 if (G_UNLIKELY (device_node == NULL)) {
549                         g_free (device_path);
550
551                         return;
552                 }
553
554                 nm_device = (NMDevice *) device_node->data;
555
556                 priv->nm_devices = g_list_remove (priv->nm_devices, nm_device);
557                 nm_device_unref (nm_device);
558                 g_free (device_path);
559         }
560 }
561
562 static void
563 get_devices_cb (GObject      *source_object,
564                 GAsyncResult *res,
565                 gpointer      user_data)
566 {
567         GUPnPNetworkManager *manager;
568         GVariant *ret;
569         GVariantIter *device_iter;
570         char* device_path;
571         GError *error = NULL;
572
573         manager = GUPNP_NETWORK_MANAGER (user_data);
574
575         ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
576                                         res,
577                                         &error);
578         if (error != NULL) {
579                 g_warning ("Error fetching list of devices: %s",
580                            error->message);
581
582                 g_error_free (error);
583                 goto done;
584         }
585
586         g_variant_get_child (ret, 0, "ao", &device_iter);
587         while (g_variant_iter_loop (device_iter, "o", &device_path))
588                 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
589                                           G_DBUS_PROXY_FLAGS_NONE,
590                                           NULL,
591                                           DBUS_SERVICE_NM,
592                                           device_path,
593                                           DEVICE_INTERFACE,
594                                           manager->priv->cancellable,
595                                           device_proxy_new_cb,
596                                           g_object_ref (user_data));
597         g_variant_iter_free (device_iter);
598
599         g_variant_unref (ret);
600
601 done:
602         g_object_unref (manager);
603 }
604
605 static void
606 schedule_loopback_context_creation (GUPnPNetworkManager *manager)
607 {
608         /* Create contexts in mainloop so that is happens after user has hooked
609          * to the "context-available" signal.
610          */
611         manager->priv->idle_context_creation_src = g_idle_source_new ();
612         g_source_attach (manager->priv->idle_context_creation_src,
613                          g_main_context_get_thread_default ());
614         g_source_set_callback (manager->priv->idle_context_creation_src,
615                                create_loopback_context,
616                                g_object_ref (manager),
617                                (GDestroyNotify) g_object_unref);
618         g_source_unref (manager->priv->idle_context_creation_src);
619 }
620
621 static void
622 init_network_manager (GUPnPNetworkManager *manager)
623 {
624         GUPnPNetworkManagerPrivate *priv;
625         GError *error;
626
627         priv = manager->priv;
628
629         error = NULL;
630         priv->manager_proxy = g_dbus_proxy_new_for_bus_sync (
631                         G_BUS_TYPE_SYSTEM,
632                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
633                         NULL,
634                         DBUS_SERVICE_NM,
635                         MANAGER_PATH,
636                         MANAGER_INTERFACE,
637                         priv->cancellable,
638                         &error);
639         if (error != NULL) {
640                 g_message ("Failed to connect to NetworkManager: %s",
641                            error->message);
642                 g_error_free (error);
643
644                 return;
645         }
646
647         g_signal_connect (priv->manager_proxy,
648                           "g-signal",
649                           G_CALLBACK (on_manager_signal),
650                           manager);
651
652
653         g_dbus_proxy_call (priv->manager_proxy,
654                            "GetDevices",
655                            NULL,
656                            G_DBUS_CALL_FLAGS_NONE,
657                            -1,
658                            priv->cancellable,
659                            get_devices_cb,
660                            g_object_ref (manager));
661 }
662
663 static void
664 gupnp_network_manager_init (GUPnPNetworkManager *manager)
665 {
666         manager->priv =
667                 G_TYPE_INSTANCE_GET_PRIVATE (manager,
668                                              GUPNP_TYPE_NETWORK_MANAGER,
669                                              GUPnPNetworkManagerPrivate);
670 }
671
672 static void
673 gupnp_network_manager_constructed (GObject *object)
674 {
675         GUPnPNetworkManager *manager;
676         GUPnPNetworkManagerPrivate *priv;
677         GObjectClass *object_class;
678
679         manager = GUPNP_NETWORK_MANAGER (object);
680         priv = manager->priv;
681
682         priv->cancellable = g_cancellable_new ();
683         priv->nm_devices = NULL;
684         priv->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
685
686         init_network_manager (manager);
687
688         schedule_loopback_context_creation (manager);
689
690         /* Call super */
691         object_class = G_OBJECT_CLASS (gupnp_network_manager_parent_class);
692         if (object_class->constructed != NULL) {
693                 object_class->constructed (object);
694         }
695 }
696
697 static void
698 gupnp_network_manager_dispose (GObject *object)
699 {
700         GUPnPNetworkManager *manager;
701         GUPnPNetworkManagerPrivate *priv;
702         GObjectClass *object_class;
703
704         manager = GUPNP_NETWORK_MANAGER (object);
705         priv = manager->priv;
706
707         if (manager->priv->idle_context_creation_src) {
708                 g_source_destroy (manager->priv->idle_context_creation_src);
709                 manager->priv->idle_context_creation_src = NULL;
710         }
711
712         if (priv->manager_proxy != NULL) {
713                 g_object_unref (priv->manager_proxy);
714                 priv->manager_proxy = NULL;
715         }
716
717         if (priv->nm_devices != NULL) {
718                 g_list_foreach (priv->nm_devices, (GFunc) nm_device_unref,
719                     NULL);
720                 g_list_free (priv->nm_devices);
721                 priv->nm_devices = NULL;
722         }
723
724         if (priv->cancellable != NULL)  {
725                 g_object_unref (priv->cancellable);
726                 priv->cancellable = NULL;
727         }
728
729         g_clear_object (&(priv->system_bus));
730
731         /* Call super */
732         object_class = G_OBJECT_CLASS (gupnp_network_manager_parent_class);
733         object_class->dispose (object);
734 }
735
736 static void
737 gupnp_network_manager_class_init (GUPnPNetworkManagerClass *klass)
738 {
739         GObjectClass *object_class;
740
741         object_class = G_OBJECT_CLASS (klass);
742
743         object_class->constructed  = gupnp_network_manager_constructed;
744         object_class->dispose      = gupnp_network_manager_dispose;
745
746         g_type_class_add_private (klass, sizeof (GUPnPNetworkManagerPrivate));
747 }
748
749 gboolean
750 gupnp_network_manager_is_available ()
751 {
752         GDBusProxy *dbus_proxy;
753         GVariant *ret_values;
754         GError *error = NULL;
755         gboolean ret = FALSE;
756
757         dbus_proxy = g_dbus_proxy_new_for_bus_sync (
758                         G_BUS_TYPE_SYSTEM,
759                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
760                         NULL,
761                         DBUS_SERVICE_DBUS,
762                         DBUS_PATH_DBUS,
763                         DBUS_INTERFACE_DBUS,
764                         NULL,
765                         &error);
766         if (error != NULL) {
767                 g_message ("Failed to connect to NetworkManager: %s",
768                            error->message);
769                 g_error_free (error);
770
771                 return ret;
772         }
773
774         ret_values = g_dbus_proxy_call_sync (dbus_proxy,
775                                              "NameHasOwner",
776                                              g_variant_new ("(s)",
777                                                             DBUS_SERVICE_NM),
778                                              G_DBUS_CALL_FLAGS_NONE,
779                                              -1,
780                                              NULL,
781                                              &error);
782         if (error != NULL) {
783                 g_warning ("%s.NameHasOwner() failed: %s",
784                            DBUS_INTERFACE_DBUS,
785                            error->message);
786                 g_error_free (error);
787         } else {
788                 g_variant_get_child (ret_values, 0, "b", &ret);
789                 g_variant_unref (ret_values);
790         }
791
792         g_object_unref (dbus_proxy);
793
794         return ret;
795 }