| Index: third_party/grpc/src/core/transport/chttp2/bin_encoder.c
|
| diff --git a/third_party/grpc/src/core/transport/chttp2/bin_encoder.c b/third_party/grpc/src/core/transport/chttp2/bin_encoder.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f26bc7e29b14727212872d8d4cb6527869bf25b4
|
| --- /dev/null
|
| +++ b/third_party/grpc/src/core/transport/chttp2/bin_encoder.c
|
| @@ -0,0 +1,285 @@
|
| +/*
|
| + *
|
| + * Copyright 2015-2016, Google Inc.
|
| + * All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + *
|
| + */
|
| +
|
| +#include "src/core/transport/chttp2/bin_encoder.h"
|
| +
|
| +#include <string.h>
|
| +
|
| +#include "src/core/transport/chttp2/huffsyms.h"
|
| +#include <grpc/support/log.h>
|
| +
|
| +static const char alphabet[] =
|
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
| +
|
| +typedef struct {
|
| + uint16_t bits;
|
| + uint8_t length;
|
| +} b64_huff_sym;
|
| +
|
| +static const b64_huff_sym huff_alphabet[64] = {{0x21, 6},
|
| + {0x5d, 7},
|
| + {0x5e, 7},
|
| + {0x5f, 7},
|
| + {0x60, 7},
|
| + {0x61, 7},
|
| + {0x62, 7},
|
| + {0x63, 7},
|
| + {0x64, 7},
|
| + {0x65, 7},
|
| + {0x66, 7},
|
| + {0x67, 7},
|
| + {0x68, 7},
|
| + {0x69, 7},
|
| + {0x6a, 7},
|
| + {0x6b, 7},
|
| + {0x6c, 7},
|
| + {0x6d, 7},
|
| + {0x6e, 7},
|
| + {0x6f, 7},
|
| + {0x70, 7},
|
| + {0x71, 7},
|
| + {0x72, 7},
|
| + {0xfc, 8},
|
| + {0x73, 7},
|
| + {0xfd, 8},
|
| + {0x3, 5},
|
| + {0x23, 6},
|
| + {0x4, 5},
|
| + {0x24, 6},
|
| + {0x5, 5},
|
| + {0x25, 6},
|
| + {0x26, 6},
|
| + {0x27, 6},
|
| + {0x6, 5},
|
| + {0x74, 7},
|
| + {0x75, 7},
|
| + {0x28, 6},
|
| + {0x29, 6},
|
| + {0x2a, 6},
|
| + {0x7, 5},
|
| + {0x2b, 6},
|
| + {0x76, 7},
|
| + {0x2c, 6},
|
| + {0x8, 5},
|
| + {0x9, 5},
|
| + {0x2d, 6},
|
| + {0x77, 7},
|
| + {0x78, 7},
|
| + {0x79, 7},
|
| + {0x7a, 7},
|
| + {0x7b, 7},
|
| + {0x0, 5},
|
| + {0x1, 5},
|
| + {0x2, 5},
|
| + {0x19, 6},
|
| + {0x1a, 6},
|
| + {0x1b, 6},
|
| + {0x1c, 6},
|
| + {0x1d, 6},
|
| + {0x1e, 6},
|
| + {0x1f, 6},
|
| + {0x7fb, 11},
|
| + {0x18, 6}};
|
| +
|
| +static const uint8_t tail_xtra[3] = {0, 2, 3};
|
| +
|
| +gpr_slice grpc_chttp2_base64_encode(gpr_slice input) {
|
| + size_t input_length = GPR_SLICE_LENGTH(input);
|
| + size_t input_triplets = input_length / 3;
|
| + size_t tail_case = input_length % 3;
|
| + size_t output_length = input_triplets * 4 + tail_xtra[tail_case];
|
| + gpr_slice output = gpr_slice_malloc(output_length);
|
| + uint8_t *in = GPR_SLICE_START_PTR(input);
|
| + char *out = (char *)GPR_SLICE_START_PTR(output);
|
| + size_t i;
|
| +
|
| + /* encode full triplets */
|
| + for (i = 0; i < input_triplets; i++) {
|
| + out[0] = alphabet[in[0] >> 2];
|
| + out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
|
| + out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)];
|
| + out[3] = alphabet[in[2] & 0x3f];
|
| + out += 4;
|
| + in += 3;
|
| + }
|
| +
|
| + /* encode the remaining bytes */
|
| + switch (tail_case) {
|
| + case 0:
|
| + break;
|
| + case 1:
|
| + out[0] = alphabet[in[0] >> 2];
|
| + out[1] = alphabet[(in[0] & 0x3) << 4];
|
| + out += 2;
|
| + in += 1;
|
| + break;
|
| + case 2:
|
| + out[0] = alphabet[in[0] >> 2];
|
| + out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
|
| + out[2] = alphabet[(in[1] & 0xf) << 2];
|
| + out += 3;
|
| + in += 2;
|
| + break;
|
| + }
|
| +
|
| + GPR_ASSERT(out == (char *)GPR_SLICE_END_PTR(output));
|
| + GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
|
| + return output;
|
| +}
|
| +
|
| +gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) {
|
| + size_t nbits;
|
| + uint8_t *in;
|
| + uint8_t *out;
|
| + gpr_slice output;
|
| + uint32_t temp = 0;
|
| + uint32_t temp_length = 0;
|
| +
|
| + nbits = 0;
|
| + for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
|
| + nbits += grpc_chttp2_huffsyms[*in].length;
|
| + }
|
| +
|
| + output = gpr_slice_malloc(nbits / 8 + (nbits % 8 != 0));
|
| + out = GPR_SLICE_START_PTR(output);
|
| + for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
|
| + int sym = *in;
|
| + temp <<= grpc_chttp2_huffsyms[sym].length;
|
| + temp |= grpc_chttp2_huffsyms[sym].bits;
|
| + temp_length += grpc_chttp2_huffsyms[sym].length;
|
| +
|
| + while (temp_length > 8) {
|
| + temp_length -= 8;
|
| + *out++ = (uint8_t)(temp >> temp_length);
|
| + }
|
| + }
|
| +
|
| + if (temp_length) {
|
| + /* NB: the following integer arithmetic operation needs to be in its
|
| + * expanded form due to the "integral promotion" performed (see section
|
| + * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
|
| + * is then required to avoid the compiler warning */
|
| + *out++ = (uint8_t)((uint8_t)(temp << (8u - temp_length)) |
|
| + (uint8_t)(0xffu >> temp_length));
|
| + }
|
| +
|
| + GPR_ASSERT(out == GPR_SLICE_END_PTR(output));
|
| +
|
| + return output;
|
| +}
|
| +
|
| +typedef struct {
|
| + uint32_t temp;
|
| + uint32_t temp_length;
|
| + uint8_t *out;
|
| +} huff_out;
|
| +
|
| +static void enc_flush_some(huff_out *out) {
|
| + while (out->temp_length > 8) {
|
| + out->temp_length -= 8;
|
| + *out->out++ = (uint8_t)(out->temp >> out->temp_length);
|
| + }
|
| +}
|
| +
|
| +static void enc_add2(huff_out *out, uint8_t a, uint8_t b) {
|
| + b64_huff_sym sa = huff_alphabet[a];
|
| + b64_huff_sym sb = huff_alphabet[b];
|
| + out->temp = (out->temp << (sa.length + sb.length)) |
|
| + ((uint32_t)sa.bits << sb.length) | sb.bits;
|
| + out->temp_length += (uint32_t)sa.length + (uint32_t)sb.length;
|
| + enc_flush_some(out);
|
| +}
|
| +
|
| +static void enc_add1(huff_out *out, uint8_t a) {
|
| + b64_huff_sym sa = huff_alphabet[a];
|
| + out->temp = (out->temp << sa.length) | sa.bits;
|
| + out->temp_length += sa.length;
|
| + enc_flush_some(out);
|
| +}
|
| +
|
| +gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input) {
|
| + size_t input_length = GPR_SLICE_LENGTH(input);
|
| + size_t input_triplets = input_length / 3;
|
| + size_t tail_case = input_length % 3;
|
| + size_t output_syms = input_triplets * 4 + tail_xtra[tail_case];
|
| + size_t max_output_bits = 11 * output_syms;
|
| + size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0);
|
| + gpr_slice output = gpr_slice_malloc(max_output_length);
|
| + uint8_t *in = GPR_SLICE_START_PTR(input);
|
| + uint8_t *start_out = GPR_SLICE_START_PTR(output);
|
| + huff_out out;
|
| + size_t i;
|
| +
|
| + out.temp = 0;
|
| + out.temp_length = 0;
|
| + out.out = start_out;
|
| +
|
| + /* encode full triplets */
|
| + for (i = 0; i < input_triplets; i++) {
|
| + enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4) | (in[1] >> 4));
|
| + enc_add2(&out, (uint8_t)((in[1] & 0xf) << 2) | (in[2] >> 6),
|
| + (uint8_t)(in[2] & 0x3f));
|
| + in += 3;
|
| + }
|
| +
|
| + /* encode the remaining bytes */
|
| + switch (tail_case) {
|
| + case 0:
|
| + break;
|
| + case 1:
|
| + enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4));
|
| + in += 1;
|
| + break;
|
| + case 2:
|
| + enc_add2(&out, in[0] >> 2,
|
| + (uint8_t)((in[0] & 0x3) << 4) | (uint8_t)(in[1] >> 4));
|
| + enc_add1(&out, (uint8_t)((in[1] & 0xf) << 2));
|
| + in += 2;
|
| + break;
|
| + }
|
| +
|
| + if (out.temp_length) {
|
| + /* NB: the following integer arithmetic operation needs to be in its
|
| + * expanded form due to the "integral promotion" performed (see section
|
| + * 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
|
| + * is then required to avoid the compiler warning */
|
| + *out.out++ = (uint8_t)((uint8_t)(out.temp << (8u - out.temp_length)) |
|
| + (uint8_t)(0xffu >> out.temp_length));
|
| + }
|
| +
|
| + GPR_ASSERT(out.out <= GPR_SLICE_END_PTR(output));
|
| + GPR_SLICE_SET_LENGTH(output, out.out - start_out);
|
| +
|
| + GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
|
| + return output;
|
| +}
|
|
|