Hello community, here is the log from the commit of package krdc for openSUSE:Factory checked in at 2013-12-02 12:36:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/krdc (Old) and /work/SRC/openSUSE:Factory/.krdc.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "krdc" Changes: -------- --- /work/SRC/openSUSE:Factory/krdc/krdc.changes 2013-10-04 07:24:14.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.krdc.new/krdc.changes 2013-12-02 12:36:05.000000000 +0100 @@ -1,0 +2,21 @@ +Sat Nov 16 18:33:11 UTC 2013 - [email protected] + +- Update to 4.11.90 + * KDE 4.12 Beta 2 release + * See http://www.kde.org/announcements/announce-4.12-beta2.php + +------------------------------------------------------------------- +Sun Nov 10 08:04:55 UTC 2013 - [email protected] + +- Update to 4.11.80 + * KDE 4.12 Beta 1 release + * See http://www.kde.org/announcements/announce-4.12-beta1.php + +------------------------------------------------------------------- +Sat Nov 2 15:51:39 UTC 2013 - [email protected] + +- Update to 4.11.3 + * KDE 4.11.3 bugfix release + * See http://www.kde.org/announcements/announce-4.11.3.php + +------------------------------------------------------------------- Old: ---- krdc-4.11.2.tar.xz New: ---- krdc-4.11.90.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ krdc.spec ++++++ --- /var/tmp/diff_new_pack.5wy5rj/_old 2013-12-02 12:36:06.000000000 +0100 +++ /var/tmp/diff_new_pack.5wy5rj/_new 2013-12-02 12:36:06.000000000 +0100 @@ -25,7 +25,7 @@ BuildRequires: pkgconfig(TelepathyQt4) %endif BuildRequires: oxygen-icon-theme-large -Version: 4.11.2 +Version: 4.11.90 Release: 0 Summary: Remote Desktop Connection License: GPL-2.0+ ++++++ krdc-4.11.2.tar.xz -> krdc-4.11.90.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krdc-4.11.2/core/krdc_plugin.desktop new/krdc-4.11.90/core/krdc_plugin.desktop --- old/krdc-4.11.2/core/krdc_plugin.desktop 2013-08-28 19:16:31.000000000 +0200 +++ new/krdc-4.11.90/core/krdc_plugin.desktop 2013-11-07 10:47:57.000000000 +0100 @@ -50,6 +50,7 @@ Name[sv]=Insticksprogram för KRDC Name[th]=ส่วนเสริมของ KRDC Name[tr]=KRDC Eklentisi +Name[ug]=KRDC قىستۇرما Name[uk]=Додаток KRDC Name[x-test]=xxKRDC Pluginxx Name[zh_CN]=KRDC 插件 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krdc-4.11.2/krdc_approver/krdc_rfb_approver.notifyrc new/krdc-4.11.90/krdc_approver/krdc_rfb_approver.notifyrc --- old/krdc-4.11.2/krdc_approver/krdc_rfb_approver.notifyrc 2013-08-28 19:16:31.000000000 +0200 +++ new/krdc-4.11.90/krdc_approver/krdc_rfb_approver.notifyrc 2013-11-07 10:47:57.000000000 +0100 @@ -118,6 +118,7 @@ [Event/newrfb] Name=Incoming RFB Tube Name[ast]=RFB Tube entrante +Name[bg]=Входяща връзка RFB Name[bs]=Dolazna RFB cijev Name[ca]=Tub RFB entrant Name[ca@valencia]=Tub RFB entrant diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krdc-4.11.2/vnc/vncclientthread.cpp new/krdc-4.11.90/vnc/vncclientthread.cpp --- old/krdc-4.11.2/vnc/vncclientthread.cpp 2013-08-28 19:16:31.000000000 +0200 +++ new/krdc-4.11.90/vnc/vncclientthread.cpp 2013-11-07 10:47:57.000000000 +0100 @@ -23,14 +23,71 @@ #include "vncclientthread.h" +#include <cerrno> +#include <netinet/tcp.h> #include <QMutexLocker> +#include <QThreadStorage> #include <QTimer> //for detecting intel AMT KVM vnc server static const QString INTEL_AMT_KVM_STRING= "Intel(r) AMT KVM"; -static QString outputErrorMessageString; +static QThreadStorage<VncClientThread **> instances; -QVector<QRgb> VncClientThread::m_colorTable; +// Dispatch from this static callback context to the member context. +rfbBool VncClientThread::newclientStatic(rfbClient *cl) +{ + VncClientThread *t = (VncClientThread *)rfbClientGetClientData(cl, 0); + Q_ASSERT(t); + + return t->newclient(); +} + +// Dispatch from this static callback context to the member context. +void VncClientThread::updatefbStatic(rfbClient *cl, int x, int y, int w, int h) +{ + VncClientThread *t = (VncClientThread *)rfbClientGetClientData(cl, 0); + Q_ASSERT(t); + + return t->updatefb(x, y, w, h); +} + +// Dispatch from this static callback context to the member context. +void VncClientThread::cuttextStatic(rfbClient *cl, const char *text, int textlen) +{ + VncClientThread *t = (VncClientThread *)rfbClientGetClientData(cl, 0); + Q_ASSERT(t); + + t->cuttext(text, textlen); +} + +// Dispatch from this static callback context to the member context. +char *VncClientThread::passwdHandlerStatic(rfbClient *cl) +{ + VncClientThread *t = (VncClientThread *)rfbClientGetClientData(cl, 0); + Q_ASSERT(t); + + return t->passwdHandler(); +} + +// Dispatch from this static callback context to the member context. +rfbCredential *VncClientThread::credentialHandlerStatic(rfbClient *cl, int credentialType) +{ + VncClientThread *t = (VncClientThread *)rfbClientGetClientData(cl, 0); + Q_ASSERT(t); + + return t->credentialHandler(credentialType); +} + +// Dispatch from this static callback context to the member context. +void VncClientThread::outputHandlerStatic(const char *format, ...) +{ + VncClientThread **t = instances.localData(); + + va_list args; + va_start(args, format); + (*t)->outputHandler(format, args); + va_end(args); +} void VncClientThread::setClientColorDepth(rfbClient* cl, VncClientThread::ColorDepth cd) { @@ -80,27 +137,24 @@ } } -rfbBool VncClientThread::newclient(rfbClient *cl) +rfbBool VncClientThread::newclient() { - VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0); - Q_ASSERT(t); - //8bit color hack for Intel(r) AMT KVM "classic vnc" = vnc server built in in Intel Vpro chipsets. if (INTEL_AMT_KVM_STRING == cl->desktopName) { kDebug(5011) << "Intel(R) AMT KVM: switching to 8 bit color depth (workaround, recent libvncserver needed)"; - t->setColorDepth(bpp8); + setColorDepth(bpp8); } - setClientColorDepth(cl, t->colorDepth()); + setClientColorDepth(cl, colorDepth()); const int width = cl->width, height = cl->height, depth = cl->format.bitsPerPixel; const int size = width * height * (depth / 8); - if (t->frameBuffer) - delete [] t->frameBuffer; // do not leak if we get a new framebuffer size - t->frameBuffer = new uint8_t[size]; - cl->frameBuffer = t->frameBuffer; + if (frameBuffer) + delete [] frameBuffer; // do not leak if we get a new framebuffer size + frameBuffer = new uint8_t[size]; + cl->frameBuffer = frameBuffer; memset(cl->frameBuffer, '\0', size); - switch (t->quality()) { + switch (quality()) { case RemoteView::High: cl->appData.encodingsString = "copyrect zlib hextile raw"; cl->appData.compressLevel = 0; @@ -124,15 +178,13 @@ return true; } -void VncClientThread::updatefb(rfbClient* cl, int x, int y, int w, int h) +void VncClientThread::updatefb(int x, int y, int w, int h) { // kDebug(5011) << "updated client: x: " << x << ", y: " << y << ", w: " << w << ", h: " << h; - VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0); - Q_ASSERT(t); const int width = cl->width, height = cl->height; QImage img; - switch(t->colorDepth()) { + switch(colorDepth()) { case bpp8: img = QImage(cl->frameBuffer, width, height, QImage::Format_Indexed8); img.setColorTable(m_colorTable); @@ -149,62 +201,55 @@ kDebug(5011) << "image not loaded"; } - if (t->m_stopped) { + if (m_stopped) { return; // sending data to a stopped thread is not a good idea } - t->setImage(img); + setImage(img); - t->emitUpdated(x, y, w, h); + emitUpdated(x, y, w, h); } -void VncClientThread::cuttext(rfbClient* cl, const char *text, int textlen) +void VncClientThread::cuttext(const char *text, int textlen) { const QString cutText = QString::fromUtf8(text, textlen); kDebug(5011) << cutText; if (!cutText.isEmpty()) { - VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0); - Q_ASSERT(t); - - t->emitGotCut(cutText); + emitGotCut(cutText); } } -char *VncClientThread::passwdHandler(rfbClient *cl) +char *VncClientThread::passwdHandler() { kDebug(5011) << "password request"; - VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0); - Q_ASSERT(t); - - t->passwordRequest(); - t->m_passwordError = true; - - return strdup(t->password().toUtf8()); + // Never request a password during a reconnect attempt. + if (!m_keepalive.failed) { + passwordRequest(); + m_passwordError = true; + } + return strdup(m_password.toUtf8()); } - -rfbCredential *VncClientThread::credentialHandler(rfbClient *cl, int credentialType) + +rfbCredential *VncClientThread::credentialHandler(int credentialType) { kDebug(5011) << "credential request" << credentialType; - VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0); - Q_ASSERT(t); - rfbCredential *cred = 0; switch (credentialType) { case rfbCredentialTypeUser: - t->passwordRequest(true); - t->m_passwordError = true; + passwordRequest(true); + m_passwordError = true; cred = new rfbCredential; - cred->userCredential.username = strdup(t->username().toUtf8()); - cred->userCredential.password = strdup(t->password().toUtf8()); + cred->userCredential.username = strdup(username().toUtf8()); + cred->userCredential.password = strdup(password().toUtf8()); break; default: kError(5011) << "credential request failed, unspported credentialType:" << credentialType; - t->outputErrorMessage(i18n("VNC authentication type is not supported.")); + outputErrorMessage(i18n("VNC authentication type is not supported.")); break; } return cred; @@ -225,19 +270,51 @@ kDebug(5011) << message; if ((message.contains("Couldn't convert ")) || - (message.contains("Unable to connect to VNC server"))) - outputErrorMessageString = i18n("Server not found."); + (message.contains("Unable to connect to VNC server"))) { + // Don't show a dialog if a reconnection is needed. Never contemplate + // reconnection if we don't have a password. + QString tmp = i18n("Server not found."); + if (m_keepalive.set && !m_password.isNull()) { + m_keepalive.failed = true; + if (m_previousDetails != tmp) { + m_previousDetails = tmp; + clientStateChange(RemoteView::Disconnected, tmp); + } + } else { + outputErrorMessageString = tmp; + } + } + // Process general authentication failures before more specific authentication + // failures. All authentication failures cancel any auto-reconnection that + // may be in progress. + if (message.contains("VNC connection failed: Authentication failed")) { + m_keepalive.failed = false; + outputErrorMessageString = i18n("VNC authentication failed."); + } if ((message.contains("VNC connection failed: Authentication failed, too many tries")) || - (message.contains("VNC connection failed: Too many authentication failures"))) + (message.contains("VNC connection failed: Too many authentication failures"))) { + m_keepalive.failed = false; outputErrorMessageString = i18n("VNC authentication failed because of too many authentication tries."); - - if (message.contains("VNC connection failed: Authentication failed")) - outputErrorMessageString = i18n("VNC authentication failed."); + } if (message.contains("VNC server closed connection")) outputErrorMessageString = i18n("VNC server closed connection."); + // If we are not going to attempt a reconnection, at least tell the user + // the connection went away. + if (message.contains("read (")) { + // Don't show a dialog if a reconnection is needed. Never contemplate + // reconnection if we don't have a password. + QString tmp = i18n("Disconnected: %1.", message); + if (m_keepalive.set && !m_password.isNull()) { + m_keepalive.failed = true; + clientStateChange(RemoteView::Disconnected, tmp); + } else { + outputErrorMessageString = tmp; + } + } + // internal messages, not displayed to user if (message.contains("VNC server supports protocol version 3.889")) // see http://bugs.kde.org/162640 outputErrorMessageString = "INTERNAL:APPLE_VNC_COMPATIBILTY"; @@ -249,6 +326,14 @@ , cl(0) , m_stopped(false) { + // We choose a small value for interval...after all if the connection is + // supposed to sustain a VNC session, a reasonably frequent ping should + // be perfectly supportable. + m_keepalive.intervalSeconds = 1; + m_keepalive.failedProbes = 3; + m_keepalive.set = false; + m_keepalive.failed = false; + m_previousDetails = QString::null; outputErrorMessageString.clear(); //don't deliver error messages of old instances... QMutexLocker locker(&mutex); @@ -267,10 +352,7 @@ kDebug(5011) << "Attempting to stop in deconstructor, will crash if this fails:" << quitSuccess; } - if (cl) { - // Disconnect from vnc server & cleanup allocated resources - rfbClientCleanup(cl); - } + clientDestroy(); delete [] frameBuffer; } @@ -367,47 +449,30 @@ { QMutexLocker locker(&mutex); + VncClientThread **threadTls = new VncClientThread *(); + *threadTls = this; + instances.setLocalData(threadTls); while (!m_stopped) { // try to connect as long as the server allows locker.relock(); m_passwordError = false; locker.unlock(); - rfbClientLog = outputHandler; - rfbClientErr = outputHandler; - //24bit color dept in 32 bits per pixel = default. Will change colordepth and bpp later if needed - cl = rfbGetClient(8, 3, 4); - setClientColorDepth(cl, this->colorDepth()); - cl->MallocFrameBuffer = newclient; - cl->canHandleNewFBSize = true; - cl->GetPassword = passwdHandler; - cl->GetCredential = credentialHandler; - cl->GotFrameBufferUpdate = updatefb; - cl->GotXCutText = cuttext; - rfbClientSetClientData(cl, 0, this); - - locker.relock(); - cl->serverHost = strdup(m_host.toUtf8().constData()); - - if (m_port < 0 || !m_port) // port is invalid or empty... - m_port = 5900; // fallback: try an often used VNC port - - if (m_port >= 0 && m_port < 100) // the user most likely used the short form (e.g. :1) - m_port += 5900; - cl->serverPort = m_port; - locker.unlock(); - - kDebug(5011) << "--------------------- trying init ---------------------"; - - if (rfbInitClient(cl, 0, 0)) + if (clientCreate(false)) { + // The initial connection attempt worked! break; - else - cl = 0; + } locker.relock(); - if (m_passwordError) + if (m_passwordError) { + locker.unlock(); + // Try again. continue; + } - return; + // The initial connection attempt failed, and not because of a + // password problem. Bail out. + m_stopped = true; + locker.unlock(); } locker.relock(); @@ -420,6 +485,18 @@ } if (i) { if (!HandleRFBServerMessage(cl)) { + if (m_keepalive.failed) { + do { + // Reconnect after a short delay. That way, if the + // attempt fails very quickly, we don't sit in a very + // tight loop. + clientDestroy(); + msleep(1000); + clientStateChange(RemoteView::Connecting, i18n("Reconnecting.")); + } while (!clientCreate(true)); + continue; + } + kError(5011) << "HandleRFBServerMessage failed"; break; } } @@ -437,6 +514,125 @@ m_stopped = true; } +/** + * Factor out the initialisation of the VNC client library. Notice this has + * both static parts as in @see rfbClientLog and @see rfbClientErr, + * as well as instance local data @see rfbGetClient(). + * + * On return from here, if cl is set, the connection will have been made else + * cl will not be set. + */ +bool VncClientThread::clientCreate(bool reinitialising) +{ + rfbClientLog = outputHandlerStatic; + rfbClientErr = outputHandlerStatic; + + //24bit color dept in 32 bits per pixel = default. Will change colordepth and bpp later if needed + cl = rfbGetClient(8, 3, 4); + setClientColorDepth(cl, this->colorDepth()); + cl->MallocFrameBuffer = newclientStatic; + cl->canHandleNewFBSize = true; + cl->GetPassword = passwdHandlerStatic; + cl->GetCredential = credentialHandlerStatic; + cl->GotFrameBufferUpdate = updatefbStatic; + cl->GotXCutText = cuttextStatic; + rfbClientSetClientData(cl, 0, this); + + cl->serverHost = strdup(m_host.toUtf8().constData()); + + if (m_port < 0 || !m_port) // port is invalid or empty... + m_port = 5900; // fallback: try an often used VNC port + + if (m_port >= 0 && m_port < 100) // the user most likely used the short form (e.g. :1) + m_port += 5900; + cl->serverPort = m_port; + + kDebug(5011) << "--------------------- trying init ---------------------"; + + if (!rfbInitClient(cl, 0, 0)) { + if (!reinitialising) { + // Don't whine on reconnection failure: presumably the network + // is simply still down. + kError(5011) << "rfbInitClient failed"; + } + cl = 0; + return false; + } + + if (reinitialising) { + clientStateChange(RemoteView::Connected, i18n("Reconnected.")); + } else { + clientStateChange(RemoteView::Connected, i18n("Connected.")); + } + clientSetKeepalive(); + return true; +} + +/** + * Undo @see clientCreate(). + */ +void VncClientThread::clientDestroy() +{ + + if (cl) { + // Disconnect from vnc server & cleanup allocated resources + rfbClientCleanup(cl); + cl = 0; + } +} + +/** + * The VNC client library does not make use of keepalives. We go behind its + * back to set it up. + */ +void VncClientThread::clientSetKeepalive() +{ + // If keepalive is disabled, do nothing. + m_keepalive.set = false; + m_keepalive.failed = false; + if (!m_keepalive.intervalSeconds) { + return; + } + int optval; + socklen_t optlen = sizeof(optval); + + // Try to set the option active + optval = 1; + if (setsockopt(cl->sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { + kError(5011) << "setsockopt(SO_KEEPALIVE)" << strerror(errno); + return; + } + + optval = m_keepalive.intervalSeconds; + if (setsockopt(cl->sock, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { + kError(5011) << "setsockopt(TCP_KEEPIDLE)" << strerror(errno); + return; + } + + optval = m_keepalive.intervalSeconds; + if (setsockopt(cl->sock, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { + kError(5011) << "setsockopt(TCP_KEEPINTVL)" << strerror(errno); + return; + } + + optval = m_keepalive.failedProbes; + if(setsockopt(cl->sock, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { + kError(5011) << "setsockopt(TCP_KEEPCNT)" << strerror(errno); + return; + } + m_keepalive.set = true; + kDebug(5011) << "TCP keepalive set"; +} + +/** + * The VNC client state changed. + */ +void VncClientThread::clientStateChange(RemoteView::RemoteStatus status, const QString &details) +{ + kDebug(5011) << status << details << m_host << ":" << m_port; + emit clientStateChanged(status, details); +} + ClientEvent::~ClientEvent() { } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krdc-4.11.2/vnc/vncclientthread.h new/krdc-4.11.90/vnc/vncclientthread.h --- old/krdc-4.11.2/vnc/vncclientthread.h 2013-08-28 19:16:31.000000000 +0200 +++ new/krdc-4.11.90/vnc/vncclientthread.h 2013-11-07 10:47:57.000000000 +0100 @@ -139,6 +139,14 @@ void passwordRequest(bool includingUsername = false); void outputErrorMessage(const QString &message); + /** + * When we connect/disconnect/reconnect/etc., this signal will be emitted. + * + * @param status Is the client connected? + * @param details A sentence describing what happened. + */ + void clientStateChanged(RemoteView::RemoteStatus status, const QString &details); + public slots: void mouseEvent(int x, int y, int buttonMask); void keyEvent(int key, bool pressed); @@ -148,15 +156,26 @@ void run(); private: - static void setClientColorDepth(rfbClient *cl, ColorDepth cd); + void setClientColorDepth(rfbClient *cl, ColorDepth cd); void setColorDepth(ColorDepth colorDepth); - //these static methods are callback functions for libvncclient - static rfbBool newclient(rfbClient *cl); - static void updatefb(rfbClient *cl, int x, int y, int w, int h); - static void cuttext(rfbClient *cl, const char *text, int textlen); - static char* passwdHandler(rfbClient *cl); - static rfbCredential* credentialHandler(rfbClient *cl, int credentialType); - static void outputHandler(const char *format, ...); + + // These static methods are callback functions for libvncclient. Each + // of them calls back into the corresponding member function via some + // TLS-based logic. + static rfbBool newclientStatic(rfbClient *cl); + static void updatefbStatic(rfbClient *cl, int x, int y, int w, int h); + static void cuttextStatic(rfbClient *cl, const char *text, int textlen); + static char *passwdHandlerStatic(rfbClient *cl); + static rfbCredential *credentialHandlerStatic(rfbClient *cl, int credentialType); + static void outputHandlerStatic(const char *format, ...); + + // Member functions corresponding to the above static methods. + rfbBool newclient(); + void updatefb(int x, int y, int w, int h); + void cuttext(const char *text, int textlen); + char *passwdHandler(); + rfbCredential *credentialHandler(int credentialType); + void outputHandler(const char *format, ...); QImage m_image; rfbClient *cl; @@ -169,11 +188,48 @@ ColorDepth m_colorDepth; QQueue<ClientEvent* > m_eventQueue; //color table for 8bit indexed colors - static QVector<QRgb> m_colorTable; + QVector<QRgb> m_colorTable; + QString outputErrorMessageString; volatile bool m_stopped; volatile bool m_passwordError; + /** + * Connection keepalive/reconnection support. + */ + struct { + /** + * Number of seconds between probes. If zero, we will not attempt + * to enable it. + */ + int intervalSeconds; + /** + * Number of failed probes required to recognise a disconnect. + */ + int failedProbes; + /** + * Was keepalive successfully set? + */ + bool set; + /** + * Did keepalive detect a disconnect? + */ + volatile bool failed; + } m_keepalive; + + // Initialise the VNC client library object. + bool clientCreate(bool reinitialising); + + // Uninitialise the VNC client library object. + void clientDestroy(); + + // Turn on keepalive support. + void clientSetKeepalive(); + + // Record a state change. + void clientStateChange(RemoteView::RemoteStatus status, const QString &details); + QString m_previousDetails; + private slots: void checkOutputErrorMessage(); }; -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
