diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/net/serverconnection.cpp | 54 | ||||
-rw-r--r-- | src/server/clicklabel/clicklabel.h | 6 | ||||
-rw-r--r-- | src/server/connectionframe/connectionframe.cpp | 6 | ||||
-rw-r--r-- | src/server/mainwindow/mainwindow.cpp | 248 | ||||
-rw-r--r-- | src/server/mainwindow/mainwindow.h | 6 | ||||
-rw-r--r-- | src/server/net/client.cpp | 10 | ||||
-rw-r--r-- | src/server/net/client.h | 7 | ||||
-rw-r--r-- | src/server/net/filedownloader.cpp | 2 | ||||
-rw-r--r-- | src/server/net/filedownloader.h | 18 | ||||
-rw-r--r-- | src/server/net/sslserver.h | 26 | ||||
-rw-r--r-- | src/server/sessionnamewindow/sessionnamewindow.h | 12 |
11 files changed, 245 insertions, 150 deletions
diff --git a/src/client/net/serverconnection.cpp b/src/client/net/serverconnection.cpp index 0849eab..babd64f 100644 --- a/src/client/net/serverconnection.cpp +++ b/src/client/net/serverconnection.cpp @@ -205,33 +205,33 @@ void ServerConnection::handleMsg() x, y, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - QByteArray bytes; - QBuffer jpgBuffer(&bytes); - jpgBuffer.open(QIODevice::WriteOnly); - qDebug("JPEG quality is %d", _jpegQuality); - if (desktop.save(&jpgBuffer, "JPG", _jpegQuality)) // writes pixmap into bytes in JPG format - { - // Try to adjust quality so we stay between 3 and 4.5 KB - if (_jpegQuality < 90 && bytes.size() < 3000) - _jpegQuality += 7; - else if (_jpegQuality > 40 && bytes.size() > 4500) - _jpegQuality -= 7; - } - else - { // FALLBACK - bytes.clear(); - QBuffer pngBuffer(&bytes); - pngBuffer.open(QIODevice::WriteOnly); - if (!desktop.save(&pngBuffer, "PNG")) // writes pixmap into bytes in PNG format - { - qDebug("Could not convert screenshot to PNG nor JPG"); - return; // Failed :-( - } - } - _toServer.reset(); - _toServer.setField(_ID, _THUMB); - _toServer.setField(_IMG, bytes); - sendMessage(_toServer); + QByteArray bytes; + QBuffer jpgBuffer(&bytes); + jpgBuffer.open(QIODevice::WriteOnly); + qDebug("JPEG quality is %d", _jpegQuality); + if (desktop.save(&jpgBuffer, "JPG", _jpegQuality)) // writes pixmap into bytes in JPG format + { + // Try to adjust quality so we stay between 3 and 4.5 KB + if (_jpegQuality < 90 && bytes.size() < 3000) + _jpegQuality += 7; + else if (_jpegQuality > 40 && bytes.size() > 4500) + _jpegQuality -= 7; + } + else + { // FALLBACK + bytes.clear(); + QBuffer pngBuffer(&bytes); + pngBuffer.open(QIODevice::WriteOnly); + if (!desktop.save(&pngBuffer, "PNG")) // writes pixmap into bytes in PNG format + { + qDebug("Could not convert screenshot to PNG nor JPG"); + return; // Failed :-( + } + } + _toServer.reset(); + _toServer.setField(_ID, _THUMB); + _toServer.setField(_IMG, bytes); + sendMessage(_toServer); } // message VNCSERVER - start local vncserver else if (id == _VNCSERVER) { diff --git a/src/server/clicklabel/clicklabel.h b/src/server/clicklabel/clicklabel.h index 297f1dd..4d730a9 100644 --- a/src/server/clicklabel/clicklabel.h +++ b/src/server/clicklabel/clicklabel.h @@ -9,13 +9,13 @@ */ class ClickLabel : public QLabel { - Q_OBJECT + Q_OBJECT public: - ClickLabel(QWidget *parent); + ClickLabel(QWidget *parent); protected: - void mouseReleaseEvent(QMouseEvent* e); + void mouseReleaseEvent(QMouseEvent* e); signals: diff --git a/src/server/connectionframe/connectionframe.cpp b/src/server/connectionframe/connectionframe.cpp index dbe408c..1bf6fb6 100644 --- a/src/server/connectionframe/connectionframe.cpp +++ b/src/server/connectionframe/connectionframe.cpp @@ -231,9 +231,9 @@ void ConnectionFrame::mousePressEvent(QMouseEvent *event) } else { - _clickPoint = event->pos(); - _previousPosition = this->pos(); - QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor)); + _clickPoint = event->pos(); + _previousPosition = this->pos(); + QApplication::setOverrideCursor(QCursor(Qt::ClosedHandCursor)); } // On click, the window has to be on the top-level. activateWindow(); diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp index 8762dbf..ec55f75 100644 --- a/src/server/mainwindow/mainwindow.cpp +++ b/src/server/mainwindow/mainwindow.cpp @@ -323,7 +323,7 @@ void MainWindow::tellClientCurrentSituation(Client* client) client->startVncClient(c); } } - else if (_mode == Mode::LockedMulticast) + else if (_mode == Mode::LockedUnicast) client->lockScreen(true); } @@ -465,6 +465,8 @@ void MainWindow::mouseReleaseEvent(QMouseEvent* e) */ void MainWindow::reset() { + _mode = Mode::None; + // Unlock all clients for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) if ((*it)->client() != NULL) @@ -602,72 +604,27 @@ void MainWindow::onSessionNameUpdate() } /***************************************************************************//** - * @brief MainWindow::changeProjection + * @brief MainWindow::startVncServerIfNecessary * @param from - * @param mode - * @param to */ -void MainWindow::changeProjection(Client *from, Mode mode, Client *to) +void MainWindow::startVncServerIfNecessary(int from) { - DisableButtons(); - - if (mode == Mode::Broadcast) - { - // Set all clients as watchers - for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) - { - if ((*it)->client() != NULL && (*it)->client() != getClientFromId(_streamingSource)) - { - // _watchers.insert((*it)->client()->id(), (*it)->client()); - (*it)->client()->setWatcher(true); - } - } - } - else // mode != Mode::Broadcast - { - // If this is the first call in this mode clear the watchers - if ((mode == Mode::LockedMulticast && _mode != Mode::LockedMulticast) - || (mode == Mode::Multicast && _mode != Mode::Multicast)) - { - // _watchers.clear(); - for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) - { - if ((*it)->client() != NULL) - (*it)->client()->setWatcher(false); - } - } - - // If "to" already watches "from" stop it - // if (_watchers.contains(to->id())) - if (getClientFromId(to->id())->isWatcher()) - { - // _watchers.remove(to->id()); - getClientFromId(to->id())->setWatcher(false); - } - else // list "to" as watcher - { - // _watchers.insert(to->id(), to); - getClientFromId(to->id())->setWatcher(true); - } - } - - // Set the mode - _mode = mode; + Client* os = getClientFromId(_streamingSource); + Client* ns = getClientFromId(from); // if there is a server running which is not "from" stop it. - if (getClientFromId(_streamingSource) != NULL && getClientFromId(_streamingSource) != from) - getClientFromId(_streamingSource)->stopVncServer(); + if (os != NULL && _streamingSource != from) + os->stopVncServer(); // Set new streaming source - _streamingSource = from->id(); + _streamingSource = from; // If streaming source is already active avoid a restart - Client* c = getClientFromId(_streamingSource); - if (c != NULL) { - if (c->isActiveVncServer()) - this->onVncServerStateChange(c); + if (ns != NULL) { + if (ns->isActiveVncServer()) + this->onVncServerStateChange(ns); else // Could not take shortcut, (re)start VNC server on source - c->startVncServer(); + ns->startVncServer(); } } @@ -695,7 +652,29 @@ void MainWindow::onButtonTutorToAll() else if (_clientFrames.size() == 1) QMessageBox::critical(this, tr("Projection"), sStrNoDestAv); else - changeProjection(getTutorFrame()->client(), Mode::Broadcast); + { + DisableButtons(); + + if (_mode != Mode::Broadcast) + { + // Set all clients as watchers + for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + { + if ((*it)->client() != NULL && (*it)->client() != getClientFromId(_streamingSource)) + (*it)->client()->setWatcher(true); + } + } + else // If this mode is already active + { + // Stop reset everything + reset(); + _mode = Mode::None; + return; + } + + _mode = Mode::Broadcast; + startVncServerIfNecessary(getTutorFrame()->client()->id()); + } } /***************************************************************************//** @@ -712,7 +691,29 @@ void MainWindow::onButtonStudentToAll() if (getSelectedFrame()->client() == NULL) QMessageBox::critical(this, tr("Projection"), sStrSourceOffline); else - changeProjection(getSelectedFrame()->client(), Mode::Broadcast); + { + DisableButtons(); + + if (_mode != Mode::Broadcast) + { + // Set all clients as watchers + for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + { + if ((*it)->client() != NULL && (*it)->client() != getClientFromId(_streamingSource)) + (*it)->client()->setWatcher(true); + } + } + else // If this mode is already active + { + // Stop reset everything + reset(); + _mode = Mode::None; + return; + } + + _mode = Mode::Broadcast; + startVncServerIfNecessary(getSelectedFrame()->client()->id()); + } } /***************************************************************************//** @@ -734,7 +735,36 @@ void MainWindow::onButtonTutorToStudent() else if (getTutorFrame()->client() == NULL) QMessageBox::critical(this, tr("Projection"), sStrTutorOffline); else - changeProjection(getTutorFrame()->client(), Mode::Multicast, getSelectedFrame()->client()); + { + DisableButtons(); + + // If this is the first call in this mode clear the watchers + if (_mode != Mode::Multicast) + { + // _watchers.clear(); + for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + { + if ((*it)->client() != NULL) + (*it)->client()->setWatcher(false); + } + } + + // If "to" already watches "from" stop it + // if (_watchers.contains(to->id())) + if (getClientFromId(getSelectedFrame()->client()->id())->isWatcher()) + { + // _watchers.remove(to->id()); + getClientFromId(getSelectedFrame()->client()->id())->setWatcher(false); + } + else // list "to" as watcher + { + // _watchers.insert(to->id(), to); + getClientFromId(getSelectedFrame()->client()->id())->setWatcher(true); + } + + _mode = Mode::Multicast; + startVncServerIfNecessary(getTutorFrame()->client()->id()); + } } /***************************************************************************//** @@ -755,8 +785,33 @@ void MainWindow::onButtonStudentToTutor() QMessageBox::critical(this, tr("Projection"), sStrSourceOffline); else if (getTutorFrame()->client() == NULL) QMessageBox::critical(this, tr("Projection"), sStrTutorOffline); - else - changeProjection(getSelectedFrame()->client(), Mode::Multicast, getTutorFrame()->client()); + else{ + DisableButtons(); + + if (_mode != Mode::Unicast) + { + // If this is the first run in this mode set the tutor as watcher + for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + if ((*it)->client() != NULL) + (*it)->client()->setWatcher(getTutorFrame()->client()->id() == (*it)->client()->id()); + _mode = Mode::Unicast; + } + else + { + // If this mode is already active and the current source is selected, stop the streaming. + if (getSelectedFrame()->client()->id() == _streamingSource ) + { + // Stop reset everything + _mode = Mode::None; + reset(); + return; + } + // If another client is selected solely the current streaming source shall be changed. + // This should be handled by startVncServerIfNecessary(...). + } + + startVncServerIfNecessary(getSelectedFrame()->client()->id()); + } } @@ -778,7 +833,33 @@ void MainWindow::onButtonStudentToTutorExclusive() else if (getTutorFrame()->client() == NULL) QMessageBox::critical(this, tr("Projection"), sStrTutorOffline); else - changeProjection(getSelectedFrame()->client(), Mode::LockedMulticast, getTutorFrame()->client()); + { + DisableButtons(); + + if (_mode != Mode::LockedUnicast) + { + // If this is the first run in this mode set the tutor as watcher + for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + if ((*it)->client() != NULL) + (*it)->client()->setWatcher(getTutorFrame()->client()->id() == (*it)->client()->id()); + _mode = Mode::LockedUnicast; + } + else + { + // If this mode is already active and the current source is selected, stop the streaming. + if (getSelectedFrame()->client()->id() == _streamingSource ) + { + // Stop reset everything + _mode = Mode::None; + reset(); + return; + } + // If another client is selected solely the current streaming source shall be changed. + // This should be handled by startVncServerIfNecessary(...). + } + + startVncServerIfNecessary(getSelectedFrame()->client()->id()); + } } @@ -1057,7 +1138,7 @@ void MainWindow::onVncServerStateChange(Client* client) else { // Lock others and stop their clients - (*it)->client()->lockScreen(_mode == Mode::LockedMulticast); + (*it)->client()->lockScreen(_mode == Mode::LockedUnicast); (*it)->client()->stopVncClient(); } } @@ -1093,27 +1174,36 @@ void MainWindow::onVncClientStateChange(Client* client) { // VNC Client stopped -> remove from watchers if (!client->isActiveVncClient()){ - // _watchers.remove(client->id()); if (getClientFromId(client->id()) != NULL) getClientFromId(client->id())->setWatcher(false); - // If noboody is watching the multicast stop VNC server - // if (_watchers.isEmpty() && _mode != Mode::Broadcast) - // _streamingSource->stopVncServer(); - bool noWatchers = true; - for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it) + /* + * If noboody is watching the multicast stop VNC server + * If the past connection of this client is not the current + * _streamingSource then the manager has to have stopped it + * already. This is necessary for the race condition when a server + * is stopped and another started at the same time, since the new + * server would be killed if all client disconnect before any of + * the new connect. + */ + if (client->projectionSource() == _streamingSource) { - if ((*it)->client() != NULL) + bool noWatchers = true; + for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); + it != _clientFrames.end(); ++it) { - if ((*it)->client()->isWatcher()) - noWatchers = false; + if ((*it)->client() != NULL) + { + if ((*it)->client()->isWatcher()) + noWatchers = false; + } + } + if (noWatchers && _mode != Mode::Broadcast) + { + Client* c = getClientFromId(_streamingSource); + if (c != NULL) + c->stopVncServer(); } - } - if (noWatchers && _mode != Mode::Broadcast) - { - Client* c = getClientFromId(_streamingSource); - if (c != NULL) - c->stopVncServer(); } } } diff --git a/src/server/mainwindow/mainwindow.h b/src/server/mainwindow/mainwindow.h index a07eed9..8b0f133 100644 --- a/src/server/mainwindow/mainwindow.h +++ b/src/server/mainwindow/mainwindow.h @@ -51,7 +51,9 @@ private: enum class Mode { Broadcast, Multicast, - LockedMulticast + Unicast, + LockedUnicast, + None } _mode; int _streamingSource; QMap<int, Client*> _watchers; @@ -77,7 +79,7 @@ private: ConnectionFrame* createFrame(QString computerId, QPoint position); bool loadPosition(QSettings& settings, const QString& id, int& x, int& y); void savePosition(ConnectionFrame *cf); - void changeProjection(Client *from, Mode mode = Mode::Broadcast, Client *to = NULL); + void startVncServerIfNecessary(int from); void tellClientCurrentSituation(Client* client); void reset(); diff --git a/src/server/net/client.cpp b/src/server/net/client.cpp index 584b254..a00ef88 100644 --- a/src/server/net/client.cpp +++ b/src/server/net/client.cpp @@ -21,7 +21,8 @@ Client::Client(QSslSocket* socket) : _socket(socket) { assert(socket != NULL); _authed = 0; - _currentProjectionSource = 0; + _projectionSource = 0; + _isActiveVncClient = false; _vncPort = 0; _isTutor = false; _locked = false; @@ -193,13 +194,14 @@ void Client::handleMsg() if (_fromClient.getFieldString("ENABLED").toInt() != 0) { qDebug() << "Client " << _name << " started its VNC client (watching " << projectionSource << ")"; - _currentProjectionSource = projectionSource; + _projectionSource = projectionSource; + _isActiveVncClient = true; emit vncClientStateChange(this); } else { qDebug() << "Client " << _name << " stopped its VNC client (watched " << projectionSource << ")"; - _currentProjectionSource = 0; + _isActiveVncClient = false; emit vncClientStateChange(this); } emit stateChanged(); @@ -304,7 +306,7 @@ void Client::startVncClient(const Client * const to) /******************************************************************************/ void Client::stopVncClient() { - if (_currentProjectionSource != 0) { + if (_isActiveVncClient) { NetworkMessage msg; msg.setField(_ID, _VNCCLIENT); sendMessage(msg); diff --git a/src/server/net/client.h b/src/server/net/client.h index 6872959..61b6a5b 100644 --- a/src/server/net/client.h +++ b/src/server/net/client.h @@ -33,8 +33,8 @@ public: inline const QString& host() const { return _host; } inline const QString ip() const { return _socket->peerAddress().toString(); } inline const int id() const { return _id; } - inline const int currentProjectionSource() const { return _currentProjectionSource; } - inline const bool isActiveVncClient() const { return _currentProjectionSource > 0; } + inline const int projectionSource() const { return _projectionSource; } + inline const bool isActiveVncClient() const { return _isActiveVncClient; } inline const bool isActiveVncServer() const { return _vncPort > 0; } inline const bool isLocked() const { return _locked; } inline const bool isWatcher() const { return _isWatcher; } @@ -65,7 +65,8 @@ private: int _id; // this client's unique id QString _vncRwPass, _vncRoPass; int _vncPort; // VNCserver state. Greater 0 -> active on this port. Equals 0 -> no server. - int _currentProjectionSource; // VNCclient state. indicating that the client is displaying a remote screen via VNC + int _projectionSource; // VNCclient state. The source the client was or is connected to (depends on _isActiveVncClient) + bool _isActiveVncClient; // VNCclient state. indicating that the client is displaying a remote screen via VNC bool _isTutor; // Flag indicating that the client has been set as a tutor bool _isWatcher; // Flag indicates that the client should watch to VNC Server. diff --git a/src/server/net/filedownloader.cpp b/src/server/net/filedownloader.cpp index 70e1520..aa27948 100644 --- a/src/server/net/filedownloader.cpp +++ b/src/server/net/filedownloader.cpp @@ -21,7 +21,7 @@ FileDownloader::~FileDownloader() { void FileDownloader::connectSlot(QObject* obj, const char* slot) { QObject::connect(this, SIGNAL(downloaded(QByteArray&)), - obj, slot); + obj, slot); } void FileDownloader::fileDownloaded(QNetworkReply* pReply) { diff --git a/src/server/net/filedownloader.h b/src/server/net/filedownloader.h index 68eaa39..227af50 100644 --- a/src/server/net/filedownloader.h +++ b/src/server/net/filedownloader.h @@ -16,28 +16,28 @@ class FileDownloader : public QObject { - Q_OBJECT + Q_OBJECT public: - explicit FileDownloader(QObject *parent = 0); + explicit FileDownloader(QObject *parent = 0); - virtual ~FileDownloader(); + virtual ~FileDownloader(); - void downloadFile(const QUrl& fileUrl); + void downloadFile(const QUrl& fileUrl); - void connectSlot(QObject* obj, const char* slot); + void connectSlot(QObject* obj, const char* slot); - QByteArray downloadedData() const; + QByteArray downloadedData() const; signals: - void downloaded(QByteArray& downloadedData); + void downloaded(QByteArray& downloadedData); private slots: - void fileDownloaded(QNetworkReply* pReply); + void fileDownloaded(QNetworkReply* pReply); private: - QNetworkAccessManager m_WebCtrl; + QNetworkAccessManager m_WebCtrl; }; diff --git a/src/server/net/sslserver.h b/src/server/net/sslserver.h index cdb12de..0b3120e 100644 --- a/src/server/net/sslserver.h +++ b/src/server/net/sslserver.h @@ -28,26 +28,26 @@ class QSslSocket; */ class SslServer : public QTcpServer { - Q_OBJECT + Q_OBJECT private Q_SLOTS: - void sslErrors ( const QList<QSslError> & errors ); + void sslErrors ( const QList<QSslError> & errors ); public: - SslServer(); - virtual ~SslServer(); + SslServer(); + virtual ~SslServer(); - bool hasPendingConnections (); - // This one has to return a TcpSocket as we're overwriting from the base class - // just cast it to QSslSocket later - virtual QTcpSocket* nextPendingConnection(); + bool hasPendingConnections (); + // This one has to return a TcpSocket as we're overwriting from the base class + // just cast it to QSslSocket later + virtual QTcpSocket* nextPendingConnection(); protected: - void incomingConnection(int socketDescriptor); - void timerEvent (QTimerEvent* event); - QList<QSslSocket*> _pending; - QList<QSslSocket*> _delete; - int _tmr; + void incomingConnection(int socketDescriptor); + void timerEvent (QTimerEvent* event); + QList<QSslSocket*> _pending; + QList<QSslSocket*> _delete; + int _tmr; }; #endif /* SSLSERVER_H_ */ diff --git a/src/server/sessionnamewindow/sessionnamewindow.h b/src/server/sessionnamewindow/sessionnamewindow.h index ee93ea2..761f596 100644 --- a/src/server/sessionnamewindow/sessionnamewindow.h +++ b/src/server/sessionnamewindow/sessionnamewindow.h @@ -10,19 +10,19 @@ class SessionName; class SessionNameWindow : public QDialog { - Q_OBJECT + Q_OBJECT private: - Ui::SessionName *ui; + Ui::SessionName *ui; public: - SessionNameWindow(QWidget *parent = 0); - ~SessionNameWindow(); + SessionNameWindow(QWidget *parent = 0); + ~SessionNameWindow(); - void show(const QString& name); + void show(const QString& name); protected: - void closeEvent(QCloseEvent *e); + void closeEvent(QCloseEvent *e); private slots: void onOkClicked(); |