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));

	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->idle_id)
		info->idle_id = 0;
	else {
		dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
		                          info->dbus_call);
	}
}
void
nm_firewall_manager_cancel_call (NMFirewallManagerCallId call)
{
	NMFirewallManager *self;
	NMFirewallManagerPrivate *priv;
	CBInfo *info = call;
	gs_free_error GError *error = NULL;

	g_return_if_fail (info);
	g_return_if_fail (NM_IS_FIREWALL_MANAGER (info->self));

	self = info->self;
	priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);

	if (!g_hash_table_remove (priv->pending_calls, info))
		g_return_if_reached ();

	nm_utils_error_set_cancelled (&error, FALSE, "NMFirewallManager");

	_LOGD (info, "complete: cancel (%s)", error->message);

	_cb_info_callback (info, error);

	if (_cb_info_is_idle (info)) {
		g_source_remove (info->idle.id);
		_cb_info_free (info);
	} else {
		info->mode = CB_INFO_MODE_DBUS_COMPLETED;
		g_cancellable_cancel (info->dbus.cancellable);
		g_clear_object (&info->self);
	}
}
static gboolean
_handle_idle (gpointer user_data)
{
	NMFirewallManager *self;
	CBInfo *info = user_data;

	nm_assert (info && NM_IS_FIREWALL_MANAGER (info->self));

	self = info->self;

	_LOGD (info, "complete: fake success");

	_cb_info_complete_normal (info, NULL);
	return G_SOURCE_REMOVE;
}
void nm_firewall_manager_cancel_call (NMFirewallManager *self, gpointer call)
{
	g_return_if_fail (NM_IS_FIREWALL_MANAGER (self));
	dbus_g_proxy_cancel_call (NM_FIREWALL_MANAGER_GET_PRIVATE (self)->proxy,
	                          (DBusGProxyCall *) call);
}
static NMFirewallManagerCallId
_start_request (NMFirewallManager *self,
                CBInfoOpsType ops_type,
                const char *iface,
                const char *zone,
                NMFirewallManagerAddRemoveCallback callback,
                gpointer user_data)
{
	NMFirewallManagerPrivate *priv;
	CBInfo *info;
	const char *dbus_method;

	g_return_val_if_fail (NM_IS_FIREWALL_MANAGER (self), NULL);
	g_return_val_if_fail (iface && *iface, NULL);

	priv = NM_FIREWALL_MANAGER_GET_PRIVATE (self);

	info = _cb_info_create (self, ops_type, iface, callback, user_data);

	_LOGD (info, "firewall zone %s %s:%s%s%s%s",
	       _ops_type_to_string (info->ops_type),
	       iface,
	       NM_PRINT_FMT_QUOTED (zone, "\"", zone, "\"", "default"),
	       _cb_info_is_idle (info) ? " (not running, simulate success)" : "");

	if (!_cb_info_is_idle (info)) {

		switch (ops_type) {
		case CB_INFO_OPS_ADD:
			dbus_method = "addInterface";
			break;
		case CB_INFO_OPS_CHANGE:
			dbus_method = "changeZone";
			break;
		case CB_INFO_OPS_REMOVE:
			dbus_method = "removeInterface";
			break;
		default:
			g_assert_not_reached ();
		}

		g_dbus_proxy_call (priv->proxy,
		                   dbus_method,
		                   g_variant_new ("(ss)", zone ? zone : "", iface),
		                   G_DBUS_CALL_FLAGS_NONE, 10000,
		                   info->dbus.cancellable,
		                   _handle_dbus,
		                   info);

		if (!info->callback) {
			/* if the user did not provide a callback, the call_id is useless.
			 * Especially, the user cannot use the call-id to cancel the request,
			 * because he cannot know whether the request is still pending.
			 *
			 * Hence, returning %NULL doesn't mean that the request could not be started
			 * (the request will always be started). */
			return NULL;
		}
	} else if (!info->callback) {
		/* if the user did not provide a callback and firewalld is not running,
		 * there is no point in scheduling an idle-request to fake success. Just
		 * return right away. */
		_LOGD (info, "complete: drop request simulating success");
		_cb_info_complete_normal (info, NULL);
		return NULL;
	} else
		info->idle.id = g_idle_add (_handle_idle, info);

	return info;
}