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 e6b3ed5..e513994 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -333,6 +333,7 @@
 	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 a83cc3f..ad9f792 100644
--- a/src/raw_sock.c
+++ b/src/raw_sock.c
@@ -415,12 +415,23 @@
 	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 201f04c..1d018aa 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -211,7 +211,7 @@
 	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 @@
 	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 @@
 	.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,