summaryrefslogtreecommitdiffstats
path: root/src/net/pvsServiceDiscovery.cpp
diff options
context:
space:
mode:
authorSebastian2010-05-12 19:42:27 +0200
committerSebastian2010-05-12 19:42:27 +0200
commitce3329047d378a14006ce74ec273ac59e3375303 (patch)
tree782430f270b4c7aca1b35d5b7813518e3797c555 /src/net/pvsServiceDiscovery.cpp
downloadpvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.gz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.tar.xz
pvs-ce3329047d378a14006ce74ec273ac59e3375303.zip
initial import of latest svn version
Diffstat (limited to 'src/net/pvsServiceDiscovery.cpp')
-rw-r--r--src/net/pvsServiceDiscovery.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/net/pvsServiceDiscovery.cpp b/src/net/pvsServiceDiscovery.cpp
new file mode 100644
index 0000000..0a99802
--- /dev/null
+++ b/src/net/pvsServiceDiscovery.cpp
@@ -0,0 +1,181 @@
+/*
+# 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/net/pvsServiceDiscovery.cpp
+# - handle console broadcasts, tell client to connect on match
+# -----------------------------------------------------------------------------
+*/
+
+#include <QtCore/QHash>
+#include "src/pvs.h"
+#include "pvsServiceDiscovery.h"
+#include "pvsDiscoveredServer.h"
+#include "src/setup.h"
+#include "src/util/serviceDiscoveryUtil.h"
+#include <cassert>
+
+
+
+PVSServiceDiscovery::PVSServiceDiscovery(PVS* client)
+{
+ assert(client);
+ bool ret = _sock.bind(SD_PORT_CLIENT);
+ if (!ret)
+ {
+ printf("Could not open SERVICE DISCOVERY port\n");
+ exit(1);
+ }
+ connect(&_sock, SIGNAL(readyRead()), this, SLOT(sock_dataArrival()));
+ _currentServer = 0;
+ _last = QDateTime::currentDateTime();
+ _client = client;
+ _timerId = startTimer(10000);
+}
+
+PVSServiceDiscovery::~PVSServiceDiscovery()
+{
+ killTimer(_timerId);
+}
+
+void PVSServiceDiscovery::connectToSession(QString name, QString passwd)
+{
+ _sessionName = name;
+ _sessionPasswd = passwd;
+ if (name.length() == 0) return;
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ PVSDiscoveredServer *ds = *it;
+ if (ds->isValid() && ds->getName() == name)
+ {
+ _client->connectToHost(ds, _sessionPasswd);
+ }
+ }
+}
+
+void PVSServiceDiscovery::sock_dataArrival()
+{
+ int len;
+ while ((len = _sock.pendingDatagramSize()) > -1)
+ {
+ if (len == 0) continue;
+ char *data = new char[len];
+ QHostAddress host;
+ len = _sock.readDatagram(data, len, &host);
+ SdFields fields = parseSdFields((unsigned char*)data, len);
+ QDateTime now = QDateTime::currentDateTime();
+ if (fields.contains("hsh") && fields.contains("prt") && fields.contains("aut"))
+ {
+ if (fields["aut"] == "SHA1")
+ {
+ this->handleDiscovery(
+ host,
+ atoi(fields["prt"].toUtf8().data()),
+ QByteArray::fromBase64(fields["hsh"].toAscii())
+ );
+ }
+ }
+ /*
+ // DEBUG ONLY: connect to any host without matching the session name
+ if (_last.secsTo(now) > 9 && fields.contains("prt"))
+ {
+ _last = now;
+ int port = atoi(fields["prt"].toUtf8().data());
+ _client->connectToHost(host, QByteArray(), port);
+ }
+ // ^^^^^^^^^^
+ */
+ }
+}
+
+void PVSServiceDiscovery::handleDiscovery(QHostAddress host, int port, QByteArray hash)
+{
+ int numhosts = 0; ///< while iterating we count how many entries have the same host
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ if ((**it).hasHost(host))
+ {
+ ConsoleLog writeNetwork(host.toString() + " == " + (**it).getHost().toString());
+ if (++numhosts >= 5) return; // ddos through faked service broadcasts? ignore...
+ if ((**it).hasFingerprint(hash) && (**it).getPort() == port) // known entry...
+ {
+ if ((*it)->isValid() && (*it)->getName() == _sessionName && _sessionName.length() > 0)
+ {
+ ConsoleLog writeNetwork(QString("Connecting to ").append(_sessionName));
+ _client->connectToHost((*it), _sessionPasswd);
+ }
+ (**it).update(port);
+ return;
+ }
+ }
+ }
+ if (_servers.length() >= 30) return; // !?
+ QString oname = sha1ToReadable(hash);
+ QString name = oname;
+ int dup = 0;
+ while (nameExists(name))
+ {
+ name = "(" + QString::number(++dup) + ") " + oname;
+ }
+ PVSDiscoveredServer *ds = new PVSDiscoveredServer(this, host, port, hash, name);
+ connect(ds, SIGNAL(validated(PVSDiscoveredServer*)), this, SLOT(sendServerToGui(PVSDiscoveredServer*)));
+ _servers.push_back(ds);
+ setTimerInterval();
+}
+
+bool PVSServiceDiscovery::nameExists(QString name)
+{
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ if ((**it).getName() == name) return true;
+ }
+ return false;
+}
+
+QStringList PVSServiceDiscovery::getAllServers()
+{
+ QStringList hosts;
+ for (tServerList::iterator it = _servers.begin(); it != _servers.end(); it++)
+ {
+ if ((**it).isValid()) hosts.append((**it).getName());
+ }
+ return hosts;
+}
+
+void PVSServiceDiscovery::sendServerToGui(PVSDiscoveredServer* ds)
+{
+ _client->guiAddHost(ds->getName());
+}
+
+void PVSServiceDiscovery::timerEvent(QTimerEvent *event)
+{
+ if (_servers.size() == 0) return;
+ if (_currentServer >= _servers.size()) _currentServer = 0;
+ PVSDiscoveredServer *ds = _servers.at(_currentServer);
+ if (ds->getAge() >= SB_INTERVAL*2 + 1) // Entry too old?
+ {
+ disconnect(ds, SIGNAL(validated(PVSDiscoveredServer*)), this, SLOT(sendServerToGui(PVSDiscoveredServer*)));
+ _client->guiDelHost(ds->getName());
+ delete ds;
+ _servers.removeAt(_currentServer); // Clean it up
+ setTimerInterval();
+ }
+ else
+ {
+ ds->validateCertificate();
+ }
+ ++_currentServer;
+}
+
+void PVSServiceDiscovery::setTimerInterval()
+{
+ killTimer(_timerId);
+ _timerId = startTimer(10000 / (_servers.size() + 1));
+}