summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-03-11 09:54:19 +0000
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-03-11 10:17:57 +0000
commitb7e4c63cd9490018d7f8db138de98168ae4e4050 (patch)
tree194bd33296f0ae9d32669bbdb04ab4c22fd67283
parent0dd3a10f6dbfa6f580eed5ae0f492eaaac2e540f (diff)
porter: don't close twice if we close in a send callbackmessage-example
We need to decide before we complete the "send stanza" asynchronous operation whether we have a close result pending. If we don't, we can get into a pickle if the callback to send_async calls close_async. The problem is that close_async doesn't use the same stanza queue as send_async so needs special-casing. For example: Previously, we send a stanza using send_async. The simple async result would be completed with g_simple_async_result_complete() and the callback to send_async would be called. However, if in the callback close_async is called, the stream close is sent directly with wocky_xmpp_connection_send_close_async and priv->close_result is assigned. Once the callback returns, send_stanza_cb continues BUT at the end there is a test for whether there is a close result pending. This is for when you send a whole bunch of stanzas followed by a close request, so the porter waits until all the stanzas are sent before sending the stream close, which is cool. However, priv->close_result is now != NULL so the porter thinks we're in exactly that case -- that we're waiting until all the stanzas are sent and will try and send a stream close afterwards. As we've already done that the xmpp connection will say "hey another send operation pending" and everything will fall apart. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--wocky/wocky-porter.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/wocky/wocky-porter.c b/wocky/wocky-porter.c
index d83c035..b167b96 100644
--- a/wocky/wocky-porter.c
+++ b/wocky/wocky-porter.c
@@ -90,6 +90,7 @@ struct _WockyPorterPrivate
GCancellable *receive_cancellable;
GSimpleAsyncResult *close_result;
+ gboolean waiting_to_close;
gboolean remote_closed;
gboolean local_closed;
GCancellable *close_cancellable;
@@ -750,12 +751,13 @@ send_stanza_cb (GObject *source,
}
}
- if (priv->close_result != NULL &&
+ if (priv->waiting_to_close &&
g_queue_get_length (priv->sending_queue) == 0)
{
/* Queue is empty and we are waiting to close the connection. */
DEBUG ("Queue has been flushed. Closing the connection.");
send_close (self);
+ priv->waiting_to_close = FALSE;
}
g_object_unref (self);
@@ -1429,6 +1431,7 @@ wocky_porter_close_async (WockyPorter *self,
{
DEBUG ("Sending queue is not empty. Flushing it before "
"closing the connection.");
+ priv->waiting_to_close = TRUE;
return;
}