summaryrefslogtreecommitdiffstats
path: root/src/Server/ConnectionManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Server/ConnectionManager.cpp')
-rw-r--r--src/Server/ConnectionManager.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/src/Server/ConnectionManager.cpp b/src/Server/ConnectionManager.cpp
new file mode 100644
index 0000000..279304c
--- /dev/null
+++ b/src/Server/ConnectionManager.cpp
@@ -0,0 +1,310 @@
+/*
+ * ConnectionManager.cpp
+ *
+ * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "ConnectionManager.h"
+#include <Common/ConfigEntry.h>
+#include <Common/ConfigManager.h>
+#include <Common/Logger.h>
+#include <Common/RequestHandlers/FSInfoRequestHandler.h>
+#include <Common/RequestHandlers/StatusRequestHandler.h>
+#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/UserInfoRequestHandler.h"
+#include "RequestHandlers/UserListRequestHandler.h"
+#include <Net/FdManager.h>
+#include <Net/ServerConnection.h>
+#include <Net/Packet.h>
+#include <Net/Listener.h>
+
+#include <unistd.h>
+#include <algorithm>
+
+namespace Mad {
+namespace Server {
+
+ConnectionManager ConnectionManager::connectionManager;
+
+bool ConnectionManager::Connection::send(const Net::Packet &packet) {
+ return connection->send(packet);
+}
+
+ConnectionManager::Connection::Connection(Net::ServerConnection *connection0, ConnectionType type0)
+: connection(connection0), type(type0), hostInfo(0) {
+ connection->signalReceive().connect(sigc::mem_fun(this, &Connection::receive));
+}
+
+ConnectionManager::Connection::~Connection() {
+ delete connection;
+}
+
+bool ConnectionManager::Connection::isConnected() const {
+ return connection->isConnected();
+}
+
+bool ConnectionManager::Connection::disconnect() {
+ connection->disconnect();
+
+ return true;
+}
+
+void* ConnectionManager::Connection::getCertificate(size_t *size) const {
+ const gnutls_datum_t *cert = connection->getCertificate();
+
+ *size = cert->size;
+ return cert->data;
+}
+
+void* ConnectionManager::Connection::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::list<Connection*>::iterator con = connections.begin(); con != connections.end(); ++con) {
+ if((*con)->getConnectionType() == Connection::CLIENT)
+ Common::RequestManager::get()->sendRequest<Requests::DaemonStateUpdateRequest>(*con, Common::Request::slot_type(), hostInfo->getName(), 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])));
+
+ 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<Net::IPAddress>::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()->setServer(true);
+
+ Net::Connection::init();
+
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::GSSAPIAuthRequestHandler>("AuthGSSAPI");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::DaemonCommandRequestHandler>("DaemonCommand");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::DaemonFSInfoRequestHandler>("DaemonFSInfo");
+ Common::RequestManager::get()->registerPacketType<Common::RequestHandlers::FSInfoRequestHandler>("FSInfo");
+ Common::RequestManager::get()->registerPacketType<Common::RequestHandlers::StatusRequestHandler>("GetStatus");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::DaemonStatusRequestHandler>("GetDaemonStatus");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::IdentifyRequestHandler>("Identify");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::DaemonListRequestHandler>("ListHosts");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::UserInfoRequestHandler>("GetUserInfo");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::UserListRequestHandler>("ListUsers");
+ Common::RequestManager::get()->registerPacketType<RequestHandlers::LogRequestHandler>("Log");
+}
+
+void ConnectionManager::doDeinit() {
+ for(std::list<Connection*>::iterator con = connections.begin(); con != connections.end(); ++con)
+ delete *con;
+
+
+ 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("GetUserInfo");
+ Common::RequestManager::get()->unregisterPacketType("ListUsers");
+ Common::RequestManager::get()->unregisterPacketType("Log");
+
+ Net::Connection::deinit();
+}
+
+void ConnectionManager::run() {
+ // TODO Logging
+
+ Net::FdManager::get()->run();
+
+ for(std::list<Connection*>::iterator con = connections.begin(); con != connections.end();) {
+ if(!(*con)->isConnected()) {
+ if((*con)->isIdentified())
+ updateState((*con)->getHostInfo(), Common::HostInfo::INACTIVE);
+
+ Common::RequestManager::get()->unregisterConnection(*con);
+ delete *con;
+ connections.erase(con++);
+ }
+ else
+ ++con;
+ }
+
+ for(std::list<Net::Listener*>::iterator listener = listeners.begin(); listener != listeners.end(); ++listener) {
+ Net::ServerConnection *con;
+
+ while((con = (*listener)->getConnection()) != 0) {
+ Connection *connection = new Connection(con,
+ con->isDaemonConnection() ? Connection::DAEMON : Connection::CLIENT);
+ connections.push_back(connection);
+ Common::RequestManager::get()->registerConnection(connection);
+ }
+ }
+}
+
+Common::Connection* ConnectionManager::getDaemonConnection(const std::string &name) const throw (Common::Exception&) {
+ const Common::HostInfo *hostInfo;
+
+ try {
+ hostInfo = &daemonInfo.at(name);
+ }
+ catch(std::out_of_range&) {
+ throw Common::Exception(Common::Exception::UNKNOWN_DAEMON);
+ }
+
+ if(hostInfo->getState() != Common::HostInfo::INACTIVE) {
+ for(std::list<Connection*>::const_iterator it = connections.begin(); it != connections.end(); ++it) {
+ if((*it)->getHostInfo() == hostInfo) {
+ return *it;
+ }
+ }
+ }
+
+ throw(Common::Exception::NOT_AVAILABLE);
+}
+
+std::string ConnectionManager::getDaemonName(const Common::Connection *con) const throw (Common::Exception&) {
+ const Connection *connection = dynamic_cast<const Connection*>(con);
+
+ if(connection) {
+ if(connection->isIdentified()) {
+ return connection->getHostInfo()->getName();
+ }
+ }
+
+ throw Common::Exception(Common::Exception::UNKNOWN_DAEMON);
+}
+
+void ConnectionManager::identifyDaemonConnection(Common::Connection *con, const std::string &name) throw (Common::Exception&) {
+ // TODO Logging
+
+ Connection *connection = dynamic_cast<Connection*>(con);
+
+ if(!connection || (connection->getConnectionType() != Connection::DAEMON))
+ throw Common::Exception(Common::Exception::INVALID_ACTION);
+
+ if(connection->isIdentified())
+ throw Common::Exception(Common::Exception::ALREADY_IDENTIFIED);
+
+ if(daemonInfo.count(name) == 0)
+ throw Common::Exception(Common::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(Common::Exception&) {}
+ }
+
+ connection->identify(hostInfo);
+ updateState(hostInfo, Common::HostInfo::RUNNING);
+
+ Common::Logger::logf("Identified as '%s'.", name.c_str());
+}
+
+std::vector<Common::HostInfo> ConnectionManager::getDaemonList() const {
+ std::vector<Common::HostInfo> ret;
+
+ for(std::map<std::string,Common::HostInfo>::const_iterator daemon = daemonInfo.begin(); daemon != daemonInfo.end(); ++daemon) {
+ ret.push_back(daemon->second);
+ }
+
+ return ret;
+}
+
+}
+}