1
0
mirror of https://invent.kde.org/network/krfb synced 2024-07-03 00:18:36 +00:00

Fix the broken clients design.

Currently clients are not connected immediately because the user needs
to be notified and take action upon the connection request. This makes
the design of the RfbClient class a bit strange. This new approach
applies tp-qt4's PendingOperation design to RfbClients. New connections
create a PendingRfbClient that internally handles the user notification
and the RfbClient object is only created when the user has accepted the
connection.

svn path=/trunk/KDE/kdenetwork/krfb/; revision=1195292
This commit is contained in:
George Kiagiadakis 2010-11-10 18:57:32 +00:00
parent cda3a0b972
commit 25f4383a51
16 changed files with 545 additions and 231 deletions

View File

@ -61,12 +61,14 @@ set (krfb_SRCS
rfbserver.cpp
rfbclient.cpp
invitationsrfbserver.cpp
invitationsrfbclient.cpp
)
if (TELEPATHY_QT4_FOUND)
set (krfb_SRCS
${krfb_SRCS}
tubesrfbserver.cpp
tubesrfbclient.cpp
tubesclienthandler.cpp
)
endif (TELEPATHY_QT4_FOUND)

View File

@ -0,0 +1,112 @@
/*
Copyright (C) 2009-2010 Collabora Ltd <info@collabora.co.uk>
@author George Goldberg <george.goldberg@collabora.co.uk>
@author George Kiagiadakis <george.kiagiadakis@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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "invitationsrfbclient.h"
#include "invitationmanager.h"
#include "krfbconfig.h"
#include "sockethelpers.h"
#include "connectiondialog.h"
#include <KNotification>
#include <KLocale>
bool InvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
{
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
QByteArray password = KrfbConfig::uninvitedConnectionPassword().toLocal8Bit();
bool authd = false;
kDebug() << "about to start autentication";
if (allowUninvited) {
authd = vncAuthCheckPassword(password, encryptedPassword);
}
if (!authd) {
QList<Invitation> invlist = InvitationManager::self()->invitations();
foreach(const Invitation & it, invlist) {
kDebug() << "checking password";
if (vncAuthCheckPassword(it.password().toLocal8Bit(), encryptedPassword)
&& it.isValid())
{
authd = true;
InvitationManager::self()->removeInvitation(it);
break;
}
}
}
if (!authd) {
if (InvitationManager::self()->invitations().size() > 0) {
KNotification::event("InvalidPasswordInvitations",
i18n("Failed login attempt from %1: wrong password", name()));
} else {
KNotification::event("InvalidPassword",
i18n("Failed login attempt from %1: wrong password", name()));
}
return false;
}
return true;
}
void PendingInvitationsRfbClient::processNewClient()
{
QString host = peerAddress(m_rfbClient->sock) + ":" + QString::number(peerPort(m_rfbClient->sock));
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
if (!allowUninvited && InvitationManager::self()->activeInvitations() == 0) {
KNotification::event("UnexpectedConnection",
i18n("Refused uninvited connection attempt from %1", host));
reject();
} else if (!KrfbConfig::askOnConnect()) {
KNotification::event("NewConnectionAutoAccepted",
i18n("Accepted connection from %1", host));
accept(new InvitationsRfbClient(m_rfbClient, parent()));
} else {
KNotification::event("NewConnectionOnHold",
i18n("Received connection from %1, on hold (waiting for confirmation)",
host));
ConnectionDialog *dialog = new ConnectionDialog(0);
dialog->setRemoteHost(host);
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
connect(dialog, SIGNAL(cancelClicked()), SLOT(reject()));
dialog->show();
}
}
void PendingInvitationsRfbClient::dialogAccepted()
{
ConnectionDialog *dialog = qobject_cast<ConnectionDialog *>(sender());
Q_ASSERT(dialog);
InvitationsRfbClient *client = new InvitationsRfbClient(m_rfbClient, parent());
client->setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
accept(client);
}
#include "invitationsrfbclient.moc"

View File

@ -0,0 +1,48 @@
/*
Copyright (C) 2010 Collabora Ltd <info@collabora.co.uk>
@author George Kiagiadakis <george.kiagiadakis@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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INVITATIONSRFBCLIENT_H
#define INVITATIONSRFBCLIENT_H
#include "rfbclient.h"
class InvitationsRfbClient : public RfbClient
{
public:
InvitationsRfbClient(rfbClientPtr client, QObject* parent = 0)
: RfbClient(client, parent) {}
protected:
virtual bool checkPassword(const QByteArray & encryptedPassword);
};
class PendingInvitationsRfbClient : public PendingRfbClient
{
Q_OBJECT
public:
PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent = 0)
: PendingRfbClient(client, parent) {}
protected Q_SLOTS:
virtual void processNewClient();
private Q_SLOTS:
void dialogAccepted();
};
#endif // INVITATIONSRFBCLIENT_H

View File

@ -19,10 +19,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "invitationsrfbserver.h"
#include "invitationsrfbclient.h"
#include "krfbconfig.h"
#include "invitationmanager.h"
#include "rfbservermanager.h"
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtNetwork/QHostInfo>
#include <KNotification>
#include <KLocale>
@ -30,77 +31,6 @@
#include <KUser>
#include <DNSSD/PublicService>
//************
class InvitationsRfbClient : public RfbClient
{
public:
InvitationsRfbClient(rfbClientPtr client, QObject* parent = 0)
: RfbClient(client, parent) {}
virtual rfbNewClientAction doHandle();
virtual bool checkPassword(const QByteArray & encryptedPassword);
};
rfbNewClientAction InvitationsRfbClient::doHandle()
{
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
if (!allowUninvited && InvitationManager::self()->activeInvitations() == 0) {
KNotification::event("UnexpectedConnection",
i18n("Refused uninvited connection attempt from %1", name()));
return RFB_CLIENT_REFUSE;
}
return RfbClient::doHandle();
}
bool InvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
{
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
QByteArray password = KrfbConfig::uninvitedConnectionPassword().toLocal8Bit();
bool authd = false;
kDebug() << "about to start autentication";
if (allowUninvited) {
authd = vncAuthCheckPassword(password, encryptedPassword);
}
if (!authd) {
QList<Invitation> invlist = InvitationManager::self()->invitations();
foreach(const Invitation & it, invlist) {
kDebug() << "checking password";
if (vncAuthCheckPassword(it.password().toLocal8Bit(), encryptedPassword)
&& it.isValid())
{
authd = true;
InvitationManager::self()->removeInvitation(it);
break;
}
}
}
if (!authd) {
if (InvitationManager::self()->invitations().size() > 0) {
KNotification::event("InvalidPasswordInvitations",
i18n("Failed login attempt from %1: wrong password", name()));
} else {
KNotification::event("InvalidPassword",
i18n("Failed login attempt from %1: wrong password", name()));
}
return false;
}
return true;
}
//***********
void InvitationsRfbServer::init()
{
InvitationsRfbServer *server;
@ -111,9 +41,9 @@ void InvitationsRfbServer::init()
QTimer::singleShot(0, server, SLOT(startAndCheck()));
}
RfbClient* InvitationsRfbServer::newClient(rfbClientPtr client)
PendingRfbClient* InvitationsRfbServer::newClient(rfbClientPtr client)
{
return new InvitationsRfbClient(client, this);
return new PendingInvitationsRfbClient(client, this);
}
void InvitationsRfbServer::startAndCheck()

View File

@ -31,7 +31,7 @@ public:
protected:
InvitationsRfbServer() : RfbServer(0) {}
virtual RfbClient* newClient(rfbClientPtr client);
virtual PendingRfbClient* newClient(rfbClientPtr client);
private Q_SLOTS:
void startAndCheck();

86
krfb/pendingrfbclient.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pendingrfbclient.h"
#include "connectiondialog.h"
#include "krfbconfig.h"
#include <KDebug>
#include <KNotification>
PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent)
: QObject(parent), m_client(0), m_rfbClient(client)
{
QMetaObject::invokeMethod(this, "processNewClient", Qt::QueuedConnection);
}
void PendingRfbClient::accept()
{
kDebug() << "accepted connection";
Q_ASSERT(m_client);
m_client->setOnHold(false);
Q_EMIT finished(m_client);
deleteLater();
}
void PendingRfbClient::reject()
{
kDebug() << "refused connection";
rfbCloseClient(m_rfbClient);
rfbClientConnectionGone(m_rfbClient);
Q_EMIT finished(NULL);
deleteLater();
}
void PendingRfbClient::showUserConfirmationDialog()
{
kDebug();
Q_ASSERT(m_client);
if (!KrfbConfig::askOnConnect()) {
KNotification::event("NewConnectionAutoAccepted",
i18n("Accepted connection from %1", m_client->name()));
accept();
} else {
KNotification::event("NewConnectionOnHold",
i18n("Received connection from %1, on hold (waiting for confirmation)",
m_client->name()));
ConnectionDialog *dialog = new ConnectionDialog(0);
dialog->setRemoteHost(m_client->name());
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
connect(dialog, SIGNAL(cancelClicked()), SLOT(dialogRejected()));
dialog->show();
}
}
void PendingRfbClient::dialogAccepted()
{
ConnectionDialog *dialog = qobject_cast<ConnectionDialog *>(sender());
Q_ASSERT(dialog);
m_client->setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
accept();
}
void PendingRfbClient::dialogRejected()
{
reject();
}

46
krfb/pendingrfbclient.h Normal file
View File

@ -0,0 +1,46 @@
/*
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
@author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PENDINGRFBCLIENT_H
#define PENDINGRFBCLIENT_H
#include "rfbclient.h"
#include <QtCore/QObject>
class PendingRfbClient : public QObject
{
Q_OBJECT
public:
PendingRfbClient(rfbClientPtr client, QObject* parent = 0);
Q_SIGNALS:
void finished(RfbClient *client);
protected Q_SLOTS:
virtual void processNewClient() = 0;
void showUserConfirmationDialog();
void accept();
void reject();
protected:
RfbClient *m_client;
rfbClientPtr m_rfbClient;
};
#endif // PENDINGRFBCLIENT_H

View File

@ -30,12 +30,10 @@
struct RfbClient::Private
{
Private(rfbClientPtr client) :
connected(false),
controlEnabled(false),
client(client)
{}
bool connected;
bool controlEnabled;
rfbClientPtr client;
QSocketNotifier *notifier;
@ -79,27 +77,18 @@ void RfbClient::setControlEnabled(bool enabled)
}
}
void RfbClient::update()
bool RfbClient::isOnHold() const
{
rfbUpdateClient(d->client);
//This is how we handle disconnection.
//if rfbUpdateClient() finds out that it can't write to the socket,
//it closes it and sets it to -1. So, we just have to check this here
//and call rfbClientConnectionGone() if necessary. This will call
//the clientGoneHook which in turn will remove this RfbClient instance
//from the server manager and will call deleteLater() to delete it
if (d->client->sock == -1) {
kDebug() << "disconnected during update";
d->notifier->setEnabled(false);
rfbClientConnectionGone(d->client);
}
return d->client->onHold ? true : false;
}
void RfbClient::setOnHold(bool onHold)
{
d->client->onHold = onHold;
d->notifier->setEnabled(!onHold);
if (isOnHold() != onHold) {
d->client->onHold = onHold;
d->notifier->setEnabled(!onHold);
Q_EMIT holdStatusChanged(onHold);
}
}
void RfbClient::closeConnection()
@ -109,47 +98,6 @@ void RfbClient::closeConnection()
rfbClientConnectionGone(d->client);
}
rfbNewClientAction RfbClient::doHandle()
{
kDebug();
if (!KrfbConfig::askOnConnect()) {
KNotification::event("NewConnectionAutoAccepted",
i18n("Accepted connection from %1", name()));
setStatusConnected();
return RFB_CLIENT_ACCEPT;
}
KNotification::event("NewConnectionOnHold",
i18n("Received connection from %1, on hold (waiting for confirmation)",
name()));
ConnectionDialog *dialog = new ConnectionDialog(0);
dialog->setRemoteHost(name());
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
connect(dialog, SIGNAL(cancelClicked()), SLOT(dialogRejected()));
dialog->show();
return RFB_CLIENT_ON_HOLD;
}
bool RfbClient::isConnected() const
{
return d->connected;
}
void RfbClient::setStatusConnected()
{
if (!d->connected) {
d->connected = true;
Q_EMIT connected(this);
}
}
void RfbClient::handleKeyboardEvent(bool down, rfbKeySym keySym)
{
if (d->controlEnabled) {
@ -218,24 +166,62 @@ void RfbClient::onSocketActivated()
}
}
void RfbClient::dialogAccepted()
void RfbClient::update()
{
ConnectionDialog *dialog = qobject_cast<ConnectionDialog *>(sender());
rfbUpdateClient(d->client);
if (!dialog) {
kWarning() << "Wrong type of sender.";
return;
//This is how we handle disconnection.
//if rfbUpdateClient() finds out that it can't write to the socket,
//it closes it and sets it to -1. So, we just have to check this here
//and call rfbClientConnectionGone() if necessary. This will call
//the clientGoneHook which in turn will remove this RfbClient instance
//from the server manager and will call deleteLater() to delete it
if (d->client->sock == -1) {
kDebug() << "disconnected during update";
d->notifier->setEnabled(false);
rfbClientConnectionGone(d->client);
}
setOnHold(false);
setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
setStatusConnected();
}
void RfbClient::dialogRejected()
//*************
PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent)
: QObject(parent), m_rfbClient(client)
{
kDebug();
QMetaObject::invokeMethod(this, "processNewClient", Qt::QueuedConnection);
}
PendingRfbClient::~PendingRfbClient()
{
kDebug();
}
void PendingRfbClient::accept(RfbClient *newClient)
{
kDebug() << "accepted connection";
m_rfbClient->clientData = newClient;
newClient->setOnHold(false);
Q_EMIT finished(newClient);
deleteLater();
}
static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); }
void PendingRfbClient::reject()
{
kDebug() << "refused connection";
closeConnection();
//override the clientGoneHook that was previously set by RfbServer
m_rfbClient->clientGoneHook = clientGoneHookNoop;
rfbCloseClient(m_rfbClient);
rfbClientConnectionGone(m_rfbClient);
Q_EMIT finished(NULL);
deleteLater();
}
#include "rfbclient.moc"

View File

@ -27,6 +27,7 @@ class RfbClient : public QObject
{
Q_OBJECT
Q_PROPERTY(bool controlEnabled READ controlEnabled WRITE setControlEnabled NOTIFY controlEnabledChanged)
Q_PROPERTY(bool onHold READ isOnHold WRITE setOnHold NOTIFY holdStatusChanged)
public:
RfbClient(rfbClientPtr client, QObject *parent = 0);
virtual ~RfbClient();
@ -38,28 +39,24 @@ public:
bool controlEnabled() const;
void setControlEnabled(bool enabled);
bool isOnHold() const;
public Q_SLOTS:
void setOnHold(bool onHold);
void closeConnection();
Q_SIGNALS:
void controlEnabledChanged(bool enabled);
void connected(RfbClient *self);
void holdStatusChanged(bool onHold);
protected:
friend class RfbServer;
friend class RfbServerManager;
///called by RfbServer to begin handling the client
virtual rfbNewClientAction doHandle();
///called by RfbServerManager to send framebuffer updates
///and check for possible disconnection
void update();
bool isConnected() const;
void setStatusConnected(); ///call to declare the client as connected
virtual void handleKeyboardEvent(bool down, rfbKeySym keySym);
virtual void handleMouseEvent(int buttonMask, int x, int y);
@ -79,12 +76,31 @@ protected:
private Q_SLOTS:
void onSocketActivated();
void dialogAccepted();
void dialogRejected();
private:
struct Private;
Private *const d;
};
class PendingRfbClient : public QObject
{
Q_OBJECT
public:
PendingRfbClient(rfbClientPtr client, QObject *parent = 0);
virtual ~PendingRfbClient();
Q_SIGNALS:
void finished(RfbClient *client);
protected Q_SLOTS:
virtual void processNewClient() = 0;
void accept(RfbClient *newClient);
void reject();
protected:
rfbClientPtr m_rfbClient;
};
#endif // RFBCLIENT_H

View File

@ -203,20 +203,26 @@ void RfbServer::onListenSocketActivated()
rfbProcessNewConnection(d->screen);
}
void RfbServer::pendingClientFinished(RfbClient *client)
{
kDebug();
if (client) {
RfbServerManager::instance()->addClient(client);
}
}
//static
rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl)
{
kDebug() << "New client";
RfbServer *server = static_cast<RfbServer*>(cl->screen->screenData);
RfbClient *client = server->newClient(cl);
RfbServerManager::instance()->addClient(client);
PendingRfbClient *pendingClient = server->newClient(cl);
connect(pendingClient, SIGNAL(finished(RfbClient*)),
server, SLOT(pendingClientFinished(RfbClient*)));
//clientData is used by the static callbacks to determine their context
cl->clientData = client;
cl->clientGoneHook = clientGoneHook;
return client->doHandle();
return RFB_CLIENT_ON_HOLD;
}
//static

View File

@ -48,9 +48,10 @@ public Q_SLOTS:
private Q_SLOTS:
void onListenSocketActivated();
void pendingClientFinished(RfbClient *client);
protected:
virtual RfbClient *newClient(rfbClientPtr client) = 0;
virtual PendingRfbClient *newClient(rfbClientPtr client) = 0;
private:
static rfbNewClientAction newClientHook(rfbClientPtr cl);

View File

@ -209,8 +209,7 @@ void RfbServerManager::addClient(RfbClient* cc)
}
d->clients.insert(cc);
QObject::connect(cc, SIGNAL(connected(RfbClient*)),
this, SIGNAL(clientConnected(RfbClient*)));
Q_EMIT clientConnected(cc);
}
void RfbServerManager::removeClient(RfbClient* cc)
@ -222,9 +221,7 @@ void RfbServerManager::removeClient(RfbClient* cc)
d->rfbUpdateTimer.stop();
}
if (cc->isConnected()) {
Q_EMIT clientDisconnected(cc);
}
Q_EMIT clientDisconnected(cc);
}
#include "rfbservermanager.moc"

86
krfb/tubesrfbclient.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
Copyright (C) 2009-2010 Collabora Ltd. <info@collabora.co.uk>
@author George Goldberg <george.goldberg@collabora.co.uk>
@author George Kiagiadakis <george.kiagiadakis@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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tubesrfbclient.h"
#include "krfbconfig.h"
#include "connectiondialog.h"
#include <KNotification>
#include <KLocale>
QString TubesRfbClient::name() const
{
return m_contact->alias();
}
void PendingTubesRfbClient::setContact(const Tp::ContactPtr & contact)
{
m_contact = contact;
if (m_processNewClientCalled) {
//processNewClient has already been called, so we need to act here
showConfirmationDialog();
}
}
void PendingTubesRfbClient::processNewClient()
{
if (!m_contact) {
//no associated contact yet, hold.
m_processNewClientCalled = true; //act when a contact is set
} else {
//we have a contact, begin handling
showConfirmationDialog();
}
}
void PendingTubesRfbClient::showConfirmationDialog()
{
QString name = m_contact->alias();
if (!KrfbConfig::askOnConnect()) {
KNotification::event("NewConnectionAutoAccepted",
i18n("Accepted connection from %1", name));
accept(new TubesRfbClient(m_rfbClient, m_contact, parent()));
} else {
KNotification::event("NewConnectionOnHold",
i18n("Received connection from %1, on hold (waiting for confirmation)",
name));
//TODO use a different dialog here, more suitable for the tubes use case
ConnectionDialog *dialog = new ConnectionDialog(0);
dialog->setRemoteHost(name);
dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl());
connect(dialog, SIGNAL(okClicked()), SLOT(dialogAccepted()));
connect(dialog, SIGNAL(cancelClicked()), SLOT(reject()));
dialog->show();
}
}
void PendingTubesRfbClient::dialogAccepted()
{
ConnectionDialog *dialog = qobject_cast<ConnectionDialog *>(sender());
Q_ASSERT(dialog);
TubesRfbClient *client = new TubesRfbClient(m_rfbClient, m_contact, parent());
client->setControlEnabled(dialog->cbAllowRemoteControl->isChecked());
accept(client);
}
#include "tubesrfbclient.moc"

58
krfb/tubesrfbclient.h Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright (C) 2010 Collabora Ltd. <info@collabora.co.uk>
@author George Kiagiadakis <george.kiagiadakis@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 Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TUBESRFBCLIENT_H
#define TUBESRFBCLIENT_H
#include "rfbclient.h"
#include <TelepathyQt4/Contact>
class TubesRfbClient : public RfbClient
{
public:
TubesRfbClient(rfbClientPtr client, const Tp::ContactPtr & contact, QObject* parent = 0)
: RfbClient(client, parent), m_contact(contact) {}
virtual QString name() const;
private:
Tp::ContactPtr m_contact;
};
class PendingTubesRfbClient : public PendingRfbClient
{
Q_OBJECT
public:
PendingTubesRfbClient(rfbClientPtr client, QObject* parent = 0)
: PendingRfbClient(client, parent), m_processNewClientCalled(false) {}
void setContact(const Tp::ContactPtr & contact);
protected Q_SLOTS:
virtual void processNewClient();
private Q_SLOTS:
void showConfirmationDialog();
void dialogAccepted();
private:
Tp::ContactPtr m_contact;
bool m_processNewClientCalled;
};
#endif // TUBESRFBCLIENT_H

View File

@ -17,6 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tubesrfbserver.h"
#include "tubesrfbclient.h"
#include "sockethelpers.h"
#include <QtGui/QApplication>
@ -61,72 +62,11 @@ const QDBusArgument &operator>>(const QDBusArgument &argument,
//**************
class TubesRfbClient : public RfbClient
{
public:
TubesRfbClient(rfbClientPtr client, QObject* parent = 0);
virtual QString name() const;
void setContact(const Tp::ContactPtr & contact);
protected:
virtual rfbNewClientAction doHandle();
private:
Tp::ContactPtr m_contact;
bool m_doHandleCalled;
};
TubesRfbClient::TubesRfbClient(rfbClientPtr client, QObject* parent)
: RfbClient(client, parent), m_doHandleCalled(false)
{
}
QString TubesRfbClient::name() const
{
if (m_contact) {
return m_contact->alias();
} else {
return RfbClient::name();
}
}
void TubesRfbClient::setContact(const Tp::ContactPtr & contact)
{
m_contact = contact;
if (m_doHandleCalled) {
//doHandle has already been called, so we need to call the parent's implementation here
rfbNewClientAction action = RfbClient::doHandle();
//we were previously on hold, so we now need to act if
//the parent's doHandle() says we must do something else
if (action == RFB_CLIENT_ACCEPT) {
setOnHold(false);
} else if (action == RFB_CLIENT_REFUSE) {
closeConnection();
} //else if action == RFB_CLIENT_ON_HOLD there is nothing to do
}
}
rfbNewClientAction TubesRfbClient::doHandle()
{
if (!m_contact) {
//no associated contact yet, hold.
m_doHandleCalled = true; //act when a contact is set
return RFB_CLIENT_ON_HOLD;
} else {
//we have a contact, begin handling
return RfbClient::doHandle();
}
}
//**************
struct TubesRfbServer::Private
{
Tp::ChannelPtr channel;
QHash<int, Tp::ContactPtr> contactsPerPort;
QHash<int, TubesRfbClient*> clientsPerPort;
QHash<int, PendingTubesRfbClient*> clientsPerPort;
};
TubesRfbServer::TubesRfbServer(const Tp::ChannelPtr & channel, QObject *parent)
@ -153,11 +93,11 @@ TubesRfbServer::~TubesRfbServer()
delete d;
}
RfbClient* TubesRfbServer::newClient(rfbClientPtr client)
PendingRfbClient* TubesRfbServer::newClient(rfbClientPtr client)
{
kDebug() << "new tubes client";
TubesRfbClient *c = new TubesRfbClient(client, this);
PendingTubesRfbClient *c = new PendingTubesRfbClient(client, this);
int port = peerPort(client->sock);
d->clientsPerPort[port] = c;

View File

@ -29,7 +29,7 @@ public:
TubesRfbServer(const Tp::ChannelPtr & channel, QObject* parent = 0);
virtual ~TubesRfbServer();
virtual RfbClient* newClient(rfbClientPtr client);
virtual PendingRfbClient* newClient(rfbClientPtr client);
private Q_SLOTS:
void close();