diff --git a/lsqpack.c b/lsqpack.c index 488c207..763a0ed 100644 --- a/lsqpack.c +++ b/lsqpack.c @@ -1517,9 +1517,11 @@ lsqpack_enc_encode (struct lsqpack_enc *enc, id = 0; #endif - use_dyn_table = enc_use_dynamic_table(enc); + use_dyn_table = !(flags & LQEF_NO_DYN) + && enc_use_dynamic_table(enc) + ; - index = !(flags & (LQEF_NO_INDEX|LQEF_NEVER_INDEX)) + index = !(flags & (LQEF_NO_INDEX|LQEF_NEVER_INDEX|LQEF_NO_DYN)) && use_dyn_table && enc->qpe_ins_count < LSQPACK_MAX_ABS_ID ; @@ -1528,8 +1530,7 @@ lsqpack_enc_encode (struct lsqpack_enc *enc, || enc->qpe_cur_header.others_at_risk || enc->qpe_cur_streams_at_risk < enc->qpe_max_risked_streams; - /* Add header to history if it exists */ - if (enc->qpe_hist) + if (enc->qpe_hist && !(flags & LQEF_NO_HIST_UPD)) { ++enc->qpe_cur_header.n_hdr_added_to_hist; if (enc->qpe_cur_header.n_hdr_added_to_hist > enc->qpe_hist->ehi_nels) diff --git a/lsqpack.h b/lsqpack.h index 49f5440..8aede92 100644 --- a/lsqpack.h +++ b/lsqpack.h @@ -47,7 +47,7 @@ typedef SSIZE_T ssize_t; */ #define LSQPACK_MAJOR_VERSION 0 #define LSQPACK_MINOR_VERSION 8 -#define LSQPACK_PATCH_VERSION 0 +#define LSQPACK_PATCH_VERSION 1 /** Let's start with four billion for now */ typedef unsigned lsqpack_abs_id_t; @@ -168,6 +168,16 @@ enum lsqpack_enc_flags * in the header block. Implies LQEF_NO_INDEX. */ LQEF_NEVER_INDEX = 1 << 1, + /** + * Do not update history. + */ + LQEF_NO_HIST_UPD = 1 << 2, + /** + * Do not use the dynamic table. This is stricter than LQEF_NO_INDEX: + * this means that the dynamic table will be neither referenced nor + * modified. + */ + LQEF_NO_DYN = 1 << 3, }; /** diff --git a/test/test_qpack.c b/test/test_qpack.c index 9340eb7..c51bf11 100644 --- a/test/test_qpack.c +++ b/test/test_qpack.c @@ -360,6 +360,83 @@ test_enc_init (void) } +/* Test that push promise header does not use the dynamic table, nor does + * it update history. + */ +static void +test_push_promise (void) +{ + struct lsqpack_enc enc; + ssize_t nw; + enum lsqpack_enc_status enc_st; + int s; + unsigned i; + const unsigned char *p; + uint64_t val; + struct lsqpack_dec_int_state state; + unsigned char dec_buf[LSQPACK_LONGEST_TSU]; + unsigned char header_buf[HEADER_BUF_SZ], enc_buf[ENC_BUF_SZ], + prefix_buf[PREFIX_BUF_SZ]; + size_t header_sz, enc_sz, dec_sz; + + s = lsqpack_enc_init(&enc, stderr, 0x1000, 0x1000, 100, 0, dec_buf, &dec_sz); + assert(0 == s); + + (void) dec_sz; /* We don't care for this test */ + + s = lsqpack_enc_start_header(&enc, 0, 0); + assert(0 == s); + enc_sz = sizeof(enc_buf); + header_sz = sizeof(header_buf); + enc_st = lsqpack_enc_encode(&enc, + enc_buf, &enc_sz, header_buf, &header_sz, + ":method", 7, "dude!", 5, 0); + assert(LQES_OK == enc_st); + enc_sz = sizeof(enc_buf); + header_sz = sizeof(header_buf); + enc_st = lsqpack_enc_encode(&enc, + enc_buf, &enc_sz, header_buf, &header_sz, + ":method", 7, "dude!", 5, 0); + assert(LQES_OK == enc_st); + nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf)); + assert(2 == nw); + assert(!(prefix_buf[0] == 0 && prefix_buf[1] == 0)); /* Dynamic table used */ + + s = lsqpack_enc_start_header(&enc, 0, 0); + assert(0 == s); + enc_sz = sizeof(enc_buf); + header_sz = sizeof(header_buf); + enc_st = lsqpack_enc_encode(&enc, + enc_buf, &enc_sz, header_buf, &header_sz, + ":method", 7, "dude!", 5, LQEF_NO_HIST_UPD|LQEF_NO_DYN); + assert(LQES_OK == enc_st); + enc_sz = sizeof(enc_buf); + header_sz = sizeof(header_buf); + enc_st = lsqpack_enc_encode(&enc, + enc_buf, &enc_sz, header_buf, &header_sz, + ":method", 7, "where is my car?", 16, LQEF_NO_HIST_UPD|LQEF_NO_DYN); + nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf)); + assert(2 == nw); + assert(prefix_buf[0] == 0 && prefix_buf[1] == 0); /* Dynamic table not used */ + + /* Last check that history was not updated: */ + s = lsqpack_enc_start_header(&enc, 4, 0); + assert(0 == s); + enc_sz = sizeof(enc_buf); + header_sz = sizeof(header_buf); + enc_st = lsqpack_enc_encode(&enc, + enc_buf, &enc_sz, header_buf, &header_sz, + ":method", 7, "where is my car?", 16, 0); + assert(enc_sz == 0); + assert(LQES_OK == enc_st); + nw = lsqpack_enc_end_header(&enc, prefix_buf, sizeof(prefix_buf)); + assert(2 == nw); + assert(prefix_buf[0] == 0 && prefix_buf[1] == 0); /* Dynamic table not used */ + + lsqpack_enc_cleanup(&enc); +} + + int main (void) { @@ -371,6 +448,7 @@ main (void) run_header_cancellation_test(&header_block_tests[0]); test_enc_init(); + test_push_promise(); return 0; }