фикс reorder для симплекса

This commit is contained in:
Maxim
2026-07-16 15:00:11 +03:00
parent 3b6a56e54c
commit 6294a472cd

View File

@@ -312,20 +312,19 @@ static void rb_force_to(uint32_t to) {
fflush(stdout); fflush(stdout);
} }
// Вызывается ТОЛЬКО на FDD-пути (симплекс пишет в stdout напрямую — там нечего
// переупорядочивать), поэтому досылка по NACK всегда доступна.
static void rb_insert(uint32_t seq, const uint8_t *d, size_t len) { static void rb_insert(uint32_t seq, const uint8_t *d, size_t len) {
if (len > GF_CHUNK) len = GF_CHUNK; // защита в глубину: len берётся из if (len > GF_CHUNK) len = GF_CHUNK; // защита в глубину: len берётся из
// hdr, слот кольца — ровно GF_CHUNK // hdr, слот кольца — ровно GF_CHUNK
if (seq < next_out) return; // уже выведен: дубль ретрансмита if (seq < next_out) return; // уже выведен: дубль ретрансмита
if (seq - next_out >= RB_CAP) { if (seq - next_out >= RB_CAP) {
// Дыра в голове старше окна. С ARQ это не тупик: дропаем новый кадр и // Дыра в голове старше окна: дропаем новый кадр и возвращаем его seq в
// возвращаем его seq в NACK — A дошлёт, когда голова разъедется. Без // NACK — A дошлёт, когда голова разъедется. Схлопнуть окно нельзя: это
// обратного канала досылать некому → схлопываем окно вперёд. // молча потеряло бы кадр, который ARQ ещё способен закрыть.
if (g_fb_fg) { rb_over++;
rb_over++; miss_add_sorted(seq);
miss_add_sorted(seq); return;
return;
}
rb_force_to(seq - RB_CAP + 1);
} }
rbslot_t *s = &rb[seq % RB_CAP]; rbslot_t *s = &rb[seq % RB_CAP];
s->seq = seq; s->seq = seq;
@@ -587,11 +586,19 @@ route:
if (flags & GF_FLAG_MODE) { if (flags & GF_FLAG_MODE) {
gf_seen = 1; gf_seen = 1;
group_route(flags, seq, dec, dec_len, ok); group_route(flags, seq, dec, dec_len, ok);
} else { } else if (ok) {
if (g.active) group_flush(); // TX не мешает режимы, но подстрахуемся if (g.active) group_flush(); // TX не мешает режимы, но подстрахуемся
if (ok) { if (g_fb_fg) {
rb_insert(seq, dec, dec_len); // порядок восстанавливает кольцо: rb_insert(seq, dec, dec_len); // FDD: ретрансмит приходит вне
rb_drain(); // ретрансмит приходит вне очереди rb_drain(); // очереди — порядок держит кольцо
} else {
// Симплекс: ретрансмитов нет, seq всегда растёт — переупорядочивать
// нечего. Кольцо здесь только задержало бы вывод до EOF (дыра стопорит
// next_out, а закрыть её некому). Пишем сразу, как до этапа 3b.
fwrite(dec, 1, dec_len, stdout);
fflush(stdout);
total_bytes += dec_len;
crc_final++;
} }
} }
} }