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 "mtproto/mtproto_auth_key.h"
11 #include "mtproto/mtp_instance.h"
12 #include "base/weak_ptr.h"
13 
14 namespace Storage {
15 class Account;
16 class Domain;
17 enum class StartResult : uchar;
18 } // namespace Storage
19 
20 namespace MTP {
21 class AuthKey;
22 class Config;
23 } // namespace MTP
24 
25 namespace Main {
26 
27 class Domain;
28 class Session;
29 class SessionSettings;
30 class AppConfig;
31 
32 class Account final : public base::has_weak_ptr {
33 public:
34 	Account(not_null<Domain*> domain, const QString &dataName, int index);
35 	~Account();
36 
domain()37 	[[nodiscard]] Domain &domain() const {
38 		return *_domain;
39 	}
40 
41 	[[nodiscard]] Storage::Domain &domainLocal() const;
42 
43 	[[nodiscard]] Storage::StartResult legacyStart(
44 		const QByteArray &passcode);
45 	[[nodiscard]] std::unique_ptr<MTP::Config> prepareToStart(
46 		std::shared_ptr<MTP::AuthKey> localKey);
47 	void prepareToStartAdded(
48 		std::shared_ptr<MTP::AuthKey> localKey);
49 	void start(std::unique_ptr<MTP::Config> config);
50 
51 	[[nodiscard]] uint64 willHaveSessionUniqueId(MTP::Config *config) const;
52 	void createSession(
53 		const MTPUser &user,
54 		std::unique_ptr<SessionSettings> settings = nullptr);
55 	void createSession(
56 		UserId id,
57 		QByteArray serialized,
58 		int streamVersion,
59 		std::unique_ptr<SessionSettings> settings);
60 
61 	void logOut();
62 	void forcedLogOut();
63 	[[nodiscard]] bool loggingOut() const;
64 
appConfig()65 	[[nodiscard]] AppConfig &appConfig() const {
66 		Expects(_appConfig != nullptr);
67 
68 		return *_appConfig;
69 	}
70 
local()71 	[[nodiscard]] Storage::Account &local() const {
72 		return *_local;
73 	}
74 
75 	[[nodiscard]] bool sessionExists() const;
76 	[[nodiscard]] Session &session() const;
77 	[[nodiscard]] Session *maybeSession() const;
78 	[[nodiscard]] rpl::producer<Session*> sessionValue() const;
79 	[[nodiscard]] rpl::producer<Session*> sessionChanges() const;
80 
mtp()81 	[[nodiscard]] MTP::Instance &mtp() const {
82 		return *_mtp;
83 	}
84 	[[nodiscard]] rpl::producer<not_null<MTP::Instance*>> mtpValue() const;
85 
86 	// Each time the main session changes a new copy of the pointer is fired.
87 	// This allows to resend the requests that were not requiring auth, and
88 	// which could be forgotten without calling .done() or .fail() because
89 	// of the main dc changing.
90 	[[nodiscard]] auto mtpMainSessionValue() const
91 		-> rpl::producer<not_null<MTP::Instance*>>;
92 
93 	// Set from legacy storage.
94 	void setLegacyMtpKey(std::shared_ptr<MTP::AuthKey> key);
95 
96 	void setMtpMainDcId(MTP::DcId mainDcId);
97 	void setSessionUserId(UserId userId);
98 	void setSessionFromStorage(
99 		std::unique_ptr<SessionSettings> data,
100 		QByteArray &&selfSerialized,
101 		int32 selfStreamVersion);
102 	[[nodiscard]] SessionSettings *getSessionSettings();
103 	[[nodiscard]] rpl::producer<> mtpNewSessionCreated() const;
104 	[[nodiscard]] rpl::producer<MTPUpdates> mtpUpdates() const;
105 
106 	// Serialization.
107 	[[nodiscard]] QByteArray serializeMtpAuthorization() const;
108 	void setMtpAuthorization(const QByteArray &serialized);
109 
110 	void suggestMainDcId(MTP::DcId mainDcId);
111 	void destroyStaleAuthorizationKeys();
112 
lifetime()113 	[[nodiscard]] rpl::lifetime &lifetime() {
114 		return _lifetime;
115 	}
116 
117 private:
118 	static constexpr auto kDefaultSaveDelay = crl::time(1000);
119 	enum class DestroyReason {
120 		Quitting,
121 		LoggedOut,
122 	};
123 
124 	void startMtp(std::unique_ptr<MTP::Config> config);
125 	void createSession(
126 		const MTPUser &user,
127 		QByteArray serialized,
128 		int streamVersion,
129 		std::unique_ptr<SessionSettings> settings);
130 	void watchProxyChanges();
131 	void watchSessionChanges();
132 	bool checkForUpdates(const MTP::Response &message);
133 	bool checkForNewSession(const MTP::Response &message);
134 
135 	void destroyMtpKeys(MTP::AuthKeysList &&keys);
136 	void resetAuthorizationKeys();
137 
138 	void loggedOut();
139 	void destroySession(DestroyReason reason);
140 
141 	const not_null<Domain*> _domain;
142 	const std::unique_ptr<Storage::Account> _local;
143 
144 	std::unique_ptr<MTP::Instance> _mtp;
145 	rpl::variable<MTP::Instance*> _mtpValue;
146 	std::unique_ptr<MTP::Instance> _mtpForKeysDestroy;
147 	rpl::event_stream<MTPUpdates> _mtpUpdates;
148 	rpl::event_stream<> _mtpNewSessionCreated;
149 
150 	std::unique_ptr<AppConfig> _appConfig;
151 
152 	std::unique_ptr<Session> _session;
153 	rpl::variable<Session*> _sessionValue;
154 
155 	UserId _sessionUserId = 0;
156 	QByteArray _sessionUserSerialized;
157 	int32 _sessionUserStreamVersion = 0;
158 	std::unique_ptr<SessionSettings> _storedSessionSettings;
159 	MTP::Instance::Fields _mtpFields;
160 	MTP::AuthKeysList _mtpKeysToDestroy;
161 	bool _loggingOut = false;
162 
163 	rpl::lifetime _lifetime;
164 
165 };
166 
167 } // namespace Main
168