/* * 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/UserRequestHandlerGroup.h" #include #include #include #include namespace Mad { namespace Server { ConnectionManager ConnectionManager::connectionManager; bool ConnectionManager::ServerConnection::send(const Net::Packet &packet) { return connection->send(packet); } ConnectionManager::ServerConnection::ServerConnection(boost::shared_ptr connection0) : 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(hostInfo->getName(), state)); Common::RequestManager::get()->sendRequest(con->get(), request); } } } 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(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(entry[0][0]), 6666)); } catch(Net::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(x509CertFile, x509KeyFile)); listener->connectSignalNewConnection(boost::bind(&ConnectionManager::handleNewConnection, this, _1)); listeners.push_back(listener); } catch(Net::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(x509CertFile, x509KeyFile, *address)); listener->connectSignalNewConnection(boost::bind(&ConnectionManager::handleNewConnection, this, _1)); listeners.push_back(listener); } catch(Net::Exception &e) { // TODO Log error } } } } void ConnectionManager::handleNewConnection(boost::shared_ptr con) { boost::shared_ptr connection(new ServerConnection(con)); con->connectSignalDisconnected(boost::bind(&ConnectionManager::handleDisconnect, this, connection)); connections.insert(connection); Common::RequestManager::get()->registerConnection(connection.get()); } void ConnectionManager::handleDisconnect(boost::shared_ptr con) { if(con->getHostInfo()) updateState(con->getHostInfo(), Common::HostInfo::INACTIVE); connections.erase(con); Common::RequestManager::get()->unregisterConnection(con.get()); } void ConnectionManager::doInit() { Common::RequestManager::get()->setServer(true); userRequestHandlerGroup.reset(new RequestHandlers::UserRequestHandlerGroup); //Common::RequestManager::get()->registerPacketType("AuthGSSAPI"); Common::RequestManager::get()->registerPacketType("DaemonCommand"); Common::RequestManager::get()->registerPacketType("DaemonFSInfo"); Common::RequestManager::get()->registerPacketType("FSInfo"); Common::RequestManager::get()->registerPacketType("GetStatus"); Common::RequestManager::get()->registerPacketType("GetDaemonStatus"); Common::RequestManager::get()->registerPacketType("Identify"); Common::RequestManager::get()->registerPacketType("ListHosts"); Common::RequestManager::get()->registerPacketType("Log"); Common::RequestManager::get()->registerRequestHandlerGroup(userRequestHandlerGroup); } void ConnectionManager::doDeinit() { connections.clear(); Common::RequestManager::get()->unregisterRequestHandlerGroup(userRequestHandlerGroup); //Common::RequestManager::get()->unregisterPacketType("AuthGSSAPI"); Common::RequestManager::get()->unregisterPacketType("DaemonCommand"); Common::RequestManager::get()->unregisterPacketType("DaemonFSInfo"); Common::RequestManager::get()->unregisterPacketType("FSInfo"); Common::RequestManager::get()->unregisterPacketType("GetStatus"); Common::RequestManager::get()->unregisterPacketType("GetDaemonStatus"); Common::RequestManager::get()->unregisterPacketType("Identify"); Common::RequestManager::get()->unregisterPacketType("ListHosts"); Common::RequestManager::get()->unregisterPacketType("Log"); } boost::shared_ptr ConnectionManager::getDaemonConnection(const std::string &name) const throw (Net::Exception&) { const Common::HostInfo *hostInfo; try { hostInfo = &daemonInfo.at(name); } catch(std::out_of_range&) { throw Net::Exception(Net::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 Net::Exception(Net::Exception::NOT_AVAILABLE); } std::string ConnectionManager::getDaemonName(const Common::Connection *con) const throw (Net::Exception&) { const ServerConnection *connection = dynamic_cast(con); if(connection && connection->getConnectionType() == ServerConnection::DAEMON) return connection->getHostInfo()->getName(); throw Net::Exception(Net::Exception::UNKNOWN_DAEMON); } void ConnectionManager::identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Net::Exception&) { // TODO Logging ServerConnection *connection = dynamic_cast(con); if(!connection) throw Net::Exception(Net::Exception::INVALID_ACTION); if(connection->isIdentified()) throw Net::Exception(Net::Exception::ALREADY_IDENTIFIED); if(daemonInfo.count(name) == 0) throw Net::Exception(Net::Exception::UNKNOWN_DAEMON); Common::HostInfo *hostInfo = &daemonInfo[name]; if(hostInfo->getState() != Common::HostInfo::INACTIVE) { try { getDaemonConnection(name)->disconnect(); Common::Logger::log(Common::Logger::WARNING, "Disconnecting old connection."); } catch(Net::Exception&) {} } connection->identify(hostInfo); updateState(hostInfo, Common::HostInfo::RUNNING); Common::Logger::logf("Identified as '%s'.", name.c_str()); } void ConnectionManager::identifyClientConnection(Common::Connection *con) throw (Net::Exception&) { ServerConnection *connection = dynamic_cast(con); if(!connection) throw Net::Exception(Net::Exception::INVALID_ACTION); if(connection->isIdentified()) throw Net::Exception(Net::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; } } }