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