From 4f009e64fc11ca352443e6a9df5fa4d7cb715f5c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 17 May 2016 20:55:45 +0200 Subject: [PATCH] mod_client_state: Queue chat state notifications Queue standalone chat states instead of simply dropping them when the client is inactive. Only the most recent chat state of a given client is queued. --- src/mod_client_state.erl | 30 +++++++++++++-------------- test/ejabberd_SUITE.erl | 11 +++++++--- test/ejabberd_SUITE_data/ejabberd.yml | 4 ++-- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 7d23beb0d..f51a7fd24 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -44,10 +44,10 @@ start(Host, Opts) -> QueuePresence = gen_mod:get_opt(queue_presence, Opts, fun(B) when is_boolean(B) -> B end, true), - DropChatStates = gen_mod:get_opt(drop_chat_states, Opts, - fun(B) when is_boolean(B) -> B end, - true), - if QueuePresence; DropChatStates -> + QueueChatStates = gen_mod:get_opt(queue_chat_states, Opts, + fun(B) when is_boolean(B) -> B end, + true), + if QueuePresence; QueueChatStates -> ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE, add_stream_feature, 50), if QueuePresence -> @@ -55,7 +55,7 @@ start(Host, Opts) -> filter_presence, 50); true -> ok end, - if DropChatStates -> + if QueueChatStates -> ejabberd_hooks:add(csi_filter_stanza, Host, ?MODULE, filter_chat_states, 50); true -> ok @@ -71,10 +71,10 @@ stop(Host) -> QueuePresence = gen_mod:get_module_opt(Host, ?MODULE, queue_presence, fun(B) when is_boolean(B) -> B end, true), - DropChatStates = gen_mod:get_module_opt(Host, ?MODULE, drop_chat_states, - fun(B) when is_boolean(B) -> B end, - true), - if QueuePresence; DropChatStates -> + QueueChatStates = gen_mod:get_module_opt(Host, ?MODULE, queue_chat_states, + fun(B) when is_boolean(B) -> B end, + true), + if QueuePresence; QueueChatStates -> ejabberd_hooks:delete(c2s_post_auth_features, Host, ?MODULE, add_stream_feature, 50), if QueuePresence -> @@ -82,7 +82,7 @@ stop(Host) -> filter_presence, 50); true -> ok end, - if DropChatStates -> + if QueueChatStates -> ejabberd_hooks:delete(csi_filter_stanza, Host, ?MODULE, filter_chat_states, 50); true -> ok @@ -111,12 +111,12 @@ filter_presence({C2SState, _OutStanzas} = Acc, Host, end; filter_presence(Acc, _Host, _Stanza) -> Acc. -filter_chat_states({C2SState, _OutStanzas} = Acc, _Host, +filter_chat_states({C2SState, _OutStanzas} = Acc, Host, #xmlel{name = <<"message">>} = Stanza) -> case jlib:is_standalone_chat_state(Stanza) of - true -> % Drop the stanza. + true -> ?DEBUG("Got standalone chat state notification", []), - {stop, {C2SState, []}}; + queue_add(chatstate, Stanza, Host, C2SState); false -> Acc end; @@ -177,6 +177,6 @@ get_stanzas(Queue, Host) -> mod_opt_type(queue_presence) -> fun(B) when is_boolean(B) -> B end; -mod_opt_type(drop_chat_states) -> +mod_opt_type(queue_chat_states) -> fun(B) when is_boolean(B) -> B end; -mod_opt_type(_) -> [queue_presence, drop_chat_states]. +mod_opt_type(_) -> [queue_presence, queue_chat_states]. diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index aa465fb66..f3f7ebde3 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -2257,13 +2257,15 @@ client_state_master(Config) -> Message = ChatState#message{body = [#text{data = <<"body">>}]}, %% Wait for the slave to become inactive. wait_for_slave(Config), - %% Should be dropped: - send(Config, ChatState), %% Should be queued (but see below): send(Config, Presence), %% Should replace the previous presence in the queue: send(Config, Presence#presence{type = unavailable}), - %% Should be sent immediately, together with the previous presence: + %% Should be queued (but see below): + send(Config, ChatState), + %% Should replace the previous chat state in the queue: + send(Config, ChatState#message{sub_els = [#chatstate{type = composing}]}), + %% Should be sent immediately, together with the queued stanzas: send(Config, Message), %% Wait for the slave to become active. wait_for_slave(Config), @@ -2277,6 +2279,9 @@ client_state_slave(Config) -> wait_for_master(Config), ?recv1(#presence{from = Peer, type = unavailable, sub_els = [#delay{}]}), + ?recv1(#message{from = Peer, thread = <<"1">>, + sub_els = [#chatstate{type = composing}, + #delay{}]}), ?recv1(#message{from = Peer, thread = <<"1">>, body = [#text{data = <<"body">>}], sub_els = [#chatstate{type = active}]}), diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 869c24c7a..30fff88fc 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -213,8 +213,8 @@ Welcome to this XMPP server." db_type: internal mod_carboncopy: [] mod_client_state: - drop_chat_states: true queue_presence: true + queue_chat_states: true mod_adhoc: [] mod_configure: [] mod_disco: [] @@ -269,8 +269,8 @@ Welcome to this XMPP server." db_type: internal mod_carboncopy: [] mod_client_state: - drop_chat_states: true queue_presence: true + queue_chat_states: true mod_adhoc: [] mod_configure: [] mod_disco: []