ARQ включён и для group-FEC. Паритет и ретрансмит перестали быть альтернативами:
GF гасит одиночные потери без задержки, ARQ добирает то, что паритету не по силам
(>2 стираний/группу). Дыру, закрытую паритетом, RX снимает с NACK сам — лишнего
трафика нет.
receiver.c:
- group_route: кадр ложится в кольцо ДО любого bypass. Кольцо — единственный
источник порядка и живёт независимо от сборки групп; иначе ретрансмит закрытой
группы не занял бы свой слот и next_out встал бы на нём навсегда. Паритет
получает слот нулевой длины: тратит seq, но в файл не идёт.
- group_route: bypass для кадра уже закрытой группы (base < g.base, а также
base == g.base при !active — группа финализирована по END). Без него ретрансмит
преждевременно flush-ал активную группу, сбрасывая её стирания, либо «воскрешал»
закрытую с одним элементом.
- group_flush: под FDD пишет в кольцо ТОЛЬКО восстановленные паритетом кадры
(g.fixed) и снимает их seq с NACK — принятые уже в кольце. Симплекс сохраняет
прямой вывод группы: ретрансмитов там нет, переупорядочивать нечего.
- process_end: досрочный group_flush последней группы. Штатно группа закрывается
первым кадром следующей — для последней его не будет, и её восстановление
случилось бы только при выходе потока C, то есть уже после COMPLETE.
- process_end/miss_rebuild: NACK пересобирается из кольца на каждом END. Находка
стресса 3b: miss_add при переполнении MISS_CAP молча терял seq, и вернуть его
было некому (детектор дыр по нему второй раз не срабатывает) — приём заклинивало
насмерть. Кольцо знает точно, каких кадров нет.
- arq_check_complete: критерий единый (next_out == total_seq), временный gf_seen
убран.
transmitter.c: g_arq_on = 1 безусловно при -F; arq_service в GF-цикле как в legacy.