From: Willy Tarreau Date: Fri, 9 Oct 2020 15:18:29 +0000 (+0200) Subject: MINOR: listeners: split do_unbind_listener() in two X-Git-Tag: v2.3-dev6~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7b2febde1d3dd1f9d48452e3c6daea1a7ff830a1;p=thirdparty%2Fhaproxy.git MINOR: listeners: split do_unbind_listener() in two The inner part now goes into the protocol and is used to decide how to unbind a given protocol's listener. The existing code which is able to also unbind the receiver was provided as a default function that we currently use everywhere. Some complex listeners like QUIC will use this to decide how to unbind without impacting existing connections, possibly by setting up other incoming paths for the traffic. --- diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index c30dc73fd9..399e2669a3 100644 --- a/include/haproxy/listener.h +++ b/include/haproxy/listener.h @@ -124,6 +124,12 @@ int listener_backlog(const struct listener *l); */ void listener_release(struct listener *l); +/* default function used to unbind a listener. This is for use by standard + * protocols working on top of accepted sockets. The receiver's rx_unbind() + * will automatically be used after the listener is disabled if the socket is + * still bound. This must be used under the listener's lock. + */ +void default_unbind_listener(struct listener *listener); /* * Registers the bind keyword list as a list of valid keywords for next * parsing sessions. diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 7411d6d3d0..a7d2429899 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -91,6 +91,7 @@ struct protocol { int (*listen)(struct listener *l, char *errmsg, int errlen); /* start a listener */ void (*enable)(struct listener *l); /* enable receipt of new connections */ void (*disable)(struct listener *l); /* disable receipt of new connections */ + void (*unbind)(struct listener *l); /* unbind the listener and possibly its receiver */ /* functions acting on the receiver */ void (*rx_enable)(struct receiver *rx); /* enable receiving on the receiver */ diff --git a/src/listener.c b/src/listener.c index b1c64371b1..3e305c73a9 100644 --- a/src/listener.c +++ b/src/listener.c @@ -538,18 +538,14 @@ void dequeue_proxy_listeners(struct proxy *px) } } -/* This function closes the listening socket for the specified listener, - * provided that it's already in a listening state. The listener enters the - * LI_ASSIGNED state, except if the FD is not closed, in which case it may - * remain in LI_LISTEN. Depending on the process' status (master or worker), - * the listener's bind options and the receiver's origin, it may or may not - * close the receiver's FD, according to what is provided at the receiver - * level. Must be called with the lock held. + +/* default function used to unbind a listener. This is for use by standard + * protocols working on top of accepted sockets. The receiver's rx_unbind() + * will automatically be used after the listener is disabled if the socket is + * still bound. This must be used under the listener's lock. */ -void do_unbind_listener(struct listener *listener) +void default_unbind_listener(struct listener *listener) { - MT_LIST_DEL(&listener->wait_queue); - if (listener->state <= LI_ASSIGNED) goto out_close; @@ -567,6 +563,20 @@ void do_unbind_listener(struct listener *listener) out_close: if (listener->rx.flags & RX_F_BOUND) listener->rx.proto->rx_unbind(&listener->rx); +} + +/* This function closes the listening socket for the specified listener, + * provided that it's already in a listening state. The protocol's unbind() + * is called to put the listener into LI_ASSIGNED or LI_LISTEN and handle + * the unbinding tasks. The listener enters then the LI_ASSIGNED state if + * the receiver is unbound. Must be called with the lock held. + */ +void do_unbind_listener(struct listener *listener) +{ + MT_LIST_DEL(&listener->wait_queue); + + if (listener->rx.proto->unbind) + listener->rx.proto->unbind(listener); /* we may have to downgrade the listener if the rx was closed */ if (!(listener->rx.flags & RX_F_BOUND) && listener->state > LI_ASSIGNED) diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 9eac2cc2c1..4ac5b7642a 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -72,6 +72,7 @@ static struct protocol proto_sockpair = { .listen = sockpair_bind_listener, .enable = sockpair_enable_listener, .disable = sockpair_disable_listener, + .unbind = default_unbind_listener, .rx_unbind = sock_unbind, .rx_enable = sock_enable, .rx_disable = sock_disable, diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 33eacbce0b..71d13c8b77 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -64,6 +64,7 @@ static struct protocol proto_tcpv4 = { .listen = tcp_bind_listener, .enable = tcp_enable_listener, .disable = tcp_disable_listener, + .unbind = default_unbind_listener, .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind, @@ -89,6 +90,7 @@ static struct protocol proto_tcpv6 = { .listen = tcp_bind_listener, .enable = tcp_enable_listener, .disable = tcp_disable_listener, + .unbind = default_unbind_listener, .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind, diff --git a/src/proto_udp.c b/src/proto_udp.c index 8c53c6201b..1c2477e719 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -60,6 +60,7 @@ static struct protocol proto_udp4 = { .listen = udp_bind_listener, .enable = udp_enable_listener, .disable = udp_disable_listener, + .unbind = default_unbind_listener, .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind, @@ -83,6 +84,7 @@ static struct protocol proto_udp6 = { .listen = udp_bind_listener, .enable = udp_enable_listener, .disable = udp_disable_listener, + .unbind = default_unbind_listener, .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind, diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 77415867af..04f12faa02 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -59,6 +59,7 @@ static struct protocol proto_unix = { .listen = uxst_bind_listener, .enable = uxst_enable_listener, .disable = uxst_disable_listener, + .unbind = default_unbind_listener, .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind,