diff options
author | Loïc Hoguin <[email protected]> | 2019-07-13 17:55:20 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2019-07-13 17:55:20 +0200 |
commit | c7138443995ebd56f061b85e5ee0aebb5c04a00e (patch) | |
tree | 823defd10c1e09f30af3f954296cf9b73dfe4b8d /src/gun.erl | |
parent | 071599cbcd25cd2669e26d23a6e202e0275f191a (diff) | |
download | gun-c7138443995ebd56f061b85e5ee0aebb5c04a00e.tar.gz gun-c7138443995ebd56f061b85e5ee0aebb5c04a00e.tar.bz2 gun-c7138443995ebd56f061b85e5ee0aebb5c04a00e.zip |
Add ws_upgrade/protocol_changed events
And ensure that Websocket triggers all the request/response
events.
Diffstat (limited to 'src/gun.erl')
-rw-r--r-- | src/gun.erl | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/src/gun.erl b/src/gun.erl index a15ca5b..803a5eb 100644 --- a/src/gun.erl +++ b/src/gun.erl @@ -905,25 +905,25 @@ connected(cast, {cancel, ReplyTo, StreamRef}, %% Public Websocket interface. %% @todo Maybe make an interface in the protocol module instead of checking on protocol name. %% An interface would also make sure that HTTP/1.0 can't upgrade. -connected(cast, {ws_upgrade, Owner, StreamRef, Path, Headers}, - State=#state{owner=Owner, origin_host=Host, origin_port=Port, opts=Opts, - protocol=Protocol, protocol_state=ProtoState}) - when Protocol =:= gun_http -> +connected(cast, {ws_upgrade, Owner, StreamRef, Path, Headers}, State=#state{opts=Opts}) -> WsOpts = maps:get(ws_opts, Opts, #{}), - ProtoState2 = Protocol:ws_upgrade(ProtoState, StreamRef, Host, Port, Path, Headers, WsOpts), - {keep_state, State#state{protocol_state=ProtoState2}}; + connected(cast, {ws_upgrade, Owner, StreamRef, Path, Headers, WsOpts}, State); connected(cast, {ws_upgrade, Owner, StreamRef, Path, Headers, WsOpts}, State=#state{owner=Owner, origin_host=Host, origin_port=Port, - protocol=Protocol, protocol_state=ProtoState}) + protocol=Protocol, protocol_state=ProtoState, + event_handler=EvHandler, event_handler_state=EvHandlerState0}) when Protocol =:= gun_http -> - ProtoState2 = Protocol:ws_upgrade(ProtoState, StreamRef, Host, Port, Path, Headers, WsOpts), - {keep_state, State#state{protocol_state=ProtoState2}}; - %% @todo can fail if http/1.0 -%% @todo Probably don't error out here, have a protocol function/command. -connected(cast, {ws_upgrade, ReplyTo, StreamRef, _, _}, _) -> - ReplyTo ! {gun_error, self(), StreamRef, {badstate, - "Websocket is only supported over HTTP/1.1."}}, - keep_state_and_data; + EvHandlerState1 = EvHandler:ws_upgrade(#{ + stream_ref => StreamRef, + reply_to => Owner, %% Only the owner can upgrade the connection at this time. + opts => WsOpts + }, EvHandlerState0), + %% @todo Can fail if HTTP/1.0. + {ProtoState2, EvHandlerState} = Protocol:ws_upgrade(ProtoState, + StreamRef, Host, Port, Path, Headers, WsOpts, + EvHandler, EvHandlerState1), + {keep_state, State#state{protocol_state=ProtoState2, + event_handler_state=EvHandlerState}}; connected(cast, {ws_upgrade, ReplyTo, StreamRef, _, _, _}, _) -> ReplyTo ! {gun_error, self(), StreamRef, {badstate, "Websocket is only supported over HTTP/1.1."}}, @@ -1004,14 +1004,20 @@ commands([{switch_transport, Transport, Socket}|Tail], State) -> commands(Tail, active(State#state{socket=Socket, transport=Transport, messages=Transport:messages()})); %% @todo The two loops should be reunified and this clause generalized. -commands([{switch_protocol, Protocol=gun_ws, ProtoState}], State) -> - {keep_state, keepalive_cancel(State#state{protocol=Protocol, protocol_state=ProtoState})}; +commands([{switch_protocol, Protocol=gun_ws, ProtoState}], State=#state{ + event_handler=EvHandler, event_handler_state=EvHandlerState0}) -> + EvHandlerState = EvHandler:protocol_changed(#{protocol => Protocol:name()}, EvHandlerState0), + {keep_state, keepalive_cancel(State#state{protocol=Protocol, protocol_state=ProtoState, + event_handler_state=EvHandlerState})}; %% @todo And this state should probably not be ignored. -commands([{switch_protocol, Protocol, _ProtoState0}|Tail], - State=#state{owner=Owner, opts=Opts, socket=Socket, transport=Transport}) -> +commands([{switch_protocol, Protocol, _ProtoState0}|Tail], State=#state{ + owner=Owner, opts=Opts, socket=Socket, transport=Transport, + event_handler=EvHandler, event_handler_state=EvHandlerState0}) -> ProtoOpts = maps:get(http2_opts, Opts, #{}), ProtoState = Protocol:init(Owner, Socket, Transport, ProtoOpts), - commands(Tail, keepalive_timeout(State#state{protocol=Protocol, protocol_state=ProtoState})). + EvHandlerState = EvHandler:protocol_changed(#{protocol => Protocol:name()}, EvHandlerState0), + commands(Tail, keepalive_timeout(State#state{protocol=Protocol, protocol_state=ProtoState, + event_handler_state=EvHandlerState})). disconnect(State=#state{owner=Owner, opts=Opts, socket=Socket, transport=Transport, |