tdesktop/Telegram/SourceFiles/mtproto/session.h

232 lines
5.8 KiB
C
Raw Normal View History

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
2019-01-18 11:26:43 +00:00
#include "base/timer.h"
2019-11-18 09:28:14 +00:00
#include "mtproto/mtproto_rpc_sender.h"
2019-11-13 14:12:04 +00:00
#include "mtproto/mtproto_proxy_data.h"
#include "mtproto/details/mtproto_serialized_request.h"
#include <QtCore/QTimer>
namespace MTP {
class Instance;
2017-06-26 17:38:16 +00:00
class AuthKey;
using AuthKeyPtr = std::shared_ptr<AuthKey>;
2019-12-28 10:52:29 +00:00
enum class DcType;
2019-12-02 13:10:19 +00:00
namespace details {
2017-06-26 17:38:16 +00:00
class Dcenter;
2019-12-02 13:10:19 +00:00
class SessionPrivate;
2019-11-21 10:37:39 +00:00
enum class TemporaryKeyType;
enum class CreatingKeyType;
2019-12-02 13:10:19 +00:00
struct SessionOptions {
SessionOptions() = default;
SessionOptions(
const QString &systemLangCode,
const QString &cloudLangCode,
2018-08-20 11:31:40 +00:00
const QString &langPackName,
const ProxyData &proxy,
bool useIPv4,
bool useIPv6,
bool useHttp,
bool useTcp);
QString systemLangCode;
QString cloudLangCode;
2018-08-20 11:31:40 +00:00
QString langPackName;
ProxyData proxy;
bool useIPv4 = true;
bool useIPv6 = true;
bool useHttp = true;
bool useTcp = true;
};
class Session;
2019-12-02 13:10:19 +00:00
class SessionData final {
public:
explicit SessionData(not_null<Session*> creator) : _owner(creator) {
}
2019-12-02 13:10:19 +00:00
void notifyConnectionInited(const SessionOptions &options);
void setOptions(SessionOptions options) {
2019-11-20 10:41:14 +00:00
QWriteLocker locker(&_optionsLock);
_options = options;
}
2019-12-02 13:10:19 +00:00
[[nodiscard]] SessionOptions options() const {
2019-11-20 10:41:14 +00:00
QReadLocker locker(&_optionsLock);
return _options;
}
not_null<QReadWriteLock*> toSendMutex() {
return &_toSendLock;
}
not_null<QReadWriteLock*> haveSentMutex() {
return &_haveSentLock;
}
not_null<QReadWriteLock*> haveReceivedMutex() {
return &_haveReceivedLock;
}
2019-12-02 13:10:19 +00:00
base::flat_map<mtpRequestId, SerializedRequest> &toSendMap() {
return _toSend;
}
2019-12-02 13:10:19 +00:00
base::flat_map<mtpMsgId, SerializedRequest> &haveSentMap() {
return _haveSent;
}
base::flat_map<mtpRequestId, mtpBuffer> &haveReceivedResponses() {
return _receivedResponses;
}
std::vector<mtpBuffer> &haveReceivedUpdates() {
return _receivedUpdates;
}
2019-12-02 13:10:19 +00:00
// SessionPrivate -> Session interface.
void queueTryToReceive();
void queueNeedToResumeAndSend();
void queueConnectionStateChange(int newState);
void queueResetDone();
void queueSendAnything(crl::time msCanWait = 0);
[[nodiscard]] bool connectionInited() const;
[[nodiscard]] AuthKeyPtr getPersistentKey() const;
2019-11-21 10:37:39 +00:00
[[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const;
2019-12-28 10:52:29 +00:00
[[nodiscard]] CreatingKeyType acquireKeyCreation(DcType type);
2019-11-21 10:37:39 +00:00
[[nodiscard]] bool releaseKeyCreationOnDone(
const AuthKeyPtr &temporaryKey,
2019-11-21 10:37:39 +00:00
const AuthKeyPtr &persistentKeyUsedForBind);
2019-12-28 10:52:29 +00:00
[[nodiscard]] bool releaseCdnKeyCreationOnDone(
const AuthKeyPtr &temporaryKey);
void releaseKeyCreationOnFail();
void destroyTemporaryKey(uint64 keyId);
void detach();
private:
template <typename Callback>
void withSession(Callback &&callback);
Session *_owner = nullptr;
mutable QMutex _ownerMutex;
2019-12-02 13:10:19 +00:00
SessionOptions _options;
mutable QReadWriteLock _optionsLock;
2019-12-02 13:10:19 +00:00
base::flat_map<mtpRequestId, SerializedRequest> _toSend; // map of request_id -> request, that is waiting to be sent
QReadWriteLock _toSendLock;
2019-12-02 13:10:19 +00:00
base::flat_map<mtpMsgId, SerializedRequest> _haveSent; // map of msg_id -> request, that was sent
QReadWriteLock _haveSentLock;
base::flat_map<mtpRequestId, mtpBuffer> _receivedResponses; // map of request_id -> response that should be processed in the main thread
std::vector<mtpBuffer> _receivedUpdates; // list of updates that should be processed in the main thread
QReadWriteLock _haveReceivedLock;
};
2019-12-02 13:10:19 +00:00
class Session final : public QObject {
public:
// Main thread.
2019-11-15 07:28:33 +00:00
Session(
not_null<Instance*> instance,
2019-11-27 15:09:56 +00:00
not_null<QThread*> thread,
2019-11-15 07:28:33 +00:00
ShiftedDcId shiftedDcId,
2019-11-20 13:33:45 +00:00
not_null<Dcenter*> dc);
~Session();
void start();
void reInitConnection();
void restart();
void refreshOptions();
void stop();
void kill();
void unpaused();
// Thread-safe.
[[nodiscard]] ShiftedDcId getDcWithShift() const;
[[nodiscard]] AuthKeyPtr getPersistentKey() const;
2019-11-21 10:37:39 +00:00
[[nodiscard]] AuthKeyPtr getTemporaryKey(TemporaryKeyType type) const;
[[nodiscard]] bool connectionInited() const;
void sendPrepared(
2019-12-02 13:10:19 +00:00
const SerializedRequest &request,
crl::time msCanWait = 0);
2019-12-02 13:10:19 +00:00
// SessionPrivate thread.
2019-12-28 10:52:29 +00:00
[[nodiscard]] CreatingKeyType acquireKeyCreation(DcType type);
2019-11-21 10:37:39 +00:00
[[nodiscard]] bool releaseKeyCreationOnDone(
const AuthKeyPtr &temporaryKey,
2019-11-21 10:37:39 +00:00
const AuthKeyPtr &persistentKeyUsedForBind);
2019-12-28 10:52:29 +00:00
[[nodiscard]] bool releaseCdnKeyCreationOnDone(const AuthKeyPtr &temporaryKey);
void releaseKeyCreationOnFail();
void destroyTemporaryKey(uint64 keyId);
void notifyDcConnectionInited();
void ping();
void cancel(mtpRequestId requestId, mtpMsgId msgId);
int requestState(mtpRequestId requestId) const;
int getState() const;
QString transport() const;
void tryToReceive();
void needToResumeAndSend();
void connectionStateChange(int newState);
void resetDone();
void sendAnything(crl::time msCanWait = 0);
private:
void watchDcKeyChanges();
void watchDcOptionsChanges();
void killConnection();
bool rpcErrorOccured(
mtpRequestId requestId,
const RPCFailHandlerPtr &onFail,
const RPCError &err);
2019-12-28 10:52:29 +00:00
[[nodiscard]] bool releaseGenericKeyCreationOnDone(
const AuthKeyPtr &temporaryKey,
const AuthKeyPtr &persistentKeyUsedForBind);
2019-11-14 17:39:15 +00:00
const not_null<Instance*> _instance;
const ShiftedDcId _shiftedDcId = 0;
const not_null<Dcenter*> _dc;
const std::shared_ptr<SessionData> _data;
2019-11-27 15:09:56 +00:00
const not_null<QThread*> _thread;
2019-12-02 13:10:19 +00:00
SessionPrivate *_private = nullptr;
bool _killed = false;
bool _needToReceive = false;
AuthKeyPtr _dcKeyForCheck;
2019-11-21 10:37:39 +00:00
CreatingKeyType _myKeyCreation = CreatingKeyType();
2019-11-14 07:13:17 +00:00
crl::time _msSendCall = 0;
crl::time _msWait = 0;
bool _ping = false;
2019-11-14 17:39:15 +00:00
base::Timer _timeouter;
2019-11-14 07:13:17 +00:00
base::Timer _sender;
rpl::lifetime _lifetime;
};
2019-12-02 13:10:19 +00:00
} // namespace details
} // namespace MTP