From a704f9760d4b8e3445276e08166fed58c935b18c Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Sat, 18 Oct 2003 19:15:12 +0000 Subject: [PATCH] * src/ejabberd_service.erl: Added supports for multiple hosts per service * src/Makefile.in: Minor fix SVN Revision: 153 --- ChangeLog | 7 +++ src/Makefile.in | 4 +- src/ejabberd_app.erl | 5 +- src/ejabberd_service.erl | 113 +++++++++++++++++++++++---------------- 4 files changed, 78 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index f778c613e..68a913c1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2003-10-18 Alexey Shchepin + + * src/ejabberd_service.erl: Added supports for multiple hosts per + service + + * src/Makefile.in: Minor fix + 2003-10-17 Alexey Shchepin * src/configure.ac: Build system now done using autoconf (thanks diff --git a/src/Makefile.in b/src/Makefile.in index dd33721fc..cf9e461f8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -30,9 +30,10 @@ mostlyclean-recursive maintainer-clean-recursive: done -$(ERLSHLIBS): ../%.so: %.c +$(ERLSHLIBS): %.so: %.c gcc -Wall $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LIBDIRS) \ $(subst ../,,$(subst .so,.c,$@)) \ + -lexpat \ -lerl_interface \ -lei \ -o $@ -fpic -shared \ @@ -44,4 +45,3 @@ TAGS: etags *.erl Makefile: Makefile.in - \ No newline at end of file diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 535c9d7e0..c4908c73b 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -18,7 +18,7 @@ -include("ejabberd.hrl"). -start(normal, Args) -> +start(normal, _Args) -> application:start(sasl), randoms:start(), db_init(), @@ -33,6 +33,7 @@ start(normal, Args) -> % Profiling %eprof:start(), %eprof:profile([self()]), + %fprof:trace(start, "/tmp/fprof"), Sup = ejabberd_sup:start_link(), start(), load_modules(), @@ -40,7 +41,7 @@ start(normal, Args) -> start(_, _) -> {error, badarg}. -stop(StartArgs) -> +stop(_StartArgs) -> ok. start() -> diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index cc73bf221..21b2c5851 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -13,7 +13,7 @@ -behaviour(gen_fsm). %% External exports --export([start/2, start_link/2, receiver/2, send_text/2, send_element/2]). +-export([start/2, start_link/2, receiver/3, send_text/2, send_element/2]). %% gen_fsm callbacks -export([init/1, @@ -29,8 +29,8 @@ -include("ejabberd.hrl"). -include("jlib.hrl"). --record(state, {socket, receiver, streamid, - host, password}). +-record(state, {socket, receiver, streamid, sockmod, + hosts, password}). %-define(DBGFSM, true). @@ -87,25 +87,37 @@ start_link(SockData, Opts) -> %% {stop, StopReason} %%---------------------------------------------------------------------- init([{SockMod, Socket}, Opts]) -> - {Host, Password} = - case lists:keysearch(host, 1, Opts) of - {value, {_, H, HOpts}} -> + {Hosts, Password} = + case lists:keysearch(hosts, 1, Opts) of + {value, {_, Hs, HOpts}} -> case lists:keysearch(password, 1, HOpts) of {value, {_, P}} -> - {H, P}; + {Hs, P}; _ -> % TODO: generate error false end; _ -> - % TODO: generate error - false + case lists:keysearch(host, 1, Opts) of + {value, {_, H, HOpts}} -> + case lists:keysearch(password, 1, HOpts) of + {value, {_, P}} -> + {[H], P}; + _ -> + % TODO: generate error + false + end; + _ -> + % TODO: generate error + false + end end, - ReceiverPid = spawn(?MODULE, receiver, [Socket, self()]), + ReceiverPid = spawn(?MODULE, receiver, [Socket, SockMod, self()]), {ok, wait_for_stream, #state{socket = Socket, receiver = ReceiverPid, streamid = new_id(), - host = Host, + sockmod = SockMod, + hosts = Hosts, password = Password }}. @@ -118,23 +130,23 @@ init([{SockMod, Socket}, Opts]) -> %state_name(Event, StateData) -> % {next_state, state_name, StateData}. -wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) -> +wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> % TODO case xml:get_attr_s("xmlns", Attrs) of "jabber:component:accept" -> Header = io_lib:format(?STREAM_HEADER, [StateData#state.streamid, ?MYNAME]), - send_text(StateData#state.socket, Header), + send_text(StateData, Header), {next_state, wait_for_handshake, StateData}; _ -> - send_text(StateData#state.socket, ?INVALID_HEADER_ERR), + send_text(StateData, ?INVALID_HEADER_ERR), {stop, normal, StateData} end; wait_for_stream({xmlstreamerror, _}, StateData) -> Header = io_lib:format(?STREAM_HEADER, ["none", ?MYNAME]), - send_text(StateData#state.socket, + send_text(StateData, Header ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER), {stop, normal, StateData}; @@ -143,28 +155,31 @@ wait_for_stream(closed, StateData) -> wait_for_handshake({xmlstreamelement, El}, StateData) -> - {xmlelement, Name, Attrs, Els} = El, + {xmlelement, Name, _Attrs, Els} = El, case {Name, xml:get_cdata(Els)} of {"handshake", Digest} -> case sha:sha(StateData#state.streamid ++ StateData#state.password) of Digest -> - send_text(StateData#state.socket, ""), - ejabberd_router:register_local_route(StateData#state.host), + send_text(StateData, ""), + lists:foreach( + fun(H) -> + ejabberd_router:register_local_route(H) + end, StateData#state.hosts), {next_state, stream_established, StateData}; _ -> - send_text(StateData#state.socket, ?INVALID_HEADER_ERR), + send_text(StateData, ?INVALID_HEADER_ERR), {stop, normal, StateData} end; _ -> {next_state, wait_for_key, StateData} end; -wait_for_handshake({xmlstreamend, Name}, StateData) -> +wait_for_handshake({xmlstreamend, _Name}, StateData) -> {stop, normal, StateData}; wait_for_handshake({xmlstreamerror, _}, StateData) -> - send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER), + send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER), {stop, normal, StateData}; wait_for_handshake(closed, StateData) -> @@ -172,13 +187,14 @@ wait_for_handshake(closed, StateData) -> stream_established({xmlstreamelement, El}, StateData) -> - {xmlelement, Name, Attrs, Els} = El, + {xmlelement, Name, Attrs, _Els} = El, From = xml:get_attr_s("from", Attrs), FromJID1 = jlib:string_to_jid(From), FromJID = case FromJID1 of - {Node, Server, Resource} -> - if Server == StateData#state.host -> FromJID1; - true -> error + #jid{lserver = Server} -> + case lists:member(Server, StateData#state.hosts) of + true -> FromJID1; + false -> error end; _ -> error end, @@ -194,17 +210,17 @@ stream_established({xmlstreamelement, El}, StateData) -> ejabberd_router:route(FromJID, ToJID, El); true -> Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST), - send_element(StateData#state.socket, Err), + send_element(StateData, Err), error end, {next_state, stream_established, StateData}; -stream_established({xmlstreamend, Name}, StateData) -> +stream_established({xmlstreamend, _Name}, StateData) -> % TODO {stop, normal, StateData}; stream_established({xmlstreamerror, _}, StateData) -> - send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER), + send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER), {stop, normal, StateData}; stream_established(closed, StateData) -> @@ -232,7 +248,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}. %%---------------------------------------------------------------------- @@ -244,11 +260,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}. %%---------------------------------------------------------------------- @@ -258,10 +274,10 @@ code_change(OldVsn, StateName, StateData, Extra) -> %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- handle_info({send_text, Text}, StateName, StateData) -> - send_text(StateData#state.socket, Text), + send_text(StateData, Text), {next_state, StateName, StateData}; handle_info({send_element, El}, StateName, StateData) -> - send_element(StateData#state.socket, El), + send_element(StateData, El), {next_state, StateName, StateData}; handle_info({route, From, To, Packet}, StateName, StateData) -> {xmlelement, Name, Attrs, Els} = Packet, @@ -269,7 +285,7 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> jlib:jid_to_string(To), Attrs), Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}), - send_text(StateData#state.socket, Text), + send_text(StateData, Text), {next_state, StateName, StateData}. @@ -278,40 +294,43 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> %% Purpose: Shutdown the fsm %% Returns: any %%---------------------------------------------------------------------- -terminate(Reason, StateName, StateData) -> +terminate(_Reason, StateName, StateData) -> case StateName of stream_established -> - ejabberd_router:unregister_local_route(StateData#state.host); + lists:foreach( + fun(H) -> + ejabberd_router:unregister_local_route(H) + end, StateData#state.hosts); _ -> ok end, - gen_tcp:close(StateData#state.socket), + (StateData#state.sockmod):close(StateData#state.socket), ok. %%%---------------------------------------------------------------------- %%% Internal functions %%%---------------------------------------------------------------------- -receiver(Socket, C2SPid) -> +receiver(Socket, SockMod, C2SPid) -> XMLStreamPid = xml_stream:start(C2SPid), - receiver(Socket, C2SPid, XMLStreamPid). + receiver(Socket, SockMod, C2SPid, XMLStreamPid). -receiver(Socket, C2SPid, XMLStreamPid) -> - case gen_tcp:recv(Socket, 0) of +receiver(Socket, SockMod, C2SPid, XMLStreamPid) -> + case SockMod:recv(Socket, 0) of {ok, Text} -> xml_stream:send_text(XMLStreamPid, Text), - receiver(Socket, C2SPid, XMLStreamPid); - {error, Reason} -> + receiver(Socket, SockMod, C2SPid, XMLStreamPid); + {error, _Reason} -> exit(XMLStreamPid, closed), gen_fsm:send_event(C2SPid, closed), ok end. -send_text(Socket, Text) -> - gen_tcp:send(Socket,Text). +send_text(StateData, Text) -> + (StateData#state.sockmod):send(StateData#state.socket,Text). -send_element(Socket, El) -> - send_text(Socket, xml:element_to_string(El)). +send_element(StateData, El) -> + send_text(StateData, xml:element_to_string(El)). new_id() ->