2014-07-24 12:53:33 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301 USA.
|
|
|
|
*
|
|
|
|
* Copyright 2013 Red Hat, Inc.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <config.h>
|
|
|
|
#include <gio/gio.h>
|
2014-08-19 13:52:41 +00:00
|
|
|
#include "nm-dbus-helpers.h"
|
2014-07-05 20:23:30 +00:00
|
|
|
#include "nm-dbus-interface.h"
|
2014-07-24 12:53:33 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
static GBusType nm_bus = G_BUS_TYPE_SYSTEM;
|
2014-07-24 12:53:33 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
GBusType
|
|
|
|
_nm_dbus_bus_type (void)
|
2014-07-24 12:53:33 +00:00
|
|
|
{
|
|
|
|
static gsize init_value = 0;
|
|
|
|
|
|
|
|
if (g_once_init_enter (&init_value)) {
|
2014-09-05 16:55:18 +00:00
|
|
|
if (g_getenv ("LIBNM_USE_SESSION_BUS"))
|
2014-09-10 17:51:53 +00:00
|
|
|
nm_bus = G_BUS_TYPE_SESSION;
|
2014-09-05 16:55:18 +00:00
|
|
|
|
2014-07-24 12:53:33 +00:00
|
|
|
g_once_init_leave (&init_value, 1);
|
|
|
|
}
|
2014-09-10 17:51:53 +00:00
|
|
|
|
|
|
|
return nm_bus;
|
2014-07-24 12:53:33 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 15:48:06 +00:00
|
|
|
static struct {
|
|
|
|
GMutex mutex;
|
|
|
|
GWeakRef weak_ref;
|
|
|
|
} private_connection;
|
|
|
|
|
|
|
|
static void
|
|
|
|
_private_dbus_connection_closed_cb (GDBusConnection *connection,
|
|
|
|
gboolean remote_peer_vanished,
|
|
|
|
GError *error,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GDBusConnection *p;
|
|
|
|
|
|
|
|
g_mutex_lock (&private_connection.mutex);
|
|
|
|
p = g_weak_ref_get (&private_connection.weak_ref);
|
|
|
|
if (connection == p) {
|
|
|
|
g_signal_handlers_disconnect_by_func (G_OBJECT (connection), G_CALLBACK (_private_dbus_connection_closed_cb), NULL);
|
|
|
|
g_weak_ref_set (&private_connection.weak_ref, NULL);
|
|
|
|
}
|
|
|
|
if (p)
|
|
|
|
g_object_unref (p);
|
|
|
|
g_mutex_unlock (&private_connection.mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GDBusConnection *
|
|
|
|
_private_dbus_connection_internalize (GDBusConnection *connection)
|
|
|
|
{
|
|
|
|
GDBusConnection *p;
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
|
|
|
|
g_return_val_if_fail (!g_dbus_connection_is_closed (connection), NULL);
|
|
|
|
|
|
|
|
g_mutex_lock (&private_connection.mutex);
|
|
|
|
p = g_weak_ref_get (&private_connection.weak_ref);
|
|
|
|
if (p) {
|
|
|
|
g_object_unref (connection);
|
|
|
|
connection = p;
|
|
|
|
} else {
|
|
|
|
g_weak_ref_set (&private_connection.weak_ref, connection);
|
|
|
|
g_signal_connect (connection, "closed", G_CALLBACK (_private_dbus_connection_closed_cb), NULL);
|
|
|
|
}
|
|
|
|
g_mutex_unlock (&private_connection.mutex);
|
|
|
|
return connection;
|
|
|
|
}
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
GDBusConnection *
|
|
|
|
_nm_dbus_new_connection (GCancellable *cancellable, GError **error)
|
2014-07-24 12:53:33 +00:00
|
|
|
{
|
2014-09-10 17:51:53 +00:00
|
|
|
GDBusConnection *connection = NULL;
|
2014-07-24 12:53:33 +00:00
|
|
|
|
|
|
|
/* If running as root try the private bus first */
|
2014-09-10 17:51:53 +00:00
|
|
|
if (0 == geteuid ()) {
|
|
|
|
GError *local = NULL;
|
2014-09-30 15:48:06 +00:00
|
|
|
GDBusConnection *p;
|
|
|
|
|
|
|
|
p = g_weak_ref_get (&private_connection.weak_ref);
|
|
|
|
if (p)
|
|
|
|
return p;
|
2014-07-24 12:53:33 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private",
|
|
|
|
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
|
|
|
|
NULL, cancellable, &local);
|
2014-09-19 14:45:12 +00:00
|
|
|
if (connection)
|
2014-09-30 15:48:06 +00:00
|
|
|
return _private_dbus_connection_internalize (connection);
|
2014-09-10 17:51:53 +00:00
|
|
|
|
|
|
|
if (g_error_matches (local, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
|
|
g_propagate_error (error, local);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
g_error_free (local);
|
2014-07-24 12:53:33 +00:00
|
|
|
}
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
return g_bus_get_sync (_nm_dbus_bus_type (), cancellable, error);
|
|
|
|
}
|
2014-07-24 12:53:33 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
static void
|
|
|
|
new_connection_async_got_system (GObject *source, GAsyncResult *result, gpointer user_data)
|
|
|
|
{
|
|
|
|
GSimpleAsyncResult *simple = user_data;
|
|
|
|
GDBusConnection *connection;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
connection = g_bus_get_finish (result, &error);
|
|
|
|
if (connection)
|
|
|
|
g_simple_async_result_set_op_res_gpointer (simple, connection, g_object_unref);
|
|
|
|
else
|
|
|
|
g_simple_async_result_take_error (simple, error);
|
|
|
|
|
|
|
|
g_simple_async_result_complete (simple);
|
|
|
|
g_object_unref (simple);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
new_connection_async_got_private (GObject *source, GAsyncResult *result, gpointer user_data)
|
|
|
|
{
|
|
|
|
GSimpleAsyncResult *simple = user_data;
|
|
|
|
GDBusConnection *connection;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
connection = g_dbus_connection_new_for_address_finish (result, &error);
|
|
|
|
if (connection) {
|
2014-09-30 15:48:06 +00:00
|
|
|
connection = _private_dbus_connection_internalize (connection);
|
2014-09-10 17:51:53 +00:00
|
|
|
g_simple_async_result_set_op_res_gpointer (simple, connection, g_object_unref);
|
|
|
|
g_simple_async_result_complete (simple);
|
|
|
|
g_object_unref (simple);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
|
|
g_simple_async_result_take_error (simple, error);
|
|
|
|
g_simple_async_result_complete (simple);
|
|
|
|
g_object_unref (simple);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
g_bus_get (_nm_dbus_bus_type (),
|
|
|
|
g_object_get_data (G_OBJECT (simple), "cancellable"),
|
|
|
|
new_connection_async_got_system, simple);
|
2014-07-24 12:53:33 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 15:48:06 +00:00
|
|
|
static void
|
|
|
|
_nm_dbus_new_connection_async_do (GSimpleAsyncResult *simple, GCancellable *cancellable)
|
|
|
|
{
|
|
|
|
g_dbus_connection_new_for_address ("unix:path=" NMRUNDIR "/private",
|
|
|
|
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
|
|
|
|
NULL,
|
|
|
|
cancellable,
|
|
|
|
new_connection_async_got_private, simple);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_nm_dbus_new_connection_async_get_private (gpointer user_data)
|
|
|
|
{
|
|
|
|
GSimpleAsyncResult *simple = user_data;
|
|
|
|
GDBusConnection *p;
|
|
|
|
|
|
|
|
p = g_weak_ref_get (&private_connection.weak_ref);
|
|
|
|
if (!p) {
|
|
|
|
/* The connection is gone. Create a new one async... */
|
|
|
|
_nm_dbus_new_connection_async_do (simple,
|
|
|
|
g_object_get_data (G_OBJECT (simple), "cancellable"));
|
|
|
|
} else {
|
|
|
|
g_simple_async_result_set_op_res_gpointer (simple, p, g_object_unref);
|
|
|
|
g_simple_async_result_complete (simple);
|
|
|
|
g_object_unref (simple);
|
|
|
|
}
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
2014-09-10 13:29:51 +00:00
|
|
|
void
|
|
|
|
_nm_dbus_new_connection_async (GCancellable *cancellable,
|
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GSimpleAsyncResult *simple;
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
simple = g_simple_async_result_new (NULL, callback, user_data, _nm_dbus_new_connection_async);
|
2014-09-10 13:29:51 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
/* If running as root try the private bus first */
|
|
|
|
if (0 == geteuid ()) {
|
2014-09-30 15:48:06 +00:00
|
|
|
GDBusConnection *p;
|
|
|
|
|
libnm: avoid init_async NULL dereference on cancellable=0x0
(gdb) run c add type bond
Starting program: /usr/bin/nmcli c add type bond
Got object file from memory but can't read symbols: File truncated.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff39b2700 (LWP 13042)]
[New Thread 0x7fffec4bc700 (LWP 13043)]
(process:13038): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x7ffff5cda224 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd290) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff59b6c70 in g_logv (log_domain=0x7ffff5cda224 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd290) at gmessages.c:1046
#1 0x00007ffff59b6eaf in g_log (log_domain=log_domain@entry=0x7ffff5cda224 "GLib-GObject", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff5a25a9d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff59b6ee9 in g_return_if_fail_warning (log_domain=log_domain@entry=0x7ffff5cda224 "GLib-GObject", pretty_function=pretty_function@entry=0x7ffff5cdd6b3 <__FUNCTION__.13314> "g_object_ref", expression=expression@entry=0x7ffff5cdc388 "G_IS_OBJECT (object)") at gmessages.c:1088
#3 0x00007ffff5cb39aa in g_object_ref (_object=_object@entry=0x0) at gobject.c:3041
#4 0x00007ffff7ad5418 in _nm_dbus_new_connection_async (cancellable=0x0, callback=<optimized out>, user_data=<optimized out>) at nm-dbus-helpers.c:131
#5 0x00007ffff7ae58f1 in handle_property_changed (synchronously=0, pi=0x5555558a9610, value=0x7fffe40138a0, property_name=<optimized out>, self=0x555555831980 [NMRemoteSettings]) at nm-object.c:1115
#6 0x00007ffff7ae58f1 in handle_property_changed (self=self@entry=0x555555831980 [NMRemoteSettings], dbus_name=<optimized out>, value=<optimized out>, synchronously=synchronously@entry=0) at nm-object.c:1186
#7 0x00007ffff7ae59cb in process_properties_changed (self=0x555555831980 [NMRemoteSettings], properties=<optimized out>, synchronously=0) at nm-object.c:1218
#8 0x00007ffff7ae5a7a in property_proxy_signal (proxy=<optimized out>, sender_name=<optimized out>, signal_name=<optimized out>, parameters=<optimized out>, user_data=0x555555831980) at nm-object.c:1234
#9 0x00007ffff4d34d60 in ffi_call_unix64 () at ../src/x86/unix64.S:76
#10 0x00007ffff4d347d1 in ffi_call (cif=cif@entry=0x7fffffffd7e0, fn=<optimized out>, rvalue=0x7fffffffd740, avalue=avalue@entry=0x7fffffffd6c0) at ../src/x86/ffi64.c:525
#15 0x00007ffff5cca2ef in <emit signal ??? on instance 0x555555881c10 [NMDBusSettingsProxy]> (instance=instance@entry=0x555555881c10, signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3365
#11 0x00007ffff5caf6f4 in g_cclosure_marshal_generic (closure=0x5555558aa400, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1448
#12 0x00007ffff5caeed5 in g_closure_invoke (closure=0x5555558aa400, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fffffffda10, invocation_hint=invocation_hint@entry=0x7fffffffd9b0) at gclosure.c:768
#13 0x00007ffff5cc1202 in signal_emit_unlocked_R (node=node@entry=0x555555819270, detail=detail@entry=0, instance=instance@entry=0x555555881c10, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffda10) at gsignal.c:3553
#14 0x00007ffff5cca0c1 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffdbd0) at gsignal.c:3309
#16 0x00007ffff63d8bcc in on_signal_received (connection=<optimized out>, sender_name=0x0, object_path=<optimized out>, interface_name=<optimized out>, signal_name=0x7fffe40195b0 "PropertiesChanged", parameters=0x7fffe4031000, user_data=0x5555558a3f30) at gdbusproxy.c:917
#17 0x00007ffff63c83b4 in emit_signal_instance_in_idle_cb (data=0x7fffe403a6d0) at gdbusconnection.c:3753
#18 0x00007ffff59afb6b in g_main_context_dispatch (context=0x5555557eb530) at gmain.c:3064
#19 0x00007ffff59afb6b in g_main_context_dispatch (context=context@entry=0x5555557eb530) at gmain.c:3663
#20 0x00007ffff59aff08 in g_main_context_iterate (context=0x5555557eb530, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3734
#21 0x00007ffff59b0232 in g_main_loop_run (loop=0x5555557e3440) at gmain.c:3928
#22 0x000055555556fd57 in main (argc=<optimized out>, argv=<optimized out>) at nmcli.c:587
(gdb)
https://bugzilla.gnome.org/show_bug.cgi?id=736962
2014-09-19 11:21:27 +00:00
|
|
|
if (cancellable) {
|
|
|
|
g_object_set_data_full (G_OBJECT (simple), "cancellable",
|
2014-09-30 15:48:06 +00:00
|
|
|
g_object_ref (cancellable), g_object_unref);
|
libnm: avoid init_async NULL dereference on cancellable=0x0
(gdb) run c add type bond
Starting program: /usr/bin/nmcli c add type bond
Got object file from memory but can't read symbols: File truncated.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff39b2700 (LWP 13042)]
[New Thread 0x7fffec4bc700 (LWP 13043)]
(process:13038): GLib-GObject-CRITICAL **: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x7ffff5cda224 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd290) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff59b6c70 in g_logv (log_domain=0x7ffff5cda224 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd290) at gmessages.c:1046
#1 0x00007ffff59b6eaf in g_log (log_domain=log_domain@entry=0x7ffff5cda224 "GLib-GObject", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff5a25a9d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff59b6ee9 in g_return_if_fail_warning (log_domain=log_domain@entry=0x7ffff5cda224 "GLib-GObject", pretty_function=pretty_function@entry=0x7ffff5cdd6b3 <__FUNCTION__.13314> "g_object_ref", expression=expression@entry=0x7ffff5cdc388 "G_IS_OBJECT (object)") at gmessages.c:1088
#3 0x00007ffff5cb39aa in g_object_ref (_object=_object@entry=0x0) at gobject.c:3041
#4 0x00007ffff7ad5418 in _nm_dbus_new_connection_async (cancellable=0x0, callback=<optimized out>, user_data=<optimized out>) at nm-dbus-helpers.c:131
#5 0x00007ffff7ae58f1 in handle_property_changed (synchronously=0, pi=0x5555558a9610, value=0x7fffe40138a0, property_name=<optimized out>, self=0x555555831980 [NMRemoteSettings]) at nm-object.c:1115
#6 0x00007ffff7ae58f1 in handle_property_changed (self=self@entry=0x555555831980 [NMRemoteSettings], dbus_name=<optimized out>, value=<optimized out>, synchronously=synchronously@entry=0) at nm-object.c:1186
#7 0x00007ffff7ae59cb in process_properties_changed (self=0x555555831980 [NMRemoteSettings], properties=<optimized out>, synchronously=0) at nm-object.c:1218
#8 0x00007ffff7ae5a7a in property_proxy_signal (proxy=<optimized out>, sender_name=<optimized out>, signal_name=<optimized out>, parameters=<optimized out>, user_data=0x555555831980) at nm-object.c:1234
#9 0x00007ffff4d34d60 in ffi_call_unix64 () at ../src/x86/unix64.S:76
#10 0x00007ffff4d347d1 in ffi_call (cif=cif@entry=0x7fffffffd7e0, fn=<optimized out>, rvalue=0x7fffffffd740, avalue=avalue@entry=0x7fffffffd6c0) at ../src/x86/ffi64.c:525
#15 0x00007ffff5cca2ef in <emit signal ??? on instance 0x555555881c10 [NMDBusSettingsProxy]> (instance=instance@entry=0x555555881c10, signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3365
#11 0x00007ffff5caf6f4 in g_cclosure_marshal_generic (closure=0x5555558aa400, return_gvalue=0x0, n_param_values=<optimized out>, param_values=<optimized out>, invocation_hint=<optimized out>, marshal_data=0x0) at gclosure.c:1448
#12 0x00007ffff5caeed5 in g_closure_invoke (closure=0x5555558aa400, return_value=return_value@entry=0x0, n_param_values=4, param_values=param_values@entry=0x7fffffffda10, invocation_hint=invocation_hint@entry=0x7fffffffd9b0) at gclosure.c:768
#13 0x00007ffff5cc1202 in signal_emit_unlocked_R (node=node@entry=0x555555819270, detail=detail@entry=0, instance=instance@entry=0x555555881c10, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffda10) at gsignal.c:3553
#14 0x00007ffff5cca0c1 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffdbd0) at gsignal.c:3309
#16 0x00007ffff63d8bcc in on_signal_received (connection=<optimized out>, sender_name=0x0, object_path=<optimized out>, interface_name=<optimized out>, signal_name=0x7fffe40195b0 "PropertiesChanged", parameters=0x7fffe4031000, user_data=0x5555558a3f30) at gdbusproxy.c:917
#17 0x00007ffff63c83b4 in emit_signal_instance_in_idle_cb (data=0x7fffe403a6d0) at gdbusconnection.c:3753
#18 0x00007ffff59afb6b in g_main_context_dispatch (context=0x5555557eb530) at gmain.c:3064
#19 0x00007ffff59afb6b in g_main_context_dispatch (context=context@entry=0x5555557eb530) at gmain.c:3663
#20 0x00007ffff59aff08 in g_main_context_iterate (context=0x5555557eb530, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3734
#21 0x00007ffff59b0232 in g_main_loop_run (loop=0x5555557e3440) at gmain.c:3928
#22 0x000055555556fd57 in main (argc=<optimized out>, argv=<optimized out>) at nmcli.c:587
(gdb)
https://bugzilla.gnome.org/show_bug.cgi?id=736962
2014-09-19 11:21:27 +00:00
|
|
|
}
|
2014-09-30 15:48:06 +00:00
|
|
|
p = g_weak_ref_get (&private_connection.weak_ref);
|
|
|
|
if (p) {
|
|
|
|
g_object_unref (p);
|
|
|
|
g_idle_add (_nm_dbus_new_connection_async_get_private, simple);
|
|
|
|
} else
|
|
|
|
_nm_dbus_new_connection_async_do (simple, cancellable);
|
2014-09-10 17:51:53 +00:00
|
|
|
} else {
|
|
|
|
g_bus_get (_nm_dbus_bus_type (),
|
|
|
|
cancellable,
|
|
|
|
new_connection_async_got_system, simple);
|
|
|
|
}
|
2014-09-10 13:29:51 +00:00
|
|
|
}
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
GDBusConnection *
|
2014-09-10 13:29:51 +00:00
|
|
|
_nm_dbus_new_connection_finish (GAsyncResult *result,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
|
|
|
|
|
|
|
|
if (g_simple_async_result_propagate_error (simple, error))
|
|
|
|
return NULL;
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
|
2014-09-10 13:29:51 +00:00
|
|
|
}
|
|
|
|
|
2014-07-24 12:53:33 +00:00
|
|
|
gboolean
|
2014-09-10 17:51:53 +00:00
|
|
|
_nm_dbus_is_connection_private (GDBusConnection *connection)
|
2014-07-24 12:53:33 +00:00
|
|
|
{
|
2014-09-19 14:45:12 +00:00
|
|
|
return g_dbus_connection_get_unique_name (connection) == NULL;
|
2014-07-24 12:53:33 +00:00
|
|
|
}
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
static GHashTable *proxy_types;
|
|
|
|
|
|
|
|
#undef _nm_dbus_register_proxy_type
|
|
|
|
void
|
|
|
|
_nm_dbus_register_proxy_type (const char *interface,
|
|
|
|
GType proxy_type)
|
|
|
|
{
|
|
|
|
if (!proxy_types)
|
|
|
|
proxy_types = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
|
|
|
|
g_assert (g_hash_table_lookup (proxy_types, interface) == NULL);
|
|
|
|
g_hash_table_insert (proxy_types, (char *) interface, GSIZE_TO_POINTER (proxy_type));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We don't (currently) use GDBus's property-handling code */
|
|
|
|
#define NM_DBUS_PROXY_FLAGS (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | \
|
|
|
|
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START)
|
|
|
|
|
|
|
|
GDBusProxy *
|
|
|
|
_nm_dbus_new_proxy_for_connection (GDBusConnection *connection,
|
2014-07-24 12:53:33 +00:00
|
|
|
const char *path,
|
2014-09-10 13:29:51 +00:00
|
|
|
const char *interface,
|
|
|
|
GCancellable *cancellable,
|
|
|
|
GError **error)
|
2014-07-24 12:53:33 +00:00
|
|
|
{
|
2014-09-10 17:51:53 +00:00
|
|
|
GType proxy_type;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
proxy_type = GPOINTER_TO_SIZE (g_hash_table_lookup (proxy_types, interface));
|
|
|
|
if (!proxy_type)
|
|
|
|
proxy_type = G_TYPE_DBUS_PROXY;
|
|
|
|
|
2014-07-24 12:53:33 +00:00
|
|
|
if (_nm_dbus_is_connection_private (connection))
|
2014-09-10 17:51:53 +00:00
|
|
|
name = NULL;
|
|
|
|
else
|
|
|
|
name = NM_DBUS_SERVICE;
|
2014-07-24 12:53:33 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
return g_initable_new (proxy_type, cancellable, error,
|
|
|
|
"g-connection", connection,
|
|
|
|
"g-flags", NM_DBUS_PROXY_FLAGS,
|
|
|
|
"g-name", name,
|
|
|
|
"g-object-path", path,
|
|
|
|
"g-interface-name", interface,
|
|
|
|
NULL);
|
2014-07-24 12:53:33 +00:00
|
|
|
}
|
2014-09-10 13:29:51 +00:00
|
|
|
|
|
|
|
void
|
2014-09-10 17:51:53 +00:00
|
|
|
_nm_dbus_new_proxy_for_connection_async (GDBusConnection *connection,
|
2014-09-10 13:29:51 +00:00
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
GCancellable *cancellable,
|
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
2014-09-10 17:51:53 +00:00
|
|
|
GType proxy_type;
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
proxy_type = GPOINTER_TO_SIZE (g_hash_table_lookup (proxy_types, interface));
|
|
|
|
if (!proxy_type)
|
|
|
|
proxy_type = G_TYPE_DBUS_PROXY;
|
2014-09-10 13:29:51 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
if (_nm_dbus_is_connection_private (connection))
|
|
|
|
name = NULL;
|
2014-09-10 13:29:51 +00:00
|
|
|
else
|
2014-09-10 17:51:53 +00:00
|
|
|
name = NM_DBUS_SERVICE;
|
2014-09-10 13:29:51 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
g_async_initable_new_async (proxy_type, G_PRIORITY_DEFAULT,
|
|
|
|
cancellable, callback, user_data,
|
|
|
|
"g-connection", connection,
|
|
|
|
"g-flags", NM_DBUS_PROXY_FLAGS,
|
|
|
|
"g-name", name,
|
|
|
|
"g-object-path", path,
|
|
|
|
"g-interface-name", interface,
|
|
|
|
NULL);
|
2014-09-10 13:29:51 +00:00
|
|
|
}
|
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
GDBusProxy *
|
2014-09-10 13:29:51 +00:00
|
|
|
_nm_dbus_new_proxy_for_connection_finish (GAsyncResult *result,
|
|
|
|
GError **error)
|
|
|
|
{
|
2014-09-10 17:51:53 +00:00
|
|
|
GObject *source, *proxy;
|
2014-09-10 13:29:51 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
source = g_async_result_get_source_object (result);
|
|
|
|
proxy = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error);
|
|
|
|
g_object_unref (source);
|
2014-09-10 13:29:51 +00:00
|
|
|
|
2014-09-10 17:51:53 +00:00
|
|
|
return G_DBUS_PROXY (proxy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Binds the properties on a generated server-side GDBus object to the
|
|
|
|
* corresponding properties on the public object.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
_nm_dbus_bind_properties (gpointer object, gpointer skeleton)
|
|
|
|
{
|
|
|
|
GParamSpec **properties;
|
|
|
|
guint n_properties;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (skeleton), &n_properties);
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
|
|
if (g_str_has_prefix (properties[i]->name, "g-"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
g_object_bind_property (object, properties[i]->name,
|
|
|
|
skeleton, properties[i]->name,
|
|
|
|
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
signal_name_from_method_name (const char *method_name)
|
|
|
|
{
|
|
|
|
GString *signal_name;
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
signal_name = g_string_new ("handle");
|
|
|
|
for (p = method_name; *p; p++) {
|
|
|
|
if (g_ascii_isupper (*p))
|
|
|
|
g_string_append_c (signal_name, '-');
|
|
|
|
g_string_append_c (signal_name, g_ascii_tolower (*p));
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_string_free (signal_name, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_nm_dbus_method_meta_marshal (GClosure *closure, GValue *return_value,
|
|
|
|
guint n_param_values, const GValue *param_values,
|
|
|
|
gpointer invocation_hint, gpointer marshal_data)
|
|
|
|
{
|
|
|
|
closure->marshal (closure, return_value, n_param_values,
|
|
|
|
param_values, invocation_hint,
|
|
|
|
((GCClosure *)closure)->callback);
|
|
|
|
|
|
|
|
g_value_set_boolean (return_value, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Takes (method_name, handler_func) pairs and connects the handlers to the
|
|
|
|
* signals on skeleton, with object as the user_data, but swapped so it comes
|
|
|
|
* first in the argument list, and handling the return value automatically.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
_nm_dbus_bind_methods (gpointer object, gpointer skeleton, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
const char *method_name;
|
|
|
|
char *signal_name;
|
|
|
|
GCallback handler;
|
|
|
|
GClosure *closure;
|
|
|
|
|
|
|
|
va_start (ap, skeleton);
|
|
|
|
while ( (method_name = va_arg (ap, const char *))
|
|
|
|
&& (handler = va_arg (ap, GCallback))) {
|
|
|
|
signal_name = signal_name_from_method_name (method_name);
|
|
|
|
closure = g_cclosure_new_swap (handler, object, NULL);
|
|
|
|
g_closure_set_meta_marshal (closure, NULL, _nm_dbus_method_meta_marshal);
|
|
|
|
g_signal_connect_closure (skeleton, signal_name, closure, FALSE);
|
|
|
|
g_free (signal_name);
|
|
|
|
}
|
|
|
|
va_end (ap);
|
2014-09-10 13:29:51 +00:00
|
|
|
}
|