mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-10 16:58:46 +01:00
* 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
This commit is contained in:
parent
e4b3da37ef
commit
c72599cacd
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
||||
2006-10-01 Alexey Shchepin <alexey@sevcom.net>
|
||||
|
||||
* 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 <mickael.remond@process-one.net>
|
||||
|
||||
* doc/release_notes_1.1.2.txt: Minor fixes.
|
||||
|
@ -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)).
|
||||
|
249
src/ejabberd_frontend_socket.erl
Normal file
249
src/ejabberd_frontend_socket.erl
Normal file
@ -0,0 +1,249 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% File : ejabberd_frontend_socket.erl
|
||||
%%% Author : Alexey Shchepin <alexey@process-one.net>
|
||||
%%% Purpose : Frontend socket with zlib and TLS support library
|
||||
%%% Created : 23 Aug 2006 by Alexey Shchepin <alex@alex.sevcom.net>
|
||||
%%% 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
|
||||
%%--------------------------------------------------------------------
|
@ -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,
|
||||
|
@ -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() ->
|
||||
|
@ -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)).
|
||||
|
@ -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).
|
||||
|
||||
|
@ -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};
|
||||
|
Loading…
Reference in New Issue
Block a user