Browse Source

Handle video capability exchange racing with call acceptance

master
evgeny 6 days ago
parent
commit
2c9904c345
  1. 5
      src/call/call.c
  2. 10
      src/call/call_video_transport.c

5
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",

10
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);

Loading…
Cancel
Save