Validate terminal call packets and document end acknowledgements
This commit is contained in:
1 parent
e6954b4152
commit
92f62a0121
2 files changed
+24
-8
No files matched your search
+18
-8
@@ -17,7 +17,7 @@ DM-группа, маршрутизация через `etcp_router` идент
|
||||
|
||||
| Файл | Язык | Сборки | Назначение |
|
||||
|---|---|---|---|
|
||||
| `src/call/call_proto.h` | C | везде | wire-формат, subcmd, svc_id `ETCP_RT_ID_CALL 0x34` |
|
||||
| `src/call/call_proto.h` | C | везде | wire-формат, subcmd, svc_id `ETCP_RT_ID_CALL 0x36` |
|
||||
| `src/call/call.h` / `call.c` | C | везде (autotools + GUI) | сигналинг, реестр сессий, таймеры, watchdog (20с по приёму), релей медиа с backpressure, счётчики |
|
||||
| `src/call/call_audio.h/c` | C | только GUI-сборки | Opus encode/decode, фрейминг, pull-обвязка с тонами; регистрация через `call_audio_ops` |
|
||||
| `src/call/call_tones.h/c` | C | только GUI-сборки | генератор тонов (glitch/ended), синус |
|
||||
@@ -28,19 +28,20 @@ Autotools-сборка демона остаётся C-only (`.cpp` не ком
|
||||
|
||||
Диагностика: категория `call` (`DEBUG_CATEGORY_CALL`); транспортная доставка — `etcp_route`.
|
||||
|
||||
## 3. Протокол (svc_id 0x34, первый байт payload = subcmd)
|
||||
## 3. Протокол (сигналинг svc_id 0x36, первый байт payload = subcmd)
|
||||
|
||||
Формат приёма (как media_delivery, одноуровневый): `entry->dgram[0]=svc_id`,
|
||||
`entry->dgram[1]=subcmd`, `entry->dgram[2..]=payload`.
|
||||
Формат приёма: `entry->dgram[0]=svc_id`, служебный заголовок роутера до
|
||||
`ROUTER_SVC_PAYLOAD_OFF=26`, затем subcmd и тело команды.
|
||||
|
||||
```
|
||||
CALL_INVITE 0x01 {call_id:8, group_id:8, tracks:[{type:AUDIO, codec:OPUS, sr:4, ch:1, bitrate:4}]}
|
||||
CALL_RINGING 0x02 {call_id:8}
|
||||
CALL_ACCEPT 0x03 {call_id:8, agreed_tracks}
|
||||
CALL_ACCEPT 0x03 {call_id:8}
|
||||
CALL_DECLINE 0x04 {call_id:8, reason:1}
|
||||
CALL_BUSY 0x05 {call_id:8}
|
||||
CALL_CANCEL 0x06 {call_id:8}
|
||||
CALL_HANGUP 0x07 {call_id:8, reason:1}
|
||||
CALL_END_ACK 0x08 {call_id:8}
|
||||
CALL_MEDIA 0x10 {call_id:8, track_id:1, seq:2, ts_ms:4, capture_pts_us:8, capture_epoch:8, codec_delay_samples:4, payload}
|
||||
```
|
||||
|
||||
@@ -75,9 +76,18 @@ NO_TRAFFIC / RING_TIMEOUT / CONNECT_FAIL`.
|
||||
- `CONN_EVENT_DOWN/TIMEOUT` CM не завершают звонок: роутер использует доступные пути;
|
||||
- **NO_TRAFFIC 20с** — нет входящих медиа-кадров → авто HANGUP.
|
||||
|
||||
Завершающие кодограммы (HANGUP/CANCEL/DECLINE) шлются без ретрансмиссий — потеря
|
||||
компенсируется watchdog'ом 2с у вызываемого. Запоздалые кодограммы вызова при
|
||||
идущем разговоре (`ACTIVE`) игнорируются.
|
||||
Завершающие кодограммы HANGUP/CANCEL/DECLINE повторяются каждые 300мс до END_ACK,
|
||||
не дольше 20с. Это необходимо при смене эпохи роутера: старые очереди удаляются,
|
||||
даже если отправитель ранее получил успешный результат постановки команды в очередь.
|
||||
Медиа и их локальные очереди освобождаются сразу, ENDED публикуется один раз.
|
||||
В реестре до ACK/таймаута остаётся только завершённая сессия с CM handle и таймером.
|
||||
Получатель подтверждает также повторные команды после удаления сессии, без повторного ENDED.
|
||||
Команда и ACK проверяются по подписи, шифрованию, размеру, call_id, пиру и группе существующей сессии.
|
||||
ACK не подтверждается. Новый звонок имеет другой call_id и не затрагивается поздними командами старого.
|
||||
При одновременном завершении стороны независимо подтверждают команды друг друга.
|
||||
После ACK сессия удаляется на ближайшем tick завершения; при удалённом завершении CM удерживается
|
||||
ещё 500мс для отправки ACK. Остановка ядра отменяет таймер без повторных отправок.
|
||||
Запоздалые кодограммы вызова при идущем разговоре (`ACTIVE`) игнорируются.
|
||||
|
||||
Онлайн-проверка: `topo_node_find_by_id(group, peer) == NULL` → «не в сети» (event).
|
||||
|
||||
|
||||
@@ -724,6 +724,12 @@ static void call_etcp_recv(struct ETCP_CONN* conn, struct ll_entry* entry) {
|
||||
|
||||
int terminal = subcmd == CALL_SUBCMD_HANGUP || subcmd == CALL_SUBCMD_CANCEL || subcmd == CALL_SUBCMD_DECLINE;
|
||||
if (terminal || subcmd == CALL_SUBCMD_END_ACK) {
|
||||
uint8_t required = ROUTER_FLAG_SIGNED | ROUTER_FLAG_ENCRYPTED;
|
||||
if ((d[ROUTER_SVC_FLAGS_OFF] & required) != required) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call end unauthenticated command=%s peer=%016llx flags=%02x",
|
||||
call_subcmd_name(subcmd), (unsigned long long)from, d[ROUTER_SVC_FLAGS_OFF]);
|
||||
queue_dgram_free(entry); queue_entry_free(entry); return;
|
||||
}
|
||||
size_t expected = subcmd == CALL_SUBCMD_CANCEL || subcmd == CALL_SUBCMD_END_ACK ? 9 : 10;
|
||||
if (blen != expected) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CALL, "call end invalid packet command=%s bytes=%zu expected=%zu",
|
||||
|
||||
Reference in new issue
Block a user