2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012 Tatsuhiro Tsujikawa
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:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
25 #include "nghttp2_stream.h"
30 #include "nghttp2_session.h"
31 #include "nghttp2_helper.h"
33 void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
34 uint8_t flags, nghttp2_stream_state initial_state,
35 int32_t weight, nghttp2_stream_roots *roots,
36 int32_t remote_initial_window_size,
37 int32_t local_initial_window_size,
38 void *stream_user_data) {
39 nghttp2_map_entry_init(&stream->map_entry, stream_id);
40 stream->stream_id = stream_id;
41 stream->flags = flags;
42 stream->state = initial_state;
43 stream->shut_flags = NGHTTP2_SHUT_NONE;
44 stream->stream_user_data = stream_user_data;
46 stream->remote_window_size = remote_initial_window_size;
47 stream->local_window_size = local_initial_window_size;
48 stream->recv_window_size = 0;
49 stream->consumed_size = 0;
50 stream->recv_reduction = 0;
52 stream->dep_prev = NULL;
53 stream->dep_next = NULL;
54 stream->sib_prev = NULL;
55 stream->sib_next = NULL;
57 stream->closed_prev = NULL;
58 stream->closed_next = NULL;
60 stream->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM;
61 stream->num_substreams = 1;
62 stream->weight = weight;
63 stream->effective_weight = stream->weight;
64 stream->sum_dep_weight = 0;
65 stream->sum_norest_weight = 0;
67 stream->roots = roots;
68 stream->root_prev = NULL;
69 stream->root_next = NULL;
71 stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
72 stream->content_length = -1;
73 stream->recv_content_length = 0;
74 stream->status_code = -1;
77 void nghttp2_stream_free(nghttp2_stream *stream _U_) {
78 /* We don't free stream->item. If it is assigned to aob, then
79 active_outbound_item_reset() will delete it. If it is queued,
80 then it is deleted when pq is deleted in nghttp2_session_del().
81 Otherwise, nghttp2_session_del() will delete it. */
84 void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
85 stream->shut_flags |= flag;
88 static int stream_push_item(nghttp2_stream *stream, nghttp2_session *session) {
89 /* This is required for Android NDK r10d */
91 nghttp2_outbound_item *item;
94 assert(stream->item->queued == 0);
98 /* If item is now sent, don't push it to the queue. Otherwise, we
99 may push same item twice. */
100 if (session->aob.item == item) {
104 switch (item->frame.hd.type) {
106 /* Penalize item by delaying scheduling according to effective
107 weight. This will delay low priority stream, which is good.
108 OTOH, this may incur delay for high priority item. Will
111 session->last_cycle +
112 NGHTTP2_DATA_PAYLOADLEN * NGHTTP2_MAX_WEIGHT / stream->effective_weight;
114 rv = nghttp2_pq_push(&session->ob_da_pq, item);
119 case NGHTTP2_HEADERS:
120 if (stream->state == NGHTTP2_STREAM_RESERVED) {
121 nghttp2_outbound_queue_push(&session->ob_syn, item);
123 nghttp2_outbound_queue_push(&session->ob_reg, item);
127 /* should not reach here */
136 static nghttp2_stream *stream_first_sib(nghttp2_stream *stream) {
137 for (; stream->sib_prev; stream = stream->sib_prev)
143 static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
144 for (; stream->sib_next; stream = stream->sib_next)
150 static nghttp2_stream *stream_update_dep_length(nghttp2_stream *stream,
152 stream->num_substreams += delta;
154 stream = stream_first_sib(stream);
156 if (stream->dep_prev) {
157 return stream_update_dep_length(stream->dep_prev, delta);
163 int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
165 weight = stream->weight * weight / stream->sum_dep_weight;
167 return nghttp2_max(1, weight);
170 int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
172 if (stream->sum_norest_weight == 0) {
173 return stream->effective_weight;
176 weight = stream->effective_weight * weight / stream->sum_norest_weight;
178 return nghttp2_max(1, weight);
181 static void stream_update_dep_set_rest(nghttp2_stream *stream);
183 /* Updates effective_weight of descendant streams in subtree of
184 |stream|. We assume that stream->effective_weight is already set
186 static void stream_update_dep_effective_weight(nghttp2_stream *stream) {
189 DEBUGF(fprintf(stderr, "stream: update_dep_effective_weight "
190 "stream(%p)=%d, weight=%d, sum_norest_weight=%d\n",
191 stream, stream->stream_id, stream->weight,
192 stream->sum_norest_weight));
194 /* stream->sum_norest_weight == 0 means there is no
195 NGHTTP2_STREAM_DPRI_TOP under stream */
196 if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_ITEM ||
197 stream->sum_norest_weight == 0) {
201 for (si = stream->dep_next; si; si = si->sib_next) {
202 if (si->dpri != NGHTTP2_STREAM_DPRI_REST) {
203 si->effective_weight =
204 nghttp2_stream_dep_distributed_effective_weight(stream, si->weight);
207 stream_update_dep_effective_weight(si);
211 static void stream_update_dep_set_rest(nghttp2_stream *stream) {
212 if (stream == NULL) {
216 DEBUGF(fprintf(stderr, "stream: stream=%d is rest\n", stream->stream_id));
218 if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
222 if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
223 stream->dpri = NGHTTP2_STREAM_DPRI_REST;
225 stream_update_dep_set_rest(stream->sib_next);
230 stream_update_dep_set_rest(stream->sib_next);
231 stream_update_dep_set_rest(stream->dep_next);
235 * Performs dfs starting |stream|, search stream which can become
236 * NGHTTP2_STREAM_DPRI_TOP and set its dpri.
238 static void stream_update_dep_set_top(nghttp2_stream *stream) {
241 if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
245 if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
247 fprintf(stderr, "stream: stream=%d item is top\n", stream->stream_id));
249 stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
254 for (si = stream->dep_next; si; si = si->sib_next) {
255 stream_update_dep_set_top(si);
260 * Performs dfs starting |stream|, and dueue stream whose dpri is
261 * NGHTTP2_STREAM_DPRI_TOP and has not been queued yet.
263 * This function returns 0 if it succeeds, or one of the following
264 * negative error codes:
269 static int stream_update_dep_queue_top(nghttp2_stream *stream,
270 nghttp2_session *session) {
274 if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
278 if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
279 if (!stream->item->queued) {
280 DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n", stream->stream_id));
281 rv = stream_push_item(stream, session);
291 for (si = stream->dep_next; si; si = si->sib_next) {
292 rv = stream_update_dep_queue_top(si, session);
303 * Updates stream->sum_norest_weight recursively. We have to gather
304 * effective sum of weight of descendants. If stream->dpri ==
305 * NGHTTP2_STREAM_DPRI_NO_ITEM, we have to go deeper and check that
306 * any of its descendants has dpri value of NGHTTP2_STREAM_DPRI_TOP.
307 * If so, we have to add weight of its direct descendants to
308 * stream->sum_norest_weight. To make this work, this function
309 * returns 1 if any of its descendants has dpri value of
310 * NGHTTP2_STREAM_DPRI_TOP, otherwise 0.
312 static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) {
316 stream->sum_norest_weight = 0;
318 if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
322 if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
328 for (si = stream->dep_next; si; si = si->sib_next) {
330 if (stream_update_dep_sum_norest_weight(si)) {
332 stream->sum_norest_weight += si->weight;
339 static int stream_update_dep_on_attach_item(nghttp2_stream *stream,
340 nghttp2_session *session) {
341 nghttp2_stream *root_stream;
343 stream->dpri = NGHTTP2_STREAM_DPRI_REST;
345 stream_update_dep_set_rest(stream->dep_next);
347 root_stream = nghttp2_stream_get_dep_root(stream);
349 DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream));
351 stream_update_dep_set_top(root_stream);
353 stream_update_dep_sum_norest_weight(root_stream);
354 stream_update_dep_effective_weight(root_stream);
356 return stream_update_dep_queue_top(root_stream, session);
359 static int stream_update_dep_on_detach_item(nghttp2_stream *stream,
360 nghttp2_session *session) {
361 nghttp2_stream *root_stream;
363 stream->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM;
365 root_stream = nghttp2_stream_get_dep_root(stream);
367 stream_update_dep_set_top(root_stream);
369 stream_update_dep_sum_norest_weight(root_stream);
370 stream_update_dep_effective_weight(root_stream);
372 return stream_update_dep_queue_top(root_stream, session);
375 int nghttp2_stream_attach_item(nghttp2_stream *stream,
376 nghttp2_outbound_item *item,
377 nghttp2_session *session) {
378 assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
379 assert(stream->item == NULL);
381 DEBUGF(fprintf(stderr, "stream: stream=%d attach item=%p\n",
382 stream->stream_id, item));
386 return stream_update_dep_on_attach_item(stream, session);
389 int nghttp2_stream_detach_item(nghttp2_stream *stream,
390 nghttp2_session *session) {
391 DEBUGF(fprintf(stderr, "stream: stream=%d detach item=%p\n",
392 stream->stream_id, stream->item));
395 stream->flags &= ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL;
397 return stream_update_dep_on_detach_item(stream, session);
400 int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags,
401 nghttp2_session *session) {
402 assert(stream->item);
404 DEBUGF(fprintf(stderr, "stream: stream=%d defer item=%p cause=%02x\n",
405 stream->stream_id, stream->item, flags));
407 stream->flags |= flags;
409 return stream_update_dep_on_detach_item(stream, session);
412 int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags,
413 nghttp2_session *session) {
414 assert(stream->item);
416 DEBUGF(fprintf(stderr, "stream: stream=%d resume item=%p flags=%02x\n",
417 stream->stream_id, stream->item, flags));
419 stream->flags &= ~flags;
421 if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
425 return stream_update_dep_on_attach_item(stream, session);
428 int nghttp2_stream_check_deferred_item(nghttp2_stream *stream) {
429 return stream->item && (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
432 int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream) {
433 return stream->item &&
434 (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
437 static int update_initial_window_size(int32_t *window_size_ptr,
438 int32_t new_initial_window_size,
439 int32_t old_initial_window_size) {
440 int64_t new_window_size = (int64_t)(*window_size_ptr) +
441 new_initial_window_size - old_initial_window_size;
442 if (INT32_MIN > new_window_size ||
443 new_window_size > NGHTTP2_MAX_WINDOW_SIZE) {
446 *window_size_ptr = (int32_t)new_window_size;
450 int nghttp2_stream_update_remote_initial_window_size(
451 nghttp2_stream *stream, int32_t new_initial_window_size,
452 int32_t old_initial_window_size) {
453 return update_initial_window_size(&stream->remote_window_size,
454 new_initial_window_size,
455 old_initial_window_size);
458 int nghttp2_stream_update_local_initial_window_size(
459 nghttp2_stream *stream, int32_t new_initial_window_size,
460 int32_t old_initial_window_size) {
461 return update_initial_window_size(&stream->local_window_size,
462 new_initial_window_size,
463 old_initial_window_size);
466 void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
467 stream->state = NGHTTP2_STREAM_OPENED;
468 stream->flags &= ~NGHTTP2_STREAM_FLAG_PUSH;
471 nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream) {
473 if (stream->sib_prev) {
474 stream = stream->sib_prev;
479 if (stream->dep_prev) {
480 stream = stream->dep_prev;
491 int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
492 nghttp2_stream *target) {
493 if (stream == NULL) {
497 if (stream == target) {
501 if (nghttp2_stream_dep_subtree_find(stream->sib_next, target)) {
505 return nghttp2_stream_dep_subtree_find(stream->dep_next, target);
508 void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
509 nghttp2_stream *stream) {
511 nghttp2_stream *root_stream;
513 assert(stream->item == NULL);
515 DEBUGF(fprintf(stderr,
516 "stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n",
517 dep_stream, dep_stream->stream_id, stream, stream->stream_id));
519 stream->sum_dep_weight = dep_stream->sum_dep_weight;
520 dep_stream->sum_dep_weight = stream->weight;
522 if (dep_stream->dep_next) {
523 for (si = dep_stream->dep_next; si; si = si->sib_next) {
524 stream->num_substreams += si->num_substreams;
527 stream->dep_next = dep_stream->dep_next;
528 stream->dep_next->dep_prev = stream;
531 dep_stream->dep_next = stream;
532 stream->dep_prev = dep_stream;
534 root_stream = stream_update_dep_length(dep_stream, 1);
536 stream_update_dep_sum_norest_weight(root_stream);
537 stream_update_dep_effective_weight(root_stream);
539 ++stream->roots->num_streams;
542 static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
543 dep_stream->dep_next = stream;
544 stream->dep_prev = dep_stream;
547 static void link_sib(nghttp2_stream *prev_stream, nghttp2_stream *stream) {
548 prev_stream->sib_next = stream;
549 stream->sib_prev = prev_stream;
552 static void insert_link_dep(nghttp2_stream *dep_stream,
553 nghttp2_stream *stream) {
554 nghttp2_stream *sib_next;
556 assert(stream->sib_prev == NULL);
558 sib_next = dep_stream->dep_next;
560 link_sib(stream, sib_next);
562 sib_next->dep_prev = NULL;
564 link_dep(dep_stream, stream);
567 static void unlink_sib(nghttp2_stream *stream) {
568 nghttp2_stream *prev, *next, *dep_next;
570 prev = stream->sib_prev;
571 dep_next = stream->dep_next;
577 * prev--stream(--sib_next--...)
581 dep_next->dep_prev = NULL;
583 link_sib(prev, dep_next);
585 if (stream->sib_next) {
586 link_sib(stream_last_sib(dep_next), stream->sib_next);
590 * prev--stream(--sib_next--...)
592 next = stream->sib_next;
594 prev->sib_next = next;
597 next->sib_prev = prev;
602 static void unlink_dep(nghttp2_stream *stream) {
603 nghttp2_stream *prev, *next, *dep_next;
605 prev = stream->dep_prev;
606 dep_next = stream->dep_next;
614 * stream(--sib_next--...)
618 link_dep(prev, dep_next);
620 if (stream->sib_next) {
621 link_sib(stream_last_sib(dep_next), stream->sib_next);
623 } else if (stream->sib_next) {
629 next = stream->sib_next;
631 next->sib_prev = NULL;
633 link_dep(prev, next);
635 prev->dep_next = NULL;
639 void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
640 nghttp2_stream *stream) {
641 nghttp2_stream *root_stream;
643 assert(stream->item == NULL);
645 DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
646 dep_stream, dep_stream->stream_id, stream, stream->stream_id));
648 root_stream = stream_update_dep_length(dep_stream, 1);
650 dep_stream->sum_dep_weight += stream->weight;
652 if (dep_stream->dep_next == NULL) {
653 link_dep(dep_stream, stream);
655 insert_link_dep(dep_stream, stream);
658 stream_update_dep_sum_norest_weight(root_stream);
659 stream_update_dep_effective_weight(root_stream);
661 ++stream->roots->num_streams;
664 void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
665 nghttp2_stream *prev, *next, *dep_prev, *si, *root_stream;
666 int32_t sum_dep_weight_delta;
670 DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n", stream,
673 /* Distribute weight of |stream| to direct descendants */
674 sum_dep_weight_delta = -stream->weight;
676 for (si = stream->dep_next; si; si = si->sib_next) {
677 si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
679 sum_dep_weight_delta += si->weight;
682 prev = stream_first_sib(stream);
684 dep_prev = prev->dep_prev;
687 root_stream = stream_update_dep_length(dep_prev, -1);
689 dep_prev->sum_dep_weight += sum_dep_weight_delta;
692 if (stream->sib_prev) {
694 } else if (stream->dep_prev) {
697 nghttp2_stream_roots_remove(stream->roots, stream);
699 /* stream is a root of tree. Removing stream makes its
700 descendants a root of its own subtree. */
702 for (si = stream->dep_next; si;) {
709 /* We already distributed weight of |stream| to this. */
710 si->effective_weight = si->weight;
712 nghttp2_stream_roots_add(si->roots, si);
719 stream_update_dep_sum_norest_weight(root_stream);
720 stream_update_dep_effective_weight(root_stream);
723 stream->num_substreams = 1;
724 stream->sum_dep_weight = 0;
726 stream->dep_prev = NULL;
727 stream->dep_next = NULL;
728 stream->sib_prev = NULL;
729 stream->sib_next = NULL;
731 --stream->roots->num_streams;
734 int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
735 nghttp2_stream *stream,
736 nghttp2_session *session) {
737 nghttp2_stream *last_sib;
738 nghttp2_stream *dep_next;
739 nghttp2_stream *root_stream;
740 size_t delta_substreams;
742 DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
744 dep_stream, dep_stream->stream_id, stream, stream->stream_id));
746 delta_substreams = stream->num_substreams;
748 stream_update_dep_set_rest(stream);
750 if (dep_stream->dep_next) {
751 /* dep_stream->num_substreams includes dep_stream itself */
752 stream->num_substreams += dep_stream->num_substreams - 1;
754 stream->sum_dep_weight += dep_stream->sum_dep_weight;
755 dep_stream->sum_dep_weight = stream->weight;
757 dep_next = dep_stream->dep_next;
759 stream_update_dep_set_rest(dep_next);
761 link_dep(dep_stream, stream);
763 if (stream->dep_next) {
764 last_sib = stream_last_sib(stream->dep_next);
766 link_sib(last_sib, dep_next);
768 dep_next->dep_prev = NULL;
770 link_dep(stream, dep_next);
773 link_dep(dep_stream, stream);
775 assert(dep_stream->sum_dep_weight == 0);
776 dep_stream->sum_dep_weight = stream->weight;
779 root_stream = stream_update_dep_length(dep_stream, delta_substreams);
781 stream_update_dep_set_top(root_stream);
783 stream_update_dep_sum_norest_weight(root_stream);
784 stream_update_dep_effective_weight(root_stream);
786 return stream_update_dep_queue_top(root_stream, session);
789 int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
790 nghttp2_stream *stream,
791 nghttp2_session *session) {
792 nghttp2_stream *root_stream;
794 DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
796 dep_stream, dep_stream->stream_id, stream, stream->stream_id));
798 stream_update_dep_set_rest(stream);
800 if (dep_stream->dep_next) {
801 dep_stream->sum_dep_weight += stream->weight;
803 insert_link_dep(dep_stream, stream);
805 link_dep(dep_stream, stream);
807 assert(dep_stream->sum_dep_weight == 0);
808 dep_stream->sum_dep_weight = stream->weight;
811 root_stream = stream_update_dep_length(dep_stream, stream->num_substreams);
813 stream_update_dep_set_top(root_stream);
815 stream_update_dep_sum_norest_weight(root_stream);
816 stream_update_dep_effective_weight(root_stream);
818 return stream_update_dep_queue_top(root_stream, session);
821 void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
822 nghttp2_stream *prev, *next, *dep_prev, *root_stream;
824 DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n", stream,
827 if (stream->sib_prev) {
828 prev = stream->sib_prev;
830 prev->sib_next = stream->sib_next;
831 if (prev->sib_next) {
832 prev->sib_next->sib_prev = prev;
835 prev = stream_first_sib(prev);
837 dep_prev = prev->dep_prev;
839 } else if (stream->dep_prev) {
840 dep_prev = stream->dep_prev;
841 next = stream->sib_next;
843 dep_prev->dep_next = next;
846 next->dep_prev = dep_prev;
848 next->sib_prev = NULL;
852 nghttp2_stream_roots_remove(stream->roots, stream);
858 dep_prev->sum_dep_weight -= stream->weight;
860 root_stream = stream_update_dep_length(dep_prev, -stream->num_substreams);
862 stream_update_dep_sum_norest_weight(root_stream);
863 stream_update_dep_effective_weight(root_stream);
866 stream->sib_prev = NULL;
867 stream->sib_next = NULL;
868 stream->dep_prev = NULL;
871 int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
872 nghttp2_session *session) {
873 DEBUGF(fprintf(stderr, "stream: dep_make_root stream(%p)=%d\n", stream,
876 nghttp2_stream_roots_add(stream->roots, stream);
878 stream_update_dep_set_rest(stream);
880 stream->effective_weight = stream->weight;
882 stream_update_dep_set_top(stream);
884 stream_update_dep_sum_norest_weight(stream);
885 stream_update_dep_effective_weight(stream);
887 return stream_update_dep_queue_top(stream, session);
891 nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
892 nghttp2_session *session) {
893 nghttp2_stream *first, *si;
895 DEBUGF(fprintf(stderr, "stream: ALL YOUR STREAM ARE BELONG TO US "
897 stream, stream->stream_id));
899 first = stream->roots->head;
901 /* stream must not be include in stream->roots->head list */
902 assert(first != stream);
905 nghttp2_stream *prev;
909 DEBUGF(fprintf(stderr, "stream: root stream(%p)=%d\n", first,
912 stream->sum_dep_weight += first->weight;
913 stream->num_substreams += first->num_substreams;
915 for (si = first->root_next; si; si = si->root_next) {
917 assert(si != stream);
920 fprintf(stderr, "stream: root stream(%p)=%d\n", si, si->stream_id));
922 stream->sum_dep_weight += si->weight;
923 stream->num_substreams += si->num_substreams;
930 if (stream->dep_next) {
931 nghttp2_stream *sib_next;
933 sib_next = stream->dep_next;
935 sib_next->dep_prev = NULL;
937 link_sib(first, sib_next);
938 link_dep(stream, prev);
940 link_dep(stream, first);
944 nghttp2_stream_roots_remove_all(stream->roots);
946 return nghttp2_stream_dep_make_root(stream, session);
949 int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) {
950 return stream->dep_prev || stream->dep_next || stream->sib_prev ||
951 stream->sib_next || stream->root_next || stream->root_prev ||
952 stream->roots->head == stream;
955 void nghttp2_stream_roots_init(nghttp2_stream_roots *roots) {
957 roots->num_streams = 0;
960 void nghttp2_stream_roots_free(nghttp2_stream_roots *roots _U_) {}
962 void nghttp2_stream_roots_add(nghttp2_stream_roots *roots,
963 nghttp2_stream *stream) {
965 stream->root_next = roots->head;
966 roots->head->root_prev = stream;
969 roots->head = stream;
972 void nghttp2_stream_roots_remove(nghttp2_stream_roots *roots,
973 nghttp2_stream *stream) {
974 nghttp2_stream *root_prev, *root_next;
976 root_prev = stream->root_prev;
977 root_next = stream->root_next;
980 root_prev->root_next = root_next;
983 root_next->root_prev = root_prev;
987 root_next->root_prev = NULL;
990 roots->head = root_next;
993 stream->root_prev = NULL;
994 stream->root_next = NULL;
997 void nghttp2_stream_roots_remove_all(nghttp2_stream_roots *roots) {
998 nghttp2_stream *si, *next;
1000 for (si = roots->head; si;) {
1001 next = si->root_next;
1003 si->root_prev = NULL;
1004 si->root_next = NULL;