MEDIUM: tcp-sample: Rely on addresses at the appropriate level in tcp samples

In src, src-port, dst and dst-port sample fetches, the client source and
destination addresses are retrieved from the appropriate level. It means
that, if the stream exits, we use the frontend stream-interface to get the
client source and destination addresses. Otherwise, the session is used. For
now, stream-interface or session addresses are never set. So, thanks to the
fallback mechanism, no changes are expected with this patch. But its purpose
is to rely on addresses at the appropriate level when set instead of those
at the connection level.
diff --git a/src/tcp_sample.c b/src/tcp_sample.c
index 0ea7d79..d167bde 100644
--- a/src/tcp_sample.c
+++ b/src/tcp_sample.c
@@ -39,37 +39,38 @@
 #include <haproxy/namespace.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/sample.h>
-#include <haproxy/session-t.h>
+#include <haproxy/session.h>
+#include <haproxy/stream_interface.h>
 #include <haproxy/tools.h>
 
-
 /* Fetch the connection's source IPv4/IPv6 address. Depending on the keyword, it
  * may be the frontend or the backend connection.
  */
 static int
 smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *conn;
+	const struct sockaddr_storage *src = NULL;
 
-	if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+	if (kw[0] == 'b') {
+		struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+					   ? cs_conn(__objt_check(smp->sess->origin)->cs)
+					   : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
+		if (conn && conn_get_src(conn))
+			src = conn_src(conn);
+	}
         else
-                conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
-			smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
+		src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
-	if (!conn)
+	if (!src)
 		return 0;
 
-	if (!conn_get_src(conn))
-		return 0;
-
-	switch (conn->src->ss_family) {
+	switch (src->ss_family) {
 	case AF_INET:
-		smp->data.u.ipv4 = ((struct sockaddr_in *)conn->src)->sin_addr;
+		smp->data.u.ipv4 = ((struct sockaddr_in *)src)->sin_addr;
 		smp->data.type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.u.ipv6 = ((struct sockaddr_in6 *)conn->src)->sin6_addr;
+		smp->data.u.ipv6 = ((struct sockaddr_in6 *)src)->sin6_addr;
 		smp->data.type = SMP_T_IPV6;
 		break;
 	default:
@@ -86,22 +87,23 @@
 static int
 smp_fetch_sport(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *conn;
+	const struct sockaddr_storage *src = NULL;
 
-	if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+	if (kw[0] == 'b') {
+		struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+					   ? cs_conn(__objt_check(smp->sess->origin)->cs)
+					   : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
+		if (conn && conn_get_src(conn))
+			src = conn_src(conn);
+	}
         else
-                conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
-			smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
+		src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
-	if (!conn)
+	if (!src)
 		return 0;
 
-	if (!conn_get_src(conn))
-		return 0;
-
 	smp->data.type = SMP_T_SINT;
-	if (!(smp->data.u.sint = get_host_port(conn->src)))
+	if (!(smp->data.u.sint = get_host_port(src)))
 		return 0;
 
 	smp->flags = 0;
@@ -114,27 +116,28 @@
 static int
 smp_fetch_dst(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *conn;
+	const struct sockaddr_storage *dst = NULL;
 
-	if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+	if (kw[0] == 'b') {
+		struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+					   ? cs_conn(__objt_check(smp->sess->origin)->cs)
+					   : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
+		if (conn && conn_get_dst(conn))
+			dst = conn_dst(conn);
+	}
         else
-                conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
-			smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
+		dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
-	if (!conn)
+	if (!dst)
 		return 0;
 
-	if (!conn_get_dst(conn))
-		return 0;
-
-	switch (conn->dst->ss_family) {
+	switch (dst->ss_family) {
 	case AF_INET:
-		smp->data.u.ipv4 = ((struct sockaddr_in *)conn->dst)->sin_addr;
+		smp->data.u.ipv4 = ((struct sockaddr_in *)dst)->sin_addr;
 		smp->data.type = SMP_T_IPV4;
 		break;
 	case AF_INET6:
-		smp->data.u.ipv6 = ((struct sockaddr_in6 *)conn->dst)->sin6_addr;
+		smp->data.u.ipv6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
 		smp->data.type = SMP_T_IPV6;
 		break;
 	default:
@@ -150,18 +153,15 @@
  */
 int smp_fetch_dst_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *conn = objt_conn(smp->sess->origin);
 	struct listener *li = smp->sess->listener;
-
-	if (!conn)
-		return 0;
+	const struct sockaddr_storage *dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
-	if (!conn_get_dst(conn))
+	if (!dst)
 		return 0;
 
 	smp->data.type = SMP_T_BOOL;
 	smp->flags = 0;
-	smp->data.u.sint = addr_is_local(li->rx.settings->netns, conn->dst);
+	smp->data.u.sint = addr_is_local(li->rx.settings->netns, dst);
 	return smp->data.u.sint >= 0;
 }
 
@@ -170,18 +170,15 @@
  */
 int smp_fetch_src_is_local(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *conn = objt_conn(smp->sess->origin);
 	struct listener *li = smp->sess->listener;
-
-	if (!conn)
-		return 0;
+	const struct sockaddr_storage *src = (smp->strm ? si_src(&smp->strm->si[0]) : sess_src(smp->sess));
 
-	if (!conn_get_src(conn))
+	if (!src)
 		return 0;
 
 	smp->data.type = SMP_T_BOOL;
 	smp->flags = 0;
-	smp->data.u.sint = addr_is_local(li->rx.settings->netns, conn->src);
+	smp->data.u.sint = addr_is_local(li->rx.settings->netns, src);
 	return smp->data.u.sint >= 0;
 }
 
@@ -191,22 +188,23 @@
 static int
 smp_fetch_dport(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct connection *conn;
+	const struct sockaddr_storage *dst = NULL;
 
-	if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
-                conn = (kw[0] == 'b') ? cs_conn(__objt_check(smp->sess->origin)->cs) : NULL;
+	if (kw[0] == 'b') {
+		struct connection *conn = ((obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+					   ? cs_conn(__objt_check(smp->sess->origin)->cs)
+					   : (smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)): NULL));
+		if (conn && conn_get_dst(conn))
+			dst = conn_dst(conn);
+	}
         else
-                conn = (kw[0] != 'b') ? objt_conn(smp->sess->origin) :
-			smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
+		dst = (smp->strm ? si_dst(&smp->strm->si[0]) : sess_dst(smp->sess));
 
-	if (!conn)
+	if (!dst)
 		return 0;
 
-	if (!conn_get_dst(conn))
-		return 0;
-
 	smp->data.type = SMP_T_SINT;
-	if (!(smp->data.u.sint = get_host_port(conn->dst)))
+	if (!(smp->data.u.sint = get_host_port(dst)))
 		return 0;
 
 	smp->flags = 0;