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