diff --git a/krfb/framebuffer.h b/krfb/framebuffer.h index 0013888..99828e1 100644 --- a/krfb/framebuffer.h +++ b/krfb/framebuffer.h @@ -1,57 +1,57 @@ /* This file is part of the KDE project Copyright (C) 2007 Alessandro Praduroux 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 FRAMEBUFFER_H #define FRAMEBUFFER_H #include "rfb.h" #include "krfbprivate_export.h" -#include -#include -#include +#include +#include +#include #include class FrameBuffer; /** @author Alessandro Praduroux */ class KRFBPRIVATE_EXPORT FrameBuffer : public QObject { Q_OBJECT public: explicit FrameBuffer(WId id, QObject *parent = nullptr); ~FrameBuffer() override; char *data(); virtual QList modifiedTiles(); virtual int paddedWidth(); virtual int width(); virtual int height(); virtual int depth(); virtual void startMonitor(); virtual void stopMonitor(); virtual void getServerFormat(rfbPixelFormat &format); protected: WId win; char *fb; QList tiles; private: Q_DISABLE_COPY(FrameBuffer) }; #endif diff --git a/krfb/framebuffermanager.cpp b/krfb/framebuffermanager.cpp index 684a477..342ddb9 100644 --- a/krfb/framebuffermanager.cpp +++ b/krfb/framebuffermanager.cpp @@ -1,137 +1,137 @@ /* This file is part of the KDE project Copyright (C) 2009 Collabora Ltd @author George Goldberg 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 "framebuffermanager.h" #include "framebufferplugin.h" #include "krfbconfig.h" #include #include #include #include #include -#include +#include class FrameBufferManagerStatic { public: FrameBufferManager instance; }; Q_GLOBAL_STATIC(FrameBufferManagerStatic, frameBufferManagerStatic) FrameBufferManager::FrameBufferManager() { //qDebug(); loadPlugins(); } FrameBufferManager::~FrameBufferManager() { //qDebug(); } FrameBufferManager *FrameBufferManager::instance() { //qDebug(); return &frameBufferManagerStatic->instance; } void FrameBufferManager::loadPlugins() { //qDebug(); const QVector plugins = KPluginLoader::findPlugins(QStringLiteral("krfb"), [](const KPluginMetaData & md) { return md.serviceTypes().contains(QStringLiteral("krfb/framebuffer")); }); QVectorIterator i(plugins); i.toBack(); QSet unique; while (i.hasPrevious()) { const KPluginMetaData &data = i.previous(); // only load plugins once, even if found multiple times! if (unique.contains(data.name())) continue; KPluginFactory *factory = KPluginLoader(data.fileName()).factory(); if (!factory) { qDebug() << "KPluginFactory could not load the plugin:" << data.fileName(); } else { qDebug() << "found plugin at " << data.fileName(); } FrameBufferPlugin *plugin = factory->create(this); if (plugin) { m_plugins.insert(data.pluginId(), plugin); qDebug() << "Loaded plugin with name " << data.pluginId(); } else { qDebug() << "unable to load pluign for " << data.fileName(); } unique.insert (data.name()); } } QSharedPointer FrameBufferManager::frameBuffer(WId id) { //qDebug(); // See if there is still an existing framebuffer to this WId. if (m_frameBuffers.contains(id)) { QWeakPointer weakFrameBuffer = m_frameBuffers.value(id); if (weakFrameBuffer) { //qDebug() << "Found cached frame buffer."; return weakFrameBuffer.toStrongRef(); } else { //qDebug() << "Found deleted cached frame buffer. Don't use."; m_frameBuffers.remove(id); } } // We don't already have that frame buffer. QMap::const_iterator iter = m_plugins.constBegin(); while (iter != m_plugins.constEnd()) { if (iter.key() == KrfbConfig::preferredFrameBufferPlugin()) { qDebug() << "Using FrameBuffer:" << KrfbConfig::preferredFrameBufferPlugin(); QSharedPointer frameBuffer(iter.value()->frameBuffer(id)); if (frameBuffer) { m_frameBuffers.insert(id, frameBuffer.toWeakRef()); return frameBuffer; } } ++iter; } // No valid framebuffer plugin found. qDebug() << "No valid framebuffer found. returning null."; return QSharedPointer(); } diff --git a/krfb/framebuffermanager.h b/krfb/framebuffermanager.h index dad2501..d12a216 100644 --- a/krfb/framebuffermanager.h +++ b/krfb/framebuffermanager.h @@ -1,63 +1,63 @@ /* This file is part of the KDE project Copyright (C) 2009 Collabora Ltd @author George Goldberg 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_FRAMEBUFFERMANAGER_H #define KRFB_FRAMEBUFFERMANAGER_H #include "framebuffer.h" #include "krfbprivate_export.h" -#include -#include -#include -#include +#include +#include +#include +#include #include class FrameBufferPlugin; class KPluginFactory; class KRFBPRIVATE_EXPORT FrameBufferManager : public QObject { Q_OBJECT friend class FrameBufferManagerStatic; public: static FrameBufferManager *instance(); ~FrameBufferManager() override; QSharedPointer frameBuffer(WId id); private: Q_DISABLE_COPY(FrameBufferManager) FrameBufferManager(); void loadPlugins(); QMap m_plugins; QMap > m_frameBuffers; }; #endif // Header guard diff --git a/krfb/framebufferplugin.h b/krfb/framebufferplugin.h index 961b83f..94a9d83 100644 --- a/krfb/framebufferplugin.h +++ b/krfb/framebufferplugin.h @@ -1,44 +1,44 @@ /* This file is part of the KDE project Copyright (C) 2009 Collabora Ltd @author George Goldberg 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 LIB_KRFB_FRAMEBUFFERPLUGIN_H #define LIB_KRFB_FRAMEBUFFERPLUGIN_H #include "krfbprivate_export.h" -#include +#include #include class FrameBuffer; class KRFBPRIVATE_EXPORT FrameBufferPlugin : public QObject { Q_OBJECT public: FrameBufferPlugin(QObject *parent, const QVariantList &args); ~FrameBufferPlugin() override; virtual FrameBuffer *frameBuffer(WId id) = 0; }; #endif // Header guard diff --git a/krfb/invitationsrfbclient.cpp b/krfb/invitationsrfbclient.cpp index 6cee113..fa958e2 100644 --- a/krfb/invitationsrfbclient.cpp +++ b/krfb/invitationsrfbclient.cpp @@ -1,151 +1,151 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux Copyright (C) 2001-2003 by Tim Jansen 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 . */ #include "rfb.h" #include "invitationsrfbclient.h" #include "invitationsrfbserver.h" #include "krfbconfig.h" #include "sockethelpers.h" #include "connectiondialog.h" #include #include #include -#include +#include #include #include struct PendingInvitationsRfbClient::Private { Private(rfbClientPtr client) : client(client), askOnConnect(true) {} rfbClientPtr client; QSocketNotifier *notifier; bool askOnConnect; }; static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); } PendingInvitationsRfbClient::PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent) : PendingRfbClient(client, parent), d(new Private(client)) { d->client->clientGoneHook = clientGoneHookNoop; d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this); d->notifier->setEnabled(true); connect(d->notifier, &QSocketNotifier::activated, this, &PendingInvitationsRfbClient::onSocketActivated); } PendingInvitationsRfbClient::~PendingInvitationsRfbClient() { delete d; } void PendingInvitationsRfbClient::processNewClient() { QString host = peerAddress(m_rfbClient->sock) + ":" + QString::number(peerPort(m_rfbClient->sock)); if (d->askOnConnect == false) { 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)); InvitationsConnectionDialog *dialog = new InvitationsConnectionDialog(nullptr); dialog->setRemoteHost(host); dialog->setAllowRemoteControl(KrfbConfig::allowDesktopControl()); connect(dialog, &InvitationsConnectionDialog::accepted, this, &PendingInvitationsRfbClient::dialogAccepted); connect(dialog, &InvitationsConnectionDialog::rejected, this, &PendingInvitationsRfbClient::reject); dialog->show(); } } void PendingInvitationsRfbClient::onSocketActivated() { //Process not only one, but all pending messages. //poll() idea/code copied from vino: // Copyright (C) 2003 Sun Microsystems, Inc. // License: GPL v2 or later struct pollfd pollfd = { d->client->sock, POLLIN|POLLPRI, 0 }; while(poll(&pollfd, 1, 0) == 1) { if(d->client->state == rfbClientRec::RFB_INITIALISATION) { d->notifier->setEnabled(false); //Client is Authenticated processNewClient(); break; } rfbProcessClientMessage(d->client); //This is how we handle disconnection. //if rfbProcessClientMessage() finds out that it can't read 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) { qDebug() << "disconnected from socket signal"; d->notifier->setEnabled(false); rfbClientConnectionGone(d->client); break; } } } bool PendingInvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword) { QByteArray password ; qDebug() << "about to start autentication"; if(InvitationsRfbServer::instance->allowUnattendedAccess() && vncAuthCheckPassword( InvitationsRfbServer::instance->unattendedPassword().toLocal8Bit(), encryptedPassword) ) { d->askOnConnect = false; return true; } return vncAuthCheckPassword( InvitationsRfbServer::instance->desktopPassword().toLocal8Bit(), encryptedPassword); } void PendingInvitationsRfbClient::dialogAccepted() { InvitationsConnectionDialog *dialog = qobject_cast(sender()); Q_ASSERT(dialog); InvitationsRfbClient *client = new InvitationsRfbClient(m_rfbClient, parent()); client->setControlEnabled(dialog->allowRemoteControl()); accept(client); } diff --git a/krfb/invitationsrfbserver.cpp b/krfb/invitationsrfbserver.cpp index ad895de..a650568 100644 --- a/krfb/invitationsrfbserver.cpp +++ b/krfb/invitationsrfbserver.cpp @@ -1,225 +1,225 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux Copyright (C) 2001-2003 by Tim Jansen 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 . */ #include "invitationsrfbserver.h" #include "invitationsrfbclient.h" #include "krfbconfig.h" #include "rfbservermanager.h" -#include +#include #include -#include +#include #include #include #include #include #include #include #include using KWallet::Wallet; //static InvitationsRfbServer *InvitationsRfbServer::instance; //static void InvitationsRfbServer::init() { instance = new InvitationsRfbServer; instance->m_publicService = new KDNSSD::PublicService( i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()), "_rfb._tcp", KrfbConfig::port()); instance->setListeningAddress("0.0.0.0"); instance->setListeningPort(KrfbConfig::port()); instance->setPasswordRequired(true); if (KrfbConfig::noWallet()) { instance->walletOpened(false); } else { instance->m_wallet = Wallet::openWallet( Wallet::NetworkWallet(), 0, Wallet::Asynchronous); if(instance->m_wallet) { connect(instance->m_wallet, &KWallet::Wallet::walletOpened, instance, &InvitationsRfbServer::walletOpened); } } } const QString& InvitationsRfbServer::desktopPassword() const { return m_desktopPassword; } void InvitationsRfbServer::setDesktopPassword(const QString& password) { m_desktopPassword = password; } const QString& InvitationsRfbServer::unattendedPassword() const { return m_unattendedPassword; } void InvitationsRfbServer::setUnattendedPassword(const QString& password) { m_unattendedPassword = password; } bool InvitationsRfbServer::allowUnattendedAccess() const { return m_allowUnattendedAccess; } bool InvitationsRfbServer::start() { if(RfbServer::start()) { if(KrfbConfig::publishService()) m_publicService->publishAsync(); return true; } return false; } void InvitationsRfbServer::stop() { if(m_publicService->isPublished()) m_publicService->stop(); RfbServer::stop(); } void InvitationsRfbServer::toggleUnattendedAccess(bool allow) { m_allowUnattendedAccess = allow; } InvitationsRfbServer::InvitationsRfbServer() { m_desktopPassword = readableRandomString(4)+"-"+readableRandomString(3); m_unattendedPassword = readableRandomString(4)+"-"+readableRandomString(3); KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security"); m_allowUnattendedAccess = krfbConfig.readEntry( "allowUnattendedAccess", QVariant(false)).toBool(); } InvitationsRfbServer::~InvitationsRfbServer() { stop(); KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security"); krfbConfig.writeEntry("allowUnattendedAccess",m_allowUnattendedAccess); if(!KrfbConfig::noWallet()) { if (m_wallet && m_wallet->isOpen()) { if( (m_wallet->currentFolder()=="krfb") || ((m_wallet->hasFolder("krfb") || m_wallet->createFolder("krfb")) && m_wallet->setFolder("krfb")) ) { m_wallet->writePassword("desktopSharingPassword",m_desktopPassword); m_wallet->writePassword("unattendedAccessPassword",m_unattendedPassword); } } } else { krfbConfig.writeEntry("desktopPassword", KStringHandler::obscure(m_desktopPassword)); krfbConfig.writeEntry("unattendedPassword", KStringHandler::obscure(m_unattendedPassword)); krfbConfig.writeEntry("allowUnattendedAccess", m_allowUnattendedAccess); } } PendingRfbClient* InvitationsRfbServer::newClient(rfbClientPtr client) { return new PendingInvitationsRfbClient(client, this); } void InvitationsRfbServer::walletOpened(bool opened) { QString desktopPassword; QString unattendedPassword; Q_ASSERT(m_wallet); if( opened && ( m_wallet->hasFolder("krfb") || m_wallet->createFolder("krfb") ) && m_wallet->setFolder("krfb") ) { if(m_wallet->readPassword("desktopSharingPassword", desktopPassword)==0 && !desktopPassword.isEmpty()) { m_desktopPassword = desktopPassword; emit passwordChanged(m_desktopPassword); } if(m_wallet->readPassword("unattendedAccessPassword", unattendedPassword)==0 && !unattendedPassword.isEmpty()) { m_unattendedPassword = unattendedPassword; } } else { qDebug() << "Could not open KWallet, Falling back to config file"; KConfigGroup krfbConfig(KSharedConfig::openConfig(),"Security"); desktopPassword = KStringHandler::obscure(krfbConfig.readEntry( "desktopPassword", QString())); if(!desktopPassword.isEmpty()) { m_desktopPassword = desktopPassword; emit passwordChanged(m_desktopPassword); } unattendedPassword = KStringHandler::obscure(krfbConfig.readEntry( "unattendedPassword", QString())); if(!unattendedPassword.isEmpty()) { m_unattendedPassword = unattendedPassword; } } } // a random string that doesn't contain i, I, o, O, 1, l, 0 // based on KRandom::randomString() QString InvitationsRfbServer::readableRandomString(int length) { QString str; while (length) { int r = KRandom::random() % 62; r += 48; if (r > 57) { r += 7; } if (r > 90) { r += 6; } char c = char(r); if ((c == 'i') || (c == 'I') || (c == '1') || (c == 'l') || (c == 'o') || (c == 'O') || (c == '0')) { continue; } str += c; length--; } return str; } diff --git a/krfb/mainwindow.cpp b/krfb/mainwindow.cpp index 4a645d7..9c64fce 100644 --- a/krfb/mainwindow.cpp +++ b/krfb/mainwindow.cpp @@ -1,264 +1,264 @@ /* This file is part of the KDE project Copyright (C) 2007 Alessandro Praduroux Copyright (C) 2013 Amandeep Singh 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. */ #include "mainwindow.h" #include "invitationsrfbserver.h" #include "krfbconfig.h" #include "ui_configtcp.h" #include "ui_configsecurity.h" #include "ui_configframebuffer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include class TCP: public QWidget, public Ui::TCP { public: TCP(QWidget *parent = nullptr) : QWidget(parent) { setupUi(this); } }; class Security: public QWidget, public Ui::Security { public: Security(QWidget *parent = nullptr) : QWidget(parent) { setupUi(this); } }; class ConfigFramebuffer: public QWidget, public Ui::Framebuffer { public: ConfigFramebuffer(QWidget *parent = nullptr) : QWidget(parent) { setupUi(this); // hide the line edit with framebuffer string kcfg_preferredFrameBufferPlugin->hide(); // fill drop-down combo with a list of real existing plugins this->fillFrameBuffersCombo(); // initialize combo with currently configured framebuffer plugin cb_preferredFrameBufferPlugin->setCurrentText(KrfbConfig::preferredFrameBufferPlugin()); // connect signals between combo<->lineedit // if we change selection in combo, lineedit is updated QObject::connect(cb_preferredFrameBufferPlugin, &QComboBox::currentTextChanged, kcfg_preferredFrameBufferPlugin, &QLineEdit::setText); } void fillFrameBuffersCombo() { const QVector plugins = KPluginLoader::findPlugins( QStringLiteral("krfb"), [](const KPluginMetaData & md) { return md.serviceTypes().contains(QStringLiteral("krfb/framebuffer")); }); QSet unique; QVectorIterator i(plugins); i.toBack(); while (i.hasPrevious()) { const KPluginMetaData &metadata = i.previous(); if (unique.contains(metadata.pluginId())) continue; cb_preferredFrameBufferPlugin->addItem(metadata.pluginId()); unique.insert(metadata.pluginId()); } } }; MainWindow::MainWindow(QWidget *parent) : KXmlGuiWindow(parent) { setAttribute(Qt::WA_DeleteOnClose, false); m_passwordEditable = false; m_passwordLineEdit = new KLineEdit(this); m_passwordLineEdit->setVisible(false); m_passwordLineEdit->setAlignment(Qt::AlignHCenter); QWidget *mainWidget = new QWidget; m_ui.setupUi(mainWidget); m_ui.krfbIconLabel->setPixmap(QIcon::fromTheme("krfb").pixmap(128)); m_ui.enableUnattendedCheckBox->setChecked( InvitationsRfbServer::instance->allowUnattendedAccess()); setCentralWidget(mainWidget); connect(m_ui.passwordEditButton, &QToolButton::clicked, this, &MainWindow::editPassword); connect(m_ui.enableSharingCheckBox, &QCheckBox::toggled, this, &MainWindow::toggleDesktopSharing); connect(m_ui.enableUnattendedCheckBox, &QCheckBox::toggled, InvitationsRfbServer::instance, &InvitationsRfbServer::toggleUnattendedAccess); connect(m_ui.unattendedPasswordButton, &QPushButton::clicked, this, &MainWindow::editUnattendedPassword); connect(m_ui.addressAboutButton, &QToolButton::clicked, this, &MainWindow::aboutConnectionAddress); connect(m_ui.unattendedAboutButton, &QToolButton::clicked, this, &MainWindow::aboutUnattendedMode); connect(InvitationsRfbServer::instance, &InvitationsRfbServer::passwordChanged, this, &MainWindow::passwordChanged); // Figure out the address int port = KrfbConfig::port(); QList interfaceList = QNetworkInterface::allInterfaces(); foreach(const QNetworkInterface & interface, interfaceList) { if(interface.flags() & QNetworkInterface::IsLoopBack) continue; if(interface.flags() & QNetworkInterface::IsRunning && !interface.addressEntries().isEmpty()) m_ui.addressDisplayLabel->setText(QString("%1 : %2") .arg(interface.addressEntries().first().ip().toString()) .arg(port)); } //Figure out the password m_ui.passwordDisplayLabel->setText( InvitationsRfbServer::instance->desktopPassword()); KStandardAction::quit(QCoreApplication::instance(), SLOT(quit()), actionCollection()); KStandardAction::preferences(this, SLOT(showConfiguration()), actionCollection()); setupGUI(); if (KrfbConfig::allowDesktopControl()) { m_ui.enableSharingCheckBox->setChecked(true); } setAutoSaveSettings(); } MainWindow::~MainWindow() { } void MainWindow::editPassword() { if(m_passwordEditable) { m_passwordEditable = false; m_ui.passwordEditButton->setIcon(QIcon::fromTheme("document-properties")); m_ui.passwordGridLayout->removeWidget(m_passwordLineEdit); InvitationsRfbServer::instance->setDesktopPassword( m_passwordLineEdit->text()); m_ui.passwordDisplayLabel->setText( InvitationsRfbServer::instance->desktopPassword()); m_passwordLineEdit->setVisible(false); } else { m_passwordEditable = true; m_ui.passwordEditButton->setIcon(QIcon::fromTheme("document-save")); m_ui.passwordGridLayout->addWidget(m_passwordLineEdit,0,0); m_passwordLineEdit->setText( InvitationsRfbServer::instance->desktopPassword()); m_passwordLineEdit->setVisible(true); m_passwordLineEdit->setFocus(Qt::MouseFocusReason); } } void MainWindow::editUnattendedPassword() { KNewPasswordDialog dialog(this); dialog.setPrompt(i18n("Enter a new password for Unattended Access")); if(dialog.exec()) { InvitationsRfbServer::instance->setUnattendedPassword(dialog.password()); } } void MainWindow::toggleDesktopSharing(bool enable) { if(enable) { if(!InvitationsRfbServer::instance->start()) { KMessageBox::error(this, i18n("Failed to start the krfb server. Desktop sharing " "will not work. Try setting another port in the settings " "and restart krfb.")); } } else { InvitationsRfbServer::instance->stop(); if(m_passwordEditable) { m_passwordEditable = false; m_passwordLineEdit->setVisible(false); m_ui.passwordEditButton->setIcon(QIcon::fromTheme("document-properties")); } } } void MainWindow::passwordChanged(const QString& password) { m_passwordLineEdit->setText(password); m_ui.passwordDisplayLabel->setText(password); } void MainWindow::aboutConnectionAddress() { KMessageBox::about(this, i18n("This field contains the address of your computer and the port number, separated by a colon.\n\nThe address is just a hint - you can use any address that can reach your computer.\n\nDesktop Sharing tries to guess your address from your network configuration, but does not always succeed in doing so.\n\nIf your computer is behind a firewall it may have a different address or be unreachable for other computers."), i18n("KDE Desktop Sharing")); } void MainWindow::aboutUnattendedMode() { KMessageBox::about(this, i18n("Any remote user with normal desktop sharing password will have to be authenticated.\n\nIf unattended access is on, and the remote user provides unattended mode password, desktop sharing access will be granted without explicit confirmation."), i18n("KDE Desktop Sharing")); } void MainWindow::showConfiguration() { static QString s_prevFramebufferPlugin; // ^^ needs to be static, because lambda will be called long time // after showConfiguration() ends, so auto variable would go out of scope // save previously selected framebuffer plugin config s_prevFramebufferPlugin = KrfbConfig::preferredFrameBufferPlugin(); if (KConfigDialog::showDialog("settings")) { return; } KConfigDialog *dialog = new KConfigDialog(this, "settings", KrfbConfig::self()); dialog->addPage(new TCP, i18n("Network"), "network-wired"); dialog->addPage(new Security, i18n("Security"), "security-high"); dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), "video-display"); dialog->show(); connect(dialog, &KConfigDialog::settingsChanged, [this] () { // check if framebuffer plugin config has changed if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) { KMessageBox::information(this, i18n("To apply framebuffer plugin setting, " "you need to restart the program.")); } }); } void MainWindow::readProperties(const KConfigGroup& group) { if (group.readEntry("Visible", true)) { show(); } KMainWindow::readProperties(group); } void MainWindow::saveProperties(KConfigGroup& group) { group.writeEntry("Visible", isVisible()); KMainWindow::saveProperties(group); } diff --git a/krfb/rfbclient.cpp b/krfb/rfbclient.cpp index 8ac25c9..3da8c36 100644 --- a/krfb/rfbclient.cpp +++ b/krfb/rfbclient.cpp @@ -1,230 +1,230 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux 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 . */ #include "rfbclient.h" #include "connectiondialog.h" #include "krfbconfig.h" #include "sockethelpers.h" #include "events.h" -#include +#include #include #include #include //for bzero() struct RfbClient::Private { Private(rfbClientPtr client) : controlEnabled(KrfbConfig::allowDesktopControl()), client(client) {} bool controlEnabled; rfbClientPtr client; QSocketNotifier *notifier; QString remoteAddressString; }; RfbClient::RfbClient(rfbClientPtr client, QObject* parent) : QObject(parent), d(new Private(client)) { d->remoteAddressString = peerAddress(d->client->sock) + ":" + QString::number(peerPort(d->client->sock)); d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this); d->notifier->setEnabled(false); connect(d->notifier, &QSocketNotifier::activated, this, &RfbClient::onSocketActivated); } RfbClient::~RfbClient() { //qDebug(); delete d; } QString RfbClient::name() const { return d->remoteAddressString; } //static bool RfbClient::controlCanBeEnabled() { return KrfbConfig::allowDesktopControl(); } bool RfbClient::controlEnabled() const { return d->controlEnabled; } void RfbClient::setControlEnabled(bool enabled) { if (controlCanBeEnabled() && d->controlEnabled != enabled) { d->controlEnabled = enabled; Q_EMIT controlEnabledChanged(enabled); } } bool RfbClient::isOnHold() const { return d->client->onHold ? true : false; } void RfbClient::setOnHold(bool onHold) { if (isOnHold() != onHold) { d->client->onHold = onHold; d->notifier->setEnabled(!onHold); Q_EMIT holdStatusChanged(onHold); } } void RfbClient::closeConnection() { d->notifier->setEnabled(false); rfbCloseClient(d->client); rfbClientConnectionGone(d->client); } rfbClientPtr RfbClient::getRfbClientPtr() { return d->client; } void RfbClient::handleKeyboardEvent(bool down, rfbKeySym keySym) { if (d->controlEnabled) { EventHandler::handleKeyboard(down, keySym); } } void RfbClient::handleMouseEvent(int buttonMask, int x, int y) { if (d->controlEnabled) { EventHandler::handlePointer(buttonMask, x, y); } } void RfbClient::onSocketActivated() { //Process not only one, but all pending messages. //poll() idea/code copied from vino: // Copyright (C) 2003 Sun Microsystems, Inc. // License: GPL v2 or later struct pollfd pollfd = { d->client->sock, POLLIN|POLLPRI, 0 }; while(poll(&pollfd, 1, 0) == 1) { rfbProcessClientMessage(d->client); //This is how we handle disconnection. //if rfbProcessClientMessage() finds out that it can't read 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) { //qDebug() << "disconnected from socket signal"; d->notifier->setEnabled(false); rfbClientConnectionGone(d->client); break; } } } void RfbClient::update() { 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) { //qDebug() << "disconnected during update"; d->notifier->setEnabled(false); rfbClientConnectionGone(d->client); } } //************* PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent) : QObject(parent), m_rfbClient(client) { m_rfbClient->clientData = this; } PendingRfbClient::~PendingRfbClient() {} void PendingRfbClient::accept(RfbClient *newClient) { //qDebug() << "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() { //qDebug() << "refused connection"; //override the clientGoneHook that was previously set by RfbServer m_rfbClient->clientGoneHook = clientGoneHookNoop; rfbCloseClient(m_rfbClient); rfbClientConnectionGone(m_rfbClient); Q_EMIT finished(nullptr); deleteLater(); } bool PendingRfbClient::checkPassword(const QByteArray & encryptedPassword) { Q_UNUSED(encryptedPassword); return m_rfbClient->screen->authPasswdData == (void*)nullptr; } bool PendingRfbClient::vncAuthCheckPassword(const QByteArray& password, const QByteArray& encryptedPassword) const { if (password.isEmpty() && encryptedPassword.isEmpty()) { return true; } char passwd[MAXPWLEN]; unsigned char challenge[CHALLENGESIZE]; memcpy(challenge, m_rfbClient->authChallenge, CHALLENGESIZE); bzero(passwd, MAXPWLEN); if (!password.isEmpty()) { strncpy(passwd, password, (MAXPWLEN <= password.size()) ? MAXPWLEN : password.size()); } rfbEncryptBytes(challenge, passwd); return memcmp(challenge, encryptedPassword, encryptedPassword.size()) == 0; } diff --git a/krfb/rfbclient.h b/krfb/rfbclient.h index a9c9591..5fbe048 100644 --- a/krfb/rfbclient.h +++ b/krfb/rfbclient.h @@ -1,109 +1,109 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux 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 . */ #ifndef RFBCLIENT_H #define RFBCLIENT_H #include "rfb.h" -#include +#include 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: explicit RfbClient(rfbClientPtr client, QObject *parent = nullptr); ~RfbClient() override; /** Returns a name for the client, to be shown to the user */ virtual QString name() const; static bool controlCanBeEnabled(); bool controlEnabled() const; bool isOnHold() const; public Q_SLOTS: void setControlEnabled(bool enabled); void setOnHold(bool onHold); void closeConnection(); Q_SIGNALS: void controlEnabledChanged(bool enabled); void holdStatusChanged(bool onHold); protected: friend class RfbServer; //the following event handling methods are called by RfbServer rfbClientPtr getRfbClientPtr(); virtual void handleKeyboardEvent(bool down, rfbKeySym keySym); virtual void handleMouseEvent(int buttonMask, int x, int y); private Q_SLOTS: void onSocketActivated(); private: ///called by RfbServerManager to send framebuffer updates ///and check for possible disconnection void update(); friend class RfbServerManager; struct Private; Private *const d; }; class PendingRfbClient : public QObject { Q_OBJECT public: explicit PendingRfbClient(rfbClientPtr client, QObject *parent = nullptr); ~PendingRfbClient() override; Q_SIGNALS: void finished(RfbClient *client); protected Q_SLOTS: virtual void processNewClient() = 0; void accept(RfbClient *newClient); void reject(); protected: friend class RfbServer; //Following two methods are handled by RfbServer /** This method is supposed to check if the provided \a encryptedPassword * matches the criteria for authenticating the client. * The default implementation returns false if a password is required. * Reimplement to do more useful stuff. */ virtual bool checkPassword(const QByteArray & encryptedPassword); /** This method checks if the \a encryptedPassword that was sent from the remote * user matches the \a password that you have specified localy to be the password * for this connection. This assumes that the standard VNC authentication mechanism * is used. Returns true if the password matches or false otherwise. */ bool vncAuthCheckPassword(const QByteArray & password, const QByteArray & encryptedPassword) const; rfbClientPtr m_rfbClient; }; #endif // RFBCLIENT_H diff --git a/krfb/rfbserver.cpp b/krfb/rfbserver.cpp index 0d3c0fc..d9a813a 100644 --- a/krfb/rfbserver.cpp +++ b/krfb/rfbserver.cpp @@ -1,286 +1,286 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux 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 . */ #include "rfbserver.h" #include "rfbservermanager.h" -#include +#include #include #include #include #include struct RfbServer::Private { QByteArray listeningAddress; int listeningPort; bool passwordRequired; rfbScreenInfoPtr screen; QPointer ipv4notifier; QPointer ipv6notifier; }; RfbServer::RfbServer(QObject *parent) : QObject(parent), d(new Private) { d->listeningAddress = "0.0.0.0"; d->listeningPort = 0; d->passwordRequired = true; d->screen = nullptr; RfbServerManager::instance()->registerServer(this); } RfbServer::~RfbServer() { if (d->screen) { rfbScreenCleanup(d->screen); } delete d; RfbServerManager::instance()->unregisterServer(this); } QByteArray RfbServer::listeningAddress() const { return d->listeningAddress; } int RfbServer::listeningPort() const { return d->listeningPort; } bool RfbServer::passwordRequired() const { return d->passwordRequired; } void RfbServer::setListeningAddress(const QByteArray& address) { d->listeningAddress = address; } void RfbServer::setListeningPort(int port) { d->listeningPort = port; } void RfbServer::setPasswordRequired(bool passwordRequired) { d->passwordRequired = passwordRequired; } bool RfbServer::start() { if (!d->screen) { d->screen = RfbServerManager::instance()->newScreen(); if (!d->screen) { qDebug() << "Unable to get rbfserver screen"; return false; } // server hooks d->screen->screenData = this; d->screen->newClientHook = newClientHook; d->screen->kbdAddEvent = keyboardHook; d->screen->ptrAddEvent = pointerHook; d->screen->passwordCheck = passwordCheck; d->screen->setXCutText = clipboardHook; } else { //if we already have a screen, stop listening first rfbShutdownServer(d->screen, false); } if (listeningAddress() != "0.0.0.0") { strncpy(d->screen->thisHost, listeningAddress().data(), 254); } if (listeningPort() == 0) { d->screen->autoPort = 1; } d->screen->port = listeningPort(); // Disable/Enable password checking if (passwordRequired()) { d->screen->authPasswdData = (void *)1; } else { d->screen->authPasswdData = (void *)nullptr; } qDebug() << "Starting server. Listen port:" << listeningPort() << "Listen Address:" << listeningAddress() << "Password enabled:" << passwordRequired(); rfbInitServer(d->screen); if (!rfbIsActive(d->screen)) { qDebug() << "Failed to start server"; rfbShutdownServer(d->screen, false); return false; }; d->ipv4notifier = new QSocketNotifier(d->screen->listenSock, QSocketNotifier::Read, this); connect(d->ipv4notifier, &QSocketNotifier::activated, this, &RfbServer::onListenSocketActivated); if (d->screen->listen6Sock > 0) { // we're also listening on additional IPv6 socket, get events from there d->ipv6notifier = new QSocketNotifier(d->screen->listen6Sock, QSocketNotifier::Read, this); connect(d->ipv6notifier, &QSocketNotifier::activated, this, &RfbServer::onListenSocketActivated); } connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &RfbServer::krfbSendServerCutText); return true; } void RfbServer::stop() { if (d->screen) { rfbShutdownServer(d->screen, true); for (auto notifier : {d->ipv4notifier, d->ipv6notifier}) { if (notifier) { notifier->setEnabled(false); notifier->deleteLater(); } } } } void RfbServer::updateScreen(const QList & modifiedTiles) { if (d->screen) { QList::const_iterator it = modifiedTiles.constBegin(); for(; it != modifiedTiles.constEnd(); ++it) { rfbMarkRectAsModified(d->screen, it->x(), it->y(), it->right(), it->bottom()); } } } /* * Code copied from vino's bundled libvncserver: * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. * License: GPL v2 or later */ void krfb_rfbSetCursorPosition(rfbScreenInfoPtr screen, rfbClientPtr client, int x, int y) { rfbClientIteratorPtr iterator; rfbClientPtr cl; if (x == screen->cursorX || y == screen->cursorY) return; LOCK(screen->cursorMutex); screen->cursorX = x; screen->cursorY = y; UNLOCK(screen->cursorMutex); /* Inform all clients about this cursor movement. */ iterator = rfbGetClientIterator(screen); while ((cl = rfbClientIteratorNext(iterator)) != nullptr) { cl->cursorWasMoved = true; } rfbReleaseClientIterator(iterator); /* The cursor was moved by this client, so don't send CursorPos. */ if (client) { client->cursorWasMoved = false; } } void RfbServer::updateCursorPosition(const QPoint & position) { if (d->screen) { krfb_rfbSetCursorPosition(d->screen, nullptr, position.x(), position.y()); } } void RfbServer::krfbSendServerCutText() { if(d->screen) { QString text = QApplication::clipboard()->text(); rfbSendServerCutText(d->screen, text.toLocal8Bit().data(),text.length()); } } void RfbServer::onListenSocketActivated() { rfbProcessNewConnection(d->screen); } void RfbServer::pendingClientFinished(RfbClient *client) { //qDebug(); if (client) { RfbServerManager::instance()->addClient(client); client->getRfbClientPtr()->clientGoneHook = clientGoneHook; } } //static rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl) { //qDebug() << "New client"; RfbServer *server = static_cast(cl->screen->screenData); PendingRfbClient *pendingClient = server->newClient(cl); connect(pendingClient, &PendingRfbClient::finished, server, &RfbServer::pendingClientFinished); return RFB_CLIENT_ON_HOLD; } //static void RfbServer::clientGoneHook(rfbClientPtr cl) { //qDebug() << "client gone"; RfbClient *client = static_cast(cl->clientData); RfbServerManager::instance()->removeClient(client); client->deleteLater(); } //static rfbBool RfbServer::passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len) { PendingRfbClient *client = static_cast(cl->clientData); Q_ASSERT(client); return client->checkPassword(QByteArray::fromRawData(encryptedPassword, len)); } //static void RfbServer::keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl) { RfbClient *client = static_cast(cl->clientData); client->handleKeyboardEvent(down ? true : false, keySym); } //static void RfbServer::pointerHook(int bm, int x, int y, rfbClientPtr cl) { RfbClient *client = static_cast(cl->clientData); client->handleMouseEvent(bm, x, y); } //static void RfbServer::clipboardHook(char *str, int len, rfbClientPtr /*cl*/) { QApplication::clipboard()->setText(QString::fromLocal8Bit(str,len)); } diff --git a/krfb/rfbserver.h b/krfb/rfbserver.h index b0483d4..51b106d 100644 --- a/krfb/rfbserver.h +++ b/krfb/rfbserver.h @@ -1,72 +1,72 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux 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 . */ #ifndef RFBSERVER_H #define RFBSERVER_H #include "rfb.h" #include "rfbclient.h" -#include +#include class RfbServer : public QObject { Q_OBJECT public: explicit RfbServer(QObject *parent = nullptr); ~RfbServer() override; QByteArray listeningAddress() const; int listeningPort() const; bool passwordRequired() const; void setListeningAddress(const QByteArray & address); void setListeningPort(int port); void setPasswordRequired(bool passwordRequired); public Q_SLOTS: virtual bool start(); virtual void stop(); void updateScreen(const QList & modifiedTiles); void updateCursorPosition(const QPoint & position); private Q_SLOTS: void krfbSendServerCutText(); void onListenSocketActivated(); void pendingClientFinished(RfbClient *client); protected: virtual PendingRfbClient *newClient(rfbClientPtr client) = 0; private: static rfbNewClientAction newClientHook(rfbClientPtr cl); static void clientGoneHook(rfbClientPtr cl); static rfbBool passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len); static void keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl); static void pointerHook(int bm, int x, int y, rfbClientPtr cl); static void clipboardHook(char *str, int len, rfbClientPtr cl); Q_DISABLE_COPY(RfbServer) struct Private; Private *const d; }; #endif // RFBSERVER_H diff --git a/krfb/rfbservermanager.cpp b/krfb/rfbservermanager.cpp index 46c7e7b..5f5fa6c 100644 --- a/krfb/rfbservermanager.cpp +++ b/krfb/rfbservermanager.cpp @@ -1,234 +1,234 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux Copyright (C) 2001-2003 by Tim Jansen 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 . */ #include "rfbservermanager.h" #include "rfbserver.h" #include "framebuffer.h" #include "framebuffermanager.h" #include "sockethelpers.h" #include "krfbconfig.h" -#include +#include #include #include #include -#include +#include #include #include #include #include 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 "; struct RfbServerManagerStatic { RfbServerManager server; }; Q_GLOBAL_STATIC(RfbServerManagerStatic, s_instance) RfbServerManager* RfbServerManager::instance() { return &s_instance->server; } struct RfbServerManager::Private { QSharedPointer fb; rfbCursorPtr myCursor; QByteArray desktopName; QTimer rfbUpdateTimer; QSet servers; QSet clients; }; RfbServerManager::RfbServerManager() : QObject(), d(new Private) { init(); } RfbServerManager::~RfbServerManager() { delete d; } void RfbServerManager::init() { //qDebug(); d->fb = FrameBufferManager::instance()->frameBuffer(QApplication::desktop()->winId()); d->myCursor = rfbMakeXCursor(19, 19, (char *) cur, (char *) mask); d->myCursor->cleanup = false; d->desktopName = QString("%1@%2 (shared desktop)") //FIXME check if we can use utf8 .arg(KUser().loginName(),QHostInfo::localHostName()).toLatin1(); connect(&d->rfbUpdateTimer, &QTimer::timeout, this, &RfbServerManager::updateScreens); connect(qApp, &QApplication::aboutToQuit, this, &RfbServerManager::cleanup); } void RfbServerManager::updateScreens() { QList rects = d->fb->modifiedTiles(); QPoint currentCursorPos = QCursor::pos(); Q_FOREACH(RfbServer *server, d->servers) { server->updateScreen(rects); server->updateCursorPosition(currentCursorPos); } //update() might disconnect some of the clients, which will synchronously //call the removeClient() method and will change d->clients, so we need //to copy the set here to avoid problems. QSet clients = d->clients; Q_FOREACH(RfbClient *client, clients) { client->update(); } } void RfbServerManager::cleanup() { //qDebug(); //copy because d->servers is going to be modified while we delete the servers QSet servers = d->servers; Q_FOREACH(RfbServer *server, servers) { delete server; } Q_ASSERT(d->servers.isEmpty()); Q_ASSERT(d->clients.isEmpty()); d->myCursor->cleanup = true; rfbFreeCursor(d->myCursor); d->fb.clear(); } void RfbServerManager::registerServer(RfbServer* server) { d->servers.insert(server); } void RfbServerManager::unregisterServer(RfbServer* server) { d->servers.remove(server); } rfbScreenInfoPtr RfbServerManager::newScreen() { rfbScreenInfoPtr screen = nullptr; if (!d->fb.isNull()) { 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; } //qDebug() << "bpp: " << bpp; rfbLogEnable(0); screen = rfbGetScreen(nullptr, nullptr, w, h, 8, 3, bpp); screen->paddedWidthInBytes = d->fb->paddedWidth(); d->fb->getServerFormat(screen->serverFormat); screen->frameBuffer = d->fb->data(); screen->desktopName = d->desktopName.constData(); screen->cursor = d->myCursor; } return screen; } void RfbServerManager::addClient(RfbClient* cc) { if (d->clients.size() == 0) { //qDebug() << "Starting framebuffer monitor"; d->fb->startMonitor(); d->rfbUpdateTimer.start(50); } d->clients.insert(cc); KNotification::event("UserAcceptsConnection", i18n("The remote user %1 is now connected.", cc->name())); Q_EMIT clientConnected(cc); } void RfbServerManager::removeClient(RfbClient* cc) { d->clients.remove(cc); if (d->clients.size() == 0) { //qDebug() << "Stopping framebuffer monitor"; d->fb->stopMonitor(); d->rfbUpdateTimer.stop(); } KNotification::event("ConnectionClosed", i18n("The remote user %1 disconnected.", cc->name())); Q_EMIT clientDisconnected(cc); } diff --git a/krfb/rfbservermanager.h b/krfb/rfbservermanager.h index 263efff..a4af409 100644 --- a/krfb/rfbservermanager.h +++ b/krfb/rfbservermanager.h @@ -1,65 +1,65 @@ /* Copyright (C) 2009-2010 Collabora Ltd @author George Goldberg @author George Kiagiadakis Copyright (C) 2007 Alessandro Praduroux 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 . */ #ifndef RFBSERVERMANAGER_H #define RFBSERVERMANAGER_H #include "rfb.h" -#include +#include class RfbClient; struct RfbServerManagerStatic; class RfbServer; class RfbServerManager : public QObject { Q_OBJECT public: static RfbServerManager *instance(); Q_SIGNALS: void clientConnected(RfbClient *cc); void clientDisconnected(RfbClient *cc); private Q_SLOTS: void init(); void updateScreens(); void cleanup(); private: void registerServer(RfbServer *server); void unregisterServer(RfbServer *server); rfbScreenInfoPtr newScreen(); void addClient(RfbClient *cc); void removeClient(RfbClient *cc); RfbServerManager(); ~RfbServerManager() override; Q_DISABLE_COPY(RfbServerManager) friend class RfbServer; friend struct RfbServerManagerStatic; struct Private; Private *const d; }; #endif // RFBSERVERMANAGER_H diff --git a/krfb/sockethelpers.h b/krfb/sockethelpers.h index dae2dcc..6635f48 100644 --- a/krfb/sockethelpers.h +++ b/krfb/sockethelpers.h @@ -1,30 +1,30 @@ /* This file is part of the KDE project Copyright (C) 2009 Collabora Ltd @author George Goldberg Copyright (C) 2007 Alessandro Praduroux Copyright (C) 2001-2003 by Tim Jansen 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 +#include QString peerAddress(int sock); unsigned short peerPort(int sock); QString localAddress(int sock); unsigned short localPort(int sock);