1 /* 2 * Copyright (C) by Felix Weilbach <felix.weilbach@nextcloud.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 */ 14 15 #pragma once 16 17 #include <QWebSocket> 18 #include <QTimer> 19 20 #include "capabilities.h" 21 22 namespace OCC { 23 24 class Account; 25 class AbstractCredentials; 26 27 class OWNCLOUDSYNC_EXPORT PushNotifications : public QObject 28 { 29 Q_OBJECT 30 31 public: 32 explicit PushNotifications(Account *account, QObject *parent = nullptr); 33 34 ~PushNotifications() override; 35 36 /** 37 * Setup push notifications 38 * 39 * This method needs to be called before push notifications can be used. 40 */ 41 void setup(); 42 43 /** 44 * Set the interval for reconnection attempts 45 * 46 * @param interval Interval in milliseconds. 47 */ 48 void setReconnectTimerInterval(uint32_t interval); 49 50 /** 51 * Indicates if push notifications ready to use 52 * 53 * Ready to use means connected and authenticated. 54 */ 55 bool isReady() const; 56 57 /** 58 * Set the interval in which the websocket will ping the server if it is still alive. 59 * 60 * If the websocket does not respond in timeoutInterval, the connection will be terminated. 61 * 62 * @param interval Interval in milliseconds. 63 */ 64 void setPingInterval(int interval); 65 66 signals: 67 /** 68 * Will be emitted after a successful connection and authentication 69 */ 70 void ready(); 71 72 /** 73 * Will be emitted if files on the server changed 74 */ 75 void filesChanged(Account *account); 76 77 /** 78 * Will be emitted if activities have been changed on the server 79 */ 80 void activitiesChanged(Account *account); 81 82 /** 83 * Will be emitted if notifications have been changed on the server 84 */ 85 void notificationsChanged(Account *account); 86 87 /** 88 * Will be emitted if push notifications are unable to authenticate 89 * 90 * It's save to call #PushNotifications::setup() after this signal has been emitted. 91 */ 92 void authenticationFailed(); 93 94 /** 95 * Will be emitted if push notifications are unable to connect or the connection timed out 96 * 97 * It's save to call #PushNotifications::setup() after this signal has been emitted. 98 */ 99 void connectionLost(); 100 101 private slots: 102 void onWebSocketConnected(); 103 void onWebSocketDisconnected(); 104 void onWebSocketTextMessageReceived(const QString &message); 105 void onWebSocketError(QAbstractSocket::SocketError error); 106 void onWebSocketSslErrors(const QList<QSslError> &errors); 107 void onWebSocketPongReceived(quint64 elapsedTime, const QByteArray &payload); 108 void onPingTimedOut(); 109 110 private: 111 void openWebSocket(); 112 void reconnectToWebSocket(); 113 void closeWebSocket(); 114 void authenticateOnWebSocket(); 115 bool tryReconnectToWebSocket(); 116 void initReconnectTimer(); 117 void pingWebSocketServer(); 118 void startPingTimer(); 119 void startPingTimedOutTimer(); 120 121 void handleAuthenticated(); 122 void handleNotifyFile(); 123 void handleInvalidCredentials(); 124 void handleNotifyNotification(); 125 void handleNotifyActivity(); 126 127 void emitFilesChanged(); 128 void emitNotificationsChanged(); 129 void emitActivitiesChanged(); 130 131 Account *_account = nullptr; 132 QWebSocket *_webSocket; 133 uint8_t _failedAuthenticationAttemptsCount = 0; 134 QTimer *_reconnectTimer = nullptr; 135 uint32_t _reconnectTimerInterval = 20 * 1000; 136 bool _isReady = false; 137 138 QTimer _pingTimer; 139 QTimer _pingTimedOutTimer; 140 bool _pongReceivedFromWebSocketServer = false; 141 }; 142 } 143