mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
commit
1ef9f28f2d
@ -51,7 +51,7 @@
|
|||||||
active = false :: boolean(),
|
active = false :: boolean(),
|
||||||
c2s_pid :: pid(),
|
c2s_pid :: pid(),
|
||||||
ws :: {#ws{}, pid()},
|
ws :: {#ws{}, pid()},
|
||||||
rfc_compilant = undefined :: boolean() | undefined}).
|
rfc_compliant = undefined :: boolean() | undefined}).
|
||||||
|
|
||||||
%-define(DBGFSM, true).
|
%-define(DBGFSM, true).
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ handle_event({new_shaper, Shaper}, StateName, #state{ws = {_, WsPid}} = StateDat
|
|||||||
{next_state, StateName, StateData}.
|
{next_state, StateName, StateData}.
|
||||||
|
|
||||||
handle_sync_event({send_xml, Packet}, _From, StateName,
|
handle_sync_event({send_xml, Packet}, _From, StateName,
|
||||||
#state{ws = {_, WsPid}, rfc_compilant = R} = StateData) ->
|
#state{ws = {_, WsPid}, rfc_compliant = R} = StateData) ->
|
||||||
Packet2 = case {case R of undefined -> true; V -> V end, Packet} of
|
Packet2 = case {case R of undefined -> true; V -> V end, Packet} of
|
||||||
{true, {xmlstreamstart, _, Attrs}} ->
|
{true, {xmlstreamstart, _, Attrs}} ->
|
||||||
Attrs2 = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>} |
|
Attrs2 = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>} |
|
||||||
@ -215,7 +215,7 @@ handle_sync_event({send_xml, Packet}, _From, StateName,
|
|||||||
StateName
|
StateName
|
||||||
end,
|
end,
|
||||||
{reply, ok, SN2, StateData};
|
{reply, ok, SN2, StateData};
|
||||||
handle_sync_event(close, _From, StateName, #state{ws = {_, WsPid}, rfc_compilant = true} = StateData)
|
handle_sync_event(close, _From, StateName, #state{ws = {_, WsPid}, rfc_compliant = true} = StateData)
|
||||||
when StateName /= stream_end_sent ->
|
when StateName /= stream_end_sent ->
|
||||||
Close = #xmlel{name = <<"close">>,
|
Close = #xmlel{name = <<"close">>,
|
||||||
attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>}]},
|
attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>}]},
|
||||||
@ -313,7 +313,7 @@ get_human_html_xmlel() ->
|
|||||||
"client that supports it.">>}]}]}]}.
|
"client that supports it.">>}]}]}]}.
|
||||||
|
|
||||||
|
|
||||||
parse(#state{rfc_compilant = C} = State, Data) ->
|
parse(#state{rfc_compliant = C} = State, Data) ->
|
||||||
case C of
|
case C of
|
||||||
undefined ->
|
undefined ->
|
||||||
P = fxml_stream:new(self()),
|
P = fxml_stream:new(self()),
|
||||||
@ -321,13 +321,13 @@ parse(#state{rfc_compilant = C} = State, Data) ->
|
|||||||
fxml_stream:close(P2),
|
fxml_stream:close(P2),
|
||||||
case parsed_items([]) of
|
case parsed_items([]) of
|
||||||
error ->
|
error ->
|
||||||
{State#state{rfc_compilant = true}, <<"parse error">>};
|
{State#state{rfc_compliant = true}, <<"parse error">>};
|
||||||
[] ->
|
[] ->
|
||||||
{State#state{rfc_compilant = true}, <<"parse error">>};
|
{State#state{rfc_compliant = true}, <<"parse error">>};
|
||||||
[{xmlstreamstart, <<"open">>, _} | _] ->
|
[{xmlstreamstart, <<"open">>, _} | _] ->
|
||||||
parse(State#state{rfc_compilant = true}, Data);
|
parse(State#state{rfc_compliant = true}, Data);
|
||||||
_ ->
|
_ ->
|
||||||
parse(State#state{rfc_compilant = false}, Data)
|
parse(State#state{rfc_compliant = false}, Data)
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
El = fxml_stream:parse_element(Data),
|
El = fxml_stream:parse_element(Data),
|
||||||
|
@ -187,32 +187,32 @@ find_subprotocol(Headers) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid, SocketMode, Shaper) ->
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid, SockMod, Shaper) ->
|
||||||
receive
|
receive
|
||||||
{DataType, _Socket, Data} when DataType =:= tcp orelse DataType =:= raw ->
|
{DataType, _Socket, Data} when DataType =:= tcp orelse DataType =:= raw ->
|
||||||
case handle_data(DataType, FrameInfo, Data, Socket, WsHandleLoopPid, SocketMode, Shaper) of
|
case handle_data(DataType, FrameInfo, Data, Socket, WsHandleLoopPid, SockMod, Shaper) of
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
?DEBUG("TLS decode error ~p", [Error]),
|
?DEBUG("TLS decode error ~p", [Error]),
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, 1002); % protocol error
|
websocket_close(Socket, WsHandleLoopPid, SockMod, 1002); % protocol error
|
||||||
{NewFrameInfo, ToSend, NewShaper} ->
|
{NewFrameInfo, ToSend, NewShaper} ->
|
||||||
lists:foreach(fun(Pkt) -> SocketMode:send(Socket, Pkt)
|
lists:foreach(fun(Pkt) -> SockMod:send(Socket, Pkt)
|
||||||
end, ToSend),
|
end, ToSend),
|
||||||
ws_loop(NewFrameInfo, Socket, WsHandleLoopPid, SocketMode, NewShaper)
|
ws_loop(NewFrameInfo, Socket, WsHandleLoopPid, SockMod, NewShaper)
|
||||||
end;
|
end;
|
||||||
{new_shaper, NewShaper} ->
|
{new_shaper, NewShaper} ->
|
||||||
NewShaper = case NewShaper of
|
NewShaper = case NewShaper of
|
||||||
none when Shaper /= none ->
|
none when Shaper /= none ->
|
||||||
activate(Socket, SocketMode, true), none;
|
activate(Socket, SockMod, true), none;
|
||||||
_ ->
|
_ ->
|
||||||
NewShaper
|
NewShaper
|
||||||
end,
|
end,
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid, SocketMode, NewShaper);
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid, SockMod, NewShaper);
|
||||||
{tcp_closed, _Socket} ->
|
{tcp_closed, _Socket} ->
|
||||||
?DEBUG("TCP connection was closed, exit", []),
|
?DEBUG("TCP connection was closed, exit", []),
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, 0);
|
websocket_close(Socket, WsHandleLoopPid, SockMod, 0);
|
||||||
{tcp_error, Socket, Reason} ->
|
{tcp_error, Socket, Reason} ->
|
||||||
?DEBUG("TCP connection error: ~ts", [inet:format_error(Reason)]),
|
?DEBUG("TCP connection error: ~ts", [inet:format_error(Reason)]),
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, 0);
|
websocket_close(Socket, WsHandleLoopPid, SockMod, 0);
|
||||||
{'DOWN', Ref, process, WsHandleLoopPid, Reason} ->
|
{'DOWN', Ref, process, WsHandleLoopPid, Reason} ->
|
||||||
Code = case Reason of
|
Code = case Reason of
|
||||||
normal ->
|
normal ->
|
||||||
@ -224,39 +224,39 @@ ws_loop(FrameInfo, Socket, WsHandleLoopPid, SocketMode, Shaper) ->
|
|||||||
1011 % internal error
|
1011 % internal error
|
||||||
end,
|
end,
|
||||||
erlang:demonitor(Ref),
|
erlang:demonitor(Ref),
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, Code);
|
websocket_close(Socket, WsHandleLoopPid, SockMod, Code);
|
||||||
{text_with_reply, Data, Sender} ->
|
{text_with_reply, Data, Sender} ->
|
||||||
SocketMode:send(Socket, encode_frame(Data, 1)),
|
SockMod:send(Socket, encode_frame(Data, 1)),
|
||||||
Sender ! {text_reply, self()},
|
Sender ! {text_reply, self()},
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
||||||
SocketMode, Shaper);
|
SockMod, Shaper);
|
||||||
{data_with_reply, Data, Sender} ->
|
{data_with_reply, Data, Sender} ->
|
||||||
SocketMode:send(Socket, encode_frame(Data, 2)),
|
SockMod:send(Socket, encode_frame(Data, 2)),
|
||||||
Sender ! {data_reply, self()},
|
Sender ! {data_reply, self()},
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
||||||
SocketMode, Shaper);
|
SockMod, Shaper);
|
||||||
{text, Data} ->
|
{text, Data} ->
|
||||||
SocketMode:send(Socket, encode_frame(Data, 1)),
|
SockMod:send(Socket, encode_frame(Data, 1)),
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
||||||
SocketMode, Shaper);
|
SockMod, Shaper);
|
||||||
{data, Data} ->
|
{data, Data} ->
|
||||||
SocketMode:send(Socket, encode_frame(Data, 2)),
|
SockMod:send(Socket, encode_frame(Data, 2)),
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
||||||
SocketMode, Shaper);
|
SockMod, Shaper);
|
||||||
{ping, Data} ->
|
{ping, Data} ->
|
||||||
SocketMode:send(Socket, encode_frame(Data, 9)),
|
SockMod:send(Socket, encode_frame(Data, 9)),
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
||||||
SocketMode, Shaper);
|
SockMod, Shaper);
|
||||||
shutdown ->
|
shutdown ->
|
||||||
?DEBUG("Shutdown request received, closing websocket "
|
?DEBUG("Shutdown request received, closing websocket "
|
||||||
"with pid ~p",
|
"with pid ~p",
|
||||||
[self()]),
|
[self()]),
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, 1001); % going away
|
websocket_close(Socket, WsHandleLoopPid, SockMod, 1001); % going away
|
||||||
_Ignored ->
|
_Ignored ->
|
||||||
?WARNING_MSG("Received unexpected message, ignoring: ~p",
|
?WARNING_MSG("Received unexpected message, ignoring: ~p",
|
||||||
[_Ignored]),
|
[_Ignored]),
|
||||||
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
ws_loop(FrameInfo, Socket, WsHandleLoopPid,
|
||||||
SocketMode, Shaper)
|
SockMod, Shaper)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
encode_frame(Data, Opcode) ->
|
encode_frame(Data, Opcode) ->
|
||||||
@ -421,7 +421,7 @@ handle_data(tcp, FrameInfo, Data, Socket, WsHandleLoopPid, fast_tls, Shaper) ->
|
|||||||
handle_data(_, FrameInfo, Data, Socket, WsHandleLoopPid, SockMod, Shaper) ->
|
handle_data(_, FrameInfo, Data, Socket, WsHandleLoopPid, SockMod, Shaper) ->
|
||||||
handle_data_int(FrameInfo, Data, Socket, WsHandleLoopPid, SockMod, Shaper).
|
handle_data_int(FrameInfo, Data, Socket, WsHandleLoopPid, SockMod, Shaper).
|
||||||
|
|
||||||
handle_data_int(FrameInfo, Data, Socket, WsHandleLoopPid, SocketMode, Shaper) ->
|
handle_data_int(FrameInfo, Data, Socket, WsHandleLoopPid, SockMod, Shaper) ->
|
||||||
{NewFrameInfo, Recv, Send} = process_frame(FrameInfo, Data),
|
{NewFrameInfo, Recv, Send} = process_frame(FrameInfo, Data),
|
||||||
lists:foreach(fun (El) ->
|
lists:foreach(fun (El) ->
|
||||||
case El of
|
case El of
|
||||||
@ -434,27 +434,27 @@ handle_data_int(FrameInfo, Data, Socket, WsHandleLoopPid, SocketMode, Shaper) ->
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
Recv),
|
Recv),
|
||||||
{NewFrameInfo, Send, handle_shaping(Data, Socket, SocketMode, Shaper)}.
|
{NewFrameInfo, Send, handle_shaping(Data, Socket, SockMod, Shaper)}.
|
||||||
|
|
||||||
websocket_close(Socket, WsHandleLoopPid,
|
websocket_close(Socket, WsHandleLoopPid,
|
||||||
SocketMode, CloseCode) when CloseCode > 0 ->
|
SockMod, CloseCode) when CloseCode > 0 ->
|
||||||
Frame = encode_frame(<<CloseCode:16/integer-big>>, 8),
|
Frame = encode_frame(<<CloseCode:16/integer-big>>, 8),
|
||||||
SocketMode:send(Socket, Frame),
|
SockMod:send(Socket, Frame),
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, 0);
|
websocket_close(Socket, WsHandleLoopPid, SockMod, 0);
|
||||||
websocket_close(Socket, WsHandleLoopPid, SocketMode, _CloseCode) ->
|
websocket_close(Socket, WsHandleLoopPid, SockMod, _CloseCode) ->
|
||||||
WsHandleLoopPid ! closed,
|
WsHandleLoopPid ! closed,
|
||||||
SocketMode:close(Socket).
|
SockMod:close(Socket).
|
||||||
|
|
||||||
get_origin() ->
|
get_origin() ->
|
||||||
ejabberd_option:websocket_origin().
|
ejabberd_option:websocket_origin().
|
||||||
|
|
||||||
handle_shaping(_Data, _Socket, _SocketMode, none) ->
|
handle_shaping(_Data, _Socket, _SockMod, none) ->
|
||||||
none;
|
none;
|
||||||
handle_shaping(Data, Socket, SocketMode, Shaper) ->
|
handle_shaping(Data, Socket, SockMod, Shaper) ->
|
||||||
{NewShaper, Pause} = ejabberd_shaper:update(Shaper, byte_size(Data)),
|
{NewShaper, Pause} = ejabberd_shaper:update(Shaper, byte_size(Data)),
|
||||||
if Pause > 0 ->
|
if Pause > 0 ->
|
||||||
activate_after(Socket, self(), Pause);
|
activate_after(Socket, self(), Pause);
|
||||||
true -> activate(Socket, SocketMode, once)
|
true -> activate(Socket, SockMod, once)
|
||||||
end,
|
end,
|
||||||
NewShaper.
|
NewShaper.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user