25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

* src/ejabberd_listener.erl: Fixed starting of SSL connection

* src/ejabberd_s2s_in.erl: Partially rewriten

* src/ejabberd_router.erl: More verbose error report
* src/ejabberd_local.erl: Likewise
* src/ejabberd_sm.erl: Likewise

* src/ejabberd_s2s_out.erl: Updated to be compatible with R9C

* src/ejabberd_c2s.erl: Minor fix

SVN Revision: 164
This commit is contained in:
Alexey Shchepin 2003-10-29 20:09:09 +00:00
parent 188be0dc62
commit 23b3779b20
9 changed files with 133 additions and 182 deletions

View File

@ -1,3 +1,17 @@
2003-10-29 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_listener.erl: Fixed starting of SSL connection
* src/ejabberd_s2s_in.erl: Partially rewriten
* src/ejabberd_router.erl: More verbose error report
* src/ejabberd_local.erl: Likewise
* src/ejabberd_sm.erl: Likewise
* src/ejabberd_s2s_out.erl: Updated to be compatible with R9C
* src/ejabberd_c2s.erl: Minor fix
2003-10-28 Alexey Shchepin <alexey@sevcom.net> 2003-10-28 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_listener.erl: Added handling of accept errors, * src/ejabberd_listener.erl: Added handling of accept errors,

View File

@ -101,7 +101,8 @@ start_link(SockData, Opts) ->
%% {stop, StopReason} %% {stop, StopReason}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
init([{SockMod, Socket}, Opts]) -> init([{SockMod, Socket}, Opts]) ->
ReceiverPid = spawn(?MODULE, receiver, [Socket, SockMod, none, self()]), ReceiverPid = proc_lib:spawn(
?MODULE, receiver, [Socket, SockMod, none, self()]),
Access = case lists:keysearch(access, 1, Opts) of Access = case lists:keysearch(access, 1, Opts) of
{value, {_, A}} -> A; {value, {_, A}} -> A;
_ -> all _ -> all
@ -618,7 +619,8 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
process_presence_probe(From, To, StateData), process_presence_probe(From, To, StateData),
{false, Attrs, StateData}; {false, Attrs, StateData};
"error" -> "error" ->
NewA = remove_element(From, StateData#state.pres_a), NewA = remove_element(jlib:jid_tolower(From),
StateData#state.pres_a),
{true, Attrs, StateData#state{pres_a = NewA}}; {true, Attrs, StateData#state{pres_a = NewA}};
"invisible" -> "invisible" ->
Attrs1 = lists:keydelete("type", 1, Attrs), Attrs1 = lists:keydelete("type", 1, Attrs),
@ -774,7 +776,7 @@ receiver(Socket, SockMod, Shaper, C2SPid) ->
receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout). receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout).
receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) -> receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) ->
case SockMod:recv(Socket, 0, Timeout) of case catch SockMod:recv(Socket, 0, Timeout) of
{ok, Text} -> {ok, Text} ->
ShaperSt1 = receive ShaperSt1 = receive
{change_shaper, Shaper} -> {change_shaper, Shaper} ->
@ -799,6 +801,12 @@ receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) ->
{error, Reason} -> {error, Reason} ->
exit(XMLStreamPid, closed), exit(XMLStreamPid, closed),
gen_fsm:send_event(C2SPid, closed), gen_fsm:send_event(C2SPid, closed),
ok;
{'EXIT', Reason} ->
?ERROR_MSG("(~w) abnormal ~w:recv termination:~n\t~p~n",
[Socket, SockMod, Reason]),
exit(XMLStreamPid, closed),
gen_fsm:send_event(C2SPid, closed),
ok ok
end. end.

View File

@ -94,7 +94,8 @@ accept_ssl(ListenSocket, Module, Opts) ->
_ -> _ ->
ok ok
end, end,
Module:start_link({ssl, Socket}, Opts), {ok, Pid} = Module:start({ssl, Socket}, Opts),
ssl:controlling_process(Socket, Pid),
accept_ssl(ListenSocket, Module, Opts); accept_ssl(ListenSocket, Module, Opts);
{error, timeout} -> {error, timeout} ->
accept_ssl(ListenSocket, Module, Opts); accept_ssl(ListenSocket, Module, Opts);

View File

@ -39,7 +39,8 @@ loop(State) ->
{route, From, To, Packet} -> {route, From, To, Packet} ->
case catch do_route(State, From, To, Packet) of case catch do_route(State, From, To, Packet) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p~nwhen processing: ~p",
[Reason, {From, To, Packet}]);
_ -> _ ->
ok ok
end, end,

View File

@ -50,7 +50,8 @@ loop() ->
{route, From, To, Packet} -> {route, From, To, Packet} ->
case catch do_route(From, To, Packet) of case catch do_route(From, To, Packet) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p~nwhen processing: ~p",
[Reason, {From, To, Packet}]);
_ -> _ ->
ok ok
end, end,

View File

@ -117,7 +117,7 @@ get_key(FromTo) ->
[E] -> [E] ->
E#s2s.key; E#s2s.key;
_ -> _ ->
"" error
end. end.
try_register(FromTo) -> try_register(FromTo) ->

View File

@ -18,8 +18,6 @@
%% gen_fsm callbacks %% gen_fsm callbacks
-export([init/1, -export([init/1,
wait_for_stream/2, wait_for_stream/2,
wait_for_key/2,
wait_for_verification/2,
stream_established/2, stream_established/2,
handle_event/3, handle_event/3,
handle_sync_event/4, handle_sync_event/4,
@ -30,8 +28,11 @@
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
-define(DICT, dict).
-record(state, {socket, receiver, streamid, -record(state, {socket, receiver, streamid,
myname, server, queue}). connections = ?DICT:new()}).
%-define(DBGFSM, true). %-define(DBGFSM, true).
@ -67,7 +68,7 @@
start(SockData, Opts) -> start(SockData, Opts) ->
supervisor:start_child(ejabberd_s2s_in_sup, [SockData, Opts]). supervisor:start_child(ejabberd_s2s_in_sup, [SockData, Opts]).
start_link(SockData, Opts) -> start_link(SockData, _Opts) ->
gen_fsm:start_link(ejabberd_s2s_in, [SockData], ?FSMOPTS). gen_fsm:start_link(ejabberd_s2s_in, [SockData], ?FSMOPTS).
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
@ -87,8 +88,7 @@ init([{SockMod, Socket}]) ->
{ok, wait_for_stream, {ok, wait_for_stream,
#state{socket = Socket, #state{socket = Socket,
receiver = ReceiverPid, receiver = ReceiverPid,
streamid = new_id(), streamid = new_id()},
queue = queue:new()},
?S2STIMEOUT}. ?S2STIMEOUT}.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
@ -98,23 +98,12 @@ init([{SockMod, Socket}]) ->
%% {stop, Reason, NewStateData} %% {stop, Reason, NewStateData}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
% TODO % TODO
case {xml:get_attr_s("xmlns", Attrs), xml:get_attr_s("xmlns:db", Attrs)} of case {xml:get_attr_s("xmlns", Attrs), xml:get_attr_s("xmlns:db", Attrs)} of
{"jabber:server", "jabber:server:dialback"} -> {"jabber:server", "jabber:server:dialback"} ->
Me = case xml:get_attr_s("to", Attrs) of
"" -> ?MYNAME;
Dom -> Dom
end,
case lists:member(Me, ejabberd_router:dirty_get_all_domains()) of
true ->
send_text(StateData#state.socket, ?STREAM_HEADER), send_text(StateData#state.socket, ?STREAM_HEADER),
{next_state, wait_for_key, {next_state, stream_established, StateData#state{}, ?S2STIMEOUT};
StateData#state{myname = Me}, ?S2STIMEOUT};
_ ->
send_text(StateData#state.socket, ?HOST_UNKNOWN_ERR),
{stop, normal, StateData}
end;
_ -> _ ->
send_text(StateData#state.socket, ?INVALID_NAMESPACE_ERR), send_text(StateData#state.socket, ?INVALID_NAMESPACE_ERR),
{stop, normal, StateData} {stop, normal, StateData}
@ -131,20 +120,22 @@ wait_for_stream(timeout, StateData) ->
wait_for_stream(closed, StateData) -> wait_for_stream(closed, StateData) ->
{stop, normal, StateData}. {stop, normal, StateData}.
stream_established({xmlstreamelement, El}, StateData) ->
wait_for_key({xmlstreamelement, El}, StateData) ->
case is_key_packet(El) of case is_key_packet(El) of
{key, To, From, Id, Key} -> {key, To, From, Id, Key} ->
?INFO_MSG("GET KEY: ~p", [{To, From, Id, Key}]), ?INFO_MSG("GET KEY: ~p", [{To, From, Id, Key}]),
case lists:member(To, ejabberd_router:dirty_get_all_domains()) of LTo = jlib:nameprep(To),
LFrom = jlib:nameprep(From),
case lists:member(LTo, ejabberd_router:dirty_get_all_domains()) of
true -> true ->
ejabberd_s2s_out:start(To, From, ejabberd_s2s_out:start(To, From,
{verify, self(), {verify, self(),
Key, StateData#state.streamid}), Key, StateData#state.streamid}),
Conns = ?DICT:store({LFrom, LTo}, wait_for_verification,
StateData#state.connections),
{next_state, {next_state,
wait_for_verification, stream_established,
StateData#state{myname = To, StateData#state{connections = Conns},
server = From},
?S2STIMEOUT}; ?S2STIMEOUT};
_ -> _ ->
send_text(StateData#state.socket, ?HOST_UNKNOWN_ERR), send_text(StateData#state.socket, ?HOST_UNKNOWN_ERR),
@ -152,143 +143,81 @@ wait_for_key({xmlstreamelement, El}, StateData) ->
end; end;
{verify, To, From, Id, Key} -> {verify, To, From, Id, Key} ->
?INFO_MSG("VERIFY KEY: ~p", [{To, From, Id, Key}]), ?INFO_MSG("VERIFY KEY: ~p", [{To, From, Id, Key}]),
Key1 = ejabberd_s2s:get_key({StateData#state.myname, From}), LTo = jlib:nameprep(To),
LFrom = jlib:nameprep(From),
Key1 = ejabberd_s2s:get_key({LTo, LFrom}),
Type = if Key == Key1 -> "valid"; Type = if Key == Key1 -> "valid";
true -> "invalid" true -> "invalid"
end, end,
send_element(StateData#state.socket, send_element(StateData#state.socket,
{xmlelement, {xmlelement,
"db:verify", "db:verify",
[{"from", StateData#state.myname}, [{"from", To},
{"to", From}, {"to", From},
{"id", Id}, {"id", Id},
{"type", Type}], {"type", Type}],
[]}), []}),
{next_state, wait_for_key, StateData, ?S2STIMEOUT}; {next_state, wait_for_key, StateData, ?S2STIMEOUT};
_ -> _ ->
{next_state, wait_for_key, StateData, ?S2STIMEOUT} {xmlelement, Name, Attrs, _Els} = El,
end; From_s = xml:get_attr_s("from", Attrs),
From = jlib:string_to_jid(From_s),
wait_for_key({xmlstreamend, Name}, StateData) -> To_s = xml:get_attr_s("to", Attrs),
{stop, normal, StateData}; To = jlib:string_to_jid(To_s),
if
wait_for_key({xmlstreamerror, _}, StateData) -> (To /= error) and (From /= error) ->
send_text(StateData#state.socket, LFrom = From#jid.lserver,
?STREAM_HEADER ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER), LTo = To#jid.lserver,
{stop, normal, StateData}; case ?DICT:find({LFrom, LTo},
StateData#state.connections) of
wait_for_key(timeout, StateData) -> {ok, established} ->
{stop, normal, StateData};
wait_for_key(closed, StateData) ->
{stop, normal, StateData}.
wait_for_verification(valid, StateData) ->
send_element(StateData#state.socket,
{xmlelement,
"db:result",
[{"from", StateData#state.myname},
{"to", StateData#state.server},
{"type", "valid"}],
[]}),
send_queue(StateData#state.socket, StateData#state.queue),
{next_state, stream_established, StateData, ?S2STIMEOUT};
wait_for_verification(invalid, StateData) ->
send_element(StateData#state.socket,
{xmlelement,
"db:result",
[{"from", StateData#state.myname},
{"to", StateData#state.server},
{"type", "invalid"}],
[]}),
{stop, normal, StateData};
wait_for_verification({xmlstreamelement, El}, StateData) ->
case is_key_packet(El) of
{verify, To, From, Id, Key} ->
?INFO_MSG("VERIFY KEY: ~p", [{To, From, Id, Key}]),
Key1 = ejabberd_s2s:get_key({StateData#state.myname, From}),
Type = if Key == Key1 -> "valid";
true -> "invalid"
end,
send_element(StateData#state.socket,
{xmlelement,
"db:verify",
[{"from", StateData#state.myname},
{"to", From},
{"id", Id},
{"type", Type}],
[]}),
{next_state, wait_for_verification, StateData, ?S2STIMEOUT};
_ ->
{next_state, wait_for_verification, StateData, ?S2STIMEOUT}
end;
wait_for_verification({xmlstreamend, Name}, StateData) ->
{stop, normal, StateData};
wait_for_verification({xmlstreamerror, _}, StateData) ->
send_text(StateData#state.socket,
?STREAM_HEADER ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_verification(timeout, StateData) ->
{stop, normal, StateData};
wait_for_verification(closed, StateData) ->
{stop, normal, StateData}.
stream_established({xmlstreamelement, El}, StateData) ->
{xmlelement, Name, Attrs, Els} = El,
case Name of
"db:verify" ->
case is_key_packet(El) of
{verify, To, From, Id, Key} ->
?INFO_MSG("VERIFY KEY: ~p", [{To, From, Id, Key}]),
Key1 = ejabberd_s2s:get_key({StateData#state.myname,
From}),
Type = if Key == Key1 -> "valid";
true -> "invalid"
end,
send_element(StateData#state.socket,
{xmlelement,
"db:verify",
[{"from", StateData#state.myname},
{"to", From},
{"id", Id},
{"type", Type}],
[]});
_ ->
ok
end;
_ ->
From = xml:get_attr_s("from", Attrs),
FromJID1 = jlib:string_to_jid(From),
FromJID = case FromJID1 of
#jid{lserver = Server} ->
if Server == StateData#state.server -> FromJID1;
true -> error
end;
_ -> error
end,
To = xml:get_attr_s("to", Attrs),
ToJID = case To of
"" -> error;
_ -> jlib:string_to_jid(To)
end,
if ((Name == "iq") or if ((Name == "iq") or
(Name == "message") or (Name == "message") or
(Name == "presence")) and (Name == "presence")) ->
(ToJID /= error) and (FromJID /= error) -> ejabberd_router:route(From, To, El);
ejabberd_router:route(FromJID, ToJID, El); true ->
error
end;
_ ->
error
end;
true -> true ->
error error
end end
end, end,
{next_state, stream_established, StateData, ?S2STIMEOUT}; {next_state, stream_established, StateData, ?S2STIMEOUT};
stream_established({xmlstreamend, Name}, StateData) -> stream_established({valid, From, To}, StateData) ->
send_element(StateData#state.socket,
{xmlelement,
"db:result",
[{"from", To},
{"to", From},
{"type", "valid"}],
[]}),
LFrom = jlib:nameprep(From),
LTo = jlib:nameprep(To),
NSD = StateData#state{
connections = ?DICT:store({LFrom, LTo}, established,
StateData#state.connections)},
{next_state, stream_established, NSD, ?S2STIMEOUT};
stream_established({invalid, From, To}, StateData) ->
send_element(StateData#state.socket,
{xmlelement,
"db:result",
[{"from", To},
{"to", From},
{"type", "invalid"}],
[]}),
LFrom = jlib:nameprep(From),
LTo = jlib:nameprep(To),
NSD = StateData#state{
connections = ?DICT:store({LFrom, LTo}, established,
StateData#state.connections)},
{next_state, stream_established, NSD, ?S2STIMEOUT};
stream_established({xmlstreamend, _Name}, StateData) ->
{stop, normal, StateData}; {stop, normal, StateData};
stream_established({xmlstreamerror, _}, StateData) -> stream_established({xmlstreamerror, _}, StateData) ->
@ -323,7 +252,7 @@ stream_established(closed, StateData) ->
%% {next_state, NextStateName, NextStateData, Timeout} | %% {next_state, NextStateName, NextStateData, Timeout} |
%% {stop, Reason, NewStateData} %% {stop, Reason, NewStateData}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
handle_event(Event, StateName, StateData) -> handle_event(_Event, StateName, StateData) ->
{next_state, StateName, StateData, ?S2STIMEOUT}. {next_state, StateName, StateData, ?S2STIMEOUT}.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
@ -335,11 +264,11 @@ handle_event(Event, StateName, StateData) ->
%% {stop, Reason, NewStateData} | %% {stop, Reason, NewStateData} |
%% {stop, Reason, Reply, NewStateData} %% {stop, Reason, Reply, NewStateData}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
handle_sync_event(Event, From, StateName, StateData) -> handle_sync_event(_Event, _From, StateName, StateData) ->
Reply = ok, Reply = ok,
{reply, Reply, StateName, StateData}. {reply, Reply, StateName, StateData}.
code_change(OldVsn, StateName, StateData, Extra) -> code_change(_OldVsn, StateName, StateData, _Extra) ->
{ok, StateName, StateData}. {ok, StateName, StateData}.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
@ -351,15 +280,8 @@ code_change(OldVsn, StateName, StateData, Extra) ->
handle_info({send_text, Text}, StateName, StateData) -> handle_info({send_text, Text}, StateName, StateData) ->
send_text(StateData#state.socket, Text), send_text(StateData#state.socket, Text),
{next_state, StateName, StateData}; {next_state, StateName, StateData};
handle_info({send_element, El}, StateName, StateData) -> handle_info(_, StateName, StateData) ->
case StateName of {next_state, StateName, StateData}.
stream_established ->
send_element(StateData#state.socket, El),
{next_state, StateName, StateData, ?S2STIMEOUT};
_ ->
Q = queue:in(El, StateData#state.queue),
{next_state, StateName, StateData#state{queue = Q}, ?S2STIMEOUT}
end.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
@ -367,7 +289,7 @@ handle_info({send_element, El}, StateName, StateData) ->
%% Purpose: Shutdown the fsm %% Purpose: Shutdown the fsm
%% Returns: any %% Returns: any
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
terminate(Reason, StateName, StateData) -> terminate(Reason, _StateName, StateData) ->
% case StateData#state.user of % case StateData#state.user of
% "" -> % "" ->
% ok; % ok;
@ -393,7 +315,7 @@ receiver(Socket, C2SPid, XMLStreamPid) ->
{ok, Text} -> {ok, Text} ->
xml_stream:send_text(XMLStreamPid, Text), xml_stream:send_text(XMLStreamPid, Text),
receiver(Socket, C2SPid, XMLStreamPid); receiver(Socket, C2SPid, XMLStreamPid);
{error, Reason} -> {error, _Reason} ->
exit(XMLStreamPid, closed), exit(XMLStreamPid, closed),
gen_fsm:send_event(C2SPid, closed), gen_fsm:send_event(C2SPid, closed),
ok ok
@ -405,14 +327,6 @@ send_text(Socket, Text) ->
send_element(Socket, El) -> send_element(Socket, El) ->
send_text(Socket, xml:element_to_string(El)). send_text(Socket, xml:element_to_string(El)).
send_queue(Socket, Q) ->
case queue:out(Q) of
{{value, El}, Q1} ->
send_element(Socket, El),
send_queue(Socket, Q1);
{empty, Q1} ->
ok
end.
new_id() -> new_id() ->

View File

@ -113,8 +113,7 @@ open_socket(init, StateData) ->
{error, Reason1} -> {error, Reason1} ->
?DEBUG("s2s_out: connect return ~p~n", [Reason1]), ?DEBUG("s2s_out: connect return ~p~n", [Reason1]),
gen_tcp:connect(Addr, Port, gen_tcp:connect(Addr, Port,
[binary, {packet, 0}, [binary, {packet, 0}, inet6])
{tcp_module, inet6_tcp}])
end, end,
case Res of case Res of
{ok, Socket} -> {ok, Socket} ->
@ -215,9 +214,15 @@ wait_for_validation({xmlstreamelement, El}, StateData) ->
{Pid, _Key, _SID} -> {Pid, _Key, _SID} ->
case Type of case Type of
"valid" -> "valid" ->
gen_fsm:send_event(Pid, valid); gen_fsm:send_event(
Pid, {valid,
StateData#state.server,
StateData#state.myname});
_ -> _ ->
gen_fsm:send_event(Pid, invalid) gen_fsm:send_event(
Pid, {invalid,
StateData#state.server,
StateData#state.myname})
end, end,
{stop, normal, StateData} {stop, normal, StateData}
end; end;
@ -249,9 +254,15 @@ stream_established({xmlstreamelement, El}, StateData) ->
{VPid, _VKey, _SID} -> {VPid, _VKey, _SID} ->
case VType of case VType of
"valid" -> "valid" ->
gen_fsm:send_event(VPid, valid); gen_fsm:send_event(
VPid, {valid,
StateData#state.server,
StateData#state.myname});
_ -> _ ->
gen_fsm:send_event(VPid, invalid) gen_fsm:send_event(
VPid, {invalid,
StateData#state.server,
StateData#state.myname})
end; end;
_ -> _ ->
ok ok

View File

@ -56,7 +56,8 @@ loop() ->
{route, From, To, Packet} -> {route, From, To, Packet} ->
case catch do_route(From, To, Packet) of case catch do_route(From, To, Packet) of
{'EXIT', Reason} -> {'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]); ?ERROR_MSG("~p~nwhen processing: ~p",
[Reason, {From, To, Packet}]);
_ -> _ ->
ok ok
end, end,