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_dc_options.h"
11 #include "mtproto/mtproto_proxy_data.h"
12 #include "base/bytes.h"
13 
14 #include <QtCore/QObject>
15 #include <QtCore/QThread>
16 
17 namespace MTP {
18 
19 class Instance;
20 
21 namespace details {
22 
23 struct ConnectionOptions;
24 
25 class AbstractConnection;
26 
27 class ConnectionPointer {
28 public:
29 	ConnectionPointer();
30 	ConnectionPointer(std::nullptr_t);
31 	ConnectionPointer(ConnectionPointer &&other);
32 	ConnectionPointer &operator=(ConnectionPointer &&other);
33 
34 	template <typename ConnectionType, typename ...Args>
New(Args &&...args)35 	static ConnectionPointer New(Args &&...args) {
36 		return ConnectionPointer(new ConnectionType(
37 			std::forward<Args>(args)...
38 		));
39 	}
40 
41 	AbstractConnection *get() const;
42 	void reset(AbstractConnection *value = nullptr);
43 	operator AbstractConnection*() const;
44 	AbstractConnection *operator->() const;
45 	AbstractConnection &operator*() const;
46 	explicit operator bool() const;
47 
48 	~ConnectionPointer();
49 
50 private:
51 	explicit ConnectionPointer(AbstractConnection *value);
52 
53 	AbstractConnection *_value = nullptr;
54 
55 };
56 
57 class AbstractConnection : public QObject {
58 	Q_OBJECT
59 
60 public:
61 	AbstractConnection(QThread *thread, const ProxyData &proxy);
62 	AbstractConnection(const AbstractConnection &other) = delete;
63 	AbstractConnection &operator=(const AbstractConnection &other) = delete;
64 	virtual ~AbstractConnection() = default;
65 
66 	// virtual constructor
67 	[[nodiscard]] static ConnectionPointer Create(
68 		not_null<Instance*> instance,
69 		DcOptions::Variants::Protocol protocol,
70 		QThread *thread,
71 		const bytes::vector &secret,
72 		const ProxyData &proxy);
73 
74 	[[nodiscard]] virtual ConnectionPointer clone(const ProxyData &proxy) = 0;
75 
76 	[[nodiscard]] virtual crl::time pingTime() const = 0;
77 	[[nodiscard]] virtual crl::time fullConnectTimeout() const = 0;
78 	virtual void sendData(mtpBuffer &&buffer) = 0;
79 	virtual void disconnectFromServer() = 0;
80 	virtual void connectToServer(
81 		const QString &ip,
82 		int port,
83 		const bytes::vector &protocolSecret,
84 		int16 protocolDcId,
85 		bool protocolForFiles) = 0;
timedOut()86 	virtual void timedOut() {
87 	}
88 	[[nodiscard]] virtual bool isConnected() const = 0;
usingHttpWait()89 	[[nodiscard]] virtual bool usingHttpWait() {
90 		return false;
91 	}
needHttpWait()92 	[[nodiscard]] virtual bool needHttpWait() {
93 		return false;
94 	}
95 
96 	[[nodiscard]] virtual int32 debugState() const = 0;
97 
98 	[[nodiscard]] virtual QString transport() const = 0;
99 	[[nodiscard]] virtual QString tag() const = 0;
100 
setSentEncryptedWithKeyId(uint64 keyId)101 	void setSentEncryptedWithKeyId(uint64 keyId) {
102 		_sentEncryptedWithKeyId = keyId;
103 	}
sentEncryptedWithKeyId()104 	[[nodiscard]] uint64 sentEncryptedWithKeyId() const {
105 		return _sentEncryptedWithKeyId;
106 	}
107 
108 	using BuffersQueue = std::deque<mtpBuffer>;
received()109 	[[nodiscard]] BuffersQueue &received() {
110 		return _receivedQueue;
111 	}
112 
113 	template <typename Request>
114 	[[nodiscard]] mtpBuffer prepareNotSecurePacket(
115 		const Request &request,
116 		mtpMsgId newId) const;
117 	[[nodiscard]] mtpBuffer prepareSecurePacket(
118 		uint64 keyId,
119 		MTPint128 msgKey,
120 		uint32 size) const;
121 
122 	[[nodiscard]] gsl::span<const mtpPrime> parseNotSecureResponse(
123 		const mtpBuffer &buffer) const;
124 
125 	// Used to emit error(...) with no real code from the server.
126 	static constexpr auto kErrorCodeOther = -499;
127 
128 Q_SIGNALS:
129 	void receivedData();
130 	void receivedSome(); // to stop restart timer
131 
132 	void error(qint32 errorCodebool);
133 
134 	void connected();
135 	void disconnected();
136 
137 	void syncTimeRequest();
138 
139 protected:
140 	BuffersQueue _receivedQueue; // list of received packets, not processed yet
141 	int _pingTime = 0;
142 	ProxyData _proxy;
143 
144 	// first we always send fake MTPReq_pq to see if connection works at all
145 	// we send them simultaneously through TCP/HTTP/IPv4/IPv6 to choose the working one
146 	[[nodiscard]] mtpBuffer preparePQFake(const MTPint128 &nonce) const;
147 	[[nodiscard]] std::optional<MTPResPQ> readPQFakeReply(
148 		const mtpBuffer &buffer) const;
149 
150 private:
151 	[[nodiscard]] uint32 extendedNotSecurePadding() const;
152 
153 	uint64 _sentEncryptedWithKeyId = 0;
154 
155 };
156 
157 template <typename Request>
prepareNotSecurePacket(const Request & request,mtpMsgId newId)158 mtpBuffer AbstractConnection::prepareNotSecurePacket(
159 		const Request &request,
160 		mtpMsgId newId) const {
161 	const auto intsSize = tl::count_length(request) >> 2;
162 	const auto intsPadding = extendedNotSecurePadding();
163 
164 	auto result = mtpBuffer();
165 	constexpr auto kTcpPrefixInts = 2;
166 	constexpr auto kAuthKeyIdInts = 2;
167 	constexpr auto kMessageIdInts = 2;
168 	constexpr auto kMessageLengthInts = 1;
169 	constexpr auto kPrefixInts = kTcpPrefixInts
170 		+ kAuthKeyIdInts
171 		+ kMessageIdInts
172 		+ kMessageLengthInts;
173 	constexpr auto kTcpPostfixInts = 4;
174 
175 	result.reserve(kPrefixInts + intsSize + intsPadding + kTcpPostfixInts);
176 	result.resize(kPrefixInts);
177 
178 	const auto messageId = &result[kTcpPrefixInts + kAuthKeyIdInts];
179 	*reinterpret_cast<mtpMsgId*>(messageId) = newId;
180 
181 	request.write(result);
182 
183 	const auto messageLength = messageId + kMessageIdInts;
184 	*messageLength = (result.size() - kPrefixInts + intsPadding) << 2;
185 
186 	if (intsPadding > 0) {
187 		const auto skipPrimes = result.size();
188 		result.resize(skipPrimes + intsPadding);
189 		const auto skipBytes = skipPrimes * sizeof(mtpPrime);
190 		bytes::set_random(bytes::make_span(result).subspan(skipBytes));
191 	}
192 
193 	return result;
194 }
195 
196 } // namespace details
197 } // namespace MTP
198