Record outgoing call admission defect and verification plan
This commit is contained in:
1 parent
aa09459c70
commit
c5eb17e59b
2 files changed
+128
No files matched your search
@@ -0,0 +1,117 @@
|
||||
Аудит src/call — 26.10.2026, начат с голосовых вызовов
|
||||
|
||||
Статус: подтверждён дефект допуска второго исходящего звонка. Реализация не
|
||||
менялась; аудит остановлен перед её исправлением по правилу AGENTS.md.
|
||||
Полная проверка аудио, видео и платформенных разделов не завершена.
|
||||
База проверки: f79b9261, чистое рабочее дерево после предыдущего push stream.
|
||||
|
||||
1. Подтверждённый дефект: call_start не проверяет обычную занятость
|
||||
|
||||
call_busy возвращает1 для любой сессии state!=ENDED. Входящий INVITE проверяет
|
||||
этот же признак других сессий и отвечает BUSY. call_start проверяет только
|
||||
radio_call_busy, затем создаёт новую call_session без проверки обычного звонка.
|
||||
В результате один instance может иметь несколько незавершённых обычных сессий.
|
||||
|
||||
Точки кода на базе проверки:
|
||||
- call.c:605–623: входящий INVITE отклоняется при другом незавершённом звонке;
|
||||
- call.c:960–965: call_busy учитывает все состояния, кроме ENDED;
|
||||
- call.c:1064–1137: call_start не использует call_busy, создаёт сессию/CM,
|
||||
отправляет INVITE и запускает таймеры независимо от уже идущего звонка;
|
||||
- chat_headless_control.c:750–763: headless-команда напрямую вызывает call_start,
|
||||
без дополнительной проверки call_busy. Ограничение только в UI недостаточно.
|
||||
|
||||
Реестр может содержать завершённые записи для END_ACK/таймаута и новый звонок;
|
||||
это штатно и не означает поддержку нескольких одновременно незавершённых.
|
||||
call_audio_start_impl использует один g_call_id/codec/jitter-контур; start другого
|
||||
ID освобождает прежний. Аппаратное воспроизведение/переключение в этом аудите
|
||||
не запускалось, фактическая потеря звука не заявляется.
|
||||
|
||||
2. Изолированное воспроизведение на настоящих ядрах
|
||||
|
||||
/tmp/call-audit-busy.c использует существующий fixture tests/test_call.c:
|
||||
два UTUN_INSTANCE на одном UASYNC, свои временные конфиги/ключи/SQLite,
|
||||
настоящие CHAT/BGP/ETCP/router/CM. Сторонних узлов и пользовательской БД нет.
|
||||
После штатного получения нужного состояния вызывается публичный call_start
|
||||
с другим call_id для того же пира. Реестр и счётчики читаются в uasync.
|
||||
Ни состояние первой сессии, ни результат call_busy вручную не подменяются.
|
||||
|
||||
У каждого сценария отдельный процесс. Перед вторым call_start:
|
||||
call_busy=1, число незавершённых=1. Ожидается отказ без второй сессии/CM,
|
||||
без изменения первой сессии и c_calls_started. Фактически:
|
||||
|
||||
Сценарий Первая сессия live Новый CM c_calls_started
|
||||
outgoing caller OUTGOING, state1 1->2 да 1->2
|
||||
ringing caller RINGING, state2 1->2 да 1->2
|
||||
active обе стороны приняли, ACTIVE3 1->2 да 1->2
|
||||
incoming callee RINGING, state2 1->2 да 0->1
|
||||
wait_decision caller WAIT_DECISION, state5 1->2 да 1->2
|
||||
|
||||
Во всех пяти первая сессия/её состояние сохранены, вторая имеет OUTGOING1.
|
||||
Это две незавершённые сессии, а не доказательство двух ACTIVE-разговоров:
|
||||
стенд останавливается после проверки локального допуска, до обработки
|
||||
второго INVITE другой стороной. Два CM handles не означают два физических ETCP.
|
||||
Все5 отрицательных проверок завершаются exit1; после destroy/poll/uasync_destroy
|
||||
счётчик tracked allocations возвращается0->0. Утечка этим тестом не обнаружена.
|
||||
|
||||
Диагностика: глобальный error, категория call=debug. В логах видны оба
|
||||
call_start, ID/peer/group, отдельный CM, исходное состояние, live1->2,
|
||||
счётчики и cleanup. Все логи пяти сценариев прочитаны полностью.
|
||||
Пример ACTIVE: busy=1 live=1->2 original_state=3 preserved=1 second_created=1
|
||||
second_state=1 second_CM=1 started=1->2 expected_live=1 result=FAIL.
|
||||
|
||||
Сборка через штатный Makefile/LIBUTUN/COMMON_LIBS, без ручного списка src/*.c:
|
||||
make -C tests -f Makefile -f /tmp/call-audit-busy.mk /tmp/call-audit-busy
|
||||
PASS: /tmp/call-audit-busy-build.log.
|
||||
Логи /tmp/call-audit-busy-{outgoing,ringing,active,incoming,wait_decision}.log.
|
||||
|
||||
3. Предлагаемое исправление и проверки
|
||||
|
||||
Единая точка допуска — call_start в uasync. До создания сессии, CM, отправки
|
||||
INVITE и публикации занятости проверять call_busy. Существующий звонок не
|
||||
завершать и не заменять. Для нового ID при занятости использовать существующее
|
||||
событие ENDED/BUSY, как при pending radio invitation, с понятным INFO-логом
|
||||
нового/занятого ID, состояния и peer/group. Новые состояния/таймеры/wire не нужны.
|
||||
|
||||
До BUSY-события отдельно обработать уже зарегистрированный out_call_id:
|
||||
повтор/коллизия не должны породить ENDED с ID действующего звонка или вставить
|
||||
дубликат ключа реестра. Такой вызов безопасно отклонять с WARN без изменения
|
||||
существующего звонка. Для новой попытки caller выбирает ненулевой уникальный ID.
|
||||
Это требование к корректности будущего исправления; отдельная runtime-проверка
|
||||
коллизии ID в текущем аудите не выполнялась.
|
||||
|
||||
Постоянная регрессия должна проверить:
|
||||
- OUTGOING, caller/callee RINGING, ACTIVE и обе стороны WAIT_DECISION;
|
||||
- второй вызов тому же/другому пиру и из другой группы/DM, защита на уровне instance;
|
||||
- отсутствие второй session/CM/INVITE, новых started и изменений исходного звонка;
|
||||
- BUSY ровно для нового ID, повтор существующего ID без ложного ENDED исходного;
|
||||
- новый уникальный ID разрешён после ENDED, даже пока живёт старый tombstone;
|
||||
- сохранение правил pending radio invitation, phone-policy и нормального start;
|
||||
- исходный call/CM/аудиоприём продолжаются, cleanup без tracked leaks.
|
||||
|
||||
После исправления: сборка, test_call/test_call_headless, тесты голосового
|
||||
стека соответствующей C++ сборки и общий check.sh. Затем продолжить аудит
|
||||
call_audio/jitter/delay/timeline/tones/headless, а после них — видео.
|
||||
|
||||
4. Полнота аудита и текущие проверки
|
||||
|
||||
Полностью прочитаны call.c1230 строк, call.h134, call_priv.h43, call_proto.h111,
|
||||
call_audio.h105 и voice_sources.cmake. Размеры заголовков указаны до правок.
|
||||
В call_audio.c прочитана полная call_audio_start_impl141–258, остальной файл
|
||||
целиком ещё не проверен. doc/chat_call_arch.md прочитан до строки320 из465.
|
||||
Из теста call использован штатный fixture и просмотрены относящиеся к нему
|
||||
setup/события/сценарии; полноценный аудит всех тестовых/video-функций не заявляется.
|
||||
|
||||
call.h, call_audio.h, call_priv.h отмечены[~]; прежняя отметка call_proto.h[~]
|
||||
сохранена. Итого0[V]/4[~]/17[ ] для21 заголовка src/call. Остальные голосовые
|
||||
заголовки пока[ ], видео по просьбе пользователя ещё не проверялось.
|
||||
doc/chat_call_arch.md[~], doc/call_video.txt[ ] сохранены. В call.h и doc
|
||||
добавлено предупреждение о подтверждённом дефекте, задача записана в tasks.md.
|
||||
|
||||
Штатный tests/test_call PASS:2/2,0 failed, exit0.
|
||||
Лог /tmp/call-audit-baseline-test-call.log прочитан полностью; ERROR-сообщения
|
||||
относятся к ожидаемым отрицательным media/video-проверкам самого теста.
|
||||
Прохождение штатного набора не закрывает выявленный пробел допуска.
|
||||
Новая диагностическая программа собрана PASS, пять отрицательных проверок
|
||||
FAIL ожидаемо. C/C++ реализации и штатные тесты проекта не менялись.
|
||||
Полная сборка/check.sh, sanitizers, отдельный C++ audio/GUI и Android runtime
|
||||
в этом продолжении не запускались; прежние результаты stream сюда не переносятся.
|
||||
@@ -35,6 +35,17 @@
|
||||
Полный аудит остальных контрактов остаётся частичным; wire/формат БД не менялись.
|
||||
Подробности: [member_merkle_audit_findings.txt](member_merkle_audit_findings.txt).
|
||||
|
||||
[ ] **call: запрещать второй исходящий вызов при незавершённом обычном звонке** — подтверждено 26.10.2026.
|
||||
call_start проверяет radio_call_busy, но не call_busy: на двух настоящих CHAT/ETCP-ядрах
|
||||
во всех5 сценариях OUTGOING/RINGING/ACTIVE/входящий RINGING/WAIT_DECISION live1->2,
|
||||
создаётся второй CM handle, c_calls_started растёт; исходная сессия остаётся незавершённой.
|
||||
Проверять обычную занятость до session/CM/INVITE, сохраняя текущий звонок; новый ID отклонять ENDED/BUSY.
|
||||
Отдельно обрабатывать уже зарегистрированный ID, чтобы отказ не дал ложный ENDED действующему звонку.
|
||||
Закрепить состояния, оба направления/группы/DM, отсутствие второго INVITE, повтор ID и новый звонок после ENDED.
|
||||
Штатный test_call2/2 PASS; диагностические5 сценариев ожидаемо FAIL, cleanup allocations0->0.
|
||||
Реализация ещё не исправлена, аудит остановлен по AGENTS.md.
|
||||
Подробности: [call_audit_findings.txt](call_audit_findings.txt); логи /tmp/call-audit-busy-*.log.
|
||||
|
||||
[+] **stream: закрывать INFO-пробу при истечении её 9-байтового запроса** — исправлено и проверено 26.10.2026.
|
||||
expire_controls сверяет length9 и текущий probe_id; истёкший INFO закрывает flow с OVERLOAD.
|
||||
Лог содержит размер, возраст control и факт закрытия flow; чужой probe_id не закрывает новую попытку.
|
||||
|
||||
Reference in new issue
Block a user