11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * nghttp3
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Copyright (c) 2019 nghttp3 contributors
51cb0ef41Sopenharmony_ci * Copyright (c) 2013 nghttp2 contributors
61cb0ef41Sopenharmony_ci *
71cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
81cb0ef41Sopenharmony_ci * a copy of this software and associated documentation files (the
91cb0ef41Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
101cb0ef41Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
111cb0ef41Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
121cb0ef41Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
131cb0ef41Sopenharmony_ci * the following conditions:
141cb0ef41Sopenharmony_ci *
151cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be
161cb0ef41Sopenharmony_ci * included in all copies or substantial portions of the Software.
171cb0ef41Sopenharmony_ci *
181cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
191cb0ef41Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
201cb0ef41Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
211cb0ef41Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
221cb0ef41Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
231cb0ef41Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
241cb0ef41Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
251cb0ef41Sopenharmony_ci */
261cb0ef41Sopenharmony_ci#include "nghttp3_qpack_huffman.h"
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#include <string.h>
291cb0ef41Sopenharmony_ci#include <assert.h>
301cb0ef41Sopenharmony_ci#include <stdio.h>
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#include "nghttp3_conv.h"
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cisize_t nghttp3_qpack_huffman_encode_count(const uint8_t *src, size_t len) {
351cb0ef41Sopenharmony_ci  size_t i;
361cb0ef41Sopenharmony_ci  size_t nbits = 0;
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  for (i = 0; i < len; ++i) {
391cb0ef41Sopenharmony_ci    nbits += huffman_sym_table[src[i]].nbits;
401cb0ef41Sopenharmony_ci  }
411cb0ef41Sopenharmony_ci  /* pad the prefix of EOS (256) */
421cb0ef41Sopenharmony_ci  return (nbits + 7) / 8;
431cb0ef41Sopenharmony_ci}
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ciuint8_t *nghttp3_qpack_huffman_encode(uint8_t *dest, const uint8_t *src,
461cb0ef41Sopenharmony_ci                                      size_t srclen) {
471cb0ef41Sopenharmony_ci  const nghttp3_qpack_huffman_sym *sym;
481cb0ef41Sopenharmony_ci  const uint8_t *end = src + srclen;
491cb0ef41Sopenharmony_ci  uint64_t code = 0;
501cb0ef41Sopenharmony_ci  size_t nbits = 0;
511cb0ef41Sopenharmony_ci  uint32_t x;
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  for (; src != end;) {
541cb0ef41Sopenharmony_ci    sym = &huffman_sym_table[*src++];
551cb0ef41Sopenharmony_ci    code |= (uint64_t)sym->code << (32 - nbits);
561cb0ef41Sopenharmony_ci    nbits += sym->nbits;
571cb0ef41Sopenharmony_ci    if (nbits < 32) {
581cb0ef41Sopenharmony_ci      continue;
591cb0ef41Sopenharmony_ci    }
601cb0ef41Sopenharmony_ci    x = htonl((uint32_t)(code >> 32));
611cb0ef41Sopenharmony_ci    memcpy(dest, &x, 4);
621cb0ef41Sopenharmony_ci    dest += 4;
631cb0ef41Sopenharmony_ci    code <<= 32;
641cb0ef41Sopenharmony_ci    nbits -= 32;
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  for (; nbits >= 8;) {
681cb0ef41Sopenharmony_ci    *dest++ = (uint8_t)(code >> 56);
691cb0ef41Sopenharmony_ci    code <<= 8;
701cb0ef41Sopenharmony_ci    nbits -= 8;
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  if (nbits) {
741cb0ef41Sopenharmony_ci    *dest++ = (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1));
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  return dest;
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_civoid nghttp3_qpack_huffman_decode_context_init(
811cb0ef41Sopenharmony_ci    nghttp3_qpack_huffman_decode_context *ctx) {
821cb0ef41Sopenharmony_ci  ctx->fstate = NGHTTP3_QPACK_HUFFMAN_ACCEPTED;
831cb0ef41Sopenharmony_ci}
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_cinghttp3_ssize
861cb0ef41Sopenharmony_cinghttp3_qpack_huffman_decode(nghttp3_qpack_huffman_decode_context *ctx,
871cb0ef41Sopenharmony_ci                             uint8_t *dest, const uint8_t *src, size_t srclen,
881cb0ef41Sopenharmony_ci                             int fin) {
891cb0ef41Sopenharmony_ci  uint8_t *p = dest;
901cb0ef41Sopenharmony_ci  const uint8_t *end = src + srclen;
911cb0ef41Sopenharmony_ci  nghttp3_qpack_huffman_decode_node node = {ctx->fstate, 0};
921cb0ef41Sopenharmony_ci  const nghttp3_qpack_huffman_decode_node *t = &node;
931cb0ef41Sopenharmony_ci  uint8_t c;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  /* We use the decoding algorithm described in
961cb0ef41Sopenharmony_ci     http://graphics.ics.uci.edu/pub/Prefix.pdf */
971cb0ef41Sopenharmony_ci  for (; src != end;) {
981cb0ef41Sopenharmony_ci    c = *src++;
991cb0ef41Sopenharmony_ci    t = &qpack_huffman_decode_table[t->fstate & 0x1ff][c >> 4];
1001cb0ef41Sopenharmony_ci    if (t->fstate & NGHTTP3_QPACK_HUFFMAN_SYM) {
1011cb0ef41Sopenharmony_ci      *p++ = t->sym;
1021cb0ef41Sopenharmony_ci    }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    t = &qpack_huffman_decode_table[t->fstate & 0x1ff][c & 0xf];
1051cb0ef41Sopenharmony_ci    if (t->fstate & NGHTTP3_QPACK_HUFFMAN_SYM) {
1061cb0ef41Sopenharmony_ci      *p++ = t->sym;
1071cb0ef41Sopenharmony_ci    }
1081cb0ef41Sopenharmony_ci  }
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  ctx->fstate = t->fstate;
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  if (fin && !(ctx->fstate & NGHTTP3_QPACK_HUFFMAN_ACCEPTED)) {
1131cb0ef41Sopenharmony_ci    return NGHTTP3_ERR_QPACK_FATAL;
1141cb0ef41Sopenharmony_ci  }
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  return p - dest;
1171cb0ef41Sopenharmony_ci}
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ciint nghttp3_qpack_huffman_decode_failure_state(
1201cb0ef41Sopenharmony_ci    nghttp3_qpack_huffman_decode_context *ctx) {
1211cb0ef41Sopenharmony_ci  return ctx->fstate == 0x100;
1221cb0ef41Sopenharmony_ci}
123