-module(ephraim). -compile([debug_info, export_all]). -record(state, { conn :: pid(), roster :: pid(), event :: pid(), gui :: pid(), convs :: dict(), uis :: set() }). -spec start() -> ok. start() -> spawn(?MODULE, init, []), ok. -spec stop() -> ok. stop() -> ephraim ! stop, ok. -spec init() -> ok. init() -> register(ephraim, self()), Config = spawn(ephraim_config, init, []), % Wait for config process receive {Config, started} -> io:format("Reading config file...~n") end, 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 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}; _ -> io:format("ephraim: IQ from ~p: ~p~n", [From, IQ]) end, loop(State); Msg -> io:format("ephraim: ~p~n", [Msg]), loop(State) end.