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