From: Willy Tarreau Date: Thu, 15 Oct 2020 19:29:49 +0000 (+0200) Subject: MINOR: protocol: register the receiver's I/O handler and not the protocol's X-Git-Tag: v2.3-dev7~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a74cb38e7cdac7b032ca3b91fb6c7aee1d41680f;p=thirdparty%2Fhaproxy.git MINOR: protocol: register the receiver's I/O handler and not the protocol's Now we define a new sock_accept_iocb() for socket-based stream protocols and use it as a wrapper for listener_accept() which now takes a listener and not an FD anymore. This will allow the receiver's I/O cb to be redefined during registration, and more specifically to get rid of the hard-coded hacks in protocol_bind_all() made for syslog. The previous ->accept() callback in the protocol was removed since it doesn't have anything to do with accept() anymore but is more generic. A few places where listener_accept() was compared against the FD's IO callback for debugging purposes on the CLI were updated. --- diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index 24a126c2fc..722a9ea0e6 100644 --- a/include/haproxy/listener.h +++ b/include/haproxy/listener.h @@ -110,7 +110,7 @@ void __delete_listener(struct listener *listener); * to an accept. It tries to accept as many connections as possible, and for each * calls the listener's accept handler (generally the frontend's accept handler). */ -void listener_accept(int fd); +void listener_accept(struct listener *l); /* Returns a suitable value for a listener's backlog. It uses the listener's, * otherwise the frontend's backlog, otherwise the listener's maxconn, diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 5c9793b58c..d50c83882e 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -108,7 +108,6 @@ struct protocol { void (*default_iocb)(int fd); /* generic I/O handler (typically accept callback) */ /* functions acting on connections */ - void (*accept)(int fd); /* generic accept function */ int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */ struct list receivers; /* list of receivers using this protocol (under proto_lock) */ diff --git a/include/haproxy/sock.h b/include/haproxy/sock.h index 193d2e451b..6e81b1b22b 100644 --- a/include/haproxy/sock.h +++ b/include/haproxy/sock.h @@ -42,6 +42,7 @@ int sock_get_old_sockets(const char *unixsocket); int sock_find_compatible_fd(const struct receiver *rx); int sock_accepting_conn(const struct receiver *rx); struct connection *sock_accept_conn(struct listener *l, int *status); +void sock_accept_iocb(int fd); #endif /* _HAPROXY_SOCK_H */ diff --git a/src/cli.c b/src/cli.c index 7f4ea328a6..e39ef68b35 100644 --- a/src/cli.c +++ b/src/cli.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -1020,7 +1021,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) px = objt_proxy(((struct connection *)fdt.owner)->target); is_back = conn_is_back((struct connection *)fdt.owner); } - else if (fdt.iocb == listener_accept) + else if (fdt.iocb == sock_accept_iocb) li = fdt.owner; chunk_printf(&trash, @@ -1064,7 +1065,7 @@ static int cli_io_handler_show_fd(struct appctx *appctx) else chunk_appendf(&trash, " nomux"); } - else if (fdt.iocb == listener_accept) { + else if (fdt.iocb == sock_accept_iocb) { chunk_appendf(&trash, ") l.st=%s fe=%s", listener_state_str(li), li->bind_conf->frontend->id); @@ -1707,7 +1708,7 @@ static int _getsocks(char **args, char *payload, struct appctx *appctx, void *pr /* for now we can only retrieve namespaces and interfaces from * pure listeners. */ - if (fdtab[cur_fd].iocb == listener_accept) { + if (fdtab[cur_fd].iocb == sock_accept_iocb) { const struct listener *l = fdtab[cur_fd].owner; if (l->rx.settings->interface) { diff --git a/src/haproxy.c b/src/haproxy.c index 4ef79bc27a..83e57ce6e9 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2455,7 +2455,7 @@ void deinit(void) if (!fdtab || !fdtab[cur_fd].owner) continue; - if (fdtab[cur_fd].iocb == listener_accept) { + if (fdtab[cur_fd].iocb == &sock_accept_iocb) { struct listener *l = fdtab[cur_fd].owner; BUG_ON(l->state != LI_INIT); diff --git a/src/listener.c b/src/listener.c index 1cad1bb101..320fc5eb71 100644 --- a/src/listener.c +++ b/src/listener.c @@ -685,9 +685,8 @@ int listener_backlog(const struct listener *l) * to an accept. It tries to accept as many connections as possible, and for each * calls the listener's accept handler (generally the frontend's accept handler). */ -void listener_accept(int fd) +void listener_accept(struct listener *l) { - struct listener *l = fdtab[fd].owner; struct connection *cli_conn; struct proxy *p; unsigned int max_accept; @@ -697,8 +696,6 @@ void listener_accept(int fd) int expire; int ret; - if (!l) - return; p = l->bind_conf->frontend; /* if l->maxaccept is -1, then max_accept is UINT_MAX. It is not really diff --git a/src/mworker.c b/src/mworker.c index d45b357952..690f3f0257 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -334,7 +334,8 @@ restart_wait: /* This wrapper is called from the workers. It is registered instead of the * normal listener_accept() so the worker can exit() when it detects that the * master closed the IPC FD. If it's not a close, we just call the regular - * listener_accept() function */ + * listener_accept() function. + */ void mworker_accept_wrapper(int fd) { char c; @@ -351,7 +352,10 @@ void mworker_accept_wrapper(int fd) } break; } else if (ret > 0) { - listener_accept(fd); + struct listener *l = fdtab[fd].owner; + + if (l) + listener_accept(l); return; } else if (ret == 0) { /* At this step the master is down before diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 8be1093c3d..8e17460198 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -81,7 +81,7 @@ static struct protocol proto_sockpair = { .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_listening = sockpair_accepting_conn, - .accept = &listener_accept, + .default_iocb = &sock_accept_iocb, .connect = &sockpair_connect_server, .receivers = LIST_HEAD_INIT(proto_sockpair.receivers), .nb_receivers = 0, diff --git a/src/proto_tcp.c b/src/proto_tcp.c index cf1166415c..d872ed3182 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -74,7 +74,7 @@ static struct protocol proto_tcpv4 = { .rx_suspend = tcp_suspend_receiver, .rx_resume = tcp_resume_receiver, .rx_listening = sock_accepting_conn, - .accept = &listener_accept, + .default_iocb = &sock_accept_iocb, .connect = tcp_connect_server, .receivers = LIST_HEAD_INIT(proto_tcpv4.receivers), .nb_receivers = 0, @@ -104,7 +104,7 @@ static struct protocol proto_tcpv6 = { .rx_suspend = tcp_suspend_receiver, .rx_resume = tcp_resume_receiver, .rx_listening = sock_accepting_conn, - .accept = &listener_accept, + .default_iocb = &sock_accept_iocb, .connect = tcp_connect_server, .receivers = LIST_HEAD_INIT(proto_tcpv6.receivers), .nb_receivers = 0, diff --git a/src/proto_uxst.c b/src/proto_uxst.c index eb1cf9daa6..d33f8c3a7a 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -67,7 +67,7 @@ static struct protocol proto_unix = { .rx_unbind = sock_unbind, .rx_suspend = uxst_suspend_receiver, .rx_listening = sock_accepting_conn, - .accept = &listener_accept, + .default_iocb = &sock_accept_iocb, .connect = &uxst_connect_server, .receivers = LIST_HEAD_INIT(proto_unix.receivers), .nb_receivers = 0, diff --git a/src/protocol.c b/src/protocol.c index 82deaad4f8..18ca40a0db 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -78,12 +78,7 @@ int protocol_bind_all(int verbose) * a handler when creating the receiver yet, so we still * have to take care of special cases here. */ - handler = listener->rx.proto->accept; - if (!handler && listener->bind_conf->frontend->mode == PR_MODE_SYSLOG) { - extern void syslog_fd_handler(int); - handler = syslog_fd_handler; - } - + handler = listener->rx.iocb; lerr = proto->fam->bind(receiver, handler, &errmsg); err |= lerr; diff --git a/src/sock.c b/src/sock.c index 990db23a5a..d640190329 100644 --- a/src/sock.c +++ b/src/sock.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include #include @@ -613,6 +613,21 @@ int sock_accepting_conn(const struct receiver *rx) return opt_val; } +/* This is the FD handler IO callback for stream sockets configured for + * accepting incoming connections. It's a pass-through to listener_accept() + * which will iterate over the listener protocol's accept_conn() function. + * The FD's owner must be a listener. + */ +void sock_accept_iocb(int fd) +{ + struct listener *l = fdtab[fd].owner; + + if (!l) + return; + + listener_accept(l); +} + /* * Local variables: * c-indent-level: 8