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 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");
164 nm_connectivity
= g_variant_get_uint32 (v
);
167 if (nm_connectivity
== NM_CONNECTIVITY_NONE
)
169 new_network_available
= FALSE
;
170 new_network_metered
= FALSE
;
171 new_connectivity
= G_NETWORK_CONNECTIVITY_LOCAL
;
176 /* this is only available post NM 1.0 */
177 v
= g_dbus_proxy_get_cached_property (nm
->priv
->proxy
, "Metered");
180 new_network_metered
= FALSE
;
184 new_network_metered
= nm_metered_to_bool (g_variant_get_uint32 (v
));
188 new_network_available
= TRUE
;
189 new_connectivity
= nm_conn_to_g_conn (nm_connectivity
);
194 nm
->priv
->network_metered
= new_network_metered
;
195 nm
->priv
->network_available
= new_network_available
;
196 nm
->priv
->connectivity
= new_connectivity
;
200 if (new_network_available
!= nm
->priv
->network_available
)
202 nm
->priv
->network_available
= new_network_available
;
203 g_object_notify (G_OBJECT (nm
), "network-available");
205 if (new_network_metered
!= nm
->priv
->network_metered
)
207 nm
->priv
->network_metered
= new_network_metered
;
208 g_object_notify (G_OBJECT (nm
), "network-metered");
210 if (new_connectivity
!= nm
->priv
->connectivity
)
212 nm
->priv
->connectivity
= new_connectivity
;
213 g_object_notify (G_OBJECT (nm
), "connectivity");
218 update_cached_property (GDBusProxy
*proxy
,
219 const char *property_name
,
224 v
= g_variant_dict_lookup_value (dict
, property_name
, NULL
);
227 g_dbus_proxy_set_cached_property (proxy
, property_name
, v
);
231 proxy_signal_cb (GDBusProxy
*proxy
,
234 GVariant
*parameters
,
235 GNetworkMonitorNM
*nm
)
240 if (g_strcmp0 (signal_name
, "PropertiesChanged") != 0)
243 g_variant_get (parameters
, "(@a{sv})", &asv
);
247 dict
= g_variant_dict_new (asv
);
250 g_warning ("Failed to handle PropertiesChanged signal from NetworkManager");
254 update_cached_property (nm
->priv
->proxy
, "Connectivity", dict
);
256 g_variant_dict_unref (dict
);
258 sync_properties (nm
, TRUE
);
262 has_property (GDBusProxy
*proxy
,
263 const char *property_name
)
267 gboolean prop_found
= FALSE
;
269 props
= g_dbus_proxy_get_cached_property_names (proxy
);
274 for (i
= 0; props
[i
] != NULL
; i
++)
276 if (g_str_equal (props
[i
], property_name
))
288 g_network_monitor_nm_initable_init (GInitable
*initable
,
289 GCancellable
*cancellable
,
292 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (initable
);
294 GInitableIface
*parent_iface
;
295 gchar
*name_owner
= NULL
;
297 parent_iface
= g_type_interface_peek_parent (G_NETWORK_MONITOR_NM_GET_INITABLE_IFACE (initable
));
298 if (!parent_iface
->init (initable
, cancellable
, error
))
301 proxy
= g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM
,
302 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START
| G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES
,
304 "org.freedesktop.NetworkManager",
305 "/org/freedesktop/NetworkManager",
306 "org.freedesktop.NetworkManager",
312 name_owner
= g_dbus_proxy_get_name_owner (proxy
);
316 g_object_unref (proxy
);
322 /* Verify it has the PrimaryConnection and Connectivity properties */
323 if (!has_property (proxy
, "Connectivity"))
325 g_set_error (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
326 _("NetworkManager version too old"));
327 g_object_unref (proxy
);
331 g_signal_connect (G_OBJECT (proxy
), "g-signal",
332 G_CALLBACK (proxy_signal_cb
), nm
);
333 nm
->priv
->proxy
= proxy
;
334 sync_properties (nm
, FALSE
);
340 g_network_monitor_nm_finalize (GObject
*object
)
342 GNetworkMonitorNM
*nm
= G_NETWORK_MONITOR_NM (object
);
344 g_clear_object (&nm
->priv
->proxy
);
346 G_OBJECT_CLASS (g_network_monitor_nm_parent_class
)->finalize (object
);
350 g_network_monitor_nm_class_init (GNetworkMonitorNMClass
*nl_class
)
352 GObjectClass
*gobject_class
= G_OBJECT_CLASS (nl_class
);
354 gobject_class
->finalize
= g_network_monitor_nm_finalize
;
355 gobject_class
->get_property
= g_network_monitor_nm_get_property
;
357 g_object_class_override_property (gobject_class
, PROP_NETWORK_AVAILABLE
, "network-available");
358 g_object_class_override_property (gobject_class
, PROP_NETWORK_METERED
, "network-metered");
359 g_object_class_override_property (gobject_class
, PROP_CONNECTIVITY
, "connectivity");
363 g_network_monitor_nm_iface_init (GNetworkMonitorInterface
*monitor_iface
)
368 g_network_monitor_nm_initable_iface_init (GInitableIface
*iface
)
370 iface
->init
= g_network_monitor_nm_initable_init
;