summaryrefslogtreecommitdiffstats
path: root/src/core/pvsConnectionManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/pvsConnectionManager.cpp')
-rw-r--r--src/core/pvsConnectionManager.cpp483
1 files changed, 483 insertions, 0 deletions
diff --git a/src/core/pvsConnectionManager.cpp b/src/core/pvsConnectionManager.cpp
new file mode 100644
index 0000000..8a35ca9
--- /dev/null
+++ b/src/core/pvsConnectionManager.cpp
@@ -0,0 +1,483 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/core/pvsConnectionManager.cpp
+# -----------------------------------------------------------------------------
+*/
+
+#include "pvsConnectionManager.h"
+#include "src/gui/mainWindow.h"
+#include <QApplication>
+#include "src/setup.h"
+#include "src/util/CertManager.h"
+#include "src/util/serviceDiscoveryUtil.h"
+
+PVSConnectionManager* PVSConnectionManager::singleCM;
+
+
+PVSConnectionManager* PVSConnectionManager::getManager()
+{
+ if (!singleCM)
+ singleCM = new PVSConnectionManager();
+ return singleCM;
+}
+
+PVSConnectionManager::PVSConnectionManager()
+{
+ _busy = false;
+ _needPassword = false;
+ loadCommands();
+ ConsoleLog writeLine(QString("Connection Manager created."));
+ ConsoleLog writeChat("Log for chat is now running");
+
+ if (!(_pvsServer.startListen(SERVER_PORT_INT)))
+ ConsoleLog writeError(QString("Server listening failed!"));
+ setUpdateRate(500);
+ _sdBroadcaster.setFingerprint(
+ CertManager::getCertificate("manager").digest(QCryptographicHash::Sha1)
+ );
+ _timerId = startTimer(1000);
+}
+
+PVSConnectionManager::~PVSConnectionManager()
+{
+ killTimer(_timerId);
+}
+
+void PVSConnectionManager::setUpdateRate(int newRate)
+{
+ // TODO: Iterate over list of clients and set the updateRate on each vncConnection
+ // Object. The timer does not influence the update rate of the thumbs, thus the code
+ // here was removed.
+}
+
+void PVSConnectionManager::timerEvent(QTimerEvent *event)
+{
+ update();
+}
+
+void PVSConnectionManager::onClientNew(PVSClientConnection* newConnection)
+{
+ PVSClient* tmp = getClientFromConnection(newConnection);
+ if (tmp == NULL)
+ {
+ PVSClient* newCon = new PVSClient(newConnection);
+ _listClients.push_back(newCon);
+ sendEventToClients(QString("addedConnection"), newConnection, "");
+ }
+ else
+ {
+ // already got that one... strange, eh?
+ }
+}
+
+void PVSConnectionManager::onClientRemove(PVSClientConnection* removedConnection)
+{
+ PVSClient* tmp = getClientFromConnection(removedConnection);
+ if (tmp == NULL) return;
+ MainWindow::getWindow()->removeConnection(tmp);
+ removeConnection(tmp);
+ if(tmp->getUserName().length() > 0)
+ {
+ ConsoleLog writeChat(tmp->getUserName()+" has left the chat.");
+ sendEventToClients("removedClient", removedConnection , tmp->getUserName()+":"+tmp->getIp());
+ }
+}
+
+// Inform all chat clients about a new event.
+void PVSConnectionManager::sendEventToClients(QString event, PVSClientConnection* connection, QString clientName)
+{
+ if(event.compare("addedConnection") == 0)
+ {
+ // send the client list to new Connection.
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ QString name = (**it).getUserName();
+ QString ip = (**it).getIp();
+ if (name.length() == 0) continue;
+ connection->push_back_send(PVSMsg(PVSMESSAGE, "clientToAdd", ":" + name + ":" + ip, 0));
+ }
+ }
+ if(event.compare("addedClient") == 0)
+ {
+ // send name to everybody to all connected clients.
+ _pvsServer.sendToAll(PVSMsg(PVSMESSAGE, "clientToAdd", ":" + clientName, 0));
+ connection->push_back_send(PVSMsg(PVSMESSAGE, "assignedName", ":" + clientName, 0));
+ connection->push_back_send(PVSMsg(PVSMESSAGE, "clientToAdd", ":PVSMGR:local", 0));
+ }
+ if(event.compare("removedClient") == 0)
+ {
+ // send name of removed client to connected clients.
+ _pvsServer.sendToAll(PVSMsg(PVSMESSAGE, "clientToRemove", ":"+ clientName, 0));
+ }
+}
+
+PVSClient* PVSConnectionManager::getClientFromConnection(PVSClientConnection* client)
+{
+ if (!_listClients.empty())
+ {
+
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if ((*it)->getPVSClientConnection())
+ {
+ if ((*it)->getPVSClientConnection() == client)
+ {
+ return (*it);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+PVSClient* PVSConnectionManager::getClientFromConnectionId(int id)
+{
+ if (_listClients.empty()) return NULL;
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if ((*it)->getConnectionId() == id) return (*it);
+ }
+ return NULL;
+}
+
+PVSClient* PVSConnectionManager::getClientFromVNCConnection(VNCConnection* client)
+{
+ if (!_listClients.empty())
+ {
+
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if ((*it)->getVNCConnection())
+ {
+ if ((*it)->getVNCConnection() == client)
+ {
+ return (*it);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+PVSClient* PVSConnectionManager::getClientFromIp(QString ip)
+{
+ if (!_listClients.empty())
+ {
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ // ok, probably this could be handled better inside the PVSConnection itself
+ // but makeshift for now
+ if ((*it)->getPVSClientConnection())
+ {
+ if ((*it)->getIp() == ip)
+ {
+ return (*it);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+void PVSConnectionManager::onCommand(PVSMsg command)
+{
+ QString message = command.getMessage();
+ QString ident = command.getIdent();
+ if (ident.compare("VNCSRVRESULT") == 0)
+ {
+ int e = string2Int(message);
+ QString id = int2String(command.getSndID());
+ switch (e)
+ {
+ case 0:
+ ConsoleLog writeLine("[Client: " + id + ", VNCSRV] Server should be running");
+ break;
+ case 1:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] Server returned general error");
+ break;
+ case 2:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] ~/.pvs/vncpasswd not found");
+ break;
+ case 3:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] VNC-Script not found");
+ break;
+ case 127:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] command not found (vnc-server installed?)");
+ break;
+ default:
+ ConsoleLog writeError("[Client: " + id + ", VNCSRV] unknown error");
+ break;
+ }
+ }
+}
+void PVSConnectionManager::onChat(PVSMsg chatMsg)
+{
+
+ QString nick_to = chatMsg.getIdent();
+ int sndID = chatMsg.getSndID();
+ PVSClientConnection* clientConnection = NULL;
+ PVSClient* client;
+ QStringList l = chatMsg.getMessage().split(":");
+ QString nick_from = l[0];
+ QString msg = chatMsg.getMessage().remove(0, l[0].size()+1);
+
+ if (nick_to == "@all") // public message.
+ {
+ _pvsServer.sendToAll(chatMsg);
+ MainWindow::getWindow()->receiveChatMsg(nick_from, nick_to, msg);// get Msg on PVSMgr's Chat-GUI.
+ ConsoleLog writeChat(nick_from +" wrote '"+msg+"' in @all-Channel.");
+ }
+ else // private message.
+ {
+ if(nick_from == "PVSMGR") //Msg from Server
+ {
+ MainWindow::getWindow()->receiveChatMsg(nick_from, nick_to, msg); // get Msg on PVSMgr's Chat-GUI.
+ ConsoleLog writeChat(nick_from+" wrote '" + msg + "' to " + nick_to); // write the event to the chat log.
+ }
+ else
+ {
+ clientConnection = _pvsServer.getConnectionFromId(sndID); // become your own message.
+ if (clientConnection)
+ {
+ clientConnection->push_back_send(chatMsg);
+ }
+ else
+ {
+ ConsoleLog writeError("Got Chat Message from unknown ID");
+ }
+ }
+ if(nick_to == "PVSMGR") //Msg to Server
+ {
+ MainWindow::getWindow()->receiveChatMsg(nick_from, nick_to, msg); // get Msg on PVSMgr's Chat-GUI.
+ ConsoleLog writeChat(nick_from+" wrote '" + msg + "' to " + nick_to);// write the event to the chat log.
+ }
+ else
+ {
+ client = getClientFromUsername(nick_to); // private receiver become the message.
+ if (client)
+ {
+ client->sendMessage(chatMsg);
+ ConsoleLog writeChat(nick_from+" wrote '" + msg + "' to " + nick_to);// write the event to the chat log.
+ }
+ else
+ {
+ ConsoleLog writeError("[CHAT] There is no client with username: " + nick_to);
+ }
+ }
+
+ }
+}
+
+PVSClient* PVSConnectionManager::getClientFromUsername(QString name)
+{
+ if (!(_listClients.empty()))
+ {
+ // Check for ping timeout
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it!= _listClients.end(); it++)
+ {
+ PVSClient *client = *it;
+ if (client)
+ if (client->getUserName() == name)
+ return client;
+ }
+ }
+ return NULL;
+}
+
+void PVSConnectionManager::onLoginPassword(PVSMsg command)
+{
+ if (!_needPassword) return; // No password required
+ if (_password == command.getMessage()) return; // No password set
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+ tmp->sendMessage(
+ PVSMsg(PVSLOGIN, "FAILED", "Wrong password.")
+ );
+ tmp->shutDownClient();
+}
+
+// Set usernamen and loginname a client.
+void PVSConnectionManager::onLoginUsername(PVSMsg command)
+{
+ QStringList l = command.getMessage().split(",");
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+ if (tmp->getUserName().length() > 0) return;
+ ConsoleLog writeError("(PVSConnectionManager::onUsername) was fired.");
+ if(l[0] == "PVSMGR")
+ {
+ l[0] = "fake_PVSMGR";
+ }
+ int counter = 0;
+ QString uname = l[0];
+ while (getClientFromUsername(uname) != NULL)
+ {
+ uname = l[0].append(QString::number(counter++, 16));
+ }
+ if (tmp)
+ {
+ tmp->setUsername(uname);
+ tmp->setLoginName(l[1]);
+ MainWindow::getWindow()->addConnection(tmp);
+ ConsoleLog writeChat(tmp->getUserName()+" has joined the chat.");
+ sendEventToClients(QString("addedClient"), tmp->getPVSClientConnection(), tmp->getUserName() +":"+ tmp->getIp());
+ }
+ else
+ ConsoleLog writeError("(PVSConnectionManager::onUsername) Couldnt find connection to user-id");
+}
+
+void PVSConnectionManager::onVncPassword(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
+ if (tmp)
+ {
+ tmp->setVncPassword(command.getMessage());
+ return;
+ }
+ else
+ ConsoleLog writeError("couldnt find matching connection to id!");
+}
+
+void PVSConnectionManager::onVncRwPassword(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
+ if (tmp)
+ {
+ tmp->setVncRwPassword(command.getMessage());
+ return;
+ }
+ else
+ ConsoleLog writeError("couldnt find matching connection to id!");
+}
+
+void PVSConnectionManager::onVncAllow(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
+ if (tmp)
+ {
+ if (command.getMessage().compare("YES") == 0)
+ {
+ tmp->setAllowed(true);
+ return;
+ }
+ tmp->setAllowed(false);
+ }
+}
+
+void PVSConnectionManager::onVncPort(PVSMsg command)
+{
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+ if (tmp)
+ {
+ int port = string2Int(command.getMessage());
+ if (port > 0)
+ tmp->setVncPort(port);
+ }
+
+}
+
+void PVSConnectionManager::onVncProjection(PVSMsg command)
+{
+ if (command.getMessage().compare(QString("YES")) == 0)
+ ConsoleLog writeLine("Client is watching.(connected via vnc)");
+ if (command.getMessage().compare(QString("NO")) == 0)
+ ConsoleLog writeLine("Client failed to connect via vnc.");
+}
+
+void PVSConnectionManager::removeConnection(PVSClient* newConnection)
+{
+ if (newConnection != NULL)
+ {
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ if (newConnection == (*it))
+ {
+ // remove it from the list to keep this method from causing trouble when being called more than
+ // once in the process
+ _listClients.remove(newConnection);
+
+ // it is important to tell the GUI that the vnc is gone (or ... will be)
+ // before we really shut it down, since the removal procedure of the
+ // frames shouldnt be messed with from here.
+ MainWindow::getWindow()->onConnectionRemoved(newConnection); // to kill vncConnection
+
+ // now that the gui nows about it and does no longer call the vnc-stuff
+ newConnection->shutDownVNC();
+ // and its gone...
+
+ // clean up on the connection
+ newConnection->shutDownClient(); // just to be sure
+ newConnection->onClientDisconnected();
+
+
+ newConnection->deleteLater();
+ return;
+ }
+ }
+ }
+ else
+ {
+ // well, not our problem obviously
+ }
+}
+
+bool PVSConnectionManager::update()
+{
+ if (_busy) return true; // already ongoing, so scrap that.
+
+ _busy = true; // lock method
+
+ if (!_listClients.empty())
+ {
+ // now update the rest and check if they are alive
+ // otherwise mark dead connections
+ for (std::list<PVSClient*>::iterator it = _listClients.begin(); it != _listClients.end(); it++)
+ {
+ PVSClient* current = (*it);
+ current->tick();
+ }
+ }
+
+ //QApplication::processEvents(QEventLoop::AllEvents, 5);
+
+ _busy = false; // we're done, so unlock
+ return true;
+}
+
+void PVSConnectionManager::loadCommands()
+{
+ _pvsServer.addLoginHandler("USERNAME", this, &PVSConnectionManager::onLoginUsername);
+ _pvsServer.addLoginHandler("PASSWORD", this, &PVSConnectionManager::onLoginPassword);
+ _pvsServer.addCommandHandler("*", this, &PVSConnectionManager::onCommand);
+ _pvsServer.addCommandHandler("VNC", this, &PVSConnectionManager::onVncAllow);
+ _pvsServer.addCommandHandler("PORT", this, &PVSConnectionManager::onVncPort);
+ _pvsServer.addCommandHandler("PASSWORD", this, &PVSConnectionManager::onVncPassword);
+ _pvsServer.addCommandHandler("RWPASSWORD", this, &PVSConnectionManager::onVncRwPassword);
+ _pvsServer.addCommandHandler("PROJECTING", this, &PVSConnectionManager::onVncProjection);
+ _pvsServer.addChatHandler("*", this, &PVSConnectionManager::onChat);
+}
+
+QString PVSConnectionManager::setNeedPassword(bool enabled)
+{
+ _needPassword = enabled;
+ if (enabled && _password.isEmpty())
+ {
+ _password = QString::number(getRandom(1000, 9999), 10);
+ }
+ return _password;
+}
+
+QString PVSConnectionManager::getSessionName()
+{
+ return sha1ToReadable(CertManager::getCertificate("manager").digest(QCryptographicHash::Sha1));
+}