aboutsummaryrefslogtreecommitdiffstats
path: root/src/gun_tunnel.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/gun_tunnel.erl')
-rw-r--r--src/gun_tunnel.erl81
1 files changed, 45 insertions, 36 deletions
diff --git a/src/gun_tunnel.erl b/src/gun_tunnel.erl
index 169fd6f..1582a9d 100644
--- a/src/gun_tunnel.erl
+++ b/src/gun_tunnel.erl
@@ -152,13 +152,13 @@ init(ReplyTo, OriginSocket, OriginTransport, Opts=#{stream_ref := StreamRef, tun
%% When we receive data we pass it forward directly for TCP;
%% or we decrypt it and pass it via handle_continue for TLS.
-handle(Data, State0=#tunnel_state{transport=gun_tcp_proxy,
+handle(Data, State=#tunnel_state{transport=gun_tcp_proxy,
protocol=Proto, protocol_state=ProtoState0},
CookieStore0, EvHandler, EvHandlerState0) ->
{Commands, CookieStore, EvHandlerState1} = Proto:handle(
Data, ProtoState0, CookieStore0, EvHandler, EvHandlerState0),
- {State, EvHandlerState} = commands(Commands, State0, EvHandler, EvHandlerState1),
- {{state, State}, CookieStore, EvHandlerState};
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, CookieStore, EvHandlerState};
handle(Data, State=#tunnel_state{transport=gun_tls_proxy,
socket=ProxyPid, tls_origin_socket=OriginSocket},
CookieStore, _EvHandler, EvHandlerState) ->
@@ -226,13 +226,13 @@ handle_continue(ContinueStreamRef, {data, _ReplyTo, _StreamRef, IsFin, Data},
when is_reference(ContinueStreamRef) ->
{{send, IsFin, Data}, CookieStore, EvHandlerState};
handle_continue(ContinueStreamRef, {tls_proxy, ProxyPid, Data},
- State0=#tunnel_state{socket=ProxyPid, protocol=Proto, protocol_state=ProtoState},
+ State=#tunnel_state{socket=ProxyPid, protocol=Proto, protocol_state=ProtoState},
CookieStore0, EvHandler, EvHandlerState0)
when is_reference(ContinueStreamRef) ->
{Commands, CookieStore, EvHandlerState1} = Proto:handle(
Data, ProtoState, CookieStore0, EvHandler, EvHandlerState0),
- {State, EvHandlerState} = commands(Commands, State0, EvHandler, EvHandlerState1),
- {{state, State}, CookieStore, EvHandlerState};
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, CookieStore, EvHandlerState};
handle_continue(ContinueStreamRef, {tls_proxy_closed, ProxyPid},
#tunnel_state{socket=ProxyPid}, CookieStore, _EvHandler, EvHandlerState0)
when is_reference(ContinueStreamRef) ->
@@ -248,7 +248,7 @@ handle_continue(ContinueStreamRef, {tls_proxy_error, ProxyPid, Reason},
%%
%% @todo Assert StreamRef to be our reference().
handle_continue([_StreamRef|ContinueStreamRef0], Msg,
- State0=#tunnel_state{protocol=Proto, protocol_state=ProtoState},
+ State=#tunnel_state{protocol=Proto, protocol_state=ProtoState},
CookieStore0, EvHandler, EvHandlerState0) ->
ContinueStreamRef = case ContinueStreamRef0 of
[CSR] -> CSR;
@@ -256,16 +256,16 @@ handle_continue([_StreamRef|ContinueStreamRef0], Msg,
end,
{Commands, CookieStore, EvHandlerState1} = Proto:handle_continue(
ContinueStreamRef, Msg, ProtoState, CookieStore0, EvHandler, EvHandlerState0),
- {State, EvHandlerState} = commands(Commands, State0, EvHandler, EvHandlerState1),
- {{state, State}, CookieStore, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, CookieStore, EvHandlerState}.
%% @todo This function will need EvHandler/EvHandlerState?
-update_flow(State0=#tunnel_state{protocol=Proto, protocol_state=ProtoState},
+update_flow(State=#tunnel_state{protocol=Proto, protocol_state=ProtoState},
ReplyTo, StreamRef0, Inc) ->
- StreamRef = maybe_dereference(State0, StreamRef0),
+ StreamRef = maybe_dereference(State, StreamRef0),
Commands = Proto:update_flow(ProtoState, ReplyTo, StreamRef, Inc),
- {State, undefined} = commands(Commands, State0, undefined, undefined),
- {state, State}.
+ {ResCommands, undefined} = commands(Commands, State, undefined, undefined),
+ ResCommands.
closing(_Reason, _State, _EvHandler, EvHandlerState) ->
%% @todo Graceful shutdown must be propagated to tunnels.
@@ -280,27 +280,27 @@ keepalive(_State, _EvHandler, EvHandlerState) ->
{[], EvHandlerState}.
%% We pass the headers forward and optionally dereference StreamRef.
-headers(State0=#tunnel_state{protocol=Proto, protocol_state=ProtoState0},
+headers(State=#tunnel_state{protocol=Proto, protocol_state=ProtoState0},
StreamRef0, ReplyTo, Method, Host, Port, Path, Headers,
InitialFlow, CookieStore0, EvHandler, EvHandlerState0) ->
- StreamRef = maybe_dereference(State0, StreamRef0),
+ StreamRef = maybe_dereference(State, StreamRef0),
{Commands, CookieStore, EvHandlerState1} = Proto:headers(ProtoState0, StreamRef,
ReplyTo, Method, Host, Port, Path, Headers,
InitialFlow, CookieStore0, EvHandler, EvHandlerState0),
- {State, EvHandlerState} = commands(Commands, State0, EvHandler, EvHandlerState1),
- {{state, State}, CookieStore, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, CookieStore, EvHandlerState}.
%% We pass the request forward and optionally dereference StreamRef.
-request(State0=#tunnel_state{protocol=Proto, protocol_state=ProtoState0,
+request(State=#tunnel_state{protocol=Proto, protocol_state=ProtoState0,
info=#{origin_host := OriginHost, origin_port := OriginPort}},
StreamRef0, ReplyTo, Method, _Host, _Port, Path, Headers, Body,
InitialFlow, CookieStore0, EvHandler, EvHandlerState0) ->
- StreamRef = maybe_dereference(State0, StreamRef0),
+ StreamRef = maybe_dereference(State, StreamRef0),
{Commands, CookieStore, EvHandlerState1} = Proto:request(ProtoState0, StreamRef,
ReplyTo, Method, OriginHost, OriginPort, Path, Headers, Body,
InitialFlow, CookieStore0, EvHandler, EvHandlerState0),
- {State, EvHandlerState} = commands(Commands, State0, EvHandler, EvHandlerState1),
- {{state, State}, CookieStore, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, CookieStore, EvHandlerState}.
%% When the next tunnel is SOCKS we pass the data forward directly.
%% This is needed because SOCKS has no StreamRef and the data cannot
@@ -310,8 +310,8 @@ data(State=#tunnel_state{protocol=Proto, protocol_state=ProtoState0,
StreamRef, ReplyTo, IsFin, Data, EvHandler, EvHandlerState0) ->
{Commands, EvHandlerState1} = Proto:data(ProtoState0, StreamRef,
ReplyTo, IsFin, Data, EvHandler, EvHandlerState0),
- {State1, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
- {{state, State1}, EvHandlerState};
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, EvHandlerState};
%% CONNECT tunnels pass the data forward and dereference StreamRef
%% unless they are the recipient of the callback, in which case the
%% data is sent to the socket.
@@ -327,9 +327,9 @@ data(State=#tunnel_state{socket=Socket, transport=Transport,
StreamRef = maybe_dereference(State, StreamRef0),
{Commands, EvHandlerState1} = Proto:data(ProtoState0, StreamRef,
ReplyTo, IsFin, Data, EvHandler, EvHandlerState0),
- {State1, EvHandlerState} = commands(Commands, State,
+ {ResCommands, EvHandlerState} = commands(Commands, State,
EvHandler, EvHandlerState1),
- {{state, State1}, EvHandlerState}
+ {ResCommands, EvHandlerState}
end.
%% We pass the CONNECT request forward and optionally dereference StreamRef.
@@ -341,16 +341,16 @@ connect(State=#tunnel_state{info=#{origin_host := Host, origin_port := Port},
{Commands, EvHandlerState1} = Proto:connect(ProtoState0, StreamRef,
ReplyTo, Destination, #{host => Host, port => Port}, Headers, InitialFlow,
EvHandler, EvHandlerState0),
- {State1, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
- {{state, State1}, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, EvHandlerState}.
cancel(State=#tunnel_state{protocol=Proto, protocol_state=ProtoState0},
StreamRef0, ReplyTo, EvHandler, EvHandlerState0) ->
StreamRef = maybe_dereference(State, StreamRef0),
{Commands, EvHandlerState1} = Proto:cancel(ProtoState0, StreamRef,
ReplyTo, EvHandler, EvHandlerState0),
- {State1, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
- {{state, State1}, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, EvHandlerState}.
timeout(State=#tunnel_state{protocol=Proto, protocol_state=ProtoState0}, Msg, TRef) ->
case Proto:timeout(ProtoState0, Msg, TRef) of
@@ -436,23 +436,32 @@ ws_upgrade(State=#tunnel_state{info=TunnelInfo, protocol=Proto, protocol_state=P
{Commands, CookieStore, EvHandlerState1} = Proto:ws_upgrade(ProtoState0, StreamRef, ReplyTo,
Host, Port, Path, Headers, WsOpts,
CookieStore0, EvHandler, EvHandlerState0),
- {State1, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
- {{state, State1}, CookieStore, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, CookieStore, EvHandlerState}.
-ws_send(Frames, State0=#tunnel_state{protocol=Proto, protocol_state=ProtoState},
+ws_send(Frames, State=#tunnel_state{protocol=Proto, protocol_state=ProtoState},
StreamRef0, ReplyTo, EvHandler, EvHandlerState0) ->
- StreamRef = maybe_dereference(State0, StreamRef0),
+ StreamRef = maybe_dereference(State, StreamRef0),
{Commands, EvHandlerState1} = Proto:ws_send(Frames,
ProtoState, StreamRef, ReplyTo, EvHandler, EvHandlerState0),
- {State, EvHandlerState} = commands(Commands, State0, EvHandler, EvHandlerState1),
- {{state, State}, EvHandlerState}.
+ {ResCommands, EvHandlerState} = commands(Commands, State, EvHandler, EvHandlerState1),
+ {ResCommands, EvHandlerState}.
%% Internal.
commands(Command, State, EvHandler, EvHandlerState) when not is_list(Command) ->
commands([Command], State, EvHandler, EvHandlerState);
commands([], State, _, EvHandlerState) ->
- {State, EvHandlerState};
+ {{state, State}, EvHandlerState};
+commands([Error = {error, _}|_],
+ State=#tunnel_state{socket=Socket, transport=Transport},
+ _, EvHandlerState) ->
+ %% We must terminate the TLS proxy pid if any.
+ case Transport of
+ gun_tls_proxy -> gun_tls_proxy:close(Socket);
+ _ -> ok
+ end,
+ {[{state, State}, Error], EvHandlerState};
commands([{state, ProtoState}|Tail], State, EvHandler, EvHandlerState) ->
commands(Tail, State#tunnel_state{protocol_state=ProtoState}, EvHandler, EvHandlerState);
%% @todo What to do about IsFin?