aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_c2s.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r--src/ejabberd_c2s.erl54
1 files changed, 42 insertions, 12 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index f60699727..725351950 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -18,7 +18,8 @@
send_text/2,
send_element/2,
socket_type/0,
- get_presence/1]).
+ get_presence/1,
+ get_subscribed_and_online/1]).
%% gen_fsm callbacks
-export([init/1,
@@ -39,6 +40,7 @@
-include("jlib.hrl").
-define(SETS, gb_sets).
+-define(DICT, dict).
-record(state, {socket,
sockmod,
@@ -60,6 +62,7 @@
pres_f = ?SETS:new(),
pres_a = ?SETS:new(),
pres_i = ?SETS:new(),
+ pres_available = ?DICT:new(),
pres_last, pres_pri,
pres_timestamp,
pres_invis = false,
@@ -173,6 +176,12 @@ init([{SockMod, Socket}, Opts]) ->
shaper = Shaper,
ip = IP}, ?C2S_OPEN_TIMEOUT}.
+%% Return list of all available resources of contacts,
+%% in form [{JID, Caps}].
+get_subscribed_and_online(FsmRef) ->
+ gen_fsm:sync_send_all_state_event(
+ FsmRef, get_subscribed_and_online, 1000).
+
%%----------------------------------------------------------------------
%% Func: StateName/2
@@ -572,7 +581,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
case xml:get_subtag(El, "method") of
false ->
send_element(StateData,
- {xmlelement, "failure",
+ {xmlelement, "failure",
[{"xmlns", ?NS_COMPRESS}],
[{xmlelement, "setup-failed", [], []}]}),
fsm_next_state(wait_for_feature_request, StateData);
@@ -964,6 +973,17 @@ handle_sync_event({get_presence}, _From, StateName, StateData) ->
Reply = {User, Resource, Show, Status},
fsm_reply(Reply, StateName, StateData);
+handle_sync_event(get_subscribed_and_online, _From, StateName, StateData) ->
+ Subscribed = StateData#state.pres_f,
+ Online = StateData#state.pres_available,
+ Pred = fun(User, _Caps) ->
+ ?SETS:is_element(jlib:jid_remove_resource(User),
+ Subscribed) orelse
+ ?SETS:is_element(User, Subscribed)
+ end,
+ SubscribedAndOnline = ?DICT:filter(Pred, Online),
+ {reply, ?DICT:to_list(SubscribedAndOnline), StateName, StateData};
+
handle_sync_event(_Event, _From, StateName, StateData) ->
Reply = ok,
fsm_reply(Reply, StateName, StateData).
@@ -1054,32 +1074,42 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
allow ->
LFrom = jlib:jid_tolower(From),
LBFrom = jlib:jid_remove_resource(LFrom),
+ %% Note contact availability
+ Caps = mod_caps:read_caps(Els),
+ mod_caps:note_caps(StateData#state.server, From, Caps),
+ NewAvailable = case xml:get_attr_s("type", Attrs) of
+ "unavailable" ->
+ ?DICT:erase(LFrom, StateData#state.pres_available);
+ _ ->
+ ?DICT:store(LFrom, Caps, StateData#state.pres_available)
+ end,
+ NewStateData = StateData#state{pres_available = NewAvailable},
case ?SETS:is_element(
- LFrom, StateData#state.pres_a) orelse
+ LFrom, NewStateData#state.pres_a) orelse
?SETS:is_element(
- LBFrom, StateData#state.pres_a) of
+ LBFrom, NewStateData#state.pres_a) of
true ->
- {true, Attrs, StateData};
+ {true, Attrs, NewStateData};
false ->
case ?SETS:is_element(
- LFrom, StateData#state.pres_f) of
+ LFrom, NewStateData#state.pres_f) of
true ->
A = ?SETS:add_element(
LFrom,
- StateData#state.pres_a),
+ NewStateData#state.pres_a),
{true, Attrs,
- StateData#state{pres_a = A}};
+ NewStateData#state{pres_a = A}};
false ->
case ?SETS:is_element(
- LBFrom, StateData#state.pres_f) of
+ LBFrom, NewStateData#state.pres_f) of
true ->
A = ?SETS:add_element(
LBFrom,
- StateData#state.pres_a),
+ NewStateData#state.pres_a),
{true, Attrs,
- StateData#state{pres_a = A}};
+ NewStateData#state{pres_a = A}};
false ->
- {true, Attrs, StateData}
+ {true, Attrs, NewStateData}
end
end
end;