diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 1f77af16ca9074ab946a9c56e49c986aad7461bd..8a514b0ac44066a31465e5753d532483c5a53dd6 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -32,6 +32,7 @@ #include "transport/rosterresponder.h" #include "transport/memoryreadbytestream.h" #include "transport/logging.h" +#include "transport/admininterface.h" #include "blockresponder.h" #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" @@ -227,6 +228,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_config = config; m_component = component; m_isNextLongRun = false; + m_adminInterface = NULL; m_component->m_factory = new NetworkFactory(this); m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1)); m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1)); @@ -317,18 +319,14 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptrres = 0; client->init_res = 0; client->shared = 0; - client->willDie = 0; + // Until we receive first PONG from backend, backend is in willDie state. + client->willDie = true; // Backend does not accept new clients automatically if it's long-running client->acceptUsers = !m_isNextLongRun; client->longRun = m_isNextLongRun; LOG4CXX_INFO(logger, "New" + (client->longRun ? std::string(" long-running") : "") + " backend " << client << " connected. Current backend count=" << (m_clients.size() + 1)); - if (m_clients.size() == 0) { - // first backend connected, start the server, we're ready. - m_component->start(); - } - m_clients.push_front(client); c->onDisconnected.connect(boost::bind(&NetworkPluginServer::handleSessionFinished, this, client)); @@ -339,28 +337,6 @@ void NetworkPluginServer::handleNewClientConnection(boost::shared_ptrpongReceived = -1; - - // some users are in queue waiting for this backend - while(!m_waitingUsers.empty()) { - // There's no new backend, so stop associating users and wait for new backend, - // which has been already spawned in getFreeClient() call. - if (getFreeClient() == NULL) - break; - - User *u = m_waitingUsers.front(); - m_waitingUsers.pop_front(); - - LOG4CXX_INFO(logger, "Associating " << u->getJID().toString() << " with this backend"); - - // associate backend with user - handleUserCreated(u); - - // connect user if it's ready - if (u->isReadyToConnect()) { - handleUserReadyToConnect(u); - } - - } } void NetworkPluginServer::handleSessionFinished(Backend *c) { @@ -752,6 +728,68 @@ void NetworkPluginServer::handleFTDataNeeded(Backend *b, unsigned long ftid) { send(b->connection, message); } +void NetworkPluginServer::handlePongReceived(Backend *c) { + // This could be first PONG from the backend + if (c->pongReceived == -1) { + // Backend is fully ready to handle requests + c->willDie = false; + + if (m_clients.size() == 1) { + // first backend connected, start the server, we're ready. + m_component->start(); + } + + // some users are in queue waiting for this backend + while(!m_waitingUsers.empty()) { + // There's no new backend, so stop associating users and wait for new backend, + // which has been already spawned in getFreeClient() call. + if (getFreeClient() == NULL) + break; + + User *u = m_waitingUsers.front(); + m_waitingUsers.pop_front(); + + LOG4CXX_INFO(logger, "Associating " << u->getJID().toString() << " with this backend"); + + // associate backend with user + handleUserCreated(u); + + // connect user if it's ready + if (u->isReadyToConnect()) { + handleUserReadyToConnect(u); + } + } + } + + c->pongReceived = true; +} + +void NetworkPluginServer::handleQueryPayload(Backend *b, const std::string &data) { + pbnetwork::BackendConfig payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + if (!m_adminInterface) { + return; + } + + boost::shared_ptr msg(new Swift::Message()); + msg->setBody(payload.config()); + m_adminInterface->handleQuery(msg); + + pbnetwork::BackendConfig vcard; + vcard.set_config(msg->getBody()); + + std::string message; + vcard.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_QUERY); + + send(b->connection, message); +} + void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr data) { // Append data to buffer c->data.insert(c->data.end(), data->begin(), data->end()); @@ -802,7 +840,7 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptrpongReceived = true; + handlePongReceived(c); break; case pbnetwork::WrapperMessage_Type_TYPE_PARTICIPANT_CHANGED: handleParticipantChangedPayload(wrapper.payload()); @@ -843,6 +881,9 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptrpongReceived || (*it)->pongReceived == -1) { - sendPing((*it)); + // Don't send another ping if pongReceived == -1, because we've already sent one + // when registering backend. + if ((*it)->pongReceived) { + sendPing((*it)); + } } else { LOG4CXX_INFO(logger, "Disconnecting backend " << (*it) << " (ID=" << (*it)->id << "). PING response not received.");