From 24d25a6f406b3831df854232c955abfda89fb405 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 24 Aug 2011 08:31:32 +0200 Subject: [PATCH] Finally working disconnect/connect with multiple resources --- include/transport/transport.h | 2 +- include/transport/userregistry.h | 10 ++++++++- spectrum/src/main.cpp | 9 +++++--- src/transport.cpp | 5 ++--- src/usermanager.cpp | 34 +++++++++------------------- src/userregistry.cpp | 38 +++++++++++++++++++------------- 6 files changed, 52 insertions(+), 46 deletions(-) diff --git a/include/transport/transport.h b/include/transport/transport.h index 6728959a..4a321e5e 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -69,7 +69,7 @@ namespace Transport { /// - service.port /// - service.server_mode /// \param factory Transport Abstract factory used to create basic transport structures. - Component(Swift::EventLoop *loop, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL); + Component(Swift::EventLoop *loop, Swift::BoostNetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL); /// Component destructor. ~Component(); diff --git a/include/transport/userregistry.h b/include/transport/userregistry.h index 589a37e4..7465a3c5 100644 --- a/include/transport/userregistry.h +++ b/include/transport/userregistry.h @@ -60,7 +60,7 @@ class UserRegistry : public Swift::UserRegistry { /// \param cfg Config file /// - service.admin_username - username for admin account /// - service.admin_password - password for admin account - UserRegistry(Config *cfg); + UserRegistry(Config *cfg, Swift::NetworkFactories *factories); /// Destructor. virtual ~UserRegistry(); @@ -84,6 +84,10 @@ class UserRegistry : public Swift::UserRegistry { /// \param user JID. void onPasswordInvalid(const Swift::JID &user); + /// Removes session later. + /// \param user JID. + void removeLater(const Swift::JID &user); + /// Returns current password for particular user /// \param barejid JID. const std::string getUserPassword(const std::string &barejid); @@ -100,8 +104,12 @@ class UserRegistry : public Swift::UserRegistry { Swift::ServerFromClientSession *session; } Sess; + void handleRemoveTimeout(const Swift::JID &user); + mutable std::map users; mutable Config *config; + Swift::Timer::ref m_removeTimer; + bool m_inRemoveLater; }; } diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index a2ccf920..660820c7 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -74,10 +74,12 @@ int main(int argc, char **argv) return 1; } - UserRegistry userRegistry(&config); - Swift::SimpleEventLoop eventLoop; - Component transport(&eventLoop, &config, NULL, &userRegistry); + + Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop); + UserRegistry userRegistry(&config, factories); + + Component transport(&eventLoop, factories, &config, NULL, &userRegistry); // Logger logger(&transport); StorageBackend *storageBackend = NULL; @@ -118,4 +120,5 @@ int main(int argc, char **argv) delete userRegistration; } delete storageBackend; + delete factories; } diff --git a/src/transport.cpp b/src/transport.cpp index ea22fe92..e265dced 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -51,7 +51,7 @@ namespace Transport { static LoggerPtr logger = Logger::getLogger("Component"); static LoggerPtr logger_xml = Logger::getLogger("Component.XML"); -Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) { +Component::Component(Swift::EventLoop *loop, Swift::BoostNetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) { m_component = NULL; m_userRegistry = NULL; m_server = NULL; @@ -71,7 +71,7 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, T m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid")); - m_factories = new BoostNetworkFactories(loop); + m_factories = factories; m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000); m_reconnectTimer->onTick.connect(bind(&Component::start, this)); @@ -149,7 +149,6 @@ Component::~Component() { m_server->stop(); delete m_server; } - delete m_factories; } Swift::StanzaChannel *Component::getStanzaChannel() { diff --git a/src/usermanager.cpp b/src/usermanager.cpp index b47b962b..fd8a7088 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -212,28 +212,6 @@ void UserManager::handleRemoveTimeout(const std::string jid, User *u, bool recon } if (user) { - // Reconnect means that we're disconnecting this User instance from legacy network backend, - // but we're going to connect it again in this call. Currently it's used only when - // "service.more_resources==false". - if (reconnect) { - // Send message about reason - boost::shared_ptr msg(new Swift::Message()); - msg->setBody("You have signed on from another location."); - msg->setTo(user->getJID().toBare()); - msg->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendMessage(msg); - - // finishSession generates unavailable presence which ruins the second session which is waiting - // to be connected later in this function, so don't handle that unavailable presence by disconnecting - // the signal. TODO: < This can be fixed by ServerFromClientSession.cpp rewrite... - m_component->onUserPresenceReceived.disconnect(bind(&UserManager::handlePresence, this, _1)); - // Finish session - if (m_component->inServerMode()) { - dynamic_cast(m_component->getStanzaChannel())->finishSession(user->getJID().toBare(), boost::shared_ptr(new Swift::StreamError())); - } - // connect disconnected signal again - m_component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1)); - } removeUser(user); } @@ -328,7 +306,12 @@ void UserManager::connectUser(const Swift::JID &user) { return; } - if (m_users[user.toBare().toString()]->isConnected()) { + User *u = m_users[user.toBare().toString()]; + if (u->isConnected()) { + if (m_userRegistry->getUserPassword(user.toBare().toString()) != u->getUserInfo().password) { + m_userRegistry->removeLater(user); + return; + } if (CONFIG_BOOL(m_component->getConfig(), "service.more_resources")) { m_userRegistry->onPasswordValid(user); } @@ -344,6 +327,11 @@ void UserManager::connectUser(const Swift::JID &user) { m_component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1)); } } + else { + m_removeTimer->onTick.disconnect(boost::bind(&UserManager::handleRemoveTimeout, this, user.toBare().toString(), m_users[user.toBare().toString()], false)); + m_removeTimer->onTick.connect(boost::bind(&UserManager::handleRemoveTimeout, this, user.toBare().toString(), m_users[user.toBare().toString()], true)); + m_removeTimer->start(); + } // } // else { // // Reconnect the user if more resources per one legacy network account are not allowed diff --git a/src/userregistry.cpp b/src/userregistry.cpp index 684db560..a748cd2e 100644 --- a/src/userregistry.cpp +++ b/src/userregistry.cpp @@ -31,11 +31,13 @@ namespace Transport { static LoggerPtr logger = Logger::getLogger("UserRegistry"); -UserRegistry::UserRegistry(Config *cfg) { +UserRegistry::UserRegistry(Config *cfg, Swift::NetworkFactories *factories) { config = cfg; + m_removeTimer = factories->getTimerFactory()->createTimer(1); + m_inRemoveLater = false; } -UserRegistry::~UserRegistry() { } +UserRegistry::~UserRegistry() { m_removeTimer->stop(); } void UserRegistry::isValidUserPassword(const Swift::JID& user, Swift::ServerFromClientSession *session, const Swift::SafeByteArray& password) { if (!CONFIG_STRING(config, "service.admin_username").empty() && user.getNode() == CONFIG_STRING(config, "service.admin_username")) { @@ -52,18 +54,11 @@ void UserRegistry::isValidUserPassword(const Swift::JID& user, Swift::ServerFrom // Users try to connect twice if (users.find(key) != users.end()) { - // Kill the first session if the second password is same - if (Swift::safeByteArrayToString(password) == users[key].password) { - LOG4CXX_INFO(logger, key << ": Removing previous session and making this one active"); - Swift::ServerFromClientSession *tmp = users[key].session; - users[key].session = session; - tmp->handlePasswordInvalid(); - } - else { - LOG4CXX_INFO(logger, key << ": Possible break-in attemp (user logged as different one with bad password)"); - session->handlePasswordInvalid(); - return; - } + // Kill the first session + LOG4CXX_INFO(logger, key << ": Removing previous session and making this one active"); + Swift::ServerFromClientSession *tmp = users[key].session; + users[key].session = session; + tmp->handlePasswordInvalid(); } LOG4CXX_INFO(logger, key << ": Connecting this user to find if password is valid"); @@ -89,7 +84,9 @@ void UserRegistry::stopLogin(const Swift::JID& user, Swift::ServerFromClientSess else { LOG4CXX_WARN(logger, key << ": Stopping login process (user probably disconnected while logging in) for invalid user"); } - onDisconnectUser(user); + + if (!m_inRemoveLater) + onDisconnectUser(user); } void UserRegistry::onPasswordValid(const Swift::JID &user) { @@ -116,6 +113,17 @@ void UserRegistry::onPasswordInvalid(const Swift::JID &user) { } } +void UserRegistry::handleRemoveTimeout(const Swift::JID &user) { + m_inRemoveLater = true; + onPasswordInvalid(user); + m_inRemoveLater = false; +} + +void UserRegistry::removeLater(const Swift::JID &user) { + m_removeTimer->onTick.connect(boost::bind(&UserRegistry::handleRemoveTimeout, this, user)); + m_removeTimer->start(); +} + const std::string UserRegistry::getUserPassword(const std::string &barejid) { if (users.find(barejid) != users.end()) return users[barejid].password;