aboutsummaryrefslogtreecommitdiff
path: root/src/mod_caps.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-12-11 15:03:37 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-12-11 15:03:37 +0300
commit5cc8e807df6994fa6b0e860bbcfe0af8fa7fe19f (patch)
treef10816cf358fce8744f87e722667683a623e22ec /src/mod_caps.erl
parentFix reload_config (diff)
Initial version of new XMPP stream behaviour (for review)
Diffstat (limited to 'src/mod_caps.erl')
-rw-r--r--src/mod_caps.erl150
1 files changed, 48 insertions, 102 deletions
diff --git a/src/mod_caps.erl b/src/mod_caps.erl
index 3a4492f5c..e2ec30305 100644
--- a/src/mod_caps.erl
+++ b/src/mod_caps.erl
@@ -35,10 +35,10 @@
-behaviour(gen_mod).
--export([read_caps/1, caps_stream_features/2,
+-export([read_caps/1, list_features/1, caps_stream_features/2,
disco_features/5, disco_identity/5, disco_info/5,
get_features/2, export/1, import_info/0, import/5,
- import_start/2, import_stop/2]).
+ get_user_caps/2, import_start/2, import_stop/2]).
%% gen_mod callbacks
-export([start/2, start_link/2, stop/1, depends/2]).
@@ -48,8 +48,7 @@
handle_cast/2, terminate/2, code_change/3]).
-export([user_send_packet/4, user_receive_packet/5,
- c2s_presence_in/2, c2s_filter_packet/6,
- c2s_broadcast_recipients/6, mod_opt_type/1]).
+ c2s_presence_in/2, mod_opt_type/1]).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -104,6 +103,22 @@ get_features(Host, #caps{node = Node, version = Version,
end,
[], SubNodes).
+-spec list_features(ejabberd_c2s:state()) -> [{ljid(), caps()}].
+list_features(C2SState) ->
+ Rs = maps:get(caps_features, C2SState, gb_trees:empty()),
+ gb_trees:to_list(Rs).
+
+-spec get_user_caps(jid(), ejabberd_c2s:state()) -> {ok, caps()} | error.
+get_user_caps(JID, C2SState) ->
+ Rs = maps:get(caps_features, C2SState, gb_trees:empty()),
+ LJID = jid:tolower(JID),
+ case gb_trees:lookup(LJID, Rs) of
+ {value, Caps} ->
+ {ok, Caps};
+ none ->
+ error
+ end.
+
-spec read_caps(#presence{}) -> nothing | caps().
read_caps(Presence) ->
case xmpp:get_subtag(Presence, #caps{}) of
@@ -194,87 +209,40 @@ disco_info(Acc, Host, Module, Node, Lang) when is_atom(Module) ->
disco_info(Acc, _, _, _Node, _Lang) ->
Acc.
--spec c2s_presence_in(ejabberd_c2s:state(), {jid(), jid(), presence()}) ->
- ejabberd_c2s:state().
+-spec c2s_presence_in(ejabberd_c2s:state(), presence()) -> ejabberd_c2s:state().
c2s_presence_in(C2SState,
- {From, To, #presence{type = Type} = Presence}) ->
- Subscription = ejabberd_c2s:get_subscription(From,
- C2SState),
+ #presence{from = From, to = To, type = Type} = Presence) ->
+ Subscription = ejabberd_c2s:get_subscription(From, C2SState),
Insert = (Type == available)
and ((Subscription == both) or (Subscription == to)),
Delete = (Type == unavailable) or (Type == error),
if Insert or Delete ->
- LFrom = jid:tolower(From),
- Rs = case ejabberd_c2s:get_aux_field(caps_resources,
- C2SState)
- of
- {ok, Rs1} -> Rs1;
- error -> gb_trees:empty()
- end,
- Caps = read_caps(Presence),
- NewRs = case Caps of
- nothing when Insert == true -> Rs;
- _ when Insert == true ->
- case gb_trees:lookup(LFrom, Rs) of
- {value, Caps} -> Rs;
- none ->
- ejabberd_hooks:run(caps_add, To#jid.lserver,
- [From, To,
- get_features(To#jid.lserver, Caps)]),
- gb_trees:insert(LFrom, Caps, Rs);
- _ ->
- ejabberd_hooks:run(caps_update, To#jid.lserver,
- [From, To,
- get_features(To#jid.lserver, Caps)]),
- gb_trees:update(LFrom, Caps, Rs)
- end;
- _ -> gb_trees:delete_any(LFrom, Rs)
- end,
- ejabberd_c2s:set_aux_field(caps_resources, NewRs,
- C2SState);
- true -> C2SState
+ LFrom = jid:tolower(From),
+ Rs = maps:get(caps_resources, C2SState, gb_trees:empty()),
+ Caps = read_caps(Presence),
+ NewRs = case Caps of
+ nothing when Insert == true -> Rs;
+ _ when Insert == true ->
+ case gb_trees:lookup(LFrom, Rs) of
+ {value, Caps} -> Rs;
+ none ->
+ ejabberd_hooks:run(caps_add, To#jid.lserver,
+ [From, To,
+ get_features(To#jid.lserver, Caps)]),
+ gb_trees:insert(LFrom, Caps, Rs);
+ _ ->
+ ejabberd_hooks:run(caps_update, To#jid.lserver,
+ [From, To,
+ get_features(To#jid.lserver, Caps)]),
+ gb_trees:update(LFrom, Caps, Rs)
+ end;
+ _ -> gb_trees:delete_any(LFrom, Rs)
+ end,
+ C2SState#{caps_resources := NewRs};
+ true ->
+ C2SState
end.
--spec c2s_filter_packet(boolean(), binary(), ejabberd_c2s:state(),
- {pep_message, binary()}, jid(), stanza()) ->
- boolean().
-c2s_filter_packet(InAcc, Host, C2SState, {pep_message, Feature}, To, _Packet) ->
- case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of
- {ok, Rs} ->
- LTo = jid:tolower(To),
- case gb_trees:lookup(LTo, Rs) of
- {value, Caps} ->
- Drop = not lists:member(Feature, get_features(Host, Caps)),
- {stop, Drop};
- none ->
- {stop, true}
- end;
- _ -> InAcc
- end;
-c2s_filter_packet(Acc, _, _, _, _, _) -> Acc.
-
--spec c2s_broadcast_recipients([ljid()], binary(), ejabberd_c2s:state(),
- {pep_message, binary()}, jid(), stanza()) ->
- [ljid()].
-c2s_broadcast_recipients(InAcc, Host, C2SState,
- {pep_message, Feature}, _From, _Packet) ->
- case ejabberd_c2s:get_aux_field(caps_resources,
- C2SState)
- of
- {ok, Rs} ->
- gb_trees_fold(fun (USR, Caps, Acc) ->
- case lists:member(Feature,
- get_features(Host, Caps))
- of
- true -> [USR | Acc];
- false -> Acc
- end
- end,
- InAcc, Rs);
- _ -> InAcc
- end;
-c2s_broadcast_recipients(Acc, _, _, _, _, _) -> Acc.
-
-spec depends(binary(), gen_mod:opts()) -> [{module(), hard | soft}].
depends(_Host, _Opts) ->
[].
@@ -292,15 +260,11 @@ init([Host, Opts]) ->
[{max_size, MaxSize}, {life_time, LifeTime}]),
ejabberd_hooks:add(c2s_presence_in, Host, ?MODULE,
c2s_presence_in, 75),
- ejabberd_hooks:add(c2s_filter_packet, Host, ?MODULE,
- c2s_filter_packet, 75),
- ejabberd_hooks:add(c2s_broadcast_recipients, Host,
- ?MODULE, c2s_broadcast_recipients, 75),
ejabberd_hooks:add(user_send_packet, Host, ?MODULE,
user_send_packet, 75),
ejabberd_hooks:add(user_receive_packet, Host, ?MODULE,
user_receive_packet, 75),
- ejabberd_hooks:add(c2s_stream_features, Host, ?MODULE,
+ ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE,
caps_stream_features, 75),
ejabberd_hooks:add(s2s_stream_features, Host, ?MODULE,
caps_stream_features, 75),
@@ -325,15 +289,11 @@ terminate(_Reason, State) ->
Host = State#state.host,
ejabberd_hooks:delete(c2s_presence_in, Host, ?MODULE,
c2s_presence_in, 75),
- ejabberd_hooks:delete(c2s_filter_packet, Host, ?MODULE,
- c2s_filter_packet, 75),
- ejabberd_hooks:delete(c2s_broadcast_recipients, Host,
- ?MODULE, c2s_broadcast_recipients, 75),
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE,
user_send_packet, 75),
ejabberd_hooks:delete(user_receive_packet, Host,
?MODULE, user_receive_packet, 75),
- ejabberd_hooks:delete(c2s_stream_features, Host,
+ ejabberd_hooks:delete(c2s_post_auth_features, Host,
?MODULE, caps_stream_features, 75),
ejabberd_hooks:delete(s2s_stream_features, Host,
?MODULE, caps_stream_features, 75),
@@ -494,20 +454,6 @@ concat_xdata_fields(#xdata{fields = Fields} = X) ->
is_binary(Var), Var /= <<"FORM_TYPE">>],
[Form, $<, lists:sort(Res)].
--spec gb_trees_fold(fun((_, _, T) -> T), T, gb_trees:tree()) -> T.
-gb_trees_fold(F, Acc, Tree) ->
- Iter = gb_trees:iterator(Tree),
- gb_trees_fold_iter(F, Acc, Iter).
-
--spec gb_trees_fold_iter(fun((_, _, T) -> T), T, gb_trees:iter()) -> T.
-gb_trees_fold_iter(F, Acc, Iter) ->
- case gb_trees:next(Iter) of
- {Key, Val, NewIter} ->
- NewAcc = F(Key, Val, Acc),
- gb_trees_fold_iter(F, NewAcc, NewIter);
- _ -> Acc
- end.
-
-spec now_ts() -> integer().
now_ts() ->
p1_time_compat:system_time(seconds).