1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include "base/timer.h" 11 #include "mtproto/mtproto_response.h" 12 #include "mtproto/mtproto_proxy_data.h" 13 #include "mtproto/details/mtproto_serialized_request.h" 14 15 #include <QtCore/QTimer> 16 17 namespace MTP { 18 19 class Instance; 20 class AuthKey; 21 using AuthKeyPtr = std::shared_ptr<AuthKey>; 22 enum class DcType; 23 24 namespace details { 25 26 class Dcenter; 27 class SessionPrivate; 28 29 enum class TemporaryKeyType; 30 enum class CreatingKeyType; 31 32 struct SessionOptions { 33 SessionOptions() = default; 34 SessionOptions( 35 const QString &systemLangCode, 36 const QString &cloudLangCode, 37 const QString &langPackName, 38 const ProxyData &proxy, 39 bool useIPv4, 40 bool useIPv6, 41 bool useHttp, 42 bool useTcp); 43 44 QString systemLangCode; 45 QString cloudLangCode; 46 QString langPackName; 47 ProxyData proxy; 48 bool useIPv4 = true; 49 bool useIPv6 = true; 50 bool useHttp = true; 51 bool useTcp = true; 52 53 }; 54 55 class Session; 56 class SessionData final { 57 public: SessionData(not_null<Session * > creator)58 explicit SessionData(not_null<Session*> creator) : _owner(creator) { 59 } 60 61 void notifyConnectionInited(const SessionOptions &options); setOptions(SessionOptions options)62 void setOptions(SessionOptions options) { 63 QWriteLocker locker(&_optionsLock); 64 _options = options; 65 } options()66 [[nodiscard]] SessionOptions options() const { 67 QReadLocker locker(&_optionsLock); 68 return _options; 69 } 70 toSendMutex()71 not_null<QReadWriteLock*> toSendMutex() { 72 return &_toSendLock; 73 } haveSentMutex()74 not_null<QReadWriteLock*> haveSentMutex() { 75 return &_haveSentLock; 76 } haveReceivedMutex()77 not_null<QReadWriteLock*> haveReceivedMutex() { 78 return &_haveReceivedLock; 79 } 80 toSendMap()81 base::flat_map<mtpRequestId, SerializedRequest> &toSendMap() { 82 return _toSend; 83 } haveSentMap()84 base::flat_map<mtpMsgId, SerializedRequest> &haveSentMap() { 85 return _haveSent; 86 } haveReceivedMessages()87 std::vector<Response> &haveReceivedMessages() { 88 return _receivedMessages; 89 } 90 91 // SessionPrivate -> Session interface. 92 void queueTryToReceive(); 93 void queueNeedToResumeAndSend(); 94 void queueConnectionStateChange(int newState); 95 void queueResetDone(); 96 void queueSendAnything(crl::time msCanWait = 0); 97 98 [[nodiscard]] bool connectionInited() const; 99 [[nodiscard]] AuthKeyPtr getPersistentKey() const; 100 [[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const; 101 [[nodiscard]] CreatingKeyType acquireKeyCreation(DcType type); 102 [[nodiscard]] bool releaseKeyCreationOnDone( 103 const AuthKeyPtr &temporaryKey, 104 const AuthKeyPtr &persistentKeyUsedForBind); 105 [[nodiscard]] bool releaseCdnKeyCreationOnDone( 106 const AuthKeyPtr &temporaryKey); 107 void releaseKeyCreationOnFail(); 108 void destroyTemporaryKey(uint64 keyId); 109 110 void detach(); 111 112 private: 113 template <typename Callback> 114 void withSession(Callback &&callback); 115 116 Session *_owner = nullptr; 117 mutable QMutex _ownerMutex; 118 119 SessionOptions _options; 120 mutable QReadWriteLock _optionsLock; 121 122 base::flat_map<mtpRequestId, SerializedRequest> _toSend; // map of request_id -> request, that is waiting to be sent 123 QReadWriteLock _toSendLock; 124 125 base::flat_map<mtpMsgId, SerializedRequest> _haveSent; // map of msg_id -> request, that was sent 126 QReadWriteLock _haveSentLock; 127 128 std::vector<Response> _receivedMessages; // list of responses / updates that should be processed in the main thread 129 QReadWriteLock _haveReceivedLock; 130 131 }; 132 133 class Session final : public QObject { 134 public: 135 // Main thread. 136 Session( 137 not_null<Instance*> instance, 138 not_null<QThread*> thread, 139 ShiftedDcId shiftedDcId, 140 not_null<Dcenter*> dc); 141 ~Session(); 142 143 void start(); 144 void reInitConnection(); 145 146 void restart(); 147 void refreshOptions(); 148 void stop(); 149 void kill(); 150 151 void unpaused(); 152 153 // Thread-safe. 154 [[nodiscard]] ShiftedDcId getDcWithShift() const; 155 [[nodiscard]] AuthKeyPtr getPersistentKey() const; 156 [[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const; 157 [[nodiscard]] bool connectionInited() const; 158 void sendPrepared( 159 const SerializedRequest &request, 160 crl::time msCanWait = 0); 161 162 // SessionPrivate thread. 163 [[nodiscard]] CreatingKeyType acquireKeyCreation(DcType type); 164 [[nodiscard]] bool releaseKeyCreationOnDone( 165 const AuthKeyPtr &temporaryKey, 166 const AuthKeyPtr &persistentKeyUsedForBind); 167 [[nodiscard]] bool releaseCdnKeyCreationOnDone(const AuthKeyPtr &temporaryKey); 168 void releaseKeyCreationOnFail(); 169 void destroyTemporaryKey(uint64 keyId); 170 171 void notifyDcConnectionInited(); 172 173 void ping(); 174 void cancel(mtpRequestId requestId, mtpMsgId msgId); 175 int requestState(mtpRequestId requestId) const; 176 int getState() const; 177 QString transport() const; 178 179 void tryToReceive(); 180 void needToResumeAndSend(); 181 void connectionStateChange(int newState); 182 void resetDone(); 183 void sendAnything(crl::time msCanWait = 0); 184 185 private: 186 void watchDcKeyChanges(); 187 void watchDcOptionsChanges(); 188 189 void killConnection(); 190 191 [[nodiscard]] bool releaseGenericKeyCreationOnDone( 192 const AuthKeyPtr &temporaryKey, 193 const AuthKeyPtr &persistentKeyUsedForBind); 194 195 const not_null<Instance*> _instance; 196 const ShiftedDcId _shiftedDcId = 0; 197 const not_null<Dcenter*> _dc; 198 const std::shared_ptr<SessionData> _data; 199 const not_null<QThread*> _thread; 200 201 SessionPrivate *_private = nullptr; 202 203 bool _killed = false; 204 bool _needToReceive = false; 205 206 AuthKeyPtr _dcKeyForCheck; 207 CreatingKeyType _myKeyCreation = CreatingKeyType(); 208 209 crl::time _msSendCall = 0; 210 crl::time _msWait = 0; 211 212 bool _ping = false; 213 214 base::Timer _sender; 215 216 rpl::lifetime _lifetime; 217 218 }; 219 220 } // namespace details 221 } // namespace MTP 222