diff options
Diffstat (limited to 'modules/http2/h2_stream.h')
-rw-r--r-- | modules/http2/h2_stream.h | 129 |
1 files changed, 82 insertions, 47 deletions
diff --git a/modules/http2/h2_stream.h b/modules/http2/h2_stream.h index 7ecc0ad..405978a 100644 --- a/modules/http2/h2_stream.h +++ b/modules/http2/h2_stream.h @@ -17,7 +17,10 @@ #ifndef __mod_h2__h2_stream__ #define __mod_h2__h2_stream__ +#include <http_protocol.h> + #include "h2.h" +#include "h2_headers.h" /** * A HTTP/2 stream, e.g. a client request+response in HTTP/1.1 terms. @@ -26,8 +29,8 @@ * connection to the client. The h2_session writes to the h2_stream, * adding HEADERS and DATA and finally an EOS. When headers are done, * h2_stream is scheduled for handling, which is expected to produce - * a response h2_headers at least. - * + * h2_headers/RESPONSE buckets. + * * The h2_headers may be followed by more h2_headers (interim responses) and * by DATA frames read from the h2_stream until EOS is reached. Trailers * are send when a last h2_headers is received. This always closes the stream @@ -37,9 +40,7 @@ struct h2_mplx; struct h2_priority; struct h2_request; -struct h2_headers; struct h2_session; -struct h2_task; struct h2_bucket_beam; typedef struct h2_stream h2_stream; @@ -62,7 +63,22 @@ typedef struct h2_stream_monitor { trigger a state change */ } h2_stream_monitor; +#ifdef AP_DEBUG +#define H2_STRM_MAGIC_OK 0x5354524d +#define H2_STRM_MAGIC_SDEL 0x5344454c +#define H2_STRM_MAGIC_PDEL 0x5044454c + +#define H2_STRM_ASSIGN_MAGIC(s,m) ((s)->magic = m) +#define H2_STRM_ASSERT_MAGIC(s,m) ap_assert((s)->magic == m) +#else +#define H2_STRM_ASSIGN_MAGIC(s,m) ((void)0) +#define H2_STRM_ASSERT_MAGIC(s,m) ((void)0) +#endif + struct h2_stream { +#ifdef AP_DEBUG + uint32_t magic; +#endif int id; /* http2 stream identifier */ int initiated_on; /* initiating stream id (PUSH) or 0 */ apr_pool_t *pool; /* the memory pool for this stream */ @@ -73,9 +89,16 @@ struct h2_stream { const struct h2_request *request; /* the request made in this stream */ struct h2_request *rtmp; /* request being assembled */ - apr_table_t *trailers; /* optional incoming trailers */ + apr_table_t *trailers_in; /* optional, incoming trailers */ int request_headers_added; /* number of request headers added */ - + int request_headers_failed; /* number of request headers failed to add */ + +#if AP_HAS_RESPONSE_BUCKETS + ap_bucket_response *response; /* the final, non-interim response or NULL */ +#else + struct h2_headers *response; /* the final, non-interim response or NULL */ +#endif + struct h2_bucket_beam *input; apr_bucket_brigade *in_buffer; int in_window_size; @@ -83,17 +106,16 @@ struct h2_stream { struct h2_bucket_beam *output; apr_bucket_brigade *out_buffer; - apr_size_t max_mem; /* maximum amount of data buffered */ int rst_error; /* stream error for RST_STREAM */ unsigned int aborted : 1; /* was aborted */ unsigned int scheduled : 1; /* stream has been scheduled */ - unsigned int has_response : 1; /* response headers are known */ - unsigned int input_eof : 1; /* no more request data coming */ - unsigned int out_checked : 1; /* output eof was double checked */ + unsigned int input_closed : 1; /* no more request data/trailers coming */ unsigned int push_policy; /* which push policy to use for this request */ - - struct h2_task *task; /* assigned task to fullfill request */ + unsigned int sent_trailers : 1; /* trailers have been submitted */ + unsigned int output_eos : 1; /* output EOS in buffer/sent */ + + conn_rec *c2; /* connection processing stream */ const h2_priority *pref_priority; /* preferred priority for this stream */ apr_off_t out_frames; /* # of frames sent out */ @@ -132,13 +154,9 @@ h2_stream *h2_stream_create(int id, apr_pool_t *pool, void h2_stream_destroy(h2_stream *stream); /** - * Prepare the stream so that processing may start. - * - * This is the time to allocated resources not needed before. - * - * @param stream the stream to prep + * Perform any late initialization before stream starts processing. */ -apr_status_t h2_stream_prep_processing(h2_stream *stream); +apr_status_t h2_stream_prepare_processing(h2_stream *stream); /* * Set a new monitor for this stream, replacing any existing one. Can @@ -154,6 +172,22 @@ void h2_stream_set_monitor(h2_stream *stream, h2_stream_monitor *monitor); void h2_stream_dispatch(h2_stream *stream, h2_stream_event_t ev); /** + * Determine if stream is at given state. + * @param stream the stream to check + * @param state the state to look for + * @return != 0 iff stream is at given state. + */ +int h2_stream_is_at(const h2_stream *stream, h2_stream_state_t state); + +/** + * Determine if stream is reached given state or is past this state. + * @param stream the stream to check + * @param state the state to look for + * @return != 0 iff stream is at or past given state. + */ +int h2_stream_is_at_or_past(const h2_stream *stream, h2_stream_state_t state); + +/** * Cleanup references into requst processing. * * @param stream the stream to cleanup @@ -198,6 +232,10 @@ apr_status_t h2_stream_set_request_rec(h2_stream *stream, apr_status_t h2_stream_add_header(h2_stream *stream, const char *name, size_t nlen, const char *value, size_t vlen); + +/* End the construction of request headers */ +apr_status_t h2_stream_end_headers(h2_stream *stream, int eos, size_t raw_bytes); + apr_status_t h2_stream_send_frame(h2_stream *stream, int frame_type, int flags, size_t frame_len); apr_status_t h2_stream_recv_frame(h2_stream *stream, int frame_type, int flags, size_t frame_len); @@ -213,8 +251,6 @@ apr_status_t h2_stream_recv_frame(h2_stream *stream, int frame_type, int flags, apr_status_t h2_stream_recv_DATA(h2_stream *stream, uint8_t flags, const uint8_t *data, size_t len); -apr_status_t h2_stream_flush_input(h2_stream *stream); - /** * Reset the stream. Stream write/reads will return errors afterwards. * @@ -224,31 +260,16 @@ apr_status_t h2_stream_flush_input(h2_stream *stream); void h2_stream_rst(h2_stream *stream, int error_code); /** - * Determine if stream was closed already. This is true for - * states H2_SS_CLOSED, H2_SS_CLEANUP. But not true - * for H2_SS_CLOSED_L and H2_SS_CLOSED_R. - * - * @param stream the stream to check on - * @return != 0 iff stream has been closed + * Stream input signals change. Take necessary actions. + * @param stream the stream to read output for */ -int h2_stream_was_closed(const h2_stream *stream); +void h2_stream_on_input_change(h2_stream *stream); /** - * Do a speculative read on the stream output to determine the - * amount of data that can be read. - * - * @param stream the stream to speculatively read from - * @param plen (in-/out) number of bytes requested and on return amount of bytes that - * may be read without blocking - * @param peos (out) != 0 iff end of stream will be reached when reading plen - * bytes (out value). - * @param presponse (out) the response of one became available - * @return APR_SUCCESS if out information was computed successfully. - * APR_EAGAIN if not data is available and end of stream has not been - * reached yet. + * Stream output signals change. Take necessary actions. + * @param stream the stream to read output for */ -apr_status_t h2_stream_out_prepare(h2_stream *stream, apr_off_t *plen, - int *peos, h2_headers **presponse); +void h2_stream_on_output_change(h2_stream *stream); /** * Read a maximum number of bytes into the bucket brigade. @@ -277,23 +298,34 @@ apr_table_t *h2_stream_get_trailers(h2_stream *stream); /** * Submit any server push promises on this stream and schedule - * the tasks connection with these. + * the streams for these. * * @param stream the stream for which to submit */ -apr_status_t h2_stream_submit_pushes(h2_stream *stream, h2_headers *response); +#if AP_HAS_RESPONSE_BUCKETS +apr_status_t h2_stream_submit_pushes(h2_stream *stream, + ap_bucket_response *response); +#else +apr_status_t h2_stream_submit_pushes(h2_stream *stream, + struct h2_headers *response); +#endif /** * Get priority information set for this stream. */ -const struct h2_priority *h2_stream_get_priority(h2_stream *stream, - h2_headers *response); +#if AP_HAS_RESPONSE_BUCKETS +const struct h2_priority *h2_stream_get_priority(h2_stream *stream, + ap_bucket_response *response); +#else +const struct h2_priority *h2_stream_get_priority(h2_stream *stream, + struct h2_headers *response); +#endif /** * Return a textual representation of the stream state as in RFC 7540 * nomenclator, all caps, underscores. */ -const char *h2_stream_state_str(h2_stream *stream); +const char *h2_stream_state_str(const h2_stream *stream); /** * Determine if stream is ready for submitting a response or a RST @@ -301,8 +333,11 @@ const char *h2_stream_state_str(h2_stream *stream); */ int h2_stream_is_ready(h2_stream *stream); +int h2_stream_wants_send_data(h2_stream *stream); + #define H2_STRM_MSG(s, msg) \ - "h2_stream(%ld-%d,%s): "msg, s->session->id, s->id, h2_stream_state_str(s) + "h2_stream(%d-%lu-%d,%s): "msg, s->session->child_num, \ + (unsigned long)s->session->id, s->id, h2_stream_state_str(s) #define H2_STRM_LOG(aplogno, s, msg) aplogno H2_STRM_MSG(s, msg) |