|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#ifndef __mod_h2__h2_session__
|
|
Packit |
90a5c9 |
#define __mod_h2__h2_session__
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "h2_conn_io.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* A HTTP/2 connection, a session with a specific client.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* h2_session sits on top of a httpd conn_rec* instance and takes complete
|
|
Packit |
90a5c9 |
* control of the connection data. It receives protocol frames from the
|
|
Packit |
90a5c9 |
* client. For new HTTP/2 streams it creates h2_task(s) that are sent
|
|
Packit |
90a5c9 |
* via callback to a dispatcher (see h2_conn.c).
|
|
Packit |
90a5c9 |
* h2_session keeps h2_io's for each ongoing stream which buffer the
|
|
Packit |
90a5c9 |
* payload for that stream.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* New incoming HEADER frames are converted into a h2_stream+h2_task instance
|
|
Packit |
90a5c9 |
* that both represent a HTTP/2 stream, but may have separate lifetimes. This
|
|
Packit |
90a5c9 |
* allows h2_task to be scheduled in other threads without semaphores
|
|
Packit |
90a5c9 |
* all over the place. It allows task memory to be freed independent of
|
|
Packit |
90a5c9 |
* session lifetime and sessions may close down while tasks are still running.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "h2.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct apr_thread_mutext_t;
|
|
Packit |
90a5c9 |
struct apr_thread_cond_t;
|
|
Packit |
90a5c9 |
struct h2_ctx;
|
|
Packit |
90a5c9 |
struct h2_config;
|
|
Packit |
90a5c9 |
struct h2_filter_cin;
|
|
Packit |
90a5c9 |
struct h2_ihash_t;
|
|
Packit |
90a5c9 |
struct h2_mplx;
|
|
Packit |
90a5c9 |
struct h2_priority;
|
|
Packit |
90a5c9 |
struct h2_push;
|
|
Packit |
90a5c9 |
struct h2_push_diary;
|
|
Packit |
90a5c9 |
struct h2_session;
|
|
Packit |
90a5c9 |
struct h2_stream;
|
|
Packit |
90a5c9 |
struct h2_stream_monitor;
|
|
Packit |
90a5c9 |
struct h2_task;
|
|
Packit |
90a5c9 |
struct h2_workers;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct nghttp2_session;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef enum {
|
|
Packit |
90a5c9 |
H2_SESSION_EV_INIT, /* session was initialized */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_LOCAL_GOAWAY, /* we send a GOAWAY */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_REMOTE_GOAWAY, /* remote send us a GOAWAY */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_CONN_ERROR, /* connection error */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_PROTO_ERROR, /* protocol error */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_CONN_TIMEOUT, /* connection timeout */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_NO_IO, /* nothing has been read or written */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_FRAME_RCVD, /* a frame has been received */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_NGH2_DONE, /* nghttp2 wants neither read nor write anything */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_MPM_STOPPING, /* the process is stopping */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_PRE_CLOSE, /* connection will close after this */
|
|
Packit |
90a5c9 |
H2_SESSION_EV_STREAM_CHANGE, /* a stream (state/input/output) changed */
|
|
Packit |
90a5c9 |
} h2_session_event_t;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct h2_session {
|
|
Packit |
90a5c9 |
long id; /* identifier of this session, unique
|
|
Packit |
90a5c9 |
* inside a httpd process */
|
|
Packit |
90a5c9 |
conn_rec *c; /* the connection this session serves */
|
|
Packit |
90a5c9 |
request_rec *r; /* the request that started this in case
|
|
Packit |
90a5c9 |
* of 'h2c', NULL otherwise */
|
|
Packit |
90a5c9 |
server_rec *s; /* server/vhost we're starting on */
|
|
Packit |
90a5c9 |
const struct h2_config *config; /* Relevant config for this session */
|
|
Packit |
90a5c9 |
apr_pool_t *pool; /* pool to use in session */
|
|
Packit |
90a5c9 |
struct h2_mplx *mplx; /* multiplexer for stream data */
|
|
Packit |
90a5c9 |
struct h2_workers *workers; /* for executing stream tasks */
|
|
Packit |
90a5c9 |
struct h2_filter_cin *cin; /* connection input filter context */
|
|
Packit |
90a5c9 |
h2_conn_io io; /* io on httpd conn filters */
|
|
Packit |
90a5c9 |
struct nghttp2_session *ngh2; /* the nghttp2 session (internal use) */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
h2_session_state state; /* state session is in */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
h2_session_props local; /* properties of local session */
|
|
Packit |
90a5c9 |
h2_session_props remote; /* properites of remote session */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
unsigned int reprioritize : 1; /* scheduled streams priority changed */
|
|
Packit |
90a5c9 |
unsigned int flush : 1; /* flushing output necessary */
|
|
Packit |
90a5c9 |
unsigned int have_read : 1; /* session has read client data */
|
|
Packit |
90a5c9 |
unsigned int have_written : 1; /* session did write data to client */
|
|
Packit |
90a5c9 |
apr_interval_time_t wait_us; /* timeout during BUSY_WAIT state, micro secs */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct h2_push_diary *push_diary; /* remember pushes, avoid duplicates */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct h2_stream_monitor *monitor;/* monitor callbacks for streams */
|
|
Packit |
90a5c9 |
int open_streams; /* number of client streams open */
|
|
Packit |
90a5c9 |
int unsent_submits; /* number of submitted, but not yet written responses. */
|
|
Packit |
90a5c9 |
int unsent_promises; /* number of submitted, but not yet written push promises */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int responses_submitted; /* number of http/2 responses submitted */
|
|
Packit |
90a5c9 |
int streams_reset; /* number of http/2 streams reset by client */
|
|
Packit |
90a5c9 |
int pushes_promised; /* number of http/2 push promises submitted */
|
|
Packit |
90a5c9 |
int pushes_submitted; /* number of http/2 pushed responses submitted */
|
|
Packit |
90a5c9 |
int pushes_reset; /* number of http/2 pushed reset by client */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_size_t frames_received; /* number of http/2 frames received */
|
|
Packit |
90a5c9 |
apr_size_t frames_sent; /* number of http/2 frames sent */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_size_t max_stream_count; /* max number of open streams */
|
|
Packit |
90a5c9 |
apr_size_t max_stream_mem; /* max buffer memory for a single stream */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_time_t idle_until; /* Time we shut down due to sheer boredom */
|
|
Packit |
90a5c9 |
apr_time_t idle_sync_until; /* Time we sync wait until keepalive handling kicks in */
|
|
Packit |
90a5c9 |
apr_size_t idle_frames; /* number of rcvd frames that kept session in idle state */
|
|
Packit |
90a5c9 |
apr_interval_time_t idle_delay; /* Time we delay processing rcvd frames in idle state */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_bucket_brigade *bbtmp; /* brigade for keeping temporary data */
|
|
Packit |
90a5c9 |
struct apr_thread_cond_t *iowait; /* our cond when trywaiting for data */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char status[64]; /* status message for scoreboard */
|
|
Packit |
90a5c9 |
int last_status_code; /* the one already reported */
|
|
Packit |
90a5c9 |
const char *last_status_msg; /* the one already reported */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct h2_iqueue *in_pending; /* all streams with input pending */
|
|
Packit |
90a5c9 |
struct h2_iqueue *in_process; /* all streams ready for processing on slave */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
} h2_session;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
const char *h2_session_state_str(h2_session_state state);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Create a new h2_session for the given connection.
|
|
Packit |
90a5c9 |
* The session will apply the configured parameter.
|
|
Packit |
90a5c9 |
* @param psession pointer receiving the created session on success or NULL
|
|
Packit |
90a5c9 |
* @param c the connection to work on
|
|
Packit |
90a5c9 |
* @param cfg the module config to apply
|
|
Packit |
90a5c9 |
* @param workers the worker pool to use
|
|
Packit |
90a5c9 |
* @return the created session
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_status_t h2_session_create(h2_session **psession,
|
|
Packit |
90a5c9 |
conn_rec *c, struct h2_ctx *ctx,
|
|
Packit |
90a5c9 |
struct h2_workers *workers);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Create a new h2_session for the given request.
|
|
Packit |
90a5c9 |
* The session will apply the configured parameter.
|
|
Packit |
90a5c9 |
* @param psession pointer receiving the created session on success or NULL
|
|
Packit |
90a5c9 |
* @param r the request that was upgraded
|
|
Packit |
90a5c9 |
* @param cfg the module config to apply
|
|
Packit |
90a5c9 |
* @param workers the worker pool to use
|
|
Packit |
90a5c9 |
* @return the created session
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_status_t h2_session_rcreate(h2_session **psession,
|
|
Packit |
90a5c9 |
request_rec *r, struct h2_ctx *ctx,
|
|
Packit |
90a5c9 |
struct h2_workers *workers);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
void h2_session_event(h2_session *session, h2_session_event_t ev,
|
|
Packit |
90a5c9 |
int err, const char *msg);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Process the given HTTP/2 session until it is ended or a fatal
|
|
Packit |
90a5c9 |
* error occurred.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* @param session the sessionm to process
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_status_t h2_session_process(h2_session *session, int async);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Last chance to do anything before the connection is closed.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_status_t h2_session_pre_close(h2_session *session, int async);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Called when a serious error occurred and the session needs to terminate
|
|
Packit |
90a5c9 |
* without further connection io.
|
|
Packit |
90a5c9 |
* @param session the session to abort
|
|
Packit |
90a5c9 |
* @param reason the apache status that caused the abort
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
void h2_session_abort(h2_session *session, apr_status_t reason);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Close and deallocate the given session.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
void h2_session_close(h2_session *session);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Returns if client settings have push enabled.
|
|
Packit |
90a5c9 |
* @param != 0 iff push is enabled in client settings
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
int h2_session_push_enabled(h2_session *session);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Look up the stream in this session with the given id.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
struct h2_stream *h2_session_stream_get(h2_session *session, int stream_id);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Submit a push promise on the stream and schedule the new steam for
|
|
Packit |
90a5c9 |
* processing..
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* @param session the session to work in
|
|
Packit |
90a5c9 |
* @param is the stream initiating the push
|
|
Packit |
90a5c9 |
* @param push the push to promise
|
|
Packit |
90a5c9 |
* @return the new promised stream or NULL
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
struct h2_stream *h2_session_push(h2_session *session,
|
|
Packit |
90a5c9 |
struct h2_stream *is, struct h2_push *push);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t h2_session_set_prio(h2_session *session,
|
|
Packit |
90a5c9 |
struct h2_stream *stream,
|
|
Packit |
90a5c9 |
const struct h2_priority *prio);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define H2_SSSN_MSG(s, msg) \
|
|
Packit |
90a5c9 |
"h2_session(%ld,%s,%d): "msg, s->id, h2_session_state_str(s->state), \
|
|
Packit |
90a5c9 |
s->open_streams
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#define H2_SSSN_LOG(aplogno, s, msg) aplogno H2_SSSN_MSG(s, msg)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#endif /* defined(__mod_h2__h2_session__) */
|