1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __mod_h2__h2_session__
#define __mod_h2__h2_session__
#include "h2_conn_io.h"
/**
* A HTTP/2 connection, a session with a specific client.
*
* h2_session sits on top of a httpd conn_rec* instance and takes complete
* control of the connection data. It receives protocol frames from the
* client. For new HTTP/2 streams it creates h2_task(s) that are sent
* via callback to a dispatcher (see h2_conn.c).
* h2_session keeps h2_io's for each ongoing stream which buffer the
* payload for that stream.
*
* New incoming HEADER frames are converted into a h2_stream+h2_task instance
* that both represent a HTTP/2 stream, but may have separate lifetimes. This
* allows h2_task to be scheduled in other threads without semaphores
* all over the place. It allows task memory to be freed independent of
* session lifetime and sessions may close down while tasks are still running.
*
*
*/
#include "h2.h"
struct apr_thread_mutext_t;
struct apr_thread_cond_t;
struct h2_ctx;
struct h2_config;
struct h2_filter_cin;
struct h2_ihash_t;
struct h2_mplx;
struct h2_priority;
struct h2_push;
struct h2_push_diary;
struct h2_session;
struct h2_stream;
struct h2_stream_monitor;
struct h2_task;
struct h2_workers;
struct nghttp2_session;
typedef enum {
H2_SESSION_EV_INIT, /* session was initialized */
H2_SESSION_EV_LOCAL_GOAWAY, /* we send a GOAWAY */
H2_SESSION_EV_REMOTE_GOAWAY, /* remote send us a GOAWAY */
H2_SESSION_EV_CONN_ERROR, /* connection error */
H2_SESSION_EV_PROTO_ERROR, /* protocol error */
H2_SESSION_EV_CONN_TIMEOUT, /* connection timeout */
H2_SESSION_EV_NO_IO, /* nothing has been read or written */
H2_SESSION_EV_FRAME_RCVD, /* a frame has been received */
H2_SESSION_EV_NGH2_DONE, /* nghttp2 wants neither read nor write anything */
H2_SESSION_EV_MPM_STOPPING, /* the process is stopping */
H2_SESSION_EV_PRE_CLOSE, /* connection will close after this */
H2_SESSION_EV_STREAM_CHANGE, /* a stream (state/input/output) changed */
} h2_session_event_t;
typedef struct h2_session {
long id; /* identifier of this session, unique
* inside a httpd process */
conn_rec *c; /* the connection this session serves */
request_rec *r; /* the request that started this in case
* of 'h2c', NULL otherwise */
server_rec *s; /* server/vhost we're starting on */
apr_pool_t *pool; /* pool to use in session */
struct h2_mplx *mplx; /* multiplexer for stream data */
struct h2_workers *workers; /* for executing stream tasks */
struct h2_filter_cin *cin; /* connection input filter context */
h2_conn_io io; /* io on httpd conn filters */
int padding_max; /* max number of padding bytes */
int padding_always; /* padding has precedence over I/O optimizations */
struct nghttp2_session *ngh2; /* the nghttp2 session (internal use) */
h2_session_state state; /* state session is in */
h2_session_props local; /* properties of local session */
h2_session_props remote; /* properites of remote session */
unsigned int reprioritize : 1; /* scheduled streams priority changed */
unsigned int flush : 1; /* flushing output necessary */
unsigned int have_read : 1; /* session has read client data */
unsigned int have_written : 1; /* session did write data to client */
apr_interval_time_t wait_us; /* timeout during BUSY_WAIT state, micro secs */
struct h2_push_diary *push_diary; /* remember pushes, avoid duplicates */
struct h2_stream_monitor *monitor;/* monitor callbacks for streams */
int open_streams; /* number of client streams open */
int unsent_submits; /* number of submitted, but not yet written responses. */
int unsent_promises; /* number of submitted, but not yet written push promises */
int responses_submitted; /* number of http/2 responses submitted */
int streams_reset; /* number of http/2 streams reset by client */
int pushes_promised; /* number of http/2 push promises submitted */
int pushes_submitted; /* number of http/2 pushed responses submitted */
int pushes_reset; /* number of http/2 pushed reset by client */
apr_size_t frames_received; /* number of http/2 frames received */
apr_size_t frames_sent; /* number of http/2 frames sent */
apr_size_t max_stream_count; /* max number of open streams */
apr_size_t max_stream_mem; /* max buffer memory for a single stream */
apr_time_t idle_until; /* Time we shut down due to sheer boredom */
apr_time_t idle_sync_until; /* Time we sync wait until keepalive handling kicks in */
apr_size_t idle_frames; /* number of rcvd frames that kept session in idle state */
apr_interval_time_t idle_delay; /* Time we delay processing rcvd frames in idle state */
apr_bucket_brigade *bbtmp; /* brigade for keeping temporary data */
struct apr_thread_cond_t *iowait; /* our cond when trywaiting for data */
char status[64]; /* status message for scoreboard */
int last_status_code; /* the one already reported */
const char *last_status_msg; /* the one already reported */
struct h2_iqueue *in_pending; /* all streams with input pending */
struct h2_iqueue *in_process; /* all streams ready for processing on a secondary */
} h2_session;
const char *h2_session_state_str(h2_session_state state);
/**
* Create a new h2_session for the given connection.
* The session will apply the configured parameter.
* @param psession pointer receiving the created session on success or NULL
* @param c the connection to work on
* @param r optional request when protocol was upgraded
* @param cfg the module config to apply
* @param workers the worker pool to use
* @return the created session
*/
apr_status_t h2_session_create(h2_session **psession,
conn_rec *c, request_rec *r, server_rec *,
struct h2_workers *workers);
void h2_session_event(h2_session *session, h2_session_event_t ev,
int err, const char *msg);
/**
* Process the given HTTP/2 session until it is ended or a fatal
* error occurred.
*
* @param session the sessionm to process
*/
apr_status_t h2_session_process(h2_session *session, int async);
/**
* Last chance to do anything before the connection is closed.
*/
apr_status_t h2_session_pre_close(h2_session *session, int async);
/**
* Called when a serious error occurred and the session needs to terminate
* without further connection io.
* @param session the session to abort
* @param reason the apache status that caused the abort
*/
void h2_session_abort(h2_session *session, apr_status_t reason);
/**
* Close and deallocate the given session.
*/
void h2_session_close(h2_session *session);
/**
* Returns if client settings have push enabled.
* @param != 0 iff push is enabled in client settings
*/
int h2_session_push_enabled(h2_session *session);
/**
* Look up the stream in this session with the given id.
*/
struct h2_stream *h2_session_stream_get(h2_session *session, int stream_id);
/**
* Submit a push promise on the stream and schedule the new steam for
* processing..
*
* @param session the session to work in
* @param is the stream initiating the push
* @param push the push to promise
* @return the new promised stream or NULL
*/
struct h2_stream *h2_session_push(h2_session *session,
struct h2_stream *is, struct h2_push *push);
apr_status_t h2_session_set_prio(h2_session *session,
struct h2_stream *stream,
const struct h2_priority *prio);
#define H2_SSSN_MSG(s, msg) \
"h2_session(%ld,%s,%d): "msg, s->id, h2_session_state_str(s->state), \
s->open_streams
#define H2_SSSN_LOG(aplogno, s, msg) aplogno H2_SSSN_MSG(s, msg)
#endif /* defined(__mod_h2__h2_session__) */
|