lsquic_push_promise.h revision 5392f7a3
1/* Copyright (c) 2017 - 2019 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 9enum push_promise_key_type { 10 PPKT_ID, 11 PPKT_CONTENT, 12}; 13 14 15struct push_promise 16{ 17 /* A push promise is associated with a single stream, while a stream can 18 * have several push promises it depends on. These push promises are 19 * stored on a list. A push promise is destroyed when the dependent 20 * stream is destroyed. This bounds the amount of time when DUPLICATE_PUSH 21 * frames can be sent out. 22 */ 23 SLIST_ENTRY(push_promise) pp_next; 24 /* Push promises are stored in the same hash and can be searched either 25 * by ID or by content. To differentiate the two keys, the key type is 26 * appended at the end PPKT_ID or PPKT_CONTENT. 27 */ 28 struct lsquic_hash_elem pp_hash_id, 29 pp_hash_content; 30 union { 31 uint64_t id; 32 unsigned char buf[9]; 33 } pp_u_id; 34#define pp_id pp_u_id.id 35 struct lsquic_stream *pp_pushed_stream; 36 /* This does not include the last key-type byte: */ 37 size_t pp_content_len; 38 /* Number of streams holding a reference to this push promise. When this 39 * value becomes zero, the push promise is destroyed. See lsquic_pp_put(). 40 * 41 * The stream on which PUSH_PROMISE frame is sent has a reference in its 42 * sm_promises list. The push streams themselves have a reference in 43 * sm_promise. 44 */ 45 unsigned pp_refcnt; 46 /* State for the promise reader. If the state is not PPWS_NONE, we are 47 * in the process of writing the first push promise on sm_promises list 48 * (that's the last promise received). 49 */ 50 enum { 51 PPWS_ID0, /* Write first byte of Push ID */ 52 PPWS_ID1, /* Write second byte of Push ID */ 53 PPWS_ID2, /* Write third byte of Push ID */ 54 PPWS_ID3, /* Write fourth byte of Push ID */ 55 PPWS_ID4, /* Write fifth byte of Push ID */ 56 PPWS_ID5, /* Write sixth byte of Push ID */ 57 PPWS_ID6, /* Write seventh byte of Push ID */ 58 PPWS_ID7, /* Write eighth byte of Push ID */ 59 PPWS_PFX0, /* Write first NUL byte of the Header Block Prefix */ 60 PPWS_PFX1, /* Write second NUL byte of the Header Block Prefix */ 61 PPWS_HBLOCK, /* Write header block -- use sm_push_hblock_off */ 62 PPWS_DONE, 63 } pp_write_state; 64 unsigned pp_write_off; 65 unsigned char pp_encoded_push_id[8]; 66 /* The content buffer is the header block: it does not include Header 67 * Block Prefix. It is followed by one-byte key type PPKT_CONTENT. 68 */ 69 unsigned char pp_content_buf[0]; 70}; 71 72 73#define lsquic_pp_put(promise_, all_promises_) do { \ 74 if ((promise_)->pp_refcnt > 0) { \ 75 --(promise_)->pp_refcnt; \ 76 if (0 == (promise_)->pp_refcnt) { \ 77 LSQ_DEBUG("destroy push promise %"PRIu64, (promise_)->pp_id); \ 78 if ((promise_)->pp_hash_id.qhe_flags & QHE_HASHED) \ 79 lsquic_hash_erase(all_promises_, &(promise_)->pp_hash_id); \ 80 if ((promise_)->pp_hash_content.qhe_flags & QHE_HASHED) \ 81 lsquic_hash_erase(all_promises_, \ 82 &(promise_)->pp_hash_content); \ 83 free(promise); \ 84 } \ 85 } \ 86 else \ 87 assert(0); \ 88} while (0) 89 90#endif 91