summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorManuel Schneider2014-07-22 14:35:30 +0200
committerManuel Schneider2014-07-22 14:35:30 +0200
commit4d522589c0ab04ae2be76d53788597626e57e71f (patch)
tree8f4352ca4d3ca259f4111a44955b8a0adc0c026a /src
parentNew bug detected (diff)
downloadpvs2-4d522589c0ab04ae2be76d53788597626e57e71f.tar.gz
pvs2-4d522589c0ab04ae2be76d53788597626e57e71f.tar.xz
pvs2-4d522589c0ab04ae2be76d53788597626e57e71f.zip
Bugfix: One click source change now fully supported
Since the async nature of this protocol introduces race conditions when changing the source of the projection, the possiblity that two servers exist at a moment is still there. Even though we thought we do not support multiple sources. This is the reason why _desiredProjectionSource is needed after all.
Diffstat (limited to 'src')
-rw-r--r--src/server/mainwindow/mainwindow.cpp130
-rw-r--r--src/server/net/client.h14
2 files changed, 67 insertions, 77 deletions
diff --git a/src/server/mainwindow/mainwindow.cpp b/src/server/mainwindow/mainwindow.cpp
index d7cab75..ab94535 100644
--- a/src/server/mainwindow/mainwindow.cpp
+++ b/src/server/mainwindow/mainwindow.cpp
@@ -316,8 +316,7 @@ void MainWindow::tellClientCurrentSituation(Client* client)
client->lockScreen(true);
if (_mode == Mode::Broadcast){
- // _watchers.insert(client->id(), client);
- client->setWatcher(true);
+ client->setDesiredProjectionSource(_streamingSource);
Client* c = getClientFromId(_streamingSource);
if (c != NULL) {
client->startVncClient(c);
@@ -660,8 +659,10 @@ void MainWindow::onButtonTutorToAll()
// 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);
+ if ((*it)->client() != NULL && (*it)->client() != getClientFromId(_streamingSource)){
+ (*it)->client()->setDesiredProjectionSource(getTutorFrame()->client()->id());
+ }
+
}
}
else // If this mode is already active
@@ -702,25 +703,21 @@ void MainWindow::onButtonTutorToStudent()
// 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);
+ (*it)->client()->setDesiredProjectionSource(NO_SOURCE);
}
}
// If "to" already watches "from" stop it
- // if (_watchers.contains(to->id()))
- if (getClientFromId(getSelectedFrame()->client()->id())->isWatcher())
+ if (getSelectedFrame()->client()->isWatcher())
{
- // _watchers.remove(to->id());
- getClientFromId(getSelectedFrame()->client()->id())->setWatcher(false);
+ getSelectedFrame()->client()->setDesiredProjectionSource(NO_SOURCE);
}
else // list "to" as watcher
{
- // _watchers.insert(to->id(), to);
- getClientFromId(getSelectedFrame()->client()->id())->setWatcher(true);
+ getSelectedFrame()->client()->setDesiredProjectionSource(getTutorFrame()->client()->id());
}
_mode = Mode::Multicast;
@@ -746,31 +743,25 @@ void MainWindow::onButtonStudentToTutor()
QMessageBox::critical(this, tr("Projection"), sStrSourceOffline);
else if (getTutorFrame()->client() == NULL)
QMessageBox::critical(this, tr("Projection"), sStrTutorOffline);
- 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
+ else
+ {
+ // If this is not the first run in this mode and the current source is selected, stop the streaming.
+ if (_mode == Mode::Unicast && getSelectedFrame()->client()->id() == _streamingSource)
{
- // 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(...).
+ // Stop reset everything
+ _mode = Mode::None;
+ reset();
+ return;
}
+ // Unset all clients desired sources. Except the tutors desired source, this has to be the selecteds frame
+ for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
+ if ((*it)->client() != NULL){
+ (*it)->client()->setDesiredProjectionSource(getTutorFrame()->client()->id() == (*it)->client()->id() ? getSelectedFrame()->client()->id():NO_SOURCE);
+ qDebug() << "ID" <<(*it)->client()->id() << "ds" << (*it)->client()->desiredProjectionSource() <<"ps"<< (*it)->client()->projectionSource();
+}
+ DisableButtons();
+ _mode = Mode::Unicast;
startVncServerIfNecessary(getSelectedFrame()->client()->id());
}
}
@@ -802,7 +793,8 @@ void MainWindow::onButtonStudentToTutorExclusive()
// 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());
+ // Unset all but tutors desired projection, which is student
+ (*it)->client()->setDesiredProjectionSource(getTutorFrame()->client()->id() == (*it)->client()->id() ? getSelectedFrame()->client()->id():NO_SOURCE);
_mode = Mode::LockedUnicast;
}
else
@@ -1062,46 +1054,34 @@ void MainWindow::onVncServerStateChange(Client* client)
if (client->isActiveVncServer())
{
- if (_mode == Mode::Broadcast)
- {
- for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
- {
- if ((*it)->client() != NULL)
- {
- // Unlock all online clients
- (*it)->client()->lockScreen(false);
-
- // Start VNCclients on all online clients but source
- if ((*it)->client() != client)
- (*it)->client()->startVncClient(client);
- }
- }
- }
- else // !Mode::Broadcast --> Mode::LockedMC || Mode::MC
+// if (_mode == Mode::Broadcast)
+// {
+// for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
+// {
+// if ((*it)->client() != NULL)
+// {
+// // Unlock all online clients
+// (*it)->client()->lockScreen(false);
+
+// // Start VNCclients on all online clients but source
+// if ((*it)->client() != client)
+// (*it)->client()->startVncClient(client);
+// }
+// }
+// }
+// else
{
+ // apply the desired projection sources
for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
{
// Ignore offline clients
if ( (*it)->client() != NULL)
{
- // if (_watchers.contains((*it)->client()->id()))
- if ((*it)->client()->isWatcher())
- {
- // Unlock destination and connect VNCclient
- (*it)->client()->lockScreen(false);
+ qDebug() << "ID" <<(*it)->client()->id() << "ds" << (*it)->client()->desiredProjectionSource() <<"ps"<< (*it)->client()->projectionSource();
+ if ( (*it)->client()->desiredProjectionSource() == client->id() )
(*it)->client()->startVncClient(client);
- }
- else if ((*it)->client()->id() == client->id() )
- {
- // Unlock source
- (*it)->client()->lockScreen(false);
- }
- else
- {
- // Lock others and stop their clients
- (*it)->client()->lockScreen(_mode == Mode::LockedUnicast);
- (*it)->client()->stopVncClient();
- }
+
+ (*it)->client()->lockScreen((*it)->client()->desiredProjectionSource() == NO_SOURCE && _mode == Mode::LockedUnicast);
}
}
}
@@ -1109,15 +1089,16 @@ void MainWindow::onVncServerStateChange(Client* client)
else
{
// VNC server stopped on some client or failed to start - reset local pending projection information
- // foreach (Client *c, _watchers) {
- // c->stopVncClient();
- // }
for (QList<ConnectionFrame*>::iterator it(_clientFrames.begin()); it != _clientFrames.end(); ++it)
{
if ((*it)->client() != NULL)
{
- if ((*it)->client()->isWatcher())
+ if ((*it)->client()->desiredProjectionSource() == client->id()) {
+ (*it)->client()->setDesiredProjectionSource(NO_SOURCE);
(*it)->client()->stopVncClient();
+ if (_mode == Mode::LockedUnicast)
+ (*it)->client()->lockScreen(true);
+ }
}
}
}
@@ -1135,11 +1116,10 @@ void MainWindow::onVncClientStateChange(Client* client)
{
// VNC Client stopped -> remove from watchers
if (!client->isActiveVncClient()){
- if (getClientFromId(client->id()) != NULL)
- getClientFromId(client->id())->setWatcher(false);
+ // client->setDesiredProjectionSource(NO_SOURCE);
/*
- * If noboody is watching the multicast stop VNC server
+ * If nobody 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
diff --git a/src/server/net/client.h b/src/server/net/client.h
index 61b6a5b..6dbb5bd 100644
--- a/src/server/net/client.h
+++ b/src/server/net/client.h
@@ -10,6 +10,8 @@
//class QSslSocket;
+#define NO_SOURCE 0
+
struct ClientLogin
{
bool accept;
@@ -33,15 +35,22 @@ 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 desiredProjectionSource(){ return _desiredSource; }
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; }
+ inline const bool isWatcher() const { return _desiredSource != 0; }
+
+
// Setters
inline void setTutor(bool enable){ _isTutor = enable; }
inline void setWatcher(bool enable){ _isWatcher = enable; }
+ inline void setDesiredProjectionSource(int id){
+ qDebug() << "ID" <<_id << " new source " << _desiredSource;
+ _desiredSource = id;
+ }
//Send message stuff
void startVncServer();
@@ -65,7 +74,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 _projectionSource; // VNCclient state. The source the client was or is connected to (depends on _isActiveVncClient)
+ int _desiredSource; // The source the client shall be connected to
+ int _projectionSource; // 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.