From c72599cacdca34788fe0c342c9a4364d366c3821 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Sun, 1 Oct 2006 01:53:37 +0000 Subject: [PATCH] * src/ejabberd_frontend_socket.erl: Support for frontend connection manager * src/ejabberd_c2s.erl: Likewise * src/ejabberd_listener.erl: Likewise * src/ejabberd_s2s_in.erl: Likewise * src/ejabberd_service.erl: Likewise * src/ejabberd_socket.erl: Likewise * src/web/ejabberd_http_poll.erl: Likewise SVN Revision: 657 --- ChangeLog | 11 ++ src/ejabberd_c2s.erl | 41 ++--- src/ejabberd_frontend_socket.erl | 249 +++++++++++++++++++++++++++++++ src/ejabberd_listener.erl | 5 +- src/ejabberd_s2s_in.erl | 29 ++-- src/ejabberd_service.erl | 9 +- src/ejabberd_socket.erl | 21 ++- src/web/ejabberd_http_poll.erl | 34 +++-- 8 files changed, 343 insertions(+), 56 deletions(-) create mode 100644 src/ejabberd_frontend_socket.erl diff --git a/ChangeLog b/ChangeLog index a763bff43..5f468dabc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-10-01 Alexey Shchepin + + * src/ejabberd_frontend_socket.erl: Support for frontend + connection manager + * src/ejabberd_c2s.erl: Likewise + * src/ejabberd_listener.erl: Likewise + * src/ejabberd_s2s_in.erl: Likewise + * src/ejabberd_service.erl: Likewise + * src/ejabberd_socket.erl: Likewise + * src/web/ejabberd_http_poll.erl: Likewise + 2006-09-27 Mickael Remond * doc/release_notes_1.1.2.txt: Minor fixes. diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index a9e0d01ef..5c05d863a 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -41,6 +41,7 @@ -define(SETS, gb_sets). -record(state, {socket, + sockmod, streamid, sasl_state, access, @@ -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 @@ -137,11 +138,12 @@ init([Socket, Opts]) -> Socket1 = if TLSEnabled -> - ejabberd_socket:starttls(Socket, TLSOpts); + SockMod:starttls(Socket, TLSOpts); true -> Socket end, {ok, wait_for_stream, #state{socket = Socket1, + sockmod = SockMod, zlib = Zlib, tls = TLS, tls_required = StartTLSRequired, @@ -198,8 +200,9 @@ 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):get_sockmod( + StateData#state.socket), Zlib = StateData#state.zlib, CompressFeature = case Zlib andalso @@ -453,7 +456,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):get_sockmod(StateData#state.socket), 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 +465,8 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> Mech, ClientIn) of {ok, Props} -> - ejabberd_socket:reset_stream(StateData#state.socket), + (StateData#state.sockmod):reset_stream( + StateData#state.socket), send_element(StateData, {xmlelement, "success", [{"xmlns", ?NS_SASL}], []}), @@ -502,9 +506,10 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> certfile, 1, StateData#state.tls_options)] end, Socket = StateData#state.socket, - TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts), - send_element(StateData, - {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}), + TLSSocket = (StateData#state.sockmod):starttls( + Socket, TLSOpts, + xml:element_to_string( + {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})), {next_state, wait_for_stream, StateData#state{socket = TLSSocket, streamid = new_id(), @@ -523,10 +528,11 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> case xml:get_tag_cdata(Method) of "zlib" -> Socket = StateData#state.socket, - ZlibSocket = ejabberd_socket:compress(Socket), - send_element(StateData, - {xmlelement, "compressed", - [{"xmlns", ?NS_COMPRESS}], []}), + ZlibSocket = (StateData#state.sockmod):compress( + Socket, + xml:element_to_string( + {xmlelement, "compressed", + [{"xmlns", ?NS_COMPRESS}], []})), {next_state, wait_for_stream, StateData#state{socket = ZlibSocket, streamid = new_id() @@ -575,7 +581,8 @@ 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), + (StateData#state.sockmod):reset_stream( + StateData#state.socket), send_element(StateData, {xmlelement, "success", [{"xmlns", ?NS_SASL}], []}), @@ -1167,7 +1174,7 @@ terminate(_Reason, StateName, StateData) -> _ -> ok end, - ejabberd_socket:close(StateData#state.socket), + (StateData#state.sockmod):close(StateData#state.socket), ok. %%%---------------------------------------------------------------------- @@ -1177,11 +1184,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). + (StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper). send_text(StateData, Text) -> ?DEBUG("Send XML on stream = ~p", [lists:flatten(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_frontend_socket.erl b/src/ejabberd_frontend_socket.erl new file mode 100644 index 000000000..c69fac5b2 --- /dev/null +++ b/src/ejabberd_frontend_socket.erl @@ -0,0 +1,249 @@ +%%%------------------------------------------------------------------- +%%% File : ejabberd_frontend_socket.erl +%%% Author : Alexey Shchepin +%%% Purpose : Frontend socket with zlib and TLS support library +%%% Created : 23 Aug 2006 by Alexey Shchepin +%%% Id : $Id$ +%%%---------------------------------------------------------------------- + +-module(ejabberd_frontend_socket). +-author('alexey@process-one.net'). + +-behaviour(gen_server). + +%% API +-export([start/4, + start_link/4, + %connect/3, + starttls/2, + starttls/3, + compress/1, + compress/2, + reset_stream/1, + send/2, + change_shaper/2, + get_sockmod/1, + get_peer_certificate/1, + get_verify_result/1, + close/1]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, {sockmod, socket, receiver}). + +%%==================================================================== +%% API +%%==================================================================== +%%-------------------------------------------------------------------- +%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} +%% Description: Starts the server +%%-------------------------------------------------------------------- +start_link(Module, SockMod, Socket, Opts) -> + gen_server:start_link(?MODULE, + [Module, SockMod, Socket, Opts], []). + +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), + case SockMod:controlling_process(Socket, Receiver) of + ok -> + ok; + {error, _Reason} -> + SockMod:close(Socket) + end, + gen_server:start(?MODULE, + [Module, SockMod, Socket, Opts, Receiver], []); + raw -> + %{ok, Pid} = Module:start({SockMod, Socket}, Opts), + %case SockMod:controlling_process(Socket, Pid) of + % ok -> + % ok; + % {error, _Reason} -> + % SockMod:close(Socket) + %end + todo + end. + +starttls(FsmRef, TLSOpts) -> + gen_server:call(FsmRef, {starttls, TLSOpts}), + FsmRef. + +starttls(FsmRef, TLSOpts, Data) -> + gen_server:call(FsmRef, {starttls, TLSOpts, Data}), + FsmRef. + +compress(FsmRef) -> + gen_server:call(FsmRef, compress), + FsmRef. + +compress(FsmRef, Data) -> + gen_server:call(FsmRef, {compress, Data}), + FsmRef. + +reset_stream(FsmRef) -> + gen_server:call(FsmRef, reset_stream). + +send(FsmRef, Data) -> + gen_server:call(FsmRef, {send, Data}). + +change_shaper(FsmRef, Shaper) -> + gen_server:call(FsmRef, {change_shaper, Shaper}). + +get_sockmod(FsmRef) -> + gen_server:call(FsmRef, get_sockmod). + +get_peer_certificate(FsmRef) -> + gen_server:call(FsmRef, get_peer_certificate). + +get_verify_result(FsmRef) -> + gen_server:call(FsmRef, get_verify_result). + +close(FsmRef) -> + gen_server:call(FsmRef, close). + + +%%==================================================================== +%% gen_server callbacks +%%==================================================================== + +%%-------------------------------------------------------------------- +%% Function: init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% Description: Initiates the server +%%-------------------------------------------------------------------- +init([Module, SockMod, Socket, Opts, Receiver]) -> + Nodes = mnesia:table_info(schema, disc_copies), + Node = lists:nth(erlang:phash(now(), length(Nodes)), Nodes), + {ok, Pid} = + rpc:call(Node, Module, start, [{?MODULE, self()}, Opts]), + ejabberd_receiver:become_controller(Receiver, Pid), + {ok, #state{sockmod = SockMod, + socket = Socket, + receiver = Receiver}}. + +%%-------------------------------------------------------------------- +%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | +%% {stop, Reason, State} +%% Description: Handling call messages +%%-------------------------------------------------------------------- +handle_call({starttls, TLSOpts}, _From, State) -> + {ok, TLSSocket} = tls:tcp_to_tls(State#state.socket, TLSOpts), + ejabberd_receiver:starttls(State#state.receiver, TLSSocket), + Reply = ok, + {reply, Reply, State#state{socket = TLSSocket, sockmod = tls}}; + +handle_call({starttls, TLSOpts, Data}, _From, State) -> + {ok, TLSSocket} = tls:tcp_to_tls(State#state.socket, TLSOpts), + ejabberd_receiver:starttls(State#state.receiver, TLSSocket), + catch (State#state.sockmod):send( + State#state.socket, Data), + Reply = ok, + {reply, Reply, State#state{socket = TLSSocket, sockmod = tls}}; + +handle_call(compress, _From, State) -> + {ok, ZlibSocket} = ejabberd_zlib:enable_zlib( + State#state.sockmod, + State#state.socket), + ejabberd_receiver:compress(State#state.receiver, ZlibSocket), + Reply = ok, + {reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib}}; + +handle_call({compress, Data}, _From, State) -> + {ok, ZlibSocket} = ejabberd_zlib:enable_zlib( + State#state.sockmod, + State#state.socket), + ejabberd_receiver:compress(State#state.receiver, ZlibSocket), + catch (State#state.sockmod):send( + State#state.socket, Data), + Reply = ok, + {reply, Reply, State#state{socket = ZlibSocket, sockmod = ejabberd_zlib}}; + +handle_call(reset_stream, _From, State) -> + ejabberd_receiver:reset_stream(State#state.receiver), + Reply = ok, + {reply, Reply, State}; + +handle_call({send, Data}, _From, State) -> + catch (State#state.sockmod):send( + State#state.socket, Data), + Reply = ok, + {reply, Reply, State}; + +handle_call({change_shaper, Shaper}, _From, State) -> + ejabberd_receiver:change_shaper(State#state.receiver, Shaper), + Reply = ok, + {reply, Reply, State}; + +handle_call(get_sockmod, _From, State) -> + Reply = State#state.sockmod, + {reply, Reply, State}; + +handle_call(get_peer_certificate, _From, State) -> + Reply = tls:get_peer_certificate(State#state.socket), + {reply, Reply, State}; + +handle_call(get_verify_result, _From, State) -> + Reply = tls:get_verify_result(State#state.socket), + {reply, Reply, State}; + +handle_call(close, _From, State) -> + ejabberd_receiver:close(State#state.receiver), + Reply = ok, + {stop, normal, Reply, State}; + +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. + +%%-------------------------------------------------------------------- +%% Function: handle_cast(Msg, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling cast messages +%%-------------------------------------------------------------------- +handle_cast(_Msg, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% Function: handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling all non call/cast messages +%%-------------------------------------------------------------------- +handle_info(_Info, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% Function: terminate(Reason, State) -> void() +%% Description: This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any necessary +%% cleaning up. When it returns, the gen_server terminates with Reason. +%% The return value is ignored. +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} +%% Description: Convert process state when code is changed +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 8bc168421..4a4a39b47 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -93,9 +93,8 @@ 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); + {frontend, Mod} -> + ejabberd_frontend_socket:start(Mod, gen_tcp, Socket, Opts); _ -> ejabberd_socket:start(Module, gen_tcp, Socket, Opts) end, diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 64a85fc1c..b5f89c95b 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -37,6 +37,7 @@ -define(DICT, dict). -record(state, {socket, + sockmod, streamid, shaper, tls = false, @@ -99,7 +100,7 @@ socket_type() -> %% ignore | %% {stop, StopReason} %%---------------------------------------------------------------------- -init([Socket, Opts]) -> +init([{SockMod, Socket}, Opts]) -> ?INFO_MSG("started: ~p", [Socket]), Shaper = case lists:keysearch(shaper, 1, Opts) of {value, {_, S}} -> S; @@ -120,6 +121,7 @@ init([Socket, Opts]) -> Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, wait_for_stream, #state{socket = Socket, + sockmod = SockMod, streamid = new_id(), shaper = Shaper, tls = StartTLS, @@ -144,10 +146,10 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> SASL = if StateData#state.tls_enabled -> - case ejabberd_socket:get_peer_certificate( + case (StateData#state.sockmod):get_peer_certificate( StateData#state.socket) of {ok, _Cert} -> - case ejabberd_socket:get_verify_result( + case (StateData#state.sockmod):get_verify_result( StateData#state.socket) of 0 -> [{xmlelement, "mechanisms", @@ -204,7 +206,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):get_sockmod(StateData#state.socket), case {xml:get_attr_s("xmlns", Attrs), Name} of {?NS_TLS, "starttls"} when TLS == true, TLSEnabled == false, @@ -212,9 +214,10 @@ 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), - send_element(StateData, - {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}), + TLSSocket = (StateData#state.sockmod):starttls( + Socket, TLSOpts, + xml:element_to_string( + {xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})), {next_state, wait_for_stream, StateData#state{socket = TLSSocket, streamid = new_id(), @@ -227,10 +230,10 @@ 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( + case (StateData#state.sockmod):get_peer_certificate( StateData#state.socket) of {ok, Cert} -> - case ejabberd_socket:get_verify_result( + case (StateData#state.sockmod):get_verify_result( StateData#state.socket) of 0 -> case AuthDomain of @@ -256,7 +259,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) -> end, if AuthRes -> - ejabberd_socket:reset_stream( + (StateData#state.sockmod):reset_stream( StateData#state.socket), send_element(StateData, {xmlelement, "success", @@ -500,7 +503,7 @@ handle_info(_, StateName, StateData) -> %%---------------------------------------------------------------------- terminate(Reason, _StateName, StateData) -> ?INFO_MSG("terminated: ~p", [Reason]), - ejabberd_socket:close(StateData#state.socket), + (StateData#state.sockmod):close(StateData#state.socket), ok. %%%---------------------------------------------------------------------- @@ -508,7 +511,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 +519,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). + (StateData#state.sockmod):change_shaper(StateData#state.socket, Shaper). new_id() -> diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 925915aa9..dbc5c1682 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -33,7 +33,7 @@ -include("ejabberd.hrl"). -include("jlib.hrl"). --record(state, {socket, streamid, +-record(state, {socket, sockmod, streamid, hosts, password, access}). %-define(DBGFSM, true). @@ -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 @@ -124,6 +124,7 @@ init([Socket, Opts]) -> end end, {ok, wait_for_stream, #state{socket = Socket, + sockmod = SockMod, streamid = new_id(), hosts = Hosts, password = Password, @@ -319,7 +320,7 @@ terminate(Reason, StateName, StateData) -> _ -> ok end, - ejabberd_socket:close(StateData#state.socket), + (StateData#state.sockmod):close(StateData#state.socket), ok. %%%---------------------------------------------------------------------- @@ -327,7 +328,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_socket.erl b/src/ejabberd_socket.erl index 9b0218803..ba7a24f60 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -13,7 +13,9 @@ -export([start/4, connect/3, starttls/2, + starttls/3, compress/1, + compress/2, reset_stream/1, send/2, change_shaper/2, @@ -43,7 +45,7 @@ start(Module, SockMod, Socket, Opts) -> SocketData = #socket_state{sockmod = SockMod, socket = Socket, receiver = Receiver}, - {ok, Pid} = Module:start(SocketData, Opts), + {ok, Pid} = Module:start({?MODULE, SocketData}, Opts), case SockMod:controlling_process(Socket, Receiver) of ok -> ok; @@ -58,8 +60,7 @@ start(Module, SockMod, Socket, Opts) -> ok; {error, _Reason} -> SockMod:close(Socket) - end, - ejabberd_receiver:become_controller(Pid) + end end. connect(Addr, Port, Opts) -> @@ -87,6 +88,12 @@ starttls(SocketData, TLSOpts) -> ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket), SocketData#socket_state{socket = TLSSocket, sockmod = tls}. +starttls(SocketData, TLSOpts, Data) -> + {ok, TLSSocket} = tls:tcp_to_tls(SocketData#socket_state.socket, TLSOpts), + ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket), + send(SocketData, Data), + SocketData#socket_state{socket = TLSSocket, sockmod = tls}. + compress(SocketData) -> {ok, ZlibSocket} = ejabberd_zlib:enable_zlib( SocketData#socket_state.sockmod, @@ -94,6 +101,14 @@ compress(SocketData) -> ejabberd_receiver:compress(SocketData#socket_state.receiver, ZlibSocket), SocketData#socket_state{socket = ZlibSocket, sockmod = ejabberd_zlib}. +compress(SocketData, Data) -> + {ok, ZlibSocket} = ejabberd_zlib:enable_zlib( + SocketData#socket_state.sockmod, + SocketData#socket_state.socket), + ejabberd_receiver:compress(SocketData#socket_state.receiver, ZlibSocket), + send(SocketData, Data), + SocketData#socket_state{socket = ZlibSocket, sockmod = ejabberd_zlib}. + reset_stream(SocketData) -> ejabberd_receiver:reset_stream(SocketData#socket_state.receiver). diff --git a/src/web/ejabberd_http_poll.erl b/src/web/ejabberd_http_poll.erl index dcd041235..8bdebbdea 100644 --- a/src/web/ejabberd_http_poll.erl +++ b/src/web/ejabberd_http_poll.erl @@ -71,7 +71,7 @@ send({http_poll, FsmRef}, Packet) -> setopts({http_poll, FsmRef}, Opts) -> case lists:member({active, once}, Opts) of true -> - gen_fsm:sync_send_all_state_event(FsmRef, activate); + gen_fsm:send_all_state_event(FsmRef, {activate, self()}); _ -> ok end. @@ -148,8 +148,9 @@ process_request(_Request) -> init([ID, Key]) -> ?INFO_MSG("started: ~p", [{ID, Key}]), Opts = [], % TODO - {ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_poll, self()}}, Opts), - ejabberd_c2s:become_controller(C2SPid), + ejabberd_socket:start(ejabberd_c2s, ?MODULE, {http_poll, self()}, Opts), + %{ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_poll, self()}}, Opts), + %ejabberd_c2s:become_controller(C2SPid), Timer = erlang:start_timer(?HTTP_POLL_TIMEOUT, self(), []), {ok, loop, #state{id = ID, key = Key, @@ -182,6 +183,20 @@ init([ID, Key]) -> %% {next_state, NextStateName, NextStateData, Timeout} | %% {stop, Reason, NewStateData} %%---------------------------------------------------------------------- +handle_event({activate, From}, StateName, StateData) -> + case StateData#state.input of + "" -> + {next_state, StateName, + StateData#state{waiting_input = {From, ok}}}; + Input -> + {Receiver, _Tag} = From, + Receiver ! {tcp, {http_poll, self()}, list_to_binary(Input)}, + {next_state, StateName, StateData#state{input = "", + waiting_input = false, + last_receiver = From + }} + end; + handle_event(Event, StateName, StateData) -> {next_state, StateName, StateData}. @@ -199,19 +214,6 @@ handle_sync_event({send, Packet}, From, StateName, StateData) -> Reply = ok, {reply, Reply, StateName, StateData#state{output = Output}}; -handle_sync_event(activate, From, StateName, StateData) -> - case StateData#state.input of - "" -> - {reply, ok, StateName, StateData#state{waiting_input = From}}; - Input -> - {Receiver, _Tag} = From, - Receiver ! {tcp, {http_poll, self()}, list_to_binary(Input)}, - {reply, ok, StateName, StateData#state{input = "", - waiting_input = false, - last_receiver = From - }} - end; - handle_sync_event(stop, From, StateName, StateData) -> Reply = ok, {stop, normal, Reply, StateData};