void Component::handlePresence(Swift::Presence::ref presence) {
	bool isMUC = presence->getPayload<MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
	// filter out login/logout presence spam
	if (!presence->getTo().getNode().empty() && isMUC == false)
		return;

	// filter out bad presences
	if (!presence->getFrom().isValid()) {
		return;
	}

	if (presence->getType() == Presence::Error) {
		return;
	}

	// check if we have this client's capabilities and ask for them
	if (presence->getType() != Swift::Presence::Unavailable) {
		boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>();
		if (capsInfo && capsInfo->getHash() == "sha-1") {
			/*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
		}
#ifdef SUPPORT_LEGACY_CAPS
		else {
			GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter);
			discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
			discoInfoRequest->send();
		}
#endif
	}

	onUserPresenceReceived(presence);
}
Beispiel #2
0
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);
		}
	}
}
Beispiel #3
0
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 &currentPresence, 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 {