summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/ephraim.erl38
-rw-r--r--src/core/ephraim_conn.erl7
-rw-r--r--src/core/ephraim_conv.erl4
-rw-r--r--src/core/ephraim_event.erl42
-rw-r--r--src/core/ephraim_roster.erl52
6 files changed, 120 insertions, 24 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 792f279..c49763c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -2,6 +2,7 @@ erl_target(ephraim-core
ephraim.erl
ephraim_conn.erl
ephraim_conv.erl
+ ephraim_event.erl
ephraim_roster.erl
ephraim_util.erl
OPTIONS
diff --git a/src/core/ephraim.erl b/src/core/ephraim.erl
index 523749c..bd36118 100644
--- a/src/core/ephraim.erl
+++ b/src/core/ephraim.erl
@@ -4,6 +4,7 @@
-record(state, {
conn :: pid(),
roster :: pid(),
+ event :: pid(),
convs :: dict(),
uis :: set()
}).
@@ -25,29 +26,35 @@ init() ->
Conn = spawn(ephraim_conn, init, []),
Roster = spawn(ephraim_roster, init, []),
- loop(#state{conn=Conn,roster=Roster,convs=dict:new(),uis=sets:new()}),
+ Event = spawn(ephraim_event, init, []),
+ loop(#state{conn=Conn,roster=Roster,event=Event,convs=dict:new(),uis=sets:new()}),
init:stop().
--spec get_conv(#state{},exmpp_jid:jid()) -> {#state{},pid()}.
+-spec get_conv(#state{},exmpp_jid:jid()) -> {#state{},pid()|undefined}.
get_conv(State, JID) ->
Key = exmpp_jid:to_lower(JID),
- 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),
- {State#state{convs=Dict}, Conv}
+ case Key of
+ {_,_,undefined} ->
+ {State, undefined};
+ _ ->
+ 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),
+ {State#state{convs=Dict}, Conv}
+ end
end.
-spec loop(#state{}) -> ok.
loop(State) ->
receive
stop ->
- %dict:fold(fun(_,Conv,Msg) -> Conv ! Msg end, stop, State#state.convs),
ephraim_util:send_all_values(State#state.convs, stop),
State#state.conn ! stop,
State#state.roster ! stop,
+ State#state.event ! stop,
ok;
{register_ui, Pid} ->
@@ -78,9 +85,18 @@ loop(State) ->
{receive_message, From, Packet} ->
{State2, Conv} = get_conv(State, From),
- Conv ! {receive_message, Packet},
+ case Conv of
+ undefined ->
+ io:format("~p~n", [Packet]);
+ _ ->
+ Conv ! {receive_message, Packet}
+ end,
loop(State2);
+ {receive_event, From, Packet} ->
+ State#state.event ! {receive_event, From, Packet},
+ loop(State);
+
{receive_iq, IQ} ->
case IQ of
{iq, response, result, _, 'jabber:iq:roster', Payload, _, _, 'jabber:client'} ->
diff --git a/src/core/ephraim_conn.erl b/src/core/ephraim_conn.erl
index c4b163e..28e72b3 100644
--- a/src/core/ephraim_conn.erl
+++ b/src/core/ephraim_conn.erl
@@ -40,7 +40,12 @@ loop(State) ->
#received_packet{packet_type=message, raw_packet=Packet} ->
From = exmpp_xml:get_attribute(Packet, from, <<"unknown">>),
- ephraim ! {receive_message, From, Packet},
+ 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} ->
diff --git a/src/core/ephraim_conv.erl b/src/core/ephraim_conv.erl
index 8f53098..b502166 100644
--- a/src/core/ephraim_conv.erl
+++ b/src/core/ephraim_conv.erl
@@ -17,8 +17,8 @@ loop(State) ->
stop ->
ok;
- {receive_message, _Packet} ->
- %io:format("Received packet from ~p: ~p~n", [State#conv_state.jid, Packet]),
+ {receive_message, Packet} ->
+ io:format("Received packet from ~p:~n~p~n", [State#conv_state.jid, Packet]),
loop(State);
Msg ->
diff --git a/src/core/ephraim_event.erl b/src/core/ephraim_event.erl
new file mode 100644
index 0000000..dd86a7b
--- /dev/null
+++ b/src/core/ephraim_event.erl
@@ -0,0 +1,42 @@
+-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),
+ 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}};
+ 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_roster.erl b/src/core/ephraim_roster.erl
index bfc40b1..2426761 100644
--- a/src/core/ephraim_roster.erl
+++ b/src/core/ephraim_roster.erl
@@ -6,11 +6,16 @@
entries :: dict()
}).
+-record(avatar, {
+ data :: binary()
+ }).
+
-record(roster_entry, {
name :: binary() | undefined,
subscription :: atom() | undefined,
groups :: set(),
- resources :: dict()
+ resources :: dict(),
+ avatar :: #avatar{} | undefined
}).
-record(resource_entry, {
@@ -19,7 +24,6 @@
status :: binary()
}).
-
-spec init() -> ok.
init() ->
loop(#roster{entries=dict:new()}).
@@ -45,13 +49,11 @@ updateResource(Roster, JID, Priority, Type, Show, Status) ->
_ ->
RosterEntry#roster_entry.resources
end,
- Entries = dict:store(BareJID, RosterEntry#roster_entry{resources=Resources}, Roster#roster.entries),
- if RosterEntry#roster_entry.subscription =:= undefined ->
- ok;
- true ->
- ephraim ! {ui_update, {roster_update, BareJID, RosterEntry#roster_entry.name, RosterEntry#roster_entry.subscription,
- sets:to_list(RosterEntry#roster_entry.groups), dict:to_list(Resources)}}
- end,
+ NewEntry = RosterEntry#roster_entry{resources=Resources},
+
+ Entries = dict:store(BareJID, NewEntry, Roster#roster.entries),
+ uiUpdate(BareJID, NewEntry),
+
Roster#roster{entries=Entries}.
-spec updateRosterEntry(#roster{}, binary(), binary(), atom(), set()) -> #roster{}.
@@ -63,10 +65,36 @@ updateRosterEntry(Roster, JID, Name, Subscription, Groups) ->
dict:new()
end,
NewEntry = #roster_entry{subscription=Subscription,name=Name,resources=Resources,groups=Groups},
+
Entries = dict:store(JID, NewEntry, Roster#roster.entries),
- ephraim ! {ui_update, {roster_update, JID, Name, Subscription, sets:to_list(Groups), dict:to_list(Resources)}},
+ uiUpdate(JID, NewEntry),
+
Roster#roster{entries=Entries}.
+-spec updateAvatar(#roster{}, binary(), binary()) -> #roster{}.
+updateAvatar(Roster, JID, Avatar) ->
+ RosterEntry = case dict:find(JID, Roster#roster.entries) of
+ {ok, Entry} ->
+ Entry;
+ error ->
+ #roster_entry{resources=dict:new()}
+ end,
+ NewEntry = RosterEntry#roster_entry{avatar=#avatar{data=Avatar}},
+ Entries = dict:store(JID, NewEntry, Roster#roster.entries),
+ uiUpdate(JID, NewEntry),
+ Roster#roster{entries=Entries}.
+
+-spec uiUpdate(binary(), #roster_entry{}) -> ok.
+uiUpdate(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}},
+ ok
+ end.
+
-spec getGroups([#xmlel{}]) -> set().
getGroups(Els) ->
getGroups(sets:new(), Els).
@@ -116,6 +144,10 @@ loop(Roster) ->
Roster2 = updateResource(Roster, From, Priority, Type, Show, Status),
loop(Roster2);
+ {avatar, From, Avatar} ->
+ Roster2 = updateAvatar(Roster, From, Avatar),
+ loop(Roster2);
+
{roster_iq, Payload} ->
Roster2 = handleRosterIQs(Roster, Payload#xmlel.children),
%io:format("ephraim_roster: IQ: ~p~n", [Payload]),