MINOR: backend: rewrite alloc of stream target address

Change the API of the function used to allocate the stream target
address. This is done in order to be able to allocate the destination
address and use it to reuse a connection sharing with the same address.
In particular, the flag stream SF_ADDR_SET is now set outside of the
function.
This commit is contained in:
Amaury Denoyelle 2021-01-11 15:24:31 +01:00
parent e676239922
commit 68cf3959b3

View File

@ -827,36 +827,32 @@ out_ok:
return err; return err;
} }
/* /* Allocate an address for the destination endpoint
* This function assigns a server address to a stream, and sets SF_ADDR_SET.
* The address is taken from the currently assigned server, or from the * The address is taken from the currently assigned server, or from the
* dispatch or transparent address. * dispatch or transparent address.
* *
* It may return : * Returns SRV_STATUS_OK on success.
* SRV_STATUS_OK if everything is OK. * On error, the allocated address is freed and SRV_STATUS_INTERNAL is returned.
* SRV_STATUS_INTERNAL for other unrecoverable errors.
*
* Upon successful return, the stream flag SF_ADDR_SET is set. This flag is
* not cleared, so it's to the caller to clear it if required.
*/ */
int assign_server_address(struct stream *s) static int alloc_dst_address(struct sockaddr_storage **ss,
struct server *srv, struct stream *s)
{ {
struct connection *cli_conn = objt_conn(strm_orig(s)); struct connection *cli_conn = objt_conn(strm_orig(s));
DPRINTF(stderr,"assign_server_address : s=%p\n",s); *ss = NULL;
if (!sockaddr_alloc(&s->target_addr, NULL, 0))
return SRV_STATUS_INTERNAL;
if ((s->flags & SF_DIRECT) || (s->be->lbprm.algo & BE_LB_KIND)) { if ((s->flags & SF_DIRECT) || (s->be->lbprm.algo & BE_LB_KIND)) {
/* A server is necessarily known for this stream */ /* A server is necessarily known for this stream */
if (!(s->flags & SF_ASSIGNED)) if (!(s->flags & SF_ASSIGNED))
return SRV_STATUS_INTERNAL; return SRV_STATUS_INTERNAL;
*s->target_addr = __objt_server(s->target)->addr; if (!sockaddr_alloc(ss, NULL, 0))
set_host_port(s->target_addr, __objt_server(s->target)->svc_port); return SRV_STATUS_INTERNAL;
if (!is_addr(s->target_addr) && cli_conn) { **ss = srv->addr;
set_host_port(*ss, srv->svc_port);
if (!is_addr(*ss) && cli_conn) {
/* if the server has no address, we use the same address /* if the server has no address, we use the same address
* the client asked, which is handy for remapping ports * the client asked, which is handy for remapping ports
* locally on multiple addresses at once. Nothing is done * locally on multiple addresses at once. Nothing is done
@ -865,15 +861,17 @@ int assign_server_address(struct stream *s)
if (!conn_get_dst(cli_conn)) { if (!conn_get_dst(cli_conn)) {
/* do nothing if we can't retrieve the address */ /* do nothing if we can't retrieve the address */
} else if (cli_conn->dst->ss_family == AF_INET) { } else if (cli_conn->dst->ss_family == AF_INET) {
((struct sockaddr_in *)s->target_addr)->sin_addr = ((struct sockaddr_in *)cli_conn->dst)->sin_addr; ((struct sockaddr_in *)*ss)->sin_addr =
((struct sockaddr_in *)cli_conn->dst)->sin_addr;
} else if (cli_conn->dst->ss_family == AF_INET6) { } else if (cli_conn->dst->ss_family == AF_INET6) {
((struct sockaddr_in6 *)s->target_addr)->sin6_addr = ((struct sockaddr_in6 *)cli_conn->dst)->sin6_addr; ((struct sockaddr_in6 *)*ss)->sin6_addr =
((struct sockaddr_in6 *)cli_conn->dst)->sin6_addr;
} }
} }
/* if this server remaps proxied ports, we'll use /* if this server remaps proxied ports, we'll use
* the port the client connected to with an offset. */ * the port the client connected to with an offset. */
if ((__objt_server(s->target)->flags & SRV_F_MAPPORTS) && cli_conn) { if ((srv->flags & SRV_F_MAPPORTS) && cli_conn) {
int base_port; int base_port;
if (conn_get_dst(cli_conn)) { if (conn_get_dst(cli_conn)) {
@ -881,20 +879,26 @@ int assign_server_address(struct stream *s)
base_port = get_host_port(cli_conn->dst); base_port = get_host_port(cli_conn->dst);
/* Second, assign the outgoing connection's port */ /* Second, assign the outgoing connection's port */
base_port += get_host_port(s->target_addr); base_port += get_host_port(*ss);
set_host_port(s->target_addr, base_port); set_host_port(*ss, base_port);
} }
} }
} }
else if (s->be->options & PR_O_DISPATCH) { else if (s->be->options & PR_O_DISPATCH) {
if (!sockaddr_alloc(ss, NULL, 0))
return SRV_STATUS_INTERNAL;
/* connect to the defined dispatch addr */ /* connect to the defined dispatch addr */
*s->target_addr = s->be->dispatch_addr; **ss = s->be->dispatch_addr;
} }
else if ((s->be->options & PR_O_TRANSP) && cli_conn) { else if ((s->be->options & PR_O_TRANSP) && cli_conn) {
if (!sockaddr_alloc(ss, NULL, 0))
return SRV_STATUS_INTERNAL;
/* in transparent mode, use the original dest addr if no dispatch specified */ /* in transparent mode, use the original dest addr if no dispatch specified */
if (conn_get_dst(cli_conn) && if (conn_get_dst(cli_conn) &&
(cli_conn->dst->ss_family == AF_INET || cli_conn->dst->ss_family == AF_INET6)) (cli_conn->dst->ss_family == AF_INET || cli_conn->dst->ss_family == AF_INET6))
*s->target_addr = *cli_conn->dst; **ss = *cli_conn->dst;
} }
else if (s->be->options & PR_O_HTTP_PROXY) { else if (s->be->options & PR_O_HTTP_PROXY) {
/* If HTTP PROXY option is set, then server is already assigned /* If HTTP PROXY option is set, then server is already assigned
@ -905,7 +909,6 @@ int assign_server_address(struct stream *s)
return SRV_STATUS_INTERNAL; return SRV_STATUS_INTERNAL;
} }
s->flags |= SF_ADDR_SET;
return SRV_STATUS_OK; return SRV_STATUS_OK;
} }
@ -1467,11 +1470,13 @@ skip_reuse:
} }
if (!(s->flags & SF_ADDR_SET)) { if (!(s->flags & SF_ADDR_SET)) {
err = assign_server_address(s); err = alloc_dst_address(&s->target_addr, srv, s);
if (err != SRV_STATUS_OK) { if (err != SRV_STATUS_OK) {
conn_free(srv_conn); conn_free(srv_conn);
return SF_ERR_INTERNAL; return SF_ERR_INTERNAL;
} }
s->flags |= SF_ADDR_SET;
} }
/* copy the target address into the connection */ /* copy the target address into the connection */