From e7bc68ad4d02b8e5f6ba26c0e917abf4d9ab2ccc Mon Sep 17 00:00:00 2001 From: fiaxh Date: Thu, 23 Apr 2020 13:53:44 +0200 Subject: Handle entity hash in server features node, make ServiceDiscovery request_info/items async, add caching has_entity_feature --- .../module/xep/0030_service_discovery/flag.vala | 4 +- .../module/xep/0030_service_discovery/module.vala | 89 ++++++++++++++-------- 2 files changed, 61 insertions(+), 32 deletions(-) (limited to 'xmpp-vala/src/module/xep/0030_service_discovery') diff --git a/xmpp-vala/src/module/xep/0030_service_discovery/flag.vala b/xmpp-vala/src/module/xep/0030_service_discovery/flag.vala index d4874fca..0ecd98fb 100644 --- a/xmpp-vala/src/module/xep/0030_service_discovery/flag.vala +++ b/xmpp-vala/src/module/xep/0030_service_discovery/flag.vala @@ -23,8 +23,8 @@ public class Flag : XmppStreamFlag { owned get { return own_identities_.read_only_view; } } - public Gee.Set? get_entity_categories(Jid jid) { - return entity_identities.has_key(jid) ? entity_identities[jid] : null; // TODO isn’t this default for hashmap + public Gee.Set? get_entity_identities(Jid jid) { + return entity_identities.has_key(jid) ? entity_identities[jid].read_only_view : null; // TODO isn’t this default for hashmap } public bool? has_entity_identity(Jid jid, string category, string type) { diff --git a/xmpp-vala/src/module/xep/0030_service_discovery/module.vala b/xmpp-vala/src/module/xep/0030_service_discovery/module.vala index 332e8fc3..e63dee74 100644 --- a/xmpp-vala/src/module/xep/0030_service_discovery/module.vala +++ b/xmpp-vala/src/module/xep/0030_service_discovery/module.vala @@ -9,6 +9,8 @@ public const string NS_URI_ITEMS = NS_URI + "#items"; public class Module : XmppStreamModule, Iq.Handler { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0030_service_discovery_module"); + private HashMap> active_info_requests = new HashMap>(Jid.hash_func, Jid.equals_func); + public Identity own_identity; public Module.with_identity(string category, string type, string? name = null) { @@ -39,36 +41,63 @@ public class Module : XmppStreamModule, Iq.Handler { stream.get_flag(Flag.IDENTITY).remove_own_identity(identity); } - public delegate void HasEntryCategoryRes(XmppStream stream, Gee.Set? identities); - public void get_entity_categories(XmppStream stream, Jid jid, owned HasEntryCategoryRes listener) { - Gee.Set? res = stream.get_flag(Flag.IDENTITY).get_entity_categories(jid); - if (res != null) listener(stream, res); - request_info(stream, jid, (stream, query_result) => { - listener(stream, query_result != null ? query_result.identities : null); - }); - } - - public delegate void OnInfoResult(XmppStream stream, InfoResult? query_result); - public void request_info(XmppStream stream, Jid jid, owned OnInfoResult listener) { - Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns()); - iq.to = jid; - stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, iq) => { - InfoResult? result = InfoResult.create_from_iq(iq); - stream.get_flag(Flag.IDENTITY).set_entity_features(iq.from, result != null ? result.features : null); - stream.get_flag(Flag.IDENTITY).set_entity_identities(iq.from, result != null ? result.identities : null); - listener(stream, result); - }); - } - - public delegate void OnItemsResult(XmppStream stream, ItemsResult query_result); - public void request_items(XmppStream stream, Jid jid, owned OnItemsResult listener) { - Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns()); - iq.to = jid; - stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, (stream, iq) => { - ItemsResult? result = ItemsResult.create_from_iq(iq); - stream.get_flag(Flag.IDENTITY).set_entity_items(iq.from, result != null ? result.items : null); - listener(stream, result); - }); + public async bool has_entity_feature(XmppStream stream, Jid jid, string feature) { + Flag flag = stream.get_flag(Flag.IDENTITY); + + if (flag.has_entity_feature(jid, feature) == null) { + InfoResult? info_result = yield request_info(stream, jid); + stream.get_flag(Flag.IDENTITY).set_entity_features(info_result.iq.from, info_result != null ? info_result.features : null); + stream.get_flag(Flag.IDENTITY).set_entity_identities(info_result.iq.from, info_result != null ? info_result.identities : null); + } + + return flag.has_entity_feature(jid, feature); + } + + public async Gee.Set? get_entity_identities(XmppStream stream, Jid jid) { + Flag flag = stream.get_flag(Flag.IDENTITY); + + if (flag.get_entity_identities(jid) == null) { + InfoResult? info_result = yield request_info(stream, jid); + stream.get_flag(Flag.IDENTITY).set_entity_features(info_result.iq.from, info_result != null ? info_result.features : null); + stream.get_flag(Flag.IDENTITY).set_entity_identities(info_result.iq.from, info_result != null ? info_result.identities : null); + } + + return flag.get_entity_identities(jid); + } + + public async InfoResult? request_info(XmppStream stream, Jid jid) { + var future = active_info_requests[jid]; + if (future == null) { + var promise = new Promise(); + future = promise.future; + active_info_requests[jid] = future; + + Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_INFO).add_self_xmlns()) { to=jid }; + Iq.Stanza iq_response = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + InfoResult? result = InfoResult.create_from_iq(iq_response); + + promise.set_value(result); + active_info_requests.unset(jid); + } + + try { + InfoResult? res = yield future.wait_async(); + return res; + } catch (FutureError error) { + warning("Future error when waiting for info request result: %s", error.message); + return null; + } + } + + public async ItemsResult? request_items(XmppStream stream, Jid jid) { + StanzaNode query_node = new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns(); + Iq.Stanza iq = new Iq.Stanza.get(query_node) { to=jid }; + + Iq.Stanza iq_result = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + ItemsResult? result = ItemsResult.create_from_iq(iq_result); + stream.get_flag(Flag.IDENTITY).set_entity_items(iq_result.from, result != null ? result.items : null); + + return result; } public void on_iq_get(XmppStream stream, Iq.Stanza iq) { -- cgit v1.2.3-54-g00ecf