REORG: listener: move the listener's proto to the receiver

The receiver is the one which depends on the protocol while the listener
relies on the receiver. Let's move the protocol there. Since there's also
a list element to get back to the listener from the proto list, this list
element (proto_list) was moved as well. For now when scanning protos, we
still see listeners which are linked by their rx.proto_list part.
diff --git a/include/haproxy/listener-t.h b/include/haproxy/listener-t.h
index 2bc0d0c..d7c45d5 100644
--- a/include/haproxy/listener-t.h
+++ b/include/haproxy/listener-t.h
@@ -195,6 +195,8 @@
 struct receiver {
 	int fd;                          /* handle we receive from (fd only for now) */
 	unsigned int flags;              /* receiver options (RX_F_*) */
+	struct protocol *proto;          /* protocol this receiver belongs to */
+	struct list proto_list;          /* list in the protocol header */
 	/* warning: this struct is huge, keep it at the bottom */
 	struct sockaddr_storage addr;    /* the address the socket is bound to */
 };
@@ -210,7 +212,6 @@
 	int luid;			/* listener universally unique ID, used for SNMP */
 	int options;			/* socket options : LI_O_* */
 	struct fe_counters *counters;	/* statistics counters */
-	struct protocol *proto;		/* protocol this listener belongs to */
 	int nbconn;			/* current number of connections on this listener */
 	int maxconn;			/* maximum connections allowed on this listener */
 	unsigned int backlog;		/* if set, listen backlog */
@@ -235,7 +236,6 @@
 	struct list by_fe;              /* chaining in frontend's list of listeners */
 	struct list by_bind;            /* chaining in bind_conf's list of listeners */
 	struct bind_conf *bind_conf;	/* "bind" line settings, include SSL settings among other things */
-	struct list proto_list;         /* list in the protocol header */
 	struct receiver rx;             /* network receiver parts */
 	struct {
 		struct eb32_node id;	/* place in the tree of used IDs */
diff --git a/src/listener.c b/src/listener.c
index b62d6fd..1a8b5ad 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -296,11 +296,11 @@
 	if (l->state <= LI_ZOMBIE)
 		goto end;
 
-	if (l->proto->pause) {
+	if (l->rx.proto->pause) {
 		/* Returns < 0 in case of failure, 0 if the listener
 		 * was totally stopped, or > 0 if correctly paused.
 		 */
-		int ret = l->proto->pause(l);
+		int ret = l->rx.proto->pause(l);
 
 		if (ret < 0) {
 			ret = 0;
@@ -349,7 +349,7 @@
 		char msg[100];
 		int err;
 
-		err = l->proto->bind(l, msg, sizeof(msg));
+		err = l->rx.proto->bind(l, msg, sizeof(msg));
 		if (err & ERR_ALERT)
 			ha_alert("Resuming listener: %s\n", msg);
 		else if (err & ERR_WARN)
@@ -366,7 +366,7 @@
 		goto end;
 	}
 
-	if (l->proto->sock_prot == IPPROTO_TCP &&
+	if (l->rx.proto->sock_prot == IPPROTO_TCP &&
 	    l->state == LI_PAUSED &&
 	    listen(l->rx.fd, listener_backlog(l)) != 0) {
 		ret = 0;
@@ -442,7 +442,7 @@
 {
 	struct listener *listener;
 
-	list_for_each_entry(listener, &proto->listeners, proto_list)
+	list_for_each_entry(listener, &proto->listeners, rx.proto_list)
 		enable_listener(listener);
 	return ERR_NONE;
 }
@@ -459,7 +459,7 @@
 {
 	struct listener *listener;
 
-	list_for_each_entry(listener, &proto->listeners, proto_list)
+	list_for_each_entry(listener, &proto->listeners, rx.proto_list)
 		disable_listener(listener);
 	return ERR_NONE;
 }
@@ -596,8 +596,8 @@
 	HA_SPIN_LOCK(LISTENER_LOCK, &listener->lock);
 	if (listener->state == LI_ASSIGNED) {
 		listener->state = LI_INIT;
-		LIST_DEL(&listener->proto_list);
-		listener->proto->nb_listeners--;
+		LIST_DEL(&listener->rx.proto_list);
+		listener->rx.proto->nb_listeners--;
 		_HA_ATOMIC_SUB(&jobs, 1);
 		_HA_ATOMIC_SUB(&listeners, 1);
 	}
diff --git a/src/log.c b/src/log.c
index c1c6eda..702f443 100644
--- a/src/log.c
+++ b/src/log.c
@@ -3642,7 +3642,7 @@
 		}
 		list_for_each_entry(l, &bind_conf->listeners, by_bind) {
 			/* Currently, only UDP handlers are allowed */
-			if (l->proto->sock_domain != AF_CUST_UDP4 && l->proto->sock_domain != AF_CUST_UDP6) {
+			if (l->rx.proto->sock_domain != AF_CUST_UDP4 && l->rx.proto->sock_domain != AF_CUST_UDP6) {
 				ha_alert("parsing [%s:%d] : '%s %s' : error,  listening address must be prefixed using 'udp@', 'udp4@' or 'udp6@' %s.\n",
 				         file, linenum, args[0], args[1], args[2]);
 				err_code |= ERR_ALERT | ERR_FATAL;
diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c
index c736995..4030c33 100644
--- a/src/proto_sockpair.c
+++ b/src/proto_sockpair.c
@@ -80,8 +80,8 @@
 	if (listener->state != LI_INIT)
 		return;
 	listener->state = LI_ASSIGNED;
-	listener->proto = &proto_sockpair;
-	LIST_ADDQ(&proto_sockpair.listeners, &listener->proto_list);
+	listener->rx.proto = &proto_sockpair;
+	LIST_ADDQ(&proto_sockpair.listeners, &listener->rx.proto_list);
 	proto_sockpair.nb_listeners++;
 }
 
@@ -125,7 +125,7 @@
 
 	listener->state = LI_LISTEN;
 
-	fd_insert(fd, listener, listener->proto->accept,
+	fd_insert(fd, listener, listener->rx.proto->accept,
 	          thread_mask(listener->bind_conf->settings.bind_thread) & all_threads_mask);
 
 	return err;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index a97cdc3..79b68b4 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -739,7 +739,7 @@
                 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
 #endif
 
-	if (!ext && bind(fd, (struct sockaddr *)&listener->rx.addr, listener->proto->sock_addrlen) == -1) {
+	if (!ext && bind(fd, (struct sockaddr *)&listener->rx.addr, listener->rx.proto->sock_addrlen) == -1) {
 		err |= ERR_RETRYABLE | ERR_ALERT;
 		msg = "cannot bind socket";
 		goto tcp_close_return;
@@ -768,7 +768,7 @@
 	listener->rx.fd = fd;
 	listener->state = LI_LISTEN;
 
-	fd_insert(fd, listener, listener->proto->accept,
+	fd_insert(fd, listener, listener->rx.proto->accept,
 	          thread_mask(listener->bind_conf->settings.bind_thread) & all_threads_mask);
 
 	/* for now, all regularly bound TCP listeners are exportable */
@@ -801,9 +801,9 @@
 	if (listener->state != LI_INIT)
 		return;
 	listener->state = LI_ASSIGNED;
-	listener->proto = &proto_tcpv4;
+	listener->rx.proto = &proto_tcpv4;
 	((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
-	LIST_ADDQ(&proto_tcpv4.listeners, &listener->proto_list);
+	LIST_ADDQ(&proto_tcpv4.listeners, &listener->rx.proto_list);
 	proto_tcpv4.nb_listeners++;
 }
 
@@ -819,9 +819,9 @@
 	if (listener->state != LI_INIT)
 		return;
 	listener->state = LI_ASSIGNED;
-	listener->proto = &proto_tcpv6;
+	listener->rx.proto = &proto_tcpv6;
 	((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
-	LIST_ADDQ(&proto_tcpv6.listeners, &listener->proto_list);
+	LIST_ADDQ(&proto_tcpv6.listeners, &listener->rx.proto_list);
 	proto_tcpv6.nb_listeners++;
 }
 
diff --git a/src/proto_udp.c b/src/proto_udp.c
index 38be905..5cd7b73 100644
--- a/src/proto_udp.c
+++ b/src/proto_udp.c
@@ -184,7 +184,7 @@
 	struct sockaddr_storage addr_inet = listener->rx.addr;
 
 	/* force to classic sock family */
-	addr_inet.ss_family = listener->proto->sock_family;
+	addr_inet.ss_family = listener->rx.proto->sock_family;
 
 	/* ensure we never return garbage */
 	if (errlen)
@@ -200,7 +200,10 @@
 	 * IPPROTO (sockaddr is not enough)
 	 */
 
-	fd = my_socketat(listener->bind_conf->settings.netns, listener->proto->sock_family, listener->proto->sock_type, listener->proto->sock_prot);
+	fd = my_socketat(listener->bind_conf->settings.netns,
+	                 listener->rx.proto->sock_family,
+	                 listener->rx.proto->sock_type,
+	                 listener->rx.proto->sock_prot);
 	if (fd == -1) {
 		err |= ERR_RETRYABLE | ERR_ALERT;
 		msg = "cannot create listening socket";
@@ -268,7 +271,7 @@
                 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
 #endif
 
-	if (bind(fd, (struct sockaddr *)&addr_inet, listener->proto->sock_addrlen) < 0) {
+	if (bind(fd, (struct sockaddr *)&addr_inet, listener->rx.proto->sock_addrlen) < 0) {
 		err |= ERR_RETRYABLE | ERR_ALERT;
 		msg = "cannot bind socket";
 		goto udp_close_return;
@@ -310,9 +313,9 @@
 	if (listener->state != LI_INIT)
 		return;
 	listener->state = LI_ASSIGNED;
-	listener->proto = &proto_udp4;
+	listener->rx.proto = &proto_udp4;
 	((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
-	LIST_ADDQ(&proto_udp4.listeners, &listener->proto_list);
+	LIST_ADDQ(&proto_udp4.listeners, &listener->rx.proto_list);
 	proto_udp4.nb_listeners++;
 }
 
@@ -325,9 +328,9 @@
 	if (listener->state != LI_INIT)
 		return;
 	listener->state = LI_ASSIGNED;
-	listener->proto = &proto_udp6;
+	listener->rx.proto = &proto_udp6;
 	((struct sockaddr_in *)(&listener->rx.addr))->sin_port = htons(port);
-	LIST_ADDQ(&proto_udp6.listeners, &listener->proto_list);
+	LIST_ADDQ(&proto_udp6.listeners, &listener->rx.proto_list);
 	proto_udp6.nb_listeners++;
 }
 
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 9b5a28d..a63f183 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -261,7 +261,7 @@
 	listener->rx.fd = fd;
 	listener->state = LI_LISTEN;
 
-	fd_insert(fd, listener, listener->proto->accept,
+	fd_insert(fd, listener, listener->rx.proto->accept,
 	          thread_mask(listener->bind_conf->settings.bind_thread) & all_threads_mask);
 
 	/* for now, all regularly bound UNIX listeners are exportable */
@@ -303,8 +303,8 @@
 	if (listener->state != LI_INIT)
 		return;
 	listener->state = LI_ASSIGNED;
-	listener->proto = &proto_unix;
-	LIST_ADDQ(&proto_unix.listeners, &listener->proto_list);
+	listener->rx.proto = &proto_unix;
+	LIST_ADDQ(&proto_unix.listeners, &listener->rx.proto_list);
 	proto_unix.nb_listeners++;
 }
 
diff --git a/src/protocol.c b/src/protocol.c
index a942e44..bf1b1c5 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -66,7 +66,7 @@
 	err = 0;
 	HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
 	list_for_each_entry(proto, &protocols, list) {
-		list_for_each_entry(listener, &proto->listeners, proto_list) {
+		list_for_each_entry(listener, &proto->listeners, rx.proto_list) {
 			lerr = proto->bind(listener, msg, sizeof(msg));
 
 			/* errors are reported if <verbose> is set or if they are fatal */
@@ -106,7 +106,7 @@
 	err = 0;
 	HA_SPIN_LOCK(PROTO_LOCK, &proto_lock);
 	list_for_each_entry(proto, &protocols, list) {
-		list_for_each_entry(listener, &proto->listeners, proto_list)
+		list_for_each_entry(listener, &proto->listeners, rx.proto_list)
 			unbind_listener(listener);
 	}
 	HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
diff --git a/src/session.c b/src/session.c
index 871a6ac..58eacd4 100644
--- a/src/session.c
+++ b/src/session.c
@@ -155,7 +155,7 @@
 	cli_conn->flags |= CO_FL_ADDR_FROM_SET;
 	cli_conn->proxy_netns = l->bind_conf->settings.netns;
 
-	conn_prepare(cli_conn, l->proto, l->bind_conf->xprt);
+	conn_prepare(cli_conn, l->rx.proto, l->bind_conf->xprt);
 	conn_ctrl_init(cli_conn);
 
 	/* wait for a PROXY protocol header */
@@ -207,8 +207,8 @@
 		 *  - HEALTH mode without HTTP check => just send "OK"
 		 *  - TCP mode from monitoring address => just close
 		 */
-		if (l->proto->drain)
-			l->proto->drain(cfd);
+		if (l->rx.proto->drain)
+			l->rx.proto->drain(cfd);
 		if (p->mode == PR_MODE_HTTP ||
 		    (p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_TCPCHK_CHK &&
 		     (p->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK))
diff --git a/src/sock.c b/src/sock.c
index 161e723..8bdc3ea 100644
--- a/src/sock.c
+++ b/src/sock.c
@@ -363,7 +363,7 @@
 	int ns_namelen = 0;
 	int ret = -1;
 
-	if (!l->proto->addrcmp)
+	if (!l->rx.proto->addrcmp)
 		return -1;
 
 	/* WT: this is not the right way to do it, it is temporary for the
@@ -400,7 +400,7 @@
 #ifdef USE_NS
 		    (!ns_namelen || strcmp(l->bind_conf->settings.netns->node.key, xfer_sock->namespace) == 0) &&
 #endif
-		    l->proto->addrcmp(&xfer_sock->addr, &l->rx.addr) == 0)
+		    l->rx.proto->addrcmp(&xfer_sock->addr, &l->rx.addr) == 0)
 			break;
 		xfer_sock = xfer_sock->next;
 	}
diff --git a/src/stream.c b/src/stream.c
index f282665..b298d7b 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -2823,7 +2823,7 @@
 			     tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
 			     tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(strm->logs.accept_date.tv_usec),
 			     strm->uniq_id,
-			     strm_li(strm) ? strm_li(strm)->proto->name : "?");
+			     strm_li(strm) ? strm_li(strm)->rx.proto->name : "?");
 
 		conn = objt_conn(strm_orig(strm));
 		switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {
@@ -3232,7 +3232,7 @@
 			chunk_appendf(&trash,
 				     "%p: proto=%s",
 				     curr_strm,
-				     strm_li(curr_strm) ? strm_li(curr_strm)->proto->name : "?");
+				     strm_li(curr_strm) ? strm_li(curr_strm)->rx.proto->name : "?");
 
 			conn = objt_conn(strm_orig(curr_strm));
 			switch (conn && conn_get_src(conn) ? addr_to_str(conn->src, pn, sizeof(pn)) : AF_UNSPEC) {