lsquic_push_promise.h revision bc520ef7
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_PUSH_PROMISE_H
3#define LSQUIC_PUSH_PROMISE_H 1
4
5struct lsquic_hash_elem;
6struct lsquic_stream;
7
8
9struct push_promise
10{
11    /* A push promise is associated with a single stream, while a stream can
12     * have several push promises it depends on.  These push promises are
13     * stored on a list.  A push promise is destroyed when the dependent
14     * stream is destroyed.  This bounds the amount of time when DUPLICATE_PUSH
15     * frames can be sent out.
16     */
17    SLIST_ENTRY(push_promise)   pp_next;
18    /* Push promises are stored a hash and can be searched by ID */
19    struct lsquic_hash_elem     pp_hash_id;
20    uint64_t                    pp_id;
21    struct lsquic_stream       *pp_pushed_stream;
22    size_t                      pp_content_len;
23    /* Number of streams holding a reference to this push promise.  When this
24     * value becomes zero, the push promise is destroyed.  See lsquic_pp_put().
25     *
26     * The stream on which PUSH_PROMISE frame is sent has a reference in its
27     * sm_promises list.  The push streams themselves have a reference in
28     * sm_promise.
29     */
30    unsigned                    pp_refcnt;
31    /* State for the promise reader.  If the state is not PPWS_NONE, we are
32     * in the process of writing the first push promise on sm_promises list
33     * (that's the last promise received).
34     */
35    enum {
36        PPWS_ID0,       /* Write first byte of Push ID */
37        PPWS_ID1,       /* Write second byte of Push ID */
38        PPWS_ID2,       /* Write third byte of Push ID */
39        PPWS_ID3,       /* Write fourth byte of Push ID */
40        PPWS_ID4,       /* Write fifth byte of Push ID */
41        PPWS_ID5,       /* Write sixth byte of Push ID */
42        PPWS_ID6,       /* Write seventh byte of Push ID */
43        PPWS_ID7,       /* Write eighth byte of Push ID */
44        PPWS_PFX0,      /* Write first NUL byte of the Header Block Prefix */
45        PPWS_PFX1,      /* Write second NUL byte of the Header Block Prefix */
46        PPWS_HBLOCK,    /* Write header block -- use sm_push_hblock_off */
47        PPWS_DONE,
48    }                           pp_write_state;
49    unsigned                    pp_write_off;
50    unsigned char               pp_encoded_push_id[8];
51    /* The content buffer is the header block: it does not include Header
52     * Block Prefix.
53     */
54    unsigned char               pp_content_buf[0];
55};
56
57
58#define lsquic_pp_put(promise_, all_promises_) do {                         \
59    if ((promise_)->pp_refcnt > 0) {                                        \
60        --(promise_)->pp_refcnt;                                            \
61        if (0 == (promise_)->pp_refcnt) {                                   \
62            LSQ_DEBUG("destroy push promise %"PRIu64, (promise_)->pp_id);   \
63            if ((promise_)->pp_hash_id.qhe_flags & QHE_HASHED)              \
64                lsquic_hash_erase(all_promises_, &(promise_)->pp_hash_id);  \
65            free(promise);                                                  \
66        }                                                                   \
67    }                                                                       \
68    else                                                                    \
69        assert(0);                                                          \
70} while (0)
71
72#endif
73