• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

krfb

krfbserver.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
00003              (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 */
00010 
00011 
00012 #include "krfbserver.h"
00013 #include "krfbserver.moc"
00014 
00015 #include <QTcpServer>
00016 #include <QTcpSocket>
00017 #include <QTimer>
00018 #include <QHostInfo>
00019 #include <QApplication>
00020 #include <QDesktopWidget>
00021 #include <QPointer>
00022 
00023 #include <KGlobal>
00024 #include <KUser>
00025 #include <KLocale>
00026 #include <KDebug>
00027 #include <KMessageBox>
00028 #include <dnssd/publicservice.h>
00029 
00030 #include "connectioncontroller.h"
00031 #include "framebuffer.h"
00032 #include "krfbconfig.h"
00033 #include "invitationmanager.h"
00034 
00035 #include <X11/Xutil.h>
00036 #include <X11/extensions/XTest.h>
00037 
00038 
00039 static const char* cur=
00040         "                   "
00041         " x                 "
00042         " xx                "
00043         " xxx               "
00044         " xxxx              "
00045         " xxxxx             "
00046         " xxxxxx            "
00047         " xxxxxxx           "
00048         " xxxxxxxx          "
00049         " xxxxxxxxx         "
00050         " xxxxxxxxxx        "
00051         " xxxxx             "
00052         " xx xxx            "
00053         " x  xxx            "
00054         "     xxx           "
00055         "     xxx           "
00056         "      xxx          "
00057         "      xxx          "
00058         "                   ";
00059 
00060 static const char* mask=
00061         "xx                 "
00062         "xxx                "
00063         "xxxx               "
00064         "xxxxx              "
00065         "xxxxxx             "
00066         "xxxxxxx            "
00067         "xxxxxxxx           "
00068         "xxxxxxxxx          "
00069         "xxxxxxxxxx         "
00070         "xxxxxxxxxxx        "
00071         "xxxxxxxxxxxx       "
00072         "xxxxxxxxxx         "
00073         "xxxxxxxx           "
00074         "xxxxxxxx           "
00075         "xx  xxxxx          "
00076         "    xxxxx          "
00077         "     xxxxx         "
00078         "     xxxxx         "
00079         "      xxx          ";
00080 
00081 static rfbCursorPtr myCursor;
00082 
00083 
00084 static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
00085 {
00086     KrfbServer *server = KrfbServer::self();
00087     return server->handleNewClient(cl);
00088 }
00089 
00090 static rfbBool passwordCheck(rfbClientPtr cl,
00091                              const char* encryptedPassword,
00092                              int len)
00093 {
00094     ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
00095     return cc->handleCheckPassword(cl, encryptedPassword, len);
00096 }
00097 
00098 static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
00099 {
00100     ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
00101     cc->handleKeyEvent(down ? true : false, keySym);
00102 }
00103 
00104 static void pointerHook(int bm, int x, int y, rfbClientPtr cl)
00105 {
00106     ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
00107     cc->handlePointerEvent(bm, x, y);
00108 }
00109 
00110 static void clipboardHook(char* str,int len, rfbClientPtr cl)
00111 {
00112     ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
00113     cc->clipboardToServer(QString::fromUtf8(str, len));
00114 }
00115 
00116 
00117 class KrfbServer::KrfbServerP {
00118 
00119     public:
00120         KrfbServerP() : fb(0), screen(0), numClients(0) {};
00121 
00122         FrameBuffer *fb;
00123         QList< QPointer<ConnectionController> > controllers;
00124         rfbScreenInfoPtr screen;
00125         bool running;
00126         int numClients;
00127         QByteArray desktopName;
00128 };
00129 
00130 class KrfbServerPrivate
00131 {
00132 public:
00133     KrfbServer instance;
00134 };
00135 
00136 K_GLOBAL_STATIC(KrfbServerPrivate, krfbServerPrivate)
00137 
00138 KrfbServer * KrfbServer::self() {
00139     return &krfbServerPrivate->instance;
00140 }
00141 
00142 
00143 KrfbServer::KrfbServer()
00144     :d(new KrfbServerP)
00145 {
00146     kDebug() << "starting ";
00147     d->running = true;
00148     d->fb = FrameBuffer::getFrameBuffer(QApplication::desktop()->winId(), this);
00149     QTimer::singleShot(0, this, SLOT(startListening()));
00150     connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),SLOT(updatePassword()));
00151 }
00152 
00153 KrfbServer::~KrfbServer()
00154 {
00155     delete d;
00156 }
00157 
00158 
00159 void KrfbServer::startListening()
00160 {
00161     rfbScreenInfoPtr screen;
00162 
00163     int port = KrfbConfig::port();
00164 
00165     int w = d->fb->width();
00166     int h = d->fb->height();
00167     int depth = d->fb->depth();
00168 
00169     rfbLogEnable(0);
00170     screen = rfbGetScreen(0, 0, w, h, 8, 3,depth / 8);
00171     screen->paddedWidthInBytes = d->fb->paddedWidth();
00172 
00173     d->fb->getServerFormat(screen->serverFormat);
00174 
00175     screen->frameBuffer = d->fb->data();
00176     d->screen = screen;
00177     screen->autoPort = 0;
00178     screen->port = port;
00179 
00180     // server hooks
00181     screen->newClientHook = newClientHook;
00182 
00183     screen->kbdAddEvent = keyboardHook;
00184     screen->ptrAddEvent = pointerHook;
00185     screen->newClientHook = newClientHook;
00186     screen->passwordCheck = passwordCheck;
00187     screen->setXCutText = clipboardHook;
00188 
00189     d->desktopName = i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()).toLatin1();
00190     screen->desktopName = d->desktopName.constData();
00191 
00192     if (!myCursor) {
00193         myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
00194     }
00195     screen->cursor = myCursor;
00196 
00197     // configure passwords and desktop control here
00198     updateSettings();
00199 
00200     rfbInitServer(screen);
00201     if (!rfbIsActive(screen)) {
00202         KMessageBox::error(0,"krfb","Address already in use");
00203         disconnectAndQuit();
00204     };
00205 
00206     if (KrfbConfig::publishService()) {
00207         DNSSD::PublicService *service = new DNSSD::PublicService(i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()),"_rfb._tcp",port);
00208         service->publishAsync();
00209     }
00210 
00211     while (d->running) {
00212         foreach(QRect r, d->fb->modifiedTiles()) {
00213             rfbMarkRectAsModified(screen, r.x(), r.y(), r.right(), r.bottom());
00214         }
00215         rfbProcessEvents(screen, 100);
00216         qApp->processEvents();
00217     }
00218     rfbShutdownServer(screen, true);
00219     // framebuffer has to be deleted before X11 connection goes down
00220     delete d->fb;
00221     d->fb = 0;
00222 
00223     emit quitApp();
00224 }
00225 
00226 
00227 void KrfbServer::enableDesktopControl(bool enable)
00228 {
00229     foreach (QPointer<ConnectionController> ptr, d->controllers) {
00230         if (ptr) {
00231             ptr->setControlEnabled(enable);
00232         }
00233     }
00234 }
00235 
00236 void KrfbServer::disconnectAndQuit()
00237 {
00238     d->running = false;
00239 }
00240 
00241 enum rfbNewClientAction KrfbServer::handleNewClient(struct _rfbClientRec * cl)
00242 {
00243     ConnectionController *cc = new ConnectionController(cl, this);
00244     if (d->numClients++ == 0)
00245         d->fb->startMonitor();
00246 
00247     d->controllers.append(cc);
00248     cc->setControlEnabled(KrfbConfig::allowDesktopControl());
00249 
00250     connect(cc, SIGNAL(sessionEstablished(QString)), SIGNAL(sessionEstablished(QString)));
00251     connect(cc, SIGNAL(clientDisconnected(ConnectionController *)),SLOT(clientDisconnected(ConnectionController *)));
00252 
00253     return cc->handleNewClient();
00254 }
00255 
00256 void KrfbServer::updateSettings()
00257 {
00258     enableDesktopControl(KrfbConfig::allowDesktopControl());
00259     updatePassword();
00260 }
00261 
00262 void KrfbServer::updatePassword()
00263 {
00264 
00265     if (!d->screen) return;
00266     QString pw = KrfbConfig::uninvitedConnectionPassword();
00267     kDebug() << "password: " << pw << " allow " <<
00268             KrfbConfig::allowUninvitedConnections() <<
00269             " invitations " << InvitationManager::self()->activeInvitations() << endl;
00270 
00271     if (pw.isEmpty() && InvitationManager::self()->activeInvitations() == 0) {
00272         kDebug() << "no password from now on";
00273         d->screen->authPasswdData = (void *)0;
00274     } else {
00275         kDebug() << "Ask for password to accept connections";
00276         d->screen->authPasswdData = (void *)1;
00277     }
00278 }
00279 
00280 bool KrfbServer::checkX11Capabilities() {
00281     int bp1, bp2, majorv, minorv;
00282     Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
00283                                  &majorv, &minorv);
00284     if ((!r) || (((majorv*1000)+minorv) < 2002)) {
00285         KMessageBox::error(0,
00286                            i18n("Your X11 Server does not support the required XTest extension version 2.2. Sharing your desktop is not possible."),
00287                                 i18n("Desktop Sharing Error"));
00288         return false;
00289     }
00290 
00291     return true;
00292 }
00293 
00294 void KrfbServer::clientDisconnected(ConnectionController *cc)
00295 {
00296     kDebug() << "clients--: " << d->numClients;
00297     if (!--d->numClients) {
00298         d->fb->stopMonitor();
00299     }
00300     disconnect(cc, SIGNAL(clientDisconnected(ConnectionController)),this, SLOT(clientDisconnected(ConnectionController)));
00301 }
00302 
00303 

krfb

Skip menu "krfb"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal