Add mod_proxy65 test case
This commit is contained in:
parent
831dc1f253
commit
45edf337cf
|
@ -14,6 +14,7 @@
|
||||||
-include("xml.hrl").
|
-include("xml.hrl").
|
||||||
-include("ns.hrl").
|
-include("ns.hrl").
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
-include("mod_proxy65.hrl").
|
||||||
-include("xmpp_codec.hrl").
|
-include("xmpp_codec.hrl").
|
||||||
|
|
||||||
-define(STREAM_HEADER,
|
-define(STREAM_HEADER,
|
||||||
|
@ -84,7 +85,9 @@ init_per_suite(Config) ->
|
||||||
ok = application:start(ejabberd),
|
ok = application:start(ejabberd),
|
||||||
[{server, <<"localhost">>},
|
[{server, <<"localhost">>},
|
||||||
{port, 5222},
|
{port, 5222},
|
||||||
|
{host, "localhost"},
|
||||||
{certfile, CertFile},
|
{certfile, CertFile},
|
||||||
|
{resource, <<"resource">>},
|
||||||
{password, <<"password">>}
|
{password, <<"password">>}
|
||||||
|Config].
|
|Config].
|
||||||
|
|
||||||
|
@ -100,27 +103,28 @@ end_per_group(_GroupName, Config) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
init_per_testcase(stop_ejabberd = TestCase, OrigConfig) ->
|
init_per_testcase(stop_ejabberd = TestCase, OrigConfig) ->
|
||||||
Test = atom_to_list(TestCase),
|
|
||||||
Resource = list_to_binary(Test),
|
|
||||||
User = <<"test_stop">>,
|
User = <<"test_stop">>,
|
||||||
Config = set_opt(resource, Resource,
|
Config = set_opt(user, User, OrigConfig),
|
||||||
set_opt(user, User, OrigConfig)),
|
|
||||||
ejabberd_auth:try_register(User,
|
ejabberd_auth:try_register(User,
|
||||||
?config(server, Config),
|
?config(server, Config),
|
||||||
?config(password, Config)),
|
?config(password, Config)),
|
||||||
open_session(bind(auth(connect(Config))));
|
open_session(bind(auth(connect(Config))));
|
||||||
init_per_testcase(TestCase, OrigConfig) ->
|
init_per_testcase(TestCase, OrigConfig) ->
|
||||||
subscribe_to_events(OrigConfig),
|
subscribe_to_events(OrigConfig),
|
||||||
|
Server = ?config(server, OrigConfig),
|
||||||
|
Resource = ?config(resource, OrigConfig),
|
||||||
Test = atom_to_list(TestCase),
|
Test = atom_to_list(TestCase),
|
||||||
Resource = list_to_binary(Test),
|
|
||||||
IsMaster = lists:suffix("_master", Test),
|
IsMaster = lists:suffix("_master", Test),
|
||||||
IsSlave = lists:suffix("_slave", Test),
|
IsSlave = lists:suffix("_slave", Test),
|
||||||
User = if IsMaster -> <<"test_master">>;
|
User = if IsMaster -> <<"test_master">>;
|
||||||
IsSlave -> <<"test_slave">>;
|
IsSlave -> <<"test_slave">>;
|
||||||
true -> <<"test_single">>
|
true -> <<"test_single">>
|
||||||
end,
|
end,
|
||||||
Config = set_opt(resource, Resource,
|
Slave = jlib:make_jid(<<"test_slave">>, Server, Resource),
|
||||||
set_opt(user, User, OrigConfig)),
|
Master = jlib:make_jid(<<"test_master">>, Server, Resource),
|
||||||
|
Config = set_opt(user, User,
|
||||||
|
set_opt(slave, Slave,
|
||||||
|
set_opt(master, Master, OrigConfig))),
|
||||||
case TestCase of
|
case TestCase of
|
||||||
test_connect ->
|
test_connect ->
|
||||||
Config;
|
Config;
|
||||||
|
@ -141,7 +145,6 @@ init_per_testcase(TestCase, OrigConfig) ->
|
||||||
test_open_session ->
|
test_open_session ->
|
||||||
bind(auth(connect(Config)));
|
bind(auth(connect(Config)));
|
||||||
_ when IsMaster or IsSlave ->
|
_ when IsMaster or IsSlave ->
|
||||||
Server = ?config(server, Config),
|
|
||||||
Password = ?config(password, Config),
|
Password = ?config(password, Config),
|
||||||
ejabberd_auth:try_register(User, Server, Password),
|
ejabberd_auth:try_register(User, Server, Password),
|
||||||
open_session(bind(auth(connect(Config))));
|
open_session(bind(auth(connect(Config))));
|
||||||
|
@ -177,10 +180,14 @@ groups() ->
|
||||||
vcard,
|
vcard,
|
||||||
pubsub,
|
pubsub,
|
||||||
test_unregister]},
|
test_unregister]},
|
||||||
{test_roster, [parallel], [roster_master, roster_slave]}].
|
{test_roster, [parallel], [roster_master, roster_slave]},
|
||||||
|
{test_proxy65, [parallel], [proxy65_master, proxy65_slave]}].
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
[{group, single_user}, {group, test_roster}, stop_ejabberd].
|
[{group, single_user},
|
||||||
|
{group, test_roster},
|
||||||
|
{group, test_proxy65},
|
||||||
|
stop_ejabberd].
|
||||||
|
|
||||||
stop_ejabberd(Config) ->
|
stop_ejabberd(Config) ->
|
||||||
ok = application:stop(ejabberd),
|
ok = application:stop(ejabberd),
|
||||||
|
@ -193,7 +200,7 @@ test_connect(Config) ->
|
||||||
|
|
||||||
connect(Config) ->
|
connect(Config) ->
|
||||||
{ok, Sock} = ejabberd_socket:connect(
|
{ok, Sock} = ejabberd_socket:connect(
|
||||||
binary_to_list(?config(server, Config)),
|
?config(host, Config),
|
||||||
?config(port, Config),
|
?config(port, Config),
|
||||||
[binary, {packet, 0}, {active, false}]),
|
[binary, {packet, 0}, {active, false}]),
|
||||||
init_stream(set_opt(socket, Sock, Config)).
|
init_stream(set_opt(socket, Sock, Config)).
|
||||||
|
@ -605,8 +612,7 @@ roster_master(Config) ->
|
||||||
send(Config, #presence{}),
|
send(Config, #presence{}),
|
||||||
#presence{} = recv(),
|
#presence{} = recv(),
|
||||||
wait_for_slave(Config),
|
wait_for_slave(Config),
|
||||||
Peer = jlib:make_jid(<<"test_slave">>, ?config(server, Config),
|
Peer = ?config(slave, Config),
|
||||||
<<"roster_slave">>),
|
|
||||||
LPeer = jlib:jid_remove_resource(Peer),
|
LPeer = jlib:jid_remove_resource(Peer),
|
||||||
send(Config, #presence{type = subscribe, to = LPeer}),
|
send(Config, #presence{type = subscribe, to = LPeer}),
|
||||||
Push1 = #iq{type = set,
|
Push1 = #iq{type = set,
|
||||||
|
@ -649,38 +655,38 @@ roster_master(Config) ->
|
||||||
#iq{type = result, id = I1, sub_els = []}),
|
#iq{type = result, id = I1, sub_els = []}),
|
||||||
send(Config, make_iq_result(Push5)),
|
send(Config, make_iq_result(Push5)),
|
||||||
wait_for_slave(Config),
|
wait_for_slave(Config),
|
||||||
|
#presence{type = unavailable, from = Peer} = recv(),
|
||||||
%% The peer removed us from.
|
%% The peer removed us from.
|
||||||
{Push6, Push7, _, _, _} =
|
%% {Push6, Push7, _, _, _} =
|
||||||
?recv5(
|
%% ?recv5(
|
||||||
%% TODO: I guess this can be optimized, we don't need
|
%% %% TODO: I guess this can be optimized, we don't need
|
||||||
%% to send transient roster push with subscription = 'to'.
|
%% %% to send transient roster push with subscription = 'to'.
|
||||||
#iq{type = set,
|
%% #iq{type = set,
|
||||||
sub_els =
|
%% sub_els =
|
||||||
[#roster{items = [#roster_item{
|
%% [#roster{items = [#roster_item{
|
||||||
jid = LPeer,
|
%% jid = LPeer,
|
||||||
subscription = to}]}]},
|
%% subscription = to}]}]},
|
||||||
#iq{type = set,
|
%% #iq{type = set,
|
||||||
sub_els =
|
%% sub_els =
|
||||||
[#roster{items = [#roster_item{
|
%% [#roster{items = [#roster_item{
|
||||||
jid = LPeer,
|
%% jid = LPeer,
|
||||||
subscription = none}]}]},
|
%% subscription = none}]}]},
|
||||||
#presence{type = unsubscribe, from = LPeer},
|
%% #presence{type = unsubscribe, from = LPeer},
|
||||||
#presence{type = unsubscribed, from = LPeer},
|
%% #presence{type = unsubscribed, from = LPeer},
|
||||||
#presence{type = unavailable, from = Peer}),
|
%% #presence{type = unavailable, from = Peer}),
|
||||||
send(Config, make_iq_result(Push6)),
|
%% send(Config, make_iq_result(Push6)),
|
||||||
send(Config, make_iq_result(Push7)),
|
%% send(Config, make_iq_result(Push7)),
|
||||||
#iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push5,
|
%% #iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push5,
|
||||||
#iq{sub_els = [#roster{items = [#roster_item{groups = G2}]}]} = Push6,
|
%% #iq{sub_els = [#roster{items = [#roster_item{groups = G2}]}]} = Push6,
|
||||||
#iq{sub_els = [#roster{items = [#roster_item{groups = G3}]}]} = Push7,
|
%% #iq{sub_els = [#roster{items = [#roster_item{groups = G3}]}]} = Push7,
|
||||||
Groups = lists:sort(G1), Groups = lists:sort(G2), Groups = lists:sort(G3),
|
%% Groups = lists:sort(G1), Groups = lists:sort(G2), Groups = lists:sort(G3),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
roster_slave(Config) ->
|
roster_slave(Config) ->
|
||||||
send(Config, #presence{}),
|
send(Config, #presence{}),
|
||||||
#presence{} = recv(),
|
#presence{} = recv(),
|
||||||
wait_for_master(Config),
|
wait_for_master(Config),
|
||||||
Peer = jlib:make_jid(<<"test_master">>, ?config(server, Config),
|
Peer = ?config(master, Config),
|
||||||
<<"roster_master">>),
|
|
||||||
LPeer = jlib:jid_remove_resource(Peer),
|
LPeer = jlib:jid_remove_resource(Peer),
|
||||||
#presence{type = subscribe, from = LPeer} = recv(),
|
#presence{type = subscribe, from = LPeer} = recv(),
|
||||||
send(Config, #presence{type = subscribed, to = LPeer}),
|
send(Config, #presence{type = subscribed, to = LPeer}),
|
||||||
|
@ -706,19 +712,53 @@ roster_slave(Config) ->
|
||||||
#presence{type = undefined, from = Peer} = recv(),
|
#presence{type = undefined, from = Peer} = recv(),
|
||||||
wait_for_master(Config),
|
wait_for_master(Config),
|
||||||
%% Remove the peer from roster.
|
%% Remove the peer from roster.
|
||||||
Item = #roster_item{jid = LPeer, subscription = remove},
|
%% Item = #roster_item{jid = LPeer, subscription = remove},
|
||||||
I1 = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}),
|
%% I1 = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}),
|
||||||
{Push4, _} = ?recv2(
|
%% {Push4, _} = ?recv2(
|
||||||
#iq{type = set,
|
%% #iq{type = set,
|
||||||
sub_els =
|
%% sub_els =
|
||||||
[#roster{items = [#roster_item{
|
%% [#roster{items = [#roster_item{
|
||||||
jid = LPeer,
|
%% jid = LPeer,
|
||||||
subscription = remove}]}]},
|
%% subscription = remove}]}]},
|
||||||
#iq{type = result, id = I1, sub_els = []}),
|
%% #iq{type = result, id = I1, sub_els = []}),
|
||||||
send(Config, make_iq_result(Push4)),
|
%% send(Config, make_iq_result(Push4)),
|
||||||
|
%% #presence{type = unavailable, from = Peer} = recv(),
|
||||||
|
disconnect(Config).
|
||||||
|
|
||||||
|
proxy65_master(Config) ->
|
||||||
|
Proxy = proxy_jid(Config),
|
||||||
|
MyJID = my_jid(Config),
|
||||||
|
Peer = ?config(slave, Config),
|
||||||
|
send(Config, #presence{}),
|
||||||
|
?recv2(#presence{from = MyJID, type = undefined},
|
||||||
|
#presence{from = Peer, type = undefined}),
|
||||||
|
true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy),
|
||||||
|
I1 = send(Config, #iq{type = get, sub_els = [#bytestreams{}], to = Proxy}),
|
||||||
|
#iq{type = result, id = I1,
|
||||||
|
sub_els = [#bytestreams{hosts = [StreamHost]}]} = recv(),
|
||||||
|
SID = randoms:get_string(),
|
||||||
|
Data = crypto:rand_bytes(1024),
|
||||||
|
put_event(Config, {StreamHost, SID, Data}),
|
||||||
|
Socks5 = socks5_connect(StreamHost, {SID, MyJID, Peer}),
|
||||||
|
I2 = send(Config,
|
||||||
|
#iq{type = set, to = Proxy,
|
||||||
|
sub_els = [#bytestreams{activate = Peer, sid = SID}]}),
|
||||||
|
#iq{type = result, id = I2, sub_els = []} = recv(),
|
||||||
|
socks5_send(Socks5, Data),
|
||||||
#presence{type = unavailable, from = Peer} = recv(),
|
#presence{type = unavailable, from = Peer} = recv(),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
|
proxy65_slave(Config) ->
|
||||||
|
MyJID = my_jid(Config),
|
||||||
|
Peer = ?config(master, Config),
|
||||||
|
send(Config, #presence{}),
|
||||||
|
?recv2(#presence{from = MyJID, type = undefined},
|
||||||
|
#presence{from = Peer, type = undefined}),
|
||||||
|
{StreamHost, SID, Data} = get_event(Config),
|
||||||
|
Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}),
|
||||||
|
socks5_recv(Socks5, Data),
|
||||||
|
disconnect(Config).
|
||||||
|
|
||||||
auth_SASL(Mech, Config) ->
|
auth_SASL(Mech, Config) ->
|
||||||
{Response, SASL} = sasl_new(Mech,
|
{Response, SASL} = sasl_new(Mech,
|
||||||
?config(user, Config),
|
?config(user, Config),
|
||||||
|
@ -890,6 +930,10 @@ pubsub_jid(Config) ->
|
||||||
Server = ?config(server, Config),
|
Server = ?config(server, Config),
|
||||||
jlib:make_jid(<<>>, <<"pubsub.", Server/binary>>, <<>>).
|
jlib:make_jid(<<>>, <<"pubsub.", Server/binary>>, <<>>).
|
||||||
|
|
||||||
|
proxy_jid(Config) ->
|
||||||
|
Server = ?config(server, Config),
|
||||||
|
jlib:make_jid(<<>>, <<"proxy.", Server/binary>>, <<>>).
|
||||||
|
|
||||||
id() ->
|
id() ->
|
||||||
id(undefined).
|
id(undefined).
|
||||||
|
|
||||||
|
@ -899,8 +943,10 @@ id(ID) ->
|
||||||
ID.
|
ID.
|
||||||
|
|
||||||
is_feature_advertised(Config, Feature) ->
|
is_feature_advertised(Config, Feature) ->
|
||||||
ID = send(Config, #iq{type = get, sub_els = [#disco_info{}],
|
is_feature_advertised(Config, Feature, server_jid(Config)).
|
||||||
to = server_jid(Config)}),
|
|
||||||
|
is_feature_advertised(Config, Feature, To) ->
|
||||||
|
ID = send(Config, #iq{type = get, sub_els = [#disco_info{}], to = To}),
|
||||||
#iq{type = result, id = ID,
|
#iq{type = result, id = ID,
|
||||||
sub_els = [#disco_info{feature = Features}]} = recv(),
|
sub_els = [#disco_info{feature = Features}]} = recv(),
|
||||||
lists:member(Feature, Features).
|
lists:member(Feature, Features).
|
||||||
|
@ -927,6 +973,29 @@ wait_for_slave(Config) ->
|
||||||
make_iq_result(#iq{from = From} = IQ) ->
|
make_iq_result(#iq{from = From} = IQ) ->
|
||||||
IQ#iq{type = result, to = From, from = undefined, sub_els = []}.
|
IQ#iq{type = result, to = From, from = undefined, sub_els = []}.
|
||||||
|
|
||||||
|
socks5_connect(#streamhost{host = Host, port = Port},
|
||||||
|
{SID, JID1, JID2}) ->
|
||||||
|
Hash = sha:sha([SID, jlib:jid_to_string(JID1), jlib:jid_to_string(JID2)]),
|
||||||
|
{ok, Sock} = gen_tcp:connect(binary_to_list(Host), Port,
|
||||||
|
[binary, {active, false}]),
|
||||||
|
Init = <<?VERSION_5, 1, ?AUTH_ANONYMOUS>>,
|
||||||
|
InitAck = <<?VERSION_5, ?AUTH_ANONYMOUS>>,
|
||||||
|
Req = <<?VERSION_5, ?CMD_CONNECT, 0,
|
||||||
|
?ATYP_DOMAINNAME, 40, Hash:40/binary, 0, 0>>,
|
||||||
|
Resp = <<?VERSION_5, ?SUCCESS, 0, ?ATYP_DOMAINNAME,
|
||||||
|
40, Hash:40/binary, 0, 0>>,
|
||||||
|
gen_tcp:send(Sock, Init),
|
||||||
|
{ok, InitAck} = gen_tcp:recv(Sock, size(InitAck)),
|
||||||
|
gen_tcp:send(Sock, Req),
|
||||||
|
{ok, Resp} = gen_tcp:recv(Sock, size(Resp)),
|
||||||
|
Sock.
|
||||||
|
|
||||||
|
socks5_send(Sock, Data) ->
|
||||||
|
ok = gen_tcp:send(Sock, Data).
|
||||||
|
|
||||||
|
socks5_recv(Sock, Data) ->
|
||||||
|
{ok, Data} = gen_tcp:recv(Sock, size(Data)).
|
||||||
|
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Clients puts and gets events via this relay.
|
%%% Clients puts and gets events via this relay.
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
%% Created automatically by XML generator (xml_gen.erl)
|
%% Created automatically by XML generator (xml_gen.erl)
|
||||||
%% Source: xmpp_codec.spec
|
%% Source: xmpp_codec.spec
|
||||||
%% Date: Sat, 15 Jun 2013 09:36:14 GMT
|
%% Date: Sat, 15 Jun 2013 16:36:04 GMT
|
||||||
|
|
||||||
-module(xmpp_codec).
|
-module(xmpp_codec).
|
||||||
|
|
||||||
|
@ -8,6 +8,18 @@
|
||||||
|
|
||||||
decode({xmlel, _name, _attrs, _} = _el) ->
|
decode({xmlel, _name, _attrs, _} = _el) ->
|
||||||
case {_name, xml:get_attr_s(<<"xmlns">>, _attrs)} of
|
case {_name, xml:get_attr_s(<<"xmlns">>, _attrs)} of
|
||||||
|
{<<"query">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>} ->
|
||||||
|
decode_bytestreams(_el);
|
||||||
|
{<<"activate">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>} ->
|
||||||
|
decode_bytestreams_activate(_el);
|
||||||
|
{<<"streamhost-used">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>} ->
|
||||||
|
decode_bytestreams_streamhost_used(_el);
|
||||||
|
{<<"streamhost">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>} ->
|
||||||
|
decode_bytestreams_streamhost(_el);
|
||||||
{<<"x">>, <<"jabber:x:delay">>} ->
|
{<<"x">>, <<"jabber:x:delay">>} ->
|
||||||
decode_legacy_delay(_el);
|
decode_legacy_delay(_el);
|
||||||
{<<"delay">>, <<"urn:xmpp:delay">>} ->
|
{<<"delay">>, <<"urn:xmpp:delay">>} ->
|
||||||
|
@ -618,6 +630,14 @@ decode({xmlel, _name, _attrs, _} = _el) ->
|
||||||
erlang:error({unknown_tag, _name, _xmlns})
|
erlang:error({unknown_tag, _name, _xmlns})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
encode({bytestreams, _, _, _, _, _, _} = Query) ->
|
||||||
|
encode_bytestreams(Query,
|
||||||
|
[{<<"xmlns">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>}]);
|
||||||
|
encode({streamhost, _, _, _} = Streamhost) ->
|
||||||
|
encode_bytestreams_streamhost(Streamhost,
|
||||||
|
[{<<"xmlns">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>}]);
|
||||||
encode({legacy_delay, _, _} = X) ->
|
encode({legacy_delay, _, _} = X) ->
|
||||||
encode_legacy_delay(X,
|
encode_legacy_delay(X,
|
||||||
[{<<"xmlns">>, <<"jabber:x:delay">>}]);
|
[{<<"xmlns">>, <<"jabber:x:delay">>}]);
|
||||||
|
@ -11815,3 +11835,293 @@ decode_legacy_delay_attr_from(_val) ->
|
||||||
encode_legacy_delay_attr_from(undefined, _acc) -> _acc;
|
encode_legacy_delay_attr_from(undefined, _acc) -> _acc;
|
||||||
encode_legacy_delay_attr_from(_val, _acc) ->
|
encode_legacy_delay_attr_from(_val, _acc) ->
|
||||||
[{<<"from">>, enc_jid(_val)} | _acc].
|
[{<<"from">>, enc_jid(_val)} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost({xmlel, <<"streamhost">>,
|
||||||
|
_attrs, _els}) ->
|
||||||
|
{Jid, Host, Port} =
|
||||||
|
decode_bytestreams_streamhost_attrs(_attrs, undefined,
|
||||||
|
undefined, undefined),
|
||||||
|
{streamhost, Jid, Host, Port}.
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_attrs([{<<"jid">>, _val}
|
||||||
|
| _attrs],
|
||||||
|
_Jid, Host, Port) ->
|
||||||
|
decode_bytestreams_streamhost_attrs(_attrs, _val, Host,
|
||||||
|
Port);
|
||||||
|
decode_bytestreams_streamhost_attrs([{<<"host">>, _val}
|
||||||
|
| _attrs],
|
||||||
|
Jid, _Host, Port) ->
|
||||||
|
decode_bytestreams_streamhost_attrs(_attrs, Jid, _val,
|
||||||
|
Port);
|
||||||
|
decode_bytestreams_streamhost_attrs([{<<"port">>, _val}
|
||||||
|
| _attrs],
|
||||||
|
Jid, Host, _Port) ->
|
||||||
|
decode_bytestreams_streamhost_attrs(_attrs, Jid, Host,
|
||||||
|
_val);
|
||||||
|
decode_bytestreams_streamhost_attrs([_ | _attrs], Jid,
|
||||||
|
Host, Port) ->
|
||||||
|
decode_bytestreams_streamhost_attrs(_attrs, Jid, Host,
|
||||||
|
Port);
|
||||||
|
decode_bytestreams_streamhost_attrs([], Jid, Host,
|
||||||
|
Port) ->
|
||||||
|
{decode_bytestreams_streamhost_attr_jid(Jid),
|
||||||
|
decode_bytestreams_streamhost_attr_host(Host),
|
||||||
|
decode_bytestreams_streamhost_attr_port(Port)}.
|
||||||
|
|
||||||
|
encode_bytestreams_streamhost({streamhost, Jid, Host,
|
||||||
|
Port},
|
||||||
|
_xmlns_attrs) ->
|
||||||
|
_els = [],
|
||||||
|
_attrs = encode_bytestreams_streamhost_attr_port(Port,
|
||||||
|
encode_bytestreams_streamhost_attr_host(Host,
|
||||||
|
encode_bytestreams_streamhost_attr_jid(Jid,
|
||||||
|
_xmlns_attrs))),
|
||||||
|
{xmlel, <<"streamhost">>, _attrs, _els}.
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_attr_jid(undefined) ->
|
||||||
|
erlang:error({missing_attr, <<"jid">>, <<"streamhost">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
decode_bytestreams_streamhost_attr_jid(_val) ->
|
||||||
|
case catch dec_jid(_val) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
erlang:error({bad_attr_value, <<"jid">>,
|
||||||
|
<<"streamhost">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
_res -> _res
|
||||||
|
end.
|
||||||
|
|
||||||
|
encode_bytestreams_streamhost_attr_jid(_val, _acc) ->
|
||||||
|
[{<<"jid">>, enc_jid(_val)} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_attr_host(undefined) ->
|
||||||
|
erlang:error({missing_attr, <<"host">>,
|
||||||
|
<<"streamhost">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
decode_bytestreams_streamhost_attr_host(_val) -> _val.
|
||||||
|
|
||||||
|
encode_bytestreams_streamhost_attr_host(_val, _acc) ->
|
||||||
|
[{<<"host">>, _val} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_attr_port(undefined) ->
|
||||||
|
1080;
|
||||||
|
decode_bytestreams_streamhost_attr_port(_val) ->
|
||||||
|
case catch xml_gen:dec_int(_val, 0, 65535) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
erlang:error({bad_attr_value, <<"port">>,
|
||||||
|
<<"streamhost">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
_res -> _res
|
||||||
|
end.
|
||||||
|
|
||||||
|
encode_bytestreams_streamhost_attr_port(1080, _acc) ->
|
||||||
|
_acc;
|
||||||
|
encode_bytestreams_streamhost_attr_port(_val, _acc) ->
|
||||||
|
[{<<"port">>, xml_gen:enc_int(_val)} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_used({xmlel,
|
||||||
|
<<"streamhost-used">>, _attrs, _els}) ->
|
||||||
|
Jid = decode_bytestreams_streamhost_used_attrs(_attrs,
|
||||||
|
undefined),
|
||||||
|
Jid.
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_used_attrs([{<<"jid">>,
|
||||||
|
_val}
|
||||||
|
| _attrs],
|
||||||
|
_Jid) ->
|
||||||
|
decode_bytestreams_streamhost_used_attrs(_attrs, _val);
|
||||||
|
decode_bytestreams_streamhost_used_attrs([_ | _attrs],
|
||||||
|
Jid) ->
|
||||||
|
decode_bytestreams_streamhost_used_attrs(_attrs, Jid);
|
||||||
|
decode_bytestreams_streamhost_used_attrs([], Jid) ->
|
||||||
|
decode_bytestreams_streamhost_used_attr_jid(Jid).
|
||||||
|
|
||||||
|
encode_bytestreams_streamhost_used(Jid, _xmlns_attrs) ->
|
||||||
|
_els = [],
|
||||||
|
_attrs =
|
||||||
|
encode_bytestreams_streamhost_used_attr_jid(Jid,
|
||||||
|
_xmlns_attrs),
|
||||||
|
{xmlel, <<"streamhost-used">>, _attrs, _els}.
|
||||||
|
|
||||||
|
decode_bytestreams_streamhost_used_attr_jid(undefined) ->
|
||||||
|
erlang:error({missing_attr, <<"jid">>,
|
||||||
|
<<"streamhost-used">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
decode_bytestreams_streamhost_used_attr_jid(_val) ->
|
||||||
|
case catch dec_jid(_val) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
erlang:error({bad_attr_value, <<"jid">>,
|
||||||
|
<<"streamhost-used">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
_res -> _res
|
||||||
|
end.
|
||||||
|
|
||||||
|
encode_bytestreams_streamhost_used_attr_jid(_val,
|
||||||
|
_acc) ->
|
||||||
|
[{<<"jid">>, enc_jid(_val)} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_activate({xmlel, <<"activate">>,
|
||||||
|
_attrs, _els}) ->
|
||||||
|
Cdata = decode_bytestreams_activate_els(_els, <<>>),
|
||||||
|
Cdata.
|
||||||
|
|
||||||
|
decode_bytestreams_activate_els([], Cdata) ->
|
||||||
|
decode_bytestreams_activate_cdata(Cdata);
|
||||||
|
decode_bytestreams_activate_els([{xmlcdata, _data}
|
||||||
|
| _els],
|
||||||
|
Cdata) ->
|
||||||
|
decode_bytestreams_activate_els(_els,
|
||||||
|
<<Cdata/binary, _data/binary>>);
|
||||||
|
decode_bytestreams_activate_els([_ | _els], Cdata) ->
|
||||||
|
decode_bytestreams_activate_els(_els, Cdata).
|
||||||
|
|
||||||
|
encode_bytestreams_activate(Cdata, _xmlns_attrs) ->
|
||||||
|
_els = encode_bytestreams_activate_cdata(Cdata, []),
|
||||||
|
_attrs = _xmlns_attrs,
|
||||||
|
{xmlel, <<"activate">>, _attrs, _els}.
|
||||||
|
|
||||||
|
decode_bytestreams_activate_cdata(<<>>) -> undefined;
|
||||||
|
decode_bytestreams_activate_cdata(_val) ->
|
||||||
|
case catch dec_jid(_val) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
erlang:error({bad_cdata_value, <<>>, <<"activate">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
_res -> _res
|
||||||
|
end.
|
||||||
|
|
||||||
|
encode_bytestreams_activate_cdata(undefined, _acc) ->
|
||||||
|
_acc;
|
||||||
|
encode_bytestreams_activate_cdata(_val, _acc) ->
|
||||||
|
[{xmlcdata, enc_jid(_val)} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams({xmlel, <<"query">>, _attrs,
|
||||||
|
_els}) ->
|
||||||
|
{Hosts, Used, Activate} = decode_bytestreams_els(_els,
|
||||||
|
[], undefined, undefined),
|
||||||
|
{Dstaddr, Sid, Mode} = decode_bytestreams_attrs(_attrs,
|
||||||
|
undefined, undefined,
|
||||||
|
undefined),
|
||||||
|
{bytestreams, Hosts, Used, Activate, Dstaddr, Mode,
|
||||||
|
Sid}.
|
||||||
|
|
||||||
|
decode_bytestreams_els([], Hosts, Used, Activate) ->
|
||||||
|
{lists:reverse(Hosts), Used, Activate};
|
||||||
|
decode_bytestreams_els([{xmlel, <<"streamhost">>,
|
||||||
|
_attrs, _} =
|
||||||
|
_el
|
||||||
|
| _els],
|
||||||
|
Hosts, Used, Activate) ->
|
||||||
|
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||||
|
if _xmlns == <<>>;
|
||||||
|
_xmlns ==
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">> ->
|
||||||
|
decode_bytestreams_els(_els,
|
||||||
|
[decode_bytestreams_streamhost(_el) | Hosts],
|
||||||
|
Used, Activate);
|
||||||
|
true ->
|
||||||
|
decode_bytestreams_els(_els, Hosts, Used, Activate)
|
||||||
|
end;
|
||||||
|
decode_bytestreams_els([{xmlel, <<"streamhost-used">>,
|
||||||
|
_attrs, _} =
|
||||||
|
_el
|
||||||
|
| _els],
|
||||||
|
Hosts, Used, Activate) ->
|
||||||
|
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||||
|
if _xmlns == <<>>;
|
||||||
|
_xmlns ==
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">> ->
|
||||||
|
decode_bytestreams_els(_els, Hosts,
|
||||||
|
decode_bytestreams_streamhost_used(_el),
|
||||||
|
Activate);
|
||||||
|
true ->
|
||||||
|
decode_bytestreams_els(_els, Hosts, Used, Activate)
|
||||||
|
end;
|
||||||
|
decode_bytestreams_els([{xmlel, <<"activate">>, _attrs,
|
||||||
|
_} =
|
||||||
|
_el
|
||||||
|
| _els],
|
||||||
|
Hosts, Used, Activate) ->
|
||||||
|
_xmlns = xml:get_attr_s(<<"xmlns">>, _attrs),
|
||||||
|
if _xmlns == <<>>;
|
||||||
|
_xmlns ==
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">> ->
|
||||||
|
decode_bytestreams_els(_els, Hosts, Used,
|
||||||
|
decode_bytestreams_activate(_el));
|
||||||
|
true ->
|
||||||
|
decode_bytestreams_els(_els, Hosts, Used, Activate)
|
||||||
|
end;
|
||||||
|
decode_bytestreams_els([_ | _els], Hosts, Used,
|
||||||
|
Activate) ->
|
||||||
|
decode_bytestreams_els(_els, Hosts, Used, Activate).
|
||||||
|
|
||||||
|
decode_bytestreams_attrs([{<<"dstaddr">>, _val}
|
||||||
|
| _attrs],
|
||||||
|
_Dstaddr, Sid, Mode) ->
|
||||||
|
decode_bytestreams_attrs(_attrs, _val, Sid, Mode);
|
||||||
|
decode_bytestreams_attrs([{<<"sid">>, _val} | _attrs],
|
||||||
|
Dstaddr, _Sid, Mode) ->
|
||||||
|
decode_bytestreams_attrs(_attrs, Dstaddr, _val, Mode);
|
||||||
|
decode_bytestreams_attrs([{<<"mode">>, _val} | _attrs],
|
||||||
|
Dstaddr, Sid, _Mode) ->
|
||||||
|
decode_bytestreams_attrs(_attrs, Dstaddr, Sid, _val);
|
||||||
|
decode_bytestreams_attrs([_ | _attrs], Dstaddr, Sid,
|
||||||
|
Mode) ->
|
||||||
|
decode_bytestreams_attrs(_attrs, Dstaddr, Sid, Mode);
|
||||||
|
decode_bytestreams_attrs([], Dstaddr, Sid, Mode) ->
|
||||||
|
{decode_bytestreams_attr_dstaddr(Dstaddr),
|
||||||
|
decode_bytestreams_attr_sid(Sid),
|
||||||
|
decode_bytestreams_attr_mode(Mode)}.
|
||||||
|
|
||||||
|
encode_bytestreams({bytestreams, Hosts, Used, Activate,
|
||||||
|
Dstaddr, Mode, Sid},
|
||||||
|
_xmlns_attrs) ->
|
||||||
|
_els = 'encode_bytestreams_$activate'(Activate,
|
||||||
|
'encode_bytestreams_$used'(Used,
|
||||||
|
'encode_bytestreams_$hosts'(Hosts,
|
||||||
|
[]))),
|
||||||
|
_attrs = encode_bytestreams_attr_mode(Mode,
|
||||||
|
encode_bytestreams_attr_sid(Sid,
|
||||||
|
encode_bytestreams_attr_dstaddr(Dstaddr,
|
||||||
|
_xmlns_attrs))),
|
||||||
|
{xmlel, <<"query">>, _attrs, _els}.
|
||||||
|
|
||||||
|
'encode_bytestreams_$hosts'([], _acc) -> _acc;
|
||||||
|
'encode_bytestreams_$hosts'([Hosts | _els], _acc) ->
|
||||||
|
'encode_bytestreams_$hosts'(_els,
|
||||||
|
[encode_bytestreams_streamhost(Hosts, [])
|
||||||
|
| _acc]).
|
||||||
|
|
||||||
|
'encode_bytestreams_$used'(undefined, _acc) -> _acc;
|
||||||
|
'encode_bytestreams_$used'(Used, _acc) ->
|
||||||
|
[encode_bytestreams_streamhost_used(Used, []) | _acc].
|
||||||
|
|
||||||
|
'encode_bytestreams_$activate'(undefined, _acc) -> _acc;
|
||||||
|
'encode_bytestreams_$activate'(Activate, _acc) ->
|
||||||
|
[encode_bytestreams_activate(Activate, []) | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_attr_dstaddr(undefined) -> undefined;
|
||||||
|
decode_bytestreams_attr_dstaddr(_val) -> _val.
|
||||||
|
|
||||||
|
encode_bytestreams_attr_dstaddr(undefined, _acc) ->
|
||||||
|
_acc;
|
||||||
|
encode_bytestreams_attr_dstaddr(_val, _acc) ->
|
||||||
|
[{<<"dstaddr">>, _val} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_attr_sid(undefined) -> undefined;
|
||||||
|
decode_bytestreams_attr_sid(_val) -> _val.
|
||||||
|
|
||||||
|
encode_bytestreams_attr_sid(undefined, _acc) -> _acc;
|
||||||
|
encode_bytestreams_attr_sid(_val, _acc) ->
|
||||||
|
[{<<"sid">>, _val} | _acc].
|
||||||
|
|
||||||
|
decode_bytestreams_attr_mode(undefined) -> tcp;
|
||||||
|
decode_bytestreams_attr_mode(_val) ->
|
||||||
|
case catch xml_gen:dec_enum(_val, [tcp, udp]) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
erlang:error({bad_attr_value, <<"mode">>, <<"query">>,
|
||||||
|
<<"http://jabber.org/protocol/bytestreams">>});
|
||||||
|
_res -> _res
|
||||||
|
end.
|
||||||
|
|
||||||
|
encode_bytestreams_attr_mode(tcp, _acc) -> _acc;
|
||||||
|
encode_bytestreams_attr_mode(_val, _acc) ->
|
||||||
|
[{<<"mode">>, xml_gen:enc_enum(_val)} | _acc].
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
%% Created automatically by XML generator (xml_gen.erl)
|
%% Created automatically by XML generator (xml_gen.erl)
|
||||||
%% Source: xmpp_codec.spec
|
%% Source: xmpp_codec.spec
|
||||||
%% Date: Sat, 15 Jun 2013 09:36:14 GMT
|
%% Date: Sat, 15 Jun 2013 16:36:04 GMT
|
||||||
|
|
||||||
-record(last, {seconds, text}).
|
-record(last, {seconds, text}).
|
||||||
|
|
||||||
|
@ -196,3 +196,8 @@
|
||||||
-record(delay, {stamp, from}).
|
-record(delay, {stamp, from}).
|
||||||
|
|
||||||
-record(legacy_delay, {stamp, from}).
|
-record(legacy_delay, {stamp, from}).
|
||||||
|
|
||||||
|
-record(streamhost, {jid, host, port = 1080}).
|
||||||
|
|
||||||
|
-record(bytestreams,
|
||||||
|
{hosts = [], used, activate, dstaddr, mode = tcp, sid}).
|
||||||
|
|
|
@ -1715,6 +1715,53 @@
|
||||||
dec = {dec_jid, []},
|
dec = {dec_jid, []},
|
||||||
enc = {enc_jid, []}}]}}.
|
enc = {enc_jid, []}}]}}.
|
||||||
|
|
||||||
|
{bytestreams_streamhost,
|
||||||
|
#elem{name = <<"streamhost">>,
|
||||||
|
xmlns = <<"http://jabber.org/protocol/bytestreams">>,
|
||||||
|
result = {streamhost, '$jid', '$host', '$port'},
|
||||||
|
attrs = [#attr{name = <<"jid">>,
|
||||||
|
required = true,
|
||||||
|
dec = {dec_jid, []},
|
||||||
|
enc = {enc_jid, []}},
|
||||||
|
#attr{name = <<"host">>,
|
||||||
|
required = true},
|
||||||
|
#attr{name = <<"port">>,
|
||||||
|
default = 1080,
|
||||||
|
dec = {dec_int, [0, 65535]},
|
||||||
|
enc = {enc_int, []}}]}}.
|
||||||
|
|
||||||
|
{bytestreams_streamhost_used,
|
||||||
|
#elem{name = <<"streamhost-used">>,
|
||||||
|
xmlns = <<"http://jabber.org/protocol/bytestreams">>,
|
||||||
|
result = '$jid',
|
||||||
|
attrs = [#attr{name = <<"jid">>,
|
||||||
|
required = true,
|
||||||
|
dec = {dec_jid, []},
|
||||||
|
enc = {enc_jid, []}}]}}.
|
||||||
|
|
||||||
|
{bytestreams_activate,
|
||||||
|
#elem{name = <<"activate">>,
|
||||||
|
xmlns = <<"http://jabber.org/protocol/bytestreams">>,
|
||||||
|
cdata = #cdata{enc = {enc_jid, []}, dec = {dec_jid, []}},
|
||||||
|
result = '$cdata'}}.
|
||||||
|
|
||||||
|
{bytestreams,
|
||||||
|
#elem{name = <<"query">>,
|
||||||
|
xmlns = <<"http://jabber.org/protocol/bytestreams">>,
|
||||||
|
result = {bytestreams, '$hosts', '$used', '$activate',
|
||||||
|
'$dstaddr', '$mode', '$sid'},
|
||||||
|
attrs = [#attr{name = <<"dstaddr">>},
|
||||||
|
#attr{name = <<"sid">>},
|
||||||
|
#attr{name = <<"mode">>,
|
||||||
|
default = tcp,
|
||||||
|
dec = {dec_enum, [[tcp, udp]]},
|
||||||
|
enc = {enc_enum, []}}],
|
||||||
|
refs = [#ref{name = bytestreams_streamhost, label = '$hosts'},
|
||||||
|
#ref{name = bytestreams_streamhost_used,
|
||||||
|
min = 0, max = 1, label = '$used'},
|
||||||
|
#ref{name = bytestreams_activate,
|
||||||
|
min = 0, max = 1, label = '$activate'}]}}.
|
||||||
|
|
||||||
dec_tzo(Val) ->
|
dec_tzo(Val) ->
|
||||||
[H1, M1] = str:tokens(Val, <<":">>),
|
[H1, M1] = str:tokens(Val, <<":">>),
|
||||||
H = erlang:binary_to_integer(H1),
|
H = erlang:binary_to_integer(H1),
|
||||||
|
|
Loading…
Reference in New Issue