11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * nghttp2 - HTTP/2 C Library
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Copyright (c) 2012 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_stream.h"
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#include <assert.h>
281cb0ef41Sopenharmony_ci#include <stdio.h>
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#include "nghttp2_session.h"
311cb0ef41Sopenharmony_ci#include "nghttp2_helper.h"
321cb0ef41Sopenharmony_ci#include "nghttp2_debug.h"
331cb0ef41Sopenharmony_ci#include "nghttp2_frame.h"
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci/* Maximum distance between any two stream's cycle in the same
361cb0ef41Sopenharmony_ci   priority queue.  Imagine stream A's cycle is A, and stream B's
371cb0ef41Sopenharmony_ci   cycle is B, and A < B.  The cycle is unsigned 32 bit integer, it
381cb0ef41Sopenharmony_ci   may get overflow.  Because of how we calculate the next cycle
391cb0ef41Sopenharmony_ci   value, if B - A is less than or equals to
401cb0ef41Sopenharmony_ci   NGHTTP2_MAX_CYCLE_DISTANCE, A and B are in the same scale, in other
411cb0ef41Sopenharmony_ci   words, B is really greater than or equal to A.  Otherwise, A is a
421cb0ef41Sopenharmony_ci   result of overflow, and it is actually A > B if we consider that
431cb0ef41Sopenharmony_ci   fact. */
441cb0ef41Sopenharmony_ci#define NGHTTP2_MAX_CYCLE_DISTANCE                                             \
451cb0ef41Sopenharmony_ci  ((uint64_t)NGHTTP2_MAX_FRAME_SIZE_MAX * 256 + 255)
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_cistatic int stream_less(const void *lhsx, const void *rhsx) {
481cb0ef41Sopenharmony_ci  const nghttp2_stream *lhs, *rhs;
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry);
511cb0ef41Sopenharmony_ci  rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  if (lhs->cycle == rhs->cycle) {
541cb0ef41Sopenharmony_ci    return lhs->seq < rhs->seq;
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
581cb0ef41Sopenharmony_ci}
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_civoid nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
611cb0ef41Sopenharmony_ci                         uint8_t flags, nghttp2_stream_state initial_state,
621cb0ef41Sopenharmony_ci                         int32_t weight, int32_t remote_initial_window_size,
631cb0ef41Sopenharmony_ci                         int32_t local_initial_window_size,
641cb0ef41Sopenharmony_ci                         void *stream_user_data, nghttp2_mem *mem) {
651cb0ef41Sopenharmony_ci  nghttp2_pq_init(&stream->obq, stream_less, mem);
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  stream->stream_id = stream_id;
681cb0ef41Sopenharmony_ci  stream->flags = flags;
691cb0ef41Sopenharmony_ci  stream->state = initial_state;
701cb0ef41Sopenharmony_ci  stream->shut_flags = NGHTTP2_SHUT_NONE;
711cb0ef41Sopenharmony_ci  stream->stream_user_data = stream_user_data;
721cb0ef41Sopenharmony_ci  stream->item = NULL;
731cb0ef41Sopenharmony_ci  stream->remote_window_size = remote_initial_window_size;
741cb0ef41Sopenharmony_ci  stream->local_window_size = local_initial_window_size;
751cb0ef41Sopenharmony_ci  stream->recv_window_size = 0;
761cb0ef41Sopenharmony_ci  stream->consumed_size = 0;
771cb0ef41Sopenharmony_ci  stream->recv_reduction = 0;
781cb0ef41Sopenharmony_ci  stream->window_update_queued = 0;
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  stream->dep_prev = NULL;
811cb0ef41Sopenharmony_ci  stream->dep_next = NULL;
821cb0ef41Sopenharmony_ci  stream->sib_prev = NULL;
831cb0ef41Sopenharmony_ci  stream->sib_next = NULL;
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  stream->closed_prev = NULL;
861cb0ef41Sopenharmony_ci  stream->closed_next = NULL;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  stream->weight = weight;
891cb0ef41Sopenharmony_ci  stream->sum_dep_weight = 0;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
921cb0ef41Sopenharmony_ci  stream->content_length = -1;
931cb0ef41Sopenharmony_ci  stream->recv_content_length = 0;
941cb0ef41Sopenharmony_ci  stream->status_code = -1;
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  stream->queued = 0;
971cb0ef41Sopenharmony_ci  stream->descendant_last_cycle = 0;
981cb0ef41Sopenharmony_ci  stream->cycle = 0;
991cb0ef41Sopenharmony_ci  stream->pending_penalty = 0;
1001cb0ef41Sopenharmony_ci  stream->descendant_next_seq = 0;
1011cb0ef41Sopenharmony_ci  stream->seq = 0;
1021cb0ef41Sopenharmony_ci  stream->last_writelen = 0;
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  stream->extpri = stream->http_extpri = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_civoid nghttp2_stream_free(nghttp2_stream *stream) {
1081cb0ef41Sopenharmony_ci  nghttp2_pq_free(&stream->obq);
1091cb0ef41Sopenharmony_ci  /* We don't free stream->item.  If it is assigned to aob, then
1101cb0ef41Sopenharmony_ci     active_outbound_item_reset() will delete it.  Otherwise,
1111cb0ef41Sopenharmony_ci     nghttp2_stream_close() or session_del() will delete it. */
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_civoid nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
1151cb0ef41Sopenharmony_ci  stream->shut_flags = (uint8_t)(stream->shut_flags | flag);
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci/*
1191cb0ef41Sopenharmony_ci * Returns nonzero if |stream| is active.  This function does not take
1201cb0ef41Sopenharmony_ci * into account its descendants.
1211cb0ef41Sopenharmony_ci */
1221cb0ef41Sopenharmony_cistatic int stream_active(nghttp2_stream *stream) {
1231cb0ef41Sopenharmony_ci  return stream->item &&
1241cb0ef41Sopenharmony_ci         (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0;
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci/*
1281cb0ef41Sopenharmony_ci * Returns nonzero if |stream| or one of its descendants is active
1291cb0ef41Sopenharmony_ci */
1301cb0ef41Sopenharmony_cistatic int stream_subtree_active(nghttp2_stream *stream) {
1311cb0ef41Sopenharmony_ci  return stream_active(stream) || !nghttp2_pq_empty(&stream->obq);
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci/*
1351cb0ef41Sopenharmony_ci * Returns next cycle for |stream|.
1361cb0ef41Sopenharmony_ci */
1371cb0ef41Sopenharmony_cistatic void stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) {
1381cb0ef41Sopenharmony_ci  uint64_t penalty;
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT +
1411cb0ef41Sopenharmony_ci            stream->pending_penalty;
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
1441cb0ef41Sopenharmony_ci  stream->pending_penalty = (uint32_t)(penalty % (uint32_t)stream->weight);
1451cb0ef41Sopenharmony_ci}
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cistatic int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
1481cb0ef41Sopenharmony_ci  int rv;
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  for (; dep_stream && !stream->queued;
1511cb0ef41Sopenharmony_ci       stream = dep_stream, dep_stream = dep_stream->dep_prev) {
1521cb0ef41Sopenharmony_ci    stream_next_cycle(stream, dep_stream->descendant_last_cycle);
1531cb0ef41Sopenharmony_ci    stream->seq = dep_stream->descendant_next_seq++;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci    DEBUGF("stream: stream=%d obq push cycle=%lu\n", stream->stream_id,
1561cb0ef41Sopenharmony_ci           stream->cycle);
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci    DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id,
1591cb0ef41Sopenharmony_ci           dep_stream->stream_id);
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci    rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
1621cb0ef41Sopenharmony_ci    if (rv != 0) {
1631cb0ef41Sopenharmony_ci      return rv;
1641cb0ef41Sopenharmony_ci    }
1651cb0ef41Sopenharmony_ci    stream->queued = 1;
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci  return 0;
1691cb0ef41Sopenharmony_ci}
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci/*
1721cb0ef41Sopenharmony_ci * Removes |stream| from parent's obq.  If removal of |stream| makes
1731cb0ef41Sopenharmony_ci * parent's obq empty, and parent is not active, then parent is also
1741cb0ef41Sopenharmony_ci * removed.  This process is repeated recursively.
1751cb0ef41Sopenharmony_ci */
1761cb0ef41Sopenharmony_cistatic void stream_obq_remove(nghttp2_stream *stream) {
1771cb0ef41Sopenharmony_ci  nghttp2_stream *dep_stream;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  dep_stream = stream->dep_prev;
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  if (!stream->queued) {
1821cb0ef41Sopenharmony_ci    return;
1831cb0ef41Sopenharmony_ci  }
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
1861cb0ef41Sopenharmony_ci    DEBUGF("stream: remove stream %d from stream %d\n", stream->stream_id,
1871cb0ef41Sopenharmony_ci           dep_stream->stream_id);
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci    nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci    assert(stream->queued);
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci    stream->queued = 0;
1941cb0ef41Sopenharmony_ci    stream->cycle = 0;
1951cb0ef41Sopenharmony_ci    stream->pending_penalty = 0;
1961cb0ef41Sopenharmony_ci    stream->descendant_last_cycle = 0;
1971cb0ef41Sopenharmony_ci    stream->last_writelen = 0;
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci    if (stream_subtree_active(dep_stream)) {
2001cb0ef41Sopenharmony_ci      return;
2011cb0ef41Sopenharmony_ci    }
2021cb0ef41Sopenharmony_ci  }
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci/*
2061cb0ef41Sopenharmony_ci * Moves |stream| from |src|'s obq to |dest|'s obq.  Removal from
2071cb0ef41Sopenharmony_ci * |src|'s obq is just done calling nghttp2_pq_remove(), so it does
2081cb0ef41Sopenharmony_ci * not recursively remove |src| and ancestors, like
2091cb0ef41Sopenharmony_ci * stream_obq_remove().
2101cb0ef41Sopenharmony_ci */
2111cb0ef41Sopenharmony_cistatic int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src,
2121cb0ef41Sopenharmony_ci                           nghttp2_stream *stream) {
2131cb0ef41Sopenharmony_ci  if (!stream->queued) {
2141cb0ef41Sopenharmony_ci    return 0;
2151cb0ef41Sopenharmony_ci  }
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  DEBUGF("stream: remove stream %d from stream %d (move)\n", stream->stream_id,
2181cb0ef41Sopenharmony_ci         src->stream_id);
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  nghttp2_pq_remove(&src->obq, &stream->pq_entry);
2211cb0ef41Sopenharmony_ci  stream->queued = 0;
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  return stream_obq_push(dest, stream);
2241cb0ef41Sopenharmony_ci}
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_civoid nghttp2_stream_reschedule(nghttp2_stream *stream) {
2271cb0ef41Sopenharmony_ci  nghttp2_stream *dep_stream;
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  assert(stream->queued);
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  dep_stream = stream->dep_prev;
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
2341cb0ef41Sopenharmony_ci    nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci    stream_next_cycle(stream, dep_stream->descendant_last_cycle);
2371cb0ef41Sopenharmony_ci    stream->seq = dep_stream->descendant_next_seq++;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci    nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci    DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
2421cb0ef41Sopenharmony_ci           stream->cycle);
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci    dep_stream->last_writelen = stream->last_writelen;
2451cb0ef41Sopenharmony_ci  }
2461cb0ef41Sopenharmony_ci}
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_civoid nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
2491cb0ef41Sopenharmony_ci  nghttp2_stream *dep_stream;
2501cb0ef41Sopenharmony_ci  uint64_t last_cycle;
2511cb0ef41Sopenharmony_ci  int32_t old_weight;
2521cb0ef41Sopenharmony_ci  uint64_t wlen_penalty;
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  if (stream->weight == weight) {
2551cb0ef41Sopenharmony_ci    return;
2561cb0ef41Sopenharmony_ci  }
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  old_weight = stream->weight;
2591cb0ef41Sopenharmony_ci  stream->weight = weight;
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  dep_stream = stream->dep_prev;
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  if (!dep_stream) {
2641cb0ef41Sopenharmony_ci    return;
2651cb0ef41Sopenharmony_ci  }
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  dep_stream->sum_dep_weight += weight - old_weight;
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci  if (!stream->queued) {
2701cb0ef41Sopenharmony_ci    return;
2711cb0ef41Sopenharmony_ci  }
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci  nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  wlen_penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT;
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  /* Compute old stream->pending_penalty we used to calculate
2781cb0ef41Sopenharmony_ci     stream->cycle */
2791cb0ef41Sopenharmony_ci  stream->pending_penalty =
2801cb0ef41Sopenharmony_ci      (uint32_t)((stream->pending_penalty + (uint32_t)old_weight -
2811cb0ef41Sopenharmony_ci                  (wlen_penalty % (uint32_t)old_weight)) %
2821cb0ef41Sopenharmony_ci                 (uint32_t)old_weight);
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  last_cycle = stream->cycle -
2851cb0ef41Sopenharmony_ci               (wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight;
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  /* Now we have old stream->pending_penalty and new stream->weight in
2881cb0ef41Sopenharmony_ci     place */
2891cb0ef41Sopenharmony_ci  stream_next_cycle(stream, last_cycle);
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  if (dep_stream->descendant_last_cycle - stream->cycle <=
2921cb0ef41Sopenharmony_ci      NGHTTP2_MAX_CYCLE_DISTANCE) {
2931cb0ef41Sopenharmony_ci    stream->cycle = dep_stream->descendant_last_cycle;
2941cb0ef41Sopenharmony_ci  }
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  /* Continue to use same stream->seq */
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
3011cb0ef41Sopenharmony_ci         stream->cycle);
3021cb0ef41Sopenharmony_ci}
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_cistatic nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
3051cb0ef41Sopenharmony_ci  for (; stream->sib_next; stream = stream->sib_next)
3061cb0ef41Sopenharmony_ci    ;
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  return stream;
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ciint32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
3121cb0ef41Sopenharmony_ci                                              int32_t weight) {
3131cb0ef41Sopenharmony_ci  weight = stream->weight * weight / stream->sum_dep_weight;
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  return nghttp2_max(1, weight);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci#ifdef STREAM_DEP_DEBUG
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_cistatic void ensure_inactive(nghttp2_stream *stream) {
3211cb0ef41Sopenharmony_ci  nghttp2_stream *si;
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci  if (stream->queued) {
3241cb0ef41Sopenharmony_ci    fprintf(stderr, "stream(%p)=%d, stream->queued = 1; want 0\n", stream,
3251cb0ef41Sopenharmony_ci            stream->stream_id);
3261cb0ef41Sopenharmony_ci    assert(0);
3271cb0ef41Sopenharmony_ci  }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci  if (stream_active(stream)) {
3301cb0ef41Sopenharmony_ci    fprintf(stderr, "stream(%p)=%d, stream_active(stream) = 1; want 0\n",
3311cb0ef41Sopenharmony_ci            stream, stream->stream_id);
3321cb0ef41Sopenharmony_ci    assert(0);
3331cb0ef41Sopenharmony_ci  }
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  if (!nghttp2_pq_empty(&stream->obq)) {
3361cb0ef41Sopenharmony_ci    fprintf(stderr, "stream(%p)=%d, nghttp2_pq_size() = %zu; want 0\n", stream,
3371cb0ef41Sopenharmony_ci            stream->stream_id, nghttp2_pq_size(&stream->obq));
3381cb0ef41Sopenharmony_ci    assert(0);
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  for (si = stream->dep_next; si; si = si->sib_next) {
3421cb0ef41Sopenharmony_ci    ensure_inactive(si);
3431cb0ef41Sopenharmony_ci  }
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_cistatic void check_queued(nghttp2_stream *stream) {
3471cb0ef41Sopenharmony_ci  nghttp2_stream *si;
3481cb0ef41Sopenharmony_ci  int queued;
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci  if (stream->queued) {
3511cb0ef41Sopenharmony_ci    if (!stream_subtree_active(stream)) {
3521cb0ef41Sopenharmony_ci      fprintf(stderr,
3531cb0ef41Sopenharmony_ci              "stream(%p)=%d, stream->queued == 1, but "
3541cb0ef41Sopenharmony_ci              "stream_active() == %d and nghttp2_pq_size(&stream->obq) = %zu\n",
3551cb0ef41Sopenharmony_ci              stream, stream->stream_id, stream_active(stream),
3561cb0ef41Sopenharmony_ci              nghttp2_pq_size(&stream->obq));
3571cb0ef41Sopenharmony_ci      assert(0);
3581cb0ef41Sopenharmony_ci    }
3591cb0ef41Sopenharmony_ci    if (!stream_active(stream)) {
3601cb0ef41Sopenharmony_ci      queued = 0;
3611cb0ef41Sopenharmony_ci      for (si = stream->dep_next; si; si = si->sib_next) {
3621cb0ef41Sopenharmony_ci        if (si->queued) {
3631cb0ef41Sopenharmony_ci          ++queued;
3641cb0ef41Sopenharmony_ci        }
3651cb0ef41Sopenharmony_ci      }
3661cb0ef41Sopenharmony_ci      if (queued == 0) {
3671cb0ef41Sopenharmony_ci        fprintf(stderr,
3681cb0ef41Sopenharmony_ci                "stream(%p)=%d, stream->queued == 1, and "
3691cb0ef41Sopenharmony_ci                "!stream_active(), but no descendants is queued\n",
3701cb0ef41Sopenharmony_ci                stream, stream->stream_id);
3711cb0ef41Sopenharmony_ci        assert(0);
3721cb0ef41Sopenharmony_ci      }
3731cb0ef41Sopenharmony_ci    }
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci    for (si = stream->dep_next; si; si = si->sib_next) {
3761cb0ef41Sopenharmony_ci      check_queued(si);
3771cb0ef41Sopenharmony_ci    }
3781cb0ef41Sopenharmony_ci  } else {
3791cb0ef41Sopenharmony_ci    if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
3801cb0ef41Sopenharmony_ci      fprintf(stderr,
3811cb0ef41Sopenharmony_ci              "stream(%p) = %d, stream->queued == 0, but "
3821cb0ef41Sopenharmony_ci              "stream_active(stream) == %d and "
3831cb0ef41Sopenharmony_ci              "nghttp2_pq_size(&stream->obq) = %zu\n",
3841cb0ef41Sopenharmony_ci              stream, stream->stream_id, stream_active(stream),
3851cb0ef41Sopenharmony_ci              nghttp2_pq_size(&stream->obq));
3861cb0ef41Sopenharmony_ci      assert(0);
3871cb0ef41Sopenharmony_ci    }
3881cb0ef41Sopenharmony_ci    for (si = stream->dep_next; si; si = si->sib_next) {
3891cb0ef41Sopenharmony_ci      ensure_inactive(si);
3901cb0ef41Sopenharmony_ci    }
3911cb0ef41Sopenharmony_ci  }
3921cb0ef41Sopenharmony_ci}
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_cistatic void check_sum_dep(nghttp2_stream *stream) {
3951cb0ef41Sopenharmony_ci  nghttp2_stream *si;
3961cb0ef41Sopenharmony_ci  int32_t n = 0;
3971cb0ef41Sopenharmony_ci  for (si = stream->dep_next; si; si = si->sib_next) {
3981cb0ef41Sopenharmony_ci    n += si->weight;
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci  if (n != stream->sum_dep_weight) {
4011cb0ef41Sopenharmony_ci    fprintf(stderr, "stream(%p)=%d, sum_dep_weight = %d; want %d\n", stream,
4021cb0ef41Sopenharmony_ci            stream->stream_id, n, stream->sum_dep_weight);
4031cb0ef41Sopenharmony_ci    assert(0);
4041cb0ef41Sopenharmony_ci  }
4051cb0ef41Sopenharmony_ci  for (si = stream->dep_next; si; si = si->sib_next) {
4061cb0ef41Sopenharmony_ci    check_sum_dep(si);
4071cb0ef41Sopenharmony_ci  }
4081cb0ef41Sopenharmony_ci}
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_cistatic void check_dep_prev(nghttp2_stream *stream) {
4111cb0ef41Sopenharmony_ci  nghttp2_stream *si;
4121cb0ef41Sopenharmony_ci  for (si = stream->dep_next; si; si = si->sib_next) {
4131cb0ef41Sopenharmony_ci    if (si->dep_prev != stream) {
4141cb0ef41Sopenharmony_ci      fprintf(stderr, "si->dep_prev = %p; want %p\n", si->dep_prev, stream);
4151cb0ef41Sopenharmony_ci      assert(0);
4161cb0ef41Sopenharmony_ci    }
4171cb0ef41Sopenharmony_ci    check_dep_prev(si);
4181cb0ef41Sopenharmony_ci  }
4191cb0ef41Sopenharmony_ci}
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci#endif /* STREAM_DEP_DEBUG */
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci#ifdef STREAM_DEP_DEBUG
4241cb0ef41Sopenharmony_cistatic void validate_tree(nghttp2_stream *stream) {
4251cb0ef41Sopenharmony_ci  nghttp2_stream *si;
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci  if (!stream) {
4281cb0ef41Sopenharmony_ci    return;
4291cb0ef41Sopenharmony_ci  }
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci  for (; stream->dep_prev; stream = stream->dep_prev)
4321cb0ef41Sopenharmony_ci    ;
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci  assert(stream->stream_id == 0);
4351cb0ef41Sopenharmony_ci  assert(!stream->queued);
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci  fprintf(stderr, "checking...\n");
4381cb0ef41Sopenharmony_ci  if (nghttp2_pq_empty(&stream->obq)) {
4391cb0ef41Sopenharmony_ci    fprintf(stderr, "root obq empty\n");
4401cb0ef41Sopenharmony_ci    for (si = stream->dep_next; si; si = si->sib_next) {
4411cb0ef41Sopenharmony_ci      ensure_inactive(si);
4421cb0ef41Sopenharmony_ci    }
4431cb0ef41Sopenharmony_ci  } else {
4441cb0ef41Sopenharmony_ci    for (si = stream->dep_next; si; si = si->sib_next) {
4451cb0ef41Sopenharmony_ci      check_queued(si);
4461cb0ef41Sopenharmony_ci    }
4471cb0ef41Sopenharmony_ci  }
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci  check_sum_dep(stream);
4501cb0ef41Sopenharmony_ci  check_dep_prev(stream);
4511cb0ef41Sopenharmony_ci}
4521cb0ef41Sopenharmony_ci#else  /* !STREAM_DEP_DEBUG */
4531cb0ef41Sopenharmony_cistatic void validate_tree(nghttp2_stream *stream) { (void)stream; }
4541cb0ef41Sopenharmony_ci#endif /* !STREAM_DEP_DEBUG*/
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_cistatic int stream_update_dep_on_attach_item(nghttp2_stream *stream) {
4571cb0ef41Sopenharmony_ci  int rv;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  rv = stream_obq_push(stream->dep_prev, stream);
4601cb0ef41Sopenharmony_ci  if (rv != 0) {
4611cb0ef41Sopenharmony_ci    return rv;
4621cb0ef41Sopenharmony_ci  }
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci  validate_tree(stream);
4651cb0ef41Sopenharmony_ci  return 0;
4661cb0ef41Sopenharmony_ci}
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_cistatic void stream_update_dep_on_detach_item(nghttp2_stream *stream) {
4691cb0ef41Sopenharmony_ci  if (nghttp2_pq_empty(&stream->obq)) {
4701cb0ef41Sopenharmony_ci    stream_obq_remove(stream);
4711cb0ef41Sopenharmony_ci  }
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci  validate_tree(stream);
4741cb0ef41Sopenharmony_ci}
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ciint nghttp2_stream_attach_item(nghttp2_stream *stream,
4771cb0ef41Sopenharmony_ci                               nghttp2_outbound_item *item) {
4781cb0ef41Sopenharmony_ci  int rv;
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci  assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
4811cb0ef41Sopenharmony_ci  assert(stream->item == NULL);
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci  DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item);
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_ci  stream->item = item;
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
4881cb0ef41Sopenharmony_ci    return 0;
4891cb0ef41Sopenharmony_ci  }
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci  rv = stream_update_dep_on_attach_item(stream);
4921cb0ef41Sopenharmony_ci  if (rv != 0) {
4931cb0ef41Sopenharmony_ci    /* This may relave stream->queued == 1, but stream->item == NULL.
4941cb0ef41Sopenharmony_ci       But only consequence of this error is fatal one, and session
4951cb0ef41Sopenharmony_ci       destruction.  In that execution path, these inconsistency does
4961cb0ef41Sopenharmony_ci       not matter. */
4971cb0ef41Sopenharmony_ci    stream->item = NULL;
4981cb0ef41Sopenharmony_ci    return rv;
4991cb0ef41Sopenharmony_ci  }
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci  return 0;
5021cb0ef41Sopenharmony_ci}
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_civoid nghttp2_stream_detach_item(nghttp2_stream *stream) {
5051cb0ef41Sopenharmony_ci  DEBUGF("stream: stream=%d detach item=%p\n", stream->stream_id, stream->item);
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci  stream->item = NULL;
5081cb0ef41Sopenharmony_ci  stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
5111cb0ef41Sopenharmony_ci    return;
5121cb0ef41Sopenharmony_ci  }
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci  stream_update_dep_on_detach_item(stream);
5151cb0ef41Sopenharmony_ci}
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_civoid nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
5181cb0ef41Sopenharmony_ci  assert(stream->item);
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci  DEBUGF("stream: stream=%d defer item=%p cause=%02x\n", stream->stream_id,
5211cb0ef41Sopenharmony_ci         stream->item, flags);
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ci  stream->flags |= flags;
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
5261cb0ef41Sopenharmony_ci    return;
5271cb0ef41Sopenharmony_ci  }
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_ci  stream_update_dep_on_detach_item(stream);
5301cb0ef41Sopenharmony_ci}
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_ciint nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
5331cb0ef41Sopenharmony_ci  assert(stream->item);
5341cb0ef41Sopenharmony_ci
5351cb0ef41Sopenharmony_ci  DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id,
5361cb0ef41Sopenharmony_ci         stream->item, flags);
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  stream->flags = (uint8_t)(stream->flags & ~flags);
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
5411cb0ef41Sopenharmony_ci    return 0;
5421cb0ef41Sopenharmony_ci  }
5431cb0ef41Sopenharmony_ci
5441cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
5451cb0ef41Sopenharmony_ci    return 0;
5461cb0ef41Sopenharmony_ci  }
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci  return stream_update_dep_on_attach_item(stream);
5491cb0ef41Sopenharmony_ci}
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ciint nghttp2_stream_check_deferred_item(nghttp2_stream *stream) {
5521cb0ef41Sopenharmony_ci  return stream->item && (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
5531cb0ef41Sopenharmony_ci}
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ciint nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream) {
5561cb0ef41Sopenharmony_ci  return stream->item &&
5571cb0ef41Sopenharmony_ci         (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
5581cb0ef41Sopenharmony_ci}
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_cistatic int update_initial_window_size(int32_t *window_size_ptr,
5611cb0ef41Sopenharmony_ci                                      int32_t new_initial_window_size,
5621cb0ef41Sopenharmony_ci                                      int32_t old_initial_window_size) {
5631cb0ef41Sopenharmony_ci  int64_t new_window_size = (int64_t)(*window_size_ptr) +
5641cb0ef41Sopenharmony_ci                            new_initial_window_size - old_initial_window_size;
5651cb0ef41Sopenharmony_ci  if (INT32_MIN > new_window_size ||
5661cb0ef41Sopenharmony_ci      new_window_size > NGHTTP2_MAX_WINDOW_SIZE) {
5671cb0ef41Sopenharmony_ci    return -1;
5681cb0ef41Sopenharmony_ci  }
5691cb0ef41Sopenharmony_ci  *window_size_ptr = (int32_t)new_window_size;
5701cb0ef41Sopenharmony_ci  return 0;
5711cb0ef41Sopenharmony_ci}
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ciint nghttp2_stream_update_remote_initial_window_size(
5741cb0ef41Sopenharmony_ci    nghttp2_stream *stream, int32_t new_initial_window_size,
5751cb0ef41Sopenharmony_ci    int32_t old_initial_window_size) {
5761cb0ef41Sopenharmony_ci  return update_initial_window_size(&stream->remote_window_size,
5771cb0ef41Sopenharmony_ci                                    new_initial_window_size,
5781cb0ef41Sopenharmony_ci                                    old_initial_window_size);
5791cb0ef41Sopenharmony_ci}
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_ciint nghttp2_stream_update_local_initial_window_size(
5821cb0ef41Sopenharmony_ci    nghttp2_stream *stream, int32_t new_initial_window_size,
5831cb0ef41Sopenharmony_ci    int32_t old_initial_window_size) {
5841cb0ef41Sopenharmony_ci  return update_initial_window_size(&stream->local_window_size,
5851cb0ef41Sopenharmony_ci                                    new_initial_window_size,
5861cb0ef41Sopenharmony_ci                                    old_initial_window_size);
5871cb0ef41Sopenharmony_ci}
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_civoid nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
5901cb0ef41Sopenharmony_ci  stream->state = NGHTTP2_STREAM_OPENED;
5911cb0ef41Sopenharmony_ci  stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
5921cb0ef41Sopenharmony_ci}
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ciint nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
5951cb0ef41Sopenharmony_ci                                     nghttp2_stream *target) {
5961cb0ef41Sopenharmony_ci  for (; stream; stream = stream->dep_prev) {
5971cb0ef41Sopenharmony_ci    if (stream == target) {
5981cb0ef41Sopenharmony_ci      return 1;
5991cb0ef41Sopenharmony_ci    }
6001cb0ef41Sopenharmony_ci  }
6011cb0ef41Sopenharmony_ci  return 0;
6021cb0ef41Sopenharmony_ci}
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ciint nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
6051cb0ef41Sopenharmony_ci                              nghttp2_stream *stream) {
6061cb0ef41Sopenharmony_ci  nghttp2_stream *si;
6071cb0ef41Sopenharmony_ci  int rv;
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_ci  DEBUGF("stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
6101cb0ef41Sopenharmony_ci         dep_stream->stream_id, stream, stream->stream_id);
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  stream->sum_dep_weight = dep_stream->sum_dep_weight;
6131cb0ef41Sopenharmony_ci  dep_stream->sum_dep_weight = stream->weight;
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci  if (dep_stream->dep_next) {
6161cb0ef41Sopenharmony_ci    for (si = dep_stream->dep_next; si; si = si->sib_next) {
6171cb0ef41Sopenharmony_ci      si->dep_prev = stream;
6181cb0ef41Sopenharmony_ci      if (si->queued) {
6191cb0ef41Sopenharmony_ci        rv = stream_obq_move(stream, dep_stream, si);
6201cb0ef41Sopenharmony_ci        if (rv != 0) {
6211cb0ef41Sopenharmony_ci          return rv;
6221cb0ef41Sopenharmony_ci        }
6231cb0ef41Sopenharmony_ci      }
6241cb0ef41Sopenharmony_ci    }
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci    if (stream_subtree_active(stream)) {
6271cb0ef41Sopenharmony_ci      rv = stream_obq_push(dep_stream, stream);
6281cb0ef41Sopenharmony_ci      if (rv != 0) {
6291cb0ef41Sopenharmony_ci        return rv;
6301cb0ef41Sopenharmony_ci      }
6311cb0ef41Sopenharmony_ci    }
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci    stream->dep_next = dep_stream->dep_next;
6341cb0ef41Sopenharmony_ci  }
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_ci  dep_stream->dep_next = stream;
6371cb0ef41Sopenharmony_ci  stream->dep_prev = dep_stream;
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci  validate_tree(stream);
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci  return 0;
6421cb0ef41Sopenharmony_ci}
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_cistatic void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) {
6451cb0ef41Sopenharmony_ci  for (; stream; stream = stream->sib_next) {
6461cb0ef41Sopenharmony_ci    stream->dep_prev = dep;
6471cb0ef41Sopenharmony_ci  }
6481cb0ef41Sopenharmony_ci}
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_cistatic void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
6511cb0ef41Sopenharmony_ci  dep_stream->dep_next = stream;
6521cb0ef41Sopenharmony_ci  if (stream) {
6531cb0ef41Sopenharmony_ci    stream->dep_prev = dep_stream;
6541cb0ef41Sopenharmony_ci  }
6551cb0ef41Sopenharmony_ci}
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_cistatic void link_sib(nghttp2_stream *a, nghttp2_stream *b) {
6581cb0ef41Sopenharmony_ci  a->sib_next = b;
6591cb0ef41Sopenharmony_ci  if (b) {
6601cb0ef41Sopenharmony_ci    b->sib_prev = a;
6611cb0ef41Sopenharmony_ci  }
6621cb0ef41Sopenharmony_ci}
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_cistatic void insert_link_dep(nghttp2_stream *dep_stream,
6651cb0ef41Sopenharmony_ci                            nghttp2_stream *stream) {
6661cb0ef41Sopenharmony_ci  nghttp2_stream *sib_next;
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_ci  assert(stream->sib_prev == NULL);
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ci  sib_next = dep_stream->dep_next;
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ci  link_sib(stream, sib_next);
6731cb0ef41Sopenharmony_ci
6741cb0ef41Sopenharmony_ci  link_dep(dep_stream, stream);
6751cb0ef41Sopenharmony_ci}
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_cistatic void unlink_sib(nghttp2_stream *stream) {
6781cb0ef41Sopenharmony_ci  nghttp2_stream *prev, *next, *dep_next;
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ci  prev = stream->sib_prev;
6811cb0ef41Sopenharmony_ci  dep_next = stream->dep_next;
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_ci  assert(prev);
6841cb0ef41Sopenharmony_ci
6851cb0ef41Sopenharmony_ci  if (dep_next) {
6861cb0ef41Sopenharmony_ci    /*
6871cb0ef41Sopenharmony_ci     *  prev--stream(--sib_next--...)
6881cb0ef41Sopenharmony_ci     *         |
6891cb0ef41Sopenharmony_ci     *        dep_next
6901cb0ef41Sopenharmony_ci     */
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci    link_sib(prev, dep_next);
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ci    set_dep_prev(dep_next, stream->dep_prev);
6951cb0ef41Sopenharmony_ci
6961cb0ef41Sopenharmony_ci    if (stream->sib_next) {
6971cb0ef41Sopenharmony_ci      link_sib(stream_last_sib(dep_next), stream->sib_next);
6981cb0ef41Sopenharmony_ci    }
6991cb0ef41Sopenharmony_ci  } else {
7001cb0ef41Sopenharmony_ci    /*
7011cb0ef41Sopenharmony_ci     *  prev--stream(--sib_next--...)
7021cb0ef41Sopenharmony_ci     */
7031cb0ef41Sopenharmony_ci    next = stream->sib_next;
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci    prev->sib_next = next;
7061cb0ef41Sopenharmony_ci
7071cb0ef41Sopenharmony_ci    if (next) {
7081cb0ef41Sopenharmony_ci      next->sib_prev = prev;
7091cb0ef41Sopenharmony_ci    }
7101cb0ef41Sopenharmony_ci  }
7111cb0ef41Sopenharmony_ci}
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_cistatic void unlink_dep(nghttp2_stream *stream) {
7141cb0ef41Sopenharmony_ci  nghttp2_stream *prev, *next, *dep_next;
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_ci  prev = stream->dep_prev;
7171cb0ef41Sopenharmony_ci  dep_next = stream->dep_next;
7181cb0ef41Sopenharmony_ci
7191cb0ef41Sopenharmony_ci  assert(prev);
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  if (dep_next) {
7221cb0ef41Sopenharmony_ci    /*
7231cb0ef41Sopenharmony_ci     * prev
7241cb0ef41Sopenharmony_ci     *   |
7251cb0ef41Sopenharmony_ci     * stream(--sib_next--...)
7261cb0ef41Sopenharmony_ci     *   |
7271cb0ef41Sopenharmony_ci     * dep_next
7281cb0ef41Sopenharmony_ci     */
7291cb0ef41Sopenharmony_ci    link_dep(prev, dep_next);
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci    set_dep_prev(dep_next, stream->dep_prev);
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_ci    if (stream->sib_next) {
7341cb0ef41Sopenharmony_ci      link_sib(stream_last_sib(dep_next), stream->sib_next);
7351cb0ef41Sopenharmony_ci    }
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci  } else if (stream->sib_next) {
7381cb0ef41Sopenharmony_ci    /*
7391cb0ef41Sopenharmony_ci     * prev
7401cb0ef41Sopenharmony_ci     *   |
7411cb0ef41Sopenharmony_ci     * stream--sib_next
7421cb0ef41Sopenharmony_ci     */
7431cb0ef41Sopenharmony_ci    next = stream->sib_next;
7441cb0ef41Sopenharmony_ci
7451cb0ef41Sopenharmony_ci    next->sib_prev = NULL;
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci    link_dep(prev, next);
7481cb0ef41Sopenharmony_ci  } else {
7491cb0ef41Sopenharmony_ci    prev->dep_next = NULL;
7501cb0ef41Sopenharmony_ci  }
7511cb0ef41Sopenharmony_ci}
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_civoid nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
7541cb0ef41Sopenharmony_ci                            nghttp2_stream *stream) {
7551cb0ef41Sopenharmony_ci  DEBUGF("stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
7561cb0ef41Sopenharmony_ci         dep_stream->stream_id, stream, stream->stream_id);
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci  dep_stream->sum_dep_weight += stream->weight;
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci  if (dep_stream->dep_next == NULL) {
7611cb0ef41Sopenharmony_ci    link_dep(dep_stream, stream);
7621cb0ef41Sopenharmony_ci  } else {
7631cb0ef41Sopenharmony_ci    insert_link_dep(dep_stream, stream);
7641cb0ef41Sopenharmony_ci  }
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci  validate_tree(stream);
7671cb0ef41Sopenharmony_ci}
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ciint nghttp2_stream_dep_remove(nghttp2_stream *stream) {
7701cb0ef41Sopenharmony_ci  nghttp2_stream *dep_prev, *si;
7711cb0ef41Sopenharmony_ci  int32_t sum_dep_weight_delta;
7721cb0ef41Sopenharmony_ci  int rv;
7731cb0ef41Sopenharmony_ci
7741cb0ef41Sopenharmony_ci  DEBUGF("stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id);
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci  /* Distribute weight of |stream| to direct descendants */
7771cb0ef41Sopenharmony_ci  sum_dep_weight_delta = -stream->weight;
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci  for (si = stream->dep_next; si; si = si->sib_next) {
7801cb0ef41Sopenharmony_ci    si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
7811cb0ef41Sopenharmony_ci
7821cb0ef41Sopenharmony_ci    sum_dep_weight_delta += si->weight;
7831cb0ef41Sopenharmony_ci
7841cb0ef41Sopenharmony_ci    if (si->queued) {
7851cb0ef41Sopenharmony_ci      rv = stream_obq_move(stream->dep_prev, stream, si);
7861cb0ef41Sopenharmony_ci      if (rv != 0) {
7871cb0ef41Sopenharmony_ci        return rv;
7881cb0ef41Sopenharmony_ci      }
7891cb0ef41Sopenharmony_ci    }
7901cb0ef41Sopenharmony_ci  }
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci  assert(stream->dep_prev);
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_ci  dep_prev = stream->dep_prev;
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci  dep_prev->sum_dep_weight += sum_dep_weight_delta;
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_ci  if (stream->queued) {
7991cb0ef41Sopenharmony_ci    stream_obq_remove(stream);
8001cb0ef41Sopenharmony_ci  }
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_ci  if (stream->sib_prev) {
8031cb0ef41Sopenharmony_ci    unlink_sib(stream);
8041cb0ef41Sopenharmony_ci  } else {
8051cb0ef41Sopenharmony_ci    unlink_dep(stream);
8061cb0ef41Sopenharmony_ci  }
8071cb0ef41Sopenharmony_ci
8081cb0ef41Sopenharmony_ci  stream->sum_dep_weight = 0;
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci  stream->dep_prev = NULL;
8111cb0ef41Sopenharmony_ci  stream->dep_next = NULL;
8121cb0ef41Sopenharmony_ci  stream->sib_prev = NULL;
8131cb0ef41Sopenharmony_ci  stream->sib_next = NULL;
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_ci  validate_tree(dep_prev);
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ci  return 0;
8181cb0ef41Sopenharmony_ci}
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_ciint nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
8211cb0ef41Sopenharmony_ci                                      nghttp2_stream *stream) {
8221cb0ef41Sopenharmony_ci  nghttp2_stream *last_sib;
8231cb0ef41Sopenharmony_ci  nghttp2_stream *dep_next;
8241cb0ef41Sopenharmony_ci  nghttp2_stream *si;
8251cb0ef41Sopenharmony_ci  int rv;
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_ci  DEBUGF("stream: dep_insert_subtree dep_stream(%p)=%d stream(%p)=%d\n",
8281cb0ef41Sopenharmony_ci         dep_stream, dep_stream->stream_id, stream, stream->stream_id);
8291cb0ef41Sopenharmony_ci
8301cb0ef41Sopenharmony_ci  stream->sum_dep_weight += dep_stream->sum_dep_weight;
8311cb0ef41Sopenharmony_ci  dep_stream->sum_dep_weight = stream->weight;
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ci  if (dep_stream->dep_next) {
8341cb0ef41Sopenharmony_ci    dep_next = dep_stream->dep_next;
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_ci    link_dep(dep_stream, stream);
8371cb0ef41Sopenharmony_ci
8381cb0ef41Sopenharmony_ci    if (stream->dep_next) {
8391cb0ef41Sopenharmony_ci      last_sib = stream_last_sib(stream->dep_next);
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci      link_sib(last_sib, dep_next);
8421cb0ef41Sopenharmony_ci    } else {
8431cb0ef41Sopenharmony_ci      link_dep(stream, dep_next);
8441cb0ef41Sopenharmony_ci    }
8451cb0ef41Sopenharmony_ci
8461cb0ef41Sopenharmony_ci    for (si = dep_next; si; si = si->sib_next) {
8471cb0ef41Sopenharmony_ci      si->dep_prev = stream;
8481cb0ef41Sopenharmony_ci      if (si->queued) {
8491cb0ef41Sopenharmony_ci        rv = stream_obq_move(stream, dep_stream, si);
8501cb0ef41Sopenharmony_ci        if (rv != 0) {
8511cb0ef41Sopenharmony_ci          return rv;
8521cb0ef41Sopenharmony_ci        }
8531cb0ef41Sopenharmony_ci      }
8541cb0ef41Sopenharmony_ci    }
8551cb0ef41Sopenharmony_ci  } else {
8561cb0ef41Sopenharmony_ci    link_dep(dep_stream, stream);
8571cb0ef41Sopenharmony_ci  }
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_ci  if (stream_subtree_active(stream)) {
8601cb0ef41Sopenharmony_ci    rv = stream_obq_push(dep_stream, stream);
8611cb0ef41Sopenharmony_ci    if (rv != 0) {
8621cb0ef41Sopenharmony_ci      return rv;
8631cb0ef41Sopenharmony_ci    }
8641cb0ef41Sopenharmony_ci  }
8651cb0ef41Sopenharmony_ci
8661cb0ef41Sopenharmony_ci  validate_tree(dep_stream);
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci  return 0;
8691cb0ef41Sopenharmony_ci}
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ciint nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
8721cb0ef41Sopenharmony_ci                                   nghttp2_stream *stream) {
8731cb0ef41Sopenharmony_ci  int rv;
8741cb0ef41Sopenharmony_ci
8751cb0ef41Sopenharmony_ci  DEBUGF("stream: dep_add_subtree dep_stream(%p)=%d stream(%p)=%d\n",
8761cb0ef41Sopenharmony_ci         dep_stream, dep_stream->stream_id, stream, stream->stream_id);
8771cb0ef41Sopenharmony_ci
8781cb0ef41Sopenharmony_ci  dep_stream->sum_dep_weight += stream->weight;
8791cb0ef41Sopenharmony_ci
8801cb0ef41Sopenharmony_ci  if (dep_stream->dep_next) {
8811cb0ef41Sopenharmony_ci    insert_link_dep(dep_stream, stream);
8821cb0ef41Sopenharmony_ci  } else {
8831cb0ef41Sopenharmony_ci    link_dep(dep_stream, stream);
8841cb0ef41Sopenharmony_ci  }
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci  if (stream_subtree_active(stream)) {
8871cb0ef41Sopenharmony_ci    rv = stream_obq_push(dep_stream, stream);
8881cb0ef41Sopenharmony_ci    if (rv != 0) {
8891cb0ef41Sopenharmony_ci      return rv;
8901cb0ef41Sopenharmony_ci    }
8911cb0ef41Sopenharmony_ci  }
8921cb0ef41Sopenharmony_ci
8931cb0ef41Sopenharmony_ci  validate_tree(dep_stream);
8941cb0ef41Sopenharmony_ci
8951cb0ef41Sopenharmony_ci  return 0;
8961cb0ef41Sopenharmony_ci}
8971cb0ef41Sopenharmony_ci
8981cb0ef41Sopenharmony_civoid nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
8991cb0ef41Sopenharmony_ci  nghttp2_stream *next, *dep_prev;
9001cb0ef41Sopenharmony_ci
9011cb0ef41Sopenharmony_ci  DEBUGF("stream: dep_remove_subtree stream(%p)=%d\n", stream,
9021cb0ef41Sopenharmony_ci         stream->stream_id);
9031cb0ef41Sopenharmony_ci
9041cb0ef41Sopenharmony_ci  assert(stream->dep_prev);
9051cb0ef41Sopenharmony_ci
9061cb0ef41Sopenharmony_ci  dep_prev = stream->dep_prev;
9071cb0ef41Sopenharmony_ci
9081cb0ef41Sopenharmony_ci  if (stream->sib_prev) {
9091cb0ef41Sopenharmony_ci    link_sib(stream->sib_prev, stream->sib_next);
9101cb0ef41Sopenharmony_ci  } else {
9111cb0ef41Sopenharmony_ci    next = stream->sib_next;
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_ci    link_dep(dep_prev, next);
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_ci    if (next) {
9161cb0ef41Sopenharmony_ci      next->sib_prev = NULL;
9171cb0ef41Sopenharmony_ci    }
9181cb0ef41Sopenharmony_ci  }
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ci  dep_prev->sum_dep_weight -= stream->weight;
9211cb0ef41Sopenharmony_ci
9221cb0ef41Sopenharmony_ci  if (stream->queued) {
9231cb0ef41Sopenharmony_ci    stream_obq_remove(stream);
9241cb0ef41Sopenharmony_ci  }
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci  validate_tree(dep_prev);
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_ci  stream->sib_prev = NULL;
9291cb0ef41Sopenharmony_ci  stream->sib_next = NULL;
9301cb0ef41Sopenharmony_ci  stream->dep_prev = NULL;
9311cb0ef41Sopenharmony_ci}
9321cb0ef41Sopenharmony_ci
9331cb0ef41Sopenharmony_ciint nghttp2_stream_in_dep_tree(nghttp2_stream *stream) {
9341cb0ef41Sopenharmony_ci  return stream->dep_prev || stream->dep_next || stream->sib_prev ||
9351cb0ef41Sopenharmony_ci         stream->sib_next;
9361cb0ef41Sopenharmony_ci}
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_cinghttp2_outbound_item *
9391cb0ef41Sopenharmony_cinghttp2_stream_next_outbound_item(nghttp2_stream *stream) {
9401cb0ef41Sopenharmony_ci  nghttp2_pq_entry *ent;
9411cb0ef41Sopenharmony_ci  nghttp2_stream *si;
9421cb0ef41Sopenharmony_ci
9431cb0ef41Sopenharmony_ci  for (;;) {
9441cb0ef41Sopenharmony_ci    if (stream_active(stream)) {
9451cb0ef41Sopenharmony_ci      /* Update ascendant's descendant_last_cycle here, so that we can
9461cb0ef41Sopenharmony_ci         assure that new stream is scheduled based on it. */
9471cb0ef41Sopenharmony_ci      for (si = stream; si->dep_prev; si = si->dep_prev) {
9481cb0ef41Sopenharmony_ci        si->dep_prev->descendant_last_cycle = si->cycle;
9491cb0ef41Sopenharmony_ci      }
9501cb0ef41Sopenharmony_ci      return stream->item;
9511cb0ef41Sopenharmony_ci    }
9521cb0ef41Sopenharmony_ci    ent = nghttp2_pq_top(&stream->obq);
9531cb0ef41Sopenharmony_ci    if (!ent) {
9541cb0ef41Sopenharmony_ci      return NULL;
9551cb0ef41Sopenharmony_ci    }
9561cb0ef41Sopenharmony_ci    stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry);
9571cb0ef41Sopenharmony_ci  }
9581cb0ef41Sopenharmony_ci}
9591cb0ef41Sopenharmony_ci
9601cb0ef41Sopenharmony_cinghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
9611cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) {
9621cb0ef41Sopenharmony_ci    return NGHTTP2_STREAM_STATE_CLOSED;
9631cb0ef41Sopenharmony_ci  }
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ci  if (stream->flags & NGHTTP2_STREAM_FLAG_PUSH) {
9661cb0ef41Sopenharmony_ci    if (stream->shut_flags & NGHTTP2_SHUT_RD) {
9671cb0ef41Sopenharmony_ci      return NGHTTP2_STREAM_STATE_RESERVED_LOCAL;
9681cb0ef41Sopenharmony_ci    }
9691cb0ef41Sopenharmony_ci
9701cb0ef41Sopenharmony_ci    if (stream->shut_flags & NGHTTP2_SHUT_WR) {
9711cb0ef41Sopenharmony_ci      return NGHTTP2_STREAM_STATE_RESERVED_REMOTE;
9721cb0ef41Sopenharmony_ci    }
9731cb0ef41Sopenharmony_ci  }
9741cb0ef41Sopenharmony_ci
9751cb0ef41Sopenharmony_ci  if (stream->shut_flags & NGHTTP2_SHUT_RD) {
9761cb0ef41Sopenharmony_ci    return NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE;
9771cb0ef41Sopenharmony_ci  }
9781cb0ef41Sopenharmony_ci
9791cb0ef41Sopenharmony_ci  if (stream->shut_flags & NGHTTP2_SHUT_WR) {
9801cb0ef41Sopenharmony_ci    return NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL;
9811cb0ef41Sopenharmony_ci  }
9821cb0ef41Sopenharmony_ci
9831cb0ef41Sopenharmony_ci  if (stream->state == NGHTTP2_STREAM_IDLE) {
9841cb0ef41Sopenharmony_ci    return NGHTTP2_STREAM_STATE_IDLE;
9851cb0ef41Sopenharmony_ci  }
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ci  return NGHTTP2_STREAM_STATE_OPEN;
9881cb0ef41Sopenharmony_ci}
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_cinghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) {
9911cb0ef41Sopenharmony_ci  return stream->dep_prev;
9921cb0ef41Sopenharmony_ci}
9931cb0ef41Sopenharmony_ci
9941cb0ef41Sopenharmony_cinghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) {
9951cb0ef41Sopenharmony_ci  return stream->sib_next;
9961cb0ef41Sopenharmony_ci}
9971cb0ef41Sopenharmony_ci
9981cb0ef41Sopenharmony_cinghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) {
9991cb0ef41Sopenharmony_ci  return stream->sib_prev;
10001cb0ef41Sopenharmony_ci}
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_cinghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) {
10031cb0ef41Sopenharmony_ci  return stream->dep_next;
10041cb0ef41Sopenharmony_ci}
10051cb0ef41Sopenharmony_ci
10061cb0ef41Sopenharmony_ciint32_t nghttp2_stream_get_weight(nghttp2_stream *stream) {
10071cb0ef41Sopenharmony_ci  return stream->weight;
10081cb0ef41Sopenharmony_ci}
10091cb0ef41Sopenharmony_ci
10101cb0ef41Sopenharmony_ciint32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) {
10111cb0ef41Sopenharmony_ci  return stream->sum_dep_weight;
10121cb0ef41Sopenharmony_ci}
10131cb0ef41Sopenharmony_ci
10141cb0ef41Sopenharmony_ciint32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) {
10151cb0ef41Sopenharmony_ci  return stream->stream_id;
10161cb0ef41Sopenharmony_ci}
1017