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/basic_types.h"
11 #include "base/match_method.h"
12 #include "base/flags.h"
13 #include "base/bytes.h"
14 #include "base/algorithm.h"
15 #include "base/assertion.h"
16 #include "tl/tl_basic_types.h"
17 #include "tl/tl_boxed.h"
18 
19 #include <QtCore/QVector>
20 #include <QtCore/QString>
21 #include <QtCore/QByteArray>
22 #include <gsl/gsl>
23 
24 using mtpPrime = int32;
25 using mtpRequestId = int32;
26 using mtpMsgId = uint64;
27 using mtpPingId = uint64;
28 
29 using mtpBuffer = QVector<mtpPrime>;
30 using mtpTypeId = uint32;
31 
32 namespace MTP {
33 
34 // type DcId represents actual data center id, while in most cases
35 // we use some shifted ids, like DcId() + X * DCShift
36 using DcId = int32;
37 using ShiftedDcId = int32;
38 
39 constexpr auto kDcShift = ShiftedDcId(10000);
40 constexpr auto kConfigDcShift = 0x01;
41 constexpr auto kLogoutDcShift = 0x02;
42 constexpr auto kUpdaterDcShift = 0x03;
43 constexpr auto kExportDcShift = 0x04;
44 constexpr auto kExportMediaDcShift = 0x05;
45 constexpr auto kGroupCallStreamDcShift = 0x06;
46 constexpr auto kMaxMediaDcCount = 0x10;
47 constexpr auto kBaseDownloadDcShift = 0x10;
48 constexpr auto kBaseUploadDcShift = 0x20;
49 constexpr auto kDestroyKeyStartDcShift = 0x100;
50 
BareDcId(ShiftedDcId shiftedDcId)51 constexpr DcId BareDcId(ShiftedDcId shiftedDcId) {
52 	return (shiftedDcId % kDcShift);
53 }
54 
ShiftDcId(DcId dcId,int value)55 constexpr ShiftedDcId ShiftDcId(DcId dcId, int value) {
56 	return dcId + kDcShift * value;
57 }
58 
GetDcIdShift(ShiftedDcId shiftedDcId)59 constexpr int GetDcIdShift(ShiftedDcId shiftedDcId) {
60 	return shiftedDcId / kDcShift;
61 }
62 
63 } // namespace MTP
64 
65 enum {
66 	// core types
67 	mtpc_int = tl::id_int,
68 	mtpc_long = tl::id_long,
69 	mtpc_int128 = tl::id_int128,
70 	mtpc_int256 = tl::id_int256,
71 	mtpc_double = tl::id_double,
72 	mtpc_string = tl::id_string,
73 	mtpc_vector = tl::id_vector,
74 	mtpc_bytes = tl::id_bytes,
75 	mtpc_flags = tl::id_flags,
76 
77 	// layers
78 	mtpc_invokeWithLayer1 = 0x53835315,
79 	mtpc_invokeWithLayer2 = 0x289dd1f6,
80 	mtpc_invokeWithLayer3 = 0xb7475268,
81 	mtpc_invokeWithLayer4 = 0xdea0d430,
82 	mtpc_invokeWithLayer5 = 0x417a57ae,
83 	mtpc_invokeWithLayer6 = 0x3a64d54d,
84 	mtpc_invokeWithLayer7 = 0xa5be56d3,
85 	mtpc_invokeWithLayer8 = 0xe9abd9fd,
86 	mtpc_invokeWithLayer9 = 0x76715a63,
87 	mtpc_invokeWithLayer10 = 0x39620c41,
88 	mtpc_invokeWithLayer11 = 0xa6b88fdf,
89 	mtpc_invokeWithLayer12 = 0xdda60d3c,
90 	mtpc_invokeWithLayer13 = 0x427c8ea2,
91 	mtpc_invokeWithLayer14 = 0x2b9b08fa,
92 	mtpc_invokeWithLayer15 = 0xb4418b64,
93 	mtpc_invokeWithLayer16 = 0xcf5f0987,
94 	mtpc_invokeWithLayer17 = 0x50858a19,
95 	mtpc_invokeWithLayer18 = 0x1c900537,
96 
97 	// manually parsed
98 	mtpc_rpc_result = 0xf35c6d01,
99 	mtpc_msg_container = 0x73f1f8dc,
100 //	mtpc_msg_copy = 0xe06046b2,
101 	mtpc_gzip_packed = 0x3072cfa1
102 };
103 static const mtpTypeId mtpc_core_message = -1; // undefined type, but is used
104 static const mtpTypeId mtpLayers[] = {
105 	mtpTypeId(mtpc_invokeWithLayer1),
106 	mtpTypeId(mtpc_invokeWithLayer2),
107 	mtpTypeId(mtpc_invokeWithLayer3),
108 	mtpTypeId(mtpc_invokeWithLayer4),
109 	mtpTypeId(mtpc_invokeWithLayer5),
110 	mtpTypeId(mtpc_invokeWithLayer6),
111 	mtpTypeId(mtpc_invokeWithLayer7),
112 	mtpTypeId(mtpc_invokeWithLayer8),
113 	mtpTypeId(mtpc_invokeWithLayer9),
114 	mtpTypeId(mtpc_invokeWithLayer10),
115 	mtpTypeId(mtpc_invokeWithLayer11),
116 	mtpTypeId(mtpc_invokeWithLayer12),
117 	mtpTypeId(mtpc_invokeWithLayer13),
118 	mtpTypeId(mtpc_invokeWithLayer14),
119 	mtpTypeId(mtpc_invokeWithLayer15),
120 	mtpTypeId(mtpc_invokeWithLayer16),
121 	mtpTypeId(mtpc_invokeWithLayer17),
122 	mtpTypeId(mtpc_invokeWithLayer18),
123 };
124 static const uint32 mtpLayerMaxSingle = sizeof(mtpLayers) / sizeof(mtpLayers[0]);
125 
126 using MTPint = tl::int_type;
127 
MTP_int(int32 v)128 inline MTPint MTP_int(int32 v) {
129 	return tl::make_int(v);
130 }
131 
132 template <typename Flags>
133 using MTPflags = tl::flags_type<Flags>;
134 
135 template <typename T>
MTP_flags(base::flags<T> v)136 inline MTPflags<base::flags<T>> MTP_flags(base::flags<T> v) {
137 	return tl::make_flags(v);
138 }
139 
140 template <typename T, typename = std::enable_if_t<!std::is_same<T, int>::value>>
MTP_flags(T v)141 inline MTPflags<base::flags<T>> MTP_flags(T v) {
142 	return tl::make_flags(v);
143 }
144 
MTP_flags(void (tl::details::zero_flags_helper::*)())145 inline tl::details::zero_flags_helper MTP_flags(void(tl::details::zero_flags_helper::*)()) {
146 	return tl::details::zero_flags_helper();
147 }
148 
149 using MTPlong = tl::long_type;
150 
MTP_long(uint64 v)151 inline MTPlong MTP_long(uint64 v) {
152 	return tl::make_long(v);
153 }
154 
155 using MTPint128 = tl::int128_type;
156 
MTP_int128(uint64 l,uint64 h)157 inline MTPint128 MTP_int128(uint64 l, uint64 h) {
158 	return tl::make_int128(l, h);
159 }
160 
161 using MTPint256 = tl::int256_type;
162 
MTP_int256(const MTPint128 & l,const MTPint128 & h)163 inline MTPint256 MTP_int256(const MTPint128 &l, const MTPint128 &h) {
164 	return tl::make_int256(l, h);
165 }
166 
167 using MTPdouble = tl::double_type;
168 
MTP_double(float64 v)169 inline MTPdouble MTP_double(float64 v) {
170 	return tl::make_double(v);
171 }
172 
173 using MTPstring = tl::string_type;
174 using MTPbytes = tl::bytes_type;
175 
MTP_string(const std::string & v)176 inline MTPstring MTP_string(const std::string &v) {
177 	return tl::make_string(v);
178 }
MTP_string(const QString & v)179 inline MTPstring MTP_string(const QString &v) {
180 	return tl::make_string(v);
181 }
MTP_string(const char * v)182 inline MTPstring MTP_string(const char *v) {
183 	return tl::make_string(v);
184 }
MTP_string()185 inline MTPstring MTP_string() {
186 	return tl::make_string();
187 }
188 MTPstring MTP_string(const QByteArray &v) = delete;
189 
MTP_bytes(const QByteArray & v)190 inline MTPbytes MTP_bytes(const QByteArray &v) {
191 	return tl::make_bytes(v);
192 }
MTP_bytes(QByteArray && v)193 inline MTPbytes MTP_bytes(QByteArray &&v) {
194 	return tl::make_bytes(std::move(v));
195 }
MTP_bytes()196 inline MTPbytes MTP_bytes() {
197 	return tl::make_bytes();
198 }
MTP_bytes(bytes::const_span buffer)199 inline MTPbytes MTP_bytes(bytes::const_span buffer) {
200 	return tl::make_bytes(buffer);
201 }
MTP_bytes(const bytes::vector & buffer)202 inline MTPbytes MTP_bytes(const bytes::vector &buffer) {
203 	return tl::make_bytes(buffer);
204 }
205 
qs(const MTPstring & v)206 inline QString qs(const MTPstring &v) {
207 	return tl::utf16(v);
208 }
209 
qs(const QByteArray & v)210 inline QString qs(const QByteArray &v) {
211 	return tl::utf16(v);
212 }
213 
qba(const MTPstring & v)214 inline QByteArray qba(const MTPstring &v) {
215 	return tl::utf8(v);
216 }
217 
218 template <typename T>
219 using MTPvector = tl::vector_type<T>;
220 
221 template <typename T>
MTP_vector(uint32 count)222 inline MTPvector<T> MTP_vector(uint32 count) {
223 	return tl::make_vector<T>(count);
224 }
225 template <typename T>
MTP_vector(uint32 count,const T & value)226 inline MTPvector<T> MTP_vector(uint32 count, const T &value) {
227 	return tl::make_vector<T>(count, value);
228 }
229 template <typename T>
MTP_vector(const QVector<T> & v)230 inline MTPvector<T> MTP_vector(const QVector<T> &v) {
231 	return tl::make_vector<T>(v);
232 }
233 template <typename T>
MTP_vector(QVector<T> && v)234 inline MTPvector<T> MTP_vector(QVector<T> &&v) {
235 	return tl::make_vector<T>(std::move(v));
236 }
237 template <typename T>
MTP_vector()238 inline MTPvector<T> MTP_vector() {
239 	return tl::make_vector<T>();
240 }
241 
242 namespace tl {
243 
244 template <typename Accumulator>
245 struct Writer;
246 
247 template <typename Prime>
248 struct Reader;
249 
250 template <>
251 struct Writer<mtpBuffer> {
252 	static void PutBytes(mtpBuffer &to, const void *bytes, uint32 count) {
253 		constexpr auto kPrime = sizeof(uint32);
254 		const auto primes = (count / kPrime) + (count % kPrime ? 1 : 0);
255 		const auto size = to.size();
256 		to.resize(size + primes);
257 		memcpy(to.data() + size, bytes, count);
258 	}
259 	static void Put(mtpBuffer &to, uint32 value) {
260 		to.push_back(mtpPrime(value));
261 	}
262 };
263 
264 template <>
265 struct Reader<mtpPrime> final {
266 	[[nodiscard]] static bool HasBytes(
267 			uint32 count,
268 			const mtpPrime *from,
269 			const mtpPrime *end) {
270 		constexpr auto kPrime = sizeof(uint32);
271 		const auto primes = (count / kPrime) + (count % kPrime ? 1 : 0);
272 		return (end - from) >= primes;
273 	}
274 	static void GetBytes(
275 			void *bytes,
276 			uint32 count,
277 			const mtpPrime *&from,
278 			const mtpPrime *end) {
279 		Expects(HasBytes(count, from, end));
280 
281 		constexpr auto kPrime = sizeof(uint32);
282 		const auto primes = (count / kPrime) + (count % kPrime ? 1 : 0);
283 		memcpy(bytes, from, count);
284 		from += primes;
285 	}
286 	[[nodiscard]] static bool Has(
287 			uint32 primes,
288 			const mtpPrime *from,
289 			const mtpPrime *end) {
290 		return (end - from) >= primes;
291 	}
292 	[[nodiscard]] static uint32 Get(const mtpPrime *&from, const mtpPrime *end) {
293 		Expects(from < end);
294 
295 		return uint32(*from++);
296 	}
297 };
298 
299 } // namespace tl
300