quic 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/LICENSE-DEPENDENCIES.txt +2 -2
- data/README.md +1 -1
- data/ext/quic/connection_common.c +116 -425
- data/ext/quic/connection_common.h +31 -5
- data/ext/quic/ext_api.c +7 -5
- data/ext/quic/extconf.rb +5 -5
- data/ext/quic/include/quic/ext.h +22 -1
- data/ext/quic/stream.c +434 -45
- data/ext/quic/stream.h +68 -22
- data/lib/quic/connection.rb +11 -0
- data/lib/quic/version.rb +1 -1
- data/sig/quic.rbs +14 -12
- metadata +3 -3
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
minimum destlen ngtcp2 accepts. Revisit when PMTUD is enabled (Phase 4+). */
|
|
15
15
|
#define QUIC_WRITE_PKT_BUFLEN NGTCP2_MAX_UDP_PAYLOAD_SIZE
|
|
16
16
|
|
|
17
|
+
/* Whether the stream handler h has member, judged by the size it was built
|
|
18
|
+
with: a handler built against an older quic/ext.h is shorter, and its
|
|
19
|
+
memory ends before the members added since. Compared with the end of the
|
|
20
|
+
member, not the start of the next one, so trailing padding does not
|
|
21
|
+
count. */
|
|
22
|
+
#define QUIC_EXT_HANDLER_HAS(h, member) \
|
|
23
|
+
((h)->size >= offsetof(quic_ext_stream_handler, member) + sizeof((h)->member))
|
|
24
|
+
|
|
17
25
|
/* A QUIC::Endpoint (endpoint.c). */
|
|
18
26
|
typedef struct quic_endpoint quic_endpoint_t;
|
|
19
27
|
|
|
@@ -57,11 +65,18 @@ typedef struct {
|
|
|
57
65
|
ptls_get_data_ptr. The ref must outlive the ptls_t. */
|
|
58
66
|
ngtcp2_crypto_conn_ref conn_ref;
|
|
59
67
|
/* Back-reference to the Client or Server Ruby object that owns this
|
|
60
|
-
struct. ngtcp2
|
|
61
|
-
struct, and
|
|
62
|
-
via TypedData_Wrap_Struct, so owner is guaranteed alive
|
|
63
|
-
(no dmark needed). GC.compact may relocate owner, so
|
|
64
|
-
updates this field via rb_gc_location.
|
|
68
|
+
struct. ngtcp2 callbacks receive a void* user_data equal to this
|
|
69
|
+
struct, and reach @streams and @accept_queue via owner. We are stored
|
|
70
|
+
INSIDE owner via TypedData_Wrap_Struct, so owner is guaranteed alive
|
|
71
|
+
while we exist (no dmark needed). GC.compact may relocate owner, so
|
|
72
|
+
quic_conn_compact updates this field via rb_gc_location.
|
|
73
|
+
|
|
74
|
+
A stream's callbacks get its QUIC::Stream's quic_stream_t from
|
|
75
|
+
ngtcp2's stream_user_data, which is only safe while @streams keeps
|
|
76
|
+
that Stream alive. So a Stream goes into @streams before ngtcp2 is
|
|
77
|
+
given its struct, and leaves only at the end of the stream_close
|
|
78
|
+
callback, which must not fail after that: a failing stream_close
|
|
79
|
+
leaves the stream in ngtcp2, pointing at a struct GC may free. */
|
|
65
80
|
VALUE owner;
|
|
66
81
|
/* An exception raised by Ruby code inside an ngtcp2 callback, caught with
|
|
67
82
|
rb_protect so that it does not unwind through ngtcp2's frames. #read_pkt,
|
|
@@ -86,6 +101,11 @@ typedef struct {
|
|
|
86
101
|
/* Set by the constructor. Decides which peer-initiated streams
|
|
87
102
|
recv_stream_data queues for #accept_stream. */
|
|
88
103
|
bool is_server;
|
|
104
|
+
/* The bytes the QUIC::Streams of this connection have queued and not yet
|
|
105
|
+
handed to ngtcp2, stopped streams excepted. ngtcp2 takes off the
|
|
106
|
+
connection's flow control window only what it has sent, so #write and
|
|
107
|
+
#write_nonblock take this off as well. */
|
|
108
|
+
uint64_t stream_unsent;
|
|
89
109
|
/* <qlog_dir>/<SCID>.sqlog while ngtcp2 writes qlog to it, else NULL.
|
|
90
110
|
quic_conn_close_qlog closes it as soon as the connection ends;
|
|
91
111
|
NGTCP2_QLOG_WRITE_FLAG_FIN, sent by ngtcp2_conn_del, closes one still
|
|
@@ -126,6 +146,12 @@ VALUE quic_conn_alloc(VALUE klass);
|
|
|
126
146
|
/* CLOCK_MONOTONIC in ngtcp2's units (nanoseconds). */
|
|
127
147
|
ngtcp2_tstamp quic_now(void);
|
|
128
148
|
|
|
149
|
+
/* Run body(arg), Ruby code an ngtcp2 callback of c calls, under rb_protect.
|
|
150
|
+
An exception is kept in c->pending_exc (the first one wins; ngtcp2 stops
|
|
151
|
+
at the first failing callback anyway) and turned into
|
|
152
|
+
NGTCP2_ERR_CALLBACK_FAILURE, so that it never unwinds through ngtcp2. */
|
|
153
|
+
int quic_conn_protect(quic_conn_t *c, VALUE (*body)(VALUE), void *arg);
|
|
154
|
+
|
|
129
155
|
/* Build the next packet of the connection self (wrapping c) into dest of
|
|
130
156
|
QUIC_WRITE_PKT_BUFLEN bytes, as #write_pkt does, and store its path in
|
|
131
157
|
*path. Returns the packet's length, 0 when there is nothing to send, or a
|
data/ext/quic/ext_api.c
CHANGED
|
@@ -15,14 +15,16 @@ static quic_ext_conn *quic_ext_conn_get(VALUE conn) {
|
|
|
15
15
|
|
|
16
16
|
/* Hand every stream of the connection to h. Allowed once, and only before
|
|
17
17
|
the connection has a QUIC::Stream: the two modes cannot share streams.
|
|
18
|
-
Every member of the ABI 1.0 handler is called, so h must
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
Every member of the ABI 1.0 handler is called, so h must hold them all
|
|
19
|
+
(handshake_completed is the last). A handler built against an older
|
|
20
|
+
quic/ext.h than this one is shorter than sizeof(quic_ext_stream_handler),
|
|
21
|
+
and is called only for the members its size covers. @stream_handler marks
|
|
22
|
+
the connection for the Ruby side, which then refuses #accept_stream. */
|
|
21
23
|
static int quic_ext_set_stream_handler(quic_ext_conn *ec,
|
|
22
24
|
const quic_ext_stream_handler *h,
|
|
23
25
|
void *ud, VALUE owner) {
|
|
24
26
|
quic_conn_t *c = quic_ext_conn_struct(ec);
|
|
25
|
-
if (h == NULL || h
|
|
27
|
+
if (h == NULL || !QUIC_EXT_HANDLER_HAS(h, handshake_completed))
|
|
26
28
|
return QUIC_EXT_ERR_OTHER;
|
|
27
29
|
if (c->handler != NULL)
|
|
28
30
|
return QUIC_EXT_ERR_INVALID_STATE;
|
|
@@ -93,7 +95,7 @@ static int quic_ext_set_application_error(quic_ext_conn *ec,
|
|
|
93
95
|
|
|
94
96
|
const quic_ext_api quic_ext_api_table = {
|
|
95
97
|
.abi_major = QUIC_EXT_ABI_MAJOR,
|
|
96
|
-
.abi_minor =
|
|
98
|
+
.abi_minor = QUIC_EXT_ABI_MINOR,
|
|
97
99
|
.size = sizeof(quic_ext_api),
|
|
98
100
|
.conn_get = quic_ext_conn_get,
|
|
99
101
|
.set_stream_handler = quic_ext_set_stream_handler,
|
data/ext/quic/extconf.rb
CHANGED
|
@@ -5,11 +5,11 @@ require "mini_portile2"
|
|
|
5
5
|
require "shellwords"
|
|
6
6
|
require "fileutils"
|
|
7
7
|
|
|
8
|
-
NGTCP2_VERSION = "1.
|
|
9
|
-
NGTCP2_SHA256 = "
|
|
10
|
-
# The picotls revision that ngtcp2 1.
|
|
11
|
-
PICOTLS_COMMIT = "
|
|
12
|
-
PICOTLS_SHA256 = "
|
|
8
|
+
NGTCP2_VERSION = "1.26.0"
|
|
9
|
+
NGTCP2_SHA256 = "85174d674e7f8fd911a827c6e483fd417b21b1f54d7853dac464cee446c8d35f"
|
|
10
|
+
# The picotls revision that ngtcp2 1.26.0 is tested against (see ngtcp2's README).
|
|
11
|
+
PICOTLS_COMMIT = "a2d95de4c875d6dcb27658e476e3b624f4381bf0"
|
|
12
|
+
PICOTLS_SHA256 = "d54263601c4652ef28451533bb2e2fae3f5f44aff54338cf5110b9c12c4bab3a"
|
|
13
13
|
# Bump when ext/quic/patches/picotls/ or PicotlsRecipe::SOURCES changes;
|
|
14
14
|
# installed? only checks for the archive.
|
|
15
15
|
PICOTLS_PATCH_LEVEL = "p2"
|
data/ext/quic/include/quic/ext.h
CHANGED
|
@@ -14,7 +14,13 @@
|
|
|
14
14
|
* the table's. The structs below grow only by appending, which bumps
|
|
15
15
|
* abi_minor; reordering, removing or retyping a member bumps abi_major.
|
|
16
16
|
* Check `size` before calling a member added after the version you were
|
|
17
|
-
* built against. The handler struct follows the same rules
|
|
17
|
+
* built against. The handler struct follows the same rules:
|
|
18
|
+
* set_stream_handler takes any handler at least as large as the ABI 1.0
|
|
19
|
+
* one, and quic.so calls a member added later only when the handler's
|
|
20
|
+
* `size` covers it. Every member `size` covers must be non-NULL.
|
|
21
|
+
* A member added after ABI 1.0 is marked with the minor that brought it
|
|
22
|
+
* (abi_minor N), and quic.so calls a handler member only when the table's
|
|
23
|
+
* abi_minor is at least that N: an older quic.so leaves it uncalled.
|
|
18
24
|
* - Exceptions: no function in the table and no handler function raises a
|
|
19
25
|
* Ruby exception; they return 0 or a negative error code. The one
|
|
20
26
|
* exception is conn_get, which raises TypeError for a wrong object and is
|
|
@@ -37,6 +43,8 @@
|
|
|
37
43
|
#include <stdint.h>
|
|
38
44
|
|
|
39
45
|
#define QUIC_EXT_ABI_MAJOR 1
|
|
46
|
+
/* The abi_minor of the structs as this header declares them. */
|
|
47
|
+
#define QUIC_EXT_ABI_MINOR 1
|
|
40
48
|
|
|
41
49
|
#define QUIC_EXT_ERR_INVALID_STATE (-1)
|
|
42
50
|
#define QUIC_EXT_ERR_STREAM_ID_BLOCKED (-2)
|
|
@@ -67,6 +75,19 @@ typedef struct {
|
|
|
67
75
|
int (*stream_close)(void *ud, int64_t id, int has_code,
|
|
68
76
|
uint64_t app_error_code);
|
|
69
77
|
int (*handshake_completed)(void *ud);
|
|
78
|
+
/* abi_minor 1 */
|
|
79
|
+
/* The peer sent STOP_SENDING on stream id, which this endpoint sends on
|
|
80
|
+
(stream_stop_sending is the other way: this endpoint stopped reading).
|
|
81
|
+
Called once per stream. Once it returns 0, ngtcp2 shuts the send side
|
|
82
|
+
and sends RESET_STREAM carrying app_error_code, unless all that was
|
|
83
|
+
sent, FIN included, has been acknowledged. next_stream_data should no
|
|
84
|
+
longer offer the stream; if it does, stream_shut_write follows. It can
|
|
85
|
+
come before any recv_stream_data, for a stream the peer has just
|
|
86
|
+
opened, and also comes for a unidirectional stream this endpoint
|
|
87
|
+
opened. stream_close may follow within the same #read_pkt. Calling
|
|
88
|
+
shutdown_stream_write here sends RESET_STREAM with that code instead,
|
|
89
|
+
but stream_close still reports app_error_code. */
|
|
90
|
+
int (*recv_stop_sending)(void *ud, int64_t id, uint64_t app_error_code);
|
|
70
91
|
} quic_ext_stream_handler;
|
|
71
92
|
|
|
72
93
|
typedef struct {
|