File indexing completed on 2024-06-23 05:24:07

0001 // SPDX-FileCopyrightText: 2023 Arjen Hiemstra <ahiemstra@heimr.nl>
0002 //
0003 // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0004 
0005 #include "Server.h"
0006 
0007 #include <vector>
0008 
0009 #include <QCoreApplication>
0010 
0011 #include <freerdp/channels/channels.h>
0012 #include <freerdp/freerdp.h>
0013 #include <winpr/ssl.h>
0014 
0015 #include "RdpConnection.h"
0016 
0017 #include "krdp_logging.h"
0018 
0019 using namespace KRdp;
0020 
0021 class KRDP_NO_EXPORT Server::Private
0022 {
0023 public:
0024     std::vector<std::unique_ptr<RdpConnection>> sessions;
0025     rdp_settings *settings = nullptr;
0026 
0027     QHostAddress address = QHostAddress::LocalHost;
0028     quint16 port = 3389;
0029 
0030     QString userName;
0031     QString password;
0032 
0033     std::filesystem::path tlsCertificate;
0034     std::filesystem::path tlsCertificateKey;
0035 };
0036 
0037 Server::Server(QObject *parent)
0038     : QTcpServer(parent)
0039     , d(std::make_unique<Private>())
0040 {
0041     winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
0042     WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
0043 }
0044 
0045 Server::~Server()
0046 {
0047     stop();
0048 }
0049 
0050 bool Server::start()
0051 {
0052     if (!std::filesystem::exists(d->tlsCertificate) || !std::filesystem::exists(d->tlsCertificateKey)) {
0053         qCCritical(KRDP).nospace() << "A valid TLS certificate (" << QString::fromStdString(d->tlsCertificate.filename().string()) << ") and key ("
0054                                    << QString::fromStdString(d->tlsCertificateKey.filename().string()) << ") is required for the server to run!";
0055         return false;
0056     }
0057 
0058     if (!listen(d->address, d->port)) {
0059         qCCritical(KRDP) << "Unable to listen for connections on" << serverAddress() << serverPort();
0060         return false;
0061     }
0062 
0063 #ifdef FREERDP3
0064     // FreeRDP3 tries to use a global instance of the settings object when
0065     // initializing a new peer. However, it seems to fail at actually creating a
0066     // global default instance. So create one here and use that.
0067     d->settings = freerdp_settings_new(FREERDP_SETTINGS_SERVER_MODE);
0068 #endif
0069 
0070     qCDebug(KRDP) << "Listening for connections on" << serverAddress() << serverPort();
0071     return true;
0072 }
0073 
0074 void Server::stop()
0075 {
0076     close();
0077 
0078     if (d->settings) {
0079         freerdp_settings_free(d->settings);
0080         d->settings = nullptr;
0081     }
0082 }
0083 
0084 QHostAddress Server::address() const
0085 {
0086     return d->address;
0087 }
0088 
0089 void Server::setAddress(const QHostAddress &newAddress)
0090 {
0091     if (newAddress == d->address) {
0092         return;
0093     }
0094 
0095     d->address = newAddress;
0096 }
0097 
0098 quint16 Server::port() const
0099 {
0100     return d->port;
0101 }
0102 
0103 void Server::setPort(quint16 newPort)
0104 {
0105     if (newPort == d->port) {
0106         return;
0107     }
0108 
0109     d->port = newPort;
0110 }
0111 
0112 QString Server::userName() const
0113 {
0114     return d->userName;
0115 }
0116 
0117 void Server::setUserName(const QString &newUserName)
0118 {
0119     if (newUserName == d->userName) {
0120         return;
0121     }
0122 
0123     d->userName = newUserName;
0124 }
0125 
0126 QString Server::password() const
0127 {
0128     return d->password;
0129 }
0130 
0131 void Server::setPassword(const QString &newPassword)
0132 {
0133     if (newPassword == d->password) {
0134         return;
0135     }
0136 
0137     d->password = newPassword;
0138 }
0139 
0140 std::filesystem::path Server::tlsCertificate() const
0141 {
0142     return d->tlsCertificate;
0143 }
0144 
0145 void Server::setTlsCertificate(const std::filesystem::path &newTlsCertificate)
0146 {
0147     if (newTlsCertificate == d->tlsCertificate) {
0148         return;
0149     }
0150 
0151     d->tlsCertificate = newTlsCertificate;
0152 }
0153 
0154 std::filesystem::path Server::tlsCertificateKey() const
0155 {
0156     return d->tlsCertificateKey;
0157 }
0158 
0159 void Server::setTlsCertificateKey(const std::filesystem::path &newTlsCertificateKey)
0160 {
0161     if (newTlsCertificateKey == d->tlsCertificateKey) {
0162         return;
0163     }
0164 
0165     d->tlsCertificateKey = newTlsCertificateKey;
0166 }
0167 
0168 void Server::incomingConnection(qintptr handle)
0169 {
0170     auto session = std::make_unique<RdpConnection>(this, handle);
0171     auto sessionPtr = session.get();
0172     connect(session.get(), &RdpConnection::stateChanged, this, [this, sessionPtr]() {
0173         if (sessionPtr->state() == RdpConnection::State::Closed) {
0174             auto itr = std::find_if(d->sessions.begin(), d->sessions.end(), [sessionPtr](auto &session) {
0175                 return session.get() == sessionPtr;
0176             });
0177             d->sessions.erase(itr);
0178         }
0179     });
0180     d->sessions.push_back(std::move(session));
0181     Q_EMIT newConnection(sessionPtr);
0182 }
0183 
0184 rdp_settings *Server::rdpSettings() const
0185 {
0186     return d->settings;
0187 }
0188 
0189 #include "moc_Server.cpp"