11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * nghttp2 - HTTP/2 C Library
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Copyright (c) 2014 Tatsuhiro Tsujikawa
51cb0ef41Sopenharmony_ci *
61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
71cb0ef41Sopenharmony_ci * a copy of this software and associated documentation files (the
81cb0ef41Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
91cb0ef41Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
101cb0ef41Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
111cb0ef41Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
121cb0ef41Sopenharmony_ci * the following conditions:
131cb0ef41Sopenharmony_ci *
141cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be
151cb0ef41Sopenharmony_ci * included in all copies or substantial portions of the Software.
161cb0ef41Sopenharmony_ci *
171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
181cb0ef41Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
191cb0ef41Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
201cb0ef41Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
211cb0ef41Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
221cb0ef41Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
231cb0ef41Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
241cb0ef41Sopenharmony_ci */
251cb0ef41Sopenharmony_ci#include "nghttp2_buf.h"
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#include <stdio.h>
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include "nghttp2_helper.h"
301cb0ef41Sopenharmony_ci#include "nghttp2_debug.h"
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_civoid nghttp2_buf_init(nghttp2_buf *buf) {
331cb0ef41Sopenharmony_ci  buf->begin = NULL;
341cb0ef41Sopenharmony_ci  buf->end = NULL;
351cb0ef41Sopenharmony_ci  buf->pos = NULL;
361cb0ef41Sopenharmony_ci  buf->last = NULL;
371cb0ef41Sopenharmony_ci  buf->mark = NULL;
381cb0ef41Sopenharmony_ci}
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciint nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) {
411cb0ef41Sopenharmony_ci  nghttp2_buf_init(buf);
421cb0ef41Sopenharmony_ci  return nghttp2_buf_reserve(buf, initial, mem);
431cb0ef41Sopenharmony_ci}
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_civoid nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) {
461cb0ef41Sopenharmony_ci  if (buf == NULL) {
471cb0ef41Sopenharmony_ci    return;
481cb0ef41Sopenharmony_ci  }
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  nghttp2_mem_free(mem, buf->begin);
511cb0ef41Sopenharmony_ci  buf->begin = NULL;
521cb0ef41Sopenharmony_ci}
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciint nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
551cb0ef41Sopenharmony_ci  uint8_t *ptr;
561cb0ef41Sopenharmony_ci  size_t cap;
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  cap = nghttp2_buf_cap(buf);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  if (cap >= new_cap) {
611cb0ef41Sopenharmony_ci    return 0;
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  new_cap = nghttp2_max(new_cap, cap * 2);
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
671cb0ef41Sopenharmony_ci  if (ptr == NULL) {
681cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_NOMEM;
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  buf->pos = ptr + (buf->pos - buf->begin);
721cb0ef41Sopenharmony_ci  buf->last = ptr + (buf->last - buf->begin);
731cb0ef41Sopenharmony_ci  buf->mark = ptr + (buf->mark - buf->begin);
741cb0ef41Sopenharmony_ci  buf->begin = ptr;
751cb0ef41Sopenharmony_ci  buf->end = ptr + new_cap;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  return 0;
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_civoid nghttp2_buf_reset(nghttp2_buf *buf) {
811cb0ef41Sopenharmony_ci  buf->pos = buf->last = buf->mark = buf->begin;
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_civoid nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
851cb0ef41Sopenharmony_ci  buf->begin = buf->pos = buf->last = buf->mark = buf->end = begin;
861cb0ef41Sopenharmony_ci  if (len) {
871cb0ef41Sopenharmony_ci    buf->end += len;
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_cistatic int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length,
921cb0ef41Sopenharmony_ci                         nghttp2_mem *mem) {
931cb0ef41Sopenharmony_ci  int rv;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  *chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
961cb0ef41Sopenharmony_ci  if (*chain == NULL) {
971cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_NOMEM;
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  (*chain)->next = NULL;
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem);
1031cb0ef41Sopenharmony_ci  if (rv != 0) {
1041cb0ef41Sopenharmony_ci    nghttp2_mem_free(mem, *chain);
1051cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_NOMEM;
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  return 0;
1091cb0ef41Sopenharmony_ci}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_cistatic void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) {
1121cb0ef41Sopenharmony_ci  nghttp2_buf_free(&chain->buf, mem);
1131cb0ef41Sopenharmony_ci  nghttp2_mem_free(mem, chain);
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ciint nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
1171cb0ef41Sopenharmony_ci                      nghttp2_mem *mem) {
1181cb0ef41Sopenharmony_ci  return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem);
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ciint nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
1221cb0ef41Sopenharmony_ci                       size_t max_chunk, size_t offset, nghttp2_mem *mem) {
1231cb0ef41Sopenharmony_ci  return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset,
1241cb0ef41Sopenharmony_ci                            mem);
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ciint nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
1281cb0ef41Sopenharmony_ci                       size_t max_chunk, size_t chunk_keep, size_t offset,
1291cb0ef41Sopenharmony_ci                       nghttp2_mem *mem) {
1301cb0ef41Sopenharmony_ci  int rv;
1311cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
1341cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_INVALID_ARGUMENT;
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  rv = buf_chain_new(&chain, chunk_length, mem);
1381cb0ef41Sopenharmony_ci  if (rv != 0) {
1391cb0ef41Sopenharmony_ci    return rv;
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  bufs->mem = mem;
1431cb0ef41Sopenharmony_ci  bufs->offset = offset;
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  bufs->head = chain;
1461cb0ef41Sopenharmony_ci  bufs->cur = bufs->head;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  nghttp2_buf_shift_right(&bufs->cur->buf, offset);
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  bufs->chunk_length = chunk_length;
1511cb0ef41Sopenharmony_ci  bufs->chunk_used = 1;
1521cb0ef41Sopenharmony_ci  bufs->max_chunk = max_chunk;
1531cb0ef41Sopenharmony_ci  bufs->chunk_keep = chunk_keep;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  return 0;
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciint nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
1591cb0ef41Sopenharmony_ci  int rv;
1601cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  if (chunk_length < bufs->offset) {
1631cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_INVALID_ARGUMENT;
1641cb0ef41Sopenharmony_ci  }
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  rv = buf_chain_new(&chain, chunk_length, bufs->mem);
1671cb0ef41Sopenharmony_ci  if (rv != 0) {
1681cb0ef41Sopenharmony_ci    return rv;
1691cb0ef41Sopenharmony_ci  }
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  nghttp2_bufs_free(bufs);
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  bufs->head = chain;
1741cb0ef41Sopenharmony_ci  bufs->cur = bufs->head;
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  bufs->chunk_length = chunk_length;
1791cb0ef41Sopenharmony_ci  bufs->chunk_used = 1;
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  return 0;
1821cb0ef41Sopenharmony_ci}
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_civoid nghttp2_bufs_free(nghttp2_bufs *bufs) {
1851cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain, *next_chain;
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  if (bufs == NULL) {
1881cb0ef41Sopenharmony_ci    return;
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  for (chain = bufs->head; chain;) {
1921cb0ef41Sopenharmony_ci    next_chain = chain->next;
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci    buf_chain_del(chain, bufs->mem);
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci    chain = next_chain;
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  bufs->head = NULL;
2001cb0ef41Sopenharmony_ci}
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ciint nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
2031cb0ef41Sopenharmony_ci                           nghttp2_mem *mem) {
2041cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
2071cb0ef41Sopenharmony_ci  if (chain == NULL) {
2081cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_NOMEM;
2091cb0ef41Sopenharmony_ci  }
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  chain->next = NULL;
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  nghttp2_buf_wrap_init(&chain->buf, begin, len);
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  bufs->mem = mem;
2161cb0ef41Sopenharmony_ci  bufs->offset = 0;
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  bufs->head = chain;
2191cb0ef41Sopenharmony_ci  bufs->cur = bufs->head;
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  bufs->chunk_length = len;
2221cb0ef41Sopenharmony_ci  bufs->chunk_used = 1;
2231cb0ef41Sopenharmony_ci  bufs->max_chunk = 1;
2241cb0ef41Sopenharmony_ci  bufs->chunk_keep = 1;
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  return 0;
2271cb0ef41Sopenharmony_ci}
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ciint nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
2301cb0ef41Sopenharmony_ci                            size_t veclen, nghttp2_mem *mem) {
2311cb0ef41Sopenharmony_ci  size_t i = 0;
2321cb0ef41Sopenharmony_ci  nghttp2_buf_chain *cur_chain;
2331cb0ef41Sopenharmony_ci  nghttp2_buf_chain *head_chain;
2341cb0ef41Sopenharmony_ci  nghttp2_buf_chain **dst_chain = &head_chain;
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  if (veclen == 0) {
2371cb0ef41Sopenharmony_ci    return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem);
2381cb0ef41Sopenharmony_ci  }
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
2411cb0ef41Sopenharmony_ci  if (head_chain == NULL) {
2421cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_NOMEM;
2431cb0ef41Sopenharmony_ci  }
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  for (i = 0; i < veclen; ++i) {
2461cb0ef41Sopenharmony_ci    cur_chain = &head_chain[i];
2471cb0ef41Sopenharmony_ci    cur_chain->next = NULL;
2481cb0ef41Sopenharmony_ci    nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci    *dst_chain = cur_chain;
2511cb0ef41Sopenharmony_ci    dst_chain = &cur_chain->next;
2521cb0ef41Sopenharmony_ci  }
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  bufs->mem = mem;
2551cb0ef41Sopenharmony_ci  bufs->offset = 0;
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci  bufs->head = head_chain;
2581cb0ef41Sopenharmony_ci  bufs->cur = bufs->head;
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  /* We don't use chunk_length since no allocation is expected. */
2611cb0ef41Sopenharmony_ci  bufs->chunk_length = 0;
2621cb0ef41Sopenharmony_ci  bufs->chunk_used = veclen;
2631cb0ef41Sopenharmony_ci  bufs->max_chunk = veclen;
2641cb0ef41Sopenharmony_ci  bufs->chunk_keep = veclen;
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_ci  return 0;
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_civoid nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
2701cb0ef41Sopenharmony_ci  if (bufs == NULL) {
2711cb0ef41Sopenharmony_ci    return;
2721cb0ef41Sopenharmony_ci  }
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  if (bufs->head) {
2751cb0ef41Sopenharmony_ci    nghttp2_mem_free(bufs->mem, bufs->head);
2761cb0ef41Sopenharmony_ci  }
2771cb0ef41Sopenharmony_ci}
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_civoid nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
2801cb0ef41Sopenharmony_ci  nghttp2_buf_chain *ci;
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci  for (ci = bufs->cur; ci; ci = ci->next) {
2831cb0ef41Sopenharmony_ci    if (nghttp2_buf_len(&ci->buf) == 0) {
2841cb0ef41Sopenharmony_ci      return;
2851cb0ef41Sopenharmony_ci    } else {
2861cb0ef41Sopenharmony_ci      bufs->cur = ci;
2871cb0ef41Sopenharmony_ci    }
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci}
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_cisize_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
2921cb0ef41Sopenharmony_ci  nghttp2_buf_chain *ci;
2931cb0ef41Sopenharmony_ci  size_t len;
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  len = 0;
2961cb0ef41Sopenharmony_ci  for (ci = bufs->head; ci; ci = ci->next) {
2971cb0ef41Sopenharmony_ci    len += nghttp2_buf_len(&ci->buf);
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  return len;
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_cistatic int bufs_alloc_chain(nghttp2_bufs *bufs) {
3041cb0ef41Sopenharmony_ci  int rv;
3051cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  if (bufs->cur->next) {
3081cb0ef41Sopenharmony_ci    bufs->cur = bufs->cur->next;
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci    return 0;
3111cb0ef41Sopenharmony_ci  }
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci  if (bufs->max_chunk == bufs->chunk_used) {
3141cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_BUFFER_ERROR;
3151cb0ef41Sopenharmony_ci  }
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem);
3181cb0ef41Sopenharmony_ci  if (rv != 0) {
3191cb0ef41Sopenharmony_ci    return rv;
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",
3231cb0ef41Sopenharmony_ci         bufs->chunk_length, bufs, bufs->chunk_used);
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci  ++bufs->chunk_used;
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci  bufs->cur->next = chain;
3281cb0ef41Sopenharmony_ci  bufs->cur = chain;
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci  return 0;
3331cb0ef41Sopenharmony_ci}
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ciint nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
3361cb0ef41Sopenharmony_ci  int rv;
3371cb0ef41Sopenharmony_ci  size_t nwrite;
3381cb0ef41Sopenharmony_ci  nghttp2_buf *buf;
3391cb0ef41Sopenharmony_ci  const uint8_t *p;
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  p = data;
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  while (len) {
3441cb0ef41Sopenharmony_ci    buf = &bufs->cur->buf;
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci    nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
3471cb0ef41Sopenharmony_ci    if (nwrite == 0) {
3481cb0ef41Sopenharmony_ci      rv = bufs_alloc_chain(bufs);
3491cb0ef41Sopenharmony_ci      if (rv != 0) {
3501cb0ef41Sopenharmony_ci        return rv;
3511cb0ef41Sopenharmony_ci      }
3521cb0ef41Sopenharmony_ci      continue;
3531cb0ef41Sopenharmony_ci    }
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci    buf->last = nghttp2_cpymem(buf->last, p, nwrite);
3561cb0ef41Sopenharmony_ci    p += nwrite;
3571cb0ef41Sopenharmony_ci    len -= nwrite;
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  return 0;
3611cb0ef41Sopenharmony_ci}
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_cistatic int bufs_ensure_addb(nghttp2_bufs *bufs) {
3641cb0ef41Sopenharmony_ci  int rv;
3651cb0ef41Sopenharmony_ci  nghttp2_buf *buf;
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci  buf = &bufs->cur->buf;
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci  if (nghttp2_buf_avail(buf) > 0) {
3701cb0ef41Sopenharmony_ci    return 0;
3711cb0ef41Sopenharmony_ci  }
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  rv = bufs_alloc_chain(bufs);
3741cb0ef41Sopenharmony_ci  if (rv != 0) {
3751cb0ef41Sopenharmony_ci    return rv;
3761cb0ef41Sopenharmony_ci  }
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  return 0;
3791cb0ef41Sopenharmony_ci}
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ciint nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
3821cb0ef41Sopenharmony_ci  int rv;
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  rv = bufs_ensure_addb(bufs);
3851cb0ef41Sopenharmony_ci  if (rv != 0) {
3861cb0ef41Sopenharmony_ci    return rv;
3871cb0ef41Sopenharmony_ci  }
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  *bufs->cur->buf.last++ = b;
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  return 0;
3921cb0ef41Sopenharmony_ci}
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ciint nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
3951cb0ef41Sopenharmony_ci  int rv;
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci  rv = bufs_ensure_addb(bufs);
3981cb0ef41Sopenharmony_ci  if (rv != 0) {
3991cb0ef41Sopenharmony_ci    return rv;
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  *bufs->cur->buf.last = b;
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  return 0;
4051cb0ef41Sopenharmony_ci}
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ciint nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
4081cb0ef41Sopenharmony_ci  int rv;
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ci  rv = bufs_ensure_addb(bufs);
4111cb0ef41Sopenharmony_ci  if (rv != 0) {
4121cb0ef41Sopenharmony_ci    return rv;
4131cb0ef41Sopenharmony_ci  }
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci  *bufs->cur->buf.last++ |= b;
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci  return 0;
4181cb0ef41Sopenharmony_ci}
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ciint nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
4211cb0ef41Sopenharmony_ci  int rv;
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  rv = bufs_ensure_addb(bufs);
4241cb0ef41Sopenharmony_ci  if (rv != 0) {
4251cb0ef41Sopenharmony_ci    return rv;
4261cb0ef41Sopenharmony_ci  }
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci  *bufs->cur->buf.last |= b;
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  return 0;
4311cb0ef41Sopenharmony_ci}
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_cissize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
4341cb0ef41Sopenharmony_ci  size_t len;
4351cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
4361cb0ef41Sopenharmony_ci  nghttp2_buf *buf;
4371cb0ef41Sopenharmony_ci  uint8_t *res;
4381cb0ef41Sopenharmony_ci  nghttp2_buf resbuf;
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci  len = 0;
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci  for (chain = bufs->head; chain; chain = chain->next) {
4431cb0ef41Sopenharmony_ci    len += nghttp2_buf_len(&chain->buf);
4441cb0ef41Sopenharmony_ci  }
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ci  if (len == 0) {
4471cb0ef41Sopenharmony_ci    res = NULL;
4481cb0ef41Sopenharmony_ci    return 0;
4491cb0ef41Sopenharmony_ci  }
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  res = nghttp2_mem_malloc(bufs->mem, len);
4521cb0ef41Sopenharmony_ci  if (res == NULL) {
4531cb0ef41Sopenharmony_ci    return NGHTTP2_ERR_NOMEM;
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  nghttp2_buf_wrap_init(&resbuf, res, len);
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  for (chain = bufs->head; chain; chain = chain->next) {
4591cb0ef41Sopenharmony_ci    buf = &chain->buf;
4601cb0ef41Sopenharmony_ci    resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
4611cb0ef41Sopenharmony_ci  }
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci  *out = res;
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  return (ssize_t)len;
4661cb0ef41Sopenharmony_ci}
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_cisize_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
4691cb0ef41Sopenharmony_ci  size_t len;
4701cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
4711cb0ef41Sopenharmony_ci  nghttp2_buf *buf;
4721cb0ef41Sopenharmony_ci  nghttp2_buf resbuf;
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci  len = nghttp2_bufs_len(bufs);
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci  nghttp2_buf_wrap_init(&resbuf, out, len);
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  for (chain = bufs->head; chain; chain = chain->next) {
4791cb0ef41Sopenharmony_ci    buf = &chain->buf;
4801cb0ef41Sopenharmony_ci    resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
4811cb0ef41Sopenharmony_ci  }
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci  return len;
4841cb0ef41Sopenharmony_ci}
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_civoid nghttp2_bufs_reset(nghttp2_bufs *bufs) {
4871cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain, *ci;
4881cb0ef41Sopenharmony_ci  size_t k;
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci  k = bufs->chunk_keep;
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  for (ci = bufs->head; ci; ci = ci->next) {
4931cb0ef41Sopenharmony_ci    nghttp2_buf_reset(&ci->buf);
4941cb0ef41Sopenharmony_ci    nghttp2_buf_shift_right(&ci->buf, bufs->offset);
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci    if (--k == 0) {
4971cb0ef41Sopenharmony_ci      break;
4981cb0ef41Sopenharmony_ci    }
4991cb0ef41Sopenharmony_ci  }
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci  if (ci) {
5021cb0ef41Sopenharmony_ci    chain = ci->next;
5031cb0ef41Sopenharmony_ci    ci->next = NULL;
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci    for (ci = chain; ci;) {
5061cb0ef41Sopenharmony_ci      chain = ci->next;
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci      buf_chain_del(ci, bufs->mem);
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci      ci = chain;
5111cb0ef41Sopenharmony_ci    }
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_ci    bufs->chunk_used = bufs->chunk_keep;
5141cb0ef41Sopenharmony_ci  }
5151cb0ef41Sopenharmony_ci
5161cb0ef41Sopenharmony_ci  bufs->cur = bufs->head;
5171cb0ef41Sopenharmony_ci}
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_ciint nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ciint nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
5221cb0ef41Sopenharmony_ci  nghttp2_buf_chain *chain;
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  chain = bufs->cur->next;
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci  return chain && nghttp2_buf_len(&chain->buf);
5271cb0ef41Sopenharmony_ci}
528