25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-10-31 15:21:38 +01:00

Properly handle websocket sub-protocols

This commit is contained in:
Paweł Chmielowski 2012-09-14 10:15:32 +02:00
parent 2f7c69fd14
commit 8eef2f02bf

View File

@ -56,8 +56,7 @@ check(_Path, Headers) ->
is_acceptable(#ws{origin = Origin, protocol = Protocol, is_acceptable(#ws{origin = Origin, protocol = Protocol,
headers = Headers, acceptable_origins = Origins, headers = Headers, acceptable_origins = Origins,
auth_module = undefined}) -> auth_module = undefined}) ->
ClientProtocol = ClientProtocol = find_subprotocol(Headers),
lists:keyfind(<<"Sec-Websocket-Protocol">>, 1, Headers),
case {(Origins == []) or lists:member(Origin, Origins), case {(Origins == []) or lists:member(Origin, Origins),
ClientProtocol, Protocol} ClientProtocol, Protocol}
of of
@ -67,7 +66,7 @@ is_acceptable(#ws{origin = Origin, protocol = Protocol,
[]), []),
false; false;
{_, false, _} -> true; {_, false, _} -> true;
{_, {_, P}, P} -> true; {_, P, P} -> true;
_ = E -> _ = E ->
?INFO_MSG("Wrong protocol requested : ~p", [E]), false ?INFO_MSG("Wrong protocol requested : ~p", [E]), false
end; end;
@ -209,16 +208,29 @@ handshake({'draft-hixie', 0}, Sock, SocketMod, Headers,
[none] -> <<"">>; [none] -> <<"">>;
QParams -> <<"?", (str:join(QParams, <<"&">>))/binary>> QParams -> <<"?", (str:join(QParams, <<"&">>))/binary>>
end, end,
SubProtocolHeader = case find_subprotocol(Headers) of
false ->
[];
V ->
[<<"Sec-Websocket-Protocol:">>, V, <<"\r\n">>]
end,
[<<"HTTP/1.1 101 WebSocket Protocol Handshake\r\n">>, [<<"HTTP/1.1 101 WebSocket Protocol Handshake\r\n">>,
<<"Upgrade: WebSocket\r\n">>, <<"Upgrade: WebSocket\r\n">>,
<<"Connection: Upgrade\r\n">>, <<"Connection: Upgrade\r\n">>,
<<"Sec-WebSocket-Origin: ">>, Origin, <<"\r\n">>, <<"Sec-WebSocket-Origin: ">>, Origin, <<"\r\n">>,
SubProtocolHeader,
<<"Sec-WebSocket-Location: ws://">>, HostPort, <<"/">>, <<"Sec-WebSocket-Location: ws://">>, HostPort, <<"/">>,
str:join(Path, <<"/">>), QString, <<"\r\n\r\n">>, str:join(Path, <<"/">>), QString, <<"\r\n\r\n">>,
build_challenge({'draft-hixie', 0}, build_challenge({'draft-hixie', 0},
{Key1, Key2, Body})]; {Key1, Key2, Body})];
handshake({'draft-hixie', 68}, _Sock, _SocketMod, handshake({'draft-hixie', 68}, _Sock, _SocketMod,
Headers, {Path, _Q, Origin, Host, Port}) -> Headers, {Path, _Q, Origin, Host, Port}) ->
SubProtocolHeader = case find_subprotocol(Headers) of
false ->
[];
V ->
[<<"Sec-Websocket-Protocol:">>, V, <<"\r\n">>]
end,
HostPort = case lists:keyfind('Host', 1, Headers) of HostPort = case lists:keyfind('Host', 1, Headers) of
{_, Value} -> Value; {_, Value} -> Value;
_ -> _ ->
@ -228,19 +240,28 @@ handshake({'draft-hixie', 68}, _Sock, _SocketMod,
end, end,
[<<"HTTP/1.1 101 Web Socket Protocol Handshake\r\n">>, [<<"HTTP/1.1 101 Web Socket Protocol Handshake\r\n">>,
<<"Upgrade: WebSocket\r\n">>, <<"Upgrade: WebSocket\r\n">>,
<<"Connection: Upgrade\r\n">>, <<"WebSocket-Origin: ">>, <<"Connection: Upgrade\r\n">>,
Origin, <<"\r\n">>, <<"WebSocket-Location: ws://">>, <<"WebSocket-Origin: ">>, Origin, <<"\r\n">>,
SubProtocolHeader,
<<"WebSocket-Location: ws://">>,
HostPort, <<"/">>, str:join(Path, <<"/">>), HostPort, <<"/">>, str:join(Path, <<"/">>),
<<"\r\n\r\n">>]; <<"\r\n\r\n">>];
handshake({'draft-hybi', _}, _Sock, _SocketMod, Headers, handshake({'draft-hybi', _}, _Sock, _SocketMod, Headers,
{_Path, _Q, _Origin, _Host, _Port}) -> {_Path, _Q, _Origin, _Host, _Port}) ->
{_, Key} = lists:keyfind(<<"Sec-Websocket-Key">>, 1, {_, Key} = lists:keyfind(<<"Sec-Websocket-Key">>, 1,
Headers), Headers),
SubProtocolHeader = case find_subprotocol(Headers) of
false ->
[];
V ->
[<<"Sec-Websocket-Protocol:">>, V, <<"\r\n">>]
end,
Hash = jlib:encode_base64( Hash = jlib:encode_base64(
sha:sha1(<<Key/binary, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11">>)), sha:sha1(<<Key/binary, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11">>)),
[<<"HTTP/1.1 101 Switching Protocols\r\n">>, [<<"HTTP/1.1 101 Switching Protocols\r\n">>,
<<"Upgrade: websocket\r\n">>, <<"Upgrade: websocket\r\n">>,
<<"Connection: Upgrade\r\n">>, <<"Connection: Upgrade\r\n">>,
SubProtocolHeader
<<"Sec-WebSocket-Accept: ">>, Hash, <<"\r\n\r\n">>]. <<"Sec-WebSocket-Accept: ">>, Hash, <<"\r\n\r\n">>].
build_challenge({'draft-hixie', 0}, build_challenge({'draft-hixie', 0},
@ -255,6 +276,20 @@ build_challenge({'draft-hixie', 0},
Part2:4/big-unsigned-integer-unit:8, Key3/binary>>, Part2:4/big-unsigned-integer-unit:8, Key3/binary>>,
erlang:md5(Ckey). erlang:md5(Ckey).
find_subprotocol(Headers) ->
case lists:keysearch(<<"Sec-Websocket-Protocol">>, 1, Headers) of
false ->
case lists:keysearch(<<"Websocket-Protocol">>, 1, Headers) of
false ->
false;
{value, {_, Protocol2}} ->
Protocol2
end;
{value, {_, Protocol}} ->
Protocol
end.
ws_loop(Vsn, HandlerState, Socket, WsHandleLoopPid, ws_loop(Vsn, HandlerState, Socket, WsHandleLoopPid,
SocketMode, WsAutoExit) -> SocketMode, WsAutoExit) ->
receive receive