quic 0.0.3 → 0.0.5
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/.clang-format +1 -0
- data/.git-blame-ignore-revs +2 -0
- data/CHANGELOG.md +15 -0
- data/README.md +76 -2
- data/examples/demo_certificates.rb +67 -0
- data/examples/echo_endpoint_demo.rb +170 -0
- data/examples/echo_server_demo.rb +2 -58
- data/ext/quic/connection_client.c +77 -59
- data/ext/quic/connection_common.c +423 -377
- data/ext/quic/connection_common.h +20 -11
- data/ext/quic/connection_server.c +67 -48
- data/ext/quic/endpoint.c +206 -200
- data/ext/quic/endpoint.h +8 -5
- data/ext/quic/ext_api.c +41 -47
- data/ext/quic/include/quic/ext.h +26 -19
- data/ext/quic/quic.c +75 -67
- data/ext/quic/quic.h +4 -2
- data/ext/quic/stream.c +80 -80
- data/ext/quic/stream.h +11 -5
- data/ext/quic/tls_context.c +79 -70
- data/ext/quic/tls_context.h +2 -1
- data/lib/quic/version.rb +1 -1
- data/sig/quic.rbs +8 -4
- metadata +5 -1
data/ext/quic/endpoint.c
CHANGED
|
@@ -58,35 +58,29 @@ struct quic_endpoint {
|
|
|
58
58
|
collide. */
|
|
59
59
|
static st_index_t quic_cid_hash_seed;
|
|
60
60
|
|
|
61
|
-
static int
|
|
62
|
-
quic_cid_cmp(st_data_t a, st_data_t b)
|
|
63
|
-
{
|
|
61
|
+
static int quic_cid_cmp(st_data_t a, st_data_t b) {
|
|
64
62
|
return !ngtcp2_cid_eq((const ngtcp2_cid *)a, (const ngtcp2_cid *)b);
|
|
65
63
|
}
|
|
66
64
|
|
|
67
|
-
static st_index_t
|
|
68
|
-
quic_cid_hash(st_data_t a)
|
|
69
|
-
{
|
|
65
|
+
static st_index_t quic_cid_hash(st_data_t a) {
|
|
70
66
|
const ngtcp2_cid *cid = (const ngtcp2_cid *)a;
|
|
71
67
|
return st_hash(cid->data, cid->datalen, quic_cid_hash_seed);
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
static const struct st_hash_type quic_cid_hash_type = {quic_cid_cmp,
|
|
70
|
+
static const struct st_hash_type quic_cid_hash_type = {quic_cid_cmp,
|
|
71
|
+
quic_cid_hash};
|
|
75
72
|
|
|
76
|
-
static int
|
|
77
|
-
quic_endpoint_mark_i(st_data_t key, st_data_t value, st_data_t arg)
|
|
78
|
-
{
|
|
73
|
+
static int quic_endpoint_mark_i(st_data_t key, st_data_t value, st_data_t arg) {
|
|
79
74
|
(void)key;
|
|
80
75
|
(void)arg;
|
|
81
76
|
rb_gc_mark_movable((VALUE)value);
|
|
82
77
|
return ST_CONTINUE;
|
|
83
78
|
}
|
|
84
79
|
|
|
85
|
-
static void
|
|
86
|
-
quic_endpoint_mark(void *ptr)
|
|
87
|
-
{
|
|
80
|
+
static void quic_endpoint_mark(void *ptr) {
|
|
88
81
|
quic_endpoint_t *ep = (quic_endpoint_t *)ptr;
|
|
89
|
-
if (ep->cids != NULL)
|
|
82
|
+
if (ep->cids != NULL)
|
|
83
|
+
st_foreach(ep->cids, quic_endpoint_mark_i, 0);
|
|
90
84
|
rb_gc_mark_movable(ep->conns);
|
|
91
85
|
rb_gc_mark_movable(ep->responses);
|
|
92
86
|
rb_gc_mark_movable(ep->closed);
|
|
@@ -96,9 +90,8 @@ quic_endpoint_mark(void *ptr)
|
|
|
96
90
|
rb_gc_mark_movable(ep->settings);
|
|
97
91
|
}
|
|
98
92
|
|
|
99
|
-
static int
|
|
100
|
-
|
|
101
|
-
{
|
|
93
|
+
static int quic_endpoint_compact_check_i(st_data_t key, st_data_t value,
|
|
94
|
+
st_data_t arg, int error) {
|
|
102
95
|
(void)key;
|
|
103
96
|
(void)value;
|
|
104
97
|
(void)arg;
|
|
@@ -106,9 +99,8 @@ quic_endpoint_compact_check_i(st_data_t key, st_data_t value, st_data_t arg, int
|
|
|
106
99
|
return ST_REPLACE;
|
|
107
100
|
}
|
|
108
101
|
|
|
109
|
-
static int
|
|
110
|
-
|
|
111
|
-
{
|
|
102
|
+
static int quic_endpoint_compact_replace_i(st_data_t *key, st_data_t *value,
|
|
103
|
+
st_data_t arg, int existing) {
|
|
112
104
|
(void)key;
|
|
113
105
|
(void)arg;
|
|
114
106
|
(void)existing;
|
|
@@ -116,9 +108,7 @@ quic_endpoint_compact_replace_i(st_data_t *key, st_data_t *value, st_data_t arg,
|
|
|
116
108
|
return ST_CONTINUE;
|
|
117
109
|
}
|
|
118
110
|
|
|
119
|
-
static void
|
|
120
|
-
quic_endpoint_compact(void *ptr)
|
|
121
|
-
{
|
|
111
|
+
static void quic_endpoint_compact(void *ptr) {
|
|
122
112
|
quic_endpoint_t *ep = (quic_endpoint_t *)ptr;
|
|
123
113
|
if (ep->cids != NULL) {
|
|
124
114
|
st_foreach_with_replace(ep->cids, quic_endpoint_compact_check_i,
|
|
@@ -133,9 +123,8 @@ quic_endpoint_compact(void *ptr)
|
|
|
133
123
|
ep->settings = rb_gc_location(ep->settings);
|
|
134
124
|
}
|
|
135
125
|
|
|
136
|
-
static int
|
|
137
|
-
|
|
138
|
-
{
|
|
126
|
+
static int quic_endpoint_free_key_i(st_data_t key, st_data_t value,
|
|
127
|
+
st_data_t arg) {
|
|
139
128
|
(void)value;
|
|
140
129
|
(void)arg;
|
|
141
130
|
xfree((void *)key);
|
|
@@ -144,9 +133,7 @@ quic_endpoint_free_key_i(st_data_t key, st_data_t value, st_data_t arg)
|
|
|
144
133
|
|
|
145
134
|
/* Connections still in the table are unreachable too (each marks the
|
|
146
135
|
Endpoint), and quic_conn_free never reaches back here. */
|
|
147
|
-
static void
|
|
148
|
-
quic_endpoint_free(void *ptr)
|
|
149
|
-
{
|
|
136
|
+
static void quic_endpoint_free(void *ptr) {
|
|
150
137
|
quic_endpoint_t *ep = (quic_endpoint_t *)ptr;
|
|
151
138
|
if (ep->cids != NULL) {
|
|
152
139
|
st_foreach(ep->cids, quic_endpoint_free_key_i, 0);
|
|
@@ -156,31 +143,32 @@ quic_endpoint_free(void *ptr)
|
|
|
156
143
|
xfree(ep);
|
|
157
144
|
}
|
|
158
145
|
|
|
159
|
-
static size_t
|
|
160
|
-
quic_endpoint_size(const void *ptr)
|
|
161
|
-
{
|
|
146
|
+
static size_t quic_endpoint_size(const void *ptr) {
|
|
162
147
|
const quic_endpoint_t *ep = (const quic_endpoint_t *)ptr;
|
|
163
148
|
return sizeof(*ep) + (ep->cids != NULL ? st_memsize(ep->cids) : 0);
|
|
164
149
|
}
|
|
165
150
|
|
|
166
151
|
static const rb_data_type_t quic_endpoint_data_type = {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
152
|
+
"QUIC::Endpoint",
|
|
153
|
+
{
|
|
154
|
+
quic_endpoint_mark,
|
|
155
|
+
quic_endpoint_free,
|
|
156
|
+
quic_endpoint_size,
|
|
157
|
+
quic_endpoint_compact,
|
|
158
|
+
},
|
|
159
|
+
NULL,
|
|
160
|
+
NULL,
|
|
161
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
171
162
|
};
|
|
172
163
|
|
|
173
|
-
static quic_endpoint_t *
|
|
174
|
-
quic_endpoint_get(VALUE self)
|
|
175
|
-
{
|
|
164
|
+
static quic_endpoint_t *quic_endpoint_get(VALUE self) {
|
|
176
165
|
quic_endpoint_t *ep;
|
|
177
166
|
TypedData_Get_Struct(self, quic_endpoint_t, &quic_endpoint_data_type, ep);
|
|
178
167
|
return ep;
|
|
179
168
|
}
|
|
180
169
|
|
|
181
|
-
void
|
|
182
|
-
|
|
183
|
-
{
|
|
170
|
+
void quic_endpoint_associate_cid(quic_endpoint_t *ep, const ngtcp2_cid *cid,
|
|
171
|
+
VALUE conn) {
|
|
184
172
|
/* For a key already there, st_insert replaces the value and keeps the
|
|
185
173
|
key it has, so a copy is made only for a new key. */
|
|
186
174
|
if (st_lookup(ep->cids, (st_data_t)cid, NULL)) {
|
|
@@ -192,68 +180,65 @@ quic_endpoint_associate_cid(quic_endpoint_t *ep, const ngtcp2_cid *cid, VALUE co
|
|
|
192
180
|
st_insert(ep->cids, (st_data_t)key, (st_data_t)conn);
|
|
193
181
|
}
|
|
194
182
|
|
|
195
|
-
void
|
|
196
|
-
|
|
197
|
-
{
|
|
183
|
+
void quic_endpoint_dissociate_cid(quic_endpoint_t *ep, const ngtcp2_cid *cid,
|
|
184
|
+
VALUE conn) {
|
|
198
185
|
st_data_t key = (st_data_t)cid;
|
|
199
186
|
st_data_t value;
|
|
200
|
-
if (!st_lookup(ep->cids, key, &value) || (VALUE)value != conn)
|
|
187
|
+
if (!st_lookup(ep->cids, key, &value) || (VALUE)value != conn)
|
|
188
|
+
return;
|
|
201
189
|
/* st_delete hands back the stored key. */
|
|
202
|
-
if (st_delete(ep->cids, &key, &value))
|
|
190
|
+
if (st_delete(ep->cids, &key, &value))
|
|
191
|
+
xfree((void *)key);
|
|
203
192
|
}
|
|
204
193
|
|
|
205
|
-
int
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
? 0 : -1;
|
|
194
|
+
int quic_endpoint_generate_reset_token(const quic_endpoint_t *ep,
|
|
195
|
+
uint8_t *token, const ngtcp2_cid *cid) {
|
|
196
|
+
return ngtcp2_crypto_generate_stateless_reset_token(
|
|
197
|
+
token, ep->reset_secret, sizeof(ep->reset_secret), cid) == 0
|
|
198
|
+
? 0
|
|
199
|
+
: -1;
|
|
212
200
|
}
|
|
213
201
|
|
|
214
|
-
static VALUE
|
|
215
|
-
quic_addr_str(const ngtcp2_addr *addr)
|
|
216
|
-
{
|
|
202
|
+
static VALUE quic_addr_str(const ngtcp2_addr *addr) {
|
|
217
203
|
return rb_str_new((const char *)addr->addr, (long)addr->addrlen);
|
|
218
204
|
}
|
|
219
205
|
|
|
220
206
|
/* Queue an answer for #write_pkt. Returns false when the queue is full and
|
|
221
207
|
the answer was dropped. */
|
|
222
|
-
static bool
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
208
|
+
static bool quic_endpoint_push_response(quic_endpoint_t *ep, VALUE pkt,
|
|
209
|
+
VALUE to) {
|
|
210
|
+
if (RARRAY_LEN(ep->responses) >= QUIC_ENDPOINT_MAX_RESPONSES)
|
|
211
|
+
return false;
|
|
226
212
|
rb_ary_push(ep->responses, rb_assoc_new(pkt, to));
|
|
227
213
|
return true;
|
|
228
214
|
}
|
|
229
215
|
|
|
230
|
-
static void
|
|
231
|
-
quic_conn_set_error(quic_conn_t *c, VALUE exc)
|
|
232
|
-
{
|
|
216
|
+
static void quic_conn_set_error(quic_conn_t *c, VALUE exc) {
|
|
233
217
|
/* The first failure is the reason; what follows is its consequence. */
|
|
234
|
-
if (NIL_P(c->error))
|
|
218
|
+
if (NIL_P(c->error))
|
|
219
|
+
c->error = exc;
|
|
235
220
|
}
|
|
236
221
|
|
|
237
222
|
/* Take the Stateless Resets that came back since the last call, one per
|
|
238
223
|
whole second. Computed on read_pkt rather than with a timer. */
|
|
239
|
-
static void
|
|
240
|
-
|
|
241
|
-
{
|
|
224
|
+
static void quic_endpoint_refill_reset_bucket(quic_endpoint_t *ep,
|
|
225
|
+
ngtcp2_tstamp now) {
|
|
242
226
|
if (ep->reset_bucket >= QUIC_STATELESS_RESET_BURST) {
|
|
243
227
|
ep->reset_refill_ts = now;
|
|
244
228
|
return;
|
|
245
229
|
}
|
|
246
230
|
uint64_t n = (now - ep->reset_refill_ts) / NGTCP2_SECONDS;
|
|
247
|
-
if (n == 0)
|
|
231
|
+
if (n == 0)
|
|
232
|
+
return;
|
|
248
233
|
ep->reset_bucket = n >= QUIC_STATELESS_RESET_BURST - ep->reset_bucket
|
|
249
|
-
|
|
234
|
+
? QUIC_STATELESS_RESET_BURST
|
|
235
|
+
: ep->reset_bucket + (size_t)n;
|
|
250
236
|
ep->reset_refill_ts += n * NGTCP2_SECONDS;
|
|
251
237
|
}
|
|
252
238
|
|
|
253
|
-
static void
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
{
|
|
239
|
+
static void quic_endpoint_send_version_negotiation(quic_endpoint_t *ep,
|
|
240
|
+
const ngtcp2_version_cid *vc,
|
|
241
|
+
VALUE remote) {
|
|
257
242
|
uint8_t unused_bits;
|
|
258
243
|
uint32_t grease;
|
|
259
244
|
if (RAND_bytes(&unused_bits, 1) != 1 ||
|
|
@@ -263,77 +248,87 @@ quic_endpoint_send_version_negotiation(quic_endpoint_t *ep, const ngtcp2_version
|
|
|
263
248
|
/* A reserved version (0x?a?a?a?a) ahead of the one supported, so that
|
|
264
249
|
clients keep handling versions they do not know (RFC 9000 section
|
|
265
250
|
6.3). */
|
|
266
|
-
uint32_t versions[] = {(grease & 0xf0f0f0f0U) | 0x0a0a0a0aU,
|
|
251
|
+
uint32_t versions[] = {(grease & 0xf0f0f0f0U) | 0x0a0a0a0aU,
|
|
252
|
+
NGTCP2_PROTO_VER_V1};
|
|
267
253
|
|
|
268
254
|
VALUE pkt = rb_str_buf_new(NGTCP2_MAX_UDP_PAYLOAD_SIZE);
|
|
269
255
|
ngtcp2_ssize n = ngtcp2_pkt_write_version_negotiation(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
256
|
+
(uint8_t *)RSTRING_PTR(pkt), NGTCP2_MAX_UDP_PAYLOAD_SIZE, unused_bits,
|
|
257
|
+
vc->scid, vc->scidlen, vc->dcid, vc->dcidlen, versions,
|
|
258
|
+
sizeof(versions) / sizeof(versions[0]));
|
|
259
|
+
if (n <= 0)
|
|
260
|
+
return;
|
|
273
261
|
rb_str_set_len(pkt, n);
|
|
274
262
|
quic_endpoint_push_response(ep, pkt, rb_str_dup(remote));
|
|
275
263
|
}
|
|
276
264
|
|
|
277
265
|
/* Tell the peer that this Endpoint has no state for dcid, as
|
|
278
266
|
examples/server.cc's send_stateless_reset does. */
|
|
279
|
-
static void
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
267
|
+
static void quic_endpoint_send_stateless_reset(quic_endpoint_t *ep,
|
|
268
|
+
const ngtcp2_cid *dcid,
|
|
269
|
+
size_t pktlen, VALUE remote) {
|
|
270
|
+
if (ep->reset_bucket == 0)
|
|
271
|
+
return;
|
|
284
272
|
ep->reset_bucket--;
|
|
285
273
|
|
|
286
274
|
ngtcp2_stateless_reset_token token;
|
|
287
|
-
if (quic_endpoint_generate_reset_token(ep, token.data, dcid) != 0)
|
|
275
|
+
if (quic_endpoint_generate_reset_token(ep, token.data, dcid) != 0)
|
|
276
|
+
return;
|
|
288
277
|
|
|
289
278
|
/* Shorter than the packet that prompted it, so that two endpoints cannot
|
|
290
279
|
keep answering each other's resets (RFC 9000 section 10.3.3): one byte
|
|
291
280
|
shorter up to 43 bytes, 42 bytes beyond. */
|
|
292
|
-
enum {
|
|
281
|
+
enum {
|
|
282
|
+
MAX_RANDLEN = NGTCP2_MAX_CIDLEN + 22 - NGTCP2_STATELESS_RESET_TOKENLEN
|
|
283
|
+
};
|
|
293
284
|
uint8_t rand_bytes[MAX_RANDLEN];
|
|
294
|
-
size_t randlen =
|
|
295
|
-
|
|
285
|
+
size_t randlen =
|
|
286
|
+
pktlen <= 43 ? pktlen - NGTCP2_STATELESS_RESET_TOKENLEN - 1 : MAX_RANDLEN;
|
|
287
|
+
if (RAND_bytes(rand_bytes, (int)randlen) != 1)
|
|
288
|
+
return;
|
|
296
289
|
|
|
297
290
|
VALUE pkt = rb_str_buf_new(NGTCP2_MAX_UDP_PAYLOAD_SIZE);
|
|
298
291
|
ngtcp2_ssize n = ngtcp2_pkt_write_stateless_reset2(
|
|
299
|
-
|
|
300
|
-
|
|
292
|
+
(uint8_t *)RSTRING_PTR(pkt), NGTCP2_MAX_UDP_PAYLOAD_SIZE, &token,
|
|
293
|
+
rand_bytes, randlen);
|
|
294
|
+
if (n <= 0)
|
|
295
|
+
return;
|
|
301
296
|
rb_str_set_len(pkt, n);
|
|
302
297
|
quic_endpoint_push_response(ep, pkt, rb_str_dup(remote));
|
|
303
298
|
}
|
|
304
299
|
|
|
305
300
|
/* Turn a new connection away with CONNECTION_REFUSED in an Initial packet,
|
|
306
301
|
without making any state for it. */
|
|
307
|
-
static void
|
|
308
|
-
|
|
309
|
-
{
|
|
302
|
+
static void quic_endpoint_refuse(quic_endpoint_t *ep, const ngtcp2_pkt_hd *hd,
|
|
303
|
+
VALUE remote) {
|
|
310
304
|
VALUE pkt = rb_str_buf_new(NGTCP2_MAX_UDP_PAYLOAD_SIZE);
|
|
311
305
|
/* Despite its documentation, this returns the packet's length. */
|
|
312
306
|
ngtcp2_ssize n = ngtcp2_crypto_write_connection_close(
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (n <= 0)
|
|
307
|
+
(uint8_t *)RSTRING_PTR(pkt), NGTCP2_MAX_UDP_PAYLOAD_SIZE, hd->version,
|
|
308
|
+
&hd->scid, &hd->dcid, NGTCP2_CONNECTION_REFUSED, NULL, 0);
|
|
309
|
+
if (n <= 0)
|
|
310
|
+
return;
|
|
316
311
|
rb_str_set_len(pkt, n);
|
|
317
312
|
quic_endpoint_push_response(ep, pkt, rb_str_dup(remote));
|
|
318
313
|
}
|
|
319
314
|
|
|
320
315
|
/* The closing and draining periods last three PTOs (RFC 9000 section
|
|
321
316
|
10.2). */
|
|
322
|
-
static ngtcp2_tstamp
|
|
323
|
-
|
|
324
|
-
{
|
|
317
|
+
static ngtcp2_tstamp quic_close_deadline(const quic_conn_t *c,
|
|
318
|
+
ngtcp2_tstamp now) {
|
|
325
319
|
return now + 3 * ngtcp2_conn_get_pto2(c->conn);
|
|
326
320
|
}
|
|
327
321
|
|
|
328
322
|
/* Enter the closing period with a CONNECTION_CLOSE carrying ccerr, and
|
|
329
323
|
queue that packet. Returns false when ngtcp2 cannot build it; the
|
|
330
324
|
connection then has to leave the table at once. */
|
|
331
|
-
static bool
|
|
332
|
-
|
|
333
|
-
{
|
|
325
|
+
static bool quic_endpoint_start_closing(quic_endpoint_t *ep, quic_conn_t *c,
|
|
326
|
+
const ngtcp2_ccerr *ccerr) {
|
|
334
327
|
ngtcp2_tstamp now = quic_now();
|
|
335
|
-
if (ngtcp2_conn_in_closing_period2(c->conn) ||
|
|
336
|
-
|
|
328
|
+
if (ngtcp2_conn_in_closing_period2(c->conn) ||
|
|
329
|
+
ngtcp2_conn_in_draining_period2(c->conn)) {
|
|
330
|
+
if (c->close_deadline == 0)
|
|
331
|
+
c->close_deadline = quic_close_deadline(c, now);
|
|
337
332
|
return true;
|
|
338
333
|
}
|
|
339
334
|
|
|
@@ -342,15 +337,19 @@ quic_endpoint_start_closing(quic_endpoint_t *ep, quic_conn_t *c, const ngtcp2_cc
|
|
|
342
337
|
ngtcp2_pkt_info pi;
|
|
343
338
|
VALUE pkt = rb_str_buf_new(QUIC_WRITE_PKT_BUFLEN);
|
|
344
339
|
ngtcp2_ssize n = ngtcp2_conn_write_connection_close(
|
|
345
|
-
|
|
346
|
-
|
|
340
|
+
c->conn, &ps.path, &pi, (uint8_t *)RSTRING_PTR(pkt),
|
|
341
|
+
QUIC_WRITE_PKT_BUFLEN, ccerr, now);
|
|
342
|
+
if (n < 0)
|
|
343
|
+
return false;
|
|
347
344
|
|
|
348
345
|
c->close_deadline = quic_close_deadline(c, now);
|
|
349
346
|
c->close_next_pkts_recv = 1;
|
|
350
|
-
if (n == 0)
|
|
347
|
+
if (n == 0)
|
|
348
|
+
return true;
|
|
351
349
|
rb_str_set_len(pkt, n);
|
|
352
350
|
c->closebuf = pkt;
|
|
353
|
-
quic_endpoint_push_response(ep, rb_str_dup(pkt),
|
|
351
|
+
quic_endpoint_push_response(ep, rb_str_dup(pkt),
|
|
352
|
+
quic_addr_str(&ps.path.remote));
|
|
354
353
|
return true;
|
|
355
354
|
}
|
|
356
355
|
|
|
@@ -358,10 +357,10 @@ quic_endpoint_start_closing(quic_endpoint_t *ep, quic_conn_t *c, const ngtcp2_cc
|
|
|
358
357
|
CONNECTION_CLOSE again, but no more than three times what the peer sent
|
|
359
358
|
and to every 1st, 2nd, 4th, 8th, ... packet only (examples/server.cc's
|
|
360
359
|
Handler::send_conn_close). */
|
|
361
|
-
static void
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
360
|
+
static void quic_endpoint_resend_close(quic_endpoint_t *ep, quic_conn_t *c,
|
|
361
|
+
size_t pktlen, VALUE remote) {
|
|
362
|
+
if (NIL_P(c->closebuf))
|
|
363
|
+
return;
|
|
365
364
|
|
|
366
365
|
c->close_bytes_recv += pktlen;
|
|
367
366
|
c->close_pkts_recv++;
|
|
@@ -370,7 +369,9 @@ quic_endpoint_resend_close(quic_endpoint_t *ep, quic_conn_t *c, size_t pktlen, V
|
|
|
370
369
|
c->close_bytes_recv * 3 < c->close_bytes_sent + len) {
|
|
371
370
|
return;
|
|
372
371
|
}
|
|
373
|
-
if (!quic_endpoint_push_response(ep, rb_str_dup(c->closebuf),
|
|
372
|
+
if (!quic_endpoint_push_response(ep, rb_str_dup(c->closebuf),
|
|
373
|
+
rb_str_dup(remote)))
|
|
374
|
+
return;
|
|
374
375
|
c->close_bytes_sent += len;
|
|
375
376
|
c->close_next_pkts_recv *= 2;
|
|
376
377
|
}
|
|
@@ -380,12 +381,12 @@ quic_endpoint_resend_close(quic_endpoint_t *ep, quic_conn_t *c, size_t pktlen, V
|
|
|
380
381
|
for it; the reason goes to c->error. Returns true when the connection has
|
|
381
382
|
to leave the table now, false when it stays for its closing or draining
|
|
382
383
|
period. */
|
|
383
|
-
static bool
|
|
384
|
-
|
|
385
|
-
{
|
|
384
|
+
static bool quic_endpoint_handle_error(quic_endpoint_t *ep, quic_conn_t *c,
|
|
385
|
+
int rv) {
|
|
386
386
|
VALUE exc = c->pending_exc;
|
|
387
387
|
c->pending_exc = Qnil;
|
|
388
|
-
if (!NIL_P(exc))
|
|
388
|
+
if (!NIL_P(exc))
|
|
389
|
+
rv = NGTCP2_ERR_CALLBACK_FAILURE;
|
|
389
390
|
|
|
390
391
|
ngtcp2_ccerr ccerr;
|
|
391
392
|
switch (rv) {
|
|
@@ -412,7 +413,8 @@ quic_endpoint_handle_error(quic_endpoint_t *ep, quic_conn_t *c, int rv)
|
|
|
412
413
|
/* Send the TLS alert itself, as examples/server.cc does; set_liberr
|
|
413
414
|
would only know that the handshake failed. */
|
|
414
415
|
quic_conn_set_error(c, quic_conn_error_new(c, rv));
|
|
415
|
-
ngtcp2_ccerr_set_tls_alert(&ccerr, ngtcp2_conn_get_tls_alert2(c->conn),
|
|
416
|
+
ngtcp2_ccerr_set_tls_alert(&ccerr, ngtcp2_conn_get_tls_alert2(c->conn),
|
|
417
|
+
NULL, 0);
|
|
416
418
|
break;
|
|
417
419
|
default:
|
|
418
420
|
quic_conn_set_error(c, quic_conn_error_new(c, rv));
|
|
@@ -423,52 +425,55 @@ quic_endpoint_handle_error(quic_endpoint_t *ep, quic_conn_t *c, int rv)
|
|
|
423
425
|
}
|
|
424
426
|
|
|
425
427
|
/* Drop every table entry of conn and cut it loose from the Endpoint. */
|
|
426
|
-
static void
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
428
|
+
static void quic_endpoint_detach(quic_endpoint_t *ep, VALUE conn,
|
|
429
|
+
quic_conn_t *c) {
|
|
430
|
+
quic_endpoint_dissociate_cid(
|
|
431
|
+
ep, ngtcp2_conn_get_client_initial_dcid2(c->conn), conn);
|
|
430
432
|
|
|
431
433
|
size_t n = ngtcp2_conn_get_scid2(c->conn, NULL);
|
|
432
434
|
VALUE tmp;
|
|
433
435
|
ngtcp2_cid *scids = ALLOCV_N(ngtcp2_cid, tmp, n);
|
|
434
436
|
ngtcp2_conn_get_scid2(c->conn, scids);
|
|
435
|
-
for (size_t i = 0; i < n; i++)
|
|
437
|
+
for (size_t i = 0; i < n; i++)
|
|
438
|
+
quic_endpoint_dissociate_cid(ep, &scids[i], conn);
|
|
436
439
|
ALLOCV_END(tmp);
|
|
437
440
|
|
|
438
441
|
c->endpoint = NULL;
|
|
439
442
|
c->endpoint_owner = Qnil;
|
|
443
|
+
/* The Endpoint never drives the connection again. */
|
|
444
|
+
quic_conn_close_qlog(c);
|
|
440
445
|
}
|
|
441
446
|
|
|
442
447
|
/* Take conn out of the table and hand it to #take_closed. */
|
|
443
|
-
static void
|
|
444
|
-
|
|
445
|
-
{
|
|
448
|
+
static void quic_endpoint_remove(quic_endpoint_t *ep, VALUE conn,
|
|
449
|
+
quic_conn_t *c) {
|
|
446
450
|
quic_endpoint_detach(ep, conn, c);
|
|
447
451
|
long len = RARRAY_LEN(ep->conns);
|
|
448
452
|
for (long i = 0; i < len; i++) {
|
|
449
|
-
if (RARRAY_AREF(ep->conns, i) != conn)
|
|
453
|
+
if (RARRAY_AREF(ep->conns, i) != conn)
|
|
454
|
+
continue;
|
|
450
455
|
rb_ary_delete_at(ep->conns, i);
|
|
451
|
-
if (i < ep->write_cursor)
|
|
456
|
+
if (i < ep->write_cursor)
|
|
457
|
+
ep->write_cursor--;
|
|
452
458
|
break;
|
|
453
459
|
}
|
|
454
460
|
rb_ary_push(ep->closed, conn);
|
|
455
461
|
}
|
|
456
462
|
|
|
457
|
-
void
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
463
|
+
void quic_endpoint_close_conn(quic_endpoint_t *ep, quic_conn_t *c,
|
|
464
|
+
const ngtcp2_ccerr *ccerr) {
|
|
465
|
+
if (!quic_endpoint_start_closing(ep, c, ccerr))
|
|
466
|
+
quic_endpoint_remove(ep, c->owner, c);
|
|
461
467
|
}
|
|
462
468
|
|
|
463
469
|
/* QUIC::Endpoint._new(local_sockaddr:, tls_context:, transport_params:,
|
|
464
470
|
settings:, max_connections:), every keyword required. Endpoint.new
|
|
465
471
|
(lib/quic/endpoint.rb) fills in the defaults. */
|
|
466
|
-
static VALUE
|
|
467
|
-
quic_endpoint_s_new(int argc, VALUE *argv, VALUE klass)
|
|
468
|
-
{
|
|
472
|
+
static VALUE quic_endpoint_s_new(int argc, VALUE *argv, VALUE klass) {
|
|
469
473
|
VALUE opts = Qnil;
|
|
470
474
|
rb_scan_args(argc, argv, "0:", &opts);
|
|
471
|
-
if (NIL_P(opts))
|
|
475
|
+
if (NIL_P(opts))
|
|
476
|
+
opts = rb_hash_new();
|
|
472
477
|
|
|
473
478
|
ID keywords[5];
|
|
474
479
|
VALUE values[5];
|
|
@@ -489,11 +494,13 @@ quic_endpoint_s_new(int argc, VALUE *argv, VALUE klass)
|
|
|
489
494
|
quic_fill_settings(&settings, values[3]);
|
|
490
495
|
long max_connections = NUM2LONG(values[4]);
|
|
491
496
|
if (max_connections <= 0) {
|
|
492
|
-
rb_raise(rb_eArgError, "max_connections must be positive (got %ld)",
|
|
497
|
+
rb_raise(rb_eArgError, "max_connections must be positive (got %ld)",
|
|
498
|
+
max_connections);
|
|
493
499
|
}
|
|
494
500
|
|
|
495
501
|
quic_endpoint_t *ep;
|
|
496
|
-
VALUE self = TypedData_Make_Struct(klass, quic_endpoint_t,
|
|
502
|
+
VALUE self = TypedData_Make_Struct(klass, quic_endpoint_t,
|
|
503
|
+
&quic_endpoint_data_type, ep);
|
|
497
504
|
ep->conns = Qnil;
|
|
498
505
|
ep->responses = Qnil;
|
|
499
506
|
ep->closed = Qnil;
|
|
@@ -524,9 +531,8 @@ struct quic_endpoint_read_args {
|
|
|
524
531
|
};
|
|
525
532
|
|
|
526
533
|
/* A packet for a connection in the table. */
|
|
527
|
-
static VALUE
|
|
528
|
-
|
|
529
|
-
{
|
|
534
|
+
static VALUE quic_endpoint_dispatch(struct quic_endpoint_read_args *a,
|
|
535
|
+
VALUE conn) {
|
|
530
536
|
quic_conn_t *c = quic_conn_get(conn);
|
|
531
537
|
const uint8_t *data = (const uint8_t *)RSTRING_PTR(a->packet);
|
|
532
538
|
size_t datalen = (size_t)RSTRING_LEN(a->packet);
|
|
@@ -535,10 +541,12 @@ quic_endpoint_dispatch(struct quic_endpoint_read_args *a, VALUE conn)
|
|
|
535
541
|
quic_endpoint_resend_close(a->ep, c, datalen, a->remote);
|
|
536
542
|
return Qnil;
|
|
537
543
|
}
|
|
538
|
-
if (c->close_deadline != 0)
|
|
544
|
+
if (c->close_deadline != 0)
|
|
545
|
+
return Qnil;
|
|
539
546
|
|
|
540
547
|
int rv = quic_conn_read_pkt_raw(c, &a->path, data, datalen);
|
|
541
|
-
if ((rv != 0 || !NIL_P(c->pending_exc)) &&
|
|
548
|
+
if ((rv != 0 || !NIL_P(c->pending_exc)) &&
|
|
549
|
+
quic_endpoint_handle_error(a->ep, c, rv)) {
|
|
542
550
|
quic_endpoint_remove(a->ep, conn, c);
|
|
543
551
|
return Qnil;
|
|
544
552
|
}
|
|
@@ -547,9 +555,8 @@ quic_endpoint_dispatch(struct quic_endpoint_read_args *a, VALUE conn)
|
|
|
547
555
|
|
|
548
556
|
/* A packet for no connection in the table: a new connection, or one this
|
|
549
557
|
Endpoint has forgotten. */
|
|
550
|
-
static VALUE
|
|
551
|
-
|
|
552
|
-
{
|
|
558
|
+
static VALUE quic_endpoint_accept(struct quic_endpoint_read_args *a,
|
|
559
|
+
const ngtcp2_cid *dcid) {
|
|
553
560
|
quic_endpoint_t *ep = a->ep;
|
|
554
561
|
const uint8_t *data = (const uint8_t *)RSTRING_PTR(a->packet);
|
|
555
562
|
size_t datalen = (size_t)RSTRING_LEN(a->packet);
|
|
@@ -570,8 +577,9 @@ quic_endpoint_accept(struct quic_endpoint_read_args *a, const ngtcp2_cid *dcid)
|
|
|
570
577
|
}
|
|
571
578
|
|
|
572
579
|
/* As in Server._accept, a token is accepted without checking it. */
|
|
573
|
-
VALUE conn = quic_server_conn_new(rb_cQUICConnectionServer, &hd, &a->path,
|
|
574
|
-
ep->
|
|
580
|
+
VALUE conn = quic_server_conn_new(rb_cQUICConnectionServer, &hd, &a->path,
|
|
581
|
+
ep->tls_context, ep->transport_params,
|
|
582
|
+
ep->settings, ep, a->self);
|
|
575
583
|
quic_conn_t *c = quic_conn_get(conn);
|
|
576
584
|
int rv = quic_conn_read_pkt_raw(c, &a->path, data, datalen);
|
|
577
585
|
if (rv != 0 || !NIL_P(c->pending_exc)) {
|
|
@@ -582,20 +590,20 @@ quic_endpoint_accept(struct quic_endpoint_read_args *a, const ngtcp2_cid *dcid)
|
|
|
582
590
|
return Qnil;
|
|
583
591
|
}
|
|
584
592
|
|
|
585
|
-
quic_endpoint_associate_cid(ep, ngtcp2_conn_get_client_initial_dcid2(c->conn),
|
|
593
|
+
quic_endpoint_associate_cid(ep, ngtcp2_conn_get_client_initial_dcid2(c->conn),
|
|
594
|
+
conn);
|
|
586
595
|
size_t n = ngtcp2_conn_get_scid2(c->conn, NULL);
|
|
587
596
|
VALUE tmp;
|
|
588
597
|
ngtcp2_cid *scids = ALLOCV_N(ngtcp2_cid, tmp, n);
|
|
589
598
|
ngtcp2_conn_get_scid2(c->conn, scids);
|
|
590
|
-
for (size_t i = 0; i < n; i++)
|
|
599
|
+
for (size_t i = 0; i < n; i++)
|
|
600
|
+
quic_endpoint_associate_cid(ep, &scids[i], conn);
|
|
591
601
|
ALLOCV_END(tmp);
|
|
592
602
|
rb_ary_push(ep->conns, conn);
|
|
593
603
|
return conn;
|
|
594
604
|
}
|
|
595
605
|
|
|
596
|
-
static VALUE
|
|
597
|
-
quic_endpoint_read_pkt_body(VALUE arg)
|
|
598
|
-
{
|
|
606
|
+
static VALUE quic_endpoint_read_pkt_body(VALUE arg) {
|
|
599
607
|
struct quic_endpoint_read_args *a = (struct quic_endpoint_read_args *)arg;
|
|
600
608
|
const uint8_t *data = (const uint8_t *)RSTRING_PTR(a->packet);
|
|
601
609
|
size_t datalen = (size_t)RSTRING_LEN(a->packet);
|
|
@@ -603,7 +611,8 @@ quic_endpoint_read_pkt_body(VALUE arg)
|
|
|
603
611
|
quic_endpoint_refill_reset_bucket(a->ep, quic_now());
|
|
604
612
|
|
|
605
613
|
/* ngtcp2_pkt_decode_version_cid asserts datalen > 0. */
|
|
606
|
-
if (datalen == 0)
|
|
614
|
+
if (datalen == 0)
|
|
615
|
+
return Qnil;
|
|
607
616
|
|
|
608
617
|
ngtcp2_version_cid vc;
|
|
609
618
|
int rv = ngtcp2_pkt_decode_version_cid(&vc, data, datalen, QUIC_SCID_LEN);
|
|
@@ -612,7 +621,8 @@ quic_endpoint_read_pkt_body(VALUE arg)
|
|
|
612
621
|
return Qnil;
|
|
613
622
|
}
|
|
614
623
|
/* A supported version never carries a DCID longer than this. */
|
|
615
|
-
if (rv != 0 || vc.dcidlen > NGTCP2_MAX_CIDLEN)
|
|
624
|
+
if (rv != 0 || vc.dcidlen > NGTCP2_MAX_CIDLEN)
|
|
625
|
+
return Qnil;
|
|
616
626
|
|
|
617
627
|
ngtcp2_cid dcid;
|
|
618
628
|
ngtcp2_cid_init(&dcid, vc.dcid, vc.dcidlen);
|
|
@@ -623,9 +633,7 @@ quic_endpoint_read_pkt_body(VALUE arg)
|
|
|
623
633
|
return quic_endpoint_accept(a, &dcid);
|
|
624
634
|
}
|
|
625
635
|
|
|
626
|
-
static VALUE
|
|
627
|
-
quic_endpoint_read_pkt_unlock(VALUE arg)
|
|
628
|
-
{
|
|
636
|
+
static VALUE quic_endpoint_read_pkt_unlock(VALUE arg) {
|
|
629
637
|
rb_str_unlocktmp(((struct quic_endpoint_read_args *)arg)->packet);
|
|
630
638
|
return Qnil;
|
|
631
639
|
}
|
|
@@ -634,13 +642,12 @@ quic_endpoint_read_pkt_unlock(VALUE arg)
|
|
|
634
642
|
Connection::Server it went to, which may be a new one, or nil when the
|
|
635
643
|
Endpoint answered or dropped it. A connection's own failure is never
|
|
636
644
|
raised; it closes that connection (see quic_endpoint_handle_error). */
|
|
637
|
-
static VALUE
|
|
638
|
-
quic_endpoint_read_pkt(int argc, VALUE *argv, VALUE self)
|
|
639
|
-
{
|
|
645
|
+
static VALUE quic_endpoint_read_pkt(int argc, VALUE *argv, VALUE self) {
|
|
640
646
|
VALUE packet = Qnil;
|
|
641
647
|
VALUE opts = Qnil;
|
|
642
648
|
rb_scan_args(argc, argv, "1:", &packet, &opts);
|
|
643
|
-
if (NIL_P(opts))
|
|
649
|
+
if (NIL_P(opts))
|
|
650
|
+
opts = rb_hash_new();
|
|
644
651
|
|
|
645
652
|
ID keywords[2];
|
|
646
653
|
VALUE values[2];
|
|
@@ -650,7 +657,8 @@ quic_endpoint_read_pkt(int argc, VALUE *argv, VALUE self)
|
|
|
650
657
|
|
|
651
658
|
quic_endpoint_t *ep = quic_endpoint_get(self);
|
|
652
659
|
VALUE remote = values[0];
|
|
653
|
-
VALUE local =
|
|
660
|
+
VALUE local =
|
|
661
|
+
values[1] == Qundef || NIL_P(values[1]) ? ep->local_sockaddr : values[1];
|
|
654
662
|
quic_require_binary(packet, "packet");
|
|
655
663
|
quic_require_sockaddr(remote, "remote");
|
|
656
664
|
quic_require_sockaddr(local, "local");
|
|
@@ -679,12 +687,11 @@ quic_endpoint_read_pkt(int argc, VALUE *argv, VALUE self)
|
|
|
679
687
|
nil when there is none left. The Endpoint's own answers go first, then
|
|
680
688
|
each connection's packets until it has none, resuming where the last
|
|
681
689
|
call stopped. After nil, the next call starts over. */
|
|
682
|
-
static VALUE
|
|
683
|
-
quic_endpoint_write_pkt(VALUE self)
|
|
684
|
-
{
|
|
690
|
+
static VALUE quic_endpoint_write_pkt(VALUE self) {
|
|
685
691
|
quic_endpoint_t *ep = quic_endpoint_get(self);
|
|
686
692
|
for (;;) {
|
|
687
|
-
if (RARRAY_LEN(ep->responses) > 0)
|
|
693
|
+
if (RARRAY_LEN(ep->responses) > 0)
|
|
694
|
+
return rb_ary_shift(ep->responses);
|
|
688
695
|
if (ep->write_cursor >= RARRAY_LEN(ep->conns)) {
|
|
689
696
|
ep->write_cursor = 0;
|
|
690
697
|
return Qnil;
|
|
@@ -701,7 +708,8 @@ quic_endpoint_write_pkt(VALUE self)
|
|
|
701
708
|
VALUE pkt = rb_str_buf_new(QUIC_WRITE_PKT_BUFLEN);
|
|
702
709
|
ngtcp2_path_storage ps;
|
|
703
710
|
ngtcp2_path_storage_zero(&ps);
|
|
704
|
-
ngtcp2_ssize n =
|
|
711
|
+
ngtcp2_ssize n =
|
|
712
|
+
quic_conn_write_pkt_raw(conn, c, &ps.path, (uint8_t *)RSTRING_PTR(pkt));
|
|
705
713
|
if (n < 0 || !NIL_P(c->pending_exc)) {
|
|
706
714
|
if (quic_endpoint_handle_error(ep, c, n < 0 ? (int)n : 0)) {
|
|
707
715
|
quic_endpoint_remove(ep, conn, c);
|
|
@@ -720,15 +728,15 @@ quic_endpoint_write_pkt(VALUE self)
|
|
|
720
728
|
/* #expiry: the earliest time (CLOCK_MONOTONIC ns) any connection in the
|
|
721
729
|
table needs #handle_expiry, the end of a closing or draining period
|
|
722
730
|
included. nil when no connection waits for one. */
|
|
723
|
-
static VALUE
|
|
724
|
-
quic_endpoint_expiry(VALUE self)
|
|
725
|
-
{
|
|
731
|
+
static VALUE quic_endpoint_expiry(VALUE self) {
|
|
726
732
|
quic_endpoint_t *ep = quic_endpoint_get(self);
|
|
727
733
|
ngtcp2_tstamp earliest = UINT64_MAX;
|
|
728
734
|
for (long i = 0; i < RARRAY_LEN(ep->conns); i++) {
|
|
729
735
|
quic_conn_t *c = quic_conn_get(RARRAY_AREF(ep->conns, i));
|
|
730
|
-
ngtcp2_tstamp t = c->close_deadline != 0 ? c->close_deadline
|
|
731
|
-
|
|
736
|
+
ngtcp2_tstamp t = c->close_deadline != 0 ? c->close_deadline
|
|
737
|
+
: ngtcp2_conn_get_expiry2(c->conn);
|
|
738
|
+
if (t < earliest)
|
|
739
|
+
earliest = t;
|
|
732
740
|
}
|
|
733
741
|
return earliest == UINT64_MAX ? Qnil : ULL2NUM((unsigned long long)earliest);
|
|
734
742
|
}
|
|
@@ -736,9 +744,7 @@ quic_endpoint_expiry(VALUE self)
|
|
|
736
744
|
/* #handle_expiry: run the timers of every connection due, and take out of
|
|
737
745
|
the table those whose closing or draining period is over or that timed
|
|
738
746
|
out. */
|
|
739
|
-
static VALUE
|
|
740
|
-
quic_endpoint_handle_expiry(VALUE self)
|
|
741
|
-
{
|
|
747
|
+
static VALUE quic_endpoint_handle_expiry(VALUE self) {
|
|
742
748
|
quic_endpoint_t *ep = quic_endpoint_get(self);
|
|
743
749
|
ngtcp2_tstamp now = quic_now();
|
|
744
750
|
/* A copy, since connections leave ep->conns along the way. */
|
|
@@ -746,16 +752,20 @@ quic_endpoint_handle_expiry(VALUE self)
|
|
|
746
752
|
for (long i = 0; i < RARRAY_LEN(conns); i++) {
|
|
747
753
|
VALUE conn = RARRAY_AREF(conns, i);
|
|
748
754
|
quic_conn_t *c = quic_conn_get(conn);
|
|
749
|
-
if (c->endpoint == NULL)
|
|
755
|
+
if (c->endpoint == NULL)
|
|
756
|
+
continue;
|
|
750
757
|
if (c->close_deadline != 0) {
|
|
751
|
-
if (c->close_deadline <= now)
|
|
758
|
+
if (c->close_deadline <= now)
|
|
759
|
+
quic_endpoint_remove(ep, conn, c);
|
|
752
760
|
continue;
|
|
753
761
|
}
|
|
754
|
-
if (ngtcp2_conn_get_expiry2(c->conn) > now)
|
|
762
|
+
if (ngtcp2_conn_get_expiry2(c->conn) > now)
|
|
763
|
+
continue;
|
|
755
764
|
|
|
756
765
|
c->now = now;
|
|
757
766
|
int rv = ngtcp2_conn_handle_expiry(c->conn, now);
|
|
758
|
-
if ((rv != 0 || !NIL_P(c->pending_exc)) &&
|
|
767
|
+
if ((rv != 0 || !NIL_P(c->pending_exc)) &&
|
|
768
|
+
quic_endpoint_handle_error(ep, c, rv)) {
|
|
759
769
|
quic_endpoint_remove(ep, conn, c);
|
|
760
770
|
}
|
|
761
771
|
}
|
|
@@ -765,9 +775,7 @@ quic_endpoint_handle_expiry(VALUE self)
|
|
|
765
775
|
|
|
766
776
|
/* #take_closed: the connections that left the table since the last call,
|
|
767
777
|
in the order they left. */
|
|
768
|
-
static VALUE
|
|
769
|
-
quic_endpoint_take_closed(VALUE self)
|
|
770
|
-
{
|
|
778
|
+
static VALUE quic_endpoint_take_closed(VALUE self) {
|
|
771
779
|
quic_endpoint_t *ep = quic_endpoint_get(self);
|
|
772
780
|
VALUE closed = ep->closed;
|
|
773
781
|
ep->closed = rb_ary_new();
|
|
@@ -776,36 +784,29 @@ quic_endpoint_take_closed(VALUE self)
|
|
|
776
784
|
|
|
777
785
|
/* #connections: the connections in the table, closing and draining ones
|
|
778
786
|
included. */
|
|
779
|
-
static VALUE
|
|
780
|
-
quic_endpoint_connections(VALUE self)
|
|
781
|
-
{
|
|
787
|
+
static VALUE quic_endpoint_connections(VALUE self) {
|
|
782
788
|
return rb_ary_dup(quic_endpoint_get(self)->conns);
|
|
783
789
|
}
|
|
784
790
|
|
|
785
791
|
/* #stop_accepting: refuse every new connection from now on with
|
|
786
792
|
CONNECTION_REFUSED. There is no way back. */
|
|
787
|
-
static VALUE
|
|
788
|
-
quic_endpoint_stop_accepting(VALUE self)
|
|
789
|
-
{
|
|
793
|
+
static VALUE quic_endpoint_stop_accepting(VALUE self) {
|
|
790
794
|
quic_endpoint_get(self)->accepting = false;
|
|
791
795
|
return Qnil;
|
|
792
796
|
}
|
|
793
797
|
|
|
794
798
|
/* #tls_context=: the context new connections are made with. Connections
|
|
795
799
|
already made keep theirs. */
|
|
796
|
-
static VALUE
|
|
797
|
-
quic_endpoint_set_tls_context(VALUE self, VALUE tls_context)
|
|
798
|
-
{
|
|
800
|
+
static VALUE quic_endpoint_set_tls_context(VALUE self, VALUE tls_context) {
|
|
799
801
|
quic_endpoint_t *ep = quic_endpoint_get(self);
|
|
800
802
|
quic_tls_context_get(tls_context);
|
|
801
803
|
ep->tls_context = tls_context;
|
|
802
804
|
return tls_context;
|
|
803
805
|
}
|
|
804
806
|
|
|
805
|
-
void
|
|
806
|
-
|
|
807
|
-
{
|
|
808
|
-
if (RAND_bytes((uint8_t *)&quic_cid_hash_seed, sizeof(quic_cid_hash_seed)) != 1) {
|
|
807
|
+
void Init_quic_endpoint(VALUE rb_mQUICArg) {
|
|
808
|
+
if (RAND_bytes((uint8_t *)&quic_cid_hash_seed, sizeof(quic_cid_hash_seed)) !=
|
|
809
|
+
1) {
|
|
809
810
|
rb_raise(rb_eRuntimeError, "RAND_bytes(CID hash seed) failed");
|
|
810
811
|
}
|
|
811
812
|
|
|
@@ -815,9 +816,14 @@ Init_quic_endpoint(VALUE rb_mQUICArg)
|
|
|
815
816
|
rb_define_method(rb_cQUICEndpoint, "read_pkt", quic_endpoint_read_pkt, -1);
|
|
816
817
|
rb_define_method(rb_cQUICEndpoint, "write_pkt", quic_endpoint_write_pkt, 0);
|
|
817
818
|
rb_define_method(rb_cQUICEndpoint, "expiry", quic_endpoint_expiry, 0);
|
|
818
|
-
rb_define_method(rb_cQUICEndpoint, "handle_expiry",
|
|
819
|
-
|
|
820
|
-
rb_define_method(rb_cQUICEndpoint, "
|
|
821
|
-
|
|
822
|
-
rb_define_method(rb_cQUICEndpoint, "
|
|
819
|
+
rb_define_method(rb_cQUICEndpoint, "handle_expiry",
|
|
820
|
+
quic_endpoint_handle_expiry, 0);
|
|
821
|
+
rb_define_method(rb_cQUICEndpoint, "take_closed", quic_endpoint_take_closed,
|
|
822
|
+
0);
|
|
823
|
+
rb_define_method(rb_cQUICEndpoint, "connections", quic_endpoint_connections,
|
|
824
|
+
0);
|
|
825
|
+
rb_define_method(rb_cQUICEndpoint, "stop_accepting",
|
|
826
|
+
quic_endpoint_stop_accepting, 0);
|
|
827
|
+
rb_define_method(rb_cQUICEndpoint,
|
|
828
|
+
"tls_context=", quic_endpoint_set_tls_context, 1);
|
|
823
829
|
}
|