|
@@ -0,0 +1,85 @@
|
|
|
+-module(n4u_proto).
|
|
|
+-include_lib("n4u/include/n4u.hrl").
|
|
|
+
|
|
|
+-export([init/4, terminate/2]).
|
|
|
+-export([info/3, stream/3, nop/2, reply/3, push/5]).
|
|
|
+-export([protocols/0]).
|
|
|
+
|
|
|
+
|
|
|
+% N4U Protocol WebSocket endpoint handler
|
|
|
+
|
|
|
+formatter(O)->
|
|
|
+ case lists:keyfind(formatter, 1, O) of
|
|
|
+ {formatter, F} -> F;
|
|
|
+ X -> X
|
|
|
+ end.
|
|
|
+
|
|
|
+
|
|
|
+upack(D) -> erlang:binary_to_term(D, [safe]).
|
|
|
+
|
|
|
+
|
|
|
+protocols() -> application:get_env(n4u, protocols, [ n4u_heart,
|
|
|
+ n4u_nitrogen,
|
|
|
+ n4u_file,
|
|
|
+ n4u_client,
|
|
|
+ n4u_http ]).
|
|
|
+
|
|
|
+
|
|
|
+terminate(_R, #cx{module = Module}) ->
|
|
|
+ catch Module:event(terminate);
|
|
|
+
|
|
|
+%terminate(_R, []) -> ok;
|
|
|
+terminate(R, C) ->
|
|
|
+ wf:info(?MODULE, "terminate: ~p ~p~n", [R, C]),
|
|
|
+ ok.
|
|
|
+
|
|
|
+
|
|
|
+init(_Transport, Req, Opts, _N) ->
|
|
|
+ erlang:put(actions, []),
|
|
|
+ Ctx = (n4u_cx:init_context(Req))#cx{formatter = formatter(Opts)},
|
|
|
+ %wf:info(?MODULE, "init: ~p~n ~p~n ~p~n ~p~n ~p~n", [_Transport, Req, Opts, _N, Ctx]),
|
|
|
+ NewCtx = n4u_cx:fold(init, Ctx#cx.handlers, Ctx),
|
|
|
+ erlang:put(context, NewCtx),
|
|
|
+ wf:reg(broadcast, {wf:peer(Req)}),
|
|
|
+ Origin = wf:get_header(<<"origin">>, Req, <<"*">>),
|
|
|
+ Config_Origin = nitro:to_binary(application:get_env(n4u, origin, Origin)),
|
|
|
+ wf:info(?MODULE, "Origin: ~p", [Config_Origin]),
|
|
|
+ Req1 = wf:set_header(<<"Access-Control-Allow-Origin">>, Config_Origin, NewCtx#cx.req),
|
|
|
+ {ok, Req1, NewCtx}.
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+%% N4U top level protocol NOP REPLY PUSH
|
|
|
+
|
|
|
+%info(M, R, S) -> filter(M, R, S, protocols(), []).
|
|
|
+%stream({text, _} = M, R, S) -> filter(M, R, S, protocols(), []);
|
|
|
+%stream({binary, <<>>}, R, S) -> nop(R, S);
|
|
|
+%stream({binary, D}, R, S) -> filter(upack(D), R, S, protocols(), []);
|
|
|
+%stream(_, R, S) -> nop(R, S).
|
|
|
+%
|
|
|
+%filter(M, R, S, Protos, Acc) ->
|
|
|
+% case application:get_env(n4u, filter, {?MODULE, push}) of
|
|
|
+% undefined -> push(M, R, S, Protos, Acc);
|
|
|
+% {Mod, Fun} -> Mod:Fun(M, R, S, Protos, Acc)
|
|
|
+% end.
|
|
|
+
|
|
|
+
|
|
|
+info(M, R, S) -> push(M, R, S, protocols(), []).
|
|
|
+stream({text, _} = M, R, S) -> push(M, R, S, protocols(), []);
|
|
|
+stream({binary, <<>>}, R, S) -> nop(R, S);
|
|
|
+stream({binary, D}, R, S) -> push(upack(D), R, S, protocols(), []);
|
|
|
+stream(_, R, S) -> nop(R, S).
|
|
|
+
|
|
|
+
|
|
|
+nop(R, S) -> {reply, <<>>, R, S}.
|
|
|
+reply(M, R, S) -> {reply, M, R, S}.
|
|
|
+push(_, R, S, [], _) -> nop(R, S);
|
|
|
+push(M, R, S, [H|T], Acc) ->
|
|
|
+ %io:format("n4u_proto:::push ~p~n~p~n~p~n~p~n", [H, M, R, S]),
|
|
|
+ %io:format("n4u_proto:::push ~p~n~p~n", [H, M]),
|
|
|
+ case H:info(M, R, S) of
|
|
|
+ {unknown, _, _, _} -> push(M, R, S, T, Acc);
|
|
|
+ {reply, M1, R1, S1} -> reply(M1, R1, S1);
|
|
|
+ A -> push(M, R, S, T, [A|Acc])
|
|
|
+ end.
|
|
|
+
|