summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-11-12 15:44:26 +0100
committerDan Williams <dcbw@redhat.com>2014-11-12 17:48:37 -0600
commit20d008633f56ca41e46d041a91021e5655132615 (patch)
treee2dcd4e4cf9f9a92ddebefbee0fb770ad661ca2b
parent2dfa722d42ab3aa777e469aa0b84933e87a69a01 (diff)
downloadNetworkManager-20d008633f56ca41e46d041a91021e5655132615.tar.gz
firewall: always complete callbacks asynchronously
Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--src/nm-firewall-manager.c129
1 files changed, 98 insertions, 31 deletions
diff --git a/src/nm-firewall-manager.c b/src/nm-firewall-manager.c
index ccd30cbca9..afef42e989 100644
--- a/src/nm-firewall-manager.c
+++ b/src/nm-firewall-manager.c
@@ -45,6 +45,8 @@ typedef struct {
guint name_owner_id;
DBusGProxy * proxy;
gboolean running;
+
+ GSList *pending_calls;
} NMFirewallManagerPrivate;
enum {
@@ -57,17 +59,27 @@ static guint signals[LAST_SIGNAL] = { 0 };
/********************************************************************/
+#define PENDING_CALL_DUMMY ((NMFirewallPendingCall) ((void *) nm_firewall_manager_init) )
+#define PENDING_CALL_FROM_INFO(info) ((NMFirewallPendingCall) info)
+
typedef struct {
+ NMFirewallManager *self;
char *iface;
FwAddToZoneFunc callback;
gpointer user_data;
guint id;
gboolean completed;
+
+ gboolean cancelled;
+ gboolean is_idly_scheduled;
+ DBusGProxyCall *dbus_call;
} CBInfo;
static void
-cb_info_free (CBInfo *info)
+_cb_info_free (CBInfo *info)
{
+ NMFirewallManagerPrivate *priv;
+
g_return_if_fail (info != NULL);
if (!info->completed) {
@@ -82,27 +94,54 @@ cb_info_free (CBInfo *info)
}
}
g_free (info->iface);
- g_free (info);
+
+ priv = NM_FIREWALL_MANAGER_GET_PRIVATE (info->self);
+ priv->pending_calls = g_slist_remove (priv->pending_calls, info);
+ g_object_unref (info->self);
+
+ g_slice_free (CBInfo, info);
}
static CBInfo *
-_cb_info_create (const char *iface, FwAddToZoneFunc callback, gpointer user_data)
+_cb_info_create (NMFirewallManager *self, const char *iface, FwAddToZoneFunc callback, gpointer user_data)
{
+ NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
static guint id;
CBInfo *info;
- info = g_malloc (sizeof (CBInfo));
+ info = g_slice_new0 (CBInfo);
if (++id == 0)
++id;
+ info->self = g_object_ref (self);
info->id = id;
info->iface = g_strdup (iface);
info->completed = FALSE;
info->callback = callback;
info->user_data = user_data;
+ priv->pending_calls = g_slist_prepend (priv->pending_calls, info);
return info;
}
+static gboolean
+add_or_change_idle_cb (gpointer user_data)
+{
+ CBInfo *info = user_data;
+
+ if (info->cancelled) {
+ /* operation was cancelled. _cb_info_free will invoke callback. */
+ } else {
+ nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone call pretends success [%u]",
+ info->iface, info->id);
+ if (info->callback)
+ info->callback (NULL, info->user_data);
+ info->completed = TRUE;
+ }
+
+ _cb_info_free (info);
+ return G_SOURCE_REMOVE;
+}
+
static void
add_or_change_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
{
@@ -146,25 +185,33 @@ nm_firewall_manager_add_or_change_zone (NMFirewallManager *self,
CBInfo *info;
if (priv->running == FALSE) {
- nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change skipped (not running)", iface);
- if (callback)
- callback (NULL, user_data);
- return NULL;
+ if (callback) {
+ info = _cb_info_create (self, iface, callback, user_data);
+ info->is_idly_scheduled= TRUE;
+ g_idle_add (add_or_change_idle_cb, info);
+ nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u] (not running, simulate success)", iface, add ? "add" : "change",
+ zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id);
+ return PENDING_CALL_FROM_INFO (info);
+ } else {
+ nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone add/change skipped (not running)", iface);
+ return PENDING_CALL_DUMMY;
+ }
}
- info = _cb_info_create (iface, callback, user_data);
+ info = _cb_info_create (self, iface, callback, user_data);
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone %s -> %s%s%s [%u]", iface, add ? "add" : "change",
zone?"\"":"", zone ? zone : "default", zone?"\"":"", info->id);
- return (NMFirewallPendingCall) dbus_g_proxy_begin_call_with_timeout (priv->proxy,
- add ? "addInterface" : "changeZone",
- add_or_change_cb,
- info,
- (GDestroyNotify) cb_info_free,
- 10000, /* timeout */
- G_TYPE_STRING, zone ? zone : "",
- G_TYPE_STRING, iface,
- G_TYPE_INVALID);
+ info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
+ add ? "addInterface" : "changeZone",
+ add_or_change_cb,
+ info,
+ (GDestroyNotify) _cb_info_free,
+ 10000, /* timeout */
+ G_TYPE_STRING, zone ? zone : "",
+ G_TYPE_STRING, iface,
+ G_TYPE_INVALID);
+ return PENDING_CALL_FROM_INFO (info);
}
static void
@@ -206,29 +253,49 @@ nm_firewall_manager_remove_from_zone (NMFirewallManager *self,
if (priv->running == FALSE) {
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove skipped (not running)", iface);
- return NULL;
+ return PENDING_CALL_DUMMY;
}
- info = _cb_info_create (iface, NULL, NULL);
+ info = _cb_info_create (self, iface, NULL, NULL);
nm_log_dbg (LOGD_FIREWALL, "(%s) firewall zone remove -> %s%s%s [%u]", iface,
zone?"\"":"", zone ? zone : "*", zone?"\"":"", info->id);
- return (NMFirewallPendingCall) dbus_g_proxy_begin_call_with_timeout (priv->proxy,
- "removeInterface",
- remove_cb,
- info,
- (GDestroyNotify) cb_info_free,
- 10000, /* timeout */
- G_TYPE_STRING, zone ? zone : "",
- G_TYPE_STRING, iface,
- G_TYPE_INVALID);
+ info->dbus_call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
+ "removeInterface",
+ remove_cb,
+ info,
+ (GDestroyNotify) _cb_info_free,
+ 10000, /* timeout */
+ G_TYPE_STRING, zone ? zone : "",
+ G_TYPE_STRING, iface,
+ G_TYPE_INVALID);
+ return PENDING_CALL_FROM_INFO (info);
}
void nm_firewall_manager_cancel_call (NMFirewallManager *self, NMFirewallPendingCall call)
{
+ NMFirewallManagerPrivate *priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);
+ GSList *pending;
+ CBInfo *info;
+
g_return_if_fail (NM_IS_FIREWALL_MANAGER (self));
- dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
- (DBusGProxyCall *) call);
+
+ if (call == PENDING_CALL_DUMMY)
+ return;
+
+ pending = g_slist_find (priv->pending_calls, call);
+
+ if (!pending)
+ return;
+ priv->pending_calls = g_slist_remove_link (priv->pending_calls, pending);
+
+ info = (CBInfo *) call;
+ if (info->is_idly_scheduled)
+ info->cancelled = TRUE;
+ else {
+ dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
+ info->dbus_call);
+ }
}
static void