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
);
234 proxy_signal_cb (GDBusProxy
*proxy
,
237 GVariant
*parameters
,
238 GNetworkMonitorNM
*nm
)
243 if (g_strcmp0 (signal_name
, "PropertiesChanged") != 0)
246 g_variant_get (parameters
, "(@a{sv})", &asv
);
250 dict
= g_variant_dict_new (asv
);
253 g_warning ("Failed to handle PropertiesChanged signal from NetworkManager");
257 update_cached_property (nm
->priv
->proxy
, "Connectivity", dict
);
259 g_variant_dict_unref (dict
);
261 sync_properties (nm
, TRUE
);
265 has_property (GDBusProxy
*proxy
,
266 const char *property_name
)
270 gboolean prop_found
= FALSE
;
272 props
= g_dbus_proxy_get_cached_property_names (proxy
);
277 for (i
= 0; props
[i
] != NULL
; i
++)
279 if (g_str_equal (props
[i
], property_name
))
291 g_network_monitor_nm_initable_init (GInitable
*initable
,
292 GCancellable
*cancellable
,
295 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (initable
);
297 GInitableIface
*parent_iface
;
298 gchar
*name_owner
= NULL
;
300 parent_iface
= g_type_interface_peek_parent (G_NETWORK_MONITOR_NM_GET_INITABLE_IFACE (initable
));
301 if (!parent_iface
->init (initable
, cancellable
, error
))
304 proxy
= g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM
,
305 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START
| G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES
,
307 "org.freedesktop.NetworkManager",
308 "/org/freedesktop/NetworkManager",
309 "org.freedesktop.NetworkManager",
315 name_owner
= g_dbus_proxy_get_name_owner (proxy
);
319 g_object_unref (proxy
);
325 /* Verify it has the PrimaryConnection and Connectivity properties */
326 if (!has_property (proxy
, "Connectivity"))
328 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
329 _("NetworkManager version too old"));
330 g_object_unref (proxy
);
334 g_signal_connect (G_OBJECT (proxy
), "g-signal",
335 G_CALLBACK (proxy_signal_cb
), nm
);
336 nm
->priv
->proxy
= proxy
;
337 sync_properties (nm
, FALSE
);
343 g_network_monitor_nm_finalize (GObject
*object
)
345 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (object
);
347 g_clear_object (&nm
->priv
->proxy
);
349 G_OBJECT_CLASS (g_network_monitor_nm_parent_class
)->finalize (object
);
353 g_network_monitor_nm_class_init (GNetworkMonitorNMClass
*nl_class
)
355 GObjectClass
*gobject_class
= G_OBJECT_CLASS (nl_class
);
357 gobject_class
->finalize
= g_network_monitor_nm_finalize
;
358 gobject_class
->get_property
= g_network_monitor_nm_get_property
;
360 g_object_class_override_property (gobject_class
, PROP_NETWORK_AVAILABLE
, "network-available");
361 g_object_class_override_property (gobject_class
, PROP_NETWORK_METERED
, "network-metered");
362 g_object_class_override_property (gobject_class
, PROP_CONNECTIVITY
, "connectivity");
366 g_network_monitor_nm_iface_init (GNetworkMonitorInterface
*monitor_iface
)
371 g_network_monitor_nm_initable_iface_init (GInitableIface
*iface
)
373 iface
->init
= g_network_monitor_nm_initable_init
;