no more compiling warnings in the whole KGet source code:
[kdenetwork.git] / krfb / krfbserver.cpp
blob0f39ec3ee986fb3c0134cd29e3301f6f78d27bdb
1 /* This file is part of the KDE project
2 Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
3 (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; version 2
8 of the License.
9 */
12 #include "krfbserver.h"
13 #include "krfbserver.moc"
15 #include <QTcpServer>
16 #include <QTcpSocket>
17 #include <QTimer>
18 #include <QHostInfo>
19 #include <QApplication>
20 #include <QDesktopWidget>
21 #include <QPointer>
23 #include <KGlobal>
24 #include <KUser>
25 #include <KLocale>
26 #include <KStaticDeleter>
27 #include <KMessageBox>
28 #include <dnssd/publicservice.h>
30 #include "connectioncontroller.h"
31 #include "framebuffer.h"
32 #include "krfbconfig.h"
33 #include "invitationmanager.h"
35 #include <X11/Xutil.h>
36 #include <X11/extensions/XTest.h>
39 static const char* cur=
40 " "
41 " x "
42 " xx "
43 " xxx "
44 " xxxx "
45 " xxxxx "
46 " xxxxxx "
47 " xxxxxxx "
48 " xxxxxxxx "
49 " xxxxxxxxx "
50 " xxxxxxxxxx "
51 " xxxxx "
52 " xx xxx "
53 " x xxx "
54 " xxx "
55 " xxx "
56 " xxx "
57 " xxx "
58 " ";
60 static const char* mask=
61 "xx "
62 "xxx "
63 "xxxx "
64 "xxxxx "
65 "xxxxxx "
66 "xxxxxxx "
67 "xxxxxxxx "
68 "xxxxxxxxx "
69 "xxxxxxxxxx "
70 "xxxxxxxxxxx "
71 "xxxxxxxxxxxx "
72 "xxxxxxxxxx "
73 "xxxxxxxx "
74 "xxxxxxxx "
75 "xx xxxxx "
76 " xxxxx "
77 " xxxxx "
78 " xxxxx "
79 " xxx ";
81 static rfbCursorPtr myCursor;
84 static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
86 KrfbServer *server = KrfbServer::self();
87 return server->handleNewClient(cl);
90 static rfbBool passwordCheck(rfbClientPtr cl,
91 const char* encryptedPassword,
92 int len)
94 ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
95 return cc->handleCheckPassword(cl, encryptedPassword, len);
98 static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
100 ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
101 cc->handleKeyEvent(down ? true : false, keySym);
104 static void pointerHook(int bm, int x, int y, rfbClientPtr cl)
106 ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
107 cc->handlePointerEvent(bm, x, y);
110 static void clipboardHook(char* str,int len, rfbClientPtr cl)
112 ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
113 cc->clipboardToServer(QString::fromUtf8(str, len));
117 class KrfbServer::KrfbServerP {
119 public:
120 KrfbServerP() : fb(0), screen(0), numClients(0) {};
122 FrameBuffer *fb;
123 QList< QPointer<ConnectionController> > controllers;
124 rfbScreenInfoPtr screen;
125 bool running;
126 int numClients;
127 QByteArray desktopName;
131 static KStaticDeleter<KrfbServer> sdServer;
132 KrfbServer * KrfbServer::_self = 0;
133 KrfbServer * KrfbServer::self() {
134 if (!_self) sdServer.setObject(_self, new KrfbServer);
135 return _self;
139 KrfbServer::KrfbServer()
140 :d(new KrfbServerP)
142 kDebug() << "starting " << endl;
143 d->running = true;
144 d->fb = FrameBuffer::getFrameBuffer(QApplication::desktop()->winId(), this);
145 QTimer::singleShot(0, this, SLOT(startListening()));
146 connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),SLOT(updatePassword()));
150 KrfbServer::~KrfbServer()
152 delete d;
156 void KrfbServer::startListening()
158 rfbScreenInfoPtr screen;
160 int port = KrfbConfig::port();
162 int w = d->fb->width();
163 int h = d->fb->height();
164 int depth = d->fb->depth();
166 rfbLogEnable(0);
167 screen = rfbGetScreen(0, 0, w, h, 8, 3,depth / 8);
168 screen->paddedWidthInBytes = d->fb->paddedWidth();
170 d->fb->getServerFormat(screen->serverFormat);
172 screen->frameBuffer = d->fb->data();
173 d->screen = screen;
174 screen->autoPort = 0;
175 screen->port = port;
177 // server hooks
178 screen->newClientHook = newClientHook;
180 screen->kbdAddEvent = keyboardHook;
181 screen->ptrAddEvent = pointerHook;
182 screen->newClientHook = newClientHook;
183 screen->passwordCheck = passwordCheck;
184 screen->setXCutText = clipboardHook;
186 d->desktopName = i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()).toLatin1();
187 screen->desktopName = d->desktopName.constData();
189 if (!myCursor) {
190 myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
192 screen->cursor = myCursor;
194 // configure passwords and desktop control here
195 updateSettings();
197 rfbInitServer(screen);
198 if (!rfbIsActive(screen)) {
199 KMessageBox::error(0,"krfb","Address already in use");
200 disconnectAndQuit();
203 if (KrfbConfig::publishService()) {
204 DNSSD::PublicService *service = new DNSSD::PublicService(i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()),"_rfb._tcp",port);
205 service->publishAsync();
208 while (d->running) {
209 foreach(QRect r, d->fb->modifiedTiles()) {
210 rfbMarkRectAsModified(screen, r.x(), r.y(), r.right(), r.bottom());
212 rfbProcessEvents(screen, 100);
213 qApp->processEvents();
215 rfbShutdownServer(screen, true);
216 emit quitApp();
220 void KrfbServer::enableDesktopControl(bool enable)
222 foreach (QPointer<ConnectionController> ptr, d->controllers) {
223 if (ptr) {
224 ptr->setControlEnabled(enable);
229 void KrfbServer::disconnectAndQuit()
231 d->running = false;
234 enum rfbNewClientAction KrfbServer::handleNewClient(struct _rfbClientRec * cl)
236 ConnectionController *cc = new ConnectionController(cl, this);
237 if (d->numClients == 0) {
238 d->fb->startMonitor();
239 d->numClients++;
242 d->controllers.append(cc);
243 cc->setControlEnabled(KrfbConfig::allowDesktopControl());
245 connect(cc, SIGNAL(sessionEstablished(QString)), SIGNAL(sessionEstablished(QString)));
246 connect(cc, SIGNAL(clientDisconnected(ConnectionController *)),SLOT(clientDisconnected(ConnectionController *)));
248 return cc->handleNewClient();
251 void KrfbServer::updateSettings()
253 enableDesktopControl(KrfbConfig::allowDesktopControl());
254 updatePassword();
257 void KrfbServer::updatePassword()
260 if (!d->screen) return;
261 QString pw = KrfbConfig::uninvitedConnectionPassword();
262 kDebug() << "password: " << pw << " allow " <<
263 KrfbConfig::allowUninvitedConnections() <<
264 " invitations " << InvitationManager::self()->activeInvitations() << endl;
266 if (pw.isEmpty() && InvitationManager::self()->activeInvitations() == 0) {
267 kDebug() << "no password from now on" << endl;
268 d->screen->authPasswdData = (void *)0;
269 } else {
270 kDebug() << "Ask for password to accept connections" << endl;
271 d->screen->authPasswdData = (void *)1;
275 bool KrfbServer::checkX11Capabilities() {
276 int bp1, bp2, majorv, minorv;
277 Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
278 &majorv, &minorv);
279 if ((!r) || (((majorv*1000)+minorv) < 2002)) {
280 KMessageBox::error(0,
281 i18n("Your X11 Server does not support the required XTest extension version 2.2. Sharing your desktop is not possible."),
282 i18n("Desktop Sharing Error"));
283 return false;
286 return true;
289 void KrfbServer::clientDisconnected(ConnectionController *cc)
291 kDebug() << "clients--: " << d->numClients << endl;
292 d->numClients--;
293 if (d->numClients == 0) {
294 d->fb->stopMonitor();
296 disconnect(cc, SIGNAL(clientDisconnected(ConnectionController)),this, SLOT(clientDisconnected(ConnectionController)));