From c333f062ddcba9b35330647bf6cbd0a07f2d786e Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 11 May 2017 14:55:55 +0200 Subject: New upstream version 1.8.0 --- src/nm-pacrunner-manager.c | 373 ++++++++++++++++++++++++++++----------------- 1 file changed, 237 insertions(+), 136 deletions(-) (limited to 'src/nm-pacrunner-manager.c') diff --git a/src/nm-pacrunner-manager.c b/src/nm-pacrunner-manager.c index 450cf0e3..cfc028c2 100644 --- a/src/nm-pacrunner-manager.c +++ b/src/nm-pacrunner-manager.c @@ -28,24 +28,29 @@ #include "nm-ip4-config.h" #include "nm-ip6-config.h" +static void pacrunner_remove_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data); + #define PACRUNNER_DBUS_SERVICE "org.pacrunner" #define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager" #define PACRUNNER_DBUS_PATH "/org/pacrunner/manager" /*****************************************************************************/ -struct remove_data { - char *iface; +struct _NMPacrunnerCallId { + NMPacrunnerManager *manager; + GVariant *args; char *path; + guint refcount; + bool removed; }; +typedef struct _NMPacrunnerCallId Config; + typedef struct { char *iface; - GPtrArray *domains; GDBusProxy *pacrunner; GCancellable *pacrunner_cancellable; - GList *args; - GList *remove; + GList *configs; } NMPacrunnerManagerPrivate; struct _NMPacrunnerManager { @@ -68,23 +73,58 @@ NM_DEFINE_SINGLETON_GETTER (NMPacrunnerManager, nm_pacrunner_manager_get, NM_TYP /*****************************************************************************/ #define _NMLOG_DOMAIN LOGD_PROXY -#define _NMLOG(level, ...) __NMLOG_DEFAULT_WITH_ADDR (level, _NMLOG_DOMAIN, "pacrunner", __VA_ARGS__) +#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "pacrunner", __VA_ARGS__) + +#define _NMLOG2_PREFIX_NAME "pacrunner" +#define _NMLOG2(level, config, ...) \ + G_STMT_START { \ + nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ + "%s%p]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + "pacrunner: call[", \ + (config) \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END /*****************************************************************************/ +static Config * +config_new (NMPacrunnerManager *manager, GVariant *args) +{ + Config *config; + + config = g_slice_new0 (Config); + config->manager = manager; + config->args = g_variant_ref_sink (args); + config->refcount = 1; + + return config; +} + static void -remove_data_destroy (struct remove_data *data) +config_ref (Config *config) { - g_return_if_fail (data != NULL); + g_assert (config); + g_assert (config->refcount > 0); - g_free (data->iface); - g_free (data->path); - memset (data, 0, sizeof (struct remove_data)); - g_free (data); + config->refcount++; } static void -add_proxy_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, const NMProxyConfig *proxy_config) +config_unref (Config *config) +{ + g_assert (config); + g_assert (config->refcount > 0); + + if (config->refcount == 1) { + g_variant_unref (config->args); + g_free (config->path); + g_slice_free (Config, config); + } else + config->refcount--; +} + +static void +add_proxy_config (GVariantBuilder *proxy_data, const NMProxyConfig *proxy_config) { const char *pac_url, *pac_script; NMProxyConfigMethod method; @@ -113,19 +153,18 @@ add_proxy_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, const N } static void -add_ip4_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP4Config *ip4) +get_ip4_domains (GPtrArray *domains, NMIP4Config *ip4) { - NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); + char *cidr; int i; - char *cidr = NULL; /* Extract searches */ for (i = 0; i < nm_ip4_config_get_num_searches (ip4); i++) - g_ptr_array_add (priv->domains, g_strdup (nm_ip4_config_get_search (ip4, i))); + g_ptr_array_add (domains, g_strdup (nm_ip4_config_get_search (ip4, i))); /* Extract domains */ for (i = 0; i < nm_ip4_config_get_num_domains (ip4); i++) - g_ptr_array_add (priv->domains, g_strdup (nm_ip4_config_get_domain (ip4, i))); + g_ptr_array_add (domains, g_strdup (nm_ip4_config_get_domain (ip4, i))); /* Add addresses and routes in CIDR form */ for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) { @@ -134,8 +173,7 @@ add_ip4_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP4Conf cidr = g_strdup_printf ("%s/%u", nm_utils_inet4_ntop (address->address, NULL), address->plen); - g_ptr_array_add (priv->domains, g_strdup (cidr)); - g_free (cidr); + g_ptr_array_add (domains, cidr); } for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) { @@ -144,25 +182,23 @@ add_ip4_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP4Conf cidr = g_strdup_printf ("%s/%u", nm_utils_inet4_ntop (routes->network, NULL), routes->plen); - g_ptr_array_add (priv->domains, g_strdup (cidr)); - g_free (cidr); + g_ptr_array_add (domains, cidr); } } static void -add_ip6_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP6Config *ip6) +get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6) { - NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); + char *cidr; int i; - char *cidr = NULL; /* Extract searches */ for (i = 0; i < nm_ip6_config_get_num_searches (ip6); i++) - g_ptr_array_add (priv->domains, g_strdup (nm_ip6_config_get_search (ip6, i))); + g_ptr_array_add (domains, g_strdup (nm_ip6_config_get_search (ip6, i))); /* Extract domains */ for (i = 0; i < nm_ip6_config_get_num_domains (ip6); i++) - g_ptr_array_add (priv->domains, g_strdup (nm_ip6_config_get_domain (ip6, i))); + g_ptr_array_add (domains, g_strdup (nm_ip6_config_get_domain (ip6, i))); /* Add addresses and routes in CIDR form */ for (i = 0; i < nm_ip6_config_get_num_addresses (ip6); i++) { @@ -171,8 +207,7 @@ add_ip6_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP6Conf cidr = g_strdup_printf ("%s/%u", nm_utils_inet6_ntop (&address->address, NULL), address->plen); - g_ptr_array_add (priv->domains, g_strdup (cidr)); - g_free (cidr); + g_ptr_array_add (domains, cidr); } for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) { @@ -181,92 +216,100 @@ add_ip6_config (NMPacrunnerManager *self, GVariantBuilder *proxy_data, NMIP6Conf cidr = g_strdup_printf ("%s/%u", nm_utils_inet6_ntop (&routes->network, NULL), routes->plen); - g_ptr_array_add (priv->domains, g_strdup (cidr)); - g_free (cidr); + g_ptr_array_add (domains, cidr); } } static void -pacrunner_send_done (GObject *source, GAsyncResult *res, gpointer user_data) +pacrunner_send_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { - NMPacrunnerManager *self = NM_PACRUNNER_MANAGER (user_data); - NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); + Config *config = user_data; + NMPacrunnerManager *self; + NMPacrunnerManagerPrivate *priv; gs_free_error GError *error = NULL; gs_unref_variant GVariant *variant = NULL; const char *path = NULL; - GList *iter = NULL; - gboolean found = FALSE; - variant = g_dbus_proxy_call_finish (priv->pacrunner, res, &error); - if (!variant) { - _LOGD ("sending proxy config to pacrunner failed: %s", error->message); - } else { - struct remove_data *data; - g_variant_get (variant, "(&o)", &path); + g_return_if_fail (!config->path); - /* Replace the old path (if any) of proxy config with the new one returned - * from CreateProxyConfiguration() DBus method on pacrunner. - */ - for (iter = g_list_first (priv->remove); iter; iter = g_list_next (iter)) { - struct remove_data *r = iter->data; - if (g_strcmp0 (priv->iface, r->iface) == 0) { - g_free (r->path); - r->path = g_strdup (path); - found = TRUE; - break; - } - } + variant = g_dbus_proxy_call_finish (proxy, res, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + config_unref (config); + return; + } + + self = NM_PACRUNNER_MANAGER (config->manager); + priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); - if (!found) { - data = g_malloc0 (sizeof (struct remove_data)); - data->iface = g_strdup (priv->iface); - data->path = g_strdup (path); - priv->remove = g_list_append (priv->remove, data); - _LOGD ("proxy config sent to pacrunner"); + if (!variant) + _LOG2D (config, "sending failed: %s", error->message); + else { + g_variant_get (variant, "(&o)", &path); + + config->path = g_strdup (path); + _LOG2D (config, "sent"); + + if (config->removed) { + g_dbus_proxy_call (priv->pacrunner, + "DestroyProxyConfiguration", + g_variant_new ("(o)", config->path), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + priv->pacrunner_cancellable, + (GAsyncReadyCallback) pacrunner_remove_done, + config); } } + config_unref (config); } static void -send_pacrunner_proxy_data (NMPacrunnerManager *self, GVariant *pacrunner_manager_args) +pacrunner_send_config (NMPacrunnerManager *self, Config *config) { NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); - if (!pacrunner_manager_args) - return; + if (priv->pacrunner) { + _LOG2T (config, "sending..."); + + config_ref (config); + g_clear_pointer (&config->path, g_free); - if (priv->pacrunner) g_dbus_proxy_call (priv->pacrunner, "CreateProxyConfiguration", - pacrunner_manager_args, - G_DBUS_CALL_FLAGS_NONE, + config->args, + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, - NULL, - (GAsyncReadyCallback) pacrunner_send_done, - self); + priv->pacrunner_cancellable, + (GAsyncReadyCallback) pacrunner_send_done, + config); + } } static void -name_owner_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) +name_owner_changed (NMPacrunnerManager *self) { - NMPacrunnerManager *self = NM_PACRUNNER_MANAGER (user_data); NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); gs_free char *owner = NULL; GList *iter = NULL; - owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)); + owner = g_dbus_proxy_get_name_owner (priv->pacrunner); if (owner) { - _LOGD ("pacrunner appeared as %s", owner); - for (iter = g_list_first(priv->args); iter; iter = g_list_next(iter)) { - send_pacrunner_proxy_data (self, iter->data); - } + _LOGD ("name owner appeared (%s)", owner); + for (iter = g_list_first (priv->configs); iter; iter = g_list_next (iter)) + pacrunner_send_config (self, iter->data); } else { - _LOGD ("pacrunner disappeared"); + _LOGD ("name owner disappeared"); } } +static void +name_owner_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + name_owner_changed (user_data); +} + static void pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data) { @@ -289,7 +332,8 @@ pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data) nm_clear_g_cancellable (&priv->pacrunner_cancellable); g_signal_connect (priv->pacrunner, "notify::g-name-owner", - G_CALLBACK (name_owner_changed), self); + G_CALLBACK (name_owner_changed_cb), self); + name_owner_changed (self); } /** @@ -297,10 +341,18 @@ pacrunner_proxy_cb (GObject *source, GAsyncResult *res, gpointer user_data) * @self: the #NMPacrunnerManager * @iface: the iface for the connection or %NULL * @proxy_config: proxy config of the connection - * @ip4_config: IP4 config of the connection - * @ip6_config: IP6 config of the connection + * @ip4_config: IP4 config of the connection to extract domain info from + * @ip6_config: IP6 config of the connection to extract domain info from + * + * Returns: a #NMPacrunnerCallId call id. The function cannot + * fail and always returns a non NULL pointer. The call-id may + * be used to remove the configuration later via nm_pacrunner_manager_remove(). + * Note that the call-id does not keep the @self instance alive. + * If you plan to remove the configuration later, you must keep + * the instance alive long enough. You can remove the configuration + * at most once using this call call-id. */ -void +NMPacrunnerCallId * nm_pacrunner_manager_send (NMPacrunnerManager *self, const char *iface, NMProxyConfig *proxy_config, @@ -311,10 +363,11 @@ nm_pacrunner_manager_send (NMPacrunnerManager *self, NMProxyConfigMethod method; NMPacrunnerManagerPrivate *priv; GVariantBuilder proxy_data; - GVariant *pacrunner_manager_args; + GPtrArray *domains; + Config *config; - g_return_if_fail (NM_IS_PACRUNNER_MANAGER (self)); - g_return_if_fail (proxy_config); + g_return_val_if_fail (NM_IS_PACRUNNER_MANAGER (self), NULL); + g_return_val_if_fail (proxy_config, NULL); priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); @@ -343,80 +396,133 @@ nm_pacrunner_manager_send (NMPacrunnerManager *self, g_variant_new_string ("direct")); } - priv->domains = g_ptr_array_new_with_free_func (g_free); /* Extract stuff from configs */ - add_proxy_config (self, &proxy_data, proxy_config); + add_proxy_config (&proxy_data, proxy_config); - if (ip4_config) - add_ip4_config (self, &proxy_data, ip4_config); - if (ip6_config) - add_ip6_config (self, &proxy_data, ip6_config); + if (ip4_config || ip6_config) { + domains = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (priv->domains, NULL); - strv = (char **) g_ptr_array_free (priv->domains, (priv->domains->len == 1)); + if (ip4_config) + get_ip4_domains (domains, ip4_config); + if (ip6_config) + get_ip6_domains (domains, ip6_config); - if (strv) { - g_variant_builder_add (&proxy_data, "{sv}", - "Domains", - g_variant_new_strv ((const char *const *) strv, -1)); - g_strfreev (strv); + g_ptr_array_add (domains, NULL); + strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); + + if (strv) { + g_variant_builder_add (&proxy_data, "{sv}", + "Domains", + g_variant_new_strv ((const char *const *) strv, -1)); + g_strfreev (strv); + } } - pacrunner_manager_args = g_variant_ref_sink (g_variant_new ("(a{sv})", &proxy_data)); - priv->args = g_list_append (priv->args, pacrunner_manager_args); + config = config_new (self, g_variant_new ("(a{sv})", &proxy_data)); + priv->configs = g_list_append (priv->configs, config); - /* Send if pacrunner is available on Bus, otherwise - * argument has already been appended above to be + { + gs_free char *args_str = NULL; + + _LOG2D (config, "send: new config %s", + (args_str = g_variant_print (config->args, FALSE))); + } + + /* Send if pacrunner is available on bus, otherwise + * config has already been appended above to be * sent when pacrunner appears. */ - send_pacrunner_proxy_data (self, pacrunner_manager_args); + pacrunner_send_config (self, config); + + return config; } static void -pacrunner_remove_done (GObject *source, GAsyncResult *res, gpointer user_data) +pacrunner_remove_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { - /* @self may be a dangling pointer. However, we don't use it as the - * logging macro below does not dereference @self. */ - NMPacrunnerManager *self = user_data; + Config *config = user_data; + NMPacrunnerManager *self; gs_free_error GError *error = NULL; gs_unref_variant GVariant *ret = NULL; - ret = g_dbus_proxy_call_finish ((GDBusProxy *) source, res, &error); + ret = g_dbus_proxy_call_finish (proxy, res, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + config_unref (config); + return; + } + + self = NM_PACRUNNER_MANAGER (config->manager); if (!ret) - _LOGD ("Couldn't remove proxy config from pacrunner: %s", error->message); + _LOG2D (config, "remove failed: %s", error->message); else - _LOGD ("Successfully removed proxy config from pacrunner"); + _LOG2D (config, "removed"); + + config_unref (config); } /** * nm_pacrunner_manager_remove: * @self: the #NMPacrunnerManager - * @iface: the iface for the connection to be removed - * from pacrunner + * @call_id: the call-id obtained from nm_pacrunner_manager_send() */ void -nm_pacrunner_manager_remove (NMPacrunnerManager *self, const char *iface) +nm_pacrunner_manager_remove (NMPacrunnerManager *self, NMPacrunnerCallId *call_id) { - NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); + NMPacrunnerManagerPrivate *priv; + Config *config; GList *list; - for (list = g_list_first(priv->remove); list; list = g_list_next(list)) { - struct remove_data *data = list->data; - if (g_strcmp0 (data->iface, iface) == 0) { - if (priv->pacrunner && data->path) - g_dbus_proxy_call (priv->pacrunner, - "DestroyProxyConfiguration", - g_variant_new ("(o)", data->path), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - (GAsyncReadyCallback) pacrunner_remove_done, - self); - break; + g_return_if_fail (NM_IS_PACRUNNER_MANAGER (self)); + g_return_if_fail (call_id); + + config = call_id; + priv = NM_PACRUNNER_MANAGER_GET_PRIVATE (self); + + _LOG2T (config, "removing..."); + + list = g_list_find (priv->configs, config); + if (!list) + g_return_if_reached (); + + if (priv->pacrunner) { + if (!config->path) { + /* send() failed or is still pending. Mark the item as + * removed, so that we ask pacrunner to drop it when the + * send() completes. + */ + config->removed = TRUE; + config_unref (config); + } else { + g_dbus_proxy_call (priv->pacrunner, + "DestroyProxyConfiguration", + g_variant_new ("(o)", config->path), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + priv->pacrunner_cancellable, + (GAsyncReadyCallback) pacrunner_remove_done, + config); } - } + } else + config_unref (config); + priv->configs = g_list_delete_link (priv->configs, list); +} + +gboolean +nm_pacrunner_manager_remove_clear (NMPacrunnerManager *self, + NMPacrunnerCallId **p_call_id) +{ + g_return_val_if_fail (p_call_id, FALSE); + + /* if we have no call-id, allow for %NULL */ + g_return_val_if_fail ((!self && !*p_call_id) || NM_IS_PACRUNNER_MANAGER (self), FALSE); + + if (!*p_call_id) + return FALSE; + nm_pacrunner_manager_remove (self, + g_steal_pointer (p_call_id)); + return TRUE; } /*****************************************************************************/ @@ -445,16 +551,11 @@ dispose (GObject *object) NMPacrunnerManagerPrivate *priv = NM_PACRUNNER_MANAGER_GET_PRIVATE ((NMPacrunnerManager *) object); g_clear_pointer (&priv->iface, g_free); - nm_clear_g_cancellable (&priv->pacrunner_cancellable); - g_clear_object (&priv->pacrunner); - g_list_free_full (priv->args, (GDestroyNotify) g_variant_unref); - priv->args = NULL; - - g_list_free_full (priv->remove, (GDestroyNotify) remove_data_destroy); - priv->remove = NULL; + g_list_free_full (priv->configs, (GDestroyNotify) config_unref); + priv->configs = NULL; G_OBJECT_CLASS (nm_pacrunner_manager_parent_class)->dispose (object); } -- cgit 1.3.0-6-gf8a5