diff --git a/include/transport/config.h b/include/transport/config.h index 3cf03973..70660c3f 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -69,6 +69,8 @@ class Config { /// \param configfile path to config file bool load(const std::string &configfile); + bool reload(); + /// Returns value of variable defined by key. /// For variables in sections you can use "section.variable" key format. diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 6dc942cd..f5cbd9b0 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -42,7 +42,7 @@ class RosterResponder; class NetworkPluginServer { public: - struct Client { + struct Backend { bool pongReceived; std::list users; Swift::SafeByteArray data; @@ -57,12 +57,16 @@ class NetworkPluginServer { return m_clients.size(); } + const std::list &getBackends() { + return m_clients; + } + void handleMessageReceived(NetworkConversation *conv, boost::shared_ptr &message); private: void handleNewClientConnection(boost::shared_ptr c); - void handleSessionFinished(Client *c); - void handleDataRead(Client *c, const Swift::SafeByteArray&); + void handleSessionFinished(Backend *c); + void handleDataRead(Backend *c, const Swift::SafeByteArray&); void handleConnectedPayload(const std::string &payload); void handleDisconnectedPayload(const std::string &payload); @@ -92,15 +96,15 @@ class NetworkPluginServer { void send(boost::shared_ptr &, const std::string &data); void pingTimeout(); - void sendPing(Client *c); - Client *getFreeClient(); + void sendPing(Backend *c); + Backend *getFreeClient(); UserManager *m_userManager; VCardResponder *m_vcardResponder; RosterResponder *m_rosterResponder; Config *m_config; boost::shared_ptr m_server; - std::list m_clients; + std::list m_clients; Swift::Timer::ref m_pingTimer; Component *m_component; }; diff --git a/include/transport/usermanager.h b/include/transport/usermanager.h index a4f84845..33f176c8 100644 --- a/include/transport/usermanager.h +++ b/include/transport/usermanager.h @@ -52,6 +52,10 @@ class UserManager { /// \return User class associated with this user User *getUser(const std::string &barejid); + const std::map &getUsers() { + return m_users; + } + /// Returns number of online users. /// \return number of online users int getUserCount(); diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 05463fdd..eb786e10 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -56,13 +56,13 @@ int main(int argc, char **argv) Swift::SimpleEventLoop eventLoop; Component transport(&eventLoop, &config, NULL, &userRegistry); - Logger logger(&transport); +// Logger logger(&transport); StorageBackend *storageBackend = NULL; if (CONFIG_STRING(&config, "database.type") == "sqlite3") { storageBackend = new SQLite3Backend(&config); - logger.setStorageBackend(storageBackend); +// logger.setStorageBackend(storageBackend); if (!storageBackend->connect()) { std::cerr << "Can't connect to database.\n"; } @@ -70,10 +70,11 @@ int main(int argc, char **argv) UserManager userManager(&transport, &userRegistry, storageBackend); if (storageBackend) { - UserRegistration userRegistration(&transport, &userManager, storageBackend); - logger.setUserRegistration(&userRegistration); + UserRegistration *userRegistration = new UserRegistration(&transport, &userManager, storageBackend); + userRegistration->start(); +// logger.setUserRegistration(&userRegistration); } - logger.setUserManager(&userManager); +// logger.setUserManager(&userManager); NetworkPluginServer plugin(&transport, &config, &userManager); diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index 48929919..31204ea1 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -29,7 +29,9 @@ static void handleConnected(Swift::Client *client) { } static void handleMessageReceived(Swift::Client *client, Swift::Message::ref message) { - std::cout << "[ OK ] " << client->getJID().getDomain() << ": " << message->getBody() << "\n"; + std::string body = message->getBody(); + boost::replace_all(body, "\n", "\n[ OK ] " + client->getJID().getDomain() + ": "); + std::cout << "[ OK ] " << client->getJID().getDomain() << ": " << body << "\n"; if (--finished == 0) { exit(0); } diff --git a/spectrum_manager/src/spectrum_manager.cfg b/spectrum_manager/src/spectrum_manager.cfg index c24383f5..4b9ec622 100644 --- a/spectrum_manager/src/spectrum_manager.cfg +++ b/spectrum_manager/src/spectrum_manager.cfg @@ -1,7 +1,8 @@ [service] -admin_username=admin -admin_password=test +admin_username=admin_ +admin_password=test_ [servers] -server=localhost -server=icq.spectrum.im \ No newline at end of file +#server=localhost +server=icq.spectrum.im +server=msn.spectrum.im \ No newline at end of file diff --git a/src/admininterface.cpp b/src/admininterface.cpp index 0302aa60..1185151f 100644 --- a/src/admininterface.cpp +++ b/src/admininterface.cpp @@ -35,6 +35,14 @@ namespace Transport { static LoggerPtr logger = Logger::getLogger("AdminInterface"); +static std::string getArg(const std::string &body) { + std::string ret; + if (body.find(" ") == std::string::npos) + return ret; + + return body.substr(body.find(" ") + 1); +} + AdminInterface::AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) { m_component = component; m_storageBackend = storageBackend; @@ -65,8 +73,75 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { int backends = m_server->getBackendCount() - 1; message->setBody("Running (" + boost::lexical_cast(users) + " users connected using " + boost::lexical_cast(backends) + " backends)"); } + else if (message->getBody() == "online_users") { + std::string lst; + const std::map &users = m_userManager->getUsers(); + if (users.size() == 0) + lst = "0"; + + for (std::map::const_iterator it = users.begin(); it != users.end(); it ++) { + lst += (*it).first + "\n"; + } + + message->setBody(lst); + } + else if (message->getBody() == "online_users_count") { + int users = m_userManager->getUserCount(); + message->setBody(boost::lexical_cast(users)); + } + else if (message->getBody() == "reload") { + bool done = m_component->getConfig()->reload(); + if (done) { + message->setBody("Config reloaded"); + } + else { + message->setBody("Error during config reload"); + } + } + else if (message->getBody() == "online_users_per_backend") { + std::string lst; + int id = 1; + + const std::list &backends = m_server->getBackends(); + for (std::list ::const_iterator b = backends.begin(); b != backends.end(); b++) { + NetworkPluginServer::Backend *backend = *b; + lst += "Backend " + boost::lexical_cast(id) + ":\n"; + if (backend->users.size() == 0) { + lst += " waiting for users\n"; + } + else { + for (std::list::const_iterator u = backend->users.begin(); u != backend->users.end(); u++) { + User *user = *u; + lst += " " + user->getJID().toBare().toString() + "\n"; + } + } + id++; + } + + message->setBody(lst); + } + else if (message->getBody().find("has_online_user") == 0) { + User *user = m_userManager->getUser(getArg(message->getBody())); + std::cout << getArg(message->getBody()) << "\n"; + message->setBody(boost::lexical_cast(user != NULL)); + } + else if (message->getBody() == "backends_count") { + int backends = m_server->getBackendCount() - 1; + message->setBody(boost::lexical_cast(backends)); + } + else if (message->getBody().find("help") == 0) { + std::string help; + help += "status - shows instance status\n"; + help += "online_users - returns list of all online users\n"; + help += "online_users_count - number of online users\n"; + help += "online_users_per_backend - shows online users per backends\n"; + help += "has_online_user - returns 1 if user is online\n"; + help += "backends_count - number of active backends\n"; + help += "reload - Reloads config file\n"; + message->setBody(help); + } else { - message->setBody("Unknown command"); + message->setBody("Unknown command. Try \"help\""); } m_component->getStanzaChannel()->sendMessage(message); diff --git a/src/config.cpp b/src/config.cpp index 737ca7e2..efa040ec 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -46,6 +46,9 @@ bool Config::load(const std::string &configfile, boost::program_options::options ("service.cert_password", value()->default_value(""), "PKCS#12 Certificate password.") ("service.admin_username", value()->default_value(""), "Administrator username.") ("service.admin_password", value()->default_value(""), "Administrator password.") + ("identity.name", value()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.") + ("identity.category", value()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.") + ("identity.type", value()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)") ("registration.enable_public_registration", value()->default_value(true), "True if users should be able to register.") ("registration.language", value()->default_value("en"), "Default language for registration form") ("registration.instructions", value()->default_value(""), "Instructions showed to user in registration form") @@ -74,4 +77,12 @@ bool Config::load(const std::string &configfile) { return load(configfile, opts); } +bool Config::reload() { + if (m_file.empty()) { + return false; + } + + return load(m_file); +} + } diff --git a/src/discoinforesponder.cpp b/src/discoinforesponder.cpp index 891ef958..0e694feb 100644 --- a/src/discoinforesponder.cpp +++ b/src/discoinforesponder.cpp @@ -26,16 +26,20 @@ #include "Swiften/Queries/IQRouter.h" #include "Swiften/Elements/DiscoInfo.h" #include "Swiften/Swiften.h" +#include "transport/config.h" using namespace Swift; using namespace boost; namespace Transport { -DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router) : Swift::GetResponder(router) { - m_transportInfo.addIdentity(DiscoInfo::Identity("libtransport", "gateway", "identity")); +DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder(router) { + m_config = config; + m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), + CONFIG_STRING(m_config, "identity.category"), + CONFIG_STRING(m_config, "identity.type"))); - m_buddyInfo.addIdentity(DiscoInfo::Identity("libtransport", "client", "pc")); + m_buddyInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), "client", "pc")); std::list features; features.push_back("jabber:iq:register"); features.push_back("jabber:iq:gateway"); diff --git a/src/discoinforesponder.h b/src/discoinforesponder.h index f609e666..b6cf9e84 100644 --- a/src/discoinforesponder.h +++ b/src/discoinforesponder.h @@ -28,9 +28,11 @@ namespace Transport { +class Config; + class DiscoInfoResponder : public Swift::GetResponder { public: - DiscoInfoResponder(Swift::IQRouter *router); + DiscoInfoResponder(Swift::IQRouter *router, Config *config); ~DiscoInfoResponder(); void setTransportFeatures(std::list &features); @@ -43,6 +45,7 @@ class DiscoInfoResponder : public Swift::GetResponder { Swift::DiscoInfo m_transportInfo; Swift::DiscoInfo m_buddyInfo; + Config *m_config; }; } \ No newline at end of file diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 94d3c3cd..978cb607 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -173,7 +173,7 @@ NetworkPluginServer::~NetworkPluginServer() { } void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr c) { - Client *client = new Client; + Backend *client = new Backend; client->pongReceived = true; client->connection = c; @@ -191,7 +191,7 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptrgetJID().toString()); @@ -203,7 +203,7 @@ void NetworkPluginServer::handleSessionFinished(Client *c) { delete c; // Execute new session only if there's no free one after this crash/disconnection - for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { + for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { if ((*it)->users.size() < CONFIG_INT(m_config, "service.users_per_backend")) { return; } @@ -429,7 +429,7 @@ void NetworkPluginServer::handleAttentionPayload(const std::string &data) { conv->handleMessage(msg); } -void NetworkPluginServer::handleDataRead(Client *c, const Swift::SafeByteArray &data) { +void NetworkPluginServer::handleDataRead(Backend *c, const Swift::SafeByteArray &data) { c->data.insert(c->data.end(), data.begin(), data.end()); while (c->data.size() != 0) { unsigned int expected_size; @@ -509,7 +509,7 @@ void NetworkPluginServer::send(boost::shared_ptr &c, const st void NetworkPluginServer::pingTimeout() { // check ping responses - for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { + for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { if ((*it)->pongReceived) { sendPing((*it)); } @@ -521,10 +521,10 @@ void NetworkPluginServer::pingTimeout() { } void NetworkPluginServer::handleUserCreated(User *user) { - Client *c = getFreeClient(); + Backend *c = getFreeClient(); if (!c) { LOG4CXX_ERROR(logger, "There is no backend to handle user " << user->getJID().toString()); - user->handleDisconnected("Internal Server Error, please reconnect."); + user->handleDisconnected("Internal Server Error (no free backend to handle your session), please reconnect."); return; } user->setData(c); @@ -550,7 +550,7 @@ void NetworkPluginServer::handleUserReadyToConnect(User *user) { WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGIN); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); } @@ -570,7 +570,7 @@ void NetworkPluginServer::handleUserPresenceChanged(User *user, Swift::Presence: WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); } @@ -588,7 +588,7 @@ void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, con WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true); @@ -610,7 +610,7 @@ void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) { WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LEAVE_ROOM); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(r); @@ -635,7 +635,7 @@ void NetworkPluginServer::handleUserDestroyed(User *user) { WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGOUT); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); if (!c) { return; } @@ -677,7 +677,7 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost WRAP(message, type); - Client *c = (Client *) conv->getConversationManager()->getUser()->getData(); + Backend *c = (Backend *) conv->getConversationManager()->getUser()->getData(); send(c->connection, message); } } @@ -694,7 +694,7 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ATTENTION); - Client *c = (Client *) conv->getConversationManager()->getUser()->getData(); + Backend *c = (Backend *) conv->getConversationManager()->getUser()->getData(); send(c->connection, message); return; } @@ -719,7 +719,7 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE); - Client *c = (Client *) conv->getConversationManager()->getUser()->getData(); + Backend *c = (Backend *) conv->getConversationManager()->getUser()->getData(); send(c->connection, message); } } @@ -739,7 +739,7 @@ void NetworkPluginServer::handleBuddyRemoved(Buddy *b) { WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); } @@ -762,7 +762,7 @@ void NetworkPluginServer::handleBuddyUpdated(Buddy *b, const Swift::RosterItemPa WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); } @@ -782,7 +782,7 @@ void NetworkPluginServer::handleVCardUpdated(User *user, boost::shared_ptrgetData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); } @@ -797,11 +797,11 @@ void NetworkPluginServer::handleVCardRequired(User *user, const std::string &nam WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_VCARD); - Client *c = (Client *) user->getData(); + Backend *c = (Backend *) user->getData(); send(c->connection, message); } -void NetworkPluginServer::sendPing(Client *c) { +void NetworkPluginServer::sendPing(Backend *c) { std::string message; pbnetwork::WrapperMessage wrap; @@ -813,14 +813,17 @@ void NetworkPluginServer::sendPing(Client *c) { LOG4CXX_INFO(logger, "PING to " << c); } -NetworkPluginServer::Client *NetworkPluginServer::getFreeClient() { - NetworkPluginServer::Client *c = NULL; +NetworkPluginServer::Backend *NetworkPluginServer::getFreeClient() { + NetworkPluginServer::Backend *c = NULL; bool spawnNew = false; - for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { + for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { + // This backend is free. if ((*it)->users.size() < CONFIG_INT(m_config, "service.users_per_backend")) { - if ((*it)->users.size() + 1 == CONFIG_INT(m_config, "service.users_per_backend")) { + // After this user, this backend could be full, so we have to spawn new one... + if ((*it)->users.size() + 1 >= CONFIG_INT(m_config, "service.users_per_backend")) { spawnNew = true; } + if (c == NULL) { c = *it; } diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 50550383..369a4a00 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -59,6 +59,9 @@ RosterManager::~RosterManager() { for (std::map::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { Buddy *buddy = (*it).second; + if (!buddy) { + continue; + } delete buddy; } if (m_rosterStorage) @@ -141,7 +144,10 @@ Buddy *RosterManager::getBuddy(const std::string &name) { void RosterManager::sendRIE() { m_RIETimer->stop(); - LOG4CXX_INFO(logger, "Sending RIE stanza to " << m_user->getJID().toString()); + Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(m_user->getJID().toBare()); + + LOG4CXX_INFO(logger, "Sending RIE stanza to " << highest->getFrom().toString()); + Swift::RosterItemExchangePayload::ref payload = Swift::RosterItemExchangePayload::ref(new Swift::RosterItemExchangePayload()); for (std::map::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { Buddy *buddy = (*it).second; @@ -154,7 +160,7 @@ void RosterManager::sendRIE() { payload->addItem(item); } - boost::shared_ptr > request(new Swift::GenericRequest(Swift::IQ::Set, m_user->getJID(), payload, m_component->getIQRouter())); + boost::shared_ptr > request(new Swift::GenericRequest(Swift::IQ::Set, highest->getFrom(), payload, m_component->getIQRouter())); request->send(); } @@ -211,6 +217,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { } else { Swift::Presence::ref response = Swift::Presence::create(); + Swift::Presence::ref presence; response->setTo(presence->getFrom()); response->setFrom(presence->getTo()); @@ -220,6 +227,11 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { // buddy is already there, so nothing to do, just answer case Swift::Presence::Subscribe: response->setType(Swift::Presence::Subscribed); + presence = buddy->generatePresenceStanza(255); + if (presence) { + presence->setTo(presence->getFrom()); + m_component->getStanzaChannel()->sendPresence(presence); + } break; // remove buddy case Swift::Presence::Unsubscribe: @@ -228,11 +240,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { break; // just send response case Swift::Presence::Unsubscribed: - response->setType(Swift::Presence::Unsubscribe); - break; - // just send response - case Swift::Presence::Subscribed: - response->setType(Swift::Presence::Subscribe); +// response->setType(Swift::Presence::Unsubscribe); break; default: return; @@ -263,9 +271,6 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { response->setType(Swift::Presence::Unsubscribe); break; // just send response - case Swift::Presence::Subscribed: - response->setType(Swift::Presence::Subscribe); - break; default: return; } @@ -312,6 +317,9 @@ Swift::RosterPayload::ref RosterManager::generateRosterPayload() { for (std::map::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { Buddy *buddy = (*it).second; + if (!buddy) { + continue; + } Swift::RosterItemPayload item; item.setJID(buddy->getJID().toBare()); item.setName(buddy->getAlias()); @@ -325,6 +333,9 @@ Swift::RosterPayload::ref RosterManager::generateRosterPayload() { void RosterManager::sendCurrentPresences(const Swift::JID &to) { for (std::map::const_iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { Buddy *buddy = (*it).second; + if (!buddy) { + continue; + } Swift::Presence::ref presence = buddy->generatePresenceStanza(255); if (presence) { presence->setTo(to); diff --git a/src/sqlite3backend.cpp b/src/sqlite3backend.cpp index d75b52d6..3ec5694c 100644 --- a/src/sqlite3backend.cpp +++ b/src/sqlite3backend.cpp @@ -272,7 +272,7 @@ long SQLite3Backend::addBuddy(long userId, const BuddyInfo &buddyInfo) { void SQLite3Backend::updateBuddy(long userId, const BuddyInfo &buddyInfo) { // UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=? BEGIN(m_updateBuddy); - BIND_STR(m_updateBuddy, buddyInfo.groups[0]); // TODO: serialize groups + BIND_STR(m_updateBuddy, buddyInfo.groups.size() == 0 ? "" : buddyInfo.groups[0]); // TODO: serialize groups BIND_STR(m_updateBuddy, buddyInfo.alias); BIND_INT(m_updateBuddy, buddyInfo.flags); BIND_STR(m_updateBuddy, buddyInfo.subscription); diff --git a/src/transport.cpp b/src/transport.cpp index 6385adb8..3fc63aec 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -69,7 +69,7 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, T m_factories = new BoostNetworkFactories(loop); - m_reconnectTimer = m_factories->getTimerFactory()->createTimer(1000); + m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000); m_reconnectTimer->onTick.connect(bind(&Component::start, this)); if (CONFIG_BOOL(m_config, "service.server_mode")) { @@ -98,6 +98,7 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, T m_server->onDataWritten.connect(bind(&Component::handleDataWritten, this, _1)); } else { + LOG4CXX_INFO(logger, "Creating component in gateway mode"); m_component = new Swift::Component(loop, m_factories, m_jid, CONFIG_STRING(m_config, "service.password")); m_component->setSoftwareVersion("", ""); m_component->onConnected.connect(bind(&Component::handleConnected, this)); @@ -116,7 +117,7 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, T m_presenceOracle = new PresenceOracle(m_stanzaChannel); m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1)); - m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter); + m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config); m_discoInfoResponder->start(); m_discoItemsResponder = new DiscoItemsResponder(m_iqRouter); @@ -159,6 +160,7 @@ void Component::setBuddyFeatures(std::list &features) { void Component::start() { if (m_component) { + LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port")); m_reconnectCount++; m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port")); m_reconnectTimer->stop(); @@ -190,6 +192,17 @@ void Component::handleConnectionError(const ComponentError &error) { onConnectionError(error); // if (m_reconnectCount == 2) // Component::instance()->userManager()->removeAllUsers(); + std::string str = "Unknown error"; + switch (error.getType()) { + case ComponentError::UnknownError: str = "Unknown error"; break; + case ComponentError::ConnectionError: str = "Connection error"; break; + case ComponentError::ConnectionReadError: str = "Connection read error"; break; + case ComponentError::ConnectionWriteError: str = "Connection write error"; break; + case ComponentError::XMLError: str = "XML Error"; break; + case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break; + case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break; + } + LOG4CXX_INFO(logger, "Disconnected from XMPP server. Error: " << str); m_reconnectTimer->start(); } diff --git a/src/user.cpp b/src/user.cpp index 2ca77538..5452ddc4 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -115,11 +115,12 @@ void User::handlePresence(Swift::Presence::ref presence) { Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); if (highest) { - highest->setTo(presence->getFrom().toBare()); - highest->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendPresence(highest); - LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << highest->getType()); - onPresenceChanged(highest); + Swift::Presence::ref response = Swift::Presence::create(highest); + response->setTo(presence->getFrom().toBare()); + response->setFrom(m_component->getJID()); + m_component->getStanzaChannel()->sendPresence(response); + LOG4CXX_INFO(logger, m_jid.toString() << ": Changing legacy network presence to " << response->getType()); + onPresenceChanged(response); } else { Swift::Presence::ref response = Swift::Presence::create(); @@ -158,11 +159,15 @@ void User::handleDisconnected(const std::string &error) { msg->setFrom(m_component->getJID()); m_component->getStanzaChannel()->sendMessage(msg); + // In server mode, server finishes the session and pass unavailable session to userManager, + // 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()) { dynamic_cast(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr(new Swift::StreamError())); } - - m_userManager->removeUser(this); + else { + m_userManager->removeUser(this); + } } } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index d8c8e695..8e16c029 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -98,6 +98,10 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { User *user = getUser(userkey); if (!user) { + if (CONFIG_STRING(m_component->getConfig(), "service.admin_username") == presence->getFrom().getNode()) { + return; + } + // No user and unavailable presence -> answer with unavailable if (presence->getType() == Swift::Presence::Unavailable) { Swift::Presence::ref response = Swift::Presence::create(); @@ -225,11 +229,11 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) { response->setType(Swift::Presence::Subscribed); m_component->getStanzaChannel()->sendPresence(response); - response = Swift::Presence::create(); - response->setFrom(presence->getTo()); - response->setTo(presence->getFrom()); - response->setType(Swift::Presence::Subscribe); - m_component->getStanzaChannel()->sendPresence(response); +// response = Swift::Presence::create(); +// response->setFrom(presence->getTo()); +// response->setTo(presence->getFrom()); +// response->setType(Swift::Presence::Subscribe); +// m_component->getStanzaChannel()->sendPresence(response); return; } diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 8dd6a9c7..b03b3e4e 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -25,11 +25,15 @@ #include "transport/user.h" #include "Swiften/Elements/ErrorPayload.h" #include +#include "log4cxx/logger.h" using namespace Swift; +using namespace log4cxx; namespace Transport { +static LoggerPtr logger = Logger::getLogger("UserRegistration"); + UserRegistration::UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder(component->m_iqRouter) { m_component = component; m_config = m_component->m_config;