diff options
Diffstat (limited to 'Swiften/Disco')
29 files changed, 1327 insertions, 1327 deletions
diff --git a/Swiften/Disco/CapsInfoGenerator.cpp b/Swiften/Disco/CapsInfoGenerator.cpp index 1b07c43..b4637c7 100644 --- a/Swiften/Disco/CapsInfoGenerator.cpp +++ b/Swiften/Disco/CapsInfoGenerator.cpp @@ -15,9 +15,9 @@ #include <Swiften/StringCodecs/Base64.h> namespace { - bool compareFields(Swift::FormField::ref f1, Swift::FormField::ref f2) { - return f1->getName() < f2->getName(); - } + bool compareFields(Swift::FormField::ref f1, Swift::FormField::ref f2) { + return f1->getName() < f2->getName(); + } } namespace Swift { @@ -26,39 +26,39 @@ CapsInfoGenerator::CapsInfoGenerator(const std::string& node, CryptoProvider* cr } CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { - std::string serializedCaps; + std::string serializedCaps; - std::vector<DiscoInfo::Identity> identities(discoInfo.getIdentities()); - std::sort(identities.begin(), identities.end()); - foreach (const DiscoInfo::Identity& identity, identities) { - serializedCaps += identity.getCategory() + "/" + identity.getType() + "/" + identity.getLanguage() + "/" + identity.getName() + "<"; - } + std::vector<DiscoInfo::Identity> identities(discoInfo.getIdentities()); + std::sort(identities.begin(), identities.end()); + foreach (const DiscoInfo::Identity& identity, identities) { + serializedCaps += identity.getCategory() + "/" + identity.getType() + "/" + identity.getLanguage() + "/" + identity.getName() + "<"; + } - std::vector<std::string> features(discoInfo.getFeatures()); - std::sort(features.begin(), features.end()); - foreach (const std::string& feature, features) { - serializedCaps += feature + "<"; - } + std::vector<std::string> features(discoInfo.getFeatures()); + std::sort(features.begin(), features.end()); + foreach (const std::string& feature, features) { + serializedCaps += feature + "<"; + } - foreach(Form::ref extension, discoInfo.getExtensions()) { - serializedCaps += extension->getFormType() + "<"; - std::vector<FormField::ref> fields(extension->getFields()); - std::sort(fields.begin(), fields.end(), &compareFields); - foreach(FormField::ref field, fields) { - if (field->getName() == "FORM_TYPE") { - continue; - } - serializedCaps += field->getName() + "<"; - std::vector<std::string> values(field->getValues()); - std::sort(values.begin(), values.end()); - foreach(const std::string& value, values) { - serializedCaps += value + "<"; - } - } - } + foreach(Form::ref extension, discoInfo.getExtensions()) { + serializedCaps += extension->getFormType() + "<"; + std::vector<FormField::ref> fields(extension->getFields()); + std::sort(fields.begin(), fields.end(), &compareFields); + foreach(FormField::ref field, fields) { + if (field->getName() == "FORM_TYPE") { + continue; + } + serializedCaps += field->getName() + "<"; + std::vector<std::string> values(field->getValues()); + std::sort(values.begin(), values.end()); + foreach(const std::string& value, values) { + serializedCaps += value + "<"; + } + } + } - std::string version(Base64::encode(crypto_->getSHA1Hash(createByteArray(serializedCaps)))); - return CapsInfo(node_, version, "sha-1"); + std::string version(Base64::encode(crypto_->getSHA1Hash(createByteArray(serializedCaps)))); + return CapsInfo(node_, version, "sha-1"); } } diff --git a/Swiften/Disco/CapsInfoGenerator.h b/Swiften/Disco/CapsInfoGenerator.h index b964816..ed1b1bd 100644 --- a/Swiften/Disco/CapsInfoGenerator.h +++ b/Swiften/Disco/CapsInfoGenerator.h @@ -12,17 +12,17 @@ #include <Swiften/Elements/CapsInfo.h> namespace Swift { - class DiscoInfo; - class CryptoProvider; + class DiscoInfo; + class CryptoProvider; - class SWIFTEN_API CapsInfoGenerator { - public: - CapsInfoGenerator(const std::string& node, CryptoProvider* crypto); + class SWIFTEN_API CapsInfoGenerator { + public: + CapsInfoGenerator(const std::string& node, CryptoProvider* crypto); - CapsInfo generateCapsInfo(const DiscoInfo& discoInfo) const; + CapsInfo generateCapsInfo(const DiscoInfo& discoInfo) const; - private: - std::string node_; - CryptoProvider* crypto_; - }; + private: + std::string node_; + CryptoProvider* crypto_; + }; } diff --git a/Swiften/Disco/CapsManager.cpp b/Swiften/Disco/CapsManager.cpp index 5616f0a..139ee6c 100644 --- a/Swiften/Disco/CapsManager.cpp +++ b/Swiften/Disco/CapsManager.cpp @@ -19,66 +19,66 @@ namespace Swift { CapsManager::CapsManager(CapsStorage* capsStorage, StanzaChannel* stanzaChannel, IQRouter* iqRouter, CryptoProvider* crypto) : iqRouter(iqRouter), crypto(crypto), capsStorage(capsStorage), warnOnInvalidHash(true) { - stanzaChannel->onPresenceReceived.connect(boost::bind(&CapsManager::handlePresenceReceived, this, _1)); - stanzaChannel->onAvailableChanged.connect(boost::bind(&CapsManager::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel->onPresenceReceived.connect(boost::bind(&CapsManager::handlePresenceReceived, this, _1)); + stanzaChannel->onAvailableChanged.connect(boost::bind(&CapsManager::handleStanzaChannelAvailableChanged, this, _1)); } void CapsManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) { - boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); - if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { - return; - } - std::string hash = capsInfo->getVersion(); - if (capsStorage->getDiscoInfo(hash)) { - return; - } - if (failingCaps.find(std::make_pair(presence->getFrom(), hash)) != failingCaps.end()) { - return; - } - if (requestedDiscoInfos.find(hash) != requestedDiscoInfos.end()) { - fallbacks[hash].insert(std::make_pair(presence->getFrom(), capsInfo->getNode())); - return; - } - requestDiscoInfo(presence->getFrom(), capsInfo->getNode(), hash); + boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); + if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { + return; + } + std::string hash = capsInfo->getVersion(); + if (capsStorage->getDiscoInfo(hash)) { + return; + } + if (failingCaps.find(std::make_pair(presence->getFrom(), hash)) != failingCaps.end()) { + return; + } + if (requestedDiscoInfos.find(hash) != requestedDiscoInfos.end()) { + fallbacks[hash].insert(std::make_pair(presence->getFrom(), capsInfo->getNode())); + return; + } + requestDiscoInfo(presence->getFrom(), capsInfo->getNode(), hash); } void CapsManager::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - failingCaps.clear(); - fallbacks.clear(); - requestedDiscoInfos.clear(); - } + if (available) { + failingCaps.clear(); + fallbacks.clear(); + requestedDiscoInfos.clear(); + } } void CapsManager::handleDiscoInfoReceived(const JID& from, const std::string& hash, DiscoInfo::ref discoInfo, ErrorPayload::ref error) { - requestedDiscoInfos.erase(hash); - if (error || !discoInfo || CapsInfoGenerator("", crypto).generateCapsInfo(*discoInfo.get()).getVersion() != hash) { - if (warnOnInvalidHash && !error && discoInfo) { - std::cerr << "Warning: Caps from " << from.toString() << " do not verify" << std::endl; - } - failingCaps.insert(std::make_pair(from, hash)); - std::map<std::string, std::set< std::pair<JID, std::string> > >::iterator i = fallbacks.find(hash); - if (i != fallbacks.end() && !i->second.empty()) { - std::pair<JID,std::string> fallbackAndNode = *i->second.begin(); - i->second.erase(i->second.begin()); - requestDiscoInfo(fallbackAndNode.first, fallbackAndNode.second, hash); - } - return; - } - fallbacks.erase(hash); - capsStorage->setDiscoInfo(hash, discoInfo); - onCapsAvailable(hash); + requestedDiscoInfos.erase(hash); + if (error || !discoInfo || CapsInfoGenerator("", crypto).generateCapsInfo(*discoInfo.get()).getVersion() != hash) { + if (warnOnInvalidHash && !error && discoInfo) { + std::cerr << "Warning: Caps from " << from.toString() << " do not verify" << std::endl; + } + failingCaps.insert(std::make_pair(from, hash)); + std::map<std::string, std::set< std::pair<JID, std::string> > >::iterator i = fallbacks.find(hash); + if (i != fallbacks.end() && !i->second.empty()) { + std::pair<JID,std::string> fallbackAndNode = *i->second.begin(); + i->second.erase(i->second.begin()); + requestDiscoInfo(fallbackAndNode.first, fallbackAndNode.second, hash); + } + return; + } + fallbacks.erase(hash); + capsStorage->setDiscoInfo(hash, discoInfo); + onCapsAvailable(hash); } void CapsManager::requestDiscoInfo(const JID& jid, const std::string& node, const std::string& hash) { - GetDiscoInfoRequest::ref request = GetDiscoInfoRequest::create(jid, node + "#" + hash, iqRouter); - request->onResponse.connect(boost::bind(&CapsManager::handleDiscoInfoReceived, this, jid, hash, _1, _2)); - requestedDiscoInfos.insert(hash); - request->send(); + GetDiscoInfoRequest::ref request = GetDiscoInfoRequest::create(jid, node + "#" + hash, iqRouter); + request->onResponse.connect(boost::bind(&CapsManager::handleDiscoInfoReceived, this, jid, hash, _1, _2)); + requestedDiscoInfos.insert(hash); + request->send(); } DiscoInfo::ref CapsManager::getCaps(const std::string& hash) const { - return capsStorage->getDiscoInfo(hash); + return capsStorage->getDiscoInfo(hash); } diff --git a/Swiften/Disco/CapsManager.h b/Swiften/Disco/CapsManager.h index 77e736d..c96db13 100644 --- a/Swiften/Disco/CapsManager.h +++ b/Swiften/Disco/CapsManager.h @@ -18,36 +18,36 @@ #include <Swiften/Elements/Presence.h> namespace Swift { - class StanzaChannel; - class IQRouter; - class JID; - class CapsStorage; - class CryptoProvider; - - class SWIFTEN_API CapsManager : public CapsProvider, public boost::bsignals::trackable { - public: - CapsManager(CapsStorage*, StanzaChannel*, IQRouter*, CryptoProvider*); - - DiscoInfo::ref getCaps(const std::string&) const; - - // Mainly for testing purposes - void setWarnOnInvalidHash(bool b) { - warnOnInvalidHash = b; - } - - private: - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleStanzaChannelAvailableChanged(bool); - void handleDiscoInfoReceived(const JID&, const std::string& hash, DiscoInfo::ref, ErrorPayload::ref); - void requestDiscoInfo(const JID& jid, const std::string& node, const std::string& hash); - - private: - IQRouter* iqRouter; - CryptoProvider* crypto; - CapsStorage* capsStorage; - bool warnOnInvalidHash; - std::set<std::string> requestedDiscoInfos; - std::set< std::pair<JID, std::string> > failingCaps; - std::map<std::string, std::set< std::pair<JID, std::string> > > fallbacks; - }; + class StanzaChannel; + class IQRouter; + class JID; + class CapsStorage; + class CryptoProvider; + + class SWIFTEN_API CapsManager : public CapsProvider, public boost::bsignals::trackable { + public: + CapsManager(CapsStorage*, StanzaChannel*, IQRouter*, CryptoProvider*); + + DiscoInfo::ref getCaps(const std::string&) const; + + // Mainly for testing purposes + void setWarnOnInvalidHash(bool b) { + warnOnInvalidHash = b; + } + + private: + void handlePresenceReceived(boost::shared_ptr<Presence>); + void handleStanzaChannelAvailableChanged(bool); + void handleDiscoInfoReceived(const JID&, const std::string& hash, DiscoInfo::ref, ErrorPayload::ref); + void requestDiscoInfo(const JID& jid, const std::string& node, const std::string& hash); + + private: + IQRouter* iqRouter; + CryptoProvider* crypto; + CapsStorage* capsStorage; + bool warnOnInvalidHash; + std::set<std::string> requestedDiscoInfos; + std::set< std::pair<JID, std::string> > failingCaps; + std::map<std::string, std::set< std::pair<JID, std::string> > > fallbacks; + }; } diff --git a/Swiften/Disco/CapsMemoryStorage.h b/Swiften/Disco/CapsMemoryStorage.h index e635ea1..39559ec 100644 --- a/Swiften/Disco/CapsMemoryStorage.h +++ b/Swiften/Disco/CapsMemoryStorage.h @@ -15,26 +15,26 @@ #include <Swiften/Disco/CapsStorage.h> namespace Swift { - class SWIFTEN_API CapsMemoryStorage : public CapsStorage { - public: - CapsMemoryStorage() {} - - virtual DiscoInfo::ref getDiscoInfo(const std::string& hash) const { - CapsMap::const_iterator i = caps.find(hash); - if (i != caps.end()) { - return i->second; - } - else { - return DiscoInfo::ref(); - } - } - - virtual void setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo) { - caps[hash] = discoInfo; - } - - private: - typedef std::map<std::string, DiscoInfo::ref> CapsMap; - CapsMap caps; - }; + class SWIFTEN_API CapsMemoryStorage : public CapsStorage { + public: + CapsMemoryStorage() {} + + virtual DiscoInfo::ref getDiscoInfo(const std::string& hash) const { + CapsMap::const_iterator i = caps.find(hash); + if (i != caps.end()) { + return i->second; + } + else { + return DiscoInfo::ref(); + } + } + + virtual void setDiscoInfo(const std::string& hash, DiscoInfo::ref discoInfo) { + caps[hash] = discoInfo; + } + + private: + typedef std::map<std::string, DiscoInfo::ref> CapsMap; + CapsMap caps; + }; } diff --git a/Swiften/Disco/CapsProvider.h b/Swiften/Disco/CapsProvider.h index 0f7e49d..9cba027 100644 --- a/Swiften/Disco/CapsProvider.h +++ b/Swiften/Disco/CapsProvider.h @@ -12,14 +12,14 @@ #include <Swiften/Elements/DiscoInfo.h> namespace Swift { - - class SWIFTEN_API CapsProvider { - public: - virtual ~CapsProvider() {} - virtual DiscoInfo::ref getCaps(const std::string&) const = 0; + class SWIFTEN_API CapsProvider { + public: + virtual ~CapsProvider() {} - boost::signal<void (const std::string&)> onCapsAvailable; - }; + virtual DiscoInfo::ref getCaps(const std::string&) const = 0; + + boost::signal<void (const std::string&)> onCapsAvailable; + }; } diff --git a/Swiften/Disco/CapsStorage.h b/Swiften/Disco/CapsStorage.h index 61c508b..5459ecf 100644 --- a/Swiften/Disco/CapsStorage.h +++ b/Swiften/Disco/CapsStorage.h @@ -12,11 +12,11 @@ #include <Swiften/Elements/DiscoInfo.h> namespace Swift { - class SWIFTEN_API CapsStorage { - public: - virtual ~CapsStorage(); + class SWIFTEN_API CapsStorage { + public: + virtual ~CapsStorage(); - virtual DiscoInfo::ref getDiscoInfo(const std::string&) const = 0; - virtual void setDiscoInfo(const std::string&, DiscoInfo::ref) = 0; - }; + virtual DiscoInfo::ref getDiscoInfo(const std::string&) const = 0; + virtual void setDiscoInfo(const std::string&, DiscoInfo::ref) = 0; + }; } diff --git a/Swiften/Disco/ClientDiscoManager.cpp b/Swiften/Disco/ClientDiscoManager.cpp index 0b6eccf..8c90d2d 100644 --- a/Swiften/Disco/ClientDiscoManager.cpp +++ b/Swiften/Disco/ClientDiscoManager.cpp @@ -13,31 +13,31 @@ namespace Swift { ClientDiscoManager::ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto) : crypto(crypto) { - discoInfoResponder = new DiscoInfoResponder(iqRouter); - discoInfoResponder->start(); - this->presenceSender = new PayloadAddingPresenceSender(presenceSender); + discoInfoResponder = new DiscoInfoResponder(iqRouter); + discoInfoResponder->start(); + this->presenceSender = new PayloadAddingPresenceSender(presenceSender); } ClientDiscoManager::~ClientDiscoManager() { - delete presenceSender; - discoInfoResponder->stop(); - delete discoInfoResponder; + delete presenceSender; + discoInfoResponder->stop(); + delete discoInfoResponder; } void ClientDiscoManager::setCapsNode(const std::string& node) { - capsNode = node; + capsNode = node; } void ClientDiscoManager::setDiscoInfo(const DiscoInfo& discoInfo) { - capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode, crypto).generateCapsInfo(discoInfo))); - discoInfoResponder->clearDiscoInfo(); - discoInfoResponder->setDiscoInfo(discoInfo); - discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo); - presenceSender->setPayload(capsInfo); + capsInfo = CapsInfo::ref(new CapsInfo(CapsInfoGenerator(capsNode, crypto).generateCapsInfo(discoInfo))); + discoInfoResponder->clearDiscoInfo(); + discoInfoResponder->setDiscoInfo(discoInfo); + discoInfoResponder->setDiscoInfo(capsInfo->getNode() + "#" + capsInfo->getVersion(), discoInfo); + presenceSender->setPayload(capsInfo); } void ClientDiscoManager::handleConnected() { - presenceSender->reset(); + presenceSender->reset(); } } diff --git a/Swiften/Disco/ClientDiscoManager.h b/Swiften/Disco/ClientDiscoManager.h index 560c69a..fe68dd7 100644 --- a/Swiften/Disco/ClientDiscoManager.h +++ b/Swiften/Disco/ClientDiscoManager.h @@ -12,66 +12,66 @@ #include <Swiften/Presence/PayloadAddingPresenceSender.h> namespace Swift { - class IQRouter; - class DiscoInfoResponder; - class PayloadAddingPresenceSender; - class PresenceSender; - class CryptoProvider; + class IQRouter; + class DiscoInfoResponder; + class PayloadAddingPresenceSender; + class PresenceSender; + class CryptoProvider; - /** - * Class responsible for managing outgoing disco information for a client. - * - * The manager will respond to disco#info requests, and add entity capabilities information - * to outgoing presence. - * - * To use this class, call setCapsNode() once with the caps URI of the client. After this, - * call setDiscoInfo() with the capabilities for the client. This can be - * called whenever the capabilities change. - */ - class SWIFTEN_API ClientDiscoManager { - public: - /** - * Constructs the manager - * - * \param iqRouter the router on which requests will be answered - * \param presenceSender the presence sender to which all outgoing presence - * (with caps information) will be sent. - */ - ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto); - ~ClientDiscoManager(); + /** + * Class responsible for managing outgoing disco information for a client. + * + * The manager will respond to disco#info requests, and add entity capabilities information + * to outgoing presence. + * + * To use this class, call setCapsNode() once with the caps URI of the client. After this, + * call setDiscoInfo() with the capabilities for the client. This can be + * called whenever the capabilities change. + */ + class SWIFTEN_API ClientDiscoManager { + public: + /** + * Constructs the manager + * + * \param iqRouter the router on which requests will be answered + * \param presenceSender the presence sender to which all outgoing presence + * (with caps information) will be sent. + */ + ClientDiscoManager(IQRouter* iqRouter, PresenceSender* presenceSender, CryptoProvider* crypto); + ~ClientDiscoManager(); - /** - * Needs to be called before calling setDiscoInfo(). - */ - void setCapsNode(const std::string& node); + /** + * Needs to be called before calling setDiscoInfo(). + */ + void setCapsNode(const std::string& node); - /** - * Sets the capabilities of the client. - */ - void setDiscoInfo(const DiscoInfo& info); + /** + * Sets the capabilities of the client. + */ + void setDiscoInfo(const DiscoInfo& info); - /** - * Returns the presence sender through which all outgoing presence - * should be sent. - * The manager will add the necessary caps information, and forward it to - * the presence sender passed at construction time. - */ - PresenceSender* getPresenceSender() const { - return presenceSender; - } + /** + * Returns the presence sender through which all outgoing presence + * should be sent. + * The manager will add the necessary caps information, and forward it to + * the presence sender passed at construction time. + */ + PresenceSender* getPresenceSender() const { + return presenceSender; + } - /** - * Called when the client is connected. - * This resets the presence sender, such that it assumes initial presence - * hasn't been sent yet. - */ - void handleConnected(); + /** + * Called when the client is connected. + * This resets the presence sender, such that it assumes initial presence + * hasn't been sent yet. + */ + void handleConnected(); - private: - PayloadAddingPresenceSender* presenceSender; - CryptoProvider* crypto; - DiscoInfoResponder* discoInfoResponder; - std::string capsNode; - CapsInfo::ref capsInfo; - }; + private: + PayloadAddingPresenceSender* presenceSender; + CryptoProvider* crypto; + DiscoInfoResponder* discoInfoResponder; + std::string capsNode; + CapsInfo::ref capsInfo; + }; } diff --git a/Swiften/Disco/DiscoInfoResponder.cpp b/Swiften/Disco/DiscoInfoResponder.cpp index bb3937a..cf18f43 100644 --- a/Swiften/Disco/DiscoInfoResponder.cpp +++ b/Swiften/Disco/DiscoInfoResponder.cpp @@ -17,34 +17,34 @@ DiscoInfoResponder::DiscoInfoResponder(IQRouter* router) : GetResponder<DiscoInf } void DiscoInfoResponder::clearDiscoInfo() { - info_ = DiscoInfo(); - nodeInfo_.clear(); + info_ = DiscoInfo(); + nodeInfo_.clear(); } void DiscoInfoResponder::setDiscoInfo(const DiscoInfo& info) { - info_ = info; + info_ = info; } void DiscoInfoResponder::setDiscoInfo(const std::string& node, const DiscoInfo& info) { - DiscoInfo newInfo(info); - newInfo.setNode(node); - nodeInfo_[node] = newInfo; + DiscoInfo newInfo(info); + newInfo.setNode(node); + nodeInfo_[node] = newInfo; } bool DiscoInfoResponder::handleGetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<DiscoInfo> info) { - if (info->getNode().empty()) { - sendResponse(from, id, boost::make_shared<DiscoInfo>(info_)); - } - else { - std::map<std::string,DiscoInfo>::const_iterator i = nodeInfo_.find(info->getNode()); - if (i != nodeInfo_.end()) { - sendResponse(from, id, boost::make_shared<DiscoInfo>((*i).second)); - } - else { - sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - } - return true; + if (info->getNode().empty()) { + sendResponse(from, id, boost::make_shared<DiscoInfo>(info_)); + } + else { + std::map<std::string,DiscoInfo>::const_iterator i = nodeInfo_.find(info->getNode()); + if (i != nodeInfo_.end()) { + sendResponse(from, id, boost::make_shared<DiscoInfo>((*i).second)); + } + else { + sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + return true; } } diff --git a/Swiften/Disco/DiscoInfoResponder.h b/Swiften/Disco/DiscoInfoResponder.h index 92d337b..0781173 100644 --- a/Swiften/Disco/DiscoInfoResponder.h +++ b/Swiften/Disco/DiscoInfoResponder.h @@ -13,21 +13,21 @@ #include <Swiften/Queries/GetResponder.h> namespace Swift { - class IQRouter; + class IQRouter; - class SWIFTEN_API DiscoInfoResponder : public GetResponder<DiscoInfo> { - public: - DiscoInfoResponder(IQRouter* router); + class SWIFTEN_API DiscoInfoResponder : public GetResponder<DiscoInfo> { + public: + DiscoInfoResponder(IQRouter* router); - void clearDiscoInfo(); - void setDiscoInfo(const DiscoInfo& info); - void setDiscoInfo(const std::string& node, const DiscoInfo& info); + void clearDiscoInfo(); + void setDiscoInfo(const DiscoInfo& info); + void setDiscoInfo(const std::string& node, const DiscoInfo& info); - private: - virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> payload); + private: + virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> payload); - private: - DiscoInfo info_; - std::map<std::string, DiscoInfo> nodeInfo_; - }; + private: + DiscoInfo info_; + std::map<std::string, DiscoInfo> nodeInfo_; + }; } diff --git a/Swiften/Disco/DiscoServiceWalker.cpp b/Swiften/Disco/DiscoServiceWalker.cpp index 5803602..19170ce 100644 --- a/Swiften/Disco/DiscoServiceWalker.cpp +++ b/Swiften/Disco/DiscoServiceWalker.cpp @@ -18,118 +18,118 @@ DiscoServiceWalker::DiscoServiceWalker(const JID& service, IQRouter* iqRouter, s } void DiscoServiceWalker::beginWalk() { - SWIFT_LOG(debug) << "Starting walk to " << service_ << std::endl; - assert(!active_); - assert(servicesBeingSearched_.empty()); - active_ = true; - walkNode(service_); + SWIFT_LOG(debug) << "Starting walk to " << service_ << std::endl; + assert(!active_); + assert(servicesBeingSearched_.empty()); + active_ = true; + walkNode(service_); } void DiscoServiceWalker::endWalk() { - if (active_) { - SWIFT_LOG(debug) << "Ending walk to " << service_ << std::endl; - foreach (GetDiscoInfoRequest::ref request, pendingDiscoInfoRequests_) { - request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); - } - foreach (GetDiscoItemsRequest::ref request, pendingDiscoItemsRequests_) { - request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); - } - active_ = false; - onWalkAborted(); - } + if (active_) { + SWIFT_LOG(debug) << "Ending walk to " << service_ << std::endl; + foreach (GetDiscoInfoRequest::ref request, pendingDiscoInfoRequests_) { + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); + } + foreach (GetDiscoItemsRequest::ref request, pendingDiscoItemsRequests_) { + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); + } + active_ = false; + onWalkAborted(); + } } void DiscoServiceWalker::walkNode(const JID& jid) { - SWIFT_LOG(debug) << "Walking node " << jid << std::endl; - servicesBeingSearched_.insert(jid); - searchedServices_.insert(jid); - GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(jid, iqRouter_); - discoInfoRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, discoInfoRequest)); - pendingDiscoInfoRequests_.insert(discoInfoRequest); - discoInfoRequest->send(); + SWIFT_LOG(debug) << "Walking node " << jid << std::endl; + servicesBeingSearched_.insert(jid); + searchedServices_.insert(jid); + GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(jid, iqRouter_); + discoInfoRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, discoInfoRequest)); + pendingDiscoInfoRequests_.insert(discoInfoRequest); + discoInfoRequest->send(); } void DiscoServiceWalker::handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request) { - /* If we got canceled, don't do anything */ - if (!active_) { - return; - } - - SWIFT_LOG(debug) << "Disco info response from " << request->getReceiver() << std::endl; - - request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); - pendingDiscoInfoRequests_.erase(request); - if (error) { - handleDiscoError(request->getReceiver(), 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(request->getReceiver(), iqRouter_); - discoItemsRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, discoItemsRequest)); - pendingDiscoItemsRequests_.insert(discoItemsRequest); - discoItemsRequest->send(); - } else { - completed = true; - } - onServiceFound(request->getReceiver(), info); - if (completed) { - markNodeCompleted(request->getReceiver()); - } + /* If we got canceled, don't do anything */ + if (!active_) { + return; + } + + SWIFT_LOG(debug) << "Disco info response from " << request->getReceiver() << std::endl; + + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoInfoResponse, this, _1, _2, request)); + pendingDiscoInfoRequests_.erase(request); + if (error) { + handleDiscoError(request->getReceiver(), 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(request->getReceiver(), iqRouter_); + discoItemsRequest->onResponse.connect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, discoItemsRequest)); + pendingDiscoItemsRequests_.insert(discoItemsRequest); + discoItemsRequest->send(); + } else { + completed = true; + } + onServiceFound(request->getReceiver(), info); + if (completed) { + markNodeCompleted(request->getReceiver()); + } } void DiscoServiceWalker::handleDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request) { - /* If we got canceled, don't do anything */ - if (!active_) { - return; - } - - SWIFT_LOG(debug) << "Received disco items from " << request->getReceiver() << std::endl; - request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); - pendingDiscoItemsRequests_.erase(request); - if (error) { - handleDiscoError(request->getReceiver(), error); - return; - } - foreach (DiscoItems::Item item, items->getItems()) { - if (item.getNode().empty()) { - /* 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. - */ - if (std::find(searchedServices_.begin(), searchedServices_.end(), item.getJID()) == searchedServices_.end()) { /* Don't recurse infinitely */ - SWIFT_LOG(debug) << "Received disco item " << item.getJID() << std::endl; - walkNode(item.getJID()); - } - } - } - markNodeCompleted(request->getReceiver()); + /* If we got canceled, don't do anything */ + if (!active_) { + return; + } + + SWIFT_LOG(debug) << "Received disco items from " << request->getReceiver() << std::endl; + request->onResponse.disconnect(boost::bind(&DiscoServiceWalker::handleDiscoItemsResponse, this, _1, _2, request)); + pendingDiscoItemsRequests_.erase(request); + if (error) { + handleDiscoError(request->getReceiver(), error); + return; + } + foreach (DiscoItems::Item item, items->getItems()) { + if (item.getNode().empty()) { + /* 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. + */ + if (std::find(searchedServices_.begin(), searchedServices_.end(), item.getJID()) == searchedServices_.end()) { /* Don't recurse infinitely */ + SWIFT_LOG(debug) << "Received disco item " << item.getJID() << std::endl; + walkNode(item.getJID()); + } + } + } + markNodeCompleted(request->getReceiver()); } void DiscoServiceWalker::handleDiscoError(const JID& jid, ErrorPayload::ref /*error*/) { - SWIFT_LOG(debug) << "Disco error from " << jid << std::endl; - markNodeCompleted(jid); + SWIFT_LOG(debug) << "Disco error from " << jid << std::endl; + markNodeCompleted(jid); } void DiscoServiceWalker::markNodeCompleted(const JID& jid) { - SWIFT_LOG(debug) << "Node completed " << jid << std::endl; - servicesBeingSearched_.erase(jid); - /* All results are in */ - if (servicesBeingSearched_.empty()) { - active_ = false; - onWalkComplete(); - } - /* Check if we're on a rampage */ - else if (searchedServices_.size() >= maxSteps_) { - active_ = false; - onWalkComplete(); - } + SWIFT_LOG(debug) << "Node completed " << jid << std::endl; + servicesBeingSearched_.erase(jid); + /* All results are in */ + if (servicesBeingSearched_.empty()) { + active_ = false; + onWalkComplete(); + } + /* Check if we're on a rampage */ + else if (searchedServices_.size() >= maxSteps_) { + active_ = false; + onWalkComplete(); + } } } diff --git a/Swiften/Disco/DiscoServiceWalker.h b/Swiften/Disco/DiscoServiceWalker.h index 17376b7..bd8102b 100644 --- a/Swiften/Disco/DiscoServiceWalker.h +++ b/Swiften/Disco/DiscoServiceWalker.h @@ -22,55 +22,55 @@ #include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; - /** - * Recursively walk service discovery trees to find all services offered. - * This stops on any disco item that's not reporting itself as a server. - */ - class SWIFTEN_API DiscoServiceWalker { - public: - DiscoServiceWalker(const JID& service, IQRouter* iqRouter, size_t maxSteps = 200); + class IQRouter; + /** + * Recursively walk service discovery trees to find all services offered. + * This stops on any disco item that's not reporting itself as a server. + */ + class SWIFTEN_API DiscoServiceWalker { + public: + DiscoServiceWalker(const JID& service, IQRouter* iqRouter, size_t maxSteps = 200); - /** - * Start the walk. - * - * Call this exactly once. - */ - void beginWalk(); + /** + * Start the walk. + * + * Call this exactly once. + */ + void beginWalk(); - /** - * End the walk. - */ - void endWalk(); + /** + * End the walk. + */ + void endWalk(); - bool isActive() const { - return active_; - } + bool isActive() const { + return active_; + } - /** Emitted for each service found. */ - boost::signal<void(const JID&, boost::shared_ptr<DiscoInfo>)> onServiceFound; + /** Emitted for each service found. */ + boost::signal<void(const JID&, boost::shared_ptr<DiscoInfo>)> onServiceFound; - /** Emitted when walking is aborted. */ - boost::signal<void()> onWalkAborted; + /** Emitted when walking is aborted. */ + boost::signal<void()> onWalkAborted; - /** Emitted when walking is complete.*/ - boost::signal<void()> onWalkComplete; + /** Emitted when walking is complete.*/ + boost::signal<void()> onWalkComplete; - private: - void walkNode(const JID& jid); - void markNodeCompleted(const JID& jid); - void handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request); - void handleDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request); - void handleDiscoError(const JID& jid, ErrorPayload::ref error); + private: + void walkNode(const JID& jid); + void markNodeCompleted(const JID& jid); + void handleDiscoInfoResponse(boost::shared_ptr<DiscoInfo> info, ErrorPayload::ref error, GetDiscoInfoRequest::ref request); + void handleDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error, GetDiscoItemsRequest::ref request); + void handleDiscoError(const JID& jid, ErrorPayload::ref error); - private: - JID service_; - IQRouter* iqRouter_; - size_t maxSteps_; - bool active_; - std::set<JID> servicesBeingSearched_; - std::set<JID> searchedServices_; - std::set<GetDiscoInfoRequest::ref> pendingDiscoInfoRequests_; - std::set<GetDiscoItemsRequest::ref> pendingDiscoItemsRequests_; - }; + private: + JID service_; + IQRouter* iqRouter_; + size_t maxSteps_; + bool active_; + std::set<JID> servicesBeingSearched_; + std::set<JID> searchedServices_; + std::set<GetDiscoInfoRequest::ref> pendingDiscoInfoRequests_; + std::set<GetDiscoItemsRequest::ref> pendingDiscoItemsRequests_; + }; } diff --git a/Swiften/Disco/DummyEntityCapsProvider.cpp b/Swiften/Disco/DummyEntityCapsProvider.cpp index 65baf7a..6e9d898 100644 --- a/Swiften/Disco/DummyEntityCapsProvider.cpp +++ b/Swiften/Disco/DummyEntityCapsProvider.cpp @@ -11,11 +11,11 @@ namespace Swift { DiscoInfo::ref DummyEntityCapsProvider::getCaps(const JID& jid) const { - std::map<JID, DiscoInfo::ref>::const_iterator i = caps.find(jid); - if (i != caps.end()) { - return i->second; - } - return DiscoInfo::ref(); + std::map<JID, DiscoInfo::ref>::const_iterator i = caps.find(jid); + if (i != caps.end()) { + return i->second; + } + return DiscoInfo::ref(); } } diff --git a/Swiften/Disco/DummyEntityCapsProvider.h b/Swiften/Disco/DummyEntityCapsProvider.h index d6b2c82..5171c91 100644 --- a/Swiften/Disco/DummyEntityCapsProvider.h +++ b/Swiften/Disco/DummyEntityCapsProvider.h @@ -12,13 +12,13 @@ #include <Swiften/Disco/EntityCapsProvider.h> namespace Swift { - class SWIFTEN_API DummyEntityCapsProvider : public EntityCapsProvider { - public: - DummyEntityCapsProvider() { - } + class SWIFTEN_API DummyEntityCapsProvider : public EntityCapsProvider { + public: + DummyEntityCapsProvider() { + } - DiscoInfo::ref getCaps(const JID& jid) const; + DiscoInfo::ref getCaps(const JID& jid) const; - std::map<JID, DiscoInfo::ref> caps; - }; + std::map<JID, DiscoInfo::ref> caps; + }; } diff --git a/Swiften/Disco/EntityCapsManager.cpp b/Swiften/Disco/EntityCapsManager.cpp index a79033d..d30af54 100644 --- a/Swiften/Disco/EntityCapsManager.cpp +++ b/Swiften/Disco/EntityCapsManager.cpp @@ -14,66 +14,66 @@ namespace Swift { EntityCapsManager::EntityCapsManager(CapsProvider* capsProvider, StanzaChannel* stanzaChannel) : capsProvider(capsProvider) { - stanzaChannel->onPresenceReceived.connect(boost::bind(&EntityCapsManager::handlePresenceReceived, this, _1)); - stanzaChannel->onAvailableChanged.connect(boost::bind(&EntityCapsManager::handleStanzaChannelAvailableChanged, this, _1)); - capsProvider->onCapsAvailable.connect(boost::bind(&EntityCapsManager::handleCapsAvailable, this, _1)); + stanzaChannel->onPresenceReceived.connect(boost::bind(&EntityCapsManager::handlePresenceReceived, this, _1)); + stanzaChannel->onAvailableChanged.connect(boost::bind(&EntityCapsManager::handleStanzaChannelAvailableChanged, this, _1)); + capsProvider->onCapsAvailable.connect(boost::bind(&EntityCapsManager::handleCapsAvailable, this, _1)); } void EntityCapsManager::handlePresenceReceived(boost::shared_ptr<Presence> presence) { - JID from = presence->getFrom(); - if (presence->isAvailable()) { - boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); - if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { - return; - } - std::string hash = capsInfo->getVersion(); - std::map<JID, std::string>::iterator i = caps.find(from); - if (i == caps.end() || i->second != hash) { - caps.insert(std::make_pair(from, hash)); - DiscoInfo::ref disco = capsProvider->getCaps(hash); - if (disco) { - onCapsChanged(from); - } - else if (i != caps.end()) { - caps.erase(i); - onCapsChanged(from); - } - } - } - else { - std::map<JID, std::string>::iterator i = caps.find(from); - if (i != caps.end()) { - caps.erase(i); - onCapsChanged(from); - } - } + JID from = presence->getFrom(); + if (presence->isAvailable()) { + boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>(); + if (!capsInfo || capsInfo->getHash() != "sha-1" || presence->getPayload<ErrorPayload>()) { + return; + } + std::string hash = capsInfo->getVersion(); + std::map<JID, std::string>::iterator i = caps.find(from); + if (i == caps.end() || i->second != hash) { + caps.insert(std::make_pair(from, hash)); + DiscoInfo::ref disco = capsProvider->getCaps(hash); + if (disco) { + onCapsChanged(from); + } + else if (i != caps.end()) { + caps.erase(i); + onCapsChanged(from); + } + } + } + else { + std::map<JID, std::string>::iterator i = caps.find(from); + if (i != caps.end()) { + caps.erase(i); + onCapsChanged(from); + } + } } void EntityCapsManager::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - std::map<JID, std::string> capsCopy; - capsCopy.swap(caps); - for (std::map<JID,std::string>::const_iterator i = capsCopy.begin(); i != capsCopy.end(); ++i) { - onCapsChanged(i->first); - } - } + if (available) { + std::map<JID, std::string> capsCopy; + capsCopy.swap(caps); + for (std::map<JID,std::string>::const_iterator i = capsCopy.begin(); i != capsCopy.end(); ++i) { + onCapsChanged(i->first); + } + } } void EntityCapsManager::handleCapsAvailable(const std::string& hash) { - // TODO: Use Boost.Bimap ? - for (std::map<JID,std::string>::const_iterator i = caps.begin(); i != caps.end(); ++i) { - if (i->second == hash) { - onCapsChanged(i->first); - } - } + // TODO: Use Boost.Bimap ? + for (std::map<JID,std::string>::const_iterator i = caps.begin(); i != caps.end(); ++i) { + if (i->second == hash) { + onCapsChanged(i->first); + } + } } DiscoInfo::ref EntityCapsManager::getCaps(const JID& jid) const { - std::map<JID, std::string>::const_iterator i = caps.find(jid); - if (i != caps.end()) { - return capsProvider->getCaps(i->second); - } - return DiscoInfo::ref(); + std::map<JID, std::string>::const_iterator i = caps.find(jid); + if (i != caps.end()) { + return capsProvider->getCaps(i->second); + } + return DiscoInfo::ref(); } } diff --git a/Swiften/Disco/EntityCapsManager.h b/Swiften/Disco/EntityCapsManager.h index 62c0002..2a5d2d7 100644 --- a/Swiften/Disco/EntityCapsManager.h +++ b/Swiften/Disco/EntityCapsManager.h @@ -16,31 +16,31 @@ #include <Swiften/Elements/Presence.h> namespace Swift { - class StanzaChannel; - class CapsProvider; - - /** - * This class is responsible for gathering and providing - * information about capabilities of entities on the network. - * This information is provided in the form of service discovery - * information. - */ - class SWIFTEN_API EntityCapsManager : public EntityCapsProvider, public boost::bsignals::trackable { - public: - EntityCapsManager(CapsProvider*, StanzaChannel*); - - /** - * Returns the service discovery information of the given JID. - */ - DiscoInfo::ref getCaps(const JID&) const; - - private: - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleStanzaChannelAvailableChanged(bool); - void handleCapsAvailable(const std::string&); - - private: - CapsProvider* capsProvider; - std::map<JID, std::string> caps; - }; + class StanzaChannel; + class CapsProvider; + + /** + * This class is responsible for gathering and providing + * information about capabilities of entities on the network. + * This information is provided in the form of service discovery + * information. + */ + class SWIFTEN_API EntityCapsManager : public EntityCapsProvider, public boost::bsignals::trackable { + public: + EntityCapsManager(CapsProvider*, StanzaChannel*); + + /** + * Returns the service discovery information of the given JID. + */ + DiscoInfo::ref getCaps(const JID&) const; + + private: + void handlePresenceReceived(boost::shared_ptr<Presence>); + void handleStanzaChannelAvailableChanged(bool); + void handleCapsAvailable(const std::string&); + + private: + CapsProvider* capsProvider; + std::map<JID, std::string> caps; + }; } diff --git a/Swiften/Disco/EntityCapsProvider.h b/Swiften/Disco/EntityCapsProvider.h index abc5758..34984ca 100644 --- a/Swiften/Disco/EntityCapsProvider.h +++ b/Swiften/Disco/EntityCapsProvider.h @@ -12,23 +12,23 @@ #include <Swiften/JID/JID.h> namespace Swift { - /** - * This class provides information about capabilities of entities on the network. - * This information is provided in the form of service discovery - * information. - */ - class SWIFTEN_API EntityCapsProvider { - public: - virtual ~EntityCapsProvider(); + /** + * This class provides information about capabilities of entities on the network. + * This information is provided in the form of service discovery + * information. + */ + class SWIFTEN_API EntityCapsProvider { + public: + virtual ~EntityCapsProvider(); - /** - * Returns the service discovery information of the given JID. - */ - virtual DiscoInfo::ref getCaps(const JID&) const = 0; + /** + * Returns the service discovery information of the given JID. + */ + virtual DiscoInfo::ref getCaps(const JID&) const = 0; - /** - * Emitted when the capabilities of a JID changes. - */ - boost::signal<void (const JID&)> onCapsChanged; - }; + /** + * Emitted when the capabilities of a JID changes. + */ + boost::signal<void (const JID&)> onCapsChanged; + }; } diff --git a/Swiften/Disco/FeatureOracle.cpp b/Swiften/Disco/FeatureOracle.cpp index 4e61aa9..1267cb0 100644 --- a/Swiften/Disco/FeatureOracle.cpp +++ b/Swiften/Disco/FeatureOracle.cpp @@ -24,74 +24,74 @@ FeatureOracle::FeatureOracle(EntityCapsProvider* capsProvider, PresenceOracle* p } Tristate FeatureOracle::isFileTransferSupported(const JID& jid) { - DiscoInfo::ref discoInfo = getDiscoResultForJID(jid); - if (discoInfo) { - return FileTransferManager::isSupportedBy(discoInfo) ? Yes : No; - } - else { - return Maybe; - } + DiscoInfo::ref discoInfo = getDiscoResultForJID(jid); + if (discoInfo) { + return FileTransferManager::isSupportedBy(discoInfo) ? Yes : No; + } + else { + return Maybe; + } } Tristate FeatureOracle::isMessageReceiptsSupported(const JID& jid) { - return isFeatureSupported(jid, DiscoInfo::MessageDeliveryReceiptsFeature); + return isFeatureSupported(jid, DiscoInfo::MessageDeliveryReceiptsFeature); } Tristate FeatureOracle::isMessageCorrectionSupported(const JID& jid) { - return isFeatureSupported(jid, DiscoInfo::MessageCorrectionFeature); + return isFeatureSupported(jid, DiscoInfo::MessageCorrectionFeature); } DiscoInfo::ref FeatureOracle::getDiscoResultForJID(const JID& jid) { - DiscoInfo::ref discoInfo; - if (jid.isBare()) { - // Calculate the common subset of disco features of all available results and return that. - std::vector<Presence::ref> availablePresences = presenceOracle_->getAllPresence(jid); - - bool commonFeaturesInitialized = false; - std::vector<std::string> commonFeatures; - foreach(Presence::ref presence, availablePresences) { - DiscoInfo::ref presenceDiscoInfo = capsProvider_->getCaps(presence->getFrom()); - if (presenceDiscoInfo) { - std::vector<std::string> features = presenceDiscoInfo->getFeatures(); - if (!commonFeaturesInitialized) { - commonFeatures = features; - commonFeaturesInitialized = true; - } - else { - std::vector<std::string> featuresToRemove; - foreach(const std::string& feature, commonFeatures) { - if (std::find(features.begin(), features.end(), feature) == features.end()) { - featuresToRemove.push_back(feature); - } - } - foreach(const std::string& featureToRemove, featuresToRemove) { - commonFeatures.erase(std::remove(commonFeatures.begin(), commonFeatures.end(), featureToRemove), commonFeatures.end()); - } - } - } - } - discoInfo = boost::make_shared<DiscoInfo>(); - - foreach(const std::string& commonFeature, commonFeatures) { - discoInfo->addFeature(commonFeature); - } - } - else { - // Return the disco result of the full JID. - discoInfo = capsProvider_->getCaps(jid); - } - - return discoInfo; + DiscoInfo::ref discoInfo; + if (jid.isBare()) { + // Calculate the common subset of disco features of all available results and return that. + std::vector<Presence::ref> availablePresences = presenceOracle_->getAllPresence(jid); + + bool commonFeaturesInitialized = false; + std::vector<std::string> commonFeatures; + foreach(Presence::ref presence, availablePresences) { + DiscoInfo::ref presenceDiscoInfo = capsProvider_->getCaps(presence->getFrom()); + if (presenceDiscoInfo) { + std::vector<std::string> features = presenceDiscoInfo->getFeatures(); + if (!commonFeaturesInitialized) { + commonFeatures = features; + commonFeaturesInitialized = true; + } + else { + std::vector<std::string> featuresToRemove; + foreach(const std::string& feature, commonFeatures) { + if (std::find(features.begin(), features.end(), feature) == features.end()) { + featuresToRemove.push_back(feature); + } + } + foreach(const std::string& featureToRemove, featuresToRemove) { + commonFeatures.erase(std::remove(commonFeatures.begin(), commonFeatures.end(), featureToRemove), commonFeatures.end()); + } + } + } + } + discoInfo = boost::make_shared<DiscoInfo>(); + + foreach(const std::string& commonFeature, commonFeatures) { + discoInfo->addFeature(commonFeature); + } + } + else { + // Return the disco result of the full JID. + discoInfo = capsProvider_->getCaps(jid); + } + + return discoInfo; } Tristate FeatureOracle::isFeatureSupported(const JID& jid, const std::string& feature) { - DiscoInfo::ref discoInfo = getDiscoResultForJID(jid); - if (discoInfo) { - return discoInfo->hasFeature(feature) ? Yes : No; - } - else { - return Maybe; - } + DiscoInfo::ref discoInfo = getDiscoResultForJID(jid); + if (discoInfo) { + return discoInfo->hasFeature(feature) ? Yes : No; + } + else { + return Maybe; + } } } diff --git a/Swiften/Disco/FeatureOracle.h b/Swiften/Disco/FeatureOracle.h index d579e5a..d434e86 100644 --- a/Swiften/Disco/FeatureOracle.h +++ b/Swiften/Disco/FeatureOracle.h @@ -20,27 +20,27 @@ class PresenceOracle; * @brief The FeatureOracle class enables direct feature support lookup for client features supported by Swiften. */ class SWIFTEN_API FeatureOracle { - public: - FeatureOracle(EntityCapsProvider* capsProvider, PresenceOracle* presenceOracle); - - public: - Tristate isFileTransferSupported(const JID& jid); - Tristate isMessageReceiptsSupported(const JID& jid); - Tristate isMessageCorrectionSupported(const JID& jid); - - private: - /** - * @brief getDiscoResultForJID returns a shared reference to a DiscoInfo representing features supported by the jid. - * @param jid The JID to return the DiscoInfo::ref for. - * @return DiscoResult::ref - */ - DiscoInfo::ref getDiscoResultForJID(const JID& jid); - - Tristate isFeatureSupported(const JID& jid, const std::string& feature); - - private: - EntityCapsProvider* capsProvider_; - PresenceOracle* presenceOracle_; + public: + FeatureOracle(EntityCapsProvider* capsProvider, PresenceOracle* presenceOracle); + + public: + Tristate isFileTransferSupported(const JID& jid); + Tristate isMessageReceiptsSupported(const JID& jid); + Tristate isMessageCorrectionSupported(const JID& jid); + + private: + /** + * @brief getDiscoResultForJID returns a shared reference to a DiscoInfo representing features supported by the jid. + * @param jid The JID to return the DiscoInfo::ref for. + * @return DiscoResult::ref + */ + DiscoInfo::ref getDiscoResultForJID(const JID& jid); + + Tristate isFeatureSupported(const JID& jid, const std::string& feature); + + private: + EntityCapsProvider* capsProvider_; + PresenceOracle* presenceOracle_; }; } diff --git a/Swiften/Disco/GetDiscoInfoRequest.h b/Swiften/Disco/GetDiscoInfoRequest.h index 81b212c..ccbd3e2 100644 --- a/Swiften/Disco/GetDiscoInfoRequest.h +++ b/Swiften/Disco/GetDiscoInfoRequest.h @@ -13,26 +13,26 @@ #include <Swiften/Queries/GenericRequest.h> namespace Swift { - class SWIFTEN_API GetDiscoInfoRequest : public GenericRequest<DiscoInfo> { - public: - typedef boost::shared_ptr<GetDiscoInfoRequest> ref; - - static ref create(const JID& jid, IQRouter* router) { - return ref(new GetDiscoInfoRequest(jid, router)); - } - - static ref create(const JID& jid, const std::string& node, IQRouter* router) { - return ref(new GetDiscoInfoRequest(jid, node, router)); - } - - private: - GetDiscoInfoRequest(const JID& jid, IQRouter* router) : - GenericRequest<DiscoInfo>(IQ::Get, jid, boost::make_shared<DiscoInfo>(), router) { - } - - GetDiscoInfoRequest(const JID& jid, const std::string& node, IQRouter* router) : - GenericRequest<DiscoInfo>(IQ::Get, jid, boost::make_shared<DiscoInfo>(), router) { - getPayloadGeneric()->setNode(node); - } - }; + class SWIFTEN_API GetDiscoInfoRequest : public GenericRequest<DiscoInfo> { + public: + typedef boost::shared_ptr<GetDiscoInfoRequest> ref; + + static ref create(const JID& jid, IQRouter* router) { + return ref(new GetDiscoInfoRequest(jid, router)); + } + + static ref create(const JID& jid, const std::string& node, IQRouter* router) { + return ref(new GetDiscoInfoRequest(jid, node, router)); + } + + private: + GetDiscoInfoRequest(const JID& jid, IQRouter* router) : + GenericRequest<DiscoInfo>(IQ::Get, jid, boost::make_shared<DiscoInfo>(), router) { + } + + GetDiscoInfoRequest(const JID& jid, const std::string& node, IQRouter* router) : + GenericRequest<DiscoInfo>(IQ::Get, jid, boost::make_shared<DiscoInfo>(), router) { + getPayloadGeneric()->setNode(node); + } + }; } diff --git a/Swiften/Disco/GetDiscoItemsRequest.h b/Swiften/Disco/GetDiscoItemsRequest.h index 0a96f96..7f1adc6 100644 --- a/Swiften/Disco/GetDiscoItemsRequest.h +++ b/Swiften/Disco/GetDiscoItemsRequest.h @@ -13,26 +13,26 @@ #include <Swiften/Queries/GenericRequest.h> namespace Swift { - class SWIFTEN_API GetDiscoItemsRequest : public GenericRequest<DiscoItems> { - public: - typedef boost::shared_ptr<GetDiscoItemsRequest> ref; - - static ref create(const JID& jid, IQRouter* router) { - return ref(new GetDiscoItemsRequest(jid, router)); - } - - static ref create(const JID& jid, const std::string& node, IQRouter* router) { - return ref(new GetDiscoItemsRequest(jid, node, router)); - } - - private: - GetDiscoItemsRequest(const JID& jid, IQRouter* router) : - GenericRequest<DiscoItems>(IQ::Get, jid, boost::make_shared<DiscoItems>(), router) { - } - - GetDiscoItemsRequest(const JID& jid, const std::string& node, IQRouter* router) : - GenericRequest<DiscoItems>(IQ::Get, jid, boost::make_shared<DiscoItems>(), router) { - getPayloadGeneric()->setNode(node); - } - }; + class SWIFTEN_API GetDiscoItemsRequest : public GenericRequest<DiscoItems> { + public: + typedef boost::shared_ptr<GetDiscoItemsRequest> ref; + + static ref create(const JID& jid, IQRouter* router) { + return ref(new GetDiscoItemsRequest(jid, router)); + } + + static ref create(const JID& jid, const std::string& node, IQRouter* router) { + return ref(new GetDiscoItemsRequest(jid, node, router)); + } + + private: + GetDiscoItemsRequest(const JID& jid, IQRouter* router) : + GenericRequest<DiscoItems>(IQ::Get, jid, boost::make_shared<DiscoItems>(), router) { + } + + GetDiscoItemsRequest(const JID& jid, const std::string& node, IQRouter* router) : + GenericRequest<DiscoItems>(IQ::Get, jid, boost::make_shared<DiscoItems>(), router) { + getPayloadGeneric()->setNode(node); + } + }; } diff --git a/Swiften/Disco/JIDDiscoInfoResponder.cpp b/Swiften/Disco/JIDDiscoInfoResponder.cpp index 8803b6b..7bec992 100644 --- a/Swiften/Disco/JIDDiscoInfoResponder.cpp +++ b/Swiften/Disco/JIDDiscoInfoResponder.cpp @@ -17,41 +17,41 @@ JIDDiscoInfoResponder::JIDDiscoInfoResponder(IQRouter* router) : GetResponder<Di } void JIDDiscoInfoResponder::clearDiscoInfo(const JID& jid) { - info.erase(jid); + info.erase(jid); } void JIDDiscoInfoResponder::setDiscoInfo(const JID& jid, const DiscoInfo& discoInfo) { - JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; - i->second.discoInfo = discoInfo; + JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; + i->second.discoInfo = discoInfo; } void JIDDiscoInfoResponder::setDiscoInfo(const JID& jid, const std::string& node, const DiscoInfo& discoInfo) { - JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; - DiscoInfo newInfo(discoInfo); - newInfo.setNode(node); - i->second.nodeDiscoInfo[node] = newInfo; + JIDDiscoInfoMap::iterator i = info.insert(std::make_pair(jid, JIDDiscoInfo())).first; + DiscoInfo newInfo(discoInfo); + newInfo.setNode(node); + i->second.nodeDiscoInfo[node] = newInfo; } bool JIDDiscoInfoResponder::handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> discoInfo) { - JIDDiscoInfoMap::const_iterator i = info.find(to); - if (i != info.end()) { - if (discoInfo->getNode().empty()) { - sendResponse(from, to, id, boost::make_shared<DiscoInfo>(i->second.discoInfo)); - } - else { - std::map<std::string,DiscoInfo>::const_iterator j = i->second.nodeDiscoInfo.find(discoInfo->getNode()); - if (j != i->second.nodeDiscoInfo.end()) { - sendResponse(from, to, id, boost::make_shared<DiscoInfo>(j->second)); - } - else { - sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - } - } - else { - sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); - } - return true; + JIDDiscoInfoMap::const_iterator i = info.find(to); + if (i != info.end()) { + if (discoInfo->getNode().empty()) { + sendResponse(from, to, id, boost::make_shared<DiscoInfo>(i->second.discoInfo)); + } + else { + std::map<std::string,DiscoInfo>::const_iterator j = i->second.nodeDiscoInfo.find(discoInfo->getNode()); + if (j != i->second.nodeDiscoInfo.end()) { + sendResponse(from, to, id, boost::make_shared<DiscoInfo>(j->second)); + } + else { + sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + } + } + else { + sendError(from, to, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel); + } + return true; } } diff --git a/Swiften/Disco/JIDDiscoInfoResponder.h b/Swiften/Disco/JIDDiscoInfoResponder.h index 1323b2d..e2fbb5b7 100644 --- a/Swiften/Disco/JIDDiscoInfoResponder.h +++ b/Swiften/Disco/JIDDiscoInfoResponder.h @@ -14,25 +14,25 @@ #include <Swiften/Queries/GetResponder.h> namespace Swift { - class IQRouter; - - class SWIFTEN_API JIDDiscoInfoResponder : public GetResponder<DiscoInfo> { - public: - JIDDiscoInfoResponder(IQRouter* router); - - void clearDiscoInfo(const JID& jid); - void setDiscoInfo(const JID& jid, const DiscoInfo& info); - void setDiscoInfo(const JID& jid, const std::string& node, const DiscoInfo& info); - - private: - virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> payload); - - private: - struct JIDDiscoInfo { - DiscoInfo discoInfo; - std::map<std::string, DiscoInfo> nodeDiscoInfo; - }; - typedef std::map<JID, JIDDiscoInfo> JIDDiscoInfoMap; - JIDDiscoInfoMap info; - }; + class IQRouter; + + class SWIFTEN_API JIDDiscoInfoResponder : public GetResponder<DiscoInfo> { + public: + JIDDiscoInfoResponder(IQRouter* router); + + void clearDiscoInfo(const JID& jid); + void setDiscoInfo(const JID& jid, const DiscoInfo& info); + void setDiscoInfo(const JID& jid, const std::string& node, const DiscoInfo& info); + + private: + virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<DiscoInfo> payload); + + private: + struct JIDDiscoInfo { + DiscoInfo discoInfo; + std::map<std::string, DiscoInfo> nodeDiscoInfo; + }; + typedef std::map<JID, JIDDiscoInfo> JIDDiscoInfoMap; + JIDDiscoInfoMap info; + }; } diff --git a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp index 857d6ff..58c9531 100644 --- a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp +++ b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp @@ -15,72 +15,72 @@ using namespace Swift; class CapsInfoGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CapsInfoGeneratorTest); - CPPUNIT_TEST(testGenerate_XEP0115SimpleExample); - CPPUNIT_TEST(testGenerate_XEP0115ComplexExample); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(CapsInfoGeneratorTest); + CPPUNIT_TEST(testGenerate_XEP0115SimpleExample); + CPPUNIT_TEST(testGenerate_XEP0115ComplexExample); + CPPUNIT_TEST_SUITE_END(); - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } + public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } - void testGenerate_XEP0115SimpleExample() { - DiscoInfo discoInfo; - discoInfo.addIdentity(DiscoInfo::Identity("Exodus 0.9.1", "client", "pc")); - discoInfo.addFeature("http://jabber.org/protocol/disco#items"); - discoInfo.addFeature("http://jabber.org/protocol/caps"); - discoInfo.addFeature("http://jabber.org/protocol/disco#info"); - discoInfo.addFeature("http://jabber.org/protocol/muc"); + void testGenerate_XEP0115SimpleExample() { + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity("Exodus 0.9.1", "client", "pc")); + discoInfo.addFeature("http://jabber.org/protocol/disco#items"); + discoInfo.addFeature("http://jabber.org/protocol/caps"); + discoInfo.addFeature("http://jabber.org/protocol/disco#info"); + discoInfo.addFeature("http://jabber.org/protocol/muc"); - CapsInfoGenerator testling("http://code.google.com/p/exodus", crypto.get()); - CapsInfo result = testling.generateCapsInfo(discoInfo); + CapsInfoGenerator testling("http://code.google.com/p/exodus", crypto.get()); + CapsInfo result = testling.generateCapsInfo(discoInfo); - CPPUNIT_ASSERT_EQUAL(std::string("http://code.google.com/p/exodus"), result.getNode()); - CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), result.getHash()); - CPPUNIT_ASSERT_EQUAL(std::string("QgayPKawpkPSDYmwT/WM94uAlu0="), result.getVersion()); - } + CPPUNIT_ASSERT_EQUAL(std::string("http://code.google.com/p/exodus"), result.getNode()); + CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), result.getHash()); + CPPUNIT_ASSERT_EQUAL(std::string("QgayPKawpkPSDYmwT/WM94uAlu0="), result.getVersion()); + } - void testGenerate_XEP0115ComplexExample() { - DiscoInfo discoInfo; - discoInfo.addIdentity(DiscoInfo::Identity("Psi 0.11", "client", "pc", "en")); - discoInfo.addIdentity(DiscoInfo::Identity("\xce\xa8 0.11", "client", "pc", "el")); - discoInfo.addFeature("http://jabber.org/protocol/disco#items"); - discoInfo.addFeature("http://jabber.org/protocol/caps"); - discoInfo.addFeature("http://jabber.org/protocol/disco#info"); - discoInfo.addFeature("http://jabber.org/protocol/muc"); + void testGenerate_XEP0115ComplexExample() { + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity("Psi 0.11", "client", "pc", "en")); + discoInfo.addIdentity(DiscoInfo::Identity("\xce\xa8 0.11", "client", "pc", "el")); + discoInfo.addFeature("http://jabber.org/protocol/disco#items"); + discoInfo.addFeature("http://jabber.org/protocol/caps"); + discoInfo.addFeature("http://jabber.org/protocol/disco#info"); + discoInfo.addFeature("http://jabber.org/protocol/muc"); - Form::ref extension(new Form(Form::ResultType)); - FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); - field->setName("FORM_TYPE"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::ListMultiType); - field->addValue("ipv6"); - field->addValue("ipv4"); - field->setName("ip_version"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "Psi"); - field->setName("software"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "0.11"); - field->setName("software_version"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "Mac"); - field->setName("os"); - extension->addField(field); - field = boost::make_shared<FormField>(FormField::TextSingleType, "10.5.1"); - field->setName("os_version"); - extension->addField(field); - discoInfo.addExtension(extension); + Form::ref extension(new Form(Form::ResultType)); + FormField::ref field = boost::make_shared<FormField>(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); + field->setName("FORM_TYPE"); + extension->addField(field); + field = boost::make_shared<FormField>(FormField::ListMultiType); + field->addValue("ipv6"); + field->addValue("ipv4"); + field->setName("ip_version"); + extension->addField(field); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Psi"); + field->setName("software"); + extension->addField(field); + field = boost::make_shared<FormField>(FormField::TextSingleType, "0.11"); + field->setName("software_version"); + extension->addField(field); + field = boost::make_shared<FormField>(FormField::TextSingleType, "Mac"); + field->setName("os"); + extension->addField(field); + field = boost::make_shared<FormField>(FormField::TextSingleType, "10.5.1"); + field->setName("os_version"); + extension->addField(field); + discoInfo.addExtension(extension); - CapsInfoGenerator testling("http://psi-im.org", crypto.get()); - CapsInfo result = testling.generateCapsInfo(discoInfo); + CapsInfoGenerator testling("http://psi-im.org", crypto.get()); + CapsInfo result = testling.generateCapsInfo(discoInfo); - CPPUNIT_ASSERT_EQUAL(std::string("q07IKJEyjvHSyhy//CH0CxmKi8w="), result.getVersion()); - } - - private: - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_ASSERT_EQUAL(std::string("q07IKJEyjvHSyhy//CH0CxmKi8w="), result.getVersion()); + } + + private: + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsInfoGeneratorTest); diff --git a/Swiften/Disco/UnitTest/CapsManagerTest.cpp b/Swiften/Disco/UnitTest/CapsManagerTest.cpp index 50f369c..fe7ee7e 100644 --- a/Swiften/Disco/UnitTest/CapsManagerTest.cpp +++ b/Swiften/Disco/UnitTest/CapsManagerTest.cpp @@ -24,269 +24,269 @@ using namespace Swift; class CapsManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(CapsManagerTest); - CPPUNIT_TEST(testReceiveNewHashRequestsDisco); - CPPUNIT_TEST(testReceiveSameHashDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveLegacyCapsDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco); - CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco); - CPPUNIT_TEST(testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco); - CPPUNIT_TEST(testReceiveSuccesfulDiscoStoresCaps); - CPPUNIT_TEST(testReceiveIncorrectVerificationDiscoDoesNotStoreCaps); - CPPUNIT_TEST(testReceiveFailingDiscoFallsBack); - CPPUNIT_TEST(testReceiveNoDiscoFallsBack); - CPPUNIT_TEST(testReceiveFailingFallbackDiscoFallsBack); - CPPUNIT_TEST(testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco); - CPPUNIT_TEST(testReconnectResetsFallback); - CPPUNIT_TEST(testReconnectResetsRequests); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - storage = new CapsMemoryStorage(); - user1 = JID("user1@bar.com/bla"); - discoInfo1 = boost::make_shared<DiscoInfo>(); - discoInfo1->addFeature("http://swift.im/feature1"); - capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - user2 = JID("user2@foo.com/baz"); - discoInfo2 = boost::make_shared<DiscoInfo>(); - discoInfo2->addFeature("http://swift.im/feature2"); - capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); - user3 = JID("user3@foo.com/baz"); - legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", ""); - } - - void tearDown() { - delete storage; - delete iqRouter; - delete stanzaChannel; - } - - void testReceiveNewHashRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT_EQUAL("http://node1.im#" + capsInfo1->getVersion(), discoInfo->getNode()); - } - - void testReceiveSameHashDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveLegacyCapsDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, legacyCapsInfo); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo1); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashFromSameUserAfterIncorrectVerificationDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo2); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user2, capsInfo1); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); - } - - void testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo2); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user2, capsInfo1); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); - } - - void testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); - - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo2); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - } - - void testReceiveSuccesfulDiscoStoresCaps() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo1); - - boost::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT(discoInfo->hasFeature("http://swift.im/feature1")); - } - - void testReceiveIncorrectVerificationDiscoDoesNotStoreCaps() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendDiscoInfoResult(discoInfo2); - - boost::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); - CPPUNIT_ASSERT(!discoInfo); - } - - void testReceiveFailingDiscoFallsBack() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); - boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); - } - - void testReceiveNoDiscoFallsBack() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), boost::shared_ptr<DiscoInfo>())); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); - boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(discoInfo); - CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); - } - - void testReceiveFailingFallbackDiscoFallsBack() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - sendPresenceWithCaps(user3, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[1]->getTo(), stanzaChannel->sentStanzas[1]->getID())); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(2, user3, IQ::Get)); - } - - void testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - stanzaChannel->sentStanzas.clear(); - - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - } - - void testReconnectResetsFallback() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo1alt); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - stanzaChannel->sentStanzas.clear(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testReconnectResetsRequests() { - boost::shared_ptr<CapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - stanzaChannel->sentStanzas.clear(); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); - } - - private: - boost::shared_ptr<CapsManager> createManager() { - boost::shared_ptr<CapsManager> manager(new CapsManager(storage, stanzaChannel, iqRouter, crypto.get())); - manager->setWarnOnInvalidHash(false); - //manager->onCapsChanged.connect(boost::bind(&CapsManagerTest::handleCapsChanged, this, _1)); - return manager; - } - - void handleCapsChanged(const JID& jid) { - changes.push_back(jid); - } - - void sendPresenceWithCaps(const JID& jid, boost::shared_ptr<CapsInfo> caps) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->addPayload(caps); - stanzaChannel->onPresenceReceived(presence); - } - - void sendDiscoInfoResult(boost::shared_ptr<DiscoInfo> discoInfo) { - stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), discoInfo)); - } - - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - CapsStorage* storage; - std::vector<JID> changes; - JID user1; - boost::shared_ptr<DiscoInfo> discoInfo1; - boost::shared_ptr<CapsInfo> capsInfo1; - boost::shared_ptr<CapsInfo> capsInfo1alt; - JID user2; - boost::shared_ptr<DiscoInfo> discoInfo2; - boost::shared_ptr<CapsInfo> capsInfo2; - boost::shared_ptr<CapsInfo> legacyCapsInfo; - JID user3; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(CapsManagerTest); + CPPUNIT_TEST(testReceiveNewHashRequestsDisco); + CPPUNIT_TEST(testReceiveSameHashDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveLegacyCapsDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco); + CPPUNIT_TEST(testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco); + CPPUNIT_TEST(testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco); + CPPUNIT_TEST(testReceiveSuccesfulDiscoStoresCaps); + CPPUNIT_TEST(testReceiveIncorrectVerificationDiscoDoesNotStoreCaps); + CPPUNIT_TEST(testReceiveFailingDiscoFallsBack); + CPPUNIT_TEST(testReceiveNoDiscoFallsBack); + CPPUNIT_TEST(testReceiveFailingFallbackDiscoFallsBack); + CPPUNIT_TEST(testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco); + CPPUNIT_TEST(testReconnectResetsFallback); + CPPUNIT_TEST(testReconnectResetsRequests); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + storage = new CapsMemoryStorage(); + user1 = JID("user1@bar.com/bla"); + discoInfo1 = boost::make_shared<DiscoInfo>(); + discoInfo1->addFeature("http://swift.im/feature1"); + capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + user2 = JID("user2@foo.com/baz"); + discoInfo2 = boost::make_shared<DiscoInfo>(); + discoInfo2->addFeature("http://swift.im/feature2"); + capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); + user3 = JID("user3@foo.com/baz"); + legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", ""); + } + + void tearDown() { + delete storage; + delete iqRouter; + delete stanzaChannel; + } + + void testReceiveNewHashRequestsDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT_EQUAL("http://node1.im#" + capsInfo1->getVersion(), discoInfo->getNode()); + } + + void testReceiveSameHashDoesNotRequestDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveLegacyCapsDoesNotRequestDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, legacyCapsInfo); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashAfterSuccesfulDiscoDoesNotRequestDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo1); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashFromSameUserAfterIncorrectVerificationDoesNotRequestDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo2); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReceiveSameHashFromDifferentUserAfterFailedDiscoRequestsDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user2, capsInfo1); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); + } + + void testReceiveSameHashFromDifferentUserAfterIncorrectVerificationRequestsDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo2); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user2, capsInfo1); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user2, IQ::Get)); + } + + void testReceiveDifferentHashFromSameUserAfterFailedDiscoDoesNotRequestDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getID())); + + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo2); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + } + + void testReceiveSuccesfulDiscoStoresCaps() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo1); + + boost::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT(discoInfo->hasFeature("http://swift.im/feature1")); + } + + void testReceiveIncorrectVerificationDiscoDoesNotStoreCaps() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendDiscoInfoResult(discoInfo2); + + boost::shared_ptr<DiscoInfo> discoInfo(storage->getDiscoInfo(capsInfo1->getVersion())); + CPPUNIT_ASSERT(!discoInfo); + } + + void testReceiveFailingDiscoFallsBack() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); + boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); + } + + void testReceiveNoDiscoFallsBack() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), boost::shared_ptr<DiscoInfo>())); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(1, user2, IQ::Get)); + boost::shared_ptr<DiscoInfo> discoInfo(stanzaChannel->sentStanzas[1]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(discoInfo); + CPPUNIT_ASSERT_EQUAL("http://node2.im#" + capsInfo1alt->getVersion(), discoInfo->getNode()); + } + + void testReceiveFailingFallbackDiscoFallsBack() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + sendPresenceWithCaps(user3, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[1]->getTo(), stanzaChannel->sentStanzas[1]->getID())); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(2, user3, IQ::Get)); + } + + void testReceiveSameHashFromFailingUserAfterReconnectRequestsDisco() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + stanzaChannel->sentStanzas.clear(); + + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + } + + void testReconnectResetsFallback() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo1alt); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + stanzaChannel->sentStanzas.clear(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testReconnectResetsRequests() { + boost::shared_ptr<CapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + stanzaChannel->sentStanzas.clear(); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<DiscoInfo>(0, user1, IQ::Get)); + } + + private: + boost::shared_ptr<CapsManager> createManager() { + boost::shared_ptr<CapsManager> manager(new CapsManager(storage, stanzaChannel, iqRouter, crypto.get())); + manager->setWarnOnInvalidHash(false); + //manager->onCapsChanged.connect(boost::bind(&CapsManagerTest::handleCapsChanged, this, _1)); + return manager; + } + + void handleCapsChanged(const JID& jid) { + changes.push_back(jid); + } + + void sendPresenceWithCaps(const JID& jid, boost::shared_ptr<CapsInfo> caps) { + boost::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->addPayload(caps); + stanzaChannel->onPresenceReceived(presence); + } + + void sendDiscoInfoResult(boost::shared_ptr<DiscoInfo> discoInfo) { + stanzaChannel->onIQReceived(IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID(), discoInfo)); + } + + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + CapsStorage* storage; + std::vector<JID> changes; + JID user1; + boost::shared_ptr<DiscoInfo> discoInfo1; + boost::shared_ptr<CapsInfo> capsInfo1; + boost::shared_ptr<CapsInfo> capsInfo1alt; + JID user2; + boost::shared_ptr<DiscoInfo> discoInfo2; + boost::shared_ptr<CapsInfo> capsInfo2; + boost::shared_ptr<CapsInfo> legacyCapsInfo; + JID user3; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(CapsManagerTest); diff --git a/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp b/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp index 2bd50a3..907029e 100644 --- a/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp +++ b/Swiften/Disco/UnitTest/DiscoInfoResponderTest.cpp @@ -16,82 +16,82 @@ using namespace Swift; class DiscoInfoResponderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DiscoInfoResponderTest); - CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); - CPPUNIT_TEST(testHandleRequest_GetNodeInfo); - CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - } - - void tearDown() { - delete router_; - delete channel_; - } - - void testHandleRequest_GetToplevelInfo() { - DiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(discoInfo); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("foo")); - - testling.stop(); - } - - void testHandleRequest_GetNodeInfo() { - DiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(discoInfo); - DiscoInfo discoInfoBar; - discoInfoBar.addFeature("bar"); - testling.setDiscoInfo("bar-node", discoInfoBar); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("bar")); - - testling.stop(); - } - - void testHandleRequest_GetInvalidNodeInfo() { - DiscoInfoResponder testling(router_); - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); - testling.start(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(payload); - - testling.stop(); - } - - private: - IQRouter* router_; - DummyIQChannel* channel_; + CPPUNIT_TEST_SUITE(DiscoInfoResponderTest); + CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); + CPPUNIT_TEST(testHandleRequest_GetNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + } + + void tearDown() { + delete router_; + delete channel_; + } + + void testHandleRequest_GetToplevelInfo() { + DiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(discoInfo); + + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("foo")); + + testling.stop(); + } + + void testHandleRequest_GetNodeInfo() { + DiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(discoInfo); + DiscoInfo discoInfoBar; + discoInfoBar.addFeature("bar"); + testling.setDiscoInfo("bar-node", discoInfoBar); + + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("bar")); + + testling.stop(); + } + + void testHandleRequest_GetInvalidNodeInfo() { + DiscoInfoResponder testling(router_); + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com"), "id-1", query)); + testling.start(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + private: + IQRouter* router_; + DummyIQChannel* channel_; }; CPPUNIT_TEST_SUITE_REGISTRATION(DiscoInfoResponderTest); diff --git a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp index 0a52dec..4062753 100644 --- a/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp +++ b/Swiften/Disco/UnitTest/EntityCapsManagerTest.cpp @@ -22,174 +22,174 @@ using namespace Swift; class EntityCapsManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(EntityCapsManagerTest); - CPPUNIT_TEST(testReceiveKnownHash); - CPPUNIT_TEST(testReceiveKnownHashTwiceDoesNotTriggerChange); - CPPUNIT_TEST(testReceiveUnknownHashDoesNotTriggerChange); - CPPUNIT_TEST(testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps); - CPPUNIT_TEST(testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps); - CPPUNIT_TEST(testReconnectTriggersChangeAndClearsCaps); - CPPUNIT_TEST(testHashAvailable); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - - stanzaChannel = new DummyStanzaChannel(); - capsProvider = new DummyCapsProvider(); - - user1 = JID("user1@bar.com/bla"); - discoInfo1 = boost::make_shared<DiscoInfo>(); - discoInfo1->addFeature("http://swift.im/feature1"); - capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); - user2 = JID("user2@foo.com/baz"); - discoInfo2 = boost::make_shared<DiscoInfo>(); - discoInfo2->addFeature("http://swift.im/feature2"); - capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); - user3 = JID("user3@foo.com/baz"); - legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", ""); - } - - void tearDown() { - delete capsProvider; - delete stanzaChannel; - } - - void testReceiveKnownHash() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); - } - - void testReceiveKnownHashTwiceDoesNotTriggerChange() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - changes.clear(); - - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testReceiveUnknownHashDoesNotTriggerChange() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); - } - - void testHashAvailable() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - sendPresenceWithCaps(user1, capsInfo1); - - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - capsProvider->onCapsAvailable(capsInfo1->getVersion()); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); - } - - void testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - changes.clear(); - sendPresenceWithCaps(user1, capsInfo2); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT(!testling->getCaps(user1)); - } - - void testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - sendPresenceWithCaps(user1, capsInfo1); - changes.clear(); - sendUnavailablePresence(user1); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT(!testling->getCaps(user1)); - } - - void testReconnectTriggersChangeAndClearsCaps() { - boost::shared_ptr<EntityCapsManager> testling = createManager(); - capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; - capsProvider->caps[capsInfo2->getVersion()] = discoInfo2; - sendPresenceWithCaps(user1, capsInfo1); - sendPresenceWithCaps(user2, capsInfo2); - changes.clear(); - stanzaChannel->setAvailable(false); - stanzaChannel->setAvailable(true); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size())); - CPPUNIT_ASSERT_EQUAL(user1, changes[0]); - CPPUNIT_ASSERT(!testling->getCaps(user1)); - CPPUNIT_ASSERT_EQUAL(user2, changes[1]); - CPPUNIT_ASSERT(!testling->getCaps(user2)); - } - - private: - boost::shared_ptr<EntityCapsManager> createManager() { - boost::shared_ptr<EntityCapsManager> manager(new EntityCapsManager(capsProvider, stanzaChannel)); - manager->onCapsChanged.connect(boost::bind(&EntityCapsManagerTest::handleCapsChanged, this, _1)); - return manager; - } - - void handleCapsChanged(const JID& jid) { - changes.push_back(jid); - } - - void sendPresenceWithCaps(const JID& jid, boost::shared_ptr<CapsInfo> caps) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->addPayload(caps); - stanzaChannel->onPresenceReceived(presence); - } - - void sendUnavailablePresence(const JID& jid) { - boost::shared_ptr<Presence> presence(new Presence()); - presence->setFrom(jid); - presence->setType(Presence::Unavailable); - stanzaChannel->onPresenceReceived(presence); - } - - private: - struct DummyCapsProvider : public CapsProvider { - virtual DiscoInfo::ref getCaps(const std::string& hash) const { - std::map<std::string, DiscoInfo::ref>::const_iterator i = caps.find(hash); - if (i != caps.end()) { - return i->second; - } - return DiscoInfo::ref(); - } - - std::map<std::string, DiscoInfo::ref> caps; - }; - - private: - DummyStanzaChannel* stanzaChannel; - DummyCapsProvider* capsProvider; - JID user1; - boost::shared_ptr<DiscoInfo> discoInfo1; - boost::shared_ptr<CapsInfo> capsInfo1; - boost::shared_ptr<CapsInfo> capsInfo1alt; - JID user2; - boost::shared_ptr<DiscoInfo> discoInfo2; - boost::shared_ptr<CapsInfo> capsInfo2; - boost::shared_ptr<CapsInfo> legacyCapsInfo; - JID user3; - std::vector<JID> changes; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(EntityCapsManagerTest); + CPPUNIT_TEST(testReceiveKnownHash); + CPPUNIT_TEST(testReceiveKnownHashTwiceDoesNotTriggerChange); + CPPUNIT_TEST(testReceiveUnknownHashDoesNotTriggerChange); + CPPUNIT_TEST(testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps); + CPPUNIT_TEST(testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps); + CPPUNIT_TEST(testReconnectTriggersChangeAndClearsCaps); + CPPUNIT_TEST(testHashAvailable); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + + stanzaChannel = new DummyStanzaChannel(); + capsProvider = new DummyCapsProvider(); + + user1 = JID("user1@bar.com/bla"); + discoInfo1 = boost::make_shared<DiscoInfo>(); + discoInfo1->addFeature("http://swift.im/feature1"); + capsInfo1 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node1.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + capsInfo1alt = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo1.get())); + user2 = JID("user2@foo.com/baz"); + discoInfo2 = boost::make_shared<DiscoInfo>(); + discoInfo2->addFeature("http://swift.im/feature2"); + capsInfo2 = boost::make_shared<CapsInfo>(CapsInfoGenerator("http://node2.im", crypto.get()).generateCapsInfo(*discoInfo2.get())); + user3 = JID("user3@foo.com/baz"); + legacyCapsInfo = boost::make_shared<CapsInfo>("http://swift.im", "ver1", ""); + } + + void tearDown() { + delete capsProvider; + delete stanzaChannel; + } + + void testReceiveKnownHash() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); + } + + void testReceiveKnownHashTwiceDoesNotTriggerChange() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + changes.clear(); + + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testReceiveUnknownHashDoesNotTriggerChange() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changes.size())); + } + + void testHashAvailable() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + sendPresenceWithCaps(user1, capsInfo1); + + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + capsProvider->onCapsAvailable(capsInfo1->getVersion()); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT_EQUAL(discoInfo1, testling->getCaps(user1)); + } + + void testReceiveUnknownHashAfterKnownHashTriggersChangeAndClearsCaps() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + changes.clear(); + sendPresenceWithCaps(user1, capsInfo2); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT(!testling->getCaps(user1)); + } + + void testReceiveUnavailablePresenceAfterKnownHashTriggersChangeAndClearsCaps() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + sendPresenceWithCaps(user1, capsInfo1); + changes.clear(); + sendUnavailablePresence(user1); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT(!testling->getCaps(user1)); + } + + void testReconnectTriggersChangeAndClearsCaps() { + boost::shared_ptr<EntityCapsManager> testling = createManager(); + capsProvider->caps[capsInfo1->getVersion()] = discoInfo1; + capsProvider->caps[capsInfo2->getVersion()] = discoInfo2; + sendPresenceWithCaps(user1, capsInfo1); + sendPresenceWithCaps(user2, capsInfo2); + changes.clear(); + stanzaChannel->setAvailable(false); + stanzaChannel->setAvailable(true); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(changes.size())); + CPPUNIT_ASSERT_EQUAL(user1, changes[0]); + CPPUNIT_ASSERT(!testling->getCaps(user1)); + CPPUNIT_ASSERT_EQUAL(user2, changes[1]); + CPPUNIT_ASSERT(!testling->getCaps(user2)); + } + + private: + boost::shared_ptr<EntityCapsManager> createManager() { + boost::shared_ptr<EntityCapsManager> manager(new EntityCapsManager(capsProvider, stanzaChannel)); + manager->onCapsChanged.connect(boost::bind(&EntityCapsManagerTest::handleCapsChanged, this, _1)); + return manager; + } + + void handleCapsChanged(const JID& jid) { + changes.push_back(jid); + } + + void sendPresenceWithCaps(const JID& jid, boost::shared_ptr<CapsInfo> caps) { + boost::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->addPayload(caps); + stanzaChannel->onPresenceReceived(presence); + } + + void sendUnavailablePresence(const JID& jid) { + boost::shared_ptr<Presence> presence(new Presence()); + presence->setFrom(jid); + presence->setType(Presence::Unavailable); + stanzaChannel->onPresenceReceived(presence); + } + + private: + struct DummyCapsProvider : public CapsProvider { + virtual DiscoInfo::ref getCaps(const std::string& hash) const { + std::map<std::string, DiscoInfo::ref>::const_iterator i = caps.find(hash); + if (i != caps.end()) { + return i->second; + } + return DiscoInfo::ref(); + } + + std::map<std::string, DiscoInfo::ref> caps; + }; + + private: + DummyStanzaChannel* stanzaChannel; + DummyCapsProvider* capsProvider; + JID user1; + boost::shared_ptr<DiscoInfo> discoInfo1; + boost::shared_ptr<CapsInfo> capsInfo1; + boost::shared_ptr<CapsInfo> capsInfo1alt; + JID user2; + boost::shared_ptr<DiscoInfo> discoInfo2; + boost::shared_ptr<CapsInfo> capsInfo2; + boost::shared_ptr<CapsInfo> legacyCapsInfo; + JID user3; + std::vector<JID> changes; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(EntityCapsManagerTest); diff --git a/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp b/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp index 613b049..3c1a057 100644 --- a/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp +++ b/Swiften/Disco/UnitTest/JIDDiscoInfoResponderTest.cpp @@ -16,104 +16,104 @@ using namespace Swift; class JIDDiscoInfoResponderTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(JIDDiscoInfoResponderTest); - CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); - CPPUNIT_TEST(testHandleRequest_GetNodeInfo); - CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); - CPPUNIT_TEST(testHandleRequest_GetUnknownJID); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - channel_ = new DummyIQChannel(); - router_ = new IQRouter(channel_); - } - - void tearDown() { - delete router_; - delete channel_; - } - - void testHandleRequest_GetToplevelInfo() { - JIDDiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("foo")); - - testling.stop(); - } - - void testHandleRequest_GetNodeInfo() { - JIDDiscoInfoResponder testling(router_); - testling.start(); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - DiscoInfo discoInfoBar; - discoInfoBar.addFeature("bar"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), "bar-node", discoInfoBar); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); - CPPUNIT_ASSERT(payload); - CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); - CPPUNIT_ASSERT(payload->hasFeature("bar")); - - testling.stop(); - } - - void testHandleRequest_GetInvalidNodeInfo() { - JIDDiscoInfoResponder testling(router_); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - testling.start(); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - query->setNode("bar-node"); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(payload); - - testling.stop(); - } - - void testHandleRequest_GetUnknownJID() { - JIDDiscoInfoResponder testling(router_); - DiscoInfo discoInfo; - discoInfo.addFeature("foo"); - testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); - testling.start(); - - boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); - channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/fum"), "id-1", query)); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); - boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); - CPPUNIT_ASSERT(payload); - - testling.stop(); - } - - private: - IQRouter* router_; - DummyIQChannel* channel_; + CPPUNIT_TEST_SUITE(JIDDiscoInfoResponderTest); + CPPUNIT_TEST(testHandleRequest_GetToplevelInfo); + CPPUNIT_TEST(testHandleRequest_GetNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetInvalidNodeInfo); + CPPUNIT_TEST(testHandleRequest_GetUnknownJID); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + channel_ = new DummyIQChannel(); + router_ = new IQRouter(channel_); + } + + void tearDown() { + delete router_; + delete channel_; + } + + void testHandleRequest_GetToplevelInfo() { + JIDDiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string(""), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("foo")); + + testling.stop(); + } + + void testHandleRequest_GetNodeInfo() { + JIDDiscoInfoResponder testling(router_); + testling.start(); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + DiscoInfo discoInfoBar; + discoInfoBar.addFeature("bar"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), "bar-node", discoInfoBar); + + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<DiscoInfo> payload(channel_->iqs_[0]->getPayload<DiscoInfo>()); + CPPUNIT_ASSERT(payload); + CPPUNIT_ASSERT_EQUAL(std::string("bar-node"), payload->getNode()); + CPPUNIT_ASSERT(payload->hasFeature("bar")); + + testling.stop(); + } + + void testHandleRequest_GetInvalidNodeInfo() { + JIDDiscoInfoResponder testling(router_); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + testling.start(); + + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + query->setNode("bar-node"); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/baz"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + void testHandleRequest_GetUnknownJID() { + JIDDiscoInfoResponder testling(router_); + DiscoInfo discoInfo; + discoInfo.addFeature("foo"); + testling.setDiscoInfo(JID("foo@bar.com/baz"), discoInfo); + testling.start(); + + boost::shared_ptr<DiscoInfo> query(new DiscoInfo()); + channel_->onIQReceived(IQ::createRequest(IQ::Get, JID("foo@bar.com/fum"), "id-1", query)); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel_->iqs_.size())); + boost::shared_ptr<ErrorPayload> payload(channel_->iqs_[0]->getPayload<ErrorPayload>()); + CPPUNIT_ASSERT(payload); + + testling.stop(); + } + + private: + IQRouter* router_; + DummyIQChannel* channel_; }; CPPUNIT_TEST_SUITE_REGISTRATION(JIDDiscoInfoResponderTest); |