mirror of
https://github.com/processone/ejabberd.git
synced 2024-10-03 14:45:16 +02:00
[TECH-1511] clean support for websockets.
Added handlers in configuration file
This commit is contained in:
parent
c41bdea1f1
commit
35a0e27d04
@ -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,
|
||||
|
@ -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
|
||||
}).
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user