diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2013-02-22 08:31:18 +0000 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2013-02-22 08:33:14 +0000 |
commit | fa8be7c05185ce92696a5771b556e70b8eb99a00 (patch) | |
tree | 7f6111c6735bf414a11fb926b24061fde5eb29e8 | |
parent | f843f499be4c16683a4a5b054a5bf747254b2050 (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.c | 25 | ||||
-rw-r--r-- | tests/twisted/muc/chat-states.py | 39 |
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) |