diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd_c2s.erl | 66 | ||||
-rw-r--r-- | src/ejabberd_listener.erl | 13 | ||||
-rw-r--r-- | src/ejabberd_receiver.erl | 28 | ||||
-rw-r--r-- | src/ejabberd_s2s_in.erl | 57 | ||||
-rw-r--r-- | src/ejabberd_s2s_out.erl | 49 | ||||
-rw-r--r-- | src/ejabberd_service.erl | 24 | ||||
-rw-r--r-- | src/ejabberd_socket.erl | 121 | ||||
-rw-r--r-- | src/web/ejabberd_http.erl | 4 |
8 files changed, 148 insertions, 214 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index a9e0d01ef..84c855c30 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -17,7 +17,7 @@ start_link/2, send_text/2, send_element/2, - socket_type/0, + become_controller/1, get_presence/1]). %% gen_fsm callbacks @@ -40,7 +40,8 @@ -define(SETS, gb_sets). --record(state, {socket, +-record(state, {socket, receiver, + sockmod, streamid, sasl_state, access, @@ -99,8 +100,8 @@ start(SockData, Opts) -> start_link(SockData, Opts) -> gen_fsm:start_link(ejabberd_c2s, [SockData, Opts], ?FSMOPTS). -socket_type() -> - xml_stream. +become_controller(Pid) -> + gen_fsm:send_all_state_event(Pid, become_controller). %% Return Username, Resource and presence information get_presence(FsmRef) -> @@ -117,7 +118,7 @@ get_presence(FsmRef) -> %% ignore | %% {stop, StopReason} %%---------------------------------------------------------------------- -init([Socket, Opts]) -> +init([{SockMod, Socket}, Opts]) -> Access = case lists:keysearch(access, 1, Opts) of {value, {_, A}} -> A; _ -> all @@ -126,6 +127,11 @@ init([Socket, Opts]) -> {value, {_, S}} -> S; _ -> none end, + MaxStanzaSize = + case lists:keysearch(max_stanza_size, 1, Opts) of + {value, {_, Size}} -> Size; + _ -> infinity + end, Zlib = lists:member(zlib, Opts), StartTLS = lists:member(starttls, Opts), StartTLSRequired = lists:member(starttls_required, Opts), @@ -134,14 +140,21 @@ init([Socket, Opts]) -> TLSOpts = lists:filter(fun({certfile, _}) -> true; (_) -> false end, Opts), - Socket1 = + {SockMod1, Socket1, ReceiverPid} = if TLSEnabled -> - ejabberd_socket:starttls(Socket, TLSOpts); + {ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts), + RecPid = ejabberd_receiver:start( + TLSSocket, tls, none, MaxStanzaSize), + {tls, TLSSocket, RecPid}; true -> - Socket + RecPid = ejabberd_receiver:start( + Socket, SockMod, none, MaxStanzaSize), + {SockMod, Socket, RecPid} end, {ok, wait_for_stream, #state{socket = Socket1, + sockmod = SockMod1, + receiver = ReceiverPid, zlib = Zlib, tls = TLS, tls_required = StartTLSRequired, @@ -198,8 +211,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> {xmlelement, "mechanism", [], [{xmlcdata, S}]} end, cyrsasl:listmech(Server)), - SockMod = ejabberd_socket:get_sockmod( - StateData#state.socket), + SockMod = StateData#state.sockmod, Zlib = StateData#state.zlib, CompressFeature = case Zlib andalso @@ -453,7 +465,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> TLS = StateData#state.tls, TLSEnabled = StateData#state.tls_enabled, TLSRequired = StateData#state.tls_required, - SockMod = ejabberd_socket:get_sockmod(StateData#state.socket), + SockMod = StateData#state.sockmod, case {xml:get_attr_s("xmlns", Attrs), Name} of {?NS_SASL, "auth"} when not ((SockMod == gen_tcp) and TLSRequired) -> Mech = xml:get_attr_s("mechanism", Attrs), @@ -462,7 +474,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> Mech, ClientIn) of {ok, Props} -> - ejabberd_socket:reset_stream(StateData#state.socket), + ejabberd_receiver:reset_stream(StateData#state.receiver), send_element(StateData, {xmlelement, "success", [{"xmlns", ?NS_SASL}], []}), @@ -492,6 +504,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> {?NS_TLS, "starttls"} when TLS == true, TLSEnabled == false, SockMod == gen_tcp -> + Socket = StateData#state.socket, TLSOpts = case ejabberd_config:get_local_option( {domain_certfile, StateData#state.server}) of undefined -> @@ -501,12 +514,13 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> lists:keydelete( certfile, 1, StateData#state.tls_options)] end, - Socket = StateData#state.socket, - TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts), + {ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts), + ejabberd_receiver:starttls(StateData#state.receiver, TLSSocket), send_element(StateData, {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}), {next_state, wait_for_stream, - StateData#state{socket = TLSSocket, + StateData#state{sockmod = tls, + socket = TLSSocket, streamid = new_id(), tls_enabled = true }}; @@ -523,12 +537,16 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> case xml:get_tag_cdata(Method) of "zlib" -> Socket = StateData#state.socket, - ZlibSocket = ejabberd_socket:compress(Socket), + {ok, ZlibSocket} = ejabberd_zlib:enable_zlib(SockMod, + Socket), + ejabberd_receiver:compress(StateData#state.receiver, + ZlibSocket), send_element(StateData, {xmlelement, "compressed", [{"xmlns", ?NS_COMPRESS}], []}), {next_state, wait_for_stream, - StateData#state{socket = ZlibSocket, + StateData#state{sockmod = ejabberd_zlib, + socket = ZlibSocket, streamid = new_id() }}; _ -> @@ -575,7 +593,7 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) -> case cyrsasl:server_step(StateData#state.sasl_state, ClientIn) of {ok, Props} -> - ejabberd_socket:reset_stream(StateData#state.socket), + ejabberd_receiver:reset_stream(StateData#state.receiver), send_element(StateData, {xmlelement, "success", [{"xmlns", ?NS_SASL}], []}), @@ -841,6 +859,12 @@ session_established(closed, StateData) -> %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- +handle_event(become_controller, StateName, StateData) -> + ok = (StateData#state.sockmod):controlling_process( + StateData#state.socket, + StateData#state.receiver), + ejabberd_receiver:become_controller(StateData#state.receiver), + {next_state, StateName, StateData}; handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. @@ -1167,7 +1191,7 @@ terminate(_Reason, StateName, StateData) -> _ -> ok end, - ejabberd_socket:close(StateData#state.socket), + ejabberd_receiver:close(StateData#state.receiver), ok. %%%---------------------------------------------------------------------- @@ -1177,11 +1201,11 @@ terminate(_Reason, StateName, StateData) -> change_shaper(StateData, JID) -> Shaper = acl:match_rule(StateData#state.server, StateData#state.shaper, JID), - ejabberd_socket:change_shaper(StateData#state.socket, Shaper). + ejabberd_receiver:change_shaper(StateData#state.receiver, Shaper). send_text(StateData, Text) -> ?DEBUG("Send XML on stream = ~p", [lists:flatten(Text)]), - ejabberd_socket:send(StateData#state.socket, Text). + catch (StateData#state.sockmod):send(StateData#state.socket, Text). send_element(StateData, El) -> send_text(StateData, xml:element_to_string(El)). diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 8bc168421..d387de7d4 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -92,13 +92,14 @@ accept(ListenSocket, Module, Opts) -> _ -> ok end, - case Module of - ejabberd_http -> - {ok, Pid} = Module:start({gen_tcp, Socket}, Opts), - catch gen_tcp:controlling_process(Socket, Pid); - _ -> - ejabberd_socket:start(Module, gen_tcp, Socket, Opts) + {ok, Pid} = Module:start({gen_tcp, Socket}, Opts), + case gen_tcp:controlling_process(Socket, Pid) of + ok -> + ok; + {error, _Reason} -> + gen_tcp:close(Socket) end, + Module:become_controller(Pid), accept(ListenSocket, Module, Opts); {error, Reason} -> ?INFO_MSG("(~w) Failed TCP accept: ~w", diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index dfa03fd4e..9591bd9c0 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -13,14 +13,14 @@ -behaviour(gen_server). %% API --export([start_link/4, +-export([start_link/5, start/3, start/4, change_shaper/2, reset_stream/1, starttls/2, compress/2, - become_controller/2, + become_controller/1, close/1]). %% gen_server callbacks @@ -44,9 +44,9 @@ %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- -start_link(Socket, SockMod, Shaper, MaxStanzaSize) -> +start_link(Socket, SockMod, Shaper, MaxStanzaSize, C2SPid) -> gen_server:start_link( - ?MODULE, [Socket, SockMod, Shaper, MaxStanzaSize], []). + ?MODULE, [Socket, SockMod, Shaper, MaxStanzaSize, C2SPid], []). %%-------------------------------------------------------------------- %% Function: start() -> {ok,Pid} | ignore | {error,Error} @@ -58,7 +58,7 @@ start(Socket, SockMod, Shaper) -> start(Socket, SockMod, Shaper, MaxStanzaSize) -> {ok, Pid} = supervisor:start_child( ejabberd_receiver_sup, - [Socket, SockMod, Shaper, MaxStanzaSize]), + [Socket, SockMod, Shaper, MaxStanzaSize, self()]), Pid. change_shaper(Pid, Shaper) -> @@ -73,8 +73,8 @@ starttls(Pid, TLSSocket) -> compress(Pid, ZlibSocket) -> gen_server:call(Pid, {compress, ZlibSocket}). -become_controller(Pid, C2SPid) -> - gen_server:call(Pid, {become_controller, C2SPid}). +become_controller(Pid) -> + gen_server:call(Pid, become_controller). close(Pid) -> gen_server:cast(Pid, close). @@ -90,7 +90,8 @@ close(Pid) -> %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- -init([Socket, SockMod, Shaper, MaxStanzaSize]) -> +init([Socket, SockMod, Shaper, MaxStanzaSize, C2SPid]) -> + XMLStreamState = xml_stream:new(C2SPid, MaxStanzaSize), ShaperState = shaper:new(Shaper), Timeout = case SockMod of ssl -> @@ -101,7 +102,9 @@ init([Socket, SockMod, Shaper, MaxStanzaSize]) -> {ok, #state{socket = Socket, sock_mod = SockMod, shaper_state = ShaperState, + c2s_pid = C2SPid, max_stanza_size = MaxStanzaSize, + xml_stream_state = XMLStreamState, timeout = Timeout}}. %%-------------------------------------------------------------------- @@ -151,13 +154,10 @@ handle_call(reset_stream, _From, NewXMLStreamState = xml_stream:new(C2SPid, MaxStanzaSize), Reply = ok, {reply, Reply, State#state{xml_stream_state = NewXMLStreamState}}; -handle_call({become_controller, C2SPid}, _From, State) -> - XMLStreamState = xml_stream:new(C2SPid, State#state.max_stanza_size), - NewState = State#state{c2s_pid = C2SPid, - xml_stream_state = XMLStreamState}, - activate_socket(NewState), +handle_call(become_controller, _From, State) -> + activate_socket(State), Reply = ok, - {reply, Reply, NewState}; + {reply, Reply, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 64a85fc1c..725421d1d 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -14,8 +14,8 @@ %% External exports -export([start/2, start_link/2, - match_domain/2, - socket_type/0]). + become_controller/1, + match_domain/2]). %% gen_fsm callbacks -export([init/1, @@ -37,6 +37,8 @@ -define(DICT, dict). -record(state, {socket, + sockmod, + receiver, streamid, shaper, tls = false, @@ -85,8 +87,8 @@ start(SockData, Opts) -> start_link(SockData, Opts) -> gen_fsm:start_link(ejabberd_s2s_in, [SockData, Opts], ?FSMOPTS). -socket_type() -> - xml_stream. +become_controller(Pid) -> + gen_fsm:send_all_state_event(Pid, become_controller). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm @@ -99,12 +101,19 @@ socket_type() -> %% ignore | %% {stop, StopReason} %%---------------------------------------------------------------------- -init([Socket, Opts]) -> - ?INFO_MSG("started: ~p", [Socket]), +init([{SockMod, Socket}, Opts]) -> + ?INFO_MSG("started: ~p", [{SockMod, Socket}]), Shaper = case lists:keysearch(shaper, 1, Opts) of {value, {_, S}} -> S; _ -> none end, + MaxStanzaSize = + case lists:keysearch(max_stanza_size, 1, Opts) of + {value, {_, Size}} -> Size; + _ -> infinity + end, + ReceiverPid = ejabberd_receiver:start( + Socket, SockMod, none, MaxStanzaSize), StartTLS = case ejabberd_config:get_local_option(s2s_use_starttls) of undefined -> false; @@ -120,6 +129,8 @@ init([Socket, Opts]) -> Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, wait_for_stream, #state{socket = Socket, + sockmod = SockMod, + receiver = ReceiverPid, streamid = new_id(), shaper = Shaper, tls = StartTLS, @@ -144,10 +155,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> SASL = if StateData#state.tls_enabled -> - case ejabberd_socket:get_peer_certificate( - StateData#state.socket) of + case tls:get_peer_certificate(StateData#state.socket) of {ok, _Cert} -> - case ejabberd_socket:get_verify_result( + case tls:get_verify_result( StateData#state.socket) of 0 -> [{xmlelement, "mechanisms", @@ -204,7 +214,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> {xmlelement, Name, Attrs, Els} = El, TLS = StateData#state.tls, TLSEnabled = StateData#state.tls_enabled, - SockMod = ejabberd_socket:get_sockmod(StateData#state.socket), + SockMod = StateData#state.sockmod, case {xml:get_attr_s("xmlns", Attrs), Name} of {?NS_TLS, "starttls"} when TLS == true, TLSEnabled == false, @@ -212,11 +222,13 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> ?INFO_MSG("starttls", []), Socket = StateData#state.socket, TLSOpts = StateData#state.tls_options, - TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts), + {ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts), + ejabberd_receiver:starttls(StateData#state.receiver, TLSSocket), send_element(StateData, {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}), {next_state, wait_for_stream, - StateData#state{socket = TLSSocket, + StateData#state{sockmod = tls, + socket = TLSSocket, streamid = new_id(), tls_enabled = true }}; @@ -227,10 +239,9 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> Auth = jlib:decode_base64(xml:get_cdata(Els)), AuthDomain = jlib:nameprep(Auth), AuthRes = - case ejabberd_socket:get_peer_certificate( - StateData#state.socket) of + case tls:get_peer_certificate(StateData#state.socket) of {ok, Cert} -> - case ejabberd_socket:get_verify_result( + case tls:get_verify_result( StateData#state.socket) of 0 -> case AuthDomain of @@ -256,8 +267,8 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> end, if AuthRes -> - ejabberd_socket:reset_stream( - StateData#state.socket), + ejabberd_receiver:reset_stream( + StateData#state.receiver), send_element(StateData, {xmlelement, "success", [{"xmlns", ?NS_SASL}], []}), @@ -456,6 +467,12 @@ stream_established(closed, StateData) -> %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- +handle_event(become_controller, StateName, StateData) -> + ok = (StateData#state.sockmod):controlling_process( + StateData#state.socket, + StateData#state.receiver), + ejabberd_receiver:become_controller(StateData#state.receiver), + {next_state, StateName, StateData}; handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. @@ -500,7 +517,7 @@ handle_info(_, StateName, StateData) -> %%---------------------------------------------------------------------- terminate(Reason, _StateName, StateData) -> ?INFO_MSG("terminated: ~p", [Reason]), - ejabberd_socket:close(StateData#state.socket), + ejabberd_receiver:close(StateData#state.receiver), ok. %%%---------------------------------------------------------------------- @@ -508,7 +525,7 @@ terminate(Reason, _StateName, StateData) -> %%%---------------------------------------------------------------------- send_text(StateData, Text) -> - ejabberd_socket:send(StateData#state.socket, Text). + (StateData#state.sockmod):send(StateData#state.socket, Text). send_element(StateData, El) -> send_text(StateData, xml:element_to_string(El)). @@ -516,7 +533,7 @@ send_element(StateData, El) -> change_shaper(StateData, Host, JID) -> Shaper = acl:match_rule(Host, StateData#state.shaper, JID), - ejabberd_socket:change_shaper(StateData#state.socket, Shaper). + ejabberd_receiver:change_shaper(StateData#state.receiver, Shaper). new_id() -> diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 80fa78baf..358abf5a3 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -36,7 +36,8 @@ -include("ejabberd.hrl"). -include("jlib.hrl"). --record(state, {socket, +-record(state, {socket, receiver, + sockmod, streamid, use_v10, tls = false, @@ -151,6 +152,9 @@ open_socket(init, StateData) -> end end, {error, badarg}, AddrList) of {ok, Socket} -> + ReceiverPid = ejabberd_receiver:start(Socket, gen_tcp, none), + ok = gen_tcp:controlling_process(Socket, ReceiverPid), + ejabberd_receiver:become_controller(ReceiverPid), Version = if StateData#state.use_v10 -> " version='1.0'"; @@ -158,7 +162,9 @@ open_socket(init, StateData) -> "" end, NewStateData = StateData#state{socket = Socket, + sockmod = gen_tcp, tls_enabled = false, + receiver = ReceiverPid, streamid = new_id()}, send_text(NewStateData, io_lib:format(?STREAM_HEADER, [StateData#state.server, @@ -178,23 +184,20 @@ open_socket1(Addr, Port) -> false -> {error, badarg}; ASCIIAddr -> ?DEBUG("s2s_out: connecting to ~s:~p~n", [ASCIIAddr, Port]), - case catch ejabberd_socket:connect( - ASCIIAddr, Port, - [binary, {packet, 0}, - {active, false}]) of + case catch gen_tcp:connect(ASCIIAddr, Port, + [binary, {packet, 0}, + {active, false}]) of {ok, _Socket} = R -> R; {error, Reason1} -> ?DEBUG("s2s_out: connect return ~p~n", [Reason1]), - catch ejabberd_socket:connect( - Addr, Port, - [binary, {packet, 0}, - {active, false}, inet6]); + catch gen_tcp:connect(Addr, Port, + [binary, {packet, 0}, + {active, false}, inet6]); {'EXIT', Reason1} -> ?DEBUG("s2s_out: connect crashed ~p~n", [Reason1]), - catch ejabberd_socket:connect( - Addr, Port, - [binary, {packet, 0}, - {active, false}, inet6]) + catch gen_tcp:connect(Addr, Port, + [binary, {packet, 0}, + {active, false}, inet6]) end end, case Res of @@ -360,7 +363,7 @@ wait_for_features({xmlstreamelement, El}, StateData) -> StartTLSRequired and (not StateData#state.tls) -> ?INFO_MSG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), - ejabberd_socket:close(StateData#state.socket), + ejabberd_receiver:close(StateData#state.receiver), {next_state, reopen_socket, StateData#state{socket = undefined, use_v10 = false}}; @@ -370,7 +373,7 @@ wait_for_features({xmlstreamelement, El}, StateData) -> ?INFO_MSG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), % TODO: clear message queue - ejabberd_socket:close(StateData#state.socket), + ejabberd_receiver:close(StateData#state.receiver), {next_state, reopen_socket, StateData#state{socket = undefined, use_v10 = false}} end; @@ -403,7 +406,8 @@ wait_for_auth_result({xmlstreamelement, El}, StateData) -> ?NS_SASL -> ?INFO_MSG("auth: ~p", [{StateData#state.myname, StateData#state.server}]), - ejabberd_socket:reset_stream(StateData#state.socket), + ejabberd_receiver:reset_stream( + StateData#state.receiver), send_text(StateData, io_lib:format(?STREAM_HEADER, [StateData#state.server, @@ -423,7 +427,7 @@ wait_for_auth_result({xmlstreamelement, El}, StateData) -> ?NS_SASL -> ?INFO_MSG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), - ejabberd_socket:close(StateData#state.socket), + ejabberd_receiver:close(StateData#state.receiver), {next_state, reopen_socket, StateData#state{socket = undefined}}; _ -> @@ -473,8 +477,11 @@ wait_for_starttls_proceed({xmlstreamelement, El}, StateData) -> certfile, 1, StateData#state.tls_options)] end, - TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts), - NewStateData = StateData#state{socket = TLSSocket, + {ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts), + ejabberd_receiver:starttls( + StateData#state.receiver, TLSSocket), + NewStateData = StateData#state{sockmod = tls, + socket = TLSSocket, streamid = new_id(), tls_enabled = true }, @@ -665,7 +672,7 @@ terminate(Reason, StateName, StateData) -> undefined -> ok; _Socket -> - ejabberd_socket:close(StateData#state.socket) + ejabberd_receiver:close(StateData#state.receiver) end, ok. @@ -674,7 +681,7 @@ terminate(Reason, StateName, StateData) -> %%%---------------------------------------------------------------------- send_text(StateData, Text) -> - ejabberd_socket:send(StateData#state.socket, Text). + (StateData#state.sockmod):send(StateData#state.socket, Text). send_element(StateData, El) -> send_text(StateData, xml:element_to_string(El)). diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 925915aa9..551ff436e 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -17,7 +17,7 @@ start_link/2, send_text/2, send_element/2, - socket_type/0]). + become_controller/1]). %% gen_fsm callbacks -export([init/1, @@ -33,7 +33,7 @@ -include("ejabberd.hrl"). -include("jlib.hrl"). --record(state, {socket, streamid, +-record(state, {socket, receiver, streamid, sockmod, hosts, password, access}). %-define(DBGFSM, true). @@ -79,8 +79,8 @@ start(SockData, Opts) -> start_link(SockData, Opts) -> gen_fsm:start_link(ejabberd_service, [SockData, Opts], ?FSMOPTS). -socket_type() -> - xml_stream. +become_controller(Pid) -> + gen_fsm:send_all_state_event(Pid, become_controller). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm @@ -93,7 +93,7 @@ socket_type() -> %% ignore | %% {stop, StopReason} %%---------------------------------------------------------------------- -init([Socket, Opts]) -> +init([{SockMod, Socket}, Opts]) -> Access = case lists:keysearch(access, 1, Opts) of {value, {_, A}} -> A; _ -> all @@ -123,8 +123,11 @@ init([Socket, Opts]) -> false end end, + ReceiverPid = ejabberd_receiver:start(Socket, SockMod, none), {ok, wait_for_stream, #state{socket = Socket, + receiver = ReceiverPid, streamid = new_id(), + sockmod = SockMod, hosts = Hosts, password = Password, access = Access @@ -256,6 +259,12 @@ stream_established(closed, StateData) -> %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- +handle_event(become_controller, StateName, StateData) -> + ok = (StateData#state.sockmod):controlling_process( + StateData#state.socket, + StateData#state.receiver), + ejabberd_receiver:become_controller(StateData#state.receiver), + {next_state, StateName, StateData}; handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. @@ -319,7 +328,7 @@ terminate(Reason, StateName, StateData) -> _ -> ok end, - ejabberd_socket:close(StateData#state.socket), + ejabberd_receiver:close(StateData#state.receiver), ok. %%%---------------------------------------------------------------------- @@ -327,11 +336,12 @@ terminate(Reason, StateName, StateData) -> %%%---------------------------------------------------------------------- send_text(StateData, Text) -> - ejabberd_socket:send(StateData#state.socket, Text). + (StateData#state.sockmod):send(StateData#state.socket,Text). send_element(StateData, El) -> send_text(StateData, xml:element_to_string(El)). + new_id() -> randoms:get_string(). diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl deleted file mode 100644 index 9b0218803..000000000 --- a/src/ejabberd_socket.erl +++ /dev/null @@ -1,121 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : ejabberd_socket.erl -%%% Author : Alexey Shchepin <alexey@process-one.net> -%%% Purpose : Socket with zlib and TLS support library -%%% Created : 23 Aug 2006 by Alexey Shchepin <alex@alex.sevcom.net> -%%% Id : $Id$ -%%%---------------------------------------------------------------------- - --module(ejabberd_socket). --author('alexey@process-one.net'). - -%% API --export([start/4, - connect/3, - starttls/2, - compress/1, - reset_stream/1, - send/2, - change_shaper/2, - get_sockmod/1, - get_peer_certificate/1, - get_verify_result/1, - close/1]). - --record(socket_state, {sockmod, socket, receiver}). - -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: -%% Description: -%%-------------------------------------------------------------------- -start(Module, SockMod, Socket, Opts) -> - case Module:socket_type() of - xml_stream -> - MaxStanzaSize = - case lists:keysearch(max_stanza_size, 1, Opts) of - {value, {_, Size}} -> Size; - _ -> infinity - end, - Receiver = ejabberd_receiver:start(Socket, SockMod, none, MaxStanzaSize), - SocketData = #socket_state{sockmod = SockMod, - socket = Socket, - receiver = Receiver}, - {ok, Pid} = Module:start(SocketData, Opts), - case SockMod:controlling_process(Socket, Receiver) of - ok -> - ok; - {error, _Reason} -> - SockMod:close(Socket) - end, - ejabberd_receiver:become_controller(Receiver, Pid); - raw -> - {ok, Pid} = Module:start({SockMod, Socket}, Opts), - case SockMod:controlling_process(Socket, Pid) of - ok -> - ok; - {error, _Reason} -> - SockMod:close(Socket) - end, - ejabberd_receiver:become_controller(Pid) - end. - -connect(Addr, Port, Opts) -> - case gen_tcp:connect(Addr, Port, Opts) of - {ok, Socket} -> - Receiver = ejabberd_receiver:start(Socket, gen_tcp, none), - SocketData = #socket_state{sockmod = gen_tcp, - socket = Socket, - receiver = Receiver}, - Pid = self(), - case gen_tcp:controlling_process(Socket, Receiver) of - ok -> - ejabberd_receiver:become_controller(Receiver, Pid), - {ok, SocketData}; - {error, _Reason} = Error -> - gen_tcp:close(Socket), - Error - end; - {error, _Reason} = Error -> - Error - end. - -starttls(SocketData, TLSOpts) -> - {ok, TLSSocket} = tls:tcp_to_tls(SocketData#socket_state.socket, TLSOpts), - ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket), - SocketData#socket_state{socket = TLSSocket, sockmod = tls}. - -compress(SocketData) -> - {ok, ZlibSocket} = ejabberd_zlib:enable_zlib( - SocketData#socket_state.sockmod, - SocketData#socket_state.socket), - ejabberd_receiver:compress(SocketData#socket_state.receiver, ZlibSocket), - SocketData#socket_state{socket = ZlibSocket, sockmod = ejabberd_zlib}. - -reset_stream(SocketData) -> - ejabberd_receiver:reset_stream(SocketData#socket_state.receiver). - -send(SocketData, Data) -> - catch (SocketData#socket_state.sockmod):send( - SocketData#socket_state.socket, Data). - -change_shaper(SocketData, Shaper) -> - ejabberd_receiver:change_shaper(SocketData#socket_state.receiver, Shaper). - -get_sockmod(SocketData) -> - SocketData#socket_state.sockmod. - -get_peer_certificate(SocketData) -> - tls:get_peer_certificate(SocketData#socket_state.socket). - -get_verify_result(SocketData) -> - tls:get_verify_result(SocketData#socket_state.socket). - -close(SocketData) -> - ejabberd_receiver:close(SocketData#socket_state.receiver). - -%%==================================================================== -%% Internal functions -%%==================================================================== diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl index 3220925ec..5113f1afe 100644 --- a/src/web/ejabberd_http.erl +++ b/src/web/ejabberd_http.erl @@ -14,7 +14,6 @@ -export([start/2, start_link/2, become_controller/1, - socket_type/0, receive_headers/1, url_encode/1]). @@ -86,9 +85,6 @@ start_link({SockMod, Socket}, Opts) -> become_controller(_Pid) -> ok. -socket_type() -> - raw. - send_text(State, Text) -> (State#state.sockmod):send(State#state.socket, Text). |