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