cow_hpack.erl 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. %% Copyright (c) 2015-2018, Loïc Hoguin <essen@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. %% The current implementation is not suitable for use in
  15. %% intermediaries as the information about headers that
  16. %% should never be indexed is currently lost.
  17. -module(cow_hpack).
  18. -dialyzer(no_improper_lists).
  19. -export([init/0]).
  20. -export([init/1]).
  21. -export([set_max_size/2]).
  22. -export([decode/1]).
  23. -export([decode/2]).
  24. -export([encode/1]).
  25. -export([encode/2]).
  26. -export([encode/3]).
  27. -record(state, {
  28. size = 0 :: non_neg_integer(),
  29. max_size = 4096 :: non_neg_integer(),
  30. configured_max_size = 4096 :: non_neg_integer(),
  31. dyn_table = [] :: [{pos_integer(), {binary(), binary()}}]
  32. }).
  33. -opaque state() :: #state{}.
  34. -export_type([state/0]).
  35. -type opts() :: map().
  36. -export_type([opts/0]).
  37. -ifdef(TEST).
  38. -include_lib("proper/include/proper.hrl").
  39. -endif.
  40. %% State initialization.
  41. -spec init() -> state().
  42. init() ->
  43. #state{}.
  44. -spec init(non_neg_integer()) -> state().
  45. init(MaxSize) ->
  46. #state{max_size=MaxSize, configured_max_size=MaxSize}.
  47. %% Update the configured max size.
  48. %%
  49. %% When decoding, the local endpoint also needs to send a SETTINGS
  50. %% frame with this value and it is then up to the remote endpoint
  51. %% to decide what actual limit it will use. The actual limit is
  52. %% signaled via dynamic table size updates in the encoded data.
  53. %%
  54. %% When encoding, the local endpoint will call this function after
  55. %% receiving a SETTINGS frame with this value. The encoder will
  56. %% then use this value as the new max after signaling via a dynamic
  57. %% table size update. The value given as argument may be lower
  58. %% than the one received in the SETTINGS.
  59. -spec set_max_size(non_neg_integer(), State) -> State when State::state().
  60. set_max_size(MaxSize, State) ->
  61. State#state{configured_max_size=MaxSize}.
  62. %% Decoding.
  63. -spec decode(binary()) -> {cow_http:headers(), state()}.
  64. decode(Data) ->
  65. decode(Data, init()).
  66. -spec decode(binary(), State) -> {cow_http:headers(), State} when State::state().
  67. %% Dynamic table size update is only allowed at the beginning of a HEADERS block.
  68. decode(<< 0:2, 1:1, Rest/bits >>, State=#state{configured_max_size=ConfigMaxSize}) ->
  69. {MaxSize, Rest2} = dec_int5(Rest),
  70. if
  71. MaxSize =< ConfigMaxSize ->
  72. State2 = table_update_size(MaxSize, State),
  73. decode(Rest2, State2)
  74. end;
  75. decode(Data, State) ->
  76. decode(Data, State, []).
  77. decode(<<>>, State, Acc) ->
  78. {lists:reverse(Acc), State};
  79. %% Indexed header field representation.
  80. decode(<< 1:1, Rest/bits >>, State, Acc) ->
  81. dec_indexed(Rest, State, Acc);
  82. %% Literal header field with incremental indexing: new name.
  83. decode(<< 0:1, 1:1, 0:6, Rest/bits >>, State, Acc) ->
  84. dec_lit_index_new_name(Rest, State, Acc);
  85. %% Literal header field with incremental indexing: indexed name.
  86. decode(<< 0:1, 1:1, Rest/bits >>, State, Acc) ->
  87. dec_lit_index_indexed_name(Rest, State, Acc);
  88. %% Literal header field without indexing: new name.
  89. decode(<< 0:8, Rest/bits >>, State, Acc) ->
  90. dec_lit_no_index_new_name(Rest, State, Acc);
  91. %% Literal header field without indexing: indexed name.
  92. decode(<< 0:4, Rest/bits >>, State, Acc) ->
  93. dec_lit_no_index_indexed_name(Rest, State, Acc);
  94. %% Literal header field never indexed: new name.
  95. %% @todo Keep track of "never indexed" headers.
  96. decode(<< 0:3, 1:1, 0:4, Rest/bits >>, State, Acc) ->
  97. dec_lit_no_index_new_name(Rest, State, Acc);
  98. %% Literal header field never indexed: indexed name.
  99. %% @todo Keep track of "never indexed" headers.
  100. decode(<< 0:3, 1:1, Rest/bits >>, State, Acc) ->
  101. dec_lit_no_index_indexed_name(Rest, State, Acc).
  102. %% Indexed header field representation.
  103. %% We do the integer decoding inline where appropriate, falling
  104. %% back to dec_big_int for larger values.
  105. dec_indexed(<<2#1111111:7, 0:1, Int:7, Rest/bits>>, State, Acc) ->
  106. {Name, Value} = table_get(127 + Int, State),
  107. decode(Rest, State, [{Name, Value}|Acc]);
  108. dec_indexed(<<2#1111111:7, Rest0/bits>>, State, Acc) ->
  109. {Index, Rest} = dec_big_int(Rest0, 127, 0),
  110. {Name, Value} = table_get(Index, State),
  111. decode(Rest, State, [{Name, Value}|Acc]);
  112. dec_indexed(<<Index:7, Rest/bits>>, State, Acc) ->
  113. {Name, Value} = table_get(Index, State),
  114. decode(Rest, State, [{Name, Value}|Acc]).
  115. %% Literal header field with incremental indexing.
  116. dec_lit_index_new_name(Rest, State, Acc) ->
  117. {Name, Rest2} = dec_str(Rest),
  118. dec_lit_index(Rest2, State, Acc, Name).
  119. %% We do the integer decoding inline where appropriate, falling
  120. %% back to dec_big_int for larger values.
  121. dec_lit_index_indexed_name(<<2#111111:6, 0:1, Int:7, Rest/bits>>, State, Acc) ->
  122. Name = table_get_name(63 + Int, State),
  123. dec_lit_index(Rest, State, Acc, Name);
  124. dec_lit_index_indexed_name(<<2#111111:6, Rest0/bits>>, State, Acc) ->
  125. {Index, Rest} = dec_big_int(Rest0, 63, 0),
  126. Name = table_get_name(Index, State),
  127. dec_lit_index(Rest, State, Acc, Name);
  128. dec_lit_index_indexed_name(<<Index:6, Rest/bits>>, State, Acc) ->
  129. Name = table_get_name(Index, State),
  130. dec_lit_index(Rest, State, Acc, Name).
  131. dec_lit_index(Rest, State, Acc, Name) ->
  132. {Value, Rest2} = dec_str(Rest),
  133. State2 = table_insert({Name, Value}, State),
  134. decode(Rest2, State2, [{Name, Value}|Acc]).
  135. %% Literal header field without indexing.
  136. dec_lit_no_index_new_name(Rest, State, Acc) ->
  137. {Name, Rest2} = dec_str(Rest),
  138. dec_lit_no_index(Rest2, State, Acc, Name).
  139. %% We do the integer decoding inline where appropriate, falling
  140. %% back to dec_big_int for larger values.
  141. dec_lit_no_index_indexed_name(<<2#1111:4, 0:1, Int:7, Rest/bits>>, State, Acc) ->
  142. Name = table_get_name(15 + Int, State),
  143. dec_lit_no_index(Rest, State, Acc, Name);
  144. dec_lit_no_index_indexed_name(<<2#1111:4, Rest0/bits>>, State, Acc) ->
  145. {Index, Rest} = dec_big_int(Rest0, 15, 0),
  146. Name = table_get_name(Index, State),
  147. dec_lit_no_index(Rest, State, Acc, Name);
  148. dec_lit_no_index_indexed_name(<<Index:4, Rest/bits>>, State, Acc) ->
  149. Name = table_get_name(Index, State),
  150. dec_lit_no_index(Rest, State, Acc, Name).
  151. dec_lit_no_index(Rest, State, Acc, Name) ->
  152. {Value, Rest2} = dec_str(Rest),
  153. decode(Rest2, State, [{Name, Value}|Acc]).
  154. %% @todo Literal header field never indexed.
  155. %% Decode an integer.
  156. %% The HPACK format has 4 different integer prefixes length (from 4 to 7)
  157. %% and each can be used to create an indefinite length integer if all bits
  158. %% of the prefix are set to 1.
  159. dec_int5(<< 2#11111:5, Rest/bits >>) ->
  160. dec_big_int(Rest, 31, 0);
  161. dec_int5(<< Int:5, Rest/bits >>) ->
  162. {Int, Rest}.
  163. dec_big_int(<< 0:1, Value:7, Rest/bits >>, Int, M) ->
  164. {Int + (Value bsl M), Rest};
  165. dec_big_int(<< 1:1, Value:7, Rest/bits >>, Int, M) ->
  166. dec_big_int(Rest, Int + (Value bsl M), M + 7).
  167. %% Decode a string.
  168. dec_str(<<0:1, 2#1111111:7, Rest0/bits>>) ->
  169. {Length, Rest1} = dec_big_int(Rest0, 127, 0),
  170. <<Str:Length/binary, Rest/bits>> = Rest1,
  171. {Str, Rest};
  172. dec_str(<<0:1, Length:7, Rest0/bits>>) ->
  173. <<Str:Length/binary, Rest/bits>> = Rest0,
  174. {Str, Rest};
  175. dec_str(<<1:1, 2#1111111:7, Rest0/bits>>) ->
  176. {Length, Rest} = dec_big_int(Rest0, 127, 0),
  177. dec_huffman(Rest, Length, 0, <<>>);
  178. dec_str(<<1:1, Length:7, Rest/bits>>) ->
  179. dec_huffman(Rest, Length, 0, <<>>).
  180. %% We use a lookup table that allows us to benefit from
  181. %% the binary match context optimization. A more naive
  182. %% implementation using bit pattern matching cannot reuse
  183. %% a match context because it wouldn't always match on
  184. %% byte boundaries.
  185. %%
  186. %% See cow_hpack_dec_huffman_lookup.hrl for more details.
  187. dec_huffman(<<A:4, B:4, R/bits>>, Len, Huff0, Acc) when Len > 1 ->
  188. {_, CharA, Huff1} = dec_huffman_lookup(Huff0, A),
  189. {_, CharB, Huff} = dec_huffman_lookup(Huff1, B),
  190. case {CharA, CharB} of
  191. {undefined, undefined} -> dec_huffman(R, Len - 1, Huff, Acc);
  192. {CharA, undefined} -> dec_huffman(R, Len - 1, Huff, <<Acc/binary, CharA>>);
  193. {undefined, CharB} -> dec_huffman(R, Len - 1, Huff, <<Acc/binary, CharB>>);
  194. {CharA, CharB} -> dec_huffman(R, Len - 1, Huff, <<Acc/binary, CharA, CharB>>)
  195. end;
  196. dec_huffman(<<A:4, B:4, Rest/bits>>, 1, Huff0, Acc) ->
  197. {_, CharA, Huff} = dec_huffman_lookup(Huff0, A),
  198. {ok, CharB, _} = dec_huffman_lookup(Huff, B),
  199. case {CharA, CharB} of
  200. %% {undefined, undefined} (> 7-bit final padding) is rejected with a crash.
  201. {CharA, undefined} ->
  202. {<<Acc/binary, CharA>>, Rest};
  203. {undefined, CharB} ->
  204. {<<Acc/binary, CharB>>, Rest};
  205. _ ->
  206. {<<Acc/binary, CharA, CharB>>, Rest}
  207. end;
  208. %% Can only be reached when the string length to decode is 0.
  209. dec_huffman(Rest, 0, _, <<>>) ->
  210. {<<>>, Rest}.
  211. -include("cow_hpack_dec_huffman_lookup.hrl").
  212. -ifdef(TEST).
  213. %% Test case extracted from h2spec.
  214. decode_reject_eos_test() ->
  215. {'EXIT', _} = (catch decode(<<16#0085f2b24a84ff874951fffffffa7f:120>>)),
  216. ok.
  217. req_decode_test() ->
  218. %% First request (raw then huffman).
  219. {Headers1, State1} = decode(<< 16#828684410f7777772e6578616d706c652e636f6d:160 >>),
  220. {Headers1, State1} = decode(<< 16#828684418cf1e3c2e5f23a6ba0ab90f4ff:136 >>),
  221. Headers1 = [
  222. {<<":method">>, <<"GET">>},
  223. {<<":scheme">>, <<"http">>},
  224. {<<":path">>, <<"/">>},
  225. {<<":authority">>, <<"www.example.com">>}
  226. ],
  227. #state{size=57, dyn_table=[{57,{<<":authority">>, <<"www.example.com">>}}]} = State1,
  228. %% Second request (raw then huffman).
  229. {Headers2, State2} = decode(<< 16#828684be58086e6f2d6361636865:112 >>, State1),
  230. {Headers2, State2} = decode(<< 16#828684be5886a8eb10649cbf:96 >>, State1),
  231. Headers2 = [
  232. {<<":method">>, <<"GET">>},
  233. {<<":scheme">>, <<"http">>},
  234. {<<":path">>, <<"/">>},
  235. {<<":authority">>, <<"www.example.com">>},
  236. {<<"cache-control">>, <<"no-cache">>}
  237. ],
  238. #state{size=110, dyn_table=[
  239. {53,{<<"cache-control">>, <<"no-cache">>}},
  240. {57,{<<":authority">>, <<"www.example.com">>}}]} = State2,
  241. %% Third request (raw then huffman).
  242. {Headers3, State3} = decode(<< 16#828785bf400a637573746f6d2d6b65790c637573746f6d2d76616c7565:232 >>, State2),
  243. {Headers3, State3} = decode(<< 16#828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf:192 >>, State2),
  244. Headers3 = [
  245. {<<":method">>, <<"GET">>},
  246. {<<":scheme">>, <<"https">>},
  247. {<<":path">>, <<"/index.html">>},
  248. {<<":authority">>, <<"www.example.com">>},
  249. {<<"custom-key">>, <<"custom-value">>}
  250. ],
  251. #state{size=164, dyn_table=[
  252. {54,{<<"custom-key">>, <<"custom-value">>}},
  253. {53,{<<"cache-control">>, <<"no-cache">>}},
  254. {57,{<<":authority">>, <<"www.example.com">>}}]} = State3,
  255. ok.
  256. resp_decode_test() ->
  257. %% Use a max_size of 256 to trigger header evictions.
  258. State0 = init(256),
  259. %% First response (raw then huffman).
  260. {Headers1, State1} = decode(<< 16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560 >>, State0),
  261. {Headers1, State1} = decode(<< 16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432 >>, State0),
  262. Headers1 = [
  263. {<<":status">>, <<"302">>},
  264. {<<"cache-control">>, <<"private">>},
  265. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  266. {<<"location">>, <<"https://www.example.com">>}
  267. ],
  268. #state{size=222, dyn_table=[
  269. {63,{<<"location">>, <<"https://www.example.com">>}},
  270. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  271. {52,{<<"cache-control">>, <<"private">>}},
  272. {42,{<<":status">>, <<"302">>}}]} = State1,
  273. %% Second response (raw then huffman).
  274. {Headers2, State2} = decode(<< 16#4803333037c1c0bf:64 >>, State1),
  275. {Headers2, State2} = decode(<< 16#4883640effc1c0bf:64 >>, State1),
  276. Headers2 = [
  277. {<<":status">>, <<"307">>},
  278. {<<"cache-control">>, <<"private">>},
  279. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  280. {<<"location">>, <<"https://www.example.com">>}
  281. ],
  282. #state{size=222, dyn_table=[
  283. {42,{<<":status">>, <<"307">>}},
  284. {63,{<<"location">>, <<"https://www.example.com">>}},
  285. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  286. {52,{<<"cache-control">>, <<"private">>}}]} = State2,
  287. %% Third response (raw then huffman).
  288. {Headers3, State3} = decode(<< 16#88c1611d4d6f6e2c203231204f637420323031332032303a31333a323220474d54c05a04677a69707738666f6f3d4153444a4b48514b425a584f5157454f50495541585157454f49553b206d61782d6167653d333630303b2076657273696f6e3d31:784 >>, State2),
  289. {Headers3, State3} = decode(<< 16#88c16196d07abe941054d444a8200595040b8166e084a62d1bffc05a839bd9ab77ad94e7821dd7f2e6c7b335dfdfcd5b3960d5af27087f3672c1ab270fb5291f9587316065c003ed4ee5b1063d5007:632 >>, State2),
  290. Headers3 = [
  291. {<<":status">>, <<"200">>},
  292. {<<"cache-control">>, <<"private">>},
  293. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:22 GMT">>},
  294. {<<"location">>, <<"https://www.example.com">>},
  295. {<<"content-encoding">>, <<"gzip">>},
  296. {<<"set-cookie">>, <<"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1">>}
  297. ],
  298. #state{size=215, dyn_table=[
  299. {98,{<<"set-cookie">>, <<"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1">>}},
  300. {52,{<<"content-encoding">>, <<"gzip">>}},
  301. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:22 GMT">>}}]} = State3,
  302. ok.
  303. table_update_decode_test() ->
  304. %% Use a max_size of 256 to trigger header evictions
  305. %% when the code is not updating the max size.
  306. State0 = init(256),
  307. %% First response (raw then huffman).
  308. {Headers1, State1} = decode(<< 16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560 >>, State0),
  309. {Headers1, State1} = decode(<< 16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432 >>, State0),
  310. Headers1 = [
  311. {<<":status">>, <<"302">>},
  312. {<<"cache-control">>, <<"private">>},
  313. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  314. {<<"location">>, <<"https://www.example.com">>}
  315. ],
  316. #state{size=222, configured_max_size=256, dyn_table=[
  317. {63,{<<"location">>, <<"https://www.example.com">>}},
  318. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  319. {52,{<<"cache-control">>, <<"private">>}},
  320. {42,{<<":status">>, <<"302">>}}]} = State1,
  321. %% Set a new configured max_size to avoid header evictions.
  322. State2 = set_max_size(512, State1),
  323. %% Second response with the table size update (raw then huffman).
  324. MaxSize = enc_big_int(512 - 31, <<>>),
  325. {Headers2, State3} = decode(
  326. iolist_to_binary([<< 2#00111111>>, MaxSize, <<16#4803333037c1c0bf:64>>]),
  327. State2),
  328. {Headers2, State3} = decode(
  329. iolist_to_binary([<< 2#00111111>>, MaxSize, <<16#4883640effc1c0bf:64>>]),
  330. State2),
  331. Headers2 = [
  332. {<<":status">>, <<"307">>},
  333. {<<"cache-control">>, <<"private">>},
  334. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  335. {<<"location">>, <<"https://www.example.com">>}
  336. ],
  337. #state{size=264, configured_max_size=512, dyn_table=[
  338. {42,{<<":status">>, <<"307">>}},
  339. {63,{<<"location">>, <<"https://www.example.com">>}},
  340. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  341. {52,{<<"cache-control">>, <<"private">>}},
  342. {42,{<<":status">>, <<"302">>}}]} = State3,
  343. ok.
  344. table_update_decode_smaller_test() ->
  345. %% Use a max_size of 256 to trigger header evictions
  346. %% when the code is not updating the max size.
  347. State0 = init(256),
  348. %% First response (raw then huffman).
  349. {Headers1, State1} = decode(<< 16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560 >>, State0),
  350. {Headers1, State1} = decode(<< 16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432 >>, State0),
  351. Headers1 = [
  352. {<<":status">>, <<"302">>},
  353. {<<"cache-control">>, <<"private">>},
  354. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  355. {<<"location">>, <<"https://www.example.com">>}
  356. ],
  357. #state{size=222, configured_max_size=256, dyn_table=[
  358. {63,{<<"location">>, <<"https://www.example.com">>}},
  359. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  360. {52,{<<"cache-control">>, <<"private">>}},
  361. {42,{<<":status">>, <<"302">>}}]} = State1,
  362. %% Set a new configured max_size to avoid header evictions.
  363. State2 = set_max_size(512, State1),
  364. %% Second response with the table size update smaller than the limit (raw then huffman).
  365. MaxSize = enc_big_int(400 - 31, <<>>),
  366. {Headers2, State3} = decode(
  367. iolist_to_binary([<< 2#00111111>>, MaxSize, <<16#4803333037c1c0bf:64>>]),
  368. State2),
  369. {Headers2, State3} = decode(
  370. iolist_to_binary([<< 2#00111111>>, MaxSize, <<16#4883640effc1c0bf:64>>]),
  371. State2),
  372. Headers2 = [
  373. {<<":status">>, <<"307">>},
  374. {<<"cache-control">>, <<"private">>},
  375. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  376. {<<"location">>, <<"https://www.example.com">>}
  377. ],
  378. #state{size=264, configured_max_size=512, dyn_table=[
  379. {42,{<<":status">>, <<"307">>}},
  380. {63,{<<"location">>, <<"https://www.example.com">>}},
  381. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  382. {52,{<<"cache-control">>, <<"private">>}},
  383. {42,{<<":status">>, <<"302">>}}]} = State3,
  384. ok.
  385. table_update_decode_too_large_test() ->
  386. %% Use a max_size of 256 to trigger header evictions
  387. %% when the code is not updating the max size.
  388. State0 = init(256),
  389. %% First response (raw then huffman).
  390. {Headers1, State1} = decode(<< 16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560 >>, State0),
  391. {Headers1, State1} = decode(<< 16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432 >>, State0),
  392. Headers1 = [
  393. {<<":status">>, <<"302">>},
  394. {<<"cache-control">>, <<"private">>},
  395. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  396. {<<"location">>, <<"https://www.example.com">>}
  397. ],
  398. #state{size=222, configured_max_size=256, dyn_table=[
  399. {63,{<<"location">>, <<"https://www.example.com">>}},
  400. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  401. {52,{<<"cache-control">>, <<"private">>}},
  402. {42,{<<":status">>, <<"302">>}}]} = State1,
  403. %% Set a new configured max_size to avoid header evictions.
  404. State2 = set_max_size(512, State1),
  405. %% Second response with the table size update (raw then huffman).
  406. MaxSize = enc_big_int(1024 - 31, <<>>),
  407. {'EXIT', _} = (catch decode(
  408. iolist_to_binary([<< 2#00111111>>, MaxSize, <<16#4803333037c1c0bf:64>>]),
  409. State2)),
  410. {'EXIT', _} = (catch decode(
  411. iolist_to_binary([<< 2#00111111>>, MaxSize, <<16#4883640effc1c0bf:64>>]),
  412. State2)),
  413. ok.
  414. table_update_decode_zero_test() ->
  415. State0 = init(256),
  416. %% First response (raw then huffman).
  417. {Headers1, State1} = decode(<< 16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560 >>, State0),
  418. {Headers1, State1} = decode(<< 16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432 >>, State0),
  419. Headers1 = [
  420. {<<":status">>, <<"302">>},
  421. {<<"cache-control">>, <<"private">>},
  422. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  423. {<<"location">>, <<"https://www.example.com">>}
  424. ],
  425. #state{size=222, configured_max_size=256, dyn_table=[
  426. {63,{<<"location">>, <<"https://www.example.com">>}},
  427. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  428. {52,{<<"cache-control">>, <<"private">>}},
  429. {42,{<<":status">>, <<"302">>}}]} = State1,
  430. %% Set a new configured max_size to avoid header evictions.
  431. State2 = set_max_size(512, State1),
  432. %% Second response with the table size update (raw then huffman).
  433. %% We set the table size to 0 to evict all values before setting
  434. %% it to 512 so we only get the second request indexed.
  435. MaxSize = enc_big_int(512 - 31, <<>>),
  436. {Headers1, State3} = decode(iolist_to_binary([
  437. <<2#00100000, 2#00111111>>, MaxSize,
  438. <<16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560>>]),
  439. State2),
  440. {Headers1, State3} = decode(iolist_to_binary([
  441. <<2#00100000, 2#00111111>>, MaxSize,
  442. <<16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432>>]),
  443. State2),
  444. #state{size=222, configured_max_size=512, dyn_table=[
  445. {63,{<<"location">>, <<"https://www.example.com">>}},
  446. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  447. {52,{<<"cache-control">>, <<"private">>}},
  448. {42,{<<":status">>, <<"302">>}}]} = State3,
  449. ok.
  450. horse_decode_raw() ->
  451. horse:repeat(20000,
  452. do_horse_decode_raw()
  453. ).
  454. do_horse_decode_raw() ->
  455. {_, State1} = decode(<<16#828684410f7777772e6578616d706c652e636f6d:160>>),
  456. {_, State2} = decode(<<16#828684be58086e6f2d6361636865:112>>, State1),
  457. {_, _} = decode(<<16#828785bf400a637573746f6d2d6b65790c637573746f6d2d76616c7565:232>>, State2),
  458. ok.
  459. horse_decode_huffman() ->
  460. horse:repeat(20000,
  461. do_horse_decode_huffman()
  462. ).
  463. do_horse_decode_huffman() ->
  464. {_, State1} = decode(<<16#828684418cf1e3c2e5f23a6ba0ab90f4ff:136>>),
  465. {_, State2} = decode(<<16#828684be5886a8eb10649cbf:96>>, State1),
  466. {_, _} = decode(<<16#828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf:192>>, State2),
  467. ok.
  468. -endif.
  469. %% Encoding.
  470. -spec encode(cow_http:headers()) -> {iodata(), state()}.
  471. encode(Headers) ->
  472. encode(Headers, init(), huffman, []).
  473. -spec encode(cow_http:headers(), State) -> {iodata(), State} when State::state().
  474. encode(Headers, State=#state{max_size=MaxSize, configured_max_size=MaxSize}) ->
  475. encode(Headers, State, huffman, []);
  476. encode(Headers, State0=#state{configured_max_size=MaxSize}) ->
  477. State1 = table_update_size(MaxSize, State0),
  478. {Data, State} = encode(Headers, State1, huffman, []),
  479. {[enc_int5(MaxSize, 2#001)|Data], State}.
  480. -spec encode(cow_http:headers(), State, opts()) -> {iodata(), State} when State::state().
  481. encode(Headers, State=#state{max_size=MaxSize, configured_max_size=MaxSize}, Opts) ->
  482. encode(Headers, State, huffman_opt(Opts), []);
  483. encode(Headers, State0=#state{configured_max_size=MaxSize}, Opts) ->
  484. State1 = table_update_size(MaxSize, State0),
  485. {Data, State} = encode(Headers, State1, huffman_opt(Opts), []),
  486. {[enc_int5(MaxSize, 2#001)|Data], State}.
  487. huffman_opt(#{huffman := false}) -> no_huffman;
  488. huffman_opt(_) -> huffman.
  489. %% @todo Handle cases where no/never indexing is expected.
  490. encode([], State, _, Acc) ->
  491. {lists:reverse(Acc), State};
  492. encode([{Name, Value0}|Tail], State, HuffmanOpt, Acc) ->
  493. %% We conditionally call iolist_to_binary/1 because a small
  494. %% but noticeable speed improvement happens when we do this.
  495. Value = if
  496. is_binary(Value0) -> Value0;
  497. true -> iolist_to_binary(Value0)
  498. end,
  499. Header = {Name, Value},
  500. case table_find(Header, State) of
  501. %% Indexed header field representation.
  502. {field, Index} ->
  503. encode(Tail, State, HuffmanOpt,
  504. [enc_int7(Index, 2#1)|Acc]);
  505. %% Literal header field representation: indexed name.
  506. {name, Index} ->
  507. State2 = table_insert(Header, State),
  508. encode(Tail, State2, HuffmanOpt,
  509. [[enc_int6(Index, 2#01)|enc_str(Value, HuffmanOpt)]|Acc]);
  510. %% Literal header field representation: new name.
  511. not_found ->
  512. State2 = table_insert(Header, State),
  513. encode(Tail, State2, HuffmanOpt,
  514. [[<< 0:1, 1:1, 0:6 >>|[enc_str(Name, HuffmanOpt)|enc_str(Value, HuffmanOpt)]]|Acc])
  515. end.
  516. %% Encode an integer.
  517. enc_int5(Int, Prefix) when Int < 31 ->
  518. << Prefix:3, Int:5 >>;
  519. enc_int5(Int, Prefix) ->
  520. enc_big_int(Int - 31, << Prefix:3, 2#11111:5 >>).
  521. enc_int6(Int, Prefix) when Int < 63 ->
  522. << Prefix:2, Int:6 >>;
  523. enc_int6(Int, Prefix) ->
  524. enc_big_int(Int - 63, << Prefix:2, 2#111111:6 >>).
  525. enc_int7(Int, Prefix) when Int < 127 ->
  526. << Prefix:1, Int:7 >>;
  527. enc_int7(Int, Prefix) ->
  528. enc_big_int(Int - 127, << Prefix:1, 2#1111111:7 >>).
  529. enc_big_int(Int, Acc) when Int < 128 ->
  530. <<Acc/binary, Int:8>>;
  531. enc_big_int(Int, Acc) ->
  532. enc_big_int(Int bsr 7, <<Acc/binary, 1:1, Int:7>>).
  533. %% Encode a string.
  534. enc_str(Str, huffman) ->
  535. Str2 = enc_huffman(Str, <<>>),
  536. [enc_int7(byte_size(Str2), 2#1)|Str2];
  537. enc_str(Str, no_huffman) ->
  538. [enc_int7(byte_size(Str), 2#0)|Str].
  539. enc_huffman(<<>>, Acc) ->
  540. case bit_size(Acc) rem 8 of
  541. 1 -> << Acc/bits, 2#1111111:7 >>;
  542. 2 -> << Acc/bits, 2#111111:6 >>;
  543. 3 -> << Acc/bits, 2#11111:5 >>;
  544. 4 -> << Acc/bits, 2#1111:4 >>;
  545. 5 -> << Acc/bits, 2#111:3 >>;
  546. 6 -> << Acc/bits, 2#11:2 >>;
  547. 7 -> << Acc/bits, 2#1:1 >>;
  548. 0 -> Acc
  549. end;
  550. enc_huffman(<< 0, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111000:13 >>);
  551. enc_huffman(<< 1, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011000:23 >>);
  552. enc_huffman(<< 2, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111100010:28 >>);
  553. enc_huffman(<< 3, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111100011:28 >>);
  554. enc_huffman(<< 4, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111100100:28 >>);
  555. enc_huffman(<< 5, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111100101:28 >>);
  556. enc_huffman(<< 6, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111100110:28 >>);
  557. enc_huffman(<< 7, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111100111:28 >>);
  558. enc_huffman(<< 8, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101000:28 >>);
  559. enc_huffman(<< 9, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111101010:24 >>);
  560. enc_huffman(<< 10, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111111111100:30 >>);
  561. enc_huffman(<< 11, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101001:28 >>);
  562. enc_huffman(<< 12, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101010:28 >>);
  563. enc_huffman(<< 13, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111111111101:30 >>);
  564. enc_huffman(<< 14, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101011:28 >>);
  565. enc_huffman(<< 15, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101100:28 >>);
  566. enc_huffman(<< 16, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101101:28 >>);
  567. enc_huffman(<< 17, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101110:28 >>);
  568. enc_huffman(<< 18, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111101111:28 >>);
  569. enc_huffman(<< 19, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110000:28 >>);
  570. enc_huffman(<< 20, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110001:28 >>);
  571. enc_huffman(<< 21, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110010:28 >>);
  572. enc_huffman(<< 22, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111111111110:30 >>);
  573. enc_huffman(<< 23, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110011:28 >>);
  574. enc_huffman(<< 24, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110100:28 >>);
  575. enc_huffman(<< 25, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110101:28 >>);
  576. enc_huffman(<< 26, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110110:28 >>);
  577. enc_huffman(<< 27, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111110111:28 >>);
  578. enc_huffman(<< 28, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111000:28 >>);
  579. enc_huffman(<< 29, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111001:28 >>);
  580. enc_huffman(<< 30, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111010:28 >>);
  581. enc_huffman(<< 31, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111011:28 >>);
  582. enc_huffman(<< 32, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#010100:6 >>);
  583. enc_huffman(<< 33, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111000:10 >>);
  584. enc_huffman(<< 34, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111001:10 >>);
  585. enc_huffman(<< 35, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111010:12 >>);
  586. enc_huffman(<< 36, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111001:13 >>);
  587. enc_huffman(<< 37, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#010101:6 >>);
  588. enc_huffman(<< 38, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111000:8 >>);
  589. enc_huffman(<< 39, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111010:11 >>);
  590. enc_huffman(<< 40, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111010:10 >>);
  591. enc_huffman(<< 41, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111011:10 >>);
  592. enc_huffman(<< 42, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111001:8 >>);
  593. enc_huffman(<< 43, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111011:11 >>);
  594. enc_huffman(<< 44, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111010:8 >>);
  595. enc_huffman(<< 45, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#010110:6 >>);
  596. enc_huffman(<< 46, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#010111:6 >>);
  597. enc_huffman(<< 47, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011000:6 >>);
  598. enc_huffman(<< 48, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00000:5 >>);
  599. enc_huffman(<< 49, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00001:5 >>);
  600. enc_huffman(<< 50, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00010:5 >>);
  601. enc_huffman(<< 51, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011001:6 >>);
  602. enc_huffman(<< 52, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011010:6 >>);
  603. enc_huffman(<< 53, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011011:6 >>);
  604. enc_huffman(<< 54, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011100:6 >>);
  605. enc_huffman(<< 55, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011101:6 >>);
  606. enc_huffman(<< 56, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011110:6 >>);
  607. enc_huffman(<< 57, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#011111:6 >>);
  608. enc_huffman(<< 58, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1011100:7 >>);
  609. enc_huffman(<< 59, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111011:8 >>);
  610. enc_huffman(<< 60, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111100:15 >>);
  611. enc_huffman(<< 61, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100000:6 >>);
  612. enc_huffman(<< 62, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111011:12 >>);
  613. enc_huffman(<< 63, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111100:10 >>);
  614. enc_huffman(<< 64, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111010:13 >>);
  615. enc_huffman(<< 65, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100001:6 >>);
  616. enc_huffman(<< 66, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1011101:7 >>);
  617. enc_huffman(<< 67, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1011110:7 >>);
  618. enc_huffman(<< 68, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1011111:7 >>);
  619. enc_huffman(<< 69, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100000:7 >>);
  620. enc_huffman(<< 70, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100001:7 >>);
  621. enc_huffman(<< 71, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100010:7 >>);
  622. enc_huffman(<< 72, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100011:7 >>);
  623. enc_huffman(<< 73, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100100:7 >>);
  624. enc_huffman(<< 74, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100101:7 >>);
  625. enc_huffman(<< 75, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100110:7 >>);
  626. enc_huffman(<< 76, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1100111:7 >>);
  627. enc_huffman(<< 77, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101000:7 >>);
  628. enc_huffman(<< 78, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101001:7 >>);
  629. enc_huffman(<< 79, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101010:7 >>);
  630. enc_huffman(<< 80, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101011:7 >>);
  631. enc_huffman(<< 81, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101100:7 >>);
  632. enc_huffman(<< 82, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101101:7 >>);
  633. enc_huffman(<< 83, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101110:7 >>);
  634. enc_huffman(<< 84, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1101111:7 >>);
  635. enc_huffman(<< 85, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110000:7 >>);
  636. enc_huffman(<< 86, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110001:7 >>);
  637. enc_huffman(<< 87, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110010:7 >>);
  638. enc_huffman(<< 88, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111100:8 >>);
  639. enc_huffman(<< 89, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110011:7 >>);
  640. enc_huffman(<< 90, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111101:8 >>);
  641. enc_huffman(<< 91, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111011:13 >>);
  642. enc_huffman(<< 92, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111110000:19 >>);
  643. enc_huffman(<< 93, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111100:13 >>);
  644. enc_huffman(<< 94, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111100:14 >>);
  645. enc_huffman(<< 95, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100010:6 >>);
  646. enc_huffman(<< 96, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111101:15 >>);
  647. enc_huffman(<< 97, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00011:5 >>);
  648. enc_huffman(<< 98, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100011:6 >>);
  649. enc_huffman(<< 99, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00100:5 >>);
  650. enc_huffman(<< 100, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100100:6 >>);
  651. enc_huffman(<< 101, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00101:5 >>);
  652. enc_huffman(<< 102, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100101:6 >>);
  653. enc_huffman(<< 103, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100110:6 >>);
  654. enc_huffman(<< 104, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#100111:6 >>);
  655. enc_huffman(<< 105, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00110:5 >>);
  656. enc_huffman(<< 106, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110100:7 >>);
  657. enc_huffman(<< 107, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110101:7 >>);
  658. enc_huffman(<< 108, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#101000:6 >>);
  659. enc_huffman(<< 109, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#101001:6 >>);
  660. enc_huffman(<< 110, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#101010:6 >>);
  661. enc_huffman(<< 111, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#00111:5 >>);
  662. enc_huffman(<< 112, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#101011:6 >>);
  663. enc_huffman(<< 113, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110110:7 >>);
  664. enc_huffman(<< 114, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#101100:6 >>);
  665. enc_huffman(<< 115, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#01000:5 >>);
  666. enc_huffman(<< 116, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#01001:5 >>);
  667. enc_huffman(<< 117, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#101101:6 >>);
  668. enc_huffman(<< 118, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1110111:7 >>);
  669. enc_huffman(<< 119, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111000:7 >>);
  670. enc_huffman(<< 120, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111001:7 >>);
  671. enc_huffman(<< 121, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111010:7 >>);
  672. enc_huffman(<< 122, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111011:7 >>);
  673. enc_huffman(<< 123, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111110:15 >>);
  674. enc_huffman(<< 124, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111100:11 >>);
  675. enc_huffman(<< 125, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111101:14 >>);
  676. enc_huffman(<< 126, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111101:13 >>);
  677. enc_huffman(<< 127, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111100:28 >>);
  678. enc_huffman(<< 128, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111100110:20 >>);
  679. enc_huffman(<< 129, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111010010:22 >>);
  680. enc_huffman(<< 130, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111100111:20 >>);
  681. enc_huffman(<< 131, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111101000:20 >>);
  682. enc_huffman(<< 132, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111010011:22 >>);
  683. enc_huffman(<< 133, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111010100:22 >>);
  684. enc_huffman(<< 134, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111010101:22 >>);
  685. enc_huffman(<< 135, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011001:23 >>);
  686. enc_huffman(<< 136, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111010110:22 >>);
  687. enc_huffman(<< 137, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011010:23 >>);
  688. enc_huffman(<< 138, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011011:23 >>);
  689. enc_huffman(<< 139, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011100:23 >>);
  690. enc_huffman(<< 140, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011101:23 >>);
  691. enc_huffman(<< 141, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011110:23 >>);
  692. enc_huffman(<< 142, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111101011:24 >>);
  693. enc_huffman(<< 143, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111011111:23 >>);
  694. enc_huffman(<< 144, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111101100:24 >>);
  695. enc_huffman(<< 145, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111101101:24 >>);
  696. enc_huffman(<< 146, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111010111:22 >>);
  697. enc_huffman(<< 147, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100000:23 >>);
  698. enc_huffman(<< 148, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111101110:24 >>);
  699. enc_huffman(<< 149, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100001:23 >>);
  700. enc_huffman(<< 150, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100010:23 >>);
  701. enc_huffman(<< 151, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100011:23 >>);
  702. enc_huffman(<< 152, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100100:23 >>);
  703. enc_huffman(<< 153, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111011100:21 >>);
  704. enc_huffman(<< 154, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011000:22 >>);
  705. enc_huffman(<< 155, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100101:23 >>);
  706. enc_huffman(<< 156, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011001:22 >>);
  707. enc_huffman(<< 157, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100110:23 >>);
  708. enc_huffman(<< 158, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111100111:23 >>);
  709. enc_huffman(<< 159, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111101111:24 >>);
  710. enc_huffman(<< 160, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011010:22 >>);
  711. enc_huffman(<< 161, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111011101:21 >>);
  712. enc_huffman(<< 162, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111101001:20 >>);
  713. enc_huffman(<< 163, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011011:22 >>);
  714. enc_huffman(<< 164, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011100:22 >>);
  715. enc_huffman(<< 165, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101000:23 >>);
  716. enc_huffman(<< 166, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101001:23 >>);
  717. enc_huffman(<< 167, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111011110:21 >>);
  718. enc_huffman(<< 168, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101010:23 >>);
  719. enc_huffman(<< 169, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011101:22 >>);
  720. enc_huffman(<< 170, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011110:22 >>);
  721. enc_huffman(<< 171, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111110000:24 >>);
  722. enc_huffman(<< 172, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111011111:21 >>);
  723. enc_huffman(<< 173, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111011111:22 >>);
  724. enc_huffman(<< 174, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101011:23 >>);
  725. enc_huffman(<< 175, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101100:23 >>);
  726. enc_huffman(<< 176, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100000:21 >>);
  727. enc_huffman(<< 177, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100001:21 >>);
  728. enc_huffman(<< 178, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100000:22 >>);
  729. enc_huffman(<< 179, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100010:21 >>);
  730. enc_huffman(<< 180, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101101:23 >>);
  731. enc_huffman(<< 181, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100001:22 >>);
  732. enc_huffman(<< 182, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101110:23 >>);
  733. enc_huffman(<< 183, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111101111:23 >>);
  734. enc_huffman(<< 184, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111101010:20 >>);
  735. enc_huffman(<< 185, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100010:22 >>);
  736. enc_huffman(<< 186, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100011:22 >>);
  737. enc_huffman(<< 187, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100100:22 >>);
  738. enc_huffman(<< 188, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111110000:23 >>);
  739. enc_huffman(<< 189, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100101:22 >>);
  740. enc_huffman(<< 190, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100110:22 >>);
  741. enc_huffman(<< 191, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111110001:23 >>);
  742. enc_huffman(<< 192, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100000:26 >>);
  743. enc_huffman(<< 193, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100001:26 >>);
  744. enc_huffman(<< 194, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111101011:20 >>);
  745. enc_huffman(<< 195, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111110001:19 >>);
  746. enc_huffman(<< 196, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111100111:22 >>);
  747. enc_huffman(<< 197, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111110010:23 >>);
  748. enc_huffman(<< 198, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111101000:22 >>);
  749. enc_huffman(<< 199, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111101100:25 >>);
  750. enc_huffman(<< 200, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100010:26 >>);
  751. enc_huffman(<< 201, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100011:26 >>);
  752. enc_huffman(<< 202, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100100:26 >>);
  753. enc_huffman(<< 203, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111011110:27 >>);
  754. enc_huffman(<< 204, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111011111:27 >>);
  755. enc_huffman(<< 205, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100101:26 >>);
  756. enc_huffman(<< 206, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111110001:24 >>);
  757. enc_huffman(<< 207, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111101101:25 >>);
  758. enc_huffman(<< 208, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111110010:19 >>);
  759. enc_huffman(<< 209, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100011:21 >>);
  760. enc_huffman(<< 210, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100110:26 >>);
  761. enc_huffman(<< 211, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100000:27 >>);
  762. enc_huffman(<< 212, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100001:27 >>);
  763. enc_huffman(<< 213, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111100111:26 >>);
  764. enc_huffman(<< 214, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100010:27 >>);
  765. enc_huffman(<< 215, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111110010:24 >>);
  766. enc_huffman(<< 216, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100100:21 >>);
  767. enc_huffman(<< 217, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100101:21 >>);
  768. enc_huffman(<< 218, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101000:26 >>);
  769. enc_huffman(<< 219, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101001:26 >>);
  770. enc_huffman(<< 220, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111101:28 >>);
  771. enc_huffman(<< 221, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100011:27 >>);
  772. enc_huffman(<< 222, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100100:27 >>);
  773. enc_huffman(<< 223, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100101:27 >>);
  774. enc_huffman(<< 224, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111101100:20 >>);
  775. enc_huffman(<< 225, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111110011:24 >>);
  776. enc_huffman(<< 226, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111101101:20 >>);
  777. enc_huffman(<< 227, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100110:21 >>);
  778. enc_huffman(<< 228, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111101001:22 >>);
  779. enc_huffman(<< 229, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111100111:21 >>);
  780. enc_huffman(<< 230, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111101000:21 >>);
  781. enc_huffman(<< 231, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111110011:23 >>);
  782. enc_huffman(<< 232, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111101010:22 >>);
  783. enc_huffman(<< 233, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111101011:22 >>);
  784. enc_huffman(<< 234, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111101110:25 >>);
  785. enc_huffman(<< 235, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111101111:25 >>);
  786. enc_huffman(<< 236, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111110100:24 >>);
  787. enc_huffman(<< 237, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111110101:24 >>);
  788. enc_huffman(<< 238, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101010:26 >>);
  789. enc_huffman(<< 239, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111110100:23 >>);
  790. enc_huffman(<< 240, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101011:26 >>);
  791. enc_huffman(<< 241, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100110:27 >>);
  792. enc_huffman(<< 242, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101100:26 >>);
  793. enc_huffman(<< 243, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101101:26 >>);
  794. enc_huffman(<< 244, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111100111:27 >>);
  795. enc_huffman(<< 245, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101000:27 >>);
  796. enc_huffman(<< 246, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101001:27 >>);
  797. enc_huffman(<< 247, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101010:27 >>);
  798. enc_huffman(<< 248, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101011:27 >>);
  799. enc_huffman(<< 249, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#1111111111111111111111111110:28 >>);
  800. enc_huffman(<< 250, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101100:27 >>);
  801. enc_huffman(<< 251, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101101:27 >>);
  802. enc_huffman(<< 252, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101110:27 >>);
  803. enc_huffman(<< 253, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111101111:27 >>);
  804. enc_huffman(<< 254, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#111111111111111111111110000:27 >>);
  805. enc_huffman(<< 255, R/bits >>, A) -> enc_huffman(R, << A/bits, 2#11111111111111111111101110:26 >>).
  806. -ifdef(TEST).
  807. req_encode_test() ->
  808. %% First request (raw then huffman).
  809. Headers1 = [
  810. {<<":method">>, <<"GET">>},
  811. {<<":scheme">>, <<"http">>},
  812. {<<":path">>, <<"/">>},
  813. {<<":authority">>, <<"www.example.com">>}
  814. ],
  815. {Raw1, State1} = encode(Headers1, init(), #{huffman => false}),
  816. << 16#828684410f7777772e6578616d706c652e636f6d:160 >> = iolist_to_binary(Raw1),
  817. {Huff1, State1} = encode(Headers1),
  818. << 16#828684418cf1e3c2e5f23a6ba0ab90f4ff:136 >> = iolist_to_binary(Huff1),
  819. #state{size=57, dyn_table=[{57,{<<":authority">>, <<"www.example.com">>}}]} = State1,
  820. %% Second request (raw then huffman).
  821. Headers2 = [
  822. {<<":method">>, <<"GET">>},
  823. {<<":scheme">>, <<"http">>},
  824. {<<":path">>, <<"/">>},
  825. {<<":authority">>, <<"www.example.com">>},
  826. {<<"cache-control">>, <<"no-cache">>}
  827. ],
  828. {Raw2, State2} = encode(Headers2, State1, #{huffman => false}),
  829. << 16#828684be58086e6f2d6361636865:112 >> = iolist_to_binary(Raw2),
  830. {Huff2, State2} = encode(Headers2, State1),
  831. << 16#828684be5886a8eb10649cbf:96 >> = iolist_to_binary(Huff2),
  832. #state{size=110, dyn_table=[
  833. {53,{<<"cache-control">>, <<"no-cache">>}},
  834. {57,{<<":authority">>, <<"www.example.com">>}}]} = State2,
  835. %% Third request (raw then huffman).
  836. Headers3 = [
  837. {<<":method">>, <<"GET">>},
  838. {<<":scheme">>, <<"https">>},
  839. {<<":path">>, <<"/index.html">>},
  840. {<<":authority">>, <<"www.example.com">>},
  841. {<<"custom-key">>, <<"custom-value">>}
  842. ],
  843. {Raw3, State3} = encode(Headers3, State2, #{huffman => false}),
  844. << 16#828785bf400a637573746f6d2d6b65790c637573746f6d2d76616c7565:232 >> = iolist_to_binary(Raw3),
  845. {Huff3, State3} = encode(Headers3, State2),
  846. << 16#828785bf408825a849e95ba97d7f8925a849e95bb8e8b4bf:192 >> = iolist_to_binary(Huff3),
  847. #state{size=164, dyn_table=[
  848. {54,{<<"custom-key">>, <<"custom-value">>}},
  849. {53,{<<"cache-control">>, <<"no-cache">>}},
  850. {57,{<<":authority">>, <<"www.example.com">>}}]} = State3,
  851. ok.
  852. resp_encode_test() ->
  853. %% Use a max_size of 256 to trigger header evictions.
  854. State0 = init(256),
  855. %% First response (raw then huffman).
  856. Headers1 = [
  857. {<<":status">>, <<"302">>},
  858. {<<"cache-control">>, <<"private">>},
  859. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  860. {<<"location">>, <<"https://www.example.com">>}
  861. ],
  862. {Raw1, State1} = encode(Headers1, State0, #{huffman => false}),
  863. << 16#4803333032580770726976617465611d4d6f6e2c203231204f637420323031332032303a31333a323120474d546e1768747470733a2f2f7777772e6578616d706c652e636f6d:560 >> = iolist_to_binary(Raw1),
  864. {Huff1, State1} = encode(Headers1, State0),
  865. << 16#488264025885aec3771a4b6196d07abe941054d444a8200595040b8166e082a62d1bff6e919d29ad171863c78f0b97c8e9ae82ae43d3:432 >> = iolist_to_binary(Huff1),
  866. #state{size=222, dyn_table=[
  867. {63,{<<"location">>, <<"https://www.example.com">>}},
  868. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  869. {52,{<<"cache-control">>, <<"private">>}},
  870. {42,{<<":status">>, <<"302">>}}]} = State1,
  871. %% Second response (raw then huffman).
  872. Headers2 = [
  873. {<<":status">>, <<"307">>},
  874. {<<"cache-control">>, <<"private">>},
  875. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  876. {<<"location">>, <<"https://www.example.com">>}
  877. ],
  878. {Raw2, State2} = encode(Headers2, State1, #{huffman => false}),
  879. << 16#4803333037c1c0bf:64 >> = iolist_to_binary(Raw2),
  880. {Huff2, State2} = encode(Headers2, State1),
  881. << 16#4883640effc1c0bf:64 >> = iolist_to_binary(Huff2),
  882. #state{size=222, dyn_table=[
  883. {42,{<<":status">>, <<"307">>}},
  884. {63,{<<"location">>, <<"https://www.example.com">>}},
  885. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  886. {52,{<<"cache-control">>, <<"private">>}}]} = State2,
  887. %% Third response (raw then huffman).
  888. Headers3 = [
  889. {<<":status">>, <<"200">>},
  890. {<<"cache-control">>, <<"private">>},
  891. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:22 GMT">>},
  892. {<<"location">>, <<"https://www.example.com">>},
  893. {<<"content-encoding">>, <<"gzip">>},
  894. {<<"set-cookie">>, <<"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1">>}
  895. ],
  896. {Raw3, State3} = encode(Headers3, State2, #{huffman => false}),
  897. << 16#88c1611d4d6f6e2c203231204f637420323031332032303a31333a323220474d54c05a04677a69707738666f6f3d4153444a4b48514b425a584f5157454f50495541585157454f49553b206d61782d6167653d333630303b2076657273696f6e3d31:784 >> = iolist_to_binary(Raw3),
  898. {Huff3, State3} = encode(Headers3, State2),
  899. << 16#88c16196d07abe941054d444a8200595040b8166e084a62d1bffc05a839bd9ab77ad94e7821dd7f2e6c7b335dfdfcd5b3960d5af27087f3672c1ab270fb5291f9587316065c003ed4ee5b1063d5007:632 >> = iolist_to_binary(Huff3),
  900. #state{size=215, dyn_table=[
  901. {98,{<<"set-cookie">>, <<"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1">>}},
  902. {52,{<<"content-encoding">>, <<"gzip">>}},
  903. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:22 GMT">>}}]} = State3,
  904. ok.
  905. %% This test assumes that table updates work correctly when decoding.
  906. table_update_encode_test() ->
  907. %% Use a max_size of 256 to trigger header evictions
  908. %% when the code is not updating the max size.
  909. DecState0 = EncState0 = init(256),
  910. %% First response.
  911. Headers1 = [
  912. {<<":status">>, <<"302">>},
  913. {<<"cache-control">>, <<"private">>},
  914. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  915. {<<"location">>, <<"https://www.example.com">>}
  916. ],
  917. {Encoded1, EncState1} = encode(Headers1, EncState0),
  918. {Headers1, DecState1} = decode(iolist_to_binary(Encoded1), DecState0),
  919. #state{size=222, configured_max_size=256, dyn_table=[
  920. {63,{<<"location">>, <<"https://www.example.com">>}},
  921. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  922. {52,{<<"cache-control">>, <<"private">>}},
  923. {42,{<<":status">>, <<"302">>}}]} = DecState1,
  924. #state{size=222, configured_max_size=256, dyn_table=[
  925. {63,{<<"location">>, <<"https://www.example.com">>}},
  926. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  927. {52,{<<"cache-control">>, <<"private">>}},
  928. {42,{<<":status">>, <<"302">>}}]} = EncState1,
  929. %% Set a new configured max_size to avoid header evictions.
  930. DecState2 = set_max_size(512, DecState1),
  931. EncState2 = set_max_size(512, EncState1),
  932. %% Second response.
  933. Headers2 = [
  934. {<<":status">>, <<"307">>},
  935. {<<"cache-control">>, <<"private">>},
  936. {<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>},
  937. {<<"location">>, <<"https://www.example.com">>}
  938. ],
  939. {Encoded2, EncState3} = encode(Headers2, EncState2),
  940. {Headers2, DecState3} = decode(iolist_to_binary(Encoded2), DecState2),
  941. #state{size=264, max_size=512, dyn_table=[
  942. {42,{<<":status">>, <<"307">>}},
  943. {63,{<<"location">>, <<"https://www.example.com">>}},
  944. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  945. {52,{<<"cache-control">>, <<"private">>}},
  946. {42,{<<":status">>, <<"302">>}}]} = DecState3,
  947. #state{size=264, max_size=512, dyn_table=[
  948. {42,{<<":status">>, <<"307">>}},
  949. {63,{<<"location">>, <<"https://www.example.com">>}},
  950. {65,{<<"date">>, <<"Mon, 21 Oct 2013 20:13:21 GMT">>}},
  951. {52,{<<"cache-control">>, <<"private">>}},
  952. {42,{<<":status">>, <<"302">>}}]} = EncState3,
  953. ok.
  954. %% Check that encode/2 is using the new table size after calling
  955. %% set_max_size/1 and that adding entries larger than the max size
  956. %% results in an empty table.
  957. table_update_encode_max_size_0_test() ->
  958. %% Encoding starts with default max size
  959. EncState0 = init(),
  960. %% Decoding starts with max size of 0
  961. DecState0 = init(0),
  962. %% First request.
  963. Headers1 = [
  964. {<<":method">>, <<"GET">>},
  965. {<<":scheme">>, <<"http">>},
  966. {<<":path">>, <<"/">>},
  967. {<<":authority">>, <<"www.example.com">>}
  968. ],
  969. {Encoded1, EncState1} = encode(Headers1, EncState0),
  970. {Headers1, DecState1} = decode(iolist_to_binary(Encoded1), DecState0),
  971. #state{size=57, dyn_table=[{57,{<<":authority">>, <<"www.example.com">>}}]} = EncState1,
  972. #state{size=0, dyn_table=[]} = DecState1,
  973. %% Settings received after the first request.
  974. EncState2 = set_max_size(0, EncState1),
  975. #state{configured_max_size=0, max_size=4096,
  976. size=57, dyn_table=[{57,{<<":authority">>, <<"www.example.com">>}}]} = EncState2,
  977. %% Second request.
  978. Headers2 = [
  979. {<<":method">>, <<"GET">>},
  980. {<<":scheme">>, <<"http">>},
  981. {<<":path">>, <<"/">>},
  982. {<<":authority">>, <<"www.example.com">>},
  983. {<<"cache-control">>, <<"no-cache">>}
  984. ],
  985. {Encoded2, EncState3} = encode(Headers2, EncState2),
  986. {Headers2, DecState2} = decode(iolist_to_binary(Encoded2), DecState1),
  987. #state{configured_max_size=0, max_size=0, size=0, dyn_table=[]} = EncState3,
  988. #state{size=0, dyn_table=[]} = DecState2,
  989. ok.
  990. encode_iolist_test() ->
  991. Headers = [
  992. {<<":method">>, <<"GET">>},
  993. {<<":scheme">>, <<"http">>},
  994. {<<":path">>, <<"/">>},
  995. {<<":authority">>, <<"www.example.com">>},
  996. {<<"content-type">>, [<<"image">>,<<"/">>,<<"png">>,<<>>]}
  997. ],
  998. {_, _} = encode(Headers),
  999. ok.
  1000. horse_encode_raw() ->
  1001. horse:repeat(20000,
  1002. do_horse_encode_raw()
  1003. ).
  1004. do_horse_encode_raw() ->
  1005. Headers1 = [
  1006. {<<":method">>, <<"GET">>},
  1007. {<<":scheme">>, <<"http">>},
  1008. {<<":path">>, <<"/">>},
  1009. {<<":authority">>, <<"www.example.com">>}
  1010. ],
  1011. {_, State1} = encode(Headers1, init(), #{huffman => false}),
  1012. Headers2 = [
  1013. {<<":method">>, <<"GET">>},
  1014. {<<":scheme">>, <<"http">>},
  1015. {<<":path">>, <<"/">>},
  1016. {<<":authority">>, <<"www.example.com">>},
  1017. {<<"cache-control">>, <<"no-cache">>}
  1018. ],
  1019. {_, State2} = encode(Headers2, State1, #{huffman => false}),
  1020. Headers3 = [
  1021. {<<":method">>, <<"GET">>},
  1022. {<<":scheme">>, <<"https">>},
  1023. {<<":path">>, <<"/index.html">>},
  1024. {<<":authority">>, <<"www.example.com">>},
  1025. {<<"custom-key">>, <<"custom-value">>}
  1026. ],
  1027. {_, _} = encode(Headers3, State2, #{huffman => false}),
  1028. ok.
  1029. horse_encode_huffman() ->
  1030. horse:repeat(20000,
  1031. do_horse_encode_huffman()
  1032. ).
  1033. do_horse_encode_huffman() ->
  1034. Headers1 = [
  1035. {<<":method">>, <<"GET">>},
  1036. {<<":scheme">>, <<"http">>},
  1037. {<<":path">>, <<"/">>},
  1038. {<<":authority">>, <<"www.example.com">>}
  1039. ],
  1040. {_, State1} = encode(Headers1),
  1041. Headers2 = [
  1042. {<<":method">>, <<"GET">>},
  1043. {<<":scheme">>, <<"http">>},
  1044. {<<":path">>, <<"/">>},
  1045. {<<":authority">>, <<"www.example.com">>},
  1046. {<<"cache-control">>, <<"no-cache">>}
  1047. ],
  1048. {_, State2} = encode(Headers2, State1),
  1049. Headers3 = [
  1050. {<<":method">>, <<"GET">>},
  1051. {<<":scheme">>, <<"https">>},
  1052. {<<":path">>, <<"/index.html">>},
  1053. {<<":authority">>, <<"www.example.com">>},
  1054. {<<"custom-key">>, <<"custom-value">>}
  1055. ],
  1056. {_, _} = encode(Headers3, State2),
  1057. ok.
  1058. -endif.
  1059. %% Static and dynamic tables.
  1060. %% @todo There must be a more efficient way.
  1061. table_find(Header = {Name, _}, State) ->
  1062. case table_find_field(Header, State) of
  1063. not_found ->
  1064. case table_find_name(Name, State) of
  1065. NotFound = not_found ->
  1066. NotFound;
  1067. Found ->
  1068. {name, Found}
  1069. end;
  1070. Found ->
  1071. {field, Found}
  1072. end.
  1073. table_find_field({<<":authority">>, <<>>}, _) -> 1;
  1074. table_find_field({<<":method">>, <<"GET">>}, _) -> 2;
  1075. table_find_field({<<":method">>, <<"POST">>}, _) -> 3;
  1076. table_find_field({<<":path">>, <<"/">>}, _) -> 4;
  1077. table_find_field({<<":path">>, <<"/index.html">>}, _) -> 5;
  1078. table_find_field({<<":scheme">>, <<"http">>}, _) -> 6;
  1079. table_find_field({<<":scheme">>, <<"https">>}, _) -> 7;
  1080. table_find_field({<<":status">>, <<"200">>}, _) -> 8;
  1081. table_find_field({<<":status">>, <<"204">>}, _) -> 9;
  1082. table_find_field({<<":status">>, <<"206">>}, _) -> 10;
  1083. table_find_field({<<":status">>, <<"304">>}, _) -> 11;
  1084. table_find_field({<<":status">>, <<"400">>}, _) -> 12;
  1085. table_find_field({<<":status">>, <<"404">>}, _) -> 13;
  1086. table_find_field({<<":status">>, <<"500">>}, _) -> 14;
  1087. table_find_field({<<"accept-charset">>, <<>>}, _) -> 15;
  1088. table_find_field({<<"accept-encoding">>, <<"gzip, deflate">>}, _) -> 16;
  1089. table_find_field({<<"accept-language">>, <<>>}, _) -> 17;
  1090. table_find_field({<<"accept-ranges">>, <<>>}, _) -> 18;
  1091. table_find_field({<<"accept">>, <<>>}, _) -> 19;
  1092. table_find_field({<<"access-control-allow-origin">>, <<>>}, _) -> 20;
  1093. table_find_field({<<"age">>, <<>>}, _) -> 21;
  1094. table_find_field({<<"allow">>, <<>>}, _) -> 22;
  1095. table_find_field({<<"authorization">>, <<>>}, _) -> 23;
  1096. table_find_field({<<"cache-control">>, <<>>}, _) -> 24;
  1097. table_find_field({<<"content-disposition">>, <<>>}, _) -> 25;
  1098. table_find_field({<<"content-encoding">>, <<>>}, _) -> 26;
  1099. table_find_field({<<"content-language">>, <<>>}, _) -> 27;
  1100. table_find_field({<<"content-length">>, <<>>}, _) -> 28;
  1101. table_find_field({<<"content-location">>, <<>>}, _) -> 29;
  1102. table_find_field({<<"content-range">>, <<>>}, _) -> 30;
  1103. table_find_field({<<"content-type">>, <<>>}, _) -> 31;
  1104. table_find_field({<<"cookie">>, <<>>}, _) -> 32;
  1105. table_find_field({<<"date">>, <<>>}, _) -> 33;
  1106. table_find_field({<<"etag">>, <<>>}, _) -> 34;
  1107. table_find_field({<<"expect">>, <<>>}, _) -> 35;
  1108. table_find_field({<<"expires">>, <<>>}, _) -> 36;
  1109. table_find_field({<<"from">>, <<>>}, _) -> 37;
  1110. table_find_field({<<"host">>, <<>>}, _) -> 38;
  1111. table_find_field({<<"if-match">>, <<>>}, _) -> 39;
  1112. table_find_field({<<"if-modified-since">>, <<>>}, _) -> 40;
  1113. table_find_field({<<"if-none-match">>, <<>>}, _) -> 41;
  1114. table_find_field({<<"if-range">>, <<>>}, _) -> 42;
  1115. table_find_field({<<"if-unmodified-since">>, <<>>}, _) -> 43;
  1116. table_find_field({<<"last-modified">>, <<>>}, _) -> 44;
  1117. table_find_field({<<"link">>, <<>>}, _) -> 45;
  1118. table_find_field({<<"location">>, <<>>}, _) -> 46;
  1119. table_find_field({<<"max-forwards">>, <<>>}, _) -> 47;
  1120. table_find_field({<<"proxy-authenticate">>, <<>>}, _) -> 48;
  1121. table_find_field({<<"proxy-authorization">>, <<>>}, _) -> 49;
  1122. table_find_field({<<"range">>, <<>>}, _) -> 50;
  1123. table_find_field({<<"referer">>, <<>>}, _) -> 51;
  1124. table_find_field({<<"refresh">>, <<>>}, _) -> 52;
  1125. table_find_field({<<"retry-after">>, <<>>}, _) -> 53;
  1126. table_find_field({<<"server">>, <<>>}, _) -> 54;
  1127. table_find_field({<<"set-cookie">>, <<>>}, _) -> 55;
  1128. table_find_field({<<"strict-transport-security">>, <<>>}, _) -> 56;
  1129. table_find_field({<<"transfer-encoding">>, <<>>}, _) -> 57;
  1130. table_find_field({<<"user-agent">>, <<>>}, _) -> 58;
  1131. table_find_field({<<"vary">>, <<>>}, _) -> 59;
  1132. table_find_field({<<"via">>, <<>>}, _) -> 60;
  1133. table_find_field({<<"www-authenticate">>, <<>>}, _) -> 61;
  1134. table_find_field(Header, #state{dyn_table=DynamicTable}) ->
  1135. table_find_field_dyn(Header, DynamicTable, 62).
  1136. table_find_field_dyn(_, [], _) -> not_found;
  1137. table_find_field_dyn(Header, [{_, Header}|_], Index) -> Index;
  1138. table_find_field_dyn(Header, [_|Tail], Index) -> table_find_field_dyn(Header, Tail, Index + 1).
  1139. table_find_name(<<":authority">>, _) -> 1;
  1140. table_find_name(<<":method">>, _) -> 2;
  1141. table_find_name(<<":path">>, _) -> 4;
  1142. table_find_name(<<":scheme">>, _) -> 6;
  1143. table_find_name(<<":status">>, _) -> 8;
  1144. table_find_name(<<"accept-charset">>, _) -> 15;
  1145. table_find_name(<<"accept-encoding">>, _) -> 16;
  1146. table_find_name(<<"accept-language">>, _) -> 17;
  1147. table_find_name(<<"accept-ranges">>, _) -> 18;
  1148. table_find_name(<<"accept">>, _) -> 19;
  1149. table_find_name(<<"access-control-allow-origin">>, _) -> 20;
  1150. table_find_name(<<"age">>, _) -> 21;
  1151. table_find_name(<<"allow">>, _) -> 22;
  1152. table_find_name(<<"authorization">>, _) -> 23;
  1153. table_find_name(<<"cache-control">>, _) -> 24;
  1154. table_find_name(<<"content-disposition">>, _) -> 25;
  1155. table_find_name(<<"content-encoding">>, _) -> 26;
  1156. table_find_name(<<"content-language">>, _) -> 27;
  1157. table_find_name(<<"content-length">>, _) -> 28;
  1158. table_find_name(<<"content-location">>, _) -> 29;
  1159. table_find_name(<<"content-range">>, _) -> 30;
  1160. table_find_name(<<"content-type">>, _) -> 31;
  1161. table_find_name(<<"cookie">>, _) -> 32;
  1162. table_find_name(<<"date">>, _) -> 33;
  1163. table_find_name(<<"etag">>, _) -> 34;
  1164. table_find_name(<<"expect">>, _) -> 35;
  1165. table_find_name(<<"expires">>, _) -> 36;
  1166. table_find_name(<<"from">>, _) -> 37;
  1167. table_find_name(<<"host">>, _) -> 38;
  1168. table_find_name(<<"if-match">>, _) -> 39;
  1169. table_find_name(<<"if-modified-since">>, _) -> 40;
  1170. table_find_name(<<"if-none-match">>, _) -> 41;
  1171. table_find_name(<<"if-range">>, _) -> 42;
  1172. table_find_name(<<"if-unmodified-since">>, _) -> 43;
  1173. table_find_name(<<"last-modified">>, _) -> 44;
  1174. table_find_name(<<"link">>, _) -> 45;
  1175. table_find_name(<<"location">>, _) -> 46;
  1176. table_find_name(<<"max-forwards">>, _) -> 47;
  1177. table_find_name(<<"proxy-authenticate">>, _) -> 48;
  1178. table_find_name(<<"proxy-authorization">>, _) -> 49;
  1179. table_find_name(<<"range">>, _) -> 50;
  1180. table_find_name(<<"referer">>, _) -> 51;
  1181. table_find_name(<<"refresh">>, _) -> 52;
  1182. table_find_name(<<"retry-after">>, _) -> 53;
  1183. table_find_name(<<"server">>, _) -> 54;
  1184. table_find_name(<<"set-cookie">>, _) -> 55;
  1185. table_find_name(<<"strict-transport-security">>, _) -> 56;
  1186. table_find_name(<<"transfer-encoding">>, _) -> 57;
  1187. table_find_name(<<"user-agent">>, _) -> 58;
  1188. table_find_name(<<"vary">>, _) -> 59;
  1189. table_find_name(<<"via">>, _) -> 60;
  1190. table_find_name(<<"www-authenticate">>, _) -> 61;
  1191. table_find_name(Name, #state{dyn_table=DynamicTable}) ->
  1192. table_find_name_dyn(Name, DynamicTable, 62).
  1193. table_find_name_dyn(_, [], _) -> not_found;
  1194. table_find_name_dyn(Name, [{Name, _}|_], Index) -> Index;
  1195. table_find_name_dyn(Name, [_|Tail], Index) -> table_find_name_dyn(Name, Tail, Index + 1).
  1196. table_get(1, _) -> {<<":authority">>, <<>>};
  1197. table_get(2, _) -> {<<":method">>, <<"GET">>};
  1198. table_get(3, _) -> {<<":method">>, <<"POST">>};
  1199. table_get(4, _) -> {<<":path">>, <<"/">>};
  1200. table_get(5, _) -> {<<":path">>, <<"/index.html">>};
  1201. table_get(6, _) -> {<<":scheme">>, <<"http">>};
  1202. table_get(7, _) -> {<<":scheme">>, <<"https">>};
  1203. table_get(8, _) -> {<<":status">>, <<"200">>};
  1204. table_get(9, _) -> {<<":status">>, <<"204">>};
  1205. table_get(10, _) -> {<<":status">>, <<"206">>};
  1206. table_get(11, _) -> {<<":status">>, <<"304">>};
  1207. table_get(12, _) -> {<<":status">>, <<"400">>};
  1208. table_get(13, _) -> {<<":status">>, <<"404">>};
  1209. table_get(14, _) -> {<<":status">>, <<"500">>};
  1210. table_get(15, _) -> {<<"accept-charset">>, <<>>};
  1211. table_get(16, _) -> {<<"accept-encoding">>, <<"gzip, deflate">>};
  1212. table_get(17, _) -> {<<"accept-language">>, <<>>};
  1213. table_get(18, _) -> {<<"accept-ranges">>, <<>>};
  1214. table_get(19, _) -> {<<"accept">>, <<>>};
  1215. table_get(20, _) -> {<<"access-control-allow-origin">>, <<>>};
  1216. table_get(21, _) -> {<<"age">>, <<>>};
  1217. table_get(22, _) -> {<<"allow">>, <<>>};
  1218. table_get(23, _) -> {<<"authorization">>, <<>>};
  1219. table_get(24, _) -> {<<"cache-control">>, <<>>};
  1220. table_get(25, _) -> {<<"content-disposition">>, <<>>};
  1221. table_get(26, _) -> {<<"content-encoding">>, <<>>};
  1222. table_get(27, _) -> {<<"content-language">>, <<>>};
  1223. table_get(28, _) -> {<<"content-length">>, <<>>};
  1224. table_get(29, _) -> {<<"content-location">>, <<>>};
  1225. table_get(30, _) -> {<<"content-range">>, <<>>};
  1226. table_get(31, _) -> {<<"content-type">>, <<>>};
  1227. table_get(32, _) -> {<<"cookie">>, <<>>};
  1228. table_get(33, _) -> {<<"date">>, <<>>};
  1229. table_get(34, _) -> {<<"etag">>, <<>>};
  1230. table_get(35, _) -> {<<"expect">>, <<>>};
  1231. table_get(36, _) -> {<<"expires">>, <<>>};
  1232. table_get(37, _) -> {<<"from">>, <<>>};
  1233. table_get(38, _) -> {<<"host">>, <<>>};
  1234. table_get(39, _) -> {<<"if-match">>, <<>>};
  1235. table_get(40, _) -> {<<"if-modified-since">>, <<>>};
  1236. table_get(41, _) -> {<<"if-none-match">>, <<>>};
  1237. table_get(42, _) -> {<<"if-range">>, <<>>};
  1238. table_get(43, _) -> {<<"if-unmodified-since">>, <<>>};
  1239. table_get(44, _) -> {<<"last-modified">>, <<>>};
  1240. table_get(45, _) -> {<<"link">>, <<>>};
  1241. table_get(46, _) -> {<<"location">>, <<>>};
  1242. table_get(47, _) -> {<<"max-forwards">>, <<>>};
  1243. table_get(48, _) -> {<<"proxy-authenticate">>, <<>>};
  1244. table_get(49, _) -> {<<"proxy-authorization">>, <<>>};
  1245. table_get(50, _) -> {<<"range">>, <<>>};
  1246. table_get(51, _) -> {<<"referer">>, <<>>};
  1247. table_get(52, _) -> {<<"refresh">>, <<>>};
  1248. table_get(53, _) -> {<<"retry-after">>, <<>>};
  1249. table_get(54, _) -> {<<"server">>, <<>>};
  1250. table_get(55, _) -> {<<"set-cookie">>, <<>>};
  1251. table_get(56, _) -> {<<"strict-transport-security">>, <<>>};
  1252. table_get(57, _) -> {<<"transfer-encoding">>, <<>>};
  1253. table_get(58, _) -> {<<"user-agent">>, <<>>};
  1254. table_get(59, _) -> {<<"vary">>, <<>>};
  1255. table_get(60, _) -> {<<"via">>, <<>>};
  1256. table_get(61, _) -> {<<"www-authenticate">>, <<>>};
  1257. table_get(Index, #state{dyn_table=DynamicTable}) ->
  1258. {_, Header} = lists:nth(Index - 61, DynamicTable),
  1259. Header.
  1260. table_get_name(1, _) -> <<":authority">>;
  1261. table_get_name(2, _) -> <<":method">>;
  1262. table_get_name(3, _) -> <<":method">>;
  1263. table_get_name(4, _) -> <<":path">>;
  1264. table_get_name(5, _) -> <<":path">>;
  1265. table_get_name(6, _) -> <<":scheme">>;
  1266. table_get_name(7, _) -> <<":scheme">>;
  1267. table_get_name(8, _) -> <<":status">>;
  1268. table_get_name(9, _) -> <<":status">>;
  1269. table_get_name(10, _) -> <<":status">>;
  1270. table_get_name(11, _) -> <<":status">>;
  1271. table_get_name(12, _) -> <<":status">>;
  1272. table_get_name(13, _) -> <<":status">>;
  1273. table_get_name(14, _) -> <<":status">>;
  1274. table_get_name(15, _) -> <<"accept-charset">>;
  1275. table_get_name(16, _) -> <<"accept-encoding">>;
  1276. table_get_name(17, _) -> <<"accept-language">>;
  1277. table_get_name(18, _) -> <<"accept-ranges">>;
  1278. table_get_name(19, _) -> <<"accept">>;
  1279. table_get_name(20, _) -> <<"access-control-allow-origin">>;
  1280. table_get_name(21, _) -> <<"age">>;
  1281. table_get_name(22, _) -> <<"allow">>;
  1282. table_get_name(23, _) -> <<"authorization">>;
  1283. table_get_name(24, _) -> <<"cache-control">>;
  1284. table_get_name(25, _) -> <<"content-disposition">>;
  1285. table_get_name(26, _) -> <<"content-encoding">>;
  1286. table_get_name(27, _) -> <<"content-language">>;
  1287. table_get_name(28, _) -> <<"content-length">>;
  1288. table_get_name(29, _) -> <<"content-location">>;
  1289. table_get_name(30, _) -> <<"content-range">>;
  1290. table_get_name(31, _) -> <<"content-type">>;
  1291. table_get_name(32, _) -> <<"cookie">>;
  1292. table_get_name(33, _) -> <<"date">>;
  1293. table_get_name(34, _) -> <<"etag">>;
  1294. table_get_name(35, _) -> <<"expect">>;
  1295. table_get_name(36, _) -> <<"expires">>;
  1296. table_get_name(37, _) -> <<"from">>;
  1297. table_get_name(38, _) -> <<"host">>;
  1298. table_get_name(39, _) -> <<"if-match">>;
  1299. table_get_name(40, _) -> <<"if-modified-since">>;
  1300. table_get_name(41, _) -> <<"if-none-match">>;
  1301. table_get_name(42, _) -> <<"if-range">>;
  1302. table_get_name(43, _) -> <<"if-unmodified-since">>;
  1303. table_get_name(44, _) -> <<"last-modified">>;
  1304. table_get_name(45, _) -> <<"link">>;
  1305. table_get_name(46, _) -> <<"location">>;
  1306. table_get_name(47, _) -> <<"max-forwards">>;
  1307. table_get_name(48, _) -> <<"proxy-authenticate">>;
  1308. table_get_name(49, _) -> <<"proxy-authorization">>;
  1309. table_get_name(50, _) -> <<"range">>;
  1310. table_get_name(51, _) -> <<"referer">>;
  1311. table_get_name(52, _) -> <<"refresh">>;
  1312. table_get_name(53, _) -> <<"retry-after">>;
  1313. table_get_name(54, _) -> <<"server">>;
  1314. table_get_name(55, _) -> <<"set-cookie">>;
  1315. table_get_name(56, _) -> <<"strict-transport-security">>;
  1316. table_get_name(57, _) -> <<"transfer-encoding">>;
  1317. table_get_name(58, _) -> <<"user-agent">>;
  1318. table_get_name(59, _) -> <<"vary">>;
  1319. table_get_name(60, _) -> <<"via">>;
  1320. table_get_name(61, _) -> <<"www-authenticate">>;
  1321. table_get_name(Index, #state{dyn_table=DynamicTable}) ->
  1322. {_, {Name, _}} = lists:nth(Index - 61, DynamicTable),
  1323. Name.
  1324. table_insert(Entry = {Name, Value}, State=#state{size=Size, max_size=MaxSize, dyn_table=DynamicTable}) ->
  1325. EntrySize = byte_size(Name) + byte_size(Value) + 32,
  1326. if
  1327. EntrySize + Size =< MaxSize ->
  1328. %% Add entry without eviction
  1329. State#state{size=Size + EntrySize, dyn_table=[{EntrySize, Entry}|DynamicTable]};
  1330. EntrySize =< MaxSize ->
  1331. %% Evict, then add entry
  1332. {DynamicTable2, Size2} = table_resize(DynamicTable, MaxSize - EntrySize, 0, []),
  1333. State#state{size=Size2 + EntrySize, dyn_table=[{EntrySize, Entry}|DynamicTable2]};
  1334. EntrySize > MaxSize ->
  1335. %% "an attempt to add an entry larger than the
  1336. %% maximum size causes the table to be emptied
  1337. %% of all existing entries and results in an
  1338. %% empty table" (RFC 7541, 4.4)
  1339. State#state{size=0, dyn_table=[]}
  1340. end.
  1341. table_resize([], _, Size, Acc) ->
  1342. {lists:reverse(Acc), Size};
  1343. table_resize([{EntrySize, _}|_], MaxSize, Size, Acc) when Size + EntrySize > MaxSize ->
  1344. {lists:reverse(Acc), Size};
  1345. table_resize([Entry = {EntrySize, _}|Tail], MaxSize, Size, Acc) ->
  1346. table_resize(Tail, MaxSize, Size + EntrySize, [Entry|Acc]).
  1347. table_update_size(0, State) ->
  1348. State#state{size=0, max_size=0, dyn_table=[]};
  1349. table_update_size(MaxSize, State=#state{max_size=CurrentMaxSize})
  1350. when CurrentMaxSize =< MaxSize ->
  1351. State#state{max_size=MaxSize};
  1352. table_update_size(MaxSize, State=#state{dyn_table=DynTable}) ->
  1353. {DynTable2, Size} = table_resize(DynTable, MaxSize, 0, []),
  1354. State#state{size=Size, max_size=MaxSize, dyn_table=DynTable2}.
  1355. -ifdef(TEST).
  1356. prop_str_raw() ->
  1357. ?FORALL(Str, binary(), begin
  1358. {Str, <<>>} =:= dec_str(iolist_to_binary(enc_str(Str, no_huffman)))
  1359. end).
  1360. prop_str_huffman() ->
  1361. ?FORALL(Str, binary(), begin
  1362. {Str, <<>>} =:= dec_str(iolist_to_binary(enc_str(Str, huffman)))
  1363. end).
  1364. -endif.