/* * 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 "ConfigManager.h" #include #include "RequestHandlers/DaemonListRequestHandler.h" #include "RequestHandlers/DaemonStatusRequestHandler.h" #include "RequestHandlers/GSSAPIAuthRequestHandler.h" #include "RequestHandlers/IdentifyRequestHandler.h" #include #include #include #include #include #include namespace Mad { namespace Core { std::auto_ptr ConnectionManager::connectionManager; void ConnectionManager::refreshPollfds() { pollfds.clear(); pollfdMap.clear(); for(std::list::iterator listener = listeners.begin(); listener != listeners.end(); ++listener) { std::vector fds = (*listener)->getPollfds(); for(std::vector::iterator fd = fds.begin(); fd != fds.end(); ++fd) { pollfds.push_back(*fd); pollfdMap.insert(std::make_pair(fd->fd, &pollfds.back().revents)); } } for(std::list::iterator con = daemonConnections.begin(); con != daemonConnections.end(); ++con) { pollfds.push_back((*con)->getPollfd()); pollfdMap.insert(std::make_pair(pollfds.back().fd, &pollfds.back().revents)); } for(std::list::iterator con = clientConnections.begin(); con != clientConnections.end(); ++con) { pollfds.push_back((*con)->getPollfd()); pollfdMap.insert(std::make_pair(pollfds.back().fd, &pollfds.back().revents)); } } ConnectionManager::ConnectionManager() { Common::RequestManager::init(true); Common::RequestManager::getRequestManager()->registerPacketType(Net::Packet::STATUS); Common::RequestManager::getRequestManager()->registerPacketType(Net::Packet::LIST_DAEMONS); Common::RequestManager::getRequestManager()->registerPacketType(Net::Packet::DAEMON_STATUS); Common::RequestManager::getRequestManager()->registerPacketType(Net::Packet::GSSAPI_AUTH); Common::RequestManager::getRequestManager()->registerPacketType(Net::Packet::IDENTIFY); ConfigManager *configManager = ConfigManager::getConfigManager(); Net::Connection::init(); const std::vector &listenerAddresses = configManager->getListenerAddresses(); if(listenerAddresses.empty()) { try { listeners.push_back(new Net::Listener(configManager->getX509CertFile(), configManager->getX509KeyFile())); } catch(Net::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(configManager->getX509CertFile(), configManager->getX509KeyFile(), *address)); } catch(Net::Exception &e) { // TODO Log error } } } refreshPollfds(); const std::vector& daemons = configManager->getDaemonList(); for(std::vector::const_iterator daemon = daemons.begin(); daemon != daemons.end(); ++daemon) { daemonInfo.insert(std::make_pair(daemon->getName(), *daemon)); identifiedDaemonConnections.insert(std::make_pair(daemon->getName(), 0)); } } ConnectionManager::~ConnectionManager() { 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; Net::Connection::deinit(); } void ConnectionManager::handleConnections(std::list& connections) { for(std::list::iterator con = connections.begin(); con != connections.end();) { if((*con)->isConnected()) { std::map::iterator events = pollfdMap.find((*con)->getSocket()); if(events != pollfdMap.end() && *events->second) (*con)->sendReceive(*events->second); ++con; } else { if((*con)->isIdentified()) { for(std::map::iterator idCon = identifiedDaemonConnections.begin(); idCon != identifiedDaemonConnections.end(); ++idCon) { if(idCon->second == *con) { idCon->second = 0; break; } } } Common::RequestManager::getRequestManager()->unregisterConnection(*con); delete *con; connections.erase(con++); } } } void ConnectionManager::run() { // TODO Logging handleConnections(daemonConnections); handleConnections(clientConnections); for(std::list::iterator listener = listeners.begin(); listener != listeners.end(); ++listener) { Net::ServerConnection *con; while((con = (*listener)->getConnection(pollfdMap)) != 0) { (con->isDaemonConnection() ? daemonConnections : clientConnections).push_back(con); Common::RequestManager::getRequestManager()->registerConnection(con); } } refreshPollfds(); } 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::DAEMON_INACTIVE); return daemon->second; } 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(); std::cerr << "Disconnecting old connection" << std::endl; } idCon->second = *con; connection->setIdentified(); std::cerr << "Identified as '" << name << "'." << std::endl; } std::map ConnectionManager::getDaemonList() const { std::map ret; for(std::map::const_iterator con = identifiedDaemonConnections.begin(); con != identifiedDaemonConnections.end(); ++con) { if(con->second) ret.insert(std::make_pair(con->first, daemonInfo.at(con->first))); } return ret; } } }