File indexing completed on 2024-03-24 05:01:40
0001 /* This file is part of the KDE project 0002 Copyright (C) 2021 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public 0006 License as published by the Free Software Foundation; either 0007 version 3 of the License, or (at your option) any later version. 0008 */ 0009 0010 #include <QApplication> 0011 #include <QCommandLineParser> 0012 #include <QCommandLineOption> 0013 #include <QDebug> 0014 #include <QTimer> 0015 #include <KNotification> 0016 #include <KLocalizedString> 0017 #include <KWindowSystem> 0018 #include <KAboutData> 0019 #include "sockethelpers.h" 0020 #include "krfb_version.h" 0021 #include "rfbserver.h" 0022 #include <signal.h> 0023 #include "rfbservermanager.h" 0024 0025 class VirtualMonitorRfbClient : public RfbClient 0026 { 0027 public: 0028 explicit VirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr) 0029 : RfbClient(client, parent) 0030 {} 0031 }; 0032 0033 class PendingVirtualMonitorRfbClient : public PendingRfbClient 0034 { 0035 public: 0036 explicit PendingVirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr) 0037 : PendingRfbClient(client, parent) 0038 {} 0039 ~PendingVirtualMonitorRfbClient() override {} 0040 0041 static QByteArray password; 0042 0043 protected: 0044 void processNewClient() override { 0045 qDebug() << "new client!"; 0046 const QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock)); 0047 0048 KNotification::event(QStringLiteral("NewConnectionAutoAccepted"), 0049 i18n("Creating a Virtual Monitor from %1", host)); 0050 } 0051 bool checkPassword(const QByteArray & encryptedPassword) override { 0052 bool b = vncAuthCheckPassword(password, encryptedPassword); 0053 if (b) { 0054 QTimer::singleShot(0, this, [this] { 0055 accept(new VirtualMonitorRfbClient(m_rfbClient, parent())); 0056 }); 0057 } 0058 return b; 0059 } 0060 }; 0061 0062 QByteArray PendingVirtualMonitorRfbClient::password; 0063 0064 class VirtualMonitorRfbServer : public RfbServer 0065 { 0066 public: 0067 PendingRfbClient *newClient(rfbClientPtr client) override { 0068 qDebug() << "new client request"; 0069 return new PendingVirtualMonitorRfbClient(client, this); 0070 } 0071 }; 0072 0073 int main(int argc, char *argv[]) 0074 { 0075 QApplication app(argc, argv); 0076 0077 KLocalizedString::setApplicationDomain("krfb"); 0078 0079 KAboutData aboutData(QStringLiteral("krfb-virtualmonitor"), 0080 i18n("Remote Virtual Monitor"), 0081 QStringLiteral(KRFB_VERSION_STRING), 0082 i18n("Offer a Virtual Monitor that can be accessed remotely"), 0083 KAboutLicense::GPL, 0084 i18n("(c) 2009-2010, Collabora Ltd.\n" 0085 "(c) 2007, Alessandro Praduroux\n" 0086 "(c) 2001-2003, Tim Jansen\n" 0087 "(c) 2001, Johannes E. Schindelin\n" 0088 "(c) 2000-2001, Const Kaplinsky\n" 0089 "(c) 2000, Tridia Corporation\n" 0090 "(c) 1999, AT&T Laboratories Boston\n")); 0091 aboutData.addAuthor(QStringLiteral("Aleix Pol i Gonzalez"), i18n("Virtual Monitor implementation"), QStringLiteral("aleixpol@kde.org")); 0092 aboutData.addAuthor(i18n("George Kiagiadakis"), QString(), QStringLiteral("george.kiagiadakis@collabora.co.uk")); 0093 aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), QStringLiteral("pradu@pradu.it")); 0094 aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), QStringLiteral("tim@tjansen.de")); 0095 aboutData.addCredit(i18n("Johannes E. Schindelin"), 0096 i18n("libvncserver")); 0097 aboutData.addCredit(i18n("Const Kaplinsky"), 0098 i18n("TightVNC encoder")); 0099 aboutData.addCredit(i18n("Tridia Corporation"), 0100 i18n("ZLib encoder")); 0101 aboutData.addCredit(i18n("AT&T Laboratories Boston"), 0102 i18n("original VNC encoders and " 0103 "protocol design")); 0104 KAboutData::setApplicationData(aboutData); 0105 0106 QCommandLineParser parser; 0107 aboutData.setupCommandLine(&parser); 0108 const QCommandLineOption resolutionOption({ QStringLiteral("resolution") }, i18n("Logical resolution of the new monitor"), i18n("resolution")); 0109 parser.addOption(resolutionOption); 0110 const QCommandLineOption nameOption({ QStringLiteral("name") }, i18n("Name of the monitor"), i18n("name")); 0111 parser.addOption(nameOption); 0112 const QCommandLineOption passwordOption({ QStringLiteral("password") }, i18n("Password for the client to connect to it"), i18n("password")); 0113 parser.addOption(passwordOption); 0114 const QCommandLineOption scaleOption({ QStringLiteral("scale") }, i18n("The device-pixel-ratio of the device, the scaling factor"), i18n("dpr"), QStringLiteral("1")); 0115 parser.addOption(scaleOption); 0116 const QCommandLineOption portOption({ QStringLiteral("port") }, i18n("The port we will be listening to"), i18n("number"), QStringLiteral("9999")); 0117 parser.addOption(portOption); 0118 0119 parser.process(app); 0120 aboutData.processCommandLine(&parser); 0121 0122 app.setQuitOnLastWindowClosed(false); 0123 0124 if (!KWindowSystem::isPlatformWayland()) { 0125 qCritical() << "Virtual Monitors are only supported on Wayland"; 0126 return 1; 0127 } 0128 if (!parser.isSet(nameOption)) { 0129 qCritical() << "error: please define --name"; 0130 return 2; 0131 } else { 0132 if (!parser.isSet(passwordOption)) { 0133 qCritical() << "error: please define --password"; 0134 return 3; 0135 } 0136 if (!parser.isSet(resolutionOption)) { 0137 qCritical() << "error: please define --resolution"; 0138 return 4; 0139 } 0140 } 0141 if (!parser.isSet(portOption)) { 0142 qCritical() << "error: please define --port"; 0143 return 5; 0144 } 0145 const QString res = parser.value(resolutionOption); 0146 const auto resSplit = res.split(QLatin1Char('x')); 0147 if (resSplit.size() != 2) { 0148 qCritical() << "error: the resolution should be formatted as WIDTHxHEIGHT (e.g. --resolution 1920x1080)"; 0149 return 6; 0150 } 0151 0152 0153 if (parser.isSet(nameOption)) { 0154 RfbServerManager::s_pluginArgs = { 0155 { QStringLiteral("name"), parser.value(nameOption) }, 0156 { QStringLiteral("resolution"), QSize(resSplit[0].toInt(), resSplit[1].toInt()) }, 0157 { QStringLiteral("scale"), parser.value(scaleOption).toDouble() }, 0158 }; 0159 } 0160 0161 VirtualMonitorRfbServer server; 0162 server.setPasswordRequired(true); 0163 server.setListeningPort(parser.value(portOption).toInt()); 0164 PendingVirtualMonitorRfbClient::password = parser.value(passwordOption).toUtf8(); 0165 0166 sigset_t sigs; 0167 sigemptyset(&sigs); 0168 sigaddset(&sigs, SIGPIPE); 0169 sigprocmask(SIG_BLOCK, &sigs, nullptr); 0170 if (!server.start()) { 0171 return 1; 0172 } 0173 0174 return app.exec(); 0175 }