Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-12-11 18:24:51 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-12-11 18:24:51 +0300
commit7f653cfe762ecf33ae9522b8df25f2902d5546df (patch)
tree53698cee80c834570768b119edfb4d7a0bf71d7e /src/ejabberd_c2s.erl
parent5cc8e807df6994fa6b0e860bbcfe0af8fa7fe19f (diff)
Rewrite ejabberd_service to use new XMPP stream API
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r--src/ejabberd_c2s.erl137
1 files changed, 74 insertions, 63 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 1568d5db6..b5113c34b 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -21,20 +21,24 @@
%%%-------------------------------------------------------------------
-module(ejabberd_c2s).
-behaviour(xmpp_stream_in).
+-behaviour(ejabberd_config).
-protocol({rfc, 6121}).
%% ejabberd_socket callbacks
-export([start/2, socket_type/0]).
+%% ejabberd_config callbacks
+-export([opt_type/1, transform_listen_option/2]).
%% xmpp_stream_in callbacks
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
--export([tls_options/1, tls_required/1, sasl_mechanisms/1, init_sasl/1, bind/2,
+-export([tls_options/1, tls_required/1, compress_methods/1,
+ sasl_mechanisms/1, init_sasl/1, bind/2, handshake/2,
unauthenticated_stream_features/1, authenticated_stream_features/1,
handle_stream_start/1, handle_stream_end/1, handle_stream_close/1,
handle_unauthenticated_packet/2, handle_authenticated_packet/2,
- handle_auth_success/4, handle_auth_failure/4,
- handle_unbinded_packet/2]).
+ handle_auth_success/4, handle_auth_failure/4, handle_send/5,
+ handle_unbinded_packet/2, handle_cdata/2]).
%% API
-export([get_presence/1, get_subscription/2, get_subscribed/1,
send/2, close/1]).
@@ -99,8 +103,7 @@ send(State, Pkt) ->
%%%===================================================================
%%% xmpp_stream_in callbacks
%%%===================================================================
-tls_options(#{server := Server, tls_options := TLSOpts}) ->
- LServer = jid:nameprep(Server),
+tls_options(#{lserver := LServer, tls_options := TLSOpts}) ->
case ejabberd_config:get_option({domain_certfile, LServer},
fun iolist_to_binary/1) of
undefined ->
@@ -112,19 +115,21 @@ tls_options(#{server := Server, tls_options := TLSOpts}) ->
tls_required(#{tls_required := TLSRequired}) ->
TLSRequired.
-unauthenticated_stream_features(#{server := Server}) ->
- LServer = jid:nameprep(Server),
+compress_methods(#{zlib := true}) ->
+ [<<"zlib">>];
+compress_methods(_) ->
+ [].
+
+sasl_mechanisms(#{lserver := LServer}) ->
+ cyrsasl:listmech(LServer).
+
+unauthenticated_stream_features(#{lserver := LServer}) ->
ejabberd_hooks:run_fold(c2s_pre_auth_features, LServer, [], [LServer]).
-authenticated_stream_features(#{server := Server}) ->
- LServer = jid:nameprep(Server),
+authenticated_stream_features(#{lserver := LServer}) ->
ejabberd_hooks:run_fold(c2s_post_auth_features, LServer, [], [LServer]).
-sasl_mechanisms(#{server := Server}) ->
- cyrsasl:listmech(jid:nameprep(Server)).
-
-init_sasl(#{server := Server}) ->
- LServer = jid:nameprep(Server),
+init_sasl(#{lserver := LServer}) ->
cyrsasl:server_new(
<<"jabber">>, LServer, <<"">>, [],
fun(U) ->
@@ -147,8 +152,11 @@ bind(R, #{user := U, server := S} = State) ->
open_session(State, Resource)
end.
-handle_stream_start(#{server := Server, ip := IP, lang := Lang} = State) ->
- LServer = jid:nameprep(Server),
+handshake(_Data, State) ->
+ %% This is only for jabber component
+ {ok, State}.
+
+handle_stream_start(#{lserver := LServer, ip := IP, lang := Lang} = State) ->
case lists:member(LServer, ?MYHOSTS) of
false ->
xmpp_stream_in:send(State, xmpp:serr_host_unknown());
@@ -172,8 +180,7 @@ handle_stream_close(State) ->
{stop, normal, State}.
handle_auth_success(User, Mech, AuthModule,
- #{socket := Socket, ip := IP, server := Server} = State) ->
- LServer = jid:nameprep(Server),
+ #{socket := Socket, ip := IP, lserver := LServer} = State) ->
?INFO_MSG("(~w) Accepted ~s authentication for ~s@~s by ~p from ~s",
[Socket, Mech, User, LServer, AuthModule,
ejabberd_config:may_hide_data(jlib:ip_to_list(IP))]),
@@ -182,8 +189,7 @@ handle_auth_success(User, Mech, AuthModule,
{noreply, State1}, [true, User]).
handle_auth_failure(User, Mech, Reason,
- #{socket := Socket, ip := IP, server := Server} = State) ->
- LServer = jid:nameprep(Server),
+ #{socket := Socket, ip := IP, lserver := LServer} = State) ->
?INFO_MSG("(~w) Failed ~s authentication ~sfrom ~s: ~s",
[Socket, Mech,
if User /= <<"">> -> ["for ", User, "@", LServer, " "];
@@ -193,22 +199,18 @@ handle_auth_failure(User, Mech, Reason,
ejabberd_hooks:run_fold(c2s_auth_result, LServer,
{noreply, State}, [false, User]).
-handle_unbinded_packet(Pkt, #{server := Server} = State) ->
- LServer = jid:nameprep(Server),
+handle_unbinded_packet(Pkt, #{lserver := LServer} = State) ->
ejabberd_hooks:run_fold(c2s_unbinded_packet, LServer,
{noreply, State}, [Pkt]).
-handle_unauthenticated_packet(Pkt, #{server := Server} = State) ->
- LServer = jid:nameprep(Server),
+handle_unauthenticated_packet(Pkt, #{lserver := LServer} = State) ->
ejabberd_hooks:run_fold(c2s_unauthenticated_packet,
LServer, {noreply, State}, [Pkt]).
-handle_authenticated_packet(Pkt, #{server := Server} = State) when not ?is_stanza(Pkt) ->
- LServer = jid:nameprep(Server),
+handle_authenticated_packet(Pkt, #{lserver := LServer} = State) when not ?is_stanza(Pkt) ->
ejabberd_hooks:run_fold(c2s_authenticated_packet,
LServer, {noreply, State}, [Pkt]);
-handle_authenticated_packet(Pkt, #{server := Server} = State) ->
- LServer = jid:nameprep(Server),
+handle_authenticated_packet(Pkt, #{lserver := LServer} = State) ->
case ejabberd_hooks:run_fold(c2s_authenticated_packet,
LServer, {noreply, State}, [Pkt]) of
{noreply, State1} ->
@@ -228,6 +230,14 @@ handle_authenticated_packet(Pkt, #{server := Server} = State) ->
Err
end.
+handle_cdata(Data, #{lserver := LServer} = State) ->
+ ejabberd_hooks:run_fold(c2s_handle_cdata, LServer,
+ {noreply, State}, [Data]).
+
+handle_send(Reason, Pkt, El, Data, #{lserver := LServer} = State) ->
+ ejabberd_hooks:run_fold(c2s_handle_send, LServer,
+ {noreply, State}, [Reason, Pkt, El, Data]).
+
init([State, Opts]) ->
Access = gen_mod:get_opt(access, Opts, fun acl:access_rules_validator/1, all),
Shaper = gen_mod:get_opt(shaper, Opts, fun acl:shaper_rules_validator/1, none),
@@ -239,6 +249,7 @@ init([State, Opts]) ->
end, Opts),
TLSRequired = proplists:get_bool(starttls_required, Opts),
TLSVerify = proplists:get_bool(tls_verify, Opts),
+ Zlib = proplists:get_bool(zlib, Opts),
State1 = State#{tls_options => TLSOpts,
tls_required => TLSRequired,
tls_verify => TLSVerify,
@@ -246,19 +257,18 @@ init([State, Opts]) ->
pres_f => ?SETS:new(),
pres_t => ?SETS:new(),
sid => ejabberd_sm:make_sid(),
+ zlib => Zlib,
lang => ?MYLANG,
server => ?MYNAME,
access => Access,
shaper => Shaper},
ejabberd_hooks:run_fold(c2s_init, {ok, State1}, []).
-handle_call(get_presence, _From,
- #{user := U, server := S, resource := R} = State) ->
+handle_call(get_presence, _From, #{jid := JID} = State) ->
Pres = case maps:get(pres_last, State, undefined) of
undefined ->
- From = jid:make(U, S, R),
- To = jid:remove_resource(From),
- #presence{from = From, to = To, type = unavailable};
+ BareJID = jid:remove_resource(JID),
+ #presence{from = JID, to = BareJID, type = unavailable};
P ->
P
end,
@@ -266,20 +276,17 @@ handle_call(get_presence, _From,
handle_call(get_subscribed, _From, #{pres_f := PresF} = State) ->
Subscribed = ?SETS:to_list(PresF),
{reply, Subscribed, State};
-handle_call(Request, From, #{server := Server} = State) ->
- LServer = jid:nameprep(Server),
+handle_call(Request, From, #{lserver := LServer} = State) ->
ejabberd_hooks:run_fold(
c2s_handle_call, LServer, {noreply, State}, [Request, From]).
handle_cast(closed, State) ->
handle_stream_close(State);
-handle_cast(Msg, #{server := Server} = State) ->
- LServer = jid:nameprep(Server),
+handle_cast(Msg, #{lserver := LServer} = State) ->
ejabberd_hooks:run_fold(c2s_handle_cast, LServer, {noreply, State}, [Msg]).
-handle_info({route, From, To, Packet0}, #{server := Server} = State) ->
+handle_info({route, From, To, Packet0}, #{lserver := LServer} = State) ->
Packet = xmpp:set_from_to(Packet0, From, To),
- LServer = jid:nameprep(Server),
{Pass, NewState} = case Packet of
#presence{} ->
process_presence_in(State, Packet);
@@ -289,7 +296,6 @@ handle_info({route, From, To, Packet0}, #{server := Server} = State) ->
process_iq_in(State, Packet)
end,
if Pass ->
- LServer = jid:nameprep(Server),
Packet1 = ejabberd_hooks:run_fold(
user_receive_packet, LServer, Packet, [NewState]),
ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]),
@@ -300,8 +306,7 @@ handle_info({route, From, To, Packet0}, #{server := Server} = State) ->
end;
handle_info(system_shutdown, State) ->
xmpp_stream_in:send(State, xmpp:serr_system_shutdown());
-handle_info(Info, #{server := Server} = State) ->
- LServer = jid:nameprep(Server),
+handle_info(Info, #{lserver := LServer} = State) ->
ejabberd_hooks:run_fold(c2s_handle_info, LServer, {noreply, State}, [Info]).
terminate(_Reason, _State) ->
@@ -319,11 +324,10 @@ check_bl_c2s({IP, _Port}, Lang) ->
ejabberd_hooks:run_fold(check_bl_c2s, false, [IP, Lang]).
-spec open_session(state(), binary()) -> {ok, state()} | {error, stanza_error(), state()}.
-open_session(#{user := U, server := S, sid := SID,
+open_session(#{user := U, server := S, lserver := LServer, sid := SID,
socket := Socket, ip := IP, auth_module := AuthMod,
access := Access, lang := Lang} = State, R) ->
JID = jid:make(U, S, R),
- LServer = JID#jid.lserver,
case acl:access_matches(Access,
#{usr => jid:split(JID), ip => IP},
LServer) of
@@ -374,9 +378,8 @@ process_message_in(State, #message{type = T} = Msg) ->
end.
-spec process_presence_in(state(), presence()) -> {boolean(), state()}.
-process_presence_in(#{server := Server, pres_a := PresA} = State0,
+process_presence_in(#{lserver := LServer, pres_a := PresA} = State0,
#presence{from = From, to = To, type = T} = Pres) ->
- LServer = jid:nameprep(Server),
State = ejabberd_hooks:run_fold(c2s_presence_in, LServer, State0, [Pres]),
case T of
probe ->
@@ -399,7 +402,7 @@ process_presence_in(#{server := Server, pres_a := PresA} = State0,
end.
-spec route_probe_reply(jid(), jid(), state()) -> ok.
-route_probe_reply(From, To, #{server := Server, pres_f := PresF,
+route_probe_reply(From, To, #{lserver := LServer, pres_f := PresF,
pres_last := LastPres,
pres_timestamp := TS} = State) ->
LFrom = jid:tolower(From),
@@ -413,7 +416,6 @@ route_probe_reply(From, To, #{server := Server, pres_f := PresF,
deny ->
ok;
allow ->
- LServer = jid:nameprep(Server),
ejabberd_hooks:run(presence_probe_hook,
LServer,
[From, To, self()]),
@@ -432,10 +434,9 @@ route_probe_reply(_, _, _) ->
ok.
-spec process_presence_out(state(), presence()) -> next_state().
-process_presence_out(#{user := User, server := Server,
- lang := Lang, pres_a := PresA} = State,
+process_presence_out(#{user := User, server := Server, lserver := LServer,
+ jid := JID, lang := Lang, pres_a := PresA} = State,
#presence{from = From, to = To, type = Type} = Pres) ->
- LServer = jid:nameprep(Server),
LTo = jid:tolower(To),
case privacy_check_packet(State, Pres, out) of
deny ->
@@ -448,7 +449,7 @@ process_presence_out(#{user := User, server := Server,
Access = gen_mod:get_module_opt(LServer, mod_roster, access,
fun(A) when is_atom(A) -> A end,
all),
- MyBareJID = jid:make(User, Server, <<"">>),
+ MyBareJID = jid:remove_resource(JID),
case acl:match_rule(LServer, Access, MyBareJID) of
deny ->
ErrText = <<"Denied by ACL">>,
@@ -485,9 +486,8 @@ process_self_presence(#{ip := IP, conn := Conn,
State1 = broadcast_presence_unavailable(State, Pres),
State2 = maps:remove(pres_last, maps:remove(pres_timestamp, State1)),
{noreply, State2};
-process_self_presence(#{server := Server} = State,
+process_self_presence(#{lserver := LServer} = State,
#presence{type = available} = Pres) ->
- LServer = jid:nameprep(Server),
PreviousPres = maps:get(pres_last, State, undefined),
update_priority(State, Pres),
State1 = ejabberd_hooks:run_fold(user_available_hook, LServer, State, [Pres]),
@@ -543,8 +543,7 @@ check_privacy_then_route(#{lang := Lang} = State, Pkt) ->
end.
-spec privacy_check_packet(state(), stanza(), in | out) -> allow | deny.
-privacy_check_packet(#{server := Server} = State, Pkt, Dir) ->
- LServer = jid:nameprep(Server),
+privacy_check_packet(#{lserver := LServer} = State, Pkt, Dir) ->
ejabberd_hooks:run_fold(privacy_check_packet, LServer, allow, [State, Pkt, Dir]).
-spec get_priority_from_presence(presence()) -> integer().
@@ -555,9 +554,7 @@ get_priority_from_presence(#presence{priority = Prio}) ->
end.
-spec filter_blocked(state(), presence(), ?SETS:set()) -> [jid()].
-filter_blocked(#{user := U, server := S, resource := R} = State,
- Pres, LJIDSet) ->
- From = jid:make(U, S, R),
+filter_blocked(#{jid := From} = State, Pres, LJIDSet) ->
?SETS:fold(
fun(LJID, Acc) ->
To = jid:make(LJID),
@@ -581,8 +578,7 @@ route_error(Pkt, Err) ->
ejabberd_router:route_error(To, From, Pkt, Err).
-spec route_multiple(state(), [jid()], stanza()) -> ok.
-route_multiple(#{server := Server}, JIDs, Pkt) ->
- LServer = jid:nameprep(Server),
+route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
From = xmpp:get_from(Pkt),
ejabberd_router_multicast:route_multicast(From, LServer, JIDs, Pkt).
@@ -636,9 +632,9 @@ get_conn_type(State) ->
end.
-spec change_shaper(state()) -> ok.
-change_shaper(#{shaper := ShaperName, ip := IP,
+change_shaper(#{shaper := ShaperName, ip := IP, lserver := LServer,
user := U, server := S, resource := R} = State) ->
- #jid{lserver = LServer} = JID = jid:make(U, S, R),
+ JID = jid:make(U, S, R),
Shaper = acl:access_matches(ShaperName,
#{usr => jid:split(JID), ip => IP},
LServer),
@@ -680,3 +676,18 @@ fsm_limit_opts(Opts) ->
N -> [{max_queue, N}]
end
end.
+
+transform_listen_option(Opt, Opts) ->
+ [Opt|Opts].
+
+opt_type(domain_certfile) -> fun iolist_to_binary/1;
+opt_type(max_fsm_queue) ->
+ fun (I) when is_integer(I), I > 0 -> I end;
+opt_type(resource_conflict) ->
+ fun (setresource) -> setresource;
+ (closeold) -> closeold;
+ (closenew) -> closenew;
+ (acceptnew) -> acceptnew
+ end;
+opt_type(_) ->
+ [domain_certfile, max_fsm_queue, resource_conflict].