From d662e959d07fd690c7cf0d7ed1d81f689f96b017 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 1 Feb 2016 10:42:40 +0100 Subject: [client] Retry VNC connection up to 5 times --- src/client/vnc/vncthread.cpp | 75 ++++++++++++++++++++++++++------------------ src/client/vnc/vncthread.h | 2 +- src/client/vnc/vncwindow.cpp | 2 +- 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/client/vnc/vncthread.cpp b/src/client/vnc/vncthread.cpp index 7d23afa..c9327ad 100644 --- a/src/client/vnc/vncthread.cpp +++ b/src/client/vnc/vncthread.cpp @@ -66,6 +66,7 @@ VncThread::~VncThread() { if (_client->sock != -1) ::close(_client->sock); + _client->sock = -1; _client->frameBuffer = NULL; rfbClientCleanup(_client); } @@ -112,9 +113,11 @@ void VncThread::setTargetSize(const QSize size) if (_localSize == size) return; qDebug() << "Setting target size to " << size; - QMutexLocker lock(&_mutex); - _newLocalSize = size; - _hasNewLocalSize = true; + { + QMutexLocker lock(&_mutex); + _newLocalSize = size; + _hasNewLocalSize = true; + } } /** @@ -134,26 +137,37 @@ void VncThread::run() qPrintable(_passwd), _quality); // setup network - _client = rfbGetClient(8, 3, 4); - _client->MallocFrameBuffer = &frameBufferHandler; - _client->canHandleNewFBSize = true; - free(_client->serverHost); // in rfbGetClient, serverHost is assigned strdup(""), so free that first. - _client->serverHost = strdup(_host.toUtf8().constData()); - _client->desktopName = NULL; - _client->serverPort = _port; - _client->GetPassword = &passwdHandler; - _client->GotFrameBufferUpdate = &updateImage; - _client->frameBuffer = NULL; + for (int retry = 0; retry < 5 && _run; ++retry) { + this->msleep(1 + qrand() % 60); + if (!_run) + break; + _client = rfbGetClient(8, 3, 4); + _client->MallocFrameBuffer = &frameBufferHandler; + _client->canHandleNewFBSize = true; + free(_client->serverHost); // in rfbGetClient, serverHost is assigned strdup(""), so free that first. + _client->serverHost = strdup(_host.toUtf8().constData()); + _client->desktopName = NULL; + _client->serverPort = _port; + _client->GetPassword = &passwdHandler; + _client->GotFrameBufferUpdate = &updateImage; + _client->frameBuffer = NULL; - // save this instance in vnc-struct for callbacks - rfbClientSetClientData(_client, 0, this); + // save this instance in vnc-struct for callbacks + rfbClientSetClientData(_client, 0, this); - // start client - 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 + // start client + if (rfbInitClient(_client, NULL, NULL)) + { + break; // Success! + } + // Connection failed + _client = NULL; // InitClient frees the client on failure, so make sure we don't keep an invalid pointer around + if (!_run) + break; + // error, let's try again + this->msleep(10 + qrand() % 50); } - else + if(_client != NULL) { qDebug("[%s] Connection successful!", metaObject()->className()); int one = 1; @@ -163,9 +177,6 @@ void VncThread::run() // Main VNC event loop emit projectionStarted(); - } - - if(_client != NULL) while (_run) { _connected = true; @@ -187,6 +198,7 @@ void VncThread::run() this->calcScaling(); } } + } _connected = false; emit projectionStopped(); @@ -240,13 +252,16 @@ void VncThread::processImageUpdate(const int x, const int y, const int w, const const int dstW = endX * _dstStepX - dstX; const int dstH = endY * _dstStepY - dstY; // Rescale - if (_painter != NULL) { - QImage scaled( - _img.copy(srcX, srcY, srcW, srcH).scaled(dstW, dstH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - _painter->drawImage(dstX, dstY, scaled, 0, 0, dstW, dstH); - emit imageUpdated(dstX, dstY, dstW, dstH); + QMutexLocker lock(&_mutex); + if (_painter != NULL) + { + QImage scaled( + _img.copy(srcX, srcY, srcW, srcH).scaled(dstW, dstH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + _painter->drawImage(dstX, dstY, scaled, 0, 0, dstW, dstH); + } } + emit imageUpdated(dstX, dstY, dstW, dstH); } else { @@ -280,7 +295,7 @@ char* VncThread::passwdHandler(rfbClient *client) rfbBool VncThread::frameBufferHandler(rfbClient *client) { VncThread *t = (VncThread*)rfbClientGetClientData(client, 0); - const int width = client->width, height = client->height, depth = client->format.bitsPerPixel; + const int width = client->width, height = client->height, depth = 32; // client->format.bitsPerPixel; const int size = width * height * (depth / 8); qDebug("[%s] Remote desktop: %ix%ix%i", t->metaObject()->className(), width, height, depth); @@ -292,7 +307,7 @@ rfbBool VncThread::frameBufferHandler(rfbClient *client) t->_frameBuffer = new uint8_t[size]; client->frameBuffer = t->_frameBuffer; memset(client->frameBuffer, '\0', size); - client->format.bitsPerPixel = 32; + client->format.bitsPerPixel = depth; client->format.redShift = 16; client->format.greenShift = 8; client->format.blueShift = 0; diff --git a/src/client/vnc/vncthread.h b/src/client/vnc/vncthread.h index 2e94c2d..bb1405c 100644 --- a/src/client/vnc/vncthread.h +++ b/src/client/vnc/vncthread.h @@ -61,6 +61,7 @@ private: volatile bool _run; void calcScaling(); + void processImageUpdate(const int x, const int y, const int w, const int h); // Callbacks for rfb lib. make them class members so the callbacks can access private members of the class. @@ -75,7 +76,6 @@ public: const QImage& getImage() const { if (_srcStepX > 1 || _srcStepY > 1) return _imgScaled; return _img; } const QSize& getSourceSize() const { return _clientSize; } const QString getDesktopName() const; - void processImageUpdate(const int x, const int y, const int w, const int h); const bool isConnected() const { return _connected; } void stop() { _run = false; } void setTargetSize(const QSize size); diff --git a/src/client/vnc/vncwindow.cpp b/src/client/vnc/vncwindow.cpp index 13ad107..ff7c5d4 100644 --- a/src/client/vnc/vncwindow.cpp +++ b/src/client/vnc/vncwindow.cpp @@ -171,7 +171,7 @@ void VncWindow::onUpdateImage(const int x, const int y, const int w, const int h void VncWindow::onProjectionStarted() { emit running(true, _clientId); - _redrawTimer = startTimer(5000); + _redrawTimer = startTimer(3000); } /** -- cgit v1.2.3-55-g7522