File: | out/../deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c |
Warning: | line 3449, column 13 Access to field 'type' results in a dereference of a null pointer (loaded from variable 'vmsg') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * ngtcp2 | |||
3 | * | |||
4 | * Copyright (c) 2017 ngtcp2 contributors | |||
5 | * | |||
6 | * Permission is hereby granted, free of charge, to any person obtaining | |||
7 | * a copy of this software and associated documentation files (the | |||
8 | * "Software"), to deal in the Software without restriction, including | |||
9 | * without limitation the rights to use, copy, modify, merge, publish, | |||
10 | * distribute, sublicense, and/or sell copies of the Software, and to | |||
11 | * permit persons to whom the Software is furnished to do so, subject to | |||
12 | * the following conditions: | |||
13 | * | |||
14 | * The above copyright notice and this permission notice shall be | |||
15 | * included in all copies or substantial portions of the Software. | |||
16 | * | |||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |||
21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
24 | */ | |||
25 | #include "ngtcp2_conn.h" | |||
26 | ||||
27 | #include <string.h> | |||
28 | #include <assert.h> | |||
29 | #include <math.h> | |||
30 | ||||
31 | #include "ngtcp2_macro.h" | |||
32 | #include "ngtcp2_log.h" | |||
33 | #include "ngtcp2_cid.h" | |||
34 | #include "ngtcp2_conv.h" | |||
35 | #include "ngtcp2_vec.h" | |||
36 | #include "ngtcp2_addr.h" | |||
37 | #include "ngtcp2_path.h" | |||
38 | #include "ngtcp2_rcvry.h" | |||
39 | ||||
40 | /* NGTCP2_FLOW_WINDOW_RTT_FACTOR is the factor of RTT when flow | |||
41 | control window auto-tuning is triggered. */ | |||
42 | #define NGTCP2_FLOW_WINDOW_RTT_FACTOR2 2 | |||
43 | /* NGTCP2_FLOW_WINDOW_SCALING_FACTOR is the growth factor of flow | |||
44 | control window. */ | |||
45 | #define NGTCP2_FLOW_WINDOW_SCALING_FACTOR2 2 | |||
46 | ||||
47 | /* | |||
48 | * conn_local_stream returns nonzero if |stream_id| indicates that it | |||
49 | * is the stream initiated by local endpoint. | |||
50 | */ | |||
51 | static int conn_local_stream(ngtcp2_conn *conn, int64_t stream_id) { | |||
52 | return (uint8_t)(stream_id & 1) == conn->server; | |||
53 | } | |||
54 | ||||
55 | /* | |||
56 | * bidi_stream returns nonzero if |stream_id| is a bidirectional | |||
57 | * stream ID. | |||
58 | */ | |||
59 | static int bidi_stream(int64_t stream_id) { return (stream_id & 0x2) == 0; } | |||
60 | ||||
61 | static int conn_call_recv_client_initial(ngtcp2_conn *conn, | |||
62 | const ngtcp2_cid *dcid) { | |||
63 | int rv; | |||
64 | ||||
65 | assert(conn->callbacks.recv_client_initial)((void) (0)); | |||
66 | ||||
67 | rv = conn->callbacks.recv_client_initial(conn, dcid, conn->user_data); | |||
68 | if (rv != 0) { | |||
69 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
70 | } | |||
71 | ||||
72 | return 0; | |||
73 | } | |||
74 | ||||
75 | static int conn_call_handshake_completed(ngtcp2_conn *conn) { | |||
76 | int rv; | |||
77 | ||||
78 | if (!conn->callbacks.handshake_completed) { | |||
79 | return 0; | |||
80 | } | |||
81 | ||||
82 | rv = conn->callbacks.handshake_completed(conn, conn->user_data); | |||
83 | if (rv != 0) { | |||
84 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
85 | } | |||
86 | ||||
87 | return 0; | |||
88 | } | |||
89 | ||||
90 | static int conn_call_recv_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
91 | uint32_t flags, uint64_t offset, | |||
92 | const uint8_t *data, size_t datalen) { | |||
93 | int rv; | |||
94 | ||||
95 | if (!conn->callbacks.recv_stream_data) { | |||
96 | return 0; | |||
97 | } | |||
98 | ||||
99 | rv = conn->callbacks.recv_stream_data(conn, flags, strm->stream_id, offset, | |||
100 | data, datalen, conn->user_data, | |||
101 | strm->stream_user_data); | |||
102 | if (rv != 0) { | |||
103 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
104 | } | |||
105 | ||||
106 | return 0; | |||
107 | } | |||
108 | ||||
109 | static int conn_call_recv_crypto_data(ngtcp2_conn *conn, | |||
110 | ngtcp2_crypto_level crypto_level, | |||
111 | uint64_t offset, const uint8_t *data, | |||
112 | size_t datalen) { | |||
113 | int rv; | |||
114 | ||||
115 | assert(conn->callbacks.recv_crypto_data)((void) (0)); | |||
116 | ||||
117 | rv = conn->callbacks.recv_crypto_data(conn, crypto_level, offset, data, | |||
118 | datalen, conn->user_data); | |||
119 | switch (rv) { | |||
120 | case 0: | |||
121 | case NGTCP2_ERR_CRYPTO-215: | |||
122 | case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM-217: | |||
123 | case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM-218: | |||
124 | case NGTCP2_ERR_TRANSPORT_PARAM-234: | |||
125 | case NGTCP2_ERR_PROTO-205: | |||
126 | case NGTCP2_ERR_CALLBACK_FAILURE-502: | |||
127 | return rv; | |||
128 | default: | |||
129 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
130 | } | |||
131 | } | |||
132 | ||||
133 | static int conn_call_stream_open(ngtcp2_conn *conn, ngtcp2_strm *strm) { | |||
134 | int rv; | |||
135 | ||||
136 | if (!conn->callbacks.stream_open) { | |||
137 | return 0; | |||
138 | } | |||
139 | ||||
140 | rv = conn->callbacks.stream_open(conn, strm->stream_id, conn->user_data); | |||
141 | if (rv != 0) { | |||
142 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
143 | } | |||
144 | ||||
145 | return 0; | |||
146 | } | |||
147 | ||||
148 | static int conn_call_stream_close(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
149 | uint64_t app_error_code) { | |||
150 | int rv; | |||
151 | ||||
152 | if (!conn->callbacks.stream_close) { | |||
153 | return 0; | |||
154 | } | |||
155 | ||||
156 | rv = conn->callbacks.stream_close(conn, strm->stream_id, app_error_code, | |||
157 | conn->user_data, strm->stream_user_data); | |||
158 | if (rv != 0) { | |||
159 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
160 | } | |||
161 | ||||
162 | return 0; | |||
163 | } | |||
164 | ||||
165 | static int conn_call_stream_reset(ngtcp2_conn *conn, int64_t stream_id, | |||
166 | uint64_t final_size, uint64_t app_error_code, | |||
167 | void *stream_user_data) { | |||
168 | int rv; | |||
169 | ||||
170 | if (!conn->callbacks.stream_reset) { | |||
171 | return 0; | |||
172 | } | |||
173 | ||||
174 | rv = conn->callbacks.stream_reset(conn, stream_id, final_size, app_error_code, | |||
175 | conn->user_data, stream_user_data); | |||
176 | if (rv != 0) { | |||
177 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
178 | } | |||
179 | ||||
180 | return 0; | |||
181 | } | |||
182 | ||||
183 | static int conn_call_extend_max_local_streams_bidi(ngtcp2_conn *conn, | |||
184 | uint64_t max_streams) { | |||
185 | int rv; | |||
186 | ||||
187 | if (!conn->callbacks.extend_max_local_streams_bidi) { | |||
188 | return 0; | |||
189 | } | |||
190 | ||||
191 | rv = conn->callbacks.extend_max_local_streams_bidi(conn, max_streams, | |||
192 | conn->user_data); | |||
193 | if (rv != 0) { | |||
194 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
195 | } | |||
196 | ||||
197 | return 0; | |||
198 | } | |||
199 | ||||
200 | static int conn_call_extend_max_local_streams_uni(ngtcp2_conn *conn, | |||
201 | uint64_t max_streams) { | |||
202 | int rv; | |||
203 | ||||
204 | if (!conn->callbacks.extend_max_local_streams_uni) { | |||
205 | return 0; | |||
206 | } | |||
207 | ||||
208 | rv = conn->callbacks.extend_max_local_streams_uni(conn, max_streams, | |||
209 | conn->user_data); | |||
210 | if (rv != 0) { | |||
211 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
212 | } | |||
213 | ||||
214 | return 0; | |||
215 | } | |||
216 | ||||
217 | static int conn_call_get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, | |||
218 | uint8_t *token, size_t cidlen) { | |||
219 | int rv; | |||
220 | ||||
221 | assert(conn->callbacks.get_new_connection_id)((void) (0)); | |||
222 | ||||
223 | rv = conn->callbacks.get_new_connection_id(conn, cid, token, cidlen, | |||
224 | conn->user_data); | |||
225 | if (rv != 0) { | |||
226 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
227 | } | |||
228 | ||||
229 | return 0; | |||
230 | } | |||
231 | ||||
232 | static int conn_call_remove_connection_id(ngtcp2_conn *conn, | |||
233 | const ngtcp2_cid *cid) { | |||
234 | int rv; | |||
235 | ||||
236 | if (!conn->callbacks.remove_connection_id) { | |||
237 | return 0; | |||
238 | } | |||
239 | ||||
240 | rv = conn->callbacks.remove_connection_id(conn, cid, conn->user_data); | |||
241 | if (rv != 0) { | |||
242 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
243 | } | |||
244 | ||||
245 | return 0; | |||
246 | } | |||
247 | ||||
248 | static int conn_call_path_validation(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
249 | ngtcp2_path_validation_result res) { | |||
250 | int rv; | |||
251 | ||||
252 | if (!conn->callbacks.path_validation) { | |||
253 | return 0; | |||
254 | } | |||
255 | ||||
256 | rv = conn->callbacks.path_validation(conn, path, res, conn->user_data); | |||
257 | if (rv != 0) { | |||
258 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
259 | } | |||
260 | ||||
261 | return 0; | |||
262 | } | |||
263 | ||||
264 | static int conn_call_select_preferred_addr(ngtcp2_conn *conn, | |||
265 | ngtcp2_addr *dest) { | |||
266 | int rv; | |||
267 | ||||
268 | if (!conn->callbacks.select_preferred_addr) { | |||
269 | return 0; | |||
270 | } | |||
271 | ||||
272 | assert(conn->remote.transport_params.preferred_address_present)((void) (0)); | |||
273 | ||||
274 | rv = conn->callbacks.select_preferred_addr( | |||
275 | conn, dest, &conn->remote.transport_params.preferred_address, | |||
276 | conn->user_data); | |||
277 | if (rv != 0) { | |||
278 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
279 | } | |||
280 | ||||
281 | return 0; | |||
282 | } | |||
283 | ||||
284 | static int conn_call_extend_max_remote_streams_bidi(ngtcp2_conn *conn, | |||
285 | uint64_t max_streams) { | |||
286 | int rv; | |||
287 | ||||
288 | if (!conn->callbacks.extend_max_remote_streams_bidi) { | |||
289 | return 0; | |||
290 | } | |||
291 | ||||
292 | rv = conn->callbacks.extend_max_remote_streams_bidi(conn, max_streams, | |||
293 | conn->user_data); | |||
294 | if (rv != 0) { | |||
295 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
296 | } | |||
297 | ||||
298 | return 0; | |||
299 | } | |||
300 | ||||
301 | static int conn_call_extend_max_remote_streams_uni(ngtcp2_conn *conn, | |||
302 | uint64_t max_streams) { | |||
303 | int rv; | |||
304 | ||||
305 | if (!conn->callbacks.extend_max_remote_streams_uni) { | |||
306 | return 0; | |||
307 | } | |||
308 | ||||
309 | rv = conn->callbacks.extend_max_remote_streams_uni(conn, max_streams, | |||
310 | conn->user_data); | |||
311 | if (rv != 0) { | |||
312 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
313 | } | |||
314 | ||||
315 | return 0; | |||
316 | } | |||
317 | ||||
318 | static int conn_call_extend_max_stream_data(ngtcp2_conn *conn, | |||
319 | ngtcp2_strm *strm, | |||
320 | int64_t stream_id, | |||
321 | uint64_t datalen) { | |||
322 | int rv; | |||
323 | ||||
324 | if (!conn->callbacks.extend_max_stream_data) { | |||
325 | return 0; | |||
326 | } | |||
327 | ||||
328 | rv = conn->callbacks.extend_max_stream_data( | |||
329 | conn, stream_id, datalen, conn->user_data, strm->stream_user_data); | |||
330 | if (rv != 0) { | |||
331 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
332 | } | |||
333 | ||||
334 | return 0; | |||
335 | } | |||
336 | ||||
337 | static int conn_call_dcid_status(ngtcp2_conn *conn, | |||
338 | ngtcp2_connection_id_status_type type, | |||
339 | const ngtcp2_dcid *dcid) { | |||
340 | int rv; | |||
341 | ||||
342 | if (!conn->callbacks.dcid_status) { | |||
343 | return 0; | |||
344 | } | |||
345 | ||||
346 | rv = conn->callbacks.dcid_status( | |||
347 | conn, (int)type, dcid->seq, &dcid->cid, | |||
348 | ngtcp2_check_invalid_stateless_reset_token(dcid->token) ? NULL((void*)0) | |||
349 | : dcid->token, | |||
350 | conn->user_data); | |||
351 | if (rv != 0) { | |||
352 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
353 | } | |||
354 | ||||
355 | return 0; | |||
356 | } | |||
357 | ||||
358 | static int conn_call_activate_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid) { | |||
359 | return conn_call_dcid_status(conn, NGTCP2_CONNECTION_ID_STATUS_TYPE_ACTIVATE, | |||
360 | dcid); | |||
361 | } | |||
362 | ||||
363 | static int conn_call_deactivate_dcid(ngtcp2_conn *conn, | |||
364 | const ngtcp2_dcid *dcid) { | |||
365 | return conn_call_dcid_status( | |||
366 | conn, NGTCP2_CONNECTION_ID_STATUS_TYPE_DEACTIVATE, dcid); | |||
367 | } | |||
368 | ||||
369 | static void conn_call_delete_crypto_aead_ctx(ngtcp2_conn *conn, | |||
370 | ngtcp2_crypto_aead_ctx *aead_ctx) { | |||
371 | if (!aead_ctx->native_handle) { | |||
372 | return; | |||
373 | } | |||
374 | ||||
375 | assert(conn->callbacks.delete_crypto_aead_ctx)((void) (0)); | |||
376 | ||||
377 | conn->callbacks.delete_crypto_aead_ctx(conn, aead_ctx, conn->user_data); | |||
378 | } | |||
379 | ||||
380 | static void | |||
381 | conn_call_delete_crypto_cipher_ctx(ngtcp2_conn *conn, | |||
382 | ngtcp2_crypto_cipher_ctx *cipher_ctx) { | |||
383 | if (!cipher_ctx->native_handle) { | |||
384 | return; | |||
385 | } | |||
386 | ||||
387 | assert(conn->callbacks.delete_crypto_cipher_ctx)((void) (0)); | |||
388 | ||||
389 | conn->callbacks.delete_crypto_cipher_ctx(conn, cipher_ctx, conn->user_data); | |||
390 | } | |||
391 | ||||
392 | static int crypto_offset_less(const ngtcp2_ksl_key *lhs, | |||
393 | const ngtcp2_ksl_key *rhs) { | |||
394 | return *(int64_t *)lhs < *(int64_t *)rhs; | |||
395 | } | |||
396 | ||||
397 | static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, | |||
398 | ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log, | |||
399 | ngtcp2_qlog *qlog, const ngtcp2_mem *mem) { | |||
400 | int rv; | |||
401 | ||||
402 | memset(pktns, 0, sizeof(*pktns)); | |||
403 | ||||
404 | rv = ngtcp2_gaptr_init(&pktns->rx.pngap, mem); | |||
405 | if (rv != 0) { | |||
406 | return rv; | |||
407 | } | |||
408 | ||||
409 | pktns->tx.last_pkt_num = -1; | |||
410 | pktns->rx.max_pkt_num = -1; | |||
411 | pktns->rx.max_ack_eliciting_pkt_num = -1; | |||
412 | ||||
413 | rv = ngtcp2_acktr_init(&pktns->acktr, log, mem); | |||
414 | if (rv != 0) { | |||
415 | goto fail_acktr_init; | |||
416 | } | |||
417 | ||||
418 | rv = ngtcp2_strm_init(&pktns->crypto.strm, 0, NGTCP2_STRM_FLAG_NONE0x00, 0, 0, | |||
419 | NULL((void*)0), mem); | |||
420 | if (rv != 0) { | |||
421 | goto fail_crypto_init; | |||
422 | } | |||
423 | ||||
424 | rv = ngtcp2_ksl_init(&pktns->crypto.tx.frq, crypto_offset_less, | |||
425 | sizeof(uint64_t), mem); | |||
426 | if (rv != 0) { | |||
427 | goto fail_tx_frq_init; | |||
428 | } | |||
429 | ||||
430 | ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, log, | |||
431 | qlog, mem); | |||
432 | ||||
433 | return 0; | |||
434 | ||||
435 | fail_tx_frq_init: | |||
436 | ngtcp2_strm_free(&pktns->crypto.strm); | |||
437 | fail_crypto_init: | |||
438 | ngtcp2_acktr_free(&pktns->acktr); | |||
439 | fail_acktr_init: | |||
440 | ngtcp2_gaptr_free(&pktns->rx.pngap); | |||
441 | ||||
442 | return rv; | |||
443 | } | |||
444 | ||||
445 | static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, | |||
446 | ngtcp2_rst *rst, ngtcp2_cc *cc, ngtcp2_log *log, | |||
447 | ngtcp2_qlog *qlog, const ngtcp2_mem *mem) { | |||
448 | int rv; | |||
449 | ||||
450 | *ppktns = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pktns)); | |||
451 | if (*ppktns == NULL((void*)0)) { | |||
452 | return NGTCP2_ERR_NOMEM-501; | |||
453 | } | |||
454 | ||||
455 | rv = pktns_init(*ppktns, pktns_id, rst, cc, log, qlog, mem); | |||
456 | if (rv != 0) { | |||
457 | ngtcp2_mem_free(mem, *ppktns); | |||
458 | } | |||
459 | ||||
460 | return rv; | |||
461 | } | |||
462 | ||||
463 | static int cycle_less(const ngtcp2_pq_entry *lhs, const ngtcp2_pq_entry *rhs) { | |||
464 | ngtcp2_strm *ls = ngtcp2_struct_of(lhs, ngtcp2_strm, pe)((ngtcp2_strm *)(void *)((char *)(lhs)-__builtin_offsetof(ngtcp2_strm , pe))); | |||
465 | ngtcp2_strm *rs = ngtcp2_struct_of(rhs, ngtcp2_strm, pe)((ngtcp2_strm *)(void *)((char *)(rhs)-__builtin_offsetof(ngtcp2_strm , pe))); | |||
466 | ||||
467 | if (ls->cycle == rs->cycle) { | |||
468 | return ls->stream_id < rs->stream_id; | |||
469 | } | |||
470 | ||||
471 | return rs->cycle - ls->cycle <= 1; | |||
472 | } | |||
473 | ||||
474 | static void delete_buffed_pkts(ngtcp2_pkt_chain *pc, const ngtcp2_mem *mem) { | |||
475 | ngtcp2_pkt_chain *next; | |||
476 | ||||
477 | for (; pc;) { | |||
478 | next = pc->next; | |||
479 | ngtcp2_pkt_chain_del(pc, mem); | |||
480 | pc = next; | |||
481 | } | |||
482 | } | |||
483 | ||||
484 | static void pktns_free(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) { | |||
485 | ngtcp2_frame_chain *frc; | |||
486 | ngtcp2_ksl_it it; | |||
487 | ||||
488 | delete_buffed_pkts(pktns->rx.buffed_pkts, mem); | |||
489 | ||||
490 | ngtcp2_frame_chain_list_del(pktns->tx.frq, mem); | |||
491 | ||||
492 | ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, mem); | |||
493 | ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, mem); | |||
494 | ||||
495 | for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
496 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
497 | frc = ngtcp2_ksl_it_get(&it); | |||
498 | ngtcp2_frame_chain_del(frc, mem); | |||
499 | } | |||
500 | ||||
501 | ngtcp2_ksl_free(&pktns->crypto.tx.frq); | |||
502 | ngtcp2_rtb_free(&pktns->rtb); | |||
503 | ngtcp2_strm_free(&pktns->crypto.strm); | |||
504 | ngtcp2_acktr_free(&pktns->acktr); | |||
505 | ngtcp2_gaptr_free(&pktns->rx.pngap); | |||
506 | } | |||
507 | ||||
508 | static void pktns_del(ngtcp2_pktns *pktns, const ngtcp2_mem *mem) { | |||
509 | if (pktns == NULL((void*)0)) { | |||
510 | return; | |||
511 | } | |||
512 | ||||
513 | pktns_free(pktns, mem); | |||
514 | ||||
515 | ngtcp2_mem_free(mem, pktns); | |||
516 | } | |||
517 | ||||
518 | static void cc_del(ngtcp2_cc *cc, ngtcp2_cc_algo cc_algo, | |||
519 | const ngtcp2_mem *mem) { | |||
520 | switch (cc_algo) { | |||
521 | case NGTCP2_CC_ALGO_RENO: | |||
522 | ngtcp2_cc_reno_cc_free(cc, mem); | |||
523 | break; | |||
524 | case NGTCP2_CC_ALGO_CUBIC: | |||
525 | ngtcp2_cc_cubic_cc_free(cc, mem); | |||
526 | break; | |||
527 | default: | |||
528 | break; | |||
529 | } | |||
530 | } | |||
531 | ||||
532 | static int cid_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { | |||
533 | return ngtcp2_cid_less(lhs, rhs); | |||
534 | } | |||
535 | ||||
536 | static int ts_retired_less(const ngtcp2_pq_entry *lhs, | |||
537 | const ngtcp2_pq_entry *rhs) { | |||
538 | const ngtcp2_scid *a = ngtcp2_struct_of(lhs, ngtcp2_scid, pe)((ngtcp2_scid *)(void *)((char *)(lhs)-__builtin_offsetof(ngtcp2_scid , pe))); | |||
539 | const ngtcp2_scid *b = ngtcp2_struct_of(rhs, ngtcp2_scid, pe)((ngtcp2_scid *)(void *)((char *)(rhs)-__builtin_offsetof(ngtcp2_scid , pe))); | |||
540 | ||||
541 | return a->ts_retired < b->ts_retired; | |||
542 | } | |||
543 | ||||
544 | /* | |||
545 | * conn_reset_conn_stat_cc resets congestion state in |cstat|. | |||
546 | */ | |||
547 | static void conn_reset_conn_stat_cc(ngtcp2_conn *conn, | |||
548 | ngtcp2_conn_stat *cstat) { | |||
549 | cstat->latest_rtt = 0; | |||
550 | cstat->min_rtt = UINT64_MAX(18446744073709551615UL); | |||
551 | cstat->smoothed_rtt = conn->local.settings.initial_rtt; | |||
552 | cstat->rttvar = conn->local.settings.initial_rtt / 2; | |||
553 | cstat->first_rtt_sample_ts = UINT64_MAX(18446744073709551615UL); | |||
554 | cstat->pto_count = 0; | |||
555 | cstat->loss_detection_timer = UINT64_MAX(18446744073709551615UL); | |||
556 | cstat->cwnd = | |||
557 | ngtcp2_cc_compute_initcwnd(conn->local.settings.max_udp_payload_size); | |||
558 | cstat->ssthresh = UINT64_MAX(18446744073709551615UL); | |||
559 | cstat->congestion_recovery_start_ts = UINT64_MAX(18446744073709551615UL); | |||
560 | cstat->bytes_in_flight = 0; | |||
561 | cstat->delivery_rate_sec = 0; | |||
562 | } | |||
563 | ||||
564 | /* | |||
565 | * reset_conn_stat_recovery resets the fields related to the recovery | |||
566 | * function | |||
567 | */ | |||
568 | static void reset_conn_stat_recovery(ngtcp2_conn_stat *cstat) { | |||
569 | // Initializes them with UINT64_MAX. | |||
570 | memset(cstat->loss_time, 0xff, sizeof(cstat->loss_time)); | |||
571 | memset(cstat->last_tx_pkt_ts, 0xff, sizeof(cstat->last_tx_pkt_ts)); | |||
572 | } | |||
573 | ||||
574 | /* | |||
575 | * conn_reset_conn_stat resets |cstat|. The following fields are not | |||
576 | * reset: initial_rtt and max_udp_payload_size. | |||
577 | */ | |||
578 | static void conn_reset_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) { | |||
579 | conn_reset_conn_stat_cc(conn, cstat); | |||
580 | reset_conn_stat_recovery(cstat); | |||
581 | } | |||
582 | ||||
583 | static void delete_scid(ngtcp2_ksl *scids, const ngtcp2_mem *mem) { | |||
584 | ngtcp2_ksl_it it; | |||
585 | ||||
586 | for (it = ngtcp2_ksl_begin(scids); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
587 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
588 | ngtcp2_mem_free(mem, ngtcp2_ksl_it_get(&it)); | |||
589 | } | |||
590 | } | |||
591 | ||||
592 | /* | |||
593 | * compute_pto computes PTO. | |||
594 | */ | |||
595 | static ngtcp2_duration compute_pto(ngtcp2_duration smoothed_rtt, | |||
596 | ngtcp2_duration rttvar, | |||
597 | ngtcp2_duration max_ack_delay) { | |||
598 | ngtcp2_duration var = ngtcp2_max(4 * rttvar, NGTCP2_GRANULARITY)((4 * rttvar) > (((uint64_t)1000000ULL)) ? (4 * rttvar) : ( ((uint64_t)1000000ULL))); | |||
599 | return smoothed_rtt + var + max_ack_delay; | |||
600 | } | |||
601 | ||||
602 | /* | |||
603 | * conn_compute_initial_pto computes PTO using the initial RTT. | |||
604 | */ | |||
605 | static ngtcp2_duration conn_compute_initial_pto(ngtcp2_conn *conn, | |||
606 | ngtcp2_pktns *pktns) { | |||
607 | ngtcp2_duration initial_rtt = conn->local.settings.initial_rtt; | |||
608 | ngtcp2_duration max_ack_delay = | |||
609 | pktns->rtb.pktns_id == NGTCP2_PKTNS_ID_APPLICATION | |||
610 | ? conn->remote.transport_params.max_ack_delay | |||
611 | : 0; | |||
612 | return compute_pto(initial_rtt, initial_rtt / 2, max_ack_delay); | |||
613 | } | |||
614 | ||||
615 | /* | |||
616 | * conn_compute_pto computes the current PTO. | |||
617 | */ | |||
618 | static ngtcp2_duration conn_compute_pto(ngtcp2_conn *conn, | |||
619 | ngtcp2_pktns *pktns) { | |||
620 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
621 | ngtcp2_duration max_ack_delay = | |||
622 | pktns->rtb.pktns_id == NGTCP2_PKTNS_ID_APPLICATION | |||
623 | ? conn->remote.transport_params.max_ack_delay | |||
624 | : 0; | |||
625 | return compute_pto(cstat->smoothed_rtt, cstat->rttvar, max_ack_delay); | |||
626 | } | |||
627 | ||||
628 | static void conn_handle_tx_ecn(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, | |||
629 | uint8_t *prtb_entry_flags, ngtcp2_pktns *pktns, | |||
630 | const ngtcp2_pkt_hd *hd, ngtcp2_tstamp ts) { | |||
631 | assert(pi)((void) (0)); | |||
632 | ||||
633 | if (pi->ecn != NGTCP2_ECN_NOT_ECT0x0) { | |||
634 | /* We have already made a transition of validation state and | |||
635 | deceided to send UDP datagram with ECN bit set. Coalesced QUIC | |||
636 | packets also bear ECN bits set. */ | |||
637 | if (pktns->tx.ecn.start_pkt_num == INT64_MAX(9223372036854775807L)) { | |||
638 | pktns->tx.ecn.start_pkt_num = hd->pkt_num; | |||
639 | } | |||
640 | ||||
641 | ++pktns->tx.ecn.validation_pkt_sent; | |||
642 | ||||
643 | if (prtb_entry_flags) { | |||
644 | *prtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ECN0x20; | |||
645 | } | |||
646 | ||||
647 | ++pktns->tx.ecn.ect0; | |||
648 | ||||
649 | return; | |||
650 | } | |||
651 | ||||
652 | switch (conn->tx.ecn.state) { | |||
653 | case NGTCP2_ECN_STATE_TESTING: | |||
654 | if (conn->tx.ecn.validation_start_ts == UINT64_MAX(18446744073709551615UL)) { | |||
655 | assert(0 == pktns->tx.ecn.validation_pkt_sent)((void) (0)); | |||
656 | assert(0 == pktns->tx.ecn.validation_pkt_lost)((void) (0)); | |||
657 | ||||
658 | conn->tx.ecn.validation_start_ts = ts; | |||
659 | } else if (ts - conn->tx.ecn.validation_start_ts >= | |||
660 | 3 * conn_compute_pto(conn, pktns)) { | |||
661 | conn->tx.ecn.state = NGTCP2_ECN_STATE_UNKNOWN; | |||
662 | break; | |||
663 | } | |||
664 | ||||
665 | if (pktns->tx.ecn.start_pkt_num == INT64_MAX(9223372036854775807L)) { | |||
666 | pktns->tx.ecn.start_pkt_num = hd->pkt_num; | |||
667 | } | |||
668 | ||||
669 | ++pktns->tx.ecn.validation_pkt_sent; | |||
670 | ||||
671 | if (++conn->tx.ecn.dgram_sent == NGTCP2_ECN_MAX_NUM_VALIDATION_PKTS10) { | |||
672 | conn->tx.ecn.state = NGTCP2_ECN_STATE_UNKNOWN; | |||
673 | } | |||
674 | /* fall through */ | |||
675 | case NGTCP2_ECN_STATE_CAPABLE: | |||
676 | /* pi is provided per UDP datagram. */ | |||
677 | assert(NGTCP2_ECN_NOT_ECT == pi->ecn)((void) (0)); | |||
678 | ||||
679 | pi->ecn = NGTCP2_ECN_ECT_00x2; | |||
680 | ||||
681 | if (prtb_entry_flags) { | |||
682 | *prtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ECN0x20; | |||
683 | } | |||
684 | ||||
685 | ++pktns->tx.ecn.ect0; | |||
686 | break; | |||
687 | case NGTCP2_ECN_STATE_UNKNOWN: | |||
688 | case NGTCP2_ECN_STATE_FAILED: | |||
689 | break; | |||
690 | default: | |||
691 | assert(0)((void) (0)); | |||
692 | } | |||
693 | } | |||
694 | ||||
695 | static void conn_reset_ecn_validation_state(ngtcp2_conn *conn) { | |||
696 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
697 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
698 | ngtcp2_pktns *pktns = &conn->pktns; | |||
699 | ||||
700 | conn->tx.ecn.state = NGTCP2_ECN_STATE_TESTING; | |||
701 | conn->tx.ecn.validation_start_ts = UINT64_MAX(18446744073709551615UL); | |||
702 | conn->tx.ecn.dgram_sent = 0; | |||
703 | ||||
704 | if (in_pktns) { | |||
705 | in_pktns->tx.ecn.start_pkt_num = INT64_MAX(9223372036854775807L); | |||
706 | in_pktns->tx.ecn.validation_pkt_sent = 0; | |||
707 | in_pktns->tx.ecn.validation_pkt_lost = 0; | |||
708 | } | |||
709 | ||||
710 | if (hs_pktns) { | |||
711 | hs_pktns->tx.ecn.start_pkt_num = INT64_MAX(9223372036854775807L); | |||
712 | hs_pktns->tx.ecn.validation_pkt_sent = 0; | |||
713 | hs_pktns->tx.ecn.validation_pkt_lost = 0; | |||
714 | } | |||
715 | ||||
716 | pktns->tx.ecn.start_pkt_num = INT64_MAX(9223372036854775807L); | |||
717 | pktns->tx.ecn.validation_pkt_sent = 0; | |||
718 | pktns->tx.ecn.validation_pkt_lost = 0; | |||
719 | } | |||
720 | ||||
721 | static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, | |||
722 | const ngtcp2_cid *scid, const ngtcp2_path *path, | |||
723 | uint32_t version, const ngtcp2_callbacks *callbacks, | |||
724 | const ngtcp2_settings *settings, | |||
725 | const ngtcp2_transport_params *params, | |||
726 | const ngtcp2_mem *mem, void *user_data, int server) { | |||
727 | int rv; | |||
728 | ngtcp2_scid *scident; | |||
729 | uint8_t *buf; | |||
730 | ||||
731 | assert(settings->max_window <= NGTCP2_MAX_VARINT)((void) (0)); | |||
732 | assert(settings->max_stream_window <= NGTCP2_MAX_VARINT)((void) (0)); | |||
733 | assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE)((void) (0)); | |||
734 | assert(params->initial_max_data <= NGTCP2_MAX_VARINT)((void) (0)); | |||
735 | assert(params->initial_max_stream_data_bidi_local <= NGTCP2_MAX_VARINT)((void) (0)); | |||
736 | assert(params->initial_max_stream_data_bidi_remote <= NGTCP2_MAX_VARINT)((void) (0)); | |||
737 | assert(params->initial_max_stream_data_uni <= NGTCP2_MAX_VARINT)((void) (0)); | |||
738 | ||||
739 | if (mem == NULL((void*)0)) { | |||
740 | mem = ngtcp2_mem_default(); | |||
741 | } | |||
742 | ||||
743 | *pconn = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_conn)); | |||
744 | if (*pconn == NULL((void*)0)) { | |||
745 | rv = NGTCP2_ERR_NOMEM-501; | |||
746 | goto fail_conn; | |||
747 | } | |||
748 | ||||
749 | rv = ngtcp2_ringbuf_init(&(*pconn)->dcid.bound, | |||
750 | NGTCP2_MAX_BOUND_DCID_POOL_SIZE4, sizeof(ngtcp2_dcid), | |||
751 | mem); | |||
752 | if (rv != 0) { | |||
753 | goto fail_dcid_bound_init; | |||
754 | } | |||
755 | ||||
756 | rv = ngtcp2_ringbuf_init(&(*pconn)->dcid.unused, NGTCP2_MAX_DCID_POOL_SIZE8, | |||
757 | sizeof(ngtcp2_dcid), mem); | |||
758 | if (rv != 0) { | |||
759 | goto fail_dcid_unused_init; | |||
760 | } | |||
761 | ||||
762 | rv = | |||
763 | ngtcp2_ringbuf_init(&(*pconn)->dcid.retired, NGTCP2_MAX_DCID_RETIRED_SIZE2, | |||
764 | sizeof(ngtcp2_dcid), mem); | |||
765 | if (rv != 0) { | |||
766 | goto fail_dcid_retired_init; | |||
767 | } | |||
768 | ||||
769 | rv = ngtcp2_gaptr_init(&(*pconn)->dcid.seqgap, mem); | |||
770 | if (rv != 0) { | |||
771 | goto fail_seqgap_init; | |||
772 | } | |||
773 | ||||
774 | rv = ngtcp2_ksl_init(&(*pconn)->scid.set, cid_less, sizeof(ngtcp2_cid), mem); | |||
775 | if (rv != 0) { | |||
776 | goto fail_scid_set_init; | |||
777 | } | |||
778 | ||||
779 | ngtcp2_pq_init(&(*pconn)->scid.used, ts_retired_less, mem); | |||
780 | ||||
781 | rv = ngtcp2_map_init(&(*pconn)->strms, mem); | |||
782 | if (rv != 0) { | |||
783 | goto fail_strms_init; | |||
784 | } | |||
785 | ||||
786 | ngtcp2_pq_init(&(*pconn)->tx.strmq, cycle_less, mem); | |||
787 | ||||
788 | rv = ngtcp2_idtr_init(&(*pconn)->remote.bidi.idtr, !server, mem); | |||
789 | if (rv != 0) { | |||
790 | goto fail_remote_bidi_idtr_init; | |||
791 | } | |||
792 | ||||
793 | rv = ngtcp2_idtr_init(&(*pconn)->remote.uni.idtr, !server, mem); | |||
794 | if (rv != 0) { | |||
795 | goto fail_remote_uni_idtr_init; | |||
796 | } | |||
797 | ||||
798 | rv = ngtcp2_ringbuf_init(&(*pconn)->rx.path_challenge, 4, | |||
799 | sizeof(ngtcp2_path_challenge_entry), mem); | |||
800 | if (rv != 0) { | |||
801 | goto fail_rx_path_challenge_init; | |||
802 | } | |||
803 | ||||
804 | ngtcp2_log_init(&(*pconn)->log, scid, settings->log_printf, | |||
805 | settings->initial_ts, user_data); | |||
806 | ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog.write, settings->initial_ts, | |||
807 | user_data); | |||
808 | if ((*pconn)->qlog.write) { | |||
809 | buf = ngtcp2_mem_malloc(mem, NGTCP2_QLOG_BUFLEN4096); | |||
810 | if (buf == NULL((void*)0)) { | |||
811 | goto fail_qlog_buf; | |||
812 | } | |||
813 | ngtcp2_buf_init(&(*pconn)->qlog.buf, buf, NGTCP2_QLOG_BUFLEN4096); | |||
814 | } | |||
815 | ||||
816 | (*pconn)->local.settings = *settings; | |||
817 | (*pconn)->local.transport_params = *params; | |||
818 | ||||
819 | if (settings->token.len) { | |||
820 | buf = ngtcp2_mem_malloc(mem, settings->token.len); | |||
821 | if (buf == NULL((void*)0)) { | |||
822 | goto fail_token; | |||
823 | } | |||
824 | memcpy(buf, settings->token.base, settings->token.len); | |||
825 | (*pconn)->local.settings.token.base = buf; | |||
826 | } else { | |||
827 | (*pconn)->local.settings.token.base = NULL((void*)0); | |||
828 | (*pconn)->local.settings.token.len = 0; | |||
829 | } | |||
830 | ||||
831 | if (settings->max_udp_payload_size == 0) { | |||
832 | (*pconn)->local.settings.max_udp_payload_size = NGTCP2_DEFAULT_MAX_PKTLEN1200; | |||
833 | } | |||
834 | ||||
835 | conn_reset_conn_stat(*pconn, &(*pconn)->cstat); | |||
836 | (*pconn)->cstat.initial_rtt = settings->initial_rtt; | |||
837 | (*pconn)->cstat.max_udp_payload_size = | |||
838 | (*pconn)->local.settings.max_udp_payload_size; | |||
839 | ||||
840 | ngtcp2_rst_init(&(*pconn)->rst); | |||
841 | ||||
842 | (*pconn)->cc_algo = settings->cc_algo; | |||
843 | ||||
844 | switch (settings->cc_algo) { | |||
845 | case NGTCP2_CC_ALGO_RENO: | |||
846 | rv = ngtcp2_cc_reno_cc_init(&(*pconn)->cc, &(*pconn)->log, mem); | |||
847 | if (rv != 0) { | |||
848 | goto fail_cc_init; | |||
849 | } | |||
850 | break; | |||
851 | case NGTCP2_CC_ALGO_CUBIC: | |||
852 | rv = ngtcp2_cc_cubic_cc_init(&(*pconn)->cc, &(*pconn)->log, mem); | |||
853 | if (rv != 0) { | |||
854 | goto fail_cc_init; | |||
855 | } | |||
856 | break; | |||
857 | case NGTCP2_CC_ALGO_CUSTOM: | |||
858 | assert(settings->cc)((void) (0)); | |||
859 | (*pconn)->cc = *settings->cc; | |||
860 | (*pconn)->cc.ccb->log = &(*pconn)->log; | |||
861 | break; | |||
862 | default: | |||
863 | assert(0)((void) (0)); | |||
864 | } | |||
865 | ||||
866 | rv = pktns_new(&(*pconn)->in_pktns, NGTCP2_PKTNS_ID_INITIAL, &(*pconn)->rst, | |||
867 | &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem); | |||
868 | if (rv != 0) { | |||
869 | goto fail_in_pktns_init; | |||
870 | } | |||
871 | ||||
872 | rv = pktns_new(&(*pconn)->hs_pktns, NGTCP2_PKTNS_ID_HANDSHAKE, &(*pconn)->rst, | |||
873 | &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem); | |||
874 | if (rv != 0) { | |||
875 | goto fail_hs_pktns_init; | |||
876 | } | |||
877 | ||||
878 | rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst, | |||
879 | &(*pconn)->cc, &(*pconn)->log, &(*pconn)->qlog, mem); | |||
880 | if (rv != 0) { | |||
881 | goto fail_pktns_init; | |||
882 | } | |||
883 | ||||
884 | scident = ngtcp2_mem_malloc(mem, sizeof(*scident)); | |||
885 | if (scident == NULL((void*)0)) { | |||
886 | rv = NGTCP2_ERR_NOMEM-501; | |||
887 | goto fail_scident; | |||
888 | } | |||
889 | ||||
890 | /* Set stateless reset token later if it is available in the local | |||
891 | transport parameters */ | |||
892 | ngtcp2_scid_init(scident, 0, scid, NULL((void*)0)); | |||
893 | ||||
894 | rv = ngtcp2_ksl_insert(&(*pconn)->scid.set, NULL((void*)0), &scident->cid, scident); | |||
895 | if (rv != 0) { | |||
896 | goto fail_scid_set_insert; | |||
897 | } | |||
898 | ||||
899 | scident = NULL((void*)0); | |||
900 | ||||
901 | ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL((void*)0)); | |||
902 | ngtcp2_path_copy(&(*pconn)->dcid.current.ps.path, path); | |||
903 | ||||
904 | rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1); | |||
905 | if (rv != 0) { | |||
906 | goto fail_seqgap_push; | |||
907 | } | |||
908 | ||||
909 | (*pconn)->server = server; | |||
910 | (*pconn)->oscid = *scid; | |||
911 | (*pconn)->callbacks = *callbacks; | |||
912 | (*pconn)->version = version; | |||
913 | (*pconn)->mem = mem; | |||
914 | (*pconn)->user_data = user_data; | |||
915 | (*pconn)->idle_ts = settings->initial_ts; | |||
916 | (*pconn)->crypto.key_update.confirmed_ts = UINT64_MAX(18446744073709551615UL); | |||
917 | (*pconn)->tx.last_max_data_ts = UINT64_MAX(18446744073709551615UL); | |||
918 | (*pconn)->early.discard_started_ts = UINT64_MAX(18446744073709551615UL); | |||
919 | ||||
920 | conn_reset_ecn_validation_state(*pconn); | |||
921 | ||||
922 | ngtcp2_qlog_start(&(*pconn)->qlog, server ? &settings->qlog.odcid : dcid, | |||
923 | server); | |||
924 | ||||
925 | return 0; | |||
926 | ||||
927 | fail_seqgap_push: | |||
928 | fail_scid_set_insert: | |||
929 | ngtcp2_mem_free(mem, scident); | |||
930 | fail_scident: | |||
931 | ngtcp2_mem_free(mem, (*pconn)->local.settings.token.base); | |||
932 | fail_token: | |||
933 | pktns_free(&(*pconn)->pktns, mem); | |||
934 | fail_pktns_init: | |||
935 | pktns_del((*pconn)->hs_pktns, mem); | |||
936 | fail_hs_pktns_init: | |||
937 | pktns_del((*pconn)->in_pktns, mem); | |||
938 | fail_in_pktns_init: | |||
939 | cc_del(&(*pconn)->cc, settings->cc_algo, mem); | |||
940 | fail_cc_init: | |||
941 | ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin); | |||
942 | fail_qlog_buf: | |||
943 | ngtcp2_ringbuf_free(&(*pconn)->rx.path_challenge); | |||
944 | fail_rx_path_challenge_init: | |||
945 | ngtcp2_idtr_free(&(*pconn)->remote.uni.idtr); | |||
946 | fail_remote_uni_idtr_init: | |||
947 | ngtcp2_idtr_free(&(*pconn)->remote.bidi.idtr); | |||
948 | fail_remote_bidi_idtr_init: | |||
949 | ngtcp2_map_free(&(*pconn)->strms); | |||
950 | fail_strms_init: | |||
951 | delete_scid(&(*pconn)->scid.set, mem); | |||
952 | ngtcp2_ksl_free(&(*pconn)->scid.set); | |||
953 | fail_scid_set_init: | |||
954 | ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap); | |||
955 | fail_seqgap_init: | |||
956 | ngtcp2_ringbuf_free(&(*pconn)->dcid.retired); | |||
957 | fail_dcid_retired_init: | |||
958 | ngtcp2_ringbuf_free(&(*pconn)->dcid.unused); | |||
959 | fail_dcid_unused_init: | |||
960 | ngtcp2_ringbuf_free(&(*pconn)->dcid.bound); | |||
961 | fail_dcid_bound_init: | |||
962 | ngtcp2_mem_free(mem, *pconn); | |||
963 | fail_conn: | |||
964 | return rv; | |||
965 | } | |||
966 | ||||
967 | int ngtcp2_conn_client_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, | |||
968 | const ngtcp2_cid *scid, const ngtcp2_path *path, | |||
969 | uint32_t version, const ngtcp2_callbacks *callbacks, | |||
970 | const ngtcp2_settings *settings, | |||
971 | const ngtcp2_transport_params *params, | |||
972 | const ngtcp2_mem *mem, void *user_data) { | |||
973 | int rv; | |||
974 | rv = conn_new(pconn, dcid, scid, path, version, callbacks, settings, params, | |||
975 | mem, user_data, 0); | |||
976 | if (rv != 0) { | |||
977 | return rv; | |||
978 | } | |||
979 | (*pconn)->rcid = *dcid; | |||
980 | (*pconn)->state = NGTCP2_CS_CLIENT_INITIAL; | |||
981 | (*pconn)->local.bidi.next_stream_id = 0; | |||
982 | (*pconn)->local.uni.next_stream_id = 2; | |||
983 | ||||
984 | rv = ngtcp2_conn_commit_local_transport_params(*pconn); | |||
985 | if (rv != 0) { | |||
986 | ngtcp2_conn_del(*pconn); | |||
987 | return rv; | |||
988 | } | |||
989 | ||||
990 | return 0; | |||
991 | } | |||
992 | ||||
993 | int ngtcp2_conn_server_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, | |||
994 | const ngtcp2_cid *scid, const ngtcp2_path *path, | |||
995 | uint32_t version, const ngtcp2_callbacks *callbacks, | |||
996 | const ngtcp2_settings *settings, | |||
997 | const ngtcp2_transport_params *params, | |||
998 | const ngtcp2_mem *mem, void *user_data) { | |||
999 | int rv; | |||
1000 | rv = conn_new(pconn, dcid, scid, path, version, callbacks, settings, params, | |||
1001 | mem, user_data, 1); | |||
1002 | if (rv != 0) { | |||
1003 | return rv; | |||
1004 | } | |||
1005 | (*pconn)->state = NGTCP2_CS_SERVER_INITIAL; | |||
1006 | (*pconn)->local.bidi.next_stream_id = 1; | |||
1007 | (*pconn)->local.uni.next_stream_id = 3; | |||
1008 | ||||
1009 | if ((*pconn)->local.settings.token.len) { | |||
1010 | /* Usage of token lifts amplification limit */ | |||
1011 | (*pconn)->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED0x01; | |||
1012 | } | |||
1013 | ||||
1014 | return 0; | |||
1015 | } | |||
1016 | ||||
1017 | /* | |||
1018 | * conn_fc_credits returns the number of bytes allowed to be sent to | |||
1019 | * the given stream. Both connection and stream level flow control | |||
1020 | * credits are considered. | |||
1021 | */ | |||
1022 | static uint64_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) { | |||
1023 | return ngtcp2_min(strm->tx.max_offset - strm->tx.offset,((strm->tx.max_offset - strm->tx.offset) < (conn-> tx.max_offset - conn->tx.offset) ? (strm->tx.max_offset - strm->tx.offset) : (conn->tx.max_offset - conn->tx .offset)) | |||
1024 | conn->tx.max_offset - conn->tx.offset)((strm->tx.max_offset - strm->tx.offset) < (conn-> tx.max_offset - conn->tx.offset) ? (strm->tx.max_offset - strm->tx.offset) : (conn->tx.max_offset - conn->tx .offset)); | |||
1025 | } | |||
1026 | ||||
1027 | /* | |||
1028 | * conn_enforce_flow_control returns the number of bytes allowed to be | |||
1029 | * sent to the given stream. |len| might be shorted because of | |||
1030 | * available flow control credits. | |||
1031 | */ | |||
1032 | static size_t conn_enforce_flow_control(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
1033 | size_t len) { | |||
1034 | uint64_t fc_credits = conn_fc_credits(conn, strm); | |||
1035 | return (size_t)ngtcp2_min((uint64_t)len, fc_credits)(((uint64_t)len) < (fc_credits) ? ((uint64_t)len) : (fc_credits )); | |||
1036 | } | |||
1037 | ||||
1038 | static int delete_strms_each(ngtcp2_map_entry *ent, void *ptr) { | |||
1039 | const ngtcp2_mem *mem = ptr; | |||
1040 | ngtcp2_strm *s = ngtcp2_struct_of(ent, ngtcp2_strm, me)((ngtcp2_strm *)(void *)((char *)(ent)-__builtin_offsetof(ngtcp2_strm , me))); | |||
1041 | ||||
1042 | ngtcp2_strm_free(s); | |||
1043 | ngtcp2_mem_free(mem, s); | |||
1044 | ||||
1045 | return 0; | |||
1046 | } | |||
1047 | ||||
1048 | void ngtcp2_conn_del(ngtcp2_conn *conn) { | |||
1049 | if (conn == NULL((void*)0)) { | |||
1050 | return; | |||
1051 | } | |||
1052 | ||||
1053 | ngtcp2_qlog_end(&conn->qlog); | |||
1054 | ||||
1055 | if (conn->early.ckm) { | |||
1056 | conn_call_delete_crypto_aead_ctx(conn, &conn->early.ckm->aead_ctx); | |||
1057 | } | |||
1058 | conn_call_delete_crypto_cipher_ctx(conn, &conn->early.hp_ctx); | |||
1059 | ||||
1060 | if (conn->crypto.key_update.old_rx_ckm) { | |||
1061 | conn_call_delete_crypto_aead_ctx( | |||
1062 | conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx); | |||
1063 | } | |||
1064 | if (conn->crypto.key_update.new_rx_ckm) { | |||
1065 | conn_call_delete_crypto_aead_ctx( | |||
1066 | conn, &conn->crypto.key_update.new_rx_ckm->aead_ctx); | |||
1067 | } | |||
1068 | if (conn->crypto.key_update.new_tx_ckm) { | |||
1069 | conn_call_delete_crypto_aead_ctx( | |||
1070 | conn, &conn->crypto.key_update.new_tx_ckm->aead_ctx); | |||
1071 | } | |||
1072 | ||||
1073 | if (conn->pktns.crypto.rx.ckm) { | |||
1074 | conn_call_delete_crypto_aead_ctx(conn, | |||
1075 | &conn->pktns.crypto.rx.ckm->aead_ctx); | |||
1076 | } | |||
1077 | conn_call_delete_crypto_cipher_ctx(conn, &conn->pktns.crypto.rx.hp_ctx); | |||
1078 | ||||
1079 | if (conn->pktns.crypto.tx.ckm) { | |||
1080 | conn_call_delete_crypto_aead_ctx(conn, | |||
1081 | &conn->pktns.crypto.tx.ckm->aead_ctx); | |||
1082 | } | |||
1083 | conn_call_delete_crypto_cipher_ctx(conn, &conn->pktns.crypto.tx.hp_ctx); | |||
1084 | ||||
1085 | if (conn->hs_pktns) { | |||
1086 | if (conn->hs_pktns->crypto.rx.ckm) { | |||
1087 | conn_call_delete_crypto_aead_ctx( | |||
1088 | conn, &conn->hs_pktns->crypto.rx.ckm->aead_ctx); | |||
1089 | } | |||
1090 | conn_call_delete_crypto_cipher_ctx(conn, &conn->hs_pktns->crypto.rx.hp_ctx); | |||
1091 | ||||
1092 | if (conn->hs_pktns->crypto.tx.ckm) { | |||
1093 | conn_call_delete_crypto_aead_ctx( | |||
1094 | conn, &conn->hs_pktns->crypto.tx.ckm->aead_ctx); | |||
1095 | } | |||
1096 | conn_call_delete_crypto_cipher_ctx(conn, &conn->hs_pktns->crypto.tx.hp_ctx); | |||
1097 | } | |||
1098 | if (conn->in_pktns) { | |||
1099 | if (conn->in_pktns->crypto.rx.ckm) { | |||
1100 | conn_call_delete_crypto_aead_ctx( | |||
1101 | conn, &conn->in_pktns->crypto.rx.ckm->aead_ctx); | |||
1102 | } | |||
1103 | conn_call_delete_crypto_cipher_ctx(conn, &conn->in_pktns->crypto.rx.hp_ctx); | |||
1104 | ||||
1105 | if (conn->in_pktns->crypto.tx.ckm) { | |||
1106 | conn_call_delete_crypto_aead_ctx( | |||
1107 | conn, &conn->in_pktns->crypto.tx.ckm->aead_ctx); | |||
1108 | } | |||
1109 | conn_call_delete_crypto_cipher_ctx(conn, &conn->in_pktns->crypto.tx.hp_ctx); | |||
1110 | } | |||
1111 | ||||
1112 | conn_call_delete_crypto_aead_ctx(conn, &conn->crypto.retry_aead_ctx); | |||
1113 | ||||
1114 | ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base); | |||
1115 | ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_hp_buf.base); | |||
1116 | ngtcp2_mem_free(conn->mem, conn->local.settings.token.base); | |||
1117 | ||||
1118 | ngtcp2_crypto_km_del(conn->crypto.key_update.old_rx_ckm, conn->mem); | |||
1119 | ngtcp2_crypto_km_del(conn->crypto.key_update.new_rx_ckm, conn->mem); | |||
1120 | ngtcp2_crypto_km_del(conn->crypto.key_update.new_tx_ckm, conn->mem); | |||
1121 | ngtcp2_crypto_km_del(conn->early.ckm, conn->mem); | |||
1122 | ||||
1123 | pktns_free(&conn->pktns, conn->mem); | |||
1124 | pktns_del(conn->hs_pktns, conn->mem); | |||
1125 | pktns_del(conn->in_pktns, conn->mem); | |||
1126 | ||||
1127 | cc_del(&conn->cc, conn->cc_algo, conn->mem); | |||
1128 | ||||
1129 | ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin); | |||
1130 | ||||
1131 | ngtcp2_ringbuf_free(&conn->rx.path_challenge); | |||
1132 | ||||
1133 | ngtcp2_pv_del(conn->pv); | |||
1134 | ||||
1135 | ngtcp2_idtr_free(&conn->remote.uni.idtr); | |||
1136 | ngtcp2_idtr_free(&conn->remote.bidi.idtr); | |||
1137 | ngtcp2_mem_free(conn->mem, conn->tx.ack); | |||
1138 | ngtcp2_pq_free(&conn->tx.strmq); | |||
1139 | ngtcp2_map_each_free(&conn->strms, delete_strms_each, (void *)conn->mem); | |||
1140 | ngtcp2_map_free(&conn->strms); | |||
1141 | ||||
1142 | ngtcp2_pq_free(&conn->scid.used); | |||
1143 | delete_scid(&conn->scid.set, conn->mem); | |||
1144 | ngtcp2_ksl_free(&conn->scid.set); | |||
1145 | ngtcp2_gaptr_free(&conn->dcid.seqgap); | |||
1146 | ngtcp2_ringbuf_free(&conn->dcid.retired); | |||
1147 | ngtcp2_ringbuf_free(&conn->dcid.unused); | |||
1148 | ngtcp2_ringbuf_free(&conn->dcid.bound); | |||
1149 | ||||
1150 | ngtcp2_mem_free(conn->mem, conn); | |||
1151 | } | |||
1152 | ||||
1153 | /* | |||
1154 | * conn_ensure_ack_blks makes sure that conn->tx.ack->ack.blks can | |||
1155 | * contain at least |n| additional ngtcp2_ack_blk. | |||
1156 | * | |||
1157 | * This function returns 0 if it succeeds, or one of the following | |||
1158 | * negative error codes: | |||
1159 | * | |||
1160 | * NGTCP2_ERR_NOMEM | |||
1161 | * Out of memory. | |||
1162 | */ | |||
1163 | static int conn_ensure_ack_blks(ngtcp2_conn *conn, size_t n) { | |||
1164 | ngtcp2_frame *fr; | |||
1165 | size_t max = conn->tx.max_ack_blks; | |||
1166 | ||||
1167 | if (n <= max) { | |||
1168 | return 0; | |||
1169 | } | |||
1170 | ||||
1171 | max *= 2; | |||
1172 | ||||
1173 | assert(max >= n)((void) (0)); | |||
1174 | ||||
1175 | fr = ngtcp2_mem_realloc(conn->mem, conn->tx.ack, | |||
1176 | sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_blk) * max); | |||
1177 | if (fr == NULL((void*)0)) { | |||
1178 | return NGTCP2_ERR_NOMEM-501; | |||
1179 | } | |||
1180 | ||||
1181 | conn->tx.ack = fr; | |||
1182 | conn->tx.max_ack_blks = max; | |||
1183 | ||||
1184 | return 0; | |||
1185 | } | |||
1186 | ||||
1187 | /* | |||
1188 | * conn_compute_ack_delay computes ACK delay for outgoing protected | |||
1189 | * ACK. | |||
1190 | */ | |||
1191 | static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) { | |||
1192 | return ngtcp2_min(conn->local.transport_params.max_ack_delay,((conn->local.transport_params.max_ack_delay) < (conn-> cstat.smoothed_rtt / 8) ? (conn->local.transport_params.max_ack_delay ) : (conn->cstat.smoothed_rtt / 8)) | |||
1193 | conn->cstat.smoothed_rtt / 8)((conn->local.transport_params.max_ack_delay) < (conn-> cstat.smoothed_rtt / 8) ? (conn->local.transport_params.max_ack_delay ) : (conn->cstat.smoothed_rtt / 8)); | |||
1194 | } | |||
1195 | ||||
1196 | /* | |||
1197 | * conn_create_ack_frame creates ACK frame, and assigns its pointer to | |||
1198 | * |*pfr| if there are any received packets to acknowledge. If there | |||
1199 | * are no packets to acknowledge, this function returns 0, and |*pfr| | |||
1200 | * is untouched. The caller is advised to set |*pfr| to NULL before | |||
1201 | * calling this function, and check it after this function returns. | |||
1202 | * If |nodelay| is nonzero, delayed ACK timer is ignored. | |||
1203 | * | |||
1204 | * The memory for ACK frame is dynamically allocated by this function. | |||
1205 | * A caller is responsible to free it. | |||
1206 | * | |||
1207 | * Call ngtcp2_acktr_commit_ack after a created ACK frame is | |||
1208 | * successfully serialized into a packet. | |||
1209 | * | |||
1210 | * This function returns 0 if it succeeds, or one of the following | |||
1211 | * negative error codes: | |||
1212 | * | |||
1213 | * NGTCP2_ERR_NOMEM | |||
1214 | * Out of memory. | |||
1215 | */ | |||
1216 | static int conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, | |||
1217 | ngtcp2_pktns *pktns, uint8_t type, | |||
1218 | ngtcp2_tstamp ts, ngtcp2_duration ack_delay, | |||
1219 | uint64_t ack_delay_exponent) { | |||
1220 | /* TODO Measure an actual size of ACK blocks to find the best | |||
1221 | default value. */ | |||
1222 | const size_t initial_max_ack_blks = 8; | |||
1223 | int64_t last_pkt_num; | |||
1224 | ngtcp2_acktr *acktr = &pktns->acktr; | |||
1225 | ngtcp2_ack_blk *blk; | |||
1226 | ngtcp2_ksl_it it; | |||
1227 | ngtcp2_acktr_entry *rpkt; | |||
1228 | ngtcp2_ack *ack; | |||
1229 | size_t blk_idx; | |||
1230 | ngtcp2_tstamp largest_ack_ts; | |||
1231 | int rv; | |||
1232 | ||||
1233 | if (acktr->flags & NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK0x01) { | |||
1234 | ack_delay = 0; | |||
1235 | } | |||
1236 | ||||
1237 | if (!ngtcp2_acktr_require_active_ack(acktr, ack_delay, ts)) { | |||
1238 | return 0; | |||
1239 | } | |||
1240 | ||||
1241 | it = ngtcp2_acktr_get(acktr); | |||
1242 | if (ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0))) { | |||
1243 | ngtcp2_acktr_commit_ack(acktr); | |||
1244 | return 0; | |||
1245 | } | |||
1246 | ||||
1247 | if (conn->tx.ack == NULL((void*)0)) { | |||
1248 | conn->tx.ack = ngtcp2_mem_malloc( | |||
1249 | conn->mem, | |||
1250 | sizeof(ngtcp2_ack) + sizeof(ngtcp2_ack_blk) * initial_max_ack_blks); | |||
1251 | if (conn->tx.ack == NULL((void*)0)) { | |||
1252 | return NGTCP2_ERR_NOMEM-501; | |||
1253 | } | |||
1254 | conn->tx.max_ack_blks = initial_max_ack_blks; | |||
1255 | } | |||
1256 | ||||
1257 | ack = &conn->tx.ack->ack; | |||
1258 | ||||
1259 | if (pktns->rx.ecn.ect0 || pktns->rx.ecn.ect1 || pktns->rx.ecn.ce) { | |||
1260 | ack->type = NGTCP2_FRAME_ACK_ECN; | |||
1261 | ack->ecn.ect0 = pktns->rx.ecn.ect0; | |||
1262 | ack->ecn.ect1 = pktns->rx.ecn.ect1; | |||
1263 | ack->ecn.ce = pktns->rx.ecn.ce; | |||
1264 | } else { | |||
1265 | ack->type = NGTCP2_FRAME_ACK; | |||
1266 | } | |||
1267 | ack->num_blks = 0; | |||
1268 | ||||
1269 | rpkt = ngtcp2_ksl_it_get(&it); | |||
1270 | ||||
1271 | if (rpkt->pkt_num == pktns->rx.max_pkt_num) { | |||
1272 | last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); | |||
1273 | largest_ack_ts = rpkt->tstamp; | |||
1274 | ack->largest_ack = rpkt->pkt_num; | |||
1275 | ack->first_ack_blklen = rpkt->len - 1; | |||
1276 | ||||
1277 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0); | |||
1278 | } else { | |||
1279 | assert(rpkt->pkt_num < pktns->rx.max_pkt_num)((void) (0)); | |||
1280 | ||||
1281 | last_pkt_num = pktns->rx.max_pkt_num; | |||
1282 | largest_ack_ts = pktns->rx.max_pkt_ts; | |||
1283 | ack->largest_ack = pktns->rx.max_pkt_num; | |||
1284 | ack->first_ack_blklen = 0; | |||
1285 | } | |||
1286 | ||||
1287 | if (type == NGTCP2_PKT_SHORT) { | |||
1288 | ack->ack_delay_unscaled = ts - largest_ack_ts; | |||
1289 | ack->ack_delay = ack->ack_delay_unscaled / NGTCP2_MICROSECONDS((uint64_t)1000ULL) / | |||
1290 | (1ULL << ack_delay_exponent); | |||
1291 | } else { | |||
1292 | ack->ack_delay_unscaled = 0; | |||
1293 | ack->ack_delay = 0; | |||
1294 | } | |||
1295 | ||||
1296 | for (; !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
1297 | if (ack->num_blks == NGTCP2_MAX_ACK_BLKS32) { | |||
1298 | break; | |||
1299 | } | |||
1300 | ||||
1301 | rpkt = ngtcp2_ksl_it_get(&it); | |||
1302 | ||||
1303 | blk_idx = ack->num_blks++; | |||
1304 | rv = conn_ensure_ack_blks(conn, ack->num_blks); | |||
1305 | if (rv != 0) { | |||
1306 | return rv; | |||
1307 | } | |||
1308 | ack = &conn->tx.ack->ack; | |||
1309 | blk = &ack->blks[blk_idx]; | |||
1310 | blk->gap = (uint64_t)(last_pkt_num - rpkt->pkt_num - 2); | |||
1311 | blk->blklen = rpkt->len - 1; | |||
1312 | ||||
1313 | last_pkt_num = rpkt->pkt_num - (int64_t)(rpkt->len - 1); | |||
1314 | } | |||
1315 | ||||
1316 | /* TODO Just remove entries which cannot fit into a single ACK frame | |||
1317 | for now. */ | |||
1318 | if (!ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0))) { | |||
1319 | ngtcp2_acktr_forget(acktr, ngtcp2_ksl_it_get(&it)); | |||
1320 | } | |||
1321 | ||||
1322 | *pfr = conn->tx.ack; | |||
1323 | ||||
1324 | return 0; | |||
1325 | } | |||
1326 | ||||
1327 | /* | |||
1328 | * conn_ppe_write_frame writes |fr| to |ppe|. If |hd_logged| is not | |||
1329 | * NULL and |*hd_logged| is zero, packet header is logged, and 1 is | |||
1330 | * assigned to |*hd_logged|. | |||
1331 | * | |||
1332 | * This function returns 0 if it succeeds, or one of the following | |||
1333 | * negative error codes: | |||
1334 | * | |||
1335 | * NGTCP2_ERR_NOBUF | |||
1336 | * Buffer is too small. | |||
1337 | */ | |||
1338 | static int conn_ppe_write_frame_hd_log(ngtcp2_conn *conn, ngtcp2_ppe *ppe, | |||
1339 | int *hd_logged, const ngtcp2_pkt_hd *hd, | |||
1340 | ngtcp2_frame *fr) { | |||
1341 | int rv; | |||
1342 | ||||
1343 | rv = ngtcp2_ppe_encode_frame(ppe, fr); | |||
1344 | if (rv != 0) { | |||
1345 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
1346 | return rv; | |||
1347 | } | |||
1348 | ||||
1349 | if (hd_logged && !*hd_logged) { | |||
1350 | *hd_logged = 1; | |||
1351 | ngtcp2_log_tx_pkt_hd(&conn->log, hd); | |||
1352 | ngtcp2_qlog_pkt_sent_start(&conn->qlog); | |||
1353 | } | |||
1354 | ||||
1355 | ngtcp2_log_tx_fr(&conn->log, hd, fr); | |||
1356 | ngtcp2_qlog_write_frame(&conn->qlog, fr); | |||
1357 | ||||
1358 | return 0; | |||
1359 | } | |||
1360 | ||||
1361 | /* | |||
1362 | * conn_ppe_write_frame writes |fr| to |ppe|. | |||
1363 | * | |||
1364 | * This function returns 0 if it succeeds, or one of the following | |||
1365 | * negative error codes: | |||
1366 | * | |||
1367 | * NGTCP2_ERR_NOBUF | |||
1368 | * Buffer is too small. | |||
1369 | */ | |||
1370 | static int conn_ppe_write_frame(ngtcp2_conn *conn, ngtcp2_ppe *ppe, | |||
1371 | const ngtcp2_pkt_hd *hd, ngtcp2_frame *fr) { | |||
1372 | return conn_ppe_write_frame_hd_log(conn, ppe, NULL((void*)0), hd, fr); | |||
1373 | } | |||
1374 | ||||
1375 | /* | |||
1376 | * conn_on_pkt_sent is called when new non-ACK-only packet is sent. | |||
1377 | * | |||
1378 | * This function returns 0 if it succeeds, or one of the following | |||
1379 | * negative error codes: | |||
1380 | * | |||
1381 | * NGTCP2_ERR_NOMEM | |||
1382 | * Out of memory | |||
1383 | */ | |||
1384 | static int conn_on_pkt_sent(ngtcp2_conn *conn, ngtcp2_rtb *rtb, | |||
1385 | ngtcp2_rtb_entry *ent) { | |||
1386 | int rv; | |||
1387 | ||||
1388 | /* This function implements OnPacketSent, but it handles only | |||
1389 | non-ACK-only packet. */ | |||
1390 | rv = ngtcp2_rtb_add(rtb, ent, &conn->cstat); | |||
1391 | if (rv != 0) { | |||
1392 | return rv; | |||
1393 | } | |||
1394 | ||||
1395 | if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) { | |||
1396 | conn->cstat.last_tx_pkt_ts[rtb->pktns_id] = ent->ts; | |||
1397 | } | |||
1398 | ||||
1399 | ngtcp2_conn_set_loss_detection_timer(conn, ent->ts); | |||
1400 | ||||
1401 | return 0; | |||
1402 | } | |||
1403 | ||||
1404 | /* | |||
1405 | * pktns_select_pkt_numlen selects shortest packet number encoding for | |||
1406 | * the next packet number based on the largest acknowledged packet | |||
1407 | * number. It returns the number of bytes to encode the packet | |||
1408 | * number. | |||
1409 | */ | |||
1410 | static size_t pktns_select_pkt_numlen(ngtcp2_pktns *pktns) { | |||
1411 | int64_t pkt_num = pktns->tx.last_pkt_num + 1; | |||
1412 | ngtcp2_rtb *rtb = &pktns->rtb; | |||
1413 | int64_t n = pkt_num - rtb->largest_acked_tx_pkt_num; | |||
1414 | ||||
1415 | if (NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1)) / 2 <= pkt_num) { | |||
1416 | return 4; | |||
1417 | } | |||
1418 | ||||
1419 | n = n * 2 + 1; | |||
1420 | ||||
1421 | if (n > 0xffffff) { | |||
1422 | return 4; | |||
1423 | } | |||
1424 | if (n > 0xffff) { | |||
1425 | return 3; | |||
1426 | } | |||
1427 | if (n > 0xff) { | |||
1428 | return 2; | |||
1429 | } | |||
1430 | return 1; | |||
1431 | } | |||
1432 | ||||
1433 | /* | |||
1434 | * conn_cwnd_is_zero returns nonzero if the number of bytes the local | |||
1435 | * endpoint can sent at this time is zero. | |||
1436 | */ | |||
1437 | static uint64_t conn_cwnd_is_zero(ngtcp2_conn *conn) { | |||
1438 | uint64_t bytes_in_flight = conn->cstat.bytes_in_flight; | |||
1439 | uint64_t cwnd = | |||
1440 | conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) | |||
1441 | ? ngtcp2_cc_compute_initcwnd(conn->cstat.max_udp_payload_size) | |||
1442 | : conn->cstat.cwnd; | |||
1443 | ||||
1444 | return bytes_in_flight >= cwnd; | |||
1445 | } | |||
1446 | ||||
1447 | /* | |||
1448 | * conn_retry_early_payloadlen returns the estimated wire length of | |||
1449 | * the first STREAM frame of 0-RTT packet which should be | |||
1450 | * retransmitted due to Retry frame | |||
1451 | */ | |||
1452 | static size_t conn_retry_early_payloadlen(ngtcp2_conn *conn) { | |||
1453 | ngtcp2_frame_chain *frc; | |||
1454 | ngtcp2_strm *strm; | |||
1455 | ||||
1456 | if (conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED0x20) { | |||
1457 | return 0; | |||
1458 | } | |||
1459 | ||||
1460 | for (; !ngtcp2_pq_empty(&conn->tx.strmq);) { | |||
1461 | strm = ngtcp2_conn_tx_strmq_top(conn); | |||
1462 | if (ngtcp2_strm_streamfrq_empty(strm)) { | |||
1463 | ngtcp2_conn_tx_strmq_pop(conn); | |||
1464 | continue; | |||
1465 | } | |||
1466 | ||||
1467 | frc = ngtcp2_strm_streamfrq_top(strm); | |||
1468 | return ngtcp2_vec_len(frc->fr.stream.data, frc->fr.stream.datacnt) + | |||
1469 | NGTCP2_STREAM_OVERHEAD(1 + 8 + 8 + 8); | |||
1470 | } | |||
1471 | ||||
1472 | return 0; | |||
1473 | } | |||
1474 | ||||
1475 | static void conn_cryptofrq_clear(ngtcp2_conn *conn, ngtcp2_pktns *pktns) { | |||
1476 | ngtcp2_frame_chain *frc; | |||
1477 | ngtcp2_ksl_it it; | |||
1478 | ||||
1479 | for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
1480 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
1481 | frc = ngtcp2_ksl_it_get(&it); | |||
1482 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1483 | } | |||
1484 | ngtcp2_ksl_clear(&pktns->crypto.tx.frq); | |||
1485 | } | |||
1486 | ||||
1487 | /* | |||
1488 | * conn_cryptofrq_unacked_offset returns the CRYPTO frame offset by | |||
1489 | * taking into account acknowledged offset. If there is no data to | |||
1490 | * send, this function returns (uint64_t)-1. | |||
1491 | */ | |||
1492 | static uint64_t conn_cryptofrq_unacked_offset(ngtcp2_conn *conn, | |||
1493 | ngtcp2_pktns *pktns) { | |||
1494 | ngtcp2_frame_chain *frc; | |||
1495 | ngtcp2_crypto *fr; | |||
1496 | ngtcp2_range gap; | |||
1497 | ngtcp2_rtb *rtb = &pktns->rtb; | |||
1498 | ngtcp2_ksl_it it; | |||
1499 | size_t datalen; | |||
1500 | ||||
1501 | (void)conn; | |||
1502 | ||||
1503 | for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
1504 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
1505 | frc = ngtcp2_ksl_it_get(&it); | |||
1506 | fr = &frc->fr.crypto; | |||
1507 | ||||
1508 | gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, fr->offset); | |||
1509 | ||||
1510 | datalen = ngtcp2_vec_len(fr->data, fr->datacnt); | |||
1511 | ||||
1512 | if (gap.begin <= fr->offset) { | |||
1513 | return fr->offset; | |||
1514 | } | |||
1515 | if (gap.begin < fr->offset + datalen) { | |||
1516 | return gap.begin; | |||
1517 | } | |||
1518 | } | |||
1519 | ||||
1520 | return (uint64_t)-1; | |||
1521 | } | |||
1522 | ||||
1523 | static int conn_cryptofrq_unacked_pop(ngtcp2_conn *conn, ngtcp2_pktns *pktns, | |||
1524 | ngtcp2_frame_chain **pfrc) { | |||
1525 | ngtcp2_frame_chain *frc, *nfrc; | |||
1526 | ngtcp2_crypto *fr, *nfr; | |||
1527 | uint64_t offset, end_offset; | |||
1528 | size_t idx, end_idx; | |||
1529 | uint64_t base_offset, end_base_offset; | |||
1530 | ngtcp2_range gap; | |||
1531 | ngtcp2_rtb *rtb = &pktns->rtb; | |||
1532 | ngtcp2_vec *v; | |||
1533 | int rv; | |||
1534 | ngtcp2_ksl_it it; | |||
1535 | ||||
1536 | *pfrc = NULL((void*)0); | |||
1537 | ||||
1538 | for (it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0));) { | |||
1539 | frc = ngtcp2_ksl_it_get(&it); | |||
1540 | fr = &frc->fr.crypto; | |||
1541 | ||||
1542 | ngtcp2_ksl_remove(&pktns->crypto.tx.frq, &it, &fr->offset); | |||
1543 | ||||
1544 | idx = 0; | |||
1545 | offset = fr->offset; | |||
1546 | base_offset = 0; | |||
1547 | ||||
1548 | gap = ngtcp2_strm_get_unacked_range_after(rtb->crypto, offset); | |||
1549 | if (gap.begin < offset) { | |||
1550 | gap.begin = offset; | |||
1551 | } | |||
1552 | ||||
1553 | for (; idx < fr->datacnt && offset < gap.begin; ++idx) { | |||
1554 | v = &fr->data[idx]; | |||
1555 | if (offset + v->len > gap.begin) { | |||
1556 | base_offset = gap.begin - offset; | |||
1557 | break; | |||
1558 | } | |||
1559 | ||||
1560 | offset += v->len; | |||
1561 | } | |||
1562 | ||||
1563 | if (idx == fr->datacnt) { | |||
1564 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1565 | continue; | |||
1566 | } | |||
1567 | ||||
1568 | assert(gap.begin == offset + base_offset)((void) (0)); | |||
1569 | ||||
1570 | end_idx = idx; | |||
1571 | end_offset = offset; | |||
1572 | end_base_offset = 0; | |||
1573 | ||||
1574 | for (; end_idx < fr->datacnt; ++end_idx) { | |||
1575 | v = &fr->data[end_idx]; | |||
1576 | if (end_offset + v->len > gap.end) { | |||
1577 | end_base_offset = gap.end - end_offset; | |||
1578 | break; | |||
1579 | } | |||
1580 | ||||
1581 | end_offset += v->len; | |||
1582 | } | |||
1583 | ||||
1584 | if (fr->offset == offset && base_offset == 0 && fr->datacnt == end_idx) { | |||
1585 | *pfrc = frc; | |||
1586 | return 0; | |||
1587 | } | |||
1588 | ||||
1589 | if (fr->datacnt == end_idx) { | |||
1590 | memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx)); | |||
1591 | ||||
1592 | assert(fr->data[0].len > base_offset)((void) (0)); | |||
1593 | ||||
1594 | fr->offset = offset + base_offset; | |||
1595 | fr->datacnt = end_idx - idx; | |||
1596 | fr->data[0].base += base_offset; | |||
1597 | fr->data[0].len -= (size_t)base_offset; | |||
1598 | ||||
1599 | *pfrc = frc; | |||
1600 | return 0; | |||
1601 | } | |||
1602 | ||||
1603 | rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, fr->datacnt - end_idx, | |||
1604 | conn->mem); | |||
1605 | if (rv != 0) { | |||
1606 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1607 | return rv; | |||
1608 | } | |||
1609 | ||||
1610 | nfr = &nfrc->fr.crypto; | |||
1611 | nfr->type = NGTCP2_FRAME_CRYPTO; | |||
1612 | memcpy(nfr->data, fr->data + end_idx, | |||
1613 | sizeof(nfr->data[0]) * (fr->datacnt - end_idx)); | |||
1614 | ||||
1615 | assert(nfr->data[0].len > end_base_offset)((void) (0)); | |||
1616 | ||||
1617 | nfr->offset = end_offset + end_base_offset; | |||
1618 | nfr->datacnt = fr->datacnt - end_idx; | |||
1619 | nfr->data[0].base += end_base_offset; | |||
1620 | nfr->data[0].len -= (size_t)end_base_offset; | |||
1621 | ||||
1622 | rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL((void*)0), &nfr->offset, nfrc); | |||
1623 | if (rv != 0) { | |||
1624 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
1625 | ngtcp2_frame_chain_del(nfrc, conn->mem); | |||
1626 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1627 | return rv; | |||
1628 | } | |||
1629 | ||||
1630 | if (end_base_offset) { | |||
1631 | ++end_idx; | |||
1632 | } | |||
1633 | ||||
1634 | memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx)); | |||
1635 | ||||
1636 | assert(fr->data[0].len > base_offset)((void) (0)); | |||
1637 | ||||
1638 | fr->offset = offset + base_offset; | |||
1639 | fr->datacnt = end_idx - idx; | |||
1640 | if (end_base_offset) { | |||
1641 | assert(fr->data[fr->datacnt - 1].len > end_base_offset)((void) (0)); | |||
1642 | fr->data[fr->datacnt - 1].len = (size_t)end_base_offset; | |||
1643 | } | |||
1644 | fr->data[0].base += base_offset; | |||
1645 | fr->data[0].len -= (size_t)base_offset; | |||
1646 | ||||
1647 | *pfrc = frc; | |||
1648 | return 0; | |||
1649 | } | |||
1650 | ||||
1651 | return 0; | |||
1652 | } | |||
1653 | static int conn_cryptofrq_pop(ngtcp2_conn *conn, ngtcp2_frame_chain **pfrc, | |||
1654 | ngtcp2_pktns *pktns, size_t left) { | |||
1655 | ngtcp2_crypto *fr, *nfr; | |||
1656 | ngtcp2_frame_chain *frc, *nfrc; | |||
1657 | int rv; | |||
1658 | size_t nmerged; | |||
1659 | size_t datalen; | |||
1660 | ngtcp2_vec a[NGTCP2_MAX_CRYPTO_DATACNT8]; | |||
1661 | ngtcp2_vec b[NGTCP2_MAX_CRYPTO_DATACNT8]; | |||
1662 | size_t acnt, bcnt; | |||
1663 | ngtcp2_ksl_it it; | |||
1664 | ||||
1665 | rv = conn_cryptofrq_unacked_pop(conn, pktns, &frc); | |||
1666 | if (rv != 0) { | |||
1667 | return rv; | |||
1668 | } | |||
1669 | if (frc == NULL((void*)0)) { | |||
1670 | *pfrc = NULL((void*)0); | |||
1671 | return 0; | |||
1672 | } | |||
1673 | ||||
1674 | fr = &frc->fr.crypto; | |||
1675 | datalen = ngtcp2_vec_len(fr->data, fr->datacnt); | |||
1676 | ||||
1677 | if (datalen > left) { | |||
1678 | ngtcp2_vec_copy(a, fr->data, fr->datacnt); | |||
1679 | acnt = fr->datacnt; | |||
1680 | ||||
1681 | bcnt = 0; | |||
1682 | ngtcp2_vec_split(a, &acnt, b, &bcnt, left, NGTCP2_MAX_CRYPTO_DATACNT8); | |||
1683 | ||||
1684 | assert(acnt > 0)((void) (0)); | |||
1685 | assert(bcnt > 0)((void) (0)); | |||
1686 | ||||
1687 | rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, bcnt, conn->mem); | |||
1688 | if (rv != 0) { | |||
1689 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
1690 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1691 | return rv; | |||
1692 | } | |||
1693 | ||||
1694 | nfr = &nfrc->fr.crypto; | |||
1695 | nfr->type = NGTCP2_FRAME_CRYPTO; | |||
1696 | nfr->offset = fr->offset + left; | |||
1697 | nfr->datacnt = bcnt; | |||
1698 | ngtcp2_vec_copy(nfr->data, b, bcnt); | |||
1699 | ||||
1700 | rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL((void*)0), &nfr->offset, nfrc); | |||
1701 | if (rv != 0) { | |||
1702 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
1703 | ngtcp2_frame_chain_del(nfrc, conn->mem); | |||
1704 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1705 | return rv; | |||
1706 | } | |||
1707 | ||||
1708 | rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, acnt, conn->mem); | |||
1709 | if (rv != 0) { | |||
1710 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
1711 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1712 | return rv; | |||
1713 | } | |||
1714 | ||||
1715 | nfr = &nfrc->fr.crypto; | |||
1716 | *nfr = *fr; | |||
1717 | nfr->datacnt = acnt; | |||
1718 | ngtcp2_vec_copy(nfr->data, a, acnt); | |||
1719 | ||||
1720 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1721 | ||||
1722 | *pfrc = nfrc; | |||
1723 | ||||
1724 | return 0; | |||
1725 | } | |||
1726 | ||||
1727 | left -= datalen; | |||
1728 | ||||
1729 | ngtcp2_vec_copy(a, fr->data, fr->datacnt); | |||
1730 | acnt = fr->datacnt; | |||
1731 | ||||
1732 | for (; left && ngtcp2_ksl_len(&pktns->crypto.tx.frq);) { | |||
1733 | it = ngtcp2_ksl_begin(&pktns->crypto.tx.frq); | |||
1734 | nfrc = ngtcp2_ksl_it_get(&it); | |||
1735 | nfr = &nfrc->fr.crypto; | |||
1736 | ||||
1737 | if (nfr->offset != fr->offset + datalen) { | |||
1738 | assert(fr->offset + datalen < nfr->offset)((void) (0)); | |||
1739 | break; | |||
1740 | } | |||
1741 | ||||
1742 | rv = conn_cryptofrq_unacked_pop(conn, pktns, &nfrc); | |||
1743 | if (rv != 0) { | |||
1744 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
1745 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1746 | return rv; | |||
1747 | } | |||
1748 | if (nfrc == NULL((void*)0)) { | |||
1749 | break; | |||
1750 | } | |||
1751 | ||||
1752 | nfr = &nfrc->fr.crypto; | |||
1753 | ||||
1754 | nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left, | |||
1755 | NGTCP2_MAX_CRYPTO_DATACNT8); | |||
1756 | if (nmerged == 0) { | |||
1757 | rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL((void*)0), &nfr->offset, nfrc); | |||
1758 | if (rv != 0) { | |||
1759 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
1760 | ngtcp2_frame_chain_del(nfrc, conn->mem); | |||
1761 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1762 | return rv; | |||
1763 | } | |||
1764 | break; | |||
1765 | } | |||
1766 | ||||
1767 | datalen += nmerged; | |||
1768 | left -= nmerged; | |||
1769 | ||||
1770 | if (nfr->datacnt == 0) { | |||
1771 | ngtcp2_frame_chain_del(nfrc, conn->mem); | |||
1772 | continue; | |||
1773 | } | |||
1774 | ||||
1775 | nfr->offset += nmerged; | |||
1776 | ||||
1777 | rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL((void*)0), &nfr->offset, nfrc); | |||
1778 | if (rv != 0) { | |||
1779 | ngtcp2_frame_chain_del(nfrc, conn->mem); | |||
1780 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1781 | return rv; | |||
1782 | } | |||
1783 | ||||
1784 | break; | |||
1785 | } | |||
1786 | ||||
1787 | if (acnt == fr->datacnt) { | |||
1788 | assert(acnt > 0)((void) (0)); | |||
1789 | fr->data[acnt - 1] = a[acnt - 1]; | |||
1790 | ||||
1791 | *pfrc = frc; | |||
1792 | return 0; | |||
1793 | } | |||
1794 | ||||
1795 | assert(acnt > fr->datacnt)((void) (0)); | |||
1796 | ||||
1797 | rv = ngtcp2_frame_chain_crypto_datacnt_new(&nfrc, acnt, conn->mem); | |||
1798 | if (rv != 0) { | |||
1799 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1800 | return rv; | |||
1801 | } | |||
1802 | ||||
1803 | nfr = &nfrc->fr.crypto; | |||
1804 | *nfr = *fr; | |||
1805 | nfr->datacnt = acnt; | |||
1806 | ngtcp2_vec_copy(nfr->data, a, acnt); | |||
1807 | ||||
1808 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
1809 | ||||
1810 | *pfrc = nfrc; | |||
1811 | ||||
1812 | return 0; | |||
1813 | } | |||
1814 | ||||
1815 | /* | |||
1816 | * conn_verify_dcid verifies that destination connection ID in |hd| is | |||
1817 | * valid for the connection. If it is successfully verified and the | |||
1818 | * remote endpoint uses new DCID in the packet, nonzero value is | |||
1819 | * assigned to |*pnew_cid_used| if it is not NULL. Otherwise 0 is | |||
1820 | * assigned to it. | |||
1821 | * | |||
1822 | * This function returns 0 if it succeeds, or one of the following | |||
1823 | * negative error codes: | |||
1824 | * | |||
1825 | * NGTCP2_ERR_NOMEM | |||
1826 | * Out of memory. | |||
1827 | * NGTCP2_ERR_INVALID_ARGUMENT | |||
1828 | * |dcid| is not known to the local endpoint. | |||
1829 | */ | |||
1830 | static int conn_verify_dcid(ngtcp2_conn *conn, int *pnew_cid_used, | |||
1831 | const ngtcp2_pkt_hd *hd) { | |||
1832 | ngtcp2_ksl_it it; | |||
1833 | ngtcp2_scid *scid; | |||
1834 | int rv; | |||
1835 | ||||
1836 | it = ngtcp2_ksl_lower_bound(&conn->scid.set, &hd->dcid); | |||
1837 | if (ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0))) { | |||
1838 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
1839 | } | |||
1840 | ||||
1841 | scid = ngtcp2_ksl_it_get(&it); | |||
1842 | if (!ngtcp2_cid_eq(&scid->cid, &hd->dcid)) { | |||
1843 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
1844 | } | |||
1845 | ||||
1846 | if (!(scid->flags & NGTCP2_SCID_FLAG_USED0x01)) { | |||
1847 | scid->flags |= NGTCP2_SCID_FLAG_USED0x01; | |||
1848 | ||||
1849 | if (scid->pe.index == NGTCP2_PQ_BAD_INDEX(18446744073709551615UL)) { | |||
1850 | rv = ngtcp2_pq_push(&conn->scid.used, &scid->pe); | |||
1851 | if (rv != 0) { | |||
1852 | return rv; | |||
1853 | } | |||
1854 | } | |||
1855 | ||||
1856 | if (pnew_cid_used) { | |||
1857 | *pnew_cid_used = 1; | |||
1858 | } | |||
1859 | } else if (pnew_cid_used) { | |||
1860 | *pnew_cid_used = 0; | |||
1861 | } | |||
1862 | ||||
1863 | return 0; | |||
1864 | } | |||
1865 | ||||
1866 | /* | |||
1867 | * conn_should_pad_pkt returns nonzero if the packet should be padded. | |||
1868 | * |type| is the type of packet. |left| is the space left in packet | |||
1869 | * buffer. |early_datalen| is the number of bytes which will be sent | |||
1870 | * in the next, coalesced 0-RTT packet. | |||
1871 | */ | |||
1872 | static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, | |||
1873 | size_t early_datalen, int ack_eliciting) { | |||
1874 | size_t min_payloadlen; | |||
1875 | ||||
1876 | if (conn->server) { | |||
1877 | if (type != NGTCP2_PKT_INITIAL || !ack_eliciting) { | |||
1878 | return 0; | |||
1879 | } | |||
1880 | ||||
1881 | if (conn->hs_pktns->crypto.tx.ckm && | |||
1882 | (conn->hs_pktns->rtb.probe_pkt_left || | |||
1883 | ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) || | |||
1884 | !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) { | |||
1885 | /* If we have something to send in Handshake packet, then add | |||
1886 | PADDING in Handshake packet. */ | |||
1887 | min_payloadlen = 128; | |||
1888 | } else { | |||
1889 | return 1; | |||
1890 | } | |||
1891 | } else { | |||
1892 | if (type == NGTCP2_PKT_HANDSHAKE) { | |||
1893 | return conn->in_pktns != NULL((void*)0); | |||
1894 | } | |||
1895 | ||||
1896 | if (conn->hs_pktns->crypto.tx.ckm && | |||
1897 | (conn->hs_pktns->rtb.probe_pkt_left || | |||
1898 | ngtcp2_ksl_len(&conn->hs_pktns->crypto.tx.frq) || | |||
1899 | !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) { | |||
1900 | /* If we have something to send in Handshake packet, then add | |||
1901 | PADDING in Handshake packet. */ | |||
1902 | min_payloadlen = 128; | |||
1903 | } else if (!conn->early.ckm || early_datalen == 0) { | |||
1904 | return 1; | |||
1905 | } else { | |||
1906 | /* If we have something to send in 0RTT packet, then add PADDING | |||
1907 | in 0RTT packet. */ | |||
1908 | min_payloadlen = ngtcp2_min(early_datalen, 128)((early_datalen) < (128) ? (early_datalen) : (128)); | |||
1909 | } | |||
1910 | } | |||
1911 | ||||
1912 | return left < | |||
1913 | /* TODO Assuming that pkt_num is encoded in 1 byte. */ | |||
1914 | NGTCP2_MIN_LONG_HEADERLEN(1 + 4 + 1 + 1 + 1 + 1) + conn->dcid.current.cid.datalen + | |||
1915 | conn->oscid.datalen + 1 /* payloadlen bytes - 1 */ + | |||
1916 | min_payloadlen + NGTCP2_MAX_AEAD_OVERHEAD16; | |||
1917 | } | |||
1918 | ||||
1919 | static void conn_restart_timer_on_write(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
1920 | conn->idle_ts = ts; | |||
1921 | conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE0x2000; | |||
1922 | } | |||
1923 | ||||
1924 | static void conn_restart_timer_on_read(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
1925 | conn->idle_ts = ts; | |||
1926 | conn->flags |= NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE0x2000; | |||
1927 | } | |||
1928 | ||||
1929 | /* NGTCP2_WRITE_PKT_FLAG_NONE indicates that no flag is set. */ | |||
1930 | #define NGTCP2_WRITE_PKT_FLAG_NONE0x00 0x00 | |||
1931 | /* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING indicates that packet should | |||
1932 | be padded */ | |||
1933 | #define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING0x01 0x01 | |||
1934 | /* NGTCP2_WRITE_PKT_FLAG_MORE indicates that more frames might come | |||
1935 | and it should be encoded into the current packet. */ | |||
1936 | #define NGTCP2_WRITE_PKT_FLAG_MORE0x02 0x02 | |||
1937 | ||||
1938 | /* | |||
1939 | * conn_write_handshake_pkt writes handshake packet in the buffer | |||
1940 | * pointed by |dest| whose length is |destlen|. |type| specifies long | |||
1941 | * packet type. It should be either NGTCP2_PKT_INITIAL or | |||
1942 | * NGTCP2_PKT_HANDSHAKE_PKT. | |||
1943 | * | |||
1944 | * This function returns the number of bytes written in |dest| if it | |||
1945 | * succeeds, or one of the following negative error codes: | |||
1946 | * | |||
1947 | * NGTCP2_ERR_NOMEM | |||
1948 | * Out of memory. | |||
1949 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
1950 | * User-defined callback function failed. | |||
1951 | */ | |||
1952 | static ngtcp2_ssize | |||
1953 | conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, | |||
1954 | size_t destlen, uint8_t type, uint8_t flags, | |||
1955 | size_t early_datalen, ngtcp2_tstamp ts) { | |||
1956 | int rv; | |||
1957 | ngtcp2_ppe ppe; | |||
1958 | ngtcp2_pkt_hd hd; | |||
1959 | ngtcp2_frame_chain *frq = NULL((void*)0), **pfrc = &frq; | |||
1960 | ngtcp2_frame_chain *nfrc; | |||
1961 | ngtcp2_frame *ackfr = NULL((void*)0), lfr; | |||
1962 | ngtcp2_ssize spktlen; | |||
1963 | ngtcp2_crypto_cc cc; | |||
1964 | ngtcp2_rtb_entry *rtbent; | |||
1965 | ngtcp2_pktns *pktns; | |||
1966 | size_t left; | |||
1967 | uint8_t rtb_entry_flags = NGTCP2_RTB_ENTRY_FLAG_NONE0x00; | |||
1968 | int require_padding = (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING0x01) != 0; | |||
1969 | int pkt_empty = 1; | |||
1970 | int padded = 0; | |||
1971 | int hd_logged = 0; | |||
1972 | uint64_t crypto_offset; | |||
1973 | ngtcp2_ssize num_reclaimed; | |||
1974 | ||||
1975 | switch (type) { | |||
1976 | case NGTCP2_PKT_INITIAL: | |||
1977 | if (!conn->in_pktns) { | |||
1978 | return 0; | |||
1979 | } | |||
1980 | assert(conn->in_pktns->crypto.tx.ckm)((void) (0)); | |||
1981 | pktns = conn->in_pktns; | |||
1982 | break; | |||
1983 | case NGTCP2_PKT_HANDSHAKE: | |||
1984 | if (!conn->hs_pktns || !conn->hs_pktns->crypto.tx.ckm) { | |||
1985 | return 0; | |||
1986 | } | |||
1987 | pktns = conn->hs_pktns; | |||
1988 | break; | |||
1989 | default: | |||
1990 | assert(0)((void) (0)); | |||
1991 | } | |||
1992 | ||||
1993 | cc.aead = pktns->crypto.ctx.aead; | |||
1994 | cc.hp = pktns->crypto.ctx.hp; | |||
1995 | cc.ckm = pktns->crypto.tx.ckm; | |||
1996 | cc.hp_ctx = pktns->crypto.tx.hp_ctx; | |||
1997 | cc.encrypt = conn->callbacks.encrypt; | |||
1998 | cc.hp_mask = conn->callbacks.hp_mask; | |||
1999 | ||||
2000 | ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM0x01, type, | |||
2001 | &conn->dcid.current.cid, &conn->oscid, | |||
2002 | pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), | |||
2003 | conn->version, 0); | |||
2004 | ||||
2005 | if (!conn->server && type == NGTCP2_PKT_INITIAL && | |||
2006 | conn->local.settings.token.len) { | |||
2007 | hd.token = conn->local.settings.token; | |||
2008 | } | |||
2009 | ||||
2010 | ngtcp2_ppe_init(&ppe, dest, destlen, &cc); | |||
2011 | ||||
2012 | rv = ngtcp2_ppe_encode_hd(&ppe, &hd); | |||
2013 | if (rv != 0) { | |||
2014 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
2015 | return 0; | |||
2016 | } | |||
2017 | ||||
2018 | if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) { | |||
2019 | return 0; | |||
2020 | } | |||
2021 | ||||
2022 | rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, | |||
2023 | /* ack_delay = */ 0, | |||
2024 | NGTCP2_DEFAULT_ACK_DELAY_EXPONENT3); | |||
2025 | if (rv != 0) { | |||
2026 | ngtcp2_frame_chain_list_del(frq, conn->mem); | |||
2027 | return rv; | |||
2028 | } | |||
2029 | ||||
2030 | if (ackfr) { | |||
2031 | rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, ackfr); | |||
2032 | if (rv != 0) { | |||
2033 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
2034 | } else { | |||
2035 | ngtcp2_acktr_commit_ack(&pktns->acktr); | |||
2036 | ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, ackfr->ack.largest_ack); | |||
2037 | pkt_empty = 0; | |||
2038 | } | |||
2039 | } | |||
2040 | ||||
2041 | /* Server requires at least NGTCP2_DEFAULT_MAX_PKTLEN bytes in order | |||
2042 | to send ack-eliciting Initial packet. */ | |||
2043 | if (!conn->server || type != NGTCP2_PKT_INITIAL || | |||
2044 | destlen >= NGTCP2_DEFAULT_MAX_PKTLEN1200) { | |||
2045 | build_pkt: | |||
2046 | for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) { | |||
2047 | left = ngtcp2_ppe_left(&ppe); | |||
2048 | ||||
2049 | crypto_offset = conn_cryptofrq_unacked_offset(conn, pktns); | |||
2050 | if (crypto_offset == (size_t)-1) { | |||
2051 | conn_cryptofrq_clear(conn, pktns); | |||
2052 | break; | |||
2053 | } | |||
2054 | ||||
2055 | left = ngtcp2_pkt_crypto_max_datalen(crypto_offset, left, left); | |||
2056 | if (left == (size_t)-1) { | |||
2057 | break; | |||
2058 | } | |||
2059 | ||||
2060 | rv = conn_cryptofrq_pop(conn, &nfrc, pktns, left); | |||
2061 | if (rv != 0) { | |||
2062 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
2063 | ngtcp2_frame_chain_list_del(frq, conn->mem); | |||
2064 | return rv; | |||
2065 | } | |||
2066 | ||||
2067 | if (nfrc == NULL((void*)0)) { | |||
2068 | break; | |||
2069 | } | |||
2070 | ||||
2071 | rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &nfrc->fr); | |||
2072 | if (rv != 0) { | |||
2073 | assert(0)((void) (0)); | |||
2074 | } | |||
2075 | ||||
2076 | *pfrc = nfrc; | |||
2077 | pfrc = &(*pfrc)->next; | |||
2078 | ||||
2079 | pkt_empty = 0; | |||
2080 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
2081 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
2082 | } | |||
2083 | ||||
2084 | if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) && | |||
2085 | pktns->rtb.num_retransmittable && pktns->rtb.probe_pkt_left) { | |||
2086 | num_reclaimed = ngtcp2_rtb_reclaim_on_pto(&pktns->rtb, conn, pktns, | |||
2087 | pktns->rtb.probe_pkt_left + 1); | |||
2088 | if (num_reclaimed < 0) { | |||
2089 | ngtcp2_frame_chain_list_del(frq, conn->mem); | |||
2090 | return rv; | |||
2091 | } | |||
2092 | if (num_reclaimed) { | |||
2093 | goto build_pkt; | |||
2094 | } | |||
2095 | /* We had pktns->rtb.num_retransmittable > 0 but the contents of | |||
2096 | those packets have been acknowledged (i.e., retransmission in | |||
2097 | another packet). For server, in this case, we don't have to | |||
2098 | send any probe packet. Client needs to send probe packets | |||
2099 | until it knows that server has completed address validation or | |||
2100 | handshake has been confirmed. */ | |||
2101 | if (pktns->rtb.num_retransmittable == 0 && | |||
2102 | (conn->server || | |||
2103 | (conn->flags & (NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000 | | |||
2104 | NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80)))) { | |||
2105 | pktns->rtb.probe_pkt_left = 0; | |||
2106 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
2107 | } | |||
2108 | } | |||
2109 | ||||
2110 | /* Don't send any PING frame if client Initial has not been | |||
2111 | acknowledged yet. */ | |||
2112 | if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) && | |||
2113 | pktns->rtb.probe_pkt_left && | |||
2114 | (type != NGTCP2_PKT_INITIAL || | |||
2115 | ngtcp2_strm_is_all_tx_data_acked(&pktns->crypto.strm))) { | |||
2116 | lfr.type = NGTCP2_FRAME_PING; | |||
2117 | ||||
2118 | rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr); | |||
2119 | if (rv != 0) { | |||
2120 | assert(rv == NGTCP2_ERR_NOBUF)((void) (0)); | |||
2121 | } else { | |||
2122 | rtb_entry_flags |= | |||
2123 | NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | NGTCP2_RTB_ENTRY_FLAG_PROBE0x01; | |||
2124 | pkt_empty = 0; | |||
2125 | } | |||
2126 | } | |||
2127 | ||||
2128 | if (!pkt_empty) { | |||
2129 | if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04)) { | |||
2130 | /* The intention of smaller limit is get more chance to measure | |||
2131 | RTT samples in early phase. */ | |||
2132 | if (pktns->rtb.probe_pkt_left || pktns->tx.num_non_ack_pkt >= 1) { | |||
2133 | lfr.type = NGTCP2_FRAME_PING; | |||
2134 | ||||
2135 | rv = conn_ppe_write_frame_hd_log(conn, &ppe, &hd_logged, &hd, &lfr); | |||
2136 | if (rv != 0) { | |||
2137 | assert(rv == NGTCP2_ERR_NOBUF)((void) (0)); | |||
2138 | } else { | |||
2139 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04; | |||
2140 | pktns->tx.num_non_ack_pkt = 0; | |||
2141 | } | |||
2142 | } else { | |||
2143 | ++pktns->tx.num_non_ack_pkt; | |||
2144 | } | |||
2145 | } else { | |||
2146 | pktns->tx.num_non_ack_pkt = 0; | |||
2147 | } | |||
2148 | } | |||
2149 | } | |||
2150 | ||||
2151 | if (pkt_empty) { | |||
2152 | return 0; | |||
2153 | } | |||
2154 | ||||
2155 | /* If we cannot write another packet, then we need to add padding to | |||
2156 | Initial here. */ | |||
2157 | if (require_padding || | |||
2158 | conn_should_pad_pkt( | |||
2159 | conn, type, ngtcp2_ppe_left(&ppe), early_datalen, | |||
2160 | (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) != 0)) { | |||
2161 | lfr.type = NGTCP2_FRAME_PADDING; | |||
2162 | lfr.padding.len = ngtcp2_ppe_padding(&ppe); | |||
2163 | } else { | |||
2164 | lfr.type = NGTCP2_FRAME_PADDING; | |||
2165 | lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe); | |||
2166 | } | |||
2167 | ||||
2168 | if (lfr.padding.len) { | |||
2169 | padded = 1; | |||
2170 | ngtcp2_log_tx_fr(&conn->log, &hd, &lfr); | |||
2171 | ngtcp2_qlog_write_frame(&conn->qlog, &lfr); | |||
2172 | } | |||
2173 | ||||
2174 | spktlen = ngtcp2_ppe_final(&ppe, NULL((void*)0)); | |||
2175 | if (spktlen < 0) { | |||
2176 | assert(ngtcp2_err_is_fatal((int)spktlen))((void) (0)); | |||
2177 | ngtcp2_frame_chain_list_del(frq, conn->mem); | |||
2178 | return spktlen; | |||
2179 | } | |||
2180 | ||||
2181 | ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)spktlen); | |||
2182 | ||||
2183 | if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) || padded) { | |||
2184 | if (pi) { | |||
2185 | conn_handle_tx_ecn(conn, pi, &rtb_entry_flags, pktns, &hd, ts); | |||
2186 | } | |||
2187 | ||||
2188 | rv = ngtcp2_rtb_entry_new(&rtbent, &hd, frq, ts, (size_t)spktlen, | |||
2189 | rtb_entry_flags, conn->mem); | |||
2190 | if (rv != 0) { | |||
2191 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
2192 | ngtcp2_frame_chain_list_del(frq, conn->mem); | |||
2193 | return rv; | |||
2194 | } | |||
2195 | ||||
2196 | rv = conn_on_pkt_sent(conn, &pktns->rtb, rtbent); | |||
2197 | if (rv != 0) { | |||
2198 | ngtcp2_rtb_entry_del(rtbent, conn->mem); | |||
2199 | return rv; | |||
2200 | } | |||
2201 | ||||
2202 | if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) && | |||
2203 | (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE0x2000)) { | |||
2204 | conn_restart_timer_on_write(conn, ts); | |||
2205 | } | |||
2206 | } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { | |||
2207 | conn_handle_tx_ecn(conn, pi, NULL((void*)0), pktns, &hd, ts); | |||
2208 | } | |||
2209 | ||||
2210 | if (pktns->rtb.probe_pkt_left && | |||
2211 | (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04)) { | |||
2212 | --pktns->rtb.probe_pkt_left; | |||
2213 | } | |||
2214 | ||||
2215 | conn->dcid.current.bytes_sent += (uint64_t)spktlen; | |||
2216 | ||||
2217 | ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); | |||
2218 | ||||
2219 | ++pktns->tx.last_pkt_num; | |||
2220 | ||||
2221 | return spktlen; | |||
2222 | } | |||
2223 | ||||
2224 | /* | |||
2225 | * conn_write_ack_pkt writes QUIC packet for type |type| which only | |||
2226 | * includes ACK frame in the buffer pointed by |dest| whose length is | |||
2227 | * |destlen|. | |||
2228 | * | |||
2229 | * This function returns the number of bytes written in |dest| if it | |||
2230 | * succeeds, or one of the following negative error codes: | |||
2231 | * | |||
2232 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
2233 | * User-defined callback function failed. | |||
2234 | * NGTCP2_ERR_NOMEM | |||
2235 | * Out of memory. | |||
2236 | */ | |||
2237 | static ngtcp2_ssize conn_write_ack_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, | |||
2238 | uint8_t *dest, size_t destlen, | |||
2239 | uint8_t type, ngtcp2_tstamp ts) { | |||
2240 | int rv; | |||
2241 | ngtcp2_frame *ackfr; | |||
2242 | ngtcp2_pktns *pktns; | |||
2243 | ngtcp2_duration ack_delay; | |||
2244 | uint64_t ack_delay_exponent; | |||
2245 | ngtcp2_ssize spktlen; | |||
2246 | ||||
2247 | assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING))((void) (0)); | |||
2248 | ||||
2249 | switch (type) { | |||
2250 | case NGTCP2_PKT_INITIAL: | |||
2251 | assert(conn->server)((void) (0)); | |||
2252 | pktns = conn->in_pktns; | |||
2253 | ack_delay = 0; | |||
2254 | ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT3; | |||
2255 | break; | |||
2256 | case NGTCP2_PKT_HANDSHAKE: | |||
2257 | pktns = conn->hs_pktns; | |||
2258 | ack_delay = 0; | |||
2259 | ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT3; | |||
2260 | break; | |||
2261 | case NGTCP2_PKT_SHORT: | |||
2262 | pktns = &conn->pktns; | |||
2263 | ack_delay = conn_compute_ack_delay(conn); | |||
2264 | ack_delay_exponent = conn->local.transport_params.ack_delay_exponent; | |||
2265 | break; | |||
2266 | default: | |||
2267 | assert(0)((void) (0)); | |||
2268 | } | |||
2269 | ||||
2270 | if (!pktns->crypto.tx.ckm) { | |||
2271 | return 0; | |||
2272 | } | |||
2273 | ||||
2274 | ackfr = NULL((void*)0); | |||
2275 | rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, ack_delay, | |||
2276 | ack_delay_exponent); | |||
2277 | if (rv != 0) { | |||
2278 | return rv; | |||
2279 | } | |||
2280 | ||||
2281 | if (!ackfr) { | |||
2282 | return 0; | |||
2283 | } | |||
2284 | ||||
2285 | spktlen = ngtcp2_conn_write_single_frame_pkt( | |||
2286 | conn, pi, dest, destlen, type, &conn->dcid.current.cid, ackfr, | |||
2287 | NGTCP2_RTB_ENTRY_FLAG_NONE0x00, NULL((void*)0), ts); | |||
2288 | ||||
2289 | if (spktlen <= 0) { | |||
2290 | return spktlen; | |||
2291 | } | |||
2292 | ||||
2293 | conn->dcid.current.bytes_sent += (uint64_t)spktlen; | |||
2294 | ||||
2295 | return spktlen; | |||
2296 | } | |||
2297 | ||||
2298 | static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns, | |||
2299 | ngtcp2_tstamp ts) { | |||
2300 | ngtcp2_pktns *pktns = *ppktns; | |||
2301 | uint64_t bytes_in_flight; | |||
2302 | ||||
2303 | bytes_in_flight = pktns->rtb.cc_bytes_in_flight; | |||
2304 | ||||
2305 | assert(conn->cstat.bytes_in_flight >= bytes_in_flight)((void) (0)); | |||
2306 | ||||
2307 | conn->cstat.bytes_in_flight -= bytes_in_flight; | |||
2308 | conn->cstat.pto_count = 0; | |||
2309 | conn->cstat.last_tx_pkt_ts[pktns->rtb.pktns_id] = UINT64_MAX(18446744073709551615UL); | |||
2310 | conn->cstat.loss_time[pktns->rtb.pktns_id] = UINT64_MAX(18446744073709551615UL); | |||
2311 | ||||
2312 | conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.rx.ckm->aead_ctx); | |||
2313 | conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.rx.hp_ctx); | |||
2314 | conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.tx.ckm->aead_ctx); | |||
2315 | conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.tx.hp_ctx); | |||
2316 | ||||
2317 | pktns_del(pktns, conn->mem); | |||
2318 | *ppktns = NULL((void*)0); | |||
2319 | ||||
2320 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
2321 | } | |||
2322 | ||||
2323 | /* | |||
2324 | * conn_discard_initial_state discards state for Initial packet number | |||
2325 | * space. | |||
2326 | */ | |||
2327 | static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
2328 | if (!conn->in_pktns) { | |||
2329 | return; | |||
2330 | } | |||
2331 | ||||
2332 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
2333 | "discarding Initial packet number space"); | |||
2334 | ||||
2335 | conn_discard_pktns(conn, &conn->in_pktns, ts); | |||
2336 | } | |||
2337 | ||||
2338 | /* | |||
2339 | * conn_discard_handshake_state discards state for Handshake packet | |||
2340 | * number space. | |||
2341 | */ | |||
2342 | static void conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
2343 | if (!conn->hs_pktns) { | |||
2344 | return; | |||
2345 | } | |||
2346 | ||||
2347 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
2348 | "discarding Handshake packet number space"); | |||
2349 | ||||
2350 | conn_discard_pktns(conn, &conn->hs_pktns, ts); | |||
2351 | } | |||
2352 | ||||
2353 | /* | |||
2354 | * conn_discard_early_key discards early key. | |||
2355 | */ | |||
2356 | static void conn_discard_early_key(ngtcp2_conn *conn) { | |||
2357 | assert(conn->early.ckm)((void) (0)); | |||
2358 | ||||
2359 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "discarding early key"); | |||
2360 | ||||
2361 | conn_call_delete_crypto_aead_ctx(conn, &conn->early.ckm->aead_ctx); | |||
2362 | conn_call_delete_crypto_cipher_ctx(conn, &conn->early.hp_ctx); | |||
2363 | memset(&conn->early.hp_ctx, 0, sizeof(conn->early.hp_ctx)); | |||
2364 | ||||
2365 | ngtcp2_crypto_km_del(conn->early.ckm, conn->mem); | |||
2366 | conn->early.ckm = NULL((void*)0); | |||
2367 | } | |||
2368 | ||||
2369 | /* | |||
2370 | * conn_write_handshake_ack_pkts writes packets which contain ACK | |||
2371 | * frame only. This function writes at most 2 packets for each | |||
2372 | * Initial and Handshake packet. | |||
2373 | */ | |||
2374 | static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn, | |||
2375 | ngtcp2_pkt_info *pi, | |||
2376 | uint8_t *dest, size_t destlen, | |||
2377 | ngtcp2_tstamp ts) { | |||
2378 | ngtcp2_ssize res = 0, nwrite = 0; | |||
2379 | ||||
2380 | /* In the most cases, client sends ACK in conn_write_handshake_pkt. | |||
2381 | This function is only called when it is CWND limited. It is not | |||
2382 | required for client to send ACK for server Initial. This is | |||
2383 | because once it gets server Initial, it gets Handshake tx key and | |||
2384 | discards Initial key. The only good reason to send ACK is give | |||
2385 | server RTT measurement early. */ | |||
2386 | if (conn->server && conn->in_pktns) { | |||
2387 | nwrite = | |||
2388 | conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, ts); | |||
2389 | if (nwrite < 0) { | |||
2390 | assert(nwrite != NGTCP2_ERR_NOBUF)((void) (0)); | |||
2391 | return nwrite; | |||
2392 | } | |||
2393 | ||||
2394 | res += nwrite; | |||
2395 | dest += nwrite; | |||
2396 | destlen -= (size_t)nwrite; | |||
2397 | } | |||
2398 | ||||
2399 | if (conn->hs_pktns->crypto.tx.ckm) { | |||
2400 | nwrite = | |||
2401 | conn_write_ack_pkt(conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, ts); | |||
2402 | if (nwrite < 0) { | |||
2403 | assert(nwrite != NGTCP2_ERR_NOBUF)((void) (0)); | |||
2404 | return nwrite; | |||
2405 | } | |||
2406 | ||||
2407 | res += nwrite; | |||
2408 | ||||
2409 | if (!conn->server && nwrite) { | |||
2410 | conn_discard_initial_state(conn, ts); | |||
2411 | } | |||
2412 | } | |||
2413 | ||||
2414 | return res; | |||
2415 | } | |||
2416 | ||||
2417 | /* | |||
2418 | * conn_write_client_initial writes Initial packet in the buffer | |||
2419 | * pointed by |dest| whose length is |destlen|. | |||
2420 | * | |||
2421 | * This function returns the number of bytes written in |dest| if it | |||
2422 | * succeeds, or one of the following negative error codes: | |||
2423 | * | |||
2424 | * NGTCP2_ERR_NOMEM | |||
2425 | * Out of memory. | |||
2426 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
2427 | * User-defined callback function failed. | |||
2428 | */ | |||
2429 | static ngtcp2_ssize conn_write_client_initial(ngtcp2_conn *conn, | |||
2430 | ngtcp2_pkt_info *pi, | |||
2431 | uint8_t *dest, size_t destlen, | |||
2432 | size_t early_datalen, | |||
2433 | ngtcp2_tstamp ts) { | |||
2434 | int rv; | |||
2435 | ||||
2436 | assert(conn->callbacks.client_initial)((void) (0)); | |||
2437 | ||||
2438 | rv = conn->callbacks.client_initial(conn, conn->user_data); | |||
2439 | if (rv != 0) { | |||
2440 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
2441 | } | |||
2442 | ||||
2443 | return conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, | |||
2444 | NGTCP2_WRITE_PKT_FLAG_NONE0x00, early_datalen, | |||
2445 | ts); | |||
2446 | } | |||
2447 | ||||
2448 | /* | |||
2449 | * conn_write_handshake_pkts writes Initial and Handshake packets in | |||
2450 | * the buffer pointed by |dest| whose length is |destlen|. | |||
2451 | * | |||
2452 | * This function returns the number of bytes written in |dest| if it | |||
2453 | * succeeds, or one of the following negative error codes: | |||
2454 | * | |||
2455 | * NGTCP2_ERR_NOMEM | |||
2456 | * Out of memory. | |||
2457 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
2458 | * User-defined callback function failed. | |||
2459 | */ | |||
2460 | static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, | |||
2461 | ngtcp2_pkt_info *pi, | |||
2462 | uint8_t *dest, size_t destlen, | |||
2463 | size_t early_datalen, | |||
2464 | ngtcp2_tstamp ts) { | |||
2465 | ngtcp2_ssize nwrite; | |||
2466 | ngtcp2_ssize res = 0; | |||
2467 | int64_t prev_pkt_num = -1; | |||
2468 | ngtcp2_rtb_entry *rtbent; | |||
2469 | uint8_t wflags = NGTCP2_WRITE_PKT_FLAG_NONE0x00; | |||
2470 | ngtcp2_ksl_it it; | |||
2471 | ||||
2472 | /* As a client, we would like to discard Initial packet number space | |||
2473 | when sending the first Handshake packet. When sending Handshake | |||
2474 | packet, it should be one of 1) sending ACK, 2) sending PTO probe | |||
2475 | packet, or 3) sending CRYPTO. If we have pending acknowledgement | |||
2476 | for Initial, then do not discard Initial packet number space. | |||
2477 | Otherwise, if either 1) or 2) is satisfied, discard Initial | |||
2478 | packet number space. When sending Handshake CRYPTO, it indicates | |||
2479 | that client has received Handshake CRYPTO from server. Initial | |||
2480 | packet number space is discarded because 1) is met. If there is | |||
2481 | pending Initial ACK, Initial packet number space is discarded | |||
2482 | after writing the first Handshake packet. | |||
2483 | */ | |||
2484 | if (!conn->server && conn->hs_pktns->crypto.tx.ckm && conn->in_pktns && | |||
2485 | !ngtcp2_acktr_require_active_ack(&conn->in_pktns->acktr, | |||
2486 | /* max_ack_delay = */ 0, ts) && | |||
2487 | (ngtcp2_acktr_require_active_ack(&conn->hs_pktns->acktr, | |||
2488 | /* max_ack_delay = */ 0, ts) || | |||
2489 | conn->hs_pktns->rtb.probe_pkt_left)) { | |||
2490 | /* Discard Initial state here so that Handshake packet is not | |||
2491 | padded. */ | |||
2492 | conn_discard_initial_state(conn, ts); | |||
2493 | } else if (conn->in_pktns) { | |||
2494 | if (conn->server) { | |||
2495 | it = ngtcp2_rtb_head(&conn->in_pktns->rtb); | |||
2496 | if (!ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0))) { | |||
2497 | rtbent = ngtcp2_ksl_it_get(&it); | |||
2498 | prev_pkt_num = rtbent->hd.pkt_num; | |||
2499 | } | |||
2500 | } | |||
2501 | ||||
2502 | nwrite = | |||
2503 | conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, | |||
2504 | NGTCP2_WRITE_PKT_FLAG_NONE0x00, early_datalen, ts); | |||
2505 | if (nwrite < 0) { | |||
2506 | assert(nwrite != NGTCP2_ERR_NOBUF)((void) (0)); | |||
2507 | return nwrite; | |||
2508 | } | |||
2509 | ||||
2510 | if (nwrite == 0) { | |||
2511 | if (conn->server && (conn->in_pktns->rtb.probe_pkt_left || | |||
2512 | ngtcp2_ksl_len(&conn->in_pktns->crypto.tx.frq))) { | |||
2513 | return 0; | |||
2514 | } | |||
2515 | } else { | |||
2516 | res += nwrite; | |||
2517 | dest += nwrite; | |||
2518 | destlen -= (size_t)nwrite; | |||
2519 | ||||
2520 | if (conn->server && destlen) { | |||
2521 | it = ngtcp2_rtb_head(&conn->in_pktns->rtb); | |||
2522 | if (!ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0))) { | |||
2523 | rtbent = ngtcp2_ksl_it_get(&it); | |||
2524 | if (rtbent->hd.pkt_num != prev_pkt_num && | |||
2525 | (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04)) { | |||
2526 | /* We might have already added padding to Initial, but in | |||
2527 | that case, we should have destlen == 0 and no Handshake | |||
2528 | packet will be written. */ | |||
2529 | wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING0x01; | |||
2530 | } | |||
2531 | } | |||
2532 | } | |||
2533 | } | |||
2534 | } | |||
2535 | ||||
2536 | nwrite = conn_write_handshake_pkt(conn, pi, dest, destlen, | |||
2537 | NGTCP2_PKT_HANDSHAKE, wflags, 0, ts); | |||
2538 | if (nwrite < 0) { | |||
2539 | assert(nwrite != NGTCP2_ERR_NOBUF)((void) (0)); | |||
2540 | return nwrite; | |||
2541 | } | |||
2542 | ||||
2543 | res += nwrite; | |||
2544 | ||||
2545 | if (!conn->server && conn->hs_pktns->crypto.tx.ckm && nwrite) { | |||
2546 | /* We don't need to send further Initial packet if we have | |||
2547 | Handshake key and sent something with it. So discard initial | |||
2548 | state here. */ | |||
2549 | conn_discard_initial_state(conn, ts); | |||
2550 | } | |||
2551 | ||||
2552 | return res; | |||
2553 | } | |||
2554 | ||||
2555 | /* | |||
2556 | * conn_initial_stream_rx_offset returns the initial maximum offset of | |||
2557 | * data for a stream denoted by |stream_id|. | |||
2558 | */ | |||
2559 | static uint64_t conn_initial_stream_rx_offset(ngtcp2_conn *conn, | |||
2560 | int64_t stream_id) { | |||
2561 | int local_stream = conn_local_stream(conn, stream_id); | |||
2562 | ||||
2563 | if (bidi_stream(stream_id)) { | |||
2564 | if (local_stream) { | |||
2565 | return conn->local.transport_params.initial_max_stream_data_bidi_local; | |||
2566 | } | |||
2567 | return conn->local.transport_params.initial_max_stream_data_bidi_remote; | |||
2568 | } | |||
2569 | ||||
2570 | if (local_stream) { | |||
2571 | return 0; | |||
2572 | } | |||
2573 | return conn->local.transport_params.initial_max_stream_data_uni; | |||
2574 | } | |||
2575 | ||||
2576 | /* | |||
2577 | * conn_should_send_max_stream_data returns nonzero if MAX_STREAM_DATA | |||
2578 | * frame should be send for |strm|. | |||
2579 | */ | |||
2580 | static int conn_should_send_max_stream_data(ngtcp2_conn *conn, | |||
2581 | ngtcp2_strm *strm) { | |||
2582 | uint64_t inc = strm->rx.unsent_max_offset - strm->rx.max_offset; | |||
2583 | (void)conn; | |||
2584 | ||||
2585 | return strm->rx.window < 2 * inc; | |||
2586 | } | |||
2587 | ||||
2588 | /* | |||
2589 | * conn_should_send_max_data returns nonzero if MAX_DATA frame should | |||
2590 | * be sent. | |||
2591 | */ | |||
2592 | static int conn_should_send_max_data(ngtcp2_conn *conn) { | |||
2593 | uint64_t inc = conn->rx.unsent_max_offset - conn->rx.max_offset; | |||
2594 | ||||
2595 | return conn->rx.window < 2 * inc; | |||
2596 | } | |||
2597 | ||||
2598 | /* | |||
2599 | * conn_required_num_new_connection_id returns the number of | |||
2600 | * additional connection ID the local endpoint has to provide to the | |||
2601 | * remote endpoint. | |||
2602 | */ | |||
2603 | static size_t conn_required_num_new_connection_id(ngtcp2_conn *conn) { | |||
2604 | uint64_t n; | |||
2605 | size_t len = ngtcp2_ksl_len(&conn->scid.set); | |||
2606 | ||||
2607 | if (len >= NGTCP2_MAX_SCID_POOL_SIZE8) { | |||
2608 | return 0; | |||
2609 | } | |||
2610 | ||||
2611 | assert(conn->remote.transport_params.active_connection_id_limit)((void) (0)); | |||
2612 | ||||
2613 | /* len includes retired CID. We don't provide extra CID if doing so | |||
2614 | exceeds NGTCP2_MAX_SCID_POOL_SIZE. */ | |||
2615 | ||||
2616 | n = conn->remote.transport_params.active_connection_id_limit + | |||
2617 | conn->scid.num_retired; | |||
2618 | ||||
2619 | return (size_t)ngtcp2_min(NGTCP2_MAX_SCID_POOL_SIZE, n)((8) < (n) ? (8) : (n)) - len; | |||
2620 | } | |||
2621 | ||||
2622 | /* | |||
2623 | * conn_enqueue_new_connection_id generates additional connection IDs | |||
2624 | * and prepares to send them to the remote endpoint. | |||
2625 | * | |||
2626 | * This function returns 0 if it succeeds, or one of the following | |||
2627 | * negative error codes: | |||
2628 | * | |||
2629 | * NGTCP2_ERR_NOMEM | |||
2630 | * Out of memory. | |||
2631 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
2632 | * User-defined callback function failed. | |||
2633 | */ | |||
2634 | static int conn_enqueue_new_connection_id(ngtcp2_conn *conn) { | |||
2635 | size_t i, need = conn_required_num_new_connection_id(conn); | |||
2636 | size_t cidlen = conn->oscid.datalen; | |||
2637 | ngtcp2_cid cid; | |||
2638 | uint64_t seq; | |||
2639 | int rv; | |||
2640 | uint8_t token[NGTCP2_STATELESS_RESET_TOKENLEN16]; | |||
2641 | ngtcp2_frame_chain *nfrc; | |||
2642 | ngtcp2_pktns *pktns = &conn->pktns; | |||
2643 | ngtcp2_scid *scid; | |||
2644 | ngtcp2_ksl_it it; | |||
2645 | ||||
2646 | for (i = 0; i < need; ++i) { | |||
2647 | rv = conn_call_get_new_connection_id(conn, &cid, token, cidlen); | |||
2648 | if (rv != 0) { | |||
2649 | return rv; | |||
2650 | } | |||
2651 | ||||
2652 | if (cid.datalen != cidlen) { | |||
2653 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
2654 | } | |||
2655 | ||||
2656 | /* Assert uniqueness */ | |||
2657 | it = ngtcp2_ksl_lower_bound(&conn->scid.set, &cid); | |||
2658 | if (!ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)) && | |||
2659 | ngtcp2_cid_eq(ngtcp2_ksl_it_key(&it)((ngtcp2_ksl_key *)((ngtcp2_ksl_node *)(void *)(((&it)-> blk)->nodes + ((&it)->ksl)->nodelen * ((&it) ->i)))->key), &cid)) { | |||
2660 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
2661 | } | |||
2662 | ||||
2663 | seq = ++conn->scid.last_seq; | |||
2664 | ||||
2665 | scid = ngtcp2_mem_malloc(conn->mem, sizeof(*scid)); | |||
2666 | if (scid == NULL((void*)0)) { | |||
2667 | return NGTCP2_ERR_NOMEM-501; | |||
2668 | } | |||
2669 | ||||
2670 | ngtcp2_scid_init(scid, seq, &cid, token); | |||
2671 | ||||
2672 | rv = ngtcp2_ksl_insert(&conn->scid.set, NULL((void*)0), &scid->cid, scid); | |||
2673 | if (rv != 0) { | |||
2674 | ngtcp2_mem_free(conn->mem, scid); | |||
2675 | return rv; | |||
2676 | } | |||
2677 | ||||
2678 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
2679 | if (rv != 0) { | |||
2680 | return rv; | |||
2681 | } | |||
2682 | ||||
2683 | nfrc->fr.type = NGTCP2_FRAME_NEW_CONNECTION_ID; | |||
2684 | nfrc->fr.new_connection_id.seq = seq; | |||
2685 | nfrc->fr.new_connection_id.retire_prior_to = 0; | |||
2686 | nfrc->fr.new_connection_id.cid = cid; | |||
2687 | memcpy(nfrc->fr.new_connection_id.stateless_reset_token, token, | |||
2688 | sizeof(token)); | |||
2689 | nfrc->next = pktns->tx.frq; | |||
2690 | pktns->tx.frq = nfrc; | |||
2691 | } | |||
2692 | ||||
2693 | return 0; | |||
2694 | } | |||
2695 | ||||
2696 | /* | |||
2697 | * conn_remove_retired_connection_id removes the already retired | |||
2698 | * connection ID. It waits PTO before actually removing a connection | |||
2699 | * ID after it receives RETIRE_CONNECTION_ID from peer to catch | |||
2700 | * reordered packets. | |||
2701 | * | |||
2702 | * This function returns 0 if it succeeds, or one of the following | |||
2703 | * negative error codes: | |||
2704 | * | |||
2705 | * NGTCP2_ERR_NOMEM | |||
2706 | * Out of memory. | |||
2707 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
2708 | * User-defined callback function failed. | |||
2709 | */ | |||
2710 | static int conn_remove_retired_connection_id(ngtcp2_conn *conn, | |||
2711 | ngtcp2_duration pto, | |||
2712 | ngtcp2_tstamp ts) { | |||
2713 | ngtcp2_duration timeout = pto; | |||
2714 | ngtcp2_scid *scid; | |||
2715 | ngtcp2_dcid *dcid; | |||
2716 | int rv; | |||
2717 | ||||
2718 | for (; !ngtcp2_pq_empty(&conn->scid.used);) { | |||
2719 | scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe)((ngtcp2_scid *)(void *)((char *)(ngtcp2_pq_top(&conn-> scid.used))-__builtin_offsetof(ngtcp2_scid, pe))); | |||
2720 | ||||
2721 | if (scid->ts_retired == UINT64_MAX(18446744073709551615UL) || scid->ts_retired + timeout >= ts) { | |||
2722 | break; | |||
2723 | } | |||
2724 | ||||
2725 | assert(scid->flags & NGTCP2_SCID_FLAG_RETIRED)((void) (0)); | |||
2726 | ||||
2727 | rv = conn_call_remove_connection_id(conn, &scid->cid); | |||
2728 | if (rv != 0) { | |||
2729 | return rv; | |||
2730 | } | |||
2731 | ||||
2732 | ngtcp2_ksl_remove(&conn->scid.set, NULL((void*)0), &scid->cid); | |||
2733 | ngtcp2_pq_pop(&conn->scid.used); | |||
2734 | ngtcp2_mem_free(conn->mem, scid); | |||
2735 | ||||
2736 | assert(conn->scid.num_retired)((void) (0)); | |||
2737 | --conn->scid.num_retired; | |||
2738 | } | |||
2739 | ||||
2740 | for (; ngtcp2_ringbuf_len(&conn->dcid.retired)((&conn->dcid.retired)->len);) { | |||
2741 | dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, 0); | |||
2742 | if (dcid->ts_retired + timeout >= ts) { | |||
2743 | break; | |||
2744 | } | |||
2745 | ||||
2746 | rv = conn_call_deactivate_dcid(conn, dcid); | |||
2747 | if (rv != 0) { | |||
2748 | return rv; | |||
2749 | } | |||
2750 | ||||
2751 | ngtcp2_ringbuf_pop_front(&conn->dcid.retired); | |||
2752 | } | |||
2753 | ||||
2754 | return 0; | |||
2755 | } | |||
2756 | ||||
2757 | /* | |||
2758 | * conn_min_short_pktlen returns the minimum length of Short packet | |||
2759 | * this endpoint sends. | |||
2760 | */ | |||
2761 | static size_t conn_min_short_pktlen(ngtcp2_conn *conn) { | |||
2762 | return conn->dcid.current.cid.datalen + NGTCP2_MIN_PKT_EXPANDLEN22; | |||
2763 | } | |||
2764 | ||||
2765 | /* | |||
2766 | * conn_write_pkt writes a protected packet in the buffer pointed by | |||
2767 | * |dest| whose length if |destlen|. |type| specifies the type of | |||
2768 | * packet. It can be NGTCP2_PKT_SHORT or NGTCP2_PKT_0RTT. | |||
2769 | * | |||
2770 | * This function can send new stream data. In order to send stream | |||
2771 | * data, specify the underlying stream and parameters to | |||
2772 | * |vmsg|->stream. If |vmsg|->stream.fin is set to nonzero, it | |||
2773 | * signals that the given data is the final portion of the stream. | |||
2774 | * |vmsg|->stream.data vector of length |vmsg|->stream.datacnt | |||
2775 | * specifies stream data to send. The number of bytes sent to the | |||
2776 | * stream is assigned to *|vmsg|->stream.pdatalen. If 0 length STREAM | |||
2777 | * data is sent, 0 is assigned to it. The caller should initialize | |||
2778 | * *|vmsg|->stream.pdatalen to -1. | |||
2779 | * | |||
2780 | * If |require_padding| is nonzero, padding bytes are added to occupy | |||
2781 | * the remaining packet payload. | |||
2782 | * | |||
2783 | * This function returns the number of bytes written in |dest| if it | |||
2784 | * succeeds, or one of the following negative error codes: | |||
2785 | * | |||
2786 | * NGTCP2_ERR_NOMEM | |||
2787 | * Out of memory. | |||
2788 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
2789 | * User-defined callback function failed. | |||
2790 | * NGTCP2_ERR_STREAM_DATA_BLOCKED | |||
2791 | * Stream data could not be written because of flow control. | |||
2792 | */ | |||
2793 | static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, | |||
2794 | uint8_t *dest, size_t destlen, | |||
2795 | ngtcp2_vmsg *vmsg, uint8_t type, | |||
2796 | uint8_t flags, ngtcp2_tstamp ts) { | |||
2797 | int rv = 0; | |||
2798 | ngtcp2_crypto_cc *cc = &conn->pkt.cc; | |||
2799 | ngtcp2_ppe *ppe = &conn->pkt.ppe; | |||
2800 | ngtcp2_pkt_hd *hd = &conn->pkt.hd; | |||
2801 | ngtcp2_frame *ackfr = NULL((void*)0), lfr; | |||
2802 | ngtcp2_ssize nwrite; | |||
2803 | ngtcp2_frame_chain **pfrc, *nfrc, *frc; | |||
2804 | ngtcp2_rtb_entry *ent; | |||
2805 | ngtcp2_strm *strm; | |||
2806 | int pkt_empty = 1; | |||
2807 | size_t ndatalen = 0; | |||
2808 | int send_stream = 0; | |||
2809 | int stream_blocked = 0; | |||
2810 | int send_datagram = 0; | |||
2811 | ngtcp2_pktns *pktns = &conn->pktns; | |||
2812 | size_t left; | |||
2813 | size_t datalen = 0; | |||
2814 | ngtcp2_vec data[NGTCP2_MAX_STREAM_DATACNT256]; | |||
2815 | size_t datacnt; | |||
2816 | uint8_t rtb_entry_flags = NGTCP2_RTB_ENTRY_FLAG_NONE0x00; | |||
2817 | int hd_logged = 0; | |||
2818 | ngtcp2_path_challenge_entry *pcent; | |||
2819 | uint8_t hd_flags; | |||
2820 | int require_padding = (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING0x01) != 0; | |||
| ||||
2821 | int write_more = (flags & NGTCP2_WRITE_PKT_FLAG_MORE0x02) != 0; | |||
2822 | int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING0x1000) != 0; | |||
2823 | size_t min_pktlen = conn_min_short_pktlen(conn); | |||
2824 | int padded = 0; | |||
2825 | int credit_expanded = 0; | |||
2826 | ngtcp2_cc_pkt cc_pkt; | |||
2827 | uint64_t crypto_offset; | |||
2828 | uint64_t stream_offset; | |||
2829 | ngtcp2_ssize num_reclaimed; | |||
2830 | int fin; | |||
2831 | uint64_t target_max_data; | |||
2832 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
2833 | uint64_t delta; | |||
2834 | ||||
2835 | /* Return 0 if destlen is less than minimum packet length which can | |||
2836 | trigger Stateless Reset */ | |||
2837 | if (destlen < min_pktlen) { | |||
2838 | return 0; | |||
2839 | } | |||
2840 | ||||
2841 | if (vmsg) { | |||
2842 | switch (vmsg->type) { | |||
2843 | case NGTCP2_VMSG_TYPE_STREAM: | |||
2844 | datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt); | |||
2845 | ndatalen = conn_enforce_flow_control(conn, vmsg->stream.strm, datalen); | |||
2846 | /* 0 length STREAM frame is allowed */ | |||
2847 | if (ndatalen || datalen == 0) { | |||
2848 | send_stream = 1; | |||
2849 | } else { | |||
2850 | stream_blocked = 1; | |||
2851 | } | |||
2852 | break; | |||
2853 | case NGTCP2_VMSG_TYPE_DATAGRAM: | |||
2854 | datalen = ngtcp2_vec_len(vmsg->datagram.data, vmsg->datagram.datacnt); | |||
2855 | send_datagram = 1; | |||
2856 | break; | |||
2857 | default: | |||
2858 | break; | |||
2859 | } | |||
2860 | } | |||
2861 | ||||
2862 | if (!ppe_pending
| |||
2863 | switch (type) { | |||
2864 | case NGTCP2_PKT_SHORT: | |||
2865 | hd_flags = | |||
2866 | (pktns->crypto.tx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE0x01) | |||
2867 | ? NGTCP2_PKT_FLAG_KEY_PHASE0x04 | |||
2868 | : NGTCP2_PKT_FLAG_NONE0; | |||
2869 | cc->aead = pktns->crypto.ctx.aead; | |||
2870 | cc->hp = pktns->crypto.ctx.hp; | |||
2871 | cc->ckm = pktns->crypto.tx.ckm; | |||
2872 | cc->hp_ctx = pktns->crypto.tx.hp_ctx; | |||
2873 | ||||
2874 | /* transport parameter is only valid after handshake completion | |||
2875 | which means we don't know how many connection ID that remote | |||
2876 | peer can accept before handshake completion. */ | |||
2877 | if (conn->oscid.datalen && | |||
2878 | (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
2879 | rv = conn_enqueue_new_connection_id(conn); | |||
2880 | if (rv != 0) { | |||
2881 | return rv; | |||
2882 | } | |||
2883 | } | |||
2884 | ||||
2885 | break; | |||
2886 | case NGTCP2_PKT_0RTT: | |||
2887 | assert(!conn->server)((void) (0)); | |||
2888 | if (!conn->early.ckm) { | |||
2889 | return 0; | |||
2890 | } | |||
2891 | hd_flags = NGTCP2_PKT_FLAG_LONG_FORM0x01; | |||
2892 | cc->aead = conn->early.ctx.aead; | |||
2893 | cc->hp = conn->early.ctx.hp; | |||
2894 | cc->ckm = conn->early.ckm; | |||
2895 | cc->hp_ctx = conn->early.hp_ctx; | |||
2896 | break; | |||
2897 | default: | |||
2898 | /* Unreachable */ | |||
2899 | assert(0)((void) (0)); | |||
2900 | } | |||
2901 | ||||
2902 | cc->encrypt = conn->callbacks.encrypt; | |||
2903 | cc->hp_mask = conn->callbacks.hp_mask; | |||
2904 | ||||
2905 | if (conn_should_send_max_data(conn)) { | |||
2906 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
2907 | if (rv != 0) { | |||
2908 | return rv; | |||
2909 | } | |||
2910 | ||||
2911 | if (conn->local.settings.max_window && | |||
2912 | conn->tx.last_max_data_ts != UINT64_MAX(18446744073709551615UL) && | |||
2913 | ts - conn->tx.last_max_data_ts < | |||
2914 | NGTCP2_FLOW_WINDOW_RTT_FACTOR2 * cstat->smoothed_rtt && | |||
2915 | conn->local.settings.max_window > conn->rx.window) { | |||
2916 | target_max_data = NGTCP2_FLOW_WINDOW_SCALING_FACTOR2 * conn->rx.window; | |||
2917 | if (target_max_data > conn->local.settings.max_window) { | |||
2918 | target_max_data = conn->local.settings.max_window; | |||
2919 | } | |||
2920 | ||||
2921 | delta = target_max_data - conn->rx.window; | |||
2922 | if (conn->rx.unsent_max_offset + delta > NGTCP2_MAX_VARINT((1ULL << 62) - 1)) { | |||
2923 | delta = NGTCP2_MAX_VARINT((1ULL << 62) - 1) - conn->rx.unsent_max_offset; | |||
2924 | } | |||
2925 | ||||
2926 | conn->rx.window = target_max_data; | |||
2927 | } else { | |||
2928 | delta = 0; | |||
2929 | } | |||
2930 | ||||
2931 | conn->tx.last_max_data_ts = ts; | |||
2932 | ||||
2933 | nfrc->fr.type = NGTCP2_FRAME_MAX_DATA; | |||
2934 | nfrc->fr.max_data.max_data = conn->rx.unsent_max_offset + delta; | |||
2935 | nfrc->next = pktns->tx.frq; | |||
2936 | pktns->tx.frq = nfrc; | |||
2937 | ||||
2938 | conn->rx.max_offset = conn->rx.unsent_max_offset = | |||
2939 | nfrc->fr.max_data.max_data; | |||
2940 | credit_expanded = 1; | |||
2941 | } | |||
2942 | ||||
2943 | ngtcp2_pkt_hd_init(hd, hd_flags, type, &conn->dcid.current.cid, | |||
2944 | &conn->oscid, pktns->tx.last_pkt_num + 1, | |||
2945 | pktns_select_pkt_numlen(pktns), conn->version, 0); | |||
2946 | ||||
2947 | ngtcp2_ppe_init(ppe, dest, destlen, cc); | |||
2948 | ||||
2949 | rv = ngtcp2_ppe_encode_hd(ppe, hd); | |||
2950 | if (rv != 0) { | |||
2951 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
2952 | return 0; | |||
2953 | } | |||
2954 | ||||
2955 | if (!ngtcp2_ppe_ensure_hp_sample(ppe)) { | |||
2956 | return 0; | |||
2957 | } | |||
2958 | ||||
2959 | if (ngtcp2_ringbuf_len(&conn->rx.path_challenge)((&conn->rx.path_challenge)->len)) { | |||
2960 | pcent = ngtcp2_ringbuf_get(&conn->rx.path_challenge, 0); | |||
2961 | ||||
2962 | /* PATH_RESPONSE is bound to the path that the corresponding | |||
2963 | PATH_CHALLENGE is received. */ | |||
2964 | if (ngtcp2_path_eq(&conn->dcid.current.ps.path, &pcent->ps.path)) { | |||
2965 | lfr.type = NGTCP2_FRAME_PATH_RESPONSE; | |||
2966 | memcpy(lfr.path_response.data, pcent->data, | |||
2967 | sizeof(lfr.path_response.data)); | |||
2968 | ||||
2969 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr); | |||
2970 | if (rv != 0) { | |||
2971 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
2972 | } else { | |||
2973 | ngtcp2_ringbuf_pop_front(&conn->rx.path_challenge); | |||
2974 | ||||
2975 | pkt_empty = 0; | |||
2976 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04; | |||
2977 | require_padding = !conn->server || destlen >= 1200; | |||
2978 | /* We don't retransmit PATH_RESPONSE. */ | |||
2979 | } | |||
2980 | } | |||
2981 | } | |||
2982 | ||||
2983 | rv = conn_create_ack_frame(conn, &ackfr, pktns, type, ts, | |||
2984 | conn_compute_ack_delay(conn), | |||
2985 | conn->local.transport_params.ack_delay_exponent); | |||
2986 | if (rv != 0) { | |||
2987 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
2988 | return rv; | |||
2989 | } | |||
2990 | ||||
2991 | if (ackfr) { | |||
2992 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, ackfr); | |||
2993 | if (rv != 0) { | |||
2994 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
2995 | } else { | |||
2996 | ngtcp2_acktr_commit_ack(&pktns->acktr); | |||
2997 | ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num, | |||
2998 | ackfr->ack.largest_ack); | |||
2999 | pkt_empty = 0; | |||
3000 | } | |||
3001 | } | |||
3002 | ||||
3003 | build_pkt: | |||
3004 | for (pfrc = &pktns->tx.frq; *pfrc;) { | |||
3005 | if ((*pfrc)->binder && | |||
3006 | ((*pfrc)->binder->flags & NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK0x01)) { | |||
3007 | frc = *pfrc; | |||
3008 | *pfrc = (*pfrc)->next; | |||
3009 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
3010 | continue; | |||
3011 | } | |||
3012 | ||||
3013 | switch ((*pfrc)->fr.type) { | |||
3014 | case NGTCP2_FRAME_STOP_SENDING: | |||
3015 | strm = | |||
3016 | ngtcp2_conn_find_stream(conn, (*pfrc)->fr.stop_sending.stream_id); | |||
3017 | if (strm == NULL((void*)0) || (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01)) { | |||
3018 | frc = *pfrc; | |||
3019 | *pfrc = (*pfrc)->next; | |||
3020 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
3021 | continue; | |||
3022 | } | |||
3023 | break; | |||
3024 | case NGTCP2_FRAME_STREAM: | |||
3025 | assert(0)((void) (0)); | |||
3026 | break; | |||
3027 | case NGTCP2_FRAME_MAX_STREAMS_BIDI: | |||
3028 | if ((*pfrc)->fr.max_streams.max_streams < | |||
3029 | conn->remote.bidi.max_streams) { | |||
3030 | frc = *pfrc; | |||
3031 | *pfrc = (*pfrc)->next; | |||
3032 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
3033 | continue; | |||
3034 | } | |||
3035 | break; | |||
3036 | case NGTCP2_FRAME_MAX_STREAMS_UNI: | |||
3037 | if ((*pfrc)->fr.max_streams.max_streams < | |||
3038 | conn->remote.uni.max_streams) { | |||
3039 | frc = *pfrc; | |||
3040 | *pfrc = (*pfrc)->next; | |||
3041 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
3042 | continue; | |||
3043 | } | |||
3044 | break; | |||
3045 | case NGTCP2_FRAME_MAX_STREAM_DATA: | |||
3046 | strm = ngtcp2_conn_find_stream(conn, | |||
3047 | (*pfrc)->fr.max_stream_data.stream_id); | |||
3048 | if (strm == NULL((void*)0) || (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) || | |||
3049 | (*pfrc)->fr.max_stream_data.max_stream_data < strm->rx.max_offset) { | |||
3050 | frc = *pfrc; | |||
3051 | *pfrc = (*pfrc)->next; | |||
3052 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
3053 | continue; | |||
3054 | } | |||
3055 | break; | |||
3056 | case NGTCP2_FRAME_MAX_DATA: | |||
3057 | if ((*pfrc)->fr.max_data.max_data < conn->rx.max_offset) { | |||
3058 | frc = *pfrc; | |||
3059 | *pfrc = (*pfrc)->next; | |||
3060 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
3061 | continue; | |||
3062 | } | |||
3063 | break; | |||
3064 | case NGTCP2_FRAME_RETIRE_CONNECTION_ID: | |||
3065 | ++conn->dcid.num_retire_queued; | |||
3066 | break; | |||
3067 | case NGTCP2_FRAME_CRYPTO: | |||
3068 | assert(0)((void) (0)); | |||
3069 | break; | |||
3070 | } | |||
3071 | ||||
3072 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr); | |||
3073 | if (rv != 0) { | |||
3074 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3075 | break; | |||
3076 | } | |||
3077 | ||||
3078 | pkt_empty = 0; | |||
3079 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3080 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3081 | pfrc = &(*pfrc)->next; | |||
3082 | } | |||
3083 | ||||
3084 | if (rv != NGTCP2_ERR_NOBUF-203) { | |||
3085 | for (; ngtcp2_ksl_len(&pktns->crypto.tx.frq);) { | |||
3086 | left = ngtcp2_ppe_left(ppe); | |||
3087 | ||||
3088 | crypto_offset = conn_cryptofrq_unacked_offset(conn, pktns); | |||
3089 | if (crypto_offset == (size_t)-1) { | |||
3090 | conn_cryptofrq_clear(conn, pktns); | |||
3091 | break; | |||
3092 | } | |||
3093 | ||||
3094 | left = ngtcp2_pkt_crypto_max_datalen(crypto_offset, left, left); | |||
3095 | ||||
3096 | if (left == (size_t)-1) { | |||
3097 | break; | |||
3098 | } | |||
3099 | ||||
3100 | rv = conn_cryptofrq_pop(conn, &nfrc, pktns, left); | |||
3101 | if (rv != 0) { | |||
3102 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3103 | return rv; | |||
3104 | } | |||
3105 | ||||
3106 | if (nfrc == NULL((void*)0)) { | |||
3107 | break; | |||
3108 | } | |||
3109 | ||||
3110 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); | |||
3111 | if (rv != 0) { | |||
3112 | assert(0)((void) (0)); | |||
3113 | } | |||
3114 | ||||
3115 | *pfrc = nfrc; | |||
3116 | pfrc = &(*pfrc)->next; | |||
3117 | ||||
3118 | pkt_empty = 0; | |||
3119 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3120 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3121 | } | |||
3122 | } | |||
3123 | ||||
3124 | /* Write MAX_STREAM_ID after RESET_STREAM so that we can extend stream | |||
3125 | ID space in one packet. */ | |||
3126 | if (rv != NGTCP2_ERR_NOBUF-203 && *pfrc == NULL((void*)0) && | |||
3127 | conn->remote.bidi.unsent_max_streams > conn->remote.bidi.max_streams) { | |||
3128 | rv = conn_call_extend_max_remote_streams_bidi( | |||
3129 | conn, conn->remote.bidi.unsent_max_streams); | |||
3130 | if (rv != 0) { | |||
3131 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3132 | return rv; | |||
3133 | } | |||
3134 | ||||
3135 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
3136 | if (rv != 0) { | |||
3137 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3138 | return rv; | |||
3139 | } | |||
3140 | nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_BIDI; | |||
3141 | nfrc->fr.max_streams.max_streams = conn->remote.bidi.unsent_max_streams; | |||
3142 | *pfrc = nfrc; | |||
3143 | ||||
3144 | conn->remote.bidi.max_streams = conn->remote.bidi.unsent_max_streams; | |||
3145 | ||||
3146 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &(*pfrc)->fr); | |||
3147 | if (rv != 0) { | |||
3148 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3149 | } else { | |||
3150 | pkt_empty = 0; | |||
3151 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3152 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3153 | pfrc = &(*pfrc)->next; | |||
3154 | } | |||
3155 | } | |||
3156 | ||||
3157 | if (rv != NGTCP2_ERR_NOBUF-203 && *pfrc == NULL((void*)0)) { | |||
3158 | if (conn->remote.uni.unsent_max_streams > conn->remote.uni.max_streams) { | |||
3159 | rv = conn_call_extend_max_remote_streams_uni( | |||
3160 | conn, conn->remote.uni.unsent_max_streams); | |||
3161 | if (rv != 0) { | |||
3162 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3163 | return rv; | |||
3164 | } | |||
3165 | ||||
3166 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
3167 | if (rv != 0) { | |||
3168 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3169 | return rv; | |||
3170 | } | |||
3171 | nfrc->fr.type = NGTCP2_FRAME_MAX_STREAMS_UNI; | |||
3172 | nfrc->fr.max_streams.max_streams = conn->remote.uni.unsent_max_streams; | |||
3173 | *pfrc = nfrc; | |||
3174 | ||||
3175 | conn->remote.uni.max_streams = conn->remote.uni.unsent_max_streams; | |||
3176 | ||||
3177 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, | |||
3178 | &(*pfrc)->fr); | |||
3179 | if (rv != 0) { | |||
3180 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3181 | } else { | |||
3182 | pkt_empty = 0; | |||
3183 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3184 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3185 | pfrc = &(*pfrc)->next; | |||
3186 | } | |||
3187 | } | |||
3188 | } | |||
3189 | ||||
3190 | if (rv != NGTCP2_ERR_NOBUF-203) { | |||
3191 | for (; !ngtcp2_pq_empty(&conn->tx.strmq);) { | |||
3192 | strm = ngtcp2_conn_tx_strmq_top(conn); | |||
3193 | ||||
3194 | if (!(strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) && | |||
3195 | conn_should_send_max_stream_data(conn, strm)) { | |||
3196 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
3197 | if (rv != 0) { | |||
3198 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3199 | return rv; | |||
3200 | } | |||
3201 | ||||
3202 | if (conn->local.settings.max_stream_window && | |||
3203 | strm->tx.last_max_stream_data_ts != UINT64_MAX(18446744073709551615UL) && | |||
3204 | ts - strm->tx.last_max_stream_data_ts < | |||
3205 | NGTCP2_FLOW_WINDOW_RTT_FACTOR2 * cstat->smoothed_rtt && | |||
3206 | conn->local.settings.max_stream_window > strm->rx.window) { | |||
3207 | target_max_data = | |||
3208 | NGTCP2_FLOW_WINDOW_SCALING_FACTOR2 * strm->rx.window; | |||
3209 | if (target_max_data > conn->local.settings.max_stream_window) { | |||
3210 | target_max_data = conn->local.settings.max_stream_window; | |||
3211 | } | |||
3212 | ||||
3213 | delta = target_max_data - strm->rx.window; | |||
3214 | if (strm->rx.unsent_max_offset + delta > NGTCP2_MAX_VARINT((1ULL << 62) - 1)) { | |||
3215 | delta = NGTCP2_MAX_VARINT((1ULL << 62) - 1) - strm->rx.unsent_max_offset; | |||
3216 | } | |||
3217 | ||||
3218 | strm->rx.window = target_max_data; | |||
3219 | } else { | |||
3220 | delta = 0; | |||
3221 | } | |||
3222 | ||||
3223 | strm->tx.last_max_stream_data_ts = ts; | |||
3224 | ||||
3225 | nfrc->fr.type = NGTCP2_FRAME_MAX_STREAM_DATA; | |||
3226 | nfrc->fr.max_stream_data.stream_id = strm->stream_id; | |||
3227 | nfrc->fr.max_stream_data.max_stream_data = | |||
3228 | strm->rx.unsent_max_offset + delta; | |||
3229 | ngtcp2_list_insert(nfrc, pfrc)do { (nfrc)->next = *(pfrc); *(pfrc) = (nfrc); } while (0); | |||
3230 | ||||
3231 | rv = | |||
3232 | conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); | |||
3233 | if (rv != 0) { | |||
3234 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3235 | break; | |||
3236 | } | |||
3237 | ||||
3238 | pkt_empty = 0; | |||
3239 | credit_expanded = 1; | |||
3240 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3241 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3242 | pfrc = &(*pfrc)->next; | |||
3243 | strm->rx.max_offset = strm->rx.unsent_max_offset = | |||
3244 | nfrc->fr.max_stream_data.max_stream_data; | |||
3245 | } | |||
3246 | ||||
3247 | if (ngtcp2_strm_streamfrq_empty(strm)) { | |||
3248 | ngtcp2_conn_tx_strmq_pop(conn); | |||
3249 | continue; | |||
3250 | } | |||
3251 | ||||
3252 | stream_offset = ngtcp2_strm_streamfrq_unacked_offset(strm); | |||
3253 | if (stream_offset == (uint64_t)-1) { | |||
3254 | ngtcp2_strm_streamfrq_clear(strm); | |||
3255 | ngtcp2_conn_tx_strmq_pop(conn); | |||
3256 | continue; | |||
3257 | } | |||
3258 | ||||
3259 | left = ngtcp2_ppe_left(ppe); | |||
3260 | ||||
3261 | left = ngtcp2_pkt_stream_max_datalen(strm->stream_id, stream_offset, | |||
3262 | left, left); | |||
3263 | ||||
3264 | if (left == (size_t)-1) { | |||
3265 | break; | |||
3266 | } | |||
3267 | ||||
3268 | rv = ngtcp2_strm_streamfrq_pop(strm, &nfrc, left); | |||
3269 | if (rv != 0) { | |||
3270 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3271 | return rv; | |||
3272 | } | |||
3273 | ||||
3274 | if (nfrc == NULL((void*)0)) { | |||
3275 | /* TODO Why? */ | |||
3276 | break; | |||
3277 | } | |||
3278 | ||||
3279 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); | |||
3280 | if (rv != 0) { | |||
3281 | assert(0)((void) (0)); | |||
3282 | } | |||
3283 | ||||
3284 | *pfrc = nfrc; | |||
3285 | pfrc = &(*pfrc)->next; | |||
3286 | ||||
3287 | pkt_empty = 0; | |||
3288 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3289 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3290 | ||||
3291 | if (ngtcp2_strm_streamfrq_empty(strm)) { | |||
3292 | ngtcp2_conn_tx_strmq_pop(conn); | |||
3293 | continue; | |||
3294 | } | |||
3295 | ||||
3296 | ngtcp2_conn_tx_strmq_pop(conn); | |||
3297 | ++strm->cycle; | |||
3298 | rv = ngtcp2_conn_tx_strmq_push(conn, strm); | |||
3299 | if (rv != 0) { | |||
3300 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3301 | return rv; | |||
3302 | } | |||
3303 | } | |||
3304 | } | |||
3305 | ||||
3306 | /* Add ACK if MAX_DATA or MAX_STREAM_DATA frame is encoded to | |||
3307 | decrease packet count. */ | |||
3308 | if (ackfr == NULL((void*)0) && credit_expanded) { | |||
3309 | rv = conn_create_ack_frame( | |||
3310 | conn, &ackfr, pktns, type, ts, /* ack_delay = */ 0, | |||
3311 | conn->local.transport_params.ack_delay_exponent); | |||
3312 | if (rv != 0) { | |||
3313 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3314 | return rv; | |||
3315 | } | |||
3316 | ||||
3317 | if (ackfr) { | |||
3318 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, ackfr); | |||
3319 | if (rv != 0) { | |||
3320 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3321 | } else { | |||
3322 | ngtcp2_acktr_commit_ack(&pktns->acktr); | |||
3323 | ngtcp2_acktr_add_ack(&pktns->acktr, hd->pkt_num, | |||
3324 | ackfr->ack.largest_ack); | |||
3325 | } | |||
3326 | } | |||
3327 | } | |||
3328 | ||||
3329 | if (rv != NGTCP2_ERR_NOBUF-203 && !send_stream && !send_datagram && | |||
3330 | !(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) && | |||
3331 | pktns->rtb.num_retransmittable && pktns->tx.frq == NULL((void*)0) && | |||
3332 | pktns->rtb.probe_pkt_left) { | |||
3333 | num_reclaimed = ngtcp2_rtb_reclaim_on_pto(&pktns->rtb, conn, pktns, | |||
3334 | pktns->rtb.probe_pkt_left + 1); | |||
3335 | if (num_reclaimed < 0) { | |||
3336 | return rv; | |||
3337 | } | |||
3338 | if (num_reclaimed) { | |||
3339 | goto build_pkt; | |||
3340 | } | |||
3341 | ||||
3342 | /* We had pktns->rtb.num_retransmittable > 0 but the contents of | |||
3343 | those packets have been acknowledged (i.e., retransmission in | |||
3344 | another packet). In this case, we don't have to send any | |||
3345 | probe packet. */ | |||
3346 | if (pktns->rtb.num_retransmittable == 0) { | |||
3347 | pktns->rtb.probe_pkt_left = 0; | |||
3348 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
3349 | } | |||
3350 | } | |||
3351 | } else { | |||
3352 | pfrc = conn->pkt.pfrc; | |||
3353 | rtb_entry_flags |= conn->pkt.rtb_entry_flags; | |||
3354 | pkt_empty = conn->pkt.pkt_empty; | |||
3355 | hd_logged = conn->pkt.hd_logged; | |||
3356 | } | |||
3357 | ||||
3358 | left = ngtcp2_ppe_left(ppe); | |||
3359 | ||||
3360 | if (rv != NGTCP2_ERR_NOBUF-203 && send_stream
| |||
3361 | (ndatalen = ngtcp2_pkt_stream_max_datalen( | |||
3362 | vmsg->stream.strm->stream_id, vmsg->stream.strm->tx.offset, ndatalen, | |||
3363 | left)) != (size_t)-1 && | |||
3364 | (ndatalen || datalen == 0)) { | |||
3365 | datacnt = ngtcp2_vec_copy_at_most( | |||
3366 | data, &ndatalen, NGTCP2_MAX_STREAM_DATACNT256, vmsg->stream.data, | |||
3367 | vmsg->stream.datacnt, ndatalen); | |||
3368 | ||||
3369 | rv = ngtcp2_frame_chain_stream_datacnt_new(&nfrc, datacnt, conn->mem); | |||
3370 | if (rv != 0) { | |||
3371 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3372 | return rv; | |||
3373 | } | |||
3374 | ||||
3375 | nfrc->fr.stream.type = NGTCP2_FRAME_STREAM; | |||
3376 | nfrc->fr.stream.flags = 0; | |||
3377 | nfrc->fr.stream.stream_id = vmsg->stream.strm->stream_id; | |||
3378 | nfrc->fr.stream.offset = vmsg->stream.strm->tx.offset; | |||
3379 | nfrc->fr.stream.datacnt = datacnt; | |||
3380 | ngtcp2_vec_copy(nfrc->fr.stream.data, data, datacnt); | |||
3381 | ||||
3382 | fin = (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_FIN0x02) && | |||
3383 | ndatalen == datalen; | |||
3384 | nfrc->fr.stream.fin = (uint8_t)fin; | |||
3385 | ||||
3386 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &nfrc->fr); | |||
3387 | if (rv != 0) { | |||
3388 | assert(0)((void) (0)); | |||
3389 | } | |||
3390 | ||||
3391 | *pfrc = nfrc; | |||
3392 | pfrc = &(*pfrc)->next; | |||
3393 | ||||
3394 | pkt_empty = 0; | |||
3395 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04 | | |||
3396 | NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE0x02; | |||
3397 | ||||
3398 | vmsg->stream.strm->tx.offset += ndatalen; | |||
3399 | conn->tx.offset += ndatalen; | |||
3400 | ||||
3401 | if (fin) { | |||
3402 | ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR0x02); | |||
3403 | } | |||
3404 | ||||
3405 | if (vmsg->stream.pdatalen) { | |||
3406 | *vmsg->stream.pdatalen = (ngtcp2_ssize)ndatalen; | |||
3407 | } | |||
3408 | } else { | |||
3409 | send_stream = 0; | |||
3410 | } | |||
3411 | ||||
3412 | if (rv != NGTCP2_ERR_NOBUF-203 && send_datagram
| |||
3413 | left >= ngtcp2_pkt_datagram_framelen(datalen)) { | |||
3414 | lfr.datagram.type = NGTCP2_FRAME_DATAGRAM_LEN; | |||
3415 | lfr.datagram.datacnt = vmsg->datagram.datacnt; | |||
3416 | lfr.datagram.data = (ngtcp2_vec *)vmsg->datagram.data; | |||
3417 | ||||
3418 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr); | |||
3419 | assert(rv == 0)((void) (0)); | |||
3420 | ||||
3421 | pkt_empty = 0; | |||
3422 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04; | |||
3423 | ||||
3424 | if (vmsg->datagram.paccepted) { | |||
3425 | *vmsg->datagram.paccepted = 1; | |||
3426 | } | |||
3427 | } else { | |||
3428 | send_datagram = 0; | |||
3429 | } | |||
3430 | ||||
3431 | if (pkt_empty) { | |||
3432 | assert(rv == 0 || NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3433 | if (rv == 0 && stream_blocked && ngtcp2_conn_get_max_data_left(conn)) { | |||
3434 | return NGTCP2_ERR_STREAM_DATA_BLOCKED-210; | |||
3435 | } | |||
3436 | ||||
3437 | if (conn->pktns.rtb.probe_pkt_left == 0) { | |||
3438 | return 0; | |||
3439 | } | |||
3440 | } else if (write_more
| |||
3441 | conn->pkt.pfrc = pfrc; | |||
3442 | conn->pkt.pkt_empty = pkt_empty; | |||
3443 | conn->pkt.rtb_entry_flags = rtb_entry_flags; | |||
3444 | conn->pkt.hd_logged = hd_logged; | |||
3445 | conn->flags |= NGTCP2_CONN_FLAG_PPE_PENDING0x1000; | |||
3446 | ||||
3447 | assert(vmsg)((void) (0)); | |||
3448 | ||||
3449 | switch (vmsg->type) { | |||
| ||||
3450 | case NGTCP2_VMSG_TYPE_STREAM: | |||
3451 | if (send_stream) { | |||
3452 | if (ngtcp2_ppe_left(ppe)) { | |||
3453 | return NGTCP2_ERR_WRITE_MORE-240; | |||
3454 | } | |||
3455 | } else if (ngtcp2_conn_get_max_data_left(conn) && stream_blocked) { | |||
3456 | return NGTCP2_ERR_STREAM_DATA_BLOCKED-210; | |||
3457 | } | |||
3458 | break; | |||
3459 | case NGTCP2_VMSG_TYPE_DATAGRAM: | |||
3460 | if (send_datagram && ngtcp2_ppe_left(ppe)) { | |||
3461 | return NGTCP2_ERR_WRITE_MORE-240; | |||
3462 | } | |||
3463 | /* If DATAGRAM cannot be written due to insufficient space, | |||
3464 | continue to create a packet with the hope that application | |||
3465 | calls ngtcp2_conn_writev_datagram again. */ | |||
3466 | break; | |||
3467 | default: | |||
3468 | assert(0)((void) (0)); | |||
3469 | } | |||
3470 | } | |||
3471 | ||||
3472 | if (!(rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04)) { | |||
3473 | if (pktns->tx.num_non_ack_pkt >= NGTCP2_MAX_NON_ACK_TX_PKT3) { | |||
3474 | lfr.type = NGTCP2_FRAME_PING; | |||
3475 | ||||
3476 | rv = conn_ppe_write_frame_hd_log(conn, ppe, &hd_logged, hd, &lfr); | |||
3477 | if (rv != 0) { | |||
3478 | assert(rv == NGTCP2_ERR_NOBUF)((void) (0)); | |||
3479 | /* TODO If buffer is too small, PING cannot be written if | |||
3480 | packet is still empty. */ | |||
3481 | } else { | |||
3482 | rtb_entry_flags |= NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04; | |||
3483 | pktns->tx.num_non_ack_pkt = 0; | |||
3484 | } | |||
3485 | } else { | |||
3486 | ++pktns->tx.num_non_ack_pkt; | |||
3487 | } | |||
3488 | } else { | |||
3489 | pktns->tx.num_non_ack_pkt = 0; | |||
3490 | } | |||
3491 | ||||
3492 | /* TODO Push STREAM frame back to ngtcp2_strm if there is an error | |||
3493 | before ngtcp2_rtb_entry is safely created and added. */ | |||
3494 | lfr.type = NGTCP2_FRAME_PADDING; | |||
3495 | if ((require_padding || | |||
3496 | /* Making full sized packet will help GSO a bit */ | |||
3497 | ngtcp2_ppe_left(ppe) < 10 || | |||
3498 | (type == NGTCP2_PKT_0RTT && conn->state == NGTCP2_CS_CLIENT_INITIAL)) && | |||
3499 | ngtcp2_ppe_left(ppe)) { | |||
3500 | lfr.padding.len = ngtcp2_ppe_padding(ppe); | |||
3501 | } else { | |||
3502 | lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); | |||
3503 | } | |||
3504 | ||||
3505 | if (lfr.padding.len) { | |||
3506 | padded = 1; | |||
3507 | ngtcp2_log_tx_fr(&conn->log, hd, &lfr); | |||
3508 | ngtcp2_qlog_write_frame(&conn->qlog, &lfr); | |||
3509 | } | |||
3510 | ||||
3511 | nwrite = ngtcp2_ppe_final(ppe, NULL((void*)0)); | |||
3512 | if (nwrite < 0) { | |||
3513 | assert(ngtcp2_err_is_fatal((int)nwrite))((void) (0)); | |||
3514 | return nwrite; | |||
3515 | } | |||
3516 | ||||
3517 | ++cc->ckm->use_count; | |||
3518 | ||||
3519 | ngtcp2_qlog_pkt_sent_end(&conn->qlog, hd, (size_t)nwrite); | |||
3520 | ||||
3521 | /* TODO ack-eliciting vs needs-tracking */ | |||
3522 | /* probe packet needs tracking but it does not need ACK, could be lost. */ | |||
3523 | if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) || padded) { | |||
3524 | if (pi) { | |||
3525 | conn_handle_tx_ecn(conn, pi, &rtb_entry_flags, pktns, hd, ts); | |||
3526 | } | |||
3527 | ||||
3528 | rv = ngtcp2_rtb_entry_new(&ent, hd, NULL((void*)0), ts, (size_t)nwrite, | |||
3529 | rtb_entry_flags, conn->mem); | |||
3530 | if (rv != 0) { | |||
3531 | assert(ngtcp2_err_is_fatal((int)nwrite))((void) (0)); | |||
3532 | return rv; | |||
3533 | } | |||
3534 | ||||
3535 | if (*pfrc != pktns->tx.frq) { | |||
3536 | ent->frc = pktns->tx.frq; | |||
3537 | pktns->tx.frq = *pfrc; | |||
3538 | *pfrc = NULL((void*)0); | |||
3539 | } | |||
3540 | ||||
3541 | if ((rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) && | |||
3542 | pktns->rtb.num_ack_eliciting == 0 && conn->cc.event) { | |||
3543 | conn->cc.event(&conn->cc, &conn->cstat, NGTCP2_CC_EVENT_TYPE_TX_START, | |||
3544 | ts); | |||
3545 | } | |||
3546 | ||||
3547 | rv = conn_on_pkt_sent(conn, &pktns->rtb, ent); | |||
3548 | if (rv != 0) { | |||
3549 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
3550 | ngtcp2_rtb_entry_del(ent, conn->mem); | |||
3551 | return rv; | |||
3552 | } | |||
3553 | ||||
3554 | if (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) { | |||
3555 | if (conn->cc.on_pkt_sent) { | |||
3556 | conn->cc.on_pkt_sent( | |||
3557 | &conn->cc, &conn->cstat, | |||
3558 | ngtcp2_cc_pkt_init(&cc_pkt, hd->pkt_num, (size_t)nwrite, | |||
3559 | NGTCP2_PKTNS_ID_APPLICATION, ts)); | |||
3560 | } | |||
3561 | ||||
3562 | if (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE0x2000) { | |||
3563 | conn_restart_timer_on_write(conn, ts); | |||
3564 | } | |||
3565 | } | |||
3566 | } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { | |||
3567 | conn_handle_tx_ecn(conn, pi, NULL((void*)0), pktns, hd, ts); | |||
3568 | } | |||
3569 | ||||
3570 | conn->flags &= (uint16_t)~NGTCP2_CONN_FLAG_PPE_PENDING0x1000; | |||
3571 | ||||
3572 | if (pktns->rtb.probe_pkt_left && | |||
3573 | (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04)) { | |||
3574 | --pktns->rtb.probe_pkt_left; | |||
3575 | ||||
3576 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "probe pkt size=%td", | |||
3577 | nwrite); | |||
3578 | } | |||
3579 | ||||
3580 | conn->dcid.current.bytes_sent += (uint64_t)nwrite; | |||
3581 | ||||
3582 | ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); | |||
3583 | ||||
3584 | ++pktns->tx.last_pkt_num; | |||
3585 | ||||
3586 | return nwrite; | |||
3587 | } | |||
3588 | ||||
3589 | ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( | |||
3590 | ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, | |||
3591 | uint8_t type, const ngtcp2_cid *dcid, ngtcp2_frame *fr, uint8_t rtb_flags, | |||
3592 | const ngtcp2_path *path, ngtcp2_tstamp ts) { | |||
3593 | int rv; | |||
3594 | ngtcp2_ppe ppe; | |||
3595 | ngtcp2_pkt_hd hd; | |||
3596 | ngtcp2_frame lfr; | |||
3597 | ngtcp2_ssize nwrite; | |||
3598 | ngtcp2_crypto_cc cc; | |||
3599 | ngtcp2_pktns *pktns; | |||
3600 | uint8_t flags; | |||
3601 | ngtcp2_rtb_entry *rtbent; | |||
3602 | int padded = 0; | |||
3603 | ||||
3604 | switch (type) { | |||
3605 | case NGTCP2_PKT_INITIAL: | |||
3606 | pktns = conn->in_pktns; | |||
3607 | flags = NGTCP2_PKT_FLAG_LONG_FORM0x01; | |||
3608 | break; | |||
3609 | case NGTCP2_PKT_HANDSHAKE: | |||
3610 | pktns = conn->hs_pktns; | |||
3611 | flags = NGTCP2_PKT_FLAG_LONG_FORM0x01; | |||
3612 | break; | |||
3613 | case NGTCP2_PKT_SHORT: | |||
3614 | /* 0 means Short packet. */ | |||
3615 | pktns = &conn->pktns; | |||
3616 | flags = (pktns->crypto.tx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE0x01) | |||
3617 | ? NGTCP2_PKT_FLAG_KEY_PHASE0x04 | |||
3618 | : NGTCP2_PKT_FLAG_NONE0; | |||
3619 | break; | |||
3620 | default: | |||
3621 | /* We don't support 0-RTT packet in this function. */ | |||
3622 | assert(0)((void) (0)); | |||
3623 | } | |||
3624 | ||||
3625 | cc.aead = pktns->crypto.ctx.aead; | |||
3626 | cc.hp = pktns->crypto.ctx.hp; | |||
3627 | cc.ckm = pktns->crypto.tx.ckm; | |||
3628 | cc.hp_ctx = pktns->crypto.tx.hp_ctx; | |||
3629 | cc.encrypt = conn->callbacks.encrypt; | |||
3630 | cc.hp_mask = conn->callbacks.hp_mask; | |||
3631 | ||||
3632 | ngtcp2_pkt_hd_init(&hd, flags, type, dcid, &conn->oscid, | |||
3633 | pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), | |||
3634 | conn->version, 0); | |||
3635 | ||||
3636 | ngtcp2_ppe_init(&ppe, dest, destlen, &cc); | |||
3637 | ||||
3638 | rv = ngtcp2_ppe_encode_hd(&ppe, &hd); | |||
3639 | if (rv != 0) { | |||
3640 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3641 | return 0; | |||
3642 | } | |||
3643 | ||||
3644 | if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) { | |||
3645 | return 0; | |||
3646 | } | |||
3647 | ||||
3648 | ngtcp2_log_tx_pkt_hd(&conn->log, &hd); | |||
3649 | ngtcp2_qlog_pkt_sent_start(&conn->qlog); | |||
3650 | ||||
3651 | rv = conn_ppe_write_frame(conn, &ppe, &hd, fr); | |||
3652 | if (rv != 0) { | |||
3653 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
3654 | return 0; | |||
3655 | } | |||
3656 | ||||
3657 | lfr.type = NGTCP2_FRAME_PADDING; | |||
3658 | switch (fr->type) { | |||
3659 | case NGTCP2_FRAME_PATH_CHALLENGE: | |||
3660 | case NGTCP2_FRAME_PATH_RESPONSE: | |||
3661 | if (!conn->server || destlen >= 1200) { | |||
3662 | lfr.padding.len = ngtcp2_ppe_padding(&ppe); | |||
3663 | } else { | |||
3664 | lfr.padding.len = 0; | |||
3665 | } | |||
3666 | break; | |||
3667 | default: | |||
3668 | if (type == NGTCP2_PKT_SHORT) { | |||
3669 | lfr.padding.len = | |||
3670 | ngtcp2_ppe_padding_size(&ppe, conn_min_short_pktlen(conn)); | |||
3671 | } else { | |||
3672 | lfr.padding.len = ngtcp2_ppe_padding_hp_sample(&ppe); | |||
3673 | } | |||
3674 | } | |||
3675 | if (lfr.padding.len) { | |||
3676 | padded = 1; | |||
3677 | ngtcp2_log_tx_fr(&conn->log, &hd, &lfr); | |||
3678 | ngtcp2_qlog_write_frame(&conn->qlog, &lfr); | |||
3679 | } | |||
3680 | ||||
3681 | nwrite = ngtcp2_ppe_final(&ppe, NULL((void*)0)); | |||
3682 | if (nwrite < 0) { | |||
3683 | return nwrite; | |||
3684 | } | |||
3685 | ||||
3686 | if (type == NGTCP2_PKT_SHORT) { | |||
3687 | ++cc.ckm->use_count; | |||
3688 | } | |||
3689 | ||||
3690 | ngtcp2_qlog_pkt_sent_end(&conn->qlog, &hd, (size_t)nwrite); | |||
3691 | ||||
3692 | /* Do this when we are sure that there is no error. */ | |||
3693 | switch (fr->type) { | |||
3694 | case NGTCP2_FRAME_ACK: | |||
3695 | case NGTCP2_FRAME_ACK_ECN: | |||
3696 | ngtcp2_acktr_commit_ack(&pktns->acktr); | |||
3697 | ngtcp2_acktr_add_ack(&pktns->acktr, hd.pkt_num, fr->ack.largest_ack); | |||
3698 | break; | |||
3699 | } | |||
3700 | ||||
3701 | if (((rtb_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) || padded) && | |||
3702 | (!path || ngtcp2_path_eq(&conn->dcid.current.ps.path, path))) { | |||
3703 | if (pi) { | |||
3704 | conn_handle_tx_ecn(conn, pi, &rtb_flags, pktns, &hd, ts); | |||
3705 | } | |||
3706 | ||||
3707 | rv = ngtcp2_rtb_entry_new(&rtbent, &hd, NULL((void*)0), ts, (size_t)nwrite, rtb_flags, | |||
3708 | conn->mem); | |||
3709 | if (rv != 0) { | |||
3710 | return rv; | |||
3711 | } | |||
3712 | ||||
3713 | rv = conn_on_pkt_sent(conn, &pktns->rtb, rtbent); | |||
3714 | if (rv != 0) { | |||
3715 | ngtcp2_rtb_entry_del(rtbent, conn->mem); | |||
3716 | return rv; | |||
3717 | } | |||
3718 | ||||
3719 | if ((rtb_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04) && | |||
3720 | (conn->flags & NGTCP2_CONN_FLAG_RESTART_IDLE_TIMER_ON_WRITE0x2000)) { | |||
3721 | conn_restart_timer_on_write(conn, ts); | |||
3722 | } | |||
3723 | } else if (pi && conn->tx.ecn.state == NGTCP2_ECN_STATE_CAPABLE) { | |||
3724 | conn_handle_tx_ecn(conn, pi, NULL((void*)0), pktns, &hd, ts); | |||
3725 | } | |||
3726 | ||||
3727 | ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); | |||
3728 | ||||
3729 | ++pktns->tx.last_pkt_num; | |||
3730 | ||||
3731 | return nwrite; | |||
3732 | } | |||
3733 | ||||
3734 | /* | |||
3735 | * conn_process_early_rtb makes any pending 0RTT packet Short packet. | |||
3736 | */ | |||
3737 | static void conn_process_early_rtb(ngtcp2_conn *conn) { | |||
3738 | ngtcp2_rtb_entry *ent; | |||
3739 | ngtcp2_rtb *rtb = &conn->pktns.rtb; | |||
3740 | ngtcp2_ksl_it it; | |||
3741 | ||||
3742 | for (it = ngtcp2_rtb_head(rtb); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
3743 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
3744 | ent = ngtcp2_ksl_it_get(&it); | |||
3745 | ||||
3746 | if ((ent->hd.flags & NGTCP2_PKT_FLAG_LONG_FORM0x01) == 0 || | |||
3747 | ent->hd.type != NGTCP2_PKT_0RTT) { | |||
3748 | continue; | |||
3749 | } | |||
3750 | ||||
3751 | /* 0-RTT packet is retransmitted as a Short packet. */ | |||
3752 | ent->hd.flags &= (uint8_t)~NGTCP2_PKT_FLAG_LONG_FORM0x01; | |||
3753 | ent->hd.type = NGTCP2_PKT_SHORT; | |||
3754 | } | |||
3755 | } | |||
3756 | ||||
3757 | /* | |||
3758 | * conn_handshake_remnants_left returns nonzero if there may be | |||
3759 | * handshake packets the local endpoint has to send, including new | |||
3760 | * packets and lost ones. | |||
3761 | */ | |||
3762 | static int conn_handshake_remnants_left(ngtcp2_conn *conn) { | |||
3763 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
3764 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
3765 | ||||
3766 | return !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01) || | |||
3767 | (in_pktns && (in_pktns->rtb.num_retransmittable || | |||
3768 | ngtcp2_ksl_len(&in_pktns->crypto.tx.frq))) || | |||
3769 | (hs_pktns && (hs_pktns->rtb.num_retransmittable || | |||
3770 | ngtcp2_ksl_len(&hs_pktns->crypto.tx.frq))); | |||
3771 | } | |||
3772 | ||||
3773 | /* | |||
3774 | * conn_retire_dcid_seq retires destination connection ID denoted by | |||
3775 | * |seq|. | |||
3776 | * | |||
3777 | * This function returns 0 if it succeeds, or one of the following | |||
3778 | * negative error codes: | |||
3779 | * | |||
3780 | * NGTCP2_ERR_NOMEM | |||
3781 | * Out of memory. | |||
3782 | */ | |||
3783 | static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { | |||
3784 | ngtcp2_pktns *pktns = &conn->pktns; | |||
3785 | ngtcp2_frame_chain *nfrc; | |||
3786 | int rv; | |||
3787 | ||||
3788 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
3789 | if (rv != 0) { | |||
3790 | return rv; | |||
3791 | } | |||
3792 | ||||
3793 | nfrc->fr.type = NGTCP2_FRAME_RETIRE_CONNECTION_ID; | |||
3794 | nfrc->fr.retire_connection_id.seq = seq; | |||
3795 | nfrc->next = pktns->tx.frq; | |||
3796 | pktns->tx.frq = nfrc; | |||
3797 | ||||
3798 | return 0; | |||
3799 | } | |||
3800 | ||||
3801 | /* | |||
3802 | * conn_retire_dcid retires |dcid|. | |||
3803 | * | |||
3804 | * This function returns 0 if it succeeds, or one of the following | |||
3805 | * negative error codes: | |||
3806 | * | |||
3807 | * NGTCP2_ERR_NOMEM | |||
3808 | * Out of memory | |||
3809 | */ | |||
3810 | static int conn_retire_dcid(ngtcp2_conn *conn, const ngtcp2_dcid *dcid, | |||
3811 | ngtcp2_tstamp ts) { | |||
3812 | ngtcp2_ringbuf *rb = &conn->dcid.retired; | |||
3813 | ngtcp2_dcid *dest, *stale_dcid; | |||
3814 | int rv; | |||
3815 | ||||
3816 | assert(dcid->cid.datalen)((void) (0)); | |||
3817 | ||||
3818 | if (ngtcp2_ringbuf_full(rb)) { | |||
3819 | stale_dcid = ngtcp2_ringbuf_get(rb, 0); | |||
3820 | rv = conn_call_deactivate_dcid(conn, stale_dcid); | |||
3821 | if (rv != 0) { | |||
3822 | return rv; | |||
3823 | } | |||
3824 | ||||
3825 | ngtcp2_ringbuf_pop_front(rb); | |||
3826 | } | |||
3827 | ||||
3828 | dest = ngtcp2_ringbuf_push_back(rb); | |||
3829 | ngtcp2_dcid_copy(dest, dcid); | |||
3830 | dest->ts_retired = ts; | |||
3831 | ||||
3832 | return conn_retire_dcid_seq(conn, dcid->seq); | |||
3833 | } | |||
3834 | ||||
3835 | /* | |||
3836 | * conn_bind_dcid stores the DCID to |*pdcid| bound to |path|. If | |||
3837 | * such DCID is not found, bind the new DCID to |path| and stores it | |||
3838 | * to |*pdcid|. If a remote endpoint uses zero-length connection ID, | |||
3839 | * the pointer to conn->dcid.current is assigned to |*pdcid|. | |||
3840 | * | |||
3841 | * This function returns 0 if it succeeds, or one of the following | |||
3842 | * negative error codes: | |||
3843 | * | |||
3844 | * NGTCP2_ERR_CONN_ID_BLOCKED | |||
3845 | * No unused DCID is available | |||
3846 | * NGTCP2_ERR_NOMEM | |||
3847 | * Out of memory | |||
3848 | */ | |||
3849 | static int conn_bind_dcid(ngtcp2_conn *conn, ngtcp2_dcid **pdcid, | |||
3850 | const ngtcp2_path *path, ngtcp2_tstamp ts) { | |||
3851 | ngtcp2_pv *pv = conn->pv; | |||
3852 | ngtcp2_dcid *dcid, *ndcid; | |||
3853 | ngtcp2_cid cid; | |||
3854 | size_t i, len; | |||
3855 | int rv; | |||
3856 | ||||
3857 | assert(!ngtcp2_path_eq(&conn->dcid.current.ps.path, path))((void) (0)); | |||
3858 | assert(!pv || !ngtcp2_path_eq(&pv->dcid.ps.path, path))((void) (0)); | |||
3859 | assert(!pv || !(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE) ||((void) (0)) | |||
3860 | !ngtcp2_path_eq(&pv->fallback_dcid.ps.path, path))((void) (0)); | |||
3861 | ||||
3862 | len = ngtcp2_ringbuf_len(&conn->dcid.bound)((&conn->dcid.bound)->len); | |||
3863 | for (i = 0; i < len; ++i) { | |||
3864 | dcid = ngtcp2_ringbuf_get(&conn->dcid.bound, i); | |||
3865 | ||||
3866 | if (ngtcp2_path_eq(&dcid->ps.path, path)) { | |||
3867 | *pdcid = dcid; | |||
3868 | return 0; | |||
3869 | } | |||
3870 | } | |||
3871 | ||||
3872 | if (conn->dcid.current.cid.datalen == 0) { | |||
3873 | ndcid = ngtcp2_ringbuf_push_back(&conn->dcid.bound); | |||
3874 | ngtcp2_cid_zero(&cid); | |||
3875 | ngtcp2_dcid_init(ndcid, ++conn->dcid.zerolen_seq, &cid, NULL((void*)0)); | |||
3876 | ngtcp2_path_copy(&ndcid->ps.path, path); | |||
3877 | ||||
3878 | *pdcid = ndcid; | |||
3879 | ||||
3880 | return 0; | |||
3881 | } | |||
3882 | ||||
3883 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len) == 0) { | |||
3884 | return NGTCP2_ERR_CONN_ID_BLOCKED-237; | |||
3885 | } | |||
3886 | ||||
3887 | if (ngtcp2_ringbuf_full(&conn->dcid.bound)) { | |||
3888 | dcid = ngtcp2_ringbuf_get(&conn->dcid.bound, 0); | |||
3889 | rv = conn_retire_dcid(conn, dcid, ts); | |||
3890 | if (rv != 0) { | |||
3891 | return rv; | |||
3892 | } | |||
3893 | } | |||
3894 | ||||
3895 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0); | |||
3896 | ndcid = ngtcp2_ringbuf_push_back(&conn->dcid.bound); | |||
3897 | ||||
3898 | ngtcp2_dcid_copy(ndcid, dcid); | |||
3899 | ngtcp2_path_copy(&ndcid->ps.path, path); | |||
3900 | ||||
3901 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
3902 | ||||
3903 | *pdcid = ndcid; | |||
3904 | ||||
3905 | return 0; | |||
3906 | } | |||
3907 | ||||
3908 | /* | |||
3909 | * conn_stop_pv stops the path validation which is currently running. | |||
3910 | * This function does nothing if no path validation is currently being | |||
3911 | * performed. | |||
3912 | * | |||
3913 | * This function returns 0 if it succeeds, or one of the following | |||
3914 | * negative error codes: | |||
3915 | * | |||
3916 | * NGTCP2_ERR_NOMEM | |||
3917 | * Out of memory | |||
3918 | */ | |||
3919 | static int conn_stop_pv(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
3920 | int rv = 0; | |||
3921 | ngtcp2_pv *pv = conn->pv; | |||
3922 | ||||
3923 | if (pv == NULL((void*)0)) { | |||
3924 | return 0; | |||
3925 | } | |||
3926 | ||||
3927 | if (pv->dcid.cid.datalen && pv->dcid.seq != conn->dcid.current.seq) { | |||
3928 | rv = conn_retire_dcid(conn, &pv->dcid, ts); | |||
3929 | if (rv != 0) { | |||
3930 | goto fin; | |||
3931 | } | |||
3932 | } | |||
3933 | ||||
3934 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
3935 | pv->fallback_dcid.cid.datalen && | |||
3936 | pv->fallback_dcid.seq != conn->dcid.current.seq && | |||
3937 | pv->fallback_dcid.seq != pv->dcid.seq) { | |||
3938 | rv = conn_retire_dcid(conn, &pv->fallback_dcid, ts); | |||
3939 | if (rv != 0) { | |||
3940 | goto fin; | |||
3941 | } | |||
3942 | } | |||
3943 | ||||
3944 | fin: | |||
3945 | ngtcp2_pv_del(pv); | |||
3946 | conn->pv = NULL((void*)0); | |||
3947 | ||||
3948 | return rv; | |||
3949 | } | |||
3950 | ||||
3951 | static void conn_reset_congestion_state(ngtcp2_conn *conn); | |||
3952 | ||||
3953 | /* | |||
3954 | * conn_on_path_validation_failed is called when path validation | |||
3955 | * fails. This function may delete |pv|. | |||
3956 | * | |||
3957 | * This function returns 0 if it succeeds, or one of the following | |||
3958 | * negative error codes: | |||
3959 | * | |||
3960 | * NGTCP2_ERR_NOMEM | |||
3961 | * Out of memory | |||
3962 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
3963 | * User-defined callback function failed. | |||
3964 | */ | |||
3965 | static int conn_on_path_validation_failed(ngtcp2_conn *conn, ngtcp2_pv *pv, | |||
3966 | ngtcp2_tstamp ts) { | |||
3967 | int rv; | |||
3968 | ||||
3969 | rv = conn_call_path_validation(conn, &pv->dcid.ps.path, | |||
3970 | NGTCP2_PATH_VALIDATION_RESULT_FAILURE); | |||
3971 | if (rv != 0) { | |||
3972 | return rv; | |||
3973 | } | |||
3974 | ||||
3975 | if (pv->flags & NGTCP2_PV_FLAG_MTU_PROBE0x08) { | |||
3976 | return NGTCP2_ERR_NO_VIABLE_PATH-244; | |||
3977 | } | |||
3978 | ||||
3979 | if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) { | |||
3980 | ngtcp2_dcid_copy(&conn->dcid.current, &pv->fallback_dcid); | |||
3981 | conn_reset_congestion_state(conn); | |||
3982 | } | |||
3983 | ||||
3984 | return conn_stop_pv(conn, ts); | |||
3985 | } | |||
3986 | ||||
3987 | /* | |||
3988 | * dcid_tx_left returns the maximum number of bytes that server is | |||
3989 | * allowed to send to an unvalidated path associated to |dcid|. | |||
3990 | */ | |||
3991 | static size_t dcid_tx_left(ngtcp2_dcid *dcid) { | |||
3992 | if (dcid->flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01) { | |||
3993 | return SIZE_MAX(18446744073709551615UL); | |||
3994 | } | |||
3995 | /* From QUIC spec: Prior to validating the client address, servers | |||
3996 | MUST NOT send more than three times as many bytes as the number | |||
3997 | of bytes they have received. */ | |||
3998 | assert(dcid->bytes_recv * 3 >= dcid->bytes_sent)((void) (0)); | |||
3999 | ||||
4000 | return dcid->bytes_recv * 3 - dcid->bytes_sent; | |||
4001 | } | |||
4002 | ||||
4003 | /* | |||
4004 | * conn_server_tx_left returns the maximum number of bytes that server | |||
4005 | * is allowed to send to an unvalidated path. | |||
4006 | */ | |||
4007 | static size_t conn_server_tx_left(ngtcp2_conn *conn, ngtcp2_dcid *dcid) { | |||
4008 | assert(conn->server)((void) (0)); | |||
4009 | ||||
4010 | /* If pv->dcid has the current path, use conn->dcid.current. This | |||
4011 | is because conn->dcid.current gets update for bytes_recv and | |||
4012 | bytes_sent. */ | |||
4013 | if (ngtcp2_path_eq(&dcid->ps.path, &conn->dcid.current.ps.path)) { | |||
4014 | return dcid_tx_left(&conn->dcid.current); | |||
4015 | } | |||
4016 | ||||
4017 | return dcid_tx_left(dcid); | |||
4018 | } | |||
4019 | ||||
4020 | /* | |||
4021 | * conn_write_path_challenge writes a packet which includes | |||
4022 | * PATH_CHALLENGE frame into |dest| of length |destlen|. | |||
4023 | * | |||
4024 | * This function returns the number of bytes written to |dest|, or one | |||
4025 | * of the following negative error codes: | |||
4026 | * | |||
4027 | * NGTCP2_ERR_NOMEM | |||
4028 | * Out of memory | |||
4029 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4030 | * User-defined callback function failed. | |||
4031 | */ | |||
4032 | static ngtcp2_ssize conn_write_path_challenge(ngtcp2_conn *conn, | |||
4033 | ngtcp2_path *path, | |||
4034 | ngtcp2_pkt_info *pi, | |||
4035 | uint8_t *dest, size_t destlen, | |||
4036 | ngtcp2_tstamp ts) { | |||
4037 | int rv; | |||
4038 | ngtcp2_ssize nwrite; | |||
4039 | ngtcp2_tstamp expiry; | |||
4040 | ngtcp2_pv *pv = conn->pv; | |||
4041 | ngtcp2_frame lfr; | |||
4042 | ngtcp2_duration timeout; | |||
4043 | uint8_t flags; | |||
4044 | size_t tx_left; | |||
4045 | ||||
4046 | if (ngtcp2_pv_validation_timed_out(pv, ts)) { | |||
4047 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV, | |||
4048 | "path validation was timed out"); | |||
4049 | return conn_on_path_validation_failed(conn, pv, ts); | |||
4050 | } | |||
4051 | ||||
4052 | ngtcp2_pv_handle_entry_expiry(pv, ts); | |||
4053 | ||||
4054 | if (!ngtcp2_pv_should_send_probe(pv)) { | |||
4055 | return 0; | |||
4056 | } | |||
4057 | ||||
4058 | assert(conn->callbacks.rand)((void) (0)); | |||
4059 | rv = conn->callbacks.rand( | |||
4060 | lfr.path_challenge.data, sizeof(lfr.path_challenge.data), | |||
4061 | &conn->local.settings.rand_ctx, NGTCP2_RAND_USAGE_PATH_CHALLENGE); | |||
4062 | if (rv != 0) { | |||
4063 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
4064 | } | |||
4065 | ||||
4066 | lfr.type = NGTCP2_FRAME_PATH_CHALLENGE; | |||
4067 | ||||
4068 | timeout = conn_compute_pto(conn, &conn->pktns); | |||
4069 | timeout = ngtcp2_max(timeout, 3 * conn->cstat.initial_rtt)((timeout) > (3 * conn->cstat.initial_rtt) ? (timeout) : (3 * conn->cstat.initial_rtt)); | |||
4070 | expiry = ts + timeout * (1ULL << pv->round); | |||
4071 | ||||
4072 | if (conn->server) { | |||
4073 | if (!(pv->dcid.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01)) { | |||
4074 | tx_left = conn_server_tx_left(conn, &pv->dcid); | |||
4075 | destlen = ngtcp2_min(destlen, tx_left)((destlen) < (tx_left) ? (destlen) : (tx_left)); | |||
4076 | if (destlen == 0) { | |||
4077 | return 0; | |||
4078 | } | |||
4079 | } | |||
4080 | ||||
4081 | if (destlen < 1200) { | |||
4082 | flags = NGTCP2_PV_ENTRY_FLAG_UNDERSIZED0x01; | |||
4083 | } else { | |||
4084 | flags = NGTCP2_PV_ENTRY_FLAG_NONE0x00; | |||
4085 | } | |||
4086 | } else { | |||
4087 | flags = NGTCP2_PV_ENTRY_FLAG_NONE0x00; | |||
4088 | } | |||
4089 | ||||
4090 | ngtcp2_pv_add_entry(pv, lfr.path_challenge.data, expiry, flags, ts); | |||
4091 | ||||
4092 | nwrite = ngtcp2_conn_write_single_frame_pkt( | |||
4093 | conn, pi, dest, destlen, NGTCP2_PKT_SHORT, &pv->dcid.cid, &lfr, | |||
4094 | NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04, &pv->dcid.ps.path, ts); | |||
4095 | if (nwrite <= 0) { | |||
4096 | return nwrite; | |||
4097 | } | |||
4098 | ||||
4099 | if (path) { | |||
4100 | ngtcp2_path_copy(path, &pv->dcid.ps.path); | |||
4101 | } | |||
4102 | ||||
4103 | if (ngtcp2_path_eq(&pv->dcid.ps.path, &conn->dcid.current.ps.path)) { | |||
4104 | conn->dcid.current.bytes_sent += (uint64_t)nwrite; | |||
4105 | } else { | |||
4106 | pv->dcid.bytes_sent += (uint64_t)nwrite; | |||
4107 | } | |||
4108 | ||||
4109 | return nwrite; | |||
4110 | } | |||
4111 | ||||
4112 | /* | |||
4113 | * conn_write_path_response writes a packet which includes | |||
4114 | * PATH_RESPONSE frame into |dest| of length |destlen|. | |||
4115 | * | |||
4116 | * This function returns the number of bytes written to |dest|, or one | |||
4117 | * of the following negative error codes: | |||
4118 | * | |||
4119 | * NGTCP2_ERR_NOMEM | |||
4120 | * Out of memory | |||
4121 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4122 | * User-defined callback function failed. | |||
4123 | */ | |||
4124 | static ngtcp2_ssize conn_write_path_response(ngtcp2_conn *conn, | |||
4125 | ngtcp2_path *path, | |||
4126 | ngtcp2_pkt_info *pi, uint8_t *dest, | |||
4127 | size_t destlen, ngtcp2_tstamp ts) { | |||
4128 | ngtcp2_pv *pv = conn->pv; | |||
4129 | ngtcp2_path_challenge_entry *pcent = NULL((void*)0); | |||
4130 | ngtcp2_dcid *dcid = NULL((void*)0); | |||
4131 | ngtcp2_frame lfr; | |||
4132 | ngtcp2_ssize nwrite; | |||
4133 | int rv; | |||
4134 | size_t tx_left; | |||
4135 | ||||
4136 | for (; ngtcp2_ringbuf_len(&conn->rx.path_challenge)((&conn->rx.path_challenge)->len);) { | |||
4137 | pcent = ngtcp2_ringbuf_get(&conn->rx.path_challenge, 0); | |||
4138 | ||||
4139 | if (ngtcp2_path_eq(&conn->dcid.current.ps.path, &pcent->ps.path)) { | |||
4140 | /* Send PATH_RESPONSE from conn_write_pkt. */ | |||
4141 | return 0; | |||
4142 | } | |||
4143 | ||||
4144 | if (pv) { | |||
4145 | if (ngtcp2_path_eq(&pv->dcid.ps.path, &pcent->ps.path)) { | |||
4146 | dcid = &pv->dcid; | |||
4147 | break; | |||
4148 | } | |||
4149 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
4150 | ngtcp2_path_eq(&pv->fallback_dcid.ps.path, &pcent->ps.path)) { | |||
4151 | dcid = &pv->fallback_dcid; | |||
4152 | break; | |||
4153 | } | |||
4154 | } | |||
4155 | ||||
4156 | if (conn->server) { | |||
4157 | break; | |||
4158 | } | |||
4159 | ||||
4160 | /* Client does not expect to respond to path validation against | |||
4161 | unknown path */ | |||
4162 | ngtcp2_ringbuf_pop_front(&conn->rx.path_challenge); | |||
4163 | pcent = NULL((void*)0); | |||
4164 | } | |||
4165 | ||||
4166 | if (pcent == NULL((void*)0)) { | |||
4167 | return 0; | |||
4168 | } | |||
4169 | ||||
4170 | if (dcid == NULL((void*)0)) { | |||
4171 | /* client is expected to have |path| in conn->dcid.current or | |||
4172 | conn->pv. */ | |||
4173 | assert(conn->server)((void) (0)); | |||
4174 | ||||
4175 | rv = conn_bind_dcid(conn, &dcid, &pcent->ps.path, ts); | |||
4176 | if (rv != 0) { | |||
4177 | if (ngtcp2_err_is_fatal(rv)) { | |||
4178 | return rv; | |||
4179 | } | |||
4180 | return 0; | |||
4181 | } | |||
4182 | } | |||
4183 | ||||
4184 | if (conn->server && !(dcid->flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01)) { | |||
4185 | tx_left = conn_server_tx_left(conn, dcid); | |||
4186 | destlen = ngtcp2_min(destlen, tx_left)((destlen) < (tx_left) ? (destlen) : (tx_left)); | |||
4187 | if (destlen == 0) { | |||
4188 | return 0; | |||
4189 | } | |||
4190 | } | |||
4191 | ||||
4192 | lfr.type = NGTCP2_FRAME_PATH_RESPONSE; | |||
4193 | memcpy(lfr.path_response.data, pcent->data, sizeof(lfr.path_response.data)); | |||
4194 | ||||
4195 | nwrite = ngtcp2_conn_write_single_frame_pkt( | |||
4196 | conn, pi, dest, destlen, NGTCP2_PKT_SHORT, &dcid->cid, &lfr, | |||
4197 | NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING0x04, &pcent->ps.path, ts); | |||
4198 | if (nwrite <= 0) { | |||
4199 | return nwrite; | |||
4200 | } | |||
4201 | ||||
4202 | if (path) { | |||
4203 | ngtcp2_path_copy(path, &pcent->ps.path); | |||
4204 | } | |||
4205 | ||||
4206 | ngtcp2_ringbuf_pop_front(&conn->rx.path_challenge); | |||
4207 | ||||
4208 | dcid->bytes_sent += (uint64_t)nwrite; | |||
4209 | ||||
4210 | return nwrite; | |||
4211 | } | |||
4212 | ||||
4213 | ngtcp2_ssize ngtcp2_conn_write_pkt(ngtcp2_conn *conn, ngtcp2_path *path, | |||
4214 | ngtcp2_pkt_info *pi, uint8_t *dest, | |||
4215 | size_t destlen, ngtcp2_tstamp ts) { | |||
4216 | return ngtcp2_conn_writev_stream(conn, path, pi, dest, destlen, | |||
4217 | /* pdatalen = */ NULL((void*)0), | |||
4218 | NGTCP2_WRITE_STREAM_FLAG_NONE0x00, | |||
4219 | /* stream_id = */ -1, | |||
4220 | /* datav = */ NULL((void*)0), /* datavcnt = */ 0, ts); | |||
4221 | } | |||
4222 | ||||
4223 | /* | |||
4224 | * conn_on_version_negotiation is called when Version Negotiation | |||
4225 | * packet is received. The function decodes the data in the buffer | |||
4226 | * pointed by |payload| whose length is |payloadlen| as Version | |||
4227 | * Negotiation packet payload. The packet header is given in |hd|. | |||
4228 | * | |||
4229 | * This function returns 0 if it succeeds, or one of the following | |||
4230 | * negative error codes: | |||
4231 | * | |||
4232 | * NGTCP2_ERR_NOMEM | |||
4233 | * Out of memory. | |||
4234 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4235 | * User-defined callback function failed. | |||
4236 | * NGTCP2_ERR_INVALID_ARGUMENT | |||
4237 | * Packet payload is badly formatted. | |||
4238 | */ | |||
4239 | static int conn_on_version_negotiation(ngtcp2_conn *conn, | |||
4240 | const ngtcp2_pkt_hd *hd, | |||
4241 | const uint8_t *payload, | |||
4242 | size_t payloadlen) { | |||
4243 | uint32_t sv[16]; | |||
4244 | uint32_t *p; | |||
4245 | int rv = 0; | |||
4246 | size_t nsv; | |||
4247 | size_t i; | |||
4248 | ||||
4249 | if (payloadlen % sizeof(uint32_t)) { | |||
4250 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
4251 | } | |||
4252 | ||||
4253 | if (payloadlen > sizeof(sv)) { | |||
4254 | p = ngtcp2_mem_malloc(conn->mem, payloadlen); | |||
4255 | if (p == NULL((void*)0)) { | |||
4256 | return NGTCP2_ERR_NOMEM-501; | |||
4257 | } | |||
4258 | } else { | |||
4259 | p = sv; | |||
4260 | } | |||
4261 | ||||
4262 | nsv = ngtcp2_pkt_decode_version_negotiation(p, payload, payloadlen); | |||
4263 | ||||
4264 | ngtcp2_log_rx_vn(&conn->log, hd, p, nsv); | |||
4265 | ||||
4266 | for (i = 0; i < nsv; ++i) { | |||
4267 | if (p[i] == conn->version) { | |||
4268 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
4269 | "ignore Version Negotiation because it contains version " | |||
4270 | "selected by client"); | |||
4271 | ||||
4272 | rv = NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
4273 | goto fin; | |||
4274 | } | |||
4275 | } | |||
4276 | ||||
4277 | if (conn->callbacks.recv_version_negotiation) { | |||
4278 | rv = conn->callbacks.recv_version_negotiation(conn, hd, p, nsv, | |||
4279 | conn->user_data); | |||
4280 | if (rv != 0) { | |||
4281 | rv = NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
4282 | } | |||
4283 | } | |||
4284 | ||||
4285 | if (rv == 0) { | |||
4286 | /* TODO Just move to the terminal state for now in order not to | |||
4287 | send CONNECTION_CLOSE frame. */ | |||
4288 | conn->state = NGTCP2_CS_DRAINING; | |||
4289 | } | |||
4290 | ||||
4291 | fin: | |||
4292 | if (p != sv) { | |||
4293 | ngtcp2_mem_free(conn->mem, p); | |||
4294 | } | |||
4295 | ||||
4296 | return rv; | |||
4297 | } | |||
4298 | ||||
4299 | static uint64_t conn_tx_strmq_first_cycle(ngtcp2_conn *conn) { | |||
4300 | ngtcp2_strm *strm; | |||
4301 | ||||
4302 | if (ngtcp2_pq_empty(&conn->tx.strmq)) { | |||
4303 | return 0; | |||
4304 | } | |||
4305 | ||||
4306 | strm = ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe)((ngtcp2_strm *)(void *)((char *)(ngtcp2_pq_top(&conn-> tx.strmq))-__builtin_offsetof(ngtcp2_strm, pe))); | |||
4307 | return strm->cycle; | |||
4308 | } | |||
4309 | ||||
4310 | uint64_t ngtcp2_conn_tx_strmq_first_cycle(ngtcp2_conn *conn) { | |||
4311 | ngtcp2_strm *strm; | |||
4312 | ||||
4313 | if (ngtcp2_pq_empty(&conn->tx.strmq)) { | |||
4314 | return 0; | |||
4315 | } | |||
4316 | ||||
4317 | strm = ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe)((ngtcp2_strm *)(void *)((char *)(ngtcp2_pq_top(&conn-> tx.strmq))-__builtin_offsetof(ngtcp2_strm, pe))); | |||
4318 | return strm->cycle; | |||
4319 | } | |||
4320 | ||||
4321 | int ngtcp2_conn_resched_frames(ngtcp2_conn *conn, ngtcp2_pktns *pktns, | |||
4322 | ngtcp2_frame_chain **pfrc) { | |||
4323 | ngtcp2_frame_chain **first = pfrc; | |||
4324 | ngtcp2_frame_chain *frc; | |||
4325 | ngtcp2_stream *sfr; | |||
4326 | ngtcp2_strm *strm; | |||
4327 | int rv; | |||
4328 | ||||
4329 | if (*pfrc == NULL((void*)0)) { | |||
4330 | return 0; | |||
4331 | } | |||
4332 | ||||
4333 | for (; *pfrc;) { | |||
4334 | switch ((*pfrc)->fr.type) { | |||
4335 | case NGTCP2_FRAME_STREAM: | |||
4336 | frc = *pfrc; | |||
4337 | ||||
4338 | *pfrc = frc->next; | |||
4339 | frc->next = NULL((void*)0); | |||
4340 | sfr = &frc->fr.stream; | |||
4341 | ||||
4342 | strm = ngtcp2_conn_find_stream(conn, sfr->stream_id); | |||
4343 | if (!strm) { | |||
4344 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
4345 | break; | |||
4346 | } | |||
4347 | rv = ngtcp2_strm_streamfrq_push(strm, frc); | |||
4348 | if (rv != 0) { | |||
4349 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
4350 | return rv; | |||
4351 | } | |||
4352 | if (!ngtcp2_strm_is_tx_queued(strm)) { | |||
4353 | strm->cycle = conn_tx_strmq_first_cycle(conn); | |||
4354 | rv = ngtcp2_conn_tx_strmq_push(conn, strm); | |||
4355 | if (rv != 0) { | |||
4356 | return rv; | |||
4357 | } | |||
4358 | } | |||
4359 | break; | |||
4360 | case NGTCP2_FRAME_CRYPTO: | |||
4361 | frc = *pfrc; | |||
4362 | ||||
4363 | *pfrc = frc->next; | |||
4364 | frc->next = NULL((void*)0); | |||
4365 | ||||
4366 | rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL((void*)0), | |||
4367 | &frc->fr.crypto.offset, frc); | |||
4368 | if (rv != 0) { | |||
4369 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
4370 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
4371 | return rv; | |||
4372 | } | |||
4373 | break; | |||
4374 | default: | |||
4375 | pfrc = &(*pfrc)->next; | |||
4376 | } | |||
4377 | } | |||
4378 | ||||
4379 | *pfrc = pktns->tx.frq; | |||
4380 | pktns->tx.frq = *first; | |||
4381 | ||||
4382 | return 0; | |||
4383 | } | |||
4384 | ||||
4385 | /* | |||
4386 | * conn_on_retry is called when Retry packet is received. The | |||
4387 | * function decodes the data in the buffer pointed by |pkt| whose | |||
4388 | * length is |pktlen| as Retry packet. The length of long packet | |||
4389 | * header is given in |hdpktlen|. |pkt| includes packet header. | |||
4390 | * | |||
4391 | * This function returns 0 if it succeeds, or one of the following | |||
4392 | * negative error codes: | |||
4393 | * | |||
4394 | * NGTCP2_ERR_NOMEM | |||
4395 | * Out of memory. | |||
4396 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4397 | * User-defined callback function failed. | |||
4398 | * NGTCP2_ERR_INVALID_ARGUMENT | |||
4399 | * Packet payload is badly formatted. | |||
4400 | * NGTCP2_ERR_PROTO | |||
4401 | * ODCID does not match; or Token is empty. | |||
4402 | */ | |||
4403 | static int conn_on_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd, | |||
4404 | size_t hdpktlen, const uint8_t *pkt, size_t pktlen) { | |||
4405 | int rv; | |||
4406 | ngtcp2_pkt_retry retry; | |||
4407 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
4408 | ngtcp2_rtb *rtb = &conn->pktns.rtb; | |||
4409 | ngtcp2_rtb *in_rtb; | |||
4410 | uint8_t cidbuf[sizeof(retry.odcid.data) * 2 + 1]; | |||
4411 | ngtcp2_vec *token; | |||
4412 | ||||
4413 | if (!in_pktns || conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY0x10) { | |||
4414 | return 0; | |||
4415 | } | |||
4416 | ||||
4417 | in_rtb = &in_pktns->rtb; | |||
4418 | ||||
4419 | rv = ngtcp2_pkt_decode_retry(&retry, pkt + hdpktlen, pktlen - hdpktlen); | |||
4420 | if (rv != 0) { | |||
4421 | return rv; | |||
4422 | } | |||
4423 | ||||
4424 | retry.odcid = conn->dcid.current.cid; | |||
4425 | ||||
4426 | rv = ngtcp2_pkt_verify_retry_tag( | |||
4427 | conn->version, &retry, pkt, pktlen, conn->callbacks.encrypt, | |||
4428 | &conn->crypto.retry_aead, &conn->crypto.retry_aead_ctx); | |||
4429 | if (rv != 0) { | |||
4430 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
4431 | "unable to verify Retry packet integrity"); | |||
4432 | return rv; | |||
4433 | } | |||
4434 | ||||
4435 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "odcid=0x%s", | |||
4436 | (const char *)ngtcp2_encode_hex(cidbuf, retry.odcid.data, | |||
4437 | retry.odcid.datalen)); | |||
4438 | ||||
4439 | if (retry.token.len == 0) { | |||
4440 | return NGTCP2_ERR_PROTO-205; | |||
4441 | } | |||
4442 | ||||
4443 | if (ngtcp2_cid_eq(&conn->dcid.current.cid, &hd->scid)) { | |||
4444 | return 0; | |||
4445 | } | |||
4446 | ||||
4447 | ngtcp2_qlog_retry_pkt_received(&conn->qlog, hd); | |||
4448 | ||||
4449 | /* DCID must be updated before invoking callback because client | |||
4450 | generates new initial keys there. */ | |||
4451 | conn->dcid.current.cid = hd->scid; | |||
4452 | conn->retry_scid = hd->scid; | |||
4453 | ||||
4454 | conn->flags |= NGTCP2_CONN_FLAG_RECV_RETRY0x10; | |||
4455 | ||||
4456 | assert(conn->callbacks.recv_retry)((void) (0)); | |||
4457 | ||||
4458 | rv = conn->callbacks.recv_retry(conn, hd, conn->user_data); | |||
4459 | if (rv != 0) { | |||
4460 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
4461 | } | |||
4462 | ||||
4463 | conn->state = NGTCP2_CS_CLIENT_INITIAL; | |||
4464 | ||||
4465 | /* Just freeing memory is dangerous because we might free twice. */ | |||
4466 | ||||
4467 | rv = ngtcp2_rtb_remove_all(rtb, conn, &conn->pktns, &conn->cstat); | |||
4468 | if (rv != 0) { | |||
4469 | return rv; | |||
4470 | } | |||
4471 | ||||
4472 | rv = ngtcp2_rtb_remove_all(in_rtb, conn, in_pktns, &conn->cstat); | |||
4473 | if (rv != 0) { | |||
4474 | return rv; | |||
4475 | } | |||
4476 | ||||
4477 | token = &conn->local.settings.token; | |||
4478 | ||||
4479 | ngtcp2_mem_free(conn->mem, token->base); | |||
4480 | token->base = NULL((void*)0); | |||
4481 | token->len = 0; | |||
4482 | ||||
4483 | token->base = ngtcp2_mem_malloc(conn->mem, retry.token.len); | |||
4484 | if (token->base == NULL((void*)0)) { | |||
4485 | return NGTCP2_ERR_NOMEM-501; | |||
4486 | } | |||
4487 | token->len = retry.token.len; | |||
4488 | ||||
4489 | ngtcp2_cpymem(token->base, retry.token.base, retry.token.len); | |||
4490 | ||||
4491 | reset_conn_stat_recovery(&conn->cstat); | |||
4492 | conn_reset_congestion_state(conn); | |||
4493 | conn_reset_ecn_validation_state(conn); | |||
4494 | ||||
4495 | return 0; | |||
4496 | } | |||
4497 | ||||
4498 | int ngtcp2_conn_detect_lost_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns, | |||
4499 | ngtcp2_conn_stat *cstat, ngtcp2_tstamp ts) { | |||
4500 | ngtcp2_duration pto = conn_compute_pto(conn, pktns); | |||
4501 | int rv = ngtcp2_rtb_detect_lost_pkt(&pktns->rtb, conn, pktns, cstat, pto, ts); | |||
4502 | if (rv != 0) { | |||
4503 | return rv; | |||
4504 | } | |||
4505 | ||||
4506 | return 0; | |||
4507 | } | |||
4508 | ||||
4509 | /* | |||
4510 | * conn_recv_ack processes received ACK frame |fr|. |pkt_ts| is the | |||
4511 | * timestamp when packet is received. |ts| should be the current | |||
4512 | * time. Usually they are the same, but for buffered packets, | |||
4513 | * |pkt_ts| would be earlier than |ts|. | |||
4514 | * | |||
4515 | * This function returns 0 if it succeeds, or one of the following | |||
4516 | * negative error codes: | |||
4517 | * | |||
4518 | * NGTCP2_ERR_NOMEM | |||
4519 | * Out of memory | |||
4520 | * NGTCP2_ERR_ACK_FRAME | |||
4521 | * ACK frame is malformed. | |||
4522 | * NGTCP2_ERR_PROTO | |||
4523 | * |fr| acknowledges a packet this endpoint has not sent. | |||
4524 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4525 | * User callback failed. | |||
4526 | */ | |||
4527 | static int conn_recv_ack(ngtcp2_conn *conn, ngtcp2_pktns *pktns, ngtcp2_ack *fr, | |||
4528 | ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) { | |||
4529 | int rv; | |||
4530 | ngtcp2_frame_chain *frc = NULL((void*)0); | |||
4531 | ngtcp2_ssize num_acked; | |||
4532 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
4533 | ||||
4534 | if (pktns->tx.last_pkt_num < fr->largest_ack) { | |||
4535 | return NGTCP2_ERR_PROTO-205; | |||
4536 | } | |||
4537 | ||||
4538 | rv = ngtcp2_pkt_validate_ack(fr); | |||
4539 | if (rv != 0) { | |||
4540 | return rv; | |||
4541 | } | |||
4542 | ||||
4543 | ngtcp2_acktr_recv_ack(&pktns->acktr, fr); | |||
4544 | ||||
4545 | num_acked = ngtcp2_rtb_recv_ack(&pktns->rtb, fr, &conn->cstat, conn, pktns, | |||
4546 | pkt_ts, ts); | |||
4547 | if (num_acked < 0) { | |||
4548 | /* TODO assert this */ | |||
4549 | assert(ngtcp2_err_is_fatal((int)num_acked))((void) (0)); | |||
4550 | ngtcp2_frame_chain_list_del(frc, conn->mem); | |||
4551 | return (int)num_acked; | |||
4552 | } | |||
4553 | ||||
4554 | if (num_acked == 0) { | |||
4555 | return 0; | |||
4556 | } | |||
4557 | ||||
4558 | rv = ngtcp2_conn_detect_lost_pkt(conn, pktns, &conn->cstat, ts); | |||
4559 | if (rv != 0) { | |||
4560 | return rv; | |||
4561 | } | |||
4562 | ||||
4563 | pktns->rtb.probe_pkt_left = 0; | |||
4564 | ||||
4565 | if (cstat->pto_count && | |||
4566 | (conn->server || (conn->flags & NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000))) { | |||
4567 | /* Reset PTO count but no less than 2 to avoid frequent probe | |||
4568 | packet transmission. */ | |||
4569 | cstat->pto_count = ngtcp2_min(cstat->pto_count, 2)((cstat->pto_count) < (2) ? (cstat->pto_count) : (2) ); | |||
4570 | } | |||
4571 | ||||
4572 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
4573 | ||||
4574 | return 0; | |||
4575 | } | |||
4576 | ||||
4577 | /* | |||
4578 | * conn_assign_recved_ack_delay_unscaled assigns | |||
4579 | * fr->ack_delay_unscaled. | |||
4580 | */ | |||
4581 | static void assign_recved_ack_delay_unscaled(ngtcp2_ack *fr, | |||
4582 | uint64_t ack_delay_exponent) { | |||
4583 | fr->ack_delay_unscaled = | |||
4584 | fr->ack_delay * (1ULL << ack_delay_exponent) * NGTCP2_MICROSECONDS((uint64_t)1000ULL); | |||
4585 | } | |||
4586 | ||||
4587 | /* | |||
4588 | * conn_recv_max_stream_data processes received MAX_STREAM_DATA frame | |||
4589 | * |fr|. | |||
4590 | * | |||
4591 | * This function returns 0 if it succeeds, or one of the following | |||
4592 | * negative error codes: | |||
4593 | * | |||
4594 | * NGTCP2_ERR_STREAM_STATE | |||
4595 | * Stream ID indicates that it is a local stream, and the local | |||
4596 | * endpoint has not initiated it; or stream is peer initiated | |||
4597 | * unidirectional stream. | |||
4598 | * NGTCP2_ERR_STREAM_LIMIT | |||
4599 | * Stream ID exceeds allowed limit. | |||
4600 | * NGTCP2_ERR_NOMEM | |||
4601 | * Out of memory. | |||
4602 | */ | |||
4603 | static int conn_recv_max_stream_data(ngtcp2_conn *conn, | |||
4604 | const ngtcp2_max_stream_data *fr) { | |||
4605 | ngtcp2_strm *strm; | |||
4606 | ngtcp2_idtr *idtr; | |||
4607 | int local_stream = conn_local_stream(conn, fr->stream_id); | |||
4608 | int bidi = bidi_stream(fr->stream_id); | |||
4609 | int rv; | |||
4610 | ||||
4611 | if (bidi) { | |||
4612 | if (local_stream) { | |||
4613 | if (conn->local.bidi.next_stream_id <= fr->stream_id) { | |||
4614 | return NGTCP2_ERR_STREAM_STATE-226; | |||
4615 | } | |||
4616 | } else if (conn->remote.bidi.max_streams < | |||
4617 | ngtcp2_ord_stream_id(fr->stream_id)) { | |||
4618 | return NGTCP2_ERR_STREAM_LIMIT-213; | |||
4619 | } | |||
4620 | ||||
4621 | idtr = &conn->remote.bidi.idtr; | |||
4622 | } else { | |||
4623 | if (!local_stream || conn->local.uni.next_stream_id <= fr->stream_id) { | |||
4624 | return NGTCP2_ERR_STREAM_STATE-226; | |||
4625 | } | |||
4626 | ||||
4627 | idtr = &conn->remote.uni.idtr; | |||
4628 | } | |||
4629 | ||||
4630 | strm = ngtcp2_conn_find_stream(conn, fr->stream_id); | |||
4631 | if (strm == NULL((void*)0)) { | |||
4632 | if (local_stream) { | |||
4633 | /* Stream has been closed. */ | |||
4634 | return 0; | |||
4635 | } | |||
4636 | ||||
4637 | rv = ngtcp2_idtr_open(idtr, fr->stream_id); | |||
4638 | if (rv != 0) { | |||
4639 | if (ngtcp2_err_is_fatal(rv)) { | |||
4640 | return rv; | |||
4641 | } | |||
4642 | assert(rv == NGTCP2_ERR_STREAM_IN_USE)((void) (0)); | |||
4643 | /* Stream has been closed. */ | |||
4644 | return 0; | |||
4645 | } | |||
4646 | ||||
4647 | strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm)); | |||
4648 | if (strm == NULL((void*)0)) { | |||
4649 | return NGTCP2_ERR_NOMEM-501; | |||
4650 | } | |||
4651 | rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL((void*)0)); | |||
4652 | if (rv != 0) { | |||
4653 | ngtcp2_mem_free(conn->mem, strm); | |||
4654 | return rv; | |||
4655 | } | |||
4656 | } | |||
4657 | ||||
4658 | if (strm->tx.max_offset < fr->max_stream_data) { | |||
4659 | strm->tx.max_offset = fr->max_stream_data; | |||
4660 | ||||
4661 | /* Don't call callback if stream is half-closed local */ | |||
4662 | if (strm->flags & NGTCP2_STRM_FLAG_SHUT_WR0x02) { | |||
4663 | return 0; | |||
4664 | } | |||
4665 | ||||
4666 | rv = conn_call_extend_max_stream_data(conn, strm, fr->stream_id, | |||
4667 | fr->max_stream_data); | |||
4668 | if (rv != 0) { | |||
4669 | return rv; | |||
4670 | } | |||
4671 | } | |||
4672 | ||||
4673 | return 0; | |||
4674 | } | |||
4675 | ||||
4676 | /* | |||
4677 | * conn_recv_max_data processes received MAX_DATA frame |fr|. | |||
4678 | */ | |||
4679 | static void conn_recv_max_data(ngtcp2_conn *conn, const ngtcp2_max_data *fr) { | |||
4680 | conn->tx.max_offset = ngtcp2_max(conn->tx.max_offset, fr->max_data)((conn->tx.max_offset) > (fr->max_data) ? (conn-> tx.max_offset) : (fr->max_data)); | |||
4681 | } | |||
4682 | ||||
4683 | /* | |||
4684 | * conn_buffer_pkt buffers |pkt| of length |pktlen|, chaining it from | |||
4685 | * |*ppc|. | |||
4686 | * | |||
4687 | * This function returns 0 if it succeeds, or one of the following | |||
4688 | * negative error codes: | |||
4689 | * | |||
4690 | * NGTCP2_ERR_NOMEM | |||
4691 | * Out of memory. | |||
4692 | */ | |||
4693 | static int conn_buffer_pkt(ngtcp2_conn *conn, ngtcp2_pktns *pktns, | |||
4694 | const ngtcp2_path *path, const ngtcp2_pkt_info *pi, | |||
4695 | const uint8_t *pkt, size_t pktlen, size_t dgramlen, | |||
4696 | ngtcp2_tstamp ts) { | |||
4697 | int rv; | |||
4698 | ngtcp2_pkt_chain **ppc = &pktns->rx.buffed_pkts, *pc; | |||
4699 | size_t i; | |||
4700 | for (i = 0; *ppc && i < NGTCP2_MAX_NUM_BUFFED_RX_PKTS4; | |||
4701 | ppc = &(*ppc)->next, ++i) | |||
4702 | ; | |||
4703 | ||||
4704 | if (i == NGTCP2_MAX_NUM_BUFFED_RX_PKTS4) { | |||
4705 | return 0; | |||
4706 | } | |||
4707 | ||||
4708 | rv = | |||
4709 | ngtcp2_pkt_chain_new(&pc, path, pi, pkt, pktlen, dgramlen, ts, conn->mem); | |||
4710 | if (rv != 0) { | |||
4711 | return rv; | |||
4712 | } | |||
4713 | ||||
4714 | *ppc = pc; | |||
4715 | ||||
4716 | return 0; | |||
4717 | } | |||
4718 | ||||
4719 | static int ensure_decrypt_buffer(ngtcp2_vec *vec, size_t n, size_t initial, | |||
4720 | const ngtcp2_mem *mem) { | |||
4721 | uint8_t *nbuf; | |||
4722 | size_t len; | |||
4723 | ||||
4724 | if (vec->len >= n) { | |||
4725 | return 0; | |||
4726 | } | |||
4727 | ||||
4728 | len = vec->len == 0 ? initial : vec->len * 2; | |||
4729 | for (; len < n; len *= 2) | |||
4730 | ; | |||
4731 | nbuf = ngtcp2_mem_realloc(mem, vec->base, len); | |||
4732 | if (nbuf == NULL((void*)0)) { | |||
4733 | return NGTCP2_ERR_NOMEM-501; | |||
4734 | } | |||
4735 | vec->base = nbuf; | |||
4736 | vec->len = len; | |||
4737 | ||||
4738 | return 0; | |||
4739 | } | |||
4740 | ||||
4741 | /* | |||
4742 | * conn_ensure_decrypt_hp_buffer ensures that | |||
4743 | * conn->crypto.decrypt_hp_buf has at least |n| bytes space. | |||
4744 | * | |||
4745 | * This function returns 0 if it succeeds, or one of the following | |||
4746 | * negative error codes: | |||
4747 | * | |||
4748 | * NGTCP2_ERR_NOMEM | |||
4749 | * Out of memory. | |||
4750 | */ | |||
4751 | static int conn_ensure_decrypt_hp_buffer(ngtcp2_conn *conn, size_t n) { | |||
4752 | return ensure_decrypt_buffer(&conn->crypto.decrypt_hp_buf, n, 256, conn->mem); | |||
4753 | } | |||
4754 | ||||
4755 | /* | |||
4756 | * conn_ensure_decrypt_buffer ensures that conn->crypto.decrypt_buf | |||
4757 | * has at least |n| bytes space. | |||
4758 | * | |||
4759 | * This function returns 0 if it succeeds, or one of the following | |||
4760 | * negative error codes: | |||
4761 | * | |||
4762 | * NGTCP2_ERR_NOMEM | |||
4763 | * Out of memory. | |||
4764 | */ | |||
4765 | static int conn_ensure_decrypt_buffer(ngtcp2_conn *conn, size_t n) { | |||
4766 | return ensure_decrypt_buffer(&conn->crypto.decrypt_buf, n, 2048, conn->mem); | |||
4767 | } | |||
4768 | ||||
4769 | /* | |||
4770 | * decrypt_pkt decrypts the data pointed by |payload| whose length is | |||
4771 | * |payloadlen|, and writes plaintext data to the buffer pointed by | |||
4772 | * |dest|. The buffer pointed by |ad| is the Additional Data, and its | |||
4773 | * length is |adlen|. |pkt_num| is used to create a nonce. |ckm| is | |||
4774 | * the cryptographic key, and iv to use. |decrypt| is a callback | |||
4775 | * function which actually decrypts a packet. | |||
4776 | * | |||
4777 | * This function returns the number of bytes written in |dest| if it | |||
4778 | * succeeds, or one of the following negative error codes: | |||
4779 | * | |||
4780 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4781 | * User callback failed. | |||
4782 | * NGTCP2_ERR_TLS_DECRYPT | |||
4783 | * TLS backend failed to decrypt data. | |||
4784 | */ | |||
4785 | static ngtcp2_ssize decrypt_pkt(uint8_t *dest, const ngtcp2_crypto_aead *aead, | |||
4786 | const uint8_t *payload, size_t payloadlen, | |||
4787 | const uint8_t *ad, size_t adlen, | |||
4788 | int64_t pkt_num, ngtcp2_crypto_km *ckm, | |||
4789 | ngtcp2_decrypt decrypt) { | |||
4790 | /* TODO nonce is limited to 64 bytes. */ | |||
4791 | uint8_t nonce[64]; | |||
4792 | int rv; | |||
4793 | ||||
4794 | assert(sizeof(nonce) >= ckm->iv.len)((void) (0)); | |||
4795 | ||||
4796 | ngtcp2_crypto_create_nonce(nonce, ckm->iv.base, ckm->iv.len, pkt_num); | |||
4797 | ||||
4798 | rv = decrypt(dest, aead, &ckm->aead_ctx, payload, payloadlen, nonce, | |||
4799 | ckm->iv.len, ad, adlen); | |||
4800 | ||||
4801 | if (rv != 0) { | |||
4802 | if (rv == NGTCP2_ERR_TLS_DECRYPT-220) { | |||
4803 | return rv; | |||
4804 | } | |||
4805 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
4806 | } | |||
4807 | ||||
4808 | assert(payloadlen >= aead->max_overhead)((void) (0)); | |||
4809 | ||||
4810 | return (ngtcp2_ssize)(payloadlen - aead->max_overhead); | |||
4811 | } | |||
4812 | ||||
4813 | /* | |||
4814 | * decrypt_hp decryptes packet header. The packet number starts at | |||
4815 | * |pkt| + |pkt_num_offset|. The entire plaintext QUIC packet header | |||
4816 | * will be written to the buffer pointed by |dest| whose capacity is | |||
4817 | * |destlen|. | |||
4818 | * | |||
4819 | * This function returns the number of bytes written to |dest|, or one | |||
4820 | * of the following negative error codes: | |||
4821 | * | |||
4822 | * NGTCP2_ERR_PROTO | |||
4823 | * Packet is badly formatted | |||
4824 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4825 | * User-defined callback function failed; or it does not return | |||
4826 | * expected result. | |||
4827 | */ | |||
4828 | static ngtcp2_ssize decrypt_hp(ngtcp2_pkt_hd *hd, uint8_t *dest, | |||
4829 | const ngtcp2_crypto_cipher *hp, | |||
4830 | const uint8_t *pkt, size_t pktlen, | |||
4831 | size_t pkt_num_offset, ngtcp2_crypto_km *ckm, | |||
4832 | const ngtcp2_crypto_cipher_ctx *hp_ctx, | |||
4833 | ngtcp2_hp_mask hp_mask) { | |||
4834 | size_t sample_offset; | |||
4835 | uint8_t *p = dest; | |||
4836 | uint8_t mask[NGTCP2_HP_MASKLEN5]; | |||
4837 | size_t i; | |||
4838 | int rv; | |||
4839 | ||||
4840 | assert(hp_mask)((void) (0)); | |||
4841 | assert(ckm)((void) (0)); | |||
4842 | ||||
4843 | if (pkt_num_offset + 4 + NGTCP2_HP_SAMPLELEN16 > pktlen) { | |||
4844 | return NGTCP2_ERR_PROTO-205; | |||
4845 | } | |||
4846 | ||||
4847 | p = ngtcp2_cpymem(p, pkt, pkt_num_offset); | |||
4848 | ||||
4849 | sample_offset = pkt_num_offset + 4; | |||
4850 | ||||
4851 | rv = hp_mask(mask, hp, hp_ctx, pkt + sample_offset); | |||
4852 | if (rv != 0) { | |||
4853 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
4854 | } | |||
4855 | ||||
4856 | if (hd->flags & NGTCP2_PKT_FLAG_LONG_FORM0x01) { | |||
4857 | dest[0] = (uint8_t)(dest[0] ^ (mask[0] & 0x0f)); | |||
4858 | } else { | |||
4859 | dest[0] = (uint8_t)(dest[0] ^ (mask[0] & 0x1f)); | |||
4860 | if (dest[0] & NGTCP2_SHORT_KEY_PHASE_BIT0x04) { | |||
4861 | hd->flags |= NGTCP2_PKT_FLAG_KEY_PHASE0x04; | |||
4862 | } | |||
4863 | } | |||
4864 | ||||
4865 | hd->pkt_numlen = (size_t)((dest[0] & NGTCP2_PKT_NUMLEN_MASK0x03) + 1); | |||
4866 | ||||
4867 | for (i = 0; i < hd->pkt_numlen; ++i) { | |||
4868 | *p++ = *(pkt + pkt_num_offset + i) ^ mask[i + 1]; | |||
4869 | } | |||
4870 | ||||
4871 | hd->pkt_num = ngtcp2_get_pkt_num(p - hd->pkt_numlen, hd->pkt_numlen); | |||
4872 | ||||
4873 | return p - dest; | |||
4874 | } | |||
4875 | ||||
4876 | /* | |||
4877 | * conn_emit_pending_crypto_data delivers pending stream data to the | |||
4878 | * application due to packet reordering. | |||
4879 | * | |||
4880 | * This function returns 0 if it succeeds, or one of the following | |||
4881 | * negative error codes: | |||
4882 | * | |||
4883 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
4884 | * User callback failed | |||
4885 | * NGTCP2_ERR_CRYPTO | |||
4886 | * TLS backend reported error | |||
4887 | */ | |||
4888 | static int conn_emit_pending_crypto_data(ngtcp2_conn *conn, | |||
4889 | ngtcp2_crypto_level crypto_level, | |||
4890 | ngtcp2_strm *strm, | |||
4891 | uint64_t rx_offset) { | |||
4892 | size_t datalen; | |||
4893 | const uint8_t *data; | |||
4894 | int rv; | |||
4895 | uint64_t offset; | |||
4896 | ||||
4897 | if (!strm->rx.rob) { | |||
4898 | return 0; | |||
4899 | } | |||
4900 | ||||
4901 | for (;;) { | |||
4902 | datalen = ngtcp2_rob_data_at(strm->rx.rob, &data, rx_offset); | |||
4903 | if (datalen == 0) { | |||
4904 | assert(rx_offset == ngtcp2_strm_rx_offset(strm))((void) (0)); | |||
4905 | return 0; | |||
4906 | } | |||
4907 | ||||
4908 | offset = rx_offset; | |||
4909 | rx_offset += datalen; | |||
4910 | ||||
4911 | rv = conn_call_recv_crypto_data(conn, crypto_level, offset, data, datalen); | |||
4912 | if (rv != 0) { | |||
4913 | return rv; | |||
4914 | } | |||
4915 | ||||
4916 | ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen); | |||
4917 | } | |||
4918 | } | |||
4919 | ||||
4920 | /* | |||
4921 | * conn_recv_connection_close is called when CONNECTION_CLOSE or | |||
4922 | * APPLICATION_CLOSE frame is received. | |||
4923 | */ | |||
4924 | static void conn_recv_connection_close(ngtcp2_conn *conn, | |||
4925 | ngtcp2_connection_close *fr) { | |||
4926 | conn->state = NGTCP2_CS_DRAINING; | |||
4927 | if (fr->type == NGTCP2_FRAME_CONNECTION_CLOSE) { | |||
4928 | conn->rx.ccec.type = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT; | |||
4929 | } else { | |||
4930 | conn->rx.ccec.type = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION; | |||
4931 | } | |||
4932 | conn->rx.ccec.error_code = fr->error_code; | |||
4933 | } | |||
4934 | ||||
4935 | static void conn_recv_path_challenge(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
4936 | ngtcp2_path_challenge *fr) { | |||
4937 | ngtcp2_path_challenge_entry *ent; | |||
4938 | ||||
4939 | /* client only responds to PATH_CHALLENGE from the current path. */ | |||
4940 | if (!conn->server && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { | |||
4941 | ngtcp2_log_info( | |||
4942 | &conn->log, NGTCP2_LOG_EVENT_CON, | |||
4943 | "discard PATH_CHALLENGE from the path which is not current"); | |||
4944 | return; | |||
4945 | } | |||
4946 | ||||
4947 | ent = ngtcp2_ringbuf_push_front(&conn->rx.path_challenge); | |||
4948 | ngtcp2_path_challenge_entry_init(ent, path, fr->data); | |||
4949 | } | |||
4950 | ||||
4951 | /* | |||
4952 | * conn_reset_congestion_state resets congestion state. | |||
4953 | */ | |||
4954 | static void conn_reset_congestion_state(ngtcp2_conn *conn) { | |||
4955 | conn_reset_conn_stat_cc(conn, &conn->cstat); | |||
4956 | ||||
4957 | conn->cc.reset(&conn->cc); | |||
4958 | ||||
4959 | if (conn->hs_pktns) { | |||
4960 | ngtcp2_rtb_reset_cc_state(&conn->hs_pktns->rtb, | |||
4961 | conn->hs_pktns->tx.last_pkt_num + 1); | |||
4962 | } | |||
4963 | ngtcp2_rtb_reset_cc_state(&conn->pktns.rtb, conn->pktns.tx.last_pkt_num + 1); | |||
4964 | ngtcp2_rst_init(&conn->rst); | |||
4965 | } | |||
4966 | ||||
4967 | static int conn_recv_path_response(ngtcp2_conn *conn, ngtcp2_path_response *fr, | |||
4968 | ngtcp2_tstamp ts) { | |||
4969 | int rv; | |||
4970 | ngtcp2_duration pto, timeout; | |||
4971 | ngtcp2_pv *pv = conn->pv, *npv; | |||
4972 | uint8_t ent_flags; | |||
4973 | ||||
4974 | if (!pv) { | |||
4975 | return 0; | |||
4976 | } | |||
4977 | ||||
4978 | rv = ngtcp2_pv_validate(pv, &ent_flags, fr->data); | |||
4979 | if (rv != 0) { | |||
4980 | if (rv == NGTCP2_ERR_PATH_VALIDATION_FAILED-236) { | |||
4981 | return conn_on_path_validation_failed(conn, pv, ts); | |||
4982 | } | |||
4983 | return 0; | |||
4984 | } | |||
4985 | ||||
4986 | if (!(pv->flags & NGTCP2_PV_FLAG_DONT_CARE0x01)) { | |||
4987 | if (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04)) { | |||
4988 | if (pv->dcid.seq != conn->dcid.current.seq) { | |||
4989 | assert(conn->dcid.current.cid.datalen)((void) (0)); | |||
4990 | ||||
4991 | rv = conn_retire_dcid(conn, &conn->dcid.current, ts); | |||
4992 | if (rv != 0) { | |||
4993 | goto fail; | |||
4994 | } | |||
4995 | ngtcp2_dcid_copy(&conn->dcid.current, &pv->dcid); | |||
4996 | } | |||
4997 | conn_reset_congestion_state(conn); | |||
4998 | conn_reset_ecn_validation_state(conn); | |||
4999 | } | |||
5000 | ||||
5001 | if (ngtcp2_path_eq(&pv->dcid.ps.path, &conn->dcid.current.ps.path)) { | |||
5002 | conn->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED0x01; | |||
5003 | } | |||
5004 | ||||
5005 | rv = conn_call_path_validation(conn, &pv->dcid.ps.path, | |||
5006 | NGTCP2_PATH_VALIDATION_RESULT_SUCCESS); | |||
5007 | if (rv != 0) { | |||
5008 | goto fail; | |||
5009 | } | |||
5010 | } | |||
5011 | ||||
5012 | if (pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) { | |||
5013 | pto = conn_compute_pto(conn, &conn->pktns); | |||
5014 | timeout = 3 * ngtcp2_max(pto, pv->fallback_pto)((pto) > (pv->fallback_pto) ? (pto) : (pv->fallback_pto )); | |||
5015 | ||||
5016 | if (ent_flags & NGTCP2_PV_ENTRY_FLAG_UNDERSIZED0x01) { | |||
5017 | assert(conn->server)((void) (0)); | |||
5018 | ||||
5019 | /* Validate path again */ | |||
5020 | rv = ngtcp2_pv_new(&npv, &pv->dcid, timeout, | |||
5021 | NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04 | | |||
5022 | NGTCP2_PV_FLAG_MTU_PROBE0x08, | |||
5023 | &conn->log, conn->mem); | |||
5024 | if (rv != 0) { | |||
5025 | goto fail; | |||
5026 | } | |||
5027 | ||||
5028 | npv->dcid.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED0x01; | |||
5029 | ngtcp2_dcid_copy(&npv->fallback_dcid, &pv->fallback_dcid); | |||
5030 | npv->fallback_pto = pv->fallback_pto; | |||
5031 | } else { | |||
5032 | rv = ngtcp2_pv_new(&npv, &pv->fallback_dcid, timeout, | |||
5033 | NGTCP2_PV_FLAG_DONT_CARE0x01, &conn->log, conn->mem); | |||
5034 | if (rv != 0) { | |||
5035 | goto fail; | |||
5036 | } | |||
5037 | } | |||
5038 | ||||
5039 | /* Unset the flag bit so that conn_stop_pv does not retire | |||
5040 | DCID. */ | |||
5041 | pv->flags &= (uint8_t)~NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04; | |||
5042 | ||||
5043 | rv = conn_stop_pv(conn, ts); | |||
5044 | if (rv != 0) { | |||
5045 | ngtcp2_pv_del(npv); | |||
5046 | return rv; | |||
5047 | } | |||
5048 | ||||
5049 | conn->pv = npv; | |||
5050 | ||||
5051 | return 0; | |||
5052 | } | |||
5053 | ||||
5054 | fail: | |||
5055 | return conn_stop_pv(conn, ts); | |||
5056 | } | |||
5057 | ||||
5058 | /* | |||
5059 | * pkt_num_bits returns the number of bits available when packet | |||
5060 | * number is encoded in |pkt_numlen| bytes. | |||
5061 | */ | |||
5062 | static size_t pkt_num_bits(size_t pkt_numlen) { | |||
5063 | switch (pkt_numlen) { | |||
5064 | case 1: | |||
5065 | return 8; | |||
5066 | case 2: | |||
5067 | return 16; | |||
5068 | case 3: | |||
5069 | return 24; | |||
5070 | case 4: | |||
5071 | return 32; | |||
5072 | default: | |||
5073 | assert(0)((void) (0)); | |||
5074 | abort(); | |||
5075 | } | |||
5076 | } | |||
5077 | ||||
5078 | /* | |||
5079 | * pktns_pkt_num_is_duplicate returns nonzero if |pkt_num| is | |||
5080 | * duplicated packet number. | |||
5081 | */ | |||
5082 | static int pktns_pkt_num_is_duplicate(ngtcp2_pktns *pktns, int64_t pkt_num) { | |||
5083 | return ngtcp2_gaptr_is_pushed(&pktns->rx.pngap, (uint64_t)pkt_num, 1); | |||
5084 | } | |||
5085 | ||||
5086 | /* | |||
5087 | * pktns_commit_recv_pkt_num marks packet number |pkt_num| as | |||
5088 | * received. | |||
5089 | */ | |||
5090 | static int pktns_commit_recv_pkt_num(ngtcp2_pktns *pktns, int64_t pkt_num, | |||
5091 | int ack_eliciting, ngtcp2_tstamp ts) { | |||
5092 | int rv; | |||
5093 | ||||
5094 | if (ack_eliciting && pktns->rx.max_ack_eliciting_pkt_num + 1 != pkt_num) { | |||
5095 | ngtcp2_acktr_immediate_ack(&pktns->acktr); | |||
5096 | } | |||
5097 | if (pktns->rx.max_pkt_num < pkt_num) { | |||
5098 | pktns->rx.max_pkt_num = pkt_num; | |||
5099 | pktns->rx.max_pkt_ts = ts; | |||
5100 | } | |||
5101 | if (ack_eliciting && pktns->rx.max_ack_eliciting_pkt_num < pkt_num) { | |||
5102 | pktns->rx.max_ack_eliciting_pkt_num = pkt_num; | |||
5103 | } | |||
5104 | ||||
5105 | rv = ngtcp2_gaptr_push(&pktns->rx.pngap, (uint64_t)pkt_num, 1); | |||
5106 | if (rv != 0) { | |||
5107 | return rv; | |||
5108 | } | |||
5109 | ||||
5110 | if (ngtcp2_ksl_len(&pktns->rx.pngap.gap) > 256) { | |||
5111 | ngtcp2_gaptr_drop_first_gap(&pktns->rx.pngap); | |||
5112 | } | |||
5113 | ||||
5114 | return 0; | |||
5115 | } | |||
5116 | ||||
5117 | /* | |||
5118 | * verify_token verifies |hd| contains |token| in its token field. It | |||
5119 | * returns 0 if it succeeds, or NGTCP2_ERR_PROTO. | |||
5120 | */ | |||
5121 | static int verify_token(const ngtcp2_vec *token, const ngtcp2_pkt_hd *hd) { | |||
5122 | if (token->len == hd->token.len && | |||
5123 | ngtcp2_cmemeq(token->base, hd->token.base, token->len)) { | |||
5124 | return 0; | |||
5125 | } | |||
5126 | return NGTCP2_ERR_PROTO-205; | |||
5127 | } | |||
5128 | ||||
5129 | static void pktns_increase_ecn_counts(ngtcp2_pktns *pktns, | |||
5130 | const ngtcp2_pkt_info *pi) { | |||
5131 | switch (pi->ecn & NGTCP2_ECN_MASK0x3) { | |||
5132 | case NGTCP2_ECN_ECT_00x2: | |||
5133 | ++pktns->rx.ecn.ect0; | |||
5134 | break; | |||
5135 | case NGTCP2_ECN_ECT_10x1: | |||
5136 | ++pktns->rx.ecn.ect1; | |||
5137 | break; | |||
5138 | case NGTCP2_ECN_CE0x3: | |||
5139 | ++pktns->rx.ecn.ce; | |||
5140 | break; | |||
5141 | } | |||
5142 | } | |||
5143 | ||||
5144 | static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, | |||
5145 | ngtcp2_strm *strm, const ngtcp2_crypto *fr); | |||
5146 | ||||
5147 | static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
5148 | const ngtcp2_pkt_info *pi, const uint8_t *pkt, | |||
5149 | size_t pktlen, size_t dgramlen, | |||
5150 | ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts); | |||
5151 | ||||
5152 | static int conn_process_buffered_protected_pkt(ngtcp2_conn *conn, | |||
5153 | ngtcp2_pktns *pktns, | |||
5154 | ngtcp2_tstamp ts); | |||
5155 | ||||
5156 | /* | |||
5157 | * conn_recv_handshake_pkt processes received packet |pkt| whose | |||
5158 | * length is |pktlen| during handshake period. The buffer pointed by | |||
5159 | * |pkt| might contain multiple packets. This function only processes | |||
5160 | * one packet. |pkt_ts| is the timestamp when packet is received. | |||
5161 | * |ts| should be the current time. Usually they are the same, but | |||
5162 | * for buffered packets, |pkt_ts| would be earlier than |ts|. | |||
5163 | * | |||
5164 | * This function returns the number of bytes it reads if it succeeds, | |||
5165 | * or one of the following negative error codes: | |||
5166 | * | |||
5167 | * NGTCP2_ERR_RECV_VERSION_NEGOTIATION | |||
5168 | * Version Negotiation packet is received. | |||
5169 | * NGTCP2_ERR_NOMEM | |||
5170 | * Out of memory. | |||
5171 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
5172 | * User-defined callback function failed. | |||
5173 | * NGTCP2_ERR_DISCARD_PKT | |||
5174 | * Packet was discarded because plain text header was malformed; | |||
5175 | * or its payload could not be decrypted. | |||
5176 | * NGTCP2_ERR_FRAME_FORMAT | |||
5177 | * Frame is badly formatted | |||
5178 | * NGTCP2_ERR_ACK_FRAME | |||
5179 | * ACK frame is malformed. | |||
5180 | * NGTCP2_ERR_CRYPTO | |||
5181 | * TLS stack reported error. | |||
5182 | * NGTCP2_ERR_PROTO | |||
5183 | * Generic QUIC protocol error. | |||
5184 | * | |||
5185 | * In addition to the above error codes, error codes returned from | |||
5186 | * conn_recv_pkt are also returned. | |||
5187 | */ | |||
5188 | static ngtcp2_ssize | |||
5189 | conn_recv_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
5190 | const ngtcp2_pkt_info *pi, const uint8_t *pkt, | |||
5191 | size_t pktlen, size_t dgramlen, ngtcp2_tstamp pkt_ts, | |||
5192 | ngtcp2_tstamp ts) { | |||
5193 | ngtcp2_ssize nread; | |||
5194 | ngtcp2_pkt_hd hd; | |||
5195 | ngtcp2_max_frame mfr; | |||
5196 | ngtcp2_frame *fr = &mfr.fr; | |||
5197 | int rv; | |||
5198 | int require_ack = 0; | |||
5199 | size_t hdpktlen; | |||
5200 | const uint8_t *payload; | |||
5201 | size_t payloadlen; | |||
5202 | ngtcp2_ssize nwrite; | |||
5203 | ngtcp2_crypto_aead *aead; | |||
5204 | ngtcp2_crypto_cipher *hp; | |||
5205 | ngtcp2_crypto_km *ckm; | |||
5206 | ngtcp2_crypto_cipher_ctx *hp_ctx; | |||
5207 | ngtcp2_hp_mask hp_mask; | |||
5208 | ngtcp2_decrypt decrypt; | |||
5209 | ngtcp2_pktns *pktns; | |||
5210 | ngtcp2_strm *crypto; | |||
5211 | ngtcp2_crypto_level crypto_level; | |||
5212 | int invalid_reserved_bits = 0; | |||
5213 | ||||
5214 | if (pktlen == 0) { | |||
5215 | return 0; | |||
5216 | } | |||
5217 | ||||
5218 | if (!(pkt[0] & NGTCP2_HEADER_FORM_BIT0x80)) { | |||
5219 | if (conn->state == NGTCP2_CS_SERVER_INITIAL) { | |||
5220 | /* Ignore Short packet unless server's first Handshake packet | |||
5221 | has been transmitted. */ | |||
5222 | return (ngtcp2_ssize)pktlen; | |||
5223 | } | |||
5224 | ||||
5225 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
5226 | "buffering Short packet len=%zu", pktlen); | |||
5227 | ||||
5228 | rv = conn_buffer_pkt(conn, &conn->pktns, path, pi, pkt, pktlen, dgramlen, | |||
5229 | ts); | |||
5230 | if (rv != 0) { | |||
5231 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
5232 | return rv; | |||
5233 | } | |||
5234 | return (ngtcp2_ssize)pktlen; | |||
5235 | } | |||
5236 | ||||
5237 | nread = ngtcp2_pkt_decode_hd_long(&hd, pkt, pktlen); | |||
5238 | if (nread < 0) { | |||
5239 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5240 | } | |||
5241 | ||||
5242 | switch (hd.type) { | |||
5243 | case NGTCP2_PKT_VERSION_NEGOTIATION: | |||
5244 | hdpktlen = (size_t)nread; | |||
5245 | ||||
5246 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
5247 | ||||
5248 | if (conn->server) { | |||
5249 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5250 | } | |||
5251 | ||||
5252 | /* Receiving Version Negotiation packet after getting Handshake | |||
5253 | packet from server is invalid. */ | |||
5254 | if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02) { | |||
5255 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5256 | } | |||
5257 | ||||
5258 | if (!ngtcp2_cid_eq(&conn->oscid, &hd.dcid)) { | |||
5259 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5260 | "packet was ignored because of mismatched DCID"); | |||
5261 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5262 | } | |||
5263 | ||||
5264 | if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) { | |||
5265 | /* Just discard invalid Version Negotiation packet */ | |||
5266 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5267 | "packet was ignored because of mismatched SCID"); | |||
5268 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5269 | } | |||
5270 | rv = conn_on_version_negotiation(conn, &hd, pkt + hdpktlen, | |||
5271 | pktlen - hdpktlen); | |||
5272 | if (rv != 0) { | |||
5273 | if (ngtcp2_err_is_fatal(rv)) { | |||
5274 | return rv; | |||
5275 | } | |||
5276 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5277 | } | |||
5278 | return NGTCP2_ERR_RECV_VERSION_NEGOTIATION-229; | |||
5279 | case NGTCP2_PKT_RETRY: | |||
5280 | hdpktlen = (size_t)nread; | |||
5281 | ||||
5282 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
5283 | ||||
5284 | if (conn->server) { | |||
5285 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5286 | } | |||
5287 | ||||
5288 | /* Receiving Retry packet after getting Initial packet from server | |||
5289 | is invalid. */ | |||
5290 | if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02) { | |||
5291 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5292 | } | |||
5293 | ||||
5294 | rv = conn_on_retry(conn, &hd, hdpktlen, pkt, pktlen); | |||
5295 | if (rv != 0) { | |||
5296 | if (ngtcp2_err_is_fatal(rv)) { | |||
5297 | return rv; | |||
5298 | } | |||
5299 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5300 | } | |||
5301 | return (ngtcp2_ssize)pktlen; | |||
5302 | } | |||
5303 | ||||
5304 | if (pktlen < (size_t)nread + hd.len) { | |||
5305 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5306 | } | |||
5307 | ||||
5308 | pktlen = (size_t)nread + hd.len; | |||
5309 | ||||
5310 | if (conn->version != hd.version) { | |||
5311 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5312 | } | |||
5313 | ||||
5314 | /* Quoted from spec: if subsequent packets of those types include a | |||
5315 | different Source Connection ID, they MUST be discarded. */ | |||
5316 | if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02) && | |||
5317 | !ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) { | |||
5318 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
5319 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5320 | "packet was ignored because of mismatched SCID"); | |||
5321 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5322 | } | |||
5323 | ||||
5324 | switch (hd.type) { | |||
5325 | case NGTCP2_PKT_0RTT: | |||
5326 | if (!conn->server) { | |||
5327 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5328 | } | |||
5329 | if (conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02) { | |||
5330 | if (conn->early.ckm) { | |||
5331 | ngtcp2_ssize nread2; | |||
5332 | /* TODO Avoid to parse header twice. */ | |||
5333 | nread2 = | |||
5334 | conn_recv_pkt(conn, path, pi, pkt, pktlen, dgramlen, pkt_ts, ts); | |||
5335 | if (nread2 < 0) { | |||
5336 | return nread2; | |||
5337 | } | |||
5338 | } | |||
5339 | ||||
5340 | /* Discard 0-RTT packet if we don't have a key to decrypt it. */ | |||
5341 | return (ngtcp2_ssize)pktlen; | |||
5342 | } | |||
5343 | ||||
5344 | /* Buffer re-ordered 0-RTT packet. */ | |||
5345 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
5346 | "buffering 0-RTT packet len=%zu", pktlen); | |||
5347 | ||||
5348 | rv = conn_buffer_pkt(conn, conn->in_pktns, path, pi, pkt, pktlen, dgramlen, | |||
5349 | ts); | |||
5350 | if (rv != 0) { | |||
5351 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
5352 | return rv; | |||
5353 | } | |||
5354 | ||||
5355 | return (ngtcp2_ssize)pktlen; | |||
5356 | case NGTCP2_PKT_INITIAL: | |||
5357 | if (!conn->in_pktns) { | |||
5358 | ngtcp2_log_info( | |||
5359 | &conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5360 | "Initial packet is discarded because keys have been discarded"); | |||
5361 | return (ngtcp2_ssize)pktlen; | |||
5362 | } | |||
5363 | ||||
5364 | assert(conn->in_pktns)((void) (0)); | |||
5365 | ||||
5366 | if (conn->server) { | |||
5367 | if (conn->local.settings.token.len) { | |||
5368 | rv = verify_token(&conn->local.settings.token, &hd); | |||
5369 | if (rv != 0) { | |||
5370 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5371 | "packet was ignored because token is invalid"); | |||
5372 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5373 | } | |||
5374 | } | |||
5375 | if ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02) == 0) { | |||
5376 | /* Set rcid here so that it is available to callback. If this | |||
5377 | packet is discarded later in this function and no packet is | |||
5378 | processed in this connection attempt so far, connection | |||
5379 | will be dropped. */ | |||
5380 | conn->rcid = hd.dcid; | |||
5381 | ||||
5382 | rv = conn_call_recv_client_initial(conn, &hd.dcid); | |||
5383 | if (rv != 0) { | |||
5384 | return rv; | |||
5385 | } | |||
5386 | } | |||
5387 | } else if (hd.token.len != 0) { | |||
5388 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5389 | "packet was ignored because token is not empty"); | |||
5390 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5391 | } | |||
5392 | ||||
5393 | pktns = conn->in_pktns; | |||
5394 | crypto = &pktns->crypto.strm; | |||
5395 | crypto_level = NGTCP2_CRYPTO_LEVEL_INITIAL; | |||
5396 | ||||
5397 | break; | |||
5398 | case NGTCP2_PKT_HANDSHAKE: | |||
5399 | if (!conn->hs_pktns->crypto.rx.ckm) { | |||
5400 | if (conn->server) { | |||
5401 | ngtcp2_log_info( | |||
5402 | &conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5403 | "Handshake packet at this point is unexpected and discarded"); | |||
5404 | return (ngtcp2_ssize)pktlen; | |||
5405 | } | |||
5406 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
5407 | "buffering Handshake packet len=%zu", pktlen); | |||
5408 | ||||
5409 | rv = conn_buffer_pkt(conn, conn->hs_pktns, path, pi, pkt, pktlen, | |||
5410 | dgramlen, ts); | |||
5411 | if (rv != 0) { | |||
5412 | assert(ngtcp2_err_is_fatal(rv))((void) (0)); | |||
5413 | return rv; | |||
5414 | } | |||
5415 | return (ngtcp2_ssize)pktlen; | |||
5416 | } | |||
5417 | ||||
5418 | pktns = conn->hs_pktns; | |||
5419 | crypto = &pktns->crypto.strm; | |||
5420 | crypto_level = NGTCP2_CRYPTO_LEVEL_HANDSHAKE; | |||
5421 | ||||
5422 | break; | |||
5423 | default: | |||
5424 | /* unknown packet type */ | |||
5425 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5426 | "packet was ignored because of unknown packet type"); | |||
5427 | return (ngtcp2_ssize)pktlen; | |||
5428 | } | |||
5429 | ||||
5430 | hp_mask = conn->callbacks.hp_mask; | |||
5431 | decrypt = conn->callbacks.decrypt; | |||
5432 | aead = &pktns->crypto.ctx.aead; | |||
5433 | hp = &pktns->crypto.ctx.hp; | |||
5434 | ckm = pktns->crypto.rx.ckm; | |||
5435 | hp_ctx = &pktns->crypto.rx.hp_ctx; | |||
5436 | ||||
5437 | assert(ckm)((void) (0)); | |||
5438 | assert(hp_mask)((void) (0)); | |||
5439 | assert(decrypt)((void) (0)); | |||
5440 | ||||
5441 | rv = conn_ensure_decrypt_hp_buffer(conn, (size_t)nread + 4); | |||
5442 | if (rv != 0) { | |||
5443 | return rv; | |||
5444 | } | |||
5445 | ||||
5446 | nwrite = decrypt_hp(&hd, conn->crypto.decrypt_hp_buf.base, hp, pkt, pktlen, | |||
5447 | (size_t)nread, ckm, hp_ctx, hp_mask); | |||
5448 | if (nwrite < 0) { | |||
5449 | if (ngtcp2_err_is_fatal((int)nwrite)) { | |||
5450 | return nwrite; | |||
5451 | } | |||
5452 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5453 | "could not decrypt packet number"); | |||
5454 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5455 | } | |||
5456 | ||||
5457 | hdpktlen = (size_t)nwrite; | |||
5458 | payload = pkt + hdpktlen; | |||
5459 | payloadlen = hd.len - hd.pkt_numlen; | |||
5460 | ||||
5461 | hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, | |||
5462 | pkt_num_bits(hd.pkt_numlen)); | |||
5463 | if (hd.pkt_num > NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1))) { | |||
5464 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5465 | "pkn=%" PRId64"l" "d" " is greater than maximum pkn", hd.pkt_num); | |||
5466 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5467 | } | |||
5468 | ||||
5469 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
5470 | ||||
5471 | rv = ngtcp2_pkt_verify_reserved_bits(conn->crypto.decrypt_hp_buf.base[0]); | |||
5472 | if (rv != 0) { | |||
5473 | invalid_reserved_bits = 1; | |||
5474 | ||||
5475 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5476 | "packet has incorrect reserved bits"); | |||
5477 | ||||
5478 | /* Will return error after decrypting payload */ | |||
5479 | } | |||
5480 | ||||
5481 | if (pktns_pkt_num_is_duplicate(pktns, hd.pkt_num)) { | |||
5482 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5483 | "packet was discarded because of duplicated packet number"); | |||
5484 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5485 | } | |||
5486 | ||||
5487 | rv = conn_ensure_decrypt_buffer(conn, payloadlen); | |||
5488 | if (rv != 0) { | |||
5489 | return rv; | |||
5490 | } | |||
5491 | ||||
5492 | nwrite = decrypt_pkt(conn->crypto.decrypt_buf.base, aead, payload, payloadlen, | |||
5493 | conn->crypto.decrypt_hp_buf.base, hdpktlen, hd.pkt_num, | |||
5494 | ckm, decrypt); | |||
5495 | if (nwrite < 0) { | |||
5496 | if (ngtcp2_err_is_fatal((int)nwrite)) { | |||
5497 | return nwrite; | |||
5498 | } | |||
5499 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5500 | "could not decrypt packet payload"); | |||
5501 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5502 | } | |||
5503 | ||||
5504 | if (invalid_reserved_bits) { | |||
5505 | return NGTCP2_ERR_PROTO-205; | |||
5506 | } | |||
5507 | ||||
5508 | payload = conn->crypto.decrypt_buf.base; | |||
5509 | payloadlen = (size_t)nwrite; | |||
5510 | ||||
5511 | switch (hd.type) { | |||
5512 | case NGTCP2_PKT_INITIAL: | |||
5513 | if (!conn->server || ((conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02) && | |||
5514 | !ngtcp2_cid_eq(&conn->rcid, &hd.dcid))) { | |||
5515 | rv = conn_verify_dcid(conn, NULL((void*)0), &hd); | |||
5516 | if (rv != 0) { | |||
5517 | if (ngtcp2_err_is_fatal(rv)) { | |||
5518 | return rv; | |||
5519 | } | |||
5520 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5521 | "packet was ignored because of mismatched DCID"); | |||
5522 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5523 | } | |||
5524 | } | |||
5525 | break; | |||
5526 | case NGTCP2_PKT_HANDSHAKE: | |||
5527 | rv = conn_verify_dcid(conn, NULL((void*)0), &hd); | |||
5528 | if (rv != 0) { | |||
5529 | if (ngtcp2_err_is_fatal(rv)) { | |||
5530 | return rv; | |||
5531 | } | |||
5532 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5533 | "packet was ignored because of mismatched DCID"); | |||
5534 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5535 | } | |||
5536 | break; | |||
5537 | default: | |||
5538 | assert(0)((void) (0)); | |||
5539 | } | |||
5540 | ||||
5541 | if (payloadlen == 0) { | |||
5542 | /* QUIC packet must contain at least one frame */ | |||
5543 | if (hd.type == NGTCP2_PKT_INITIAL) { | |||
5544 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
5545 | } | |||
5546 | return NGTCP2_ERR_PROTO-205; | |||
5547 | } | |||
5548 | ||||
5549 | if (hd.type == NGTCP2_PKT_INITIAL && | |||
5550 | !(conn->flags & NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02)) { | |||
5551 | conn->flags |= NGTCP2_CONN_FLAG_CONN_ID_NEGOTIATED0x02; | |||
5552 | if (!conn->server) { | |||
5553 | conn->dcid.current.cid = hd.scid; | |||
5554 | } | |||
5555 | } | |||
5556 | ||||
5557 | ngtcp2_qlog_pkt_received_start(&conn->qlog); | |||
5558 | ||||
5559 | for (; payloadlen;) { | |||
5560 | nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen); | |||
5561 | if (nread < 0) { | |||
5562 | return nread; | |||
5563 | } | |||
5564 | ||||
5565 | payload += nread; | |||
5566 | payloadlen -= (size_t)nread; | |||
5567 | ||||
5568 | switch (fr->type) { | |||
5569 | case NGTCP2_FRAME_ACK: | |||
5570 | case NGTCP2_FRAME_ACK_ECN: | |||
5571 | fr->ack.ack_delay = 0; | |||
5572 | fr->ack.ack_delay_unscaled = 0; | |||
5573 | break; | |||
5574 | } | |||
5575 | ||||
5576 | ngtcp2_log_rx_fr(&conn->log, &hd, fr); | |||
5577 | ||||
5578 | switch (fr->type) { | |||
5579 | case NGTCP2_FRAME_ACK: | |||
5580 | case NGTCP2_FRAME_ACK_ECN: | |||
5581 | if (!conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) { | |||
5582 | conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000; | |||
5583 | } | |||
5584 | rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts); | |||
5585 | if (rv != 0) { | |||
5586 | return rv; | |||
5587 | } | |||
5588 | break; | |||
5589 | case NGTCP2_FRAME_PADDING: | |||
5590 | break; | |||
5591 | case NGTCP2_FRAME_CRYPTO: | |||
5592 | rv = conn_recv_crypto(conn, crypto_level, crypto, &fr->crypto); | |||
5593 | if (rv != 0) { | |||
5594 | return rv; | |||
5595 | } | |||
5596 | require_ack = 1; | |||
5597 | break; | |||
5598 | case NGTCP2_FRAME_CONNECTION_CLOSE: | |||
5599 | conn_recv_connection_close(conn, &fr->connection_close); | |||
5600 | break; | |||
5601 | case NGTCP2_FRAME_PING: | |||
5602 | require_ack = 1; | |||
5603 | break; | |||
5604 | default: | |||
5605 | return NGTCP2_ERR_PROTO-205; | |||
5606 | } | |||
5607 | ||||
5608 | ngtcp2_qlog_write_frame(&conn->qlog, fr); | |||
5609 | } | |||
5610 | ||||
5611 | if (conn->server && hd.type == NGTCP2_PKT_HANDSHAKE) { | |||
5612 | /* Successful processing of Handshake packet from client verifies | |||
5613 | source address. */ | |||
5614 | conn->dcid.current.flags |= NGTCP2_DCID_FLAG_PATH_VALIDATED0x01; | |||
5615 | } | |||
5616 | ||||
5617 | ngtcp2_qlog_pkt_received_end(&conn->qlog, &hd, pktlen); | |||
5618 | ||||
5619 | rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, require_ack, pkt_ts); | |||
5620 | if (rv != 0) { | |||
5621 | return rv; | |||
5622 | } | |||
5623 | ||||
5624 | pktns_increase_ecn_counts(pktns, pi); | |||
5625 | ||||
5626 | /* TODO Initial and Handshake are always acknowledged without | |||
5627 | delay. */ | |||
5628 | if (require_ack && | |||
5629 | (++pktns->acktr.rx_npkt >= conn->local.settings.ack_thresh || | |||
5630 | (pi->ecn & NGTCP2_ECN_MASK0x3) == NGTCP2_ECN_CE0x3)) { | |||
5631 | ngtcp2_acktr_immediate_ack(&pktns->acktr); | |||
5632 | } | |||
5633 | ||||
5634 | rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, | |||
5635 | pkt_ts); | |||
5636 | if (rv != 0) { | |||
5637 | return rv; | |||
5638 | } | |||
5639 | ||||
5640 | conn_restart_timer_on_read(conn, ts); | |||
5641 | ||||
5642 | ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); | |||
5643 | ||||
5644 | return conn->state == NGTCP2_CS_DRAINING ? NGTCP2_ERR_DRAINING-231 | |||
5645 | : (ngtcp2_ssize)pktlen; | |||
5646 | } | |||
5647 | ||||
5648 | /* | |||
5649 | * conn_recv_handshake_cpkt processes compound packet during | |||
5650 | * handshake. The buffer pointed by |pkt| might contain multiple | |||
5651 | * packets. The Short packet must be the last one because it does not | |||
5652 | * have payload length field. | |||
5653 | * | |||
5654 | * This function returns the same error code returned by | |||
5655 | * conn_recv_handshake_pkt. | |||
5656 | */ | |||
5657 | static int conn_recv_handshake_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
5658 | const ngtcp2_pkt_info *pi, | |||
5659 | const uint8_t *pkt, size_t pktlen, | |||
5660 | ngtcp2_tstamp ts) { | |||
5661 | ngtcp2_ssize nread; | |||
5662 | size_t dgramlen = pktlen; | |||
5663 | ||||
5664 | if (ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { | |||
5665 | conn->dcid.current.bytes_recv += dgramlen; | |||
5666 | } | |||
5667 | ||||
5668 | while (pktlen) { | |||
5669 | nread = | |||
5670 | conn_recv_handshake_pkt(conn, path, pi, pkt, pktlen, dgramlen, ts, ts); | |||
5671 | if (nread < 0) { | |||
5672 | if (ngtcp2_err_is_fatal((int)nread)) { | |||
5673 | return (int)nread; | |||
5674 | } | |||
5675 | ||||
5676 | if (nread == NGTCP2_ERR_DRAINING-231) { | |||
5677 | return NGTCP2_ERR_DRAINING-231; | |||
5678 | } | |||
5679 | ||||
5680 | if ((pkt[0] & NGTCP2_HEADER_FORM_BIT0x80) && | |||
5681 | /* Not a Version Negotiation packet */ | |||
5682 | pktlen > 4 && ngtcp2_get_uint32(&pkt[1]) > 0 && | |||
5683 | ngtcp2_pkt_get_type_long(pkt[0]) == NGTCP2_PKT_INITIAL) { | |||
5684 | if (conn->server) { | |||
5685 | /* If server discards first Initial, then drop connection | |||
5686 | state. This is because SCID in packet might be corrupted | |||
5687 | and the current connection state might wrongly discard | |||
5688 | valid packet and prevent the handshake from | |||
5689 | completing. */ | |||
5690 | if (conn->in_pktns && conn->in_pktns->rx.max_pkt_num == -1) { | |||
5691 | /* If this is crypto related error, then return normally | |||
5692 | in order to send CONNECTION_CLOSE with TLS alert (e.g., | |||
5693 | no_application_protocol). */ | |||
5694 | switch (nread) { | |||
5695 | case NGTCP2_ERR_CRYPTO-215: | |||
5696 | case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM-217: | |||
5697 | case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM-218: | |||
5698 | case NGTCP2_ERR_TRANSPORT_PARAM-234: | |||
5699 | return (int)nread; | |||
5700 | } | |||
5701 | ||||
5702 | return NGTCP2_ERR_DROP_CONN-242; | |||
5703 | } | |||
5704 | return 0; | |||
5705 | } | |||
5706 | /* client */ | |||
5707 | if (nread == NGTCP2_ERR_CRYPTO-215) { | |||
5708 | /* If client gets crypto error from TLS stack, it is | |||
5709 | unrecoverable, therefore drop connection. */ | |||
5710 | return (int)nread; | |||
5711 | } | |||
5712 | return 0; | |||
5713 | } | |||
5714 | ||||
5715 | if (nread == NGTCP2_ERR_DISCARD_PKT-235) { | |||
5716 | return 0; | |||
5717 | } | |||
5718 | ||||
5719 | return (int)nread; | |||
5720 | } | |||
5721 | ||||
5722 | assert(pktlen >= (size_t)nread)((void) (0)); | |||
5723 | pkt += nread; | |||
5724 | pktlen -= (size_t)nread; | |||
5725 | ||||
5726 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
5727 | "read packet %td left %zu", nread, pktlen); | |||
5728 | } | |||
5729 | ||||
5730 | return 0; | |||
5731 | } | |||
5732 | ||||
5733 | int ngtcp2_conn_init_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
5734 | int64_t stream_id, void *stream_user_data) { | |||
5735 | int rv; | |||
5736 | uint64_t max_rx_offset; | |||
5737 | uint64_t max_tx_offset; | |||
5738 | int local_stream = conn_local_stream(conn, stream_id); | |||
5739 | ||||
5740 | if (bidi_stream(stream_id)) { | |||
5741 | if (local_stream) { | |||
5742 | max_rx_offset = | |||
5743 | conn->local.transport_params.initial_max_stream_data_bidi_local; | |||
5744 | max_tx_offset = | |||
5745 | conn->remote.transport_params.initial_max_stream_data_bidi_remote; | |||
5746 | } else { | |||
5747 | max_rx_offset = | |||
5748 | conn->local.transport_params.initial_max_stream_data_bidi_remote; | |||
5749 | max_tx_offset = | |||
5750 | conn->remote.transport_params.initial_max_stream_data_bidi_local; | |||
5751 | } | |||
5752 | } else if (local_stream) { | |||
5753 | max_rx_offset = 0; | |||
5754 | max_tx_offset = conn->remote.transport_params.initial_max_stream_data_uni; | |||
5755 | } else { | |||
5756 | max_rx_offset = conn->local.transport_params.initial_max_stream_data_uni; | |||
5757 | max_tx_offset = 0; | |||
5758 | } | |||
5759 | ||||
5760 | rv = ngtcp2_strm_init(strm, stream_id, NGTCP2_STRM_FLAG_NONE0x00, max_rx_offset, | |||
5761 | max_tx_offset, stream_user_data, conn->mem); | |||
5762 | if (rv != 0) { | |||
5763 | return rv; | |||
5764 | } | |||
5765 | ||||
5766 | rv = ngtcp2_map_insert(&conn->strms, &strm->me); | |||
5767 | if (rv != 0) { | |||
5768 | assert(rv != NGTCP2_ERR_INVALID_ARGUMENT)((void) (0)); | |||
5769 | goto fail; | |||
5770 | } | |||
5771 | ||||
5772 | if (!conn_local_stream(conn, stream_id)) { | |||
5773 | rv = conn_call_stream_open(conn, strm); | |||
5774 | if (rv != 0) { | |||
5775 | goto fail; | |||
5776 | } | |||
5777 | } | |||
5778 | ||||
5779 | return 0; | |||
5780 | ||||
5781 | fail: | |||
5782 | ngtcp2_strm_free(strm); | |||
5783 | return rv; | |||
5784 | } | |||
5785 | ||||
5786 | /* | |||
5787 | * conn_emit_pending_stream_data passes buffered ordered stream data | |||
5788 | * to the application. |rx_offset| is the first offset to deliver to | |||
5789 | * the application. This function assumes that the data up to | |||
5790 | * |rx_offset| has been delivered already. This function only passes | |||
5791 | * the ordered data without any gap. If there is a gap, it stops | |||
5792 | * providing the data to the application, and returns. | |||
5793 | * | |||
5794 | * This function returns 0 if it succeeds, or one of the following | |||
5795 | * negative error codes: | |||
5796 | * | |||
5797 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
5798 | * User callback failed. | |||
5799 | * NGTCP2_ERR_NOMEM | |||
5800 | * Out of memory. | |||
5801 | */ | |||
5802 | static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
5803 | uint64_t rx_offset) { | |||
5804 | size_t datalen; | |||
5805 | const uint8_t *data; | |||
5806 | int rv; | |||
5807 | uint64_t offset; | |||
5808 | uint32_t sdflags; | |||
5809 | int handshake_completed = conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01; | |||
5810 | ||||
5811 | if (!strm->rx.rob) { | |||
5812 | return 0; | |||
5813 | } | |||
5814 | ||||
5815 | for (;;) { | |||
5816 | /* Stop calling callback if application has called | |||
5817 | ngtcp2_conn_shutdown_stream_read() inside the callback. | |||
5818 | Because it doubly counts connection window. */ | |||
5819 | if (strm->flags & (NGTCP2_STRM_FLAG_STOP_SENDING0x10)) { | |||
5820 | return 0; | |||
5821 | } | |||
5822 | ||||
5823 | datalen = ngtcp2_rob_data_at(strm->rx.rob, &data, rx_offset); | |||
5824 | if (datalen == 0) { | |||
5825 | assert(rx_offset == ngtcp2_strm_rx_offset(strm))((void) (0)); | |||
5826 | return 0; | |||
5827 | } | |||
5828 | ||||
5829 | offset = rx_offset; | |||
5830 | rx_offset += datalen; | |||
5831 | ||||
5832 | sdflags = NGTCP2_STREAM_DATA_FLAG_NONE0x00; | |||
5833 | if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) && | |||
5834 | rx_offset == strm->rx.last_offset) { | |||
5835 | sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN0x01; | |||
5836 | } | |||
5837 | if (!handshake_completed) { | |||
5838 | sdflags |= NGTCP2_STREAM_DATA_FLAG_EARLY0x02; | |||
5839 | } | |||
5840 | ||||
5841 | rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data, datalen); | |||
5842 | if (rv != 0) { | |||
5843 | return rv; | |||
5844 | } | |||
5845 | ||||
5846 | ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen); | |||
5847 | } | |||
5848 | } | |||
5849 | ||||
5850 | /* | |||
5851 | * conn_recv_crypto is called when CRYPTO frame |fr| is received. | |||
5852 | * |rx_offset_base| is the offset in the entire TLS handshake stream. | |||
5853 | * fr->offset specifies the offset in each encryption level. | |||
5854 | * |max_rx_offset| is, if it is nonzero, the maximum offset in the | |||
5855 | * entire TLS handshake stream that |fr| can carry. |crypto_level| is | |||
5856 | * the encryption level where this data is received. | |||
5857 | * | |||
5858 | * This function returns 0 if it succeeds, or one of the following | |||
5859 | * negative error codes: | |||
5860 | * | |||
5861 | * NGTCP2_ERR_PROTO | |||
5862 | * CRYPTO frame has invalid offset. | |||
5863 | * NGTCP2_ERR_NOMEM | |||
5864 | * Out of memory. | |||
5865 | * NGTCP2_ERR_CRYPTO | |||
5866 | * TLS stack reported error. | |||
5867 | * NGTCP2_ERR_FRAME_ENCODING | |||
5868 | * The end offset exceeds the maximum value. | |||
5869 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
5870 | * User-defined callback function failed. | |||
5871 | */ | |||
5872 | static int conn_recv_crypto(ngtcp2_conn *conn, ngtcp2_crypto_level crypto_level, | |||
5873 | ngtcp2_strm *crypto, const ngtcp2_crypto *fr) { | |||
5874 | uint64_t fr_end_offset; | |||
5875 | uint64_t rx_offset; | |||
5876 | int rv; | |||
5877 | ||||
5878 | if (fr->datacnt == 0) { | |||
5879 | return 0; | |||
5880 | } | |||
5881 | ||||
5882 | fr_end_offset = fr->offset + fr->data[0].len; | |||
5883 | ||||
5884 | if (NGTCP2_MAX_VARINT((1ULL << 62) - 1) < fr_end_offset) { | |||
5885 | return NGTCP2_ERR_FRAME_ENCODING-219; | |||
5886 | } | |||
5887 | ||||
5888 | rx_offset = ngtcp2_strm_rx_offset(crypto); | |||
5889 | ||||
5890 | if (fr_end_offset <= rx_offset) { | |||
5891 | if (conn->server && | |||
5892 | !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_EARLY_RETRANSMIT0x0200) && | |||
5893 | crypto_level == NGTCP2_CRYPTO_LEVEL_INITIAL) { | |||
5894 | /* recovery draft: Speeding Up Handshake Completion | |||
5895 | ||||
5896 | When a server receives an Initial packet containing duplicate | |||
5897 | CRYPTO data, it can assume the client did not receive all of | |||
5898 | the server's CRYPTO data sent in Initial packets, or the | |||
5899 | client's estimated RTT is too small. ... To speed up | |||
5900 | handshake completion under these conditions, an endpoint MAY | |||
5901 | send a packet containing unacknowledged CRYPTO data earlier | |||
5902 | than the PTO expiry, subject to address validation limits; | |||
5903 | ... */ | |||
5904 | conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_EARLY_RETRANSMIT0x0200; | |||
5905 | conn->in_pktns->rtb.probe_pkt_left = 1; | |||
5906 | conn->hs_pktns->rtb.probe_pkt_left = 1; | |||
5907 | } | |||
5908 | return 0; | |||
5909 | } | |||
5910 | ||||
5911 | crypto->rx.last_offset = ngtcp2_max(crypto->rx.last_offset, fr_end_offset)((crypto->rx.last_offset) > (fr_end_offset) ? (crypto-> rx.last_offset) : (fr_end_offset)); | |||
5912 | ||||
5913 | /* TODO Before dispatching incoming data to TLS stack, make sure | |||
5914 | that previous data in previous encryption level has been | |||
5915 | completely sent to TLS stack. Usually, if data is left, it is an | |||
5916 | error because key is generated after consuming all data in the | |||
5917 | previous encryption level. */ | |||
5918 | if (fr->offset <= rx_offset) { | |||
5919 | size_t ncut = (size_t)(rx_offset - fr->offset); | |||
5920 | const uint8_t *data = fr->data[0].base + ncut; | |||
5921 | size_t datalen = fr->data[0].len - ncut; | |||
5922 | uint64_t offset = rx_offset; | |||
5923 | ||||
5924 | rx_offset += datalen; | |||
5925 | rv = ngtcp2_strm_update_rx_offset(crypto, rx_offset); | |||
5926 | if (rv != 0) { | |||
5927 | return rv; | |||
5928 | } | |||
5929 | ||||
5930 | rv = conn_call_recv_crypto_data(conn, crypto_level, offset, data, datalen); | |||
5931 | if (rv != 0) { | |||
5932 | return rv; | |||
5933 | } | |||
5934 | ||||
5935 | rv = conn_emit_pending_crypto_data(conn, crypto_level, crypto, rx_offset); | |||
5936 | if (rv != 0) { | |||
5937 | return rv; | |||
5938 | } | |||
5939 | ||||
5940 | return 0; | |||
5941 | } | |||
5942 | ||||
5943 | if (fr_end_offset - rx_offset > NGTCP2_MAX_REORDERED_CRYPTO_DATA65536) { | |||
5944 | return NGTCP2_ERR_CRYPTO_BUFFER_EXCEEDED-239; | |||
5945 | } | |||
5946 | ||||
5947 | return ngtcp2_strm_recv_reordering(crypto, fr->data[0].base, fr->data[0].len, | |||
5948 | fr->offset); | |||
5949 | } | |||
5950 | ||||
5951 | /* | |||
5952 | * conn_max_data_violated returns nonzero if receiving |datalen| | |||
5953 | * violates connection flow control on local endpoint. | |||
5954 | */ | |||
5955 | static int conn_max_data_violated(ngtcp2_conn *conn, uint64_t datalen) { | |||
5956 | return conn->rx.max_offset - conn->rx.offset < datalen; | |||
5957 | } | |||
5958 | ||||
5959 | /* | |||
5960 | * conn_recv_stream is called when STREAM frame |fr| is received. | |||
5961 | * | |||
5962 | * This function returns 0 if it succeeds, or one of the following | |||
5963 | * negative error codes: | |||
5964 | * | |||
5965 | * NGTCP2_ERR_STREAM_STATE | |||
5966 | * STREAM frame is received for a local stream which is not | |||
5967 | * initiated; or STREAM frame is received for a local | |||
5968 | * unidirectional stream | |||
5969 | * NGTCP2_ERR_STREAM_LIMIT | |||
5970 | * STREAM frame has remote stream ID which is strictly greater | |||
5971 | * than the allowed limit. | |||
5972 | * NGTCP2_ERR_NOMEM | |||
5973 | * Out of memory. | |||
5974 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
5975 | * User-defined callback function failed. | |||
5976 | * NGTCP2_ERR_FLOW_CONTROL | |||
5977 | * Flow control limit is violated; or the end offset of stream | |||
5978 | * data is beyond the NGTCP2_MAX_VARINT. | |||
5979 | * NGTCP2_ERR_FINAL_SIZE | |||
5980 | * STREAM frame has strictly larger end offset than it is | |||
5981 | * permitted. | |||
5982 | */ | |||
5983 | static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { | |||
5984 | int rv; | |||
5985 | ngtcp2_strm *strm; | |||
5986 | ngtcp2_idtr *idtr; | |||
5987 | uint64_t rx_offset, fr_end_offset; | |||
5988 | int local_stream; | |||
5989 | int bidi; | |||
5990 | size_t datalen = ngtcp2_vec_len(fr->data, fr->datacnt); | |||
5991 | uint32_t sdflags = NGTCP2_STREAM_DATA_FLAG_NONE0x00; | |||
5992 | ||||
5993 | local_stream = conn_local_stream(conn, fr->stream_id); | |||
5994 | bidi = bidi_stream(fr->stream_id); | |||
5995 | ||||
5996 | if (bidi) { | |||
5997 | if (local_stream) { | |||
5998 | if (conn->local.bidi.next_stream_id <= fr->stream_id) { | |||
5999 | return NGTCP2_ERR_STREAM_STATE-226; | |||
6000 | } | |||
6001 | } else if (conn->remote.bidi.max_streams < | |||
6002 | ngtcp2_ord_stream_id(fr->stream_id)) { | |||
6003 | return NGTCP2_ERR_STREAM_LIMIT-213; | |||
6004 | } | |||
6005 | ||||
6006 | idtr = &conn->remote.bidi.idtr; | |||
6007 | } else { | |||
6008 | if (local_stream) { | |||
6009 | return NGTCP2_ERR_STREAM_STATE-226; | |||
6010 | } | |||
6011 | if (conn->remote.uni.max_streams < ngtcp2_ord_stream_id(fr->stream_id)) { | |||
6012 | return NGTCP2_ERR_STREAM_LIMIT-213; | |||
6013 | } | |||
6014 | ||||
6015 | idtr = &conn->remote.uni.idtr; | |||
6016 | } | |||
6017 | ||||
6018 | if (NGTCP2_MAX_VARINT((1ULL << 62) - 1) - datalen < fr->offset) { | |||
6019 | return NGTCP2_ERR_FLOW_CONTROL-211; | |||
6020 | } | |||
6021 | ||||
6022 | strm = ngtcp2_conn_find_stream(conn, fr->stream_id); | |||
6023 | if (strm == NULL((void*)0)) { | |||
6024 | if (local_stream) { | |||
6025 | /* TODO The stream has been closed. This should be responded | |||
6026 | with RESET_STREAM, or simply ignored. */ | |||
6027 | return 0; | |||
6028 | } | |||
6029 | ||||
6030 | rv = ngtcp2_idtr_open(idtr, fr->stream_id); | |||
6031 | if (rv != 0) { | |||
6032 | if (ngtcp2_err_is_fatal(rv)) { | |||
6033 | return rv; | |||
6034 | } | |||
6035 | assert(rv == NGTCP2_ERR_STREAM_IN_USE)((void) (0)); | |||
6036 | /* TODO The stream has been closed. This should be responded | |||
6037 | with RESET_STREAM, or simply ignored. */ | |||
6038 | return 0; | |||
6039 | } | |||
6040 | ||||
6041 | strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm)); | |||
6042 | if (strm == NULL((void*)0)) { | |||
6043 | return NGTCP2_ERR_NOMEM-501; | |||
6044 | } | |||
6045 | /* TODO Perhaps, call new_stream callback? */ | |||
6046 | rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL((void*)0)); | |||
6047 | if (rv != 0) { | |||
6048 | ngtcp2_mem_free(conn->mem, strm); | |||
6049 | return rv; | |||
6050 | } | |||
6051 | if (!bidi) { | |||
6052 | ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_WR0x02); | |||
6053 | } | |||
6054 | } | |||
6055 | ||||
6056 | fr_end_offset = fr->offset + datalen; | |||
6057 | ||||
6058 | if (strm->rx.max_offset < fr_end_offset) { | |||
6059 | return NGTCP2_ERR_FLOW_CONTROL-211; | |||
6060 | } | |||
6061 | ||||
6062 | if (strm->rx.last_offset < fr_end_offset) { | |||
6063 | uint64_t len = fr_end_offset - strm->rx.last_offset; | |||
6064 | ||||
6065 | if (conn_max_data_violated(conn, len)) { | |||
6066 | return NGTCP2_ERR_FLOW_CONTROL-211; | |||
6067 | } | |||
6068 | ||||
6069 | conn->rx.offset += len; | |||
6070 | ||||
6071 | if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING0x10) { | |||
6072 | ngtcp2_conn_extend_max_offset(conn, len); | |||
6073 | } | |||
6074 | } | |||
6075 | ||||
6076 | rx_offset = ngtcp2_strm_rx_offset(strm); | |||
6077 | ||||
6078 | if (fr->fin) { | |||
6079 | if (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) { | |||
6080 | if (strm->rx.last_offset != fr_end_offset) { | |||
6081 | return NGTCP2_ERR_FINAL_SIZE-214; | |||
6082 | } | |||
6083 | ||||
6084 | if (strm->flags & | |||
6085 | (NGTCP2_STRM_FLAG_STOP_SENDING0x10 | NGTCP2_STRM_FLAG_RECV_RST0x08)) { | |||
6086 | return 0; | |||
6087 | } | |||
6088 | ||||
6089 | if (rx_offset == fr_end_offset) { | |||
6090 | return 0; | |||
6091 | } | |||
6092 | } else if (strm->rx.last_offset > fr_end_offset) { | |||
6093 | return NGTCP2_ERR_FINAL_SIZE-214; | |||
6094 | } else { | |||
6095 | strm->rx.last_offset = fr_end_offset; | |||
6096 | ||||
6097 | ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_RD0x01); | |||
6098 | ||||
6099 | if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING0x10) { | |||
6100 | return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, | |||
6101 | strm->app_error_code); | |||
6102 | } | |||
6103 | } | |||
6104 | } else { | |||
6105 | if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) && | |||
6106 | strm->rx.last_offset < fr_end_offset) { | |||
6107 | return NGTCP2_ERR_FINAL_SIZE-214; | |||
6108 | } | |||
6109 | ||||
6110 | strm->rx.last_offset = ngtcp2_max(strm->rx.last_offset, fr_end_offset)((strm->rx.last_offset) > (fr_end_offset) ? (strm->rx .last_offset) : (fr_end_offset)); | |||
6111 | ||||
6112 | if (fr_end_offset <= rx_offset) { | |||
6113 | return 0; | |||
6114 | } | |||
6115 | ||||
6116 | if (strm->flags & | |||
6117 | (NGTCP2_STRM_FLAG_STOP_SENDING0x10 | NGTCP2_STRM_FLAG_RECV_RST0x08)) { | |||
6118 | return 0; | |||
6119 | } | |||
6120 | } | |||
6121 | ||||
6122 | if (fr->offset <= rx_offset) { | |||
6123 | size_t ncut = (size_t)(rx_offset - fr->offset); | |||
6124 | uint64_t offset = rx_offset; | |||
6125 | const uint8_t *data; | |||
6126 | int fin; | |||
6127 | ||||
6128 | if (fr->datacnt) { | |||
6129 | data = fr->data[0].base + ncut; | |||
6130 | datalen -= ncut; | |||
6131 | ||||
6132 | rx_offset += datalen; | |||
6133 | rv = ngtcp2_strm_update_rx_offset(strm, rx_offset); | |||
6134 | if (rv != 0) { | |||
6135 | return rv; | |||
6136 | } | |||
6137 | } else { | |||
6138 | data = NULL((void*)0); | |||
6139 | datalen = 0; | |||
6140 | } | |||
6141 | ||||
6142 | fin = (strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) && | |||
6143 | rx_offset == strm->rx.last_offset; | |||
6144 | ||||
6145 | if (fin || datalen) { | |||
6146 | if (fin) { | |||
6147 | sdflags |= NGTCP2_STREAM_DATA_FLAG_FIN0x01; | |||
6148 | } | |||
6149 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
6150 | sdflags |= NGTCP2_STREAM_DATA_FLAG_EARLY0x02; | |||
6151 | } | |||
6152 | rv = conn_call_recv_stream_data(conn, strm, sdflags, offset, data, | |||
6153 | datalen); | |||
6154 | if (rv != 0) { | |||
6155 | return rv; | |||
6156 | } | |||
6157 | ||||
6158 | rv = conn_emit_pending_stream_data(conn, strm, rx_offset); | |||
6159 | if (rv != 0) { | |||
6160 | return rv; | |||
6161 | } | |||
6162 | } | |||
6163 | } else if (fr->datacnt) { | |||
6164 | rv = ngtcp2_strm_recv_reordering(strm, fr->data[0].base, fr->data[0].len, | |||
6165 | fr->offset); | |||
6166 | if (rv != 0) { | |||
6167 | return rv; | |||
6168 | } | |||
6169 | } | |||
6170 | return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, NGTCP2_NO_ERROR0x0u); | |||
6171 | } | |||
6172 | ||||
6173 | /* | |||
6174 | * conn_reset_stream adds RESET_STREAM frame to the transmission | |||
6175 | * queue. | |||
6176 | * | |||
6177 | * This function returns 0 if it succeeds, or one of the following | |||
6178 | * negative error codes: | |||
6179 | * | |||
6180 | * NGTCP2_ERR_NOMEM | |||
6181 | * Out of memory. | |||
6182 | */ | |||
6183 | static int conn_reset_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
6184 | uint64_t app_error_code) { | |||
6185 | int rv; | |||
6186 | ngtcp2_frame_chain *frc; | |||
6187 | ngtcp2_pktns *pktns = &conn->pktns; | |||
6188 | ||||
6189 | rv = ngtcp2_frame_chain_new(&frc, conn->mem); | |||
6190 | if (rv != 0) { | |||
6191 | return rv; | |||
6192 | } | |||
6193 | ||||
6194 | frc->fr.type = NGTCP2_FRAME_RESET_STREAM; | |||
6195 | frc->fr.reset_stream.stream_id = strm->stream_id; | |||
6196 | frc->fr.reset_stream.app_error_code = app_error_code; | |||
6197 | frc->fr.reset_stream.final_size = strm->tx.offset; | |||
6198 | ||||
6199 | /* TODO This prepends RESET_STREAM to pktns->tx.frq. */ | |||
6200 | frc->next = pktns->tx.frq; | |||
6201 | pktns->tx.frq = frc; | |||
6202 | ||||
6203 | return 0; | |||
6204 | } | |||
6205 | ||||
6206 | /* | |||
6207 | * conn_stop_sending adds STOP_SENDING frame to the transmission | |||
6208 | * queue. | |||
6209 | * | |||
6210 | * This function returns 0 if it succeeds, or one of the following | |||
6211 | * negative error codes: | |||
6212 | * | |||
6213 | * NGTCP2_ERR_NOMEM | |||
6214 | * Out of memory. | |||
6215 | */ | |||
6216 | static int conn_stop_sending(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
6217 | uint64_t app_error_code) { | |||
6218 | int rv; | |||
6219 | ngtcp2_frame_chain *frc; | |||
6220 | ngtcp2_pktns *pktns = &conn->pktns; | |||
6221 | ||||
6222 | rv = ngtcp2_frame_chain_new(&frc, conn->mem); | |||
6223 | if (rv != 0) { | |||
6224 | return rv; | |||
6225 | } | |||
6226 | ||||
6227 | frc->fr.type = NGTCP2_FRAME_STOP_SENDING; | |||
6228 | frc->fr.stop_sending.stream_id = strm->stream_id; | |||
6229 | frc->fr.stop_sending.app_error_code = app_error_code; | |||
6230 | ||||
6231 | /* TODO This prepends STOP_SENDING to pktns->tx.frq. */ | |||
6232 | frc->next = pktns->tx.frq; | |||
6233 | pktns->tx.frq = frc; | |||
6234 | ||||
6235 | return 0; | |||
6236 | } | |||
6237 | ||||
6238 | /* | |||
6239 | * handle_max_remote_streams_extension extends | |||
6240 | * |*punsent_max_remote_streams| by |n| if a condition allows it. | |||
6241 | */ | |||
6242 | static void | |||
6243 | handle_max_remote_streams_extension(uint64_t *punsent_max_remote_streams, | |||
6244 | size_t n) { | |||
6245 | if ( | |||
6246 | #if SIZE_MAX(18446744073709551615UL) > UINT32_MAX(4294967295U) | |||
6247 | NGTCP2_MAX_STREAMS(1LL << 60) < n || | |||
6248 | #endif /* SIZE_MAX > UINT32_MAX */ | |||
6249 | *punsent_max_remote_streams > (uint64_t)(NGTCP2_MAX_STREAMS(1LL << 60) - n)) { | |||
6250 | *punsent_max_remote_streams = NGTCP2_MAX_STREAMS(1LL << 60); | |||
6251 | } else { | |||
6252 | *punsent_max_remote_streams += n; | |||
6253 | } | |||
6254 | } | |||
6255 | ||||
6256 | /* | |||
6257 | * conn_recv_reset_stream is called when RESET_STREAM |fr| is | |||
6258 | * received. | |||
6259 | * | |||
6260 | * This function returns 0 if it succeeds, or one of the following | |||
6261 | * negative error codes: | |||
6262 | * | |||
6263 | * NGTCP2_ERR_STREAM_STATE | |||
6264 | * RESET_STREAM frame is received to the local stream which is not | |||
6265 | * initiated. | |||
6266 | * NGTCP2_ERR_STREAM_LIMIT | |||
6267 | * RESET_STREAM frame has remote stream ID which is strictly | |||
6268 | * greater than the allowed limit. | |||
6269 | * NGTCP2_ERR_PROTO | |||
6270 | * RESET_STREAM frame is received to the local unidirectional | |||
6271 | * stream | |||
6272 | * NGTCP2_ERR_NOMEM | |||
6273 | * Out of memory. | |||
6274 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
6275 | * User-defined callback function failed. | |||
6276 | * NGTCP2_ERR_FLOW_CONTROL | |||
6277 | * Flow control limit is violated; or the final size is beyond the | |||
6278 | * NGTCP2_MAX_VARINT. | |||
6279 | * NGTCP2_ERR_FINAL_SIZE | |||
6280 | * The final offset is strictly larger than it is permitted. | |||
6281 | */ | |||
6282 | static int conn_recv_reset_stream(ngtcp2_conn *conn, | |||
6283 | const ngtcp2_reset_stream *fr) { | |||
6284 | ngtcp2_strm *strm; | |||
6285 | int local_stream = conn_local_stream(conn, fr->stream_id); | |||
6286 | int bidi = bidi_stream(fr->stream_id); | |||
6287 | uint64_t datalen; | |||
6288 | ngtcp2_idtr *idtr; | |||
6289 | int rv; | |||
6290 | ||||
6291 | /* TODO share this piece of code */ | |||
6292 | if (bidi) { | |||
6293 | if (local_stream) { | |||
6294 | if (conn->local.bidi.next_stream_id <= fr->stream_id) { | |||
6295 | return NGTCP2_ERR_STREAM_STATE-226; | |||
6296 | } | |||
6297 | } else if (conn->remote.bidi.max_streams < | |||
6298 | ngtcp2_ord_stream_id(fr->stream_id)) { | |||
6299 | return NGTCP2_ERR_STREAM_LIMIT-213; | |||
6300 | } | |||
6301 | ||||
6302 | idtr = &conn->remote.bidi.idtr; | |||
6303 | } else { | |||
6304 | if (local_stream) { | |||
6305 | return NGTCP2_ERR_PROTO-205; | |||
6306 | } | |||
6307 | if (conn->remote.uni.max_streams < ngtcp2_ord_stream_id(fr->stream_id)) { | |||
6308 | return NGTCP2_ERR_STREAM_LIMIT-213; | |||
6309 | } | |||
6310 | ||||
6311 | idtr = &conn->remote.uni.idtr; | |||
6312 | } | |||
6313 | ||||
6314 | if (NGTCP2_MAX_VARINT((1ULL << 62) - 1) < fr->final_size) { | |||
6315 | return NGTCP2_ERR_FLOW_CONTROL-211; | |||
6316 | } | |||
6317 | ||||
6318 | strm = ngtcp2_conn_find_stream(conn, fr->stream_id); | |||
6319 | if (strm == NULL((void*)0)) { | |||
6320 | if (local_stream) { | |||
6321 | return 0; | |||
6322 | } | |||
6323 | ||||
6324 | rv = ngtcp2_idtr_open(idtr, fr->stream_id); | |||
6325 | if (rv != 0) { | |||
6326 | if (ngtcp2_err_is_fatal(rv)) { | |||
6327 | return rv; | |||
6328 | } | |||
6329 | assert(rv == NGTCP2_ERR_STREAM_IN_USE)((void) (0)); | |||
6330 | return 0; | |||
6331 | } | |||
6332 | ||||
6333 | if (conn_initial_stream_rx_offset(conn, fr->stream_id) < fr->final_size || | |||
6334 | conn_max_data_violated(conn, fr->final_size)) { | |||
6335 | return NGTCP2_ERR_FLOW_CONTROL-211; | |||
6336 | } | |||
6337 | ||||
6338 | /* Stream is reset before we create ngtcp2_strm object. */ | |||
6339 | conn->rx.offset += fr->final_size; | |||
6340 | ngtcp2_conn_extend_max_offset(conn, fr->final_size); | |||
6341 | ||||
6342 | rv = conn_call_stream_reset(conn, fr->stream_id, fr->final_size, | |||
6343 | fr->app_error_code, NULL((void*)0)); | |||
6344 | if (rv != 0) { | |||
6345 | return rv; | |||
6346 | } | |||
6347 | ||||
6348 | /* There will be no activity in this stream because we got | |||
6349 | RESET_STREAM and don't write stream data any further. This | |||
6350 | effectively allows another new stream for peer. */ | |||
6351 | if (bidi) { | |||
6352 | handle_max_remote_streams_extension(&conn->remote.bidi.unsent_max_streams, | |||
6353 | 1); | |||
6354 | } else { | |||
6355 | handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams, | |||
6356 | 1); | |||
6357 | } | |||
6358 | ||||
6359 | return 0; | |||
6360 | } | |||
6361 | ||||
6362 | if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01)) { | |||
6363 | if (strm->rx.last_offset != fr->final_size) { | |||
6364 | return NGTCP2_ERR_FINAL_SIZE-214; | |||
6365 | } | |||
6366 | } else if (strm->rx.last_offset > fr->final_size) { | |||
6367 | return NGTCP2_ERR_FINAL_SIZE-214; | |||
6368 | } | |||
6369 | ||||
6370 | datalen = fr->final_size - strm->rx.last_offset; | |||
6371 | ||||
6372 | if (strm->rx.max_offset < fr->final_size || | |||
6373 | conn_max_data_violated(conn, datalen)) { | |||
6374 | return NGTCP2_ERR_FLOW_CONTROL-211; | |||
6375 | } | |||
6376 | ||||
6377 | if (!(strm->flags & NGTCP2_STRM_FLAG_RECV_RST0x08)) { | |||
6378 | rv = conn_call_stream_reset(conn, fr->stream_id, fr->final_size, | |||
6379 | fr->app_error_code, strm->stream_user_data); | |||
6380 | if (rv != 0) { | |||
6381 | return rv; | |||
6382 | } | |||
6383 | ||||
6384 | /* Extend connection flow control window for the amount of data | |||
6385 | which are not passed to application. */ | |||
6386 | if (!(strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING0x10)) { | |||
6387 | ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset - | |||
6388 | ngtcp2_strm_rx_offset(strm)); | |||
6389 | } | |||
6390 | } | |||
6391 | ||||
6392 | conn->rx.offset += datalen; | |||
6393 | ngtcp2_conn_extend_max_offset(conn, datalen); | |||
6394 | ||||
6395 | strm->rx.last_offset = fr->final_size; | |||
6396 | strm->flags |= NGTCP2_STRM_FLAG_SHUT_RD0x01 | NGTCP2_STRM_FLAG_RECV_RST0x08; | |||
6397 | ||||
6398 | return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, fr->app_error_code); | |||
6399 | } | |||
6400 | ||||
6401 | /* | |||
6402 | * conn_recv_stop_sending is called when STOP_SENDING |fr| is received. | |||
6403 | * | |||
6404 | * This function returns 0 if it succeeds, or one of the following | |||
6405 | * negative error codes: | |||
6406 | * | |||
6407 | * NGTCP2_ERR_STREAM_STATE | |||
6408 | * STOP_SENDING frame is received for a local stream which is not | |||
6409 | * initiated; or STOP_SENDING frame is received for a local | |||
6410 | * unidirectional stream. | |||
6411 | * NGTCP2_ERR_STREAM_LIMIT | |||
6412 | * STOP_SENDING frame has remote stream ID which is strictly | |||
6413 | * greater than the allowed limit. | |||
6414 | * NGTCP2_ERR_NOMEM | |||
6415 | * Out of memory. | |||
6416 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
6417 | * User-defined callback function failed. | |||
6418 | */ | |||
6419 | static int conn_recv_stop_sending(ngtcp2_conn *conn, | |||
6420 | const ngtcp2_stop_sending *fr) { | |||
6421 | int rv; | |||
6422 | ngtcp2_strm *strm; | |||
6423 | ngtcp2_idtr *idtr; | |||
6424 | int local_stream = conn_local_stream(conn, fr->stream_id); | |||
6425 | int bidi = bidi_stream(fr->stream_id); | |||
6426 | ||||
6427 | if (bidi) { | |||
6428 | if (local_stream) { | |||
6429 | if (conn->local.bidi.next_stream_id <= fr->stream_id) { | |||
6430 | return NGTCP2_ERR_STREAM_STATE-226; | |||
6431 | } | |||
6432 | } else if (conn->remote.bidi.max_streams < | |||
6433 | ngtcp2_ord_stream_id(fr->stream_id)) { | |||
6434 | return NGTCP2_ERR_STREAM_LIMIT-213; | |||
6435 | } | |||
6436 | ||||
6437 | idtr = &conn->remote.bidi.idtr; | |||
6438 | } else { | |||
6439 | if (!local_stream || conn->local.uni.next_stream_id <= fr->stream_id) { | |||
6440 | return NGTCP2_ERR_STREAM_STATE-226; | |||
6441 | } | |||
6442 | ||||
6443 | idtr = &conn->remote.uni.idtr; | |||
6444 | } | |||
6445 | ||||
6446 | strm = ngtcp2_conn_find_stream(conn, fr->stream_id); | |||
6447 | if (strm == NULL((void*)0)) { | |||
6448 | if (local_stream) { | |||
6449 | return 0; | |||
6450 | } | |||
6451 | rv = ngtcp2_idtr_open(idtr, fr->stream_id); | |||
6452 | if (rv != 0) { | |||
6453 | if (ngtcp2_err_is_fatal(rv)) { | |||
6454 | return rv; | |||
6455 | } | |||
6456 | assert(rv == NGTCP2_ERR_STREAM_IN_USE)((void) (0)); | |||
6457 | return 0; | |||
6458 | } | |||
6459 | ||||
6460 | /* Frame is received reset before we create ngtcp2_strm | |||
6461 | object. */ | |||
6462 | strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm)); | |||
6463 | if (strm == NULL((void*)0)) { | |||
6464 | return NGTCP2_ERR_NOMEM-501; | |||
6465 | } | |||
6466 | rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL((void*)0)); | |||
6467 | if (rv != 0) { | |||
6468 | ngtcp2_mem_free(conn->mem, strm); | |||
6469 | return rv; | |||
6470 | } | |||
6471 | } | |||
6472 | ||||
6473 | /* No RESET_STREAM is required if we have sent FIN and all data have | |||
6474 | been acknowledged. */ | |||
6475 | if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_WR0x02) && | |||
6476 | ngtcp2_strm_is_all_tx_data_acked(strm)) { | |||
6477 | return 0; | |||
6478 | } | |||
6479 | ||||
6480 | rv = conn_reset_stream(conn, strm, fr->app_error_code); | |||
6481 | if (rv != 0) { | |||
6482 | return rv; | |||
6483 | } | |||
6484 | ||||
6485 | strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR0x02 | NGTCP2_STRM_FLAG_SENT_RST0x04; | |||
6486 | ||||
6487 | ngtcp2_strm_streamfrq_clear(strm); | |||
6488 | ||||
6489 | return ngtcp2_conn_close_stream_if_shut_rdwr(conn, strm, fr->app_error_code); | |||
6490 | } | |||
6491 | ||||
6492 | /* | |||
6493 | * check_stateless_reset returns nonzero if Stateless Reset |sr| | |||
6494 | * coming via |path| is valid against |dcid|. | |||
6495 | */ | |||
6496 | static int check_stateless_reset(const ngtcp2_dcid *dcid, | |||
6497 | const ngtcp2_path *path, | |||
6498 | const ngtcp2_pkt_stateless_reset *sr) { | |||
6499 | return ngtcp2_path_eq(&dcid->ps.path, path) && | |||
6500 | ngtcp2_verify_stateless_reset_token(dcid->token, | |||
6501 | sr->stateless_reset_token) == 0; | |||
6502 | } | |||
6503 | ||||
6504 | /* | |||
6505 | * conn_on_stateless_reset decodes Stateless Reset from the buffer | |||
6506 | * pointed by |payload| whose length is |payloadlen|. |payload| | |||
6507 | * should start after first byte of packet. | |||
6508 | * | |||
6509 | * If Stateless Reset is decoded, and the Stateless Reset Token is | |||
6510 | * validated, the connection is closed. | |||
6511 | * | |||
6512 | * This function returns 0 if it succeeds, or one of the following | |||
6513 | * negative error codes: | |||
6514 | * | |||
6515 | * NGTCP2_ERR_INVALID_ARGUMENT | |||
6516 | * Could not decode Stateless Reset; or Stateless Reset Token does | |||
6517 | * not match; or No stateless reset token is available. | |||
6518 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
6519 | * User callback failed. | |||
6520 | */ | |||
6521 | static int conn_on_stateless_reset(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
6522 | const uint8_t *payload, size_t payloadlen) { | |||
6523 | int rv = 1; | |||
6524 | ngtcp2_pv *pv = conn->pv; | |||
6525 | ngtcp2_dcid *dcid; | |||
6526 | ngtcp2_pkt_stateless_reset sr; | |||
6527 | size_t len, i; | |||
6528 | ||||
6529 | rv = ngtcp2_pkt_decode_stateless_reset(&sr, payload, payloadlen); | |||
6530 | if (rv != 0) { | |||
6531 | return rv; | |||
6532 | } | |||
6533 | ||||
6534 | if (!check_stateless_reset(&conn->dcid.current, path, &sr) && | |||
6535 | (!pv || (!check_stateless_reset(&pv->dcid, path, &sr) && | |||
6536 | (!(pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) || | |||
6537 | !check_stateless_reset(&pv->fallback_dcid, path, &sr))))) { | |||
6538 | len = ngtcp2_ringbuf_len(&conn->dcid.retired)((&conn->dcid.retired)->len); | |||
6539 | for (i = 0; i < len; ++i) { | |||
6540 | dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, i); | |||
6541 | if (check_stateless_reset(dcid, path, &sr)) { | |||
6542 | break; | |||
6543 | } | |||
6544 | } | |||
6545 | ||||
6546 | if (i == len) { | |||
6547 | len = ngtcp2_ringbuf_len(&conn->dcid.bound)((&conn->dcid.bound)->len); | |||
6548 | for (i = 0; i < len; ++i) { | |||
6549 | dcid = ngtcp2_ringbuf_get(&conn->dcid.bound, i); | |||
6550 | if (check_stateless_reset(dcid, path, &sr)) { | |||
6551 | break; | |||
6552 | } | |||
6553 | } | |||
6554 | ||||
6555 | if (i == len) { | |||
6556 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
6557 | } | |||
6558 | } | |||
6559 | } | |||
6560 | ||||
6561 | conn->state = NGTCP2_CS_DRAINING; | |||
6562 | ||||
6563 | ngtcp2_log_rx_sr(&conn->log, &sr); | |||
6564 | ||||
6565 | if (!conn->callbacks.recv_stateless_reset) { | |||
6566 | return 0; | |||
6567 | } | |||
6568 | ||||
6569 | rv = conn->callbacks.recv_stateless_reset(conn, &sr, conn->user_data); | |||
6570 | if (rv != 0) { | |||
6571 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
6572 | } | |||
6573 | ||||
6574 | return 0; | |||
6575 | } | |||
6576 | ||||
6577 | /* | |||
6578 | * conn_recv_max_streams processes the incoming MAX_STREAMS frame | |||
6579 | * |fr|. | |||
6580 | * | |||
6581 | * This function returns 0 if it succeeds, or one of the following | |||
6582 | * negative error codes: | |||
6583 | * | |||
6584 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
6585 | * User callback failed. | |||
6586 | * NGTCP2_ERR_FRAME_ENCODING | |||
6587 | * The maximum streams field exceeds the maximum value. | |||
6588 | */ | |||
6589 | static int conn_recv_max_streams(ngtcp2_conn *conn, | |||
6590 | const ngtcp2_max_streams *fr) { | |||
6591 | uint64_t n; | |||
6592 | ||||
6593 | if (fr->max_streams > NGTCP2_MAX_STREAMS(1LL << 60)) { | |||
6594 | return NGTCP2_ERR_FRAME_ENCODING-219; | |||
6595 | } | |||
6596 | ||||
6597 | n = ngtcp2_min(fr->max_streams, NGTCP2_MAX_STREAMS)((fr->max_streams) < ((1LL << 60)) ? (fr->max_streams ) : ((1LL << 60))); | |||
6598 | ||||
6599 | if (fr->type == NGTCP2_FRAME_MAX_STREAMS_BIDI) { | |||
6600 | if (conn->local.bidi.max_streams < n) { | |||
6601 | conn->local.bidi.max_streams = n; | |||
6602 | return conn_call_extend_max_local_streams_bidi(conn, n); | |||
6603 | } | |||
6604 | return 0; | |||
6605 | } | |||
6606 | ||||
6607 | if (conn->local.uni.max_streams < n) { | |||
6608 | conn->local.uni.max_streams = n; | |||
6609 | return conn_call_extend_max_local_streams_uni(conn, n); | |||
6610 | } | |||
6611 | return 0; | |||
6612 | } | |||
6613 | ||||
6614 | static int conn_retire_dcid_prior_to(ngtcp2_conn *conn, ngtcp2_ringbuf *rb, | |||
6615 | uint64_t retire_prior_to) { | |||
6616 | size_t i; | |||
6617 | ngtcp2_dcid *dcid, *last; | |||
6618 | int rv; | |||
6619 | ||||
6620 | for (i = 0; i < ngtcp2_ringbuf_len(rb)((rb)->len);) { | |||
6621 | dcid = ngtcp2_ringbuf_get(rb, i); | |||
6622 | if (dcid->seq >= retire_prior_to) { | |||
6623 | ++i; | |||
6624 | continue; | |||
6625 | } | |||
6626 | ||||
6627 | rv = conn_retire_dcid_seq(conn, dcid->seq); | |||
6628 | if (rv != 0) { | |||
6629 | return rv; | |||
6630 | } | |||
6631 | if (i == 0) { | |||
6632 | ngtcp2_ringbuf_pop_front(rb); | |||
6633 | } else if (i == ngtcp2_ringbuf_len(rb)((rb)->len) - 1) { | |||
6634 | ngtcp2_ringbuf_pop_back(rb); | |||
6635 | break; | |||
6636 | } else { | |||
6637 | last = ngtcp2_ringbuf_get(rb, ngtcp2_ringbuf_len(rb)((rb)->len) - 1); | |||
6638 | ngtcp2_dcid_copy(dcid, last); | |||
6639 | ngtcp2_ringbuf_pop_back(rb); | |||
6640 | } | |||
6641 | } | |||
6642 | ||||
6643 | return 0; | |||
6644 | } | |||
6645 | ||||
6646 | /* | |||
6647 | * conn_recv_new_connection_id processes the incoming | |||
6648 | * NEW_CONNECTION_ID frame |fr|. | |||
6649 | * | |||
6650 | * This function returns 0 if it succeeds, or one of the following | |||
6651 | * negative error codes: | |||
6652 | * | |||
6653 | * NGTCP2_ERR_PROTO | |||
6654 | * |fr| has the duplicated sequence number with different CID or | |||
6655 | * token; or DCID is zero-length. | |||
6656 | */ | |||
6657 | static int conn_recv_new_connection_id(ngtcp2_conn *conn, | |||
6658 | const ngtcp2_new_connection_id *fr) { | |||
6659 | size_t i, len; | |||
6660 | ngtcp2_dcid *dcid; | |||
6661 | ngtcp2_pv *pv = conn->pv; | |||
6662 | int rv; | |||
6663 | int found = 0; | |||
6664 | size_t extra_dcid = 0; | |||
6665 | ||||
6666 | if (conn->dcid.current.cid.datalen == 0) { | |||
6667 | return NGTCP2_ERR_PROTO-205; | |||
6668 | } | |||
6669 | ||||
6670 | if (fr->retire_prior_to > fr->seq) { | |||
6671 | return NGTCP2_ERR_FRAME_ENCODING-219; | |||
6672 | } | |||
6673 | ||||
6674 | rv = ngtcp2_dcid_verify_uniqueness(&conn->dcid.current, fr->seq, &fr->cid, | |||
6675 | fr->stateless_reset_token); | |||
6676 | if (rv != 0) { | |||
6677 | return rv; | |||
6678 | } | |||
6679 | if (ngtcp2_cid_eq(&conn->dcid.current.cid, &fr->cid)) { | |||
6680 | found = 1; | |||
6681 | } | |||
6682 | ||||
6683 | if (pv) { | |||
6684 | rv = ngtcp2_dcid_verify_uniqueness(&pv->dcid, fr->seq, &fr->cid, | |||
6685 | fr->stateless_reset_token); | |||
6686 | if (rv != 0) { | |||
6687 | return rv; | |||
6688 | } | |||
6689 | if (ngtcp2_cid_eq(&pv->dcid.cid, &fr->cid)) { | |||
6690 | found = 1; | |||
6691 | } | |||
6692 | } | |||
6693 | ||||
6694 | len = ngtcp2_ringbuf_len(&conn->dcid.bound)((&conn->dcid.bound)->len); | |||
6695 | ||||
6696 | for (i = 0; i < len; ++i) { | |||
6697 | dcid = ngtcp2_ringbuf_get(&conn->dcid.bound, i); | |||
6698 | rv = ngtcp2_dcid_verify_uniqueness(dcid, fr->seq, &fr->cid, | |||
6699 | fr->stateless_reset_token); | |||
6700 | if (rv != 0) { | |||
6701 | return NGTCP2_ERR_PROTO-205; | |||
6702 | } | |||
6703 | if (ngtcp2_cid_eq(&dcid->cid, &fr->cid)) { | |||
6704 | found = 1; | |||
6705 | } | |||
6706 | } | |||
6707 | ||||
6708 | len = ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len); | |||
6709 | ||||
6710 | for (i = 0; i < len; ++i) { | |||
6711 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, i); | |||
6712 | rv = ngtcp2_dcid_verify_uniqueness(dcid, fr->seq, &fr->cid, | |||
6713 | fr->stateless_reset_token); | |||
6714 | if (rv != 0) { | |||
6715 | return NGTCP2_ERR_PROTO-205; | |||
6716 | } | |||
6717 | if (ngtcp2_cid_eq(&dcid->cid, &fr->cid)) { | |||
6718 | found = 1; | |||
6719 | } | |||
6720 | } | |||
6721 | ||||
6722 | if (conn->dcid.retire_prior_to < fr->retire_prior_to) { | |||
6723 | conn->dcid.retire_prior_to = fr->retire_prior_to; | |||
6724 | ||||
6725 | rv = | |||
6726 | conn_retire_dcid_prior_to(conn, &conn->dcid.bound, fr->retire_prior_to); | |||
6727 | if (rv != 0) { | |||
6728 | return rv; | |||
6729 | } | |||
6730 | ||||
6731 | rv = conn_retire_dcid_prior_to(conn, &conn->dcid.unused, | |||
6732 | conn->dcid.retire_prior_to); | |||
6733 | if (rv != 0) { | |||
6734 | return rv; | |||
6735 | } | |||
6736 | } else if (fr->seq < conn->dcid.retire_prior_to) { | |||
6737 | /* If packets are reordered, we might have retire_prior_to which | |||
6738 | is larger than fr->seq. | |||
6739 | ||||
6740 | A malicious peer might send crafted NEW_CONNECTION_ID to force | |||
6741 | local endpoint to create lots of RETIRE_CONNECTION_ID frames. | |||
6742 | For example, a peer might send seq = 50000 and retire_prior_to | |||
6743 | = 50000. Then send NEW_CONNECTION_ID frames with seq < | |||
6744 | 50000. */ | |||
6745 | /* TODO we might queue lots of RETIRE_CONNECTION_ID frame here | |||
6746 | because conn->dcid.num_retire_queued is incremented when the | |||
6747 | frame is serialized. */ | |||
6748 | if (conn->dcid.num_retire_queued < NGTCP2_MAX_DCID_POOL_SIZE8 * 2) { | |||
6749 | return conn_retire_dcid_seq(conn, fr->seq); | |||
6750 | } | |||
6751 | return 0; | |||
6752 | } | |||
6753 | ||||
6754 | if (found) { | |||
6755 | return 0; | |||
6756 | } | |||
6757 | ||||
6758 | if (ngtcp2_gaptr_is_pushed(&conn->dcid.seqgap, fr->seq, 1)) { | |||
6759 | return 0; | |||
6760 | } | |||
6761 | ||||
6762 | rv = ngtcp2_gaptr_push(&conn->dcid.seqgap, fr->seq, 1); | |||
6763 | if (rv != 0) { | |||
6764 | return rv; | |||
6765 | } | |||
6766 | ||||
6767 | if (ngtcp2_ksl_len(&conn->dcid.seqgap.gap) > 32) { | |||
6768 | ngtcp2_gaptr_drop_first_gap(&conn->dcid.seqgap); | |||
6769 | } | |||
6770 | ||||
6771 | len = ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len); | |||
6772 | ||||
6773 | if (conn->dcid.current.seq >= conn->dcid.retire_prior_to) { | |||
6774 | ++extra_dcid; | |||
6775 | } | |||
6776 | if (pv) { | |||
6777 | if (pv->dcid.seq != conn->dcid.current.seq && | |||
6778 | pv->dcid.seq >= conn->dcid.retire_prior_to) { | |||
6779 | ++extra_dcid; | |||
6780 | } | |||
6781 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
6782 | pv->fallback_dcid.seq != conn->dcid.current.seq && | |||
6783 | pv->fallback_dcid.seq >= conn->dcid.retire_prior_to) { | |||
6784 | ++extra_dcid; | |||
6785 | } | |||
6786 | } | |||
6787 | ||||
6788 | if (conn->local.transport_params.active_connection_id_limit <= | |||
6789 | len + extra_dcid) { | |||
6790 | return NGTCP2_ERR_CONNECTION_ID_LIMIT-212; | |||
6791 | } | |||
6792 | ||||
6793 | if (len >= NGTCP2_MAX_DCID_POOL_SIZE8) { | |||
6794 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "too many connection ID"); | |||
6795 | return 0; | |||
6796 | } | |||
6797 | ||||
6798 | dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused); | |||
6799 | ngtcp2_dcid_init(dcid, fr->seq, &fr->cid, fr->stateless_reset_token); | |||
6800 | ||||
6801 | return 0; | |||
6802 | } | |||
6803 | ||||
6804 | /* | |||
6805 | * conn_post_process_recv_new_connection_id handles retirement request | |||
6806 | * of active DCIDs. | |||
6807 | * | |||
6808 | * This function returns 0 if it succeeds, or one of the following | |||
6809 | * negative error codes: | |||
6810 | * | |||
6811 | * NGTCP2_ERR_NOMEM | |||
6812 | * Out of memory. | |||
6813 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
6814 | * User-defined callback function failed. | |||
6815 | */ | |||
6816 | static int conn_post_process_recv_new_connection_id(ngtcp2_conn *conn, | |||
6817 | ngtcp2_tstamp ts) { | |||
6818 | ngtcp2_pv *pv = conn->pv; | |||
6819 | ngtcp2_dcid *dcid; | |||
6820 | int rv; | |||
6821 | ||||
6822 | if (conn->dcid.current.seq < conn->dcid.retire_prior_to) { | |||
6823 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len) == 0) { | |||
6824 | return 0; | |||
6825 | } | |||
6826 | ||||
6827 | rv = conn_retire_dcid(conn, &conn->dcid.current, ts); | |||
6828 | if (rv != 0) { | |||
6829 | return rv; | |||
6830 | } | |||
6831 | ||||
6832 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0); | |||
6833 | if (pv) { | |||
6834 | if (conn->dcid.current.seq == pv->dcid.seq) { | |||
6835 | ngtcp2_dcid_copy_cid_token(&pv->dcid, dcid); | |||
6836 | } | |||
6837 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
6838 | conn->dcid.current.seq == pv->fallback_dcid.seq) { | |||
6839 | ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, dcid); | |||
6840 | } | |||
6841 | } | |||
6842 | ||||
6843 | ngtcp2_dcid_copy_cid_token(&conn->dcid.current, dcid); | |||
6844 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
6845 | ||||
6846 | rv = conn_call_activate_dcid(conn, &conn->dcid.current); | |||
6847 | if (rv != 0) { | |||
6848 | return rv; | |||
6849 | } | |||
6850 | } | |||
6851 | ||||
6852 | if (pv) { | |||
6853 | if (pv->dcid.seq < conn->dcid.retire_prior_to) { | |||
6854 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len)) { | |||
6855 | rv = conn_retire_dcid(conn, &pv->dcid, ts); | |||
6856 | if (rv != 0) { | |||
6857 | return rv; | |||
6858 | } | |||
6859 | ||||
6860 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0); | |||
6861 | ||||
6862 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
6863 | pv->dcid.seq == pv->fallback_dcid.seq) { | |||
6864 | ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, dcid); | |||
6865 | } | |||
6866 | ||||
6867 | ngtcp2_dcid_copy_cid_token(&pv->dcid, dcid); | |||
6868 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
6869 | ||||
6870 | rv = conn_call_activate_dcid(conn, &pv->dcid); | |||
6871 | if (rv != 0) { | |||
6872 | return rv; | |||
6873 | } | |||
6874 | } else { | |||
6875 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV, | |||
6876 | "path migration is aborted because connection ID is" | |||
6877 | "retired and no unused connection ID is available"); | |||
6878 | ||||
6879 | return conn_stop_pv(conn, ts); | |||
6880 | } | |||
6881 | } | |||
6882 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
6883 | pv->fallback_dcid.seq < conn->dcid.retire_prior_to) { | |||
6884 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len)) { | |||
6885 | rv = conn_retire_dcid(conn, &pv->fallback_dcid, ts); | |||
6886 | if (rv != 0) { | |||
6887 | return rv; | |||
6888 | } | |||
6889 | ||||
6890 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0); | |||
6891 | ngtcp2_dcid_copy_cid_token(&pv->fallback_dcid, dcid); | |||
6892 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
6893 | ||||
6894 | rv = conn_call_activate_dcid(conn, &pv->fallback_dcid); | |||
6895 | if (rv != 0) { | |||
6896 | return rv; | |||
6897 | } | |||
6898 | } else { | |||
6899 | /* Now we have no fallback dcid. */ | |||
6900 | return conn_stop_pv(conn, ts); | |||
6901 | } | |||
6902 | } | |||
6903 | } | |||
6904 | ||||
6905 | return 0; | |||
6906 | } | |||
6907 | ||||
6908 | /* | |||
6909 | * conn_recv_retire_connection_id processes the incoming | |||
6910 | * RETIRE_CONNECTION_ID frame |fr|. |hd| is a packet header which | |||
6911 | * |fr| is included. | |||
6912 | * | |||
6913 | * This function returns 0 if it succeeds, or one of the following | |||
6914 | * negative error codes: | |||
6915 | * | |||
6916 | * NGTCP2_ERR_NOMEM | |||
6917 | * Out of memory. | |||
6918 | * NGTCP2_ERR_PROTO | |||
6919 | * SCID is zero-length. | |||
6920 | * NGTCP2_ERR_FRAME_ENCODING | |||
6921 | * Attempt to retire CID which is used as DCID to send this frame. | |||
6922 | */ | |||
6923 | static int conn_recv_retire_connection_id(ngtcp2_conn *conn, | |||
6924 | const ngtcp2_pkt_hd *hd, | |||
6925 | const ngtcp2_retire_connection_id *fr, | |||
6926 | ngtcp2_tstamp ts) { | |||
6927 | ngtcp2_ksl_it it; | |||
6928 | ngtcp2_scid *scid; | |||
6929 | ||||
6930 | if (conn->oscid.datalen == 0 || conn->scid.last_seq < fr->seq) { | |||
6931 | return NGTCP2_ERR_PROTO-205; | |||
6932 | } | |||
6933 | ||||
6934 | for (it = ngtcp2_ksl_begin(&conn->scid.set); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
6935 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
6936 | scid = ngtcp2_ksl_it_get(&it); | |||
6937 | if (scid->seq == fr->seq) { | |||
6938 | if (ngtcp2_cid_eq(&scid->cid, &hd->dcid)) { | |||
6939 | return NGTCP2_ERR_PROTO-205; | |||
6940 | } | |||
6941 | ||||
6942 | if (!(scid->flags & NGTCP2_SCID_FLAG_RETIRED0x02)) { | |||
6943 | scid->flags |= NGTCP2_SCID_FLAG_RETIRED0x02; | |||
6944 | ++conn->scid.num_retired; | |||
6945 | } | |||
6946 | ||||
6947 | if (scid->pe.index != NGTCP2_PQ_BAD_INDEX(18446744073709551615UL)) { | |||
6948 | ngtcp2_pq_remove(&conn->scid.used, &scid->pe); | |||
6949 | scid->pe.index = NGTCP2_PQ_BAD_INDEX(18446744073709551615UL); | |||
6950 | } | |||
6951 | ||||
6952 | scid->ts_retired = ts; | |||
6953 | ||||
6954 | return ngtcp2_pq_push(&conn->scid.used, &scid->pe); | |||
6955 | } | |||
6956 | } | |||
6957 | ||||
6958 | return 0; | |||
6959 | } | |||
6960 | ||||
6961 | /* | |||
6962 | * conn_recv_new_token processes the incoming NEW_TOKEN frame |fr|. | |||
6963 | * | |||
6964 | * This function returns 0 if it succeeds, or one of the following | |||
6965 | * negative error codes: | |||
6966 | * | |||
6967 | * NGTCP2_ERR_FRAME_ENCODING | |||
6968 | * Token is empty | |||
6969 | * NGTCP2_ERR_PROTO: | |||
6970 | * Server received NEW_TOKEN. | |||
6971 | */ | |||
6972 | static int conn_recv_new_token(ngtcp2_conn *conn, const ngtcp2_new_token *fr) { | |||
6973 | int rv; | |||
6974 | ||||
6975 | if (conn->server) { | |||
6976 | return NGTCP2_ERR_PROTO-205; | |||
6977 | } | |||
6978 | ||||
6979 | if (fr->token.len == 0) { | |||
6980 | return NGTCP2_ERR_FRAME_ENCODING-219; | |||
6981 | } | |||
6982 | ||||
6983 | if (conn->callbacks.recv_new_token) { | |||
6984 | rv = conn->callbacks.recv_new_token(conn, &fr->token, conn->user_data); | |||
6985 | if (rv != 0) { | |||
6986 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
6987 | } | |||
6988 | } | |||
6989 | ||||
6990 | return 0; | |||
6991 | } | |||
6992 | ||||
6993 | /* | |||
6994 | * conn_recv_streams_blocked_bidi processes the incoming | |||
6995 | * STREAMS_BLOCKED (0x16). | |||
6996 | * | |||
6997 | * This function returns 0 if it succeeds, or one of the following | |||
6998 | * negative error codes: | |||
6999 | * | |||
7000 | * NGTCP2_ERR_FRAME_ENCODING | |||
7001 | * Maximum Streams is larger than advertised value. | |||
7002 | */ | |||
7003 | static int conn_recv_streams_blocked_bidi(ngtcp2_conn *conn, | |||
7004 | ngtcp2_streams_blocked *fr) { | |||
7005 | if (fr->max_streams > conn->remote.bidi.max_streams) { | |||
7006 | return NGTCP2_ERR_FRAME_ENCODING-219; | |||
7007 | } | |||
7008 | ||||
7009 | return 0; | |||
7010 | } | |||
7011 | ||||
7012 | /* | |||
7013 | * conn_recv_streams_blocked_uni processes the incoming | |||
7014 | * STREAMS_BLOCKED (0x17). | |||
7015 | * | |||
7016 | * This function returns 0 if it succeeds, or one of the following | |||
7017 | * negative error codes: | |||
7018 | * | |||
7019 | * NGTCP2_ERR_FRAME_ENCODING | |||
7020 | * Maximum Streams is larger than advertised value. | |||
7021 | */ | |||
7022 | static int conn_recv_streams_blocked_uni(ngtcp2_conn *conn, | |||
7023 | ngtcp2_streams_blocked *fr) { | |||
7024 | if (fr->max_streams > conn->remote.uni.max_streams) { | |||
7025 | return NGTCP2_ERR_FRAME_ENCODING-219; | |||
7026 | } | |||
7027 | ||||
7028 | return 0; | |||
7029 | } | |||
7030 | ||||
7031 | /* | |||
7032 | * conn_select_preferred_addr asks a client application to select a | |||
7033 | * server address from preferred addresses received from server. If a | |||
7034 | * client chooses the address, path validation will start. | |||
7035 | * | |||
7036 | * This function returns 0 if it succeeds, or one of the following | |||
7037 | * negative error codes: | |||
7038 | * | |||
7039 | * NGTCP2_ERR_NOMEM | |||
7040 | * Out of memory. | |||
7041 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
7042 | * User-defined callback function failed. | |||
7043 | */ | |||
7044 | static int conn_select_preferred_addr(ngtcp2_conn *conn) { | |||
7045 | struct sockaddr_storage buf; | |||
7046 | ngtcp2_addr addr; | |||
7047 | int rv; | |||
7048 | ngtcp2_duration pto, initial_pto, timeout; | |||
7049 | ngtcp2_pv *pv; | |||
7050 | ngtcp2_dcid *dcid; | |||
7051 | ||||
7052 | ngtcp2_addr_init(&addr, (struct sockaddr *)&buf, 0, NULL((void*)0)); | |||
7053 | ||||
7054 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len) == 0) { | |||
7055 | return 0; | |||
7056 | } | |||
7057 | ||||
7058 | rv = conn_call_select_preferred_addr(conn, &addr); | |||
7059 | if (rv != 0) { | |||
7060 | return rv; | |||
7061 | } | |||
7062 | ||||
7063 | if (addr.addrlen == 0 || | |||
7064 | ngtcp2_addr_eq(&conn->dcid.current.ps.path.remote, &addr)) { | |||
7065 | return 0; | |||
7066 | } | |||
7067 | ||||
7068 | assert(conn->pv == NULL)((void) (0)); | |||
7069 | ||||
7070 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0); | |||
7071 | pto = conn_compute_pto(conn, &conn->pktns); | |||
7072 | initial_pto = conn_compute_initial_pto(conn, &conn->pktns); | |||
7073 | timeout = 3 * ngtcp2_max(pto, initial_pto)((pto) > (initial_pto) ? (pto) : (initial_pto)); | |||
7074 | ||||
7075 | rv = ngtcp2_pv_new(&pv, dcid, timeout, NGTCP2_PV_FLAG_NONE0x00, &conn->log, | |||
7076 | conn->mem); | |||
7077 | if (rv != 0) { | |||
7078 | /* TODO Call ngtcp2_dcid_free here if it is introduced */ | |||
7079 | return rv; | |||
7080 | } | |||
7081 | ||||
7082 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
7083 | conn->pv = pv; | |||
7084 | ||||
7085 | ngtcp2_addr_copy(&pv->dcid.ps.path.local, &conn->dcid.current.ps.path.local); | |||
7086 | ngtcp2_addr_copy(&pv->dcid.ps.path.remote, &addr); | |||
7087 | ||||
7088 | return conn_call_activate_dcid(conn, &pv->dcid); | |||
7089 | } | |||
7090 | ||||
7091 | /* | |||
7092 | * conn_recv_handshake_done processes the incoming HANDSHAKE_DONE | |||
7093 | * frame |fr|. | |||
7094 | * | |||
7095 | * This function returns 0 if it succeeds, or one of the following | |||
7096 | * negative error codes: | |||
7097 | * | |||
7098 | * NGTCP2_ERR_PROTO | |||
7099 | * Server received HANDSHAKE_DONE frame. | |||
7100 | * NGTCP2_ERR_NOMEM | |||
7101 | * Out of memory. | |||
7102 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
7103 | * User-defined callback function failed. | |||
7104 | */ | |||
7105 | static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
7106 | int rv; | |||
7107 | ||||
7108 | if (conn->server) { | |||
7109 | return NGTCP2_ERR_PROTO-205; | |||
7110 | } | |||
7111 | ||||
7112 | if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80) { | |||
7113 | return 0; | |||
7114 | } | |||
7115 | ||||
7116 | conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80 | | |||
7117 | NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000; | |||
7118 | ||||
7119 | conn->pktns.rtb.persistent_congestion_start_ts = ts; | |||
7120 | ||||
7121 | conn_discard_handshake_state(conn, ts); | |||
7122 | ||||
7123 | if (conn->remote.transport_params.preferred_address_present) { | |||
7124 | rv = conn_select_preferred_addr(conn); | |||
7125 | if (rv != 0) { | |||
7126 | return rv; | |||
7127 | } | |||
7128 | } | |||
7129 | ||||
7130 | if (conn->callbacks.handshake_confirmed) { | |||
7131 | rv = conn->callbacks.handshake_confirmed(conn, conn->user_data); | |||
7132 | if (rv != 0) { | |||
7133 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
7134 | } | |||
7135 | } | |||
7136 | ||||
7137 | /* Re-arm loss detection timer after handshake has been | |||
7138 | confirmed. */ | |||
7139 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
7140 | ||||
7141 | return 0; | |||
7142 | } | |||
7143 | ||||
7144 | /* | |||
7145 | * conn_recv_datagram processes the incoming DATAGRAM frame |fr|. | |||
7146 | * | |||
7147 | * This function returns 0 if it succeeds, or one of the following | |||
7148 | * negative error codes: | |||
7149 | * | |||
7150 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
7151 | * User-defined callback function failed. | |||
7152 | */ | |||
7153 | static int conn_recv_datagram(ngtcp2_conn *conn, ngtcp2_datagram *fr) { | |||
7154 | const uint8_t *data; | |||
7155 | size_t datalen; | |||
7156 | int rv; | |||
7157 | uint32_t flags = NGTCP2_DATAGRAM_FLAG_NONE0x00; | |||
7158 | ||||
7159 | assert(conn->local.transport_params.max_datagram_frame_size)((void) (0)); | |||
7160 | ||||
7161 | if (!conn->callbacks.recv_datagram) { | |||
7162 | return 0; | |||
7163 | } | |||
7164 | ||||
7165 | if (fr->datacnt) { | |||
7166 | assert(fr->datacnt == 1)((void) (0)); | |||
7167 | ||||
7168 | data = fr->data->base; | |||
7169 | datalen = fr->data->len; | |||
7170 | } else { | |||
7171 | data = NULL((void*)0); | |||
7172 | datalen = 0; | |||
7173 | } | |||
7174 | ||||
7175 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
7176 | flags |= NGTCP2_DATAGRAM_FLAG_EARLY0x01; | |||
7177 | } | |||
7178 | ||||
7179 | rv = conn->callbacks.recv_datagram(conn, flags, data, datalen, | |||
7180 | conn->user_data); | |||
7181 | if (rv != 0) { | |||
7182 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
7183 | } | |||
7184 | ||||
7185 | return 0; | |||
7186 | } | |||
7187 | ||||
7188 | /* | |||
7189 | * conn_key_phase_changed returns nonzero if |hd| indicates that the | |||
7190 | * key phase has unexpected value. | |||
7191 | */ | |||
7192 | static int conn_key_phase_changed(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd) { | |||
7193 | ngtcp2_pktns *pktns = &conn->pktns; | |||
7194 | ||||
7195 | return !(pktns->crypto.rx.ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE0x01) ^ | |||
7196 | !(hd->flags & NGTCP2_PKT_FLAG_KEY_PHASE0x04); | |||
7197 | } | |||
7198 | ||||
7199 | /* | |||
7200 | * conn_prepare_key_update installs new updated keys. | |||
7201 | */ | |||
7202 | static int conn_prepare_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
7203 | int rv; | |||
7204 | ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts; | |||
7205 | ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); | |||
7206 | ngtcp2_pktns *pktns = &conn->pktns; | |||
7207 | ngtcp2_crypto_km *rx_ckm = pktns->crypto.rx.ckm; | |||
7208 | ngtcp2_crypto_km *tx_ckm = pktns->crypto.tx.ckm; | |||
7209 | ngtcp2_crypto_km *new_rx_ckm, *new_tx_ckm; | |||
7210 | ngtcp2_crypto_aead_ctx rx_aead_ctx = {0}, tx_aead_ctx = {0}; | |||
7211 | size_t secretlen, ivlen; | |||
7212 | ||||
7213 | if ((conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80) && | |||
7214 | tx_ckm->use_count >= pktns->crypto.ctx.max_encryption && | |||
7215 | ngtcp2_conn_initiate_key_update(conn, ts) != 0) { | |||
7216 | return NGTCP2_ERR_AEAD_LIMIT_REACHED-243; | |||
7217 | } | |||
7218 | ||||
7219 | if ((conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED0x0800) || | |||
7220 | (confirmed_ts != UINT64_MAX(18446744073709551615UL) && confirmed_ts + pto > ts)) { | |||
7221 | return 0; | |||
7222 | } | |||
7223 | ||||
7224 | if (conn->crypto.key_update.new_rx_ckm || | |||
7225 | conn->crypto.key_update.new_tx_ckm) { | |||
7226 | assert(conn->crypto.key_update.new_rx_ckm)((void) (0)); | |||
7227 | assert(conn->crypto.key_update.new_tx_ckm)((void) (0)); | |||
7228 | return 0; | |||
7229 | } | |||
7230 | ||||
7231 | secretlen = rx_ckm->secret.len; | |||
7232 | ivlen = rx_ckm->iv.len; | |||
7233 | ||||
7234 | rv = ngtcp2_crypto_km_nocopy_new(&conn->crypto.key_update.new_rx_ckm, | |||
7235 | secretlen, ivlen, conn->mem); | |||
7236 | if (rv != 0) { | |||
7237 | return rv; | |||
7238 | } | |||
7239 | ||||
7240 | rv = ngtcp2_crypto_km_nocopy_new(&conn->crypto.key_update.new_tx_ckm, | |||
7241 | secretlen, ivlen, conn->mem); | |||
7242 | if (rv != 0) { | |||
7243 | return rv; | |||
7244 | } | |||
7245 | ||||
7246 | new_rx_ckm = conn->crypto.key_update.new_rx_ckm; | |||
7247 | new_tx_ckm = conn->crypto.key_update.new_tx_ckm; | |||
7248 | ||||
7249 | assert(conn->callbacks.update_key)((void) (0)); | |||
7250 | ||||
7251 | rv = conn->callbacks.update_key( | |||
7252 | conn, new_rx_ckm->secret.base, new_tx_ckm->secret.base, &rx_aead_ctx, | |||
7253 | new_rx_ckm->iv.base, &tx_aead_ctx, new_tx_ckm->iv.base, | |||
7254 | rx_ckm->secret.base, tx_ckm->secret.base, secretlen, conn->user_data); | |||
7255 | if (rv != 0) { | |||
7256 | return NGTCP2_ERR_CALLBACK_FAILURE-502; | |||
7257 | } | |||
7258 | ||||
7259 | new_rx_ckm->aead_ctx = rx_aead_ctx; | |||
7260 | new_tx_ckm->aead_ctx = tx_aead_ctx; | |||
7261 | ||||
7262 | if (!(rx_ckm->flags & NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE0x01)) { | |||
7263 | new_rx_ckm->flags |= NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE0x01; | |||
7264 | new_tx_ckm->flags |= NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE0x01; | |||
7265 | } | |||
7266 | ||||
7267 | if (conn->crypto.key_update.old_rx_ckm) { | |||
7268 | conn_call_delete_crypto_aead_ctx( | |||
7269 | conn, &conn->crypto.key_update.old_rx_ckm->aead_ctx); | |||
7270 | ngtcp2_crypto_km_del(conn->crypto.key_update.old_rx_ckm, conn->mem); | |||
7271 | conn->crypto.key_update.old_rx_ckm = NULL((void*)0); | |||
7272 | } | |||
7273 | ||||
7274 | return 0; | |||
7275 | } | |||
7276 | ||||
7277 | /* | |||
7278 | * conn_rotate_keys rotates keys. The current key moves to old key, | |||
7279 | * and new key moves to the current key. | |||
7280 | */ | |||
7281 | static void conn_rotate_keys(ngtcp2_conn *conn, int64_t pkt_num) { | |||
7282 | ngtcp2_pktns *pktns = &conn->pktns; | |||
7283 | ||||
7284 | assert(conn->crypto.key_update.new_rx_ckm)((void) (0)); | |||
7285 | assert(conn->crypto.key_update.new_tx_ckm)((void) (0)); | |||
7286 | assert(!conn->crypto.key_update.old_rx_ckm)((void) (0)); | |||
7287 | assert(!(conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING))((void) (0)); | |||
7288 | ||||
7289 | conn->crypto.key_update.old_rx_ckm = pktns->crypto.rx.ckm; | |||
7290 | ||||
7291 | pktns->crypto.rx.ckm = conn->crypto.key_update.new_rx_ckm; | |||
7292 | conn->crypto.key_update.new_rx_ckm = NULL((void*)0); | |||
7293 | pktns->crypto.rx.ckm->pkt_num = pkt_num; | |||
7294 | ||||
7295 | assert(pktns->crypto.tx.ckm)((void) (0)); | |||
7296 | ||||
7297 | conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.tx.ckm->aead_ctx); | |||
7298 | ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); | |||
7299 | ||||
7300 | pktns->crypto.tx.ckm = conn->crypto.key_update.new_tx_ckm; | |||
7301 | conn->crypto.key_update.new_tx_ckm = NULL((void*)0); | |||
7302 | pktns->crypto.tx.ckm->pkt_num = pktns->tx.last_pkt_num + 1; | |||
7303 | ||||
7304 | conn->flags |= NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED0x0800; | |||
7305 | } | |||
7306 | ||||
7307 | /* | |||
7308 | * conn_path_validation_in_progress returns nonzero if path validation | |||
7309 | * against |path| is underway. | |||
7310 | */ | |||
7311 | static int conn_path_validation_in_progress(ngtcp2_conn *conn, | |||
7312 | const ngtcp2_path *path) { | |||
7313 | ngtcp2_pv *pv = conn->pv; | |||
7314 | ||||
7315 | return pv && ngtcp2_path_eq(&pv->dcid.ps.path, path); | |||
7316 | } | |||
7317 | ||||
7318 | /* | |||
7319 | * conn_recv_non_probing_pkt_on_new_path is called when non-probing | |||
7320 | * packet is received via new path. It starts path validation against | |||
7321 | * the new path. | |||
7322 | * | |||
7323 | * This function returns 0 if it succeeds, or one of the following | |||
7324 | * negative error codes: | |||
7325 | * | |||
7326 | * NGTCP2_ERR_CONN_ID_BLOCKED | |||
7327 | * No DCID is available | |||
7328 | * NGTCP2_ERR_NOMEM | |||
7329 | * Out of memory | |||
7330 | */ | |||
7331 | static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, | |||
7332 | const ngtcp2_path *path, | |||
7333 | size_t dgramlen, | |||
7334 | int new_cid_used, | |||
7335 | ngtcp2_tstamp ts) { | |||
7336 | ||||
7337 | ngtcp2_dcid dcid, *bound_dcid, *last; | |||
7338 | ngtcp2_pv *pv; | |||
7339 | int rv; | |||
7340 | ngtcp2_duration pto, initial_pto, timeout; | |||
7341 | int require_new_cid; | |||
7342 | int local_addr_eq; | |||
7343 | uint32_t remote_addr_cmp; | |||
7344 | size_t len, i; | |||
7345 | ||||
7346 | assert(conn->server)((void) (0)); | |||
7347 | ||||
7348 | if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
7349 | ngtcp2_path_eq(&conn->pv->fallback_dcid.ps.path, path)) { | |||
7350 | /* If new path equals fallback path, that means connection | |||
7351 | migrated back to the original path. Fallback path is | |||
7352 | considered to be validated. */ | |||
7353 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PTV, | |||
7354 | "path is migrated back to the original path"); | |||
7355 | ngtcp2_dcid_copy(&conn->dcid.current, &conn->pv->fallback_dcid); | |||
7356 | conn_reset_congestion_state(conn); | |||
7357 | conn->dcid.current.bytes_recv += dgramlen; | |||
7358 | conn_reset_ecn_validation_state(conn); | |||
7359 | rv = conn_stop_pv(conn, ts); | |||
7360 | if (rv != 0) { | |||
7361 | return rv; | |||
7362 | } | |||
7363 | return 0; | |||
7364 | } | |||
7365 | ||||
7366 | remote_addr_cmp = | |||
7367 | ngtcp2_addr_compare(&conn->dcid.current.ps.path.remote, &path->remote); | |||
7368 | local_addr_eq = | |||
7369 | ngtcp2_addr_eq(&conn->dcid.current.ps.path.local, &path->local); | |||
7370 | ||||
7371 | /* The transport specification draft-27 says: | |||
7372 | * | |||
7373 | * An endpoint MUST use a new connection ID if it initiates | |||
7374 | * connection migration as described in Section 9.2 or probes a new | |||
7375 | * network path as described in Section 9.1. An endpoint MUST use a | |||
7376 | * new connection ID in response to a change in the address of a | |||
7377 | * peer if the packet with the new peer address uses an active | |||
7378 | * connection ID that has not been previously used by the peer. | |||
7379 | */ | |||
7380 | require_new_cid = conn->dcid.current.cid.datalen && | |||
7381 | ((new_cid_used && remote_addr_cmp) || !local_addr_eq); | |||
7382 | ||||
7383 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
7384 | "non-probing packet was received from new remote address"); | |||
7385 | ||||
7386 | pto = conn_compute_pto(conn, &conn->pktns); | |||
7387 | initial_pto = conn_compute_initial_pto(conn, &conn->pktns); | |||
7388 | timeout = 3 * ngtcp2_max(pto, initial_pto)((pto) > (initial_pto) ? (pto) : (initial_pto)); | |||
7389 | ||||
7390 | len = ngtcp2_ringbuf_len(&conn->dcid.bound)((&conn->dcid.bound)->len); | |||
7391 | ||||
7392 | for (i = 0; i < len; ++i) { | |||
7393 | bound_dcid = ngtcp2_ringbuf_get(&conn->dcid.bound, i); | |||
7394 | if (ngtcp2_path_eq(&bound_dcid->ps.path, path)) { | |||
7395 | ngtcp2_log_info( | |||
7396 | &conn->log, NGTCP2_LOG_EVENT_CON, | |||
7397 | "Found DCID which has already been bound to the new path"); | |||
7398 | ||||
7399 | ngtcp2_dcid_copy(&dcid, bound_dcid); | |||
7400 | if (i == 0) { | |||
7401 | ngtcp2_ringbuf_pop_front(&conn->dcid.bound); | |||
7402 | } else if (i == ngtcp2_ringbuf_len(&conn->dcid.bound)((&conn->dcid.bound)->len) - 1) { | |||
7403 | ngtcp2_ringbuf_pop_back(&conn->dcid.bound); | |||
7404 | } else { | |||
7405 | last = ngtcp2_ringbuf_get(&conn->dcid.bound, len - 1); | |||
7406 | ngtcp2_dcid_copy(bound_dcid, last); | |||
7407 | ngtcp2_ringbuf_pop_back(&conn->dcid.bound); | |||
7408 | } | |||
7409 | require_new_cid = 0; | |||
7410 | ||||
7411 | if (dcid.cid.datalen) { | |||
7412 | rv = conn_call_activate_dcid(conn, &dcid); | |||
7413 | if (rv != 0) { | |||
7414 | return rv; | |||
7415 | } | |||
7416 | } | |||
7417 | break; | |||
7418 | } | |||
7419 | } | |||
7420 | ||||
7421 | if (i == len) { | |||
7422 | if (require_new_cid) { | |||
7423 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len) == 0) { | |||
7424 | return NGTCP2_ERR_CONN_ID_BLOCKED-237; | |||
7425 | } | |||
7426 | ngtcp2_dcid_copy(&dcid, ngtcp2_ringbuf_get(&conn->dcid.unused, 0)); | |||
7427 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
7428 | ||||
7429 | rv = conn_call_activate_dcid(conn, &dcid); | |||
7430 | if (rv != 0) { | |||
7431 | return rv; | |||
7432 | } | |||
7433 | } else { | |||
7434 | /* Use the current DCID if a remote endpoint does not change | |||
7435 | DCID. */ | |||
7436 | ngtcp2_dcid_copy(&dcid, &conn->dcid.current); | |||
7437 | dcid.bytes_sent = 0; | |||
7438 | dcid.bytes_recv = 0; | |||
7439 | dcid.flags &= (uint8_t)~NGTCP2_DCID_FLAG_PATH_VALIDATED0x01; | |||
7440 | } | |||
7441 | } | |||
7442 | ||||
7443 | ngtcp2_path_copy(&dcid.ps.path, path); | |||
7444 | dcid.bytes_recv += dgramlen; | |||
7445 | ||||
7446 | rv = ngtcp2_pv_new(&pv, &dcid, timeout, NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04, | |||
7447 | &conn->log, conn->mem); | |||
7448 | if (rv != 0) { | |||
7449 | return rv; | |||
7450 | } | |||
7451 | ||||
7452 | if (conn->pv && (conn->pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04)) { | |||
7453 | ngtcp2_dcid_copy(&pv->fallback_dcid, &conn->pv->fallback_dcid); | |||
7454 | pv->fallback_pto = conn->pv->fallback_pto; | |||
7455 | } else { | |||
7456 | ngtcp2_dcid_copy(&pv->fallback_dcid, &conn->dcid.current); | |||
7457 | pv->fallback_pto = pto; | |||
7458 | } | |||
7459 | ||||
7460 | ngtcp2_dcid_copy(&conn->dcid.current, &dcid); | |||
7461 | ||||
7462 | if (!local_addr_eq || (remote_addr_cmp & (NGTCP2_ADDR_COMPARE_FLAG_ADDR0x1 | | |||
7463 | NGTCP2_ADDR_COMPARE_FLAG_FAMILY0x4))) { | |||
7464 | conn_reset_congestion_state(conn); | |||
7465 | } | |||
7466 | conn_reset_ecn_validation_state(conn); | |||
7467 | ||||
7468 | if (conn->pv) { | |||
7469 | ngtcp2_log_info( | |||
7470 | &conn->log, NGTCP2_LOG_EVENT_PTV, | |||
7471 | "path migration is aborted because new migration has started"); | |||
7472 | rv = conn_stop_pv(conn, ts); | |||
7473 | if (rv != 0) { | |||
7474 | return rv; | |||
7475 | } | |||
7476 | } | |||
7477 | ||||
7478 | conn->pv = pv; | |||
7479 | ||||
7480 | return 0; | |||
7481 | } | |||
7482 | ||||
7483 | /* | |||
7484 | * conn_recv_pkt_from_new_path is called when a Short packet is | |||
7485 | * received from new path (not current path). This packet would be a | |||
7486 | * packet which only contains probing frame, or reordered packet, or a | |||
7487 | * path is being validated. | |||
7488 | * | |||
7489 | * This function returns 0 if it succeeds, or one of the following | |||
7490 | * negative error codes: | |||
7491 | * | |||
7492 | * NGTCP2_ERR_CONN_ID_BLOCKED | |||
7493 | * No unused DCID is available | |||
7494 | * NGTCP2_ERR_NOMEM | |||
7495 | * Out of memory | |||
7496 | */ | |||
7497 | static int conn_recv_pkt_from_new_path(ngtcp2_conn *conn, | |||
7498 | const ngtcp2_path *path, size_t dgramlen, | |||
7499 | int path_challenge_recved, | |||
7500 | ngtcp2_tstamp ts) { | |||
7501 | ngtcp2_pv *pv = conn->pv; | |||
7502 | ngtcp2_dcid *bound_dcid; | |||
7503 | int rv; | |||
7504 | ||||
7505 | if (pv) { | |||
7506 | if (ngtcp2_path_eq(&pv->dcid.ps.path, path)) { | |||
7507 | pv->dcid.bytes_recv += dgramlen; | |||
7508 | return 0; | |||
7509 | } | |||
7510 | ||||
7511 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
7512 | ngtcp2_path_eq(&pv->fallback_dcid.ps.path, path)) { | |||
7513 | pv->fallback_dcid.bytes_recv += dgramlen; | |||
7514 | return 0; | |||
7515 | } | |||
7516 | } | |||
7517 | ||||
7518 | if (!path_challenge_recved) { | |||
7519 | return 0; | |||
7520 | } | |||
7521 | ||||
7522 | rv = conn_bind_dcid(conn, &bound_dcid, path, ts); | |||
7523 | if (rv != 0) { | |||
7524 | return rv; | |||
7525 | } | |||
7526 | ||||
7527 | ngtcp2_path_copy(&bound_dcid->ps.path, path); | |||
7528 | bound_dcid->bytes_recv += dgramlen; | |||
7529 | ||||
7530 | return 0; | |||
7531 | } | |||
7532 | ||||
7533 | /* | |||
7534 | * conn_recv_delayed_handshake_pkt processes the received Handshake | |||
7535 | * packet which is received after handshake completed. This function | |||
7536 | * does the minimal job, and its purpose is send acknowledgement of | |||
7537 | * this packet to the peer. We assume that hd->type == | |||
7538 | * NGTCP2_PKT_HANDSHAKE. | |||
7539 | * | |||
7540 | * This function returns 0 if it succeeds, or one of the following | |||
7541 | * negative error codes: | |||
7542 | * | |||
7543 | * NGTCP2_ERR_FRAME_ENCODING | |||
7544 | * Frame is badly formatted; or frame type is unknown. | |||
7545 | * NGTCP2_ERR_NOMEM | |||
7546 | * Out of memory | |||
7547 | * NGTCP2_ERR_DISCARD_PKT | |||
7548 | * Packet was discarded. | |||
7549 | * NGTCP2_ERR_ACK_FRAME | |||
7550 | * ACK frame is malformed. | |||
7551 | * NGTCP2_ERR_PROTO | |||
7552 | * Frame that is not allowed in Handshake packet is received. | |||
7553 | */ | |||
7554 | static int | |||
7555 | conn_recv_delayed_handshake_pkt(ngtcp2_conn *conn, const ngtcp2_pkt_info *pi, | |||
7556 | const ngtcp2_pkt_hd *hd, size_t pktlen, | |||
7557 | const uint8_t *payload, size_t payloadlen, | |||
7558 | ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) { | |||
7559 | ngtcp2_ssize nread; | |||
7560 | ngtcp2_max_frame mfr; | |||
7561 | ngtcp2_frame *fr = &mfr.fr; | |||
7562 | int rv; | |||
7563 | int require_ack = 0; | |||
7564 | ngtcp2_pktns *pktns; | |||
7565 | ||||
7566 | assert(hd->type == NGTCP2_PKT_HANDSHAKE)((void) (0)); | |||
7567 | ||||
7568 | pktns = conn->hs_pktns; | |||
7569 | ||||
7570 | if (payloadlen == 0) { | |||
7571 | /* QUIC packet must contain at least one frame */ | |||
7572 | return NGTCP2_ERR_PROTO-205; | |||
7573 | } | |||
7574 | ||||
7575 | ngtcp2_qlog_pkt_received_start(&conn->qlog); | |||
7576 | ||||
7577 | for (; payloadlen;) { | |||
7578 | nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen); | |||
7579 | if (nread < 0) { | |||
7580 | return (int)nread; | |||
7581 | } | |||
7582 | ||||
7583 | payload += nread; | |||
7584 | payloadlen -= (size_t)nread; | |||
7585 | ||||
7586 | switch (fr->type) { | |||
7587 | case NGTCP2_FRAME_ACK: | |||
7588 | case NGTCP2_FRAME_ACK_ECN: | |||
7589 | fr->ack.ack_delay = 0; | |||
7590 | fr->ack.ack_delay_unscaled = 0; | |||
7591 | break; | |||
7592 | } | |||
7593 | ||||
7594 | ngtcp2_log_rx_fr(&conn->log, hd, fr); | |||
7595 | ||||
7596 | switch (fr->type) { | |||
7597 | case NGTCP2_FRAME_ACK: | |||
7598 | case NGTCP2_FRAME_ACK_ECN: | |||
7599 | if (!conn->server) { | |||
7600 | conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000; | |||
7601 | } | |||
7602 | rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts); | |||
7603 | if (rv != 0) { | |||
7604 | return rv; | |||
7605 | } | |||
7606 | break; | |||
7607 | case NGTCP2_FRAME_PADDING: | |||
7608 | break; | |||
7609 | case NGTCP2_FRAME_CONNECTION_CLOSE: | |||
7610 | conn_recv_connection_close(conn, &fr->connection_close); | |||
7611 | break; | |||
7612 | case NGTCP2_FRAME_CRYPTO: | |||
7613 | case NGTCP2_FRAME_PING: | |||
7614 | require_ack = 1; | |||
7615 | break; | |||
7616 | default: | |||
7617 | return NGTCP2_ERR_PROTO-205; | |||
7618 | } | |||
7619 | ||||
7620 | ngtcp2_qlog_write_frame(&conn->qlog, fr); | |||
7621 | } | |||
7622 | ||||
7623 | ngtcp2_qlog_pkt_received_end(&conn->qlog, hd, pktlen); | |||
7624 | ||||
7625 | rv = pktns_commit_recv_pkt_num(pktns, hd->pkt_num, require_ack, pkt_ts); | |||
7626 | if (rv != 0) { | |||
7627 | return rv; | |||
7628 | } | |||
7629 | ||||
7630 | pktns_increase_ecn_counts(pktns, pi); | |||
7631 | ||||
7632 | if (require_ack && | |||
7633 | (++pktns->acktr.rx_npkt >= conn->local.settings.ack_thresh || | |||
7634 | (pi->ecn & NGTCP2_ECN_MASK0x3) == NGTCP2_ECN_CE0x3)) { | |||
7635 | ngtcp2_acktr_immediate_ack(&pktns->acktr); | |||
7636 | } | |||
7637 | ||||
7638 | rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd->pkt_num, require_ack, | |||
7639 | pkt_ts); | |||
7640 | if (rv != 0) { | |||
7641 | return rv; | |||
7642 | } | |||
7643 | ||||
7644 | conn_restart_timer_on_read(conn, ts); | |||
7645 | ||||
7646 | ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); | |||
7647 | ||||
7648 | return 0; | |||
7649 | } | |||
7650 | ||||
7651 | /* | |||
7652 | * conn_recv_pkt processes a packet contained in the buffer pointed by | |||
7653 | * |pkt| of length |pktlen|. |pkt| may contain multiple QUIC packets. | |||
7654 | * This function only processes the first packet. |pkt_ts| is the | |||
7655 | * timestamp when packet is received. |ts| should be the current | |||
7656 | * time. Usually they are the same, but for buffered packets, | |||
7657 | * |pkt_ts| would be earlier than |ts|. | |||
7658 | * | |||
7659 | * This function returns the number of bytes processed if it succeeds, | |||
7660 | * or one of the following negative error codes: | |||
7661 | * | |||
7662 | * NGTCP2_ERR_DISCARD_PKT | |||
7663 | * Packet was discarded because plain text header was malformed; | |||
7664 | * or its payload could not be decrypted. | |||
7665 | * NGTCP2_ERR_PROTO | |||
7666 | * Packet is badly formatted; or 0RTT packet contains other than | |||
7667 | * PADDING or STREAM frames; or other QUIC protocol violation is | |||
7668 | * found. | |||
7669 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
7670 | * User-defined callback function failed. | |||
7671 | * NGTCP2_ERR_NOMEM | |||
7672 | * Out of memory. | |||
7673 | * NGTCP2_ERR_FRAME_ENCODING | |||
7674 | * Frame is badly formatted; or frame type is unknown. | |||
7675 | * NGTCP2_ERR_ACK_FRAME | |||
7676 | * ACK frame is malformed. | |||
7677 | * NGTCP2_ERR_STREAM_STATE | |||
7678 | * Frame is received to the local stream which is not initiated. | |||
7679 | * NGTCP2_ERR_STREAM_LIMIT | |||
7680 | * Frame has remote stream ID which is strictly greater than the | |||
7681 | * allowed limit. | |||
7682 | * NGTCP2_ERR_FLOW_CONTROL | |||
7683 | * Flow control limit is violated. | |||
7684 | * NGTCP2_ERR_FINAL_SIZE | |||
7685 | * Frame has strictly larger end offset than it is permitted. | |||
7686 | */ | |||
7687 | static ngtcp2_ssize conn_recv_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
7688 | const ngtcp2_pkt_info *pi, const uint8_t *pkt, | |||
7689 | size_t pktlen, size_t dgramlen, | |||
7690 | ngtcp2_tstamp pkt_ts, ngtcp2_tstamp ts) { | |||
7691 | ngtcp2_pkt_hd hd; | |||
7692 | int rv = 0; | |||
7693 | size_t hdpktlen; | |||
7694 | const uint8_t *payload; | |||
7695 | size_t payloadlen; | |||
7696 | ngtcp2_ssize nread, nwrite; | |||
7697 | ngtcp2_max_frame mfr; | |||
7698 | ngtcp2_frame *fr = &mfr.fr; | |||
7699 | int require_ack = 0; | |||
7700 | ngtcp2_crypto_aead *aead; | |||
7701 | ngtcp2_crypto_cipher *hp; | |||
7702 | ngtcp2_crypto_km *ckm; | |||
7703 | ngtcp2_crypto_cipher_ctx *hp_ctx; | |||
7704 | ngtcp2_hp_mask hp_mask; | |||
7705 | ngtcp2_decrypt decrypt; | |||
7706 | ngtcp2_pktns *pktns; | |||
7707 | int non_probing_pkt = 0; | |||
7708 | int key_phase_bit_changed = 0; | |||
7709 | int force_decrypt_failure = 0; | |||
7710 | int recv_ncid = 0; | |||
7711 | int new_cid_used = 0; | |||
7712 | int path_challenge_recved = 0; | |||
7713 | ||||
7714 | if (pkt[0] & NGTCP2_HEADER_FORM_BIT0x80) { | |||
7715 | nread = ngtcp2_pkt_decode_hd_long(&hd, pkt, pktlen); | |||
7716 | if (nread < 0) { | |||
7717 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7718 | "could not decode long header"); | |||
7719 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7720 | } | |||
7721 | ||||
7722 | if (pktlen < (size_t)nread + hd.len || conn->version != hd.version) { | |||
7723 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7724 | } | |||
7725 | ||||
7726 | pktlen = (size_t)nread + hd.len; | |||
7727 | ||||
7728 | /* Quoted from spec: if subsequent packets of those types include | |||
7729 | a different Source Connection ID, they MUST be discarded. */ | |||
7730 | if (!ngtcp2_cid_eq(&conn->dcid.current.cid, &hd.scid)) { | |||
7731 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
7732 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7733 | "packet was ignored because of mismatched SCID"); | |||
7734 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7735 | } | |||
7736 | ||||
7737 | switch (hd.type) { | |||
7738 | case NGTCP2_PKT_INITIAL: | |||
7739 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7740 | "delayed Initial packet was discarded"); | |||
7741 | return (ngtcp2_ssize)pktlen; | |||
7742 | case NGTCP2_PKT_HANDSHAKE: | |||
7743 | if (!conn->hs_pktns) { | |||
7744 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7745 | "delayed Handshake packet was discarded"); | |||
7746 | return (ngtcp2_ssize)pktlen; | |||
7747 | } | |||
7748 | ||||
7749 | pktns = conn->hs_pktns; | |||
7750 | aead = &pktns->crypto.ctx.aead; | |||
7751 | hp = &pktns->crypto.ctx.hp; | |||
7752 | ckm = pktns->crypto.rx.ckm; | |||
7753 | hp_ctx = &pktns->crypto.rx.hp_ctx; | |||
7754 | hp_mask = conn->callbacks.hp_mask; | |||
7755 | decrypt = conn->callbacks.decrypt; | |||
7756 | break; | |||
7757 | case NGTCP2_PKT_0RTT: | |||
7758 | if (!conn->server) { | |||
7759 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7760 | } | |||
7761 | ||||
7762 | if (!conn->early.ckm) { | |||
7763 | return (ngtcp2_ssize)pktlen; | |||
7764 | } | |||
7765 | ||||
7766 | pktns = &conn->pktns; | |||
7767 | aead = &conn->early.ctx.aead; | |||
7768 | hp = &conn->early.ctx.hp; | |||
7769 | ckm = conn->early.ckm; | |||
7770 | hp_ctx = &conn->early.hp_ctx; | |||
7771 | hp_mask = conn->callbacks.hp_mask; | |||
7772 | decrypt = conn->callbacks.decrypt; | |||
7773 | break; | |||
7774 | default: | |||
7775 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
7776 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7777 | "packet type 0x%02x was ignored", hd.type); | |||
7778 | return (ngtcp2_ssize)pktlen; | |||
7779 | } | |||
7780 | } else { | |||
7781 | nread = ngtcp2_pkt_decode_hd_short(&hd, pkt, pktlen, conn->oscid.datalen); | |||
7782 | if (nread < 0) { | |||
7783 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7784 | "could not decode short header"); | |||
7785 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7786 | } | |||
7787 | ||||
7788 | pktns = &conn->pktns; | |||
7789 | aead = &pktns->crypto.ctx.aead; | |||
7790 | hp = &pktns->crypto.ctx.hp; | |||
7791 | ckm = pktns->crypto.rx.ckm; | |||
7792 | hp_ctx = &pktns->crypto.rx.hp_ctx; | |||
7793 | hp_mask = conn->callbacks.hp_mask; | |||
7794 | decrypt = conn->callbacks.decrypt; | |||
7795 | } | |||
7796 | ||||
7797 | rv = conn_ensure_decrypt_hp_buffer(conn, (size_t)nread + 4); | |||
7798 | if (rv != 0) { | |||
7799 | return rv; | |||
7800 | } | |||
7801 | ||||
7802 | nwrite = decrypt_hp(&hd, conn->crypto.decrypt_hp_buf.base, hp, pkt, pktlen, | |||
7803 | (size_t)nread, ckm, hp_ctx, hp_mask); | |||
7804 | if (nwrite < 0) { | |||
7805 | if (ngtcp2_err_is_fatal((int)nwrite)) { | |||
7806 | return nwrite; | |||
7807 | } | |||
7808 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7809 | "could not decrypt packet number"); | |||
7810 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7811 | } | |||
7812 | ||||
7813 | hdpktlen = (size_t)nwrite; | |||
7814 | payload = pkt + hdpktlen; | |||
7815 | payloadlen = pktlen - hdpktlen; | |||
7816 | ||||
7817 | hd.pkt_num = ngtcp2_pkt_adjust_pkt_num(pktns->rx.max_pkt_num, hd.pkt_num, | |||
7818 | pkt_num_bits(hd.pkt_numlen)); | |||
7819 | if (hd.pkt_num > NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1))) { | |||
7820 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7821 | "pkn=%" PRId64"l" "d" " is greater than maximum pkn", hd.pkt_num); | |||
7822 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7823 | } | |||
7824 | ||||
7825 | ngtcp2_log_rx_pkt_hd(&conn->log, &hd); | |||
7826 | ||||
7827 | if (hd.type == NGTCP2_PKT_SHORT) { | |||
7828 | key_phase_bit_changed = conn_key_phase_changed(conn, &hd); | |||
7829 | } | |||
7830 | ||||
7831 | rv = conn_ensure_decrypt_buffer(conn, payloadlen); | |||
7832 | if (rv != 0) { | |||
7833 | return rv; | |||
7834 | } | |||
7835 | ||||
7836 | if (key_phase_bit_changed) { | |||
7837 | assert(hd.type == NGTCP2_PKT_SHORT)((void) (0)); | |||
7838 | ||||
7839 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, "unexpected KEY_PHASE"); | |||
7840 | ||||
7841 | if (ckm->pkt_num > hd.pkt_num) { | |||
7842 | if (conn->crypto.key_update.old_rx_ckm) { | |||
7843 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7844 | "decrypting with old key"); | |||
7845 | ckm = conn->crypto.key_update.old_rx_ckm; | |||
7846 | } else { | |||
7847 | force_decrypt_failure = 1; | |||
7848 | } | |||
7849 | } else if (pktns->rx.max_pkt_num < hd.pkt_num) { | |||
7850 | assert(ckm->pkt_num < hd.pkt_num)((void) (0)); | |||
7851 | if (!conn->crypto.key_update.new_rx_ckm) { | |||
7852 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7853 | "new key is not available"); | |||
7854 | force_decrypt_failure = 1; | |||
7855 | } else { | |||
7856 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7857 | "decrypting with new key"); | |||
7858 | ckm = conn->crypto.key_update.new_rx_ckm; | |||
7859 | } | |||
7860 | } else { | |||
7861 | force_decrypt_failure = 1; | |||
7862 | } | |||
7863 | } | |||
7864 | ||||
7865 | nwrite = decrypt_pkt(conn->crypto.decrypt_buf.base, aead, payload, payloadlen, | |||
7866 | conn->crypto.decrypt_hp_buf.base, hdpktlen, hd.pkt_num, | |||
7867 | ckm, decrypt); | |||
7868 | ||||
7869 | if (force_decrypt_failure) { | |||
7870 | nwrite = NGTCP2_ERR_TLS_DECRYPT-220; | |||
7871 | } | |||
7872 | ||||
7873 | if (nwrite < 0) { | |||
7874 | if (ngtcp2_err_is_fatal((int)nwrite)) { | |||
7875 | return nwrite; | |||
7876 | } | |||
7877 | ||||
7878 | assert(NGTCP2_ERR_TLS_DECRYPT == nwrite)((void) (0)); | |||
7879 | ||||
7880 | if (hd.type == NGTCP2_PKT_SHORT && | |||
7881 | ++conn->crypto.decryption_failure_count >= | |||
7882 | pktns->crypto.ctx.max_decryption_failure) { | |||
7883 | return NGTCP2_ERR_AEAD_LIMIT_REACHED-243; | |||
7884 | } | |||
7885 | ||||
7886 | if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM0x01) { | |||
7887 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7888 | "could not decrypt packet payload"); | |||
7889 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7890 | } | |||
7891 | ||||
7892 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7893 | "could not decrypt packet payload"); | |||
7894 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7895 | } | |||
7896 | ||||
7897 | rv = ngtcp2_pkt_verify_reserved_bits(conn->crypto.decrypt_hp_buf.base[0]); | |||
7898 | if (rv != 0) { | |||
7899 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7900 | "packet has incorrect reserved bits"); | |||
7901 | ||||
7902 | return NGTCP2_ERR_PROTO-205; | |||
7903 | } | |||
7904 | ||||
7905 | if (pktns_pkt_num_is_duplicate(pktns, hd.pkt_num)) { | |||
7906 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7907 | "packet was discarded because of duplicated packet number"); | |||
7908 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7909 | } | |||
7910 | ||||
7911 | payload = conn->crypto.decrypt_buf.base; | |||
7912 | payloadlen = (size_t)nwrite; | |||
7913 | ||||
7914 | if (payloadlen == 0) { | |||
7915 | /* QUIC packet must contain at least one frame */ | |||
7916 | return NGTCP2_ERR_PROTO-205; | |||
7917 | } | |||
7918 | ||||
7919 | if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM0x01) { | |||
7920 | switch (hd.type) { | |||
7921 | case NGTCP2_PKT_HANDSHAKE: | |||
7922 | rv = conn_verify_dcid(conn, NULL((void*)0), &hd); | |||
7923 | if (rv != 0) { | |||
7924 | if (ngtcp2_err_is_fatal(rv)) { | |||
7925 | return rv; | |||
7926 | } | |||
7927 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7928 | "packet was ignored because of mismatched DCID"); | |||
7929 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7930 | } | |||
7931 | ||||
7932 | rv = conn_recv_delayed_handshake_pkt(conn, pi, &hd, pktlen, payload, | |||
7933 | payloadlen, pkt_ts, ts); | |||
7934 | if (rv < 0) { | |||
7935 | return (ngtcp2_ssize)rv; | |||
7936 | } | |||
7937 | ||||
7938 | return (ngtcp2_ssize)pktlen; | |||
7939 | case NGTCP2_PKT_0RTT: | |||
7940 | if (!ngtcp2_cid_eq(&conn->rcid, &hd.dcid)) { | |||
7941 | rv = conn_verify_dcid(conn, NULL((void*)0), &hd); | |||
7942 | if (rv != 0) { | |||
7943 | if (ngtcp2_err_is_fatal(rv)) { | |||
7944 | return rv; | |||
7945 | } | |||
7946 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7947 | "packet was ignored because of mismatched DCID"); | |||
7948 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7949 | } | |||
7950 | } | |||
7951 | break; | |||
7952 | default: | |||
7953 | /* Unreachable */ | |||
7954 | assert(0)((void) (0)); | |||
7955 | } | |||
7956 | } else { | |||
7957 | rv = conn_verify_dcid(conn, &new_cid_used, &hd); | |||
7958 | if (rv != 0) { | |||
7959 | if (ngtcp2_err_is_fatal(rv)) { | |||
7960 | return rv; | |||
7961 | } | |||
7962 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
7963 | "packet was ignored because of mismatched DCID"); | |||
7964 | return NGTCP2_ERR_DISCARD_PKT-235; | |||
7965 | } | |||
7966 | ||||
7967 | conn->flags |= NGTCP2_CONN_FLAG_RECV_PROTECTED_PKT0x08; | |||
7968 | } | |||
7969 | ||||
7970 | ngtcp2_qlog_pkt_received_start(&conn->qlog); | |||
7971 | ||||
7972 | for (; payloadlen;) { | |||
7973 | nread = ngtcp2_pkt_decode_frame(fr, payload, payloadlen); | |||
7974 | if (nread < 0) { | |||
7975 | return nread; | |||
7976 | } | |||
7977 | ||||
7978 | payload += nread; | |||
7979 | payloadlen -= (size_t)nread; | |||
7980 | ||||
7981 | switch (fr->type) { | |||
7982 | case NGTCP2_FRAME_ACK: | |||
7983 | case NGTCP2_FRAME_ACK_ECN: | |||
7984 | if ((hd.flags & NGTCP2_PKT_FLAG_LONG_FORM0x01) && | |||
7985 | hd.type == NGTCP2_PKT_0RTT) { | |||
7986 | return NGTCP2_ERR_PROTO-205; | |||
7987 | } | |||
7988 | assign_recved_ack_delay_unscaled( | |||
7989 | &fr->ack, conn->remote.transport_params.ack_delay_exponent); | |||
7990 | break; | |||
7991 | } | |||
7992 | ||||
7993 | ngtcp2_log_rx_fr(&conn->log, &hd, fr); | |||
7994 | ||||
7995 | if (hd.type == NGTCP2_PKT_0RTT) { | |||
7996 | switch (fr->type) { | |||
7997 | case NGTCP2_FRAME_PADDING: | |||
7998 | case NGTCP2_FRAME_PING: | |||
7999 | case NGTCP2_FRAME_RESET_STREAM: | |||
8000 | case NGTCP2_FRAME_STOP_SENDING: | |||
8001 | case NGTCP2_FRAME_STREAM: | |||
8002 | case NGTCP2_FRAME_MAX_DATA: | |||
8003 | case NGTCP2_FRAME_MAX_STREAM_DATA: | |||
8004 | case NGTCP2_FRAME_MAX_STREAMS_BIDI: | |||
8005 | case NGTCP2_FRAME_MAX_STREAMS_UNI: | |||
8006 | case NGTCP2_FRAME_DATA_BLOCKED: | |||
8007 | case NGTCP2_FRAME_STREAM_DATA_BLOCKED: | |||
8008 | case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI: | |||
8009 | case NGTCP2_FRAME_STREAMS_BLOCKED_UNI: | |||
8010 | case NGTCP2_FRAME_NEW_CONNECTION_ID: | |||
8011 | case NGTCP2_FRAME_PATH_CHALLENGE: | |||
8012 | case NGTCP2_FRAME_CONNECTION_CLOSE: | |||
8013 | case NGTCP2_FRAME_CONNECTION_CLOSE_APP: | |||
8014 | case NGTCP2_FRAME_DATAGRAM: | |||
8015 | case NGTCP2_FRAME_DATAGRAM_LEN: | |||
8016 | break; | |||
8017 | default: | |||
8018 | return NGTCP2_ERR_PROTO-205; | |||
8019 | } | |||
8020 | } | |||
8021 | ||||
8022 | switch (fr->type) { | |||
8023 | case NGTCP2_FRAME_ACK: | |||
8024 | case NGTCP2_FRAME_ACK_ECN: | |||
8025 | case NGTCP2_FRAME_PADDING: | |||
8026 | case NGTCP2_FRAME_CONNECTION_CLOSE: | |||
8027 | case NGTCP2_FRAME_CONNECTION_CLOSE_APP: | |||
8028 | break; | |||
8029 | default: | |||
8030 | require_ack = 1; | |||
8031 | } | |||
8032 | ||||
8033 | switch (fr->type) { | |||
8034 | case NGTCP2_FRAME_ACK: | |||
8035 | case NGTCP2_FRAME_ACK_ECN: | |||
8036 | if (!conn->server) { | |||
8037 | conn->flags |= NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000; | |||
8038 | } | |||
8039 | rv = conn_recv_ack(conn, pktns, &fr->ack, pkt_ts, ts); | |||
8040 | if (rv != 0) { | |||
8041 | return rv; | |||
8042 | } | |||
8043 | non_probing_pkt = 1; | |||
8044 | break; | |||
8045 | case NGTCP2_FRAME_STREAM: | |||
8046 | rv = conn_recv_stream(conn, &fr->stream); | |||
8047 | if (rv != 0) { | |||
8048 | return rv; | |||
8049 | } | |||
8050 | non_probing_pkt = 1; | |||
8051 | break; | |||
8052 | case NGTCP2_FRAME_CRYPTO: | |||
8053 | rv = conn_recv_crypto(conn, NGTCP2_CRYPTO_LEVEL_APPLICATION, | |||
8054 | &pktns->crypto.strm, &fr->crypto); | |||
8055 | if (rv != 0) { | |||
8056 | return rv; | |||
8057 | } | |||
8058 | non_probing_pkt = 1; | |||
8059 | break; | |||
8060 | case NGTCP2_FRAME_RESET_STREAM: | |||
8061 | rv = conn_recv_reset_stream(conn, &fr->reset_stream); | |||
8062 | if (rv != 0) { | |||
8063 | return rv; | |||
8064 | } | |||
8065 | non_probing_pkt = 1; | |||
8066 | break; | |||
8067 | case NGTCP2_FRAME_STOP_SENDING: | |||
8068 | rv = conn_recv_stop_sending(conn, &fr->stop_sending); | |||
8069 | if (rv != 0) { | |||
8070 | return rv; | |||
8071 | } | |||
8072 | non_probing_pkt = 1; | |||
8073 | break; | |||
8074 | case NGTCP2_FRAME_MAX_STREAM_DATA: | |||
8075 | rv = conn_recv_max_stream_data(conn, &fr->max_stream_data); | |||
8076 | if (rv != 0) { | |||
8077 | return rv; | |||
8078 | } | |||
8079 | non_probing_pkt = 1; | |||
8080 | break; | |||
8081 | case NGTCP2_FRAME_MAX_DATA: | |||
8082 | conn_recv_max_data(conn, &fr->max_data); | |||
8083 | non_probing_pkt = 1; | |||
8084 | break; | |||
8085 | case NGTCP2_FRAME_MAX_STREAMS_BIDI: | |||
8086 | case NGTCP2_FRAME_MAX_STREAMS_UNI: | |||
8087 | rv = conn_recv_max_streams(conn, &fr->max_streams); | |||
8088 | if (rv != 0) { | |||
8089 | return rv; | |||
8090 | } | |||
8091 | non_probing_pkt = 1; | |||
8092 | break; | |||
8093 | case NGTCP2_FRAME_CONNECTION_CLOSE: | |||
8094 | case NGTCP2_FRAME_CONNECTION_CLOSE_APP: | |||
8095 | conn_recv_connection_close(conn, &fr->connection_close); | |||
8096 | break; | |||
8097 | case NGTCP2_FRAME_PING: | |||
8098 | non_probing_pkt = 1; | |||
8099 | break; | |||
8100 | case NGTCP2_FRAME_PATH_CHALLENGE: | |||
8101 | conn_recv_path_challenge(conn, path, &fr->path_challenge); | |||
8102 | path_challenge_recved = 1; | |||
8103 | break; | |||
8104 | case NGTCP2_FRAME_PATH_RESPONSE: | |||
8105 | rv = conn_recv_path_response(conn, &fr->path_response, ts); | |||
8106 | if (rv != 0) { | |||
8107 | return rv; | |||
8108 | } | |||
8109 | break; | |||
8110 | case NGTCP2_FRAME_NEW_CONNECTION_ID: | |||
8111 | rv = conn_recv_new_connection_id(conn, &fr->new_connection_id); | |||
8112 | if (rv != 0) { | |||
8113 | return rv; | |||
8114 | } | |||
8115 | recv_ncid = 1; | |||
8116 | break; | |||
8117 | case NGTCP2_FRAME_RETIRE_CONNECTION_ID: | |||
8118 | rv = conn_recv_retire_connection_id(conn, &hd, &fr->retire_connection_id, | |||
8119 | ts); | |||
8120 | if (rv != 0) { | |||
8121 | return rv; | |||
8122 | } | |||
8123 | non_probing_pkt = 1; | |||
8124 | break; | |||
8125 | case NGTCP2_FRAME_NEW_TOKEN: | |||
8126 | rv = conn_recv_new_token(conn, &fr->new_token); | |||
8127 | if (rv != 0) { | |||
8128 | return rv; | |||
8129 | } | |||
8130 | non_probing_pkt = 1; | |||
8131 | break; | |||
8132 | case NGTCP2_FRAME_HANDSHAKE_DONE: | |||
8133 | rv = conn_recv_handshake_done(conn, ts); | |||
8134 | if (rv != 0) { | |||
8135 | return rv; | |||
8136 | } | |||
8137 | non_probing_pkt = 1; | |||
8138 | break; | |||
8139 | case NGTCP2_FRAME_STREAMS_BLOCKED_BIDI: | |||
8140 | rv = conn_recv_streams_blocked_bidi(conn, &fr->streams_blocked); | |||
8141 | if (rv != 0) { | |||
8142 | return rv; | |||
8143 | } | |||
8144 | non_probing_pkt = 1; | |||
8145 | break; | |||
8146 | case NGTCP2_FRAME_STREAMS_BLOCKED_UNI: | |||
8147 | rv = conn_recv_streams_blocked_uni(conn, &fr->streams_blocked); | |||
8148 | if (rv != 0) { | |||
8149 | return rv; | |||
8150 | } | |||
8151 | non_probing_pkt = 1; | |||
8152 | break; | |||
8153 | case NGTCP2_FRAME_DATA_BLOCKED: | |||
8154 | /* TODO Not implemented yet */ | |||
8155 | non_probing_pkt = 1; | |||
8156 | break; | |||
8157 | case NGTCP2_FRAME_DATAGRAM: | |||
8158 | case NGTCP2_FRAME_DATAGRAM_LEN: | |||
8159 | if ((uint64_t)nread > | |||
8160 | conn->local.transport_params.max_datagram_frame_size) { | |||
8161 | return NGTCP2_ERR_PROTO-205; | |||
8162 | } | |||
8163 | rv = conn_recv_datagram(conn, &fr->datagram); | |||
8164 | if (rv != 0) { | |||
8165 | return rv; | |||
8166 | } | |||
8167 | non_probing_pkt = 1; | |||
8168 | break; | |||
8169 | } | |||
8170 | ||||
8171 | ngtcp2_qlog_write_frame(&conn->qlog, fr); | |||
8172 | } | |||
8173 | ||||
8174 | ngtcp2_qlog_pkt_received_end(&conn->qlog, &hd, pktlen); | |||
8175 | ||||
8176 | if (recv_ncid) { | |||
8177 | rv = conn_post_process_recv_new_connection_id(conn, ts); | |||
8178 | if (rv != 0) { | |||
8179 | return rv; | |||
8180 | } | |||
8181 | } | |||
8182 | ||||
8183 | if (conn->server && hd.type == NGTCP2_PKT_SHORT && | |||
8184 | !ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { | |||
8185 | if (non_probing_pkt && pktns->rx.max_pkt_num < hd.pkt_num && | |||
8186 | !conn_path_validation_in_progress(conn, path)) { | |||
8187 | rv = conn_recv_non_probing_pkt_on_new_path(conn, path, dgramlen, | |||
8188 | new_cid_used, ts); | |||
8189 | if (rv != 0) { | |||
8190 | if (ngtcp2_err_is_fatal(rv)) { | |||
8191 | return rv; | |||
8192 | } | |||
8193 | ||||
8194 | /* DCID is not available. Just continue. */ | |||
8195 | assert(NGTCP2_ERR_CONN_ID_BLOCKED == rv)((void) (0)); | |||
8196 | } | |||
8197 | } else { | |||
8198 | rv = conn_recv_pkt_from_new_path(conn, path, dgramlen, | |||
8199 | path_challenge_recved, ts); | |||
8200 | if (rv != 0) { | |||
8201 | if (ngtcp2_err_is_fatal(rv)) { | |||
8202 | return rv; | |||
8203 | } | |||
8204 | ||||
8205 | /* DCID is not available. Just continue. */ | |||
8206 | assert(NGTCP2_ERR_CONN_ID_BLOCKED == rv)((void) (0)); | |||
8207 | } | |||
8208 | } | |||
8209 | } | |||
8210 | ||||
8211 | if (hd.type == NGTCP2_PKT_SHORT) { | |||
8212 | if (ckm == conn->crypto.key_update.new_rx_ckm) { | |||
8213 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "rotate keys"); | |||
8214 | conn_rotate_keys(conn, hd.pkt_num); | |||
8215 | } else if (ckm->pkt_num > hd.pkt_num) { | |||
8216 | ckm->pkt_num = hd.pkt_num; | |||
8217 | } | |||
8218 | ||||
8219 | if (conn->server && conn->early.ckm && | |||
8220 | conn->early.discard_started_ts == UINT64_MAX(18446744073709551615UL)) { | |||
8221 | conn->early.discard_started_ts = ts; | |||
8222 | } | |||
8223 | } | |||
8224 | ||||
8225 | rv = pktns_commit_recv_pkt_num(pktns, hd.pkt_num, require_ack, pkt_ts); | |||
8226 | if (rv != 0) { | |||
8227 | return rv; | |||
8228 | } | |||
8229 | ||||
8230 | pktns_increase_ecn_counts(pktns, pi); | |||
8231 | ||||
8232 | if (require_ack && | |||
8233 | (++pktns->acktr.rx_npkt >= conn->local.settings.ack_thresh || | |||
8234 | (pi->ecn & NGTCP2_ECN_MASK0x3) == NGTCP2_ECN_CE0x3)) { | |||
8235 | ngtcp2_acktr_immediate_ack(&pktns->acktr); | |||
8236 | } | |||
8237 | ||||
8238 | rv = ngtcp2_conn_sched_ack(conn, &pktns->acktr, hd.pkt_num, require_ack, | |||
8239 | pkt_ts); | |||
8240 | if (rv != 0) { | |||
8241 | return rv; | |||
8242 | } | |||
8243 | ||||
8244 | conn_restart_timer_on_read(conn, ts); | |||
8245 | ||||
8246 | ngtcp2_qlog_metrics_updated(&conn->qlog, &conn->cstat); | |||
8247 | ||||
8248 | return conn->state == NGTCP2_CS_DRAINING ? NGTCP2_ERR_DRAINING-231 | |||
8249 | : (ngtcp2_ssize)pktlen; | |||
8250 | } | |||
8251 | ||||
8252 | /* | |||
8253 | * conn_process_buffered_protected_pkt processes buffered 0RTT or | |||
8254 | * Short packets. | |||
8255 | * | |||
8256 | * This function returns 0 if it succeeds, or the same negative error | |||
8257 | * codes from conn_recv_pkt. | |||
8258 | */ | |||
8259 | static int conn_process_buffered_protected_pkt(ngtcp2_conn *conn, | |||
8260 | ngtcp2_pktns *pktns, | |||
8261 | ngtcp2_tstamp ts) { | |||
8262 | ngtcp2_ssize nread; | |||
8263 | ngtcp2_pkt_chain **ppc, *next; | |||
8264 | int rv; | |||
8265 | ||||
8266 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
8267 | "processing buffered protected packet"); | |||
8268 | ||||
8269 | for (ppc = &pktns->rx.buffed_pkts; *ppc;) { | |||
8270 | next = (*ppc)->next; | |||
8271 | nread = conn_recv_pkt(conn, &(*ppc)->path.path, &(*ppc)->pi, (*ppc)->pkt, | |||
8272 | (*ppc)->pktlen, (*ppc)->dgramlen, (*ppc)->ts, ts); | |||
8273 | if (nread < 0 && !ngtcp2_err_is_fatal((int)nread) && | |||
8274 | nread != NGTCP2_ERR_DRAINING-231) { | |||
8275 | /* TODO We don't know this is the first QUIC packet in a | |||
8276 | datagram. */ | |||
8277 | rv = conn_on_stateless_reset(conn, &(*ppc)->path.path, (*ppc)->pkt, | |||
8278 | (*ppc)->pktlen); | |||
8279 | if (rv == 0) { | |||
8280 | ngtcp2_pkt_chain_del(*ppc, conn->mem); | |||
8281 | *ppc = next; | |||
8282 | return NGTCP2_ERR_DRAINING-231; | |||
8283 | } | |||
8284 | } | |||
8285 | ||||
8286 | ngtcp2_pkt_chain_del(*ppc, conn->mem); | |||
8287 | *ppc = next; | |||
8288 | if (nread < 0) { | |||
8289 | if (nread == NGTCP2_ERR_DISCARD_PKT-235) { | |||
8290 | continue; | |||
8291 | } | |||
8292 | return (int)nread; | |||
8293 | } | |||
8294 | } | |||
8295 | ||||
8296 | return 0; | |||
8297 | } | |||
8298 | ||||
8299 | /* | |||
8300 | * conn_process_buffered_handshake_pkt processes buffered Handshake | |||
8301 | * packets. | |||
8302 | * | |||
8303 | * This function returns 0 if it succeeds, or the same negative error | |||
8304 | * codes from conn_recv_handshake_pkt. | |||
8305 | */ | |||
8306 | static int conn_process_buffered_handshake_pkt(ngtcp2_conn *conn, | |||
8307 | ngtcp2_tstamp ts) { | |||
8308 | ngtcp2_pktns *pktns = conn->hs_pktns; | |||
8309 | ngtcp2_ssize nread; | |||
8310 | ngtcp2_pkt_chain **ppc, *next; | |||
8311 | ||||
8312 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
8313 | "processing buffered handshake packet"); | |||
8314 | ||||
8315 | for (ppc = &pktns->rx.buffed_pkts; *ppc;) { | |||
8316 | next = (*ppc)->next; | |||
8317 | nread = conn_recv_handshake_pkt(conn, &(*ppc)->path.path, &(*ppc)->pi, | |||
8318 | (*ppc)->pkt, (*ppc)->pktlen, | |||
8319 | (*ppc)->dgramlen, (*ppc)->ts, ts); | |||
8320 | ngtcp2_pkt_chain_del(*ppc, conn->mem); | |||
8321 | *ppc = next; | |||
8322 | if (nread < 0) { | |||
8323 | if (nread == NGTCP2_ERR_DISCARD_PKT-235) { | |||
8324 | continue; | |||
8325 | } | |||
8326 | return (int)nread; | |||
8327 | } | |||
8328 | } | |||
8329 | ||||
8330 | return 0; | |||
8331 | } | |||
8332 | ||||
8333 | static void conn_sync_stream_id_limit(ngtcp2_conn *conn) { | |||
8334 | ngtcp2_transport_params *params = &conn->remote.transport_params; | |||
8335 | ||||
8336 | conn->local.bidi.max_streams = params->initial_max_streams_bidi; | |||
8337 | conn->local.uni.max_streams = params->initial_max_streams_uni; | |||
8338 | } | |||
8339 | ||||
8340 | /* | |||
8341 | * conn_handshake_completed is called once cryptographic handshake has | |||
8342 | * completed. | |||
8343 | * | |||
8344 | * This function returns 0 if it succeeds, or one of the following | |||
8345 | * negative error codes: | |||
8346 | * | |||
8347 | * NGTCP2_ERR_CALLBACK_FAILURE | |||
8348 | * User callback failed. | |||
8349 | */ | |||
8350 | static int conn_handshake_completed(ngtcp2_conn *conn) { | |||
8351 | int rv; | |||
8352 | ||||
8353 | conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED0x0100; | |||
8354 | ||||
8355 | rv = conn_call_handshake_completed(conn); | |||
8356 | if (rv != 0) { | |||
8357 | return rv; | |||
8358 | } | |||
8359 | ||||
8360 | if (conn->local.bidi.max_streams > 0) { | |||
8361 | rv = conn_call_extend_max_local_streams_bidi(conn, | |||
8362 | conn->local.bidi.max_streams); | |||
8363 | if (rv != 0) { | |||
8364 | return rv; | |||
8365 | } | |||
8366 | } | |||
8367 | if (conn->local.uni.max_streams > 0) { | |||
8368 | rv = conn_call_extend_max_local_streams_uni(conn, | |||
8369 | conn->local.uni.max_streams); | |||
8370 | if (rv != 0) { | |||
8371 | return rv; | |||
8372 | } | |||
8373 | } | |||
8374 | ||||
8375 | return 0; | |||
8376 | } | |||
8377 | ||||
8378 | /* | |||
8379 | * conn_recv_cpkt processes compound packet after handshake. The | |||
8380 | * buffer pointed by |pkt| might contain multiple packets. The Short | |||
8381 | * packet must be the last one because it does not have payload length | |||
8382 | * field. | |||
8383 | * | |||
8384 | * This function returns 0 if it succeeds, or the same negative error | |||
8385 | * codes from conn_recv_pkt except for NGTCP2_ERR_DISCARD_PKT. | |||
8386 | */ | |||
8387 | static int conn_recv_cpkt(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
8388 | const ngtcp2_pkt_info *pi, const uint8_t *pkt, | |||
8389 | size_t pktlen, ngtcp2_tstamp ts) { | |||
8390 | ngtcp2_ssize nread; | |||
8391 | int rv; | |||
8392 | const uint8_t *origpkt = pkt; | |||
8393 | size_t dgramlen = pktlen; | |||
8394 | ||||
8395 | if (ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { | |||
8396 | conn->dcid.current.bytes_recv += dgramlen; | |||
8397 | } | |||
8398 | ||||
8399 | while (pktlen) { | |||
8400 | nread = conn_recv_pkt(conn, path, pi, pkt, pktlen, dgramlen, ts, ts); | |||
8401 | if (nread < 0) { | |||
8402 | if (ngtcp2_err_is_fatal((int)nread)) { | |||
8403 | return (int)nread; | |||
8404 | } | |||
8405 | ||||
8406 | if (nread == NGTCP2_ERR_DRAINING-231) { | |||
8407 | return NGTCP2_ERR_DRAINING-231; | |||
8408 | } | |||
8409 | ||||
8410 | if (origpkt == pkt) { | |||
8411 | rv = conn_on_stateless_reset(conn, path, origpkt, dgramlen); | |||
8412 | if (rv == 0) { | |||
8413 | return NGTCP2_ERR_DRAINING-231; | |||
8414 | } | |||
8415 | } | |||
8416 | if (nread == NGTCP2_ERR_DISCARD_PKT-235) { | |||
8417 | return 0; | |||
8418 | } | |||
8419 | return (int)nread; | |||
8420 | } | |||
8421 | ||||
8422 | assert(pktlen >= (size_t)nread)((void) (0)); | |||
8423 | pkt += nread; | |||
8424 | pktlen -= (size_t)nread; | |||
8425 | ||||
8426 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_PKT, | |||
8427 | "read packet %td left %zu", nread, pktlen); | |||
8428 | } | |||
8429 | ||||
8430 | return 0; | |||
8431 | } | |||
8432 | ||||
8433 | /* | |||
8434 | * conn_is_retired_path returns nonzero if |path| is included in | |||
8435 | * retired path list. | |||
8436 | */ | |||
8437 | static int conn_is_retired_path(ngtcp2_conn *conn, const ngtcp2_path *path) { | |||
8438 | size_t i, len = ngtcp2_ringbuf_len(&conn->dcid.retired)((&conn->dcid.retired)->len); | |||
8439 | ngtcp2_dcid *dcid; | |||
8440 | ||||
8441 | for (i = 0; i < len; ++i) { | |||
8442 | dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, i); | |||
8443 | if (ngtcp2_path_eq(&dcid->ps.path, path)) { | |||
8444 | return 1; | |||
8445 | } | |||
8446 | } | |||
8447 | ||||
8448 | return 0; | |||
8449 | } | |||
8450 | ||||
8451 | /* | |||
8452 | * conn_enqueue_handshake_done enqueues HANDSHAKE_DONE frame for | |||
8453 | * transmission. | |||
8454 | */ | |||
8455 | static int conn_enqueue_handshake_done(ngtcp2_conn *conn) { | |||
8456 | ngtcp2_pktns *pktns = &conn->pktns; | |||
8457 | ngtcp2_frame_chain *nfrc; | |||
8458 | int rv; | |||
8459 | ||||
8460 | assert(conn->server)((void) (0)); | |||
8461 | ||||
8462 | rv = ngtcp2_frame_chain_new(&nfrc, conn->mem); | |||
8463 | if (rv != 0) { | |||
8464 | return rv; | |||
8465 | } | |||
8466 | ||||
8467 | nfrc->fr.type = NGTCP2_FRAME_HANDSHAKE_DONE; | |||
8468 | nfrc->next = pktns->tx.frq; | |||
8469 | pktns->tx.frq = nfrc; | |||
8470 | ||||
8471 | return 0; | |||
8472 | } | |||
8473 | ||||
8474 | /** | |||
8475 | * @function | |||
8476 | * | |||
8477 | * `conn_read_handshake` performs QUIC cryptographic handshake by | |||
8478 | * reading given data. |pkt| points to the buffer to read and | |||
8479 | * |pktlen| is the length of the buffer. |path| is the network path. | |||
8480 | * | |||
8481 | * This function returns 0 if it succeeds, or one of the following | |||
8482 | * negative error codes: (TBD). | |||
8483 | */ | |||
8484 | static int conn_read_handshake(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
8485 | const ngtcp2_pkt_info *pi, const uint8_t *pkt, | |||
8486 | size_t pktlen, ngtcp2_tstamp ts) { | |||
8487 | int rv; | |||
8488 | ||||
8489 | switch (conn->state) { | |||
8490 | case NGTCP2_CS_CLIENT_INITIAL: | |||
8491 | /* TODO Better to log something when we ignore input */ | |||
8492 | return 0; | |||
8493 | case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: | |||
8494 | rv = conn_recv_handshake_cpkt(conn, path, pi, pkt, pktlen, ts); | |||
8495 | if (rv < 0) { | |||
8496 | return rv; | |||
8497 | } | |||
8498 | ||||
8499 | if (conn->state == NGTCP2_CS_CLIENT_INITIAL) { | |||
8500 | /* Retry packet was received */ | |||
8501 | return 0; | |||
8502 | } | |||
8503 | ||||
8504 | assert(conn->hs_pktns)((void) (0)); | |||
8505 | ||||
8506 | if (conn->hs_pktns->crypto.rx.ckm && conn->in_pktns) { | |||
8507 | rv = conn_process_buffered_handshake_pkt(conn, ts); | |||
8508 | if (rv != 0) { | |||
8509 | return rv; | |||
8510 | } | |||
8511 | } | |||
8512 | ||||
8513 | if ((conn->flags & (NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01 | | |||
8514 | NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED0x0100)) == | |||
8515 | NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01) { | |||
8516 | rv = conn_handshake_completed(conn); | |||
8517 | if (rv != 0) { | |||
8518 | return rv; | |||
8519 | } | |||
8520 | } | |||
8521 | ||||
8522 | return 0; | |||
8523 | case NGTCP2_CS_SERVER_INITIAL: | |||
8524 | rv = conn_recv_handshake_cpkt(conn, path, pi, pkt, pktlen, ts); | |||
8525 | if (rv < 0) { | |||
8526 | return rv; | |||
8527 | } | |||
8528 | ||||
8529 | /* | |||
8530 | * Client ServerHello might not fit into single Initial packet | |||
8531 | * (e.g., resuming session with client authentication). If we get | |||
8532 | * Client Initial which does not increase offset or it is 0RTT | |||
8533 | * packet buffered, perform address validation in order to buffer | |||
8534 | * validated data only. | |||
8535 | */ | |||
8536 | if (ngtcp2_strm_rx_offset(&conn->in_pktns->crypto.strm) == 0) { | |||
8537 | if (conn->in_pktns->crypto.strm.rx.rob && | |||
8538 | ngtcp2_rob_data_buffered(conn->in_pktns->crypto.strm.rx.rob)) { | |||
8539 | /* Address has been validated with token */ | |||
8540 | if (conn->local.settings.token.len) { | |||
8541 | return 0; | |||
8542 | } | |||
8543 | return NGTCP2_ERR_RETRY-241; | |||
8544 | } | |||
8545 | if (conn->in_pktns->rx.buffed_pkts) { | |||
8546 | /* 0RTT is buffered, force retry */ | |||
8547 | return NGTCP2_ERR_RETRY-241; | |||
8548 | } | |||
8549 | /* If neither CRYPTO frame nor 0RTT packet is processed, just | |||
8550 | drop connection. */ | |||
8551 | return NGTCP2_ERR_DROP_CONN-242; | |||
8552 | } | |||
8553 | ||||
8554 | /* Process re-ordered 0-RTT packets which arrived before Initial | |||
8555 | packet. */ | |||
8556 | if (conn->early.ckm) { | |||
8557 | assert(conn->in_pktns)((void) (0)); | |||
8558 | ||||
8559 | rv = conn_process_buffered_protected_pkt(conn, conn->in_pktns, ts); | |||
8560 | if (rv != 0) { | |||
8561 | return rv; | |||
8562 | } | |||
8563 | } | |||
8564 | ||||
8565 | return 0; | |||
8566 | case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: | |||
8567 | rv = conn_recv_handshake_cpkt(conn, path, pi, pkt, pktlen, ts); | |||
8568 | if (rv < 0) { | |||
8569 | return rv; | |||
8570 | } | |||
8571 | ||||
8572 | if (conn->hs_pktns->crypto.rx.ckm) { | |||
8573 | rv = conn_process_buffered_handshake_pkt(conn, ts); | |||
8574 | if (rv != 0) { | |||
8575 | return rv; | |||
8576 | } | |||
8577 | } | |||
8578 | ||||
8579 | if (conn->hs_pktns->rx.max_pkt_num != -1) { | |||
8580 | conn_discard_initial_state(conn, ts); | |||
8581 | } | |||
8582 | ||||
8583 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
8584 | /* If server hits amplification limit, it cancels loss detection | |||
8585 | timer. If server receives a packet from client, the limit is | |||
8586 | increased and server can send more. If server has | |||
8587 | ack-eliciting Initial or Handshake packets, it should resend | |||
8588 | it if timer fired but timer is not armed in this case. So | |||
8589 | instead of resending Initial/Handshake packets, if server has | |||
8590 | 1RTT data to send, it might send them and then might hit | |||
8591 | amplification limit again until it hits stream data limit. | |||
8592 | Initial/Handshake data is not resent. In order to avoid this | |||
8593 | situation, try to arm loss detection and check the expiry | |||
8594 | here so that on next write call, we can resend | |||
8595 | Initial/Handshake first. */ | |||
8596 | if (conn->cstat.loss_detection_timer == UINT64_MAX(18446744073709551615UL)) { | |||
8597 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
8598 | if (ngtcp2_conn_loss_detection_expiry(conn) <= ts) { | |||
8599 | rv = ngtcp2_conn_on_loss_detection_timer(conn, ts); | |||
8600 | if (rv != 0) { | |||
8601 | return rv; | |||
8602 | } | |||
8603 | } | |||
8604 | } | |||
8605 | ||||
8606 | return 0; | |||
8607 | } | |||
8608 | ||||
8609 | if (!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED0x04)) { | |||
8610 | return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM-217; | |||
8611 | } | |||
8612 | ||||
8613 | rv = conn_handshake_completed(conn); | |||
8614 | if (rv != 0) { | |||
8615 | return rv; | |||
8616 | } | |||
8617 | conn->state = NGTCP2_CS_POST_HANDSHAKE; | |||
8618 | ||||
8619 | rv = conn_call_activate_dcid(conn, &conn->dcid.current); | |||
8620 | if (rv != 0) { | |||
8621 | return rv; | |||
8622 | } | |||
8623 | ||||
8624 | rv = conn_process_buffered_protected_pkt(conn, &conn->pktns, ts); | |||
8625 | if (rv != 0) { | |||
8626 | return rv; | |||
8627 | } | |||
8628 | ||||
8629 | conn_discard_handshake_state(conn, ts); | |||
8630 | ||||
8631 | rv = conn_enqueue_handshake_done(conn); | |||
8632 | if (rv != 0) { | |||
8633 | return rv; | |||
8634 | } | |||
8635 | ||||
8636 | conn->pktns.rtb.persistent_congestion_start_ts = ts; | |||
8637 | ||||
8638 | /* Re-arm loss detection timer here after handshake has been | |||
8639 | confirmed. */ | |||
8640 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
8641 | ||||
8642 | return 0; | |||
8643 | case NGTCP2_CS_CLOSING: | |||
8644 | return NGTCP2_ERR_CLOSING-230; | |||
8645 | case NGTCP2_CS_DRAINING: | |||
8646 | return NGTCP2_ERR_DRAINING-231; | |||
8647 | default: | |||
8648 | return 0; | |||
8649 | } | |||
8650 | } | |||
8651 | ||||
8652 | int ngtcp2_conn_read_pkt(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
8653 | const ngtcp2_pkt_info *pi, const uint8_t *pkt, | |||
8654 | size_t pktlen, ngtcp2_tstamp ts) { | |||
8655 | int rv = 0; | |||
8656 | ||||
8657 | conn->log.last_ts = ts; | |||
8658 | conn->qlog.last_ts = ts; | |||
8659 | ||||
8660 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, "recv packet len=%zu", | |||
8661 | pktlen); | |||
8662 | ||||
8663 | if (pktlen == 0) { | |||
8664 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
8665 | } | |||
8666 | ||||
8667 | /* client does not expect a packet from unknown path. */ | |||
8668 | if (!conn->server && !ngtcp2_path_eq(&conn->dcid.current.ps.path, path) && | |||
8669 | (!conn->pv || !ngtcp2_path_eq(&conn->pv->dcid.ps.path, path)) && | |||
8670 | !conn_is_retired_path(conn, path)) { | |||
8671 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
8672 | "ignore packet from unknown path"); | |||
8673 | return 0; | |||
8674 | } | |||
8675 | ||||
8676 | switch (conn->state) { | |||
8677 | case NGTCP2_CS_CLIENT_INITIAL: | |||
8678 | case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: | |||
8679 | case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED: | |||
8680 | return conn_read_handshake(conn, path, pi, pkt, pktlen, ts); | |||
8681 | case NGTCP2_CS_SERVER_INITIAL: | |||
8682 | case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: | |||
8683 | case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED: | |||
8684 | if (!ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { | |||
8685 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
8686 | "ignore packet from unknown path during handshake"); | |||
8687 | ||||
8688 | if (conn->state == NGTCP2_CS_SERVER_INITIAL && | |||
8689 | ngtcp2_strm_rx_offset(&conn->in_pktns->crypto.strm) == 0 && | |||
8690 | (!conn->in_pktns->crypto.strm.rx.rob || | |||
8691 | !ngtcp2_rob_data_buffered(conn->in_pktns->crypto.strm.rx.rob))) { | |||
8692 | return NGTCP2_ERR_DROP_CONN-242; | |||
8693 | } | |||
8694 | ||||
8695 | return 0; | |||
8696 | } | |||
8697 | return conn_read_handshake(conn, path, pi, pkt, pktlen, ts); | |||
8698 | case NGTCP2_CS_CLOSING: | |||
8699 | return NGTCP2_ERR_CLOSING-230; | |||
8700 | case NGTCP2_CS_DRAINING: | |||
8701 | return NGTCP2_ERR_DRAINING-231; | |||
8702 | case NGTCP2_CS_POST_HANDSHAKE: | |||
8703 | rv = conn_prepare_key_update(conn, ts); | |||
8704 | if (rv != 0) { | |||
8705 | return rv; | |||
8706 | } | |||
8707 | return conn_recv_cpkt(conn, path, pi, pkt, pktlen, ts); | |||
8708 | default: | |||
8709 | assert(0)((void) (0)); | |||
8710 | abort(); | |||
8711 | } | |||
8712 | } | |||
8713 | ||||
8714 | /* | |||
8715 | * conn_check_pkt_num_exhausted returns nonzero if packet number is | |||
8716 | * exhausted in at least one of packet number space. | |||
8717 | */ | |||
8718 | static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) { | |||
8719 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
8720 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
8721 | ||||
8722 | return (in_pktns && in_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1))) || | |||
8723 | (hs_pktns && hs_pktns->tx.last_pkt_num == NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1))) || | |||
8724 | conn->pktns.tx.last_pkt_num == NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1)); | |||
8725 | } | |||
8726 | ||||
8727 | /* | |||
8728 | * conn_retransmit_retry_early retransmits 0RTT packet after Retry is | |||
8729 | * received from server. | |||
8730 | */ | |||
8731 | static ngtcp2_ssize conn_retransmit_retry_early(ngtcp2_conn *conn, | |||
8732 | ngtcp2_pkt_info *pi, | |||
8733 | uint8_t *dest, size_t destlen, | |||
8734 | ngtcp2_tstamp ts) { | |||
8735 | return conn_write_pkt(conn, pi, dest, destlen, NULL((void*)0), NGTCP2_PKT_0RTT, | |||
8736 | NGTCP2_WRITE_PKT_FLAG_NONE0x00, ts); | |||
8737 | } | |||
8738 | ||||
8739 | /* | |||
8740 | * conn_handshake_probe_left returns nonzero if there are probe | |||
8741 | * packets to be sent for Initial or Handshake packet number space | |||
8742 | * left. | |||
8743 | */ | |||
8744 | static int conn_handshake_probe_left(ngtcp2_conn *conn) { | |||
8745 | return (conn->in_pktns && conn->in_pktns->rtb.probe_pkt_left) || | |||
8746 | conn->hs_pktns->rtb.probe_pkt_left; | |||
8747 | } | |||
8748 | ||||
8749 | /* | |||
8750 | * conn_write_handshake writes QUIC handshake packets to the buffer | |||
8751 | * pointed by |dest| of length |destlen|. |early_datalen| specifies | |||
8752 | * the expected length of early data to send. Specify 0 to | |||
8753 | * |early_datalen| if there is no early data. | |||
8754 | * | |||
8755 | * This function returns the number of bytes written to the buffer, or | |||
8756 | * one of the following negative error codes: | |||
8757 | * | |||
8758 | * NGTCP2_ERR_PKT_NUM_EXHAUSTED | |||
8759 | * Packet number is exhausted. | |||
8760 | * NGTCP2_ERR_NOMEM | |||
8761 | * Out of memory | |||
8762 | * NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM | |||
8763 | * Required transport parameter is missing. | |||
8764 | * NGTCP2_CS_CLOSING | |||
8765 | * Connection is in closing state. | |||
8766 | * NGTCP2_CS_DRAINING | |||
8767 | * Connection is in draining state. | |||
8768 | * | |||
8769 | * In addition to the above negative error codes, the same error codes | |||
8770 | * from conn_recv_pkt may also be returned. | |||
8771 | */ | |||
8772 | static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, | |||
8773 | uint8_t *dest, size_t destlen, | |||
8774 | size_t early_datalen, | |||
8775 | ngtcp2_tstamp ts) { | |||
8776 | int rv; | |||
8777 | ngtcp2_ssize res = 0, nwrite = 0, early_spktlen = 0; | |||
8778 | size_t origlen = destlen; | |||
8779 | size_t server_tx_left; | |||
8780 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
8781 | size_t pending_early_datalen; | |||
8782 | ngtcp2_dcid *dcid; | |||
8783 | ngtcp2_preferred_addr *paddr; | |||
8784 | ||||
8785 | switch (conn->state) { | |||
8786 | case NGTCP2_CS_CLIENT_INITIAL: | |||
8787 | pending_early_datalen = conn_retry_early_payloadlen(conn); | |||
8788 | if (pending_early_datalen) { | |||
8789 | early_datalen = pending_early_datalen; | |||
8790 | } | |||
8791 | ||||
8792 | if (!(conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY0x10)) { | |||
8793 | nwrite = | |||
8794 | conn_write_client_initial(conn, pi, dest, destlen, early_datalen, ts); | |||
8795 | if (nwrite <= 0) { | |||
8796 | return nwrite; | |||
8797 | } | |||
8798 | } else { | |||
8799 | nwrite = conn_write_handshake_pkt( | |||
8800 | conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, | |||
8801 | NGTCP2_WRITE_PKT_FLAG_NONE0x00, early_datalen, ts); | |||
8802 | if (nwrite < 0) { | |||
8803 | return nwrite; | |||
8804 | } | |||
8805 | } | |||
8806 | ||||
8807 | if (pending_early_datalen) { | |||
8808 | early_spktlen = conn_retransmit_retry_early(conn, pi, dest + nwrite, | |||
8809 | destlen - (size_t)nwrite, ts); | |||
8810 | ||||
8811 | if (early_spktlen < 0) { | |||
8812 | assert(ngtcp2_err_is_fatal((int)early_spktlen))((void) (0)); | |||
8813 | return early_spktlen; | |||
8814 | } | |||
8815 | } | |||
8816 | ||||
8817 | conn->state = NGTCP2_CS_CLIENT_WAIT_HANDSHAKE; | |||
8818 | ||||
8819 | res = nwrite + early_spktlen; | |||
8820 | ||||
8821 | return res; | |||
8822 | case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: | |||
8823 | if (!conn_handshake_probe_left(conn) && conn_cwnd_is_zero(conn)) { | |||
8824 | destlen = 0; | |||
8825 | } else { | |||
8826 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED0x0100)) { | |||
8827 | pending_early_datalen = conn_retry_early_payloadlen(conn); | |||
8828 | if (pending_early_datalen) { | |||
8829 | early_datalen = pending_early_datalen; | |||
8830 | } | |||
8831 | } | |||
8832 | ||||
8833 | nwrite = | |||
8834 | conn_write_handshake_pkts(conn, pi, dest, destlen, early_datalen, ts); | |||
8835 | if (nwrite < 0) { | |||
8836 | return nwrite; | |||
8837 | } | |||
8838 | ||||
8839 | res += nwrite; | |||
8840 | dest += nwrite; | |||
8841 | destlen -= (size_t)nwrite; | |||
8842 | } | |||
8843 | ||||
8844 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
8845 | if (!(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED0x20)) { | |||
8846 | nwrite = conn_retransmit_retry_early(conn, pi, dest, destlen, ts); | |||
8847 | if (nwrite < 0) { | |||
8848 | return nwrite; | |||
8849 | } | |||
8850 | ||||
8851 | res += nwrite; | |||
8852 | } | |||
8853 | ||||
8854 | if (res == 0) { | |||
8855 | nwrite = conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); | |||
8856 | if (nwrite < 0) { | |||
8857 | return nwrite; | |||
8858 | } | |||
8859 | res = nwrite; | |||
8860 | } | |||
8861 | ||||
8862 | return res; | |||
8863 | } | |||
8864 | ||||
8865 | if (!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED0x04)) { | |||
8866 | return NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM-217; | |||
8867 | } | |||
8868 | ||||
8869 | conn->state = NGTCP2_CS_POST_HANDSHAKE; | |||
8870 | ||||
8871 | if (conn->remote.transport_params.preferred_address_present) { | |||
8872 | assert(!ngtcp2_ringbuf_full(&conn->dcid.unused))((void) (0)); | |||
8873 | ||||
8874 | paddr = &conn->remote.transport_params.preferred_address; | |||
8875 | dcid = ngtcp2_ringbuf_push_back(&conn->dcid.unused); | |||
8876 | ngtcp2_dcid_init(dcid, 1, &paddr->cid, paddr->stateless_reset_token); | |||
8877 | ||||
8878 | rv = ngtcp2_gaptr_push(&conn->dcid.seqgap, 1, 1); | |||
8879 | if (rv != 0) { | |||
8880 | return (ngtcp2_ssize)rv; | |||
8881 | } | |||
8882 | } | |||
8883 | ||||
8884 | if (conn->remote.transport_params.stateless_reset_token_present) { | |||
8885 | assert(conn->dcid.current.seq == 0)((void) (0)); | |||
8886 | memcpy(conn->dcid.current.token, | |||
8887 | conn->remote.transport_params.stateless_reset_token, | |||
8888 | sizeof(conn->dcid.current.token)); | |||
8889 | } | |||
8890 | ||||
8891 | rv = conn_call_activate_dcid(conn, &conn->dcid.current); | |||
8892 | if (rv != 0) { | |||
8893 | return rv; | |||
8894 | } | |||
8895 | ||||
8896 | conn_process_early_rtb(conn); | |||
8897 | ||||
8898 | rv = conn_process_buffered_protected_pkt(conn, &conn->pktns, ts); | |||
8899 | if (rv != 0) { | |||
8900 | return (ngtcp2_ssize)rv; | |||
8901 | } | |||
8902 | ||||
8903 | return res; | |||
8904 | case NGTCP2_CS_SERVER_INITIAL: | |||
8905 | nwrite = conn_write_handshake_pkts(conn, pi, dest, destlen, | |||
8906 | /* early_datalen = */ 0, ts); | |||
8907 | if (nwrite < 0) { | |||
8908 | return nwrite; | |||
8909 | } | |||
8910 | ||||
8911 | if (nwrite) { | |||
8912 | conn->state = NGTCP2_CS_SERVER_WAIT_HANDSHAKE; | |||
8913 | } | |||
8914 | ||||
8915 | return nwrite; | |||
8916 | case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: | |||
8917 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
8918 | if (!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01)) { | |||
8919 | server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); | |||
8920 | if (server_tx_left == 0) { | |||
8921 | if (cstat->loss_detection_timer != UINT64_MAX(18446744073709551615UL)) { | |||
8922 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
8923 | "loss detection timer canceled"); | |||
8924 | cstat->loss_detection_timer = UINT64_MAX(18446744073709551615UL); | |||
8925 | cstat->pto_count = 0; | |||
8926 | } | |||
8927 | return 0; | |||
8928 | } | |||
8929 | } | |||
8930 | ||||
8931 | if (conn_handshake_probe_left(conn) || !conn_cwnd_is_zero(conn)) { | |||
8932 | nwrite = conn_write_handshake_pkts(conn, pi, dest, destlen, | |||
8933 | /* early_datalen = */ 0, ts); | |||
8934 | if (nwrite < 0) { | |||
8935 | return nwrite; | |||
8936 | } | |||
8937 | ||||
8938 | res += nwrite; | |||
8939 | dest += nwrite; | |||
8940 | destlen -= (size_t)nwrite; | |||
8941 | } | |||
8942 | ||||
8943 | if (res == 0) { | |||
8944 | nwrite = conn_write_handshake_ack_pkts(conn, pi, dest, origlen, ts); | |||
8945 | if (nwrite < 0) { | |||
8946 | return nwrite; | |||
8947 | } | |||
8948 | ||||
8949 | res += nwrite; | |||
8950 | dest += nwrite; | |||
8951 | origlen -= (size_t)nwrite; | |||
8952 | } | |||
8953 | ||||
8954 | return res; | |||
8955 | } | |||
8956 | ||||
8957 | return 0; | |||
8958 | case NGTCP2_CS_CLOSING: | |||
8959 | return NGTCP2_ERR_CLOSING-230; | |||
8960 | case NGTCP2_CS_DRAINING: | |||
8961 | return NGTCP2_ERR_DRAINING-231; | |||
8962 | default: | |||
8963 | return 0; | |||
8964 | } | |||
8965 | } | |||
8966 | ||||
8967 | /** | |||
8968 | * @function | |||
8969 | * | |||
8970 | * `conn_client_write_handshake` writes client side handshake data and | |||
8971 | * 0RTT packet. | |||
8972 | * | |||
8973 | * In order to send STREAM data in 0RTT packet, specify | |||
8974 | * |vmsg|->stream. |vmsg|->stream.strm, |vmsg|->stream.fin, | |||
8975 | * |vmsg|->stream.data, and |vmsg|->stream.datacnt are stream to which | |||
8976 | * 0-RTT data is sent, whether it is a last data chunk in this stream, | |||
8977 | * a vector of 0-RTT data, and its number of elements respectively. | |||
8978 | * The amount of 0RTT data sent is assigned to | |||
8979 | * *|vmsg|->stream.pdatalen. If no data is sent, -1 is assigned. | |||
8980 | * Note that 0 length STREAM frame is allowed in QUIC, so 0 might be | |||
8981 | * assigned to *|vmsg|->stream.pdatalen. | |||
8982 | * | |||
8983 | * This function returns 0 if it cannot write any frame because buffer | |||
8984 | * is too small, or packet is congestion limited. Application should | |||
8985 | * keep reading and wait for congestion window to grow. | |||
8986 | * | |||
8987 | * This function returns the number of bytes written to the buffer | |||
8988 | * pointed by |dest| if it succeeds, or one of the following negative | |||
8989 | * error codes: (TBD). | |||
8990 | */ | |||
8991 | static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, | |||
8992 | ngtcp2_pkt_info *pi, | |||
8993 | uint8_t *dest, size_t destlen, | |||
8994 | ngtcp2_vmsg *vmsg, | |||
8995 | ngtcp2_tstamp ts) { | |||
8996 | int send_stream = 0; | |||
8997 | int send_datagram = 0; | |||
8998 | ngtcp2_ssize spktlen, early_spktlen; | |||
8999 | int was_client_initial; | |||
9000 | size_t datalen; | |||
9001 | size_t early_datalen = 0; | |||
9002 | uint8_t wflags = NGTCP2_WRITE_PKT_FLAG_NONE0x00; | |||
9003 | int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING0x1000) != 0; | |||
9004 | ||||
9005 | assert(!conn->server)((void) (0)); | |||
9006 | ||||
9007 | /* conn->early.ckm might be created in the first call of | |||
9008 | conn_handshake(). Check it later. */ | |||
9009 | if (vmsg && !(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED0x20)) { | |||
9010 | switch (vmsg->type) { | |||
9011 | case NGTCP2_VMSG_TYPE_STREAM: | |||
9012 | datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt); | |||
9013 | send_stream = | |||
9014 | conn_retry_early_payloadlen(conn) == 0 && | |||
9015 | /* 0 length STREAM frame is allowed */ | |||
9016 | (datalen == 0 || | |||
9017 | (datalen > 0 && | |||
9018 | (vmsg->stream.strm->tx.max_offset - vmsg->stream.strm->tx.offset) && | |||
9019 | (conn->tx.max_offset - conn->tx.offset))); | |||
9020 | if (send_stream) { | |||
9021 | early_datalen = | |||
9022 | conn_enforce_flow_control(conn, vmsg->stream.strm, datalen) + | |||
9023 | NGTCP2_STREAM_OVERHEAD(1 + 8 + 8 + 8); | |||
9024 | ||||
9025 | if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE0x01) { | |||
9026 | wflags |= NGTCP2_WRITE_PKT_FLAG_MORE0x02; | |||
9027 | } | |||
9028 | } else { | |||
9029 | vmsg = NULL((void*)0); | |||
9030 | } | |||
9031 | break; | |||
9032 | case NGTCP2_VMSG_TYPE_DATAGRAM: | |||
9033 | datalen = ngtcp2_vec_len(vmsg->datagram.data, vmsg->datagram.datacnt); | |||
9034 | /* TODO Do we need this? DATAGRAM is independent from STREAM | |||
9035 | data and no retransmission */ | |||
9036 | send_datagram = conn_retry_early_payloadlen(conn) == 0; | |||
9037 | if (send_datagram) { | |||
9038 | early_datalen = datalen + NGTCP2_DATAGRAM_OVERHEAD(1 + 8); | |||
9039 | ||||
9040 | if (vmsg->datagram.flags & NGTCP2_WRITE_DATAGRAM_FLAG_MORE0x01) { | |||
9041 | wflags |= NGTCP2_WRITE_PKT_FLAG_MORE0x02; | |||
9042 | } | |||
9043 | } else { | |||
9044 | vmsg = NULL((void*)0); | |||
9045 | } | |||
9046 | break; | |||
9047 | } | |||
9048 | } | |||
9049 | ||||
9050 | if (!ppe_pending) { | |||
9051 | was_client_initial = conn->state == NGTCP2_CS_CLIENT_INITIAL; | |||
9052 | spktlen = conn_write_handshake(conn, pi, dest, destlen, early_datalen, ts); | |||
9053 | ||||
9054 | if (spktlen < 0) { | |||
9055 | return spktlen; | |||
9056 | } | |||
9057 | ||||
9058 | if (conn->pktns.crypto.tx.ckm || !conn->early.ckm || | |||
9059 | (!send_stream && !send_datagram)) { | |||
9060 | return spktlen; | |||
9061 | } | |||
9062 | } else { | |||
9063 | assert(!conn->pktns.crypto.tx.ckm)((void) (0)); | |||
9064 | assert(conn->early.ckm)((void) (0)); | |||
9065 | ||||
9066 | was_client_initial = conn->pkt.was_client_initial; | |||
9067 | spktlen = conn->pkt.hs_spktlen; | |||
9068 | } | |||
9069 | ||||
9070 | /* If spktlen > 0, we are making a compound packet. If Initial | |||
9071 | packet is written, we have to pad bytes to 0-RTT packet. */ | |||
9072 | ||||
9073 | if (spktlen && was_client_initial) { | |||
9074 | wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING0x01; | |||
9075 | } | |||
9076 | ||||
9077 | dest += spktlen; | |||
9078 | destlen -= (size_t)spktlen; | |||
9079 | ||||
9080 | if (conn_cwnd_is_zero(conn)) { | |||
9081 | return spktlen; | |||
9082 | } | |||
9083 | ||||
9084 | early_spktlen = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_0RTT, | |||
9085 | wflags, ts); | |||
9086 | ||||
9087 | if (early_spktlen < 0) { | |||
9088 | switch (early_spktlen) { | |||
9089 | case NGTCP2_ERR_STREAM_DATA_BLOCKED-210: | |||
9090 | return spktlen; | |||
9091 | case NGTCP2_ERR_WRITE_MORE-240: | |||
9092 | conn->pkt.was_client_initial = was_client_initial; | |||
9093 | conn->pkt.hs_spktlen = spktlen; | |||
9094 | break; | |||
9095 | } | |||
9096 | return early_spktlen; | |||
9097 | } | |||
9098 | ||||
9099 | return spktlen + early_spktlen; | |||
9100 | } | |||
9101 | ||||
9102 | void ngtcp2_conn_handshake_completed(ngtcp2_conn *conn) { | |||
9103 | conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01; | |||
9104 | if (conn->server) { | |||
9105 | conn->flags |= NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80; | |||
9106 | } | |||
9107 | } | |||
9108 | ||||
9109 | int ngtcp2_conn_get_handshake_completed(ngtcp2_conn *conn) { | |||
9110 | return (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01) && | |||
9111 | (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED0x0100); | |||
9112 | } | |||
9113 | ||||
9114 | int ngtcp2_conn_sched_ack(ngtcp2_conn *conn, ngtcp2_acktr *acktr, | |||
9115 | int64_t pkt_num, int active_ack, ngtcp2_tstamp ts) { | |||
9116 | int rv; | |||
9117 | (void)conn; | |||
9118 | ||||
9119 | rv = ngtcp2_acktr_add(acktr, pkt_num, active_ack, ts); | |||
9120 | if (rv != 0) { | |||
9121 | assert(rv != NGTCP2_ERR_INVALID_ARGUMENT)((void) (0)); | |||
9122 | return rv; | |||
9123 | } | |||
9124 | ||||
9125 | return 0; | |||
9126 | } | |||
9127 | ||||
9128 | int ngtcp2_accept(ngtcp2_pkt_hd *dest, const uint8_t *pkt, size_t pktlen) { | |||
9129 | ngtcp2_ssize nread; | |||
9130 | ngtcp2_pkt_hd hd, *p; | |||
9131 | ||||
9132 | if (dest) { | |||
9133 | p = dest; | |||
9134 | } else { | |||
9135 | p = &hd; | |||
9136 | } | |||
9137 | ||||
9138 | if (pktlen == 0 || (pkt[0] & NGTCP2_HEADER_FORM_BIT0x80) == 0) { | |||
9139 | return -1; | |||
9140 | } | |||
9141 | ||||
9142 | nread = ngtcp2_pkt_decode_hd_long(p, pkt, pktlen); | |||
9143 | if (nread < 0) { | |||
9144 | return -1; | |||
9145 | } | |||
9146 | ||||
9147 | switch (p->type) { | |||
9148 | case NGTCP2_PKT_INITIAL: | |||
9149 | if (pktlen < NGTCP2_MIN_INITIAL_PKTLEN1200) { | |||
9150 | return -1; | |||
9151 | } | |||
9152 | if (p->token.len == 0 && p->dcid.datalen < NGTCP2_MIN_INITIAL_DCIDLEN8) { | |||
9153 | return -1; | |||
9154 | } | |||
9155 | break; | |||
9156 | case NGTCP2_PKT_0RTT: | |||
9157 | /* 0-RTT packet may arrive before Initial packet due to | |||
9158 | re-ordering. */ | |||
9159 | break; | |||
9160 | default: | |||
9161 | return -1; | |||
9162 | } | |||
9163 | ||||
9164 | if (p->version != NGTCP2_PROTO_VER_V10x00000001u && | |||
9165 | (p->version < NGTCP2_PROTO_VER_DRAFT_MIN0xff00001du || | |||
9166 | NGTCP2_PROTO_VER_DRAFT_MAX0xff000020u < p->version)) { | |||
9167 | return 1; | |||
9168 | } | |||
9169 | ||||
9170 | return 0; | |||
9171 | } | |||
9172 | ||||
9173 | int ngtcp2_conn_install_initial_key( | |||
9174 | ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *rx_aead_ctx, | |||
9175 | const uint8_t *rx_iv, const ngtcp2_crypto_cipher_ctx *rx_hp_ctx, | |||
9176 | const ngtcp2_crypto_aead_ctx *tx_aead_ctx, const uint8_t *tx_iv, | |||
9177 | const ngtcp2_crypto_cipher_ctx *tx_hp_ctx, size_t ivlen) { | |||
9178 | ngtcp2_pktns *pktns = conn->in_pktns; | |||
9179 | int rv; | |||
9180 | ||||
9181 | assert(pktns)((void) (0)); | |||
9182 | ||||
9183 | conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.rx.hp_ctx); | |||
9184 | pktns->crypto.rx.hp_ctx.native_handle = NULL((void*)0); | |||
9185 | ||||
9186 | if (pktns->crypto.rx.ckm) { | |||
9187 | conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.rx.ckm->aead_ctx); | |||
9188 | ngtcp2_crypto_km_del(pktns->crypto.rx.ckm, conn->mem); | |||
9189 | pktns->crypto.rx.ckm = NULL((void*)0); | |||
9190 | } | |||
9191 | ||||
9192 | conn_call_delete_crypto_cipher_ctx(conn, &pktns->crypto.tx.hp_ctx); | |||
9193 | pktns->crypto.tx.hp_ctx.native_handle = NULL((void*)0); | |||
9194 | ||||
9195 | if (pktns->crypto.tx.ckm) { | |||
9196 | conn_call_delete_crypto_aead_ctx(conn, &pktns->crypto.tx.ckm->aead_ctx); | |||
9197 | ngtcp2_crypto_km_del(pktns->crypto.tx.ckm, conn->mem); | |||
9198 | pktns->crypto.tx.ckm = NULL((void*)0); | |||
9199 | } | |||
9200 | ||||
9201 | rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, NULL((void*)0), 0, NULL((void*)0), rx_iv, ivlen, | |||
9202 | conn->mem); | |||
9203 | if (rv != 0) { | |||
9204 | return rv; | |||
9205 | } | |||
9206 | ||||
9207 | rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL((void*)0), 0, NULL((void*)0), tx_iv, ivlen, | |||
9208 | conn->mem); | |||
9209 | if (rv != 0) { | |||
9210 | return rv; | |||
9211 | } | |||
9212 | ||||
9213 | /* Take owner ship after we are sure that no failure occurs, so that | |||
9214 | caller can delete these contexts on failure. */ | |||
9215 | pktns->crypto.rx.ckm->aead_ctx = *rx_aead_ctx; | |||
9216 | pktns->crypto.rx.hp_ctx = *rx_hp_ctx; | |||
9217 | pktns->crypto.tx.ckm->aead_ctx = *tx_aead_ctx; | |||
9218 | pktns->crypto.tx.hp_ctx = *tx_hp_ctx; | |||
9219 | ||||
9220 | return 0; | |||
9221 | } | |||
9222 | ||||
9223 | int ngtcp2_conn_install_rx_handshake_key( | |||
9224 | ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, | |||
9225 | const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) { | |||
9226 | ngtcp2_pktns *pktns = conn->hs_pktns; | |||
9227 | int rv; | |||
9228 | ||||
9229 | assert(pktns)((void) (0)); | |||
9230 | assert(!pktns->crypto.rx.hp_ctx.native_handle)((void) (0)); | |||
9231 | assert(!pktns->crypto.rx.ckm)((void) (0)); | |||
9232 | ||||
9233 | rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, NULL((void*)0), 0, aead_ctx, iv, ivlen, | |||
9234 | conn->mem); | |||
9235 | if (rv != 0) { | |||
9236 | return rv; | |||
9237 | } | |||
9238 | ||||
9239 | pktns->crypto.rx.hp_ctx = *hp_ctx; | |||
9240 | ||||
9241 | return 0; | |||
9242 | } | |||
9243 | ||||
9244 | int ngtcp2_conn_install_tx_handshake_key( | |||
9245 | ngtcp2_conn *conn, const ngtcp2_crypto_aead_ctx *aead_ctx, | |||
9246 | const uint8_t *iv, size_t ivlen, const ngtcp2_crypto_cipher_ctx *hp_ctx) { | |||
9247 | ngtcp2_pktns *pktns = conn->hs_pktns; | |||
9248 | int rv; | |||
9249 | ||||
9250 | assert(pktns)((void) (0)); | |||
9251 | assert(!pktns->crypto.tx.hp_ctx.native_handle)((void) (0)); | |||
9252 | assert(!pktns->crypto.tx.ckm)((void) (0)); | |||
9253 | ||||
9254 | rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, NULL((void*)0), 0, aead_ctx, iv, ivlen, | |||
9255 | conn->mem); | |||
9256 | if (rv != 0) { | |||
9257 | return rv; | |||
9258 | } | |||
9259 | ||||
9260 | pktns->crypto.tx.hp_ctx = *hp_ctx; | |||
9261 | ||||
9262 | if (conn->server) { | |||
9263 | return ngtcp2_conn_commit_local_transport_params(conn); | |||
9264 | } | |||
9265 | ||||
9266 | return 0; | |||
9267 | } | |||
9268 | ||||
9269 | int ngtcp2_conn_install_early_key(ngtcp2_conn *conn, | |||
9270 | const ngtcp2_crypto_aead_ctx *aead_ctx, | |||
9271 | const uint8_t *iv, size_t ivlen, | |||
9272 | const ngtcp2_crypto_cipher_ctx *hp_ctx) { | |||
9273 | int rv; | |||
9274 | ||||
9275 | assert(!conn->early.hp_ctx.native_handle)((void) (0)); | |||
9276 | assert(!conn->early.ckm)((void) (0)); | |||
9277 | ||||
9278 | rv = ngtcp2_crypto_km_new(&conn->early.ckm, NULL((void*)0), 0, aead_ctx, iv, ivlen, | |||
9279 | conn->mem); | |||
9280 | if (rv != 0) { | |||
9281 | return rv; | |||
9282 | } | |||
9283 | ||||
9284 | conn->early.hp_ctx = *hp_ctx; | |||
9285 | ||||
9286 | return 0; | |||
9287 | } | |||
9288 | ||||
9289 | int ngtcp2_conn_install_rx_key(ngtcp2_conn *conn, const uint8_t *secret, | |||
9290 | size_t secretlen, | |||
9291 | const ngtcp2_crypto_aead_ctx *aead_ctx, | |||
9292 | const uint8_t *iv, size_t ivlen, | |||
9293 | const ngtcp2_crypto_cipher_ctx *hp_ctx) { | |||
9294 | ngtcp2_pktns *pktns = &conn->pktns; | |||
9295 | int rv; | |||
9296 | ||||
9297 | assert(!pktns->crypto.rx.hp_ctx.native_handle)((void) (0)); | |||
9298 | assert(!pktns->crypto.rx.ckm)((void) (0)); | |||
9299 | ||||
9300 | rv = ngtcp2_crypto_km_new(&pktns->crypto.rx.ckm, secret, secretlen, aead_ctx, | |||
9301 | iv, ivlen, conn->mem); | |||
9302 | if (rv != 0) { | |||
9303 | return rv; | |||
9304 | } | |||
9305 | ||||
9306 | pktns->crypto.rx.hp_ctx = *hp_ctx; | |||
9307 | ||||
9308 | if (!conn->server) { | |||
9309 | conn->remote.transport_params = conn->remote.pending_transport_params; | |||
9310 | conn_sync_stream_id_limit(conn); | |||
9311 | conn->tx.max_offset = conn->remote.transport_params.initial_max_data; | |||
9312 | } | |||
9313 | ||||
9314 | return 0; | |||
9315 | } | |||
9316 | ||||
9317 | int ngtcp2_conn_install_tx_key(ngtcp2_conn *conn, const uint8_t *secret, | |||
9318 | size_t secretlen, | |||
9319 | const ngtcp2_crypto_aead_ctx *aead_ctx, | |||
9320 | const uint8_t *iv, size_t ivlen, | |||
9321 | const ngtcp2_crypto_cipher_ctx *hp_ctx) { | |||
9322 | ngtcp2_pktns *pktns = &conn->pktns; | |||
9323 | int rv; | |||
9324 | ||||
9325 | assert(!pktns->crypto.tx.hp_ctx.native_handle)((void) (0)); | |||
9326 | assert(!pktns->crypto.tx.ckm)((void) (0)); | |||
9327 | ||||
9328 | rv = ngtcp2_crypto_km_new(&pktns->crypto.tx.ckm, secret, secretlen, aead_ctx, | |||
9329 | iv, ivlen, conn->mem); | |||
9330 | if (rv != 0) { | |||
9331 | return rv; | |||
9332 | } | |||
9333 | ||||
9334 | pktns->crypto.tx.hp_ctx = *hp_ctx; | |||
9335 | ||||
9336 | if (conn->server) { | |||
9337 | conn->remote.transport_params = conn->remote.pending_transport_params; | |||
9338 | conn_sync_stream_id_limit(conn); | |||
9339 | conn->tx.max_offset = conn->remote.transport_params.initial_max_data; | |||
9340 | } else if (conn->early.ckm) { | |||
9341 | conn_discard_early_key(conn); | |||
9342 | } | |||
9343 | ||||
9344 | return 0; | |||
9345 | } | |||
9346 | ||||
9347 | int ngtcp2_conn_initiate_key_update(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
9348 | ngtcp2_tstamp confirmed_ts = conn->crypto.key_update.confirmed_ts; | |||
9349 | ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); | |||
9350 | ||||
9351 | assert(conn->state == NGTCP2_CS_POST_HANDSHAKE)((void) (0)); | |||
9352 | ||||
9353 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80) || | |||
9354 | (conn->flags & NGTCP2_CONN_FLAG_KEY_UPDATE_NOT_CONFIRMED0x0800) || | |||
9355 | !conn->crypto.key_update.new_tx_ckm || | |||
9356 | !conn->crypto.key_update.new_rx_ckm || | |||
9357 | (confirmed_ts != UINT64_MAX(18446744073709551615UL) && confirmed_ts + 3 * pto > ts)) { | |||
9358 | return NGTCP2_ERR_INVALID_STATE-206; | |||
9359 | } | |||
9360 | ||||
9361 | conn_rotate_keys(conn, NGTCP2_MAX_PKT_NUM((int64_t)((1ll << 62) - 1))); | |||
9362 | ||||
9363 | return 0; | |||
9364 | } | |||
9365 | ||||
9366 | ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) { | |||
9367 | return conn->cstat.loss_detection_timer; | |||
9368 | } | |||
9369 | ||||
9370 | ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { | |||
9371 | ngtcp2_tstamp res = UINT64_MAX(18446744073709551615UL), t; | |||
9372 | ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); | |||
9373 | ngtcp2_scid *scid; | |||
9374 | ngtcp2_dcid *dcid; | |||
9375 | ||||
9376 | if (conn->pv) { | |||
9377 | res = ngtcp2_pv_next_expiry(conn->pv); | |||
9378 | } | |||
9379 | ||||
9380 | if (!ngtcp2_pq_empty(&conn->scid.used)) { | |||
9381 | scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe)((ngtcp2_scid *)(void *)((char *)(ngtcp2_pq_top(&conn-> scid.used))-__builtin_offsetof(ngtcp2_scid, pe))); | |||
9382 | if (scid->ts_retired != UINT64_MAX(18446744073709551615UL)) { | |||
9383 | res = ngtcp2_min(res, scid->ts_retired + pto)((res) < (scid->ts_retired + pto) ? (res) : (scid->ts_retired + pto)); | |||
9384 | } | |||
9385 | } | |||
9386 | ||||
9387 | if (ngtcp2_ringbuf_len(&conn->dcid.retired)((&conn->dcid.retired)->len)) { | |||
9388 | dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, 0); | |||
9389 | res = ngtcp2_min(res, dcid->ts_retired + pto)((res) < (dcid->ts_retired + pto) ? (res) : (dcid->ts_retired + pto)); | |||
9390 | } | |||
9391 | ||||
9392 | if (conn->server && conn->early.ckm && | |||
9393 | conn->early.discard_started_ts != UINT64_MAX(18446744073709551615UL)) { | |||
9394 | t = conn->early.discard_started_ts + 3 * pto; | |||
9395 | res = ngtcp2_min(res, t)((res) < (t) ? (res) : (t)); | |||
9396 | } | |||
9397 | ||||
9398 | return res; | |||
9399 | } | |||
9400 | ||||
9401 | ngtcp2_tstamp ngtcp2_conn_ack_delay_expiry(ngtcp2_conn *conn) { | |||
9402 | ngtcp2_acktr *acktr = &conn->pktns.acktr; | |||
9403 | ||||
9404 | if (!(acktr->flags & NGTCP2_ACKTR_FLAG_CANCEL_TIMER0x0100) && | |||
9405 | acktr->first_unacked_ts != UINT64_MAX(18446744073709551615UL)) { | |||
9406 | return acktr->first_unacked_ts + conn_compute_ack_delay(conn); | |||
9407 | } | |||
9408 | return UINT64_MAX(18446744073709551615UL); | |||
9409 | } | |||
9410 | ||||
9411 | ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn) { | |||
9412 | ngtcp2_tstamp t1 = ngtcp2_conn_loss_detection_expiry(conn); | |||
9413 | ngtcp2_tstamp t2 = ngtcp2_conn_ack_delay_expiry(conn); | |||
9414 | ngtcp2_tstamp t3 = ngtcp2_conn_internal_expiry(conn); | |||
9415 | ngtcp2_tstamp t4 = ngtcp2_conn_lost_pkt_expiry(conn); | |||
9416 | ngtcp2_tstamp res = ngtcp2_min(t1, t2)((t1) < (t2) ? (t1) : (t2)); | |||
9417 | res = ngtcp2_min(res, t3)((res) < (t3) ? (res) : (t3)); | |||
9418 | return ngtcp2_min(res, t4)((res) < (t4) ? (res) : (t4)); | |||
9419 | } | |||
9420 | ||||
9421 | int ngtcp2_conn_handle_expiry(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
9422 | int rv; | |||
9423 | ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); | |||
9424 | ||||
9425 | ngtcp2_conn_cancel_expired_ack_delay_timer(conn, ts); | |||
9426 | ||||
9427 | ngtcp2_conn_remove_lost_pkt(conn, ts); | |||
9428 | ||||
9429 | if (conn->pv) { | |||
9430 | ngtcp2_pv_cancel_expired_timer(conn->pv, ts); | |||
9431 | } | |||
9432 | ||||
9433 | if (ngtcp2_conn_loss_detection_expiry(conn) <= ts) { | |||
9434 | rv = ngtcp2_conn_on_loss_detection_timer(conn, ts); | |||
9435 | if (rv != 0) { | |||
9436 | return rv; | |||
9437 | } | |||
9438 | } | |||
9439 | ||||
9440 | rv = conn_remove_retired_connection_id(conn, pto, ts); | |||
9441 | if (rv != 0) { | |||
9442 | return rv; | |||
9443 | } | |||
9444 | ||||
9445 | if (conn->server && conn->early.ckm && | |||
9446 | conn->early.discard_started_ts != UINT64_MAX(18446744073709551615UL)) { | |||
9447 | if (conn->early.discard_started_ts + 3 * pto <= ts) { | |||
9448 | conn_discard_early_key(conn); | |||
9449 | } | |||
9450 | } | |||
9451 | ||||
9452 | return 0; | |||
9453 | } | |||
9454 | ||||
9455 | static void acktr_cancel_expired_ack_delay_timer(ngtcp2_acktr *acktr, | |||
9456 | ngtcp2_tstamp ts) { | |||
9457 | if (!(acktr->flags & NGTCP2_ACKTR_FLAG_CANCEL_TIMER0x0100) && | |||
9458 | acktr->first_unacked_ts <= ts) { | |||
9459 | acktr->flags |= NGTCP2_ACKTR_FLAG_CANCEL_TIMER0x0100; | |||
9460 | } | |||
9461 | } | |||
9462 | ||||
9463 | void ngtcp2_conn_cancel_expired_ack_delay_timer(ngtcp2_conn *conn, | |||
9464 | ngtcp2_tstamp ts) { | |||
9465 | if (conn->in_pktns) { | |||
9466 | acktr_cancel_expired_ack_delay_timer(&conn->in_pktns->acktr, ts); | |||
9467 | } | |||
9468 | if (conn->hs_pktns) { | |||
9469 | acktr_cancel_expired_ack_delay_timer(&conn->hs_pktns->acktr, ts); | |||
9470 | } | |||
9471 | acktr_cancel_expired_ack_delay_timer(&conn->pktns.acktr, ts); | |||
9472 | } | |||
9473 | ||||
9474 | ngtcp2_tstamp ngtcp2_conn_lost_pkt_expiry(ngtcp2_conn *conn) { | |||
9475 | ngtcp2_tstamp res = UINT64_MAX(18446744073709551615UL), ts; | |||
9476 | ||||
9477 | if (conn->in_pktns) { | |||
9478 | ts = ngtcp2_rtb_lost_pkt_ts(&conn->in_pktns->rtb); | |||
9479 | if (ts != UINT64_MAX(18446744073709551615UL)) { | |||
9480 | ts += conn_compute_pto(conn, conn->in_pktns); | |||
9481 | res = ngtcp2_min(res, ts)((res) < (ts) ? (res) : (ts)); | |||
9482 | } | |||
9483 | } | |||
9484 | ||||
9485 | if (conn->hs_pktns) { | |||
9486 | ts = ngtcp2_rtb_lost_pkt_ts(&conn->hs_pktns->rtb); | |||
9487 | if (ts != UINT64_MAX(18446744073709551615UL)) { | |||
9488 | ts += conn_compute_pto(conn, conn->hs_pktns); | |||
9489 | res = ngtcp2_min(res, ts)((res) < (ts) ? (res) : (ts)); | |||
9490 | } | |||
9491 | } | |||
9492 | ||||
9493 | ts = ngtcp2_rtb_lost_pkt_ts(&conn->pktns.rtb); | |||
9494 | if (ts != UINT64_MAX(18446744073709551615UL)) { | |||
9495 | ts += conn_compute_pto(conn, &conn->pktns); | |||
9496 | res = ngtcp2_min(res, ts)((res) < (ts) ? (res) : (ts)); | |||
9497 | } | |||
9498 | ||||
9499 | return res; | |||
9500 | } | |||
9501 | ||||
9502 | void ngtcp2_conn_remove_lost_pkt(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
9503 | ngtcp2_duration pto; | |||
9504 | ||||
9505 | if (conn->in_pktns) { | |||
9506 | pto = conn_compute_pto(conn, conn->in_pktns); | |||
9507 | ngtcp2_rtb_remove_expired_lost_pkt(&conn->in_pktns->rtb, pto, ts); | |||
9508 | } | |||
9509 | if (conn->hs_pktns) { | |||
9510 | pto = conn_compute_pto(conn, conn->hs_pktns); | |||
9511 | ngtcp2_rtb_remove_expired_lost_pkt(&conn->hs_pktns->rtb, pto, ts); | |||
9512 | } | |||
9513 | pto = conn_compute_pto(conn, &conn->pktns); | |||
9514 | ngtcp2_rtb_remove_expired_lost_pkt(&conn->pktns.rtb, pto, ts); | |||
9515 | } | |||
9516 | ||||
9517 | /* | |||
9518 | * conn_client_validate_transport_params validates |params| as client. | |||
9519 | * |params| must be sent with Encrypted Extensions. | |||
9520 | * | |||
9521 | * This function returns 0 if it succeeds, or one of the following | |||
9522 | * negative error codes: | |||
9523 | * | |||
9524 | * NGTCP2_ERR_PROTO | |||
9525 | * Validation against either of original_dcid and retry_scid is | |||
9526 | * failed. | |||
9527 | * NGTCP2_ERR_TRANSPORT_PARAM | |||
9528 | * params contains preferred address but server chose zero-length | |||
9529 | * connection ID. | |||
9530 | */ | |||
9531 | static int | |||
9532 | conn_client_validate_transport_params(ngtcp2_conn *conn, | |||
9533 | const ngtcp2_transport_params *params) { | |||
9534 | if (!ngtcp2_cid_eq(&conn->rcid, ¶ms->original_dcid)) { | |||
9535 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9536 | } | |||
9537 | ||||
9538 | if (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY0x10) { | |||
9539 | if (!params->retry_scid_present) { | |||
9540 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9541 | } | |||
9542 | if (!ngtcp2_cid_eq(&conn->retry_scid, ¶ms->retry_scid)) { | |||
9543 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9544 | } | |||
9545 | } else if (params->retry_scid_present) { | |||
9546 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9547 | } | |||
9548 | ||||
9549 | if (params->preferred_address_present && | |||
9550 | conn->dcid.current.cid.datalen == 0) { | |||
9551 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9552 | } | |||
9553 | ||||
9554 | return 0; | |||
9555 | } | |||
9556 | ||||
9557 | int ngtcp2_conn_set_remote_transport_params( | |||
9558 | ngtcp2_conn *conn, const ngtcp2_transport_params *params) { | |||
9559 | int rv; | |||
9560 | ||||
9561 | assert(!(conn->flags & NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED))((void) (0)); | |||
9562 | ||||
9563 | /* Assume that ngtcp2_decode_transport_params sets default value if | |||
9564 | active_connection_id_limit is omitted. */ | |||
9565 | if (params->active_connection_id_limit < | |||
9566 | NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT2) { | |||
9567 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9568 | } | |||
9569 | ||||
9570 | /* We assume that conn->dcid.current.cid is still the initial one. | |||
9571 | This requires that transport parameter must be fed into | |||
9572 | ngtcp2_conn as early as possible. */ | |||
9573 | if (!ngtcp2_cid_eq(&conn->dcid.current.cid, ¶ms->initial_scid)) { | |||
9574 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9575 | } | |||
9576 | ||||
9577 | if (params->max_udp_payload_size < 1200) { | |||
9578 | return NGTCP2_ERR_TRANSPORT_PARAM-234; | |||
9579 | } | |||
9580 | ||||
9581 | if (!conn->server) { | |||
9582 | rv = conn_client_validate_transport_params(conn, params); | |||
9583 | if (rv != 0) { | |||
9584 | return rv; | |||
9585 | } | |||
9586 | } | |||
9587 | ||||
9588 | ngtcp2_log_remote_tp(&conn->log, | |||
9589 | conn->server | |||
9590 | ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO | |||
9591 | : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS, | |||
9592 | params); | |||
9593 | ||||
9594 | ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server, | |||
9595 | NGTCP2_QLOG_SIDE_REMOTE); | |||
9596 | ||||
9597 | if ((conn->server && conn->pktns.crypto.tx.ckm) || | |||
9598 | (!conn->server && conn->pktns.crypto.rx.ckm)) { | |||
9599 | conn->remote.transport_params = *params; | |||
9600 | conn_sync_stream_id_limit(conn); | |||
9601 | conn->tx.max_offset = conn->remote.transport_params.initial_max_data; | |||
9602 | } else { | |||
9603 | conn->remote.pending_transport_params = *params; | |||
9604 | } | |||
9605 | ||||
9606 | conn->flags |= NGTCP2_CONN_FLAG_TRANSPORT_PARAM_RECVED0x04; | |||
9607 | ||||
9608 | return 0; | |||
9609 | } | |||
9610 | ||||
9611 | void ngtcp2_conn_get_remote_transport_params(ngtcp2_conn *conn, | |||
9612 | ngtcp2_transport_params *params) { | |||
9613 | if (conn->pktns.crypto.rx.ckm) { | |||
9614 | *params = conn->remote.transport_params; | |||
9615 | } else { | |||
9616 | *params = conn->remote.pending_transport_params; | |||
9617 | } | |||
9618 | } | |||
9619 | ||||
9620 | void ngtcp2_conn_set_early_remote_transport_params( | |||
9621 | ngtcp2_conn *conn, const ngtcp2_transport_params *params) { | |||
9622 | ngtcp2_transport_params *p = &conn->remote.transport_params; | |||
9623 | ||||
9624 | assert(!conn->server)((void) (0)); | |||
9625 | ||||
9626 | memset(p, 0, sizeof(*p)); | |||
9627 | ||||
9628 | p->initial_max_streams_bidi = params->initial_max_streams_bidi; | |||
9629 | p->initial_max_streams_uni = params->initial_max_streams_uni; | |||
9630 | p->initial_max_stream_data_bidi_local = | |||
9631 | params->initial_max_stream_data_bidi_local; | |||
9632 | p->initial_max_stream_data_bidi_remote = | |||
9633 | params->initial_max_stream_data_bidi_remote; | |||
9634 | p->initial_max_stream_data_uni = params->initial_max_stream_data_uni; | |||
9635 | p->initial_max_data = params->initial_max_data; | |||
9636 | p->max_datagram_frame_size = params->max_datagram_frame_size; | |||
9637 | ||||
9638 | conn_sync_stream_id_limit(conn); | |||
9639 | ||||
9640 | conn->tx.max_offset = p->initial_max_data; | |||
9641 | ||||
9642 | ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, p, conn->server, | |||
9643 | NGTCP2_QLOG_SIDE_REMOTE); | |||
9644 | } | |||
9645 | ||||
9646 | int ngtcp2_conn_set_local_transport_params( | |||
9647 | ngtcp2_conn *conn, const ngtcp2_transport_params *params) { | |||
9648 | assert(conn->server)((void) (0)); | |||
9649 | assert(params->active_connection_id_limit <= NGTCP2_MAX_DCID_POOL_SIZE)((void) (0)); | |||
9650 | ||||
9651 | if (conn->hs_pktns == NULL((void*)0) || conn->hs_pktns->crypto.tx.ckm) { | |||
9652 | return NGTCP2_ERR_INVALID_STATE-206; | |||
9653 | } | |||
9654 | ||||
9655 | conn->local.transport_params = *params; | |||
9656 | ||||
9657 | return 0; | |||
9658 | } | |||
9659 | ||||
9660 | int ngtcp2_conn_commit_local_transport_params(ngtcp2_conn *conn) { | |||
9661 | const ngtcp2_mem *mem = conn->mem; | |||
9662 | ngtcp2_transport_params *params = &conn->local.transport_params; | |||
9663 | ngtcp2_scid *scident; | |||
9664 | ngtcp2_ksl_it it; | |||
9665 | int rv; | |||
9666 | ||||
9667 | assert(1 == ngtcp2_ksl_len(&conn->scid.set))((void) (0)); | |||
9668 | ||||
9669 | if (params->active_connection_id_limit == 0) { | |||
9670 | params->active_connection_id_limit = | |||
9671 | NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT2; | |||
9672 | } | |||
9673 | ||||
9674 | params->initial_scid = conn->oscid; | |||
9675 | ||||
9676 | if (conn->oscid.datalen == 0) { | |||
9677 | params->preferred_address_present = 0; | |||
9678 | } | |||
9679 | ||||
9680 | if (conn->server) { | |||
9681 | if (params->stateless_reset_token_present) { | |||
9682 | it = ngtcp2_ksl_begin(&conn->scid.set); | |||
9683 | scident = ngtcp2_ksl_it_get(&it); | |||
9684 | ||||
9685 | memcpy(scident->token, params->stateless_reset_token, | |||
9686 | NGTCP2_STATELESS_RESET_TOKENLEN16); | |||
9687 | } | |||
9688 | ||||
9689 | if (params->preferred_address_present) { | |||
9690 | scident = ngtcp2_mem_malloc(mem, sizeof(*scident)); | |||
9691 | if (scident == NULL((void*)0)) { | |||
9692 | return NGTCP2_ERR_NOMEM-501; | |||
9693 | } | |||
9694 | ||||
9695 | ngtcp2_scid_init(scident, 1, ¶ms->preferred_address.cid, | |||
9696 | params->preferred_address.stateless_reset_token); | |||
9697 | ||||
9698 | rv = ngtcp2_ksl_insert(&conn->scid.set, NULL((void*)0), &scident->cid, scident); | |||
9699 | if (rv != 0) { | |||
9700 | ngtcp2_mem_free(mem, scident); | |||
9701 | return rv; | |||
9702 | } | |||
9703 | ||||
9704 | conn->scid.last_seq = 1; | |||
9705 | } | |||
9706 | } | |||
9707 | ||||
9708 | conn->rx.window = conn->rx.unsent_max_offset = conn->rx.max_offset = | |||
9709 | params->initial_max_data; | |||
9710 | conn->remote.bidi.unsent_max_streams = params->initial_max_streams_bidi; | |||
9711 | conn->remote.bidi.max_streams = params->initial_max_streams_bidi; | |||
9712 | conn->remote.uni.unsent_max_streams = params->initial_max_streams_uni; | |||
9713 | conn->remote.uni.max_streams = params->initial_max_streams_uni; | |||
9714 | ||||
9715 | ngtcp2_qlog_parameters_set_transport_params(&conn->qlog, params, conn->server, | |||
9716 | NGTCP2_QLOG_SIDE_LOCAL); | |||
9717 | ||||
9718 | return 0; | |||
9719 | } | |||
9720 | ||||
9721 | void ngtcp2_conn_get_local_transport_params(ngtcp2_conn *conn, | |||
9722 | ngtcp2_transport_params *params) { | |||
9723 | *params = conn->local.transport_params; | |||
9724 | } | |||
9725 | ||||
9726 | int ngtcp2_conn_open_bidi_stream(ngtcp2_conn *conn, int64_t *pstream_id, | |||
9727 | void *stream_user_data) { | |||
9728 | int rv; | |||
9729 | ngtcp2_strm *strm; | |||
9730 | ||||
9731 | if (ngtcp2_conn_get_streams_bidi_left(conn) == 0) { | |||
9732 | return NGTCP2_ERR_STREAM_ID_BLOCKED-208; | |||
9733 | } | |||
9734 | ||||
9735 | strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm)); | |||
9736 | if (strm == NULL((void*)0)) { | |||
9737 | return NGTCP2_ERR_NOMEM-501; | |||
9738 | } | |||
9739 | ||||
9740 | rv = ngtcp2_conn_init_stream(conn, strm, conn->local.bidi.next_stream_id, | |||
9741 | stream_user_data); | |||
9742 | if (rv != 0) { | |||
9743 | ngtcp2_mem_free(conn->mem, strm); | |||
9744 | return rv; | |||
9745 | } | |||
9746 | ||||
9747 | *pstream_id = conn->local.bidi.next_stream_id; | |||
9748 | conn->local.bidi.next_stream_id += 4; | |||
9749 | ||||
9750 | return 0; | |||
9751 | } | |||
9752 | ||||
9753 | int ngtcp2_conn_open_uni_stream(ngtcp2_conn *conn, int64_t *pstream_id, | |||
9754 | void *stream_user_data) { | |||
9755 | int rv; | |||
9756 | ngtcp2_strm *strm; | |||
9757 | ||||
9758 | if (ngtcp2_conn_get_streams_uni_left(conn) == 0) { | |||
9759 | return NGTCP2_ERR_STREAM_ID_BLOCKED-208; | |||
9760 | } | |||
9761 | ||||
9762 | strm = ngtcp2_mem_malloc(conn->mem, sizeof(ngtcp2_strm)); | |||
9763 | if (strm == NULL((void*)0)) { | |||
9764 | return NGTCP2_ERR_NOMEM-501; | |||
9765 | } | |||
9766 | ||||
9767 | rv = ngtcp2_conn_init_stream(conn, strm, conn->local.uni.next_stream_id, | |||
9768 | stream_user_data); | |||
9769 | if (rv != 0) { | |||
9770 | ngtcp2_mem_free(conn->mem, strm); | |||
9771 | return rv; | |||
9772 | } | |||
9773 | ngtcp2_strm_shutdown(strm, NGTCP2_STRM_FLAG_SHUT_RD0x01); | |||
9774 | ||||
9775 | *pstream_id = conn->local.uni.next_stream_id; | |||
9776 | conn->local.uni.next_stream_id += 4; | |||
9777 | ||||
9778 | return 0; | |||
9779 | } | |||
9780 | ||||
9781 | ngtcp2_strm *ngtcp2_conn_find_stream(ngtcp2_conn *conn, int64_t stream_id) { | |||
9782 | ngtcp2_map_entry *me; | |||
9783 | ||||
9784 | me = ngtcp2_map_find(&conn->strms, (uint64_t)stream_id); | |||
9785 | if (me == NULL((void*)0)) { | |||
9786 | return NULL((void*)0); | |||
9787 | } | |||
9788 | ||||
9789 | return ngtcp2_struct_of(me, ngtcp2_strm, me)((ngtcp2_strm *)(void *)((char *)(me)-__builtin_offsetof(ngtcp2_strm , me))); | |||
9790 | } | |||
9791 | ||||
9792 | ngtcp2_ssize ngtcp2_conn_write_stream(ngtcp2_conn *conn, ngtcp2_path *path, | |||
9793 | ngtcp2_pkt_info *pi, uint8_t *dest, | |||
9794 | size_t destlen, ngtcp2_ssize *pdatalen, | |||
9795 | uint32_t flags, int64_t stream_id, | |||
9796 | const uint8_t *data, size_t datalen, | |||
9797 | ngtcp2_tstamp ts) { | |||
9798 | ngtcp2_vec datav; | |||
9799 | ||||
9800 | datav.len = datalen; | |||
9801 | datav.base = (uint8_t *)data; | |||
9802 | ||||
9803 | return ngtcp2_conn_writev_stream(conn, path, pi, dest, destlen, pdatalen, | |||
9804 | flags, stream_id, &datav, 1, ts); | |||
9805 | } | |||
9806 | ||||
9807 | ngtcp2_ssize ngtcp2_conn_writev_stream(ngtcp2_conn *conn, ngtcp2_path *path, | |||
9808 | ngtcp2_pkt_info *pi, uint8_t *dest, | |||
9809 | size_t destlen, ngtcp2_ssize *pdatalen, | |||
9810 | uint32_t flags, int64_t stream_id, | |||
9811 | const ngtcp2_vec *datav, size_t datavcnt, | |||
9812 | ngtcp2_tstamp ts) { | |||
9813 | ngtcp2_vmsg vmsg, *pvmsg; | |||
9814 | ngtcp2_strm *strm; | |||
9815 | ||||
9816 | if (pdatalen) { | |||
9817 | *pdatalen = -1; | |||
9818 | } | |||
9819 | ||||
9820 | if (stream_id != -1) { | |||
9821 | strm = ngtcp2_conn_find_stream(conn, stream_id); | |||
9822 | if (strm == NULL((void*)0)) { | |||
9823 | return NGTCP2_ERR_STREAM_NOT_FOUND-222; | |||
9824 | } | |||
9825 | ||||
9826 | if (strm->flags & NGTCP2_STRM_FLAG_SHUT_WR0x02) { | |||
9827 | return NGTCP2_ERR_STREAM_SHUT_WR-221; | |||
9828 | } | |||
9829 | ||||
9830 | vmsg.type = NGTCP2_VMSG_TYPE_STREAM; | |||
9831 | vmsg.stream.strm = strm; | |||
9832 | vmsg.stream.flags = flags; | |||
9833 | vmsg.stream.data = datav; | |||
9834 | vmsg.stream.datacnt = datavcnt; | |||
9835 | vmsg.stream.pdatalen = pdatalen; | |||
9836 | ||||
9837 | pvmsg = &vmsg; | |||
9838 | } else { | |||
9839 | pvmsg = NULL((void*)0); | |||
9840 | } | |||
9841 | ||||
9842 | return ngtcp2_conn_write_vmsg(conn, path, pi, dest, destlen, pvmsg, ts); | |||
9843 | } | |||
9844 | ||||
9845 | ngtcp2_ssize ngtcp2_conn_writev_datagram(ngtcp2_conn *conn, ngtcp2_path *path, | |||
9846 | ngtcp2_pkt_info *pi, uint8_t *dest, | |||
9847 | size_t destlen, int *paccepted, | |||
9848 | uint32_t flags, | |||
9849 | const ngtcp2_vec *datav, | |||
9850 | size_t datavcnt, ngtcp2_tstamp ts) { | |||
9851 | ngtcp2_vmsg vmsg; | |||
9852 | ||||
9853 | if (paccepted) { | |||
9854 | *paccepted = 0; | |||
9855 | } | |||
9856 | ||||
9857 | if (conn->remote.transport_params.max_datagram_frame_size == 0) { | |||
9858 | return NGTCP2_ERR_INVALID_STATE-206; | |||
9859 | } | |||
9860 | if (conn->remote.transport_params.max_datagram_frame_size < | |||
9861 | ngtcp2_pkt_datagram_framelen(ngtcp2_vec_len(datav, datavcnt))) { | |||
9862 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
9863 | } | |||
9864 | ||||
9865 | vmsg.type = NGTCP2_VMSG_TYPE_DATAGRAM; | |||
9866 | vmsg.datagram.flags = flags; | |||
9867 | vmsg.datagram.data = datav; | |||
9868 | vmsg.datagram.datacnt = datavcnt; | |||
9869 | vmsg.datagram.paccepted = paccepted; | |||
9870 | ||||
9871 | return ngtcp2_conn_write_vmsg(conn, path, pi, dest, destlen, &vmsg, ts); | |||
9872 | } | |||
9873 | ||||
9874 | ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, | |||
9875 | ngtcp2_pkt_info *pi, uint8_t *dest, | |||
9876 | size_t destlen, ngtcp2_vmsg *vmsg, | |||
9877 | ngtcp2_tstamp ts) { | |||
9878 | ngtcp2_ssize nwrite; | |||
9879 | ngtcp2_pktns *pktns = &conn->pktns; | |||
9880 | size_t origlen = destlen; | |||
9881 | int rv; | |||
9882 | uint8_t wflags = NGTCP2_WRITE_PKT_FLAG_NONE0x00; | |||
9883 | int ppe_pending = (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING0x1000) != 0; | |||
9884 | ngtcp2_ssize res = 0; | |||
9885 | size_t server_tx_left; | |||
9886 | ||||
9887 | conn->log.last_ts = ts; | |||
9888 | conn->qlog.last_ts = ts; | |||
9889 | ||||
9890 | if (path) { | |||
9891 | ngtcp2_path_copy(path, &conn->dcid.current.ps.path); | |||
9892 | } | |||
9893 | ||||
9894 | if (!ppe_pending && pi) { | |||
9895 | pi->ecn = NGTCP2_ECN_NOT_ECT0x0; | |||
9896 | } | |||
9897 | ||||
9898 | switch (conn->state) { | |||
9899 | case NGTCP2_CS_CLIENT_INITIAL: | |||
9900 | case NGTCP2_CS_CLIENT_WAIT_HANDSHAKE: | |||
9901 | case NGTCP2_CS_CLIENT_TLS_HANDSHAKE_FAILED: | |||
9902 | nwrite = conn_client_write_handshake(conn, pi, dest, destlen, vmsg, ts); | |||
9903 | if (nwrite < 0) { | |||
9904 | return nwrite; | |||
9905 | } | |||
9906 | if (conn->state != NGTCP2_CS_POST_HANDSHAKE) { | |||
9907 | return nwrite; | |||
9908 | } | |||
9909 | res = nwrite; | |||
9910 | dest += nwrite; | |||
9911 | destlen -= (size_t)nwrite; | |||
9912 | /* Break here so that we can coalesces Short packets. */ | |||
9913 | break; | |||
9914 | case NGTCP2_CS_SERVER_INITIAL: | |||
9915 | case NGTCP2_CS_SERVER_WAIT_HANDSHAKE: | |||
9916 | case NGTCP2_CS_SERVER_TLS_HANDSHAKE_FAILED: | |||
9917 | if (!ppe_pending) { | |||
9918 | if (!(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01)) { | |||
9919 | server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); | |||
9920 | destlen = ngtcp2_min(destlen, server_tx_left)((destlen) < (server_tx_left) ? (destlen) : (server_tx_left )); | |||
9921 | } | |||
9922 | ||||
9923 | nwrite = conn_write_handshake(conn, pi, dest, destlen, 0, ts); | |||
9924 | if (nwrite < 0) { | |||
9925 | return nwrite; | |||
9926 | } | |||
9927 | ||||
9928 | if (conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01) { | |||
9929 | destlen = origlen; | |||
9930 | } else { | |||
9931 | origlen = destlen; | |||
9932 | } | |||
9933 | ||||
9934 | res = nwrite; | |||
9935 | dest += nwrite; | |||
9936 | destlen -= (size_t)nwrite; | |||
9937 | } | |||
9938 | if (conn->state != NGTCP2_CS_POST_HANDSHAKE && | |||
9939 | conn->pktns.crypto.tx.ckm == NULL((void*)0)) { | |||
9940 | return res; | |||
9941 | } | |||
9942 | break; | |||
9943 | case NGTCP2_CS_POST_HANDSHAKE: | |||
9944 | break; | |||
9945 | case NGTCP2_CS_CLOSING: | |||
9946 | return NGTCP2_ERR_CLOSING-230; | |||
9947 | case NGTCP2_CS_DRAINING: | |||
9948 | return NGTCP2_ERR_DRAINING-231; | |||
9949 | default: | |||
9950 | return 0; | |||
9951 | } | |||
9952 | ||||
9953 | assert(pktns->crypto.tx.ckm)((void) (0)); | |||
9954 | ||||
9955 | if (conn_check_pkt_num_exhausted(conn)) { | |||
9956 | return NGTCP2_ERR_PKT_NUM_EXHAUSTED-216; | |||
9957 | } | |||
9958 | ||||
9959 | if (vmsg) { | |||
9960 | switch (vmsg->type) { | |||
9961 | case NGTCP2_VMSG_TYPE_STREAM: | |||
9962 | if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE0x01) { | |||
9963 | wflags |= NGTCP2_WRITE_PKT_FLAG_MORE0x02; | |||
9964 | } | |||
9965 | break; | |||
9966 | case NGTCP2_VMSG_TYPE_DATAGRAM: | |||
9967 | if (vmsg->datagram.flags & NGTCP2_WRITE_DATAGRAM_FLAG_MORE0x01) { | |||
9968 | wflags |= NGTCP2_WRITE_PKT_FLAG_MORE0x02; | |||
9969 | } | |||
9970 | break; | |||
9971 | default: | |||
9972 | break; | |||
9973 | } | |||
9974 | } | |||
9975 | ||||
9976 | if (ppe_pending) { | |||
9977 | res = conn->pkt.hs_spktlen; | |||
9978 | conn->pkt.hs_spktlen = 0; | |||
9979 | /* dest and destlen have already been adjusted in ppe in the first | |||
9980 | run. They are adjusted for probe packet later. */ | |||
9981 | nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_SHORT, | |||
9982 | wflags, ts); | |||
9983 | goto fin; | |||
9984 | } else { | |||
9985 | if (conn->state == NGTCP2_CS_POST_HANDSHAKE) { | |||
9986 | rv = conn_prepare_key_update(conn, ts); | |||
9987 | if (rv != 0) { | |||
9988 | return rv; | |||
9989 | } | |||
9990 | } | |||
9991 | ||||
9992 | if (!conn->pktns.rtb.probe_pkt_left && conn_cwnd_is_zero(conn)) { | |||
9993 | destlen = 0; | |||
9994 | } else { | |||
9995 | nwrite = conn_write_path_response(conn, path, pi, dest, destlen, ts); | |||
9996 | if (nwrite) { | |||
9997 | goto fin; | |||
9998 | } | |||
9999 | ||||
10000 | if (conn->pv) { | |||
10001 | nwrite = conn_write_path_challenge(conn, path, pi, dest, destlen, ts); | |||
10002 | if (nwrite) { | |||
10003 | goto fin; | |||
10004 | } | |||
10005 | } | |||
10006 | ||||
10007 | if (conn->server && | |||
10008 | !(conn->dcid.current.flags & NGTCP2_DCID_FLAG_PATH_VALIDATED0x01)) { | |||
10009 | server_tx_left = conn_server_tx_left(conn, &conn->dcid.current); | |||
10010 | origlen = ngtcp2_min(origlen, server_tx_left)((origlen) < (server_tx_left) ? (origlen) : (server_tx_left )); | |||
10011 | destlen = ngtcp2_min(destlen, server_tx_left)((destlen) < (server_tx_left) ? (destlen) : (server_tx_left )); | |||
10012 | ||||
10013 | if (destlen == 0 && conn->cstat.loss_detection_timer != UINT64_MAX(18446744073709551615UL)) { | |||
10014 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10015 | "loss detection timer canceled"); | |||
10016 | conn->cstat.loss_detection_timer = UINT64_MAX(18446744073709551615UL); | |||
10017 | conn->cstat.pto_count = 0; | |||
10018 | } | |||
10019 | } | |||
10020 | } | |||
10021 | } | |||
10022 | ||||
10023 | if (res == 0) { | |||
10024 | if (conn_handshake_remnants_left(conn)) { | |||
10025 | if (conn_handshake_probe_left(conn)) { | |||
10026 | destlen = origlen; | |||
10027 | } | |||
10028 | nwrite = conn_write_handshake_pkts(conn, pi, dest, destlen, 0, ts); | |||
10029 | if (nwrite < 0) { | |||
10030 | return nwrite; | |||
10031 | } | |||
10032 | if (nwrite > 0) { | |||
10033 | res = nwrite; | |||
10034 | dest += nwrite; | |||
10035 | destlen -= (size_t)nwrite; | |||
10036 | } | |||
10037 | } | |||
10038 | } | |||
10039 | ||||
10040 | if (conn->pktns.rtb.probe_pkt_left) { | |||
10041 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_CON, | |||
10042 | "transmit probe pkt left=%zu", | |||
10043 | conn->pktns.rtb.probe_pkt_left); | |||
10044 | ||||
10045 | nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_SHORT, | |||
10046 | wflags, ts); | |||
10047 | ||||
10048 | goto fin; | |||
10049 | } | |||
10050 | ||||
10051 | nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_SHORT, | |||
10052 | wflags, ts); | |||
10053 | if (nwrite) { | |||
10054 | assert(nwrite != NGTCP2_ERR_NOBUF)((void) (0)); | |||
10055 | goto fin; | |||
10056 | } | |||
10057 | ||||
10058 | if (res == 0) { | |||
10059 | nwrite = conn_write_ack_pkt(conn, pi, dest, origlen, NGTCP2_PKT_SHORT, ts); | |||
10060 | } | |||
10061 | ||||
10062 | fin: | |||
10063 | conn->pkt.hs_spktlen = 0; | |||
10064 | ||||
10065 | if (nwrite >= 0) { | |||
10066 | res += nwrite; | |||
10067 | return res; | |||
10068 | } | |||
10069 | /* NGTCP2_CONN_FLAG_PPE_PENDING is set in conn_write_pkt above. | |||
10070 | ppe_pending cannot be used here. */ | |||
10071 | if (conn->flags & NGTCP2_CONN_FLAG_PPE_PENDING0x1000) { | |||
10072 | conn->pkt.hs_spktlen = res; | |||
10073 | } | |||
10074 | ||||
10075 | return nwrite; | |||
10076 | } | |||
10077 | ||||
10078 | static ngtcp2_ssize | |||
10079 | conn_write_connection_close(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, | |||
10080 | uint8_t *dest, size_t destlen, uint8_t pkt_type, | |||
10081 | uint64_t error_code, ngtcp2_tstamp ts) { | |||
10082 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
10083 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
10084 | ngtcp2_ssize res = 0, nwrite; | |||
10085 | ngtcp2_frame fr; | |||
10086 | ||||
10087 | fr.type = NGTCP2_FRAME_CONNECTION_CLOSE; | |||
10088 | fr.connection_close.error_code = error_code; | |||
10089 | fr.connection_close.frame_type = 0; | |||
10090 | fr.connection_close.reasonlen = 0; | |||
10091 | fr.connection_close.reason = NULL((void*)0); | |||
10092 | ||||
10093 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80) && | |||
10094 | pkt_type != NGTCP2_PKT_INITIAL) { | |||
10095 | if (in_pktns && conn->server) { | |||
10096 | nwrite = ngtcp2_conn_write_single_frame_pkt( | |||
10097 | conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, &conn->dcid.current.cid, | |||
10098 | &fr, NGTCP2_RTB_ENTRY_FLAG_NONE0x00, NULL((void*)0), ts); | |||
10099 | if (nwrite < 0) { | |||
10100 | return nwrite; | |||
10101 | } | |||
10102 | ||||
10103 | dest += nwrite; | |||
10104 | destlen -= (size_t)nwrite; | |||
10105 | res += nwrite; | |||
10106 | } | |||
10107 | ||||
10108 | if (pkt_type != NGTCP2_PKT_HANDSHAKE && hs_pktns && | |||
10109 | hs_pktns->crypto.tx.ckm) { | |||
10110 | nwrite = ngtcp2_conn_write_single_frame_pkt( | |||
10111 | conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, | |||
10112 | &conn->dcid.current.cid, &fr, NGTCP2_RTB_ENTRY_FLAG_NONE0x00, NULL((void*)0), ts); | |||
10113 | if (nwrite < 0) { | |||
10114 | return nwrite; | |||
10115 | } | |||
10116 | ||||
10117 | dest += nwrite; | |||
10118 | destlen -= (size_t)nwrite; | |||
10119 | res += nwrite; | |||
10120 | } | |||
10121 | } | |||
10122 | ||||
10123 | nwrite = ngtcp2_conn_write_single_frame_pkt( | |||
10124 | conn, pi, dest, destlen, pkt_type, &conn->dcid.current.cid, &fr, | |||
10125 | NGTCP2_RTB_ENTRY_FLAG_NONE0x00, NULL((void*)0), ts); | |||
10126 | ||||
10127 | if (nwrite < 0) { | |||
10128 | return nwrite; | |||
10129 | } | |||
10130 | ||||
10131 | res += nwrite; | |||
10132 | ||||
10133 | if (res == 0) { | |||
10134 | return NGTCP2_ERR_NOBUF-203; | |||
10135 | } | |||
10136 | ||||
10137 | return res; | |||
10138 | } | |||
10139 | ||||
10140 | ngtcp2_ssize ngtcp2_conn_write_connection_close( | |||
10141 | ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, | |||
10142 | size_t destlen, uint64_t error_code, ngtcp2_tstamp ts) { | |||
10143 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
10144 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
10145 | uint8_t pkt_type; | |||
10146 | ngtcp2_ssize nwrite; | |||
10147 | ||||
10148 | conn->log.last_ts = ts; | |||
10149 | conn->qlog.last_ts = ts; | |||
10150 | ||||
10151 | if (conn_check_pkt_num_exhausted(conn)) { | |||
10152 | return NGTCP2_ERR_PKT_NUM_EXHAUSTED-216; | |||
10153 | } | |||
10154 | ||||
10155 | switch (conn->state) { | |||
10156 | case NGTCP2_CS_CLIENT_INITIAL: | |||
10157 | case NGTCP2_CS_CLOSING: | |||
10158 | case NGTCP2_CS_DRAINING: | |||
10159 | return NGTCP2_ERR_INVALID_STATE-206; | |||
10160 | default: | |||
10161 | break; | |||
10162 | } | |||
10163 | ||||
10164 | if (path) { | |||
10165 | ngtcp2_path_copy(path, &conn->dcid.current.ps.path); | |||
10166 | } | |||
10167 | ||||
10168 | if (pi) { | |||
10169 | pi->ecn = NGTCP2_ECN_NOT_ECT0x0; | |||
10170 | } | |||
10171 | ||||
10172 | if (conn->state == NGTCP2_CS_POST_HANDSHAKE || | |||
10173 | (conn->server && conn->pktns.crypto.tx.ckm)) { | |||
10174 | pkt_type = NGTCP2_PKT_SHORT; | |||
10175 | } else if (hs_pktns && hs_pktns->crypto.tx.ckm) { | |||
10176 | pkt_type = NGTCP2_PKT_HANDSHAKE; | |||
10177 | } else if (in_pktns && in_pktns->crypto.tx.ckm) { | |||
10178 | pkt_type = NGTCP2_PKT_INITIAL; | |||
10179 | } else { | |||
10180 | /* This branch is taken if server has not read any Initial packet | |||
10181 | from client. */ | |||
10182 | return NGTCP2_ERR_INVALID_STATE-206; | |||
10183 | } | |||
10184 | ||||
10185 | nwrite = conn_write_connection_close(conn, pi, dest, destlen, pkt_type, | |||
10186 | error_code, ts); | |||
10187 | if (nwrite < 0) { | |||
10188 | return nwrite; | |||
10189 | } | |||
10190 | ||||
10191 | conn->state = NGTCP2_CS_CLOSING; | |||
10192 | ||||
10193 | return nwrite; | |||
10194 | } | |||
10195 | ||||
10196 | ngtcp2_ssize ngtcp2_conn_write_application_close( | |||
10197 | ngtcp2_conn *conn, ngtcp2_path *path, ngtcp2_pkt_info *pi, uint8_t *dest, | |||
10198 | size_t destlen, uint64_t app_error_code, ngtcp2_tstamp ts) { | |||
10199 | ngtcp2_ssize nwrite; | |||
10200 | ngtcp2_ssize res = 0; | |||
10201 | ngtcp2_frame fr; | |||
10202 | ||||
10203 | conn->log.last_ts = ts; | |||
10204 | conn->qlog.last_ts = ts; | |||
10205 | ||||
10206 | if (conn_check_pkt_num_exhausted(conn)) { | |||
10207 | return NGTCP2_ERR_PKT_NUM_EXHAUSTED-216; | |||
10208 | } | |||
10209 | ||||
10210 | switch (conn->state) { | |||
10211 | case NGTCP2_CS_CLIENT_INITIAL: | |||
10212 | case NGTCP2_CS_CLOSING: | |||
10213 | case NGTCP2_CS_DRAINING: | |||
10214 | return NGTCP2_ERR_INVALID_STATE-206; | |||
10215 | default: | |||
10216 | break; | |||
10217 | } | |||
10218 | ||||
10219 | if (path) { | |||
10220 | ngtcp2_path_copy(path, &conn->dcid.current.ps.path); | |||
10221 | } | |||
10222 | ||||
10223 | if (pi) { | |||
10224 | pi->ecn = NGTCP2_ECN_NOT_ECT0x0; | |||
10225 | } | |||
10226 | ||||
10227 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80)) { | |||
10228 | nwrite = conn_write_connection_close(conn, pi, dest, destlen, | |||
10229 | conn->hs_pktns->crypto.tx.ckm | |||
10230 | ? NGTCP2_PKT_HANDSHAKE | |||
10231 | : NGTCP2_PKT_INITIAL, | |||
10232 | NGTCP2_APPLICATION_ERROR0xcu, ts); | |||
10233 | if (nwrite < 0) { | |||
10234 | return nwrite; | |||
10235 | } | |||
10236 | res = nwrite; | |||
10237 | dest += nwrite; | |||
10238 | destlen -= (size_t)nwrite; | |||
10239 | } | |||
10240 | ||||
10241 | if (conn->state != NGTCP2_CS_POST_HANDSHAKE) { | |||
10242 | assert(res)((void) (0)); | |||
10243 | ||||
10244 | if (!conn->server || !conn->pktns.crypto.tx.ckm) { | |||
10245 | return res; | |||
10246 | } | |||
10247 | } | |||
10248 | ||||
10249 | assert(conn->pktns.crypto.tx.ckm)((void) (0)); | |||
10250 | ||||
10251 | fr.type = NGTCP2_FRAME_CONNECTION_CLOSE_APP; | |||
10252 | fr.connection_close.error_code = app_error_code; | |||
10253 | fr.connection_close.frame_type = 0; | |||
10254 | fr.connection_close.reasonlen = 0; | |||
10255 | fr.connection_close.reason = NULL((void*)0); | |||
10256 | ||||
10257 | nwrite = ngtcp2_conn_write_single_frame_pkt( | |||
10258 | conn, pi, dest, destlen, NGTCP2_PKT_SHORT, &conn->dcid.current.cid, &fr, | |||
10259 | NGTCP2_RTB_ENTRY_FLAG_NONE0x00, NULL((void*)0), ts); | |||
10260 | ||||
10261 | if (nwrite < 0) { | |||
10262 | return nwrite; | |||
10263 | } | |||
10264 | ||||
10265 | res += nwrite; | |||
10266 | ||||
10267 | if (res == 0) { | |||
10268 | return NGTCP2_ERR_NOBUF-203; | |||
10269 | } | |||
10270 | ||||
10271 | conn->state = NGTCP2_CS_CLOSING; | |||
10272 | ||||
10273 | return res; | |||
10274 | } | |||
10275 | ||||
10276 | int ngtcp2_conn_is_in_closing_period(ngtcp2_conn *conn) { | |||
10277 | return conn->state == NGTCP2_CS_CLOSING; | |||
10278 | } | |||
10279 | ||||
10280 | int ngtcp2_conn_is_in_draining_period(ngtcp2_conn *conn) { | |||
10281 | return conn->state == NGTCP2_CS_DRAINING; | |||
10282 | } | |||
10283 | ||||
10284 | int ngtcp2_conn_close_stream(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
10285 | uint64_t app_error_code) { | |||
10286 | int rv; | |||
10287 | ||||
10288 | if (!strm->app_error_code) { | |||
10289 | app_error_code = strm->app_error_code; | |||
10290 | } | |||
10291 | ||||
10292 | rv = ngtcp2_map_remove(&conn->strms, strm->me.key); | |||
10293 | if (rv != 0) { | |||
10294 | assert(rv != NGTCP2_ERR_INVALID_ARGUMENT)((void) (0)); | |||
10295 | return rv; | |||
10296 | } | |||
10297 | ||||
10298 | rv = conn_call_stream_close(conn, strm, app_error_code); | |||
10299 | if (rv != 0) { | |||
10300 | goto fin; | |||
10301 | } | |||
10302 | ||||
10303 | if (ngtcp2_strm_is_tx_queued(strm)) { | |||
10304 | ngtcp2_pq_remove(&conn->tx.strmq, &strm->pe); | |||
10305 | } | |||
10306 | ||||
10307 | fin: | |||
10308 | ngtcp2_strm_free(strm); | |||
10309 | ngtcp2_mem_free(conn->mem, strm); | |||
10310 | ||||
10311 | return rv; | |||
10312 | } | |||
10313 | ||||
10314 | int ngtcp2_conn_close_stream_if_shut_rdwr(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
10315 | uint64_t app_error_code) { | |||
10316 | if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RDWR(0x01 | 0x02)) == | |||
10317 | NGTCP2_STRM_FLAG_SHUT_RDWR(0x01 | 0x02) && | |||
10318 | ((strm->flags & NGTCP2_STRM_FLAG_RECV_RST0x08) || | |||
10319 | ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) && | |||
10320 | (((strm->flags & NGTCP2_STRM_FLAG_SENT_RST0x04) && | |||
10321 | (strm->flags & NGTCP2_STRM_FLAG_RST_ACKED0x20)) || | |||
10322 | (!(strm->flags & NGTCP2_STRM_FLAG_SENT_RST0x04) && | |||
10323 | ngtcp2_strm_is_all_tx_data_acked(strm)))) { | |||
10324 | return ngtcp2_conn_close_stream(conn, strm, app_error_code); | |||
10325 | } | |||
10326 | return 0; | |||
10327 | } | |||
10328 | ||||
10329 | /* | |||
10330 | * conn_shutdown_stream_write closes send stream with error code | |||
10331 | * |app_error_code|. RESET_STREAM frame is scheduled. | |||
10332 | * | |||
10333 | * This function returns 0 if it succeeds, or one of the following | |||
10334 | * negative error codes: | |||
10335 | * | |||
10336 | * NGTCP2_ERR_NOMEM | |||
10337 | * Out of memory. | |||
10338 | */ | |||
10339 | static int conn_shutdown_stream_write(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
10340 | uint64_t app_error_code) { | |||
10341 | if (strm->flags & NGTCP2_STRM_FLAG_SENT_RST0x04) { | |||
10342 | return 0; | |||
10343 | } | |||
10344 | ||||
10345 | /* Set this flag so that we don't accidentally send DATA to this | |||
10346 | stream. */ | |||
10347 | strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR0x02 | NGTCP2_STRM_FLAG_SENT_RST0x04; | |||
10348 | strm->app_error_code = app_error_code; | |||
10349 | ||||
10350 | ngtcp2_strm_streamfrq_clear(strm); | |||
10351 | ||||
10352 | return conn_reset_stream(conn, strm, app_error_code); | |||
10353 | } | |||
10354 | ||||
10355 | /* | |||
10356 | * conn_shutdown_stream_read closes read stream with error code | |||
10357 | * |app_error_code|. STOP_SENDING frame is scheduled. | |||
10358 | * | |||
10359 | * This function returns 0 if it succeeds, or one of the following | |||
10360 | * negative error codes: | |||
10361 | * | |||
10362 | * NGTCP2_ERR_NOMEM | |||
10363 | * Out of memory. | |||
10364 | */ | |||
10365 | static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
10366 | uint64_t app_error_code) { | |||
10367 | if (strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING0x10) { | |||
10368 | return 0; | |||
10369 | } | |||
10370 | if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD0x01) && | |||
10371 | ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset) { | |||
10372 | return 0; | |||
10373 | } | |||
10374 | ||||
10375 | /* Extend connection flow control window for the amount of data | |||
10376 | which are not passed to application. */ | |||
10377 | if (!(strm->flags & | |||
10378 | (NGTCP2_STRM_FLAG_STOP_SENDING0x10 | NGTCP2_STRM_FLAG_RECV_RST0x08))) { | |||
10379 | ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset - | |||
10380 | ngtcp2_strm_rx_offset(strm)); | |||
10381 | } | |||
10382 | ||||
10383 | strm->flags |= NGTCP2_STRM_FLAG_STOP_SENDING0x10; | |||
10384 | strm->app_error_code = app_error_code; | |||
10385 | ||||
10386 | return conn_stop_sending(conn, strm, app_error_code); | |||
10387 | } | |||
10388 | ||||
10389 | int ngtcp2_conn_shutdown_stream(ngtcp2_conn *conn, int64_t stream_id, | |||
10390 | uint64_t app_error_code) { | |||
10391 | int rv; | |||
10392 | ngtcp2_strm *strm; | |||
10393 | ||||
10394 | strm = ngtcp2_conn_find_stream(conn, stream_id); | |||
10395 | if (strm == NULL((void*)0)) { | |||
10396 | return NGTCP2_ERR_STREAM_NOT_FOUND-222; | |||
10397 | } | |||
10398 | ||||
10399 | rv = conn_shutdown_stream_read(conn, strm, app_error_code); | |||
10400 | if (rv != 0) { | |||
10401 | return rv; | |||
10402 | } | |||
10403 | ||||
10404 | rv = conn_shutdown_stream_write(conn, strm, app_error_code); | |||
10405 | if (rv != 0) { | |||
10406 | return rv; | |||
10407 | } | |||
10408 | ||||
10409 | return 0; | |||
10410 | } | |||
10411 | ||||
10412 | int ngtcp2_conn_shutdown_stream_write(ngtcp2_conn *conn, int64_t stream_id, | |||
10413 | uint64_t app_error_code) { | |||
10414 | ngtcp2_strm *strm; | |||
10415 | ||||
10416 | strm = ngtcp2_conn_find_stream(conn, stream_id); | |||
10417 | if (strm == NULL((void*)0)) { | |||
10418 | return NGTCP2_ERR_STREAM_NOT_FOUND-222; | |||
10419 | } | |||
10420 | ||||
10421 | return conn_shutdown_stream_write(conn, strm, app_error_code); | |||
10422 | } | |||
10423 | ||||
10424 | int ngtcp2_conn_shutdown_stream_read(ngtcp2_conn *conn, int64_t stream_id, | |||
10425 | uint64_t app_error_code) { | |||
10426 | ngtcp2_strm *strm; | |||
10427 | ||||
10428 | strm = ngtcp2_conn_find_stream(conn, stream_id); | |||
10429 | if (strm == NULL((void*)0)) { | |||
10430 | return NGTCP2_ERR_STREAM_NOT_FOUND-222; | |||
10431 | } | |||
10432 | ||||
10433 | return conn_shutdown_stream_read(conn, strm, app_error_code); | |||
10434 | } | |||
10435 | ||||
10436 | /* | |||
10437 | * conn_extend_max_stream_offset extends stream level flow control | |||
10438 | * window by |datalen| of the stream denoted by |strm|. | |||
10439 | * | |||
10440 | * This function returns 0 if it succeeds, or one of the following | |||
10441 | * negative error codes: | |||
10442 | * | |||
10443 | * NGTCP2_ERR_NOMEM | |||
10444 | * Out of memory. | |||
10445 | */ | |||
10446 | static int conn_extend_max_stream_offset(ngtcp2_conn *conn, ngtcp2_strm *strm, | |||
10447 | uint64_t datalen) { | |||
10448 | ngtcp2_strm *top; | |||
10449 | ||||
10450 | if (datalen > NGTCP2_MAX_VARINT((1ULL << 62) - 1) || | |||
10451 | strm->rx.unsent_max_offset > NGTCP2_MAX_VARINT((1ULL << 62) - 1) - datalen) { | |||
10452 | strm->rx.unsent_max_offset = NGTCP2_MAX_VARINT((1ULL << 62) - 1); | |||
10453 | } else { | |||
10454 | strm->rx.unsent_max_offset += datalen; | |||
10455 | } | |||
10456 | ||||
10457 | if (!(strm->flags & | |||
10458 | (NGTCP2_STRM_FLAG_SHUT_RD0x01 | NGTCP2_STRM_FLAG_STOP_SENDING0x10)) && | |||
10459 | !ngtcp2_strm_is_tx_queued(strm) && | |||
10460 | conn_should_send_max_stream_data(conn, strm)) { | |||
10461 | if (!ngtcp2_pq_empty(&conn->tx.strmq)) { | |||
10462 | top = ngtcp2_conn_tx_strmq_top(conn); | |||
10463 | strm->cycle = top->cycle; | |||
10464 | } | |||
10465 | strm->cycle = conn_tx_strmq_first_cycle(conn); | |||
10466 | return ngtcp2_conn_tx_strmq_push(conn, strm); | |||
10467 | } | |||
10468 | ||||
10469 | return 0; | |||
10470 | } | |||
10471 | ||||
10472 | int ngtcp2_conn_extend_max_stream_offset(ngtcp2_conn *conn, int64_t stream_id, | |||
10473 | uint64_t datalen) { | |||
10474 | ngtcp2_strm *strm; | |||
10475 | ||||
10476 | strm = ngtcp2_conn_find_stream(conn, stream_id); | |||
10477 | if (strm == NULL((void*)0)) { | |||
10478 | return NGTCP2_ERR_STREAM_NOT_FOUND-222; | |||
10479 | } | |||
10480 | ||||
10481 | return conn_extend_max_stream_offset(conn, strm, datalen); | |||
10482 | } | |||
10483 | ||||
10484 | void ngtcp2_conn_extend_max_offset(ngtcp2_conn *conn, uint64_t datalen) { | |||
10485 | if (NGTCP2_MAX_VARINT((1ULL << 62) - 1) < datalen || | |||
10486 | conn->rx.unsent_max_offset > NGTCP2_MAX_VARINT((1ULL << 62) - 1) - datalen) { | |||
10487 | conn->rx.unsent_max_offset = NGTCP2_MAX_VARINT((1ULL << 62) - 1); | |||
10488 | return; | |||
10489 | } | |||
10490 | ||||
10491 | conn->rx.unsent_max_offset += datalen; | |||
10492 | } | |||
10493 | ||||
10494 | void ngtcp2_conn_extend_max_streams_bidi(ngtcp2_conn *conn, size_t n) { | |||
10495 | handle_max_remote_streams_extension(&conn->remote.bidi.unsent_max_streams, n); | |||
10496 | } | |||
10497 | ||||
10498 | void ngtcp2_conn_extend_max_streams_uni(ngtcp2_conn *conn, size_t n) { | |||
10499 | handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams, n); | |||
10500 | } | |||
10501 | ||||
10502 | const ngtcp2_cid *ngtcp2_conn_get_dcid(ngtcp2_conn *conn) { | |||
10503 | return &conn->dcid.current.cid; | |||
10504 | } | |||
10505 | ||||
10506 | uint32_t ngtcp2_conn_get_negotiated_version(ngtcp2_conn *conn) { | |||
10507 | return conn->version; | |||
10508 | } | |||
10509 | ||||
10510 | int ngtcp2_conn_early_data_rejected(ngtcp2_conn *conn) { | |||
10511 | ngtcp2_pktns *pktns = &conn->pktns; | |||
10512 | ngtcp2_rtb *rtb = &conn->pktns.rtb; | |||
10513 | int rv; | |||
10514 | ||||
10515 | conn->flags |= NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED0x20; | |||
10516 | ||||
10517 | rv = ngtcp2_rtb_remove_all(rtb, conn, pktns, &conn->cstat); | |||
10518 | if (rv != 0) { | |||
10519 | return rv; | |||
10520 | } | |||
10521 | ||||
10522 | return rv; | |||
10523 | } | |||
10524 | ||||
10525 | void ngtcp2_conn_update_rtt(ngtcp2_conn *conn, ngtcp2_duration rtt, | |||
10526 | ngtcp2_duration ack_delay, ngtcp2_tstamp ts) { | |||
10527 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
10528 | ngtcp2_duration min_rtt; | |||
10529 | ||||
10530 | rtt = ngtcp2_max(rtt, NGTCP2_GRANULARITY)((rtt) > (((uint64_t)1000000ULL)) ? (rtt) : (((uint64_t)1000000ULL ))); | |||
10531 | ||||
10532 | cstat->latest_rtt = rtt; | |||
10533 | ||||
10534 | if (cstat->min_rtt == UINT64_MAX(18446744073709551615UL)) { | |||
10535 | cstat->min_rtt = rtt; | |||
10536 | cstat->smoothed_rtt = rtt; | |||
10537 | cstat->rttvar = rtt / 2; | |||
10538 | cstat->first_rtt_sample_ts = ts; | |||
10539 | } else { | |||
10540 | min_rtt = ngtcp2_min(cstat->min_rtt, rtt)((cstat->min_rtt) < (rtt) ? (cstat->min_rtt) : (rtt) ); | |||
10541 | if (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80) { | |||
10542 | ack_delay = | |||
10543 | ngtcp2_min(ack_delay, conn->remote.transport_params.max_ack_delay)((ack_delay) < (conn->remote.transport_params.max_ack_delay ) ? (ack_delay) : (conn->remote.transport_params.max_ack_delay )); | |||
10544 | } else if (ack_delay > 0 && rtt < cstat->min_rtt + ack_delay) { | |||
10545 | /* Ignore RTT sample if adjusting ack_delay causes the sample | |||
10546 | less than min_rtt before handshake confirmation. */ | |||
10547 | ngtcp2_log_info( | |||
10548 | &conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10549 | "ignore rtt sample because ack_delay is too large latest_rtt=%" PRIu64"l" "u" | |||
10550 | " min_rtt=%" PRIu64"l" "u" " ack_delay=%" PRIu64"l" "u", | |||
10551 | (uint64_t)(rtt / NGTCP2_MILLISECONDS((uint64_t)1000000ULL)), | |||
10552 | (uint64_t)(cstat->min_rtt / NGTCP2_MILLISECONDS((uint64_t)1000000ULL)), | |||
10553 | (uint64_t)(ack_delay / NGTCP2_MILLISECONDS((uint64_t)1000000ULL))); | |||
10554 | return; | |||
10555 | } | |||
10556 | ||||
10557 | if (rtt > min_rtt + ack_delay) { | |||
10558 | rtt -= ack_delay; | |||
10559 | } | |||
10560 | ||||
10561 | cstat->min_rtt = min_rtt; | |||
10562 | cstat->rttvar = (cstat->rttvar * 3 + (cstat->smoothed_rtt < rtt | |||
10563 | ? rtt - cstat->smoothed_rtt | |||
10564 | : cstat->smoothed_rtt - rtt)) / | |||
10565 | 4; | |||
10566 | cstat->smoothed_rtt = (cstat->smoothed_rtt * 7 + rtt) / 8; | |||
10567 | } | |||
10568 | ||||
10569 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10570 | "latest_rtt=%" PRIu64"l" "u" " min_rtt=%" PRIu64"l" "u" | |||
10571 | " smoothed_rtt=%" PRIu64"l" "u" " rttvar=%" PRIu64"l" "u" | |||
10572 | " ack_delay=%" PRIu64"l" "u", | |||
10573 | (uint64_t)(cstat->latest_rtt / NGTCP2_MILLISECONDS((uint64_t)1000000ULL)), | |||
10574 | (uint64_t)(cstat->min_rtt / NGTCP2_MILLISECONDS((uint64_t)1000000ULL)), | |||
10575 | cstat->smoothed_rtt / NGTCP2_MILLISECONDS((uint64_t)1000000ULL), | |||
10576 | cstat->rttvar / NGTCP2_MILLISECONDS((uint64_t)1000000ULL), | |||
10577 | (uint64_t)(ack_delay / NGTCP2_MILLISECONDS((uint64_t)1000000ULL))); | |||
10578 | } | |||
10579 | ||||
10580 | void ngtcp2_conn_get_conn_stat(ngtcp2_conn *conn, ngtcp2_conn_stat *cstat) { | |||
10581 | *cstat = conn->cstat; | |||
10582 | } | |||
10583 | ||||
10584 | static ngtcp2_pktns *conn_get_earliest_pktns(ngtcp2_conn *conn, | |||
10585 | ngtcp2_tstamp *pts, | |||
10586 | const ngtcp2_tstamp *times) { | |||
10587 | ngtcp2_pktns *ns[] = {conn->in_pktns, conn->hs_pktns, &conn->pktns}; | |||
10588 | ngtcp2_pktns *res = ns[0]; | |||
10589 | size_t i; | |||
10590 | ngtcp2_tstamp earliest_ts = times[NGTCP2_PKTNS_ID_INITIAL]; | |||
10591 | ||||
10592 | for (i = NGTCP2_PKTNS_ID_HANDSHAKE; i < NGTCP2_PKTNS_ID_MAX; ++i) { | |||
10593 | if (ns[i] == NULL((void*)0) || ns[i]->rtb.num_retransmittable == 0 || | |||
10594 | (times[i] == UINT64_MAX(18446744073709551615UL) || | |||
10595 | (earliest_ts != UINT64_MAX(18446744073709551615UL) && times[i] >= earliest_ts) || | |||
10596 | (i == NGTCP2_PKTNS_ID_APPLICATION && | |||
10597 | !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80)))) { | |||
10598 | continue; | |||
10599 | } | |||
10600 | ||||
10601 | earliest_ts = times[i]; | |||
10602 | res = ns[i]; | |||
10603 | } | |||
10604 | ||||
10605 | if (res == NULL((void*)0) && !conn->server) { | |||
10606 | earliest_ts = UINT64_MAX(18446744073709551615UL); | |||
10607 | ||||
10608 | if (conn->hs_pktns && conn->hs_pktns->crypto.tx.ckm) { | |||
10609 | res = conn->hs_pktns; | |||
10610 | } else { | |||
10611 | res = conn->in_pktns; | |||
10612 | } | |||
10613 | } | |||
10614 | ||||
10615 | if (pts) { | |||
10616 | *pts = earliest_ts; | |||
10617 | } | |||
10618 | return res; | |||
10619 | } | |||
10620 | ||||
10621 | void ngtcp2_conn_set_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
10622 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
10623 | ngtcp2_duration timeout; | |||
10624 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
10625 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
10626 | ngtcp2_pktns *pktns = &conn->pktns; | |||
10627 | ngtcp2_pktns *earliest_pktns; | |||
10628 | ngtcp2_tstamp earliest_loss_time; | |||
10629 | ngtcp2_tstamp last_tx_pkt_ts; | |||
10630 | ||||
10631 | conn_get_earliest_pktns(conn, &earliest_loss_time, cstat->loss_time); | |||
10632 | ||||
10633 | if (earliest_loss_time != UINT64_MAX(18446744073709551615UL)) { | |||
10634 | cstat->loss_detection_timer = earliest_loss_time; | |||
10635 | ||||
10636 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10637 | "loss_detection_timer=%" PRIu64"l" "u" " nonzero crypto loss time", | |||
10638 | cstat->loss_detection_timer); | |||
10639 | return; | |||
10640 | } | |||
10641 | ||||
10642 | if ((!in_pktns || in_pktns->rtb.num_retransmittable == 0) && | |||
10643 | (!hs_pktns || hs_pktns->rtb.num_retransmittable == 0) && | |||
10644 | (pktns->rtb.num_retransmittable == 0 || | |||
10645 | !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80)) && | |||
10646 | (conn->server || | |||
10647 | (conn->flags & (NGTCP2_CONN_FLAG_SERVER_ADDR_VERIFIED0x4000 | | |||
10648 | NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80)))) { | |||
10649 | if (cstat->loss_detection_timer != UINT64_MAX(18446744073709551615UL)) { | |||
10650 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10651 | "loss detection timer canceled"); | |||
10652 | cstat->loss_detection_timer = UINT64_MAX(18446744073709551615UL); | |||
10653 | cstat->pto_count = 0; | |||
10654 | } | |||
10655 | return; | |||
10656 | } | |||
10657 | ||||
10658 | earliest_pktns = | |||
10659 | conn_get_earliest_pktns(conn, &last_tx_pkt_ts, cstat->last_tx_pkt_ts); | |||
10660 | ||||
10661 | assert(earliest_pktns)((void) (0)); | |||
10662 | ||||
10663 | if (last_tx_pkt_ts == UINT64_MAX(18446744073709551615UL)) { | |||
10664 | last_tx_pkt_ts = ts; | |||
10665 | } | |||
10666 | ||||
10667 | timeout = conn_compute_pto(conn, earliest_pktns) * (1ULL << cstat->pto_count); | |||
10668 | ||||
10669 | cstat->loss_detection_timer = last_tx_pkt_ts + timeout; | |||
10670 | ||||
10671 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10672 | "loss_detection_timer=%" PRIu64"l" "u" " last_tx_pkt_ts=%" PRIu64"l" "u" | |||
10673 | " timeout=%" PRIu64"l" "u", | |||
10674 | cstat->loss_detection_timer, last_tx_pkt_ts, | |||
10675 | (uint64_t)(timeout / NGTCP2_MILLISECONDS((uint64_t)1000000ULL))); | |||
10676 | } | |||
10677 | ||||
10678 | int ngtcp2_conn_on_loss_detection_timer(ngtcp2_conn *conn, ngtcp2_tstamp ts) { | |||
10679 | ngtcp2_conn_stat *cstat = &conn->cstat; | |||
10680 | int rv; | |||
10681 | ngtcp2_pktns *in_pktns = conn->in_pktns; | |||
10682 | ngtcp2_pktns *hs_pktns = conn->hs_pktns; | |||
10683 | ngtcp2_tstamp earliest_loss_time; | |||
10684 | ngtcp2_pktns *loss_pktns = | |||
10685 | conn_get_earliest_pktns(conn, &earliest_loss_time, cstat->loss_time); | |||
10686 | ngtcp2_pktns *earliest_pktns; | |||
10687 | ||||
10688 | conn->log.last_ts = ts; | |||
10689 | conn->qlog.last_ts = ts; | |||
10690 | ||||
10691 | switch (conn->state) { | |||
10692 | case NGTCP2_CS_CLOSING: | |||
10693 | case NGTCP2_CS_DRAINING: | |||
10694 | cstat->loss_detection_timer = UINT64_MAX(18446744073709551615UL); | |||
10695 | cstat->pto_count = 0; | |||
10696 | return 0; | |||
10697 | default: | |||
10698 | break; | |||
10699 | } | |||
10700 | ||||
10701 | if (cstat->loss_detection_timer == UINT64_MAX(18446744073709551615UL)) { | |||
10702 | return 0; | |||
10703 | } | |||
10704 | ||||
10705 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, | |||
10706 | "loss detection timer fired"); | |||
10707 | ||||
10708 | if (earliest_loss_time != UINT64_MAX(18446744073709551615UL)) { | |||
10709 | rv = ngtcp2_conn_detect_lost_pkt(conn, loss_pktns, cstat, ts); | |||
10710 | if (rv != 0) { | |||
10711 | return rv; | |||
10712 | } | |||
10713 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
10714 | return 0; | |||
10715 | } | |||
10716 | ||||
10717 | if (!conn->server && !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01)) { | |||
10718 | if (hs_pktns->crypto.tx.ckm) { | |||
10719 | hs_pktns->rtb.probe_pkt_left = 1; | |||
10720 | } else { | |||
10721 | in_pktns->rtb.probe_pkt_left = 1; | |||
10722 | } | |||
10723 | } else { | |||
10724 | earliest_pktns = conn_get_earliest_pktns(conn, NULL((void*)0), cstat->last_tx_pkt_ts); | |||
10725 | ||||
10726 | assert(earliest_pktns)((void) (0)); | |||
10727 | ||||
10728 | switch (earliest_pktns->rtb.pktns_id) { | |||
10729 | case NGTCP2_PKTNS_ID_INITIAL: | |||
10730 | assert(in_pktns)((void) (0)); | |||
10731 | in_pktns->rtb.probe_pkt_left = 1; | |||
10732 | if (!conn->server) { | |||
10733 | break; | |||
10734 | } | |||
10735 | /* fall through for server so that it can coalesce packets. */ | |||
10736 | /* fall through */ | |||
10737 | case NGTCP2_PKTNS_ID_HANDSHAKE: | |||
10738 | assert(hs_pktns)((void) (0)); | |||
10739 | hs_pktns->rtb.probe_pkt_left = 1; | |||
10740 | break; | |||
10741 | case NGTCP2_PKTNS_ID_APPLICATION: | |||
10742 | conn->pktns.rtb.probe_pkt_left = 2; | |||
10743 | break; | |||
10744 | default: | |||
10745 | assert(0)((void) (0)); | |||
10746 | } | |||
10747 | } | |||
10748 | ||||
10749 | ++cstat->pto_count; | |||
10750 | ||||
10751 | ngtcp2_log_info(&conn->log, NGTCP2_LOG_EVENT_RCV, "pto_count=%zu", | |||
10752 | cstat->pto_count); | |||
10753 | ||||
10754 | ngtcp2_conn_set_loss_detection_timer(conn, ts); | |||
10755 | ||||
10756 | return 0; | |||
10757 | } | |||
10758 | ||||
10759 | int ngtcp2_conn_submit_crypto_data(ngtcp2_conn *conn, | |||
10760 | ngtcp2_crypto_level crypto_level, | |||
10761 | const uint8_t *data, const size_t datalen) { | |||
10762 | ngtcp2_pktns *pktns; | |||
10763 | ngtcp2_frame_chain *frc; | |||
10764 | ngtcp2_crypto *fr; | |||
10765 | int rv; | |||
10766 | ||||
10767 | if (datalen == 0) { | |||
10768 | return 0; | |||
10769 | } | |||
10770 | ||||
10771 | switch (crypto_level) { | |||
10772 | case NGTCP2_CRYPTO_LEVEL_INITIAL: | |||
10773 | assert(conn->in_pktns)((void) (0)); | |||
10774 | pktns = conn->in_pktns; | |||
10775 | break; | |||
10776 | case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: | |||
10777 | assert(conn->hs_pktns)((void) (0)); | |||
10778 | pktns = conn->hs_pktns; | |||
10779 | break; | |||
10780 | case NGTCP2_CRYPTO_LEVEL_APPLICATION: | |||
10781 | pktns = &conn->pktns; | |||
10782 | break; | |||
10783 | default: | |||
10784 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
10785 | } | |||
10786 | ||||
10787 | rv = ngtcp2_frame_chain_new(&frc, conn->mem); | |||
10788 | if (rv != 0) { | |||
10789 | return rv; | |||
10790 | } | |||
10791 | ||||
10792 | fr = &frc->fr.crypto; | |||
10793 | ||||
10794 | fr->type = NGTCP2_FRAME_CRYPTO; | |||
10795 | fr->offset = pktns->crypto.tx.offset; | |||
10796 | fr->datacnt = 1; | |||
10797 | fr->data[0].len = datalen; | |||
10798 | fr->data[0].base = (uint8_t *)data; | |||
10799 | ||||
10800 | rv = ngtcp2_ksl_insert(&pktns->crypto.tx.frq, NULL((void*)0), &fr->offset, frc); | |||
10801 | if (rv != 0) { | |||
10802 | ngtcp2_frame_chain_del(frc, conn->mem); | |||
10803 | return rv; | |||
10804 | } | |||
10805 | ||||
10806 | pktns->crypto.strm.tx.offset += datalen; | |||
10807 | pktns->crypto.tx.offset += datalen; | |||
10808 | ||||
10809 | return 0; | |||
10810 | } | |||
10811 | ||||
10812 | int ngtcp2_conn_submit_new_token(ngtcp2_conn *conn, const uint8_t *token, | |||
10813 | size_t tokenlen) { | |||
10814 | int rv; | |||
10815 | ngtcp2_frame_chain *nfrc; | |||
10816 | uint8_t *p; | |||
10817 | ||||
10818 | assert(conn->server)((void) (0)); | |||
10819 | assert(token)((void) (0)); | |||
10820 | assert(tokenlen)((void) (0)); | |||
10821 | ||||
10822 | rv = ngtcp2_frame_chain_extralen_new(&nfrc, tokenlen, conn->mem); | |||
10823 | if (rv != 0) { | |||
10824 | return rv; | |||
10825 | } | |||
10826 | ||||
10827 | nfrc->fr.type = NGTCP2_FRAME_NEW_TOKEN; | |||
10828 | ||||
10829 | p = (uint8_t *)nfrc + sizeof(*nfrc); | |||
10830 | memcpy(p, token, tokenlen); | |||
10831 | ||||
10832 | ngtcp2_vec_init(&nfrc->fr.new_token.token, p, tokenlen); | |||
10833 | ||||
10834 | nfrc->next = conn->pktns.tx.frq; | |||
10835 | conn->pktns.tx.frq = nfrc; | |||
10836 | ||||
10837 | return 0; | |||
10838 | } | |||
10839 | ||||
10840 | ngtcp2_strm *ngtcp2_conn_tx_strmq_top(ngtcp2_conn *conn) { | |||
10841 | assert(!ngtcp2_pq_empty(&conn->tx.strmq))((void) (0)); | |||
10842 | return ngtcp2_struct_of(ngtcp2_pq_top(&conn->tx.strmq), ngtcp2_strm, pe)((ngtcp2_strm *)(void *)((char *)(ngtcp2_pq_top(&conn-> tx.strmq))-__builtin_offsetof(ngtcp2_strm, pe))); | |||
10843 | } | |||
10844 | ||||
10845 | void ngtcp2_conn_tx_strmq_pop(ngtcp2_conn *conn) { | |||
10846 | ngtcp2_strm *strm = ngtcp2_conn_tx_strmq_top(conn); | |||
10847 | assert(strm)((void) (0)); | |||
10848 | ngtcp2_pq_pop(&conn->tx.strmq); | |||
10849 | strm->pe.index = NGTCP2_PQ_BAD_INDEX(18446744073709551615UL); | |||
10850 | } | |||
10851 | ||||
10852 | int ngtcp2_conn_tx_strmq_push(ngtcp2_conn *conn, ngtcp2_strm *strm) { | |||
10853 | return ngtcp2_pq_push(&conn->tx.strmq, &strm->pe); | |||
10854 | } | |||
10855 | ||||
10856 | size_t ngtcp2_conn_get_num_scid(ngtcp2_conn *conn) { | |||
10857 | return ngtcp2_ksl_len(&conn->scid.set); | |||
10858 | } | |||
10859 | ||||
10860 | size_t ngtcp2_conn_get_scid(ngtcp2_conn *conn, ngtcp2_cid *dest) { | |||
10861 | ngtcp2_ksl_it it; | |||
10862 | ngtcp2_scid *scid; | |||
10863 | ||||
10864 | for (it = ngtcp2_ksl_begin(&conn->scid.set); !ngtcp2_ksl_it_end(&it)((&it)->blk->n == (&it)->i && (& it)->blk->next == ((void*)0)); | |||
10865 | ngtcp2_ksl_it_next(&it)(++(&it)->i == (&it)->blk->n && (& it)->blk->next ? ((&it)->blk = (&it)->blk ->next, (&it)->i = 0) : 0)) { | |||
10866 | scid = ngtcp2_ksl_it_get(&it); | |||
10867 | *dest++ = scid->cid; | |||
10868 | } | |||
10869 | ||||
10870 | return ngtcp2_ksl_len(&conn->scid.set); | |||
10871 | } | |||
10872 | ||||
10873 | size_t ngtcp2_conn_get_num_active_dcid(ngtcp2_conn *conn) { | |||
10874 | size_t n = 1; /* for conn->dcid.current */ | |||
10875 | ngtcp2_pv *pv = conn->pv; | |||
10876 | ||||
10877 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED0x0100)) { | |||
10878 | return 0; | |||
10879 | } | |||
10880 | ||||
10881 | if (pv) { | |||
10882 | if (pv->dcid.seq != conn->dcid.current.seq) { | |||
10883 | ++n; | |||
10884 | } | |||
10885 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
10886 | pv->fallback_dcid.seq != conn->dcid.current.seq && | |||
10887 | pv->fallback_dcid.seq != pv->dcid.seq) { | |||
10888 | ++n; | |||
10889 | } | |||
10890 | } | |||
10891 | ||||
10892 | n += ngtcp2_ringbuf_len(&conn->dcid.retired)((&conn->dcid.retired)->len); | |||
10893 | ||||
10894 | return n; | |||
10895 | } | |||
10896 | ||||
10897 | static void copy_dcid_to_cid_token(ngtcp2_cid_token *dest, | |||
10898 | const ngtcp2_dcid *src) { | |||
10899 | dest->seq = src->seq; | |||
10900 | dest->cid = src->cid; | |||
10901 | ngtcp2_path_storage_init2(&dest->ps, &src->ps.path); | |||
10902 | dest->token_present = | |||
10903 | (uint8_t)!ngtcp2_check_invalid_stateless_reset_token(src->token); | |||
10904 | memcpy(dest->token, src->token, NGTCP2_STATELESS_RESET_TOKENLEN16); | |||
10905 | } | |||
10906 | ||||
10907 | size_t ngtcp2_conn_get_active_dcid(ngtcp2_conn *conn, ngtcp2_cid_token *dest) { | |||
10908 | ngtcp2_pv *pv = conn->pv; | |||
10909 | ngtcp2_cid_token *orig = dest; | |||
10910 | ngtcp2_dcid *dcid; | |||
10911 | size_t len, i; | |||
10912 | ||||
10913 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED_HANDLED0x0100)) { | |||
10914 | return 0; | |||
10915 | } | |||
10916 | ||||
10917 | copy_dcid_to_cid_token(dest, &conn->dcid.current); | |||
10918 | ++dest; | |||
10919 | ||||
10920 | if (pv) { | |||
10921 | if (pv->dcid.seq != conn->dcid.current.seq) { | |||
10922 | copy_dcid_to_cid_token(dest, &pv->dcid); | |||
10923 | ++dest; | |||
10924 | } | |||
10925 | if ((pv->flags & NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE0x04) && | |||
10926 | pv->fallback_dcid.seq != conn->dcid.current.seq && | |||
10927 | pv->fallback_dcid.seq != pv->dcid.seq) { | |||
10928 | copy_dcid_to_cid_token(dest, &pv->fallback_dcid); | |||
10929 | ++dest; | |||
10930 | } | |||
10931 | } | |||
10932 | ||||
10933 | len = ngtcp2_ringbuf_len(&conn->dcid.retired)((&conn->dcid.retired)->len); | |||
10934 | for (i = 0; i < len; ++i) { | |||
10935 | dcid = ngtcp2_ringbuf_get(&conn->dcid.retired, i); | |||
10936 | copy_dcid_to_cid_token(dest, dcid); | |||
10937 | ++dest; | |||
10938 | } | |||
10939 | ||||
10940 | return (size_t)(dest - orig); | |||
10941 | } | |||
10942 | ||||
10943 | void ngtcp2_conn_set_local_addr(ngtcp2_conn *conn, const ngtcp2_addr *addr) { | |||
10944 | ngtcp2_addr *dest = &conn->dcid.current.ps.path.local; | |||
10945 | ||||
10946 | assert(addr->addrlen <= sizeof(conn->dcid.current.ps.local_addrbuf))((void) (0)); | |||
10947 | ngtcp2_addr_copy(dest, addr); | |||
10948 | } | |||
10949 | ||||
10950 | void ngtcp2_conn_set_remote_addr(ngtcp2_conn *conn, const ngtcp2_addr *addr) { | |||
10951 | ngtcp2_addr *dest = &conn->dcid.current.ps.path.remote; | |||
10952 | ||||
10953 | assert(addr->addrlen <= sizeof(conn->dcid.current.ps.remote_addrbuf))((void) (0)); | |||
10954 | ngtcp2_addr_copy(dest, addr); | |||
10955 | } | |||
10956 | ||||
10957 | const ngtcp2_path *ngtcp2_conn_get_path(ngtcp2_conn *conn) { | |||
10958 | return &conn->dcid.current.ps.path; | |||
10959 | } | |||
10960 | ||||
10961 | int ngtcp2_conn_initiate_migration(ngtcp2_conn *conn, const ngtcp2_path *path, | |||
10962 | ngtcp2_tstamp ts) { | |||
10963 | int rv; | |||
10964 | ngtcp2_dcid *dcid; | |||
10965 | ||||
10966 | assert(!conn->server)((void) (0)); | |||
10967 | ||||
10968 | conn->log.last_ts = ts; | |||
10969 | conn->qlog.last_ts = ts; | |||
10970 | ||||
10971 | if (conn->remote.transport_params.disable_active_migration || | |||
10972 | conn->dcid.current.cid.datalen == 0 || | |||
10973 | !(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_CONFIRMED0x80)) { | |||
10974 | return NGTCP2_ERR_INVALID_STATE-206; | |||
10975 | } | |||
10976 | if (ngtcp2_ringbuf_len(&conn->dcid.unused)((&conn->dcid.unused)->len) == 0) { | |||
10977 | return NGTCP2_ERR_CONN_ID_BLOCKED-237; | |||
10978 | } | |||
10979 | ||||
10980 | if (ngtcp2_path_eq(&conn->dcid.current.ps.path, path)) { | |||
10981 | return NGTCP2_ERR_INVALID_ARGUMENT-201; | |||
10982 | } | |||
10983 | ||||
10984 | dcid = ngtcp2_ringbuf_get(&conn->dcid.unused, 0); | |||
10985 | ||||
10986 | rv = conn_stop_pv(conn, ts); | |||
10987 | if (rv != 0) { | |||
10988 | return rv; | |||
10989 | } | |||
10990 | ||||
10991 | rv = conn_retire_dcid(conn, &conn->dcid.current, ts); | |||
10992 | if (rv != 0) { | |||
10993 | return rv; | |||
10994 | } | |||
10995 | ||||
10996 | ngtcp2_dcid_copy(&conn->dcid.current, dcid); | |||
10997 | ngtcp2_path_copy(&conn->dcid.current.ps.path, path); | |||
10998 | ngtcp2_ringbuf_pop_front(&conn->dcid.unused); | |||
10999 | ||||
11000 | rv = conn_call_activate_dcid(conn, &conn->dcid.current); | |||
11001 | if (rv != 0) { | |||
11002 | return rv; | |||
11003 | } | |||
11004 | ||||
11005 | conn_reset_congestion_state(conn); | |||
11006 | conn_reset_ecn_validation_state(conn); | |||
11007 | ||||
11008 | return 0; | |||
11009 | } | |||
11010 | ||||
11011 | uint64_t ngtcp2_conn_get_max_local_streams_uni(ngtcp2_conn *conn) { | |||
11012 | return conn->local.uni.max_streams; | |||
11013 | } | |||
11014 | ||||
11015 | uint64_t ngtcp2_conn_get_max_data_left(ngtcp2_conn *conn) { | |||
11016 | return conn->tx.max_offset - conn->tx.offset; | |||
11017 | } | |||
11018 | ||||
11019 | uint64_t ngtcp2_conn_get_streams_bidi_left(ngtcp2_conn *conn) { | |||
11020 | uint64_t n = ngtcp2_ord_stream_id(conn->local.bidi.next_stream_id); | |||
11021 | ||||
11022 | return n > conn->local.bidi.max_streams | |||
11023 | ? 0 | |||
11024 | : conn->local.bidi.max_streams - n + 1; | |||
11025 | } | |||
11026 | ||||
11027 | uint64_t ngtcp2_conn_get_streams_uni_left(ngtcp2_conn *conn) { | |||
11028 | uint64_t n = ngtcp2_ord_stream_id(conn->local.uni.next_stream_id); | |||
11029 | ||||
11030 | return n > conn->local.uni.max_streams ? 0 | |||
11031 | : conn->local.uni.max_streams - n + 1; | |||
11032 | } | |||
11033 | ||||
11034 | ngtcp2_tstamp ngtcp2_conn_get_idle_expiry(ngtcp2_conn *conn) { | |||
11035 | ngtcp2_duration trpto; | |||
11036 | ngtcp2_duration idle_timeout; | |||
11037 | ||||
11038 | /* TODO Remote max_idle_timeout becomes effective after handshake | |||
11039 | completion. */ | |||
11040 | ||||
11041 | if (!(conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01) || | |||
11042 | conn->remote.transport_params.max_idle_timeout == 0 || | |||
11043 | (conn->local.transport_params.max_idle_timeout && | |||
11044 | conn->local.transport_params.max_idle_timeout < | |||
11045 | conn->remote.transport_params.max_idle_timeout)) { | |||
11046 | idle_timeout = conn->local.transport_params.max_idle_timeout; | |||
11047 | } else { | |||
11048 | idle_timeout = conn->remote.transport_params.max_idle_timeout; | |||
11049 | } | |||
11050 | ||||
11051 | if (idle_timeout == 0) { | |||
11052 | return UINT64_MAX(18446744073709551615UL); | |||
11053 | } | |||
11054 | ||||
11055 | trpto = 3 * conn_compute_pto( | |||
11056 | conn, (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01) | |||
11057 | ? &conn->pktns | |||
11058 | : conn->hs_pktns); | |||
11059 | ||||
11060 | return conn->idle_ts + ngtcp2_max(idle_timeout, trpto)((idle_timeout) > (trpto) ? (idle_timeout) : (trpto)); | |||
11061 | } | |||
11062 | ||||
11063 | ngtcp2_duration ngtcp2_conn_get_pto(ngtcp2_conn *conn) { | |||
11064 | return conn_compute_pto(conn, | |||
11065 | (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED0x01) | |||
11066 | ? &conn->pktns | |||
11067 | : conn->hs_pktns); | |||
11068 | } | |||
11069 | ||||
11070 | void ngtcp2_conn_set_initial_crypto_ctx(ngtcp2_conn *conn, | |||
11071 | const ngtcp2_crypto_ctx *ctx) { | |||
11072 | assert(conn->in_pktns)((void) (0)); | |||
11073 | conn->in_pktns->crypto.ctx = *ctx; | |||
11074 | } | |||
11075 | ||||
11076 | const ngtcp2_crypto_ctx *ngtcp2_conn_get_initial_crypto_ctx(ngtcp2_conn *conn) { | |||
11077 | assert(conn->in_pktns)((void) (0)); | |||
11078 | return &conn->in_pktns->crypto.ctx; | |||
11079 | } | |||
11080 | ||||
11081 | void ngtcp2_conn_set_retry_aead(ngtcp2_conn *conn, | |||
11082 | const ngtcp2_crypto_aead *aead, | |||
11083 | const ngtcp2_crypto_aead_ctx *aead_ctx) { | |||
11084 | assert(!conn->crypto.retry_aead_ctx.native_handle)((void) (0)); | |||
11085 | ||||
11086 | conn->crypto.retry_aead = *aead; | |||
11087 | conn->crypto.retry_aead_ctx = *aead_ctx; | |||
11088 | } | |||
11089 | ||||
11090 | void ngtcp2_conn_set_crypto_ctx(ngtcp2_conn *conn, | |||
11091 | const ngtcp2_crypto_ctx *ctx) { | |||
11092 | assert(conn->hs_pktns)((void) (0)); | |||
11093 | conn->hs_pktns->crypto.ctx = *ctx; | |||
11094 | conn->pktns.crypto.ctx = *ctx; | |||
11095 | } | |||
11096 | ||||
11097 | const ngtcp2_crypto_ctx *ngtcp2_conn_get_crypto_ctx(ngtcp2_conn *conn) { | |||
11098 | return &conn->pktns.crypto.ctx; | |||
11099 | } | |||
11100 | ||||
11101 | void ngtcp2_conn_set_early_crypto_ctx(ngtcp2_conn *conn, | |||
11102 | const ngtcp2_crypto_ctx *ctx) { | |||
11103 | conn->early.ctx = *ctx; | |||
11104 | } | |||
11105 | ||||
11106 | const ngtcp2_crypto_ctx *ngtcp2_conn_get_early_crypto_ctx(ngtcp2_conn *conn) { | |||
11107 | return &conn->early.ctx; | |||
11108 | } | |||
11109 | ||||
11110 | void *ngtcp2_conn_get_tls_native_handle(ngtcp2_conn *conn) { | |||
11111 | return conn->crypto.tls_native_handle; | |||
11112 | } | |||
11113 | ||||
11114 | void ngtcp2_conn_set_tls_native_handle(ngtcp2_conn *conn, | |||
11115 | void *tls_native_handle) { | |||
11116 | conn->crypto.tls_native_handle = tls_native_handle; | |||
11117 | } | |||
11118 | ||||
11119 | void ngtcp2_conn_get_connection_close_error_code( | |||
11120 | ngtcp2_conn *conn, ngtcp2_connection_close_error_code *ccec) { | |||
11121 | *ccec = conn->rx.ccec; | |||
11122 | } | |||
11123 | ||||
11124 | void ngtcp2_conn_set_tls_error(ngtcp2_conn *conn, int liberr) { | |||
11125 | conn->crypto.tls_error = liberr; | |||
11126 | } | |||
11127 | ||||
11128 | int ngtcp2_conn_get_tls_error(ngtcp2_conn *conn) { | |||
11129 | return conn->crypto.tls_error; | |||
11130 | } | |||
11131 | ||||
11132 | int ngtcp2_conn_is_local_stream(ngtcp2_conn *conn, int64_t stream_id) { | |||
11133 | return conn_local_stream(conn, stream_id); | |||
11134 | } | |||
11135 | ||||
11136 | int ngtcp2_conn_is_server(ngtcp2_conn *conn) { return conn->server; } | |||
11137 | ||||
11138 | int ngtcp2_conn_after_retry(ngtcp2_conn *conn) { | |||
11139 | return (conn->flags & NGTCP2_CONN_FLAG_RECV_RETRY0x10) != 0; | |||
11140 | } | |||
11141 | ||||
11142 | int ngtcp2_conn_set_stream_user_data(ngtcp2_conn *conn, int64_t stream_id, | |||
11143 | void *stream_user_data) { | |||
11144 | ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id); | |||
11145 | ||||
11146 | if (strm == NULL((void*)0)) { | |||
11147 | return NGTCP2_ERR_STREAM_NOT_FOUND-222; | |||
11148 | } | |||
11149 | ||||
11150 | strm->stream_user_data = stream_user_data; | |||
11151 | ||||
11152 | return 0; | |||
11153 | } | |||
11154 | ||||
11155 | void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, | |||
11156 | const ngtcp2_path *path, | |||
11157 | const uint8_t *data) { | |||
11158 | ngtcp2_path_storage_init2(&pcent->ps, path); | |||
11159 | memcpy(pcent->data, data, sizeof(pcent->data)); | |||
11160 | } | |||
11161 | ||||
11162 | void ngtcp2_settings_default(ngtcp2_settings *settings) { | |||
11163 | memset(settings, 0, sizeof(*settings)); | |||
11164 | settings->cc_algo = NGTCP2_CC_ALGO_CUBIC; | |||
11165 | settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT(333 * ((uint64_t)1000000ULL)); | |||
11166 | settings->ack_thresh = 2; | |||
11167 | } | |||
11168 | ||||
11169 | void ngtcp2_transport_params_default(ngtcp2_transport_params *params) { | |||
11170 | memset(params, 0, sizeof(*params)); | |||
11171 | params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_UDP_PAYLOAD_SIZE65527; | |||
11172 | params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT3; | |||
11173 | params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY(25 * ((uint64_t)1000000ULL)); | |||
11174 | params->active_connection_id_limit = | |||
11175 | NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT2; | |||
11176 | } | |||
11177 | ||||
11178 | /* The functions prefixed with ngtcp2_pkt_ are usually put inside | |||
11179 | ngtcp2_pkt.c. This function uses encryption construct and uses | |||
11180 | test data defined only in ngtcp2_conn_test.c, so it is written | |||
11181 | here. */ | |||
11182 | ngtcp2_ssize ngtcp2_pkt_write_connection_close( | |||
11183 | uint8_t *dest, size_t destlen, uint32_t version, const ngtcp2_cid *dcid, | |||
11184 | const ngtcp2_cid *scid, uint64_t error_code, ngtcp2_encrypt encrypt, | |||
11185 | const ngtcp2_crypto_aead *aead, const ngtcp2_crypto_aead_ctx *aead_ctx, | |||
11186 | const uint8_t *iv, ngtcp2_hp_mask hp_mask, const ngtcp2_crypto_cipher *hp, | |||
11187 | const ngtcp2_crypto_cipher_ctx *hp_ctx) { | |||
11188 | ngtcp2_pkt_hd hd; | |||
11189 | ngtcp2_crypto_km ckm; | |||
11190 | ngtcp2_crypto_cc cc; | |||
11191 | ngtcp2_ppe ppe; | |||
11192 | ngtcp2_frame fr = {0}; | |||
11193 | int rv; | |||
11194 | ||||
11195 | ngtcp2_pkt_hd_init(&hd, NGTCP2_PKT_FLAG_LONG_FORM0x01, NGTCP2_PKT_INITIAL, dcid, | |||
11196 | scid, /* pkt_num = */ 0, /* pkt_numlen = */ 1, version, | |||
11197 | /* len = */ 0); | |||
11198 | ||||
11199 | ngtcp2_vec_init(&ckm.secret, NULL((void*)0), 0); | |||
11200 | ngtcp2_vec_init(&ckm.iv, iv, 12); | |||
11201 | ckm.aead_ctx = *aead_ctx; | |||
11202 | ckm.pkt_num = 0; | |||
11203 | ckm.flags = NGTCP2_CRYPTO_KM_FLAG_NONE0x00; | |||
11204 | ||||
11205 | cc.aead = *aead; | |||
11206 | cc.hp = *hp; | |||
11207 | cc.ckm = &ckm; | |||
11208 | cc.hp_ctx = *hp_ctx; | |||
11209 | cc.encrypt = encrypt; | |||
11210 | cc.hp_mask = hp_mask; | |||
11211 | ||||
11212 | ngtcp2_ppe_init(&ppe, dest, destlen, &cc); | |||
11213 | ||||
11214 | rv = ngtcp2_ppe_encode_hd(&ppe, &hd); | |||
11215 | if (rv != 0) { | |||
11216 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
11217 | return rv; | |||
11218 | } | |||
11219 | ||||
11220 | if (!ngtcp2_ppe_ensure_hp_sample(&ppe)) { | |||
11221 | return NGTCP2_ERR_NOBUF-203; | |||
11222 | } | |||
11223 | ||||
11224 | fr.type = NGTCP2_FRAME_CONNECTION_CLOSE; | |||
11225 | fr.connection_close.error_code = error_code; | |||
11226 | ||||
11227 | rv = ngtcp2_ppe_encode_frame(&ppe, &fr); | |||
11228 | if (rv != 0) { | |||
11229 | assert(NGTCP2_ERR_NOBUF == rv)((void) (0)); | |||
11230 | return rv; | |||
11231 | } | |||
11232 | ||||
11233 | return ngtcp2_ppe_final(&ppe, NULL((void*)0)); | |||
11234 | } | |||
11235 | ||||
11236 | int ngtcp2_is_bidi_stream(int64_t stream_id) { return bidi_stream(stream_id); } |