From 7b2febde1d3dd1f9d48452e3c6daea1a7ff830a1 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 9 Oct 2020 17:18:29 +0200 Subject: [PATCH] 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. --- include/haproxy/listener.h | 6 ++++++ include/haproxy/protocol-t.h | 1 + src/listener.c | 32 +++++++++++++++++++++----------- src/proto_sockpair.c | 1 + src/proto_tcp.c | 2 ++ src/proto_udp.c | 2 ++ src/proto_uxst.c | 1 + 7 files changed, 34 insertions(+), 11 deletions(-) diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index c30dc73fd..399e2669a 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 7411d6d3d..a7d242989 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 b1c64371b..3e305c73a 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. - */ -void do_unbind_listener(struct listener *listener) -{ - MT_LIST_DEL(&listener->wait_queue); +/* 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) +{ 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 9eac2cc2c..4ac5b7642 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 33eacbce0..71d13c8b7 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 8c53c6201..1c2477e71 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 77415867a..04f12faa0 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,