summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2013-02-22 08:31:18 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2013-02-22 08:33:14 +0000
commitfa8be7c05185ce92696a5771b556e70b8eb99a00 (patch)
tree7f6111c6735bf414a11fb926b24061fde5eb29e8
parentf843f499be4c16683a4a5b054a5bf747254b2050 (diff)
MUC: stop sending chat states after <error type=wait>
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=43166#c0
-rw-r--r--src/muc-channel.c25
-rw-r--r--tests/twisted/muc/chat-states.py39
2 files changed, 57 insertions, 7 deletions
diff --git a/src/muc-channel.c b/src/muc-channel.c
index 47ab9d5b9..15c337b07 100644
--- a/src/muc-channel.c
+++ b/src/muc-channel.c
@@ -214,6 +214,8 @@ struct _GabbleMucChannelPrivate
GPtrArray *initial_channels;
GArray *initial_handles;
char **initial_ids;
+
+ gboolean have_received_error_type_wait;
};
typedef struct {
@@ -2885,9 +2887,25 @@ handle_errmsg (GObject *source,
}
if (etype == WOCKY_XMPP_ERROR_TYPE_WAIT)
- ds = TP_DELIVERY_STATUS_TEMPORARILY_FAILED;
+ {
+ ds = TP_DELIVERY_STATUS_TEMPORARILY_FAILED;
+ /* Some MUCs have very strict rate limiting like "at most one stanza per
+ * second". Since chat state notifications count towards this, if the
+ * user types a message very quickly then the typing notification is
+ * accepted but then the stanza containing the actual message is
+ * rejected.
+ *
+ * So: if we ever get rate-limited, let's just stop sending chat states.
+ *
+ * https://bugs.freedesktop.org/show_bug.cgi?id=43166
+ */
+ DEBUG ("got <error type='wait'>, disabling chat state notifications");
+ priv->have_received_error_type_wait = TRUE;
+ }
else
- ds = TP_DELIVERY_STATUS_PERMANENTLY_FAILED;
+ {
+ ds = TP_DELIVERY_STATUS_PERMANENTLY_FAILED;
+ }
if (text != NULL)
_gabble_muc_channel_receive (gmuc, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE,
@@ -3831,6 +3849,9 @@ gabble_muc_channel_send_chat_state (GObject *object,
GabbleMucChannelPrivate *priv = self->priv;
TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ if (priv->have_received_error_type_wait)
+ return TRUE;
+
return gabble_message_util_send_chat_state (G_OBJECT (self),
GABBLE_CONNECTION (tp_base_channel_get_connection (base)),
WOCKY_STANZA_SUB_TYPE_GROUPCHAT, state, priv->jid, error);
diff --git a/tests/twisted/muc/chat-states.py b/tests/twisted/muc/chat-states.py
index 48e66786f..4be5f50b2 100644
--- a/tests/twisted/muc/chat-states.py
+++ b/tests/twisted/muc/chat-states.py
@@ -3,8 +3,8 @@ Regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=32952>,
wherein chat states in MUCs were misparsed, and MUC chat states in general.
"""
-from servicetest import assertEquals, assertLength
-from gabbletest import exec_test, elem, make_muc_presence
+from servicetest import assertEquals, assertLength, EventPattern
+from gabbletest import exec_test, elem, make_muc_presence, sync_stream
from mucutil import join_muc_and_check
import ns
import constants as cs
@@ -12,16 +12,23 @@ import constants as cs
MUC = 'ohai@groupchat.google.com'
BOB = MUC + '/bob'
+def get_state_notification(stanza):
+ for x in stanza.elements():
+ if x.uri == ns.CHAT_STATES:
+ return x
+
+ return None
+
def check_state_notification(elem, name, allow_body=False):
assertEquals('message', elem.name)
assertEquals('groupchat', elem['type'])
- children = list(elem.elements())
- notification = [x for x in children if x.uri == ns.CHAT_STATES][0]
+ notification = get_state_notification(elem)
+ assert notification is not None, elem.toXml()
assert notification.name == name, notification.toXml()
if not allow_body:
- assert len(children) == 1, elem.toXml()
+ assert len(elem.children) == 1, elem.toXml()
def test(q, bus, conn, stream):
(muc_handle, chan, user, bob) = join_muc_and_check(q, bus, conn, stream,
@@ -115,5 +122,27 @@ def test(q, bus, conn, stream):
assertLength(1, bodies)
assertEquals(u'hi.', bodies[0].children[0])
+ # If we get an error with type='wait', stop sending chat states.
+ stanza['type'] = 'error'
+ stanza['from'] = MUC
+ stanza['to'] = 'test@localhost/Resource'
+
+ error = stanza.addElement('error')
+ error['type'] = 'wait'
+ error.addElement((ns.STANZA, 'resource-constraint'))
+ stream.send(stanza)
+
+ q.expect('dbus-signal', signal='MessageReceived',
+ predicate=lambda e: e.args[0][0]['message-type'] == cs.MT_DELIVERY_REPORT)
+
+ q.forbid_events([
+ EventPattern('stream-message', to=MUC,
+ predicate=lambda e: get_state_notification(e.stanza) is not None)
+ ])
+
+ # User starts typing again but nothing should be seen or heard on the stream.
+ chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING)
+ sync_stream(q, stream)
+
if __name__ == '__main__':
exec_test(test)