diff --git a/src/call/call.c b/src/call/call.c index 26c688d3..5d88c449 100644 --- a/src/call/call.c +++ b/src/call/call.c @@ -246,7 +246,8 @@ static void call_post_bgp_path(struct call_ctx* ctx, struct call_session* s) { static void call_post_connection(struct call_session* s) { struct ETCP_ROUTER_PATH path = {0}; if (s->state != CALL_ST_ENDED) - path = etcp_router_get_path(s->ctx->inst, s->group_id, s->peer_node_id, ETCP_RT_ID_CALL); + path = etcp_router_get_path(s->ctx->inst, s->group_id, s->peer_node_id, + s->state == CALL_ST_ACTIVE ? ETCP_RT_ID_CALL_AUDIO : ETCP_RT_ID_CALL); if (s->connection_reported && s->connection_type == path.type && s->connection_next_hop == path.next_hop_node_id) return; s->connection_reported = 1; s->connection_type = path.type; s->connection_next_hop = path.next_hop_node_id; uint8_t buf[17]; @@ -442,7 +443,7 @@ static void call_post_stats(struct call_session* s) { uint16_t rtt_tb = 0; struct ETCP_ROUTER_CONN* rconn = - etcp_router_conn_get(ctx->inst, s->group_id, s->peer_node_id, ETCP_RT_ID_CALL); + etcp_router_conn_get(ctx->inst, s->group_id, s->peer_node_id, ETCP_RT_ID_CALL_AUDIO); if (rconn && rconn->recv_conn) rtt_tb = rconn->recv_conn->rtt_last; uint16_t rtt = rtt_tb / 10; /* ETCP хранит RTT в 0.1мс; CALL_STATS передаёт миллисекунды. */ DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "%s: stats id=%016llx recv_peer=%016llx rtt_tb=%u rtt_ms=%u buffer=%dms tempo=%d dropped=%u underruns=%u", diff --git a/src/call/call_video_transport.c b/src/call/call_video_transport.c index 61a758e5..bf47df1c 100644 --- a/src/call/call_video_transport.c +++ b/src/call/call_video_transport.c @@ -3,6 +3,7 @@ #include "../utun_instance.h" #include "../routing_layer/etcp_router.h" #include "../routing_layer/route_crypto.h" +#include "../transport_layer/etcp.h" #include "../../lib/mem.h" #include "../../lib/u_async.h" #include "../../lib/debug_config.h" @@ -18,7 +19,7 @@ struct call_video_transport { struct call_video_frame tx; uint8_t *data; uint64_t tx_started_tb, tx_last_id, key_request_tb; - uint64_t local_revision, peer_revision, acknowledged_revision; + uint64_t local_revision, peer_revision, acknowledged_revision, caps_sent_tb; int64_t audio_end_pts, tx_last_pts; int have_peer, need_key; }; @@ -56,6 +57,7 @@ static int control_send(struct call_video_transport *v, uint8_t type) { if (!conn || etcp_router_conn_send(conn, data, length, ROUTE_CRYPTO_SIGN | ROUTE_CRYPTO_ENCRYPT)) { DEBUG_WARN(DEBUG_CATEGORY_CALL, "video control send failed call=%llu type=%u", (unsigned long long)s->call_id, type); return -1; } + if (type == VIDEO_CAPS) v->caps_sent_tb = get_time_tb(); return 0; } static void discard_tx(struct call_video_transport *v, const char *reason) { @@ -91,6 +93,9 @@ static void flush(struct call_video_transport *v) { static void tick(void *arg) { struct call_video_transport *v = arg; v->timer = NULL; + // Отдельный control может обогнать ACCEPT: повторяем до подтверждения приложения. + if (v->local_revision && v->acknowledged_revision != v->local_revision && get_time_tb() - v->caps_sent_tb >= 5000) + control_send(v, VIDEO_CAPS); flush(v); v->timer = uasync_set_timeout(v->session->ctx->inst->ua, 500, v, tick, "call_video"); if (!v->timer) DEBUG_ERROR(DEBUG_CATEGORY_CALL, "video timer rearm failed call=%llu", (unsigned long long)v->session->call_id); @@ -216,7 +221,8 @@ static void receive(struct ETCP_CONN *conn, struct ll_entry *entry) { caps.encode[0].width, caps.encode[1].width, caps.decode[0].width, caps.decode[1].width); if (v->ops.capabilities) v->ops.capabilities(v->arg, &v->peer); control_send(v, VIDEO_CAPS_ACK); - } else if (data[0] == VIDEO_CAPS_ACK && length == 17 && revision && revision == v->local_revision) { + } else if (data[0] == VIDEO_CAPS_ACK && length == 17 && revision && revision <= v->local_revision) { + if (revision < v->local_revision) goto done; v->acknowledged_revision = revision; DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "video capabilities acknowledged call=%llu revision=%llu", (unsigned long long)id, (unsigned long long)revision);