]> granicus.if.org Git - ejabberd/commitdiff
Add tests for Client State Indication support
authorHolger Weiss <holger@zedat.fu-berlin.de>
Thu, 11 Sep 2014 16:18:20 +0000 (18:18 +0200)
committerHolger Weiss <holger@zedat.fu-berlin.de>
Thu, 11 Sep 2014 16:18:20 +0000 (18:18 +0200)
test/ejabberd_SUITE.erl
test/ejabberd_SUITE_data/ejabberd.yml
test/suite.erl
tools/xmpp_codec.erl
tools/xmpp_codec.hrl
tools/xmpp_codec.spec

index fbf2444b63f72db82b15912d2782f6bc4a6e9398..0cc5afec3dc0db659605eff3fb672b19386d00bc 100644 (file)
@@ -237,6 +237,8 @@ db_tests(mnesia) ->
       [offline_master, offline_slave]},
      {test_carbons, [parallel],
       [carbons_master, carbons_slave]},
+     {test_client_state, [parallel],
+      [client_state_master, client_state_slave]},
      {test_muc, [parallel],
       [muc_master, muc_slave]},
      {test_announce, [sequence],
@@ -1505,6 +1507,42 @@ carbons_slave(Config) ->
     #presence{from = Peer, type = unavailable} = recv(),
     disconnect(Config).
 
+client_state_master(Config) ->
+    Peer = ?config(slave, Config),
+    Presence = #presence{to = Peer},
+    Message = #message{to = Peer, thread = <<"1">>,
+                      sub_els = [#chatstate_active{}]},
+    wait_for_slave(Config),
+    %% Should be queued (but see below):
+    send(Config, Presence),
+    %% Should be sent immediately, together with the previous presence:
+    send(Config, Message#message{body = [#text{data = <<"body">>}]}),
+    %% Should be dropped:
+    send(Config, Message),
+    %% Should be queued (but see below):
+    send(Config, Presence),
+    %% Should replace the previous presence in the queue:
+    send(Config, Presence#presence{type = unavailable}),
+    wait_for_slave(Config),
+    %% Should be sent immediately, as the client is active again.
+    send(Config, Message),
+    disconnect(Config).
+
+client_state_slave(Config) ->
+    true = ?config(csi, Config),
+    Peer = ?config(master, Config),
+    send(Config, #csi_inactive{}),
+    wait_for_master(Config),
+    #presence{from = Peer, sub_els = [#delay{}]} = recv(),
+    #message{from = Peer, thread = <<"1">>, sub_els = [#chatstate_active{}],
+            body = [#text{data = <<"body">>}]} = recv(),
+    wait_for_master(Config),
+    send(Config, #csi_active{}),
+    ?recv2(#presence{from = Peer, type = unavailable, sub_els = [#delay{}]},
+          #message{from = Peer, thread = <<"1">>,
+                   sub_els = [#chatstate_active{}]}),
+    disconnect(Config).
+
 %%%===================================================================
 %%% Aux functions
 %%%===================================================================
index f096fc53f97937cfe3964c87bf907c8cf54b312b..597ba5be736c51ba9785192f0543992e65ff8f4b 100644 (file)
@@ -143,6 +143,9 @@ Welcome to this XMPP server."
         db_type: internal
       mod_carboncopy:
         db_type: internal
+      mod_client_state:
+        drop_chat_states: true
+        queue_presence: true
       mod_adhoc: []
       mod_configure: []
       mod_disco: []
index a1043526f387b867243ecfd170ba911de8fdfe47..a50bb64dfc16ff059e084774c66a232a3cb3201e 100644 (file)
@@ -155,6 +155,8 @@ wait_auth_SASL_result(Config) ->
            lists:foldl(
              fun(#feature_sm{}, ConfigAcc) ->
                      set_opt(sm, true, ConfigAcc);
+                (#feature_csi{}, ConfigAcc) ->
+                     set_opt(csi, true, ConfigAcc);
                 (_, ConfigAcc) ->
                      ConfigAcc
              end, Config, Fs);
index 2b9372973116af775103c38635c29079e22106d9..d106fa8f408bed6bcc7ce01bde153f8f89c9b4e0 100644 (file)
@@ -47,6 +47,14 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
          decode_feature_sm(<<"urn:xmpp:sm:2">>, IgnoreEls, _el);
       {<<"sm">>, <<"urn:xmpp:sm:3">>} ->
          decode_feature_sm(<<"urn:xmpp:sm:3">>, IgnoreEls, _el);
+      {<<"inactive">>, <<"urn:xmpp:csi:0">>} ->
+         decode_csi_inactive(<<"urn:xmpp:csi:0">>, IgnoreEls,
+                             _el);
+      {<<"active">>, <<"urn:xmpp:csi:0">>} ->
+         decode_csi_active(<<"urn:xmpp:csi:0">>, IgnoreEls, _el);
+      {<<"csi">>, <<"urn:xmpp:csi:0">>} ->
+         decode_feature_csi(<<"urn:xmpp:csi:0">>, IgnoreEls,
+                            _el);
       {<<"sent">>, <<"urn:xmpp:carbons:2">>} ->
          decode_carbons_sent(<<"urn:xmpp:carbons:2">>, IgnoreEls,
                              _el);
@@ -163,6 +171,26 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
                              _el);
       {<<"delay">>, <<"urn:xmpp:delay">>} ->
          decode_delay(<<"urn:xmpp:delay">>, IgnoreEls, _el);
+      {<<"paused">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         decode_chatstate_paused(<<"http://jabber.org/protocol/chatstates">>,
+                                 IgnoreEls, _el);
+      {<<"inactive">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         decode_chatstate_inactive(<<"http://jabber.org/protocol/chatstates">>,
+                                   IgnoreEls, _el);
+      {<<"gone">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         decode_chatstate_gone(<<"http://jabber.org/protocol/chatstates">>,
+                               IgnoreEls, _el);
+      {<<"composing">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         decode_chatstate_composing(<<"http://jabber.org/protocol/chatstates">>,
+                                    IgnoreEls, _el);
+      {<<"active">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         decode_chatstate_active(<<"http://jabber.org/protocol/chatstates">>,
+                                 IgnoreEls, _el);
       {<<"headers">>,
        <<"http://jabber.org/protocol/shim">>} ->
          decode_shim_headers(<<"http://jabber.org/protocol/shim">>,
@@ -998,6 +1026,9 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
       {<<"enable">>, <<"urn:xmpp:sm:3">>} -> true;
       {<<"sm">>, <<"urn:xmpp:sm:2">>} -> true;
       {<<"sm">>, <<"urn:xmpp:sm:3">>} -> true;
+      {<<"inactive">>, <<"urn:xmpp:csi:0">>} -> true;
+      {<<"active">>, <<"urn:xmpp:csi:0">>} -> true;
+      {<<"csi">>, <<"urn:xmpp:csi:0">>} -> true;
       {<<"sent">>, <<"urn:xmpp:carbons:2">>} -> true;
       {<<"received">>, <<"urn:xmpp:carbons:2">>} -> true;
       {<<"private">>, <<"urn:xmpp:carbons:2">>} -> true;
@@ -1074,6 +1105,21 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) ->
          true;
       {<<"x">>, <<"jabber:x:delay">>} -> true;
       {<<"delay">>, <<"urn:xmpp:delay">>} -> true;
+      {<<"paused">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         true;
+      {<<"inactive">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         true;
+      {<<"gone">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         true;
+      {<<"composing">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         true;
+      {<<"active">>,
+       <<"http://jabber.org/protocol/chatstates">>} ->
+         true;
       {<<"headers">>,
        <<"http://jabber.org/protocol/shim">>} ->
          true;
@@ -1856,6 +1902,26 @@ encode({pubsub, _, _, _, _, _, _, _, _} = Pubsub) ->
 encode({shim, _} = Headers) ->
     encode_shim_headers(Headers,
                        [{<<"xmlns">>, <<"http://jabber.org/protocol/shim">>}]);
+encode({chatstate_active} = Active) ->
+    encode_chatstate_active(Active,
+                           [{<<"xmlns">>,
+                             <<"http://jabber.org/protocol/chatstates">>}]);
+encode({chatstate_composing} = Composing) ->
+    encode_chatstate_composing(Composing,
+                              [{<<"xmlns">>,
+                                <<"http://jabber.org/protocol/chatstates">>}]);
+encode({chatstate_gone} = Gone) ->
+    encode_chatstate_gone(Gone,
+                         [{<<"xmlns">>,
+                           <<"http://jabber.org/protocol/chatstates">>}]);
+encode({chatstate_inactive} = Inactive) ->
+    encode_chatstate_inactive(Inactive,
+                             [{<<"xmlns">>,
+                               <<"http://jabber.org/protocol/chatstates">>}]);
+encode({chatstate_paused} = Paused) ->
+    encode_chatstate_paused(Paused,
+                           [{<<"xmlns">>,
+                             <<"http://jabber.org/protocol/chatstates">>}]);
 encode({delay, _, _} = Delay) ->
     encode_delay(Delay,
                 [{<<"xmlns">>, <<"urn:xmpp:delay">>}]);
@@ -1926,6 +1992,14 @@ encode({carbons_received, _} = Received) ->
 encode({carbons_sent, _} = Sent) ->
     encode_carbons_sent(Sent,
                        [{<<"xmlns">>, <<"urn:xmpp:carbons:2">>}]);
+encode({feature_csi, _} = Csi) ->
+    encode_feature_csi(Csi, []);
+encode({csi_active} = Active) ->
+    encode_csi_active(Active,
+                     [{<<"xmlns">>, <<"urn:xmpp:csi:0">>}]);
+encode({csi_inactive} = Inactive) ->
+    encode_csi_inactive(Inactive,
+                       [{<<"xmlns">>, <<"urn:xmpp:csi:0">>}]);
 encode({feature_sm, _} = Sm) ->
     encode_feature_sm(Sm, []);
 encode({sm_enable, _, _, _} = Enable) ->
@@ -2084,6 +2158,16 @@ get_ns({pubsub, _, _, _, _, _, _, _, _}) ->
     <<"http://jabber.org/protocol/pubsub">>;
 get_ns({shim, _}) ->
     <<"http://jabber.org/protocol/shim">>;
+get_ns({chatstate_active}) ->
+    <<"http://jabber.org/protocol/chatstates">>;
+get_ns({chatstate_composing}) ->
+    <<"http://jabber.org/protocol/chatstates">>;
+get_ns({chatstate_gone}) ->
+    <<"http://jabber.org/protocol/chatstates">>;
+get_ns({chatstate_inactive}) ->
+    <<"http://jabber.org/protocol/chatstates">>;
+get_ns({chatstate_paused}) ->
+    <<"http://jabber.org/protocol/chatstates">>;
 get_ns({delay, _, _}) -> <<"urn:xmpp:delay">>;
 get_ns({legacy_delay, _, _}) -> <<"jabber:x:delay">>;
 get_ns({streamhost, _, _, _}) ->
@@ -2115,6 +2199,9 @@ get_ns({carbons_private}) -> <<"urn:xmpp:carbons:2">>;
 get_ns({carbons_received, _}) ->
     <<"urn:xmpp:carbons:2">>;
 get_ns({carbons_sent, _}) -> <<"urn:xmpp:carbons:2">>;
+get_ns({feature_csi, _}) -> <<"urn:xmpp:csi:0">>;
+get_ns({csi_active}) -> <<"urn:xmpp:csi:0">>;
+get_ns({csi_inactive}) -> <<"urn:xmpp:csi:0">>;
 get_ns(_) -> <<>>.
 
 dec_int(Val) -> dec_int(Val, infinity, infinity).
@@ -2272,6 +2359,11 @@ pp(pubsub, 8) ->
     [subscriptions, affiliations, publish, subscribe,
      unsubscribe, options, items, retract];
 pp(shim, 1) -> [headers];
+pp(chatstate_active, 0) -> [];
+pp(chatstate_composing, 0) -> [];
+pp(chatstate_gone, 0) -> [];
+pp(chatstate_inactive, 0) -> [];
+pp(chatstate_paused, 0) -> [];
 pp(delay, 2) -> [stamp, from];
 pp(legacy_delay, 2) -> [stamp, from];
 pp(streamhost, 3) -> [jid, host, port];
@@ -2298,6 +2390,9 @@ pp(carbons_enable, 0) -> [];
 pp(carbons_private, 0) -> [];
 pp(carbons_received, 1) -> [forwarded];
 pp(carbons_sent, 1) -> [forwarded];
+pp(feature_csi, 1) -> [xmlns];
+pp(csi_active, 0) -> [];
+pp(csi_inactive, 0) -> [];
 pp(feature_sm, 1) -> [xmlns];
 pp(sm_enable, 3) -> [max, resume, xmlns];
 pp(sm_enabled, 5) -> [id, location, max, resume, xmlns];
@@ -3268,6 +3363,54 @@ encode_feature_sm_attr_xmlns(undefined, _acc) -> _acc;
 encode_feature_sm_attr_xmlns(_val, _acc) ->
     [{<<"xmlns">>, _val} | _acc].
 
+decode_csi_inactive(__TopXMLNS, __IgnoreEls,
+                   {xmlel, <<"inactive">>, _attrs, _els}) ->
+    {csi_inactive}.
+
+encode_csi_inactive({csi_inactive}, _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"inactive">>, _attrs, _els}.
+
+decode_csi_active(__TopXMLNS, __IgnoreEls,
+                 {xmlel, <<"active">>, _attrs, _els}) ->
+    {csi_active}.
+
+encode_csi_active({csi_active}, _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"active">>, _attrs, _els}.
+
+decode_feature_csi(__TopXMLNS, __IgnoreEls,
+                  {xmlel, <<"csi">>, _attrs, _els}) ->
+    Xmlns = decode_feature_csi_attrs(__TopXMLNS, _attrs,
+                                    undefined),
+    {feature_csi, Xmlns}.
+
+decode_feature_csi_attrs(__TopXMLNS,
+                        [{<<"xmlns">>, _val} | _attrs], _Xmlns) ->
+    decode_feature_csi_attrs(__TopXMLNS, _attrs, _val);
+decode_feature_csi_attrs(__TopXMLNS, [_ | _attrs],
+                        Xmlns) ->
+    decode_feature_csi_attrs(__TopXMLNS, _attrs, Xmlns);
+decode_feature_csi_attrs(__TopXMLNS, [], Xmlns) ->
+    decode_feature_csi_attr_xmlns(__TopXMLNS, Xmlns).
+
+encode_feature_csi({feature_csi, Xmlns},
+                  _xmlns_attrs) ->
+    _els = [],
+    _attrs = encode_feature_csi_attr_xmlns(Xmlns,
+                                          _xmlns_attrs),
+    {xmlel, <<"csi">>, _attrs, _els}.
+
+decode_feature_csi_attr_xmlns(__TopXMLNS, undefined) ->
+    undefined;
+decode_feature_csi_attr_xmlns(__TopXMLNS, _val) -> _val.
+
+encode_feature_csi_attr_xmlns(undefined, _acc) -> _acc;
+encode_feature_csi_attr_xmlns(_val, _acc) ->
+    [{<<"xmlns">>, _val} | _acc].
+
 decode_carbons_sent(__TopXMLNS, __IgnoreEls,
                    {xmlel, <<"sent">>, _attrs, _els}) ->
     Forwarded = decode_carbons_sent_els(__TopXMLNS,
@@ -5355,6 +5498,55 @@ encode_delay_attr_from(undefined, _acc) -> _acc;
 encode_delay_attr_from(_val, _acc) ->
     [{<<"from">>, enc_jid(_val)} | _acc].
 
+decode_chatstate_paused(__TopXMLNS, __IgnoreEls,
+                       {xmlel, <<"paused">>, _attrs, _els}) ->
+    {chatstate_paused}.
+
+encode_chatstate_paused({chatstate_paused},
+                       _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"paused">>, _attrs, _els}.
+
+decode_chatstate_inactive(__TopXMLNS, __IgnoreEls,
+                         {xmlel, <<"inactive">>, _attrs, _els}) ->
+    {chatstate_inactive}.
+
+encode_chatstate_inactive({chatstate_inactive},
+                         _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"inactive">>, _attrs, _els}.
+
+decode_chatstate_gone(__TopXMLNS, __IgnoreEls,
+                     {xmlel, <<"gone">>, _attrs, _els}) ->
+    {chatstate_gone}.
+
+encode_chatstate_gone({chatstate_gone}, _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"gone">>, _attrs, _els}.
+
+decode_chatstate_composing(__TopXMLNS, __IgnoreEls,
+                          {xmlel, <<"composing">>, _attrs, _els}) ->
+    {chatstate_composing}.
+
+encode_chatstate_composing({chatstate_composing},
+                          _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"composing">>, _attrs, _els}.
+
+decode_chatstate_active(__TopXMLNS, __IgnoreEls,
+                       {xmlel, <<"active">>, _attrs, _els}) ->
+    {chatstate_active}.
+
+encode_chatstate_active({chatstate_active},
+                       _xmlns_attrs) ->
+    _els = [],
+    _attrs = _xmlns_attrs,
+    {xmlel, <<"active">>, _attrs, _els}.
+
 decode_shim_headers(__TopXMLNS, __IgnoreEls,
                    {xmlel, <<"headers">>, _attrs, _els}) ->
     Headers = decode_shim_headers_els(__TopXMLNS,
index 549c6fb1bf86bab7ffef0244d1d7a0f2acdbaac6..6e142414f9b79b7eccc34288164f650eaf0d3304 100644 (file)
@@ -8,6 +8,8 @@
 -record(text, {lang :: binary(),
                data :: binary()}).
 
+-record(chatstate_paused, {}).
+
 -record(streamhost, {jid :: any(),
                      host :: binary(),
                      port = 1080 :: non_neg_integer()}).
@@ -24,6 +26,8 @@
                              jid :: any(),
                              subid :: binary()}).
 
+-record(csi_inactive, {}).
+
 -record(ping, {}).
 
 -record(delay, {stamp :: any(),
@@ -57,6 +61,8 @@
                     resume = false :: any(),
                     xmlns :: binary()}).
 
+-record(chatstate_gone, {}).
+
 -record(starttls_failure, {}).
 
 -record(sasl_challenge, {text :: any()}).
 
 -record(sasl_response, {text :: any()}).
 
+-record(chatstate_inactive, {}).
+
 -record(pubsub_subscribe, {node :: binary(),
                            jid :: any()}).
 
+-record(chatstate_composing, {}).
+
 -record(sasl_auth, {mechanism :: binary(),
                     text :: any()}).
 
 -record(p1_push, {}).
 
+-record(feature_csi, {xmlns :: binary()}).
+
 -record(legacy_delay, {stamp :: binary(),
                        from :: any()}).
 
 
 -record(block_list, {}).
 
+-record(csi_active, {}).
+
 -record(xdata_field, {label :: binary(),
                       type :: 'boolean' | 'fixed' | 'hidden' | 'jid-multi' | 'jid-single' | 'list-multi' | 'list-single' | 'text-multi' | 'text-private' | 'text-single',
                       var :: binary(),
                       mode = tcp :: 'tcp' | 'udp',
                       sid :: binary()}).
 
+-record(chatstate_active, {}).
+
 -record(vcard_org, {name :: binary(),
                     units = [] :: [binary()]}).
 
 -record(time, {tzo :: any(),
                utc :: any()}).
 
--type xmpp_element() :: #session{} |
-                        #compression{} |
-                        #pubsub_subscription{} |
-                        #version{} |
-                        #pubsub_affiliation{} |
-                        #muc_admin{} |
-                        #sm_a{} |
-                        #carbons_sent{} |
-                        #p1_rebind{} |
-                        #sasl_abort{} |
-                        #carbons_received{} |
-                        #pubsub_retract{} |
-                        #compressed{} |
-                        #block_list{} |
-                        #'see-other-host'{} |
-                        #starttls_proceed{} |
-                        #sm_resumed{} |
-                        #forwarded{} |
-                        #privacy_list{} |
-                        #text{} |
-                        #vcard_org{} |
-                        #feature_sm{} |
-                        #pubsub_item{} |
-                        #roster_item{} |
-                        #pubsub_event_item{} |
-                        #muc_item{} |
-                        #shim{} |
-                        #caps{} |
-                        #muc{} |
-                        #stream_features{} |
-                        #stats{} |
-                        #pubsub_items{} |
-                        #pubsub_event_items{} |
-                        #disco_items{} |
-                        #pubsub_options{} |
-                        #starttls{} |
-                        #sasl_mechanisms{} |
-                        #sasl_success{} |
-                        #compress{} |
-                        #bytestreams{} |
-                        #vcard_key{} |
-                        #identity{} |
-                        #legacy_delay{} |
-                        #muc_user_destroy{} |
-                        #muc_owner_destroy{} |
-                        #privacy{} |
-                        #delay{} |
-                        #muc_history{} |
-                        #bookmark_url{} |
-                        #vcard_email{} |
-                        #vcard_label{} |
-                        #vcard_tel{} |
-                        #disco_info{} |
-                        #vcard_logo{} |
-                        #vcard_geo{} |
-                        #vcard_photo{} |
-                        #muc_owner{} |
-                        #pubsub{} |
-                        #sm_r{} |
-                        #muc_actor{} |
-                        #error{} |
-                        #stream_error{} |
-                        #feature_register{} |
-                        #roster{} |
-                        #muc_user{} |
-                        #vcard_adr{} |
-                        #register{} |
-                        #muc_invite{} |
-                        #carbons_disable{} |
-                        #bookmark_conference{} |
-                        #time{} |
-                        #sasl_response{} |
-                        #pubsub_subscribe{} |
-                        #presence{} |
-                        #message{} |
-                        #sm_enable{} |
-                        #starttls_failure{} |
-                        #sasl_challenge{} |
-                        #gone{} |
-                        #private{} |
-                        #compress_failure{} |
-                        #sasl_failure{} |
-                        #bookmark_storage{} |
-                        #vcard_name{} |
-                        #sm_resume{} |
-                        #carbons_enable{} |
-                        #carbons_private{} |
-                        #pubsub_unsubscribe{} |
-                        #muc_decline{} |
-                        #sasl_auth{} |
-                        #p1_push{} |
-                        #pubsub_publish{} |
-                        #unblock{} |
-                        #p1_ack{} |
-                        #block{} |
-                        #xdata{} |
-                        #iq{} |
-                        #last{} |
-                        #redirect{} |
-                        #sm_enabled{} |
-                        #pubsub_event{} |
-                        #vcard_sound{} |
-                        #streamhost{} |
-                        #stat{} |
-                        #xdata_field{} |
-                        #bind{} |
-                        #sm_failed{} |
-                        #vcard{} |
-                        #ping{} |
-                        #disco_item{} |
-                        #privacy_item{}.
+-type xmpp_codec_type() :: #session{} |
+                           #compression{} |
+                           #pubsub_subscription{} |
+                           #version{} |
+                           #pubsub_affiliation{} |
+                           #muc_admin{} |
+                           #sm_a{} |
+                           #carbons_sent{} |
+                           #p1_rebind{} |
+                           #sasl_abort{} |
+                           #carbons_received{} |
+                           #pubsub_retract{} |
+                           #compressed{} |
+                           #block_list{} |
+                           #'see-other-host'{} |
+                           #starttls_proceed{} |
+                           #sm_resumed{} |
+                           #forwarded{} |
+                           #privacy_list{} |
+                           #text{} |
+                           #vcard_org{} |
+                           #feature_sm{} |
+                           #pubsub_item{} |
+                           #roster_item{} |
+                           #pubsub_event_item{} |
+                           #muc_item{} |
+                           #shim{} |
+                           #pubsub_event_items{} |
+                           #disco_items{} |
+                           #pubsub_options{} |
+                           #sasl_success{} |
+                           #compress{} |
+                           #bytestreams{} |
+                           #vcard_key{} |
+                           #identity{} |
+                           #feature_csi{} |
+                           #legacy_delay{} |
+                           #muc_user_destroy{} |
+                           #muc_owner_destroy{} |
+                           #privacy{} |
+                           #delay{} |
+                           #muc_history{} |
+                           #bookmark_url{} |
+                           #vcard_email{} |
+                           #vcard_label{} |
+                           #vcard_tel{} |
+                           #vcard_logo{} |
+                           #disco_info{} |
+                           #vcard_geo{} |
+                           #vcard_photo{} |
+                           #muc_owner{} |
+                           #pubsub{} |
+                           #sm_r{} |
+                           #muc_actor{} |
+                           #error{} |
+                           #stream_error{} |
+                           #feature_register{} |
+                           #roster{} |
+                           #muc_user{} |
+                           #vcard_adr{} |
+                           #register{} |
+                           #csi_active{} |
+                           #muc_invite{} |
+                           #carbons_disable{} |
+                           #chatstate_active{} |
+                           #bookmark_conference{} |
+                           #time{} |
+                           #sasl_response{} |
+                           #chatstate_inactive{} |
+                           #pubsub_subscribe{} |
+                           #presence{} |
+                           #message{} |
+                           #sm_enable{} |
+                           #chatstate_gone{} |
+                           #starttls_failure{} |
+                           #sasl_challenge{} |
+                           #gone{} |
+                           #private{} |
+                           #compress_failure{} |
+                           #sasl_failure{} |
+                           #bookmark_storage{} |
+                           #vcard_name{} |
+                           #sm_resume{} |
+                           #carbons_enable{} |
+                           #carbons_private{} |
+                           #pubsub_unsubscribe{} |
+                           #csi_inactive{} |
+                           #muc_decline{} |
+                           #sasl_auth{} |
+                           #p1_push{} |
+                           #pubsub_publish{} |
+                           #unblock{} |
+                           #p1_ack{} |
+                           #block{} |
+                           #xdata{} |
+                           #iq{} |
+                           #last{} |
+                           #redirect{} |
+                           #sm_enabled{} |
+                           #pubsub_event{} |
+                           #vcard_sound{} |
+                           #chatstate_paused{} |
+                           #streamhost{} |
+                           #stat{} |
+                           #xdata_field{} |
+                           #bind{} |
+                           #sm_failed{} |
+                           #vcard{} |
+                           #chatstate_composing{} |
+                           #ping{} |
+                           #disco_item{} |
+                           #privacy_item{} |
+                           #caps{} |
+                           #muc{} |
+                           #stream_features{} |
+                           #stats{} |
+                           #pubsub_items{} |
+                           #starttls{} |
+                           #sasl_mechanisms{}.
index 4d218839b02fe769b518f0cf0df11286b62260c8..c5d9013ed3b75f99348101827502eb7a7bc2b68f 100644 (file)
            result = {shim, '$headers'},
            refs = [#ref{name = shim_header, label = '$headers'}]}).
 
+-xml(chatstate_active,
+     #elem{name = <<"active">>,
+           xmlns = <<"http://jabber.org/protocol/chatstates">>,
+           result = {chatstate_active}}).
+
+-xml(chatstate_composing,
+     #elem{name = <<"composing">>,
+           xmlns = <<"http://jabber.org/protocol/chatstates">>,
+           result = {chatstate_composing}}).
+
+-xml(chatstate_gone,
+     #elem{name = <<"gone">>,
+           xmlns = <<"http://jabber.org/protocol/chatstates">>,
+           result = {chatstate_gone}}).
+
+-xml(chatstate_inactive,
+     #elem{name = <<"inactive">>,
+           xmlns = <<"http://jabber.org/protocol/chatstates">>,
+           result = {chatstate_inactive}}).
+
+-xml(chatstate_paused,
+     #elem{name = <<"paused">>,
+           xmlns = <<"http://jabber.org/protocol/chatstates">>,
+           result = {chatstate_paused}}).
+
 -xml(delay,
      #elem{name = <<"delay">>,
            xmlns = <<"urn:xmpp:delay">>,
           refs = [#ref{name = forwarded, min = 1,
                         max = 1, label = '$forwarded'}]}).
 
+-xml(feature_csi,
+     #elem{name = <<"csi">>,
+          xmlns = <<"urn:xmpp:csi:0">>,
+          result = {feature_csi, '$xmlns'},
+          attrs = [#attr{name = <<"xmlns">>}]}).
+
+-xml(csi_active,
+     #elem{name = <<"active">>,
+          xmlns = <<"urn:xmpp:csi:0">>,
+          result = {csi_active}}).
+
+-xml(csi_inactive,
+     #elem{name = <<"inactive">>,
+          xmlns = <<"urn:xmpp:csi:0">>,
+          result = {csi_inactive}}).
+
 -xml(feature_sm,
      #elem{name = <<"sm">>,
           xmlns = [<<"urn:xmpp:sm:2">>, <<"urn:xmpp:sm:3">>],