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 24a126c..722a9ea 100644
--- a/include/haproxy/listener.h
+++ b/include/haproxy/listener.h
@@ -110,7 +110,7 @@
  * 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 5c9793b..d50c838 100644
--- a/include/haproxy/protocol-t.h
+++ b/include/haproxy/protocol-t.h
@@ -108,7 +108,6 @@
 	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 193d2e4..6e81b1b 100644
--- a/include/haproxy/sock.h
+++ b/include/haproxy/sock.h
@@ -42,6 +42,7 @@
 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 7f4ea32..e39ef68 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -53,6 +53,7 @@
 #include <haproxy/sample-t.h>
 #include <haproxy/server.h>
 #include <haproxy/session.h>
+#include <haproxy/sock.h>
 #include <haproxy/stats-t.h>
 #include <haproxy/stream.h>
 #include <haproxy/stream_interface.h>
@@ -1020,7 +1021,7 @@
 			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 @@
 			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 @@
 		/* 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 4ef79bc..83e57ce 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2455,7 +2455,7 @@
 		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 1cad1bb..320fc5e 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -685,9 +685,8 @@
  * 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 @@
 	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 d45b357..690f3f0 100644
--- a/src/mworker.c
+++ b/src/mworker.c
@@ -334,7 +334,8 @@
 /* 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 @@
 			}
 			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 8be1093..8e17460 100644
--- a/src/proto_sockpair.c
+++ b/src/proto_sockpair.c
@@ -81,7 +81,7 @@
 	.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 cf11664..d872ed3 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -74,7 +74,7 @@
 	.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 @@
 	.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 eb1cf9d..d33f8c3 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -67,7 +67,7 @@
 	.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 82deaad..18ca40a 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -78,12 +78,7 @@
 			 * 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 990db23..d640190 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -27,7 +27,7 @@
 
 #include <haproxy/api.h>
 #include <haproxy/connection.h>
-#include <haproxy/listener-t.h>
+#include <haproxy/listener.h>
 #include <haproxy/log.h>
 #include <haproxy/namespace.h>
 #include <haproxy/sock.h>
@@ -613,6 +613,21 @@
 	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