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,