Path: blob/master/Utilities/cmnghttp2/lib/nghttp2_stream.h
3153 views
/*1* nghttp2 - HTTP/2 C Library2*3* Copyright (c) 2012 Tatsuhiro Tsujikawa4*5* Permission is hereby granted, free of charge, to any person obtaining6* a copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sublicense, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice shall be14* included in all copies or substantial portions of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,17* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND19* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE20* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION21* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION22* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23*/24#ifndef NGHTTP2_STREAM_H25#define NGHTTP2_STREAM_H2627#ifdef HAVE_CONFIG_H28# include <config.h>29#endif /* HAVE_CONFIG_H */3031#include <nghttp2/nghttp2.h>32#include "nghttp2_outbound_item.h"33#include "nghttp2_map.h"34#include "nghttp2_pq.h"35#include "nghttp2_int.h"3637/*38* If local peer is stream initiator:39* NGHTTP2_STREAM_OPENING : upon sending request HEADERS40* NGHTTP2_STREAM_OPENED : upon receiving response HEADERS41* NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM42*43* If remote peer is stream initiator:44* NGHTTP2_STREAM_OPENING : upon receiving request HEADERS45* NGHTTP2_STREAM_OPENED : upon sending response HEADERS46* NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM47*/48typedef enum {49/* Initial state */50NGHTTP2_STREAM_INITIAL,51/* For stream initiator: request HEADERS has been sent, but response52HEADERS has not been received yet. For receiver: request HEADERS53has been received, but it does not send response HEADERS yet. */54NGHTTP2_STREAM_OPENING,55/* For stream initiator: response HEADERS is received. For receiver:56response HEADERS is sent. */57NGHTTP2_STREAM_OPENED,58/* RST_STREAM is received, but somehow we need to keep stream in59memory. */60NGHTTP2_STREAM_CLOSING,61/* PUSH_PROMISE is received or sent */62NGHTTP2_STREAM_RESERVED,63/* Stream is created in this state if it is used as anchor in64dependency tree. */65NGHTTP2_STREAM_IDLE66} nghttp2_stream_state;6768typedef enum {69NGHTTP2_SHUT_NONE = 0,70/* Indicates further receptions will be disallowed. */71NGHTTP2_SHUT_RD = 0x01,72/* Indicates further transmissions will be disallowed. */73NGHTTP2_SHUT_WR = 0x02,74/* Indicates both further receptions and transmissions will be75disallowed. */76NGHTTP2_SHUT_RDWR = NGHTTP2_SHUT_RD | NGHTTP2_SHUT_WR77} nghttp2_shut_flag;7879typedef enum {80NGHTTP2_STREAM_FLAG_NONE = 0,81/* Indicates that this stream is pushed stream and not opened82yet. */83NGHTTP2_STREAM_FLAG_PUSH = 0x01,84/* Indicates that this stream was closed */85NGHTTP2_STREAM_FLAG_CLOSED = 0x02,86/* Indicates the item is deferred due to flow control. */87NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL = 0x04,88/* Indicates the item is deferred by user callback */89NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08,90/* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and91NGHTTP2_STREAM_FLAG_DEFERRED_USER. */92NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c,93/* Indicates that this stream is not subject to RFC754094priorities scheme. */95NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES = 0x10,96/* Ignore client RFC 9218 priority signal. */97NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,98/* Indicates that RFC 9113 leading and trailing white spaces99validation against a field value is not performed. */100NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 0x40,101} nghttp2_stream_flag;102103/* HTTP related flags to enforce HTTP semantics */104typedef enum {105NGHTTP2_HTTP_FLAG_NONE = 0,106/* header field seen so far */107NGHTTP2_HTTP_FLAG__AUTHORITY = 1,108NGHTTP2_HTTP_FLAG__PATH = 1 << 1,109NGHTTP2_HTTP_FLAG__METHOD = 1 << 2,110NGHTTP2_HTTP_FLAG__SCHEME = 1 << 3,111/* host is not pseudo header, but we require either host or112:authority */113NGHTTP2_HTTP_FLAG_HOST = 1 << 4,114NGHTTP2_HTTP_FLAG__STATUS = 1 << 5,115/* required header fields for HTTP request except for CONNECT116method. */117NGHTTP2_HTTP_FLAG_REQ_HEADERS = NGHTTP2_HTTP_FLAG__METHOD |118NGHTTP2_HTTP_FLAG__PATH |119NGHTTP2_HTTP_FLAG__SCHEME,120NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED = 1 << 6,121/* HTTP method flags */122NGHTTP2_HTTP_FLAG_METH_CONNECT = 1 << 7,123NGHTTP2_HTTP_FLAG_METH_HEAD = 1 << 8,124NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9,125NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10,126NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT |127NGHTTP2_HTTP_FLAG_METH_HEAD |128NGHTTP2_HTTP_FLAG_METH_OPTIONS |129NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,130/* :path category */131/* path starts with "/" */132NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11,133/* path "*" */134NGHTTP2_HTTP_FLAG_PATH_ASTERISK = 1 << 12,135/* scheme */136/* "http" or "https" scheme */137NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,138/* set if final response is expected */139NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14,140NGHTTP2_HTTP_FLAG__PROTOCOL = 1 << 15,141/* set if priority header field is received */142NGHTTP2_HTTP_FLAG_PRIORITY = 1 << 16,143/* set if an error is encountered while parsing priority header144field */145NGHTTP2_HTTP_FLAG_BAD_PRIORITY = 1 << 17,146} nghttp2_http_flag;147148struct nghttp2_stream {149/* Entry for dep_prev->obq */150nghttp2_pq_entry pq_entry;151/* Priority Queue storing direct descendant (nghttp2_stream). Only152streams which itself has some data to send, or has a descendant153which has some data to sent. */154nghttp2_pq obq;155/* Content-Length of request/response body. -1 if unknown. */156int64_t content_length;157/* Received body so far */158int64_t recv_content_length;159/* Base last_cycle for direct descendent streams. */160uint64_t descendant_last_cycle;161/* Next scheduled time to sent item */162uint64_t cycle;163/* Next seq used for direct descendant streams */164uint64_t descendant_next_seq;165/* Secondary key for prioritization to break a tie for cycle. This166value is monotonically increased for single parent stream. */167uint64_t seq;168/* pointers to form dependency tree. If multiple streams depend on169a stream, only one stream (left most) has non-NULL dep_prev which170points to the stream it depends on. The remaining streams are171linked using sib_prev and sib_next. The stream which has172non-NULL dep_prev always NULL sib_prev. The right most stream173has NULL sib_next. If this stream is a root of dependency tree,174dep_prev and sib_prev are NULL. */175nghttp2_stream *dep_prev, *dep_next;176nghttp2_stream *sib_prev, *sib_next;177/* When stream is kept after closure, it may be kept in doubly178linked list pointed by nghttp2_session closed_stream_head.179closed_next points to the next stream object if it is the element180of the list. */181nghttp2_stream *closed_prev, *closed_next;182/* The arbitrary data provided by user for this stream. */183void *stream_user_data;184/* Item to send */185nghttp2_outbound_item *item;186/* Last written length of frame payload */187size_t last_writelen;188/* stream ID */189int32_t stream_id;190/* Current remote window size. This value is computed against the191current initial window size of remote endpoint. */192int32_t remote_window_size;193/* Keep track of the number of bytes received without194WINDOW_UPDATE. This could be negative after submitting negative195value to WINDOW_UPDATE */196int32_t recv_window_size;197/* The number of bytes consumed by the application and now is198subject to WINDOW_UPDATE. This is only used when auto199WINDOW_UPDATE is turned off. */200int32_t consumed_size;201/* The amount of recv_window_size cut using submitting negative202value to WINDOW_UPDATE */203int32_t recv_reduction;204/* window size for local flow control. It is initially set to205NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by206submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */207int32_t local_window_size;208/* weight of this stream */209int32_t weight;210/* This is unpaid penalty (offset) when calculating cycle. */211uint32_t pending_penalty;212/* sum of weight of direct descendants */213int32_t sum_dep_weight;214nghttp2_stream_state state;215/* status code from remote server */216int16_t status_code;217/* Bitwise OR of zero or more nghttp2_http_flag values */218uint32_t http_flags;219/* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */220uint8_t flags;221/* Bitwise OR of zero or more nghttp2_shut_flag values */222uint8_t shut_flags;223/* Nonzero if this stream has been queued to stream pointed by224dep_prev. We maintain the invariant that if a stream is queued,225then its ancestors, except for root, are also queued. This226invariant may break in fatal error condition. */227uint8_t queued;228/* This flag is used to reduce excessive queuing of WINDOW_UPDATE to229this stream. The nonzero does not necessarily mean WINDOW_UPDATE230is not queued. */231uint8_t window_update_queued;232/* extpri is a stream priority produced by nghttp2_extpri_to_uint8233used by RFC 9218 extensible priorities. */234uint8_t extpri;235/* http_extpri is a stream priority received in HTTP request header236fields and produced by nghttp2_extpri_to_uint8. */237uint8_t http_extpri;238};239240void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,241uint8_t flags, nghttp2_stream_state initial_state,242int32_t weight, int32_t remote_initial_window_size,243int32_t local_initial_window_size,244void *stream_user_data, nghttp2_mem *mem);245246void nghttp2_stream_free(nghttp2_stream *stream);247248/*249* Disallow either further receptions or transmissions, or both.250* |flag| is bitwise OR of one or more of nghttp2_shut_flag.251*/252void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);253254/*255* Defer |stream->item|. We won't call this function in the situation256* where |stream->item| == NULL. The |flags| is bitwise OR of zero or257* more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and258* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates259* the reason of this action.260*261* This function returns 0 if it succeeds, or one of the following262* negative error codes:263*264* NGHTTP2_ERR_NOMEM265* Out of memory266*/267int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);268269/*270* Put back deferred data in this stream to active state. The |flags|271* are one or more of bitwise OR of the following values:272* NGHTTP2_STREAM_FLAG_DEFERRED_USER and273* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are274* cleared if they are set. So even if this function is called, if275* one of flag is still set, data does not become active.276*277* This function returns 0 if it succeeds, or one of the following278* negative error codes:279*280* NGHTTP2_ERR_NOMEM281* Out of memory282*/283int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);284285/*286* Returns nonzero if item is deferred by whatever reason.287*/288int nghttp2_stream_check_deferred_item(nghttp2_stream *stream);289290/*291* Returns nonzero if item is deferred by flow control.292*/293int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream);294295/*296* Updates the remote window size with the new value297* |new_initial_window_size|. The |old_initial_window_size| is used to298* calculate the current window size.299*300* This function returns 0 if it succeeds or -1. The failure is due to301* overflow.302*/303int nghttp2_stream_update_remote_initial_window_size(304nghttp2_stream *stream, int32_t new_initial_window_size,305int32_t old_initial_window_size);306307/*308* Updates the local window size with the new value309* |new_initial_window_size|. The |old_initial_window_size| is used to310* calculate the current window size.311*312* This function returns 0 if it succeeds or -1. The failure is due to313* overflow.314*/315int nghttp2_stream_update_local_initial_window_size(316nghttp2_stream *stream, int32_t new_initial_window_size,317int32_t old_initial_window_size);318319/*320* Call this function if promised stream |stream| is replied with321* HEADERS. This function makes the state of the |stream| to322* NGHTTP2_STREAM_OPENED.323*/324void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);325326/*327* Returns nonzero if |target| is an ancestor of |stream|.328*/329int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,330nghttp2_stream *target);331332/*333* Computes distributed weight of a stream of the |weight| under the334* |stream| if |stream| is removed from a dependency tree.335*/336int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,337int32_t weight);338339/*340* Makes the |stream| depend on the |dep_stream|. This dependency is341* exclusive. All existing direct descendants of |dep_stream| become342* the descendants of the |stream|. This function assumes343* |stream->item| is NULL.344*345* This function returns 0 if it succeeds, or one of the following346* negative error codes:347*348* NGHTTP2_ERR_NOMEM349* Out of memory350*/351int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,352nghttp2_stream *stream);353354/*355* Makes the |stream| depend on the |dep_stream|. This dependency is356* not exclusive. This function assumes |stream->item| is NULL.357*/358void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);359360/*361* Removes the |stream| from the current dependency tree. This362* function assumes |stream->item| is NULL.363*/364int nghttp2_stream_dep_remove(nghttp2_stream *stream);365366/*367* Attaches |item| to |stream|.368*369* This function returns 0 if it succeeds, or one of the following370* negative error codes:371*372* NGHTTP2_ERR_NOMEM373* Out of memory374*/375int nghttp2_stream_attach_item(nghttp2_stream *stream,376nghttp2_outbound_item *item);377378/*379* Detaches |stream->item|. This function does not free380* |stream->item|. The caller must free it.381*382* This function returns 0 if it succeeds, or one of the following383* negative error codes:384*385* NGHTTP2_ERR_NOMEM386* Out of memory387*/388int nghttp2_stream_detach_item(nghttp2_stream *stream);389390/*391* Makes the |stream| depend on the |dep_stream|. This dependency is392* exclusive.393*394* This function returns 0 if it succeeds, or one of the following395* negative error codes:396*397* NGHTTP2_ERR_NOMEM398* Out of memory399*/400int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,401nghttp2_stream *stream);402403/*404* Makes the |stream| depend on the |dep_stream|. This dependency is405* not exclusive.406*407* This function returns 0 if it succeeds, or one of the following408* negative error codes:409*410* NGHTTP2_ERR_NOMEM411* Out of memory412*/413int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,414nghttp2_stream *stream);415416/*417* Removes subtree whose root stream is |stream|. The418* effective_weight of streams in removed subtree is not updated.419*420* This function returns 0 if it succeeds, or one of the following421* negative error codes:422*423* NGHTTP2_ERR_NOMEM424* Out of memory425*/426void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);427428/*429* Returns nonzero if |stream| is in any dependency tree.430*/431int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);432433/*434* Schedules transmission of |stream|'s item, assuming stream->item is435* attached, and stream->last_writelen was updated.436*/437void nghttp2_stream_reschedule(nghttp2_stream *stream);438439/*440* Changes |stream|'s weight to |weight|. If |stream| is queued, it441* will be rescheduled based on new weight.442*/443void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight);444445/*446* Returns a stream which has highest priority, updating447* descendant_last_cycle of selected stream's ancestors.448*/449nghttp2_outbound_item *450nghttp2_stream_next_outbound_item(nghttp2_stream *stream);451452#endif /* NGHTTP2_STREAM */453454455