diff --git a/daemon/media_socket.c b/daemon/media_socket.c index a96e12ca1..1ea8c5f9b 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -715,32 +715,47 @@ bail: release_reserved_port(pp, ret, port); } -/** - * This function just (globally) reserves a port number, it doesn't provide any binding/unbinding. - * Returns linked list if successful, or NULL if failed. - */ -static ports_q reserve_port(struct port_pool *pp, unsigned int port) { +static ports_list *get_port(struct port_pool *pp, unsigned int port) { + LOCK(&pp->free_list_lock); + __auto_type link = free_ports_link(pp, port); + if (!link) + return NULL; + + // remove link from free list and return it + t_queue_unlink(&pp->free_ports_q, link); + free_ports_link(pp, port) = NULL; + + return link; +} + +static ports_q get_port_links(struct port_pool *pp, unsigned int port) { ports_q ret = TYPED_GQUEUE_INIT; - if (!port_is_in_range(pp, port)) + __auto_type link = get_port(pp, port); + if (!link) return ret; // empty result - { - LOCK(&pp->free_list_lock); - __auto_type link = free_ports_link(pp, port); - if (!link) - return ret; // empty result - // move link from free list to output - t_queue_unlink(&pp->free_ports_q, link); - free_ports_link(pp, port) = NULL; - t_queue_push_tail_link(&ret, link); - } + t_queue_push_tail_link(&ret, link); reserve_additional_port_links(&ret, pp, port); // reverts `ret` to empty result on failure return ret; } + +/** + * This function reserves a port number, i.e. removes it from the pool. + */ +static void reserve_port(struct port_pool *pp, unsigned int port) { + if (!port_is_in_range(pp, port)) + return; + + __auto_type ret = get_port_links(pp, port); + + // and just discard + t_queue_clear(&ret); +} + /** * This function just releases reserved port number, it doesn't provide any binding/unbinding. */ @@ -942,8 +957,7 @@ static void __interface_append(struct intf_config *ifa, sockfamily_t *fam, bool unsigned int port = GPOINTER_TO_UINT(l->data); if (port > 65535) continue; - __auto_type pq = reserve_port(&spec->port_pool, port); - t_queue_clear(&pq); + reserve_port(&spec->port_pool, port); } // look for other specs with overlapping port ranges @@ -1024,8 +1038,7 @@ void interfaces_exclude_port(endpoint_t *e) { if (!port_is_in_range(pp, e->port)) continue; - __auto_type pq = reserve_port(pp, e->port); - t_queue_clear(&pq); + reserve_port(pp, e->port); } } @@ -1154,7 +1167,10 @@ void append_thread_lpr_to_glob_lpr(void) { } static struct socket_port_link get_one_port_link(unsigned int port, struct intf_spec *spec) { - __auto_type links = reserve_port(&spec->port_pool, port); + if (!port_is_in_range(&spec->port_pool, port)) + return (struct socket_port_link) {}; + + __auto_type links = get_port_links(&spec->port_pool, port); return (struct socket_port_link) { .links = links, .pp = &spec->port_pool, .socket = { .fd = -1 }}; }