Skip to content

Commit

Permalink
Escalus uses fast_tls instead of ssl
Browse files Browse the repository at this point in the history
The biggest magic is on the `escalus_ctp: tcp_to_tls/2` helper function.
Fast_tls has a pretty much hacky and undocumented way to setup client
connections, which is nothing but ugly. Anyway, that's the way it works.
  • Loading branch information
NelsonVides committed Apr 14, 2020
1 parent 4c65bcb commit 9df0f28
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 14 deletions.
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
{bbmustache, "1.8.0"},
{uuid, "1.7.5", {pkg, uuid_erl}},
{gun, "1.3.1"},
{worker_pool, "3.2.0"}
{worker_pool, "3.2.0"},
{fast_tls, {git, "https://github.com/processone/fast_tls.git", {ref, "a0fe32d"}}}
]}.

{relx, [{release, {escalus, "0.0.1"},
Expand Down
6 changes: 6 additions & 0 deletions rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@
{git,"https://github.com/esl/exml.git",
{ref,"a307e83669ad0a8d96ea3f2be9da36417efb94fc"}},
0},
{<<"fast_tls">>,
{git,"https://github.com/processone/fast_tls.git",
{ref,"a0fe32dcac2ea0ae3d282269a081f627423e6ae4"}},
0},
{<<"fusco">>,
{git,"https://github.com/esl/fusco.git",
{ref,"0a428471aefb3a38207c2141249181e6c018e565"}},
0},
{<<"gun">>,{pkg,<<"gun">>,<<"1.3.1">>},0},
{<<"meck">>,{pkg,<<"meck">>,<<"0.8.13">>},0},
{<<"p1_utils">>,{pkg,<<"p1_utils">>,<<"1.0.18">>},1},
{<<"quickrand">>,{pkg,<<"quickrand">>,<<"1.7.5">>},1},
{<<"uuid">>,{pkg,<<"uuid_erl">>,<<"1.7.5">>},0},
{<<"worker_pool">>,{pkg,<<"worker_pool">>,<<"3.2.0">>},0}]}.
Expand All @@ -24,6 +29,7 @@
{<<"cowlib">>, <<"8AA629F81A0FC189F261DC98A42243FA842625FEEA3C7EC56C48F4CCDB55490F">>},
{<<"gun">>, <<"1489FD96018431B89F401041A9CE0B02B45265247F0FDCF71273BF087C64EA4F">>},
{<<"meck">>, <<"FFEDB39F99B0B99703B8601C6F17C7F76313EE12DE6B646E671E3188401F7866">>},
{<<"p1_utils">>, <<"3FE224DE5B2E190D730A3C5DA9D6E8540C96484CF4B4692921D1E28F0C32B01C">>},
{<<"quickrand">>, <<"E3086A153EB13A057FC19192D05E2D4C6BB2BDBB55746A699BEAE9847AC17CA8">>},
{<<"uuid">>, <<"3862FF9A21C42566DFD0376B97512FA202922897129E09A05E2AFA0D9CAFD97A">>},
{<<"worker_pool">>, <<"54DD752BA4CA4B702124C45803AA958B36BCE77D683B87886606F1AADA3E124D">>}]}
Expand Down
3 changes: 2 additions & 1 deletion src/escalus.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
gun,
meck,
bbmustache,
uuid
uuid,
fast_tls
]},
{maintainers, ["ESL"]},
{licenses, ["Apache 2.0"]},
Expand Down
40 changes: 29 additions & 11 deletions src/escalus_tcp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ handle_call({upgrade_to_tls, SSLOpts}, _From, #state{socket = Socket} = State) -
SSLOpts1 = [{reuse_sessions, true}],
SSLOpts2 = lists:keymerge(1, lists:keysort(1, SSLOpts),
lists:keysort(1, SSLOpts1)),
case ssl:connect(Socket, SSLOpts2) of
{ok, Socket2} ->
inet:setopts(Socket, [{active, false}]),
case tcp_to_tls(Socket, SSLOpts2) of
{ok, TlsSocket} ->
{ok, Parser} = exml_stream:new_parser(),
{reply, Socket2,
State#state{socket = Socket2, parser = Parser, ssl=true}};
{reply, TlsSocket, State#state{socket = TlsSocket, parser = Parser, ssl = true}};
{error, _} = E ->
{reply, E, State}
end;
Expand All @@ -248,7 +248,7 @@ handle_call({set_filter_pred, Pred}, _From, State) ->
{reply, ok, State#state{filter_pred = Pred}};
handle_call(kill_connection, _, #state{socket = Socket, ssl = SSL} = S) ->
case SSL of
true -> ssl:close(Socket);
true -> fast_tls:close(Socket);
false -> gen_tcp:close(Socket)
end,
close_compression_streams(S#state.compress),
Expand Down Expand Up @@ -276,8 +276,11 @@ handle_cast(stop, State) ->
handle_info({tcp, Socket, Data}, #state{socket = Socket, ssl = false} = State) ->
NewState = handle_data(Socket, Data, State),
{noreply, NewState};
handle_info({ssl, Socket, Data}, #state{socket = Socket, ssl = true} = State) ->
NewState = handle_data(Socket, Data, State),
handle_info({tcp, TcpSocket, Data},
#state{socket = {tlssock, TcpSocket, _} = TlsSocket, ssl = true} = State) ->
% This means we're on fast_tls
{ok, NewData} = fast_tls:recv_data(TlsSocket, Data),
NewState = handle_data(TlsSocket, NewData, State),
{noreply, NewState};
handle_info({tcp_closed, _Socket}, #state{} = State) ->
{stop, normal, State};
Expand All @@ -293,7 +296,7 @@ handle_info(_, State) ->
-spec terminate(term(), state()) -> term().
terminate(Reason, #state{socket = Socket, ssl = true} = State) ->
common_terminate(Reason, State),
ssl:close(Socket);
fast_tls:close(Socket);
terminate(Reason, #state{socket = Socket} = State) ->
common_terminate(Reason, State),
gen_tcp:close(Socket).
Expand Down Expand Up @@ -348,7 +351,7 @@ set_active_opt(#state{ssl = SSL, socket = Soc} = State, at_least_once) ->


set_active_opt(true, Socket, true) ->
ssl:setopts(Socket, [{active, once}]);
fast_tls:setopts(Socket, [{active, once}]);
set_active_opt(false, Socket, true) ->
inet:setopts(Socket, [{active, once}]);
set_active_opt(_,_,_) ->
Expand Down Expand Up @@ -444,7 +447,7 @@ maybe_compress_and_send(Data, State) ->
raw_send(Data, State).

raw_send(Data, #state{socket = Socket, ssl = true}) ->
ssl:send(Socket, Data);
fast_tls:send(Socket, Data);
raw_send(Data, #state{socket = Socket}) ->
gen_tcp:send(Socket, Data).

Expand Down Expand Up @@ -506,10 +509,25 @@ do_connect(#{ssl := IsSSLConn,
Reply.

maybe_ssl_connection(true, Address, Port, SocketOpts, SSLOpts) ->
ssl:connect(Address, Port, SocketOpts ++ SSLOpts);
{ok, Socket} = gen_tcp:connect(Address, Port, SocketOpts),
tcp_to_tls(Socket, SSLOpts);
maybe_ssl_connection(_, Address, Port, SocketOpts, _) ->
gen_tcp:connect(Address, Port, SocketOpts).

tcp_to_tls(GenTcpSocket, SSLOpts) ->
inet:setopts(GenTcpSocket, [{active, false}]),
case fast_tls:tcp_to_tls(GenTcpSocket, [connect | SSLOpts]) of
{ok, TlsSocket} ->
%% fast_tls requires dummy recv_data/2 call to accomplish TLS handshake
fast_tls:recv(TlsSocket, 0, 100),
fast_tls:recv_data(TlsSocket, <<>>),
fast_tls:recv_data(TlsSocket, <<>>),
fast_tls:setopts(TlsSocket, [{active, once}]),
{ok, TlsSocket};
{error, _} = E ->
E
end.

%%===================================================================
%%% Init options parsing helpers
%%%===================================================================
Expand Down
2 changes: 1 addition & 1 deletion src/escalus_tcp.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
%%==============================================================================

-record(state, {owner,
socket,
socket :: gen_tcp:socket() | fast_tls:tls_socket(),
parser,
filter_pred,
ssl = false,
Expand Down

0 comments on commit 9df0f28

Please sign in to comment.