From 0ebc75d229ab37e816e7b181d91776a600faaca0 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 16 Oct 2025 08:24:46 -0400 Subject: [PATCH] MT#63317 rework endpoint_map hunting Store the current (last) used endpoint map in the media object. This can then be directly used when port latching is requested. Remove and close sockets from endpoint map if fewer ports are needed. Change-Id: I58aab82f82ecc3b0a7fc7a781394c8d77e715ecf --- daemon/call.c | 99 ++++++++++++++++++++++++-------------------------- include/call.h | 3 +- 2 files changed, 49 insertions(+), 53 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 16f09d643..9d4398d43 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -767,16 +767,41 @@ static int __media_want_interfaces(struct call_media *media) { want_interfaces = 1; return want_interfaces; } -static void __endpoint_map_truncate(struct endpoint_map *em, unsigned int num_intfs) { + +static bool __endpoint_map_truncate(struct endpoint_map *em, unsigned int num_intfs, unsigned int num_ports) { + if (num_ports > em->num_ports) + return false; + while (em->intf_sfds.length > num_intfs) { struct sfd_intf_list *il = t_queue_pop_tail(&em->intf_sfds); - free_sfd_intf_list(il); + free_release_sfd_intf_list(il); + } + + if (em->num_ports == num_ports) + return true; + + for (__auto_type l = em->intf_sfds.head; l; l = l->next) { + __auto_type il = l->data; + while (il->list.length > num_ports) { + __auto_type p = t_queue_pop_tail(&il->list); + stream_fd_release(p); + } } + + return true; } + +// XXX turn this into a hash lookup static struct endpoint_map *__hunt_endpoint_map(struct call_media *media, unsigned int num_ports, const struct endpoint *ep, const sdp_ng_flags *flags, bool always_reuse, - unsigned int want_interfaces) + unsigned int want_interfaces, bool port_latching) { + if (port_latching) { + struct endpoint_map *em = media->endpoint_map; + if (em && em->num_ports >= num_ports && em->intf_sfds.length == want_interfaces) + return em; + } + for (__auto_type l = media->endpoint_maps.tail; l; l = l->prev) { struct endpoint_map *em = l->data; if (em->logical_intf != media->logical_intf) @@ -800,7 +825,6 @@ static struct endpoint_map *__hunt_endpoint_map(struct call_media *media, unsign em->endpoint = *ep; em->wildcard = 0; } - __endpoint_map_truncate(em, want_interfaces); return em; } if (!ep) /* creating wildcard map */ @@ -817,41 +841,13 @@ static struct endpoint_map *__hunt_endpoint_map(struct call_media *media, unsign if (em->num_ports >= num_ports && em->intf_sfds.length >= want_interfaces) { if (is_addr_unspecified(&em->endpoint.address)) em->endpoint.address = ep->address; - __endpoint_map_truncate(em, want_interfaces); return em; } - /* endpoint matches, but not enough ports. flush existing ports - * and allocate a new set. */ - __C_DBG("endpoint matches, doesn't have enough ports"); - t_queue_clear_full(&em->intf_sfds, free_sfd_intf_list); - return em; } return NULL; } -static struct endpoint_map *__latch_endpoint_map(struct call_media *media) -{ - // simply look for the endpoint map matching the current port - if (!media->streams.length) - return NULL; - struct packet_stream *first_ps = media->streams.head->data; - if (!first_ps->sfds.length) - return NULL; - stream_fd *matcher = first_ps->sfds.head->data; - for (__auto_type l = media->endpoint_maps.tail; l; l = l->prev) { - struct endpoint_map *em = l->data; - if (!em->intf_sfds.length) - continue; - struct sfd_intf_list *em_il = em->intf_sfds.head->data; - if (!em_il->list.length) - continue; - stream_fd *first = em_il->list.head->data; - if (first == matcher) - return em; - } - return NULL; -} static struct endpoint_map *__get_endpoint_map(struct call_media *media, unsigned int num_ports, const struct endpoint *ep, const sdp_ng_flags *flags, bool always_reuse) { @@ -859,6 +855,9 @@ static struct endpoint_map *__get_endpoint_map(struct call_media *media, unsigne socket_intf_list_q intf_sockets = TYPED_GQUEUE_INIT; unsigned int want_interfaces = __media_want_interfaces(media); + if (num_ports > 16) + return NULL; + bool port_latching = false; if (flags && flags->port_latching) port_latching = true; @@ -867,36 +866,32 @@ static struct endpoint_map *__get_endpoint_map(struct call_media *media, unsigne else if (!MEDIA_ISSET(media, RECV) && (!flags || !flags->no_port_latching)) port_latching = true; - struct endpoint_map *em = NULL; - if (port_latching) - em = __latch_endpoint_map(media); - if (!em) - em = __hunt_endpoint_map(media, num_ports, ep, flags, always_reuse, want_interfaces); + struct endpoint_map *em = __hunt_endpoint_map(media, num_ports, ep, flags, always_reuse, + want_interfaces, port_latching); if (em) { - if (em->intf_sfds.length) + if (__endpoint_map_truncate(em, want_interfaces, num_ports)) { + media->endpoint_map = em; return em; - // fall through - } - else { - __C_DBG("allocating new %sendpoint map", ep ? "" : "wildcard "); - em = uid_alloc(&media->call->endpoint_maps); - if (ep) - em->endpoint = *ep; - else - em->wildcard = 1; - em->logical_intf = media->logical_intf; - t_queue_init(&em->intf_sfds); - t_queue_push_tail(&media->endpoint_maps, em); + } } + __C_DBG("allocating new %sendpoint map", ep ? "" : "wildcard "); + em = uid_alloc(&media->call->endpoint_maps); + if (ep) + em->endpoint = *ep; + else + em->wildcard = 1; + em->logical_intf = media->logical_intf; + t_queue_init(&em->intf_sfds); + t_queue_push_tail(&media->endpoint_maps, em); em->num_ports = num_ports; - if (num_ports > 16) - return NULL; if (!get_consecutive_ports(&intf_sockets, num_ports, want_interfaces, media)) return NULL; + media->endpoint_map = em; + __C_DBG("allocating stream_fds for %u ports", num_ports); MEDIA_CLEAR(media, PUBLIC); diff --git a/include/call.h b/include/call.h index 4bbc58662..ee4edc85f 100644 --- a/include/call.h +++ b/include/call.h @@ -390,7 +390,7 @@ struct stream_params { struct endpoint_map { unsigned int unique_id; struct endpoint endpoint; - unsigned int num_ports; + unsigned int num_ports; // per interface struct logical_intf *logical_intf; sfd_intf_list_q intf_sfds; /* list of struct sfd_intf_list - contains stream_fd list */ unsigned int wildcard:1; @@ -520,6 +520,7 @@ struct call_media { unsigned int media_rec_slot; packet_stream_q streams; /* normally RTP + RTCP */ + struct endpoint_map *endpoint_map; endpoint_map_q endpoint_maps; struct ssrc_hash ssrc_hash_in; struct ssrc_hash ssrc_hash_out;