Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright 2016 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 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 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include "config.h"
22 : :
23 : : #include "gnetworkmonitorportal.h"
24 : : #include "ginitable.h"
25 : : #include "giomodule-priv.h"
26 : : #include "xdp-dbus.h"
27 : : #include "gportalsupport.h"
28 : :
29 : : static GInitableIface *initable_parent_iface;
30 : : static void g_network_monitor_portal_iface_init (GNetworkMonitorInterface *iface);
31 : : static void g_network_monitor_portal_initable_iface_init (GInitableIface *iface);
32 : :
33 : : enum
34 : : {
35 : : PROP_0,
36 : : PROP_NETWORK_AVAILABLE,
37 : : PROP_NETWORK_METERED,
38 : : PROP_CONNECTIVITY
39 : : };
40 : :
41 : : struct _GNetworkMonitorPortalPrivate
42 : : {
43 : : GDBusProxy *proxy;
44 : : gboolean has_network;
45 : :
46 : : gboolean available;
47 : : gboolean metered;
48 : : GNetworkConnectivity connectivity;
49 : : };
50 : :
51 : 322 : G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorPortal, g_network_monitor_portal, G_TYPE_NETWORK_MONITOR_BASE,
52 : : G_ADD_PRIVATE (GNetworkMonitorPortal)
53 : : G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR,
54 : : g_network_monitor_portal_iface_init)
55 : : G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
56 : : g_network_monitor_portal_initable_iface_init)
57 : : _g_io_modules_ensure_extension_points_registered ();
58 : : g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME,
59 : : g_define_type_id,
60 : : "portal",
61 : : 40))
62 : :
63 : : static void
64 : 21 : g_network_monitor_portal_init (GNetworkMonitorPortal *nm)
65 : : {
66 : 21 : nm->priv = g_network_monitor_portal_get_instance_private (nm);
67 : 21 : }
68 : :
69 : : static void
70 : 0 : g_network_monitor_portal_get_property (GObject *object,
71 : : guint prop_id,
72 : : GValue *value,
73 : : GParamSpec *pspec)
74 : : {
75 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (object);
76 : :
77 : 0 : switch (prop_id)
78 : : {
79 : 0 : case PROP_NETWORK_AVAILABLE:
80 : 0 : g_value_set_boolean (value, nm->priv->available);
81 : 0 : break;
82 : :
83 : 0 : case PROP_NETWORK_METERED:
84 : 0 : g_value_set_boolean (value, nm->priv->metered);
85 : 0 : break;
86 : :
87 : 0 : case PROP_CONNECTIVITY:
88 : 0 : g_value_set_enum (value, nm->priv->connectivity);
89 : 0 : break;
90 : :
91 : 0 : default:
92 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
93 : 0 : break;
94 : : }
95 : 0 : }
96 : :
97 : : static gboolean
98 : 0 : is_valid_connectivity (guint32 value)
99 : : {
100 : : GEnumValue *enum_value;
101 : : GEnumClass *enum_klass;
102 : :
103 : 0 : enum_klass = g_type_class_ref (G_TYPE_NETWORK_CONNECTIVITY);
104 : 0 : enum_value = g_enum_get_value (enum_klass, value);
105 : :
106 : 0 : g_type_class_unref (enum_klass);
107 : :
108 : 0 : return enum_value != NULL;
109 : : }
110 : :
111 : : static void
112 : 0 : got_available (GObject *source,
113 : : GAsyncResult *res,
114 : : gpointer data)
115 : : {
116 : 0 : GDBusProxy *proxy = G_DBUS_PROXY (source);
117 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data);
118 : 0 : GError *error = NULL;
119 : : GVariant *ret;
120 : : gboolean available;
121 : :
122 : 0 : ret = g_dbus_proxy_call_finish (proxy, res, &error);
123 : 0 : if (ret == NULL)
124 : : {
125 : 0 : if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
126 : : {
127 : 0 : g_warning ("%s", error->message);
128 : 0 : g_clear_error (&error);
129 : 0 : return;
130 : : }
131 : :
132 : 0 : g_clear_error (&error);
133 : :
134 : : /* Fall back to version 1 */
135 : 0 : ret = g_dbus_proxy_get_cached_property (nm->priv->proxy, "available");
136 : 0 : if (ret == NULL)
137 : : {
138 : 0 : g_warning ("Failed to get the '%s' property", "available");
139 : 0 : return;
140 : : }
141 : :
142 : 0 : available = g_variant_get_boolean (ret);
143 : 0 : g_variant_unref (ret);
144 : : }
145 : : else
146 : : {
147 : 0 : g_variant_get (ret, "(b)", &available);
148 : 0 : g_variant_unref (ret);
149 : : }
150 : :
151 : 0 : if (nm->priv->available != available)
152 : : {
153 : 0 : nm->priv->available = available;
154 : 0 : g_object_notify (G_OBJECT (nm), "network-available");
155 : 0 : g_signal_emit_by_name (nm, "network-changed", available);
156 : : }
157 : : }
158 : :
159 : : static void
160 : 0 : got_metered (GObject *source,
161 : : GAsyncResult *res,
162 : : gpointer data)
163 : : {
164 : 0 : GDBusProxy *proxy = G_DBUS_PROXY (source);
165 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data);
166 : 0 : GError *error = NULL;
167 : : GVariant *ret;
168 : : gboolean metered;
169 : :
170 : 0 : ret = g_dbus_proxy_call_finish (proxy, res, &error);
171 : 0 : if (ret == NULL)
172 : : {
173 : 0 : if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
174 : : {
175 : 0 : g_warning ("%s", error->message);
176 : 0 : g_clear_error (&error);
177 : 0 : return;
178 : : }
179 : :
180 : 0 : g_clear_error (&error);
181 : :
182 : : /* Fall back to version 1 */
183 : 0 : ret = g_dbus_proxy_get_cached_property (nm->priv->proxy, "metered");
184 : 0 : if (ret == NULL)
185 : : {
186 : 0 : g_warning ("Failed to get the '%s' property", "metered");
187 : 0 : return;
188 : : }
189 : :
190 : 0 : metered = g_variant_get_boolean (ret);
191 : 0 : g_variant_unref (ret);
192 : : }
193 : : else
194 : : {
195 : 0 : g_variant_get (ret, "(b)", &metered);
196 : 0 : g_variant_unref (ret);
197 : : }
198 : :
199 : 0 : if (nm->priv->metered != metered)
200 : : {
201 : 0 : nm->priv->metered = metered;
202 : 0 : g_object_notify (G_OBJECT (nm), "network-metered");
203 : 0 : g_signal_emit_by_name (nm, "network-changed", nm->priv->available);
204 : : }
205 : : }
206 : :
207 : : static void
208 : 0 : got_connectivity (GObject *source,
209 : : GAsyncResult *res,
210 : : gpointer data)
211 : : {
212 : 0 : GDBusProxy *proxy = G_DBUS_PROXY (source);
213 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data);
214 : 0 : GError *error = NULL;
215 : : GVariant *ret;
216 : : GNetworkConnectivity connectivity;
217 : :
218 : 0 : ret = g_dbus_proxy_call_finish (proxy, res, &error);
219 : 0 : if (ret == NULL)
220 : : {
221 : 0 : if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
222 : : {
223 : 0 : g_warning ("%s", error->message);
224 : 0 : g_clear_error (&error);
225 : 0 : return;
226 : : }
227 : :
228 : 0 : g_clear_error (&error);
229 : :
230 : : /* Fall back to version 1 */
231 : 0 : ret = g_dbus_proxy_get_cached_property (nm->priv->proxy, "connectivity");
232 : 0 : if (ret == NULL)
233 : : {
234 : 0 : g_warning ("Failed to get the '%s' property", "connectivity");
235 : 0 : return;
236 : : }
237 : :
238 : 0 : connectivity = g_variant_get_uint32 (ret);
239 : 0 : g_variant_unref (ret);
240 : : }
241 : : else
242 : : {
243 : 0 : g_variant_get (ret, "(u)", &connectivity);
244 : 0 : g_variant_unref (ret);
245 : : }
246 : :
247 : 0 : if (nm->priv->connectivity != connectivity &&
248 : 0 : is_valid_connectivity (connectivity))
249 : : {
250 : 0 : nm->priv->connectivity = connectivity;
251 : 0 : g_object_notify (G_OBJECT (nm), "connectivity");
252 : 0 : g_signal_emit_by_name (nm, "network-changed", nm->priv->available);
253 : : }
254 : : }
255 : :
256 : : static void
257 : 0 : got_status (GObject *source,
258 : : GAsyncResult *res,
259 : : gpointer data)
260 : : {
261 : 0 : GDBusProxy *proxy = G_DBUS_PROXY (source);
262 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (data);
263 : 0 : GError *error = NULL;
264 : : GVariant *ret;
265 : : GVariant *status;
266 : : gboolean available;
267 : : gboolean metered;
268 : : GNetworkConnectivity connectivity;
269 : :
270 : 0 : ret = g_dbus_proxy_call_finish (proxy, res, &error);
271 : 0 : if (ret == NULL)
272 : : {
273 : 0 : if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
274 : : {
275 : : /* Fall back to version 2 */
276 : 0 : g_dbus_proxy_call (proxy, "GetConnectivity", NULL, 0, -1, NULL, got_connectivity, nm);
277 : 0 : g_dbus_proxy_call (proxy, "GetMetered", NULL, 0, -1, NULL, got_metered, nm);
278 : 0 : g_dbus_proxy_call (proxy, "GetAvailable", NULL, 0, -1, NULL, got_available, nm);
279 : : }
280 : : else
281 : 0 : g_warning ("%s", error->message);
282 : :
283 : 0 : g_clear_error (&error);
284 : 0 : return;
285 : : }
286 : :
287 : 0 : g_variant_get (ret, "(@a{sv})", &status);
288 : 0 : g_variant_unref (ret);
289 : :
290 : 0 : g_variant_lookup (status, "available", "b", &available);
291 : 0 : g_variant_lookup (status, "metered", "b", &metered);
292 : 0 : g_variant_lookup (status, "connectivity", "u", &connectivity);
293 : 0 : g_variant_unref (status);
294 : :
295 : 0 : g_object_freeze_notify (G_OBJECT (nm));
296 : :
297 : 0 : if (nm->priv->available != available)
298 : : {
299 : 0 : nm->priv->available = available;
300 : 0 : g_object_notify (G_OBJECT (nm), "network-available");
301 : : }
302 : :
303 : 0 : if (nm->priv->metered != metered)
304 : : {
305 : 0 : nm->priv->metered = metered;
306 : 0 : g_object_notify (G_OBJECT (nm), "network-metered");
307 : : }
308 : :
309 : 0 : if (nm->priv->connectivity != connectivity &&
310 : 0 : is_valid_connectivity (connectivity))
311 : : {
312 : 0 : nm->priv->connectivity = connectivity;
313 : 0 : g_object_notify (G_OBJECT (nm), "connectivity");
314 : : }
315 : :
316 : 0 : g_object_thaw_notify (G_OBJECT (nm));
317 : :
318 : 0 : g_signal_emit_by_name (nm, "network-changed", available);
319 : : }
320 : :
321 : : static void
322 : 0 : update_properties (GDBusProxy *proxy,
323 : : GNetworkMonitorPortal *nm)
324 : : {
325 : : /* Try version 3 first */
326 : 0 : g_dbus_proxy_call (proxy, "GetStatus", NULL, 0, -1, NULL, got_status, nm);
327 : 0 : }
328 : :
329 : : static void
330 : 0 : proxy_signal (GDBusProxy *proxy,
331 : : const char *sender,
332 : : const char *signal,
333 : : GVariant *parameters,
334 : : GNetworkMonitorPortal *nm)
335 : : {
336 : 0 : if (!nm->priv->has_network)
337 : 0 : return;
338 : :
339 : 0 : if (strcmp (signal, "changed") != 0)
340 : 0 : return;
341 : :
342 : : /* Version 1 updates "available" with the "changed" signal */
343 : 0 : if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(b)")))
344 : : {
345 : : gboolean available;
346 : :
347 : 0 : g_variant_get (parameters, "(b)", &available);
348 : 0 : if (nm->priv->available != available)
349 : : {
350 : 0 : nm->priv->available = available;
351 : 0 : g_object_notify (G_OBJECT (nm), "available");
352 : : }
353 : 0 : g_signal_emit_by_name (nm, "network-changed", available);
354 : : }
355 : : else
356 : : {
357 : 0 : update_properties (proxy, nm);
358 : : }
359 : : }
360 : :
361 : : static void
362 : 0 : proxy_properties_changed (GDBusProxy *proxy,
363 : : GVariant *changed,
364 : : GVariant *invalidated,
365 : : GNetworkMonitorPortal *nm)
366 : : {
367 : 0 : gboolean should_emit_changed = FALSE;
368 : : GVariant *ret;
369 : :
370 : 0 : if (!nm->priv->has_network)
371 : 0 : return;
372 : :
373 : 0 : ret = g_dbus_proxy_get_cached_property (proxy, "connectivity");
374 : 0 : if (ret)
375 : : {
376 : 0 : GNetworkConnectivity connectivity = g_variant_get_uint32 (ret);
377 : 0 : if (nm->priv->connectivity != connectivity &&
378 : 0 : is_valid_connectivity (connectivity))
379 : : {
380 : 0 : nm->priv->connectivity = connectivity;
381 : 0 : g_object_notify (G_OBJECT (nm), "connectivity");
382 : 0 : should_emit_changed = TRUE;
383 : : }
384 : 0 : g_variant_unref (ret);
385 : : }
386 : :
387 : 0 : ret = g_dbus_proxy_get_cached_property (proxy, "metered");
388 : 0 : if (ret)
389 : : {
390 : 0 : gboolean metered = g_variant_get_boolean (ret);
391 : 0 : if (nm->priv->metered != metered)
392 : : {
393 : 0 : nm->priv->metered = metered;
394 : 0 : g_object_notify (G_OBJECT (nm), "network-metered");
395 : 0 : should_emit_changed = TRUE;
396 : : }
397 : 0 : g_variant_unref (ret);
398 : : }
399 : :
400 : 0 : ret = g_dbus_proxy_get_cached_property (proxy, "available");
401 : 0 : if (ret)
402 : : {
403 : 0 : gboolean available = g_variant_get_boolean (ret);
404 : 0 : if (nm->priv->available != available)
405 : : {
406 : 0 : nm->priv->available = available;
407 : 0 : g_object_notify (G_OBJECT (nm), "network-available");
408 : 0 : should_emit_changed = TRUE;
409 : : }
410 : 0 : g_variant_unref (ret);
411 : : }
412 : :
413 : 0 : if (should_emit_changed)
414 : 0 : g_signal_emit_by_name (nm, "network-changed", nm->priv->available);
415 : : }
416 : :
417 : : static gboolean
418 : 21 : g_network_monitor_portal_initable_init (GInitable *initable,
419 : : GCancellable *cancellable,
420 : : GError **error)
421 : : {
422 : 21 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (initable);
423 : : GDBusProxy *proxy;
424 : 21 : gchar *name_owner = NULL;
425 : :
426 : 21 : nm->priv->available = FALSE;
427 : 21 : nm->priv->metered = FALSE;
428 : 21 : nm->priv->connectivity = G_NETWORK_CONNECTIVITY_LOCAL;
429 : :
430 : 21 : if (!glib_should_use_portal ())
431 : : {
432 : 21 : g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not using portals");
433 : 21 : return FALSE;
434 : : }
435 : :
436 : 0 : proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
437 : : G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
438 : : NULL,
439 : : "org.freedesktop.portal.Desktop",
440 : : "/org/freedesktop/portal/desktop",
441 : : "org.freedesktop.portal.NetworkMonitor",
442 : : cancellable,
443 : : error);
444 : 0 : if (!proxy)
445 : 0 : return FALSE;
446 : :
447 : 0 : name_owner = g_dbus_proxy_get_name_owner (proxy);
448 : :
449 : 0 : if (!name_owner)
450 : : {
451 : 0 : g_object_unref (proxy);
452 : 0 : g_set_error (error,
453 : : G_DBUS_ERROR,
454 : : G_DBUS_ERROR_NAME_HAS_NO_OWNER,
455 : : "Desktop portal not found");
456 : 0 : return FALSE;
457 : : }
458 : :
459 : 0 : g_free (name_owner);
460 : :
461 : 0 : g_signal_connect (proxy, "g-signal", G_CALLBACK (proxy_signal), nm);
462 : 0 : g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (proxy_properties_changed), nm);
463 : :
464 : 0 : nm->priv->proxy = proxy;
465 : 0 : nm->priv->has_network = glib_network_available_in_sandbox ();
466 : :
467 : 0 : if (!initable_parent_iface->init (initable, cancellable, error))
468 : 0 : return FALSE;
469 : :
470 : 0 : if (nm->priv->has_network)
471 : 0 : update_properties (proxy, nm);
472 : :
473 : 0 : return TRUE;
474 : : }
475 : :
476 : : static void
477 : 21 : g_network_monitor_portal_finalize (GObject *object)
478 : : {
479 : 21 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (object);
480 : :
481 : 21 : g_clear_object (&nm->priv->proxy);
482 : :
483 : 21 : G_OBJECT_CLASS (g_network_monitor_portal_parent_class)->finalize (object);
484 : 21 : }
485 : :
486 : : static void
487 : 21 : g_network_monitor_portal_class_init (GNetworkMonitorPortalClass *class)
488 : : {
489 : 21 : GObjectClass *gobject_class = G_OBJECT_CLASS (class);
490 : :
491 : 21 : gobject_class->finalize = g_network_monitor_portal_finalize;
492 : 21 : gobject_class->get_property = g_network_monitor_portal_get_property;
493 : :
494 : 21 : g_object_class_override_property (gobject_class, PROP_NETWORK_AVAILABLE, "network-available");
495 : 21 : g_object_class_override_property (gobject_class, PROP_NETWORK_METERED, "network-metered");
496 : 21 : g_object_class_override_property (gobject_class, PROP_CONNECTIVITY, "connectivity");
497 : 21 : }
498 : :
499 : : static gboolean
500 : 0 : g_network_monitor_portal_can_reach (GNetworkMonitor *monitor,
501 : : GSocketConnectable *connectable,
502 : : GCancellable *cancellable,
503 : : GError **error)
504 : : {
505 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (monitor);
506 : : GVariant *ret;
507 : : GNetworkAddress *address;
508 : 0 : gboolean reachable = FALSE;
509 : :
510 : 0 : if (!G_IS_NETWORK_ADDRESS (connectable))
511 : : {
512 : 0 : g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
513 : : "Can't handle this kind of GSocketConnectable (%s)",
514 : 0 : G_OBJECT_TYPE_NAME (connectable));
515 : 0 : return FALSE;
516 : : }
517 : :
518 : 0 : address = G_NETWORK_ADDRESS (connectable);
519 : :
520 : 0 : ret = g_dbus_proxy_call_sync (nm->priv->proxy,
521 : : "CanReach",
522 : : g_variant_new ("(su)",
523 : : g_network_address_get_hostname (address),
524 : 0 : g_network_address_get_port (address)),
525 : : G_DBUS_CALL_FLAGS_NONE,
526 : : -1,
527 : : cancellable,
528 : : error);
529 : :
530 : 0 : if (ret)
531 : : {
532 : 0 : g_variant_get (ret, "(b)", &reachable);
533 : 0 : g_variant_unref (ret);
534 : : }
535 : :
536 : 0 : return reachable;
537 : : }
538 : :
539 : : static void
540 : 0 : can_reach_done (GObject *source,
541 : : GAsyncResult *result,
542 : : gpointer data)
543 : : {
544 : 0 : GTask *task = data;
545 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (g_task_get_source_object (task));
546 : 0 : GError *error = NULL;
547 : : GVariant *ret;
548 : : gboolean reachable;
549 : :
550 : 0 : ret = g_dbus_proxy_call_finish (nm->priv->proxy, result, &error);
551 : 0 : if (ret == NULL)
552 : : {
553 : 0 : g_task_return_error (task, error);
554 : 0 : g_object_unref (task);
555 : 0 : return;
556 : : }
557 : :
558 : 0 : g_variant_get (ret, "(b)", &reachable);
559 : 0 : g_variant_unref (ret);
560 : :
561 : 0 : if (reachable)
562 : 0 : g_task_return_boolean (task, TRUE);
563 : : else
564 : 0 : g_task_return_new_error_literal (task,
565 : : G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
566 : : "Can't reach host");
567 : :
568 : 0 : g_object_unref (task);
569 : : }
570 : :
571 : : static void
572 : 0 : g_network_monitor_portal_can_reach_async (GNetworkMonitor *monitor,
573 : : GSocketConnectable *connectable,
574 : : GCancellable *cancellable,
575 : : GAsyncReadyCallback callback,
576 : : gpointer data)
577 : : {
578 : 0 : GNetworkMonitorPortal *nm = G_NETWORK_MONITOR_PORTAL (monitor);
579 : : GTask *task;
580 : : GNetworkAddress *address;
581 : :
582 : 0 : task = g_task_new (monitor, cancellable, callback, data);
583 : :
584 : 0 : if (!G_IS_NETWORK_ADDRESS (connectable))
585 : : {
586 : 0 : g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
587 : : "Can't handle this kind of GSocketConnectable (%s)",
588 : 0 : G_OBJECT_TYPE_NAME (connectable));
589 : 0 : g_object_unref (task);
590 : 0 : return;
591 : : }
592 : :
593 : 0 : address = G_NETWORK_ADDRESS (connectable);
594 : :
595 : 0 : g_dbus_proxy_call (nm->priv->proxy,
596 : : "CanReach",
597 : : g_variant_new ("(su)",
598 : : g_network_address_get_hostname (address),
599 : 0 : g_network_address_get_port (address)),
600 : : G_DBUS_CALL_FLAGS_NONE,
601 : : -1,
602 : : cancellable,
603 : : can_reach_done,
604 : : task);
605 : : }
606 : :
607 : : static gboolean
608 : 0 : g_network_monitor_portal_can_reach_finish (GNetworkMonitor *monitor,
609 : : GAsyncResult *result,
610 : : GError **error)
611 : : {
612 : 0 : return g_task_propagate_boolean (G_TASK (result), error);
613 : : }
614 : :
615 : : static void
616 : 21 : g_network_monitor_portal_iface_init (GNetworkMonitorInterface *monitor_iface)
617 : : {
618 : 21 : monitor_iface->can_reach = g_network_monitor_portal_can_reach;
619 : 21 : monitor_iface->can_reach_async = g_network_monitor_portal_can_reach_async;
620 : 21 : monitor_iface->can_reach_finish = g_network_monitor_portal_can_reach_finish;
621 : 21 : }
622 : :
623 : : static void
624 : 21 : g_network_monitor_portal_initable_iface_init (GInitableIface *iface)
625 : : {
626 : 21 : initable_parent_iface = g_type_interface_peek_parent (iface);
627 : :
628 : 21 : iface->init = g_network_monitor_portal_initable_init;
629 : 21 : }
|