24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-07-04 23:15:31 +02:00

[TECH-1511] clean support for websockets.

Added handlers in configuration file
This commit is contained in:
Eric Cestari 2010-09-13 12:04:52 +02:00
parent c41bdea1f1
commit 35a0e27d04
3 changed files with 50 additions and 17 deletions

View File

@ -65,7 +65,8 @@
request_tp,
request_headers = [],
end_of_request = false,
trail = ""
trail = "",
websocket_handlers = []
}).
@ -134,11 +135,16 @@ init({SockMod, Socket}, Opts) ->
false -> []
end,
?DEBUG("S: ~p~n", [RequestHandlers]),
WebSocketHandlers = case lists:keysearch(websocket_handlers, 1, Opts) of
{value, {websocket_handlers, WH}} -> WH;
false -> []
end,
?DEBUG("WS: ~p~n", [WebSocketHandlers]),
?INFO_MSG("started: ~p", [{SockMod1, Socket1}]),
State = #state{sockmod = SockMod1,
socket = Socket1,
request_handlers = RequestHandlers},
request_handlers = RequestHandlers,
websocket_handlers = WebSocketHandlers},
receive_headers(State).
@ -148,6 +154,9 @@ become_controller(_Pid) ->
socket_type() ->
raw.
send_text(State, none) ->
exit(normal);
send_text(State, Text) ->
case catch (State#state.sockmod):send(State#state.socket, Text) of
ok -> ok;
@ -315,6 +324,23 @@ get_transfer_protocol(SockMod, HostPort) ->
%% found, answer with HTTP 404.
process([], _) ->
ejabberd_web:error(not_found);
process(Handlers, #ws{} = Ws)->
[{HandlerPathPrefix, HandlerModule} | HandlersLeft] = Handlers,
case (lists:prefix(HandlerPathPrefix, Ws#ws.path) or
(HandlerPathPrefix==Ws#ws.path)) of
true ->
?DEBUG("~p matches ~p", [Ws#ws.path, HandlerPathPrefix]),
%% LocalPath is the path "local to the handler", i.e. if
%% the handler was registered to handle "/test/" and the
%% requested path is "/test/foo/bar", the local path is
%% ["foo", "bar"]
LocalPath = lists:nthtail(length(HandlerPathPrefix), Ws#ws.path),
ejabberd_hooks:run(ws_debug, [{LocalPath, Ws}]),
ejabberd_websocket:connect(Ws#ws{local_path = LocalPath}, HandlerModule);
false ->
?DEBUG("HandlersLeft : ~p ", [HandlersLeft]),
process(HandlersLeft, Ws)
end;
process(Handlers, Request) ->
[{HandlerPathPrefix, HandlerModule} | HandlersLeft] = Handlers,
@ -344,6 +370,7 @@ process_request(#state{request_method = Method,
request_tp = TP,
request_headers = RequestHeaders,
sockmod = SockMod,
websocket_handlers = WebSocketHandlers,
socket = Socket} = State)
when Method=:='GET' orelse Method=:='HEAD' orelse Method=:='DELETE' orelse Method=:='OPTIONS' ->
case (catch url_decode_q_split(Path)) of
@ -375,17 +402,17 @@ process_request(#state{request_method = Method,
Ws = #ws{socket = Socket,
sockmod = SockMod,
ws_autoexit = true,
path = Path,
path = LPath,
vsn = VSN,
host = Host,
port = Port,
origin = Origin,
headers = RequestHeaders
},
?DEBUG("WS: ~p/~p~n", [WebSocketHandlers, Path]),
?DEBUG("It is a websocket version : ~p",[VSN]),
ejabberd_websocket:connect(Ws, websocket_test);
process(WebSocketHandlers, Ws),
none;
false ->
Request = #request{method = Method,
path = LPath,

View File

@ -45,6 +45,8 @@
vsn, % {Maj,Min} | {'draft-hixie', Ver}
origin, % the originator
host, % the host
port,
path, % the websocket GET request path
headers % [{Tag, Val}]
headers, % [{Tag, Val}]
local_path
}).

View File

@ -41,7 +41,7 @@
-compile(export_all).
-include("ejabberd.hrl").
-include("jlib.hrl").
-include ("ejabberd_http.hrl").
-include("ejabberd_http.hrl").
check(_Path, Headers)->
?DEBUG("testing for a websocket request path: ~p headers: ~p", [_Path, Headers]),
@ -51,9 +51,9 @@ check(_Path, Headers)->
check_websockets(VsnSupported, Headers).
% Connect and handshake with Websocket.
connect(#ws{vsn = Vsn, socket = Socket, origin=Origin, host=Host,sockmod = SockMod, path = Path, headers = Headers, ws_autoexit = WsAutoExit} = Ws, WsLoop) ->
connect(#ws{vsn = Vsn, socket = Socket, origin=Origin, host=Host, port=Port, sockmod = SockMod, path = Path, headers = Headers, ws_autoexit = WsAutoExit} = Ws, WsLoop) ->
% build handshake
HandshakeServer = handshake(Vsn, Socket,SockMod, Headers, {Path, Origin, Host}),
HandshakeServer = handshake(Vsn, Socket,SockMod, Headers, {Path, Origin, Host, Port}),
% send handshake back
?DEBUG("building handshake response : ~p", [HandshakeServer]),
SockMod:send(Socket, HandshakeServer),
@ -136,7 +136,7 @@ check_headers(Headers, RequiredHeaders) ->
% Function: List
% Description: Builds the server handshake response.
handshake({'draft-hixie', 76}, Sock,SocketMod, Headers, {Path, Origin, Host}) ->
handshake({'draft-hixie', 76}, Sock,SocketMod, Headers, {Path, Origin, Host, Port}) ->
% build data
{_, Key1} = lists:keyfind("Sec-Websocket-Key1",1, Headers),
{_, Key2} = lists:keyfind("Sec-Websocket-Key2",1, Headers),
@ -156,22 +156,26 @@ handshake({'draft-hixie', 76}, Sock,SocketMod, Headers, {Path, Origin, Host}) ->
?ERROR_MSG("tcp error treating data: ~p", [_Other]),
<<>>
end,
?DEBUG("got content in body of websocket request: ~p", [Body]),
?DEBUG("got content in body of websocket request: ~p, ~p", [Body,string:join([Host, Path],"/")]),
% prepare handhsake response
["HTTP/1.1 101 WebSocket Protocol Handshake\r\n",
"Upgrade: WebSocket\r\n",
"Connection: Upgrade\r\n",
"Sec-WebSocket-Origin: ", Origin, "\r\n",
"Sec-WebSocket-Location: ws://", Host, ":5280",Path, "\r\n\r\n",
"Sec-WebSocket-Location: ws://",
string:join([Host, integer_to_list(Port)],":"),
"/",string:join(Path,"/") , "\r\n\r\n",
build_challenge({'draft-hixie', 76}, {Key1, Key2, Body})
];
handshake({'draft-hixie', 68}, _Sock,_SocketMod, _Headers, {Path, Origin, Host}) ->
handshake({'draft-hixie', 68}, _Sock,_SocketMod, _Headers, {Path, Origin, Host, Port}) ->
% prepare handhsake response
["HTTP/1.1 101 Web Socket Protocol Handshake\r\n",
"Upgrade: WebSocket\r\n",
"Connection: Upgrade\r\n",
"WebSocket-Origin: ", Origin , "\r\n",
"WebSocket-Location: ws://", lists:concat([Host, Path]), "\r\n\r\n"
"WebSocket-Location: ws://",
lists:concat([Host, integer_to_list(Port)]),
"/",string:join(Path,"/"), "\r\n\r\n"
].
% Function: List