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"