blob: 9e9258f057f2d1553942688fd9af098488022239 [file] [log] [blame]
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01001/*
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002 * QUIC xprt layer. Act as an abstraction between quic_conn and MUX layers.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01003 *
Willy Tarreau3dfb7da2022-03-02 22:33:39 +01004 * Copyright 2020 HAProxy Technologies, Frederic Lecaille <flecaille@haproxy.com>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +01005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020013#include <haproxy/api.h>
14#include <haproxy/connection.h>
15#include <haproxy/quic_conn.h>
16#include <haproxy/ssl_sock.h>
17#include <haproxy/trace.h>
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010018
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020019#define TRACE_SOURCE &trace_quic
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010020
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020021static void quic_close(struct connection *conn, void *xprt_ctx)
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010022{
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020023 struct ssl_sock_ctx *conn_ctx = xprt_ctx;
24 struct quic_conn *qc = conn_ctx->qc;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010025
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020026 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010027
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020028 /* Next application data can be dropped. */
29 qc->mux_state = QC_MUX_RELEASED;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020030
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020031 /* If the quic-conn timer has already expired free the quic-conn. */
32 if (qc->flags & QUIC_FL_CONN_EXP_TIMER) {
33 quic_conn_release(qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020034 goto leave;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010035 }
36
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020037 qc_check_close_on_released_mux(qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020038 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020039 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010040}
41
Frédéric Lécaille422a39c2021-03-03 17:28:34 +010042/* Called from the upper layer, to subscribe <es> to events <event_type>. The
43 * event subscriber <es> is not allowed to change from a previous call as long
44 * as at least one event is still subscribed. The <event_type> must only be a
45 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0.
46 */
47static int quic_conn_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
48{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020049 struct quic_conn *qc = conn->handle.qc;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020050
51 TRACE_ENTER(QUIC_EV_CONN_SUB, qc);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020052
53 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020054 BUG_ON(qc->subs && qc->subs != es);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020055
56 es->events |= event_type;
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020057 qc->subs = es;
58
59 /* TODO implement a check_events to detect if subscriber should be
60 * woken up immediately ?
61 */
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020062
63 if (event_type & SUB_RETRY_RECV)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020064 TRACE_DEVEL("subscribe(recv)", QUIC_EV_CONN_XPRTRECV, qc);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020065
66 if (event_type & SUB_RETRY_SEND)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020067 TRACE_DEVEL("subscribe(send)", QUIC_EV_CONN_XPRTSEND, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020068
69 TRACE_LEAVE(QUIC_EV_CONN_SUB, qc);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020070
71 return 0;
Frédéric Lécaille422a39c2021-03-03 17:28:34 +010072}
73
74/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
75 * The <es> pointer is not allowed to differ from the one passed to the
76 * subscribe() call. It always returns zero.
77 */
78static int quic_conn_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
79{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020080 struct quic_conn *qc = conn->handle.qc;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020081
82 TRACE_ENTER(QUIC_EV_CONN_SUB, qc);
83
84 if (event_type & SUB_RETRY_RECV)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020085 TRACE_DEVEL("unsubscribe(recv)", QUIC_EV_CONN_XPRTRECV, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020086 if (event_type & SUB_RETRY_SEND)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020087 TRACE_DEVEL("unsubscribe(send)", QUIC_EV_CONN_XPRTSEND, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020088
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020089 es->events &= ~event_type;
90 if (!es->events)
91 qc->subs = NULL;
92
93 /* TODO implement ignore_events similar to conn_unsubscribe() ? */
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020094
95 TRACE_LEAVE(QUIC_EV_CONN_SUB, qc);
96
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020097 return 0;
Frédéric Lécaille422a39c2021-03-03 17:28:34 +010098}
99
Amaury Denoyelle33ac3462022-01-18 16:44:34 +0100100/* Store in <xprt_ctx> the context attached to <conn>.
101 * Returns always 0.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100102 */
103static int qc_conn_init(struct connection *conn, void **xprt_ctx)
104{
Amaury Denoyelle7ca7c842021-12-22 18:20:38 +0100105 struct quic_conn *qc = NULL;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100106
107 TRACE_ENTER(QUIC_EV_CONN_NEW, conn);
108
Amaury Denoyelle33ac3462022-01-18 16:44:34 +0100109 /* do not store the context if already set */
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100110 if (*xprt_ctx)
111 goto out;
112
Willy Tarreau784b8682022-04-11 14:18:10 +0200113 *xprt_ctx = conn->handle.qc->xprt_ctx;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100114
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100115 out:
Frédéric Lécaillefde2a982021-12-27 15:12:09 +0100116 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100117
118 return 0;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100119}
120
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200121/* Start the QUIC transport layer */
122static int qc_xprt_start(struct connection *conn, void *ctx)
123{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +0200124 int ret = 0;
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200125 struct quic_conn *qc;
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200126
Willy Tarreau784b8682022-04-11 14:18:10 +0200127 qc = conn->handle.qc;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +0200128 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
Amaury Denoyellecfa2d562022-01-19 16:01:05 +0100129
130 /* mux-quic can now be considered ready. */
131 qc->mux_state = QC_MUX_READY;
132
Amaury Denoyelle2ed84002022-09-26 14:53:59 +0200133 tasklet_wakeup(qc->wait_event.tasklet);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +0200134
135 ret = 1;
136 out:
137 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
138 return ret;
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200139}
140
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200141static struct ssl_sock_ctx *qc_get_ssl_sock_ctx(struct connection *conn)
142{
Willy Tarreau784b8682022-04-11 14:18:10 +0200143 if (!conn || conn->xprt != xprt_get(XPRT_QUIC) || !conn->handle.qc || !conn->xprt_ctx)
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200144 return NULL;
145
Willy Tarreau784b8682022-04-11 14:18:10 +0200146 return conn->handle.qc->xprt_ctx;
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200147}
148
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100149/* transport-layer operations for QUIC connections. */
150static struct xprt_ops ssl_quic = {
Amaury Denoyelle414cac52021-09-22 11:14:37 +0200151 .close = quic_close,
Frédéric Lécaille422a39c2021-03-03 17:28:34 +0100152 .subscribe = quic_conn_subscribe,
153 .unsubscribe = quic_conn_unsubscribe,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100154 .init = qc_conn_init,
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200155 .start = qc_xprt_start,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100156 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
157 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Amaury Denoyelle71e588c2021-11-12 11:23:29 +0100158 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200159 .get_ssl_sock_ctx = qc_get_ssl_sock_ctx,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100160 .name = "QUIC",
161};
162
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100163static void __quic_conn_init(void)
164{
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100165 xprt_register(XPRT_QUIC, &ssl_quic);
166}
Willy Tarreau79367f92022-04-25 19:18:24 +0200167INITCALL0(STG_REGISTER, __quic_conn_init);