diff --git a/include/common/hpack-tbl.h b/include/common/hpack-tbl.h index bb1ac06e1..44c0cc117 100644 --- a/include/common/hpack-tbl.h +++ b/include/common/hpack-tbl.h @@ -32,6 +32,7 @@ #include #include #include +#include /* Dynamic Headers Table, usable for tables up to 4GB long and values of 64kB-1. * The model can be improved by using offsets relative to the table entry's end @@ -133,6 +134,7 @@ enum { /* static header table as in RFC7541 Appendix A. [0] unused. */ #define HPACK_SHT_SIZE 62 extern const struct http_hdr hpack_sht[HPACK_SHT_SIZE]; +extern struct pool_head *pool_head_hpack_tbl; extern int __hpack_dht_make_room(struct hpack_dht *dht, unsigned int needed); extern int hpack_dht_insert(struct hpack_dht *dht, struct ist name, struct ist value); @@ -233,23 +235,24 @@ static inline void hpack_dht_init(struct hpack_dht *dht, uint32_t size) dht->used = 0; } -/* allocate a dynamic headers table of bytes and return it initialized */ -static inline struct hpack_dht *hpack_dht_alloc(uint32_t size) +/* allocate a dynamic headers table from the pool and return it initialized */ +static inline struct hpack_dht *hpack_dht_alloc() { struct hpack_dht *dht; - dht = malloc(size); - if (!dht) - return dht; + if (unlikely(!pool_head_hpack_tbl)) + return NULL; - hpack_dht_init(dht, size); + dht = pool_alloc(pool_head_hpack_tbl); + if (dht) + hpack_dht_init(dht, pool_head_hpack_tbl->size); return dht; } /* free a dynamic headers table */ static inline void hpack_dht_free(struct hpack_dht *dht) { - free(dht); + pool_free(pool_head_hpack_tbl, dht); } #endif /* _COMMON_HPACK_TBL_H */ diff --git a/src/hpack-tbl.c b/src/hpack-tbl.c index 727ff7a17..effe5e01e 100644 --- a/src/hpack-tbl.c +++ b/src/hpack-tbl.c @@ -101,6 +101,8 @@ const struct http_hdr hpack_sht[HPACK_SHT_SIZE] = { [61] = { .n = IST("www-authenticate"), .v = IST("") }, }; +struct pool_head *pool_head_hpack_tbl = NULL; + /* returns the slot number of the oldest entry (tail). Must not be used on an * empty table. */ @@ -173,7 +175,7 @@ static struct hpack_dht *hpack_dht_defrag(struct hpack_dht *dht) /* Note: for small tables we could use alloca() instead but * portability especially for large tables can be problematic. */ - alt_dht = hpack_dht_alloc(dht->size); + alt_dht = hpack_dht_alloc(); if (!alt_dht) return NULL; diff --git a/src/mux_h2.c b/src/mux_h2.c index 6b1c0d118..297292503 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -823,7 +823,7 @@ static int h2_init(struct connection *conn, struct proxy *prx, struct session *s h2c->wait_event.tasklet->context = h2c; h2c->wait_event.events = 0; - h2c->ddht = hpack_dht_alloc(h2_settings_header_table_size); + h2c->ddht = hpack_dht_alloc(); if (!h2c->ddht) goto fail; @@ -6195,3 +6195,18 @@ static struct cfg_kw_list cfg_kws = {ILH, { }}; INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); + +/* initialize internal structs after the config is parsed. + * Returns zero on success, non-zero on error. + */ +static int init_h2() +{ + pool_head_hpack_tbl = create_pool("hpack_tbl", + h2_settings_header_table_size, + MEM_F_SHARED|MEM_F_EXACT); + if (!pool_head_hpack_tbl) + return -1; + return 0; +} + +REGISTER_POST_CHECK(init_h2);