summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2016-04-21 09:02:07 (GMT)
committerKevin Smith <kevin.smith@isode.com>2016-11-10 11:09:16 (GMT)
commitd2ba1ab8a36333523bf794c23226bd044e1717c2 (patch)
tree737ac14bc1dfcec4b80192ea23e7b0e860a2f8d3 /Swiften/Presence/PresenceOracle.cpp
parent41c771ec02682c2b344263d29f68eb6452c42dbe (diff)
downloadswift-d2ba1ab8a36333523bf794c23226bd044e1717c2.zip
swift-d2ba1ab8a36333523bf794c23226bd044e1717c2.tar.bz2
Use FeatureOracle to detect file-transfer support in roster
The FeatureOracle provides tri-state feature lookup functionality for bare JIDs. It returns Yes if a feature is supported by all resources of the bare JID, Maybe if some support it, and No if none of the resources support it. If passed a full JID, it returns the specific features supported by that end-point. Sending a file to a bare JID, will send a file to the resource of the bare JID with the highest availability by presence, show status and priority and which supports the features required for a Jingle file-transfer. Test-Information: Added unit test verifying new behavior. All tests pass on OS X 10.11.6. Added new unit tests for FeatureOracle. Manually verified that the roster and chat window both use the same mechanism to detect support for file-transfers. Manually verified that file-transfers via the contact list goes to already bound full JIDs if there is an existing ChatController. Change-Id: I0175ac42ecb73f1d54f9c96ffbba773eb5e24296
Diffstat (limited to 'Swiften/Presence/PresenceOracle.cpp')
-rw-r--r--Swiften/Presence/PresenceOracle.cpp21
1 files changed, 8 insertions, 13 deletions
diff --git a/Swiften/Presence/PresenceOracle.cpp b/Swiften/Presence/PresenceOracle.cpp
index c2c1152..1c9d0ea 100644
--- a/Swiften/Presence/PresenceOracle.cpp
+++ b/Swiften/Presence/PresenceOracle.cpp
@@ -1,43 +1,42 @@
/*
- * Copyright (c) 2010-2015 Isode Limited.
+ * Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/Presence/PresenceOracle.h>
#include <queue>
#include <boost/bind.hpp>
-#include <Swiften/Base/foreach.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Elements/StatusShow.h>
#include <Swiften/Roster/XMPPRoster.h>
namespace Swift {
PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel, XMPPRoster* roster) : stanzaChannel_(stanzaChannel), xmppRoster_(roster) {
stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
xmppRoster_->onJIDRemoved.connect(boost::bind(&PresenceOracle::handleJIDRemoved, this, _1));
}
PresenceOracle::~PresenceOracle() {
stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
xmppRoster_->onJIDRemoved.disconnect(boost::bind(&PresenceOracle::handleJIDRemoved, this, _1));
}
void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) {
if (available) {
entries_.clear();
}
}
void PresenceOracle::handleIncomingPresence(Presence::ref presence) {
JID bareJID(presence->getFrom().toBare());
if (presence->getType() == Presence::Subscribe) {
}
else {
Presence::ref passedPresence = presence;
@@ -74,146 +73,142 @@ void PresenceOracle::handleJIDRemoved(const JID& removedJID) {
if (entries_.find(removedJID) != entries_.end()) {
entries_[removedJID].clear();
entries_[removedJID][removedJID] = unavailablePresence;
}
onPresenceChange(unavailablePresence);
}
Presence::ref PresenceOracle::getLastPresence(const JID& jid) const {
PresencesMap::const_iterator i = entries_.find(jid.toBare());
if (i == entries_.end()) {
return Presence::ref();
}
PresenceMap presenceMap = i->second;
PresenceMap::const_iterator j = presenceMap.find(jid);
if (j != presenceMap.end()) {
return j->second;
}
else {
return Presence::ref();
}
}
std::vector<Presence::ref> PresenceOracle::getAllPresence(const JID& bareJID) const {
std::vector<Presence::ref> results;
PresencesMap::const_iterator i = entries_.find(bareJID);
if (i == entries_.end()) {
return results;
}
- PresenceMap presenceMap = i->second;
- PresenceMap::const_iterator j = presenceMap.begin();
- for (; j != presenceMap.end(); ++j) {
- Presence::ref current = j->second;
- results.push_back(current);
+ for (const auto& jidPresence : i->second) {
+ if (jidPresence.second) {
+ results.push_back(jidPresence.second);
+ }
}
return results;
}
struct PresenceAccountCmp {
static int preferenceFromStatusShow(StatusShow::Type showType) {
switch (showType) {
case StatusShow::FFC:
return 5;
case StatusShow::Online:
return 4;
case StatusShow::DND:
return 3;
case StatusShow::Away:
return 2;
case StatusShow::XA:
return 1;
case StatusShow::None:
return 0;
}
assert(false);
return -1;
}
bool operator()(const Presence::ref& a, const Presence::ref& b) {
int aPreference = preferenceFromStatusShow(a->getShow());
int bPreference = preferenceFromStatusShow(b->getShow());
if (aPreference != bPreference) {
return aPreference < bPreference;
}
if (a->getPriority() != b->getPriority()) {
return a->getPriority() < b->getPriority();
}
return a->getFrom().getResource() < b->getFrom().getResource();
}
};
typedef std::priority_queue<Presence::ref, std::vector<Presence::ref>, PresenceAccountCmp> PresenceAccountPriorityQueue;
Presence::ref PresenceOracle::getActivePresence(const std::vector<Presence::ref> presences) {
Presence::ref accountPresence;
PresenceAccountPriorityQueue online;
PresenceAccountPriorityQueue away;
PresenceAccountPriorityQueue offline;
- foreach(Presence::ref presence, presences) {
+ for (auto&& presence : presences) {
switch (presence->getShow()) {
case StatusShow::Online:
online.push(presence);
break;
case StatusShow::Away:
away.push(presence);
break;
case StatusShow::FFC:
online.push(presence);
break;
case StatusShow::XA:
away.push(presence);
break;
case StatusShow::DND:
away.push(presence);
break;
case StatusShow::None:
offline.push(presence);
break;
}
}
if (!online.empty()) {
accountPresence = online.top();
}
else if (!away.empty()) {
accountPresence = away.top();
}
else if (!offline.empty()) {
accountPresence = offline.top();
}
return accountPresence;
}
Presence::ref PresenceOracle::getAccountPresence(const JID& jid) const {
Presence::ref accountPresence;
std::vector<Presence::ref> allPresences = getAllPresence(jid.toBare());
accountPresence = getActivePresence(allPresences);
return accountPresence;
}
Presence::ref PresenceOracle::getHighestPriorityPresence(const JID& bareJID) const {
PresencesMap::const_iterator i = entries_.find(bareJID);
if (i == entries_.end()) {
return Presence::ref();
}
- PresenceMap presenceMap = i->second;
- PresenceMap::const_iterator j = presenceMap.begin();
Presence::ref highest;
- for (; j != presenceMap.end(); ++j) {
- Presence::ref current = j->second;
+ for (const auto& jidPresence : i->second) {
+ Presence::ref current = jidPresence.second;
if (!highest
|| current->getPriority() > highest->getPriority()
|| (current->getPriority() == highest->getPriority()
&& StatusShow::typeToAvailabilityOrdering(current->getShow()) > StatusShow::typeToAvailabilityOrdering(highest->getShow()))) {
highest = current;
}
-
}
return highest;
}
}