1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-27 03:14:39 +01:00

Merge remote-tracking branch 'origin/v8' into v8

This commit is contained in:
Mahdi 2023-09-24 15:57:06 +03:30
commit 973b38c849
2 changed files with 58 additions and 21 deletions

View File

@ -73,10 +73,7 @@ final class SecretFeedLoop extends Loop
$this->incomingUpdates = []; $this->incomingUpdates = [];
foreach ($updates as $update) { foreach ($updates as $update) {
try { try {
if (!$this->secretChat->handleEncryptedUpdate($update)) { $this->secretChat->handleEncryptedUpdate($update);
$this->logger->logger("Secret chat deleted, exiting $this...");
return self::STOP;
}
} catch (SecurityException $e) { } catch (SecurityException $e) {
$this->logger->logger("Secret chat deleted, exiting $this..."); $this->logger->logger("Secret chat deleted, exiting $this...");
throw $e; throw $e;

View File

@ -490,17 +490,20 @@ final class SecretChatController implements Stringable
unset($message['message']['bytes']); unset($message['message']['bytes']);
$message['message']['decrypted_message'] = $deserialized; $message['message']['decrypted_message'] = $deserialized;
if ($deserialized['_'] === 'decryptedMessageLayer') { if ($message['message']['decrypted_message']['_'] === 'decryptedMessageLayer') {
if (($this->checkSecretOutSeqNo($deserialized['out_seq_no'])) foreach ($this->checkSecretOutSeqNo($message) as $message) {
&& ($this->checkSecretInSeqNo($deserialized['in_seq_no']))) { $this->checkSecretInSeqNo(
$this->incoming[$this->in_seq_no++] = $message['message']; $message['message']['decrypted_message']['in_seq_no']
if ($deserialized['layer'] >= 46 && $deserialized['layer'] > $this->remoteLayer) { );
$this->remoteLayer = $deserialized['layer']; $layer = $message['message']['decrypted_message']['layer'];
if ($layer >= 46 && $layer > $this->remoteLayer) {
$this->remoteLayer = $layer;
if (\time() - $this->public->created > 15) { if (\time() - $this->public->created > 15) {
$this->notifyLayer(); $this->notifyLayer();
} }
} }
$message['message']['decrypted_message'] = $deserialized['message']; $message['message']['decrypted_message'] = $message['message']['decrypted_message']['message'];
$this->incoming[$this->in_seq_no++] = $message;
$this->handleDecryptedUpdate($message); $this->handleDecryptedUpdate($message);
} }
} else { } else {
@ -559,7 +562,7 @@ final class SecretChatController implements Stringable
return $message_data; return $message_data;
} }
private function checkSecretInSeqNo(int $seqno): bool private function checkSecretInSeqNo(int $seqno): void
{ {
$seqno = ($seqno - $this->out_seq_no_base) >> 1; $seqno = ($seqno - $this->out_seq_no_base) >> 1;
if ($seqno < $this->remote_in_seq_no) { if ($seqno < $this->remote_in_seq_no) {
@ -573,26 +576,63 @@ final class SecretChatController implements Stringable
throw new SecurityException('in_seq_no is too big'); throw new SecurityException('in_seq_no is too big');
} }
$this->remote_in_seq_no = $seqno; $this->remote_in_seq_no = $seqno;
return true;
} }
private function checkSecretOutSeqNo(int $seqno): bool
private ?int $gapEnd = null;
private ?int $gapQueueSeq = null;
private array $gapQueue = [];
private function checkSecretOutSeqNo(array $message): \Generator
{ {
$seqno = $message['message']['decrypted_message']['out_seq_no'];
$seqno = ($seqno - $this->in_seq_no_base) >> 1; $seqno = ($seqno - $this->in_seq_no_base) >> 1;
$C_plus_one = $this->in_seq_no; $C_plus_one = $this->in_seq_no;
//$this->API->logger->logger($C, $seqno); //$this->API->logger->logger($C, $seqno);
if ($seqno < $C_plus_one) { if ($seqno < $C_plus_one) {
// <= C // <= C
$this->API->logger->logger('WARNING: dropping repeated message with seqno '.$seqno); $this->API->logger->logger("WARNING: dropping repeated message in $this with seqno $seqno");
return false; return;
} }
if ($seqno > $C_plus_one) { if ($seqno > $C_plus_one) {
// > C+1 // > C+1
$this->API->logger->logger("Discarding $this, out_seq_no gap detected: ($seqno > $C_plus_one)", Logger::LEVEL_FATAL); if ($this->gapEnd !== null) {
$this->discard(); // Already recovering gap...
// TODO request resending $C_plus_one = $this->gapQueueSeq;
throw new SecurityException('WARNING: out_seq_no gap detected ('.$seqno.' > '.$C_plus_one.')!'); if ($seqno < $C_plus_one) {
// <= C
$this->API->logger->logger("WARNING: dropping repeated message in $this with seqno $seqno while recovering gaps");
return;
}
if ($seqno > $C_plus_one) {
// > C+1
$this->API->logger->logger("Discarding $this because out_seq_no gap detected: ($seqno > $C_plus_one), but already recovering gap!", Logger::LEVEL_FATAL);
$this->discard();
throw new SecurityException("Additional out_seq_no gap detected!");
}
$this->gapQueue []= $message;
$this->gapQueueSeq = $seqno+1;
return;
}
$this->API->logger->logger("Requesting resending in $this, out_seq_no gap detected: ($seqno > $C_plus_one)", Logger::LEVEL_FATAL);
$this->gapEnd = $seqno-1;
$this->gapQueue = [$message];
$this->gapQueueSeq = $seqno+1;
$this->API->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $this->id, 'message' => ['_' => 'decryptedMessageService', 'action' => [
'_' => 'decryptedMessageActionResend',
'start_seq_no' => $this->in_seq_no,
'end_seq_no' => $this->gapEnd
]]]);
return;
}
yield $message;
if ($seqno === $this->gapEnd) {
$queue = $this->gapQueue;
$this->gapQueue = [];
$this->gapQueueSeq = null;
$this->gapEnd = null;
yield from $queue;
} }
return true;
} }
private function generateSecretInSeqNo(): int private function generateSecretInSeqNo(): int
{ {