From: Olivier Houchard Date: Thu, 23 May 2019 15:47:36 +0000 (+0200) Subject: MINOR: connections: Add a new xprt method, remove_xprt. X-Git-Tag: v2.0-dev6~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5149b5985193fff9a2b7ed69f11f0621abbe2cbf;p=thirdparty%2Fhaproxy.git MINOR: connections: Add a new xprt method, remove_xprt. Add a new method to xprt_ops, remove_xprt. When called, if the provided xprt_ctx is the same as the xprt's underlying xprt_ctx, it then uses the new xprt provided, otherwise it calls the remove_xprt method of the next xprt. The goal is to be able to add a temporary xprt, that removes itself from the chain when it did what it had to do. This will be used to implement a pseudo-xprt for anything that just requires a handshake (such as the proxy protocol). --- diff --git a/include/types/connection.h b/include/types/connection.h index e6b3ed5752..e513994855 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -333,6 +333,7 @@ struct xprt_ops { char name[8]; /* transport layer name, zero-terminated */ int (*subscribe)(struct connection *conn, void *xprt_ctx, int event_type, void *param); /* Subscribe to events, such as "being able to send" */ int (*unsubscribe)(struct connection *conn, void *xprt_ctx, int event_type, void *param); /* Unsubscribe to events */ + int (*remove_xprt)(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx); /* Remove an xprt from the connection, used by temporary xprt such as the handshake one */ }; /* mux_ops describes the mux operations, which are to be performed at the diff --git a/src/raw_sock.c b/src/raw_sock.c index a83cc3fcb5..ad9f79257b 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -415,12 +415,23 @@ static int raw_sock_unsubscribe(struct connection *conn, void *xprt_ctx, int eve return conn_unsubscribe(conn, xprt_ctx, event_type, param); } +/* We can't have an underlying XPRT, so just return -1 to signify failure */ +static int raw_sock_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx) +{ + /* This is the lowest xprt we can have, so if we get there we didn't + * find the xprt we wanted to remove, that's a bug + */ + BUG_ON(1); + return -1; +} + /* transport-layer operations for RAW sockets */ static struct xprt_ops raw_sock = { .snd_buf = raw_sock_from_buf, .rcv_buf = raw_sock_to_buf, .subscribe = raw_sock_subscribe, .unsubscribe = raw_sock_unsubscribe, + .remove_xprt = raw_sock_remove_xprt, #if defined(USE_LINUX_SPLICE) .rcv_pipe = raw_sock_to_pipe, .snd_pipe = raw_sock_from_pipe, diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 201f04c206..1d018aa020 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -211,7 +211,7 @@ struct ssl_sock_ctx { struct connection *conn; SSL *ssl; BIO *bio; - struct xprt_ops *xprt; + const struct xprt_ops *xprt; void *xprt_ctx; struct wait_event wait_event; struct wait_event *recv_wait; @@ -5630,6 +5630,22 @@ static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_ty return 0; } +/* Remove the specified xprt. If if it our underlying XPRT, remove it and + * return 0, otherwise just call the remove_xprt method from the underlying + * XPRT. + */ +static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx) +{ + struct ssl_sock_ctx *ctx = xprt_ctx; + + if (ctx->xprt_ctx == toremove_ctx) { + ctx->xprt_ctx = newctx; + ctx->xprt = newops; + return 0; + } + return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx)); +} + static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state) { struct ssl_sock_ctx *ctx = context; @@ -9825,6 +9841,7 @@ static struct xprt_ops ssl_sock = { .rcv_buf = ssl_sock_to_buf, .subscribe = ssl_subscribe, .unsubscribe = ssl_unsubscribe, + .remove_xprt = ssl_remove_xprt, .rcv_pipe = NULL, .snd_pipe = NULL, .shutr = NULL,