aboutsummaryrefslogtreecommitdiffstats
path: root/src/gun_http.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2019-09-16 18:38:41 +0200
committerLoïc Hoguin <[email protected]>2019-09-22 16:46:34 +0200
commit93552edd8afb598a3ef6d358fb6918fb9ff60856 (patch)
treef71bbe40540cc18359c623ef94518a4ee426fea0 /src/gun_http.erl
parent74ab050f546ed94860da6f809617a6986a962ef5 (diff)
downloadgun-93552edd8afb598a3ef6d358fb6918fb9ff60856.tar.gz
gun-93552edd8afb598a3ef6d358fb6918fb9ff60856.tar.bz2
gun-93552edd8afb598a3ef6d358fb6918fb9ff60856.zip
Move and merge all TLS handshakes to the main Gun code
There's now an initial_tls_handshake state for the initial connection with handshake, and tls_handshake state for any subsequent TLS handshakes. The Socks5 code will be able to reuse this tls_handshake state to perform its own transport switches.
Diffstat (limited to 'src/gun_http.erl')
-rw-r--r--src/gun_http.erl69
1 files changed, 12 insertions, 57 deletions
diff --git a/src/gun_http.erl b/src/gun_http.erl
index 309772e..59b127f 100644
--- a/src/gun_http.erl
+++ b/src/gun_http.erl
@@ -17,6 +17,7 @@
-export([check_options/1]).
-export([name/0]).
-export([init/4]).
+-export([switch_transport/3]).
-export([handle/4]).
-export([update_flow/4]).
-export([closing/4]).
@@ -104,6 +105,9 @@ init(Owner, Socket, Transport, Opts) ->
#http_state{owner=Owner, socket=Socket, transport=Transport, opts=Opts, version=Version,
content_handlers=Handlers, transform_header_name=TransformHeaderName}.
+switch_transport(Transport, Socket, State) ->
+ State#http_state{socket=Socket, transport=Transport}.
+
%% Stop looping when we got no more data.
handle(<<>>, State, _, EvHandlerState) ->
{{state, State}, EvHandlerState};
@@ -253,9 +257,8 @@ handle(Data, State=#http_state{in={body, Length}, connection=Conn,
end
end.
-handle_head(Data, State=#http_state{socket=Socket, transport=Transport,
- version=ClientVersion, content_handlers=Handlers0, connection=Conn,
- streams=[Stream=#stream{ref=StreamRef, reply_to=ReplyTo,
+handle_head(Data, State=#http_state{version=ClientVersion, content_handlers=Handlers0,
+ connection=Conn, streams=[Stream=#stream{ref=StreamRef, reply_to=ReplyTo,
method=Method, is_alive=IsAlive}|Tail]},
EvHandler, EvHandlerState0) ->
{Version, Status, _, Rest} = cow_http:parse_status_line(Data),
@@ -292,65 +295,17 @@ handle_head(Data, State=#http_state{socket=Socket, transport=Transport,
State2 = end_stream(State#http_state{streams=[Stream|Tail]}),
NewHost = maps:get(host, Destination),
NewPort = maps:get(port, Destination),
+ Protocols = maps:get(protocols, Destination, [http]),
case Destination of
- #{transport := tls} when Transport =:= gun_tls ->
- TLSOpts = maps:get(tls_opts, Destination, []),
- TLSTimeout = maps:get(tls_handshake_timeout, Destination, infinity),
- HandshakeEvent = #{
- stream_ref => RealStreamRef,
- reply_to => ReplyTo,
- socket => Socket,
- tls_opts => TLSOpts,
- timeout => TLSTimeout
- },
- EvHandlerState = EvHandler:tls_handshake_start(HandshakeEvent, EvHandlerState1),
- {ok, ProxyPid} = gun_tls_proxy:start_link(NewHost, NewPort,
- TLSOpts, TLSTimeout, Socket, gun_tls, HandshakeEvent),
- %% In this case the switch_protocol is delayed and is handled by
- %% a message sent from gun_tls_proxy once the connection is established,
- %% and handled by the gun module directly.
- {[{state, State2#http_state{socket=ProxyPid, transport=gun_tls_proxy}},
- {origin, <<"https">>, NewHost, NewPort, connect},
- {switch_transport, gun_tls_proxy, ProxyPid}], EvHandlerState};
#{transport := tls} ->
TLSOpts = maps:get(tls_opts, Destination, []),
TLSTimeout = maps:get(tls_handshake_timeout, Destination, infinity),
- HandshakeEvent = #{
- stream_ref => RealStreamRef,
- reply_to => ReplyTo,
- socket => Socket,
- tls_opts => TLSOpts,
- timeout => TLSTimeout
- },
- EvHandlerState2 = EvHandler:tls_handshake_start(HandshakeEvent, EvHandlerState1),
- case gun_tls:connect(Socket, TLSOpts, TLSTimeout) of
- {ok, TLSSocket} ->
- Protocol = case ssl:negotiated_protocol(TLSSocket) of
- {ok, <<"h2">>} -> gun_http2;
- _ -> gun_http
- end,
- EvHandlerState = EvHandler:tls_handshake_end(HandshakeEvent#{
- socket => TLSSocket,
- protocol => Protocol:name()
- }, EvHandlerState2),
- case Protocol of
- gun_http2 ->
- {[{origin, <<"https">>, NewHost, NewPort, connect},
- {switch_transport, gun_tls, TLSSocket},
- {switch_protocol, gun_http2, State2}], EvHandlerState};
- gun_http ->
- {[{state, State2#http_state{socket=TLSSocket, transport=gun_tls}},
- {origin, <<"https">>, NewHost, NewPort, connect},
- {switch_transport, gun_tls, TLSSocket}], EvHandlerState}
- end;
- Error = {error, Reason} ->
- EvHandlerState = EvHandler:tls_handshake_end(HandshakeEvent#{
- error => Reason
- }, EvHandlerState2),
- {Error, EvHandlerState}
- end;
+ {[
+ {origin, <<"https">>, NewHost, NewPort, connect},
+ {tls_handshake, RealStreamRef, ReplyTo, TLSOpts, TLSTimeout, Protocols}
+ ], EvHandlerState1};
_ ->
- case maps:get(protocols, Destination, [http]) of
+ case Protocols of
[http] ->
{[{state, State2},
{origin, <<"http">>, NewHost, NewPort, connect}], EvHandlerState1};