mirror of
https://github.com/KDE/krfb
synced 2026-07-01 15:31:19 -07:00
Make RFB server and COnnectionCOntroller classes abstract and make one implementation of them for the standard rfb use case.
svn path=/trunk/KDE/kdenetwork/krfb/; revision=1189033
This commit is contained in:
@@ -83,18 +83,20 @@ add_subdirectory (framebuffers)
|
||||
set(krfb_SRCS
|
||||
main.cpp
|
||||
trayicon.cpp
|
||||
krfbserver.cpp
|
||||
manageinvitationsdialog.cpp
|
||||
invitationmanager.cpp
|
||||
invitedialog.cpp
|
||||
invitation.cpp
|
||||
connectiondialog.cpp
|
||||
personalinvitedialog.cpp
|
||||
connectioncontroller.cpp
|
||||
events.cpp
|
||||
framebuffermanager.cpp
|
||||
servermanager.cpp
|
||||
sockethelpers.cpp
|
||||
abstractrfbserver.cpp
|
||||
abstractconnectioncontroller.cpp
|
||||
krfbserver.cpp
|
||||
krfbconnectioncontroller.cpp
|
||||
)
|
||||
|
||||
kde4_add_kcfg_files(krfb_SRCS krfbconfig.kcfgc)
|
||||
|
||||
143
abstractconnectioncontroller.cpp
Normal file
143
abstractconnectioncontroller.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/* This file is part of the KDE project
|
||||
* Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
* @author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
* Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
* Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// RFB.H Why do you have to redefine the whole of fscking c++???
|
||||
#include <KDebug>
|
||||
|
||||
#include "abstractconnectioncontroller.h"
|
||||
|
||||
#include "abstractrfbserver.h"
|
||||
#include "connectiondialog.h"
|
||||
#include "events.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void clientGoneHook(rfbClientPtr cl)
|
||||
{
|
||||
AbstractConnectionController *cc = static_cast<AbstractConnectionController *>(cl->clientData);
|
||||
cc->handleClientGone();
|
||||
}
|
||||
|
||||
bool checkPassword(const QString &p, unsigned char *ochallenge, const char *response, int len)
|
||||
{
|
||||
if ((len == 0) && (p.length() == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char passwd[MAXPWLEN];
|
||||
unsigned char challenge[CHALLENGESIZE];
|
||||
|
||||
memcpy(challenge, ochallenge, CHALLENGESIZE);
|
||||
bzero(passwd, MAXPWLEN);
|
||||
if (!p.isNull()) {
|
||||
strncpy(passwd, p.toLatin1(),
|
||||
(MAXPWLEN <= p.length()) ? MAXPWLEN : p.length());
|
||||
}
|
||||
|
||||
rfbEncryptBytes(challenge, passwd);
|
||||
return memcmp(challenge, response, len) == 0;
|
||||
}
|
||||
|
||||
AbstractConnectionController::AbstractConnectionController(struct _rfbClientRec *_cl,
|
||||
AbstractRfbServer *parent)
|
||||
: QObject(parent),
|
||||
cl(_cl)
|
||||
{
|
||||
kDebug();
|
||||
|
||||
// Set the rfbClientRec client data to point to this ConnectionController so the callbacks
|
||||
// can get the right object.
|
||||
cl->clientData = (void*)this;
|
||||
|
||||
// Set the client gone hook. The ConnectionController is responsible for determining what
|
||||
// actions to take based on the state of the client in handleClientGone().
|
||||
cl->clientGoneHook = clientGoneHook;
|
||||
}
|
||||
|
||||
AbstractConnectionController::~AbstractConnectionController()
|
||||
{
|
||||
kDebug();
|
||||
}
|
||||
|
||||
void AbstractConnectionController::dialogAccepted()
|
||||
{
|
||||
ConnectionDialog *dialog = qobject_cast<ConnectionDialog*>(sender());
|
||||
|
||||
if (!dialog) {
|
||||
kWarning() << "Wrong type of sender.";
|
||||
return;
|
||||
}
|
||||
// rfbStartOnHoldClient(cl);
|
||||
cl->onHold = false;
|
||||
setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
setControlCanBeEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
emit sessionEstablished(remoteIp);
|
||||
}
|
||||
|
||||
void AbstractConnectionController::dialogRejected()
|
||||
{
|
||||
kDebug() << "refused connection";
|
||||
rfbRefuseOnHoldClient(cl);
|
||||
}
|
||||
|
||||
void AbstractConnectionController::handleKeyEvent(bool down, rfbKeySym keySym)
|
||||
{
|
||||
if (controlEnabled) {
|
||||
KeyboardEvent ev(down, keySym);
|
||||
ev.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractConnectionController::handlePointerEvent(int bm, int x, int y)
|
||||
{
|
||||
if (controlEnabled) {
|
||||
PointerEvent ev(bm, x, y);
|
||||
ev.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractConnectionController::clipboardToServer(const QString &s)
|
||||
{
|
||||
ClipboardEvent ev(this, s);
|
||||
ev.exec();
|
||||
}
|
||||
|
||||
void AbstractConnectionController::setControlEnabled(bool enable)
|
||||
{
|
||||
if (m_controlCanBeEnabled) {
|
||||
controlEnabled = enable;
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractConnectionController::setControlCanBeEnabled(bool canBeEnabled)
|
||||
{
|
||||
m_controlCanBeEnabled = canBeEnabled;
|
||||
}
|
||||
|
||||
bool AbstractConnectionController::controlCanBeEnabled() const
|
||||
{
|
||||
return m_controlCanBeEnabled;
|
||||
}
|
||||
|
||||
|
||||
#include "abstractconnectioncontroller.moc"
|
||||
|
||||
72
abstractconnectioncontroller.h
Normal file
72
abstractconnectioncontroller.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* This file is part of the KDE project
|
||||
* Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
* @author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
* Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_ABSTRACTCONNECTIONCONTROLLER_H
|
||||
#define KRFB_ABSTRACTCONNECTIONCONTROLLER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
class AbstractRfbServer;
|
||||
|
||||
bool checkPassword(const QString &p, unsigned char *ochallenge, const char *response, int len);
|
||||
|
||||
class AbstractConnectionController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AbstractConnectionController(struct _rfbClientRec *_cl, AbstractRfbServer *parent);
|
||||
|
||||
virtual ~AbstractConnectionController();
|
||||
|
||||
virtual bool handleCheckPassword(rfbClientPtr cl, const char *response, int len) = 0;
|
||||
virtual void handleKeyEvent(bool down, rfbKeySym keySym);
|
||||
virtual void handlePointerEvent(int bm, int x, int y);
|
||||
virtual void handleClientGone() = 0;
|
||||
virtual void clipboardToServer(const QString &);
|
||||
|
||||
virtual enum rfbNewClientAction handleNewClient() = 0;
|
||||
|
||||
virtual void setControlEnabled(bool enable);
|
||||
|
||||
virtual void setControlCanBeEnabled(bool canBeEnabled);
|
||||
virtual bool controlCanBeEnabled() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sessionEstablished(QString);
|
||||
void clientDisconnected(AbstractConnectionController *);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void dialogAccepted();
|
||||
void dialogRejected();
|
||||
|
||||
protected:
|
||||
QString remoteIp;
|
||||
struct _rfbClientRec *cl;
|
||||
bool controlEnabled;
|
||||
bool m_controlCanBeEnabled;
|
||||
};
|
||||
|
||||
|
||||
#endif // Header Guard
|
||||
|
||||
386
abstractrfbserver.cpp
Normal file
386
abstractrfbserver.cpp
Normal file
@@ -0,0 +1,386 @@
|
||||
/* This file is part of the KDE project
|
||||
* Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
* @author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// FUCKING RFB.H DIE DAMMIT
|
||||
#include "servermanager.h"
|
||||
|
||||
#include "abstractrfbserver.h"
|
||||
|
||||
#include "abstractconnectioncontroller.h"
|
||||
#include "framebuffer.h"
|
||||
#include "invitationmanager.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "sockethelpers.h"
|
||||
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
#include <KMessageBox>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
static const char* cur=
|
||||
" "
|
||||
" x "
|
||||
" xx "
|
||||
" xxx "
|
||||
" xxxx "
|
||||
" xxxxx "
|
||||
" xxxxxx "
|
||||
" xxxxxxx "
|
||||
" xxxxxxxx "
|
||||
" xxxxxxxxx "
|
||||
" xxxxxxxxxx "
|
||||
" xxxxx "
|
||||
" xx xxx "
|
||||
" x xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" ";
|
||||
|
||||
static const char* mask=
|
||||
"xx "
|
||||
"xxx "
|
||||
"xxxx "
|
||||
"xxxxx "
|
||||
"xxxxxx "
|
||||
"xxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxxxxx "
|
||||
"xxxxxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xx xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxx ";
|
||||
|
||||
static rfbCursorPtr myCursor;
|
||||
|
||||
|
||||
static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
|
||||
{
|
||||
AbstractRfbServer *server = ServerManager::instance()->serverForClient(cl);
|
||||
return server->handleNewClient(cl);
|
||||
}
|
||||
|
||||
static rfbBool passwordCheck(rfbClientPtr cl,
|
||||
const char* encryptedPassword,
|
||||
int len)
|
||||
{
|
||||
AbstractConnectionController *cc = static_cast<AbstractConnectionController *>(cl->clientData);
|
||||
return cc->handleCheckPassword(cl, encryptedPassword, len);
|
||||
}
|
||||
|
||||
static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
|
||||
{
|
||||
AbstractConnectionController *cc = static_cast<AbstractConnectionController *>(cl->clientData);
|
||||
cc->handleKeyEvent(down ? true : false, keySym);
|
||||
}
|
||||
|
||||
static void pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||
{
|
||||
AbstractConnectionController *cc = static_cast<AbstractConnectionController *>(cl->clientData);
|
||||
cc->handlePointerEvent(bm, x, y);
|
||||
}
|
||||
|
||||
static void clipboardHook(char* str,int len, rfbClientPtr cl)
|
||||
{
|
||||
AbstractConnectionController *cc = static_cast<AbstractConnectionController *>(cl->clientData);
|
||||
cc->clipboardToServer(QString::fromUtf8(str, len));
|
||||
}
|
||||
|
||||
|
||||
class AbstractRfbServer::AbstractRfbServerPrivate {
|
||||
public:
|
||||
AbstractRfbServerPrivate()
|
||||
: port(0), screen(0), numClients(0), listeningPort(0),
|
||||
passwordRequired(true)
|
||||
{
|
||||
address = "0.0.0.0";
|
||||
desktopName = "Shared Desktop";
|
||||
}
|
||||
|
||||
// Parameters for startListening();
|
||||
QByteArray address;
|
||||
int port;
|
||||
QSharedPointer<FrameBuffer> fb;
|
||||
rfbScreenInfoPtr screen;
|
||||
QByteArray desktopName;
|
||||
QTimer rfbProcessEventTimer;
|
||||
int numClients;
|
||||
QList< QPointer<AbstractConnectionController> > controllers;
|
||||
|
||||
QString listeningAddress;
|
||||
unsigned int listeningPort;
|
||||
|
||||
bool passwordRequired;
|
||||
};
|
||||
|
||||
AbstractRfbServer::AbstractRfbServer()
|
||||
: d(new AbstractRfbServerPrivate)
|
||||
{
|
||||
kDebug();
|
||||
}
|
||||
|
||||
AbstractRfbServer::~AbstractRfbServer()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::startListening()
|
||||
{
|
||||
if (d->fb.isNull()) {
|
||||
kWarning() << "Cannot start a rfb server without a valid framebuffer.";
|
||||
return;
|
||||
}
|
||||
|
||||
rfbScreenInfoPtr screen;
|
||||
|
||||
int w = d->fb->width();
|
||||
int h = d->fb->height();
|
||||
int depth = d->fb->depth();
|
||||
|
||||
int bpp = depth >> 3;
|
||||
if (bpp != 1 && bpp != 2 && bpp != 4) bpp = 4;
|
||||
kDebug() << "bpp: " << bpp;
|
||||
|
||||
rfbLogEnable(0);
|
||||
screen = rfbGetScreen(0, 0, w, h, 8, 3, bpp);
|
||||
|
||||
screen->paddedWidthInBytes = d->fb->paddedWidth();
|
||||
|
||||
d->fb->getServerFormat(screen->serverFormat);
|
||||
|
||||
screen->frameBuffer = d->fb->data();
|
||||
d->screen = screen;
|
||||
|
||||
if (d->address != "0.0.0.0") {
|
||||
d->address.resize(254);
|
||||
strcpy(screen->thisHost, d->address.data());
|
||||
}
|
||||
|
||||
if (d->port == 0) {
|
||||
screen->autoPort = 1;
|
||||
}
|
||||
|
||||
screen->port = d->port;
|
||||
|
||||
// Disable/Enable password checking
|
||||
if (d->passwordRequired) {
|
||||
d->screen->authPasswdData = (void *)1;
|
||||
} else {
|
||||
d->screen->authPasswdData = (void *)0;
|
||||
}
|
||||
|
||||
// server hooks
|
||||
screen->newClientHook = newClientHook;
|
||||
|
||||
screen->kbdAddEvent = keyboardHook;
|
||||
screen->ptrAddEvent = pointerHook;
|
||||
screen->newClientHook = newClientHook;
|
||||
screen->passwordCheck = passwordCheck;
|
||||
screen->setXCutText = clipboardHook;
|
||||
|
||||
screen->desktopName = d->desktopName.constData();
|
||||
|
||||
if (!myCursor) {
|
||||
myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
|
||||
}
|
||||
screen->cursor = myCursor;
|
||||
|
||||
rfbInitServer(screen);
|
||||
if (!rfbIsActive(screen)) {
|
||||
KMessageBox::error(0,i18n("Address already in use"),"krfb");
|
||||
shutdown();
|
||||
qApp->quit();
|
||||
return;
|
||||
};
|
||||
|
||||
d->listeningPort = localPort(screen->listenSock);
|
||||
d->listeningAddress = localAddress(screen->listenSock);
|
||||
|
||||
kDebug() << "Listen port:" << d->listeningPort << "Listen Address:" << d->listeningAddress;
|
||||
|
||||
/* Integrate the rfb event mechanism with qt's event loop.
|
||||
* Call processRfbEvents() every time the qt event loop is run,
|
||||
* so that it also processes and delivers rfb events and call
|
||||
* shutdown() when QApplication exits to shutdown the rfb server
|
||||
* before the X11 connection goes down.
|
||||
*/
|
||||
connect(&d->rfbProcessEventTimer, SIGNAL(timeout()), SLOT(processRfbEvents()));
|
||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(shutdown()));
|
||||
d->rfbProcessEventTimer.start(0);
|
||||
}
|
||||
|
||||
void AbstractRfbServer::setListeningAddress(const QByteArray &address)
|
||||
{
|
||||
d->address = address;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::setListeningPort(int port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::setFrameBuffer(QSharedPointer<FrameBuffer> frameBuffer)
|
||||
{
|
||||
d->fb = frameBuffer;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::setDesktopName(const QByteArray &desktopName)
|
||||
{
|
||||
d->desktopName = desktopName;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::setPasswordRequired(bool passwordRequired)
|
||||
{
|
||||
d->passwordRequired = passwordRequired;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::processRfbEvents()
|
||||
{
|
||||
foreach(const QRect &r, d->fb->modifiedTiles()) {
|
||||
rfbMarkRectAsModified(d->screen, r.x(), r.y(), r.right(), r.bottom());
|
||||
}
|
||||
rfbProcessEvents(d->screen, 100);
|
||||
}
|
||||
|
||||
void AbstractRfbServer::shutdown()
|
||||
{
|
||||
rfbShutdownServer(d->screen, true);
|
||||
d->fb.clear();
|
||||
|
||||
d->listeningPort = 0;
|
||||
d->listeningAddress.clear();
|
||||
}
|
||||
|
||||
QString AbstractRfbServer::listeningAddress() const
|
||||
{
|
||||
return d->listeningAddress;
|
||||
}
|
||||
|
||||
unsigned int AbstractRfbServer::listeningPort() const
|
||||
{
|
||||
kDebug() << "Stored listening port:" << d->listeningPort;
|
||||
if (d->screen && d->screen->listenSock) {
|
||||
kDebug() << "Actual listening port:" << localPort(d->screen->listenSock);
|
||||
kDebug() << d->screen->thisHost;
|
||||
}
|
||||
return d->listeningPort;
|
||||
}
|
||||
|
||||
bool AbstractRfbServer::checkX11Capabilities() {
|
||||
int bp1, bp2, majorv, minorv;
|
||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
||||
&majorv, &minorv);
|
||||
if ((!r) || (((majorv*1000)+minorv) < 2002)) {
|
||||
KMessageBox::error(0,
|
||||
i18n("Your X11 Server does not support the required XTest extension version 2.2. Sharing your desktop is not possible."),
|
||||
i18n("Desktop Sharing Error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::updatePassword()
|
||||
{
|
||||
if (!d->screen) return;
|
||||
QString pw = KrfbConfig::uninvitedConnectionPassword();
|
||||
kDebug() << "password: " << pw << " allow " <<
|
||||
KrfbConfig::allowUninvitedConnections() <<
|
||||
" invitations " << InvitationManager::self()->activeInvitations() << endl;
|
||||
|
||||
if (pw.isEmpty() && InvitationManager::self()->activeInvitations() == 0) {
|
||||
kDebug() << "no password from now on";
|
||||
d->screen->authPasswdData = (void *)0;
|
||||
} else {
|
||||
kDebug() << "Ask for password to accept connections";
|
||||
d->screen->authPasswdData = (void *)1;
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRfbServer::clientDisconnected(AbstractConnectionController *cc)
|
||||
{
|
||||
kDebug() << "clients--: " << d->numClients;
|
||||
if (!--d->numClients) {
|
||||
d->fb->stopMonitor();
|
||||
kDebug() << "stopMonitor: d->numClients = " << d->numClients;
|
||||
}
|
||||
disconnect(cc, SIGNAL(clientDisconnected(AbstractConnectionController*)),this, SLOT(clientDisconnected(AbstractConnectionController*)));
|
||||
|
||||
Q_EMIT sessionFinished();
|
||||
}
|
||||
|
||||
void AbstractRfbServer::enableDesktopControl(bool enable)
|
||||
{
|
||||
foreach (QPointer<AbstractConnectionController> ptr, d->controllers) {
|
||||
if (ptr) {
|
||||
if (ptr->controlCanBeEnabled()) {
|
||||
ptr->setControlEnabled(enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRfbServer::appendController(AbstractConnectionController *c)
|
||||
{
|
||||
d->controllers.append(c);
|
||||
}
|
||||
|
||||
int AbstractRfbServer::numClients() const
|
||||
{
|
||||
return d->numClients;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::incrementNumClients()
|
||||
{
|
||||
d->numClients++;
|
||||
}
|
||||
|
||||
void AbstractRfbServer::startFrameBufferMonitor()
|
||||
{
|
||||
d->fb->startMonitor();
|
||||
}
|
||||
|
||||
void AbstractRfbServer::addController(AbstractConnectionController *cc)
|
||||
{
|
||||
if (d->numClients++ == 0)
|
||||
d->fb->startMonitor();
|
||||
|
||||
d->controllers.append(cc);
|
||||
}
|
||||
|
||||
|
||||
#include "abstractrfbserver.moc"
|
||||
|
||||
87
abstractrfbserver.h
Normal file
87
abstractrfbserver.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* This file is part of the KDE project
|
||||
* Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
* @author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
* Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_ABSTRACTRFBSERVER_H
|
||||
#define KRFB_ABSTRACTRFBSERVER_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
class AbstractConnectionController;
|
||||
|
||||
class AbstractRfbServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class ServerManager;
|
||||
|
||||
public:
|
||||
virtual ~AbstractRfbServer();
|
||||
|
||||
virtual enum rfbNewClientAction handleNewClient(struct _rfbClientRec *cl) = 0;
|
||||
virtual bool checkX11Capabilities();
|
||||
|
||||
Q_SIGNALS:
|
||||
void sessionEstablished(QString);
|
||||
void sessionFinished();
|
||||
void desktopControlSettingChanged(bool);
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void processRfbEvents();
|
||||
virtual void shutdown();
|
||||
virtual void enableDesktopControl(bool);
|
||||
virtual void updateSettings() = 0;
|
||||
virtual void updatePassword();
|
||||
virtual void clientDisconnected(AbstractConnectionController *);
|
||||
|
||||
virtual QString listeningAddress() const;
|
||||
virtual unsigned int listeningPort() const;
|
||||
|
||||
protected:
|
||||
AbstractRfbServer();
|
||||
|
||||
virtual void setListeningAddress(const QByteArray &address);
|
||||
virtual void setListeningPort(int port);
|
||||
virtual void setFrameBuffer(QSharedPointer<FrameBuffer> frameBuffer);
|
||||
virtual void setDesktopName(const QByteArray &desktopName);
|
||||
virtual void setPasswordRequired(bool passwordRequired);
|
||||
virtual void startListening();
|
||||
|
||||
virtual void appendController(AbstractConnectionController *c);
|
||||
virtual int numClients() const;
|
||||
virtual void startFrameBufferMonitor();
|
||||
virtual void incrementNumClients();
|
||||
void addController(AbstractConnectionController *cc);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(AbstractRfbServer)
|
||||
|
||||
class AbstractRfbServerPrivate;
|
||||
AbstractRfbServerPrivate * const d;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTIONCONTROLLER_H
|
||||
#define CONNECTIONCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
class KrfbServer;
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class ConnectionController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConnectionController(struct _rfbClientRec *_cl, KrfbServer *parent);
|
||||
|
||||
~ConnectionController();
|
||||
|
||||
bool handleCheckPassword(rfbClientPtr cl, const char *response, int len);
|
||||
void handleNegotiationFinished(struct _rfbClientRec *cl);
|
||||
|
||||
void handleKeyEvent(bool down , rfbKeySym keySym );
|
||||
void handlePointerEvent( int bm, int x, int y);
|
||||
void handleClientGone();
|
||||
void clipboardToServer(const QString &);
|
||||
|
||||
enum rfbNewClientAction handleNewClient();
|
||||
|
||||
void setControlEnabled(bool enable);
|
||||
|
||||
void setControlCanBeEnabled(bool canBeEnabled);
|
||||
bool controlCanBeEnabled() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void sessionEstablished(QString);
|
||||
void notification(QString, QString);
|
||||
void clientDisconnected(ConnectionController *);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void dialogAccepted();
|
||||
void dialogRejected();
|
||||
|
||||
private:
|
||||
QString remoteIp;
|
||||
struct _rfbClientRec *cl;
|
||||
bool controlEnabled;
|
||||
bool m_controlCanBeEnabled;
|
||||
/*
|
||||
int fd;
|
||||
KrfbServer *server;
|
||||
rfbScreenInfoPtr screen;
|
||||
rfbClientPtr client;
|
||||
QTcpSocket *tcpConn;
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#include "abstractconnectioncontroller.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QX11Info>
|
||||
|
||||
@@ -171,7 +173,7 @@ void PointerEvent::exec() {
|
||||
}
|
||||
|
||||
|
||||
ClipboardEvent::ClipboardEvent(ConnectionController *c, const QString &ctext)
|
||||
ClipboardEvent::ClipboardEvent(AbstractConnectionController *c, const QString &ctext)
|
||||
:controller(c),text(ctext)
|
||||
{
|
||||
}
|
||||
|
||||
6
events.h
6
events.h
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
class ConnectionController;
|
||||
class AbstractConnectionController;
|
||||
|
||||
class QCursor;
|
||||
|
||||
@@ -60,10 +60,10 @@ public:
|
||||
};
|
||||
|
||||
class ClipboardEvent : public VNCEvent {
|
||||
ConnectionController *controller;
|
||||
AbstractConnectionController *controller;
|
||||
QString text;
|
||||
public:
|
||||
ClipboardEvent(ConnectionController *c, const QString &text);
|
||||
ClipboardEvent(AbstractConnectionController *c, const QString &text);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
Copyright (C) 2001-2003 by Tim Jansen <tim@tjansen.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include "connectioncontroller.h"
|
||||
#include "connectioncontroller.moc"
|
||||
|
||||
#include "krfbconnectioncontroller.h"
|
||||
|
||||
#include <QX11Info>
|
||||
#include <QHostInfo>
|
||||
@@ -35,48 +47,20 @@
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
static void clientGoneHook(rfbClientPtr cl)
|
||||
KrfbConnectionController::KrfbConnectionController(struct _rfbClientRec *_cl,
|
||||
AbstractRfbServer * parent)
|
||||
: AbstractConnectionController(_cl, parent),
|
||||
m_clientGoneRequiresAction(false)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->handleClientGone();
|
||||
kDebug();
|
||||
}
|
||||
|
||||
|
||||
static bool checkPassword(const QString &p, unsigned char *ochallenge, const char *response, int len)
|
||||
KrfbConnectionController::~KrfbConnectionController()
|
||||
{
|
||||
|
||||
if ((len == 0) && (p.length() == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char passwd[MAXPWLEN];
|
||||
unsigned char challenge[CHALLENGESIZE];
|
||||
|
||||
memcpy(challenge, ochallenge, CHALLENGESIZE);
|
||||
bzero(passwd, MAXPWLEN);
|
||||
if (!p.isNull()) {
|
||||
strncpy(passwd, p.toLatin1(),
|
||||
(MAXPWLEN <= p.length()) ? MAXPWLEN : p.length());
|
||||
}
|
||||
|
||||
rfbEncryptBytes(challenge, passwd);
|
||||
return memcmp(challenge, response, len) == 0;
|
||||
kDebug();
|
||||
}
|
||||
|
||||
|
||||
ConnectionController::ConnectionController(struct _rfbClientRec *_cl, KrfbServer * parent)
|
||||
: QObject(parent), cl(_cl)
|
||||
{
|
||||
cl->clientData = (void*)this;
|
||||
}
|
||||
|
||||
ConnectionController::~ConnectionController()
|
||||
{
|
||||
}
|
||||
|
||||
enum rfbNewClientAction ConnectionController::handleNewClient()
|
||||
enum rfbNewClientAction KrfbConnectionController::handleNewClient()
|
||||
{
|
||||
kDebug();
|
||||
|
||||
@@ -94,7 +78,7 @@ enum rfbNewClientAction ConnectionController::handleNewClient()
|
||||
|
||||
// In the remaining cases, the connection will be at least partially established, so we need
|
||||
// the clientGoneHook to be called when the connection ends.
|
||||
cl->clientGoneHook = clientGoneHook;
|
||||
m_clientGoneRequiresAction = true;
|
||||
|
||||
if (!askOnConnect) {
|
||||
KNotification::event("NewConnectionAutoAccepted",
|
||||
@@ -121,7 +105,7 @@ enum rfbNewClientAction ConnectionController::handleNewClient()
|
||||
return RFB_CLIENT_ON_HOLD;
|
||||
}
|
||||
|
||||
bool ConnectionController::handleCheckPassword(rfbClientPtr cl, const char *response, int len)
|
||||
bool KrfbConnectionController::handleCheckPassword(rfbClientPtr cl, const char *response, int len)
|
||||
{
|
||||
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
|
||||
QString password = KrfbConfig::uninvitedConnectionPassword();
|
||||
@@ -163,70 +147,15 @@ bool ConnectionController::handleCheckPassword(rfbClientPtr cl, const char *resp
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionController::handleKeyEvent(bool down, rfbKeySym keySym)
|
||||
void KrfbConnectionController::handleClientGone()
|
||||
{
|
||||
if (controlEnabled) {
|
||||
KeyboardEvent ev(down, keySym);
|
||||
ev.exec();
|
||||
if (m_clientGoneRequiresAction) {
|
||||
emit clientDisconnected(this);
|
||||
kDebug() << "client gone";
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionController::handlePointerEvent(int bm, int x, int y)
|
||||
{
|
||||
if (controlEnabled) {
|
||||
PointerEvent ev(bm, x, y);
|
||||
ev.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionController::handleClientGone()
|
||||
{
|
||||
emit clientDisconnected(this);
|
||||
kDebug() << "client gone";
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void ConnectionController::clipboardToServer(const QString &s)
|
||||
{
|
||||
ClipboardEvent ev(this, s);
|
||||
ev.exec();
|
||||
}
|
||||
|
||||
void ConnectionController::dialogAccepted()
|
||||
{
|
||||
ConnectionDialog *dialog = qobject_cast<ConnectionDialog*>(sender());
|
||||
|
||||
if (!dialog) {
|
||||
kWarning() << "Wrong type of sender.";
|
||||
return;
|
||||
}
|
||||
// rfbStartOnHoldClient(cl);
|
||||
cl->onHold = false;
|
||||
setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
setControlCanBeEnabled(dialog->cbAllowRemoteControl->isChecked());
|
||||
emit sessionEstablished(remoteIp);
|
||||
}
|
||||
|
||||
void ConnectionController::dialogRejected()
|
||||
{
|
||||
kDebug() << "refused connection";
|
||||
rfbRefuseOnHoldClient(cl);
|
||||
}
|
||||
|
||||
void ConnectionController::setControlEnabled(bool enable)
|
||||
{
|
||||
controlEnabled = enable;
|
||||
}
|
||||
|
||||
void ConnectionController::setControlCanBeEnabled(bool canBeEnabled)
|
||||
{
|
||||
m_controlCanBeEnabled = canBeEnabled;
|
||||
}
|
||||
|
||||
bool ConnectionController::controlCanBeEnabled() const
|
||||
{
|
||||
return m_controlCanBeEnabled;
|
||||
}
|
||||
|
||||
#include "krfbconnectioncontroller.moc"
|
||||
|
||||
47
krfbconnectioncontroller.h
Normal file
47
krfbconnectioncontroller.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFB_KRFBCONNECTIONCONTROLLER_H
|
||||
#define KRFB_KRFBCONNECTIONCONTROLLER_H
|
||||
|
||||
#include "abstractconnectioncontroller.h"
|
||||
|
||||
class KrfbConnectionController : public AbstractConnectionController
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KrfbConnectionController(struct _rfbClientRec *_cl, AbstractRfbServer *parent);
|
||||
virtual ~KrfbConnectionController();
|
||||
|
||||
virtual bool handleCheckPassword(rfbClientPtr cl, const char *response, int len);
|
||||
|
||||
virtual void handleClientGone();
|
||||
|
||||
virtual enum rfbNewClientAction handleNewClient();
|
||||
|
||||
private:
|
||||
bool m_clientGoneRequiresAction;
|
||||
};
|
||||
|
||||
|
||||
#endif // Header Guard
|
||||
|
||||
292
krfbserver.cpp
292
krfbserver.cpp
@@ -8,10 +8,14 @@
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
// FUCKING RFB.H POS FUCK YOU
|
||||
#include "servermanager.h"
|
||||
|
||||
#include "krfbserver.h"
|
||||
#include "krfbserver.moc"
|
||||
|
||||
#include "krfbconnectioncontroller.h"
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
@@ -27,117 +31,27 @@
|
||||
#include <KMessageBox>
|
||||
#include <dnssd/publicservice.h>
|
||||
|
||||
#include "connectioncontroller.h"
|
||||
#include "abstractconnectioncontroller.h"
|
||||
#include "framebuffer.h"
|
||||
#include "framebuffermanager.h"
|
||||
#include "krfbconfig.h"
|
||||
#include "invitationmanager.h"
|
||||
#include "servermanager.h"
|
||||
#include "sockethelpers.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
static const char* cur=
|
||||
" "
|
||||
" x "
|
||||
" xx "
|
||||
" xxx "
|
||||
" xxxx "
|
||||
" xxxxx "
|
||||
" xxxxxx "
|
||||
" xxxxxxx "
|
||||
" xxxxxxxx "
|
||||
" xxxxxxxxx "
|
||||
" xxxxxxxxxx "
|
||||
" xxxxx "
|
||||
" xx xxx "
|
||||
" x xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" xxx "
|
||||
" ";
|
||||
|
||||
static const char* mask=
|
||||
"xx "
|
||||
"xxx "
|
||||
"xxxx "
|
||||
"xxxxx "
|
||||
"xxxxxx "
|
||||
"xxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxxxxx "
|
||||
"xxxxxxxxxxxx "
|
||||
"xxxxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xxxxxxxx "
|
||||
"xx xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxxxx "
|
||||
" xxx ";
|
||||
|
||||
static rfbCursorPtr myCursor;
|
||||
|
||||
|
||||
static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
|
||||
{
|
||||
KrfbServer *server = ServerManager::instance()->serverForClient(cl);
|
||||
return server->handleNewClient(cl);
|
||||
}
|
||||
|
||||
static rfbBool passwordCheck(rfbClientPtr cl,
|
||||
const char* encryptedPassword,
|
||||
int len)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
return cc->handleCheckPassword(cl, encryptedPassword, len);
|
||||
}
|
||||
|
||||
static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->handleKeyEvent(down ? true : false, keySym);
|
||||
}
|
||||
|
||||
static void pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->handlePointerEvent(bm, x, y);
|
||||
}
|
||||
|
||||
static void clipboardHook(char* str,int len, rfbClientPtr cl)
|
||||
{
|
||||
ConnectionController *cc = static_cast<ConnectionController *>(cl->clientData);
|
||||
cc->clipboardToServer(QString::fromUtf8(str, len));
|
||||
}
|
||||
|
||||
|
||||
class KrfbServer::KrfbServerP {
|
||||
class KrfbServer::KrfbServerPrivate {
|
||||
|
||||
public:
|
||||
KrfbServerP() : screen(0), numClients(0), listeningPort(0) {};
|
||||
|
||||
QSharedPointer<FrameBuffer> fb;
|
||||
QList< QPointer<ConnectionController> > controllers;
|
||||
rfbScreenInfoPtr screen;
|
||||
int numClients;
|
||||
QByteArray desktopName;
|
||||
QTimer rfbProcessEventTimer;
|
||||
QString listeningAddress;
|
||||
unsigned int listeningPort;
|
||||
KrfbServerPrivate() {};
|
||||
};
|
||||
|
||||
KrfbServer::KrfbServer()
|
||||
:d(new KrfbServerP)
|
||||
: AbstractRfbServer(),
|
||||
d(new KrfbServerPrivate)
|
||||
|
||||
{
|
||||
kDebug() << "starting ";
|
||||
d->fb = FrameBufferManager::instance()->frameBuffer(QApplication::desktop()->winId());
|
||||
QTimer::singleShot(0, this, SLOT(startListening()));
|
||||
QTimer::singleShot(0, this, SLOT(doStartListening()));
|
||||
connect(InvitationManager::self(), SIGNAL(invitationNumChanged(int)),SLOT(updatePassword()));
|
||||
}
|
||||
|
||||
@@ -147,125 +61,29 @@ KrfbServer::~KrfbServer()
|
||||
}
|
||||
|
||||
|
||||
void KrfbServer::startListening()
|
||||
void KrfbServer::doStartListening()
|
||||
{
|
||||
rfbScreenInfoPtr screen;
|
||||
|
||||
int port = KrfbConfig::port();
|
||||
|
||||
int w = d->fb->width();
|
||||
int h = d->fb->height();
|
||||
int depth = d->fb->depth();
|
||||
|
||||
int bpp = depth >> 3;
|
||||
if (bpp != 1 && bpp != 2 && bpp != 4) bpp = 4;
|
||||
kDebug() << "bpp: " << bpp;
|
||||
|
||||
rfbLogEnable(0);
|
||||
screen = rfbGetScreen(0, 0, w, h, 8, 3, bpp);
|
||||
|
||||
screen->paddedWidthInBytes = d->fb->paddedWidth();
|
||||
|
||||
d->fb->getServerFormat(screen->serverFormat);
|
||||
|
||||
screen->frameBuffer = d->fb->data();
|
||||
d->screen = screen;
|
||||
screen->autoPort = 0;
|
||||
screen->port = port;
|
||||
|
||||
// server hooks
|
||||
screen->newClientHook = newClientHook;
|
||||
|
||||
screen->kbdAddEvent = keyboardHook;
|
||||
screen->ptrAddEvent = pointerHook;
|
||||
screen->newClientHook = newClientHook;
|
||||
screen->passwordCheck = passwordCheck;
|
||||
screen->setXCutText = clipboardHook;
|
||||
|
||||
d->desktopName = i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()).toLatin1();
|
||||
screen->desktopName = d->desktopName.constData();
|
||||
|
||||
if (!myCursor) {
|
||||
myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
|
||||
}
|
||||
screen->cursor = myCursor;
|
||||
|
||||
// configure passwords and desktop control here
|
||||
updateSettings();
|
||||
|
||||
rfbInitServer(screen);
|
||||
if (!rfbIsActive(screen)) {
|
||||
KMessageBox::error(0,i18n("Address already in use"),"krfb");
|
||||
shutdown();
|
||||
qApp->quit();
|
||||
return;
|
||||
};
|
||||
|
||||
d->listeningPort = localPort(screen->listenSock);
|
||||
d->listeningAddress = localAddress(screen->listenSock);
|
||||
|
||||
kDebug() << "Listen port:" << d->listeningPort << "Listen Address:" << d->listeningAddress;
|
||||
// Set up the parameters for the server before we get it to start listening.
|
||||
setFrameBuffer(FrameBufferManager::instance()->frameBuffer(QApplication::desktop()->winId()));
|
||||
setListeningPort(KrfbConfig::port());
|
||||
setListeningAddress("0.0.0.0"); // Listen on all available network addresses
|
||||
setDesktopName(i18n("%1@%2 (shared desktop)",
|
||||
KUser().loginName(),
|
||||
QHostInfo::localHostName()).toLatin1());
|
||||
|
||||
if (KrfbConfig::publishService()) {
|
||||
DNSSD::PublicService *service = new DNSSD::PublicService(i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()),"_rfb._tcp",port);
|
||||
DNSSD::PublicService *service = new DNSSD::PublicService(i18n("%1@%2 (shared desktop)",
|
||||
KUser().loginName(),
|
||||
QHostInfo::localHostName()),
|
||||
"_rfb._tcp",
|
||||
listeningPort());
|
||||
service->publishAsync();
|
||||
}
|
||||
|
||||
/* Integrate the rfb event mechanism with qt's event loop.
|
||||
* Call processRfbEvents() every time the qt event loop is run,
|
||||
* so that it also processes and delivers rfb events and call
|
||||
* shutdown() when QApplication exits to shutdown the rfb server
|
||||
* before the X11 connection goes down.
|
||||
*/
|
||||
connect(&d->rfbProcessEventTimer, SIGNAL(timeout()), SLOT(processRfbEvents()));
|
||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(shutdown()));
|
||||
d->rfbProcessEventTimer.start(0);
|
||||
}
|
||||
startListening();
|
||||
|
||||
void KrfbServer::processRfbEvents()
|
||||
{
|
||||
foreach(const QRect &r, d->fb->modifiedTiles()) {
|
||||
rfbMarkRectAsModified(d->screen, r.x(), r.y(), r.right(), r.bottom());
|
||||
}
|
||||
rfbProcessEvents(d->screen, 100);
|
||||
}
|
||||
|
||||
void KrfbServer::shutdown()
|
||||
{
|
||||
rfbShutdownServer(d->screen, true);
|
||||
// framebuffer has to be deleted before X11 connection goes down
|
||||
d->fb.clear();
|
||||
|
||||
d->listeningPort = 0;
|
||||
d->listeningAddress.clear();
|
||||
}
|
||||
|
||||
|
||||
void KrfbServer::enableDesktopControl(bool enable)
|
||||
{
|
||||
foreach (QPointer<ConnectionController> ptr, d->controllers) {
|
||||
if (ptr) {
|
||||
if (ptr->controlCanBeEnabled()) {
|
||||
ptr->setControlEnabled(enable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum rfbNewClientAction KrfbServer::handleNewClient(struct _rfbClientRec * cl)
|
||||
{
|
||||
ConnectionController *cc = new ConnectionController(cl, this);
|
||||
if (d->numClients++ == 0)
|
||||
d->fb->startMonitor();
|
||||
|
||||
d->controllers.append(cc);
|
||||
cc->setControlEnabled(KrfbConfig::allowDesktopControl());
|
||||
cc->setControlCanBeEnabled(KrfbConfig::allowDesktopControl());
|
||||
|
||||
connect(cc, SIGNAL(sessionEstablished(QString)), SIGNAL(sessionEstablished(QString)));
|
||||
connect(cc, SIGNAL(clientDisconnected(ConnectionController *)),SLOT(clientDisconnected(ConnectionController *)));
|
||||
|
||||
return cc->handleNewClient();
|
||||
// configure passwords and desktop control here
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
void KrfbServer::updateSettings()
|
||||
@@ -274,57 +92,17 @@ void KrfbServer::updateSettings()
|
||||
updatePassword();
|
||||
}
|
||||
|
||||
void KrfbServer::updatePassword()
|
||||
enum rfbNewClientAction KrfbServer::handleNewClient(struct _rfbClientRec * cl)
|
||||
{
|
||||
KrfbConnectionController *cc = new KrfbConnectionController(cl, this);
|
||||
|
||||
if (!d->screen) return;
|
||||
QString pw = KrfbConfig::uninvitedConnectionPassword();
|
||||
kDebug() << "password: " << pw << " allow " <<
|
||||
KrfbConfig::allowUninvitedConnections() <<
|
||||
" invitations " << InvitationManager::self()->activeInvitations() << endl;
|
||||
cc->setControlEnabled(KrfbConfig::allowDesktopControl());
|
||||
cc->setControlCanBeEnabled(KrfbConfig::allowDesktopControl());
|
||||
|
||||
if (pw.isEmpty() && InvitationManager::self()->activeInvitations() == 0) {
|
||||
kDebug() << "no password from now on";
|
||||
d->screen->authPasswdData = (void *)0;
|
||||
} else {
|
||||
kDebug() << "Ask for password to accept connections";
|
||||
d->screen->authPasswdData = (void *)1;
|
||||
}
|
||||
connect(cc, SIGNAL(sessionEstablished(QString)), SIGNAL(sessionEstablished(QString)));
|
||||
connect(cc, SIGNAL(clientDisconnected(AbstractConnectionController *)),SLOT(clientDisconnected(AbstractConnectionController *)));
|
||||
|
||||
return cc->handleNewClient();
|
||||
}
|
||||
|
||||
bool KrfbServer::checkX11Capabilities() {
|
||||
int bp1, bp2, majorv, minorv;
|
||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
||||
&majorv, &minorv);
|
||||
if ((!r) || (((majorv*1000)+minorv) < 2002)) {
|
||||
KMessageBox::error(0,
|
||||
i18n("Your X11 Server does not support the required XTest extension version 2.2. Sharing your desktop is not possible."),
|
||||
i18n("Desktop Sharing Error"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KrfbServer::clientDisconnected(ConnectionController *cc)
|
||||
{
|
||||
kDebug() << "clients--: " << d->numClients;
|
||||
if (!--d->numClients) {
|
||||
d->fb->stopMonitor();
|
||||
kDebug() << "stopMonitor: d->numClients = " << d->numClients;
|
||||
}
|
||||
disconnect(cc, SIGNAL(clientDisconnected(ConnectionController*)),this, SLOT(clientDisconnected(ConnectionController*)));
|
||||
|
||||
Q_EMIT sessionFinished();
|
||||
}
|
||||
|
||||
QString KrfbServer::listeningAddress() const
|
||||
{
|
||||
return d->listeningAddress;
|
||||
}
|
||||
|
||||
unsigned int KrfbServer::listeningPort() const
|
||||
{
|
||||
return d->listeningPort;
|
||||
}
|
||||
|
||||
|
||||
57
krfbserver.h
57
krfbserver.h
@@ -1,58 +1,51 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2009 Collabora Ltd <info@collabora.co.uk>
|
||||
@author George Goldberg <george.goldberg@collabora.co.uk>
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KRFBSERVER_H
|
||||
#define KRFBSERVER_H
|
||||
#ifndef KRFB_KRFBSERVER_H
|
||||
#define KRFB_KRFBSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <rfb/rfb.h>
|
||||
#include "abstractrfbserver.h"
|
||||
|
||||
class ConnectionController;
|
||||
/**
|
||||
This class implements the listening server for the RFB protocol.
|
||||
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class KrfbServer : public QObject
|
||||
class KrfbServer : public AbstractRfbServer
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class ServerManager;
|
||||
public:
|
||||
~KrfbServer();
|
||||
virtual ~KrfbServer();
|
||||
|
||||
enum rfbNewClientAction handleNewClient(struct _rfbClientRec *cl);
|
||||
bool checkX11Capabilities();
|
||||
|
||||
signals:
|
||||
void sessionEstablished(QString);
|
||||
void sessionFinished();
|
||||
void desktopControlSettingChanged(bool);
|
||||
virtual enum rfbNewClientAction handleNewClient(struct _rfbClientRec *cl);
|
||||
|
||||
public Q_SLOTS:
|
||||
void doStartListening();
|
||||
|
||||
void startListening();
|
||||
void processRfbEvents();
|
||||
void shutdown();
|
||||
void enableDesktopControl(bool);
|
||||
void updateSettings();
|
||||
void updatePassword();
|
||||
void clientDisconnected(ConnectionController *);
|
||||
|
||||
QString listeningAddress() const;
|
||||
unsigned int listeningPort() const;
|
||||
virtual void updateSettings();
|
||||
|
||||
private:
|
||||
KrfbServer();
|
||||
|
||||
class KrfbServerP;
|
||||
KrfbServerP * const d;
|
||||
class KrfbServerPrivate;
|
||||
KrfbServerPrivate * const d;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // Header guard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user