diff --git a/ChangeLog b/ChangeLog index fbf66da51..6319f4a9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2003-10-29 Alexey Shchepin + + * 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 * src/ejabberd_listener.erl: Added handling of accept errors, diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 66e0eb146..8da15d261 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -101,7 +101,8 @@ start_link(SockData, Opts) -> %% {stop, StopReason} %%---------------------------------------------------------------------- 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 {value, {_, A}} -> A; _ -> all @@ -618,7 +619,8 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> process_presence_probe(From, To, StateData), {false, Attrs, StateData}; "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}}; "invisible" -> 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) -> - case SockMod:recv(Socket, 0, Timeout) of + case catch SockMod:recv(Socket, 0, Timeout) of {ok, Text} -> ShaperSt1 = receive {change_shaper, Shaper} -> @@ -799,6 +801,12 @@ receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) -> {error, Reason} -> exit(XMLStreamPid, 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 end. diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index ea04765eb..7285a22b0 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -94,7 +94,8 @@ accept_ssl(ListenSocket, Module, Opts) -> _ -> ok end, - Module:start_link({ssl, Socket}, Opts), + {ok, Pid} = Module:start({ssl, Socket}, Opts), + ssl:controlling_process(Socket, Pid), accept_ssl(ListenSocket, Module, Opts); {error, timeout} -> accept_ssl(ListenSocket, Module, Opts); diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 039389a02..32f2ea02f 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -39,7 +39,8 @@ loop(State) -> {route, From, To, Packet} -> case catch do_route(State, From, To, Packet) of {'EXIT', Reason} -> - ?ERROR_MSG("~p", [Reason]); + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); _ -> ok end, diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 1c7b1fba6..5bbd030d4 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -50,7 +50,8 @@ loop() -> {route, From, To, Packet} -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> - ?ERROR_MSG("~p", [Reason]); + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); _ -> ok end, diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 29358402b..6e31a7469 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -117,7 +117,7 @@ get_key(FromTo) -> [E] -> E#s2s.key; _ -> - "" + error end. try_register(FromTo) -> diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 9dc176462..170adbbc5 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -18,8 +18,6 @@ %% gen_fsm callbacks -export([init/1, wait_for_stream/2, - wait_for_key/2, - wait_for_verification/2, stream_established/2, handle_event/3, handle_sync_event/4, @@ -30,8 +28,11 @@ -include("ejabberd.hrl"). -include("jlib.hrl"). +-define(DICT, dict). + -record(state, {socket, receiver, streamid, - myname, server, queue}). + connections = ?DICT:new()}). + %-define(DBGFSM, true). @@ -67,7 +68,7 @@ start(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). %%%---------------------------------------------------------------------- @@ -87,8 +88,7 @@ init([{SockMod, Socket}]) -> {ok, wait_for_stream, #state{socket = Socket, receiver = ReceiverPid, - streamid = new_id(), - queue = queue:new()}, + streamid = new_id()}, ?S2STIMEOUT}. %%---------------------------------------------------------------------- @@ -98,23 +98,12 @@ init([{SockMod, Socket}]) -> %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- -wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> +wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> % TODO case {xml:get_attr_s("xmlns", Attrs), xml:get_attr_s("xmlns:db", Attrs)} of {"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), - {next_state, wait_for_key, - StateData#state{myname = Me}, ?S2STIMEOUT}; - _ -> - send_text(StateData#state.socket, ?HOST_UNKNOWN_ERR), - {stop, normal, StateData} - end; + send_text(StateData#state.socket, ?STREAM_HEADER), + {next_state, stream_established, StateData#state{}, ?S2STIMEOUT}; _ -> send_text(StateData#state.socket, ?INVALID_NAMESPACE_ERR), {stop, normal, StateData} @@ -131,20 +120,22 @@ wait_for_stream(timeout, StateData) -> wait_for_stream(closed, StateData) -> {stop, normal, StateData}. - -wait_for_key({xmlstreamelement, El}, StateData) -> +stream_established({xmlstreamelement, El}, StateData) -> case is_key_packet(El) of {key, 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 -> ejabberd_s2s_out:start(To, From, {verify, self(), Key, StateData#state.streamid}), + Conns = ?DICT:store({LFrom, LTo}, wait_for_verification, + StateData#state.connections), {next_state, - wait_for_verification, - StateData#state{myname = To, - server = From}, + stream_established, + StateData#state{connections = Conns}, ?S2STIMEOUT}; _ -> send_text(StateData#state.socket, ?HOST_UNKNOWN_ERR), @@ -152,143 +143,81 @@ wait_for_key({xmlstreamelement, El}, StateData) -> end; {verify, 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"; true -> "invalid" end, send_element(StateData#state.socket, {xmlelement, "db:verify", - [{"from", StateData#state.myname}, + [{"from", To}, {"to", From}, {"id", Id}, {"type", Type}], []}), {next_state, wait_for_key, StateData, ?S2STIMEOUT}; _ -> - {next_state, wait_for_key, StateData, ?S2STIMEOUT} - end; - -wait_for_key({xmlstreamend, Name}, StateData) -> - {stop, normal, StateData}; - -wait_for_key({xmlstreamerror, _}, StateData) -> - send_text(StateData#state.socket, - ?STREAM_HEADER ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER), - {stop, normal, StateData}; - -wait_for_key(timeout, StateData) -> - {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 - (Name == "message") or - (Name == "presence")) and - (ToJID /= error) and (FromJID /= error) -> - ejabberd_router:route(FromJID, ToJID, El); - true -> + {xmlelement, Name, Attrs, _Els} = El, + From_s = xml:get_attr_s("from", Attrs), + From = jlib:string_to_jid(From_s), + To_s = xml:get_attr_s("to", Attrs), + To = jlib:string_to_jid(To_s), + if + (To /= error) and (From /= error) -> + LFrom = From#jid.lserver, + LTo = To#jid.lserver, + case ?DICT:find({LFrom, LTo}, + StateData#state.connections) of + {ok, established} -> + if ((Name == "iq") or + (Name == "message") or + (Name == "presence")) -> + ejabberd_router:route(From, To, El); + true -> + error + end; + _ -> + error + end; + true -> error end end, {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}; stream_established({xmlstreamerror, _}, StateData) -> @@ -323,7 +252,7 @@ stream_established(closed, StateData) -> %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- -handle_event(Event, StateName, StateData) -> +handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData, ?S2STIMEOUT}. %%---------------------------------------------------------------------- @@ -335,11 +264,11 @@ handle_event(Event, StateName, StateData) -> %% {stop, Reason, NewStateData} | %% {stop, Reason, Reply, NewStateData} %%---------------------------------------------------------------------- -handle_sync_event(Event, From, StateName, StateData) -> +handle_sync_event(_Event, _From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData}. -code_change(OldVsn, StateName, StateData, Extra) -> +code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. %%---------------------------------------------------------------------- @@ -351,15 +280,8 @@ code_change(OldVsn, StateName, StateData, Extra) -> handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData#state.socket, Text), {next_state, StateName, StateData}; -handle_info({send_element, El}, StateName, StateData) -> - case StateName of - 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. +handle_info(_, StateName, StateData) -> + {next_state, StateName, StateData}. %%---------------------------------------------------------------------- @@ -367,7 +289,7 @@ handle_info({send_element, El}, StateName, StateData) -> %% Purpose: Shutdown the fsm %% Returns: any %%---------------------------------------------------------------------- -terminate(Reason, StateName, StateData) -> +terminate(Reason, _StateName, StateData) -> % case StateData#state.user of % "" -> % ok; @@ -393,7 +315,7 @@ receiver(Socket, C2SPid, XMLStreamPid) -> {ok, Text} -> xml_stream:send_text(XMLStreamPid, Text), receiver(Socket, C2SPid, XMLStreamPid); - {error, Reason} -> + {error, _Reason} -> exit(XMLStreamPid, closed), gen_fsm:send_event(C2SPid, closed), ok @@ -405,14 +327,6 @@ send_text(Socket, Text) -> send_element(Socket, 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() -> diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 90faf4c55..da2c93c50 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -113,8 +113,7 @@ open_socket(init, StateData) -> {error, Reason1} -> ?DEBUG("s2s_out: connect return ~p~n", [Reason1]), gen_tcp:connect(Addr, Port, - [binary, {packet, 0}, - {tcp_module, inet6_tcp}]) + [binary, {packet, 0}, inet6]) end, case Res of {ok, Socket} -> @@ -215,9 +214,15 @@ wait_for_validation({xmlstreamelement, El}, StateData) -> {Pid, _Key, _SID} -> case Type of "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, {stop, normal, StateData} end; @@ -249,9 +254,15 @@ stream_established({xmlstreamelement, El}, StateData) -> {VPid, _VKey, _SID} -> case VType of "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; _ -> ok diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 9494fa12e..af446d829 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -56,7 +56,8 @@ loop() -> {route, From, To, Packet} -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> - ?ERROR_MSG("~p", [Reason]); + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); _ -> ok end,