aboutsummaryrefslogtreecommitdiff
path: root/src/xmpp_codec.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp_codec.erl')
-rw-r--r--src/xmpp_codec.erl184
1 files changed, 181 insertions, 3 deletions
diff --git a/src/xmpp_codec.erl b/src/xmpp_codec.erl
index 113be860b..11bd741f4 100644
--- a/src/xmpp_codec.erl
+++ b/src/xmpp_codec.erl
@@ -15,6 +15,16 @@ decode(_el) -> decode(_el, []).
decode({xmlel, _name, _attrs, _} = _el, Opts) ->
IgnoreEls = proplists:get_bool(ignore_els, Opts),
case {_name, get_attr(<<"xmlns">>, _attrs)} of
+ {<<"address">>, <<"urn:xmpp:sic:0">>} ->
+ decode_sic(<<"urn:xmpp:sic:0">>, IgnoreEls, _el);
+ {<<"address">>, <<"urn:xmpp:sic:1">>} ->
+ decode_sic(<<"urn:xmpp:sic:1">>, IgnoreEls, _el);
+ {<<"port">>, <<"urn:xmpp:sic:1">>} ->
+ decode_sip_port(<<"urn:xmpp:sic:1">>, IgnoreEls, _el);
+ {<<"ip">>, <<"urn:xmpp:sic:0">>} ->
+ decode_sic_ip(<<"urn:xmpp:sic:0">>, IgnoreEls, _el);
+ {<<"ip">>, <<"urn:xmpp:sic:1">>} ->
+ decode_sic_ip(<<"urn:xmpp:sic:1">>, IgnoreEls, _el);
{<<"x">>, <<"jabber:x:oob">>} ->
decode_oob_x(<<"jabber:x:oob">>, IgnoreEls, _el);
{<<"desc">>, <<"jabber:x:oob">>} ->
@@ -1309,6 +1319,11 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) ->
is_known_tag({xmlel, _name, _attrs, _} = _el) ->
case {_name, get_attr(<<"xmlns">>, _attrs)} of
+ {<<"address">>, <<"urn:xmpp:sic:0">>} -> true;
+ {<<"address">>, <<"urn:xmpp:sic:1">>} -> true;
+ {<<"port">>, <<"urn:xmpp:sic:1">>} -> true;
+ {<<"ip">>, <<"urn:xmpp:sic:0">>} -> true;
+ {<<"ip">>, <<"urn:xmpp:sic:1">>} -> true;
{<<"x">>, <<"jabber:x:oob">>} -> true;
{<<"desc">>, <<"jabber:x:oob">>} -> true;
{<<"url">>, <<"jabber:x:oob">>} -> true;
@@ -2609,7 +2624,9 @@ encode({media, _, _, _} = Media) ->
encode_media(Media,
[{<<"xmlns">>, <<"urn:xmpp:media-element">>}]);
encode({oob_x, _, _, _} = X) ->
- encode_oob_x(X, [{<<"xmlns">>, <<"jabber:x:oob">>}]).
+ encode_oob_x(X, [{<<"xmlns">>, <<"jabber:x:oob">>}]);
+encode({sic, _, _, _} = Address) ->
+ encode_sic(Address, []).
get_name({last, _, _}) -> <<"query">>;
get_name({version, _, _, _}) -> <<"query">>;
@@ -2802,7 +2819,8 @@ get_name({bob_data, _, _, _, _}) -> <<"data">>;
get_name({xcaptcha, _}) -> <<"captcha">>;
get_name({media_uri, _, _}) -> <<"uri">>;
get_name({media, _, _, _}) -> <<"media">>;
-get_name({oob_x, _, _, _}) -> <<"x">>.
+get_name({oob_x, _, _, _}) -> <<"x">>;
+get_name({sic, _, _, _}) -> <<"address">>.
get_ns({last, _, _}) -> <<"jabber:iq:last">>;
get_ns({version, _, _, _}) -> <<"jabber:iq:version">>;
@@ -3070,7 +3088,8 @@ get_ns({media_uri, _, _}) ->
<<"urn:xmpp:media-element">>;
get_ns({media, _, _, _}) ->
<<"urn:xmpp:media-element">>;
-get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>.
+get_ns({oob_x, _, _, _}) -> <<"jabber:x:oob">>;
+get_ns({sic, _, _, Xmlns}) -> Xmlns.
dec_int(Val) -> dec_int(Val, infinity, infinity).
@@ -3319,8 +3338,18 @@ pp(xcaptcha, 1) -> [xdata];
pp(media_uri, 2) -> [type, uri];
pp(media, 3) -> [height, width, uri];
pp(oob_x, 3) -> [url, desc, sid];
+pp(sic, 3) -> [ip, port, xmlns];
pp(_, _) -> no.
+enc_ip({0, 0, 0, 0, 0, 65535, A, B}) ->
+ enc_ip({(A bsr 8) band 255, A band 255,
+ (B bsr 8) band 255, B band 255});
+enc_ip(Addr) -> list_to_binary(inet_parse:ntoa(Addr)).
+
+dec_ip(S) ->
+ {ok, Addr} = inet_parse:address(binary_to_list(S)),
+ Addr.
+
join([], _Sep) -> <<>>;
join([H | T], Sep) ->
<<H/binary, << <<Sep, X/binary>> || X <- T >>/binary>>.
@@ -3365,6 +3394,155 @@ dec_tzo(Val) ->
M = jlib:binary_to_integer(M1),
if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end.
+decode_sic(__TopXMLNS, __IgnoreEls,
+ {xmlel, <<"address">>, _attrs, _els}) ->
+ {Ip, Port} = decode_sic_els(__TopXMLNS, __IgnoreEls,
+ _els, undefined, undefined),
+ Xmlns = decode_sic_attrs(__TopXMLNS, _attrs, undefined),
+ {sic, Ip, Port, Xmlns}.
+
+decode_sic_els(__TopXMLNS, __IgnoreEls, [], Ip, Port) ->
+ {Ip, Port};
+decode_sic_els(__TopXMLNS, __IgnoreEls,
+ [{xmlel, <<"ip">>, _attrs, _} = _el | _els], Ip,
+ Port) ->
+ case get_attr(<<"xmlns">>, _attrs) of
+ <<"">>
+ when __TopXMLNS == <<"urn:xmpp:sic:1">>;
+ __TopXMLNS == <<"urn:xmpp:sic:0">> ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els,
+ decode_sic_ip(__TopXMLNS, __IgnoreEls, _el), Port);
+ <<"urn:xmpp:sic:0">> ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els,
+ decode_sic_ip(<<"urn:xmpp:sic:0">>, __IgnoreEls, _el),
+ Port);
+ <<"urn:xmpp:sic:1">> ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els,
+ decode_sic_ip(<<"urn:xmpp:sic:1">>, __IgnoreEls, _el),
+ Port);
+ _ ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, Port)
+ end;
+decode_sic_els(__TopXMLNS, __IgnoreEls,
+ [{xmlel, <<"port">>, _attrs, _} = _el | _els], Ip,
+ Port) ->
+ case get_attr(<<"xmlns">>, _attrs) of
+ <<"">> when __TopXMLNS == <<"urn:xmpp:sic:1">> ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip,
+ decode_sip_port(__TopXMLNS, __IgnoreEls, _el));
+ <<"urn:xmpp:sic:1">> ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip,
+ decode_sip_port(<<"urn:xmpp:sic:1">>, __IgnoreEls,
+ _el));
+ _ ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, Port)
+ end;
+decode_sic_els(__TopXMLNS, __IgnoreEls, [_ | _els], Ip,
+ Port) ->
+ decode_sic_els(__TopXMLNS, __IgnoreEls, _els, Ip, Port).
+
+decode_sic_attrs(__TopXMLNS,
+ [{<<"xmlns">>, _val} | _attrs], _Xmlns) ->
+ decode_sic_attrs(__TopXMLNS, _attrs, _val);
+decode_sic_attrs(__TopXMLNS, [_ | _attrs], Xmlns) ->
+ decode_sic_attrs(__TopXMLNS, _attrs, Xmlns);
+decode_sic_attrs(__TopXMLNS, [], Xmlns) ->
+ decode_sic_attr_xmlns(__TopXMLNS, Xmlns).
+
+encode_sic({sic, Ip, Port, Xmlns}, _xmlns_attrs) ->
+ _els = lists:reverse('encode_sic_$ip'(Ip,
+ 'encode_sic_$port'(Port, []))),
+ _attrs = encode_sic_attr_xmlns(Xmlns, _xmlns_attrs),
+ {xmlel, <<"address">>, _attrs, _els}.
+
+'encode_sic_$ip'(undefined, _acc) -> _acc;
+'encode_sic_$ip'(Ip, _acc) ->
+ [encode_sic_ip(Ip, []) | _acc].
+
+'encode_sic_$port'(undefined, _acc) -> _acc;
+'encode_sic_$port'(Port, _acc) ->
+ [encode_sip_port(Port, []) | _acc].
+
+decode_sic_attr_xmlns(__TopXMLNS, undefined) ->
+ undefined;
+decode_sic_attr_xmlns(__TopXMLNS, _val) -> _val.
+
+encode_sic_attr_xmlns(undefined, _acc) -> _acc;
+encode_sic_attr_xmlns(_val, _acc) ->
+ [{<<"xmlns">>, _val} | _acc].
+
+decode_sip_port(__TopXMLNS, __IgnoreEls,
+ {xmlel, <<"port">>, _attrs, _els}) ->
+ Cdata = decode_sip_port_els(__TopXMLNS, __IgnoreEls,
+ _els, <<>>),
+ Cdata.
+
+decode_sip_port_els(__TopXMLNS, __IgnoreEls, [],
+ Cdata) ->
+ decode_sip_port_cdata(__TopXMLNS, Cdata);
+decode_sip_port_els(__TopXMLNS, __IgnoreEls,
+ [{xmlcdata, _data} | _els], Cdata) ->
+ decode_sip_port_els(__TopXMLNS, __IgnoreEls, _els,
+ <<Cdata/binary, _data/binary>>);
+decode_sip_port_els(__TopXMLNS, __IgnoreEls, [_ | _els],
+ Cdata) ->
+ decode_sip_port_els(__TopXMLNS, __IgnoreEls, _els,
+ Cdata).
+
+encode_sip_port(Cdata, _xmlns_attrs) ->
+ _els = encode_sip_port_cdata(Cdata, []),
+ _attrs = _xmlns_attrs,
+ {xmlel, <<"port">>, _attrs, _els}.
+
+decode_sip_port_cdata(__TopXMLNS, <<>>) ->
+ erlang:error({xmpp_codec,
+ {missing_cdata, <<>>, <<"port">>, __TopXMLNS}});
+decode_sip_port_cdata(__TopXMLNS, _val) ->
+ case catch dec_int(_val, 0, 65535) of
+ {'EXIT', _} ->
+ erlang:error({xmpp_codec,
+ {bad_cdata_value, <<>>, <<"port">>, __TopXMLNS}});
+ _res -> _res
+ end.
+
+encode_sip_port_cdata(_val, _acc) ->
+ [{xmlcdata, enc_int(_val)} | _acc].
+
+decode_sic_ip(__TopXMLNS, __IgnoreEls,
+ {xmlel, <<"ip">>, _attrs, _els}) ->
+ Cdata = decode_sic_ip_els(__TopXMLNS, __IgnoreEls, _els,
+ <<>>),
+ Cdata.
+
+decode_sic_ip_els(__TopXMLNS, __IgnoreEls, [], Cdata) ->
+ decode_sic_ip_cdata(__TopXMLNS, Cdata);
+decode_sic_ip_els(__TopXMLNS, __IgnoreEls,
+ [{xmlcdata, _data} | _els], Cdata) ->
+ decode_sic_ip_els(__TopXMLNS, __IgnoreEls, _els,
+ <<Cdata/binary, _data/binary>>);
+decode_sic_ip_els(__TopXMLNS, __IgnoreEls, [_ | _els],
+ Cdata) ->
+ decode_sic_ip_els(__TopXMLNS, __IgnoreEls, _els, Cdata).
+
+encode_sic_ip(Cdata, _xmlns_attrs) ->
+ _els = encode_sic_ip_cdata(Cdata, []),
+ _attrs = _xmlns_attrs,
+ {xmlel, <<"ip">>, _attrs, _els}.
+
+decode_sic_ip_cdata(__TopXMLNS, <<>>) ->
+ erlang:error({xmpp_codec,
+ {missing_cdata, <<>>, <<"ip">>, __TopXMLNS}});
+decode_sic_ip_cdata(__TopXMLNS, _val) ->
+ case catch dec_ip(_val) of
+ {'EXIT', _} ->
+ erlang:error({xmpp_codec,
+ {bad_cdata_value, <<>>, <<"ip">>, __TopXMLNS}});
+ _res -> _res
+ end.
+
+encode_sic_ip_cdata(_val, _acc) ->
+ [{xmlcdata, enc_ip(_val)} | _acc].
+
decode_oob_x(__TopXMLNS, __IgnoreEls,
{xmlel, <<"x">>, _attrs, _els}) ->
{Desc, Url} = decode_oob_x_els(__TopXMLNS, __IgnoreEls,