1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright 2014 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "gnetworkmonitornm.h"
27 #include "ginitable.h"
28 #include "giomodule-priv.h"
30 #include "glib/gstdio.h"
31 #include "gnetworkingprivate.h"
32 #include "gnetworkmonitor.h"
33 #include "gdbusproxy.h"
35 static void g_network_monitor_nm_iface_init (GNetworkMonitorInterface
*iface
);
36 static void g_network_monitor_nm_initable_iface_init (GInitableIface
*iface
);
42 PROP_NETWORK_AVAILABLE
,
48 NM_CONNECTIVITY_UNKNOWN
,
50 NM_CONNECTIVITY_PORTAL
,
51 NM_CONNECTIVITY_LIMITED
,
53 } NMConnectivityState
;
55 struct _GNetworkMonitorNMPrivate
59 GNetworkConnectivity connectivity
;
60 gboolean network_available
;
61 gboolean network_metered
;
64 #define g_network_monitor_nm_get_type _g_network_monitor_nm_get_type
65 G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorNM
, g_network_monitor_nm
, G_TYPE_NETWORK_MONITOR_NETLINK
,
66 G_ADD_PRIVATE (GNetworkMonitorNM
)
67 G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR
,
68 g_network_monitor_nm_iface_init
)
69 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE
,
70 g_network_monitor_nm_initable_iface_init
)
71 _g_io_modules_ensure_extension_points_registered ();
72 g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME
,
78 g_network_monitor_nm_init (GNetworkMonitorNM
*nm
)
80 nm
->priv
= g_network_monitor_nm_get_instance_private (nm
);
84 g_network_monitor_nm_get_property (GObject
*object
,
89 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (object
);
93 case PROP_NETWORK_AVAILABLE
:
94 g_value_set_boolean (value
, nm
->priv
->network_available
);
97 case PROP_NETWORK_METERED
:
98 g_value_set_boolean (value
, nm
->priv
->network_metered
);
101 case PROP_CONNECTIVITY
:
102 g_value_set_enum (value
, nm
->priv
->connectivity
);
106 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
111 static GNetworkConnectivity
112 nm_conn_to_g_conn (int nm_state
)
116 case NM_CONNECTIVITY_UNKNOWN
:
117 return G_NETWORK_CONNECTIVITY_LOCAL
;
118 case NM_CONNECTIVITY_NONE
:
119 return G_NETWORK_CONNECTIVITY_LOCAL
;
120 case NM_CONNECTIVITY_PORTAL
:
121 return G_NETWORK_CONNECTIVITY_PORTAL
;
122 case NM_CONNECTIVITY_LIMITED
:
123 return G_NETWORK_CONNECTIVITY_LIMITED
;
124 case NM_CONNECTIVITY_FULL
:
125 return G_NETWORK_CONNECTIVITY_FULL
;
127 g_warning ("Unknown NM connectivity state %d", nm_state
);
128 return G_NETWORK_CONNECTIVITY_LOCAL
;
133 nm_metered_to_bool (guint nm_metered
)
138 case 3: /* guess-yes */
140 case 0: /* unknown */
141 /* We default to FALSE in the unknown-because-you're-not-running-NM
142 * case, so we should return FALSE in the
143 * unknown-when-you-are-running-NM case too. */
145 case 4: /* guess-no */
148 g_warning ("Unknown NM metered state %d", nm_metered
);
154 sync_properties (GNetworkMonitorNM
*nm
,
155 gboolean emit_signals
)
158 NMConnectivityState nm_connectivity
;
159 gboolean new_network_available
;
160 gboolean new_network_metered
;
161 GNetworkConnectivity new_connectivity
;
163 v
= g_dbus_proxy_get_cached_property (nm
->priv
->proxy
, "Connectivity");
167 nm_connectivity
= g_variant_get_uint32 (v
);
170 if (nm_connectivity
== NM_CONNECTIVITY_NONE
)
172 new_network_available
= FALSE
;
173 new_network_metered
= FALSE
;
174 new_connectivity
= G_NETWORK_CONNECTIVITY_LOCAL
;
179 /* this is only available post NM 1.0 */
180 v
= g_dbus_proxy_get_cached_property (nm
->priv
->proxy
, "Metered");
183 new_network_metered
= FALSE
;
187 new_network_metered
= nm_metered_to_bool (g_variant_get_uint32 (v
));
191 new_network_available
= TRUE
;
192 new_connectivity
= nm_conn_to_g_conn (nm_connectivity
);
197 nm
->priv
->network_metered
= new_network_metered
;
198 nm
->priv
->network_available
= new_network_available
;
199 nm
->priv
->connectivity
= new_connectivity
;
203 if (new_network_available
!= nm
->priv
->network_available
)
205 nm
->priv
->network_available
= new_network_available
;
206 g_object_notify (G_OBJECT (nm
), "network-available");
208 if (new_network_metered
!= nm
->priv
->network_metered
)
210 nm
->priv
->network_metered
= new_network_metered
;
211 g_object_notify (G_OBJECT (nm
), "network-metered");
213 if (new_connectivity
!= nm
->priv
->connectivity
)
215 nm
->priv
->connectivity
= new_connectivity
;
216 g_object_notify (G_OBJECT (nm
), "connectivity");
221 update_cached_property (GDBusProxy
*proxy
,
222 const char *property_name
,
227 v
= g_variant_dict_lookup_value (dict
, property_name
, NULL
);
230 g_dbus_proxy_set_cached_property (proxy
, property_name
, v
);
235 proxy_signal_cb (GDBusProxy
*proxy
,
238 GVariant
*parameters
,
239 GNetworkMonitorNM
*nm
)
244 if (g_strcmp0 (signal_name
, "PropertiesChanged") != 0)
247 g_variant_get (parameters
, "(@a{sv})", &asv
);
251 dict
= g_variant_dict_new (asv
);
252 g_variant_unref (asv
);
255 g_warning ("Failed to handle PropertiesChanged signal from NetworkManager");
259 update_cached_property (nm
->priv
->proxy
, "Connectivity", dict
);
261 g_variant_dict_unref (dict
);
263 sync_properties (nm
, TRUE
);
267 has_property (GDBusProxy
*proxy
,
268 const char *property_name
)
271 gboolean prop_found
= FALSE
;
273 props
= g_dbus_proxy_get_cached_property_names (proxy
);
278 prop_found
= g_strv_contains ((const gchar
* const *) props
, property_name
);
284 g_network_monitor_nm_initable_init (GInitable
*initable
,
285 GCancellable
*cancellable
,
288 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (initable
);
290 GInitableIface
*parent_iface
;
291 gchar
*name_owner
= NULL
;
293 parent_iface
= g_type_interface_peek_parent (G_NETWORK_MONITOR_NM_GET_INITABLE_IFACE (initable
));
294 if (!parent_iface
->init (initable
, cancellable
, error
))
297 proxy
= g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM
,
298 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START
| G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES
,
300 "org.freedesktop.NetworkManager",
301 "/org/freedesktop/NetworkManager",
302 "org.freedesktop.NetworkManager",
308 name_owner
= g_dbus_proxy_get_name_owner (proxy
);
312 g_object_unref (proxy
);
318 /* Verify it has the PrimaryConnection and Connectivity properties */
319 if (!has_property (proxy
, "Connectivity"))
321 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
322 _("NetworkManager version too old"));
323 g_object_unref (proxy
);
327 g_signal_connect (G_OBJECT (proxy
), "g-signal",
328 G_CALLBACK (proxy_signal_cb
), nm
);
329 nm
->priv
->proxy
= proxy
;
330 sync_properties (nm
, FALSE
);
336 g_network_monitor_nm_finalize (GObject
*object
)
338 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (object
);
340 g_clear_object (&nm
->priv
->proxy
);
342 G_OBJECT_CLASS (g_network_monitor_nm_parent_class
)->finalize (object
);
346 g_network_monitor_nm_class_init (GNetworkMonitorNMClass
*nl_class
)
348 GObjectClass
*gobject_class
= G_OBJECT_CLASS (nl_class
);
350 gobject_class
->finalize
= g_network_monitor_nm_finalize
;
351 gobject_class
->get_property
= g_network_monitor_nm_get_property
;
353 g_object_class_override_property (gobject_class
, PROP_NETWORK_AVAILABLE
, "network-available");
354 g_object_class_override_property (gobject_class
, PROP_NETWORK_METERED
, "network-metered");
355 g_object_class_override_property (gobject_class
, PROP_CONNECTIVITY
, "connectivity");
359 g_network_monitor_nm_iface_init (GNetworkMonitorInterface
*monitor_iface
)
364 g_network_monitor_nm_initable_iface_init (GInitableIface
*iface
)
366 iface
->init
= g_network_monitor_nm_initable_init
;