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_strm.h"
26
27 #include <string.h>
28 #include <assert.h>
29
30 #include "ngtcp2_rtb.h"
31 #include "ngtcp2_pkt.h"
32 #include "ngtcp2_vec.h"
33
offset_less(const ngtcp2_ksl_key * lhs,const ngtcp2_ksl_key * rhs)34 static int offset_less(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) {
35 return *(int64_t *)lhs < *(int64_t *)rhs;
36 }
37
ngtcp2_strm_init(ngtcp2_strm * strm,int64_t stream_id,uint32_t flags,uint64_t max_rx_offset,uint64_t max_tx_offset,void * stream_user_data,ngtcp2_objalloc * frc_objalloc,const ngtcp2_mem * mem)38 void ngtcp2_strm_init(ngtcp2_strm *strm, int64_t stream_id, uint32_t flags,
39 uint64_t max_rx_offset, uint64_t max_tx_offset,
40 void *stream_user_data, ngtcp2_objalloc *frc_objalloc,
41 const ngtcp2_mem *mem) {
42 strm->frc_objalloc = frc_objalloc;
43 strm->cycle = 0;
44 strm->tx.acked_offset = NULL;
45 strm->tx.cont_acked_offset = 0;
46 strm->tx.streamfrq = NULL;
47 strm->tx.offset = 0;
48 strm->tx.max_offset = max_tx_offset;
49 strm->tx.last_max_stream_data_ts = UINT64_MAX;
50 strm->tx.loss_count = 0;
51 strm->tx.last_lost_pkt_num = -1;
52 strm->rx.rob = NULL;
53 strm->rx.cont_offset = 0;
54 strm->rx.last_offset = 0;
55 strm->stream_id = stream_id;
56 strm->flags = flags;
57 strm->stream_user_data = stream_user_data;
58 strm->rx.window = strm->rx.max_offset = strm->rx.unsent_max_offset =
59 max_rx_offset;
60 strm->pe.index = NGTCP2_PQ_BAD_INDEX;
61 strm->mem = mem;
62 strm->app_error_code = 0;
63 }
64
ngtcp2_strm_free(ngtcp2_strm * strm)65 void ngtcp2_strm_free(ngtcp2_strm *strm) {
66 ngtcp2_ksl_it it;
67
68 if (strm == NULL) {
69 return;
70 }
71
72 if (strm->tx.streamfrq) {
73 for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
74 ngtcp2_ksl_it_next(&it)) {
75 ngtcp2_frame_chain_objalloc_del(ngtcp2_ksl_it_get(&it),
76 strm->frc_objalloc, strm->mem);
77 }
78
79 ngtcp2_ksl_free(strm->tx.streamfrq);
80 ngtcp2_mem_free(strm->mem, strm->tx.streamfrq);
81 }
82
83 if (strm->rx.rob) {
84 ngtcp2_rob_free(strm->rx.rob);
85 ngtcp2_mem_free(strm->mem, strm->rx.rob);
86 }
87
88 if (strm->tx.acked_offset) {
89 ngtcp2_gaptr_free(strm->tx.acked_offset);
90 ngtcp2_mem_free(strm->mem, strm->tx.acked_offset);
91 }
92 }
93
strm_rob_init(ngtcp2_strm * strm)94 static int strm_rob_init(ngtcp2_strm *strm) {
95 int rv;
96 ngtcp2_rob *rob = ngtcp2_mem_malloc(strm->mem, sizeof(*rob));
97
98 if (rob == NULL) {
99 return NGTCP2_ERR_NOMEM;
100 }
101
102 rv = ngtcp2_rob_init(rob, 8 * 1024, strm->mem);
103 if (rv != 0) {
104 ngtcp2_mem_free(strm->mem, rob);
105 return rv;
106 }
107
108 strm->rx.rob = rob;
109
110 return 0;
111 }
112
ngtcp2_strm_rx_offset(ngtcp2_strm * strm)113 uint64_t ngtcp2_strm_rx_offset(ngtcp2_strm *strm) {
114 if (strm->rx.rob == NULL) {
115 return strm->rx.cont_offset;
116 }
117 return ngtcp2_rob_first_gap_offset(strm->rx.rob);
118 }
119
120 /* strm_rob_heavily_fragmented returns nonzero if the number of gaps
121 in |rob| exceeds the limit. */
strm_rob_heavily_fragmented(ngtcp2_rob * rob)122 static int strm_rob_heavily_fragmented(ngtcp2_rob *rob) {
123 return ngtcp2_ksl_len(&rob->gapksl) >= 1000;
124 }
125
ngtcp2_strm_recv_reordering(ngtcp2_strm * strm,const uint8_t * data,size_t datalen,uint64_t offset)126 int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data,
127 size_t datalen, uint64_t offset) {
128 int rv;
129
130 if (strm->rx.rob == NULL) {
131 rv = strm_rob_init(strm);
132 if (rv != 0) {
133 return rv;
134 }
135
136 if (strm->rx.cont_offset) {
137 rv = ngtcp2_rob_remove_prefix(strm->rx.rob, strm->rx.cont_offset);
138 if (rv != 0) {
139 return rv;
140 }
141 }
142 }
143
144 if (strm_rob_heavily_fragmented(strm->rx.rob)) {
145 return NGTCP2_ERR_INTERNAL;
146 }
147
148 return ngtcp2_rob_push(strm->rx.rob, offset, data, datalen);
149 }
150
ngtcp2_strm_update_rx_offset(ngtcp2_strm * strm,uint64_t offset)151 int ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset) {
152 if (strm->rx.rob == NULL) {
153 strm->rx.cont_offset = offset;
154 return 0;
155 }
156
157 return ngtcp2_rob_remove_prefix(strm->rx.rob, offset);
158 }
159
ngtcp2_strm_shutdown(ngtcp2_strm * strm,uint32_t flags)160 void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) {
161 strm->flags |= flags & NGTCP2_STRM_FLAG_SHUT_RDWR;
162 }
163
strm_streamfrq_init(ngtcp2_strm * strm)164 static int strm_streamfrq_init(ngtcp2_strm *strm) {
165 ngtcp2_ksl *streamfrq = ngtcp2_mem_malloc(strm->mem, sizeof(*streamfrq));
166 if (streamfrq == NULL) {
167 return NGTCP2_ERR_NOMEM;
168 }
169
170 ngtcp2_ksl_init(streamfrq, offset_less, sizeof(uint64_t), strm->mem);
171
172 strm->tx.streamfrq = streamfrq;
173
174 return 0;
175 }
176
ngtcp2_strm_streamfrq_push(ngtcp2_strm * strm,ngtcp2_frame_chain * frc)177 int ngtcp2_strm_streamfrq_push(ngtcp2_strm *strm, ngtcp2_frame_chain *frc) {
178 int rv;
179
180 assert(frc->fr.type == NGTCP2_FRAME_STREAM);
181 assert(frc->next == NULL);
182
183 if (strm->tx.streamfrq == NULL) {
184 rv = strm_streamfrq_init(strm);
185 if (rv != 0) {
186 return rv;
187 }
188 }
189
190 return ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &frc->fr.stream.offset,
191 frc);
192 }
193
strm_streamfrq_unacked_pop(ngtcp2_strm * strm,ngtcp2_frame_chain ** pfrc)194 static int strm_streamfrq_unacked_pop(ngtcp2_strm *strm,
195 ngtcp2_frame_chain **pfrc) {
196 ngtcp2_frame_chain *frc, *nfrc;
197 ngtcp2_stream *fr, *nfr;
198 uint64_t offset, end_offset;
199 size_t idx, end_idx;
200 uint64_t base_offset, end_base_offset;
201 ngtcp2_range gap;
202 ngtcp2_vec *v;
203 int rv;
204 ngtcp2_ksl_it it;
205
206 *pfrc = NULL;
207
208 assert(strm->tx.streamfrq);
209 assert(ngtcp2_ksl_len(strm->tx.streamfrq));
210
211 for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);) {
212 frc = ngtcp2_ksl_it_get(&it);
213 fr = &frc->fr.stream;
214
215 ngtcp2_ksl_remove_hint(strm->tx.streamfrq, &it, &it, &fr->offset);
216
217 idx = 0;
218 offset = fr->offset;
219 base_offset = 0;
220
221 gap = ngtcp2_strm_get_unacked_range_after(strm, offset);
222 if (gap.begin < offset) {
223 gap.begin = offset;
224 }
225
226 for (; idx < fr->datacnt && offset < gap.begin; ++idx) {
227 v = &fr->data[idx];
228 if (offset + v->len > gap.begin) {
229 base_offset = gap.begin - offset;
230 break;
231 }
232
233 offset += v->len;
234 }
235
236 if (idx == fr->datacnt) {
237 if (fr->fin) {
238 if (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) {
239 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
240 assert(ngtcp2_ksl_len(strm->tx.streamfrq) == 0);
241 return 0;
242 }
243
244 fr->offset += ngtcp2_vec_len(fr->data, fr->datacnt);
245 fr->datacnt = 0;
246
247 *pfrc = frc;
248
249 return 0;
250 }
251
252 if (fr->offset == 0 && fr->datacnt == 0 && strm->tx.offset == 0 &&
253 !(strm->flags & NGTCP2_STRM_FLAG_ANY_ACKED)) {
254 *pfrc = frc;
255
256 return 0;
257 }
258
259 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
260 continue;
261 }
262
263 assert(gap.begin == offset + base_offset);
264
265 end_idx = idx;
266 end_offset = offset;
267 end_base_offset = 0;
268
269 for (; end_idx < fr->datacnt; ++end_idx) {
270 v = &fr->data[end_idx];
271 if (end_offset + v->len > gap.end) {
272 end_base_offset = gap.end - end_offset;
273 break;
274 }
275
276 end_offset += v->len;
277 }
278
279 if (fr->offset == offset && base_offset == 0 && fr->datacnt == end_idx) {
280 *pfrc = frc;
281 return 0;
282 }
283
284 if (fr->datacnt == end_idx) {
285 memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
286
287 assert(fr->data[0].len > base_offset);
288
289 fr->offset = offset + base_offset;
290 fr->datacnt = end_idx - idx;
291 fr->data[0].base += base_offset;
292 fr->data[0].len -= (size_t)base_offset;
293
294 *pfrc = frc;
295 return 0;
296 }
297
298 rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new(
299 &nfrc, fr->datacnt - end_idx, strm->frc_objalloc, strm->mem);
300 if (rv != 0) {
301 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
302 return rv;
303 }
304
305 nfr = &nfrc->fr.stream;
306 memcpy(nfr->data, fr->data + end_idx,
307 sizeof(nfr->data[0]) * (fr->datacnt - end_idx));
308
309 assert(nfr->data[0].len > end_base_offset);
310
311 nfr->type = NGTCP2_FRAME_STREAM;
312 nfr->flags = 0;
313 nfr->fin = fr->fin;
314 nfr->stream_id = fr->stream_id;
315 nfr->offset = end_offset + end_base_offset;
316 nfr->datacnt = fr->datacnt - end_idx;
317 nfr->data[0].base += end_base_offset;
318 nfr->data[0].len -= (size_t)end_base_offset;
319
320 rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
321 if (rv != 0) {
322 assert(ngtcp2_err_is_fatal(rv));
323 ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem);
324 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
325 return rv;
326 }
327
328 if (end_base_offset) {
329 ++end_idx;
330 }
331
332 memmove(fr->data, fr->data + idx, sizeof(fr->data[0]) * (end_idx - idx));
333
334 assert(fr->data[0].len > base_offset);
335
336 fr->fin = 0;
337 fr->offset = offset + base_offset;
338 fr->datacnt = end_idx - idx;
339 if (end_base_offset) {
340 assert(fr->data[fr->datacnt - 1].len > end_base_offset);
341 fr->data[fr->datacnt - 1].len = (size_t)end_base_offset;
342 }
343 fr->data[0].base += base_offset;
344 fr->data[0].len -= (size_t)base_offset;
345
346 *pfrc = frc;
347 return 0;
348 }
349
350 return 0;
351 }
352
ngtcp2_strm_streamfrq_pop(ngtcp2_strm * strm,ngtcp2_frame_chain ** pfrc,size_t left)353 int ngtcp2_strm_streamfrq_pop(ngtcp2_strm *strm, ngtcp2_frame_chain **pfrc,
354 size_t left) {
355 ngtcp2_stream *fr, *nfr;
356 ngtcp2_frame_chain *frc, *nfrc;
357 int rv;
358 size_t nmerged;
359 uint64_t datalen;
360 ngtcp2_vec a[NGTCP2_MAX_STREAM_DATACNT];
361 ngtcp2_vec b[NGTCP2_MAX_STREAM_DATACNT];
362 size_t acnt, bcnt;
363 uint64_t unacked_offset;
364
365 if (strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0) {
366 *pfrc = NULL;
367 return 0;
368 }
369
370 rv = strm_streamfrq_unacked_pop(strm, &frc);
371 if (rv != 0) {
372 return rv;
373 }
374 if (frc == NULL) {
375 *pfrc = NULL;
376 return 0;
377 }
378
379 fr = &frc->fr.stream;
380 datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
381
382 if (left == 0) {
383 /* datalen could be zero if 0 length STREAM has been sent */
384 if (datalen || ngtcp2_ksl_len(strm->tx.streamfrq) > 1) {
385 rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &fr->offset, frc);
386 if (rv != 0) {
387 assert(ngtcp2_err_is_fatal(rv));
388 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
389 return rv;
390 }
391 *pfrc = NULL;
392 return 0;
393 }
394 }
395
396 if (datalen > left) {
397 ngtcp2_vec_copy(a, fr->data, fr->datacnt);
398 acnt = fr->datacnt;
399
400 bcnt = 0;
401 ngtcp2_vec_split(a, &acnt, b, &bcnt, left, NGTCP2_MAX_STREAM_DATACNT);
402
403 assert(acnt > 0);
404 assert(bcnt > 0);
405
406 rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new(
407 &nfrc, bcnt, strm->frc_objalloc, strm->mem);
408 if (rv != 0) {
409 assert(ngtcp2_err_is_fatal(rv));
410 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
411 return rv;
412 }
413
414 nfr = &nfrc->fr.stream;
415 nfr->type = NGTCP2_FRAME_STREAM;
416 nfr->flags = 0;
417 nfr->fin = fr->fin;
418 nfr->stream_id = fr->stream_id;
419 nfr->offset = fr->offset + left;
420 nfr->datacnt = bcnt;
421 ngtcp2_vec_copy(nfr->data, b, bcnt);
422
423 rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
424 if (rv != 0) {
425 assert(ngtcp2_err_is_fatal(rv));
426 ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem);
427 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
428 return rv;
429 }
430
431 rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new(
432 &nfrc, acnt, strm->frc_objalloc, strm->mem);
433 if (rv != 0) {
434 assert(ngtcp2_err_is_fatal(rv));
435 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
436 return rv;
437 }
438
439 nfr = &nfrc->fr.stream;
440 *nfr = *fr;
441 nfr->fin = 0;
442 nfr->datacnt = acnt;
443 ngtcp2_vec_copy(nfr->data, a, acnt);
444
445 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
446
447 *pfrc = nfrc;
448
449 return 0;
450 }
451
452 left -= (size_t)datalen;
453
454 ngtcp2_vec_copy(a, fr->data, fr->datacnt);
455 acnt = fr->datacnt;
456
457 for (; left && ngtcp2_ksl_len(strm->tx.streamfrq);) {
458 unacked_offset = ngtcp2_strm_streamfrq_unacked_offset(strm);
459 if (unacked_offset != fr->offset + datalen) {
460 assert(fr->offset + datalen < unacked_offset);
461 break;
462 }
463
464 rv = strm_streamfrq_unacked_pop(strm, &nfrc);
465 if (rv != 0) {
466 assert(ngtcp2_err_is_fatal(rv));
467 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
468 return rv;
469 }
470 if (nfrc == NULL) {
471 break;
472 }
473
474 nfr = &nfrc->fr.stream;
475
476 if (nfr->fin && nfr->datacnt == 0) {
477 fr->fin = 1;
478 ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem);
479 break;
480 }
481
482 nmerged = ngtcp2_vec_merge(a, &acnt, nfr->data, &nfr->datacnt, left,
483 NGTCP2_MAX_STREAM_DATACNT);
484 if (nmerged == 0) {
485 rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
486 if (rv != 0) {
487 assert(ngtcp2_err_is_fatal(rv));
488 ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem);
489 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
490 return rv;
491 }
492 break;
493 }
494
495 datalen += nmerged;
496 left -= nmerged;
497
498 if (nfr->datacnt == 0) {
499 fr->fin = nfr->fin;
500 ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem);
501 continue;
502 }
503
504 nfr->offset += nmerged;
505
506 rv = ngtcp2_ksl_insert(strm->tx.streamfrq, NULL, &nfr->offset, nfrc);
507 if (rv != 0) {
508 ngtcp2_frame_chain_objalloc_del(nfrc, strm->frc_objalloc, strm->mem);
509 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
510 return rv;
511 }
512
513 break;
514 }
515
516 if (acnt == fr->datacnt) {
517 if (acnt > 0) {
518 fr->data[acnt - 1] = a[acnt - 1];
519 }
520
521 *pfrc = frc;
522 return 0;
523 }
524
525 assert(acnt > fr->datacnt);
526
527 rv = ngtcp2_frame_chain_stream_datacnt_objalloc_new(
528 &nfrc, acnt, strm->frc_objalloc, strm->mem);
529 if (rv != 0) {
530 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
531 return rv;
532 }
533
534 nfr = &nfrc->fr.stream;
535 *nfr = *fr;
536 nfr->datacnt = acnt;
537 ngtcp2_vec_copy(nfr->data, a, acnt);
538
539 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
540
541 *pfrc = nfrc;
542
543 return 0;
544 }
545
ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm * strm)546 uint64_t ngtcp2_strm_streamfrq_unacked_offset(ngtcp2_strm *strm) {
547 ngtcp2_frame_chain *frc;
548 ngtcp2_stream *fr;
549 ngtcp2_range gap;
550 ngtcp2_ksl_it it;
551 uint64_t datalen;
552
553 assert(strm->tx.streamfrq);
554 assert(ngtcp2_ksl_len(strm->tx.streamfrq));
555
556 for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
557 ngtcp2_ksl_it_next(&it)) {
558 frc = ngtcp2_ksl_it_get(&it);
559 fr = &frc->fr.stream;
560
561 gap = ngtcp2_strm_get_unacked_range_after(strm, fr->offset);
562
563 datalen = ngtcp2_vec_len(fr->data, fr->datacnt);
564
565 if (gap.begin <= fr->offset) {
566 return fr->offset;
567 }
568 if (gap.begin < fr->offset + datalen) {
569 return gap.begin;
570 }
571 if (fr->offset + datalen == gap.begin && fr->fin &&
572 !(strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED)) {
573 return fr->offset + datalen;
574 }
575 }
576
577 return (uint64_t)-1;
578 }
579
ngtcp2_strm_streamfrq_top(ngtcp2_strm * strm)580 ngtcp2_frame_chain *ngtcp2_strm_streamfrq_top(ngtcp2_strm *strm) {
581 ngtcp2_ksl_it it;
582
583 assert(strm->tx.streamfrq);
584 assert(ngtcp2_ksl_len(strm->tx.streamfrq));
585
586 it = ngtcp2_ksl_begin(strm->tx.streamfrq);
587 return ngtcp2_ksl_it_get(&it);
588 }
589
ngtcp2_strm_streamfrq_empty(ngtcp2_strm * strm)590 int ngtcp2_strm_streamfrq_empty(ngtcp2_strm *strm) {
591 return strm->tx.streamfrq == NULL || ngtcp2_ksl_len(strm->tx.streamfrq) == 0;
592 }
593
ngtcp2_strm_streamfrq_clear(ngtcp2_strm * strm)594 void ngtcp2_strm_streamfrq_clear(ngtcp2_strm *strm) {
595 ngtcp2_frame_chain *frc;
596 ngtcp2_ksl_it it;
597
598 if (strm->tx.streamfrq == NULL) {
599 return;
600 }
601
602 for (it = ngtcp2_ksl_begin(strm->tx.streamfrq); !ngtcp2_ksl_it_end(&it);
603 ngtcp2_ksl_it_next(&it)) {
604 frc = ngtcp2_ksl_it_get(&it);
605 ngtcp2_frame_chain_objalloc_del(frc, strm->frc_objalloc, strm->mem);
606 }
607 ngtcp2_ksl_clear(strm->tx.streamfrq);
608 }
609
ngtcp2_strm_is_tx_queued(ngtcp2_strm * strm)610 int ngtcp2_strm_is_tx_queued(ngtcp2_strm *strm) {
611 return strm->pe.index != NGTCP2_PQ_BAD_INDEX;
612 }
613
ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm * strm)614 int ngtcp2_strm_is_all_tx_data_acked(ngtcp2_strm *strm) {
615 if (strm->tx.acked_offset == NULL) {
616 return strm->tx.cont_acked_offset == strm->tx.offset;
617 }
618
619 return ngtcp2_gaptr_first_gap_offset(strm->tx.acked_offset) ==
620 strm->tx.offset;
621 }
622
ngtcp2_strm_is_all_tx_data_fin_acked(ngtcp2_strm * strm)623 int ngtcp2_strm_is_all_tx_data_fin_acked(ngtcp2_strm *strm) {
624 return (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) &&
625 ngtcp2_strm_is_all_tx_data_acked(strm);
626 }
627
ngtcp2_strm_get_unacked_range_after(ngtcp2_strm * strm,uint64_t offset)628 ngtcp2_range ngtcp2_strm_get_unacked_range_after(ngtcp2_strm *strm,
629 uint64_t offset) {
630 ngtcp2_range gap;
631
632 if (strm->tx.acked_offset == NULL) {
633 gap.begin = strm->tx.cont_acked_offset;
634 gap.end = UINT64_MAX;
635 return gap;
636 }
637
638 return ngtcp2_gaptr_get_first_gap_after(strm->tx.acked_offset, offset);
639 }
640
ngtcp2_strm_get_acked_offset(ngtcp2_strm * strm)641 uint64_t ngtcp2_strm_get_acked_offset(ngtcp2_strm *strm) {
642 if (strm->tx.acked_offset == NULL) {
643 return strm->tx.cont_acked_offset;
644 }
645
646 return ngtcp2_gaptr_first_gap_offset(strm->tx.acked_offset);
647 }
648
strm_acked_offset_init(ngtcp2_strm * strm)649 static int strm_acked_offset_init(ngtcp2_strm *strm) {
650 ngtcp2_gaptr *acked_offset =
651 ngtcp2_mem_malloc(strm->mem, sizeof(*acked_offset));
652
653 if (acked_offset == NULL) {
654 return NGTCP2_ERR_NOMEM;
655 }
656
657 ngtcp2_gaptr_init(acked_offset, strm->mem);
658
659 strm->tx.acked_offset = acked_offset;
660
661 return 0;
662 }
663
ngtcp2_strm_ack_data(ngtcp2_strm * strm,uint64_t offset,uint64_t len)664 int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len) {
665 int rv;
666
667 if (strm->tx.acked_offset == NULL) {
668 if (strm->tx.cont_acked_offset == offset) {
669 strm->tx.cont_acked_offset += len;
670 return 0;
671 }
672
673 rv = strm_acked_offset_init(strm);
674 if (rv != 0) {
675 return rv;
676 }
677
678 rv =
679 ngtcp2_gaptr_push(strm->tx.acked_offset, 0, strm->tx.cont_acked_offset);
680 if (rv != 0) {
681 return rv;
682 }
683 }
684
685 return ngtcp2_gaptr_push(strm->tx.acked_offset, offset, len);
686 }
687
ngtcp2_strm_set_app_error_code(ngtcp2_strm * strm,uint64_t app_error_code)688 void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm,
689 uint64_t app_error_code) {
690 if (strm->flags & NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET) {
691 return;
692 }
693
694 assert(0 == strm->app_error_code);
695
696 strm->flags |= NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET;
697 strm->app_error_code = app_error_code;
698 }
699