summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2010-11-18 12:09:08 (GMT)
committerKevin Smith <git@kismith.co.uk>2010-12-22 20:19:07 (GMT)
commit9f04a7ec3429303118f12607703b877d8ba43888 (patch)
tree3e868395fa3c4f9cbbf84614094bb0251b425c15 /Swift/Controllers/DiscoServiceWalker.cpp
parent04b99ce8430109d0467c29c85cb6bacb85c54c44 (diff)
downloadswift-9f04a7ec3429303118f12607703b877d8ba43888.zip
swift-9f04a7ec3429303118f12607703b877d8ba43888.tar.bz2
Basic User Search support, and Find Rooms cleanup.
Adds a throbber to the MUC search, turns the Add Contact dialog into something searchy, adds the option to open chats to arbitrary JIDs. Resolves: #614 Resolves: #695 Resolves: #436 Release-Notes: On servers that support it, users can now perform searches for contacts to add or chat to.
Diffstat (limited to 'Swift/Controllers/DiscoServiceWalker.cpp')
-rw-r--r--Swift/Controllers/DiscoServiceWalker.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/Swift/Controllers/DiscoServiceWalker.cpp b/Swift/Controllers/DiscoServiceWalker.cpp
new file mode 100644
index 0000000..95ce23b
--- /dev/null
+++ b/Swift/Controllers/DiscoServiceWalker.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/Controllers/DiscoServiceWalker.h>
+
+#include <boost/bind.hpp>
+
+#include "Swiften/Disco/GetDiscoInfoRequest.h"
+#include "Swiften/Disco/GetDiscoItemsRequest.h"
+
+namespace Swift {
+
+DiscoServiceWalker::DiscoServiceWalker(const JID& service, IQRouter* iqRouter, size_t maxSteps) : service_(service), iqRouter_(iqRouter), maxSteps_(maxSteps) {
+
+}
+
+void DiscoServiceWalker::beginWalk() {
+ assert(servicesBeingSearched_.size() == 0);
+ walkNode(service_);
+}
+
+void DiscoServiceWalker::walkNode(const JID& jid) {
+ servicesBeingSearched_.push_back(jid);
+ searchedServices_.push_back(jid);
+ GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(jid, iqRouter_);
+ discoInfoRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, jid));
+ discoInfoRequest->send();
+}
+
+void DiscoServiceWalker::handleReceivedDiscoItem(const JID& item) {
+ if (std::find(searchedServices_.begin(), searchedServices_.end(), item) != searchedServices_.end()) {
+ /* Don't recurse infinitely */
+ return;
+ }
+ walkNode(item);
+}
+
+void DiscoServiceWalker::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, const JID& jid) {
+ if (error) {
+ handleDiscoError(jid, error);
+ return;
+ }
+
+ bool couldContainServices = false;
+ foreach (DiscoInfo::Identity identity, info->getIdentities()) {
+ if (identity.getCategory() == "server") {
+ couldContainServices = true;
+ }
+ }
+ bool completed = false;
+ if (couldContainServices) {
+ GetDiscoItemsRequest::ref discoItemsRequest = GetDiscoItemsRequest::create(jid, iqRouter_);
+ discoItemsRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, jid));
+ discoItemsRequest->send();
+ } else {
+ completed = true;
+ }
+ onServiceFound(jid, info);
+ if (completed) {
+ markNodeCompleted(jid);
+ }
+}
+
+void DiscoServiceWalker::handleDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, const JID& jid) {
+ if (error) {
+ handleDiscoError(jid, error);
+ return;
+ }
+ foreach (DiscoItems::Item item, items->getItems()) {
+ if (item.getNode().isEmpty()) {
+ /* Don't look at noded items. It's possible that this will exclude some services,
+ * but I've never seen one in the wild, and it's an easy fix for not looping.
+ */
+ handleReceivedDiscoItem(item.getJID());
+ }
+ }
+ markNodeCompleted(jid);
+}
+
+void DiscoServiceWalker::handleDiscoError(const JID& jid, ErrorPayload::ref /*error*/) {
+ markNodeCompleted(jid);
+}
+
+void DiscoServiceWalker::markNodeCompleted(const JID& jid) {
+ servicesBeingSearched_.erase(std::remove(servicesBeingSearched_.begin(), servicesBeingSearched_.end(), jid), servicesBeingSearched_.end());
+ /* All results are in */
+ if (servicesBeingSearched_.size() == 0) {
+ onWalkComplete();
+ }
+ /* Check if we're on a rampage */
+ if (searchedServices_.size() >= maxSteps_) {
+ onWalkComplete();
+ }
+}
+
+}