2020-11-23 13:14:04 +00:00
|
|
|
/*
|
2022-09-30 16:11:13 +00:00
|
|
|
* QUIC xprt layer. Act as an abstraction between quic_conn and MUX layers.
|
2020-11-23 13:14:04 +00:00
|
|
|
*
|
2022-03-02 21:33:39 +00:00
|
|
|
* Copyright 2020 HAProxy Technologies, Frederic Lecaille <flecaille@haproxy.com>
|
2020-11-23 13:14:04 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version
|
|
|
|
* 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2022-09-30 16:11:13 +00:00
|
|
|
#include <haproxy/api.h>
|
|
|
|
#include <haproxy/connection.h>
|
|
|
|
#include <haproxy/quic_conn.h>
|
|
|
|
#include <haproxy/ssl_sock.h>
|
2023-10-06 15:39:00 +00:00
|
|
|
#include <haproxy/quic_trace.h>
|
2022-09-30 16:11:13 +00:00
|
|
|
#include <haproxy/trace.h>
|
2020-11-23 13:14:04 +00:00
|
|
|
|
2022-09-30 16:11:13 +00:00
|
|
|
static void quic_close(struct connection *conn, void *xprt_ctx)
|
2020-11-23 13:14:04 +00:00
|
|
|
{
|
2022-09-30 16:11:13 +00:00
|
|
|
struct ssl_sock_ctx *conn_ctx = xprt_ctx;
|
|
|
|
struct quic_conn *qc = conn_ctx->qc;
|
2020-11-23 13:14:04 +00:00
|
|
|
|
2022-09-30 16:11:13 +00:00
|
|
|
TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
|
2020-11-23 13:14:04 +00:00
|
|
|
|
2022-09-30 16:11:13 +00:00
|
|
|
/* Next application data can be dropped. */
|
|
|
|
qc->mux_state = QC_MUX_RELEASED;
|
2022-08-10 15:56:45 +00:00
|
|
|
|
2023-08-08 08:50:51 +00:00
|
|
|
/* If the quic-conn timer has already expired or if already in "connection close"
|
|
|
|
* state, free the quic-conn.
|
|
|
|
*/
|
|
|
|
if (qc->flags & (QUIC_FL_CONN_EXP_TIMER|QUIC_FL_CONN_CLOSING)) {
|
2022-09-30 16:11:13 +00:00
|
|
|
quic_conn_release(qc);
|
2023-04-12 11:41:54 +00:00
|
|
|
qc = NULL;
|
2022-08-10 15:56:45 +00:00
|
|
|
goto leave;
|
2020-12-08 14:58:39 +00:00
|
|
|
}
|
2020-11-23 13:14:04 +00:00
|
|
|
|
2023-02-01 08:28:55 +00:00
|
|
|
/* Schedule a CONNECTION_CLOSE emission. If process stopping is in
|
|
|
|
* progress, quic-conn idle-timer will be scheduled immediately after
|
|
|
|
* its emission to ensure an immediate connection closing.
|
|
|
|
*/
|
2022-09-30 16:11:13 +00:00
|
|
|
qc_check_close_on_released_mux(qc);
|
2022-08-10 15:56:45 +00:00
|
|
|
leave:
|
2022-09-30 16:11:13 +00:00
|
|
|
TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
|
2020-11-23 13:14:04 +00:00
|
|
|
}
|
|
|
|
|
2021-03-03 16:28:34 +00:00
|
|
|
/* Called from the upper layer, to subscribe <es> to events <event_type>. The
|
|
|
|
* event subscriber <es> is not allowed to change from a previous call as long
|
|
|
|
* as at least one event is still subscribed. The <event_type> must only be a
|
|
|
|
* combination of SUB_RETRY_RECV and SUB_RETRY_SEND. It always returns 0.
|
|
|
|
*/
|
|
|
|
static int quic_conn_subscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
|
|
|
|
{
|
2022-08-10 15:56:45 +00:00
|
|
|
struct quic_conn *qc = conn->handle.qc;
|
|
|
|
|
|
|
|
TRACE_ENTER(QUIC_EV_CONN_SUB, qc);
|
2021-09-20 13:23:17 +00:00
|
|
|
|
|
|
|
BUG_ON(event_type & ~(SUB_RETRY_SEND|SUB_RETRY_RECV));
|
2022-09-28 13:15:51 +00:00
|
|
|
BUG_ON(qc->subs && qc->subs != es);
|
2021-09-20 13:23:17 +00:00
|
|
|
|
|
|
|
es->events |= event_type;
|
2022-09-28 13:15:51 +00:00
|
|
|
qc->subs = es;
|
|
|
|
|
|
|
|
/* TODO implement a check_events to detect if subscriber should be
|
|
|
|
* woken up immediately ?
|
|
|
|
*/
|
2021-09-20 13:23:17 +00:00
|
|
|
|
|
|
|
if (event_type & SUB_RETRY_RECV)
|
2022-09-28 13:15:51 +00:00
|
|
|
TRACE_DEVEL("subscribe(recv)", QUIC_EV_CONN_XPRTRECV, qc);
|
2021-09-20 13:23:17 +00:00
|
|
|
|
|
|
|
if (event_type & SUB_RETRY_SEND)
|
2022-09-28 13:15:51 +00:00
|
|
|
TRACE_DEVEL("subscribe(send)", QUIC_EV_CONN_XPRTSEND, qc);
|
2022-08-10 15:56:45 +00:00
|
|
|
|
|
|
|
TRACE_LEAVE(QUIC_EV_CONN_SUB, qc);
|
2021-09-20 13:23:17 +00:00
|
|
|
|
|
|
|
return 0;
|
2021-03-03 16:28:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Called from the upper layer, to unsubscribe <es> from events <event_type>.
|
|
|
|
* The <es> pointer is not allowed to differ from the one passed to the
|
|
|
|
* subscribe() call. It always returns zero.
|
|
|
|
*/
|
|
|
|
static int quic_conn_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es)
|
|
|
|
{
|
2022-08-10 15:56:45 +00:00
|
|
|
struct quic_conn *qc = conn->handle.qc;
|
|
|
|
|
|
|
|
TRACE_ENTER(QUIC_EV_CONN_SUB, qc);
|
|
|
|
|
|
|
|
if (event_type & SUB_RETRY_RECV)
|
2022-09-28 13:15:51 +00:00
|
|
|
TRACE_DEVEL("unsubscribe(recv)", QUIC_EV_CONN_XPRTRECV, qc);
|
2022-08-10 15:56:45 +00:00
|
|
|
if (event_type & SUB_RETRY_SEND)
|
2022-09-28 13:15:51 +00:00
|
|
|
TRACE_DEVEL("unsubscribe(send)", QUIC_EV_CONN_XPRTSEND, qc);
|
|
|
|
|
|
|
|
es->events &= ~event_type;
|
|
|
|
if (!es->events)
|
|
|
|
qc->subs = NULL;
|
2022-08-10 15:56:45 +00:00
|
|
|
|
2022-09-28 13:15:51 +00:00
|
|
|
/* TODO implement ignore_events similar to conn_unsubscribe() ? */
|
2022-08-10 15:56:45 +00:00
|
|
|
|
|
|
|
TRACE_LEAVE(QUIC_EV_CONN_SUB, qc);
|
|
|
|
|
2022-09-28 13:15:51 +00:00
|
|
|
return 0;
|
2021-03-03 16:28:34 +00:00
|
|
|
}
|
|
|
|
|
2022-01-18 15:44:34 +00:00
|
|
|
/* Store in <xprt_ctx> the context attached to <conn>.
|
|
|
|
* Returns always 0.
|
2020-11-23 13:14:04 +00:00
|
|
|
*/
|
|
|
|
static int qc_conn_init(struct connection *conn, void **xprt_ctx)
|
|
|
|
{
|
BUG/MAJOR: quic: complete thread migration before tcp-rules
A quic_conn is instantiated and tied on the first thread which has
received the first INITIAL packet. After handshake completion,
listener_accept() is called. For each quic_conn, a new thread is
selected among the least loaded ones Note that this occurs earlier if
handling 0-RTT data.
This thread connection migration is done in two steps :
* inside listener_accept(), on the origin thread, quic_conn
tasks/tasklet are killed. After this, no quic_conn related processing
will occur on this thread. The connection is flagged with
QUIC_FL_CONN_AFFINITY_CHANGED.
* as soon as the first quic_conn related processing occurs on the new
thread, the migration is finalized. This allows to allocate the new
tasks/tasklet directly on the destination thread.
This last step on the new thread must be done prior to other quic_conn
access. There is two events which may trigger it :
* a packet is received on the new thread. In this case,
qc_finalize_affinity_rebind() is called from quic_dgram_parse().
* the recently accepted connection is popped from accept_queue_ring via
accept_queue_process(). This will called session_accept_fd() as
listener.bind_conf.accept callback. This instantiates a new session
and start connection stack via conn_xprt_start(), which itself calls
qc_xprt_start() where qc_finalize_affinity_rebind() is used.
A condition was recently found which could cause a closing to be used
with qc_finalize_affinity_rebind() which is forbidden with a BUG_ON().
This lat step was not compatible with layer 4 rule such as "tcp-request
connection reject" which closes the connection early. In this case, most
of the body of session_accept_fd() is skipped, including
qc_xprt_start(), so thread migration is not finalized. At the end of the
function, conn_xprt_close() is then called which flags the connection as
CLOSING.
If a datagram is received for this connection before it is released,
this will call qc_finalize_affinity_rebind() which triggers its BUG_ON()
to prevent thread migration for CLOSING quic_conn.
FATAL: bug condition "qc->flags & ((1U << 29)|(1U << 30))" matched at src/quic_conn.c:2036
Thread 3 "haproxy" received signal SIGILL, Illegal instruction.
[Switching to Thread 0x7ffff794f700 (LWP 2973030)]
0x00005555556221f3 in qc_finalize_affinity_rebind (qc=0x7ffff002d060) at src/quic_conn.c:2036
2036 BUG_ON(qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING));
(gdb) bt
#0 0x00005555556221f3 in qc_finalize_affinity_rebind (qc=0x7ffff002d060) at src/quic_conn.c:2036
#1 0x0000555555682463 in quic_dgram_parse (dgram=0x7fff5003ef10, from_qc=0x0, li=0x555555f38670) at src/quic_rx.c:2602
#2 0x0000555555651aae in quic_lstnr_dghdlr (t=0x555555fc4440, ctx=0x555555fc3f78, state=32832) at src/quic_sock.c:189
#3 0x00005555558c9393 in run_tasks_from_lists (budgets=0x7ffff7944c90) at src/task.c:596
#4 0x00005555558c9e8e in process_runnable_tasks () at src/task.c:876
#5 0x000055555586b7b2 in run_poll_loop () at src/haproxy.c:2966
#6 0x000055555586be87 in run_thread_poll_loop (data=0x555555d3d340 <ha_thread_info+64>) at src/haproxy.c:3165
#7 0x00007ffff7b59609 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#8 0x00007ffff7a7e133 in clone () from /lib/x86_64-linux-gnu/libc.so.6
To fix this issue, ensure quic_conn migration is completed earlier
inside session_accept_fd(), before any tcp rules processing. This is
done by moving qc_finalize_affinity_rebind() invocation from
qc_xprt_start() to qc_conn_init().
This must be backported up to 2.7.
2023-11-20 13:56:49 +00:00
|
|
|
struct quic_conn *qc = conn->handle.qc;
|
2020-11-23 13:14:04 +00:00
|
|
|
|
2023-04-12 11:41:54 +00:00
|
|
|
TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
|
2020-11-23 13:14:04 +00:00
|
|
|
|
BUG/MAJOR: quic: complete thread migration before tcp-rules
A quic_conn is instantiated and tied on the first thread which has
received the first INITIAL packet. After handshake completion,
listener_accept() is called. For each quic_conn, a new thread is
selected among the least loaded ones Note that this occurs earlier if
handling 0-RTT data.
This thread connection migration is done in two steps :
* inside listener_accept(), on the origin thread, quic_conn
tasks/tasklet are killed. After this, no quic_conn related processing
will occur on this thread. The connection is flagged with
QUIC_FL_CONN_AFFINITY_CHANGED.
* as soon as the first quic_conn related processing occurs on the new
thread, the migration is finalized. This allows to allocate the new
tasks/tasklet directly on the destination thread.
This last step on the new thread must be done prior to other quic_conn
access. There is two events which may trigger it :
* a packet is received on the new thread. In this case,
qc_finalize_affinity_rebind() is called from quic_dgram_parse().
* the recently accepted connection is popped from accept_queue_ring via
accept_queue_process(). This will called session_accept_fd() as
listener.bind_conf.accept callback. This instantiates a new session
and start connection stack via conn_xprt_start(), which itself calls
qc_xprt_start() where qc_finalize_affinity_rebind() is used.
A condition was recently found which could cause a closing to be used
with qc_finalize_affinity_rebind() which is forbidden with a BUG_ON().
This lat step was not compatible with layer 4 rule such as "tcp-request
connection reject" which closes the connection early. In this case, most
of the body of session_accept_fd() is skipped, including
qc_xprt_start(), so thread migration is not finalized. At the end of the
function, conn_xprt_close() is then called which flags the connection as
CLOSING.
If a datagram is received for this connection before it is released,
this will call qc_finalize_affinity_rebind() which triggers its BUG_ON()
to prevent thread migration for CLOSING quic_conn.
FATAL: bug condition "qc->flags & ((1U << 29)|(1U << 30))" matched at src/quic_conn.c:2036
Thread 3 "haproxy" received signal SIGILL, Illegal instruction.
[Switching to Thread 0x7ffff794f700 (LWP 2973030)]
0x00005555556221f3 in qc_finalize_affinity_rebind (qc=0x7ffff002d060) at src/quic_conn.c:2036
2036 BUG_ON(qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING));
(gdb) bt
#0 0x00005555556221f3 in qc_finalize_affinity_rebind (qc=0x7ffff002d060) at src/quic_conn.c:2036
#1 0x0000555555682463 in quic_dgram_parse (dgram=0x7fff5003ef10, from_qc=0x0, li=0x555555f38670) at src/quic_rx.c:2602
#2 0x0000555555651aae in quic_lstnr_dghdlr (t=0x555555fc4440, ctx=0x555555fc3f78, state=32832) at src/quic_sock.c:189
#3 0x00005555558c9393 in run_tasks_from_lists (budgets=0x7ffff7944c90) at src/task.c:596
#4 0x00005555558c9e8e in process_runnable_tasks () at src/task.c:876
#5 0x000055555586b7b2 in run_poll_loop () at src/haproxy.c:2966
#6 0x000055555586be87 in run_thread_poll_loop (data=0x555555d3d340 <ha_thread_info+64>) at src/haproxy.c:3165
#7 0x00007ffff7b59609 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#8 0x00007ffff7a7e133 in clone () from /lib/x86_64-linux-gnu/libc.so.6
To fix this issue, ensure quic_conn migration is completed earlier
inside session_accept_fd(), before any tcp rules processing. This is
done by moving qc_finalize_affinity_rebind() invocation from
qc_xprt_start() to qc_conn_init().
This must be backported up to 2.7.
2023-11-20 13:56:49 +00:00
|
|
|
/* Ensure thread connection migration is finalized ASAP. */
|
|
|
|
if (qc->flags & QUIC_FL_CONN_AFFINITY_CHANGED)
|
|
|
|
qc_finalize_affinity_rebind(qc);
|
|
|
|
|
2022-01-18 15:44:34 +00:00
|
|
|
/* do not store the context if already set */
|
2020-11-23 13:14:04 +00:00
|
|
|
if (*xprt_ctx)
|
|
|
|
goto out;
|
|
|
|
|
BUG/MAJOR: quic: complete thread migration before tcp-rules
A quic_conn is instantiated and tied on the first thread which has
received the first INITIAL packet. After handshake completion,
listener_accept() is called. For each quic_conn, a new thread is
selected among the least loaded ones Note that this occurs earlier if
handling 0-RTT data.
This thread connection migration is done in two steps :
* inside listener_accept(), on the origin thread, quic_conn
tasks/tasklet are killed. After this, no quic_conn related processing
will occur on this thread. The connection is flagged with
QUIC_FL_CONN_AFFINITY_CHANGED.
* as soon as the first quic_conn related processing occurs on the new
thread, the migration is finalized. This allows to allocate the new
tasks/tasklet directly on the destination thread.
This last step on the new thread must be done prior to other quic_conn
access. There is two events which may trigger it :
* a packet is received on the new thread. In this case,
qc_finalize_affinity_rebind() is called from quic_dgram_parse().
* the recently accepted connection is popped from accept_queue_ring via
accept_queue_process(). This will called session_accept_fd() as
listener.bind_conf.accept callback. This instantiates a new session
and start connection stack via conn_xprt_start(), which itself calls
qc_xprt_start() where qc_finalize_affinity_rebind() is used.
A condition was recently found which could cause a closing to be used
with qc_finalize_affinity_rebind() which is forbidden with a BUG_ON().
This lat step was not compatible with layer 4 rule such as "tcp-request
connection reject" which closes the connection early. In this case, most
of the body of session_accept_fd() is skipped, including
qc_xprt_start(), so thread migration is not finalized. At the end of the
function, conn_xprt_close() is then called which flags the connection as
CLOSING.
If a datagram is received for this connection before it is released,
this will call qc_finalize_affinity_rebind() which triggers its BUG_ON()
to prevent thread migration for CLOSING quic_conn.
FATAL: bug condition "qc->flags & ((1U << 29)|(1U << 30))" matched at src/quic_conn.c:2036
Thread 3 "haproxy" received signal SIGILL, Illegal instruction.
[Switching to Thread 0x7ffff794f700 (LWP 2973030)]
0x00005555556221f3 in qc_finalize_affinity_rebind (qc=0x7ffff002d060) at src/quic_conn.c:2036
2036 BUG_ON(qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING));
(gdb) bt
#0 0x00005555556221f3 in qc_finalize_affinity_rebind (qc=0x7ffff002d060) at src/quic_conn.c:2036
#1 0x0000555555682463 in quic_dgram_parse (dgram=0x7fff5003ef10, from_qc=0x0, li=0x555555f38670) at src/quic_rx.c:2602
#2 0x0000555555651aae in quic_lstnr_dghdlr (t=0x555555fc4440, ctx=0x555555fc3f78, state=32832) at src/quic_sock.c:189
#3 0x00005555558c9393 in run_tasks_from_lists (budgets=0x7ffff7944c90) at src/task.c:596
#4 0x00005555558c9e8e in process_runnable_tasks () at src/task.c:876
#5 0x000055555586b7b2 in run_poll_loop () at src/haproxy.c:2966
#6 0x000055555586be87 in run_thread_poll_loop (data=0x555555d3d340 <ha_thread_info+64>) at src/haproxy.c:3165
#7 0x00007ffff7b59609 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#8 0x00007ffff7a7e133 in clone () from /lib/x86_64-linux-gnu/libc.so.6
To fix this issue, ensure quic_conn migration is completed earlier
inside session_accept_fd(), before any tcp rules processing. This is
done by moving qc_finalize_affinity_rebind() invocation from
qc_xprt_start() to qc_conn_init().
This must be backported up to 2.7.
2023-11-20 13:56:49 +00:00
|
|
|
*xprt_ctx = qc->xprt_ctx;
|
2020-11-23 13:14:04 +00:00
|
|
|
|
|
|
|
out:
|
2021-12-27 14:12:09 +00:00
|
|
|
TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
|
2020-11-23 13:14:04 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-05-31 07:30:14 +00:00
|
|
|
/* Start the QUIC transport layer */
|
|
|
|
static int qc_xprt_start(struct connection *conn, void *ctx)
|
|
|
|
{
|
2022-08-10 15:56:45 +00:00
|
|
|
int ret = 0;
|
2021-05-31 07:30:14 +00:00
|
|
|
struct quic_conn *qc;
|
|
|
|
|
2022-04-11 12:18:10 +00:00
|
|
|
qc = conn->handle.qc;
|
2022-08-10 15:56:45 +00:00
|
|
|
TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
|
2022-01-19 15:01:05 +00:00
|
|
|
|
|
|
|
/* mux-quic can now be considered ready. */
|
|
|
|
qc->mux_state = QC_MUX_READY;
|
|
|
|
|
BUG/MEDIUM: quic: fix connection freeze on post handshake
After handshake completion, QUIC server is responsible to emit
HANDSHAKE_DONE frame. Some clients wait for it to begin STREAM
transfers.
Previously, there was no explicit tasklet_wakeup() after handshake
completion, which is necessary to emit post-handshake frames. In most
cases, this was undetected as most client continue emission which will
reschedule the tasklet. However, as there is no tasklet_wakeup(), this
is not a consistent behavior. If this bug occurs, it causes a connection
freeze, preventing the client to emit any request. The connection is
finally closed on idle timeout.
To fix this, add an explicit tasklet_wakeup() after handshake
completion. It sounds simple enough but in fact it's difficult to find
the correct location efor tasklet_wakeup() invocation, as post-handshake
is directly linked to connection accept, with different orderings.
Notably, if 0-RTT is used, connection can be accepted prior handshake
completion. Another major point is that along HANDSHAKE_DONE frame, a
series of NEW_CONNECTION_ID frames are emitted. However, these new CIDs
allocation must occur after connection is migrated to its new thread as
these CIDs are tied to it. A BUG_ON() is present to check this in
qc_set_tid_affinity().
With all this in mind, 2 locations were selected for the necessary
tasklet_wakeup() :
* on qc_xprt_start() : this is useful for standard case without 0-RTT.
This ensures that this is done only after connection thread migration.
* on qc_ssl_provide_all_quic_data() : this is done on handshake
completion with 0-RTT used. In this case only, connection is already
accepted and migrated, so tasklet_wakeup() is safe.
Note that as a side-change, quic_accept_push_qc() API has evolved to
better reflect differences between standard and 0-RTT usages. It is now
forbidden to call it multiple times on a single quic_conn instance. A
BUG_ON() has been added.
This issue is labelled as medium even though it seems pretty rare. It
was only reproducible using QUIC interop runner, with haproxy compiled
with LibreSSL with quic-go as client. However, affected code parts are
pretty sensible, which justify the chosen severity.
This should fix github issue #2418.
It should be backported up to 2.6, after a brief period of observation.
Note that the extra comment added in qc_set_tid_affinity() can be
removed in 2.6 as thread migration is not implemented for this version.
Other parts should apply without conflict.
2024-03-04 17:41:39 +00:00
|
|
|
/* Schedule quic-conn to ensure post handshake frames are emitted. This
|
|
|
|
* is not done for 0-RTT as xprt->start happens before handshake
|
|
|
|
* completion.
|
|
|
|
*/
|
|
|
|
if (qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS)
|
|
|
|
tasklet_wakeup(qc->wait_event.tasklet);
|
|
|
|
|
2022-08-10 15:56:45 +00:00
|
|
|
ret = 1;
|
|
|
|
out:
|
|
|
|
TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
|
|
|
|
return ret;
|
2021-05-31 07:30:14 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 09:57:35 +00:00
|
|
|
static struct ssl_sock_ctx *qc_get_ssl_sock_ctx(struct connection *conn)
|
|
|
|
{
|
2022-04-11 12:18:10 +00:00
|
|
|
if (!conn || conn->xprt != xprt_get(XPRT_QUIC) || !conn->handle.qc || !conn->xprt_ctx)
|
2022-04-11 09:57:35 +00:00
|
|
|
return NULL;
|
|
|
|
|
2022-04-11 12:18:10 +00:00
|
|
|
return conn->handle.qc->xprt_ctx;
|
2022-04-11 09:57:35 +00:00
|
|
|
}
|
|
|
|
|
2020-11-23 13:14:04 +00:00
|
|
|
/* transport-layer operations for QUIC connections. */
|
|
|
|
static struct xprt_ops ssl_quic = {
|
2021-09-22 09:14:37 +00:00
|
|
|
.close = quic_close,
|
2021-03-03 16:28:34 +00:00
|
|
|
.subscribe = quic_conn_subscribe,
|
|
|
|
.unsubscribe = quic_conn_unsubscribe,
|
2020-11-23 13:14:04 +00:00
|
|
|
.init = qc_conn_init,
|
2021-05-31 07:30:14 +00:00
|
|
|
.start = qc_xprt_start,
|
2020-11-23 13:14:04 +00:00
|
|
|
.prepare_bind_conf = ssl_sock_prepare_bind_conf,
|
|
|
|
.destroy_bind_conf = ssl_sock_destroy_bind_conf,
|
2021-11-12 10:23:29 +00:00
|
|
|
.get_alpn = ssl_sock_get_alpn,
|
2022-04-11 09:57:35 +00:00
|
|
|
.get_ssl_sock_ctx = qc_get_ssl_sock_ctx,
|
2020-11-23 13:14:04 +00:00
|
|
|
.name = "QUIC",
|
|
|
|
};
|
|
|
|
|
|
|
|
static void __quic_conn_init(void)
|
|
|
|
{
|
|
|
|
xprt_register(XPRT_QUIC, &ssl_quic);
|
|
|
|
}
|
2022-04-25 17:18:24 +00:00
|
|
|
INITCALL0(STG_REGISTER, __quic_conn_init);
|