Record completed stream header audit and align native guide
This commit is contained in:
1 parent
de535e1713
commit
409d9f3ca9
2 files changed
+109
-28
No files matched your search
+47
-27
@@ -1,12 +1,15 @@
|
||||
Модуль стриминга. Техническое задание, этап 1.
|
||||
|
||||
Статус аудита 26.10.2026: сверка завершена для stream.h, stream_proto.h,
|
||||
stream_block.h, stream_source.h, stream_media.h и stream_optimizer.h; остальные разделы проверены частично.
|
||||
Статус аудита 26.10.2026: сверены все 18 заголовков src/stream с полными
|
||||
реализациями (15 C и playback_audio.cpp). Уточнены API, поля, владение,
|
||||
сроки и результаты операций; последние правки заголовков не меняют C-токены.
|
||||
Настоящий документ сверён в части общего ядра stream; платформенные разделы
|
||||
desktop/Android и подробности внешнего сетевого стенда остаются частично проверенными.
|
||||
Расхождение допуска deleted устранено: stream_member_load читает принятый флаг
|
||||
в том же SELECT, что и профиль, и возвращает STREAM_ERR_NOT_MEMBER до crypto.
|
||||
Штатный test_stream_member проверяет подписи/версии, source/supplier/self,
|
||||
закрытие handles/выдач, изоляцию каналов и повторное разрешение участия.
|
||||
Полный аудит оставшихся разделов ещё не завершён. Подтверждения, архитектура
|
||||
Полный аудит платформенных разделов ещё не завершён. Подтверждения, архитектура
|
||||
исправления и результаты проверок — doc/stream_audit_findings.txt.
|
||||
Дефект publisher_block устранён: помещающийся Opus уходит в отдельную аудиопачку,
|
||||
ожидающее видео получает следующий слот actor. Штатный test_stream_publisher
|
||||
@@ -27,7 +30,7 @@ stream_block.h, stream_source.h, stream_media.h и stream_optimizer.h; оста
|
||||
- Источник подписывает всю пачку один раз до RS; подпись восстанавливается вместе с содержимым и проверяется после decode.
|
||||
- В источник добавляется циклический timestamp uint16_t в миллисекундах; он сохраняется при всей ретрансляции.
|
||||
Задержка оценивается относительно предыдущих данных по дельтам timestamp и времени прихода, включая полную остановку.
|
||||
- Передаём произвольные данные как есть, без обработки форматов видео, кадров и ключевых точек.
|
||||
- Транспортная часть передаёт произвольные данные как есть. Необязательный media-слой поверх неё разбирает uAV2 и точки KEY.
|
||||
- Размер части автоматически уменьшается по длине пачки, максимум по умолчанию 1300 байт.
|
||||
Побайтовый источник сбрасывает остаток через 100 мс; publish_block публикует сразу.
|
||||
- На каждый локальный экземпляр трансляции — кольцевой буфер 32 МБ для всех её субпотоков вместе.
|
||||
@@ -127,7 +130,7 @@ Handle получателя, поколение stream-сессии, измен
|
||||
Невосстановимый пропуск обозначается событием GAP; нельзя молча склеивать данные по обе стороны разрыва или выдавать нули за исходные байты.
|
||||
Окончательно пропускаем пачку, когда её данных уже нет в окне либо все нужные выдачи прошли её индекс/сообщили пропуск,
|
||||
а k блоков не собрано. Получение более поздней пачки от одного поставщика само по себе не закрывает ожидание остальных.
|
||||
Модуль не интерпретирует содержимое и не занимается видео, кодированием, воспроизведением или поиском ключевых кадров.
|
||||
RS/сетевой слой не интерпретирует содержимое. Media store, publisher и playback — отдельные компоненты поверх него.
|
||||
|
||||
4. Подпись источника и timestamp
|
||||
|
||||
@@ -256,13 +259,19 @@ ACCEPT содержит handle, фактический начальный инд
|
||||
Реальное получение блока, а не только ACCEPT, подтверждает пригодность выдачи.
|
||||
Индекс сразу после последнего доступного блока разрешён: курсор ждёт его появления в том же кольце.
|
||||
Более далёкий будущий индекс отвергается. Пустой источник допускает выдачу с 0/с конца,
|
||||
которая ждёт первый блок; первый проверенный DATA по-прежнему устанавливает общий N.
|
||||
которая ждёт первый блок; первая структурно допустимая DATA-часть по-прежнему устанавливает общий N.
|
||||
Пустой ретранслятор пути не объявляет. Завершение без данных подтверждается подписанным END с last_seq=UINT64_MAX.
|
||||
Общий N фиксирует первая структурно допустимая RS-часть, до проверки подписи всей пачки.
|
||||
INFO/ACCEPT и счётчик принятых частей не являются подтверждением подписи; она проверяется при decode из k частей.
|
||||
Отказы различают отсутствие подписки/трансляции, эпоху, FEC, позицию, слот, перегрузку, цикл и право доступа.
|
||||
DATA содержит поколение сессии, handle, неизменяемую часть RS-пачки и изменяемый путь.
|
||||
Источник подписывает и END с ключом трансляции и индексом последней пачки, чтобы ретранслятор не мог подделать окончание.
|
||||
|
||||
Нет продления 6 секунд — отправитель закрывает выдачу и сообщает CLOSED, при необходимости через маршрутизатор группы.
|
||||
INFO/connect ограничен 5 секундами; готовая INFO-only проба остаётся до явного close.
|
||||
Control FIFO удаляет сообщения старше 4 секунд. Просроченные INFO_REQ (9 байтов), SUBSCRIBE и ACCEPT
|
||||
закрывают соответствующую незавершённую выдачу с OVERLOAD; INFO_REQ дополнительно сопоставляется по nonce.
|
||||
После первого DATA отдельного таймера тишины receive нет: восстановление выполняет selector либо ручной владелец.
|
||||
Аренда, пробы и timers используют монотонное локальное время. Таймаут аренды очищает ресурсы;
|
||||
реакция на отсутствие прогресса начинается раньше по метрикам потока.
|
||||
Потеря отдельного ETCP-линка не закрывает выдачи, пока NCD остаётся UP.
|
||||
@@ -274,7 +283,7 @@ DOWN закрывает выдачи соответствующей сессии
|
||||
Начальный запуск:
|
||||
1) По опциям мемберов и BGP выбрать первый подходящий онлайн-узел, включая сам источник.
|
||||
2) Запросить один субпоток с N=UINT64_MAX.
|
||||
3) Получить и проверить первый блок, зафиксировать его source_epoch и batch_seq=N.
|
||||
3) Принять структурно допустимую часть и зафиксировать batch_seq=N; source_epoch уже выбран по профилю источника.
|
||||
4) У остальных поставщиков запросить субпотоки этой же эпохи с конкретного N.
|
||||
5) Собрать достаточный набор блоков одной пачки, затем продолжать непрерывное получение.
|
||||
|
||||
@@ -285,7 +294,7 @@ DOWN закрывает выдачи соответствующей сессии
|
||||
Обычный перенос одного субпотока:
|
||||
1) Выбрать первую ещё нужную пачку N и поставщика, способного её выдать.
|
||||
2) Создать новую выдачу, продолжая старую; временное перекрытие также занимает исходящий слот нового поставщика.
|
||||
3) Получить блоки и подтвердить продвижение нового поставщика.
|
||||
3) Получить структурно допустимые части и подтвердить продвижение нового поставщика до курсора старого.
|
||||
4) Закрыть старую выдачу. При отказе новой сохранить старую и отменить неудачную попытку.
|
||||
|
||||
Дедупликация — по (stream key, batch_seq, subblock), независимо от handles.
|
||||
@@ -324,7 +333,9 @@ DATA несёт фактически пройденные узлы; началь
|
||||
Базу сбрасываем при отмеченном источником разрыве времени, неоднозначной дельте, новой выдаче/эпохе или разрыве последовательности.
|
||||
Резкое изменение позиции выдачи не считается доказательством улучшения задержки.
|
||||
|
||||
Ожидаемый межблочный интервал и rate источника оцениваются по окну его timestamp и объёмам блоков.
|
||||
Rate источника оценивается по timestamp и объёмам пар последовательных блоков за 60 секунд.
|
||||
Ожидаемый интервал сначала равен 100 мс; после ненулевой суммы source_delta текущей секундной корзины
|
||||
используется её среднее по интервалам, не меньше 1 мс. Первый/rebase-блок не даёт парных bytes/time для rate.
|
||||
Если несколько блоков имеют один timestamp, агрегируем объём до ненулевой дельты, не делим на ноль.
|
||||
Не используем время формирования всех n блоков одной пачки как n независимых временных интервалов.
|
||||
При отсутствии новых данных продолжаем измерять отставание от ожидаемого следующего прихода:
|
||||
@@ -363,8 +374,9 @@ INFO_RESP также сообщает число свободных исходя
|
||||
Неуспех имеет backoff; одинаковые активные пробы одного пира для разных экземпляров переиспользуются.
|
||||
Временные NCD handles невыбранных кандидатов освобождаются; рабочие экземпляры удерживают свои handles.
|
||||
|
||||
Используются route_connectivity, sock_match/NCD и метрики существующих соединений; второй адресный probe-движок не создаётся.
|
||||
Прямая доступность — UNKNOWN/REACHABLE/UNREACHABLE с временем замера, а не вечный boolean.
|
||||
Используются node_conn_direct_compatible и sock_match/NCD; stream не запускает собственные route_connectivity-пробы.
|
||||
Совместимость означает возможность direct/reverse-попытки по известным сокетам/адресам либо уже работающий транспорт.
|
||||
Фактическую доступность и RTT подтверждает INFO-обмен, снимки и неуспехи имеют ограниченный срок/backoff.
|
||||
|
||||
После проверки доступного субпотока/индекса и отсутствия цикла минимизируем интегральную оценку в миллисекундах:
|
||||
score_ms = RTT_цепочки_до_поставщика + 2 * RTT_до_поставщика + 3 * hop_count + problem_penalty_ms
|
||||
@@ -412,7 +424,8 @@ A — поступившая нагрузка, D — передано в ETCP, X
|
||||
Rate выдачи — её средний вклад в поступающую нагрузку, а не урезанная скорость выхода из перегруженного канала.
|
||||
Для разгрузки нужно снять суммарный rate больше g, чтобы очередь начала убывать.
|
||||
Число выдач оценивается по их rates, но закрывать можно только избыточные части сверх k.
|
||||
Недостаточная полоса без избыточных частей требует пропуска устаревших данных, а не разрушения FEC-набора.
|
||||
Без безопасных избыточных частей запрос завершается без принудительных закрытий. Возраст сам по себе не разрешает пропуск:
|
||||
backpressure сохраняет cursor, GAP возникает при фактическом вытеснении/утрате диапазона.
|
||||
|
||||
OVERLOAD содержит request_id, расчётное число выдач, требуемое сокращение rate и список handles с фиксированными rates.
|
||||
Получатель выбирает handles только при сохранении k различных работающих частей и отправляет OVERLOAD_SELECT.
|
||||
@@ -580,7 +593,7 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
||||
stream_network.c/h — собственный NCD owner пира, общий для его потоков/групп; ожидание его UP,
|
||||
прямые SUBSCRIBE/ACCEPT/REJECT/DATA/GAP/RENEW/UNSUBSCRIBE/CLOSED/END, routed REVERSE_REQ/CLOSED.
|
||||
Новые handles назначаются при постановке SUBSCRIBE в общую FIFO; watermark защищает от закрытых/старых запросов.
|
||||
Первый проверенный DATA с конца устанавливает общий N; прочие latest-выдачи ждут его и запрашивают конкретный N.
|
||||
Первая структурно допустимая DATA-часть с конца устанавливает общий N; прочие latest-выдачи запрашивают конкретный N.
|
||||
Повторный stream_receive_restart отменяет upstream старой попытки, оставляя кольцо/downstream;
|
||||
старые receive handles отсоединяются и требуют close. Уже сохранённый первый блок также устанавливает новый старт.
|
||||
DATA копируется из кольца только перед отправкой; пути сохраняются по каждому блоку и проверяются на LOOP.
|
||||
@@ -607,7 +620,8 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
||||
Кольцо сообщает только фактические вставки/вытеснения; повторный блок не создаёт A.
|
||||
Списки субпотоков по времени вставки дают точный возраст ещё ожидающих блоков, в том числе вне порядка batch_seq.
|
||||
Логическая DATA-очередь представлена курсорами и счетчиками: содержимое и история остаются в одном 32-МБ кольце.
|
||||
Частные/общие метрики lag/rates/late/stops подключены к подписанным DATA; после END ожидание прекращается.
|
||||
Метрики lag/rates/late/stops обновляются при приёме структурно допустимых частей, до проверки общей подписи;
|
||||
они описывают доставку поставщика и не подтверждают содержимое источника. После END ожидание прекращается.
|
||||
INFO содержит nonce пробы и 64-битный снимок метрик; RTT — uint32 мс с признаком неизвестного.
|
||||
Условие перегрузки: ожидающая нагрузка старше 200мс и рост либо нулевой D;
|
||||
непрерывное подтверждение — 500мс по монотонным часам, независимо от количества тиков.
|
||||
@@ -651,7 +665,7 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
||||
INFO сохраняет диапазон, фактический путь, metrics, RTT, свободные slots, accepting, queue, CPU и возраст прогресса.
|
||||
RTT цепочки относится к этому пути; смена фактического пути DATA делает старое измерение неизвестным,
|
||||
новая проба обновляет RTT соответствующей активной выдачи. Невыбранные снимки истекают через 60с.
|
||||
Первый поставщик запрашивается с конца; остальные стартуют с его проверенного N, даже если k уже позволили выдать пачку.
|
||||
Первый поставщик запрашивается с конца; остальные стартуют с N его первой принятой части, даже если пачка уже выдана.
|
||||
Поиск учитывает доступную старую позицию, запрет LOOP и лимит r при наличии альтернатив.
|
||||
Оценка поставщика в мс: RTT цепочки до поставщика + 2 * RTT до поставщика + 3 * hops + штраф проблем (0..1000 мс).
|
||||
hops = path.count: путь INFO содержит автора/поставщика, последний переход к получателю добавляет один hop.
|
||||
@@ -659,15 +673,19 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
||||
текущая остановка или lag > 500 мс сразу дают 1000 мс. Неизвестные метрики не дают штрафа, неизвестный RTT даёт UINT64_MAX.
|
||||
Меньшая оценка лучше; при равенстве выбираются меньше общих узлов путей, затем меньший ID поставщика.
|
||||
Более новый индекс повторно проверяется свежим INFO/SUBSCRIBE: старое объявление last не является вечным верхним пределом live-потока.
|
||||
Обычно переносится один субпоток; новая выдача перекрывает старую и заменяет её только после проверенного DATA и догоняющего cursor.
|
||||
Обычно переносится один субпоток; новая выдача заменяет старую после структурно допустимого DATA и догоняющего cursor.
|
||||
По умолчанию: подтверждение улучшения 2с, удержание поставщика 5с, гистерезис оценки 20мс; параметры доступны через stream_selection_configure.
|
||||
Перенос сравнивает ту же оценку по фактическим метрикам текущей выдачи и INFO альтернативы;
|
||||
распределение для FEC допускает ухудшение оценки не более гистерезиса. Логи выбора/переноса показывают оценку и её составляющие.
|
||||
Новая выдача без достаточного продвижения отменяется через 5с, старая остаётся. CLOSED/DOWN восстанавливают несколько отсутствующих субпотоков.
|
||||
При отсутствии decode-прогресса 5с, недостатке работающих субпотоков и наличии более новой истории возможен явный restart с конца;
|
||||
пропущенный диапазон передаётся потребителю GAP, кольцо/downstream сохраняются. Сам по себе простой источника restart не вызывает.
|
||||
После 5с без полной проверенной пачки, если anchor уже есть либо запрошен media-индекс, выполняется recovery_request;
|
||||
следующая попытка не раньше чем через 5с. Зависшие выдачи переоткрываются, consumer/media cursors сохраняются.
|
||||
Для media переход к более новому полному KEY выполняется лишь при доказанной недоступности нужного диапазона;
|
||||
тогда stream_local_restart сохраняет кольцо/downstream и передаёт пропущенный диапазон как GAP.
|
||||
Тишина источника может вызвать перезапрос, но сама по себе не доказывает потерю данных и не требует скачка к голове.
|
||||
stream_selection_get_info сообщает пробы/циклы, выдачи, перекрытия, поставщиков, миграции, отказы/restart и фактическую FEC-защиту.
|
||||
Защита подтверждается всеми n проверенными работающими субпотоками и не более r на поставщика; при недостатке поставщиков помечается ослабленной.
|
||||
Защита оценивается по всем n субпотокам с наблюдёнными частями/метриками без stopped и не более r на поставщика;
|
||||
эта оценка доступности частей не заменяет проверку общей подписи. При недостатке поставщиков защита ослаблена.
|
||||
Владельцы публикации/подписки удерживают ACTIVE; запрошенный STANDBY восстанавливается после закрытия последнего экземпляра.
|
||||
Подписанный END проходит также для источника без единого DATA.
|
||||
test_stream_core проверяет границы 32/1с/30с, новые записи, долгий/незавершённый обход и отсутствие повторного burst.
|
||||
@@ -689,8 +707,8 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
||||
17. Зафиксированный сетевой формат и пределы реализации
|
||||
|
||||
Все stream-числа на wire — big-endian, без packed-структур и зависимости от host byte order.
|
||||
Версия stream wire — 4; обратная совместимость не поддерживается.
|
||||
Заголовок raw (52 байта, version=7): cmd:1, version:1, command:1, subblock:1,
|
||||
Версия stream wire — 7; обратная совместимость не поддерживается.
|
||||
Заголовок raw (52 байта, version=7): etcp_id=0x07:1, version:1, command:1, subblock:1,
|
||||
group_id:8, source_node_id:8, source_epoch:8, sender_epoch:8, receiver_epoch:8, handle:8.
|
||||
INFO_REQ/RESP согласуют sender/receiver epochs; receiver_epoch=0 используется INFO_REQ для обнаружения поколения и REVERSE_REQ.
|
||||
Подписанный routed payload содержит тот же заголовок; его group_id сверяется с реальной группой router,
|
||||
@@ -766,7 +784,7 @@ Restart в той же source_epoch сохраняет consumer cursor: bootstra
|
||||
|
||||
8. Live media и Android
|
||||
|
||||
Транспортный wire v5 не меняется. stream_publish_block публикует одну непустую FEC-пачку
|
||||
Текущий транспортный wire — v7. stream_publish_block публикует одну непустую FEC-пачку
|
||||
немедленно, с сохранением границ. Первая запись выбирает режим источника: byte write или block write;
|
||||
смешивание отвергается до изменения данных. stream_publish_finish не освобождает буфер источника.
|
||||
|
||||
@@ -819,7 +837,8 @@ stream_media проверяет весь блок до изменения view.
|
||||
Desktop и Android открывают просмотр через stream_media_open: ядро проверяет выбранный source_epoch
|
||||
и эпоху существующей session, создаёт подписку и cursor; при ошибке снимает только нового владельца.
|
||||
Платформы сохраняют собственное планирование чтения и вывод; закрытие использует обычный stream_close.
|
||||
Ретрансляторы не разбирают uAV2 и не пересоздают подписи источника.
|
||||
Пересылка RS-частей не требует разбора uAV2 и не пересоздаёт подписи источника.
|
||||
По INFO_REQ.want_media ретранслятор дополнительно готовит общий индекс проверенных пачек для предложения полного KEY.
|
||||
|
||||
Android:
|
||||
- Один foreground publisher на процесс; каждый viewer имеет независимый session ID.
|
||||
@@ -1074,7 +1093,7 @@ Desktop:
|
||||
UI показывает video queue, суммарный inflight, send buffer и ACK_1s каждые 100ms.
|
||||
Stop закрывает источники и audio callback, join обоих workers, затем FIN и ограниченный drain 2s.
|
||||
Удаление engine происходит до SoundManager и ядра; detach отменяет posts/timers и закрывает publisher
|
||||
в uasync. Протокол uAV2 и wire v5 при добавлении desktop publisher не меняются.
|
||||
в uasync. Общий publisher использует те же uAV2 и текущий wire v7 на обеих платформах.
|
||||
- Одиночный StreamPlayerWindow либо StreamGridWindow с отдельным player на источник.
|
||||
Player содержит имя, состояние и громкость; fullscreen/close в сетке принадлежат общему окну.
|
||||
- transport/stream_bridge владеет stream_viewers: независимый cursor и ближайший батч на reader.
|
||||
@@ -1255,7 +1274,7 @@ test_stream_publish проверяет реальные encoder/decoder H.264/H.
|
||||
Сам старт публикации не запускает приём на суперузлах. Новая подписка сразу запускает INFO-пробы и отдельный
|
||||
дедлайн 100 мс. Если пригодного ответа ещё нет, запрашивается один суперузел. Первый валидный INFO с разрешённой
|
||||
выдачей выигрывает: порядок приёма фиксируется локальным счётчиком, независимо от RTT и порядка списка кандидатов.
|
||||
DATA сначала открывается только у победителя; проверенный первый блок фиксирует общий старт всех остальных субпотоков.
|
||||
DATA сначала открывается только у победителя; первая структурно допустимая часть фиксирует общий старт остальных субпотоков.
|
||||
Другие INFO-пробы продолжаются: после фиксации старта недостающие части можно брать у любых подходящих поставщиков,
|
||||
даже до первого восстановления FEC. Победитель гонки не обязан иметь все k частей. Ненужная помощь отменяется.
|
||||
Пустой доступный источник не требует помощи, пока он не публикует данные.
|
||||
@@ -1449,8 +1468,9 @@ Qt stream_view/audio/publish — 3/3, Android assembleDebug — PASS.
|
||||
Предыдущий изолированный стенд с 16 узлами: baseline 10с, WAN 2Мбит/с + RTT 300мс + loss 5% на 10с,
|
||||
восстановление, закрытие двух подписок и END — PASS. Результат: /tmp/stream-recovery-netns/result.json.
|
||||
|
||||
Новая реализация использует stream wire v6: обновляются отправитель, получатели и задействованные реле.
|
||||
Обратная совместимость v5 не поддерживается. Desktop и Android собраны из utun2.
|
||||
Историческая проверка реализации c3cf86b9 относилась к wire v6; затем телеметрия повысила версию до v7.
|
||||
При обновлении нужны отправитель, получатели и задействованные реле одной версии; совместимости с v5/v6 нет.
|
||||
Указанные ниже старые результаты desktop/Android получены из utun2 и не заменяют текущую платформенную проверку.
|
||||
|
||||
Проверка реализации c3cf86b9: ./check.sh — 187/187, proxy/burst/load — PASS; Android assembleDebug — PASS.
|
||||
Девять сетевых регрессий входят в test_stream_service; лог полного прогона: /tmp/utun2-key-check-final-pass.log.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Аудит документации src/stream — 26.10.2026, частично завершён
|
||||
Аудит документации src/stream — 26.10.2026, заголовки завершены
|
||||
|
||||
Текущий статус: deleted исправлен и покрыт штатным test_stream_member; сборка,
|
||||
профиль7/7 и check.sh195/195 PASS относятся к внедрению этого исправления (раздел 5).
|
||||
@@ -11,6 +11,10 @@
|
||||
заголовки; теперь6[V]/12[~]/0[ ]. В частично прочитанном network подтверждён
|
||||
дефект истечения INFO_REQ (раздел8). Исправление и штатные проверки выполнены:
|
||||
TTL4/4, обе реальные backpressure-сцены и check201/201 в отдельном IPv6 namespace PASS (раздел9).
|
||||
Текущий итог продолжения:18[V]/0[~]/0[ ] для заголовков src/stream; полностью
|
||||
прочитаны все16 реализаций. Раздел10 описывает финальную сверку контрактов.
|
||||
doc/stream.txt остаётся[~] из-за неполной проверки платформ desktop/Android
|
||||
и внешнего многопроцессного стенда. Старые показатели выше и в разделах1–9 — история отдельных этапов.
|
||||
|
||||
1. Подтверждённый дефект: deleted не учитывается stream_member_load
|
||||
|
||||
@@ -448,3 +452,60 @@ Proxy9/9,burst PASS,load8/8,134217728 байт; полное время175с.
|
||||
|
||||
git diff --check PASS. Sanitizers, Qt GUI и Android на устройстве в этом исправлении
|
||||
не запускались. Устранение дефекта не расширяет аудит:6[V]/12[~]/0[ ],doc/stream.txt[~].
|
||||
|
||||
10. Завершение сверки заголовков общего stream-ядра — 26.10.2026
|
||||
|
||||
Дочитан stream_network.c1616–2185: relay lifecycle, dispatch, общий tick,
|
||||
перегрузка нескольких пиров, учёт кольца, позиции получателей и телеметрия.
|
||||
Вместе с предыдущими этапами полностью прочитаны все15 C-реализаций и
|
||||
stream_playback_audio.cpp (всего7775 строк), все18 заголовков.
|
||||
Для уточнения контрактов повторно прочитаны полные buffer/media_buffer,
|
||||
member/wire, load/metrics, playback_clock/audio, publisher/viewer.
|
||||
|
||||
Уточнения заголовков
|
||||
|
||||
- network/priv: принадлежность caller-owned handles после detach, manual/internal
|
||||
ограничения, INFO nonce/повторы/сроки, аренда6с и RENEW2с, control TTL>4с,
|
||||
пределы общих бюджетов, готовая INFO-проба без автоматического close,
|
||||
первый DATA как структурная часть до проверки подписи, диапазоны/RTT/validity,
|
||||
restart с сохранением consumer floor, relay READY/BOUND и сроки помощи.
|
||||
- load/metrics: A/D/X/Q, атомарность add/remove, revision и окна роста/rates,
|
||||
live-счётчики против последнего снимка rates, rebase и 16-битный timestamp,
|
||||
первая пара для rate, строгий порог остановки, END и старение истории.
|
||||
- buffer/media_buffer: размер слотов против фактических wire-байтов,
|
||||
заимствованные данные/observer, поиск частей против проверки подписи,
|
||||
неизменяемый набор k после decode, неподписанные timing/telemetry,
|
||||
независимые позиции треков, generation/GAP/revision, status до KEY,
|
||||
bounded MORE/WAIT, audio lookahead и продолжение последнего кадра после finish.
|
||||
- member/wire: parse/format против доверенного load, BGP отдельно от членства,
|
||||
собственный online, роль deleted=0, переключатель audio против codec эпохи,
|
||||
конкретные размеры/предусловия writers/readers, путь, телеметрия и подпись END.
|
||||
- playback_clock/audio: состояние регулятора/история и часы, допустимые входы,
|
||||
producer/consumer и внешняя блокировка, 20-мс stereo output, PLC/разрыв,
|
||||
needs_input/prepare/finish, hardware frame origin, empty до опустошения устройства.
|
||||
- publisher/viewer: асинхронное открытие/stop, время занятия session ID,
|
||||
KEY/revision/admission/TTL, feed как принятие очередью, mute без смены codec,
|
||||
общие ETCP-счётчики instance, notify под lock/исключительный destroy,
|
||||
владение батчем, диапазоны demand и нулевые снимки до обновления actor.
|
||||
|
||||
Последние изменения этих12 заголовков — комментарии/оформление. Сравнение
|
||||
лексических C-токенов с сохранённой до правок базой проверяет имена, типы,
|
||||
порядок полей, объявления и выражения; все12 совпали. Публичный API/ABI,
|
||||
состояния, протокол и C/C++ логика в данном продолжении не менялись.
|
||||
Новых подтверждённых дефектов реализации в этой части аудита не найдено.
|
||||
|
||||
В stream.txt согласованы native-разделы: текущая версия wire7, INFO_REQ9,
|
||||
сроки и закрытие control, совместимость через NCD без собственного
|
||||
route_connectivity probe-движка, структурная часть против подписанной пачки,
|
||||
60-секундные rates, recovery без сброса media и отсутствие пропуска по одному
|
||||
возрасту DATA. Уточнено, что relay может готовить media-индекс по want_media.
|
||||
Старые результаты wire6/utun2 помечены историческими.
|
||||
|
||||
Покрытие:18[V]/0[~]/0[ ] в src/stream. doc/stream.txt[~]: ещё нужны
|
||||
полная сверка desktop/Android capture/decoder/audio/UI и внешнего
|
||||
tests/stream_netns, их аппаратные и старые ASAN-результаты здесь не перепроверены.
|
||||
Завершение заголовков не объявляет эти внешние компоненты проверенными.
|
||||
|
||||
Проверка ./build.sh --no-gui -j4 PASS: /tmp/stream-header-audit-build.log.
|
||||
Полный ./check.sh запущен в отдельном network namespace с IPv6/lo/::1,
|
||||
от user; основной namespace не меняется. Результат будет записан после завершения.
|
||||
Reference in new issue
Block a user