MINOR: receiver: add a receiver-specific flag to indicate the socket is bound

In order to split the receiver from the listener, we'll need to know that
a socket is already bound and ready to receive. We used to do that via
tha LI_O_ASSIGNED state but that's not sufficient anymore since the
receiver might not belong to a listener anymore. The new RX_F_BOUND flag
is used for this.
This commit is contained in:
Willy Tarreau 2020-09-01 10:47:07 +02:00
parent 818a92e87a
commit 0b9150155e
6 changed files with 24 additions and 0 deletions

View File

@ -29,6 +29,9 @@
#include <haproxy/namespace-t.h> #include <haproxy/namespace-t.h>
#include <haproxy/thread.h> #include <haproxy/thread.h>
/* Bit values for receiver->options */
#define RX_F_BOUND 0x00000001 /* receiver already bound */
/* All the settings that are used to configure a receiver */ /* All the settings that are used to configure a receiver */
struct rx_settings { struct rx_settings {
unsigned long bind_proc; /* bitmask of processes allowed to use these listeners */ unsigned long bind_proc; /* bitmask of processes allowed to use these listeners */

View File

@ -505,6 +505,7 @@ void do_unbind_listener(struct listener *listener, int do_close)
fd_stop_both(listener->rx.fd); fd_stop_both(listener->rx.fd);
if (do_close) { if (do_close) {
fd_delete(listener->rx.fd); fd_delete(listener->rx.fd);
listener->rx.flags &= ~RX_F_BOUND;
listener->rx.fd = -1; listener->rx.fd = -1;
} }
} }

View File

@ -106,6 +106,9 @@ static int sockpair_bind_listener(struct listener *listener, char *errmsg, int e
if (listener->state != LI_ASSIGNED) if (listener->state != LI_ASSIGNED)
return ERR_NONE; /* already bound */ return ERR_NONE; /* already bound */
if (listener->rx.flags & RX_F_BOUND)
goto bound;
if (listener->rx.fd == -1) { if (listener->rx.fd == -1) {
err |= ERR_FATAL | ERR_ALERT; err |= ERR_FATAL | ERR_ALERT;
msg = "sockpair can be only used with inherited FDs"; msg = "sockpair can be only used with inherited FDs";
@ -122,7 +125,9 @@ static int sockpair_bind_listener(struct listener *listener, char *errmsg, int e
msg = "cannot make sockpair non-blocking"; msg = "cannot make sockpair non-blocking";
goto err_return; goto err_return;
} }
listener->rx.flags |= RX_F_BOUND;
bound:
listener->state = LI_LISTEN; listener->state = LI_LISTEN;
fd_insert(fd, listener, listener->rx.proto->accept, fd_insert(fd, listener, listener->rx.proto->accept,

View File

@ -569,6 +569,9 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
err = ERR_NONE; err = ERR_NONE;
if (listener->rx.flags & RX_F_BOUND)
goto bound;
if (listener->rx.fd == -1) if (listener->rx.fd == -1)
listener->rx.fd = sock_find_compatible_fd(listener); listener->rx.fd = sock_find_compatible_fd(listener);
@ -744,7 +747,9 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
msg = "cannot bind socket"; msg = "cannot bind socket";
goto tcp_close_return; goto tcp_close_return;
} }
listener->rx.flags |= RX_F_BOUND;
bound:
ready = 0; ready = 0;
ready_len = sizeof(ready); ready_len = sizeof(ready);
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &ready, &ready_len) == -1) if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &ready, &ready_len) == -1)

View File

@ -195,6 +195,9 @@ int udp_bind_listener(struct listener *listener, char *errmsg, int errlen)
err = ERR_NONE; err = ERR_NONE;
if (listener->rx.flags & RX_F_BOUND)
goto bound;
/* TODO: Implement reuse fd. Take care that to identify fd to reuse /* TODO: Implement reuse fd. Take care that to identify fd to reuse
* listeners uses a special AF_CUST_ family and we MUST consider * listeners uses a special AF_CUST_ family and we MUST consider
* IPPROTO (sockaddr is not enough) * IPPROTO (sockaddr is not enough)
@ -276,7 +279,9 @@ int udp_bind_listener(struct listener *listener, char *errmsg, int errlen)
msg = "cannot bind socket"; msg = "cannot bind socket";
goto udp_close_return; goto udp_close_return;
} }
listener->rx.flags |= RX_F_BOUND;
bound:
/* the socket is ready */ /* the socket is ready */
listener->rx.fd = fd; listener->rx.fd = fd;
listener->state = LI_LISTEN; listener->state = LI_LISTEN;

View File

@ -109,6 +109,9 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errle
if (listener->state != LI_ASSIGNED) if (listener->state != LI_ASSIGNED)
return ERR_NONE; /* already bound */ return ERR_NONE; /* already bound */
if (listener->rx.flags & RX_F_BOUND)
goto bound;
if (listener->rx.fd == -1) if (listener->rx.fd == -1)
listener->rx.fd = sock_find_compatible_fd(listener); listener->rx.fd = sock_find_compatible_fd(listener);
path = ((struct sockaddr_un *)&listener->rx.addr)->sun_path; path = ((struct sockaddr_un *)&listener->rx.addr)->sun_path;
@ -230,7 +233,9 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errle
msg = "cannot change UNIX socket ownership"; msg = "cannot change UNIX socket ownership";
goto err_unlink_temp; goto err_unlink_temp;
} }
listener->rx.flags |= RX_F_BOUND;
bound:
ready = 0; ready = 0;
ready_len = sizeof(ready); ready_len = sizeof(ready);
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &ready, &ready_len) == -1) if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &ready, &ready_len) == -1)