• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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