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 #include "mtproto/mtproto_config.h"
9
10 #include "storage/serialize_common.h"
11 #include "mtproto/type_utils.h"
12 #include "logs.h"
13
14 namespace MTP {
15 namespace {
16
17 constexpr auto kVersion = 1;
18
19 }
Config(Environment environment)20 Config::Config(Environment environment) : _dcOptions(environment) {
21 _fields.webFileDcId = _dcOptions.isTestMode() ? 2 : 4;
22 _fields.txtDomainString = _dcOptions.isTestMode()
23 ? u"tapv3.stel.com"_q
24 : u"apv3.stel.com"_q;
25 }
26
Config(const Config & other)27 Config::Config(const Config &other)
28 : _dcOptions(other.dcOptions())
29 , _fields(other._fields) {
30 }
31
serialize() const32 QByteArray Config::serialize() const {
33 auto options = _dcOptions.serialize();
34 auto size = sizeof(qint32) * 2; // version + environment
35 size += Serialize::bytearraySize(options);
36 size += 28 * sizeof(qint32);
37 size += Serialize::stringSize(_fields.internalLinksDomain);
38 size += Serialize::stringSize(_fields.txtDomainString);
39
40 auto result = QByteArray();
41 result.reserve(size);
42 {
43 QDataStream stream(&result, QIODevice::WriteOnly);
44 stream.setVersion(QDataStream::Qt_5_1);
45 stream
46 << qint32(kVersion)
47 << qint32(_dcOptions.isTestMode()
48 ? Environment::Test
49 : Environment::Production)
50 << options
51 << qint32(_fields.chatSizeMax)
52 << qint32(_fields.megagroupSizeMax)
53 << qint32(_fields.forwardedCountMax)
54 << qint32(_fields.onlineUpdatePeriod)
55 << qint32(_fields.offlineBlurTimeout)
56 << qint32(_fields.offlineIdleTimeout)
57 << qint32(_fields.onlineFocusTimeout)
58 << qint32(_fields.onlineCloudTimeout)
59 << qint32(_fields.notifyCloudDelay)
60 << qint32(_fields.notifyDefaultDelay)
61 << qint32(_fields.savedGifsLimit)
62 << qint32(_fields.editTimeLimit)
63 << qint32(_fields.revokeTimeLimit)
64 << qint32(_fields.revokePrivateTimeLimit)
65 << qint32(_fields.revokePrivateInbox ? 1 : 0)
66 << qint32(_fields.stickersRecentLimit)
67 << qint32(_fields.stickersFavedLimit)
68 << qint32(_fields.pinnedDialogsCountMax.current())
69 << qint32(_fields.pinnedDialogsInFolderMax.current())
70 << _fields.internalLinksDomain
71 << qint32(_fields.channelsReadMediaPeriod)
72 << qint32(_fields.callReceiveTimeoutMs)
73 << qint32(_fields.callRingTimeoutMs)
74 << qint32(_fields.callConnectTimeoutMs)
75 << qint32(_fields.callPacketTimeoutMs)
76 << qint32(_fields.webFileDcId)
77 << _fields.txtDomainString
78 << qint32(_fields.phoneCallsEnabled.current() ? 1 : 0)
79 << qint32(_fields.blockedMode ? 1 : 0)
80 << qint32(_fields.captionLengthMax);
81 }
82 return result;
83 }
84
FromSerialized(const QByteArray & serialized)85 std::unique_ptr<Config> Config::FromSerialized(const QByteArray &serialized) {
86 auto result = std::unique_ptr<Config>();
87 auto raw = result.get();
88
89 QDataStream stream(serialized);
90 stream.setVersion(QDataStream::Qt_5_1);
91
92 auto version = qint32();
93 stream >> version;
94 if (version != kVersion) {
95 return result;
96 }
97 auto environment = qint32();
98 stream >> environment;
99 switch (environment) {
100 case qint32(Environment::Test):
101 result = std::make_unique<Config>(Environment::Test);
102 break;
103 case qint32(Environment::Production):
104 result = std::make_unique<Config>(Environment::Production);
105 break;
106 }
107 if (!(raw = result.get())) {
108 return result;
109 }
110
111 auto dcOptionsSerialized = QByteArray();
112 const auto read = [&](auto &field) {
113 using Type = std::remove_reference_t<decltype(field)>;
114 if constexpr (std::is_same_v<Type, int>
115 || std::is_same_v<Type, rpl::variable<int>>) {
116 auto value = qint32();
117 stream >> value;
118 field = value;
119 } else if constexpr (std::is_same_v<Type, bool>
120 || std::is_same_v<Type, rpl::variable<bool>>) {
121 auto value = qint32();
122 stream >> value;
123 field = (value == 1);
124 } else if constexpr (std::is_same_v<Type, QByteArray>
125 || std::is_same_v<Type, QString>) {
126 stream >> field;
127 } else {
128 static_assert(false_(field), "Bad read() call.");
129 }
130 };
131
132 read(dcOptionsSerialized);
133 read(raw->_fields.chatSizeMax);
134 read(raw->_fields.megagroupSizeMax);
135 read(raw->_fields.forwardedCountMax);
136 read(raw->_fields.onlineUpdatePeriod);
137 read(raw->_fields.offlineBlurTimeout);
138 read(raw->_fields.offlineIdleTimeout);
139 read(raw->_fields.onlineFocusTimeout);
140 read(raw->_fields.onlineCloudTimeout);
141 read(raw->_fields.notifyCloudDelay);
142 read(raw->_fields.notifyDefaultDelay);
143 read(raw->_fields.savedGifsLimit);
144 read(raw->_fields.editTimeLimit);
145 read(raw->_fields.revokeTimeLimit);
146 read(raw->_fields.revokePrivateTimeLimit);
147 read(raw->_fields.revokePrivateInbox);
148 read(raw->_fields.stickersRecentLimit);
149 read(raw->_fields.stickersFavedLimit);
150 read(raw->_fields.pinnedDialogsCountMax);
151 read(raw->_fields.pinnedDialogsInFolderMax);
152 read(raw->_fields.internalLinksDomain);
153 read(raw->_fields.channelsReadMediaPeriod);
154 read(raw->_fields.callReceiveTimeoutMs);
155 read(raw->_fields.callRingTimeoutMs);
156 read(raw->_fields.callConnectTimeoutMs);
157 read(raw->_fields.callPacketTimeoutMs);
158 read(raw->_fields.webFileDcId);
159 read(raw->_fields.txtDomainString);
160 read(raw->_fields.phoneCallsEnabled);
161 read(raw->_fields.blockedMode);
162 read(raw->_fields.captionLengthMax);
163
164 if (stream.status() != QDataStream::Ok
165 || !raw->_dcOptions.constructFromSerialized(dcOptionsSerialized)) {
166 return nullptr;
167 }
168 return result;
169 }
170
values() const171 const ConfigFields &Config::values() const {
172 return _fields;
173 }
174
apply(const MTPDconfig & data)175 void Config::apply(const MTPDconfig &data) {
176 if (mtpIsTrue(data.vtest_mode()) != _dcOptions.isTestMode()) {
177 LOG(("MTP Error: config with wrong test mode field received!"));
178 return;
179 }
180
181 DEBUG_LOG(("MTP Info: got config, "
182 "chat_size_max: %1, "
183 "date: %2, "
184 "test_mode: %3, "
185 "this_dc: %4, "
186 "dc_options.length: %5"
187 ).arg(data.vchat_size_max().v
188 ).arg(data.vdate().v
189 ).arg(mtpIsTrue(data.vtest_mode())
190 ).arg(data.vthis_dc().v
191 ).arg(data.vdc_options().v.size()));
192
193 _fields.chatSizeMax = data.vchat_size_max().v;
194 _fields.megagroupSizeMax = data.vmegagroup_size_max().v;
195 _fields.forwardedCountMax = data.vforwarded_count_max().v;
196 _fields.onlineUpdatePeriod = data.vonline_update_period_ms().v;
197 _fields.offlineBlurTimeout = data.voffline_blur_timeout_ms().v;
198 _fields.offlineIdleTimeout = data.voffline_idle_timeout_ms().v;
199 _fields.onlineCloudTimeout = data.vonline_cloud_timeout_ms().v;
200 _fields.notifyCloudDelay = data.vnotify_cloud_delay_ms().v;
201 _fields.notifyDefaultDelay = data.vnotify_default_delay_ms().v;
202 _fields.savedGifsLimit = data.vsaved_gifs_limit().v;
203 _fields.editTimeLimit = data.vedit_time_limit().v;
204 _fields.revokeTimeLimit = data.vrevoke_time_limit().v;
205 _fields.revokePrivateTimeLimit = data.vrevoke_pm_time_limit().v;
206 _fields.revokePrivateInbox = data.is_revoke_pm_inbox();
207 _fields.stickersRecentLimit = data.vstickers_recent_limit().v;
208 _fields.stickersFavedLimit = data.vstickers_faved_limit().v;
209 _fields.pinnedDialogsCountMax =
210 std::max(data.vpinned_dialogs_count_max().v, 1);
211 _fields.pinnedDialogsInFolderMax =
212 std::max(data.vpinned_infolder_count_max().v, 1);
213 _fields.internalLinksDomain = qs(data.vme_url_prefix());
214 _fields.channelsReadMediaPeriod = data.vchannels_read_media_period().v;
215 _fields.webFileDcId = data.vwebfile_dc_id().v;
216 _fields.callReceiveTimeoutMs = data.vcall_receive_timeout_ms().v;
217 _fields.callRingTimeoutMs = data.vcall_ring_timeout_ms().v;
218 _fields.callConnectTimeoutMs = data.vcall_connect_timeout_ms().v;
219 _fields.callPacketTimeoutMs = data.vcall_packet_timeout_ms().v;
220 _fields.phoneCallsEnabled = data.is_phonecalls_enabled();
221 _fields.blockedMode = data.is_blocked_mode();
222 _fields.captionLengthMax = data.vcaption_length_max().v;
223
224 if (data.vdc_options().v.empty()) {
225 LOG(("MTP Error: config with empty dc_options received!"));
226 } else {
227 dcOptions().setFromList(data.vdc_options());
228 }
229
230 _updates.fire({});
231 }
232
updates() const233 rpl::producer<> Config::updates() const {
234 return _updates.events();
235 }
236
setChatSizeMax(int value)237 void Config::setChatSizeMax(int value) {
238 _fields.chatSizeMax = value;
239 }
240
setSavedGifsLimit(int value)241 void Config::setSavedGifsLimit(int value) {
242 _fields.savedGifsLimit = value;
243 }
244
setStickersRecentLimit(int value)245 void Config::setStickersRecentLimit(int value) {
246 _fields.stickersRecentLimit = value;
247 }
248
setStickersFavedLimit(int value)249 void Config::setStickersFavedLimit(int value) {
250 _fields.stickersFavedLimit = value;
251 }
252
setMegagroupSizeMax(int value)253 void Config::setMegagroupSizeMax(int value) {
254 _fields.megagroupSizeMax = value;
255 }
256
setTxtDomainString(const QString & value)257 void Config::setTxtDomainString(const QString &value) {
258 _fields.txtDomainString = value;
259 }
260
261 } // namespace MTP
262