diff options
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r-- | src/ejabberd_c2s.erl | 54 |
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; |