summaryrefslogtreecommitdiffstats
path: root/src/core/ephraim_roster.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ephraim_roster.erl')
-rw-r--r--src/core/ephraim_roster.erl148
1 files changed, 82 insertions, 66 deletions
diff --git a/src/core/ephraim_roster.erl b/src/core/ephraim_roster.erl
index 502497f..f111f38 100644
--- a/src/core/ephraim_roster.erl
+++ b/src/core/ephraim_roster.erl
@@ -1,9 +1,15 @@
-module(ephraim_roster).
--compile([debug_info, export_all]).
-include_lib("exmpp/include/exmpp.hrl").
+-behaviour(gen_server).
--record(roster, {
- entries :: dict()
+-export([start_link/2]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+-export([presence/2, roster_iq/2, vcard_iq/3]).
+
+-record(roster_state, {
+ event_manager :: pid(),
+ connection :: pid(),
+ entries :: dict()
}).
-record(avatar, {
@@ -25,16 +31,23 @@
status :: binary()
}).
--spec init() -> ok.
-init() ->
- loop(#roster{entries=dict:new()}).
--spec updateResource(#roster{}, binary(), integer(), atom(), atom(), binary()) -> #roster{}.
+start_link(EventManager, Connection) ->
+ gen_server:start_link(?MODULE, {EventManager, Connection}, []).
+
+%-spec init() -> ok.
+init({EventManager, Connection}) ->
+ process_flag(trap_exit, true),
+
+ ephraim_roster_handler:start(EventManager, self()),
+ {ok, #roster_state{event_manager=EventManager,connection=Connection,entries=dict:new()}}.
+
+-spec updateResource(#roster_state{}, binary(), integer(), atom(), atom(), binary()) -> #roster_state{}.
updateResource(Roster, JID, Priority, Type, Show, Status) ->
{Node, Domain, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)),
BareJID = list_to_binary([Node, <<"@">>, Domain]),
- RosterEntry = case dict:find(BareJID, Roster#roster.entries) of
+ RosterEntry = case dict:find(BareJID, Roster#roster_state.entries) of
{ok, Entry} ->
Entry;
error ->
@@ -52,28 +65,28 @@ updateResource(Roster, JID, Priority, Type, Show, Status) ->
end,
NewEntry = RosterEntry#roster_entry{resources=Resources},
- Entries = dict:store(BareJID, NewEntry, Roster#roster.entries),
- uiUpdate(BareJID, NewEntry),
+ Entries = dict:store(BareJID, NewEntry, Roster#roster_state.entries),
+ viewUpdate(Roster, BareJID, NewEntry),
- Roster#roster{entries=Entries}.
+ Roster#roster_state{entries=Entries}.
--spec updateRosterEntry(#roster{}, binary(), binary(), atom(), set()) -> #roster{}.
+-spec updateRosterEntry(#roster_state{}, binary(), binary(), atom(), set()) -> #roster_state{}.
updateRosterEntry(Roster, JID, Name, Subscription, Groups) ->
- OldEntry = case dict:find(JID, Roster#roster.entries) of
+ OldEntry = case dict:find(JID, Roster#roster_state.entries) of
{ok, Entry} ->
Entry;
error ->
#roster_entry{}
end,
NewEntry = OldEntry#roster_entry{subscription=Subscription,name=Name,groups=Groups},
- Entries = dict:store(JID, NewEntry, Roster#roster.entries),
- uiUpdate(JID, NewEntry),
+ Entries = dict:store(JID, NewEntry, Roster#roster_state.entries),
+ viewUpdate(Roster, JID, NewEntry),
- Roster#roster{entries=Entries}.
+ Roster#roster_state{entries=Entries}.
--spec updateVCard(#roster{}, binary(), dict()) -> #roster{}.
+-spec updateVCard(#roster_state{}, binary(), dict()) -> #roster_state{}.
updateVCard(Roster, JID, VCard) ->
- OldEntry = case dict:find(JID, Roster#roster.entries) of
+ OldEntry = case dict:find(JID, Roster#roster_state.entries) of
{ok, Entry} ->
Entry;
error ->
@@ -89,19 +102,19 @@ updateVCard(Roster, JID, VCard) ->
NewEntry = OldEntry#roster_entry{vcard=VCard,avatar=Avatar},
- Entries = dict:store(JID, NewEntry, Roster#roster.entries),
- uiUpdate(JID, NewEntry),
+ Entries = dict:store(JID, NewEntry, Roster#roster_state.entries),
+ viewUpdate(Roster, JID, NewEntry),
- Roster#roster{entries=Entries}.
+ Roster#roster_state{entries=Entries}.
--spec uiUpdate(binary(), #roster_entry{}) -> ok.
-uiUpdate(JID, RosterEntry) ->
+-spec viewUpdate(#roster_state{}, binary(), #roster_entry{}) -> ok.
+viewUpdate(State, JID, RosterEntry) ->
if RosterEntry#roster_entry.subscription =:= undefined ->
ok;
true ->
- ephraim ! {ui_update, {roster_update, JID, RosterEntry#roster_entry.name, RosterEntry#roster_entry.subscription,
- sets:to_list(RosterEntry#roster_entry.groups), dict:to_list(RosterEntry#roster_entry.resources),
- RosterEntry#roster_entry.avatar}},
+ gen_event:notify(State#roster_state.event_manager, {view_update, {roster_update, JID, RosterEntry#roster_entry.name, RosterEntry#roster_entry.subscription,
+ sets:to_list(RosterEntry#roster_entry.groups), dict:to_list(RosterEntry#roster_entry.resources),
+ RosterEntry#roster_entry.avatar}}),
ok
end.
@@ -117,18 +130,18 @@ getGroups(Groups, [#xmlel{ns='jabber:iq:roster',name=group,children=[#xmlcdata{c
getGroups(Groups, [_|Rest]) ->
getGroups(Groups, Rest).
--spec handleRosterIQ(#roster{}, #xmlel{}) -> #roster{}.
+-spec handleRosterIQ(#roster_state{}, #xmlel{}) -> #roster_state{}.
handleRosterIQ(Roster, Item) ->
JID = exmpp_xml:get_attribute(Item, jid, undefined),
Name = exmpp_xml:get_attribute(Item, name, undefined),
Groups = getGroups(Item#xmlel.children),
Subscription = binary_to_atom(exmpp_xml:get_attribute(Item, subscription, undefined), utf8),
- ephraim ! {send_packet, exmpp_stanza:set_recipient(exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'}), JID)},
+ ephraim_conn:send_packet(Roster#roster_state.connection, exmpp_stanza:set_recipient(exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'}), JID)),
updateRosterEntry(Roster, JID, Name, Subscription, Groups).
--spec handleRosterIQs(#roster{}, [#xmlel{}]) -> #roster{}.
+-spec handleRosterIQs(#roster_state{}, [#xmlel{}]) -> #roster_state{}.
handleRosterIQs(Roster, []) ->
Roster;
@@ -161,12 +174,12 @@ handleVCardIQs(VCard, [Item|Rest]) ->
VCard2 = handleVCardIQ(VCard, Item),
handleVCardIQs(VCard2, Rest).
--spec get_alias(#roster{}, binary()) -> binary().
+-spec get_alias(#roster_state{}, binary()) -> binary().
get_alias(Roster, JID) ->
{Node, Domain, _Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)),
BareJID = list_to_binary([Node, <<"@">>, Domain]),
- case dict:find(BareJID, Roster#roster.entries) of
+ case dict:find(BareJID, Roster#roster_state.entries) of
{ok, Entry} ->
case Entry#roster_entry.name of
undefined ->
@@ -183,38 +196,41 @@ get_alias(Roster, JID) ->
Node
end.
--spec loop(#roster{}) -> ok.
-loop(Roster) ->
- receive
- stop ->
- ok;
-
- {presence, Packet} ->
- %io:format("ephraim_roster: Presence: ~p~n", [Packet]),
- From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
-
- Priority = exmpp_presence:get_priority(Packet),
- Type = exmpp_presence:get_type(Packet),
- Show = exmpp_presence:get_show(Packet),
- Status = exmpp_presence:get_status(Packet),
-
- Roster2 = updateResource(Roster, From, Priority, Type, Show, Status),
- loop(Roster2);
-
- {roster_iq, Payload} ->
- Roster2 = handleRosterIQs(Roster, Payload#xmlel.children),
- loop(Roster2);
-
- {vcard_iq, From, Payload} ->
- Dict = handleVCardIQs(dict:new(), Payload#xmlel.children),
- Roster2 = updateVCard(Roster, From, Dict),
- loop(Roster2);
-
- {Pid, get_alias, JID} ->
- Pid ! {alias,JID,get_alias(Roster, JID)},
- loop(Roster);
-
- Msg ->
- io:format("ephraim_roster: ~p~n", [Msg]),
- loop(Roster)
- end.
+presence(Roster, Packet) ->
+ gen_server:cast(Roster, {presence, Packet}).
+roster_iq(Roster, Payload) ->
+ gen_server:cast(Roster, {roster_iq, Payload}).
+vcard_iq(Roster, From, Payload) ->
+ gen_server:cast(Roster, {vcard_iq, From, Payload}).
+
+handle_call(_Msg, _From, State) ->
+ {noreply, State}.
+
+handle_cast({presence, Packet}, State) ->
+ %io:format("ephraim_roster: Presence: ~p~n", [Packet]),
+ From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
+
+ Priority = exmpp_presence:get_priority(Packet),
+ Type = exmpp_presence:get_type(Packet),
+ Show = exmpp_presence:get_show(Packet),
+ Status = exmpp_presence:get_status(Packet),
+
+ State2 = updateResource(State, From, Priority, Type, Show, Status),
+ {noreply, State2};
+
+handle_cast({roster_iq, Payload}, State) ->
+ State2 = handleRosterIQs(State, Payload#xmlel.children),
+ {noreply, State2};
+
+handle_cast({vcard_iq, From, Payload}, State) ->
+ Dict = handleVCardIQs(dict:new(), Payload#xmlel.children),
+ State2 = updateVCard(State, From, Dict),
+ {noreply, State2}.
+
+handle_info(_Msg, State) ->
+ {noreply, State}.
+terminate(_Reason, State) ->
+ ephraim_roster_handler:stop(State#roster_state.event_manager),
+ ok.
+code_change(_OldVersion, State, _Extra) ->
+ {ok, State}.