/* * 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 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "ConnectionManager.h" #include #include #include #include #include #include "Requests/DaemonStateUpdateRequest.h" #include "RequestHandlers/DaemonCommandRequestHandler.h" #include "RequestHandlers/DaemonFSInfoRequestHandler.h" #include "RequestHandlers/DaemonListRequestHandler.h" #include "RequestHandlers/DaemonStatusRequestHandler.h" #include "RequestHandlers/GSSAPIAuthRequestHandler.h" #include "RequestHandlers/IdentifyRequestHandler.h" #include "RequestHandlers/LogRequestHandler.h" #include "RequestHandlers/UserListRequestHandler.h" #include #include #include #include #include #include namespace Mad { namespace Core { ConnectionManager ConnectionManager::connectionManager; void ConnectionManager::updateState(const std::string &name, Common::HostInfo::State state) { daemonInfo[name].setState(state); for(std::list::iterator con = clientConnections.begin(); con != clientConnections.end(); ++con) { Common::RequestManager::get()->sendRequest(*con, std::auto_ptr( new Requests::DaemonStateUpdateRequest(name, state) )); } } bool ConnectionManager::handleConfigEntry(const Common::ConfigEntry &entry, bool handled) { if(handled) return false; if(entry[0].getKey().matches("Listen") && entry[1].empty()) { try { listenerAddresses.push_back(Net::IPAddress(entry[0][0])); } catch(Common::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]))); identifiedDaemonConnections.insert(std::make_pair(entry[0][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 { listeners.push_back(new Net::Listener(x509CertFile, x509KeyFile)); } catch(Common::Exception &e) { // TODO Log error } } else { for(std::vector::const_iterator address = listenerAddresses.begin(); address != listenerAddresses.end(); ++address) { try { listeners.push_back(new Net::Listener(x509CertFile, x509KeyFile, *address)); } catch(Common::Exception &e) { // TODO Log error } } } } void ConnectionManager::doInit() { Common::RequestManager::get()->setCore(true); Net::Connection::init(); Common::RequestManager::get()->registerPacketType(Net::Packet::FS_INFO); Common::RequestManager::get()->registerPacketType(Net::Packet::DAEMON_COMMAND_REBOOT); Common::RequestManager::get()->registerPacketType(Net::Packet::DAEMON_COMMAND_SHUTDOWN); Common::RequestManager::get()->registerPacketType(Net::Packet::DAEMON_FS_INFO); Common::RequestManager::get()->registerPacketType(Net::Packet::GSSAPI_AUTH); Common::RequestManager::get()->registerPacketType(Net::Packet::IDENTIFY); Common::RequestManager::get()->registerPacketType("GetStatus"); Common::RequestManager::get()->registerPacketType("GetDaemonStatus"); Common::RequestManager::get()->registerPacketType("ListHosts"); Common::RequestManager::get()->registerPacketType("ListUsers"); Common::RequestManager::get()->registerPacketType("Log"); } void ConnectionManager::doDeinit() { for(std::list::iterator con = daemonConnections.begin(); con != daemonConnections.end(); ++con) delete *con; for(std::list::iterator con = clientConnections.begin(); con != clientConnections.end(); ++con) delete *con; Common::RequestManager::get()->unregisterPacketType(Net::Packet::FS_INFO); Common::RequestManager::get()->unregisterPacketType(Net::Packet::DAEMON_COMMAND_REBOOT); Common::RequestManager::get()->unregisterPacketType(Net::Packet::DAEMON_COMMAND_SHUTDOWN); Common::RequestManager::get()->unregisterPacketType(Net::Packet::DAEMON_FS_INFO); Common::RequestManager::get()->unregisterPacketType(Net::Packet::GSSAPI_AUTH); Common::RequestManager::get()->unregisterPacketType(Net::Packet::IDENTIFY); Common::RequestManager::get()->unregisterPacketType("GetStatus"); Common::RequestManager::get()->unregisterPacketType("GetDaemonStatus"); Common::RequestManager::get()->unregisterPacketType("ListHosts"); Common::RequestManager::get()->unregisterPacketType("ListUsers"); Common::RequestManager::get()->unregisterPacketType("Log"); Net::Connection::deinit(); } void ConnectionManager::handleConnections(std::list& connections) { for(std::list::iterator con = connections.begin(); con != connections.end();) { if(!(*con)->isConnected()) { if((*con)->isIdentified()) { for(std::map::iterator idCon = identifiedDaemonConnections.begin(); idCon != identifiedDaemonConnections.end(); ++idCon) { if(idCon->second == *con) { idCon->second = 0; updateState(idCon->first, Common::HostInfo::INACTIVE); break; } } } Common::RequestManager::get()->unregisterConnection(*con); delete *con; connections.erase(con++); } else ++con; } } void ConnectionManager::run() { // TODO Logging Net::FdManager::get()->run(); handleConnections(daemonConnections); handleConnections(clientConnections); for(std::list::iterator listener = listeners.begin(); listener != listeners.end(); ++listener) { Net::ServerConnection *con; while((con = (*listener)->getConnection()) != 0) { (con->isDaemonConnection() ? daemonConnections : clientConnections).push_back(con); Common::RequestManager::get()->registerConnection(con); } } } Net::Connection* ConnectionManager::getDaemonConnection(const std::string &name) const throw (Common::Exception&) { std::map::const_iterator daemon = identifiedDaemonConnections.find(name); if(daemon == identifiedDaemonConnections.end()) throw Common::Exception(Common::Exception::UNKNOWN_DAEMON); if(!daemon->second) throw Common::Exception(Common::Exception::NOT_AVAILABLE); return daemon->second; } std::string ConnectionManager::getDaemonName(const Net::Connection *con) const throw (Common::Exception&) { for(std::map::const_iterator daemon = identifiedDaemonConnections.begin(); daemon != identifiedDaemonConnections.end(); ++daemon) { if(daemon->second == con) return daemon->first; } throw Common::Exception(Common::Exception::UNKNOWN_DAEMON); } void ConnectionManager::identifyDaemonConnection(Net::Connection *connection, const std::string &name) throw (Common::Exception&) { // TODO Logging if(connection->isIdentified()) throw Common::Exception(Common::Exception::ALREADY_IDENTIFIED); std::list::iterator con = std::find(daemonConnections.begin(), daemonConnections.end(), connection); if(con == daemonConnections.end()) throw Common::Exception(Common::Exception::INVALID_ACTION); std::map::iterator idCon = identifiedDaemonConnections.find(name); if(idCon == identifiedDaemonConnections.end()) { throw Common::Exception(Common::Exception::UNKNOWN_DAEMON); } if(idCon->second) { idCon->second->disconnect(); Common::Logger::log(Common::Logger::WARNING, "Disconnecting old connection."); } idCon->second = *con; updateState(idCon->first, Common::HostInfo::RUNNING); connection->setIdentified(); Common::Logger::logf("Identified as '%s'.", name.c_str()); } 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; } } }