public class CoreConnector { unowned Thread thread; bool running; Erl.Node node; Erl.Connection con; Erl.Term self; Roster roster; private class TermStore { public Erl.Term term; } static construct { Erl.init(); } public CoreConnector(Roster roster0) { running = false; roster = roster0; } public bool start() { if(running) return true; running = true; node = Erl.Node("ephraim-gtk", "magiccookie", 0); con = node.connect("ephraim-core@avalon.local"); self = Erl.mk_self_pid(node); con.reg_send("ephraim", Erl.format("{register_ui,~w}", self)); try { thread = Thread.create(receive, true); return true; } catch(ThreadError e) { return false; } } public void stop() { if(!running) return; running = false; thread.join(); con.reg_send("ephraim", Erl.format("{unregister_ui,~w}", self)); } private void* receive() { while(running) { TermStore response = new TermStore(); Erl.ReceiveType ret = con.receive(out response.term, 1000); switch(ret) { case Erl.ReceiveType.ERROR: if(Erl.errno == Erl.Error.TIMEDOUT) break; running = false; break; case Erl.ReceiveType.TICK: // Do nothing break; case Erl.ReceiveType.MSG: Idle.add(() => {handle_term(response); return false;}); break; } } return null; } private Erl.Term? match(string pattern, Erl.Term term) { Erl.Term pattern_term = Erl.format(pattern); if(pattern_term.match(term) != 0) return pattern_term; else return null; } private void handle_term(TermStore store) { unowned Erl.Term term = store.term; Erl.Term match_term; if((match_term = match("{roster_update,JID,Name,Subscription,Groups,Resources}", term)) != null) { Erl.Term jid_term = match_term.var_content("JID"); if(!jid_term.is_binary()) // TODO Debug output return; string jid = ((string)jid_term.bin_ptr()).ndup(jid_term.bin_size()); Erl.Term name_term = match_term.var_content("Name"); string? name; if (name_term.is_binary()) name = ((string)name_term.bin_ptr()).ndup(name_term.bin_size()); else name = null; Contact contact = new Contact(jid, name); Erl.Term resources = match_term.var_content("Resources"); while(resources.is_cons()) { Erl.Term r; if((r = match("{Name,{resource_entry,Priority,Show,Status}}", resources.hd())) != null) { Erl.Term rname_term = r.var_content("Name"); Erl.Term prio_term = r.var_content("Priority"); Erl.Term show_term = r.var_content("Show"); Erl.Term status_term = r.var_content("Status"); if(rname_term.is_binary() && prio_term.is_integer() && show_term.is_atom()) { string rname = ((string)rname_term.bin_ptr()).ndup(rname_term.bin_size()); int prio = prio_term.int_value(); Contact.Show show = Contact.Show.UNDEFINED; switch((string)show_term.atom_ptr()) { case "online": show = Contact.Show.ONLINE; break; case "away": show = Contact.Show.AWAY; break; case "chat": show = Contact.Show.CHAT; break; case "dnd": show = Contact.Show.DND; break; case "xa": show = Contact.Show.XA; break; } string? status = null; if(status_term.is_binary()) status = ((string)status_term.bin_ptr()).ndup(status_term.bin_size()); contact.update_resource(rname, new Contact.Resource(prio, show, status)); } } resources = resources.tl(); } roster.update_contact(contact); } else { Erl.print_term(stdout, term); stdout.printf("\n"); } } }