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/CMakeLists.txt | 6 +- src/core/ephraim.app | 6 ++ src/core/ephraim.erl | 167 ++++--------------------------- src/core/ephraim_account.erl | 17 ++++ src/core/ephraim_account_event_proxy.erl | 27 +++++ src/core/ephraim_accounts.erl | 11 ++ src/core/ephraim_config.erl | 3 +- src/core/ephraim_conn.erl | 96 +++++++++--------- src/core/ephraim_event.erl | 46 --------- src/core/ephraim_gui.erl | 62 +++++++----- src/core/ephraim_roster.erl | 148 +++++++++++++++------------ src/core/ephraim_roster_handler.erl | 45 +++++++++ src/core/ephraim_util.erl | 10 -- src/ephraim | 2 +- src/gui/CoreConnector.vala | 4 +- 15 files changed, 301 insertions(+), 349 deletions(-) create mode 100644 src/core/ephraim.app create mode 100644 src/core/ephraim_account.erl create mode 100644 src/core/ephraim_account_event_proxy.erl create mode 100644 src/core/ephraim_accounts.erl delete mode 100644 src/core/ephraim_event.erl create mode 100644 src/core/ephraim_roster_handler.erl delete mode 100644 src/core/ephraim_util.erl diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9c536aa..9baaeee 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,12 +1,14 @@ erl_target(ephraim-core ephraim.erl + ephraim_account.erl + ephraim_account_event_proxy.erl + ephraim_accounts.erl ephraim_config.erl ephraim_conn.erl ephraim_conv.erl - ephraim_event.erl ephraim_gui.erl ephraim_roster.erl - ephraim_util.erl + ephraim_roster_handler.erl OPTIONS +debug_info ) diff --git a/src/core/ephraim.app b/src/core/ephraim.app new file mode 100644 index 0000000..c3a5a9f --- /dev/null +++ b/src/core/ephraim.app @@ -0,0 +1,6 @@ +{application, ephraim, + [{vsn, "1"}, + {modules, [ephraim, ephraim_config]}, + {applications, [kernel, stdlib, exmpp]}, + {mod, {ephraim,[]}} + ]}. diff --git a/src/core/ephraim.erl b/src/core/ephraim.erl index 61387a5..c0736c6 100644 --- a/src/core/ephraim.erl +++ b/src/core/ephraim.erl @@ -1,152 +1,27 @@ -module(ephraim). --compile([debug_info, export_all]). +-behaviour(application). +-behaviour(supervisor). +-export([start/2, stop/1]). +-export([init/1]). +-export([notify/1]). --record(state, { - conn :: pid(), - roster :: pid(), - event :: pid(), - gui :: pid(), - convs :: dict(), - uis :: set() - }). +%-spec start() -> ok. +start(_Type, _Args) -> + Result = supervisor:start_link(?MODULE, []), + ephraim_gui:start(), + Result. --spec start() -> ok. -start() -> - spawn(?MODULE, init, []), +%-spec stop() -> ok. +stop(_State) -> ok. --spec stop() -> ok. -stop() -> - ephraim ! stop, - ok. - --spec init() -> ok. -init() -> - register(ephraim, self()), - - ephraim_config:start_link(), - - GUI = spawn(ephraim_gui, init, []), - Conn = spawn(ephraim_conn, init, []), - Roster = spawn(ephraim_roster, init, []), - Event = spawn(ephraim_event, init, []), - loop(#state{conn=Conn,roster=Roster,event=Event,gui=GUI,convs=dict:new(),uis=sets:new()}), - init:stop(). - --spec get_conv(#state{},exmpp_jid:jid()) -> {#state{},pid()|undefined}. -get_conv(State, JID) -> - {Node, Domain, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)), - - case Resource of - undefined -> - {State, undefined}; - _ -> - Key = list_to_binary([Node, <<"@">>, Domain, <<"/">>, Resource]), - - case dict:find(Key, State#state.convs) of - {ok, Conv} -> - {State, Conv}; - error -> - Conv = spawn(ephraim_conv, init, [Key]), - Dict = dict:store(Key, Conv, State#state.convs), - self() ! {ui_update, {new_conversation, Key}}, - {State#state{convs=Dict}, Conv} - end - end. - --spec get_alias(binary()) -> binary(). -get_alias(JID) -> - ephraim ! {self(),get_alias,JID}, - receive - {alias,JID,Alias} -> - Alias - end. +-spec init(term()) -> ok. +init(_Args) -> + {ok, {{rest_for_one, 1, 60}, + [{event_man, {gen_event, start_link, [{local, ephraim_event_man}]}, permanent, 1000, worker, [gen_event]}, + {config, {ephraim_config, start_link, []}, permanent, 1000, worker, [ephraim_config]}, + {accounts, {ephraim_accounts, start_link, []}, permanent, infinity, supervisor, [ephraim_accounts]}]}}. --spec loop(#state{}) -> ok. -loop(State) -> - receive - stop -> - ephraim_util:send_all_values(State#state.convs, stop), - State#state.conn ! stop, - State#state.roster ! stop, - State#state.event ! stop, - State#state.gui ! stop, - ok; - - {register_ui, Pid} -> - io:format("Registered UI ~p~n", [Pid]), - UIs = State#state.uis, - State2 = State#state{uis=sets:add_element(Pid,UIs)}, - loop(State2); - - {unregister_ui, Pid} -> - io:format("Unregistered UI ~p~n", [Pid]), - UIs = State#state.uis, - State2 = State#state{uis=sets:del_element(Pid,UIs)}, - Size = sets:size(State2#state.uis), - if Size =:= 0 -> - self() ! stop; - true -> - ok - end, - loop(State2); - - {ui_update, Msg} -> - ephraim_util:send_all(sets:to_list(State#state.uis), Msg), - loop(State); - - {roster, Packet} -> - State#state.roster ! Packet, - loop(State); - - {receive_message, From, Packet} -> - {State2, Conv} = get_conv(State, From), - case Conv of - undefined -> - io:format("~p~n", [Packet]); - _ -> - Conv ! {receive_message, Packet} - end, - loop(State2); - - {send_message, To, Type, Message} -> - {State2, Conv} = get_conv(State, To), - case Conv of - undefined -> - io:format("ephraim: send_message: ~p~n", [Message]); - _ -> - Conv ! {send_message, Type, Message} - end, - loop(State2); - - {start_conversation, To} -> - {State2, _Conv} = get_conv(State, To), - loop(State2); - - {send_packet, Packet} -> - State#state.conn ! {send_packet, Packet}, - loop(State); - - {receive_event, From, Packet} -> - State#state.event ! {receive_event, From, Packet}, - loop(State); - - {receive_iq, From, IQ} -> - case IQ of - {iq, response, result, _, 'jabber:iq:roster', Payload, _, _, 'jabber:client'} -> - State#state.roster ! {roster_iq, Payload}; - {iq, response, result, _, 'vcard-temp', Payload, _, _, 'jabber:client'} -> - State#state.roster ! {vcard_iq, From, Payload}; - _ -> - ok %io:format("ephraim: IQ from ~p: ~p~n", [From, IQ]) - end, - loop(State); - - {Pid, get_alias, JID} -> - State#state.roster ! {Pid,get_alias,JID}, - loop(State); - - Msg -> - io:format("ephraim: ~p~n", [Msg]), - loop(State) - end. +-spec notify(term()) -> ok. +notify(Event) -> + gen_event:notify(ephraim_event_man, Event). diff --git a/src/core/ephraim_account.erl b/src/core/ephraim_account.erl new file mode 100644 index 0000000..d79e118 --- /dev/null +++ b/src/core/ephraim_account.erl @@ -0,0 +1,17 @@ +-module(ephraim_account). +-behaviour(supervisor). +-export([start_link/0]). +-export([init/1]). + +start_link() -> + {ok, Pid} = supervisor:start_link(?MODULE, []), + + {ok, EventManager} = supervisor:start_child(Pid, {event_man, {gen_event, start_link, []}, permanent, 1000, worker, [gen_event]}), + ephraim_account_event_proxy:start(EventManager), + + {ok, Connection} = supervisor:start_child(Pid, {connection, {ephraim_conn, start_link, [EventManager]}, permanent, 10000, worker, [ephraim_conn]}), + {ok, _} = supervisor:start_child(Pid, {roster, {ephraim_roster, start_link, [EventManager, Connection]}, permanent, 1000, worker, [ephraim_roster]}), + {ok, Pid}. + +init(_Args) -> + {ok, {{one_for_all, 0, 1}, []}}. diff --git a/src/core/ephraim_account_event_proxy.erl b/src/core/ephraim_account_event_proxy.erl new file mode 100644 index 0000000..d9cf94e --- /dev/null +++ b/src/core/ephraim_account_event_proxy.erl @@ -0,0 +1,27 @@ +-module(ephraim_account_event_proxy). +-behaviour(gen_event). + +-export([start/1]). +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). + +start(EventManager) -> + gen_event:add_handler(EventManager, ?MODULE, foo_account). + +init(Account) -> + {ok, Account}. + +handle_event({view_update, Event}, Account) -> + ephraim:notify({view_update, {account, Account, Event}}), + {ok, Account}; + +handle_event(_Event, Account) -> + {ok, Account}. + +handle_call(_Msg, Account) -> + {noreply, Account}. +handle_info(_Msg, Account) -> + {ok, Account}. +terminate(_Reason, _Account) -> + ok. +code_change(_OldVersion, Account, _Extra) -> + {ok, Account}. diff --git a/src/core/ephraim_accounts.erl b/src/core/ephraim_accounts.erl new file mode 100644 index 0000000..a35c486 --- /dev/null +++ b/src/core/ephraim_accounts.erl @@ -0,0 +1,11 @@ +-module(ephraim_accounts). +-behaviour(supervisor). +-export([start_link/0]). +-export([init/1]). + +start_link() -> + supervisor:start_link(?MODULE, []). + +init(_Args) -> + {ok, {{one_for_one, 1, 60}, + [{account, {ephraim_account, start_link, []}, permanent, infinity, supervisor, [ephraim_account]}]}}. diff --git a/src/core/ephraim_config.erl b/src/core/ephraim_config.erl index 6c556c2..dd9e64d 100644 --- a/src/core/ephraim_config.erl +++ b/src/core/ephraim_config.erl @@ -11,6 +11,8 @@ start_link() -> -spec init(term()) -> {ok, dict()}. init(_Args) -> + process_flag(trap_exit, true), + {ok, Terms} = file:consult(config_path() ++ "/ephraim.cfg"), Config = dict:from_list(lists:map(fun(Term) -> {element(1, Term), Term} end, Terms)), @@ -40,7 +42,6 @@ get(Key) -> -spec handle_call(term(), {pid(), term()}, dict()) -> {reply, tuple() | error, dict()}. handle_call({get, Key}, _From, Config) -> - ephraim_config ! {self(), get, Key}, case dict:find(Key, Config) of {ok, Value} -> {reply, Value, Config}; diff --git a/src/core/ephraim_conn.erl b/src/core/ephraim_conn.erl index 1ac5236..f4e14e0 100644 --- a/src/core/ephraim_conn.erl +++ b/src/core/ephraim_conn.erl @@ -1,15 +1,23 @@ -module(ephraim_conn). --compile([debug_info, export_all]). -include_lib("exmpp/include/exmpp_client.hrl"). -include_lib("exmpp/include/exmpp_xml.hrl"). +-behaviour(gen_server). +-export([start_link/1]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-export([send_packet/2]). -record(conn_state, { - session :: any() + event_manager :: pid(), + session :: any() }). --spec init() -> ok. -init() -> - application:start(exmpp), +start_link(EventManager) -> + gen_server:start_link(?MODULE, EventManager, []). + +%-spec init() -> ok. +init(EventManager) -> + process_flag(trap_exit, true), + Session = exmpp_session:start(), {jid, JID} = ephraim_config:get(jid), @@ -20,55 +28,41 @@ init() -> io:format("Connecting...~n"), exmpp_session:connect_TCP(Session, Server, Port), io:format("Connected.~n"), - session(#conn_state{session=Session}). + session(Session), + {ok, #conn_state{event_manager=EventManager,session=Session}}. --spec session(#conn_state{}) -> ok. -session(State) -> +-spec session(any()) -> ok. +session(Session) -> io:format("Logging in...~n"), - exmpp_session:login(State#conn_state.session), + exmpp_session:login(Session), io:format("Getting profile...~n"), - exmpp_session:send_packet(State#conn_state.session, exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'})), + exmpp_session:send_packet(Session, exmpp_iq:get('jabber:client', #xmlel{ns='vcard-temp',name='vCard'})), io:format("Getting roster...~n"), - exmpp_session:send_packet(State#conn_state.session, exmpp_client_roster:get_roster("foo")), + exmpp_session:send_packet(Session, exmpp_client_roster:get_roster("foo")), io:format("Setting presence...~n"), - exmpp_session:send_packet(State#conn_state.session, exmpp_presence:set_status(exmpp_presence:available(), "Foo/Test\\Bar")), - io:format("Ok.~n"), - loop(State). + exmpp_session:send_packet(Session, exmpp_presence:set_status(exmpp_presence:available(), "Foo/Test\\Bar")), + io:format("Ok.~n"). + +send_packet(Connection, Packet) -> + gen_server:cast(Connection, {send_packet, Packet}). + +handle_call(_Msg, _From, State) -> + {noreply, State}. + +handle_cast({send_packet, Packet}, State) -> + exmpp_session:send_packet(State#conn_state.session, Packet), + {noreply, State}. + +handle_info(Msg = #received_packet{}, State) -> + gen_event:notify(State#conn_state.event_manager, {received_packet,Msg}), + {noreply, State}; +handle_info(Msg, State) -> + io:format("ephraim_conn: ~p~n", [Msg]), + {noreply, State}. + +terminate(_Reason, State) -> + io:format("Disconnecting...~n"), + exmpp_session:stop(State#conn_state.session). --spec loop(#conn_state{}) -> ok. -loop(State) -> - receive - stop -> - exmpp_session:stop(State#conn_state.session); - - #received_packet{packet_type=presence, raw_packet=Packet} -> - %io:format("Received packet ~p~n", [Packet]), - ephraim ! {roster, {presence, Packet}}, - loop(State); - - #received_packet{packet_type=message, raw_packet=Packet} -> - %io:format("Received packet ~p~n", [Packet]), - From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>), - HasElement = exmpp_xml:has_element(Packet,'http://jabber.org/protocol/pubsub#event',event), - if HasElement -> - ephraim ! {receive_event, From, Packet}; - true -> - ephraim ! {receive_message, From, Packet} - end, - loop(State); - - #received_packet{packet_type=iq, raw_packet=Packet} -> - %io:format("Received packet ~p~n", [Packet]), - From = exmpp_stanza:get_sender(Packet), - IQ = exmpp_iq:xmlel_to_iq(Packet), - ephraim ! {receive_iq, From, IQ}, - loop(State); - - {send_packet, Packet} -> - exmpp_session:send_packet(State#conn_state.session, Packet), - loop(State); - - Msg -> - io:format("ephraim_conn: ~p~n", [Msg]), - loop(State) - end. +code_change(_OldVersion, State, _Extra) -> + {ok, State}. diff --git a/src/core/ephraim_event.erl b/src/core/ephraim_event.erl deleted file mode 100644 index d8778e4..0000000 --- a/src/core/ephraim_event.erl +++ /dev/null @@ -1,46 +0,0 @@ --module(ephraim_event). --compile([debug_info, export_all]). --include_lib("exmpp/include/exmpp.hrl"). - --spec init() -> ok. -init() -> - loop(). - --spec handleEvent(binary(), #xmlel{}) -> ok. -handleEvent(From, Item) -> - % HasAvatarData = exmpp_xml:has_element(Item, 'urn:xmpp:avatar:data', data), - % HasAvatarMetaData = exmpp_xml:has_element(Item, 'urn:xmpp:avatar:metadata', metadata), - if %HasAvatarData -> - % Element = exmpp_xml:get_element(Item, 'urn:xmpp:avatar:data', data), - % Data = base64:decode(exmpp_xml:get_cdata_from_list(Element#xmlel.children)), - % ephraim ! {roster, {avatar, From, Data}}, - % ok; - %HasAvatarMetaData -> - % ok; - true -> - io:format("Received unhandled event from ~p:~n~p~n", [From, Item]) - end. - --spec handleEvents(binary(), [#xmlel{}]) -> ok. -handleEvents(_, []) -> - ok; -handleEvents(From, [Item|Rest]) -> - handleEvent(From, Item), - handleEvents(From, Rest). - --spec loop() -> ok. -loop() -> - receive - stop -> - ok; - - {receive_event, From, Packet} -> - Event = exmpp_xml:get_element(Packet, 'http://jabber.org/protocol/pubsub#event', event), - Items = exmpp_xml:get_element(Event, 'http://jabber.org/protocol/pubsub#event', items), - handleEvents(From, Items#xmlel.children), - loop(); - - Msg -> - io:format("ephraim_event: ~p~n", [Msg]), - loop() - end. diff --git a/src/core/ephraim_gui.erl b/src/core/ephraim_gui.erl index b049da3..92ab521 100644 --- a/src/core/ephraim_gui.erl +++ b/src/core/ephraim_gui.erl @@ -1,29 +1,43 @@ -module(ephraim_gui). --compile([debug_info, export_all]). +-behaviour(gen_event). +-export([start/0, stop/0]). +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). --spec init() -> ok. -init() -> - %{jid,JID} = ephraim_config:get(jid), +start() -> + gen_event:add_handler(ephraim_event_man, ?MODULE, []). +stop() -> + gen_event:delete_handler(ephraim_event_man, ?MODULE, []). + +-spec init(term()) -> ok. +init(_Args) -> Port = open_port({spawn_executable, "ephraim-gtk"}, [binary, nouse_stdio, {packet, 4}]), - ephraim ! {register_ui, self()}, - loop(Port), - ephraim ! {unregister_ui, self()}. + {ok, Port}. + +handle_event({view_update, Msg}, Port) -> + Port ! {self(), {command, term_to_binary(Msg)}}, + {ok, Port}; + +handle_event(_Event, Port) -> + {ok, Port}. --spec loop(port()) -> ok. -loop(Port) -> - receive +handle_call(_Msg, Port) -> + {noreply, Port}. + +handle_info({Port, {data, Data}}, Port) -> + Msg = binary_to_term(Data), + case Msg of stop -> - ok; - {Port, {data, Data}} -> - Msg = binary_to_term(Data), - case Msg of - stop -> - ok; - _ -> - ephraim ! Msg, - loop(Port) - end; - Msg -> - Port ! {self(), {command, term_to_binary(Msg)}}, - loop(Port) - end. + init:stop(), + remove_handler; + _ -> + ephraim:notify({view_event, Msg}), + {ok, Port} + end; + +handle_info(_Msg, Port) -> + {ok, Port}. + +terminate(_Reason, _Port) -> + ok. +code_change(_OldVersion, Port, _Extra) -> + {ok, Port}. 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}. diff --git a/src/core/ephraim_roster_handler.erl b/src/core/ephraim_roster_handler.erl new file mode 100644 index 0000000..fa7c1c7 --- /dev/null +++ b/src/core/ephraim_roster_handler.erl @@ -0,0 +1,45 @@ +-module(ephraim_roster_handler). +-include_lib("exmpp/include/exmpp_client.hrl"). +-behaviour(gen_event). + +-export([start/2, stop/1]). +-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). + +start(EventManager, Roster) -> + gen_event:add_handler(EventManager, ?MODULE, Roster). +stop(EventManager) -> + gen_event:delete_handler(EventManager, ?MODULE, []). + +init(Roster) -> + {ok, Roster}. + +handle_event({received_packet, #received_packet{packet_type=presence, raw_packet=Packet}}, Roster) -> + %io:format("Received packet ~p~n", [Packet]), + ephraim_roster:presence(Roster, Packet), + {ok, Roster}; + +handle_event({received_packet, #received_packet{packet_type=iq, raw_packet=Packet}}, Roster) -> + %io:format("Received packet ~p~n", [Packet]), + From = exmpp_stanza:get_sender(Packet), + IQ = exmpp_iq:xmlel_to_iq(Packet), + case IQ of + {iq, response, result, _, 'jabber:iq:roster', Payload, _, _, 'jabber:client'} -> + ephraim_roster:roster_iq(Roster, Payload); + {iq, response, result, _, 'vcard-temp', Payload, _, _, 'jabber:client'} -> + ephraim_roster:vcard_iq(Roster, From, Payload); + _ -> + ok %io:format("ephraim: IQ from ~p: ~p~n", [From, IQ]) + end, + {ok, Roster}; + +handle_event(_Event, Roster) -> + {ok, Roster}. + +handle_call(_Msg, Roster) -> + {noreply, Roster}. +handle_info(_Msg, Roster) -> + {ok, Roster}. +terminate(_Reason, _Roster) -> + ok. +code_change(_OldVersion, Roster, _Extra) -> + {ok, Roster}. diff --git a/src/core/ephraim_util.erl b/src/core/ephraim_util.erl deleted file mode 100644 index 73cb7fc..0000000 --- a/src/core/ephraim_util.erl +++ /dev/null @@ -1,10 +0,0 @@ --module(ephraim_util). --compile([debug_info, export_all]). - --spec send_all([term()], term()) -> term(). -send_all(Dest, Message) -> - lists:foldr(fun erlang:send/2, Message, Dest). - --spec send_all_values(dict(), term()) -> term(). -send_all_values(Dest, Message) -> - dict:fold(fun(_,Value,Msg) -> Value ! Msg end, Message, Dest). diff --git a/src/ephraim b/src/ephraim index ce30386..472ffce 100755 --- a/src/ephraim +++ b/src/ephraim @@ -1,3 +1,3 @@ #!/bin/sh -erl -pa core -run ephraim +erl -pa core -eval 'application:start(exmpp).' -eval 'application:start(ephraim).' diff --git a/src/gui/CoreConnector.vala b/src/gui/CoreConnector.vala index d5f0ecc..4c853ff 100644 --- a/src/gui/CoreConnector.vala +++ b/src/gui/CoreConnector.vala @@ -7,8 +7,8 @@ public class CoreConnector { static Eva.Term match_chat_message; static construct { - match_gui_init = Eva.parse("{gui_init,Terms}"); - match_roster_update = Eva.parse("{roster_update,JID,Name,Subscription,Groups,Resources,Avatar}"); + match_gui_init = Eva.parse("{global,{gui_init,Terms}}"); + match_roster_update = Eva.parse("{account,Account,{roster_update,JID,Name,Subscription,Groups,Resources,Avatar}}"); match_resource_entry = Eva.parse("{Name,{resource_entry,Priority,Show,Status}}"); match_avatar = Eva.parse("{avatar,Data}"); match_new_conversation = Eva.parse("{new_conversation,JID}"); -- cgit v1.2.3