From bc83b49dc11afffeb2e3267b756fe91bb195f023 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 23 Apr 2014 18:04:42 +0200 Subject: [SERVER] Fixed tracking of which clients is watching (trying to watch) which other client --- src/server/mainwindow/mainwindow.cpp | 15 +++++++++++++-- src/server/net/client.cpp | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index e3b7952..7543004 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -398,6 +398,15 @@ void MainWindow::prepareForProjection(Client * const from, Client * const to) qDebug("One to many requested..."); from->setProjectionSource(true); + // Set desired projection source on all clients + for (QList::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + { + Client *c = (**it).client(); + if (c == NULL || c->id() == from->id()) + continue; // Self or offline + c->setDesiredProjectionSource(from->id()); + } + if (from->isActiveVncServer()) { // From is already active, if there is at least one active client, assume it is not @@ -407,9 +416,9 @@ void MainWindow::prepareForProjection(Client * const from, Client * const to) { Client *c = (**it).client(); if (c == NULL || c->id() == from->id()) - continue; + continue; // Self or offline if (c->currentProjectionSource() != from->id()) - continue; + continue; // Other client // Yep :-) qDebug("Reusing because of active client"); this->onVncServerStateChange(from); @@ -793,8 +802,10 @@ void MainWindow::onClientAuthenticated(Client* client) msg.setField("HOST", c->ip()); msg.setField("PORT", QString::number(c->vncPort())); msg.setField("ROPASS", c->vncRoPass()); + msg.setField("CLIENTID", QString::number(c->id())); msg.setField("CAPTION", c->name() + " @ " + c->host()); client->sendMessage(msg); + client->setDesiredProjectionSource(c->id()); break; } } diff --git a/src/server/net/client.cpp b/src/server/net/client.cpp index 3adeeaa..f3cbc0d 100644 --- a/src/server/net/client.cpp +++ b/src/server/net/client.cpp @@ -195,11 +195,16 @@ void Client::handleMsg() qDebug() << "Starting VNC server on client" << _name << " (" << _ip << ") failed."; // TODO: Show message on manager } + else + { + qDebug() << "Client " << _name << " stopped its VNC server"; + } } else { _vncRoPass = _fromClient.getFieldString("ROPASS"); _vncRwPass = _fromClient.getFieldString("RWPASS"); + qDebug() << "Client " << _name << " started its VNC server"; } _vncPort = port; emit vncServerStateChange(this); @@ -210,14 +215,19 @@ void Client::handleMsg() _activeVncClient = (_fromClient.getFieldString("ENABLED").toInt() != 0); const int other = (int)_fromClient.getFieldString("CLIENTID").toInt(); - if (!_activeVncClient && other == 0) - _desiredProjectionSource = 0; + int last = (_currentProjectionSource != 0 ? _currentProjectionSource : _desiredProjectionSource); - int last = _currentProjectionSource; if (!_activeVncClient) + { _currentProjectionSource = 0; + _desiredProjectionSource = 0; + qDebug() << "Client " << _name << " stopped its VNC client (watched " << last << ")"; + } else + { _currentProjectionSource = other; + qDebug() << "Client " << _name << " started its VNC client (watching " << other << ")"; + } emit vncClientStateChange(this, last); } -- cgit v1.2.3-55-g7522 From b487c8b74252ac995d183da8908414238b00cb72 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 23 Apr 2014 18:10:36 +0200 Subject: Made vnc thread stoppable from outside. Thread kills itself. If the vnc connection cannot be established a timeout kills the thread after a short period of time. --- src/client/vnc/vncthread.cpp | 80 +++++++++++++++++++++----------------------- src/client/vnc/vncthread.h | 1 + src/client/vnc/vncwindow.cpp | 58 +++++++++++++++++--------------- src/client/vnc/vncwindow.h | 3 +- 4 files changed, 72 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/client/vnc/vncthread.cpp b/src/client/vnc/vncthread.cpp index 86db840..068a88d 100644 --- a/src/client/vnc/vncthread.cpp +++ b/src/client/vnc/vncthread.cpp @@ -45,11 +45,8 @@ VncThread::VncThread(QString host, int port, QString passwd, int quality) : // ALWAYS delete this class from another thread using delete, not deleteLater, or you will deadlock the thread VncThread::~VncThread() { - qDebug("VNC worker destructor called, waiting for thread finishing..."); - _run = false; - while (this->isRunning()) - this->msleep(10); - qDebug("Thread ended."); + qDebug("VNC worker destructor called."); + Q_ASSERT(_run == false); if (_frameBuffer) delete[] _frameBuffer; if (_client != NULL) @@ -118,50 +115,49 @@ void VncThread::run() if (!rfbInitClient(_client, NULL, NULL)) { _client = NULL; // !!! <- if you don't do this you will get a segfault later when you try to clean up _client, as rfbInitClient already did so - this->stop(); - return; } - - qDebug("[%s] Connection successful!", metaObject()->className()); - int one = 1; - setsockopt(_client->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); - one = 1; - setsockopt(_client->sock, SOL_TCP, TCP_QUICKACK, &one, sizeof(one)); - - // Main VNC event loop - emit projectionStarted(); - while (_run) + else { - _connected = true; - const int i = WaitForMessage(_client, 100 * 1000); // wait 100ms for message. returns -1 on error/disconnect, 0 if nothing happened, 1 if new data arrived - if (i < 0) - break; - if (i > 0 && !HandleRFBServerMessage(_client)) - break; - - if (_hasNewLocalSize) + qDebug("[%s] Connection successful!", metaObject()->className()); + int one = 1; + setsockopt(_client->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + one = 1; + setsockopt(_client->sock, SOL_TCP, TCP_QUICKACK, &one, sizeof(one)); + + // Main VNC event loop + emit projectionStarted(); + } + + if(_client != NULL) + while (_run) { - QMutexLocker lock(&_mutex); - _hasNewLocalSize = false; - _localSize = _newLocalSize; - if (_painter != NULL) - delete _painter; - _imgScaled = QImage(_localSize, QImage::Format_RGB32); - _painter = new QPainter(&_imgScaled); - this->calcScaling(); + _connected = true; + const int i = WaitForMessage(_client, 100 * 1000); // wait 100ms for message. returns -1 on error/disconnect, 0 if nothing happened, 1 if new data arrived + if (i < 0) + break; + if (i > 0 && !HandleRFBServerMessage(_client)) + break; + + if (_hasNewLocalSize) + { + QMutexLocker lock(&_mutex); + _hasNewLocalSize = false; + _localSize = _newLocalSize; + if (_painter != NULL) + delete _painter; + _imgScaled = QImage(_localSize, QImage::Format_RGB32); + _painter = new QPainter(&_imgScaled); + this->calcScaling(); + } } - /* - //work yourself through event queue and fire every event... - while (!_eventQueue.isEmpty()) { - SomeEvent* event = _eventQueue.dequeue(); - event->fire(_client); - delete event; - }*/ - } - _connected = false; + emit projectionStopped(); + while (_run) + this->msleep(100); qDebug("[%s] VNC client stopped.", metaObject()->className()); + this->deleteLater(); + QThread::run(); } const QString VncThread::getDesktopName() const diff --git a/src/client/vnc/vncthread.h b/src/client/vnc/vncthread.h index 23530ec..17e991d 100644 --- a/src/client/vnc/vncthread.h +++ b/src/client/vnc/vncthread.h @@ -133,6 +133,7 @@ public: signals: void imageUpdated(const int x, const int y, const int w, const int h); void projectionStarted(); + void projectionStopped(); }; diff --git a/src/client/vnc/vncwindow.cpp b/src/client/vnc/vncwindow.cpp index f55aa28..34cbab7 100644 --- a/src/client/vnc/vncwindow.cpp +++ b/src/client/vnc/vncwindow.cpp @@ -35,11 +35,13 @@ VncWindow::~VncWindow() void VncWindow::open(const QString& host, int port, const QString& passwd, bool ro, bool fullscreen, const QString& caption, const int clientId) { // start thread for vnc-updates - this->onThreadFinished(); + this->onProjectionStopped(); _clientId = clientId; _vncWorker = new VncThread(host, port, passwd, 1); - connect(_vncWorker, SIGNAL(finished()), this, SLOT(onThreadFinished()), Qt::QueuedConnection); + connect(_vncWorker, SIGNAL(projectionStopped()), this, SLOT(onProjectionStopped()), Qt::QueuedConnection); connect(_vncWorker, SIGNAL(projectionStarted()), this, SLOT(onProjectionStarted()), Qt::QueuedConnection); + + _tcpTimeoutTimer = startTimer(4000); _vncWorker->start(QThread::LowPriority); //_rfbclient = _thread->getRfbClient(); //installEventFilter(this); @@ -67,7 +69,7 @@ void VncWindow::open(const QString& host, int port, const QString& passwd, bool _vncWorker->setTargetSize(this->size()); connect(_vncWorker, SIGNAL(imageUpdated(const int, const int, const int, const int)), this, - SLOT(onUpdateImage(const int, const int, const int, const int)), + SLOT(onUpdateImage(const int, const int, const int, const int)), Qt::QueuedConnection); } @@ -76,7 +78,7 @@ void VncWindow::closeEvent(QCloseEvent *e) e->ignore(); qDebug("Closing VNC viewer window."); this->setVisible(false); - this->onThreadFinished(); + this->onProjectionStopped(); emit running(false, _clientId); } @@ -85,35 +87,30 @@ void VncWindow::onUpdateImage(const int x, const int y, const int w, const int h this->repaint(x, y, w, h); } -/** - * Thread finished, clean up and close window - */ -void VncWindow::onThreadFinished() -{ - if (_vncWorker) - { - disconnect(_vncWorker, SIGNAL(imageUpdated(const int, const int, const int, const int)), this, - SLOT(onUpdateImage(const int, const int, const int, const int))); - disconnect(_vncWorker, SIGNAL(finished()), this, SLOT(onThreadFinished())); - _vncWorker->stop(); - delete _vncWorker; - _vncWorker = NULL; - this->close(); - } - if(_redrawTimer != 0) - { - killTimer(_redrawTimer); - _redrawTimer = 0; - } -} - /** * VNC Thread successfully connected to remote end - projection will start */ void VncWindow::onProjectionStarted() { emit running(true, _clientId); - //_redrawTimer = startTimer(5000); + _redrawTimer = startTimer(5000); +} + +void VncWindow::onProjectionStopped() +{ + if(_vncWorker == NULL) + return; + + _vncWorker->blockSignals(true); + _vncWorker->stop(); + _vncWorker = NULL; + if(_redrawTimer != 0) + { + killTimer(_redrawTimer); + _redrawTimer = 0; + } + this->close(); + } //////////////////////////////////////////////////////////////////////////////// @@ -126,6 +123,13 @@ void VncWindow::timerEvent(QTimerEvent *event) if (this->isVisible()) this->repaint(); } + else if (event->timerId() == _tcpTimeoutTimer) + { + killTimer(_tcpTimeoutTimer); + if (_vncWorker != NULL && !_vncWorker->isConnected()){ + this->onProjectionStopped(); + } + } else killTimer(event->timerId()); } diff --git a/src/client/vnc/vncwindow.h b/src/client/vnc/vncwindow.h index 396e2de..60e4835 100644 --- a/src/client/vnc/vncwindow.h +++ b/src/client/vnc/vncwindow.h @@ -37,8 +37,8 @@ public: protected slots: void onUpdateImage(const int x, const int y, const int w, const int h); - void onThreadFinished(); void onProjectionStarted(); + void onProjectionStopped(); void open(const QString& host, int port, const QString& passwd, bool ro, bool fullscreen, const QString& caption, const int clientId); @@ -62,6 +62,7 @@ private: QMap _modkeys; int _clientId; int _redrawTimer; + int _tcpTimeoutTimer; bool eventFilter(QObject *obj, QEvent *event); void keyPressEvent(QKeyEvent* event); -- cgit v1.2.3-55-g7522