From 76a8189b46177eb78eee12d1cb3266f282acd380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 3 Oct 2016 00:58:21 +0200 Subject: Implement result-set-management for LIST queries ref #2948 --- src/xmpp/biboumi_component.cpp | 62 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 3a016b9..f43b5e0 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -27,6 +27,7 @@ #endif #include +#include using namespace std::string_literals; @@ -463,7 +464,22 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) } else if (node.empty() && iid.type == Iid::Type::Server) { // Disco on an IRC server: get the list of channels - bridge->send_irc_channel_list_request(iid, id, from); + ResultSetInfo rs_info; + const XmlNode* set_node = query->get_child("set", RSM_NS); + if (set_node) + { + const XmlNode* after = set_node->get_child("after", RSM_NS); + if (after) + rs_info.after = after->get_inner(); + const XmlNode* before = set_node->get_child("before", RSM_NS); + if (before) + rs_info.before = before->get_inner(); + const XmlNode* max = set_node->get_child("max", RSM_NS); + if (max) + rs_info.max = std::atoi(max->get_inner().data()); + + } + bridge->send_irc_channel_list_request(iid, id, from, std::move(rs_info)); stanza_error.disable(); } } @@ -749,10 +765,11 @@ void BiboumiComponent::send_ping_request(const std::string& from, this->waiting_iq[id] = result_cb; } -void BiboumiComponent::send_iq_room_list_result(const std::string& id, - const std::string& to_jid, - const std::string& from, - const std::vector& rooms_list) +void BiboumiComponent::send_iq_room_list_result(const std::string& id, const std::string& to_jid, + const std::string& from, const ChannelList& channel_list, + std::vector::const_iterator begin, + std::vector::const_iterator end, + const ResultSetInfo& rs_info) { Stanza iq("iq"); iq["from"] = from + "@" + this->served_hostname; @@ -761,12 +778,41 @@ void BiboumiComponent::send_iq_room_list_result(const std::string& id, iq["type"] = "result"; XmlNode query("query"); query["xmlns"] = DISCO_ITEMS_NS; - for (const auto& room: rooms_list) + + for (auto it = begin; it != end; ++it) { XmlNode item("item"); - item["jid"] = room.channel + "%" + from + "@" + this->served_hostname; + item["jid"] = it->channel + "@" + this->served_hostname; query.add_child(std::move(item)); } + + if ((rs_info.max >= 0 || !rs_info.after.empty() || !rs_info.before.empty())) + { + XmlNode set_node("set"); + set_node["xmlns"] = RSM_NS; + + if (begin != channel_list.channels.cend()) + { + XmlNode first_node("first"); + first_node["index"] = std::to_string(std::distance(channel_list.channels.cbegin(), begin)); + first_node.set_inner(begin->channel + "@" + this->served_hostname); + set_node.add_child(std::move(first_node)); + } + if (end != channel_list.channels.cbegin()) + { + XmlNode last_node("last"); + last_node.set_inner(std::prev(end)->channel + "@" + this->served_hostname); + set_node.add_child(std::move(last_node)); + } + if (channel_list.complete) + { + XmlNode count_node("count"); + count_node.set_inner(std::to_string(channel_list.channels.size())); + set_node.add_child(std::move(count_node)); + } + query.add_child(std::move(set_node)); + } + iq.add_child(std::move(query)); this->send_stanza(iq); } -- cgit v1.2.3