blob: 2a4d01e07798028d3f2e91f7d6e5350497a16baf [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 Denoyelle77ed6312023-02-01 09:28:55 +010037 /* Schedule a CONNECTION_CLOSE emission. If process stopping is in
38 * progress, quic-conn idle-timer will be scheduled immediately after
39 * its emission to ensure an immediate connection closing.
40 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020041 qc_check_close_on_released_mux(qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020042 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020043 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +010044}
45
Frédéric Lécaille422a39c2021-03-03 17:28:34 +010046/* Called from the upper layer, to subscribe <es> to events <event_type>. The
47 * event subscriber <es> is not allowed to change from a previous call as long
48 * as at least one event is still subscribed. The <event_type> must only be a
49 * combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0.
50 */
51static int quic_conn_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
52{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020053 struct quic_conn *qc = conn->handle.qc;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020054
55 TRACE_ENTER(QUIC_EV_CONN_SUB, qc);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020056
57 BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020058 BUG_ON(qc->subs && qc->subs != es);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020059
60 es->events |= event_type;
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020061 qc->subs = es;
62
63 /* TODO implement a check_events to detect if subscriber should be
64 * woken up immediately ?
65 */
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020066
67 if (event_type & SUB_RETRY_RECV)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020068 TRACE_DEVEL("subscribe(recv)", QUIC_EV_CONN_XPRTRECV, qc);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020069
70 if (event_type & SUB_RETRY_SEND)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020071 TRACE_DEVEL("subscribe(send)", QUIC_EV_CONN_XPRTSEND, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020072
73 TRACE_LEAVE(QUIC_EV_CONN_SUB, qc);
Frédéric Lécaille513b4f22021-09-20 15:23:17 +020074
75 return 0;
Frédéric Lécaille422a39c2021-03-03 17:28:34 +010076}
77
78/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
79 * The <es> pointer is not allowed to differ from the one passed to the
80 * subscribe() call. It always returns zero.
81 */
82static int quic_conn_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
83{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020084 struct quic_conn *qc = conn->handle.qc;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020085
86 TRACE_ENTER(QUIC_EV_CONN_SUB, qc);
87
88 if (event_type & SUB_RETRY_RECV)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020089 TRACE_DEVEL("unsubscribe(recv)", QUIC_EV_CONN_XPRTRECV, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020090 if (event_type & SUB_RETRY_SEND)
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020091 TRACE_DEVEL("unsubscribe(send)", QUIC_EV_CONN_XPRTSEND, qc);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020092
Amaury Denoyellebbb1c682022-09-28 15:15:51 +020093 es->events &= ~event_type;
94 if (!es->events)
95 qc->subs = NULL;
96
97 /* TODO implement ignore_events similar to conn_unsubscribe() ? */
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +020098
99 TRACE_LEAVE(QUIC_EV_CONN_SUB, qc);
100
Amaury Denoyellebbb1c682022-09-28 15:15:51 +0200101 return 0;
Frédéric Lécaille422a39c2021-03-03 17:28:34 +0100102}
103
Amaury Denoyelle33ac3462022-01-18 16:44:34 +0100104/* Store in <xprt_ctx> the context attached to <conn>.
105 * Returns always 0.
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100106 */
107static int qc_conn_init(struct connection *conn, void **xprt_ctx)
108{
Amaury Denoyelle7ca7c842021-12-22 18:20:38 +0100109 struct quic_conn *qc = NULL;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100110
111 TRACE_ENTER(QUIC_EV_CONN_NEW, conn);
112
Amaury Denoyelle33ac3462022-01-18 16:44:34 +0100113 /* do not store the context if already set */
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100114 if (*xprt_ctx)
115 goto out;
116
Willy Tarreau784b8682022-04-11 14:18:10 +0200117 *xprt_ctx = conn->handle.qc->xprt_ctx;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100118
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100119 out:
Frédéric Lécaillefde2a982021-12-27 15:12:09 +0100120 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100121
122 return 0;
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100123}
124
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200125/* Start the QUIC transport layer */
126static int qc_xprt_start(struct connection *conn, void *ctx)
127{
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +0200128 int ret = 0;
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200129 struct quic_conn *qc;
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200130
Willy Tarreau784b8682022-04-11 14:18:10 +0200131 qc = conn->handle.qc;
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +0200132 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
Amaury Denoyellecfa2d562022-01-19 16:01:05 +0100133
134 /* mux-quic can now be considered ready. */
135 qc->mux_state = QC_MUX_READY;
136
Amaury Denoyelle2ed84002022-09-26 14:53:59 +0200137 tasklet_wakeup(qc->wait_event.tasklet);
Frédéric Lécaillea8b2f842022-08-10 17:56:45 +0200138
139 ret = 1;
140 out:
141 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
142 return ret;
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200143}
144
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200145static struct ssl_sock_ctx *qc_get_ssl_sock_ctx(struct connection *conn)
146{
Willy Tarreau784b8682022-04-11 14:18:10 +0200147 if (!conn || conn->xprt != xprt_get(XPRT_QUIC) || !conn->handle.qc || !conn->xprt_ctx)
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200148 return NULL;
149
Willy Tarreau784b8682022-04-11 14:18:10 +0200150 return conn->handle.qc->xprt_ctx;
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200151}
152
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100153/* transport-layer operations for QUIC connections. */
154static struct xprt_ops ssl_quic = {
Amaury Denoyelle414cac52021-09-22 11:14:37 +0200155 .close = quic_close,
Frédéric Lécaille422a39c2021-03-03 17:28:34 +0100156 .subscribe = quic_conn_subscribe,
157 .unsubscribe = quic_conn_unsubscribe,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100158 .init = qc_conn_init,
Frédéric Lécaille3d77fa72021-05-31 09:30:14 +0200159 .start = qc_xprt_start,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100160 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
161 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Amaury Denoyelle71e588c2021-11-12 11:23:29 +0100162 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau54a1dcb2022-04-11 11:57:35 +0200163 .get_ssl_sock_ctx = qc_get_ssl_sock_ctx,
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100164 .name = "QUIC",
165};
166
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100167static void __quic_conn_init(void)
168{
Frédéric Lécaillea7e7ce92020-11-23 14:14:04 +0100169 xprt_register(XPRT_QUIC, &ssl_quic);
170}
Willy Tarreau79367f92022-04-25 19:18:24 +0200171INITCALL0(STG_REGISTER, __quic_conn_init);