mirror of
https://invent.kde.org/network/krfb
synced 2024-07-05 09:28:35 +00:00
- added single connection controller in separate thread
- added hooks to manage vnc events - moved events out of rfbcontroller.cpp/.h into their own source file svn path=/trunk/KDE/kdenetwork/krfb/; revision=650434
This commit is contained in:
parent
358cc5ee54
commit
94d6110dcd
|
@ -20,6 +20,8 @@ set(krfb_SRCS
|
|||
invitation.cpp
|
||||
connectiondialog.cpp
|
||||
personalinvitedialog.cpp
|
||||
connectioncontroller.cpp
|
||||
events.cpp
|
||||
# rfbcontroller.cc
|
||||
# xupdatescanner.cc
|
||||
)
|
||||
|
|
335
connectioncontroller.cpp
Normal file
335
connectioncontroller.cpp
Normal file
|
@ -0,0 +1,335 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(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; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "invitationmanager.h"
|
||||
#include "krfbserver.h"
|
||||
|
||||
#include <QThreadStorage>
|
||||
#include <QX11Info>
|
||||
#include <QHostInfo>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include <KConfig>
|
||||
#include <KGlobal>
|
||||
#include <KUser>
|
||||
#include <KNotification>
|
||||
#include <KLocale>
|
||||
|
||||
#include "connectioncontroller.h"
|
||||
#include "connectioncontroller.moc"
|
||||
|
||||
#include <X11/Xutil.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;
|
||||
|
||||
QThreadStorage<CurrentController *> controllers;
|
||||
|
||||
static enum rfbNewClientAction newClientHook(struct _rfbClientRec *cl)
|
||||
{
|
||||
return controllers.localData()->handleNewClient(cl);
|
||||
}
|
||||
|
||||
static rfbBool passwordCheck(rfbClientPtr cl,
|
||||
const char* encryptedPassword,
|
||||
int len)
|
||||
{
|
||||
return controllers.localData()->handleCheckPassword(cl, encryptedPassword, len);
|
||||
}
|
||||
|
||||
static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr)
|
||||
{
|
||||
controllers.localData()->handleKeyEvent(down ? true : false, keySym);
|
||||
}
|
||||
|
||||
static void pointerHook(int bm, int x, int y, rfbClientPtr)
|
||||
{
|
||||
controllers.localData()->handlePointerEvent(bm, x, y);
|
||||
}
|
||||
|
||||
static void clientGoneHook(rfbClientPtr)
|
||||
{
|
||||
controllers.localData()->handleClientGone();
|
||||
}
|
||||
|
||||
static void clipboardHook(char* str,int len, rfbClientPtr)
|
||||
{
|
||||
controllers.localData()->clipboardToServer(QString::fromUtf8(str, len));
|
||||
}
|
||||
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
CurrentController::CurrentController(int fd)
|
||||
:connFD(fd)
|
||||
{
|
||||
}
|
||||
|
||||
bool CurrentController::handleCheckPassword(rfbClientPtr cl, const char *response, int len)
|
||||
{
|
||||
KSharedConfigPtr conf = KGlobal::config();
|
||||
KConfigGroup srvconf(conf, "Server");
|
||||
|
||||
bool allowUninvited = srvconf.readEntry("allowUninvitedConnections",false);
|
||||
QString password = srvconf.readEntry("uninvitedConnectionPassword",QString());
|
||||
|
||||
bool authd = false;
|
||||
kDebug() << "about to start autentication" << endl;
|
||||
|
||||
if (allowUninvited) {
|
||||
authd = checkPassword(password, cl->authChallenge, response, len);
|
||||
}
|
||||
|
||||
if (!authd) {
|
||||
QList<Invitation> invlist = InvitationManager::self()->invitations();
|
||||
|
||||
foreach(Invitation it, invlist) {
|
||||
if (checkPassword(it.password(), cl->authChallenge, response, len) && it.isValid()) {
|
||||
authd = true;
|
||||
//configuration->removeInvitation(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!authd) {
|
||||
if (InvitationManager::self()->invitations().size() > 0) {
|
||||
sendKNotifyEvent("InvalidPasswordInvitations",
|
||||
i18n("Failed login attempt from %1: wrong password",
|
||||
remoteIp));
|
||||
} else {
|
||||
sendKNotifyEvent("InvalidPassword",
|
||||
i18n("Failed login attempt from %1: wrong password",
|
||||
remoteIp));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
asyncMutex.lock();
|
||||
asyncQueue.append(new SessionEstablishedEvent(this));
|
||||
asyncMutex.unlock();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
enum rfbNewClientAction CurrentController::handleNewClient(rfbClientPtr cl)
|
||||
{
|
||||
KSharedConfigPtr conf = KGlobal::config();
|
||||
KConfigGroup srvconf(conf, "Server");
|
||||
|
||||
bool allowDesktopControl = srvconf.readEntry("allowDesktopControl",false);
|
||||
bool askOnConnect = srvconf.readEntry("askOnConnect",false);
|
||||
|
||||
|
||||
client = cl;
|
||||
int socket = cl->sock;
|
||||
// cl->negotiationFinishedHook = negotiationFinishedHook; ???
|
||||
|
||||
QString host;
|
||||
|
||||
#if 0
|
||||
// TODO: this drops the connection >.<
|
||||
QTcpSocket t;
|
||||
t.setSocketDescriptor(socket); //, QAbstractSocket::ConnectedState, QIODevice::NotOpen);
|
||||
host = t.peerAddress().toString();
|
||||
#endif
|
||||
|
||||
remoteIp = host;
|
||||
|
||||
if (!askOnConnect && InvitationManager::self()->invitations().size() == 0) {
|
||||
sendKNotifyEvent("NewConnectionAutoAccepted",
|
||||
i18n("Accepted uninvited connection from %1",
|
||||
remoteIp));
|
||||
|
||||
sendSessionEstablished();
|
||||
return RFB_CLIENT_ACCEPT;
|
||||
}
|
||||
|
||||
sendKNotifyEvent("NewConnectionOnHold",
|
||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
||||
remoteIp));
|
||||
|
||||
//cl->screen->authPasswdData = (void *)1;
|
||||
cl->clientGoneHook = clientGoneHook;
|
||||
|
||||
// dialog.setRemoteHost(remoteIp);
|
||||
// dialog.setAllowRemoteControl( true );
|
||||
// dialog.setFixedSize(dialog.sizeHint());
|
||||
// dialog.show();
|
||||
return RFB_CLIENT_ON_HOLD;
|
||||
}
|
||||
|
||||
void CurrentController::sendKNotifyEvent(const QString & name, const QString & desc)
|
||||
{
|
||||
kDebug() << "notification: " << name << " " << desc << endl;
|
||||
emit notification(name, desc);
|
||||
}
|
||||
|
||||
void CurrentController::sendSessionEstablished()
|
||||
{
|
||||
emit sessionEstablished("BAH");
|
||||
}
|
||||
|
||||
void CurrentController::handleKeyEvent(bool down, KeySym keySym)
|
||||
{
|
||||
}
|
||||
|
||||
void CurrentController::handlePointerEvent(int bm, int x, int y)
|
||||
{
|
||||
}
|
||||
|
||||
void CurrentController::handleClientGone()
|
||||
{
|
||||
kDebug() << "Client gone" << endl;
|
||||
rfbCloseClient(client);
|
||||
}
|
||||
|
||||
void CurrentController::clipboardToServer(const QString &)
|
||||
{
|
||||
}
|
||||
|
||||
ConnectionController::ConnectionController(int connFd, KrfbServer *parent)
|
||||
: QThread(parent), fd(connFd), server(parent)
|
||||
{
|
||||
framebufferImage = XGetImage(QX11Info::display(), QApplication::desktop()->winId(),
|
||||
0, 0,
|
||||
QApplication::desktop()->width(),
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
|
||||
}
|
||||
|
||||
|
||||
ConnectionController::~ConnectionController()
|
||||
{
|
||||
}
|
||||
|
||||
void ConnectionController::run()
|
||||
{
|
||||
kDebug() << "starting server connection" << endl;
|
||||
|
||||
CurrentController *cc = new CurrentController(fd);
|
||||
controllers.setLocalData(cc);
|
||||
|
||||
connect(cc, SIGNAL(sessionEstablished(QString)), server, SIGNAL(sessionEstablished(QString)));
|
||||
connect(cc, SIGNAL(notification(QString,QString)), server, SLOT(handleNotifications(QString, QString)));
|
||||
|
||||
rfbScreenInfoPtr server;
|
||||
|
||||
int w = framebufferImage->width;
|
||||
int h = framebufferImage->height;
|
||||
char *fb = framebufferImage->data;
|
||||
|
||||
rfbLogEnable(0);
|
||||
server = rfbGetScreen(0, 0, w, h,
|
||||
framebufferImage->bits_per_pixel,
|
||||
8,
|
||||
framebufferImage->bits_per_pixel/8);
|
||||
|
||||
kDebug() << "acquired framebuffer" << endl;
|
||||
|
||||
server->paddedWidthInBytes = framebufferImage->bytes_per_line;
|
||||
server->frameBuffer = fb;
|
||||
server->autoPort = true;
|
||||
server->inetdSock = fd;
|
||||
|
||||
// server hooks
|
||||
server->newClientHook = newClientHook;
|
||||
|
||||
server->kbdAddEvent = keyboardHook;
|
||||
server->ptrAddEvent = pointerHook;
|
||||
server->newClientHook = newClientHook;
|
||||
server->passwordCheck = passwordCheck;
|
||||
server->setXCutText = clipboardHook;
|
||||
|
||||
server->desktopName = i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()).toLatin1();
|
||||
|
||||
if (!myCursor) {
|
||||
myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
|
||||
}
|
||||
server->cursor = myCursor;
|
||||
|
||||
rfbInitServer(server);
|
||||
|
||||
rfbRunEventLoop(server, 1000, false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
72
connectioncontroller.h
Normal file
72
connectioncontroller.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/* 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; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTIONCONTROLLER_H
|
||||
#define CONNECTIONCONTROLLER_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
class KrfbServer;
|
||||
|
||||
class CurrentController: public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
CurrentController(int fd);
|
||||
|
||||
bool handleCheckPassword(rfbClientPtr cl, const char *response, int len);
|
||||
enum rfbNewClientAction handleNewClient(struct _rfbClientRec *cl);
|
||||
void sendKNotifyEvent(const QString &name, const QString &desc);
|
||||
void handleNegotiationFinished(struct _rfbClientRec *cl);
|
||||
|
||||
void handleKeyEvent(bool down, KeySym keySym);
|
||||
void handlePointerEvent( int bm, int x, int y);
|
||||
void handleClientGone();
|
||||
void clipboardToServer(const QString &);
|
||||
void sendSessionEstablished();
|
||||
|
||||
Q_SIGNALS:
|
||||
void sessionEstablished(QString);
|
||||
void notification(QString, QString);
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
private:
|
||||
int connFD;
|
||||
QString remoteIp;
|
||||
rfbClientPtr client;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@author Alessandro Praduroux <pradu@pradu.it>
|
||||
*/
|
||||
class ConnectionController : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ConnectionController(int connFD, KrfbServer *parent);
|
||||
|
||||
~ConnectionController();
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
|
||||
private:
|
||||
int fd;
|
||||
KrfbServer *server;
|
||||
XImage *framebufferImage;
|
||||
};
|
||||
|
||||
#endif
|
197
events.cpp
Normal file
197
events.cpp
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(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; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QX11Info>
|
||||
#include <QString>
|
||||
#include <QDesktopWidget>
|
||||
#include <QClipboard>
|
||||
|
||||
#include <KNotification>
|
||||
|
||||
#include "events.h"
|
||||
#include "connectioncontroller.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
Display *KeyboardEvent::dpy;
|
||||
signed char KeyboardEvent::modifiers[0x100];
|
||||
KeyCode KeyboardEvent::keycodes[0x100];
|
||||
KeyCode KeyboardEvent::leftShiftCode;
|
||||
KeyCode KeyboardEvent::rightShiftCode;
|
||||
KeyCode KeyboardEvent::altGrCode;
|
||||
const int KeyboardEvent::LEFTSHIFT = 1;
|
||||
const int KeyboardEvent::RIGHTSHIFT = 2;
|
||||
const int KeyboardEvent::ALTGR = 4;
|
||||
char KeyboardEvent::ModifierState;
|
||||
|
||||
KeyboardEvent::KeyboardEvent(bool d, KeySym k)
|
||||
: down(d), keySym(k)
|
||||
{
|
||||
}
|
||||
|
||||
void KeyboardEvent::initKeycodes()
|
||||
{
|
||||
KeySym key,*keymap;
|
||||
int i,j,minkey,maxkey,syms_per_keycode;
|
||||
|
||||
dpy = QX11Info::display();
|
||||
|
||||
memset(modifiers,-1,sizeof(modifiers));
|
||||
|
||||
XDisplayKeycodes(dpy,&minkey,&maxkey);
|
||||
Q_ASSERT(minkey >= 8);
|
||||
Q_ASSERT(maxkey < 256);
|
||||
keymap = (KeySym*) XGetKeyboardMapping(dpy, minkey,
|
||||
(maxkey - minkey + 1),
|
||||
&syms_per_keycode);
|
||||
Q_ASSERT(keymap);
|
||||
|
||||
for (i = minkey; i <= maxkey; i++) {
|
||||
for (j=0; j<syms_per_keycode; j++) {
|
||||
key = keymap[(i-minkey)*syms_per_keycode+j];
|
||||
if (key>=' ' && key<0x100 && i==XKeysymToKeycode(dpy,key)) {
|
||||
keycodes[key]=i;
|
||||
modifiers[key]=j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
|
||||
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
|
||||
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
|
||||
|
||||
XFree ((char *)keymap);
|
||||
}
|
||||
|
||||
/* this function adjusts the modifiers according to mod (as from modifiers) and ModifierState */
|
||||
void KeyboardEvent::tweakModifiers(signed char mod, bool down)
|
||||
{
|
||||
|
||||
bool isShift = ModifierState & (LEFTSHIFT|RIGHTSHIFT);
|
||||
if(mod < 0)
|
||||
return;
|
||||
|
||||
if(isShift && mod != 1) {
|
||||
if(ModifierState & LEFTSHIFT) {
|
||||
XTestFakeKeyEvent(dpy, leftShiftCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
if(ModifierState & RIGHTSHIFT) {
|
||||
XTestFakeKeyEvent(dpy, rightShiftCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
if(!isShift && mod==1) {
|
||||
XTestFakeKeyEvent(dpy, leftShiftCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
|
||||
if((ModifierState&ALTGR) && mod != 2) {
|
||||
XTestFakeKeyEvent(dpy, altGrCode,
|
||||
!down, CurrentTime);
|
||||
}
|
||||
|
||||
if(!(ModifierState&ALTGR) && mod==2) {
|
||||
XTestFakeKeyEvent(dpy, altGrCode,
|
||||
down, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardEvent::exec() {
|
||||
#define ADJUSTMOD(sym,state) \
|
||||
if(keySym==sym) { if(down) ModifierState|=state; else ModifierState&=~state; }
|
||||
|
||||
ADJUSTMOD(XK_Shift_L,LEFTSHIFT);
|
||||
ADJUSTMOD(XK_Shift_R,RIGHTSHIFT);
|
||||
ADJUSTMOD(XK_Mode_switch,ALTGR);
|
||||
|
||||
if(keySym>=' ' && keySym<0x100) {
|
||||
KeyCode k;
|
||||
if (down) {
|
||||
tweakModifiers(modifiers[keySym],True);
|
||||
}
|
||||
k = keycodes[keySym];
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(dpy, k, down, CurrentTime);
|
||||
}
|
||||
if (down) {
|
||||
tweakModifiers(modifiers[keySym],False);
|
||||
}
|
||||
} else {
|
||||
KeyCode k = XKeysymToKeycode(dpy, keySym );
|
||||
if (k != NoSymbol) {
|
||||
XTestFakeKeyEvent(dpy, k, down, CurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PointerEvent::initialized = false;
|
||||
Display *PointerEvent::dpy;
|
||||
int PointerEvent::buttonMask = 0;
|
||||
|
||||
PointerEvent::PointerEvent(int b, int _x, int _y)
|
||||
: button_mask(b),x(_x),y(_y)
|
||||
{
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
dpy = QX11Info::display();
|
||||
buttonMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PointerEvent::exec() {
|
||||
QDesktopWidget *desktopWidget = QApplication::desktop();
|
||||
|
||||
int screen = desktopWidget->screenNumber();
|
||||
if (screen < 0)
|
||||
screen = 0;
|
||||
XTestFakeMotionEvent(dpy, screen, x, y, CurrentTime);
|
||||
|
||||
for(int i = 0; i < 5; i++) {
|
||||
if ((buttonMask&(1<<i))!=(button_mask&(1<<i))) {
|
||||
XTestFakeButtonEvent(dpy,
|
||||
i+1,
|
||||
(button_mask&(1<<i))?True:False,
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
buttonMask = button_mask;
|
||||
}
|
||||
|
||||
|
||||
ClipboardEvent::ClipboardEvent(CurrentController *c, const QString &ctext)
|
||||
:controller(c),text(ctext)
|
||||
{
|
||||
}
|
||||
|
||||
void ClipboardEvent::exec()
|
||||
{
|
||||
#if 0
|
||||
if ((controller->lastClipboardDirection == ConnectionController::LAST_SYNC_TO_CLIENT) &&
|
||||
(controller->lastClipboardText == text)) {
|
||||
return;
|
||||
}
|
||||
controller->lastClipboardDirection = ConnectionController::LAST_SYNC_TO_SERVER;
|
||||
controller->lastClipboardText = text;
|
||||
|
||||
controller->clipboard->setText(text, QClipboard::Clipboard);
|
||||
controller->clipboard->setText(text, QClipboard::Selection);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
VNCEvent::~ VNCEvent()
|
||||
{
|
||||
}
|
63
events.h
Normal file
63
events.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* This file is part of the KDE project
|
||||
Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it>
|
||||
(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; version 2
|
||||
of the License.
|
||||
*/
|
||||
|
||||
#ifndef EVENTS_H
|
||||
#define EVENTS_H
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
class CurrentController;
|
||||
|
||||
class VNCEvent {
|
||||
public:
|
||||
virtual void exec() = 0;
|
||||
virtual ~VNCEvent();
|
||||
};
|
||||
|
||||
class KeyboardEvent : public VNCEvent {
|
||||
bool down;
|
||||
KeySym keySym;
|
||||
|
||||
static Display *dpy;
|
||||
static signed char modifiers[0x100];
|
||||
static KeyCode keycodes[0x100], leftShiftCode, rightShiftCode, altGrCode;
|
||||
static const int LEFTSHIFT;
|
||||
static const int RIGHTSHIFT;
|
||||
static const int ALTGR;
|
||||
static char ModifierState;
|
||||
|
||||
static void tweakModifiers(signed char mod, bool down);
|
||||
public:
|
||||
static void initKeycodes();
|
||||
|
||||
KeyboardEvent(bool d, KeySym k);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
class PointerEvent : public VNCEvent {
|
||||
int button_mask, x, y;
|
||||
|
||||
static bool initialized;
|
||||
static Display *dpy;
|
||||
static int buttonMask;
|
||||
public:
|
||||
PointerEvent(int b, int _x, int _y);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
class ClipboardEvent : public VNCEvent {
|
||||
CurrentController *controller;
|
||||
QString text;
|
||||
public:
|
||||
ClipboardEvent(CurrentController *c, const QString &text);
|
||||
virtual void exec();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -12,7 +12,6 @@
|
|||
#include "krfbserver.h"
|
||||
#include "krfbserver.moc"
|
||||
|
||||
//#include "rfbcontroller.h"
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
|
@ -25,23 +24,25 @@
|
|||
#include <KGlobal>
|
||||
#include <KUser>
|
||||
#include <KLocale>
|
||||
#include <KStaticDeleter>
|
||||
#include <KNotification>
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
#include <QX11Info>
|
||||
|
||||
#include <rfb/rfb.h>
|
||||
|
||||
#include "connectioncontroller.h"
|
||||
|
||||
const int DEFAULT_TCP_PORT = 5900;
|
||||
|
||||
KrfbServer::KrfbServer()
|
||||
: QObject(0), _controller(0) //new RFBController(0))
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(startListening()));
|
||||
static KStaticDeleter<KrfbServer> sd;
|
||||
KrfbServer * KrfbServer::_self = 0;
|
||||
KrfbServer * KrfbServer::self() {
|
||||
if (!_self) sd.setObject(_self, new KrfbServer);
|
||||
return _self;
|
||||
}
|
||||
|
||||
// TESTING!!!
|
||||
QTimer::singleShot(100000, this, SLOT(disconnectAndQuit()));
|
||||
|
||||
KrfbServer::KrfbServer()
|
||||
{
|
||||
kDebug() << "starting " << endl;
|
||||
QTimer::singleShot(0, this, SLOT(startListening()));
|
||||
}
|
||||
|
||||
void KrfbServer::startListening() {
|
||||
|
@ -51,8 +52,8 @@ void KrfbServer::startListening() {
|
|||
|
||||
int port = tcpConfig.readEntry("port",DEFAULT_TCP_PORT);
|
||||
|
||||
_server = new QTcpServer(this);
|
||||
connect(_server,SIGNAL(newConnection()),SLOT(newConnection()));
|
||||
_server = new TcpServer(this);
|
||||
connect(_server,SIGNAL(connectionReceived(int)),SLOT(newConnection(int)));
|
||||
|
||||
if (!_server->listen(QHostAddress::Any, port)) {
|
||||
// TODO: handle error more gracefully
|
||||
|
@ -60,6 +61,7 @@ void KrfbServer::startListening() {
|
|||
deleteLater();
|
||||
return;
|
||||
}
|
||||
kDebug() << "server listening on port " << DEFAULT_TCP_PORT << endl;
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,16 +70,9 @@ KrfbServer::~KrfbServer()
|
|||
//delete _controller;
|
||||
}
|
||||
|
||||
void KrfbServer::newConnection()
|
||||
void KrfbServer::newConnection(int fdNum)
|
||||
{
|
||||
int fdNum = 0;
|
||||
QTcpSocket *conn = _server->nextPendingConnection();
|
||||
QString peer = conn->peerAddress().toString();
|
||||
emit sessionEstablished(peer);
|
||||
connect (conn, SIGNAL(disconnected()), SIGNAL(sessionFinished()));
|
||||
|
||||
fdNum = conn->socketDescriptor();
|
||||
// TODO: start the actual sharing implementation
|
||||
// TODO: get peer address
|
||||
startServer(fdNum);
|
||||
}
|
||||
|
||||
|
@ -93,45 +88,28 @@ void KrfbServer::disconnectAndQuit()
|
|||
emit quitApp();
|
||||
}
|
||||
|
||||
|
||||
void KrfbServer::startServer(int fd)
|
||||
{
|
||||
rfbScreenInfoPtr server;
|
||||
XImage *framebufferImage;
|
||||
ConnectionController *cc = new ConnectionController(fd, this);
|
||||
cc->start();
|
||||
}
|
||||
|
||||
framebufferImage = XGetImage(QX11Info::display(),
|
||||
QApplication::desktop()->winId(),
|
||||
0,
|
||||
0,
|
||||
QApplication::desktop()->width(),
|
||||
QApplication::desktop()->height(),
|
||||
AllPlanes,
|
||||
ZPixmap);
|
||||
TcpServer::TcpServer(QObject * parent)
|
||||
:QTcpServer(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int w = framebufferImage->width;
|
||||
int h = framebufferImage->height;
|
||||
char *fb = framebufferImage->data;
|
||||
|
||||
rfbLogEnable(0);
|
||||
server = rfbGetScreen(0, 0, w, h,
|
||||
framebufferImage->bits_per_pixel,
|
||||
8,
|
||||
framebufferImage->bits_per_pixel/8);
|
||||
|
||||
server->paddedWidthInBytes = framebufferImage->bytes_per_line;
|
||||
server->frameBuffer = fb;
|
||||
server->autoPort = TRUE;
|
||||
server->inetdSock = fd;
|
||||
|
||||
server->desktopName = i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()).toLatin1();
|
||||
|
||||
// if (!myCursor)
|
||||
// myCursor = rfbMakeXCursor(19, 19, (char*) cur, (char*) mask);
|
||||
// server->cursor = myCursor;
|
||||
|
||||
rfbInitServer(server);
|
||||
|
||||
rfbRunEventLoop(server, -1, TRUE);
|
||||
void TcpServer::incomingConnection(int fd)
|
||||
{
|
||||
emit connectionReceived(fd);
|
||||
}
|
||||
|
||||
void KrfbServer::handleNotifications(QString name, QString desc )
|
||||
{
|
||||
KNotification::event(name, desc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
33
krfbserver.h
33
krfbserver.h
|
@ -11,9 +11,22 @@
|
|||
#define KRFBSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTcpServer>
|
||||
|
||||
class QTcpServer;
|
||||
class RFBController;
|
||||
class TcpServer: public QTcpServer {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TcpServer(QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
void connectionReceived(int fd);
|
||||
|
||||
protected:
|
||||
virtual void incomingConnection(int fd);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
This class implements the listening server for the RFB protocol.
|
||||
|
@ -24,29 +37,31 @@ class KrfbServer : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KrfbServer();
|
||||
|
||||
static KrfbServer *self();
|
||||
|
||||
~KrfbServer();
|
||||
|
||||
signals:
|
||||
void sessionEstablished(const QString&);
|
||||
void sessionEstablished(QString);
|
||||
void sessionFinished();
|
||||
void desktopControlSettingChanged(bool);
|
||||
void quitApp();
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
void newConnection();
|
||||
void newConnection(int fd);
|
||||
void startListening();
|
||||
void enableDesktopControl(bool);
|
||||
void disconnectAndQuit();
|
||||
void handleNotifications(QString, QString);
|
||||
|
||||
private:
|
||||
KrfbServer();
|
||||
static KrfbServer *_self;
|
||||
|
||||
void startServer(int fd);
|
||||
|
||||
RFBController *_controller;
|
||||
QTcpServer *_server;
|
||||
|
||||
TcpServer *_server;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
18
main.cpp
18
main.cpp
|
@ -75,26 +75,26 @@ int main(int argc, char *argv[])
|
|||
|
||||
KApplication app;
|
||||
|
||||
|
||||
TrayIcon trayicon(new ManageInvitationsDialog);
|
||||
KrfbServer server;
|
||||
|
||||
KrfbServer *server = KrfbServer::self(); // initialize the server manager
|
||||
|
||||
QObject::connect(&app, SIGNAL(lastWindowClosed()), // do not show passivepopup
|
||||
&trayicon, SLOT(prepareQuit()));
|
||||
QObject::connect(&app, SIGNAL(lastWindowClosed()),
|
||||
&server, SLOT(disconnectAndQuit()));
|
||||
server, SLOT(disconnectAndQuit()));
|
||||
|
||||
QObject::connect(&trayicon, SIGNAL(enableDesktopControl(bool)),
|
||||
&server, SLOT(enableDesktopControl(bool)));
|
||||
QObject::connect(&server, SIGNAL(sessionEstablished(QString)),
|
||||
server, SLOT(enableDesktopControl(bool)));
|
||||
QObject::connect(server, SIGNAL(sessionEstablished(QString)),
|
||||
&trayicon, SLOT(showConnectedMessage(QString)));
|
||||
QObject::connect(&server, SIGNAL(sessionFinished()),
|
||||
QObject::connect(server, SIGNAL(sessionFinished()),
|
||||
&trayicon, SLOT(showDisconnectedMessage()));
|
||||
QObject::connect(&server, SIGNAL(desktopControlSettingChanged(bool)),
|
||||
QObject::connect(server, SIGNAL(desktopControlSettingChanged(bool)),
|
||||
&trayicon, SLOT(setDesktopControlSetting(bool)));
|
||||
QObject::connect(&trayicon, SIGNAL(quitApp()),
|
||||
&server, SLOT(disconnectAndQuit()));
|
||||
QObject::connect(&server, SIGNAL(quitApp()),
|
||||
server, SLOT(disconnectAndQuit()));
|
||||
QObject::connect(server, SIGNAL(quitApp()),
|
||||
&app, SLOT(quit()));
|
||||
|
||||
//TODO: implement some error reporting mechanism between server and tray icon
|
||||
|
|
Loading…
Reference in New Issue
Block a user