From 2916f3f14b30f9cd73cef6b4c7ca173171abdb3d Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 7 Mar 2023 16:07:51 +0100 Subject: [PATCH] udp: add a lock for the helpers list --- src/udp/udp.c | 102 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/src/udp/udp.c b/src/udp/udp.c index 5168b3ffd..aad2410dd 100644 --- a/src/udp/udp.c +++ b/src/udp/udp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ struct udp_sock { QOS_FLOWID qos_id; /**< QOS IPv4 flow id */ QOS_FLOWID qos_id6; /**< QOS IPv6 flow id */ #endif + mtx_t *lock; /**< A lock for helpers */ }; /** Defines a UDP helper */ @@ -120,7 +122,11 @@ static void udp_destructor(void *data) { struct udp_sock *us = data; + mtx_lock(us->lock); list_flush(&us->helpers); + mtx_unlock(us->lock); + + mem_deref(us->lock); #ifdef WIN32 if (us->qos && us->qos_id) @@ -185,6 +191,7 @@ static void udp_read(struct udp_sock *us, re_sock_t fd) (void)mbuf_resize(mb, mb->end); /* call helpers */ + mtx_lock(us->lock); le = us->helpers.head; while (le) { struct udp_helper *uh = le->data; @@ -200,6 +207,7 @@ static void udp_read(struct udp_sock *us, re_sock_t fd) us->rh(&src, mb, us->arg); out: + mtx_unlock(us->lock); mem_deref(mb); } @@ -224,6 +232,34 @@ static void udp_read_handler6(int flags, void *arg) } +static int udp_alloc(struct udp_sock **usp) +{ + int err; + struct udp_sock *us; + + if (!usp) + return EINVAL; + + us = mem_zalloc(sizeof(*us), NULL); + if (!us) + return ENOMEM; + + list_init(&us->helpers); + + err = mutex_alloc(&us->lock); + if (err) { + mem_deref(us); + return err; + } + + mem_destructor(us, udp_destructor); + + *usp = us; + + return 0; +} + + /** * Create and listen on a UDP Socket * @@ -238,19 +274,14 @@ int udp_listen(struct udp_sock **usp, const struct sa *local, udp_recv_h *rh, void *arg) { struct addrinfo hints, *res = NULL, *r; - struct udp_sock *us = NULL; + struct udp_sock *us; char addr[64] = {0}; char serv[6] = "0"; int af, error, err = 0; - if (!usp) - return EINVAL; - - us = mem_zalloc(sizeof(*us), udp_destructor); - if (!us) - return ENOMEM; - - list_init(&us->helpers); + err = udp_alloc(&us); + if (err) + return err; us->fd = RE_BAD_SOCK; us->fd6 = RE_BAD_SOCK; @@ -375,14 +406,15 @@ int udp_listen(struct udp_sock **usp, const struct sa *local, int udp_alloc_sockless(struct udp_sock **usp, udp_send_h *sendh, udp_recv_h *recvh, void *arg) { + struct udp_sock *us; + int err; + if (!usp || !sendh) return EINVAL; - struct udp_sock *us = mem_zalloc(sizeof(*us), udp_destructor); - if (!us) - return ENOMEM; - - list_init(&us->helpers); + err = udp_alloc(&us); + if (err) + return err; us->fd = RE_BAD_SOCK; us->fd6 = RE_BAD_SOCK; @@ -392,7 +424,6 @@ int udp_alloc_sockless(struct udp_sock **usp, us->rxsz = UDP_RXSZ_DEFAULT; *usp = us; - return 0; } @@ -400,14 +431,15 @@ int udp_alloc_sockless(struct udp_sock **usp, int udp_alloc_fd(struct udp_sock **usp, re_sock_t fd, udp_recv_h *recvh, void *arg) { + struct udp_sock *us; + int err; + if (!usp || fd==RE_BAD_SOCK) return EINVAL; - struct udp_sock *us = mem_zalloc(sizeof(*us), udp_destructor); - if (!us) - return ENOMEM; - - list_init(&us->helpers); + err = udp_alloc(&us); + if (err) + return err; us->fd = fd; us->fd6 = RE_BAD_SOCK; @@ -416,7 +448,6 @@ int udp_alloc_fd(struct udp_sock **usp, re_sock_t fd, us->rxsz = UDP_RXSZ_DEFAULT; *usp = us; - return 0; } @@ -431,16 +462,16 @@ int udp_alloc_fd(struct udp_sock **usp, re_sock_t fd, */ int udp_open(struct udp_sock **usp, int af) { - struct udp_sock *us = NULL; + struct udp_sock *us; int err = 0; re_sock_t fd; if (!usp) return EINVAL; - us = mem_zalloc(sizeof(*us), udp_destructor); - if (!us) - return ENOMEM; + err = udp_alloc(&us); + if (err) + return err; us->fd = RE_BAD_SOCK; us->fd6 = RE_BAD_SOCK; @@ -879,6 +910,7 @@ int udp_register_helper(struct udp_helper **uhp, struct udp_sock *us, if (!uh) return ENOMEM; + mtx_lock(us->lock); list_append(&us->helpers, &uh->le, uh); uh->layer = layer; @@ -891,6 +923,7 @@ int udp_register_helper(struct udp_helper **uhp, struct udp_sock *us, if (uhp) *uhp = uh; + mtx_unlock(us->lock); return 0; } @@ -957,19 +990,24 @@ void udp_recv_helper(struct udp_sock *us, const struct sa *src, struct udp_helper *udp_helper_find(const struct udp_sock *us, int layer) { struct le *le; + struct udp_helper *uhf = NULL; if (!us) return NULL; + mtx_lock(us->lock); for (le = us->helpers.head; le; le = le->next) { struct udp_helper *uh = le->data; - if (layer == uh->layer) - return uh; + if (layer == uh->layer) { + uhf = uh; + break; + } } - return NULL; + mtx_unlock(us->lock); + return uhf; } @@ -1005,11 +1043,13 @@ void udp_recv_packet(struct udp_sock *us, const struct sa *src, struct mbuf *mb) { struct sa hsrc; + struct le *le; if (!us || !src || !mb) return; - struct le *le = us->helpers.head; + mtx_lock(us->lock); + le = us->helpers.head; while (le) { struct udp_helper *uh = le->data; bool hdld; @@ -1023,8 +1063,10 @@ void udp_recv_packet(struct udp_sock *us, const struct sa *src, hdld = uh->recvh(&hsrc, mb, uh->arg); if (hdld) - return; + goto out; } us->rh(src, mb, us->arg); +out: + mtx_unlock(us->lock); }