Websocket open callback. #99

Closed
wants to merge 5 commits into
from
View
@@ -2738,6 +2738,9 @@ \section{WebSocket Callback Modules}
\\ \verb+handle_message/2+ callback function, depending on whether
it's a basic or advanced callback module.
+To be notified when the connection have been upgraded, you can implement,
+ \verb+handle_open/1+ callback.
+
\subsection{Basic Callback Modules}
The argument passed to \verb+handle_message/1+ callback function takes
@@ -2784,9 +2787,10 @@ \subsection{Basic Callback Modules}
\end{itemize}
To inform \Yaws\ of the details of your callback module, return
-\verb+{websocket, CallbackModule, Options}+ from your \verb+out/1+
+\verb+{websocket, CallbackModule, Options, Params}+ from your \verb+out/1+
function, where \verb+CallbackModule+ is the name of your callback
-module and \verb+Options+ is a list of options. The following options
+module, \verb+Options+ is a list of options and \verb+Params+ is an arbitrary
+param to be passed to \verb+handle_open/1+. The following options
are available:
\begin{itemize}
@@ -2823,7 +2827,7 @@ \subsection{Advanced Callback Modules}
To indicate an advanced callback module, include
\verb+{callback, {advanced, InitialState}}+ in the \\ \verb+Options+
-list when you return \verb+{websocket, CallbackModule, Options}+ from
+list when you return \verb+{websocket, CallbackModule, Options, Params}+ from
your \verb+out/1+ function, as described above.
The arguments to the \verb+handle_message/2+ callback
@@ -5,11 +5,15 @@
-module(basic_echo_callback).
%% Export for websocket callbacks
--export([handle_message/1]).
+-export([handle_open/1, handle_message/1]).
%% Export for apply
-export([say_hi/1]).
+handle_open(_Params) ->
+ io:format("The connection was opened.~n", []),
+ noreply.
+
handle_message({text, <<"bye">>}) ->
io:format("User said bye.~n", []),
{close, normal};
View
@@ -2655,10 +2655,10 @@ deliver_dyn_part(CliSock, % essential params
{streamcontent_from_pid, _, Pid} ->
Priv = deliver_accumulated(Arg, CliSock, no, undefined, stream),
wait_for_streamcontent_pid(Priv, CliSock, Pid);
- {websocket, CallbackMod, Opts} ->
+ {websocket, CallbackMod, Opts, Params} ->
%% The handshake passes control over the socket to OwnerPid
%% and terminates the Yaws worker!
- yaws_websockets:start(Arg, CallbackMod, Opts);
+ yaws_websockets:start(Arg, CallbackMod, Opts, Params);
_ ->
DeliverCont(Arg)
end.
@@ -3111,7 +3111,7 @@ handle_out_reply({streamcontent_from_pid, MimeType, Pid},
yaws:outh_set_content_type(MimeType),
{streamcontent_from_pid, MimeType, Pid};
-handle_out_reply({websocket, _CallbackMod, _Opts}=Reply,
+handle_out_reply({websocket, _CallbackMod, _Opts, _Params}=Reply,
_LineNo,_YawsFile, _UT, _ARG) ->
yaws:accumulate_header({connection, erase}),
Reply;
View
@@ -18,17 +18,17 @@
-define(MAX_PAYLOAD, 16777216). %16MB
%% API
--export([start/3, send/2]).
+-export([start/4, send/2]).
%% Exported for spawn
--export([receive_control/4]).
+-export([receive_control/5]).
-start(Arg, CallbackMod, Opts) ->
+start(Arg, CallbackMod, Opts, Params) ->
SC = get(sc),
CliSock = Arg#arg.clisock,
PrepdOpts = preprocess_opts(Opts),
OwnerPid = spawn(?MODULE, receive_control,
- [Arg, SC, CallbackMod, PrepdOpts]),
+ [Arg, SC, CallbackMod, PrepdOpts, Params]),
CliSock = Arg#arg.clisock,
case SC#sconf.ssl of
undefined ->
@@ -73,15 +73,15 @@ preprocess_opts(GivenOpts) ->
{callback, basic}],
lists:foldl(Fun, GivenOpts, Defaults).
-receive_control(Arg, SC, CallbackMod, Opts) ->
+receive_control(Arg, SC, CallbackMod, Opts, Params) ->
receive
ok ->
- handshake(Arg, SC, CallbackMod, Opts);
+ handshake(Arg, SC, CallbackMod, Opts, Params);
{error, Reason} ->
exit(Reason)
end.
-handshake(Arg, SC, CallbackMod, Opts) ->
+handshake(Arg, SC, CallbackMod, Opts, Params) ->
CliSock = Arg#arg.clisock,
OriginOpt = lists:keyfind(origin, 1, Opts),
Origin = get_origin_header(Arg#arg.headers),
@@ -100,13 +100,20 @@ handshake(Arg, SC, CallbackMod, Opts) ->
undefined -> "ws://" ++ Host ++ Path;
_ -> "wss://" ++ Host ++ Path
end,
-
Handshake = handshake(ProtocolVersion, Arg, CliSock,
WebSocketLocation, Origin, Protocol),
gen_tcp:send(CliSock, Handshake), % TODO: use the yaws way of
% supporting normal
% and ssl sockets
{callback, CallbackType} = lists:keyfind(callback, 1, Opts),
+
+ case erlang:function_exported(CallbackMod, handle_open, 1) of
@aladhami5

aladhami5 Dec 3, 2012

please make sure that the CallbackMod module is loaded before calling erlang:function_exported

+ true ->
+ CallbackMod:handle_open(Params);
+ false ->
+ ok
+ end,
+
WSState = #ws_state{sock = CliSock,
vsn = ProtocolVersion,
frag_type = none},
@@ -3,5 +3,5 @@ out(A) ->
CallbackMod = advanced_echo_callback,
InitialState = {state, none, <<>>},
Opts = [{callback, {advanced, InitialState}}],
- {websocket, CallbackMod, Opts}.
+ {websocket, CallbackMod, Opts, []}.
</erl>
@@ -2,5 +2,5 @@
out(A) ->
CallbackMod = basic_echo_callback,
Opts = [{origin, "http://" ++ (A#arg.headers)#headers.host}],
- {websocket, CallbackMod, Opts}.
+ {websocket, CallbackMod, Opts, []}.
</erl>