summaryrefslogtreecommitdiff
path: root/modules/http2/h2_proxy_session.h
blob: 7f0a194097f720fbe0ea5dffe8443bb7ce597325 (plain)
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
/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
 *
 * Licensed 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 h2_proxy_session_h
#define h2_proxy_session_h

#define H2_ALEN(a)          (sizeof(a)/sizeof((a)[0]))

#include <nghttp2/nghttp2.h>

struct h2_iqueue;
struct h2_ihash_t;

typedef enum {
    H2_PROXYS_ST_INIT,             /* send initial SETTINGS, etc. */
    H2_PROXYS_ST_DONE,             /* finished, connection close */
    H2_PROXYS_ST_IDLE,             /* no streams to process */
    H2_PROXYS_ST_BUSY,             /* read/write without stop */
    H2_PROXYS_ST_WAIT,             /* waiting for tasks reporting back */
    H2_PROXYS_ST_LOCAL_SHUTDOWN,   /* we announced GOAWAY */
    H2_PROXYS_ST_REMOTE_SHUTDOWN,  /* client announced GOAWAY */
} h2_proxys_state;

typedef enum {
    H2_PROXYS_EV_INIT,             /* session was initialized */
    H2_PROXYS_EV_LOCAL_GOAWAY,     /* we send a GOAWAY */
    H2_PROXYS_EV_REMOTE_GOAWAY,    /* remote send us a GOAWAY */
    H2_PROXYS_EV_CONN_ERROR,       /* connection error */
    H2_PROXYS_EV_PROTO_ERROR,      /* protocol error */
    H2_PROXYS_EV_CONN_TIMEOUT,     /* connection timeout */
    H2_PROXYS_EV_NO_IO,            /* nothing has been read or written */
    H2_PROXYS_EV_STREAM_SUBMITTED, /* stream has been submitted */
    H2_PROXYS_EV_STREAM_DONE,      /* stream has been finished */
    H2_PROXYS_EV_STREAM_RESUMED,   /* stream signalled availability of headers/data */
    H2_PROXYS_EV_DATA_READ,        /* connection data has been read */
    H2_PROXYS_EV_NGH2_DONE,        /* nghttp2 wants neither read nor write anything */
    H2_PROXYS_EV_PRE_CLOSE,        /* connection will close after this */
} h2_proxys_event_t;


typedef struct h2_proxy_session h2_proxy_session;
typedef void h2_proxy_request_done(h2_proxy_session *s, request_rec *r,
                                   int complete, int touched);

struct h2_proxy_session {
    const char *id;
    conn_rec *c;
    proxy_conn_rec *p_conn;
    proxy_server_conf *conf;
    apr_pool_t *pool;
    nghttp2_session *ngh2;   /* the nghttp2 session itself */
    
    unsigned int aborted : 1;

    h2_proxy_request_done *done;
    void *user_data;
    
    unsigned char window_bits_stream;
    unsigned char window_bits_connection;

    h2_proxys_state state;
    apr_interval_time_t wait_timeout;

    struct h2_ihash_t *streams;
    struct h2_iqueue *suspended;
    apr_size_t remote_max_concurrent;
    int last_stream_id;     /* last stream id processed by backend, or 0 */
    
    apr_bucket_brigade *input;
    apr_bucket_brigade *output;
};

h2_proxy_session *h2_proxy_session_setup(const char *id, proxy_conn_rec *p_conn,
                                         proxy_server_conf *conf,
                                         unsigned char window_bits_connection,
                                         unsigned char window_bits_stream,
                                         h2_proxy_request_done *done);

apr_status_t h2_proxy_session_submit(h2_proxy_session *s, const char *url,
                                     request_rec *r, int standalone);
                       
/** 
 * Perform a step in processing the proxy session. Will return aftert
 * one read/write cycle and indicate session status by status code.
 * @param s the session to process
 * @return APR_EAGAIN  when processing needs to be invoked again
 *         APR_SUCCESS when all streams have been processed, session still live
 *         APR_EOF     when the session has been terminated
 */
apr_status_t h2_proxy_session_process(h2_proxy_session *s);

void h2_proxy_session_cleanup(h2_proxy_session *s, h2_proxy_request_done *done);

void h2_proxy_session_update_window(h2_proxy_session *s, 
                                    conn_rec *c, apr_off_t bytes);

#define H2_PROXY_REQ_URL_NOTE   "h2-proxy-req-url"

#endif /* h2_proxy_session_h */