From 286af12dc1d96a1431c04a12989f3b80a4495e3b Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 May 2014 16:10:49 +0200 Subject: Add several documentation stubs. Remove autogenreated TODO --- src/server/net/discoverylistener.cpp | 54 +++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/server/net/discoverylistener.cpp b/src/server/net/discoverylistener.cpp index b308a09..f3d7d39 100644 --- a/src/server/net/discoverylistener.cpp +++ b/src/server/net/discoverylistener.cpp @@ -25,6 +25,33 @@ // +++ static ++++ hash ip address +++ + +/***************************************************************************//** + * @brief DiscoveryListener::DiscoveryListener + */ +DiscoveryListener::DiscoveryListener() : + _socket(this), _counterResetPos(0) +{ + if (!_socket.bind(SERVICE_DISCOVERY_PORT)) + qFatal("Could not bind to service discovery port %d", (int)SERVICE_DISCOVERY_PORT); + connect(&_socket, SIGNAL(readyRead()), this, SLOT(onReadyRead())); + for (int i = 0; i < SD_PACKET_TABLE_SIZE; ++i) + _packetCounter[i] = 0; + startTimer((SPAM_MODERATE_AT_ONCE * SPAM_MODERATE_INTERVAL) / SD_PACKET_TABLE_SIZE + 1); +} + +/***************************************************************************//** + * @brief DiscoveryListener::~DiscoveryListener + */ +DiscoveryListener::~DiscoveryListener() +{ +} + +/***************************************************************************//** + * @brief hash + * @param host + * @return + */ static quint16 hash(const QHostAddress& host) { static quint16 seed1 = 0, seed2 = 0; @@ -70,30 +97,13 @@ static quint16 hash(const QHostAddress& host) return result; } -// +++++++++++++++++++++++++++++++++++ - -DiscoveryListener::DiscoveryListener() : - _socket(this), _counterResetPos(0) -{ - if (!_socket.bind(SERVICE_DISCOVERY_PORT)) - qFatal("Could not bind to service discovery port %d", (int)SERVICE_DISCOVERY_PORT); - connect(&_socket, SIGNAL(readyRead()), this, SLOT(onReadyRead())); - for (int i = 0; i < SD_PACKET_TABLE_SIZE; ++i) - _packetCounter[i] = 0; - startTimer((SPAM_MODERATE_AT_ONCE * SPAM_MODERATE_INTERVAL) / SD_PACKET_TABLE_SIZE + 1); -} - -DiscoveryListener::~DiscoveryListener() -{ - // TODO Auto-generated destructor stub -} - /* * Overrides */ -/** - * Decrease packet counters per source IP in our "spam protection" table. +/***************************************************************************//** + * @brief Decrease packet counters per source IP in our "spam protection" table. + * @param event */ void DiscoveryListener::timerEvent(QTimerEvent* event) { @@ -112,8 +122,8 @@ void DiscoveryListener::timerEvent(QTimerEvent* event) * Slots */ -/** - * Incoming UDP packet on service discovery port - handle. +/***************************************************************************//** + * @brief Incoming UDP packet on service discovery port - handle. */ void DiscoveryListener::onReadyRead() { -- cgit v1.2.3-55-g7522 From 4353ffbaf8df5c42076704dbc9b7656a8dd46627 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 May 2014 16:15:36 +0200 Subject: Add several documentation stubs. Remove autogenreated TODO --- src/client/vnc/vncserver.cpp | 70 ++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/src/client/vnc/vncserver.cpp b/src/client/vnc/vncserver.cpp index 2b341fb..77beda2 100644 --- a/src/client/vnc/vncserver.cpp +++ b/src/client/vnc/vncserver.cpp @@ -12,12 +12,12 @@ #include "vncserver.h" #include "../util/util.h" -/******************************************* - * STATIC - *******************************************/ - VncServer* VncServer::me = NULL; +/***************************************************************************//** + * @brief VncServer::instance + * @return + */ VncServer* VncServer::instance() { if (me == NULL) @@ -25,7 +25,11 @@ VncServer* VncServer::instance() return me; } -// +/***************************************************************************//** + * @brief makePassword + * @param len + * @return + */ static QString makePassword(int len = 10) { char pass[len]; @@ -34,27 +38,27 @@ static QString makePassword(int len = 10) return QString::fromUtf8(pass, len); } -// Ugly hack to get an el-cheapo platform independent sleep +/***************************************************************************//** + * @brief Ugly hack to get an el-cheapo platform independent sleep + */ struct Sleeper : public QThread { -static void msleep(unsigned long msecs) { QThread::msleep(msecs); } + static void msleep(unsigned long msecs) { QThread::msleep(msecs); } }; -/******************************************* - * INSTANCE - *******************************************/ - -VncServer::VncServer() : - _process(NULL), _port(0), _timerId(0) -{ - // TODO Auto-generated constructor stub -} +/***************************************************************************//** + * @brief VncServer::VncServer + */ +VncServer::VncServer() : _process(NULL), _port(0), _timerId(0){} -VncServer::~VncServer() -{ - // TODO Auto-generated destructor stub -} +/***************************************************************************//** + * @brief VncServer::~VncServer + */ +VncServer::~VncServer(){} +/***************************************************************************//** + * @brief VncServer::start + */ void VncServer::start() { // Keep things clean @@ -117,6 +121,9 @@ void VncServer::start() _process->start("x11vnc", args, QIODevice::ReadOnly); } +/***************************************************************************//** + * @brief VncServer::stop + */ void VncServer::stop() { if (_timerId != 0) @@ -142,13 +149,16 @@ void VncServer::stop() process->deleteLater(); } + /* * Overrides */ -/** - * Timer event, currently only used to assume VNC server setup failed + +/***************************************************************************//** + * @brief Timer event, currently only used to assume VNC server setup failed * after 3 seconds... + * @param event */ void VncServer::timerEvent(QTimerEvent *event) { @@ -157,10 +167,15 @@ void VncServer::timerEvent(QTimerEvent *event) emit started(0, _ropass, _rwpass); } + /* * Slots */ + +/***************************************************************************//** + * @brief VncServer::onStdOut + */ void VncServer::onStdOut() { if (_process == NULL) @@ -188,6 +203,9 @@ void VncServer::onStdOut() } } +/***************************************************************************//** + * @brief VncServer::onStdErr + */ void VncServer::onStdErr() { if (_process == NULL) @@ -198,12 +216,20 @@ void VncServer::onStdErr() QByteArray data(_process->readAllStandardError()); } +/***************************************************************************//** + * @brief VncServer::onError + * @param error + */ void VncServer::onError(QProcess::ProcessError error) { this->stop(); emit started(0, _ropass, _rwpass); } +/***************************************************************************//** + * @brief VncServer::onFinished + * @param exitCode + */ void VncServer::onFinished(int exitCode) { this->stop(); -- cgit v1.2.3-55-g7522 From 35cb7fbc69cd0233ea5cb43405082119aa21d6b4 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Tue, 27 May 2014 16:17:37 +0200 Subject: Remove TODO. User get visual feedback via cam icon. --- src/server/net/client.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/net/client.cpp b/src/server/net/client.cpp index abd739d..4adcf01 100644 --- a/src/server/net/client.cpp +++ b/src/server/net/client.cpp @@ -169,7 +169,6 @@ void Client::handleMsg() if (_vncPort <= 0) { qDebug() << "Starting VNC server on client" << _name << " (" << _socket->peerAddress().toString()+_vncPort << ") failed."; - // TODO: Show message on manager } else { -- cgit v1.2.3-55-g7522 From afc69ca4ffb0e11d9d06b8ddd31ee40963f86f17 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 28 May 2014 00:37:28 +0200 Subject: Outsource serverDiscovery. --- src/client/connectwindow/connectwindow.cpp | 233 +++++++++-------------------- src/client/connectwindow/connectwindow.h | 53 +++---- src/client/net/serverdiscovery.cpp | 181 ++++++++++++++++++++++ src/client/net/serverdiscovery.h | 51 +++++++ src/client/toolbar/toolbar.cpp | 4 +- 5 files changed, 324 insertions(+), 198 deletions(-) create mode 100644 src/client/net/serverdiscovery.cpp create mode 100644 src/client/net/serverdiscovery.h diff --git a/src/client/connectwindow/connectwindow.cpp b/src/client/connectwindow/connectwindow.cpp index c8f7efd..34087ad 100644 --- a/src/client/connectwindow/connectwindow.cpp +++ b/src/client/connectwindow/connectwindow.cpp @@ -16,16 +16,19 @@ #define UDPBUFSIZ 9000 #define SALT_LEN 18 -/** +/***************************************************************************//** * Initialize Connection Window. * @param parent */ -ConnectWindow::ConnectWindow(QWidget *parent) : - QWidget(parent), _ui(new Ui::ConnectWindow), _connected(false), - _timerDiscover(0), _timerHide(0), _connection(NULL), _state(Idle), - _hashErrorCount(0), _hashSslErrorCount(0), _certErrorCount(0), - _ipErrorCount(0), _discoveryInterval(800) -{ +ConnectWindow::ConnectWindow(QWidget *parent) : QWidget(parent) +{ + _ui = new Ui::ConnectWindow; + _connected = false; + _timerHide = 0; + _connection = NULL; + _state = Idle; + _hashSslErrorCount = 0; + // Initialize the GUI _ui->setupUi(this); @@ -39,53 +42,21 @@ ConnectWindow::ConnectWindow(QWidget *parent) : connect(_ui->btn_connection, SIGNAL(clicked()), this, SLOT(onBtnConnection())); connect(_ui->btn_hide, SIGNAL(clicked()), this, SLOT(onBtnHide())); - int tries = 10; - while (tries-- != 0) - { - const quint16 port = (quint16)(qrand() % 10000) + 10000; - if (_discoverySocket.bind(QHostAddress::Any, port)) - break; - if (tries == 0) - qFatal("Could not bind to any UDP port for server discovery."); - } - connect(&_discoverySocket, SIGNAL(readyRead()), this, SLOT(onUdpReadyRead())); - this->setState(Idle); -} - -ConnectWindow::~ConnectWindow(){} + // React on discovery signal + connect(&_serverDiscovery, SIGNAL(serverDetected(QString,quint16,QByteArray,QByteArray)), + this, SLOT(onServerDetected(QString,quint16,QByteArray,QByteArray))); -/** - * Set Client as Connected (true) or Disconnected (false). - * After settings updateState() is called. - * @param connected - */ -void ConnectWindow::setConnected(const bool connected) -{ - _connected = connected; this->updateState(); - if (_state == Scanning) - { - killTimer(_timerDiscover); - _discoveryInterval = 1000; - _timerDiscover = startTimer(_discoveryInterval); - } } -/** - * Set current state of Client. - * After setting state updateState() is called. - * @param state +/***************************************************************************//** + * @brief ConnectWindow::~ConnectWindow */ -void ConnectWindow::setState(const ConnectionState state) -{ - if (_state != state) - { - _state = state; - this->updateState(); - } -} +ConnectWindow::~ConnectWindow(){} + -/** + +/***************************************************************************//** * Handle changes in state and update window. * Also changing TextLabel which shows the user what the program is doing. */ @@ -115,7 +86,6 @@ void ConnectWindow::updateState() break; case Scanning: _ui->lblStatus->setText(tr("Scanning for session %1.").arg(_ui->lineEditName->text())); - _timerDiscover = startTimer(_discoveryInterval); break; case Connecting: _ui->lblStatus->setText(tr("Found session, connecting...")); @@ -132,12 +102,11 @@ void ConnectWindow::updateState() case Connected: _ui->lblStatus->setText(tr("Connection established!")); break; - case InvalidIpList: - case InvalidHash: case InvalidCert: + _ui->lblStatus->setText(tr("Invalid certificate.")); + break; case InvalidSslHash: - _ui->lblStatus->setText(tr("Invalid hash: %1; invalid cert: %2; invalid iplist: %3; invalid sslhash: %4") - .arg(_hashErrorCount).arg(_certErrorCount).arg(_ipErrorCount).arg(_hashSslErrorCount)); + _ui->lblStatus->setText(tr("Invalid Ssl hash: %1.").arg(_hashSslErrorCount)); break; } } @@ -146,57 +115,13 @@ void ConnectWindow::updateState() * Overrides */ -/** +/***************************************************************************//** * Called when a Qt timer fires; used for server discovery and * auto-hiding the connect dialog. */ void ConnectWindow::timerEvent(QTimerEvent* event) { - if (event->timerId() == _timerDiscover) - { - killTimer(_timerDiscover); - if (_connected || _state != Scanning) // Not scanning, bail out - return; - if (_discoveryInterval < 30000) - _discoveryInterval += 100; - _timerDiscover = startTimer(_discoveryInterval); - // Don't send packet if we're trying to connect - if (_connection != NULL) - return; - // Send discovery - _packet.reset(); - QByteArray iplist(Network::interfaceAddressesToString().toUtf8()); - QByteArray salt1(SALT_LEN, 0); - if (_salt2.size() < SALT_LEN) - _salt2.resize(SALT_LEN); - for (int i = 0; i < SALT_LEN; ++i) - { - salt1[i] = qrand() & 0xff; - _salt2[i] = qrand() & 0xff; - } - _packet.reset(); - _packet.setField(_HASH, genSha1(&_sessionNameBytes, &salt1, &iplist)); - _packet.setField(_SALT1, salt1); - _packet.setField(_SALT2, _salt2); - _packet.setField(_IPLIST, iplist); - foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) - { - foreach (QNetworkAddressEntry entry, interface.addressEntries()) - { - if (!entry.broadcast().isNull() && entry.ip() != QHostAddress::LocalHost && entry.ip() != QHostAddress::LocalHostIPv6) - { - qDebug() << "Broadcasting to " << entry.broadcast().toString(); - if (!_packet.writeMessage(&_discoverySocket, entry.broadcast(), SERVICE_DISCOVERY_PORT)) - qDebug("FAILED"); - } - } - } - qDebug("Broadcasting to 255.255.255.255"); - if (!_packet.writeMessage(&_discoverySocket, QHostAddress::Broadcast, SERVICE_DISCOVERY_PORT)) - qDebug("FAILED"); - // End send discovery - } - else if(event->timerId() == _timerHide) + if(event->timerId() == _timerHide) { killTimer(_timerHide); _timerHide = 0; @@ -204,11 +129,11 @@ void ConnectWindow::timerEvent(QTimerEvent* event) _ui->stackedWidget->setCurrentIndex(0); } else - // Unknown/Old timer id, kill it + // Unknown/Old timer id, kill it ??? PALM -> FACE killTimer(event->timerId()); } -/** +/***************************************************************************//** * Handle incoming closeEvent and hide window. * @param e */ @@ -218,7 +143,7 @@ void ConnectWindow::closeEvent(QCloseEvent *e) this->hide(); } -/** +/***************************************************************************//** * Gives the keyboard input focus to the input line. * @param event */ @@ -227,7 +152,7 @@ void ConnectWindow::showEvent(QShowEvent* event) _ui->lineEditName->setFocus(); } -/** +/***************************************************************************//** * Public function connect to session. * Check if currently connected to server, * if not --> connect to given sessionName. @@ -237,19 +162,16 @@ void ConnectWindow::connectToSession(const QByteArray sessionName) { if (_connected || _state != Idle) return; - - _discoveryInterval = 800; - _sessionNameBytes = sessionName; - _timerDiscover = startTimer(_discoveryInterval); - _hashErrorCount = _hashSslErrorCount = _certErrorCount = _ipErrorCount = 0; - this->setState(Scanning); + _state = Scanning; + this->updateState(); + _serverDiscovery.start(_ui->lineEditName->text().toUtf8()); } /* * Slots */ -/** +/***************************************************************************//** * Handle click on Connect/Disconnect button. * If already connected --> Stop/disconnect. * Else scanning for given sessionId. @@ -258,17 +180,19 @@ void ConnectWindow::onBtnConnection() { if (_timerHide){ killTimer(_timerHide); + _timerHide = 0; _ui->stackedWidget->setCurrentIndex(0); } - _timerHide = 0; - if (_timerDiscover) - killTimer(_timerDiscover); + + if (_serverDiscovery.isActive()) + _serverDiscovery.stop(); + if (_connected || _state != Idle) { // Stop or disconnect - _timerDiscover = 0; emit disconnect(); - this->setState(Idle); + _state = Idle; + this->updateState(); } else { @@ -277,7 +201,7 @@ void ConnectWindow::onBtnConnection() } } -/** +/***************************************************************************//** * Handle click on Cancel/Hide Button. * Just hide the window. */ @@ -286,53 +210,24 @@ void ConnectWindow::onBtnHide() this->hide(); } -/** - * Handle incoming service discovery packets. + +/***************************************************************************//** + * @brief ConnectWindow::onServerDetected + * @param host + * @param port + * @param sessionName + * @param certHash */ -void ConnectWindow::onUdpReadyRead() +void ConnectWindow::onServerDetected(const QString& host, const quint16 port, const QByteArray& sessionName, const QByteArray& certHash) { - char data[UDPBUFSIZ]; - QHostAddress addr; - quint16 port; - while (_discoverySocket.hasPendingDatagrams()) - { - const qint64 size = _discoverySocket.readDatagram(data, UDPBUFSIZ, &addr, &port); - if (size <= 0 || _connection != NULL) - continue; - - _packet.reset(); - if (!_packet.readMessage(data, (quint32)size)) - continue; - // Valid packet, process it: - const QByteArray hash(_packet.getFieldBytes(_HASH)); - const QByteArray iplist(_packet.getFieldBytes(_IPLIST)); - const QByteArray port(_packet.getFieldBytes(_PORT)); - const QByteArray cert(_packet.getFieldBytes(_CERT)); - // Check if the source IP of the packet matches any of the addresses given in the IP list - if (!Network::isAddressInList(QString::fromUtf8(iplist), addr.toString())) - { - ++_ipErrorCount; - this->setState(InvalidIpList); - this->setState(Scanning); - continue; - } - // If so, check if the submitted hash seems valid - if (genSha1(&_sessionNameBytes, &_salt2, &iplist, &port, &cert) != hash) - { - // did not match local session name, or other data was spoofed - ++_hashErrorCount; - this->setState(InvalidHash); - this->setState(Scanning); - continue; - } - // Otherwise it's a valid reply, try to connect - _connection = new ServerConnection(addr.toString(), (quint16)QString::fromUtf8(port).toInt(), _sessionNameBytes, cert); - connect(_connection, SIGNAL(stateChange(ConnectWindow::ConnectionState)), this, SLOT(onConnectionStateChange(ConnectWindow::ConnectionState))); - connect(_connection, SIGNAL(destroyed(QObject*)), this, SLOT(onConnectionClosed(QObject*))); - } + _connection = new ServerConnection(host, port, sessionName, certHash); + connect(_connection, SIGNAL(stateChange(ConnectWindow::ConnectionState)), this, SLOT(onConnectionStateChange(ConnectWindow::ConnectionState))); + connect(_connection, SIGNAL(destroyed(QObject*)), this, SLOT(onConnectionClosed(QObject*))); + connect(_connection, SIGNAL(disconnected()), this, SLOT(onConnectionDisconnected())); } -/** + +/***************************************************************************//** * Handle connection state changes and update member variables describing state. * @param state */ @@ -341,7 +236,10 @@ void ConnectWindow::onConnectionStateChange(ConnectWindow::ConnectionState state bool reset = (_state == Scanning); if (state == InvalidSslHash) ++_hashSslErrorCount; - this->setState(state); + + _state = state; + this->updateState(); + if (reset) _state = Scanning; if (state == Connected) @@ -349,12 +247,16 @@ void ConnectWindow::onConnectionStateChange(ConnectWindow::ConnectionState state QObject::disconnect(_connection, SIGNAL(stateChange(ConnectWindow::ConnectionState)), this, SLOT(onConnectionStateChange(ConnectWindow::ConnectionState))); QObject::disconnect(_connection, SIGNAL(destroyed(QObject*)), this, SLOT(onConnectionClosed(QObject*))); emit connected(_connection); + + _connected = true; + this->updateState(); + _connection = NULL; _timerHide = startTimer(2000); } } -/** +/***************************************************************************//** * If connection is closed set _connection = NULL. * @param connection */ @@ -362,3 +264,12 @@ void ConnectWindow::onConnectionClosed(QObject* connection) { _connection = NULL; } + +/***************************************************************************//** + * @brief ConnectWindow::onConnectionDisconnected + */ +void ConnectWindow::onConnectionDisconnected() +{ + _connected = false; + this->updateState(); +} diff --git a/src/client/connectwindow/connectwindow.h b/src/client/connectwindow/connectwindow.h index 9319e45..39eac86 100644 --- a/src/client/connectwindow/connectwindow.h +++ b/src/client/connectwindow/connectwindow.h @@ -20,6 +20,7 @@ #include #include #include "../../shared/networkmessage.h" +#include "../net/serverdiscovery.h" namespace Ui{ class ConnectWindow; @@ -38,54 +39,37 @@ class ConnectWindow : public QWidget Q_OBJECT public: - enum ConnectionState - { + enum ConnectionState { Idle, Scanning, Connecting, AwaitingChallenge, AwaitingChallengeResponse, LoggingIn, - InvalidIpList, - InvalidHash, // Hash of UDP reply invalid InvalidSslHash, // Hash of challenge inside SSL connection invalid InvalidCert, Connected }; -private: - Ui::ConnectWindow *_ui; - - bool _connected; - int _timerDiscover, _timerHide; - ServerConnection *_connection; - ConnectionState _state; - int _hashErrorCount, _hashSslErrorCount, _certErrorCount, _ipErrorCount; - int _discoveryInterval; - - QByteArray _sessionNameBytes; - QByteArray _salt2; - QUdpSocket _discoverySocket; - NetworkMessage _packet; - - void setState(const ConnectionState state); - void updateState(); - -public: explicit ConnectWindow(QWidget *parent = NULL); virtual ~ConnectWindow(); - void setConnected(const bool connected); void connectToSession(const QByteArray sessionName); +private: + Ui::ConnectWindow *_ui; + ServerConnection *_connection; + int _hashSslErrorCount; + ServerDiscovery _serverDiscovery; + ConnectionState _state; + QByteArray _sessionNameBytes; + NetworkMessage _packet; + bool _connected; + int _timerHide; + + void updateState(); + protected: - /* - void enterEvent(QEvent *e); - void leaveEvent(QEvent *e); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - */ void timerEvent(QTimerEvent* event); void closeEvent(QCloseEvent *e); void showEvent(QShowEvent* event); @@ -93,15 +77,16 @@ protected: protected slots: void onBtnConnection(); void onBtnHide(); - void onUdpReadyRead(); + void onConnectionStateChange(ConnectWindow::ConnectionState state); void onConnectionClosed(QObject* connection); - //void onSsl + void onConnectionDisconnected(); + // void onUdpReadyRead(); + void onServerDetected(const QString& host, const quint16 port, const QByteArray& sessionName, const QByteArray& certHash); signals: void disconnect(); void connected(ServerConnection* connection); - }; #endif diff --git a/src/client/net/serverdiscovery.cpp b/src/client/net/serverdiscovery.cpp new file mode 100644 index 0000000..9f1991c --- /dev/null +++ b/src/client/net/serverdiscovery.cpp @@ -0,0 +1,181 @@ + +#include +#include "../../shared/settings.h" +#include "../../shared/network.h" +#include "../../shared/util.h" +#include "serverdiscovery.h" +#include + + +/***************************************************************************//** + * Ctor + */ +ServerDiscovery::ServerDiscovery(QObject *parent) : QObject(parent) +{ + _hashErrorCount = 0; + _ipErrorCount = 0; + + /* Try to get a UDP port for server discovery */ + int tries = 10; + while (tries-- != 0) + { + const quint16 port = (quint16)(qrand() % 10000) + 10000; + if (_discoverySocket.bind(QHostAddress::Any, port)) + break; + if (tries == 0) + qFatal("Could not bind to any UDP port for server discovery."); + } + // Handle incoming messages + connect(&_discoverySocket, SIGNAL(readyRead()), this, SLOT(onUdpReadyRead())); + + /* Setup the discovery timer */ + _discoveryTimer.setInterval(500); + _discoveryTimer.setSingleShot(true); + // + connect(&_discoveryTimer, SIGNAL(timeout()), this, SLOT(doDiscovery())); +} + +/***************************************************************************//** + * Dtor + */ +ServerDiscovery::~ServerDiscovery() +{ +} + +/***************************************************************************//** + * @brief start + */ +void ServerDiscovery::start(const QByteArray& sessionName) +{ + assert(!this->isActive()); + + // Set the session which is searched + _nameBytes = sessionName; + + // Enable signal emittance + this->blockSignals(false); + + // Reset the error counters + _hashErrorCount = _ipErrorCount = 0; + + // reset anbd start the discovery timer + _discoveryTimer.setInterval(500); + _discoveryTimer.start(); +} + +/***************************************************************************//** + * @brief stop + */ +void ServerDiscovery::stop() +{ + assert(this->isActive()); + + //Bock further signal emittance + this->blockSignals(true); + _discoveryTimer.stop(); +} + +/******************************************************************************* + * SLOTS + ***************************************************************************//** + * @brief ConnectWindow::doDiscovery + */ +void ServerDiscovery::doDiscovery() +{ + // Send discovery + _packet.reset(); + QByteArray iplist(Network::interfaceAddressesToString().toUtf8()); + // qDebug + QByteArray salt1(SALT_LEN, 0); + if (_salt2.size() < SALT_LEN) + _salt2.resize(SALT_LEN); + for (int i = 0; i < SALT_LEN; ++i) { + salt1[i] = qrand() & 0xff; + _salt2[i] = qrand() & 0xff; + } + _packet.reset(); + _packet.setField(_HASH, genSha1(&_nameBytes, &salt1, &iplist)); + _packet.setField(_SALT1, salt1); + _packet.setField(_SALT2, _salt2); + _packet.setField(_IPLIST, iplist); + foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) + { + foreach (QNetworkAddressEntry entry, interface.addressEntries()) + { + if (!entry.broadcast().isNull() && entry.ip() != QHostAddress::LocalHost && entry.ip() != QHostAddress::LocalHostIPv6) + { + qDebug() << "Broadcasting to " << entry.broadcast().toString(); + if (!_packet.writeMessage(&_discoverySocket, entry.broadcast(), SERVICE_DISCOVERY_PORT)) + qDebug("FAILED"); + } + } + } + qDebug("Broadcasting to 255.255.255.255"); + if (!_packet.writeMessage(&_discoverySocket, QHostAddress::Broadcast, SERVICE_DISCOVERY_PORT)) + qDebug("FAILED"); + + // Start the timer again with a larger interval + if (_discoveryTimer.interval() < 5000) + _discoveryTimer.setInterval(_discoveryTimer.interval() * 2); + _discoveryTimer.start(); +} + + +/***************************************************************************//** + * Handle incoming service discovery packets. + */ +void ServerDiscovery::onUdpReadyRead() +{ + char data[UDPBUFSIZ]; + QHostAddress addr; + quint16 port; + while (_discoverySocket.hasPendingDatagrams()) + { + // Discard any packets if discovery is stopped + if (!this->isActive()){ + _discoverySocket.readDatagram(NULL, 0); + continue; + } + + const qint64 size = _discoverySocket.readDatagram(data, UDPBUFSIZ, &addr, &port); + if (size <= 0) //|| _connection != NULL) // TODO CHECK + continue; + + _packet.reset(); + if (!_packet.readMessage(data, (quint32)size)) + continue; + + // Valid packet, process it: + const QByteArray hash(_packet.getFieldBytes(_HASH)); + const QByteArray iplist(_packet.getFieldBytes(_IPLIST)); + const QByteArray port(_packet.getFieldBytes(_PORT)); + const QByteArray cert(_packet.getFieldBytes(_CERT)); + + // Check if the source IP of the packet matches any of the addresses given in the IP list + if (!Network::isAddressInList(QString::fromUtf8(iplist), addr.toString())) + { + ++_ipErrorCount; + emit error(ErrorType::InvalidIpList, _hashErrorCount); + continue; + } + + // If so, check if the submitted hash seems valid + if (genSha1(&_nameBytes, &_salt2, &iplist, &port, &cert) != hash) + { + // did not match local session name, or other data was spoofed + ++_hashErrorCount; + emit error(ErrorType::InvalidHash, _ipErrorCount); + continue; + } + + /* Otherwise it's a valid reply */ + qDebug() << "Server detected:" + << addr.toString() + ":" + QString::fromUtf8(port) + "/" + _nameBytes; + + // Tell that a server hs been found + emit serverDetected(addr.toString(), (quint16)QString::fromUtf8(port).toInt(), _nameBytes, cert); + + // Stop the discovery + this->stop(); + } +} diff --git a/src/client/net/serverdiscovery.h b/src/client/net/serverdiscovery.h new file mode 100644 index 0000000..093b841 --- /dev/null +++ b/src/client/net/serverdiscovery.h @@ -0,0 +1,51 @@ +#ifndef SERVERDISCOVERY_H +#define SERVERDISCOVERY_H + +#include +#include +#include +#include "../../shared/networkmessage.h" + +class ServerDiscovery : public QObject +{ + Q_OBJECT + + public: + enum class ErrorType{ + InvalidIpList, + InvalidHash + }; + + explicit ServerDiscovery(QObject *parent = 0); + ~ServerDiscovery(); + + void start(const QByteArray& sessionName); + void stop(); + inline bool isActive(){ return _discoveryTimer.isActive(); } + + private: + QTimer _discoveryTimer; + int _hashErrorCount; + int _ipErrorCount; + QByteArray _nameBytes; + QByteArray _salt2; + QUdpSocket _discoverySocket; + NetworkMessage _packet; + + static const int UDPBUFSIZ = 9000; + static const int SALT_LEN = 18; + +public: + signals: + void serverDetected(const QString& host, const quint16 port, const QByteArray& sessionName, const QByteArray& certHash); + void error(ErrorType e, int count); + + public slots: + + private slots: + void doDiscovery(); + void onUdpReadyRead(); + +}; + +#endif // SERVERDISCOVERY_H diff --git a/src/client/toolbar/toolbar.cpp b/src/client/toolbar/toolbar.cpp index 88d4b2a..9bc5998 100644 --- a/src/client/toolbar/toolbar.cpp +++ b/src/client/toolbar/toolbar.cpp @@ -174,8 +174,7 @@ void Toolbar::onVncServerIsRunning(int port) */ void Toolbar::onDisconnected() { - _connectWindow->setConnected(false); - if (_connection != NULL) + if (_connection != NULL) _connection->blockSignals(true); _connection = NULL; _ui->lblStatus->setStyleSheet("color:red"); @@ -205,7 +204,6 @@ void Toolbar::onConnected(ServerConnection* connection) _vnc, SLOT(open(const QString&, int, const QString&, bool, bool, const QString&, const int))); connect(_connection, SIGNAL(closeVnc()), _vnc, SLOT(close())); connect(_vnc, SIGNAL(running(const bool, const int)), _connection, SLOT(onVncViewerStartStop(const bool, const int))); - _connectWindow->setConnected(true); } /***************************************************************************//** -- cgit v1.2.3-55-g7522 From c9e1030d103e96ac3485cc16f9bb977c05d06726 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 28 May 2014 17:20:31 +0200 Subject: Increase timeout for debugging --- src/server/net/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/net/client.cpp b/src/server/net/client.cpp index 4adcf01..135157c 100644 --- a/src/server/net/client.cpp +++ b/src/server/net/client.cpp @@ -46,8 +46,8 @@ Client::Client(QSslSocket* socket) : _socket(socket) msgChlng.setField(_CHALLENGE, _challenge); msgChlng.writeMessage(_socket); // give client 3 seconds to complete handshake - _timerIdAuthTimeout = startTimer(3000); - _timerPingTimeout = startTimer(600000); // for debugging purposes 10min + _timerIdAuthTimeout = startTimer(600000);// TODO undo, for debugging purposes 10min + _timerPingTimeout = startTimer(600000); // TODO undo, for debugging purposes 10min _pingTimeout = QDateTime::currentMSecsSinceEpoch() + PING_TIMEOUT_MS; } -- cgit v1.2.3-55-g7522 From 11e18ee79b54cb2bd9d95af785be3270931ff0d9 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 28 May 2014 17:22:14 +0200 Subject: Try to reconnect if the pvsmgr gets disconnected --- src/client/connectwindow/connectwindow.cpp | 12 ++++++++++-- src/client/connectwindow/connectwindow.h | 2 +- src/client/net/serverdiscovery.cpp | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/client/connectwindow/connectwindow.cpp b/src/client/connectwindow/connectwindow.cpp index 34087ad..7f24281 100644 --- a/src/client/connectwindow/connectwindow.cpp +++ b/src/client/connectwindow/connectwindow.cpp @@ -164,7 +164,7 @@ void ConnectWindow::connectToSession(const QByteArray sessionName) return; _state = Scanning; this->updateState(); - _serverDiscovery.start(_ui->lineEditName->text().toUtf8()); + _serverDiscovery.start(sessionName); } /* @@ -189,6 +189,7 @@ void ConnectWindow::onBtnConnection() if (_connected || _state != Idle) { + _tryReconnect = false; // Stop or disconnect emit disconnect(); _state = Idle; @@ -197,6 +198,7 @@ void ConnectWindow::onBtnConnection() else { // Connect (scan for session) + _tryReconnect = true; connectToSession(_ui->lineEditName->text().toUtf8()); } } @@ -233,6 +235,7 @@ void ConnectWindow::onServerDetected(const QString& host, const quint16 port, co */ void ConnectWindow::onConnectionStateChange(ConnectWindow::ConnectionState state) { + qDebug() << "STATE!"<< state; bool reset = (_state == Scanning); if (state == InvalidSslHash) ++_hashSslErrorCount; @@ -240,8 +243,10 @@ void ConnectWindow::onConnectionStateChange(ConnectWindow::ConnectionState state _state = state; this->updateState(); - if (reset) + if (reset) { + qDebug() << "RESET!!"<< state; _state = Scanning; + } if (state == Connected) { QObject::disconnect(_connection, SIGNAL(stateChange(ConnectWindow::ConnectionState)), this, SLOT(onConnectionStateChange(ConnectWindow::ConnectionState))); @@ -271,5 +276,8 @@ void ConnectWindow::onConnectionClosed(QObject* connection) void ConnectWindow::onConnectionDisconnected() { _connected = false; + _state = Idle; this->updateState(); + if (_tryReconnect) + connectToSession(_ui->lineEditName->text().toUtf8()); } diff --git a/src/client/connectwindow/connectwindow.h b/src/client/connectwindow/connectwindow.h index 39eac86..df112fe 100644 --- a/src/client/connectwindow/connectwindow.h +++ b/src/client/connectwindow/connectwindow.h @@ -64,7 +64,7 @@ private: ConnectionState _state; QByteArray _sessionNameBytes; NetworkMessage _packet; - bool _connected; + bool _connected, _tryReconnect; int _timerHide; void updateState(); diff --git a/src/client/net/serverdiscovery.cpp b/src/client/net/serverdiscovery.cpp index 9f1991c..a4edb46 100644 --- a/src/client/net/serverdiscovery.cpp +++ b/src/client/net/serverdiscovery.cpp @@ -47,7 +47,7 @@ ServerDiscovery::~ServerDiscovery() */ void ServerDiscovery::start(const QByteArray& sessionName) { - assert(!this->isActive()); + //assert(!this->isActive()); // Set the session which is searched _nameBytes = sessionName; -- cgit v1.2.3-55-g7522 From 6b3a98ee512299fffe3b0c6cf12a43bcf37318a3 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 28 May 2014 17:27:04 +0200 Subject: Give Exclusive student to tutor correct funtion. Kill all projections on lock. --- src/server/mainwindow/mainwindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index 7279869..b25f416 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -594,7 +594,7 @@ void MainWindow::onButtonStudentToTutorExclusive() else if (_tutorFrame->client() == NULL) QMessageBox::critical(this, tr("Projection"), sStrTutorOffline); else - changeProjection(_tutorFrame->client(), Mode::LockedMulticast, _selectedFrame->client()); + changeProjection(_selectedFrame->client(), Mode::LockedMulticast, _tutorFrame->client()); } @@ -623,6 +623,9 @@ void MainWindow::onButtonStopProjection() */ void MainWindow::onButtonLock(bool checked) { + // Stop all projections + onButtonStopProjection(); + for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { // Check if client is Tutor or the manager is also running on this machine. -- cgit v1.2.3-55-g7522 From 92e7d3f1a52c4ba75ef93d88181ff6fa6f3d4e69 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 28 May 2014 17:44:35 +0200 Subject: Uncheck lock if any action is performed. --- src/server/mainwindow/mainwindow.cpp | 38 +++++++++++++++++++++++++++--------- src/server/mainwindow/mainwindow.h | 1 + 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index b25f416..6afa608 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -349,6 +349,20 @@ void MainWindow::mouseReleaseEvent(QMouseEvent* e) } } +/***************************************************************************//** + * @brief reset + */ +void MainWindow::reset() +{ + // Unlock all clients + for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + if ((*it)->client() != NULL) + (*it)->client()->lockScreen(false); + + // Stop server (Clients get stopped on ACK) + if (_streamingSource != NULL) + _streamingSource->stopVncServer(); +} /* * Slots @@ -514,6 +528,8 @@ void MainWindow::onButtonHelp() */ void MainWindow::onButtonTutorToAll() { + ui->action_Lock->setChecked(false); + if (_tutorFrame == NULL) QMessageBox::critical(this, tr("Projection"), sStrTutorNdef); else if (_tutorFrame->client() == NULL) @@ -529,6 +545,8 @@ void MainWindow::onButtonTutorToAll() */ void MainWindow::onButtonStudentToAll() { + ui->action_Lock->setChecked(false); + if (_selectedFrame == NULL) QMessageBox::critical(this, tr("Projection"), sStrSourceNdef); if (_selectedFrame->client() == NULL) @@ -543,6 +561,8 @@ void MainWindow::onButtonStudentToAll() */ void MainWindow::onButtonTutorToStudent() { + ui->action_Lock->setChecked(false); + if (_selectedFrame == NULL) QMessageBox::critical(this, tr("Projection"), sStrDestNdef); else if (_tutorFrame == NULL) @@ -563,6 +583,8 @@ void MainWindow::onButtonTutorToStudent() */ void MainWindow::onButtonStudentToTutor() { + ui->action_Lock->setChecked(false); + if (_selectedFrame == NULL) QMessageBox::critical(this, tr("Projection"), sStrSourceNdef); else if (_tutorFrame == NULL) @@ -583,6 +605,8 @@ void MainWindow::onButtonStudentToTutor() */ void MainWindow::onButtonStudentToTutorExclusive() { + ui->action_Lock->setChecked(false); + if (_selectedFrame == NULL) QMessageBox::critical(this, tr("Projection"), sStrSourceNdef); else if (_tutorFrame == NULL) @@ -605,14 +629,8 @@ void MainWindow::onButtonStudentToTutorExclusive() */ void MainWindow::onButtonStopProjection() { - // Unlock all clients - for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) - if ((*it)->client() != NULL) - (*it)->client()->lockScreen(false); - - // Stop server (Clients get stopped on ACK) - if (_streamingSource != NULL) - _streamingSource->startVncServer(); + ui->action_Lock->setChecked(false); + reset(); } /***************************************************************************//** @@ -624,7 +642,7 @@ void MainWindow::onButtonStopProjection() void MainWindow::onButtonLock(bool checked) { // Stop all projections - onButtonStopProjection(); + reset(); for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) { @@ -656,6 +674,8 @@ void MainWindow::onButtonExit() */ void MainWindow::onButtonSetAsTutor() { + ui->action_Lock->setChecked(false); + // If no frame is selected, warning. if (_selectedFrame == NULL) { diff --git a/src/server/mainwindow/mainwindow.h b/src/server/mainwindow/mainwindow.h index 25eb9aa..89361c9 100644 --- a/src/server/mainwindow/mainwindow.h +++ b/src/server/mainwindow/mainwindow.h @@ -78,6 +78,7 @@ private: bool isValidClient(Client* client); void changeProjection(Client *from, Mode mode = Mode::Broadcast, Client *to = NULL); void tellClientCurrentSituation(Client* client); + void reset(); void closeEvent(QCloseEvent *e); void changeEvent(QEvent *e); -- cgit v1.2.3-55-g7522