bin_encoder.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. #include "src/core/transport/chttp2/bin_encoder.h"
  34. #include <string.h>
  35. #include "src/core/transport/chttp2/huffsyms.h"
  36. #include <grpc/support/log.h>
  37. static const char alphabet[] =
  38. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  39. typedef struct {
  40. gpr_uint16 bits;
  41. gpr_uint8 length;
  42. } b64_huff_sym;
  43. static const b64_huff_sym huff_alphabet[64] = {
  44. {0x21, 6}, {0x5d, 7}, {0x5e, 7}, {0x5f, 7}, {0x60, 7}, {0x61, 7},
  45. {0x62, 7}, {0x63, 7}, {0x64, 7}, {0x65, 7}, {0x66, 7}, {0x67, 7},
  46. {0x68, 7}, {0x69, 7}, {0x6a, 7}, {0x6b, 7}, {0x6c, 7}, {0x6d, 7},
  47. {0x6e, 7}, {0x6f, 7}, {0x70, 7}, {0x71, 7}, {0x72, 7}, {0xfc, 8},
  48. {0x73, 7}, {0xfd, 8}, {0x3, 5}, {0x23, 6}, {0x4, 5}, {0x24, 6},
  49. {0x5, 5}, {0x25, 6}, {0x26, 6}, {0x27, 6}, {0x6, 5}, {0x74, 7},
  50. {0x75, 7}, {0x28, 6}, {0x29, 6}, {0x2a, 6}, {0x7, 5}, {0x2b, 6},
  51. {0x76, 7}, {0x2c, 6}, {0x8, 5}, {0x9, 5}, {0x2d, 6}, {0x77, 7},
  52. {0x78, 7}, {0x79, 7}, {0x7a, 7}, {0x7b, 7}, {0x0, 5}, {0x1, 5},
  53. {0x2, 5}, {0x19, 6}, {0x1a, 6}, {0x1b, 6}, {0x1c, 6}, {0x1d, 6},
  54. {0x1e, 6}, {0x1f, 6}, {0x7fb, 11}, {0x18, 6}};
  55. static const gpr_uint8 tail_xtra[3] = {0, 2, 3};
  56. gpr_slice grpc_chttp2_base64_encode(gpr_slice input) {
  57. size_t input_length = GPR_SLICE_LENGTH(input);
  58. size_t input_triplets = input_length / 3;
  59. size_t tail_case = input_length % 3;
  60. size_t output_length = input_triplets * 4 + tail_xtra[tail_case];
  61. gpr_slice output = gpr_slice_malloc(output_length);
  62. gpr_uint8 *in = GPR_SLICE_START_PTR(input);
  63. gpr_uint8 *out = GPR_SLICE_START_PTR(output);
  64. size_t i;
  65. /* encode full triplets */
  66. for (i = 0; i < input_triplets; i++) {
  67. out[0] = alphabet[in[0] >> 2];
  68. out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
  69. out[2] = alphabet[((in[1] & 0xf) << 2) | (in[2] >> 6)];
  70. out[3] = alphabet[in[2] & 0x3f];
  71. out += 4;
  72. in += 3;
  73. }
  74. /* encode the remaining bytes */
  75. switch (tail_case) {
  76. case 0:
  77. break;
  78. case 1:
  79. out[0] = alphabet[in[0] >> 2];
  80. out[1] = alphabet[(in[0] & 0x3) << 4];
  81. out += 2;
  82. in += 1;
  83. break;
  84. case 2:
  85. out[0] = alphabet[in[0] >> 2];
  86. out[1] = alphabet[((in[0] & 0x3) << 4) | (in[1] >> 4)];
  87. out[2] = alphabet[(in[1] & 0xf) << 2];
  88. out += 3;
  89. in += 2;
  90. break;
  91. }
  92. GPR_ASSERT(out == GPR_SLICE_END_PTR(output));
  93. GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
  94. return output;
  95. }
  96. gpr_slice grpc_chttp2_huffman_compress(gpr_slice input) {
  97. size_t nbits;
  98. gpr_uint8 *in;
  99. gpr_uint8 *out;
  100. gpr_slice output;
  101. gpr_uint32 temp = 0;
  102. gpr_uint32 temp_length = 0;
  103. nbits = 0;
  104. for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
  105. nbits += grpc_chttp2_huffsyms[*in].length;
  106. }
  107. output = gpr_slice_malloc(nbits / 8 + (nbits % 8 != 0));
  108. out = GPR_SLICE_START_PTR(output);
  109. for (in = GPR_SLICE_START_PTR(input); in != GPR_SLICE_END_PTR(input); ++in) {
  110. int sym = *in;
  111. temp <<= grpc_chttp2_huffsyms[sym].length;
  112. temp |= grpc_chttp2_huffsyms[sym].bits;
  113. temp_length += grpc_chttp2_huffsyms[sym].length;
  114. while (temp_length > 8) {
  115. temp_length -= 8;
  116. *out++ = temp >> temp_length;
  117. }
  118. }
  119. if (temp_length) {
  120. *out++ = (temp << (8 - temp_length)) | (0xff >> temp_length);
  121. }
  122. GPR_ASSERT(out == GPR_SLICE_END_PTR(output));
  123. return output;
  124. }
  125. typedef struct {
  126. gpr_uint32 temp;
  127. gpr_uint32 temp_length;
  128. gpr_uint8 *out;
  129. } huff_out;
  130. static void enc_flush_some(huff_out *out) {
  131. while (out->temp_length > 8) {
  132. out->temp_length -= 8;
  133. *out->out++ = out->temp >> out->temp_length;
  134. }
  135. }
  136. static void enc_add2(huff_out *out, gpr_uint8 a, gpr_uint8 b) {
  137. b64_huff_sym sa = huff_alphabet[a];
  138. b64_huff_sym sb = huff_alphabet[b];
  139. out->temp =
  140. (out->temp << (sa.length + sb.length)) | (sa.bits << sb.length) | sb.bits;
  141. out->temp_length += sa.length + sb.length;
  142. enc_flush_some(out);
  143. }
  144. static void enc_add1(huff_out *out, gpr_uint8 a) {
  145. b64_huff_sym sa = huff_alphabet[a];
  146. out->temp = (out->temp << sa.length) | sa.bits;
  147. out->temp_length += sa.length;
  148. enc_flush_some(out);
  149. }
  150. gpr_slice grpc_chttp2_base64_encode_and_huffman_compress(gpr_slice input) {
  151. size_t input_length = GPR_SLICE_LENGTH(input);
  152. size_t input_triplets = input_length / 3;
  153. size_t tail_case = input_length % 3;
  154. size_t output_syms = input_triplets * 4 + tail_xtra[tail_case];
  155. size_t max_output_bits = 11 * output_syms;
  156. size_t max_output_length = max_output_bits / 8 + (max_output_bits % 8 != 0);
  157. gpr_slice output = gpr_slice_malloc(max_output_length);
  158. gpr_uint8 *in = GPR_SLICE_START_PTR(input);
  159. gpr_uint8 *start_out = GPR_SLICE_START_PTR(output);
  160. huff_out out;
  161. size_t i;
  162. out.temp = 0;
  163. out.temp_length = 0;
  164. out.out = start_out;
  165. /* encode full triplets */
  166. for (i = 0; i < input_triplets; i++) {
  167. enc_add2(&out, in[0] >> 2, ((in[0] & 0x3) << 4) | (in[1] >> 4));
  168. enc_add2(&out, ((in[1] & 0xf) << 2) | (in[2] >> 6), in[2] & 0x3f);
  169. in += 3;
  170. }
  171. /* encode the remaining bytes */
  172. switch (tail_case) {
  173. case 0:
  174. break;
  175. case 1:
  176. enc_add2(&out, in[0] >> 2, (in[0] & 0x3) << 4);
  177. in += 1;
  178. break;
  179. case 2:
  180. enc_add2(&out, in[0] >> 2, ((in[0] & 0x3) << 4) | (in[1] >> 4));
  181. enc_add1(&out, (in[1] & 0xf) << 2);
  182. in += 2;
  183. break;
  184. }
  185. if (out.temp_length) {
  186. *out.out++ =
  187. (out.temp << (8 - out.temp_length)) | (0xff >> out.temp_length);
  188. }
  189. GPR_ASSERT(out.out <= GPR_SLICE_END_PTR(output));
  190. GPR_SLICE_SET_LENGTH(output, out.out - start_out);
  191. GPR_ASSERT(in == GPR_SLICE_END_PTR(input));
  192. return output;
  193. }
  194. int grpc_is_binary_header(const char *key, size_t length) {
  195. if (length < 5) return 0;
  196. return 0 == memcmp(key + length - 4, "-bin", 4);
  197. }