Changeset - 79d0e907bb27
[Not reviewed]
0 2 0
HanzZ - 14 years ago 2011-12-07 18:41:16
hanzz.k@gmail.com
Allow only 3 reconnections in a row, then disconnect user
2 files changed with 12 insertions and 6 deletions:
0 comments (0 inline, 0 general)
include/transport/user.h
Show inline comments
 
@@ -116,27 +116,28 @@ class User : public Swift::EntityCapsProvider {
 
		boost::signal<void (const std::string &room)> onRoomLeft;
 
		boost::signal<void ()> onDisconnected;
 

	
 
	private:
 
		void onConnectingTimeout();
 

	
 
		Swift::JID m_jid;
 
		Component *m_component;
 
		RosterManager *m_rosterManager;
 
		UserManager *m_userManager;
 
		ConversationManager *m_conversationManager;
 
		Swift::EntityCapsManager *m_entityCapsManager;
 
		Swift::PresenceOracle *m_presenceOracle;
 
		UserInfo m_userInfo;
 
		void *m_data;
 
		bool m_connected;
 
		bool m_readyForConnect;
 
		bool m_ignoreDisconnect;
 
		Swift::Timer::ref m_reconnectTimer;
 
		boost::shared_ptr<Swift::Connection> connection;
 
		time_t m_lastActivity;
 
		std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
 
		std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
 
		int m_resources;
 
		int m_reconnectCounter;
 
};
 

	
 
}
src/user.cpp
Show inline comments
 
@@ -35,48 +35,49 @@
 
#include <stdlib.h>
 

	
 
using namespace log4cxx;
 
using namespace boost;
 

	
 
#define foreach         BOOST_FOREACH
 

	
 
namespace Transport {
 

	
 
static LoggerPtr logger = Logger::getLogger("User");
 

	
 
User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
 
	m_jid = jid.toBare();
 
	m_data = NULL;
 

	
 
	m_component = component;
 
	m_presenceOracle = component->m_presenceOracle;
 
	m_entityCapsManager = component->m_entityCapsManager;
 
	m_userManager = userManager;
 
	m_userInfo = userInfo;
 
	m_connected = false;
 
	m_readyForConnect = false;
 
	m_ignoreDisconnect = false;
 
	m_resources = 0;
 
	m_reconnectCounter = 0;
 

	
 
	m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(10000);
 
	m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this)); 
 

	
 
	m_rosterManager = new RosterManager(this, m_component);
 
	m_conversationManager = new ConversationManager(this, m_component);
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Created");
 
	updateLastActivity();
 
}
 

	
 
User::~User(){
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Destroying");
 
	if (m_component->inServerMode()) {
 
		dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>());
 
	}
 

	
 
	m_reconnectTimer->stop();
 
	delete m_rosterManager;
 
	delete m_conversationManager;
 
}
 

	
 
const Swift::JID &User::getJID() {
 
	return m_jid;
 
}
 
@@ -149,48 +150,49 @@ void User::sendCurrentPresence() {
 
				response->setFrom(m_component->getJID());
 
				m_component->getStanzaChannel()->sendPresence(response);
 
			}
 
			else {
 
				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 {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
			response->setTo(presence->getFrom());
 
			response->setFrom(m_component->getJID());
 
			response->setType(Swift::Presence::Unavailable);
 
			response->setStatus("Connecting");
 
			m_component->getStanzaChannel()->sendPresence(response);
 
		}
 
	}
 
}
 

	
 
void User::setConnected(bool connected) {
 
	m_connected = connected;
 
	m_reconnectCounter = 0;
 
	setIgnoreDisconnect(false);
 
	updateLastActivity();
 

	
 
	sendCurrentPresence();
 
}
 

	
 
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;
 
@@ -302,54 +304,57 @@ void User::onConnectingTimeout() {
 
		return;
 
	m_reconnectTimer->stop();
 
	m_readyForConnect = true;
 
	onReadyToConnect();
 

	
 
	Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
 
	if (highest) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << highest->getType());
 
		onPresenceChanged(highest);
 
	}
 
}
 

	
 
void User::setIgnoreDisconnect(bool ignoreDisconnect) {
 
	m_ignoreDisconnect = ignoreDisconnect;
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Setting ignoreDisconnect=" << m_ignoreDisconnect);
 
}
 

	
 
void User::handleDisconnected(const std::string &error, Swift::SpectrumErrorPayload::Error e) {
 
	if (m_ignoreDisconnect) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network ignored (probably moving between backends)");
 
		return;
 
	}
 

	
 
	if (e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR || e == Swift::SpectrumErrorPayload::CONNECTION_ERROR_NETWORK_ERROR) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network, trying to reconnect automatically.");
 
		// Simulate destruction/resurrection :)
 
		// TODO: If this stops working, create onReconnect signal
 
		m_userManager->onUserDestroyed(this);
 
		m_userManager->onUserCreated(this);
 
		return;
 
		if (m_reconnectCounter < 3) {
 
			m_reconnectCounter++;
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnecting from legacy network for, trying to reconnect automatically.");
 
			// Simulate destruction/resurrection :)
 
			// TODO: If this stops working, create onReconnect signal
 
			m_userManager->onUserDestroyed(this);
 
			m_userManager->onUserCreated(this);
 
			return;
 
		}
 
	}
 

	
 
	if (error.empty()) {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network");
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, m_jid.toString() << ": Disconnected from legacy network with error " << error);
 
	}
 
	onDisconnected();
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(error);
 
	msg->setTo(m_jid.toBare());
 
	msg->setFrom(m_component->getJID());
 
	msg->addPayload(boost::make_shared<Swift::SpectrumErrorPayload>(e));
 
	m_component->getStanzaChannel()->sendMessage(msg);
 

	
 
	// In server mode, server finishes the session and pass unavailable session to userManager if we're connected to legacy network,
 
	// so we can't removeUser() in server mode, because it would be removed twice.
 
	// Once in finishSession and once in m_userManager->removeUser.
 
	if (m_component->inServerMode()) {
 
		// Remove user later just to be sure there won't be double-free.
 
		// We can't be sure finishSession sends unavailable presence everytime, so check if user gets removed
 
		// in finishSession(...) call and if not, remove it here.
0 comments (0 inline, 0 general)