void subscribeNewBuddy() { User *user = userManager->getUser("user@localhost"); Swift::Presence::ref response = Swift::Presence::create(); response->setTo("buddy1@localhost"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Subscribe); injectPresence(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload<Swift::RosterPayload>(); CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size()); Swift::RosterItemPayload item = payload1->getItems()[0]; CPPUNIT_ASSERT_EQUAL(std::string("buddy1"), Buddy::JIDToLegacyName(item.getJID(), user)); CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[1]))); CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribed, dynamic_cast<Swift::Presence *>(getStanza(received[1]))->getType()); CPPUNIT_ASSERT_EQUAL(std::string("buddy1"), m_buddy); }
void User::handlePresence(Swift::Presence::ref presence) { int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size(); m_conversationManager->resetResources(); if (!m_connected) { // we are not connected to legacy network, so we should do it when disco#info arrive :) if (m_readyForConnect == false) { // Forward status message to legacy network, but only if it's sent from active resource // if (m_activeResource == presence->getFrom().getResource().getUTF8String()) { // forwardStatus(presenceShow, stanzaStatus); // } boost::shared_ptr<Swift::CapsInfo> capsInfo = presence->getPayload<Swift::CapsInfo>(); if (capsInfo && capsInfo->getHash() == "sha-1") { if (m_entityCapsManager->getCaps(presence->getFrom()) != Swift::DiscoInfo::ref()) { LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network"); m_readyForConnect = true; onReadyToConnect(); } else { m_reconnectTimer->start(); } } else if (m_component->inServerMode()) { LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network"); m_readyForConnect = true; onReadyToConnect(); } else { m_reconnectTimer->start(); } } } bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#'; if (isMUC) { if (presence->getType() == Swift::Presence::Unavailable) { std::string room = Buddy::JIDToLegacyName(presence->getTo()); LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room); onRoomLeft(room); Conversation *conv = m_conversationManager->getConversation(room); if (conv) { m_conversationManager->removeConversation(conv); delete conv; } } else { // force connection to legacy network to let backend to handle auto-join on connect. if (!m_readyForConnect) { LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network"); m_readyForConnect = true; onReadyToConnect(); } std::string room = Buddy::JIDToLegacyName(presence->getTo()); if (m_conversationManager->getConversation(room) != NULL) { LOG4CXX_INFO(logger, m_jid.toString() << ": User has already tried to join room " << room << " as " << presence->getTo().getResource()); return; } LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << room << " as " << presence->getTo().getResource()); std::string password = ""; if (presence->getPayload<Swift::MUCPayload>() != NULL) { password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : ""; } onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password); } return; } // User wants to disconnect this resource if (!m_component->inServerMode()) { if (presence->getType() == Swift::Presence::Unavailable) { // Send unavailable presences for online contacts m_rosterManager->sendUnavailablePresences(presence->getFrom()); // Send unavailable presence for transport contact itself Swift::Presence::ref response = Swift::Presence::create(); response->setTo(presence->getFrom()); response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); m_component->getStanzaChannel()->sendPresence(response); } else { sendCurrentPresence(); // This resource is new, so we have to send buddies presences if (currentResourcesCount != m_resources) { m_rosterManager->sendCurrentPresences(presence->getFrom()); } } } m_resources = currentResourcesCount; // Change legacy network presence if (m_readyForConnect) { Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); if (highest) { Swift::Presence::ref response = Swift::Presence::create(highest); response->setTo(m_jid); response->setFrom(m_component->getJID()); LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType()); onPresenceChanged(highest); } else { Swift::Presence::ref response = Swift::Presence::create(); response->setTo(m_jid.toBare()); response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); onPresenceChanged(response); } } }
void RosterManager::handleSubscription(Swift::Presence::ref presence) { std::string legacyName = Buddy::JIDToLegacyName(presence->getTo(), m_user); if (legacyName.empty()) { return; } // For server mode the subscription changes are handler in rosterresponder.cpp // using roster pushes. if (m_component->inServerMode()) { Swift::Presence::ref response = Swift::Presence::create(); response->setTo(presence->getFrom().toBare()); response->setFrom(presence->getTo().toBare()); Buddy *buddy = getBuddy(legacyName); if (buddy) { LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Subscription received and buddy " << legacyName << " is already there => answering"); switch (presence->getType()) { case Swift::Presence::Subscribe: onBuddyAdded(buddy); response->setType(Swift::Presence::Subscribed); break; case Swift::Presence::Unsubscribe: onBuddyRemoved(buddy); removeBuddy(buddy->getName()); buddy = NULL; response->setType(Swift::Presence::Unsubscribed); break; case Swift::Presence::Subscribed: onBuddyAdded(buddy); break; default: return; } m_component->getFrontend()->sendPresence(response); } else { BuddyInfo buddyInfo; switch (presence->getType()) { // buddy is not in roster, so add him case Swift::Presence::Subscribe: buddyInfo.id = -1; buddyInfo.alias = ""; buddyInfo.legacyName = legacyName; buddyInfo.subscription = "both"; buddyInfo.flags = Buddy::buddyFlagsFromJID(presence->getTo()); LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Subscription received for new buddy " << buddyInfo.legacyName << " => adding to legacy network"); buddy = m_component->getFactory()->createBuddy(this, buddyInfo); setBuddy(buddy); onBuddyAdded(buddy); response->setType(Swift::Presence::Subscribed); break; case Swift::Presence::Subscribed: // onBuddyAdded(buddy); return; // buddy is not there, so nothing to do, just answer case Swift::Presence::Unsubscribe: buddyInfo.id = -1; buddyInfo.alias = ""; buddyInfo.legacyName = legacyName; buddyInfo.subscription = "both"; buddyInfo.flags = Buddy::buddyFlagsFromJID(presence->getTo()); buddy = m_component->getFactory()->createBuddy(this, buddyInfo); onBuddyRemoved(buddy); delete buddy; response->setType(Swift::Presence::Unsubscribed); break; default: return; } m_component->getFrontend()->sendPresence(response); } } else { Swift::Presence::ref response = Swift::Presence::create(); Swift::Presence::ref currentPresence; response->setTo(presence->getFrom().toBare()); response->setFrom(presence->getTo().toBare()); Buddy *buddy = getBuddy(legacyName); if (buddy) { std::vector<Swift::Presence::ref> &presences = buddy->generatePresenceStanzas(255); switch (presence->getType()) { // buddy is already there, so nothing to do, just answer case Swift::Presence::Subscribe: onBuddyAdded(buddy); response->setType(Swift::Presence::Subscribed); BOOST_FOREACH(Swift::Presence::ref ¤tPresence, presences) { currentPresence->setTo(presence->getFrom()); m_component->getFrontend()->sendPresence(currentPresence); } if (buddy->getSubscription() != Buddy::Both) { buddy->setSubscription(Buddy::Both); storeBuddy(buddy); } break; // remove buddy case Swift::Presence::Unsubscribe: response->setType(Swift::Presence::Unsubscribed); onBuddyRemoved(buddy); removeBuddy(buddy->getName()); buddy = NULL; break; // just send response case Swift::Presence::Unsubscribed: response->setType(Swift::Presence::Unsubscribe); // We set both here, because this Unsubscribed can be response to // subscribe presence and we don't want that unsubscribe presence // to be send later again if (buddy->getSubscription() != Buddy::Both) { buddy->setSubscription(Buddy::Both); storeBuddy(buddy); } break; case Swift::Presence::Subscribed: if (buddy->getSubscription() != Buddy::Both) { buddy->setSubscription(Buddy::Both); storeBuddy(buddy); } return; default: return; } } else {