Blame modules/http2/h2_session.h

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__) */