From cabc0995c0e0964ecbef18470c6a483022879071 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 4 Oct 2010 06:04:19 +0200 Subject: Major reorganisation of the core, still unfinished... --- src/core/ephraim_roster.erl | 148 ++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 66 deletions(-) (limited to 'src/core/ephraim_roster.erl') 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}. -- cgit v1.2.3