mirror of
https://invent.kde.org/network/krfb
synced 2024-07-05 09:28:35 +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:
parent
cda3a0b972
commit
25f4383a51
|
@ -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)
|
||||
|
|
112
krfb/invitationsrfbclient.cpp
Normal file
112
krfb/invitationsrfbclient.cpp
Normal 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"
|
48
krfb/invitationsrfbclient.h
Normal file
48
krfb/invitationsrfbclient.h
Normal 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
|
|
@ -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()
|
||||
|
|
|
@ -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
86
krfb/pendingrfbclient.cpp
Normal 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
46
krfb/pendingrfbclient.h
Normal 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
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
86
krfb/tubesrfbclient.cpp
Normal 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
58
krfb/tubesrfbclient.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue
Block a user