From 3aff761db6789faeab97d5153650df5698ed9ddf Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Fri, 2 Nov 2012 09:50:03 +0100 Subject: [PATCH] Do not send subscribe presence just because, but send it as response to probe presence --- include/transport/usermanager.h | 1 + src/tests/usermanager.cpp | 41 +++++++++++++++++++++++++++++++++ src/transport.cpp | 13 ++++++++--- src/usermanager.cpp | 38 ++++++++++++++++++++++++++++-- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/include/transport/usermanager.h b/include/transport/usermanager.h index 683d2f05..38a5c7bc 100644 --- a/include/transport/usermanager.h +++ b/include/transport/usermanager.h @@ -131,6 +131,7 @@ class UserManager : public Swift::EntityCapsProvider { void handleMessageReceived(Swift::Message::ref message); void handleGeneralPresenceReceived(Swift::Presence::ref presence); void handleProbePresence(Swift::Presence::ref presence); + void handleErrorPresence(Swift::Presence::ref presence); void handleSubscription(Swift::Presence::ref presence); void handleRemoveTimeout(const std::string jid, User *user, bool reconnect); void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info); diff --git a/src/tests/usermanager.cpp b/src/tests/usermanager.cpp index 5177d802..26ba476a 100644 --- a/src/tests/usermanager.cpp +++ b/src/tests/usermanager.cpp @@ -72,6 +72,11 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { } void handleProbePresence() { + UserInfo info; + info.id = 1; + info.jid = "user@localhost"; + storage->setUser(info); + Swift::Presence::ref response = Swift::Presence::create(); response->setTo("localhost"); response->setFrom("user@localhost/resource"); @@ -88,8 +93,44 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { presence = dynamic_cast(getStanza(received[2])); CPPUNIT_ASSERT(presence); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Probe, presence->getType()); + + received.clear(); + response = Swift::Presence::create(); + response->setTo("localhost"); + response->setFrom("user@localhost"); + response->setType(Swift::Presence::Unsubscribed); + dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); + presence = dynamic_cast(getStanza(received[1])); + CPPUNIT_ASSERT(presence); CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribe, presence->getType()); + received.clear(); + response = Swift::Presence::create(); + response->setTo("localhost"); + response->setFrom("user@localhost"); + response->setType(Swift::Presence::Error); + dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + presence = dynamic_cast(getStanza(received[0])); + CPPUNIT_ASSERT(presence); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribe, presence->getType()); + + storage->removeUser(1); + received.clear(); + response = Swift::Presence::create(); + response->setTo("localhost"); + response->setFrom("user@localhost"); + response->setType(Swift::Presence::Unsubscribed); + dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); } void connectTwoResources() { diff --git a/src/transport.cpp b/src/transport.cpp index 95ca0319..f4e0480b 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -281,9 +281,16 @@ void Component::handlePresence(Swift::Presence::ref presence) { return; } - if (presence->getType() == Presence::Error) { - return; - } + switch (presence->getType()) { + case Presence::Error: + case Presence::Subscribe: + case Presence::Subscribed: + case Presence::Unsubscribe: + case Presence::Unsubscribed: + return; + default: + break; + }; // check if we have this client's capabilities and ask for them if (presence->getType() != Swift::Presence::Unavailable) { diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 64e1d1c3..32795e6c 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -195,13 +195,13 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { response->setType(Swift::Presence::Unavailable); m_component->getStanzaChannel()->sendPresence(response); - // bother him with subscribe presence, just to be + // bother him with probe presence, just to be // sure he is subscribed to us. if (/*registered && */presence->getType() == Swift::Presence::Probe) { Swift::Presence::ref response = Swift::Presence::create(); response->setTo(presence->getFrom()); response->setFrom(presence->getTo()); - response->setType(Swift::Presence::Subscribe); + response->setType(Swift::Presence::Probe); m_component->getStanzaChannel()->sendPresence(response); } @@ -382,6 +382,9 @@ void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) { case Swift::Presence::Probe: handleProbePresence(presence); break; + case Swift::Presence::Error: + handleErrorPresence(presence); + break; default: break; }; @@ -407,7 +410,25 @@ void UserManager::handleProbePresence(Swift::Presence::ref presence) { } } +void UserManager::handleErrorPresence(Swift::Presence::ref presence) { + // Don't let RosterManager to handle presences for us + if (!presence->getTo().getNode().empty()) { + return; + } + std::string userkey = presence->getFrom().toBare().toString(); + UserInfo res; + bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false; + if (registered) { + Swift::Presence::ref response = Swift::Presence::create(); + response->setFrom(presence->getTo().toBare()); + response->setTo(presence->getFrom().toBare()); + response->setType(Swift::Presence::Subscribe); + m_component->getStanzaChannel()->sendPresence(response); + } +} + void UserManager::handleSubscription(Swift::Presence::ref presence) { + // answer to subscibe for transport itself if (presence->getType() == Swift::Presence::Subscribe && presence->getTo().getNode().empty()) { Swift::Presence::ref response = Swift::Presence::create(); @@ -423,6 +444,19 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) { // m_component->getStanzaChannel()->sendPresence(response); return; } + else if (presence->getType() == Swift::Presence::Unsubscribed && presence->getTo().getNode().empty()) { + std::string userkey = presence->getFrom().toBare().toString(); + UserInfo res; + bool registered = m_storageBackend ? m_storageBackend->getUser(userkey, res) : false; + if (registered) { + Swift::Presence::ref response = Swift::Presence::create(); + response->setFrom(presence->getTo().toBare()); + response->setTo(presence->getFrom().toBare()); + response->setType(Swift::Presence::Subscribe); + m_component->getStanzaChannel()->sendPresence(response); + } + return; + } // Don't let RosterManager to handle presences for us if (presence->getTo().getNode().empty()) {