From 60dbaa0dacc59b4729d935afc78f30624c2f8ff3 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sat, 15 Jun 2013 00:45:04 +1000 Subject: [PATCH] Add zlib compression test case --- test/ejabberd_SUITE.erl | 58 ++++-- test/ejabberd_SUITE_data/ejabberd.cfg | 2 +- tools/xmpp_codec.erl | 273 +++++++++++++++++++++++++- tools/xmpp_codec.hrl | 10 +- tools/xmpp_codec.spec | 56 ++++++ 5 files changed, 379 insertions(+), 20 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index ccc4310b1..dc4692457 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -61,7 +61,7 @@ init_per_testcase(start_ejabberd, Config) -> Config; init_per_testcase(TestCase, OrigConfig) -> Resource = list_to_binary(atom_to_list(TestCase)), - Config = [{resource, Resource}|OrigConfig], + Config = set_opt(resource, Resource, OrigConfig), case TestCase of test_connect -> Config; @@ -69,6 +69,8 @@ init_per_testcase(TestCase, OrigConfig) -> connect(Config); test_starttls -> connect(Config); + test_zlib -> + connect(Config); test_register -> connect(Config); auth_md5 -> @@ -89,12 +91,13 @@ end_per_testcase(_TestCase, _Config) -> groups() -> []. -%%all() -> [start_ejabberd, test_starttls]. +%%all() -> [start_ejabberd, test_zlib]. all() -> [start_ejabberd, test_connect, test_starttls, + test_zlib, test_register, auth_plain, auth_md5, @@ -134,7 +137,7 @@ connect(Config) -> binary_to_list(?config(server, Config)), ?config(port, Config), [binary, {packet, 0}, {active, false}]), - init_stream([{socket, Sock}|Config]). + init_stream(set_opt(socket, Sock, Config)). init_stream(Config) -> ok = send_text(Config, io_lib:format(?STREAM_HEADER, @@ -149,15 +152,16 @@ init_stream(Config) -> (_) -> [] end, Fs), - Feats = lists:foldl( - fun(#feature_register{}, Acc) -> - [{register, true}|Acc]; - (#starttls{}, Acc) -> - [{starttls, true}|Acc]; - (_, Acc) -> - Acc - end, [], Fs), - [{mechs, Mechs}|Feats ++ Config]. + lists:foldl( + fun(#feature_register{}, Acc) -> + set_opt(register, true, Acc); + (#starttls{}, Acc) -> + set_opt(starttls, true, Acc); + (#compression{methods = Ms}, Acc) -> + set_opt(compression, Ms, Acc); + (_, Acc) -> + Acc + end, set_opt(mechs, Mechs, Config), Fs). disconnect(Config) -> Socket = ?config(socket, Config), @@ -181,8 +185,26 @@ starttls(Config) -> ?config(socket, Config), [{certfile, ?config(certfile, Config)}, connect]), - NewConfig = [{socket, TLSSocket}|lists:keydelete(socket, 1, Config)], - disconnect(init_stream(NewConfig)). + disconnect(init_stream(set_opt(socket, TLSSocket, Config))). + +test_zlib(Config) -> + case ?config(compression, Config) of + [_|_] = Ms -> + case lists:member(<<"zlib">>, Ms) of + true -> + zlib(Config); + false -> + {skipped, 'zlib_not_available'} + end; + _ -> + {skipped, 'compression_not_available'} + end. + +zlib(Config) -> + _ = send(Config, #compress{methods = [<<"zlib">>]}), + #compressed{} = recv(), + ZlibSocket = ejabberd_socket:compress(?config(socket, Config)), + disconnect(init_stream(set_opt(socket, ZlibSocket, Config))). test_register(Config) -> case ?config(register, Config) of @@ -528,7 +550,7 @@ auth_SASL(Mech, Config) -> ?config(server, Config), ?config(password, Config)), send(Config, #sasl_auth{mechanism = Mech, text = Response}), - wait_auth_SASL_result([{sasl, SASL}|Config]). + wait_auth_SASL_result(set_opt(sasl, SASL, Config)). wait_auth_SASL_result(Config) -> case recv() of @@ -545,8 +567,7 @@ wait_auth_SASL_result(Config) -> #sasl_challenge{text = ClientIn} -> {Response, SASL} = (?config(sasl, Config))(ClientIn), send(Config, #sasl_response{text = Response}), - Config1 = proplists:delete(sasl, Config), - wait_auth_SASL_result([{sasl, SASL}|Config1]); + wait_auth_SASL_result(set_opt(sasl, SASL, Config)); #sasl_failure{} -> ct:fail(sasl_auth_failed) end. @@ -716,3 +737,6 @@ bookmark_conference() -> <<"some">>, <<"some.conference.org">>, <<>>)}. + +set_opt(Opt, Val, Config) -> + [{Opt, Val}|lists:keydelete(Opt, 1, Config)]. diff --git a/test/ejabberd_SUITE_data/ejabberd.cfg b/test/ejabberd_SUITE_data/ejabberd.cfg index 5520e4c3b..48f6580ec 100644 --- a/test/ejabberd_SUITE_data/ejabberd.cfg +++ b/test/ejabberd_SUITE_data/ejabberd.cfg @@ -6,7 +6,7 @@ {5222, ejabberd_c2s, [ {access, c2s}, {shaper, c2s_shaper}, - starttls, + starttls, zlib, {certfile, 'CERTFILE'}, {max_stanza_size, 65536} ]}, diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 1fc1151ff..749663859 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -1,6 +1,6 @@ %% Created automatically by XML generator (xml_gen.erl) %% Source: xmpp_codec.spec -%% Date: Fri, 14 Jun 2013 08:43:04 GMT +%% Date: Fri, 14 Jun 2013 14:30:53 GMT -module(xmpp_codec). @@ -348,6 +348,33 @@ decode({xmlel, _name, _attrs, _} = _el) -> {<<"stream:features">>, <<"http://etherx.jabber.org/streams">>} -> decode_stream_features(_el); + {<<"compression">>, + <<"http://jabber.org/features/compress">>} -> + decode_compression(_el); + {<<"method">>, + <<"http://jabber.org/features/compress">>} -> + decode_compression_method(_el); + {<<"compressed">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compressed(_el); + {<<"compress">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compress(_el); + {<<"method">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compress_method(_el); + {<<"failure">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compress_failure(_el); + {<<"unsupported-method">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compress_failure_unsupported_method(_el); + {<<"processing-failed">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compress_failure_processing_failed(_el); + {<<"setup-failed">>, + <<"http://jabber.org/protocol/compress">>} -> + decode_compress_failure_setup_failed(_el); {<<"failure">>, <<"urn:ietf:params:xml:ns:xmpp-tls">>} -> decode_starttls_failure(_el); @@ -715,6 +742,22 @@ encode({stream_features, _} = Stream_features) -> encode_stream_features(Stream_features, [{<<"xmlns">>, <<"http://etherx.jabber.org/streams">>}]); +encode({compression, _} = Compression) -> + encode_compression(Compression, + [{<<"xmlns">>, + <<"http://jabber.org/features/compress">>}]); +encode({compressed} = Compressed) -> + encode_compressed(Compressed, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/compress">>}]); +encode({compress, _} = Compress) -> + encode_compress(Compress, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/compress">>}]); +encode({compress_failure, _} = Failure) -> + encode_compress_failure(Failure, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/compress">>}]); encode({starttls_failure} = Failure) -> encode_starttls_failure(Failure, [{<<"xmlns">>, @@ -4638,6 +4681,234 @@ encode_starttls_failure({starttls_failure}, _attrs = _xmlns_attrs, {xmlel, <<"failure">>, _attrs, _els}. +decode_compress_failure_setup_failed({xmlel, + <<"setup-failed">>, _attrs, _els}) -> + 'setup-failed'. + +encode_compress_failure_setup_failed('setup-failed', + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"setup-failed">>, _attrs, _els}. + +decode_compress_failure_processing_failed({xmlel, + <<"processing-failed">>, _attrs, + _els}) -> + 'processing-failed'. + +encode_compress_failure_processing_failed('processing-failed', + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"processing-failed">>, _attrs, _els}. + +decode_compress_failure_unsupported_method({xmlel, + <<"unsupported-method">>, _attrs, + _els}) -> + 'unsupported-method'. + +encode_compress_failure_unsupported_method('unsupported-method', + _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"unsupported-method">>, _attrs, _els}. + +decode_compress_failure({xmlel, <<"failure">>, _attrs, + _els}) -> + Reason = decode_compress_failure_els(_els, undefined), + {compress_failure, Reason}. + +decode_compress_failure_els([], Reason) -> Reason; +decode_compress_failure_els([{xmlel, <<"setup-failed">>, + _attrs, _} = + _el + | _els], + Reason) -> + _xmlns = xml:get_attr_s(<<"xmlns">>, _attrs), + if _xmlns == <<>>; + _xmlns == <<"http://jabber.org/protocol/compress">> -> + decode_compress_failure_els(_els, + decode_compress_failure_setup_failed(_el)); + true -> decode_compress_failure_els(_els, Reason) + end; +decode_compress_failure_els([{xmlel, + <<"processing-failed">>, _attrs, _} = + _el + | _els], + Reason) -> + _xmlns = xml:get_attr_s(<<"xmlns">>, _attrs), + if _xmlns == <<>>; + _xmlns == <<"http://jabber.org/protocol/compress">> -> + decode_compress_failure_els(_els, + decode_compress_failure_processing_failed(_el)); + true -> decode_compress_failure_els(_els, Reason) + end; +decode_compress_failure_els([{xmlel, + <<"unsupported-method">>, _attrs, _} = + _el + | _els], + Reason) -> + _xmlns = xml:get_attr_s(<<"xmlns">>, _attrs), + if _xmlns == <<>>; + _xmlns == <<"http://jabber.org/protocol/compress">> -> + decode_compress_failure_els(_els, + decode_compress_failure_unsupported_method(_el)); + true -> decode_compress_failure_els(_els, Reason) + end; +decode_compress_failure_els([_ | _els], Reason) -> + decode_compress_failure_els(_els, Reason). + +encode_compress_failure({compress_failure, Reason}, + _xmlns_attrs) -> + _els = 'encode_compress_failure_$reason'(Reason, []), + _attrs = _xmlns_attrs, + {xmlel, <<"failure">>, _attrs, _els}. + +'encode_compress_failure_$reason'(undefined, _acc) -> + _acc; +'encode_compress_failure_$reason'('setup-failed' = + Reason, + _acc) -> + [encode_compress_failure_setup_failed(Reason, []) + | _acc]; +'encode_compress_failure_$reason'('processing-failed' = + Reason, + _acc) -> + [encode_compress_failure_processing_failed(Reason, []) + | _acc]; +'encode_compress_failure_$reason'('unsupported-method' = + Reason, + _acc) -> + [encode_compress_failure_unsupported_method(Reason, []) + | _acc]. + +decode_compress_method({xmlel, <<"method">>, _attrs, + _els}) -> + Cdata = decode_compress_method_els(_els, <<>>), Cdata. + +decode_compress_method_els([], Cdata) -> + decode_compress_method_cdata(Cdata); +decode_compress_method_els([{xmlcdata, _data} | _els], + Cdata) -> + decode_compress_method_els(_els, + <>); +decode_compress_method_els([_ | _els], Cdata) -> + decode_compress_method_els(_els, Cdata). + +encode_compress_method(Cdata, _xmlns_attrs) -> + _els = encode_compress_method_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"method">>, _attrs, _els}. + +decode_compress_method_cdata(<<>>) -> undefined; +decode_compress_method_cdata(_val) -> _val. + +encode_compress_method_cdata(undefined, _acc) -> _acc; +encode_compress_method_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_compress({xmlel, <<"compress">>, _attrs, + _els}) -> + Methods = decode_compress_els(_els, []), + {compress, Methods}. + +decode_compress_els([], Methods) -> + lists:reverse(Methods); +decode_compress_els([{xmlel, <<"method">>, _attrs, _} = + _el + | _els], + Methods) -> + _xmlns = xml:get_attr_s(<<"xmlns">>, _attrs), + if _xmlns == <<>>; + _xmlns == <<"http://jabber.org/protocol/compress">> -> + decode_compress_els(_els, + [decode_compress_method(_el) | Methods]); + true -> decode_compress_els(_els, Methods) + end; +decode_compress_els([_ | _els], Methods) -> + decode_compress_els(_els, Methods). + +encode_compress({compress, Methods}, _xmlns_attrs) -> + _els = 'encode_compress_$methods'(Methods, []), + _attrs = _xmlns_attrs, + {xmlel, <<"compress">>, _attrs, _els}. + +'encode_compress_$methods'([], _acc) -> _acc; +'encode_compress_$methods'([Methods | _els], _acc) -> + 'encode_compress_$methods'(_els, + [encode_compress_method(Methods, []) | _acc]). + +decode_compressed({xmlel, <<"compressed">>, _attrs, + _els}) -> + {compressed}. + +encode_compressed({compressed}, _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"compressed">>, _attrs, _els}. + +decode_compression_method({xmlel, <<"method">>, _attrs, + _els}) -> + Cdata = decode_compression_method_els(_els, <<>>), + Cdata. + +decode_compression_method_els([], Cdata) -> + decode_compression_method_cdata(Cdata); +decode_compression_method_els([{xmlcdata, _data} + | _els], + Cdata) -> + decode_compression_method_els(_els, + <>); +decode_compression_method_els([_ | _els], Cdata) -> + decode_compression_method_els(_els, Cdata). + +encode_compression_method(Cdata, _xmlns_attrs) -> + _els = encode_compression_method_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"method">>, _attrs, _els}. + +decode_compression_method_cdata(<<>>) -> undefined; +decode_compression_method_cdata(_val) -> _val. + +encode_compression_method_cdata(undefined, _acc) -> + _acc; +encode_compression_method_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_compression({xmlel, <<"compression">>, _attrs, + _els}) -> + Methods = decode_compression_els(_els, []), + {compression, Methods}. + +decode_compression_els([], Methods) -> + lists:reverse(Methods); +decode_compression_els([{xmlel, <<"method">>, _attrs, + _} = + _el + | _els], + Methods) -> + _xmlns = xml:get_attr_s(<<"xmlns">>, _attrs), + if _xmlns == <<>>; + _xmlns == <<"http://jabber.org/features/compress">> -> + decode_compression_els(_els, + [decode_compression_method(_el) | Methods]); + true -> decode_compression_els(_els, Methods) + end; +decode_compression_els([_ | _els], Methods) -> + decode_compression_els(_els, Methods). + +encode_compression({compression, Methods}, + _xmlns_attrs) -> + _els = 'encode_compression_$methods'(Methods, []), + _attrs = _xmlns_attrs, + {xmlel, <<"compression">>, _attrs, _els}. + +'encode_compression_$methods'([], _acc) -> _acc; +'encode_compression_$methods'([Methods | _els], _acc) -> + 'encode_compression_$methods'(_els, + [encode_compression_method(Methods, []) + | _acc]). + decode_stream_features({xmlel, <<"stream:features">>, _attrs, _els}) -> __Els = decode_stream_features_els(_els, []), diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index 75060b1ee..96227e77d 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -1,6 +1,6 @@ %% Created automatically by XML generator (xml_gen.erl) %% Source: xmpp_codec.spec -%% Date: Fri, 14 Jun 2013 08:43:04 GMT +%% Date: Fri, 14 Jun 2013 14:30:53 GMT -record(last, {seconds, text}). @@ -86,6 +86,14 @@ -record(starttls_failure, {}). +-record(compress_failure, {reason}). + +-record(compress, {methods = []}). + +-record(compressed, {}). + +-record(compression, {methods = []}). + -record(stream_features, {sub_els = []}). -record(p1_push, {}). diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 1e55912cb..d89318223 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -748,6 +748,62 @@ xmlns = <<"urn:ietf:params:xml:ns:xmpp-tls">>, result = {starttls_failure}}}. + %% + %% + %% + +{compress_failure_setup_failed, + #elem{name = <<"setup-failed">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = 'setup-failed'}}. +{compress_failure_processing_failed, + #elem{name = <<"processing-failed">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = 'processing-failed'}}. +{compress_failure_unsupported_method, + #elem{name = <<"unsupported-method">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = 'unsupported-method'}}. + +{compress_failure, + #elem{name = <<"failure">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = {compress_failure, '$reason'}, + refs = [#ref{name = compress_failure_setup_failed, + min = 0, max = 1, label = '$reason'}, + #ref{name = compress_failure_processing_failed, + min = 0, max = 1, label = '$reason'}, + #ref{name = compress_failure_unsupported_method, + min = 0, max = 1, label = '$reason'}]}}. + +{compress_method, + #elem{name = <<"method">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = '$cdata'}}. + +{compress, + #elem{name = <<"compress">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = {compress, '$methods'}, + refs = [#ref{name = compress_method, + label = '$methods'}]}}. + +{compressed, + #elem{name = <<"compressed">>, + xmlns = <<"http://jabber.org/protocol/compress">>, + result = {compressed}}}. + +{compression_method, + #elem{name = <<"method">>, + xmlns = <<"http://jabber.org/features/compress">>, + result = '$cdata'}}. + +{compression, + #elem{name = <<"compression">>, + xmlns = <<"http://jabber.org/features/compress">>, + result = {compression, '$methods'}, + refs = [#ref{name = compression_method, label = '$methods'}]}}. + {stream_features, #elem{name = <<"stream:features">>, xmlns = <<"http://etherx.jabber.org/streams">>,