From: Christopher Faulet Date: Fri, 1 Apr 2022 11:22:50 +0000 (+0200) Subject: MINOR: stream-int/connection: Move conn_si_send_proxy() in the connection scope X-Git-Tag: v2.6-dev6~62 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa91d6292b20db5c4f3ff91fc34efa9a978cdb43;p=thirdparty%2Fhaproxy.git MINOR: stream-int/connection: Move conn_si_send_proxy() in the connection scope conn_si_send_proxy() function is renamed conn_send_proxy() and moved in connection.c --- diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index 080ef4cfd1..8240a6d40b 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -50,6 +50,7 @@ extern struct mux_stopping_data mux_stopping_data[MAX_THREADS]; /* receive a PROXY protocol header over a connection */ int conn_recv_proxy(struct connection *conn, int flag); +int conn_send_proxy(struct connection *conn, unsigned int flag); int make_proxy_line(char *buf, int buf_len, struct server *srv, struct connection *remote, struct stream *strm); int conn_append_debug_info(struct buffer *buf, const struct connection *conn, const char *pfx); diff --git a/include/haproxy/stream_interface.h b/include/haproxy/stream_interface.h index 93fffff924..f0c16c799a 100644 --- a/include/haproxy/stream_interface.h +++ b/include/haproxy/stream_interface.h @@ -40,7 +40,6 @@ struct stream_interface *si_new(struct conn_stream *cs); void si_free(struct stream_interface *si); /* main event functions used to move data between sockets and buffers */ -int conn_si_send_proxy(struct connection *conn, unsigned int flag); void si_applet_wake_cb(struct stream_interface *si); void si_update_rx(struct stream_interface *si); void si_update_tx(struct stream_interface *si); diff --git a/src/connection.c b/src/connection.c index 227e9d9a81..35549ee806 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1163,6 +1163,101 @@ int conn_recv_proxy(struct connection *conn, int flag) return 0; } +/* This callback is used to send a valid PROXY protocol line to a socket being + * established. It returns 0 if it fails in a fatal way or needs to poll to go + * further, otherwise it returns non-zero and removes itself from the connection's + * flags (the bit is provided in by the caller). It is designed to be + * called by the connection handler and relies on it to commit polling changes. + * Note that it can emit a PROXY line by relying on the other end's address + * when the connection is attached to a stream interface, or by resolving the + * local address otherwise (also called a LOCAL line). + */ +int conn_send_proxy(struct connection *conn, unsigned int flag) +{ + if (!conn_ctrl_ready(conn)) + goto out_error; + + /* If we have a PROXY line to send, we'll use this to validate the + * connection, in which case the connection is validated only once + * we've sent the whole proxy line. Otherwise we use connect(). + */ + if (conn->send_proxy_ofs) { + struct conn_stream *cs; + int ret; + + /* If there is no mux attached to the connection, it means the + * connection context is a conn-stream. + */ + cs = (conn->mux ? cs_conn_get_first(conn) : conn->ctx); + + /* The target server expects a PROXY line to be sent first. + * If the send_proxy_ofs is negative, it corresponds to the + * offset to start sending from then end of the proxy string + * (which is recomputed every time since it's constant). If + * it is positive, it means we have to send from the start. + * We can only send a "normal" PROXY line when the connection + * is attached to a stream interface. Otherwise we can only + * send a LOCAL line (eg: for use with health checks). + */ + + if (cs && cs_strm(cs)) { + ret = make_proxy_line(trash.area, trash.size, + objt_server(conn->target), + cs_conn(cs_opposite(cs)), + __cs_strm(cs)); + } + else { + /* The target server expects a LOCAL line to be sent first. Retrieving + * local or remote addresses may fail until the connection is established. + */ + if (!conn_get_src(conn) || !conn_get_dst(conn)) + goto out_wait; + + ret = make_proxy_line(trash.area, trash.size, + objt_server(conn->target), conn, + NULL); + } + + if (!ret) + goto out_error; + + if (conn->send_proxy_ofs > 0) + conn->send_proxy_ofs = -ret; /* first call */ + + /* we have to send trash from (ret+sp for -sp bytes). If the + * data layer has a pending write, we'll also set MSG_MORE. + */ + ret = conn_ctrl_send(conn, + trash.area + ret + conn->send_proxy_ofs, + -conn->send_proxy_ofs, + (conn->subs && conn->subs->events & SUB_RETRY_SEND) ? CO_SFL_MSG_MORE : 0); + + if (ret < 0) + goto out_error; + + conn->send_proxy_ofs += ret; /* becomes zero once complete */ + if (conn->send_proxy_ofs != 0) + goto out_wait; + + /* OK we've sent the whole line, we're connected */ + } + + /* The connection is ready now, simply return and let the connection + * handler notify upper layers if needed. + */ + conn->flags &= ~CO_FL_WAIT_L4_CONN; + conn->flags &= ~flag; + return 1; + + out_error: + /* Write error on the file descriptor */ + conn->flags |= CO_FL_ERROR; + return 0; + + out_wait: + return 0; +} + /* This handshake handler waits a NetScaler Client IP insertion header * at the beginning of the raw data stream. The header format is * described in doc/netscaler-client-ip-insertion-protocol.txt diff --git a/src/stream_interface.c b/src/stream_interface.c index 85e2b6190d..95985b76d2 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -269,102 +269,6 @@ static void cs_app_chk_snd(struct conn_stream *cs) task_wakeup(cs_strm_task(cs), TASK_WOKEN_IO); } -/* This callback is used to send a valid PROXY protocol line to a socket being - * established. It returns 0 if it fails in a fatal way or needs to poll to go - * further, otherwise it returns non-zero and removes itself from the connection's - * flags (the bit is provided in by the caller). It is designed to be - * called by the connection handler and relies on it to commit polling changes. - * Note that it can emit a PROXY line by relying on the other end's address - * when the connection is attached to a stream interface, or by resolving the - * local address otherwise (also called a LOCAL line). - */ -int conn_si_send_proxy(struct connection *conn, unsigned int flag) -{ - if (!conn_ctrl_ready(conn)) - goto out_error; - - /* If we have a PROXY line to send, we'll use this to validate the - * connection, in which case the connection is validated only once - * we've sent the whole proxy line. Otherwise we use connect(). - */ - if (conn->send_proxy_ofs) { - const struct conn_stream *cs; - int ret; - - /* If there is no mux attached to the connection, it means the - * connection context is a conn-stream. - */ - cs = (conn->mux ? cs_conn_get_first(conn) : conn->ctx); - - /* The target server expects a PROXY line to be sent first. - * If the send_proxy_ofs is negative, it corresponds to the - * offset to start sending from then end of the proxy string - * (which is recomputed every time since it's constant). If - * it is positive, it means we have to send from the start. - * We can only send a "normal" PROXY line when the connection - * is attached to a stream interface. Otherwise we can only - * send a LOCAL line (eg: for use with health checks). - */ - - if (cs && cs->data_cb == &si_conn_cb) { - ret = make_proxy_line(trash.area, trash.size, - objt_server(conn->target), - cs_conn(si_opposite(cs_si(cs))->cs), - cs_strm(cs)); - } - else { - /* The target server expects a LOCAL line to be sent first. Retrieving - * local or remote addresses may fail until the connection is established. - */ - if (!conn_get_src(conn) || !conn_get_dst(conn)) - goto out_wait; - - ret = make_proxy_line(trash.area, trash.size, - objt_server(conn->target), conn, - NULL); - } - - if (!ret) - goto out_error; - - if (conn->send_proxy_ofs > 0) - conn->send_proxy_ofs = -ret; /* first call */ - - /* we have to send trash from (ret+sp for -sp bytes). If the - * data layer has a pending write, we'll also set MSG_MORE. - */ - ret = conn_ctrl_send(conn, - trash.area + ret + conn->send_proxy_ofs, - -conn->send_proxy_ofs, - (conn->subs && conn->subs->events & SUB_RETRY_SEND) ? CO_SFL_MSG_MORE : 0); - - if (ret < 0) - goto out_error; - - conn->send_proxy_ofs += ret; /* becomes zero once complete */ - if (conn->send_proxy_ofs != 0) - goto out_wait; - - /* OK we've sent the whole line, we're connected */ - } - - /* The connection is ready now, simply return and let the connection - * handler notify upper layers if needed. - */ - conn->flags &= ~CO_FL_WAIT_L4_CONN; - conn->flags &= ~flag; - return 1; - - out_error: - /* Write error on the file descriptor */ - conn->flags |= CO_FL_ERROR; - return 0; - - out_wait: - return 0; -} - - /* This function is the equivalent to si_update() except that it's * designed to be called from outside the stream handlers, typically the lower * layers (applets, connections) after I/O completion. After updating the stream diff --git a/src/xprt_handshake.c b/src/xprt_handshake.c index e9b22b8ae1..75ebdae762 100644 --- a/src/xprt_handshake.c +++ b/src/xprt_handshake.c @@ -11,7 +11,6 @@ */ #include -#include struct xprt_handshake_ctx { struct connection *conn; @@ -72,7 +71,7 @@ struct task *xprt_handshake_io_cb(struct task *t, void *bctx, unsigned int state } if (conn->flags & CO_FL_SEND_PROXY) - if (!conn_si_send_proxy(conn, CO_FL_SEND_PROXY)) { + if (!conn_send_proxy(conn, CO_FL_SEND_PROXY)) { ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event); goto out;