Skip to content

Commit

Permalink
Merge pull request #30 from esl/grindr-work-rebase
Browse files Browse the repository at this point in the history
Grindr work rebase
  • Loading branch information
ppikula committed Jul 23, 2014
2 parents fa2c06f + f82b386 commit f0b4303
Show file tree
Hide file tree
Showing 11 changed files with 544 additions and 128 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ test: rebar compile
clean: rebar
./rebar clean

ct: compile
./run_ct TESTSPEC=$(TESTSPEC)

rebar:
wget https://github.com/rebar/rebar/releases/download/2.2.0/rebar
chmod u+x rebar
Expand Down
3 changes: 3 additions & 0 deletions include/escalus_xmlns.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,9 @@
% Defined by XEP-0297: Stanza Forwarding
-define(NS_FORWARD_0, <<"urn:xmpp:forward:0">>).

% Defined by XEP-0313: Message Archive Management (MAM)
-define(NS_MAM, <<"urn:xmpp:mam:tmp">>).

% Defined by XHTML 1.0.
-define(NS_XHTML, <<"http://www.w3.org/1999/xhtml">>).

Expand Down
2 changes: 1 addition & 1 deletion run_ct
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
ct_run -config test/test.config -logdir logs -dir test -erl_args -pa $PWD/ebin $PWD/deps/exml/ebin
ct_run -config test/test.config -logdir logs -dir test -erl_args -pa $PWD/ebin $PWD/deps/exml/ebin $PWD/deps/base16/ebin
23 changes: 19 additions & 4 deletions src/escalus_connection.erl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
-export([connect/1,
send/2,
get_stanza/2,
get_sm_h/1,
set_sm_h/2,
reset_parser/1,
is_connected/1,
kill/1]).
Expand Down Expand Up @@ -46,7 +48,8 @@ start(Props) ->
authenticate,
bind,
session,
maybe_stream_management]).
maybe_stream_management,
maybe_use_carbons]).

%% Usage:
%%
Expand Down Expand Up @@ -98,7 +101,7 @@ connection_step(Step, {Conn, Props, Features}) ->
catch
Error ->
(Conn#client.module):stop(Conn),
throw({connection_step_failed, {Conn, Props, Features}, Error})
throw({connection_step_failed, {Step, Conn, Props, Features}, Error})
end.

%% By default use predefined connection steps from escalus_session.
Expand Down Expand Up @@ -133,6 +136,18 @@ get_stanza(Conn, Name) ->
throw({timeout, Name})
end.

-spec get_sm_h(#client{}) -> non_neg_integer().
get_sm_h(#client{module = escalus_tcp} = Conn) ->
escalus_tcp:get_sm_h(Conn);
get_sm_h(#client{module = Mod}) ->
error({get_sm_h, {undefined_for_escalus_module, Mod}}).

-spec set_sm_h(#client{}, non_neg_integer()) -> non_neg_integer().
set_sm_h(#client{module = escalus_tcp} = Conn, H) ->
escalus_tcp:set_sm_h(Conn, H);
set_sm_h(#client{module = Mod}, _) ->
error({set_sm_h, {undefined_for_escalus_module, Mod}}).

reset_parser(#client{module = Mod} = Client) ->
Mod:reset_parser(Client).

Expand All @@ -143,8 +158,8 @@ stop(#client{module = Mod} = Client) ->
Mod:stop(Client).

%% Brutally kill the connection without terminating the XMPP stream.
kill(#client{module = Mod} = Transport) ->
Mod:kill(Transport).
kill(#client{module = Mod} = Client) ->
Mod:kill(Client).

%%%===================================================================
%%% Helpers
Expand Down
80 changes: 48 additions & 32 deletions src/escalus_pred.erl
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,14 @@
stanza_timeout/1,
is_stream_end/1,
is_bosh_report/2,
is_enabled/1, is_enabled/2,
is_failed/2,
is_ack/1, is_ack/2,
is_ack_request/1,
is_resumed/2,
is_sm_enabled/1, is_sm_enabled/2,
is_sm_failed/2,
is_sm_ack/1, is_sm_ack/2,
is_sm_ack_request/1,
is_sm_resumed/1, is_sm_resumed/2,
has_ns/2,
is_compressed/1
is_compressed/1,
is_mam_archived_message/2
]).

-export(['not'/1]).
Expand Down Expand Up @@ -177,7 +178,7 @@ has_carbon(Type, From, To, Msg, Stanza) ->
is_forwarded_message(From, To, Msg, #xmlel{name = <<"forwarded">>} = Stanza) ->
has_ns(?NS_FORWARD_0, Stanza)
andalso
is_chat_message_from_to(From, To, Msg,
is_chat_message_from_to(From, To, Msg,
exml_query:subelement(Stanza, <<"message">>)).

-spec is_chat_message(binary(), xmlterm()) -> boolean().
Expand All @@ -201,6 +202,14 @@ is_groupchat_message(Stanza) ->
andalso
has_type(<<"groupchat">>, Stanza).

%% Xep-0313 archived messages
is_mam_archived_message(Msg, #xmlel{} = Stanza) ->
M = exml_query:path(Stanza, [{element, <<"result">>},
{element, <<"forwarded">>},
{element, <<"message">>}]),
is_chat_message(Msg,M).


%% TODO: escalus_compat:bin/1 should be deprecated;
%% let's just use binaries instead of "maybe strings, maybe binaries"
-spec is_groupchat_message(binary(), xmlterm()) -> boolean().
Expand Down Expand Up @@ -229,7 +238,7 @@ has_type(Type, Stanza) ->
is_0184_request(#xmlel{children = Els}) ->
#xmlel{ name = <<"request">>,
attrs = [{<<"xmlns">>, <<"urn:xmpp:receipts">>}],
children = [] } =:= lists:keyfind(<<"request">>, 2, Els).
children = [] } =:= lists:keyfind(<<"request">>, 2, Els).

-spec is_0184_receipt(xmlterm(), xmlterm()) -> boolean().
is_0184_receipt(#xmlel{ attrs = ReqAttrs } = Request, Receipt) ->
Expand Down Expand Up @@ -509,8 +518,8 @@ is_bosh_report(Rid, #xmlel{name = <<"body">>} = Body) ->
is_bosh_report(_, _) ->
false.

is_enabled(Opts, Stanza) ->
is_enabled(Stanza)
is_sm_enabled(Opts, Stanza) ->
is_sm_enabled(Stanza)
andalso case proplists:is_defined(resume, Opts) of
false ->
true;
Expand All @@ -519,50 +528,58 @@ is_enabled(Opts, Stanza) ->
[<<"true">>, <<"1">>])
end.

is_enabled(#xmlel{name = <<"enabled">>} = Stanza) ->
is_sm_enabled(#xmlel{name = <<"enabled">>} = Stanza) ->
has_ns(?NS_STREAM_MGNT_3, Stanza);
is_enabled(_) ->
is_sm_enabled(_) ->
false.

is_failed(Type, #xmlel{name = <<"failed">>} = Stanza) ->
is_sm_failed(Type, #xmlel{name = <<"failed">>} = Stanza) ->
has_ns(?NS_STREAM_MGNT_3, Stanza)
andalso
begin
Subelem = exml_query:subelement(Stanza, Type),
is_stanza_error(Type, Subelem)
andalso
begin
Subelem = exml_query:subelement(Stanza, Type),
is_stanza_error(Type, Subelem)
end;
is_failed(_, _) ->
is_sm_failed(_, _) ->
false.

is_stanza_error(Type, #xmlel{name = T} = Stanza) when Type =:= T ->
has_ns(?NS_STANZA_ERRORS, Stanza);
is_stanza_error(_, _) ->
false.

is_ack(#xmlel{name = <<"a">>} = Stanza) ->
is_sm_ack(#xmlel{name = <<"a">>} = Stanza) ->
has_ns(?NS_STREAM_MGNT_3, Stanza);
is_ack(_) ->
is_sm_ack(_) ->
false.

is_ack(Handled, #xmlel{name = <<"a">>} = Stanza) ->
has_ns(?NS_STREAM_MGNT_3, Stanza)
andalso
Handled == binary_to_integer(exml_query:attr(Stanza, <<"h">>));
is_ack(_, _) ->
is_sm_ack(Handled, #xmlel{name = <<"a">>} = Stanza) ->
is_sm_ack(Stanza)
andalso
Handled == binary_to_integer(exml_query:attr(Stanza, <<"h">>));
is_sm_ack(_, _) ->
false.

is_ack_request(#xmlel{name = <<"r">>} = Stanza) ->
is_sm_ack_request(#xmlel{name = <<"r">>} = Stanza) ->
has_ns(?NS_STREAM_MGNT_3, Stanza);
is_ack_request(_) ->
is_sm_ack_request(_) ->
false.

is_resumed(SMID, #xmlel{name = <<"resumed">>} = Stanza) ->
is_sm_resumed(#xmlel{name = <<"resumed">>} = Stanza) ->
%% Less strict checking (no SMID verification)
has_ns(?NS_STREAM_MGNT_3, Stanza)
andalso
SMID == exml_query:attr(Stanza, <<"previd">>)
andalso
exml_query:attr(Stanza, <<"h">>) /= undefined;
is_resumed(_, _) ->
is_sm_resumed(_) ->
false.

is_sm_resumed(SMID, #xmlel{name = <<"resumed">>} = Stanza) ->
is_sm_resumed(Stanza)
andalso
SMID == exml_query:attr(Stanza, <<"previd">>)
andalso
exml_query:attr(Stanza, <<"h">>) /= undefined;
is_sm_resumed(_, _) ->
false.

has_ns(NS, Stanza) ->
Expand Down Expand Up @@ -597,4 +614,3 @@ get_roster_items(Stanza) ->
-spec has_path(xmlterm(), exml_query:path()) -> boolean().
has_path(Stanza, Path) ->
exml_query:path(Stanza, Path) /= undefined.

102 changes: 66 additions & 36 deletions src/escalus_session.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
bind/2,
compress/2,
use_ssl/2,
can_use_amp/2,
can_use_compression/2,
can_use_stream_management/2,
session/2]).

%% New style connection initiation
-export([start_stream/3,
maybe_use_ssl/3,
maybe_use_carbons/3,
maybe_use_compression/3,
maybe_stream_management/3,
maybe_stream_resumption/3,
Expand Down Expand Up @@ -45,6 +47,7 @@
features()}.
-export_type([step_state/0]).

-include_lib("exml/include/exml.hrl").
-include_lib("exml/include/exml_stream.hrl").
-define(DEFAULT_RESOURCE, <<"escalus-default-resource">>).

Expand Down Expand Up @@ -118,12 +121,22 @@ use_ssl(Props, Features) ->

-spec can_use_compression(escalus_users:spec(), features()) -> boolean().
can_use_compression(Props, Features) ->
false /= proplists:get_value(compression, Props, false) andalso
false /= proplists:get_value(compression, Features).
can_use(compression, Props, Features).

can_use_stream_management(Props, Features) ->
false /= proplists:get_value(stream_management, Props, false) andalso
false /= proplists:get_value(stream_management, Features).
can_use(stream_management, Props, Features).

can_use_carbons(Props, _Features) ->
false /= proplists:get_value(carbons, Props, false).

can_use_amp(Props, Features) ->
false /= proplists:get_value(advanced_message_processing, Features).

can_use(Feature, Props, Features) ->
false /= proplists:get_value(Feature, Props, false) andalso
false /= proplists:get_value(Feature, Features).



%%%===================================================================
%%% New style connection initiation
Expand All @@ -144,6 +157,22 @@ maybe_use_ssl(Conn, Props, Features) ->
{Conn, Props, Features}
end.

-spec maybe_use_carbons/3 :: ?CONNECTION_STEP.
maybe_use_carbons(Conn, Props, Features) ->
case can_use_carbons(Props, Features) of
true ->
use_carbons(Conn, Props, Features);
false ->
{Conn, Props, Features}
end.

-spec use_carbons/3 :: ?CONNECTION_STEP.
use_carbons(Conn, Props, Features) ->
escalus_connection:send(Conn, escalus_stanza:carbons_enable()),
Result = escalus_connection:get_stanza(Conn, carbon_iq_response),
escalus:assert(is_iq, [<<"result">>], Result),
{Conn, Props, Features}.

-spec maybe_use_compression/3 :: ?CONNECTION_STEP.
maybe_use_compression(Conn, Props, Features) ->
case can_use_compression(Props, Features) of
Expand All @@ -167,7 +196,7 @@ maybe_stream_management(Conn, Props, Features) ->
stream_management(Conn, Props, Features) ->
escalus_connection:send(Conn, escalus_stanza:enable_sm()),
Enabled = escalus_connection:get_stanza(Conn, stream_management),
true = escalus_pred:is_enabled(Enabled),
true = escalus_pred:is_sm_enabled(Enabled),
{Conn, Props, Features}.

-spec maybe_stream_resumption/3 :: ?CONNECTION_STEP.
Expand All @@ -183,7 +212,7 @@ maybe_stream_resumption(Conn, Props, Features) ->
stream_resumption(Conn, Props, Features) ->
escalus_connection:send(Conn, escalus_stanza:enable_sm([resume])),
Enabled = escalus_connection:get_stanza(Conn, stream_resumption),
true = escalus_pred:is_enabled([resume], Enabled),
true = escalus_pred:is_sm_enabled([resume], Enabled),
SMID = exml_query:attr(Enabled, <<"id">>),
{Conn, [{smid, SMID} | Props], Features}.

Expand All @@ -203,35 +232,6 @@ session(Conn, Props, Features) ->
%%% Helpers
%%%===================================================================

-spec get_stream_features(xmlterm()) -> features().
get_stream_features(Features) ->
[{compression, get_compression(Features)},
{starttls, get_starttls(Features)},
{stream_management, get_stream_management(Features)}].

-spec get_compression(xmlterm()) -> boolean().
get_compression(Features) ->
case exml_query:subelement(Features, <<"compression">>) of
#xmlel{children = MethodEls} ->
[exml_query:cdata(MethodEl) || MethodEl <- MethodEls];
_ -> false
end.

-spec get_starttls(xmlterm()) -> boolean().
get_starttls(Features) ->
case exml_query:subelement(Features, <<"starttls">>) of
undefined ->
false;
_ -> true
end.

get_stream_management(Features) ->
case exml_query:subelement(Features, <<"sm">>) of
undefined ->
false;
_ -> true
end.

assert_stream_start(StreamStartRep, Transport, IsLegacy) ->
case {StreamStartRep, Transport, IsLegacy} of
{#xmlel{name = <<"open">>}, ws, false} ->
Expand Down Expand Up @@ -260,5 +260,35 @@ assert_stream_features(StreamFeatures, Transport, IsLegacy) ->
{#xmlel{name = <<"stream:features">>}, _, _} ->
ok;
_ ->
error("Expected stream features", [StreamFeatures])
error(
lists:flatten(
io_lib:format(
"Expected stream features, got ~p",
[StreamFeatures])))
end.

-spec get_stream_features(xmlterm()) -> features().
get_stream_features(Features) ->
[{compression, get_compression(Features)},
{starttls, get_starttls(Features)},
{stream_management, get_stream_management(Features)},
{advanced_message_processing, get_advanced_message_processing(Features)}
].

-spec get_compression(xmlterm()) -> boolean().
get_compression(Features) ->
case exml_query:subelement(Features, <<"compression">>) of
#xmlel{children = MethodEls} ->
[exml_query:cdata(MethodEl) || MethodEl <- MethodEls];
_ -> false
end.

-spec get_starttls(xmlterm()) -> boolean().
get_starttls(Features) ->
undefined =/= exml_query:subelement(Features, <<"starttls">>).

get_stream_management(Features) ->
undefined =/= exml_query:subelement(Features, <<"sm">>).

get_advanced_message_processing(Features) ->
undefined =/= exml_query:subelement(Features, <<"amp">>).
Loading

0 comments on commit f0b4303

Please sign in to comment.