/*1* nghttp2 - HTTP/2 C Library2*3* Copyright (c) 2013 Tatsuhiro Tsujikawa4*5* Permission is hereby granted, free of charge, to any person obtaining6* a copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sublicense, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice shall be14* included in all copies or substantial portions of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,17* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND19* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE20* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION21* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION22* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23*/24#ifndef NGHTTP2_HD_H25#define NGHTTP2_HD_H2627#ifdef HAVE_CONFIG_H28# include <config.h>29#endif /* HAVE_CONFIG_H */3031#include <nghttp2/nghttp2.h>3233#include "nghttp2_hd_huffman.h"34#include "nghttp2_buf.h"35#include "nghttp2_mem.h"36#include "nghttp2_rcbuf.h"3738#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE39#define NGHTTP2_HD_ENTRY_OVERHEAD 324041/* The maximum length of one name/value pair. This is the sum of the42length of name and value. This is not specified by the spec. We43just chose the arbitrary size */44#define NGHTTP2_HD_MAX_NV 655364546/* Default size of maximum table buffer size for encoder. Even if47remote decoder notifies larger buffer size for its decoding,48encoder only uses the memory up to this value. */49#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)5051/* Exported for unit test */52#define NGHTTP2_STATIC_TABLE_LENGTH 615354/* Generated by genlibtokenlookup.py */55typedef enum {56NGHTTP2_TOKEN__AUTHORITY = 0,57NGHTTP2_TOKEN__METHOD = 1,58NGHTTP2_TOKEN__PATH = 3,59NGHTTP2_TOKEN__SCHEME = 5,60NGHTTP2_TOKEN__STATUS = 7,61NGHTTP2_TOKEN_ACCEPT_CHARSET = 14,62NGHTTP2_TOKEN_ACCEPT_ENCODING = 15,63NGHTTP2_TOKEN_ACCEPT_LANGUAGE = 16,64NGHTTP2_TOKEN_ACCEPT_RANGES = 17,65NGHTTP2_TOKEN_ACCEPT = 18,66NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 19,67NGHTTP2_TOKEN_AGE = 20,68NGHTTP2_TOKEN_ALLOW = 21,69NGHTTP2_TOKEN_AUTHORIZATION = 22,70NGHTTP2_TOKEN_CACHE_CONTROL = 23,71NGHTTP2_TOKEN_CONTENT_DISPOSITION = 24,72NGHTTP2_TOKEN_CONTENT_ENCODING = 25,73NGHTTP2_TOKEN_CONTENT_LANGUAGE = 26,74NGHTTP2_TOKEN_CONTENT_LENGTH = 27,75NGHTTP2_TOKEN_CONTENT_LOCATION = 28,76NGHTTP2_TOKEN_CONTENT_RANGE = 29,77NGHTTP2_TOKEN_CONTENT_TYPE = 30,78NGHTTP2_TOKEN_COOKIE = 31,79NGHTTP2_TOKEN_DATE = 32,80NGHTTP2_TOKEN_ETAG = 33,81NGHTTP2_TOKEN_EXPECT = 34,82NGHTTP2_TOKEN_EXPIRES = 35,83NGHTTP2_TOKEN_FROM = 36,84NGHTTP2_TOKEN_HOST = 37,85NGHTTP2_TOKEN_IF_MATCH = 38,86NGHTTP2_TOKEN_IF_MODIFIED_SINCE = 39,87NGHTTP2_TOKEN_IF_NONE_MATCH = 40,88NGHTTP2_TOKEN_IF_RANGE = 41,89NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE = 42,90NGHTTP2_TOKEN_LAST_MODIFIED = 43,91NGHTTP2_TOKEN_LINK = 44,92NGHTTP2_TOKEN_LOCATION = 45,93NGHTTP2_TOKEN_MAX_FORWARDS = 46,94NGHTTP2_TOKEN_PROXY_AUTHENTICATE = 47,95NGHTTP2_TOKEN_PROXY_AUTHORIZATION = 48,96NGHTTP2_TOKEN_RANGE = 49,97NGHTTP2_TOKEN_REFERER = 50,98NGHTTP2_TOKEN_REFRESH = 51,99NGHTTP2_TOKEN_RETRY_AFTER = 52,100NGHTTP2_TOKEN_SERVER = 53,101NGHTTP2_TOKEN_SET_COOKIE = 54,102NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY = 55,103NGHTTP2_TOKEN_TRANSFER_ENCODING = 56,104NGHTTP2_TOKEN_USER_AGENT = 57,105NGHTTP2_TOKEN_VARY = 58,106NGHTTP2_TOKEN_VIA = 59,107NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,108NGHTTP2_TOKEN_TE,109NGHTTP2_TOKEN_CONNECTION,110NGHTTP2_TOKEN_KEEP_ALIVE,111NGHTTP2_TOKEN_PROXY_CONNECTION,112NGHTTP2_TOKEN_UPGRADE,113NGHTTP2_TOKEN__PROTOCOL,114NGHTTP2_TOKEN_PRIORITY,115} nghttp2_token;116117struct nghttp2_hd_entry;118typedef struct nghttp2_hd_entry nghttp2_hd_entry;119120typedef struct {121/* The buffer containing header field name. NULL-termination is122guaranteed. */123nghttp2_rcbuf *name;124/* The buffer containing header field value. NULL-termination is125guaranteed. */126nghttp2_rcbuf *value;127/* nghttp2_token value for name. It could be -1 if we have no token128for that header field name. */129int32_t token;130/* Bitwise OR of one or more of nghttp2_nv_flag. */131uint8_t flags;132} nghttp2_hd_nv;133134struct nghttp2_hd_entry {135/* The header field name/value pair */136nghttp2_hd_nv nv;137/* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry138APIs to keep backward compatibility. */139nghttp2_nv cnv;140/* The next entry which shares same bucket in hash table. */141nghttp2_hd_entry *next;142/* The sequence number. We will increment it by one whenever we143store nghttp2_hd_entry to dynamic header table. */144uint32_t seq;145/* The hash value for header name (nv.name). */146uint32_t hash;147};148149/* The entry used for static header table. */150typedef struct {151nghttp2_rcbuf name;152nghttp2_rcbuf value;153nghttp2_nv cnv;154int32_t token;155uint32_t hash;156} nghttp2_hd_static_entry;157158typedef struct {159nghttp2_hd_entry **buffer;160size_t mask;161size_t first;162size_t len;163} nghttp2_hd_ringbuf;164165typedef enum {166NGHTTP2_HD_OPCODE_NONE,167NGHTTP2_HD_OPCODE_INDEXED,168NGHTTP2_HD_OPCODE_NEWNAME,169NGHTTP2_HD_OPCODE_INDNAME170} nghttp2_hd_opcode;171172typedef enum {173NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE,174NGHTTP2_HD_STATE_INFLATE_START,175NGHTTP2_HD_STATE_OPCODE,176NGHTTP2_HD_STATE_READ_TABLE_SIZE,177NGHTTP2_HD_STATE_READ_INDEX,178NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,179NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN,180NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF,181NGHTTP2_HD_STATE_NEWNAME_READ_NAME,182NGHTTP2_HD_STATE_CHECK_VALUELEN,183NGHTTP2_HD_STATE_READ_VALUELEN,184NGHTTP2_HD_STATE_READ_VALUEHUFF,185NGHTTP2_HD_STATE_READ_VALUE186} nghttp2_hd_inflate_state;187188typedef enum {189NGHTTP2_HD_WITH_INDEXING,190NGHTTP2_HD_WITHOUT_INDEXING,191NGHTTP2_HD_NEVER_INDEXING192} nghttp2_hd_indexing_mode;193194typedef struct {195/* dynamic header table */196nghttp2_hd_ringbuf hd_table;197/* Memory allocator */198nghttp2_mem *mem;199/* Abstract buffer size of hd_table as described in the spec. This200is the sum of length of name/value in hd_table +201NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */202size_t hd_table_bufsize;203/* The effective header table size. */204size_t hd_table_bufsize_max;205/* Next sequence number for nghttp2_hd_entry */206uint32_t next_seq;207/* If inflate/deflate error occurred, this value is set to 1 and208further invocation of inflate/deflate will fail with209NGHTTP2_ERR_HEADER_COMP. */210uint8_t bad;211} nghttp2_hd_context;212213#define HD_MAP_SIZE 128214215typedef struct {216nghttp2_hd_entry *table[HD_MAP_SIZE];217} nghttp2_hd_map;218219struct nghttp2_hd_deflater {220nghttp2_hd_context ctx;221nghttp2_hd_map map;222/* The upper limit of the header table size the deflater accepts. */223size_t deflate_hd_table_bufsize_max;224/* Minimum header table size notified in the next context update */225size_t min_hd_table_bufsize_max;226/* If nonzero, send header table size using encoding context update227in the next deflate process */228uint8_t notify_table_size_change;229};230231struct nghttp2_hd_inflater {232nghttp2_hd_context ctx;233/* Stores current state of huffman decoding */234nghttp2_hd_huff_decode_context huff_decode_ctx;235/* header buffer */236nghttp2_buf namebuf, valuebuf;237nghttp2_rcbuf *namercbuf, *valuercbuf;238/* Pointer to the name/value pair which are used in the current239header emission. */240nghttp2_rcbuf *nv_name_keep, *nv_value_keep;241/* The number of bytes to read */242size_t left;243/* The index in indexed repr or indexed name */244size_t index;245/* The maximum header table size the inflater supports. This is the246same value transmitted in SETTINGS_HEADER_TABLE_SIZE */247size_t settings_hd_table_bufsize_max;248/* Minimum header table size set by nghttp2_hd_inflate_change_table_size */249size_t min_hd_table_bufsize_max;250/* The number of next shift to decode integer */251size_t shift;252nghttp2_hd_opcode opcode;253nghttp2_hd_inflate_state state;254/* nonzero if string is huffman encoded */255uint8_t huffman_encoded;256/* nonzero if deflater requires that current entry is indexed */257uint8_t index_required;258/* nonzero if deflater requires that current entry must not be259indexed */260uint8_t no_index;261};262263/*264* Initializes the |ent| members. The reference counts of nv->name265* and nv->value are increased by one for each.266*/267void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv);268269/*270* This function decreases the reference counts of nv->name and271* nv->value.272*/273void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);274275/*276* Initializes |deflater| for deflating name/values pairs.277*278* The encoder only uses up to279* NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE bytes for header table280* even if the larger value is specified later in281* nghttp2_hd_change_table_size().282*283* This function returns 0 if it succeeds, or one of the following284* negative error codes:285*286* NGHTTP2_ERR_NOMEM287* Out of memory.288*/289int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);290291/*292* Initializes |deflater| for deflating name/values pairs.293*294* The encoder only uses up to |max_deflate_dynamic_table_size| bytes295* for header table even if the larger value is specified later in296* nghttp2_hd_change_table_size().297*298* This function returns 0 if it succeeds, or one of the following299* negative error codes:300*301* NGHTTP2_ERR_NOMEM302* Out of memory.303*/304int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,305size_t max_deflate_dynamic_table_size,306nghttp2_mem *mem);307308/*309* Deallocates any resources allocated for |deflater|.310*/311void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);312313/*314* Deflates the |nva|, which has the |nvlen| name/value pairs, into315* the |bufs|.316*317* This function expands |bufs| as necessary to store the result. If318* buffers is full and the process still requires more space, this319* function fails and returns NGHTTP2_ERR_HEADER_COMP.320*321* After this function returns, it is safe to delete the |nva|.322*323* This function returns 0 if it succeeds, or one of the following324* negative error codes:325*326* NGHTTP2_ERR_NOMEM327* Out of memory.328* NGHTTP2_ERR_HEADER_COMP329* Deflation process has failed.330* NGHTTP2_ERR_BUFFER_ERROR331* Out of buffer space.332*/333int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,334nghttp2_bufs *bufs, const nghttp2_nv *nva,335size_t nvlen);336337/*338* Initializes |inflater| for inflating name/values pairs.339*340* This function returns 0 if it succeeds, or one of the following341* negative error codes:342*343* :enum:`NGHTTP2_ERR_NOMEM`344* Out of memory.345*/346int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);347348/*349* Deallocates any resources allocated for |inflater|.350*/351void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);352353/*354* Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv355* instead of nghttp2_nv as output parameter |nv_out|. Other than356* that return values and semantics are the same as357* nghttp2_hd_inflate_hd().358*/359ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,360nghttp2_hd_nv *nv_out, int *inflate_flags,361const uint8_t *in, size_t inlen, int in_final);362363/* For unittesting purpose */364int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,365nghttp2_nv *nv, int indexing_mode);366367/* For unittesting purpose */368int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,369int indexing_mode);370371/* For unittesting purpose */372int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);373374/* For unittesting purpose */375nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);376377/* For unittesting purpose */378ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,379uint32_t initial, size_t shift, uint8_t *in,380uint8_t *last, size_t prefix);381382/* Huffman encoding/decoding functions */383384/*385* Counts the required bytes to encode |src| with length |len|.386*387* This function returns the number of required bytes to encode given388* data, including padding of prefix of terminal symbol code. This389* function always succeeds.390*/391size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);392393/*394* Encodes the given data |src| with length |srclen| to the |bufs|.395* This function expands extra buffers in |bufs| if necessary.396*397* This function returns 0 if it succeeds, or one of the following398* negative error codes:399*400* NGHTTP2_ERR_NOMEM401* Out of memory.402* NGHTTP2_ERR_BUFFER_ERROR403* Out of buffer space.404*/405int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,406size_t srclen);407408void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);409410/*411* Decodes the given data |src| with length |srclen|. The |ctx| must412* be initialized by nghttp2_hd_huff_decode_context_init(). The result413* will be written to |buf|. This function assumes that |buf| has the414* enough room to store the decoded byte string.415*416* The caller must set the |fin| to nonzero if the given input is the417* final block.418*419* This function returns the number of read bytes from the |in|.420*421* If this function fails, it returns one of the following negative422* return codes:423*424* NGHTTP2_ERR_NOMEM425* Out of memory.426* NGHTTP2_ERR_HEADER_COMP427* Decoding process has failed.428*/429ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,430nghttp2_buf *buf, const uint8_t *src,431size_t srclen, int fin);432433/*434* nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx|435* indicates that huffman decoding context is in failure state.436*/437int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx);438439#endif /* NGHTTP2_HD_H */440441442