diff options
Diffstat (limited to 'vala-xmpp/src/module/presence')
-rw-r--r-- | vala-xmpp/src/module/presence/flag.vala | 64 | ||||
-rw-r--r-- | vala-xmpp/src/module/presence/module.vala | 110 | ||||
-rw-r--r-- | vala-xmpp/src/module/presence/stanza.vala | 93 |
3 files changed, 267 insertions, 0 deletions
diff --git a/vala-xmpp/src/module/presence/flag.vala b/vala-xmpp/src/module/presence/flag.vala new file mode 100644 index 00000000..3dc86a5c --- /dev/null +++ b/vala-xmpp/src/module/presence/flag.vala @@ -0,0 +1,64 @@ +using Gee; + +using Xmpp.Core; + +namespace Xmpp.Presence { + +public class Flag : XmppStreamFlag { + public const string ID = "presence"; + + private HashMap<string, ArrayList<string>> resources = new HashMap<string, ArrayList<string>>(); + private HashMap<string, Presence.Stanza> presences = new HashMap<string, Presence.Stanza>(); + + public Set<string> get_available_jids() { + return resources.keys; + } + + public ArrayList<string>? get_resources(string bare_jid) { + return resources[bare_jid]; + } + + public Presence.Stanza? get_presence(string full_jid) { + return presences[full_jid]; + } + + public void add_presence(Presence.Stanza presence) { + string bare_jid = get_bare_jid(presence.from); + if (!resources.has_key(bare_jid)) { + resources[bare_jid] = new ArrayList<string>(); + } + if (resources[bare_jid].contains(presence.from)) { + resources[bare_jid].remove(presence.from); + } + resources[bare_jid].add(presence.from); + presences[presence.from] = presence; + } + + public void remove_presence(string jid) { + string bare_jid = get_bare_jid(jid); + if (resources.has_key(bare_jid)) { + if (is_bare_jid(jid)) { + foreach (string full_jid in resources[jid]) { + presences.unset(full_jid); + } + resources.unset(jid); + } else { + resources[bare_jid].remove(jid); + if (resources[bare_jid].size == 0) { + resources.unset(bare_jid); + } + presences.unset(jid); + } + } + } + + public static Flag? get_flag(XmppStream stream) { return (Flag?) stream.get_flag(NS_URI, ID); } + + public static bool has_flag(XmppStream stream) { return get_flag(stream) != null; } + + public override string get_ns() { return NS_URI; } + + public override string get_id() { return ID; } +} + +}
\ No newline at end of file diff --git a/vala-xmpp/src/module/presence/module.vala b/vala-xmpp/src/module/presence/module.vala new file mode 100644 index 00000000..6c9d183c --- /dev/null +++ b/vala-xmpp/src/module/presence/module.vala @@ -0,0 +1,110 @@ +using Xmpp.Core; + +namespace Xmpp.Presence { + private const string NS_URI = "jabber:client"; + + public class Module : XmppStreamModule { + public const string ID = "presence_module"; + + public signal void received_presence(XmppStream stream, Presence.Stanza presence); + public signal void pre_send_presence_stanza(XmppStream stream, Presence.Stanza presence); + public signal void initial_presence_sent(XmppStream stream, Presence.Stanza presence); + public signal void received_available(XmppStream stream, Presence.Stanza presence); + public signal void received_available_show(XmppStream stream, string jid, string show); + public signal void received_unavailable(XmppStream stream, string jid); + public signal void received_subscription_request(XmppStream stream, string jid); + public signal void received_unsubscription(XmppStream stream, string jid); + + public bool available_resource = true; + + public void request_subscription(XmppStream stream, string bare_jid) { + Presence.Stanza presence = new Presence.Stanza(); + presence.to = bare_jid; + presence.type_ = Presence.Stanza.TYPE_SUBSCRIBE; + send_presence(stream, presence); + } + + public void approve_subscription(XmppStream stream, string bare_jid) { + Presence.Stanza presence = new Presence.Stanza(); + presence.to = bare_jid; + presence.type_ = Presence.Stanza.TYPE_SUBSCRIBED; + send_presence(stream, presence); + } + + public void deny_subscription(XmppStream stream, string bare_jid) { + cancel_subscription(stream, bare_jid); + } + + public void cancel_subscription(XmppStream stream, string bare_jid) { + Presence.Stanza presence = new Presence.Stanza(); + presence.to = bare_jid; + presence.type_ = Presence.Stanza.TYPE_UNSUBSCRIBED; + send_presence(stream, presence); + } + + public void unsubscribe(XmppStream stream, string bare_jid) { + Presence.Stanza presence = new Presence.Stanza(); + presence.to = bare_jid; + presence.type_ = Presence.Stanza.TYPE_UNSUBSCRIBE; + send_presence(stream, presence); + } + + public void send_presence(XmppStream stream, Presence.Stanza presence) { + pre_send_presence_stanza(stream, presence); + stream.write(presence.stanza); + } + + public override void attach(XmppStream stream) { + stream.received_presence_stanza.connect(on_received_presence_stanza); + stream.stream_negotiated.connect(on_stream_negotiated); + stream.add_flag(new Flag()); + } + + public override void detach(XmppStream stream) { + stream.received_presence_stanza.disconnect(on_received_presence_stanza); + stream.stream_negotiated.disconnect(on_stream_negotiated); + } + + private void on_received_presence_stanza(XmppStream stream, StanzaNode node) { + Presence.Stanza presence = new Presence.Stanza.from_stanza(node, Bind.Flag.get_flag(stream).my_jid); + received_presence(stream, presence); + switch (presence.type_) { + case Presence.Stanza.TYPE_AVAILABLE: + Flag.get_flag(stream).add_presence(presence); + received_available(stream, presence); + received_available_show(stream, presence.from, presence.show); + break; + case Presence.Stanza.TYPE_UNAVAILABLE: + Flag.get_flag(stream).remove_presence(presence.from); + received_unavailable(stream, presence.from); + break; + case Presence.Stanza.TYPE_SUBSCRIBE: + received_subscription_request(stream, presence.from); + break; + case Presence.Stanza.TYPE_UNSUBSCRIBE: + received_unsubscription(stream, presence.from); + break; + } + } + + private void on_stream_negotiated(XmppStream stream) { + if (available_resource) { + Presence.Stanza presence = new Presence.Stanza(); + send_presence(stream, presence); + initial_presence_sent(stream, presence); + } + } + + public static Module? get_module(XmppStream stream) { + return (Module?) stream.get_module(NS_URI, ID); + } + + public static void require(XmppStream stream) { + if (get_module(stream) == null) stream.add_module(new Presence.Module()); + } + + public override string get_ns() { return NS_URI; } + public override string get_id() { return ID; } + } + +} diff --git a/vala-xmpp/src/module/presence/stanza.vala b/vala-xmpp/src/module/presence/stanza.vala new file mode 100644 index 00000000..3dc036e5 --- /dev/null +++ b/vala-xmpp/src/module/presence/stanza.vala @@ -0,0 +1,93 @@ +using Xmpp.Core; + +namespace Xmpp.Presence { + +public class Stanza : Xmpp.Stanza { + + public const string NODE_PRIORITY = "priority"; + public const string NODE_STATUS = "status"; + public const string NODE_SHOW = "show"; + + public const string SHOW_ONLINE = "online"; + public const string SHOW_AWAY = "away"; + public const string SHOW_CHAT = "chat"; + public const string SHOW_DND = "dnd"; + public const string SHOW_XA = "xa"; + + public const string TYPE_AVAILABLE = "available"; + public const string TYPE_PROBE = "probe"; + public const string TYPE_SUBSCRIBE = "subscribe"; + public const string TYPE_SUBSCRIBED = "subscribed"; + public const string TYPE_UNAVAILABLE = "unavailable"; + public const string TYPE_UNSUBSCRIBE = "unsubscribe"; + public const string TYPE_UNSUBSCRIBED = "unsubscribed"; + + public int priority { + get { + StanzaNode? priority_node = stanza.get_subnode(NODE_PRIORITY); + if (priority_node == null) { + return 0; + } else { + return int.parse(priority_node.get_string_content()); + } + } + set { + StanzaNode? priority_node = stanza.get_subnode(NODE_PRIORITY); + if (priority_node == null) { + priority_node = new StanzaNode.build(NODE_PRIORITY); + stanza.put_node(priority_node); + } + priority_node.val = value.to_string(); + } + } + + public string? status { + get { + StanzaNode? status_node = stanza.get_subnode(NODE_STATUS); + return status_node != null ? status_node.get_string_content() : null; + } + set { + StanzaNode? status_node = stanza.get_subnode(NODE_STATUS); + if (status_node == null) { + status_node = new StanzaNode.build(NODE_STATUS); + stanza.put_node(status_node); + } + status_node.val = value; + } + } + + public string show { + get { + StanzaNode? show_node = stanza.get_subnode(NODE_SHOW); + return show_node != null ? show_node.get_string_content() : SHOW_ONLINE; + } + set { + if (value != SHOW_ONLINE) { + StanzaNode? show_node = stanza.get_subnode(NODE_SHOW); + if (show_node == null) { + show_node = new StanzaNode.build(NODE_SHOW); + stanza.put_node(show_node); + } + show_node.val = value; + } + } + } + + public override string type_ { + get { + return base.type_ != null ? base.type_ : TYPE_AVAILABLE; + } + set { base.type_ = value; } + } + + public Stanza(string id = UUID.generate_random_unparsed()) { + stanza = new StanzaNode.build("presence"); + this.id = id; + } + + public Stanza.from_stanza(StanzaNode stanza_node, string my_jid) { + base.incoming(stanza_node, my_jid); + } +} + +}
\ No newline at end of file |