diff --git a/daemon/call.c b/daemon/call.c index 2b4992ade..61d2e09ad 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -896,7 +896,6 @@ static struct endpoint_map *__get_endpoint_map(struct call_media *media, unsigne struct endpoint_map *em; struct stream_fd *sfd; GQueue intf_sockets = G_QUEUE_INIT; - socket_t *sock; struct intf_list *il, *em_il; for (l = media->endpoint_maps.tail; l; l = l->prev) { @@ -965,6 +964,7 @@ alloc: em_il->local_intf = il->local_intf; g_queue_push_tail(&em->intf_sfds, em_il); + socket_t *sock; while ((sock = g_queue_pop_head(&il->list))) { set_tos(sock, media->call->tos); if (media->call->cpu_affinity >= 0) { @@ -3229,6 +3229,7 @@ static void __call_cleanup(struct call *c) { struct stream_fd *sfd = g_queue_pop_head(&c->stream_fds); if (sfd->poller) poller_del_item(sfd->poller, sfd->socket.fd); + stream_fd_release(sfd); obj_put(sfd); } diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 8ed5718b9..dada2d0d6 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -393,6 +393,9 @@ static GQueue __preferred_lists_for_family[__SF_LAST]; GQueue all_local_interfaces = G_QUEUE_INIT; +rwlock_t local_media_socket_endpoints_lock; +static GHashTable *local_media_socket_endpoints; + /* checks for free no_ports on a local interface */ @@ -728,6 +731,9 @@ void interfaces_init(GQueue *interfaces) { __interface_append(ifa, fam); } } + + local_media_socket_endpoints = g_hash_table_new_full(endpoint_t_hash, endpoint_t_eq, NULL, obj_put_ptr); + rwlock_init(&local_media_socket_endpoints_lock); } void interfaces_exclude_port(unsigned int port) { @@ -2661,9 +2667,37 @@ struct stream_fd *stream_fd_new(socket_t *fd, struct call *call, const struct lo sfd->poller = p; } + RWLOCK_W(&local_media_socket_endpoints_lock); + g_hash_table_replace(local_media_socket_endpoints, &sfd->socket.local, obj_get(sfd)); + return sfd; } +struct stream_fd *stream_fd_lookup(const endpoint_t *ep) { + RWLOCK_R(&local_media_socket_endpoints_lock); + struct stream_fd *ret = g_hash_table_lookup(local_media_socket_endpoints, ep); + if (!ret) + return NULL; + obj_hold(ret); + return ret; +} + +void stream_fd_release(struct stream_fd *sfd) { + if (!sfd) + return; + + RWLOCK_W(&local_media_socket_endpoints_lock); + struct stream_fd *ent = g_hash_table_lookup(local_media_socket_endpoints, &sfd->socket.local); + if (!ent) + return; + if (ent != sfd) // should not happen + return; + + g_hash_table_remove(local_media_socket_endpoints, &sfd->socket.local); // releases reference +} + + + const struct transport_protocol *transport_protocol(const str *s) { int i; @@ -2741,4 +2775,8 @@ void interfaces_free(void) { for (int i = 0; i < G_N_ELEMENTS(__preferred_lists_for_family); i++) g_queue_clear(&__preferred_lists_for_family[i]); + + g_hash_table_destroy(local_media_socket_endpoints); + local_media_socket_endpoints = NULL; + rwlock_destroy(&local_media_socket_endpoints_lock); } diff --git a/include/media_socket.h b/include/media_socket.h index 4f0e7ff09..43f751bdf 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -175,6 +175,8 @@ int __get_consecutive_ports(GQueue *out, unsigned int num_ports, unsigned int wa struct intf_spec *spec, const str *); int get_consecutive_ports(GQueue *out, unsigned int num_ports, struct call_media *media); struct stream_fd *stream_fd_new(socket_t *fd, struct call *call, const struct local_intf *lif); +struct stream_fd *stream_fd_lookup(const endpoint_t *); +void stream_fd_release(struct stream_fd *); void free_intf_list(struct intf_list *il); void free_socket_intf_list(struct intf_list *il);