nghttp2_hd_huffman.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * nghttp2 - HTTP/2 C Library
  3. *
  4. * Copyright (c) 2013 Tatsuhiro Tsujikawa
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "nghttp2_hd_huffman.h"
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <stdio.h>
  29. #include "nghttp2_hd.h"
  30. #include "nghttp2_net.h"
  31. size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
  32. size_t i;
  33. size_t nbits = 0;
  34. for (i = 0; i < len; ++i) {
  35. nbits += huff_sym_table[src[i]].nbits;
  36. }
  37. /* pad the prefix of EOS (256) */
  38. return (nbits + 7) / 8;
  39. }
  40. int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
  41. size_t srclen) {
  42. const nghttp2_huff_sym *sym;
  43. const uint8_t *end = src + srclen;
  44. uint64_t code = 0;
  45. uint32_t x;
  46. size_t nbits = 0;
  47. size_t avail;
  48. int rv;
  49. avail = nghttp2_bufs_cur_avail(bufs);
  50. for (; src != end;) {
  51. sym = &huff_sym_table[*src++];
  52. code |= (uint64_t)sym->code << (32 - nbits);
  53. nbits += sym->nbits;
  54. if (nbits < 32) {
  55. continue;
  56. }
  57. if (avail >= 4) {
  58. x = htonl((uint32_t)(code >> 32));
  59. memcpy(bufs->cur->buf.last, &x, 4);
  60. bufs->cur->buf.last += 4;
  61. avail -= 4;
  62. code <<= 32;
  63. nbits -= 32;
  64. continue;
  65. }
  66. for (; nbits >= 8;) {
  67. rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 56));
  68. if (rv != 0) {
  69. return rv;
  70. }
  71. code <<= 8;
  72. nbits -= 8;
  73. }
  74. avail = nghttp2_bufs_cur_avail(bufs);
  75. }
  76. for (; nbits >= 8;) {
  77. rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 56));
  78. if (rv != 0) {
  79. return rv;
  80. }
  81. code <<= 8;
  82. nbits -= 8;
  83. }
  84. if (nbits) {
  85. rv = nghttp2_bufs_addb(
  86. bufs, (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1)));
  87. if (rv != 0) {
  88. return rv;
  89. }
  90. }
  91. return 0;
  92. }
  93. void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
  94. ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
  95. }
  96. nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
  97. nghttp2_buf *buf, const uint8_t *src,
  98. size_t srclen, int final) {
  99. const uint8_t *end = src + srclen;
  100. nghttp2_huff_decode node = {ctx->fstate, 0};
  101. const nghttp2_huff_decode *t = &node;
  102. uint8_t c;
  103. /* We use the decoding algorithm described in
  104. - http://graphics.ics.uci.edu/pub/Prefix.pdf [!!! NO LONGER VALID !!!]
  105. - https://ics.uci.edu/~dan/pubs/Prefix.pdf
  106. - https://github.com/nghttp2/nghttp2/files/15141264/Prefix.pdf */
  107. for (; src != end;) {
  108. c = *src++;
  109. t = &huff_decode_table[t->fstate & 0x1ff][c >> 4];
  110. if (t->fstate & NGHTTP2_HUFF_SYM) {
  111. *buf->last++ = t->sym;
  112. }
  113. t = &huff_decode_table[t->fstate & 0x1ff][c & 0xf];
  114. if (t->fstate & NGHTTP2_HUFF_SYM) {
  115. *buf->last++ = t->sym;
  116. }
  117. }
  118. ctx->fstate = t->fstate;
  119. if (final && !(ctx->fstate & NGHTTP2_HUFF_ACCEPTED)) {
  120. return NGHTTP2_ERR_HEADER_COMP;
  121. }
  122. return (nghttp2_ssize)srclen;
  123. }
  124. int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) {
  125. return ctx->fstate == 0x100;
  126. }