/* * ConnectionManager.cpp * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include "ConnectionManager.h" #include "Application.h" #include #include #include #include #include #include "Requests/DaemonStateUpdateRequest.h" //#include "RequestHandlers/GSSAPIAuthRequestHandler.h" #include "RequestHandlers/ConnectionRequestHandlerGroup.h" #include "RequestHandlers/DaemonRequestHandlerGroup.h" #include "RequestHandlers/UserRequestHandlerGroup.h" #include #include #include #include namespace Mad { namespace Server { bool ConnectionManager::ServerConnection::send(const Net::Packet &packet) { return connection->send(packet); } ConnectionManager::ServerConnection::ServerConnection(Core::Application *application, boost::shared_ptr connection0) : Common::Connection(application), connection(connection0), type(UNKNOWN), hostInfo(0) { connection->connectSignalReceive(boost::bind(&ServerConnection::receive, this, _1)); } bool ConnectionManager::ServerConnection::isConnected() const { return connection->isConnected(); } bool ConnectionManager::ServerConnection::disconnect() { connection->disconnect(); return true; } /*void* ConnectionManager::ServerConnection::getCertificate(size_t *size) const { const gnutls_datum_t *cert = connection->getCertificate(); *size = cert->size; return cert->data; } void* ConnectionManager::ServerConnection::getPeerCertificate(size_t *size) const { const gnutls_datum_t *cert = connection->getPeerCertificate(); *size = cert->size; return cert->data; }*/ void ConnectionManager::updateState(Common::HostInfo *hostInfo, Common::HostInfo::State state) { hostInfo->setState(state); for(std::set >::iterator con = connections.begin(); con != connections.end(); ++con) { if((*con)->getConnectionType() == ServerConnection::CLIENT) { boost::shared_ptr request(new Requests::DaemonStateUpdateRequest(application, hostInfo->getName(), state)); application->getRequestManager()->sendRequest(con->get(), request); } } } bool ConnectionManager::handleConfigEntry(const Core::ConfigEntry &entry, bool handled) { if(handled) return false; if(entry[0].getKey().matches("Listen") && entry[1].empty()) { try { listenerAddresses.push_back(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(entry[0][0]), 6666)); } catch(Core::Exception &e) { // TODO Log error } return true; } else if(entry[0].getKey().matches("X509TrustFile") && entry[1].empty()) { x509TrustFile = entry[0][0]; return true; } else if(entry[0].getKey().matches("X509CrlFile") && entry[1].empty()) { x509CrlFile = entry[0][0]; return true; } else if(entry[0].getKey().matches("X509CertFile") && entry[1].empty()) { x509CertFile = entry[0][0]; return true; } else if(entry[0].getKey().matches("X509KeyFile") && entry[1].empty()) { x509KeyFile = entry[0][0]; return true; } else if(entry[0].getKey().matches("Daemon")) { if(entry[0].getSize() == 1) { if(entry[1].empty()) { daemonInfo.insert(std::make_pair(entry[0][0], Common::HostInfo(entry[0][0]))); return true; } else if(entry[1].getKey().matches("IpAddress") && entry[2].empty()) { daemonInfo[entry[0][0]].setIP(entry[1][0]); return true; } } } return false; } void ConnectionManager::configFinished() { if(listenerAddresses.empty()) { try { boost::shared_ptr listener(new Net::Listener(application, x509CertFile, x509KeyFile)); listener->connectSignalNewConnection(boost::bind(&ConnectionManager::handleNewConnection, this, _1)); listeners.push_back(listener); } catch(Core::Exception &e) { // TODO Log error } } else { for(std::vector::const_iterator address = listenerAddresses.begin(); address != listenerAddresses.end(); ++address) { try { boost::shared_ptr listener(new Net::Listener(application, x509CertFile, x509KeyFile, *address)); listener->connectSignalNewConnection(boost::bind(&ConnectionManager::handleNewConnection, this, _1)); listeners.push_back(listener); } catch(Core::Exception &e) { // TODO Log error } } } } void ConnectionManager::handleNewConnection(boost::shared_ptr con) { boost::shared_ptr connection(new ServerConnection(application, con)); con->connectSignalDisconnected(boost::bind(&ConnectionManager::handleDisconnect, this, connection)); connections.insert(connection); application->getRequestManager()->registerConnection(connection.get()); } void ConnectionManager::handleDisconnect(boost::shared_ptr con) { if(con->getHostInfo()) updateState(con->getHostInfo(), Common::HostInfo::INACTIVE); connections.erase(con); application->getRequestManager()->unregisterConnection(con.get()); } ConnectionManager::ConnectionManager(Application *application0) : application(application0), connectionRequestHandlerGroup(new RequestHandlers::ConnectionRequestHandlerGroup(application)), daemonRequestHandlerGroup(new RequestHandlers::DaemonRequestHandlerGroup), userRequestHandlerGroup(new RequestHandlers::UserRequestHandlerGroup(application)) { //requestManager->registerPacketType("AuthGSSAPI"); application->getRequestManager()->registerPacketType("FSInfo"); application->getRequestManager()->registerPacketType("GetStatus"); application->getRequestManager()->registerRequestHandlerGroup(connectionRequestHandlerGroup); application->getRequestManager()->registerRequestHandlerGroup(daemonRequestHandlerGroup); application->getRequestManager()->registerRequestHandlerGroup(userRequestHandlerGroup); application->getConfigManager()->registerConfigurable(this); } ConnectionManager::~ConnectionManager() { application->getConfigManager()->unregisterConfigurable(this); connections.clear(); application->getRequestManager()->unregisterRequestHandlerGroup(userRequestHandlerGroup); application->getRequestManager()->unregisterRequestHandlerGroup(daemonRequestHandlerGroup); application->getRequestManager()->unregisterRequestHandlerGroup(connectionRequestHandlerGroup); //requestManager->unregisterPacketType("AuthGSSAPI"); application->getRequestManager()->unregisterPacketType("FSInfo"); application->getRequestManager()->unregisterPacketType("GetStatus"); } boost::shared_ptr ConnectionManager::getDaemonConnection(const std::string &name) const throw (Core::Exception&) { const Common::HostInfo *hostInfo; try { hostInfo = &daemonInfo.at(name); } catch(std::out_of_range&) { throw Core::Exception(Core::Exception::UNKNOWN_DAEMON); } if(hostInfo->getState() != Common::HostInfo::INACTIVE) { for(std::set >::const_iterator it = connections.begin(); it != connections.end(); ++it) { if((*it)->getHostInfo() == hostInfo) { return *it; } } } throw Core::Exception(Core::Exception::NOT_AVAILABLE); } std::string ConnectionManager::getDaemonName(const Common::Connection *con) const throw (Core::Exception&) { const ServerConnection *connection = dynamic_cast(con); if(connection && connection->getConnectionType() == ServerConnection::DAEMON) return connection->getHostInfo()->getName(); throw Core::Exception(Core::Exception::UNKNOWN_DAEMON); } void ConnectionManager::identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Core::Exception&) { // TODO Logging ServerConnection *connection = dynamic_cast(con); if(!connection) throw Core::Exception(Core::Exception::INVALID_ACTION); if(connection->isIdentified()) throw Core::Exception(Core::Exception::ALREADY_IDENTIFIED); if(daemonInfo.count(name) == 0) throw Core::Exception(Core::Exception::UNKNOWN_DAEMON); Common::HostInfo *hostInfo = &daemonInfo[name]; if(hostInfo->getState() != Common::HostInfo::INACTIVE) { try { getDaemonConnection(name)->disconnect(); application->log(Core::LoggerBase::WARNING, "Disconnecting old connection."); } catch(Core::Exception&) {} } connection->identify(hostInfo); updateState(hostInfo, Common::HostInfo::RUNNING); application->logf("Identified as '%s'.", name.c_str()); } void ConnectionManager::identifyClientConnection(Common::Connection *con) throw (Core::Exception&) { ServerConnection *connection = dynamic_cast(con); if(!connection) throw Core::Exception(Core::Exception::INVALID_ACTION); if(connection->isIdentified()) throw Core::Exception(Core::Exception::ALREADY_IDENTIFIED); connection->identify(); } std::vector ConnectionManager::getDaemonList() const { std::vector ret; for(std::map::const_iterator daemon = daemonInfo.begin(); daemon != daemonInfo.end(); ++daemon) { ret.push_back(daemon->second); } return ret; } } }