mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-26 16:26:24 +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>
|
2006-09-27 Mickael Remond <mickael.remond@process-one.net>
|
||||||
|
|
||||||
* doc/release_notes_1.1.2.txt: Minor fixes.
|
* doc/release_notes_1.1.2.txt: Minor fixes.
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
-define(SETS, gb_sets).
|
-define(SETS, gb_sets).
|
||||||
|
|
||||||
-record(state, {socket,
|
-record(state, {socket,
|
||||||
|
sockmod,
|
||||||
streamid,
|
streamid,
|
||||||
sasl_state,
|
sasl_state,
|
||||||
access,
|
access,
|
||||||
@ -117,7 +118,7 @@ get_presence(FsmRef) ->
|
|||||||
%% ignore |
|
%% ignore |
|
||||||
%% {stop, StopReason}
|
%% {stop, StopReason}
|
||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
init([Socket, Opts]) ->
|
init([{SockMod, Socket}, Opts]) ->
|
||||||
Access = case lists:keysearch(access, 1, Opts) of
|
Access = case lists:keysearch(access, 1, Opts) of
|
||||||
{value, {_, A}} -> A;
|
{value, {_, A}} -> A;
|
||||||
_ -> all
|
_ -> all
|
||||||
@ -137,11 +138,12 @@ init([Socket, Opts]) ->
|
|||||||
Socket1 =
|
Socket1 =
|
||||||
if
|
if
|
||||||
TLSEnabled ->
|
TLSEnabled ->
|
||||||
ejabberd_socket:starttls(Socket, TLSOpts);
|
SockMod:starttls(Socket, TLSOpts);
|
||||||
true ->
|
true ->
|
||||||
Socket
|
Socket
|
||||||
end,
|
end,
|
||||||
{ok, wait_for_stream, #state{socket = Socket1,
|
{ok, wait_for_stream, #state{socket = Socket1,
|
||||||
|
sockmod = SockMod,
|
||||||
zlib = Zlib,
|
zlib = Zlib,
|
||||||
tls = TLS,
|
tls = TLS,
|
||||||
tls_required = StartTLSRequired,
|
tls_required = StartTLSRequired,
|
||||||
@ -198,8 +200,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
|||||||
{xmlelement, "mechanism", [],
|
{xmlelement, "mechanism", [],
|
||||||
[{xmlcdata, S}]}
|
[{xmlcdata, S}]}
|
||||||
end, cyrsasl:listmech(Server)),
|
end, cyrsasl:listmech(Server)),
|
||||||
SockMod = ejabberd_socket:get_sockmod(
|
SockMod =
|
||||||
StateData#state.socket),
|
(StateData#state.sockmod):get_sockmod(
|
||||||
|
StateData#state.socket),
|
||||||
Zlib = StateData#state.zlib,
|
Zlib = StateData#state.zlib,
|
||||||
CompressFeature =
|
CompressFeature =
|
||||||
case Zlib andalso
|
case Zlib andalso
|
||||||
@ -453,7 +456,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
TLS = StateData#state.tls,
|
TLS = StateData#state.tls,
|
||||||
TLSEnabled = StateData#state.tls_enabled,
|
TLSEnabled = StateData#state.tls_enabled,
|
||||||
TLSRequired = StateData#state.tls_required,
|
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
|
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
||||||
{?NS_SASL, "auth"} when not ((SockMod == gen_tcp) and TLSRequired) ->
|
{?NS_SASL, "auth"} when not ((SockMod == gen_tcp) and TLSRequired) ->
|
||||||
Mech = xml:get_attr_s("mechanism", Attrs),
|
Mech = xml:get_attr_s("mechanism", Attrs),
|
||||||
@ -462,7 +465,8 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
Mech,
|
Mech,
|
||||||
ClientIn) of
|
ClientIn) of
|
||||||
{ok, Props} ->
|
{ok, Props} ->
|
||||||
ejabberd_socket:reset_stream(StateData#state.socket),
|
(StateData#state.sockmod):reset_stream(
|
||||||
|
StateData#state.socket),
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "success",
|
{xmlelement, "success",
|
||||||
[{"xmlns", ?NS_SASL}], []}),
|
[{"xmlns", ?NS_SASL}], []}),
|
||||||
@ -502,9 +506,10 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
certfile, 1, StateData#state.tls_options)]
|
certfile, 1, StateData#state.tls_options)]
|
||||||
end,
|
end,
|
||||||
Socket = StateData#state.socket,
|
Socket = StateData#state.socket,
|
||||||
TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts),
|
TLSSocket = (StateData#state.sockmod):starttls(
|
||||||
send_element(StateData,
|
Socket, TLSOpts,
|
||||||
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}),
|
xml:element_to_string(
|
||||||
|
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
|
||||||
{next_state, wait_for_stream,
|
{next_state, wait_for_stream,
|
||||||
StateData#state{socket = TLSSocket,
|
StateData#state{socket = TLSSocket,
|
||||||
streamid = new_id(),
|
streamid = new_id(),
|
||||||
@ -523,10 +528,11 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
case xml:get_tag_cdata(Method) of
|
case xml:get_tag_cdata(Method) of
|
||||||
"zlib" ->
|
"zlib" ->
|
||||||
Socket = StateData#state.socket,
|
Socket = StateData#state.socket,
|
||||||
ZlibSocket = ejabberd_socket:compress(Socket),
|
ZlibSocket = (StateData#state.sockmod):compress(
|
||||||
send_element(StateData,
|
Socket,
|
||||||
{xmlelement, "compressed",
|
xml:element_to_string(
|
||||||
[{"xmlns", ?NS_COMPRESS}], []}),
|
{xmlelement, "compressed",
|
||||||
|
[{"xmlns", ?NS_COMPRESS}], []})),
|
||||||
{next_state, wait_for_stream,
|
{next_state, wait_for_stream,
|
||||||
StateData#state{socket = ZlibSocket,
|
StateData#state{socket = ZlibSocket,
|
||||||
streamid = new_id()
|
streamid = new_id()
|
||||||
@ -575,7 +581,8 @@ wait_for_sasl_response({xmlstreamelement, El}, StateData) ->
|
|||||||
case cyrsasl:server_step(StateData#state.sasl_state,
|
case cyrsasl:server_step(StateData#state.sasl_state,
|
||||||
ClientIn) of
|
ClientIn) of
|
||||||
{ok, Props} ->
|
{ok, Props} ->
|
||||||
ejabberd_socket:reset_stream(StateData#state.socket),
|
(StateData#state.sockmod):reset_stream(
|
||||||
|
StateData#state.socket),
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "success",
|
{xmlelement, "success",
|
||||||
[{"xmlns", ?NS_SASL}], []}),
|
[{"xmlns", ?NS_SASL}], []}),
|
||||||
@ -1167,7 +1174,7 @@ terminate(_Reason, StateName, StateData) ->
|
|||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
ejabberd_socket:close(StateData#state.socket),
|
(StateData#state.sockmod):close(StateData#state.socket),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -1177,11 +1184,11 @@ terminate(_Reason, StateName, StateData) ->
|
|||||||
change_shaper(StateData, JID) ->
|
change_shaper(StateData, JID) ->
|
||||||
Shaper = acl:match_rule(StateData#state.server,
|
Shaper = acl:match_rule(StateData#state.server,
|
||||||
StateData#state.shaper, JID),
|
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) ->
|
send_text(StateData, Text) ->
|
||||||
?DEBUG("Send XML on stream = ~p", [lists:flatten(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_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(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
|
ok
|
||||||
end,
|
end,
|
||||||
case Module of
|
case Module of
|
||||||
ejabberd_http ->
|
{frontend, Mod} ->
|
||||||
{ok, Pid} = Module:start({gen_tcp, Socket}, Opts),
|
ejabberd_frontend_socket:start(Mod, gen_tcp, Socket, Opts);
|
||||||
catch gen_tcp:controlling_process(Socket, Pid);
|
|
||||||
_ ->
|
_ ->
|
||||||
ejabberd_socket:start(Module, gen_tcp, Socket, Opts)
|
ejabberd_socket:start(Module, gen_tcp, Socket, Opts)
|
||||||
end,
|
end,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
-define(DICT, dict).
|
-define(DICT, dict).
|
||||||
|
|
||||||
-record(state, {socket,
|
-record(state, {socket,
|
||||||
|
sockmod,
|
||||||
streamid,
|
streamid,
|
||||||
shaper,
|
shaper,
|
||||||
tls = false,
|
tls = false,
|
||||||
@ -99,7 +100,7 @@ socket_type() ->
|
|||||||
%% ignore |
|
%% ignore |
|
||||||
%% {stop, StopReason}
|
%% {stop, StopReason}
|
||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
init([Socket, Opts]) ->
|
init([{SockMod, Socket}, Opts]) ->
|
||||||
?INFO_MSG("started: ~p", [Socket]),
|
?INFO_MSG("started: ~p", [Socket]),
|
||||||
Shaper = case lists:keysearch(shaper, 1, Opts) of
|
Shaper = case lists:keysearch(shaper, 1, Opts) of
|
||||||
{value, {_, S}} -> S;
|
{value, {_, S}} -> S;
|
||||||
@ -120,6 +121,7 @@ init([Socket, Opts]) ->
|
|||||||
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
|
Timer = erlang:start_timer(?S2STIMEOUT, self(), []),
|
||||||
{ok, wait_for_stream,
|
{ok, wait_for_stream,
|
||||||
#state{socket = Socket,
|
#state{socket = Socket,
|
||||||
|
sockmod = SockMod,
|
||||||
streamid = new_id(),
|
streamid = new_id(),
|
||||||
shaper = Shaper,
|
shaper = Shaper,
|
||||||
tls = StartTLS,
|
tls = StartTLS,
|
||||||
@ -144,10 +146,10 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
|
|||||||
SASL =
|
SASL =
|
||||||
if
|
if
|
||||||
StateData#state.tls_enabled ->
|
StateData#state.tls_enabled ->
|
||||||
case ejabberd_socket:get_peer_certificate(
|
case (StateData#state.sockmod):get_peer_certificate(
|
||||||
StateData#state.socket) of
|
StateData#state.socket) of
|
||||||
{ok, _Cert} ->
|
{ok, _Cert} ->
|
||||||
case ejabberd_socket:get_verify_result(
|
case (StateData#state.sockmod):get_verify_result(
|
||||||
StateData#state.socket) of
|
StateData#state.socket) of
|
||||||
0 ->
|
0 ->
|
||||||
[{xmlelement, "mechanisms",
|
[{xmlelement, "mechanisms",
|
||||||
@ -204,7 +206,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
{xmlelement, Name, Attrs, Els} = El,
|
{xmlelement, Name, Attrs, Els} = El,
|
||||||
TLS = StateData#state.tls,
|
TLS = StateData#state.tls,
|
||||||
TLSEnabled = StateData#state.tls_enabled,
|
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
|
case {xml:get_attr_s("xmlns", Attrs), Name} of
|
||||||
{?NS_TLS, "starttls"} when TLS == true,
|
{?NS_TLS, "starttls"} when TLS == true,
|
||||||
TLSEnabled == false,
|
TLSEnabled == false,
|
||||||
@ -212,9 +214,10 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
?INFO_MSG("starttls", []),
|
?INFO_MSG("starttls", []),
|
||||||
Socket = StateData#state.socket,
|
Socket = StateData#state.socket,
|
||||||
TLSOpts = StateData#state.tls_options,
|
TLSOpts = StateData#state.tls_options,
|
||||||
TLSSocket = ejabberd_socket:starttls(Socket, TLSOpts),
|
TLSSocket = (StateData#state.sockmod):starttls(
|
||||||
send_element(StateData,
|
Socket, TLSOpts,
|
||||||
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []}),
|
xml:element_to_string(
|
||||||
|
{xmlelement, "proceed", [{"xmlns", ?NS_TLS}], []})),
|
||||||
{next_state, wait_for_stream,
|
{next_state, wait_for_stream,
|
||||||
StateData#state{socket = TLSSocket,
|
StateData#state{socket = TLSSocket,
|
||||||
streamid = new_id(),
|
streamid = new_id(),
|
||||||
@ -227,10 +230,10 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
Auth = jlib:decode_base64(xml:get_cdata(Els)),
|
Auth = jlib:decode_base64(xml:get_cdata(Els)),
|
||||||
AuthDomain = jlib:nameprep(Auth),
|
AuthDomain = jlib:nameprep(Auth),
|
||||||
AuthRes =
|
AuthRes =
|
||||||
case ejabberd_socket:get_peer_certificate(
|
case (StateData#state.sockmod):get_peer_certificate(
|
||||||
StateData#state.socket) of
|
StateData#state.socket) of
|
||||||
{ok, Cert} ->
|
{ok, Cert} ->
|
||||||
case ejabberd_socket:get_verify_result(
|
case (StateData#state.sockmod):get_verify_result(
|
||||||
StateData#state.socket) of
|
StateData#state.socket) of
|
||||||
0 ->
|
0 ->
|
||||||
case AuthDomain of
|
case AuthDomain of
|
||||||
@ -256,7 +259,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
|
|||||||
end,
|
end,
|
||||||
if
|
if
|
||||||
AuthRes ->
|
AuthRes ->
|
||||||
ejabberd_socket:reset_stream(
|
(StateData#state.sockmod):reset_stream(
|
||||||
StateData#state.socket),
|
StateData#state.socket),
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
{xmlelement, "success",
|
{xmlelement, "success",
|
||||||
@ -500,7 +503,7 @@ handle_info(_, StateName, StateData) ->
|
|||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
terminate(Reason, _StateName, StateData) ->
|
terminate(Reason, _StateName, StateData) ->
|
||||||
?INFO_MSG("terminated: ~p", [Reason]),
|
?INFO_MSG("terminated: ~p", [Reason]),
|
||||||
ejabberd_socket:close(StateData#state.socket),
|
(StateData#state.sockmod):close(StateData#state.socket),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -508,7 +511,7 @@ terminate(Reason, _StateName, StateData) ->
|
|||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
send_text(StateData, Text) ->
|
send_text(StateData, Text) ->
|
||||||
ejabberd_socket:send(StateData#state.socket, Text).
|
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
||||||
|
|
||||||
send_element(StateData, El) ->
|
send_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(El)).
|
send_text(StateData, xml:element_to_string(El)).
|
||||||
@ -516,7 +519,7 @@ send_element(StateData, El) ->
|
|||||||
|
|
||||||
change_shaper(StateData, Host, JID) ->
|
change_shaper(StateData, Host, JID) ->
|
||||||
Shaper = acl:match_rule(Host, StateData#state.shaper, 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() ->
|
new_id() ->
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(state, {socket, streamid,
|
-record(state, {socket, sockmod, streamid,
|
||||||
hosts, password, access}).
|
hosts, password, access}).
|
||||||
|
|
||||||
%-define(DBGFSM, true).
|
%-define(DBGFSM, true).
|
||||||
@ -93,7 +93,7 @@ socket_type() ->
|
|||||||
%% ignore |
|
%% ignore |
|
||||||
%% {stop, StopReason}
|
%% {stop, StopReason}
|
||||||
%%----------------------------------------------------------------------
|
%%----------------------------------------------------------------------
|
||||||
init([Socket, Opts]) ->
|
init([{SockMod, Socket}, Opts]) ->
|
||||||
Access = case lists:keysearch(access, 1, Opts) of
|
Access = case lists:keysearch(access, 1, Opts) of
|
||||||
{value, {_, A}} -> A;
|
{value, {_, A}} -> A;
|
||||||
_ -> all
|
_ -> all
|
||||||
@ -124,6 +124,7 @@ init([Socket, Opts]) ->
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
{ok, wait_for_stream, #state{socket = Socket,
|
{ok, wait_for_stream, #state{socket = Socket,
|
||||||
|
sockmod = SockMod,
|
||||||
streamid = new_id(),
|
streamid = new_id(),
|
||||||
hosts = Hosts,
|
hosts = Hosts,
|
||||||
password = Password,
|
password = Password,
|
||||||
@ -319,7 +320,7 @@ terminate(Reason, StateName, StateData) ->
|
|||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
ejabberd_socket:close(StateData#state.socket),
|
(StateData#state.sockmod):close(StateData#state.socket),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -327,7 +328,7 @@ terminate(Reason, StateName, StateData) ->
|
|||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
|
|
||||||
send_text(StateData, Text) ->
|
send_text(StateData, Text) ->
|
||||||
ejabberd_socket:send(StateData#state.socket, Text).
|
(StateData#state.sockmod):send(StateData#state.socket, Text).
|
||||||
|
|
||||||
send_element(StateData, El) ->
|
send_element(StateData, El) ->
|
||||||
send_text(StateData, xml:element_to_string(El)).
|
send_text(StateData, xml:element_to_string(El)).
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
-export([start/4,
|
-export([start/4,
|
||||||
connect/3,
|
connect/3,
|
||||||
starttls/2,
|
starttls/2,
|
||||||
|
starttls/3,
|
||||||
compress/1,
|
compress/1,
|
||||||
|
compress/2,
|
||||||
reset_stream/1,
|
reset_stream/1,
|
||||||
send/2,
|
send/2,
|
||||||
change_shaper/2,
|
change_shaper/2,
|
||||||
@ -43,7 +45,7 @@ start(Module, SockMod, Socket, Opts) ->
|
|||||||
SocketData = #socket_state{sockmod = SockMod,
|
SocketData = #socket_state{sockmod = SockMod,
|
||||||
socket = Socket,
|
socket = Socket,
|
||||||
receiver = Receiver},
|
receiver = Receiver},
|
||||||
{ok, Pid} = Module:start(SocketData, Opts),
|
{ok, Pid} = Module:start({?MODULE, SocketData}, Opts),
|
||||||
case SockMod:controlling_process(Socket, Receiver) of
|
case SockMod:controlling_process(Socket, Receiver) of
|
||||||
ok ->
|
ok ->
|
||||||
ok;
|
ok;
|
||||||
@ -58,8 +60,7 @@ start(Module, SockMod, Socket, Opts) ->
|
|||||||
ok;
|
ok;
|
||||||
{error, _Reason} ->
|
{error, _Reason} ->
|
||||||
SockMod:close(Socket)
|
SockMod:close(Socket)
|
||||||
end,
|
end
|
||||||
ejabberd_receiver:become_controller(Pid)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
connect(Addr, Port, Opts) ->
|
connect(Addr, Port, Opts) ->
|
||||||
@ -87,6 +88,12 @@ starttls(SocketData, TLSOpts) ->
|
|||||||
ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket),
|
ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket),
|
||||||
SocketData#socket_state{socket = TLSSocket, sockmod = tls}.
|
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) ->
|
compress(SocketData) ->
|
||||||
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(
|
{ok, ZlibSocket} = ejabberd_zlib:enable_zlib(
|
||||||
SocketData#socket_state.sockmod,
|
SocketData#socket_state.sockmod,
|
||||||
@ -94,6 +101,14 @@ compress(SocketData) ->
|
|||||||
ejabberd_receiver:compress(SocketData#socket_state.receiver, ZlibSocket),
|
ejabberd_receiver:compress(SocketData#socket_state.receiver, ZlibSocket),
|
||||||
SocketData#socket_state{socket = ZlibSocket, sockmod = ejabberd_zlib}.
|
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) ->
|
reset_stream(SocketData) ->
|
||||||
ejabberd_receiver:reset_stream(SocketData#socket_state.receiver).
|
ejabberd_receiver:reset_stream(SocketData#socket_state.receiver).
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ send({http_poll, FsmRef}, Packet) ->
|
|||||||
setopts({http_poll, FsmRef}, Opts) ->
|
setopts({http_poll, FsmRef}, Opts) ->
|
||||||
case lists:member({active, once}, Opts) of
|
case lists:member({active, once}, Opts) of
|
||||||
true ->
|
true ->
|
||||||
gen_fsm:sync_send_all_state_event(FsmRef, activate);
|
gen_fsm:send_all_state_event(FsmRef, {activate, self()});
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
@ -148,8 +148,9 @@ process_request(_Request) ->
|
|||||||
init([ID, Key]) ->
|
init([ID, Key]) ->
|
||||||
?INFO_MSG("started: ~p", [{ID, Key}]),
|
?INFO_MSG("started: ~p", [{ID, Key}]),
|
||||||
Opts = [], % TODO
|
Opts = [], % TODO
|
||||||
{ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_poll, self()}}, Opts),
|
ejabberd_socket:start(ejabberd_c2s, ?MODULE, {http_poll, self()}, Opts),
|
||||||
ejabberd_c2s:become_controller(C2SPid),
|
%{ok, C2SPid} = ejabberd_c2s:start({?MODULE, {http_poll, self()}}, Opts),
|
||||||
|
%ejabberd_c2s:become_controller(C2SPid),
|
||||||
Timer = erlang:start_timer(?HTTP_POLL_TIMEOUT, self(), []),
|
Timer = erlang:start_timer(?HTTP_POLL_TIMEOUT, self(), []),
|
||||||
{ok, loop, #state{id = ID,
|
{ok, loop, #state{id = ID,
|
||||||
key = Key,
|
key = Key,
|
||||||
@ -182,6 +183,20 @@ init([ID, Key]) ->
|
|||||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||||
%% {stop, Reason, NewStateData}
|
%% {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) ->
|
handle_event(Event, StateName, StateData) ->
|
||||||
{next_state, StateName, StateData}.
|
{next_state, StateName, StateData}.
|
||||||
|
|
||||||
@ -199,19 +214,6 @@ handle_sync_event({send, Packet}, From, StateName, StateData) ->
|
|||||||
Reply = ok,
|
Reply = ok,
|
||||||
{reply, Reply, StateName, StateData#state{output = Output}};
|
{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) ->
|
handle_sync_event(stop, From, StateName, StateData) ->
|
||||||
Reply = ok,
|
Reply = ok,
|
||||||
{stop, normal, Reply, StateData};
|
{stop, normal, Reply, StateData};
|
||||||
|
Loading…
Reference in New Issue
Block a user