From f035510e47989e2a2ba3beb8bd8be069dbc6394f Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 8 Dec 2011 17:55:23 +0100 Subject: [PATCH] Fixed PresenceOracle --- .../CombinedOutgoingFileTransferManager.cpp | 3 +- .../CombinedOutgoingFileTransferManager.h | 6 +- include/transport/presenceoracle.h | 57 ++++++++ include/transport/transport.h | 6 +- include/transport/user.h | 4 +- src/presenceoracle.cpp | 134 ++++++++++++++++++ src/transport.cpp | 4 +- src/user.cpp | 1 + 8 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 include/transport/presenceoracle.h create mode 100644 src/presenceoracle.cpp diff --git a/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.cpp b/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.cpp index 710b8f83..ac06ab75 100644 --- a/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.cpp +++ b/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.cpp @@ -18,13 +18,12 @@ #include #include #include -#include #include namespace Swift { -CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) { +CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) { idGenerator = new IDGenerator(); } diff --git a/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h b/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h index 765e6ba2..17e7fc58 100644 --- a/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h +++ b/include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h @@ -11,6 +11,8 @@ #include +#include "transport/presenceoracle.h" + namespace Swift { class JingleSessionManager; @@ -30,7 +32,7 @@ class PresenceOracle; class CombinedOutgoingFileTransferManager { public: - CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, PresenceOracle* presOracle, SOCKS5BytestreamServer *server); + CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle* presOracle, SOCKS5BytestreamServer *server); ~CombinedOutgoingFileTransferManager(); boost::shared_ptr createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr, const StreamInitiationFileInfo&); @@ -46,7 +48,7 @@ private: IDGenerator *idGenerator; SOCKS5BytestreamRegistry* bytestreamRegistry; SOCKS5BytestreamProxy* bytestreamProxy; - PresenceOracle* presenceOracle; + Transport::PresenceOracle* presenceOracle; SOCKS5BytestreamServer *bytestreamServer; }; diff --git a/include/transport/presenceoracle.h b/include/transport/presenceoracle.h new file mode 100644 index 00000000..763cf83d --- /dev/null +++ b/include/transport/presenceoracle.h @@ -0,0 +1,57 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace Transport { + +class PresenceOracle { + public: + PresenceOracle(Swift::StanzaChannel* stanzaChannel); + ~PresenceOracle(); + + Swift::Presence::ref getLastPresence(const Swift::JID&) const; + Swift::Presence::ref getHighestPriorityPresence(const Swift::JID& bareJID) const; + std::vector getAllPresence(const Swift::JID& bareJID) const; + + public: + boost::signal onPresenceChange; + + private: + void handleIncomingPresence(Swift::Presence::ref presence); + void handleStanzaChannelAvailableChanged(bool); + + private: + typedef std::map PresenceMap; + typedef std::map PresencesMap; + PresencesMap entries_; + Swift::StanzaChannel* stanzaChannel_; +}; + +} + diff --git a/include/transport/transport.h b/include/transport/transport.h index 40442dcc..4a875754 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -27,7 +27,6 @@ #include "Swiften/Disco/EntityCapsManager.h" #include "Swiften/Disco/CapsManager.h" #include "Swiften/Disco/CapsMemoryStorage.h" -#include "Swiften/Presence/PresenceOracle.h" #include "Swiften/Network/BoostTimerFactory.h" #include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/Server/UserRegistry.h" @@ -37,6 +36,7 @@ #include #include "transport/config.h" #include "transport/factory.h" +#include "transport/presenceoracle.h" namespace Transport { // typedef enum { CLIENT_FEATURE_ROSTERX = 2, @@ -92,7 +92,7 @@ namespace Transport { /// You can use it to check current resource connected for particular user. /// \return Swift::PresenceOracle associated with this Transport::Component. - Swift::PresenceOracle *getPresenceOracle(); + PresenceOracle *getPresenceOracle(); /// Returns True if the component is in server mode. @@ -179,7 +179,7 @@ namespace Transport { Swift::EntityCapsManager *m_entityCapsManager; Swift::CapsManager *m_capsManager; Swift::CapsMemoryStorage *m_capsMemoryStorage; - Swift::PresenceOracle *m_presenceOracle; + PresenceOracle *m_presenceOracle; Swift::StanzaChannel *m_stanzaChannel; Swift::IQRouter *m_iqRouter; diff --git a/include/transport/user.h b/include/transport/user.h index de134634..4e98c4a8 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -22,7 +22,6 @@ #include #include "Swiften/Swiften.h" -#include "Swiften/Presence/PresenceOracle.h" #include "Swiften/Disco/EntityCapsManager.h" #include "Swiften/Disco/EntityCapsProvider.h" #include "storagebackend.h" @@ -35,6 +34,7 @@ class Component; class RosterManager; class ConversationManager; class UserManager; +class PresenceOracle; struct UserInfo; /// Represents online XMPP user. @@ -125,7 +125,7 @@ class User : public Swift::EntityCapsProvider { UserManager *m_userManager; ConversationManager *m_conversationManager; Swift::EntityCapsManager *m_entityCapsManager; - Swift::PresenceOracle *m_presenceOracle; + PresenceOracle *m_presenceOracle; UserInfo m_userInfo; void *m_data; bool m_connected; diff --git a/src/presenceoracle.cpp b/src/presenceoracle.cpp new file mode 100644 index 00000000..c6717f3b --- /dev/null +++ b/src/presenceoracle.cpp @@ -0,0 +1,134 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/presenceoracle.h" + +#include + +using namespace Swift; + +namespace Transport { + +PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel) { + stanzaChannel_ = stanzaChannel; + stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); +} + +PresenceOracle::~PresenceOracle() { + stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); + stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); +} + +void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) { + if (available) { + entries_.clear(); + } +} + + +void PresenceOracle::handleIncomingPresence(Presence::ref presence) { + // ignore presences for some contact, we're checking only presences for the transport itself here. + if (!presence->getTo().getNode().empty()) { + return; + } + + JID bareJID(presence->getFrom().toBare()); + if (presence->getType() == Presence::Subscribe) { + } + else { + Presence::ref passedPresence = presence; + if (presence->getType() == Presence::Unsubscribe) { + /* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */ + passedPresence = Presence::ref(new Presence()); + passedPresence->setType(Presence::Unavailable); + passedPresence->setFrom(bareJID); + passedPresence->setStatus(presence->getStatus()); + } + std::map > jidMap = entries_[bareJID]; + if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) { + /* Have a bare-JID only presence of offline */ + jidMap.clear(); + } else if (passedPresence->getType() == Presence::Available) { + /* Don't have a bare-JID only offline presence once there are available presences */ + jidMap.erase(bareJID); + } + if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) { + jidMap.erase(passedPresence->getFrom()); + } else { + jidMap[passedPresence->getFrom()] = passedPresence; + } + entries_[bareJID] = jidMap; + onPresenceChange(passedPresence); + } +} + +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 PresenceOracle::getAllPresence(const JID& bareJID) const { + std::vector 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); + } + return results; +} + +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; + if (!highest + || current->getPriority() > highest->getPriority() + || (current->getPriority() == highest->getPriority() + && StatusShow::typeToAvailabilityOrdering(current->getShow()) > StatusShow::typeToAvailabilityOrdering(highest->getShow()))) { + highest = current; + } + + } + return highest; +} + +} diff --git a/src/transport.cpp b/src/transport.cpp index ddcda381..f7e862d8 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -137,7 +137,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel); m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1)); - m_presenceOracle = new PresenceOracle(m_stanzaChannel); + m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel); m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1)); m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config); @@ -170,7 +170,7 @@ Swift::StanzaChannel *Component::getStanzaChannel() { return m_stanzaChannel; } -Swift::PresenceOracle *Component::getPresenceOracle() { +Transport::PresenceOracle *Component::getPresenceOracle() { return m_presenceOracle; } diff --git a/src/user.cpp b/src/user.cpp index 61740525..0467ee86 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -24,6 +24,7 @@ #include "transport/rostermanager.h" #include "transport/usermanager.h" #include "transport/conversationmanager.h" +#include "transport/presenceoracle.h" #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h"