1 /* 2 * Kaidan - A user-friendly XMPP client for every device! 3 * 4 * Copyright (C) 2016-2021 Kaidan developers and contributors 5 * (see the LICENSE file for a full list of copyright authors) 6 * 7 * Kaidan is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * In addition, as a special exception, the author of Kaidan gives 13 * permission to link the code of its release with the OpenSSL 14 * project's "OpenSSL" library (or with modified versions of it that 15 * use the same license as the "OpenSSL" library), and distribute the 16 * linked executables. You must obey the GNU General Public License in 17 * all respects for all of the code used other than "OpenSSL". If you 18 * modify this file, you may extend this exception to your version of 19 * the file, but you are not obligated to do so. If you do not wish to 20 * do so, delete this exception statement from your version. 21 * 22 * Kaidan is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with Kaidan. If not, see <http://www.gnu.org/licenses/>. 29 */ 30 31 #pragma once 32 33 // Qt 34 // QXmpp 35 #include <QXmppClient.h> 36 // Kaidan 37 #include "Enums.h" 38 39 class AccountManager; 40 class AvatarFileStorage; 41 class DiscoveryManager; 42 class DownloadManager; 43 class LogHandler; 44 class MessageHandler; 45 class MessageModel; 46 class PresenceCache; 47 class RegistrationManager; 48 class RosterManager; 49 class RosterModel; 50 class ServerFeaturesCache; 51 class TransferCache; 52 class UploadManager; 53 class VCardCache; 54 class VCardManager; 55 class VersionManager; 56 class QSettings; 57 58 /** 59 * The ClientWorker is used as a QObject-based worker on the ClientThread. 60 */ 61 class ClientWorker : public QObject 62 { 63 Q_OBJECT 64 65 Q_PROPERTY(RegistrationManager* registrationManager READ registrationManager CONSTANT) 66 Q_PROPERTY(VCardManager* vCardManager READ vCardManager CONSTANT) 67 Q_PROPERTY(RosterManager* rosterManager READ rosterManager CONSTANT) 68 Q_PROPERTY(MessageHandler* messageHandler READ messageHandler CONSTANT) 69 Q_PROPERTY(DiscoveryManager* discoveryManager READ discoveryManager CONSTANT) 70 Q_PROPERTY(UploadManager* uploadManager READ uploadManager CONSTANT) 71 Q_PROPERTY(DownloadManager* downloadManager READ downloadManager CONSTANT) 72 Q_PROPERTY(VersionManager* versionManager READ versionManager CONSTANT) 73 74 public: 75 /** 76 * enumeration of possible connection errors 77 */ 78 enum ConnectionError { 79 NoError, 80 AuthenticationFailed, 81 NotConnected, 82 TlsFailed, 83 TlsNotAvailable, 84 DnsError, 85 ConnectionRefused, 86 NoSupportedAuth, 87 KeepAliveError, 88 NoNetworkPermission, 89 RegistrationUnsupported 90 }; 91 Q_ENUM(ConnectionError) 92 93 struct Caches { 94 Caches(QObject *parent = nullptr); 95 ~Caches(); 96 97 QSettings *settings; 98 VCardCache *vCardCache; 99 AccountManager *accountManager; 100 MessageModel *msgModel; 101 RosterModel *rosterModel; 102 AvatarFileStorage *avatarStorage; 103 ServerFeaturesCache *serverFeaturesCache; 104 PresenceCache *presCache; 105 TransferCache* transferCache; 106 }; 107 108 /** 109 * @param caches All caches running in the main thread for communication with the UI. 110 * @param enableLogging If logging of the XMPP stream should be done. 111 * @param parent Optional QObject-based parent. 112 */ 113 ClientWorker(Caches *caches, bool enableLogging, QObject *parent = nullptr); 114 115 /** 116 * Initializes this client worker as soon as it runs in a separate thread. 117 */ 118 void initialize(); 119 registrationManager()120 RegistrationManager *registrationManager() const 121 { 122 return m_registrationManager; 123 } 124 vCardManager()125 VCardManager *vCardManager() const 126 { 127 return m_vCardManager; 128 } 129 rosterManager()130 RosterManager *rosterManager() const 131 { 132 return m_rosterManager; 133 } 134 messageHandler()135 MessageHandler *messageHandler() const 136 { 137 return m_messageHandler; 138 } 139 discoveryManager()140 DiscoveryManager *discoveryManager() const 141 { 142 return m_discoveryManager; 143 } 144 uploadManager()145 UploadManager *uploadManager() const 146 { 147 return m_uploadManager; 148 } 149 downloadManager()150 DownloadManager *downloadManager() const 151 { 152 return m_downloadManager; 153 } 154 versionManager()155 VersionManager *versionManager() const 156 { 157 return m_versionManager; 158 } 159 caches()160 Caches *caches() const 161 { 162 return m_caches; 163 } 164 165 /** 166 * Starts or enqueues a task which will be executed after successful login (e.g. a 167 * nickname change). 168 * 169 * This method is called by managers which must call "finishTask()" as soon as the 170 * task is completed. 171 * 172 * If the user is logged out when this method is called, a login is triggered, the 173 * task is started and a logout is triggered afterwards. However, if this method is 174 * called before a login with new credentials (e.g. during account registration), the 175 * task is started after the subsequent login. 176 * 177 * @param task task which is run directly if the user is logged in or enqueued to be 178 * run after an automatic login 179 */ 180 void startTask(const std::function<void ()> task); 181 182 /** 183 * Finishes a task started by "startTask()". 184 * 185 * This must be called after a possible completion of a pending task. 186 * 187 * A logout is triggered when this method is called after the second login with the 188 * same credentials or later. That means, a logout is not triggered after a login with 189 * new credentials (e.g. after a registration). 190 */ 191 void finishTask(); 192 193 public slots: 194 /** 195 * Connects to the server and logs in with all needed configuration variables. 196 */ 197 void logIn(); 198 199 /** 200 * Connects to the server and requests a data form for account registration. 201 */ 202 void connectToRegister(); 203 204 /** 205 * Connects to the server with a minimal configuration. 206 * 207 * Some additional configuration variables can be set by passing a configuration. 208 * 209 * @param config configuration with additional variables for connecting to the server 210 * or nothing if only the minimal configuration should be used 211 */ 212 void connectToServer(QXmppConfiguration config = QXmppConfiguration()); 213 214 /** 215 * Logs out of the server if the client is not already logged out. 216 * 217 * @param isApplicationBeingClosed true if the application will be terminated directly after logging out, false otherwise 218 */ 219 void logOut(bool isApplicationBeingClosed = false); 220 221 /** 222 * Deletes the account data from the client and server. 223 */ 224 void deleteAccountFromClientAndServer(); 225 226 /** 227 * Deletes the account data from the configuration file and database. 228 */ 229 void deleteAccountFromClient(); 230 231 /** 232 * Called when the account is deleted from the server. 233 */ 234 void handleAccountDeletedFromServer(); 235 236 /** 237 * Called when the account could not be deleted from the server. 238 * 239 * @param error error of the failed account deletion 240 */ 241 void handleAccountDeletionFromServerFailed(const QXmppStanza::Error &error); 242 243 signals: 244 /** 245 * Emitted when an authenticated connection to the server is established with new 246 * credentials for the first time. 247 * 248 * The client will be in connected state when this is emitted. 249 */ 250 void loggedInWithNewCredentials(); 251 252 /** 253 * Emitted when the client's connection state changed. 254 * 255 * @param connectionState new connection state 256 */ 257 void connectionStateChanged(Enums::ConnectionState connectionState); 258 259 /** 260 * Emitted when the client failed to connect to the server. 261 * 262 * @param error new connection error 263 */ 264 void connectionErrorChanged(ClientWorker::ConnectionError error); 265 266 private slots: 267 /** 268 * Called when an authenticated connection to the server is established. 269 */ 270 void onConnected(); 271 272 /** 273 * Called when the connection to the server is closed. 274 */ 275 void onDisconnected(); 276 277 /** 278 * Handles the change of the connection state. 279 * 280 * @param connectionState new connection state 281 */ 282 void onConnectionStateChanged(QXmppClient::State connectionState); 283 284 /** 285 * Handles a connection error. 286 * 287 * @param error new connection error 288 */ 289 void onConnectionError(QXmppClient::Error error); 290 291 private: 292 /** 293 * Starts a pending (enqueued) task (e.g. a password change) if the variable (e.g. a 294 * password) could not be changed on the server before because the client was not 295 * logged in. 296 * 297 * @return true if at least one pending task is started on the second login with the 298 * same credentials or later, otherwise false 299 */ 300 bool startPendingTasks(); 301 302 Caches *m_caches; 303 QXmppClient *m_client; 304 LogHandler *m_logger; 305 bool m_enableLogging; 306 307 RegistrationManager *const m_registrationManager; 308 VCardManager *const m_vCardManager; 309 RosterManager *const m_rosterManager; 310 MessageHandler *const m_messageHandler; 311 DiscoveryManager *const m_discoveryManager; 312 UploadManager *const m_uploadManager; 313 DownloadManager *const m_downloadManager; 314 VersionManager *const m_versionManager; 315 316 QList<std::function<void ()>> m_pendingTasks; 317 uint m_activeTasks = 0; 318 319 bool m_isFirstLoginAfterStart = true; 320 bool m_isReconnecting = false; 321 bool m_isDisconnecting = false; 322 QXmppConfiguration m_configToBeUsedOnNextConnect; 323 324 // These variables are used for checking the state of an ongoing account deletion. 325 bool m_isAccountToBeDeletedFromClient = false; 326 bool m_isAccountToBeDeletedFromClientAndServer = false; 327 bool m_isAccountDeletedFromServer = false; 328 bool m_isClientConnectedBeforeAccountDeletionFromServer = true; 329 }; 330