From 5f9e9975d3679d0bfba98fa300fcb8b8a3b1748d Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 19 Oct 2026 14:07:39 +0200 Subject: [PATCH] Initialize radio router channels before checking send backpressure --- src/radio/radio_call.c | 20 ++++++++++++++++++-- tests/test_radio.c | 3 ++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/radio/radio_call.c b/src/radio/radio_call.c index 46abdf08..7c9c5519 100644 --- a/src/radio/radio_call.c +++ b/src/radio/radio_call.c @@ -28,7 +28,7 @@ enum { RC_INVITE = 1, RC_RINGING, RC_RESULT, RC_ACK }; struct radio_call_session { uint64_t id, group, peer; /* ключ — вся тройка, чужой пакет не меняет попытку */ uint64_t started, last_peer, last_send, finished; - uint8_t state, reason, incoming, ready, awaiting_ack; + uint8_t state, reason, incoming, ready, awaiting_ack, blocked; }; struct radio_call_context { struct UTUN_INSTANCE* inst; @@ -50,12 +50,23 @@ static void rc_event(struct radio_call_context* ctx, const struct radio_call_ses /* Никакого отдельного соединения: используем живой BGP-путь канала и backpressure роутера. */ static int rc_send(struct radio_call_context* ctx, struct radio_call_session* s, uint8_t command, uint8_t reason) { s->last_send = get_time_tb(); - if (!etcp_router_send_q_has_room(ctx->inst, s->group, s->peer, ETCP_RT_ID_RADIO_CALL)) return 0; + if (!etcp_router_conn_get(ctx->inst, s->group, s->peer, ETCP_RT_ID_RADIO_CALL)) { + DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "radio call router allocation failed id=%016llx", (unsigned long long)s->id); return -1; + } + if (!etcp_router_send_q_has_room(ctx->inst, s->group, s->peer, ETCP_RT_ID_RADIO_CALL)) { + if (!s->blocked) DEBUG_DEBUG(DEBUG_CATEGORY_RADIO, "radio call waiting for send queue id=%016llx command=%u", + (unsigned long long)s->id, command); + s->blocked = 1; return 0; + } + if (s->blocked) DEBUG_DEBUG(DEBUG_CATEGORY_RADIO, "radio call send queue ready id=%016llx", (unsigned long long)s->id); + s->blocked = 0; struct ll_entry* e = queue_entry_new(0); if (!e) { DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "radio call packet allocation failed"); return -1; } e->dgram = u_malloc(1 + RC_PACKET_SIZE); if (!e->dgram) { DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "radio call payload allocation failed"); queue_entry_free(e); return -1; } e->len = 1 + RC_PACKET_SIZE; + DEBUG_TRACE(DEBUG_CATEGORY_RADIO, "radio call TX id=%016llx group=%016llx peer=%016llx command=%u reason=%u", + (unsigned long long)s->id, (unsigned long long)s->group, (unsigned long long)s->peer, command, reason); e->dgram[0] = ETCP_RT_ID_RADIO_CALL; e->dgram[1] = command; memcpy(e->dgram + 2, &s->id, 8); int64_t expires = ntp_time_get_us(ctx->inst) + 2000000; @@ -137,6 +148,9 @@ static void rc_tick(void* arg) { /* Получатель доверяет identity из подписанного router envelope, а не физическому соседу. */ static void rc_receive(struct ETCP_CONN* conn, struct ll_entry* entry) { struct radio_call_context* ctx = conn && conn->instance ? conn->instance->radio_call : NULL; + if (ctx && entry && entry->len == ROUTER_SVC_HDR_SIZE) { + DEBUG_DEBUG(DEBUG_CATEGORY_RADIO, "radio call router epoch closed/restarted; pending deadline unchanged"); goto done; + } if (!ctx || !entry || !entry->dgram || entry->len != ROUTER_SVC_PAYLOAD_OFF + RC_PACKET_SIZE) { DEBUG_WARN(DEBUG_CATEGORY_RADIO, "radio call invalid packet bytes=%u", entry ? entry->len : 0); goto done; } @@ -150,6 +164,8 @@ static void rc_receive(struct ETCP_CONN* conn, struct ll_entry* entry) { const uint8_t* b = d + ROUTER_SVC_PAYLOAD_OFF; memcpy(&id, b + 1, 8); uint8_t command = b[0], reason = b[17]; + DEBUG_TRACE(DEBUG_CATEGORY_RADIO, "radio call RX id=%016llx group=%016llx peer=%016llx command=%u reason=%u", + (unsigned long long)id, (unsigned long long)group, (unsigned long long)peer, command, reason); if (!id || command < RC_INVITE || command > RC_ACK || reason > RADIO_CALL_AUDIO_ERROR || ((command == RC_RESULT || command == RC_ACK) ? !reason : reason != 0)) { DEBUG_WARN(DEBUG_CATEGORY_RADIO, "radio call invalid command=%u reason=%u id=%llu", command, reason, (unsigned long long)id); goto done; diff --git a/tests/test_radio.c b/tests/test_radio.c index 0b21f0b0..d86bc636 100644 --- a/tests/test_radio.c +++ b/tests/test_radio.c @@ -117,7 +117,8 @@ static etcp_recv_fn g_call_recv[3]; static void call_packet_loss(struct ETCP_CONN* conn, struct ll_entry* entry) { int idx = -1; for (int i = 0; i < 3; ++i) if (conn->instance->node_id == g_sh.nid[i]) idx = i; - if (idx < 0 || !entry || entry->len <= ROUTER_SVC_PAYLOAD_OFF) abort(); + if (idx < 0 || !entry) abort(); + if (entry->len <= ROUTER_SVC_PAYLOAD_OFF) { g_call_recv[idx](conn, entry); return; } int cmd = entry->dgram[ROUTER_SVC_PAYLOAD_OFF]; if ((idx == IDX_A && cmd == 3 && g_drop_result-- > 0) || (idx == IDX_C && cmd == 4 && g_drop_ack-- > 0)) { DEBUG_INFO(DEBUG_CATEGORY_RADIO, "test drops radio result/ACK dst=%d command=%d", idx, cmd);