1 #include "EncryptedConnection.h"
2 
3 #include "CryptoHelper.h"
4 #include "rtc_base/logging.h"
5 #include "rtc_base/byte_buffer.h"
6 #include "rtc_base/time_utils.h"
7 
8 namespace tgcalls {
9 namespace {
10 
11 constexpr auto kSingleMessagePacketSeqBit = (uint32_t(1) << 31);
12 constexpr auto kMessageRequiresAckSeqBit = (uint32_t(1) << 30);
13 constexpr auto kMaxAllowedCounter = std::numeric_limits<uint32_t>::max()
14     & ~kSingleMessagePacketSeqBit
15     & ~kMessageRequiresAckSeqBit;
16 
17 static_assert(kMaxAllowedCounter < kSingleMessagePacketSeqBit, "bad");
18 static_assert(kMaxAllowedCounter < kMessageRequiresAckSeqBit, "bad");
19 
20 constexpr auto kAckSerializedSize = sizeof(uint32_t) + sizeof(uint8_t);
21 constexpr auto kNotAckedMessagesLimit = 64 * 1024;
22 constexpr auto kMaxIncomingPacketSize = 128 * 1024; // don't try decrypting more
23 constexpr auto kKeepIncomingCountersCount = 64;
24 constexpr auto kMaxFullPacketSize = 1500; // IP_PACKET_SIZE from webrtc.
25 
26 // Max seen turn_overhead is around 36.
27 constexpr auto kMaxOuterPacketSize = kMaxFullPacketSize - 48;
28 
29 constexpr auto kMaxSignalingPacketSize = 16 * 1024;
30 
31 constexpr auto kServiceCauseAcks = 1;
32 constexpr auto kServiceCauseResend = 2;
33 
34 static constexpr uint8_t kAckId = uint8_t(-1);
35 static constexpr uint8_t kEmptyId = uint8_t(-2);
36 
AppendSeq(rtc::CopyOnWriteBuffer & buffer,uint32_t seq)37 void AppendSeq(rtc::CopyOnWriteBuffer &buffer, uint32_t seq) {
38     const auto bytes = rtc::HostToNetwork32(seq);
39     buffer.AppendData(reinterpret_cast<const char*>(&bytes), sizeof(bytes));
40 }
41 
WriteSeq(void * bytes,uint32_t seq)42 void WriteSeq(void *bytes, uint32_t seq) {
43     *reinterpret_cast<uint32_t*>(bytes) = rtc::HostToNetwork32(seq);
44 }
45 
ReadSeq(const void * bytes)46 uint32_t ReadSeq(const void *bytes) {
47     return rtc::NetworkToHost32(*reinterpret_cast<const uint32_t*>(bytes));
48 }
49 
CounterFromSeq(uint32_t seq)50 uint32_t CounterFromSeq(uint32_t seq) {
51     return seq & ~kSingleMessagePacketSeqBit & ~kMessageRequiresAckSeqBit;
52 }
53 
LogError(const char * message,const std::string & additional=std::string ())54 absl::nullopt_t LogError(
55         const char *message,
56         const std::string &additional = std::string()) {
57     RTC_LOG(LS_ERROR) << "ERROR! " << message << additional;
58     return absl::nullopt;
59 }
60 
ConstTimeIsDifferent(const void * a,const void * b,size_t size)61 bool ConstTimeIsDifferent(const void *a, const void *b, size_t size) {
62     auto ca = reinterpret_cast<const char*>(a);
63     auto cb = reinterpret_cast<const char*>(b);
64     volatile auto different = false;
65     for (const auto ce = ca + size; ca != ce; ++ca, ++cb) {
66         different |= (*ca != *cb);
67     }
68     return different;
69 }
70 
71 } // namespace
72 
EncryptedConnection(Type type,const EncryptionKey & key,std::function<void (int delayMs,int cause)> requestSendService)73 EncryptedConnection::EncryptedConnection(
74     Type type,
75     const EncryptionKey &key,
76     std::function<void(int delayMs, int cause)> requestSendService) :
77 _type(type),
78 _key(key),
79 _delayIntervals(DelayIntervalsByType(type)),
80 _requestSendService(std::move(requestSendService)) {
81     assert(_key.value != nullptr);
82 }
83 
encryptRawPacket(rtc::CopyOnWriteBuffer const & buffer)84 absl::optional<rtc::CopyOnWriteBuffer> EncryptedConnection::encryptRawPacket(rtc::CopyOnWriteBuffer const &buffer) {
85     auto seq = ++_counter;
86 
87     rtc::ByteBufferWriter writer;
88     writer.WriteUInt32(seq);
89 
90     auto result = rtc::CopyOnWriteBuffer();
91     result.AppendData(writer.Data(), writer.Length());
92 
93     result.AppendData(buffer);
94 
95     auto encryptedPacket = encryptPrepared(result);
96 
97     rtc::CopyOnWriteBuffer encryptedBuffer;
98     encryptedBuffer.AppendData(encryptedPacket.bytes.data(), encryptedPacket.bytes.size());
99     return encryptedBuffer;
100 }
101 
decryptRawPacket(rtc::CopyOnWriteBuffer const & buffer)102 absl::optional<rtc::CopyOnWriteBuffer> EncryptedConnection::decryptRawPacket(rtc::CopyOnWriteBuffer const &buffer) {
103     if (buffer.size() < 21 || buffer.size() > kMaxIncomingPacketSize) {
104         return absl::nullopt;
105     }
106 
107     const auto x = (_key.isOutgoing ? 8 : 0) + (_type == Type::Signaling ? 128 : 0);
108     const auto key = _key.value->data();
109     const auto msgKey = reinterpret_cast<const uint8_t*>(buffer.data());
110     const auto encryptedData = msgKey + 16;
111     const auto dataSize = buffer.size() - 16;
112 
113     auto aesKeyIv = PrepareAesKeyIv(key, msgKey, x);
114 
115     auto decryptionBuffer = rtc::Buffer(dataSize);
116     AesProcessCtr(
117         MemorySpan{ encryptedData, dataSize },
118         decryptionBuffer.data(),
119         std::move(aesKeyIv));
120 
121     const auto msgKeyLarge = ConcatSHA256(
122         MemorySpan{ key + 88 + x, 32 },
123         MemorySpan{ decryptionBuffer.data(), decryptionBuffer.size() });
124     if (ConstTimeIsDifferent(msgKeyLarge.data() + 8, msgKey, 16)) {
125         return absl::nullopt;
126     }
127 
128     const auto incomingSeq = ReadSeq(decryptionBuffer.data());
129     const auto incomingCounter = CounterFromSeq(incomingSeq);
130     if (!registerIncomingCounter(incomingCounter)) {
131         // We've received that packet already.
132         return absl::nullopt;
133     }
134 
135     rtc::CopyOnWriteBuffer resultBuffer;
136     resultBuffer.AppendData(decryptionBuffer.data() + 4, decryptionBuffer.size() - 4);
137     return resultBuffer;
138 }
139 
prepareForSending(const Message & message)140 auto EncryptedConnection::prepareForSending(const Message &message)
141 -> absl::optional<EncryptedPacket> {
142     const auto messageRequiresAck = absl::visit([](const auto &data) {
143         return std::decay_t<decltype(data)>::kRequiresAck;
144     }, message.data);
145 
146     // If message requires ack, then we can't serialize it as a single
147     // message packet, because later it may be sent as a part of big packet.
148     const auto singleMessagePacket = !haveAdditionalMessages() && !messageRequiresAck;
149     const auto maybeSeq = computeNextSeq(messageRequiresAck, singleMessagePacket);
150     if (!maybeSeq) {
151         return absl::nullopt;
152     }
153     const auto seq = *maybeSeq;
154     auto serialized = SerializeMessageWithSeq(message, seq, singleMessagePacket);
155     if (!enoughSpaceInPacket(serialized, 0)) {
156         return LogError("Too large packet: ", std::to_string(serialized.size()));
157     }
158     const auto notYetAckedCopy = messageRequiresAck
159         ? serialized
160         : rtc::CopyOnWriteBuffer();
161     if (!messageRequiresAck) {
162         appendAdditionalMessages(serialized);
163         return encryptPrepared(serialized);
164     }
165     const auto type = uint8_t(serialized.cdata()[4]);
166     const auto sendEnqueued = !_myNotYetAckedMessages.empty();
167     if (sendEnqueued) {
168         // All requiring ack messages should always be sent in order within
169         // one packet, starting with the least not-yet-acked one.
170         // So if we still have those, we send an empty message with all
171         // requiring ack messages that will fit in correct order.
172         RTC_LOG(LS_INFO) << logHeader()
173             << "Enqueue SEND:type" << type << "#" << CounterFromSeq(seq);
174     } else {
175         RTC_LOG(LS_INFO) << logHeader()
176             << "Add SEND:type" << type << "#" << CounterFromSeq(seq);
177         appendAdditionalMessages(serialized);
178     }
179     _myNotYetAckedMessages.push_back({ notYetAckedCopy, rtc::TimeMillis() });
180     if (!sendEnqueued) {
181         return encryptPrepared(serialized);
182     }
183     for (auto &queued : _myNotYetAckedMessages) {
184         queued.lastSent = 0;
185     }
186     return prepareForSendingService(0);
187 }
188 
prepareForSendingService(int cause)189 auto EncryptedConnection::prepareForSendingService(int cause)
190 -> absl::optional<EncryptedPacket> {
191     if (cause == kServiceCauseAcks) {
192         _sendAcksTimerActive = false;
193     } else if (cause == kServiceCauseResend) {
194         _resendTimerActive = false;
195     }
196     if (!haveAdditionalMessages()) {
197         return absl::nullopt;
198     }
199     const auto messageRequiresAck = false;
200     const auto singleMessagePacket = false;
201     const auto seq = computeNextSeq(messageRequiresAck, singleMessagePacket);
202     if (!seq) {
203         return absl::nullopt;
204     }
205     auto serialized = SerializeEmptyMessageWithSeq(*seq);
206     assert(enoughSpaceInPacket(serialized, 0));
207 
208     RTC_LOG(LS_INFO) << logHeader()
209         << "SEND:empty#" << CounterFromSeq(*seq);
210 
211     appendAdditionalMessages(serialized);
212     return encryptPrepared(serialized);
213 }
214 
haveAdditionalMessages() const215 bool EncryptedConnection::haveAdditionalMessages() const {
216     return !_myNotYetAckedMessages.empty() || !_acksToSendSeqs.empty();
217 }
218 
computeNextSeq(bool messageRequiresAck,bool singleMessagePacket)219 absl::optional<uint32_t> EncryptedConnection::computeNextSeq(
220         bool messageRequiresAck,
221         bool singleMessagePacket) {
222     if (messageRequiresAck && _myNotYetAckedMessages.size() >= kNotAckedMessagesLimit) {
223         return LogError("Too many not ACKed messages.");
224     } else if (_counter == kMaxAllowedCounter) {
225         return LogError("Outgoing packet limit reached.");
226     }
227 
228     return (++_counter)
229         | (singleMessagePacket ? kSingleMessagePacketSeqBit : 0)
230         | (messageRequiresAck ? kMessageRequiresAckSeqBit : 0);
231 }
232 
packetLimit() const233 size_t EncryptedConnection::packetLimit() const {
234     switch (_type) {
235         case Type::Signaling:
236             return kMaxSignalingPacketSize;
237         default:
238             return kMaxOuterPacketSize;
239     }
240 }
241 
enoughSpaceInPacket(const rtc::CopyOnWriteBuffer & buffer,size_t amount) const242 bool EncryptedConnection::enoughSpaceInPacket(const rtc::CopyOnWriteBuffer &buffer, size_t amount) const {
243     const auto limit = packetLimit();
244     return (amount < limit)
245         && (16 + buffer.size() + amount <= limit);
246 }
247 
appendAcksToSend(rtc::CopyOnWriteBuffer & buffer)248 void EncryptedConnection::appendAcksToSend(rtc::CopyOnWriteBuffer &buffer) {
249     auto i = _acksToSendSeqs.begin();
250     while ((i != _acksToSendSeqs.end())
251         && enoughSpaceInPacket(
252             buffer,
253             kAckSerializedSize)) {
254 
255         RTC_LOG(LS_INFO) << logHeader()
256             << "Add ACK#" << CounterFromSeq(*i);
257 
258         AppendSeq(buffer, *i);
259         buffer.AppendData(&kAckId, 1);
260         ++i;
261     }
262     _acksToSendSeqs.erase(_acksToSendSeqs.begin(), i);
263     for (const auto seq : _acksToSendSeqs) {
264         RTC_LOG(LS_INFO) << logHeader()
265             << "Skip ACK#" << CounterFromSeq(seq)
266             << " (no space, length: " << kAckSerializedSize << ", already: " << buffer.size() << ")";
267     }
268 }
269 
fullNotAckedLength() const270 size_t EncryptedConnection::fullNotAckedLength() const {
271     assert(_myNotYetAckedMessages.size() < kNotAckedMessagesLimit);
272 
273     auto result = size_t();
274     for (const auto &message : _myNotYetAckedMessages) {
275         result += message.data.size();
276     }
277     return result;
278 }
279 
appendAdditionalMessages(rtc::CopyOnWriteBuffer & buffer)280 void EncryptedConnection::appendAdditionalMessages(rtc::CopyOnWriteBuffer &buffer) {
281     appendAcksToSend(buffer);
282 
283     if (_myNotYetAckedMessages.empty()) {
284         return;
285     }
286 
287     const auto now = rtc::TimeMillis();
288     for (auto &resending : _myNotYetAckedMessages) {
289         const auto sent = resending.lastSent;
290         const auto when = sent
291             ? (sent + _delayIntervals.minDelayBeforeMessageResend)
292             : 0;
293 
294         assert(resending.data.size() >= 5);
295         const auto counter = CounterFromSeq(ReadSeq(resending.data.data()));
296         const auto type = uint8_t(resending.data.data()[4]);
297         if (when > now) {
298             RTC_LOG(LS_INFO) << logHeader()
299                 << "Skip RESEND:type" << type << "#" << counter
300                 << " (wait " << (when - now) << "ms).";
301             break;
302         } else if (enoughSpaceInPacket(buffer, resending.data.size())) {
303             RTC_LOG(LS_INFO) << logHeader()
304                 << "Add RESEND:type" << type << "#" << counter;
305             buffer.AppendData(resending.data);
306             resending.lastSent = now;
307         } else {
308             RTC_LOG(LS_INFO) << logHeader()
309                 << "Skip RESEND:type" << type << "#" << counter
310                 << " (no space, length: " << resending.data.size() << ", already: " << buffer.size() << ")";
311             break;
312         }
313     }
314     if (!_resendTimerActive) {
315         _resendTimerActive = true;
316         _requestSendService(
317             _delayIntervals.maxDelayBeforeMessageResend,
318             kServiceCauseResend);
319     }
320 }
321 
encryptPrepared(const rtc::CopyOnWriteBuffer & buffer)322 auto EncryptedConnection::encryptPrepared(const rtc::CopyOnWriteBuffer &buffer)
323 -> EncryptedPacket {
324     auto result = EncryptedPacket();
325     result.counter = CounterFromSeq(ReadSeq(buffer.data()));
326     result.bytes.resize(16 + buffer.size());
327 
328     const auto x = (_key.isOutgoing ? 0 : 8) + (_type == Type::Signaling ? 128 : 0);
329     const auto key = _key.value->data();
330 
331     const auto msgKeyLarge = ConcatSHA256(
332         MemorySpan{ key + 88 + x, 32 },
333         MemorySpan{ buffer.data(), buffer.size() });
334     const auto msgKey = result.bytes.data();
335     memcpy(msgKey, msgKeyLarge.data() + 8, 16);
336 
337     auto aesKeyIv = PrepareAesKeyIv(key, msgKey, x);
338 
339     AesProcessCtr(
340         MemorySpan{ buffer.data(), buffer.size() },
341         result.bytes.data() + 16,
342         std::move(aesKeyIv));
343 
344     return result;
345 }
346 
registerIncomingCounter(uint32_t incomingCounter)347 bool EncryptedConnection::registerIncomingCounter(uint32_t incomingCounter) {
348     auto &list = _largestIncomingCounters;
349 
350     const auto position = std::lower_bound(list.begin(), list.end(), incomingCounter);
351     const auto largest = list.empty() ? 0 : list.back();
352     if (position != list.end() && *position == incomingCounter) {
353         // The packet is in the list already.
354         return false;
355     } else if (incomingCounter + kKeepIncomingCountersCount <= largest) {
356         // The packet is too old.
357         return false;
358     }
359     const auto eraseTill = std::find_if(list.begin(), list.end(), [&](uint32_t counter) {
360         return (counter + kKeepIncomingCountersCount > incomingCounter);
361     });
362     const auto eraseCount = eraseTill - list.begin();
363     const auto positionIndex = (position - list.begin()) - eraseCount;
364     list.erase(list.begin(), eraseTill);
365 
366     assert(positionIndex >= 0 && positionIndex <= list.size());
367     list.insert(list.begin() + positionIndex, incomingCounter);
368     return true;
369 }
370 
handleIncomingPacket(const char * bytes,size_t size)371 auto EncryptedConnection::handleIncomingPacket(const char *bytes, size_t size)
372 -> absl::optional<DecryptedPacket> {
373     if (size < 21 || size > kMaxIncomingPacketSize) {
374         return LogError("Bad incoming packet size: ", std::to_string(size));
375     }
376 
377     const auto x = (_key.isOutgoing ? 8 : 0) + (_type == Type::Signaling ? 128 : 0);
378     const auto key = _key.value->data();
379     const auto msgKey = reinterpret_cast<const uint8_t*>(bytes);
380     const auto encryptedData = msgKey + 16;
381     const auto dataSize = size - 16;
382 
383     auto aesKeyIv = PrepareAesKeyIv(key, msgKey, x);
384 
385     auto decryptionBuffer = rtc::Buffer(dataSize);
386     AesProcessCtr(
387         MemorySpan{ encryptedData, dataSize },
388         decryptionBuffer.data(),
389         std::move(aesKeyIv));
390 
391     const auto msgKeyLarge = ConcatSHA256(
392         MemorySpan{ key + 88 + x, 32 },
393         MemorySpan{ decryptionBuffer.data(), decryptionBuffer.size() });
394     if (ConstTimeIsDifferent(msgKeyLarge.data() + 8, msgKey, 16)) {
395         return LogError("Bad incoming data hash.");
396     }
397 
398     const auto incomingSeq = ReadSeq(decryptionBuffer.data());
399     const auto incomingCounter = CounterFromSeq(incomingSeq);
400     if (!registerIncomingCounter(incomingCounter)) {
401         // We've received that packet already.
402         return LogError("Already handled packet received.", std::to_string(incomingCounter));
403     }
404     return processPacket(decryptionBuffer, incomingSeq);
405 }
406 
processPacket(const rtc::Buffer & fullBuffer,uint32_t packetSeq)407 auto EncryptedConnection::processPacket(
408     const rtc::Buffer &fullBuffer,
409     uint32_t packetSeq)
410 -> absl::optional<DecryptedPacket> {
411     assert(fullBuffer.size() >= 5);
412 
413     auto additionalMessage = false;
414     auto firstMessageRequiringAck = true;
415     auto newRequiringAckReceived = false;
416 
417     auto currentSeq = packetSeq;
418     auto currentCounter = CounterFromSeq(currentSeq);
419     rtc::ByteBufferReader reader(
420         reinterpret_cast<const char*>(fullBuffer.data() + 4), // Skip seq.
421         fullBuffer.size() - 4);
422 
423     auto result = absl::optional<DecryptedPacket>();
424     while (true) {
425         const auto type = uint8_t(*reader.Data());
426         const auto singleMessagePacket = ((currentSeq & kSingleMessagePacketSeqBit) != 0);
427         if (singleMessagePacket && additionalMessage) {
428             return LogError("Single message packet bit in not first message.");
429         }
430 
431         if (type == kEmptyId) {
432             if (additionalMessage) {
433                 return LogError("Empty message should be only the first one in the packet.");
434             }
435             RTC_LOG(LS_INFO) << logHeader()
436                 << "Got RECV:empty" << "#" << currentCounter;
437             reader.Consume(1);
438         } else if (type == kAckId) {
439             if (!additionalMessage) {
440                 return LogError("Ack message must not be the first one in the packet.");
441             }
442             ackMyMessage(currentSeq);
443             reader.Consume(1);
444         } else if (auto message = DeserializeMessage(reader, singleMessagePacket)) {
445             const auto messageRequiresAck = ((currentSeq & kMessageRequiresAckSeqBit) != 0);
446             const auto skipMessage = messageRequiresAck
447                 ? !registerSentAck(currentCounter, firstMessageRequiringAck)
448                 : (additionalMessage && !registerIncomingCounter(currentCounter));
449             if (messageRequiresAck) {
450                 firstMessageRequiringAck = false;
451                 if (!skipMessage) {
452                     newRequiringAckReceived = true;
453                 }
454                 sendAckPostponed(currentSeq);
455                 RTC_LOG(LS_INFO) << logHeader()
456                     << (skipMessage ? "Repeated RECV:type" : "Got RECV:type") << type << "#" << currentCounter;
457             }
458             if (!skipMessage) {
459                 appendReceivedMessage(result, std::move(*message), currentSeq);
460             }
461         } else {
462             return LogError("Could not parse message from packet, type: ", std::to_string(type));
463         }
464         if (!reader.Length()) {
465             break;
466         } else if (singleMessagePacket) {
467             return LogError("Single message didn't fill the entire packet.");
468         } else if (reader.Length() < 5) {
469             return LogError("Bad remaining data size: ", std::to_string(reader.Length()));
470         }
471         const auto success = reader.ReadUInt32(&currentSeq);
472         assert(success);
473         (void)success;
474         currentCounter = CounterFromSeq(currentSeq);
475 
476         additionalMessage = true;
477     }
478 
479     if (!_acksToSendSeqs.empty()) {
480         if (newRequiringAckReceived) {
481             _requestSendService(0, 0);
482         } else if (!_sendAcksTimerActive) {
483             _sendAcksTimerActive = true;
484             _requestSendService(
485                 _delayIntervals.maxDelayBeforeAckResend,
486                 kServiceCauseAcks);
487         }
488     }
489 
490     return result;
491 }
492 
appendReceivedMessage(absl::optional<DecryptedPacket> & to,Message && message,uint32_t incomingSeq)493 void EncryptedConnection::appendReceivedMessage(
494         absl::optional<DecryptedPacket> &to,
495         Message &&message,
496         uint32_t incomingSeq) {
497     auto decrypted = DecryptedMessage{
498         std::move(message),
499         CounterFromSeq(incomingSeq)
500     };
501     if (to) {
502         to->additional.push_back(std::move(decrypted));
503     } else {
504         to = DecryptedPacket{ std::move(decrypted) };
505     }
506 }
507 
logHeader() const508 const char *EncryptedConnection::logHeader() const {
509     return (_type == Type::Signaling) ? "(signaling) " : "(transport) ";
510 }
511 
registerSentAck(uint32_t counter,bool firstInPacket)512 bool EncryptedConnection::registerSentAck(uint32_t counter, bool firstInPacket) {
513     auto &list = _acksSentCounters;
514 
515     const auto position = std::lower_bound(list.begin(), list.end(), counter);
516     const auto already = (position != list.end()) && (*position == counter);
517 
518     const auto was = list;
519     if (firstInPacket) {
520         list.erase(list.begin(), position);
521         if (!already) {
522             list.insert(list.begin(), counter);
523         }
524     } else if (!already) {
525         list.insert(position, counter);
526     }
527     return !already;
528 }
529 
sendAckPostponed(uint32_t incomingSeq)530 void EncryptedConnection::sendAckPostponed(uint32_t incomingSeq) {
531     auto &list = _acksToSendSeqs;
532     const auto already = std::find(list.begin(), list.end(), incomingSeq);
533     if (already == list.end()) {
534         list.push_back(incomingSeq);
535     }
536 }
537 
ackMyMessage(uint32_t seq)538 void EncryptedConnection::ackMyMessage(uint32_t seq) {
539     auto type = uint8_t(0);
540     auto &list = _myNotYetAckedMessages;
541     for (auto i = list.begin(), e = list.end(); i != e; ++i) {
542         assert(i->data.size() >= 5);
543         if (ReadSeq(i->data.cdata()) == seq) {
544             type = uint8_t(i->data.cdata()[4]);
545             list.erase(i);
546             break;
547         }
548     }
549     RTC_LOG(LS_INFO) << logHeader()
550         << (type ? "Got ACK:type" + std::to_string(type) + "#" : "Repeated ACK#")
551         << CounterFromSeq(seq);
552 }
553 
DelayIntervalsByType(Type type)554 auto EncryptedConnection::DelayIntervalsByType(Type type) -> DelayIntervals {
555     auto result = DelayIntervals();
556     const auto signaling = (type == Type::Signaling);
557 
558     // Don't resend faster than min delay even if we have a packet we can attach to.
559     result.minDelayBeforeMessageResend = signaling ? 3000 : 300;
560 
561     // When max delay elapsed we resend anyway, in a dedicated packet.
562     result.maxDelayBeforeMessageResend = signaling ? 5000 : 1000;
563     result.maxDelayBeforeAckResend = signaling ? 5000 : 1000;
564 
565     return result;
566 }
567 
SerializeEmptyMessageWithSeq(uint32_t seq)568 rtc::CopyOnWriteBuffer EncryptedConnection::SerializeEmptyMessageWithSeq(uint32_t seq) {
569     auto result = rtc::CopyOnWriteBuffer(5);
570     auto bytes = result.MutableData();
571     WriteSeq(bytes, seq);
572     bytes[4] = kEmptyId;
573     return result;
574 }
575 
576 } // namespace tgcalls
577