1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2fb3e20e0SDmitri Tikhonov#ifndef LSXPACK_HEADER_H_v206 3fb3e20e0SDmitri Tikhonov#define LSXPACK_HEADER_H_v206 4a5fa05f9SDmitri Tikhonov 5a5fa05f9SDmitri Tikhonov#ifdef __cplusplus 6a5fa05f9SDmitri Tikhonovextern "C" { 7a5fa05f9SDmitri Tikhonov#endif 8a5fa05f9SDmitri Tikhonov 9a5fa05f9SDmitri Tikhonov#include <assert.h> 10a5fa05f9SDmitri Tikhonov#include <stdint.h> 11a5fa05f9SDmitri Tikhonov#include <string.h> 12a5fa05f9SDmitri Tikhonov 13a5fa05f9SDmitri Tikhonov#ifndef LSXPACK_MAX_STRLEN 14a5fa05f9SDmitri Tikhonov#define LSXPACK_MAX_STRLEN UINT16_MAX 15a5fa05f9SDmitri Tikhonov#endif 16a5fa05f9SDmitri Tikhonov 17a5fa05f9SDmitri Tikhonov#if LSXPACK_MAX_STRLEN == UINT16_MAX 18a5fa05f9SDmitri Tikhonovtypedef uint16_t lsxpack_strlen_t; 19a5fa05f9SDmitri Tikhonov#elif LSXPACK_MAX_STRLEN == UINT32_MAX 20a5fa05f9SDmitri Tikhonovtypedef uint32_t lsxpack_strlen_t; 21a5fa05f9SDmitri Tikhonov#else 22a5fa05f9SDmitri Tikhonov#error unexpected LSXPACK_MAX_STRLEN 23a5fa05f9SDmitri Tikhonov#endif 24a5fa05f9SDmitri Tikhonov 2555613f44SDmitri Tikhonov#define LSXPACK_DEL ((char *)NULL) 2655613f44SDmitri Tikhonov 27a5fa05f9SDmitri Tikhonovenum lsxpack_flag 28a5fa05f9SDmitri Tikhonov{ 29fb3e20e0SDmitri Tikhonov LSXPACK_HPACK_VAL_MATCHED = 1, 30a5fa05f9SDmitri Tikhonov LSXPACK_QPACK_IDX = 2, 31a5fa05f9SDmitri Tikhonov LSXPACK_APP_IDX = 4, 32a5fa05f9SDmitri Tikhonov LSXPACK_NAME_HASH = 8, 33a5fa05f9SDmitri Tikhonov LSXPACK_NAMEVAL_HASH = 16, 34a5fa05f9SDmitri Tikhonov LSXPACK_VAL_MATCHED = 32, 35a5fa05f9SDmitri Tikhonov LSXPACK_NEVER_INDEX = 64, 36a5fa05f9SDmitri Tikhonov}; 37a5fa05f9SDmitri Tikhonov 38a5fa05f9SDmitri Tikhonov/** 39a5fa05f9SDmitri Tikhonov * When header are decoded, it should be stored to @buf starting from @name_offset, 40a5fa05f9SDmitri Tikhonov * <name>: <value>\r\n 41a5fa05f9SDmitri Tikhonov * So, it can be used directly as HTTP/1.1 header. there are 4 extra characters 42a5fa05f9SDmitri Tikhonov * added. 43a5fa05f9SDmitri Tikhonov * 44a5fa05f9SDmitri Tikhonov * limitation: we currently does not support total header size > 64KB. 45a5fa05f9SDmitri Tikhonov */ 46a5fa05f9SDmitri Tikhonov 47a5fa05f9SDmitri Tikhonovstruct lsxpack_header 48a5fa05f9SDmitri Tikhonov{ 49a5fa05f9SDmitri Tikhonov char *buf; /* the buffer for headers */ 50a5fa05f9SDmitri Tikhonov uint32_t name_hash; /* hash value for name */ 51a5fa05f9SDmitri Tikhonov uint32_t nameval_hash; /* hash value for name + value */ 52a5fa05f9SDmitri Tikhonov lsxpack_strlen_t name_offset; /* the offset for name in the buffer */ 53a5fa05f9SDmitri Tikhonov lsxpack_strlen_t name_len; /* the length of name */ 54a5fa05f9SDmitri Tikhonov lsxpack_strlen_t val_offset; /* the offset for value in the buffer */ 55a5fa05f9SDmitri Tikhonov lsxpack_strlen_t val_len; /* the length of value */ 5655613f44SDmitri Tikhonov uint16_t chain_next_idx; /* mainly for cookie value chain */ 57a5fa05f9SDmitri Tikhonov uint8_t hpack_index; /* HPACK static table index */ 58a5fa05f9SDmitri Tikhonov uint8_t qpack_index; /* QPACK static table index */ 59a5fa05f9SDmitri Tikhonov uint8_t app_index; /* APP header index */ 60a5fa05f9SDmitri Tikhonov enum lsxpack_flag flags:8; /* combination of lsxpack_flag */ 61a5fa05f9SDmitri Tikhonov uint8_t indexed_type; /* control to disable index or not */ 62a5fa05f9SDmitri Tikhonov uint8_t dec_overhead; /* num of extra bytes written to decoded buffer */ 63a5fa05f9SDmitri Tikhonov}; 64a5fa05f9SDmitri Tikhonov 65a5fa05f9SDmitri Tikhonovtypedef struct lsxpack_header lsxpack_header_t; 66a5fa05f9SDmitri Tikhonov 67a5fa05f9SDmitri Tikhonov 68a5fa05f9SDmitri Tikhonovstatic inline void 69a5fa05f9SDmitri Tikhonovlsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx, 70a5fa05f9SDmitri Tikhonov const char *val, size_t val_len) 71a5fa05f9SDmitri Tikhonov{ 72a5fa05f9SDmitri Tikhonov memset(hdr, 0, sizeof(*hdr)); 73a5fa05f9SDmitri Tikhonov hdr->buf = (char *)val; 74a5fa05f9SDmitri Tikhonov hdr->hpack_index = hpack_idx; 75a5fa05f9SDmitri Tikhonov assert(hpack_idx != 0); 76a5fa05f9SDmitri Tikhonov assert(val_len <= LSXPACK_MAX_STRLEN); 77a5fa05f9SDmitri Tikhonov hdr->val_len = val_len; 78a5fa05f9SDmitri Tikhonov} 79a5fa05f9SDmitri Tikhonov 80a5fa05f9SDmitri Tikhonov 81a5fa05f9SDmitri Tikhonovstatic inline void 8255613f44SDmitri Tikhonovlsxpack_header_set_qpack_idx(lsxpack_header_t *hdr, int qpack_idx, 8355613f44SDmitri Tikhonov const char *val, size_t val_len) 8455613f44SDmitri Tikhonov{ 8555613f44SDmitri Tikhonov memset(hdr, 0, sizeof(*hdr)); 8655613f44SDmitri Tikhonov hdr->buf = (char *)val; 8755613f44SDmitri Tikhonov hdr->qpack_index = qpack_idx; 8855613f44SDmitri Tikhonov assert(qpack_idx != -1); 8955613f44SDmitri Tikhonov hdr->flags = LSXPACK_QPACK_IDX; 9055613f44SDmitri Tikhonov assert(val_len <= LSXPACK_MAX_STRLEN); 9155613f44SDmitri Tikhonov hdr->val_len = val_len; 9255613f44SDmitri Tikhonov} 9355613f44SDmitri Tikhonov 9455613f44SDmitri Tikhonov 9555613f44SDmitri Tikhonovstatic inline void 96a5fa05f9SDmitri Tikhonovlsxpack_header_set_offset(lsxpack_header_t *hdr, const char *buf, 97a5fa05f9SDmitri Tikhonov size_t name_offset, size_t name_len, 98a5fa05f9SDmitri Tikhonov size_t val_len) 99a5fa05f9SDmitri Tikhonov{ 100a5fa05f9SDmitri Tikhonov memset(hdr, 0, sizeof(*hdr)); 101a5fa05f9SDmitri Tikhonov hdr->buf = (char *)buf; 102a5fa05f9SDmitri Tikhonov hdr->name_offset = name_offset; 103a5fa05f9SDmitri Tikhonov assert(name_len <= LSXPACK_MAX_STRLEN); 104a5fa05f9SDmitri Tikhonov hdr->name_len = name_len; 105a5fa05f9SDmitri Tikhonov assert(name_offset + name_len + 2 <= LSXPACK_MAX_STRLEN); 106a5fa05f9SDmitri Tikhonov hdr->val_offset = name_offset + name_len + 2; 107a5fa05f9SDmitri Tikhonov assert(val_len <= LSXPACK_MAX_STRLEN); 108a5fa05f9SDmitri Tikhonov hdr->val_len = val_len; 109a5fa05f9SDmitri Tikhonov} 110a5fa05f9SDmitri Tikhonov 111a5fa05f9SDmitri Tikhonov 112a5fa05f9SDmitri Tikhonovstatic inline void 113a5fa05f9SDmitri Tikhonovlsxpack_header_set_offset2(lsxpack_header_t *hdr, const char *buf, 114a5fa05f9SDmitri Tikhonov size_t name_offset, size_t name_len, 115a5fa05f9SDmitri Tikhonov size_t val_offset, size_t val_len) 116a5fa05f9SDmitri Tikhonov{ 117a5fa05f9SDmitri Tikhonov memset(hdr, 0, sizeof(*hdr)); 118a5fa05f9SDmitri Tikhonov hdr->buf = (char *)buf; 119a5fa05f9SDmitri Tikhonov hdr->name_offset = name_offset; 120a5fa05f9SDmitri Tikhonov assert(name_len <= LSXPACK_MAX_STRLEN); 121a5fa05f9SDmitri Tikhonov hdr->name_len = name_len; 122a5fa05f9SDmitri Tikhonov assert(val_offset <= LSXPACK_MAX_STRLEN); 123a5fa05f9SDmitri Tikhonov hdr->val_offset = val_offset; 124a5fa05f9SDmitri Tikhonov assert(val_len <= LSXPACK_MAX_STRLEN); 125a5fa05f9SDmitri Tikhonov hdr->val_len = val_len; 126a5fa05f9SDmitri Tikhonov} 127a5fa05f9SDmitri Tikhonov 128a5fa05f9SDmitri Tikhonov 129a5fa05f9SDmitri Tikhonovstatic inline void 130a5fa05f9SDmitri Tikhonovlsxpack_header_prepare_decode(lsxpack_header_t *hdr, 131a5fa05f9SDmitri Tikhonov char *out, size_t offset, size_t len) 132a5fa05f9SDmitri Tikhonov{ 133a5fa05f9SDmitri Tikhonov memset(hdr, 0, sizeof(*hdr)); 134a5fa05f9SDmitri Tikhonov hdr->buf = out; 135a5fa05f9SDmitri Tikhonov assert(offset <= LSXPACK_MAX_STRLEN); 136a5fa05f9SDmitri Tikhonov hdr->name_offset = offset; 137a5fa05f9SDmitri Tikhonov if (len > LSXPACK_MAX_STRLEN) 138a5fa05f9SDmitri Tikhonov hdr->val_len = LSXPACK_MAX_STRLEN; 139a5fa05f9SDmitri Tikhonov else 140a5fa05f9SDmitri Tikhonov hdr->val_len = len; 141a5fa05f9SDmitri Tikhonov} 142a5fa05f9SDmitri Tikhonov 143a5fa05f9SDmitri Tikhonov 144a5fa05f9SDmitri Tikhonovstatic inline const char * 145a5fa05f9SDmitri Tikhonovlsxpack_header_get_name(const lsxpack_header_t *hdr) 146a5fa05f9SDmitri Tikhonov{ 147fb3e20e0SDmitri Tikhonov return (hdr->name_len)? hdr->buf + hdr->name_offset : NULL; 148a5fa05f9SDmitri Tikhonov} 149a5fa05f9SDmitri Tikhonov 150a5fa05f9SDmitri Tikhonov 151a5fa05f9SDmitri Tikhonovstatic inline const char * 152a5fa05f9SDmitri Tikhonovlsxpack_header_get_value(const lsxpack_header_t *hdr) 153a5fa05f9SDmitri Tikhonov{ return hdr->buf + hdr->val_offset; } 154a5fa05f9SDmitri Tikhonov 155a5fa05f9SDmitri Tikhonovstatic inline size_t 156a5fa05f9SDmitri Tikhonovlsxpack_header_get_dec_size(const lsxpack_header_t *hdr) 157a5fa05f9SDmitri Tikhonov{ return hdr->name_len + hdr->val_len + hdr->dec_overhead; } 158a5fa05f9SDmitri Tikhonov 15908c45823SDmitri Tikhonovstatic inline void 16008c45823SDmitri Tikhonovlsxpack_header_mark_val_changed(lsxpack_header_t *hdr) 16108c45823SDmitri Tikhonov{ 16208c45823SDmitri Tikhonov hdr->flags = (enum lsxpack_flag)(hdr->flags & 163fb3e20e0SDmitri Tikhonov ~(LSXPACK_HPACK_VAL_MATCHED|LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH)); 16408c45823SDmitri Tikhonov} 165a5fa05f9SDmitri Tikhonov#ifdef __cplusplus 166a5fa05f9SDmitri Tikhonov} 167a5fa05f9SDmitri Tikhonov#endif 168a5fa05f9SDmitri Tikhonov 169fb3e20e0SDmitri Tikhonov#endif //LSXPACK_HEADER_H_v206 170