From 6a4178f1778b82521803cd5545256c1082c40234 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 18 Sep 2018 19:34:22 +0200 Subject: [PATCH] Cowboy 2.x support --- .../cowboy_simple_bridge_anchor.erl | 129 +++++++++--------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/src/cowboy_bridge_modules/cowboy_simple_bridge_anchor.erl b/src/cowboy_bridge_modules/cowboy_simple_bridge_anchor.erl index ac82e79..05dc14f 100644 --- a/src/cowboy_bridge_modules/cowboy_simple_bridge_anchor.erl +++ b/src/cowboy_bridge_modules/cowboy_simple_bridge_anchor.erl @@ -2,97 +2,100 @@ -module(cowboy_simple_bridge_anchor). -export([ - init/3, + init/2, handle/2, - terminate/3, - websocket_init/3, - websocket_handle/3, - websocket_info/3, - websocket_terminate/3 + terminate/2, + websocket_init/1, + websocket_handle/2, + websocket_info/2, + websocket_terminate/2 ]). --record(ws_state, {handler, keepalive_interval, bridge, state}). +-record(ws_state, {handler, keepalive_interval, bridge, state, init_req}). -init(_Transport, Req, _Opts) -> - {Upgrade, _} = cowboy_req:header(<<"upgrade">>, Req), +init(Req, State) -> + Upgrade = cowboy_req:header(<<"upgrade">>, Req), Upgrade2 = case Upgrade of - undefined -> undefined; - Other -> simple_bridge_util:binarize_header(Other) - end, - + undefined -> undefined; + Other -> simple_bridge_util:binarize_header(Other) + end, case Upgrade2 == <<"websocket">> of - true -> - {upgrade, protocol, cowboy_websocket}; - false -> - {ok, Req, []} - end. + true -> + %% Keepalive stuff + {KAInterval, KATimeout} = simple_bridge_util:get_websocket_keepalive_interval_timeout(cowboy), + CowboyTimeout = simple_bridge_websocket:keepalive_timeout(KAInterval, KATimeout), + + %% START YOUR ENGINES, FOLKS! + WSState = #ws_state{init_req = Req, + keepalive_interval=KAInterval}, + {cowboy_websocket, Req, WSState, #{idle_timeout => CowboyTimeout}}; + false -> + DocRoot = simple_bridge_util:get_env(document_root), + Handler = simple_bridge_util:get_env(handler), + Bridge = simple_bridge:make(cowboy, {Req, DocRoot}), + {ok, NewReq} = Handler:run(Bridge), + {ok, NewReq, State} + end. + handle(Req, State) -> - DocRoot = simple_bridge_util:get_env(document_root), - Handler = simple_bridge_util:get_env(handler), - Bridge = simple_bridge:make(cowboy, {Req, DocRoot}), - {ok, NewReq} = Handler:run(Bridge), - {ok, NewReq, State}. + {ok, Req, State}. -terminate(_Reason, _Req, _State) -> +terminate(_Reason, _State) -> ok. -websocket_init(_Transport, Req, _Opts) -> - %% Init stuff - {ok, Handler} = application:get_env(simple_bridge, handler), - Bridge = simple_bridge:make(cowboy, {Req, ""}), - UserState = simple_bridge_websocket:call_init(Handler, Bridge), +websocket_init(State) -> - %% Keepalive stuff - {KAInterval, KATimeout} = simple_bridge_util:get_websocket_keepalive_interval_timeout(cowboy), - CowboyTimeout = simple_bridge_websocket:keepalive_timeout(KAInterval, KATimeout), - simple_bridge_websocket:schedule_keepalive_msg(KAInterval), + {ok, Handler} = application:get_env(simple_bridge, handler), + Bridge = simple_bridge:make(cowboy, {State#ws_state.init_req, ""}), + UserState = simple_bridge_websocket:call_init(Handler, Bridge), + simple_bridge_websocket:schedule_keepalive_msg(State#ws_state.keepalive_interval), + %% START YOUR ENGINES, FOLKS! - WSState = #ws_state{bridge=Bridge, - keepalive_interval=KAInterval, - handler=Handler, - state=UserState}, - {ok, Req, WSState, CowboyTimeout}. + WSState = State#ws_state{state=UserState, + init_req = undefined, + bridge=Bridge, + handler=Handler + }, + {ok, WSState}. -websocket_handle({ping, _Data}, Req, WSState) -> +websocket_handle({ping, _Data}, WSState) -> %% We don't need to pong, cowboy does that automatically. So just carry on! - {ok, Req, WSState}; -websocket_handle({pong, _PongMsg}, Req, WSState) -> - {ok, Req, WSState}; -websocket_handle(Data, Req, WSState) -> + {ok, WSState}; +websocket_handle({pong, _PongMsg}, WSState) -> + {ok, WSState}; +websocket_handle(Data, WSState) -> #ws_state{handler=Handler, bridge=Bridge, state=State} = WSState, Result = Handler:ws_message(Data, Bridge, State), - massage_reply(Result, Req, WSState). + massage_reply(Result, WSState). -websocket_info(simple_bridge_send_ping, Req, WSState=#ws_state{keepalive_interval=KAInterval}) -> +websocket_info(simple_bridge_send_ping, WSState=#ws_state{keepalive_interval=KAInterval}) -> simple_bridge_websocket:schedule_keepalive_msg(KAInterval), - {reply, {ping, <<"Simple Bridge Ping">>}, Req, WSState}; + {reply, {ping, <<"Simple Bridge Ping">>}, WSState}; -websocket_info(Data, Req, WSState) -> +websocket_info(Data, WSState) -> #ws_state{handler=Handler, bridge=Bridge, state=State} = WSState, Result = Handler:ws_info(Data, Bridge, State), - massage_reply(Result, Req, WSState). + massage_reply(Result, WSState). -websocket_terminate(Reason, _Req, #ws_state{bridge=Bridge, handler=Handler, state=State}) -> +websocket_terminate(Reason, #ws_state{bridge=Bridge, handler=Handler, state=State}) -> ok = Handler:ws_terminate(Reason, Bridge, State). %% MASSAGE_REPLY reformats a simple_bridge return value into something that can %% be handled by cowboy. -massage_reply({reply, {Type, Data}, NewState}, Req, WSState) +massage_reply({reply, {Type, Data}, NewState}, WSState) when Type==binary orelse Type==text -> - {reply, {Type, iolist_to_binary(Data)}, Req, WSState#ws_state{state=NewState}}; -massage_reply({reply, List, NewState}, Req, WSState) -> + {reply, {Type, iolist_to_binary(Data)}, WSState#ws_state{state=NewState}}; +massage_reply({reply, List, NewState}, WSState) -> FixedList = [{Type, iolist_to_binary(Data)} || {Type, Data} <- List], - {reply, FixedList, Req, WSState#ws_state{state=NewState}}; -massage_reply({reply, Reply}, Req, WSState) -> - massage_reply({reply, Reply, WSState#ws_state.state}, Req, WSState); -massage_reply({noreply, NewState}, Req, WSState) -> - {ok, Req, WSState#ws_state{state=NewState}}; -massage_reply(noreply, Req, WSState) -> - {ok, Req, WSState}; -massage_reply({close, _Reason}, Req, WSState) -> - {shutdown, Req, WSState}; -massage_reply(close, Req, WSState) -> - {shutdown, Req, WSState}. + {reply, FixedList, WSState#ws_state{state=NewState}}; +massage_reply({reply, Reply}, WSState) -> + massage_reply({reply, Reply, WSState#ws_state.state}, WSState); +massage_reply({noreply, NewState}, WSState) -> + {ok, WSState#ws_state{state=NewState}}; +massage_reply({remote, _Reason}, WSState) -> + {stop, WSState}; +massage_reply(stop, WSState) -> + {stop, WSState}.