You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2015/09/17 03:16:24 UTC

trafficserver git commit: TS-3852: Add Huffman Encoder in HPACK

Repository: trafficserver
Updated Branches:
  refs/heads/master 46edbd72c -> d7170e2d7


TS-3852: Add Huffman Encoder in HPACK

This closes #294


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/d7170e2d
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/d7170e2d
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/d7170e2d

Branch: refs/heads/master
Commit: d7170e2d7030bb37febeb25e512c20149d86bb1f
Parents: 46edbd7
Author: Masaori Koshiba <mk...@yahoo-corp.jp>
Authored: Wed Sep 16 18:15:18 2015 -0700
Committer: Bryan Call <bc...@apache.org>
Committed: Wed Sep 16 18:15:18 2015 -0700

----------------------------------------------------------------------
 proxy/http2/HuffmanCodec.cc     | 50 ++++++++++++++++++++++++++++++++++++
 proxy/http2/HuffmanCodec.h      |  2 ++
 proxy/http2/test_Huffmancode.cc | 31 ++++++++++++++++++++++
 3 files changed, 83 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d7170e2d/proxy/http2/HuffmanCodec.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/HuffmanCodec.cc b/proxy/http2/HuffmanCodec.cc
index 020426f..e5b9c80 100644
--- a/proxy/http2/HuffmanCodec.cc
+++ b/proxy/http2/HuffmanCodec.cc
@@ -391,3 +391,53 @@ huffman_decode(char *dst_start, const uint8_t *src, uint32_t src_len)
 
   return dst_end - dst_start;
 }
+
+uint8_t *
+huffman_encode_append(uint8_t *dst, uint32_t src, int n = 0)
+{
+  for (int j = 3; j >= n; --j) {
+    *dst++ = ((src >> (8 * j)) & 255);
+  }
+  return dst;
+}
+
+int64_t
+huffman_encode(uint8_t *dst_start, const uint8_t *src, uint32_t src_len)
+{
+  uint8_t *dst = dst_start;
+  // NOTE: The maximum length of Huffman Code is 30, thus using uint32_t as buffer.
+  uint32_t buf = 0;
+  uint32_t remain_bits = 32;
+
+  for (uint32_t i = 0; i < src_len; ++i) {
+    const uint32_t hex = huffman_table[src[i]].code_as_hex;
+    const uint32_t bit_len = huffman_table[src[i]].bit_len;
+
+    if (remain_bits > bit_len) {
+      remain_bits = remain_bits - bit_len;
+      buf |= hex << remain_bits;
+    } else if (remain_bits == bit_len) {
+      buf |= hex;
+      dst = huffman_encode_append(dst, buf);
+      remain_bits = 32;
+      buf = 0;
+    } else {
+      buf |= hex >> (bit_len - remain_bits);
+      dst = huffman_encode_append(dst, buf);
+      remain_bits = (32 - (bit_len - remain_bits));
+      buf = hex << remain_bits;
+    }
+  }
+
+  if (buf != 0) {
+    dst = huffman_encode_append(dst, buf, remain_bits / 8);
+  }
+
+  // NOTE: Add padding w/ EOS
+  uint32_t pad_len = remain_bits % 8;
+  if (pad_len) {
+    *(dst - 1) |= 0xff >> (8 - pad_len);
+  }
+
+  return dst - dst_start;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d7170e2d/proxy/http2/HuffmanCodec.h
----------------------------------------------------------------------
diff --git a/proxy/http2/HuffmanCodec.h b/proxy/http2/HuffmanCodec.h
index 19b7621..49b5f0c 100644
--- a/proxy/http2/HuffmanCodec.h
+++ b/proxy/http2/HuffmanCodec.h
@@ -30,5 +30,7 @@
 void hpack_huffman_init();
 void hpack_huffman_fin();
 int64_t huffman_decode(char *dst_start, const uint8_t *src, uint32_t src_len);
+uint8_t *huffman_encode_append(uint8_t *dst, uint32_t src, int n);
+int64_t huffman_encode(uint8_t *dst_start, const uint8_t *src, uint32_t src_len);
 
 #endif /* __HPACK_Huffman_H__ */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/d7170e2d/proxy/http2/test_Huffmancode.cc
----------------------------------------------------------------------
diff --git a/proxy/http2/test_Huffmancode.cc b/proxy/http2/test_Huffmancode.cc
index 8c3a19d..8463f93 100644
--- a/proxy/http2/test_Huffmancode.cc
+++ b/proxy/http2/test_Huffmancode.cc
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <iostream>
 #include <assert.h>
+#include <string.h>
 
 using namespace std;
 
@@ -141,6 +142,34 @@ values_test()
   }
 }
 
+// NOTE: Test data from "C.6.1 First Response" in RFC 7541.
+const static struct {
+  uint8_t *src;
+  int64_t src_len;
+  uint8_t *expect;
+  int64_t expect_len;
+} huffman_encode_test_data[] = {
+  {(uint8_t *)"302", 3, (uint8_t *) "\x64\x02", 2},
+  {(uint8_t *)"private", 7, (uint8_t *) "\xae\xc3\x77\x1a\x4b", 5},
+  {(uint8_t *)"Mon, 21 Oct 2013 20:13:21 GMT", 29,
+   (uint8_t *) "\xd0\x7a\xbe\x94\x10\x54\xd4\x44\xa8\x20\x05\x95\x04\x0b\x81\x66\xe0\x82\xa6\x2d\x1b\xff", 22},
+  {(uint8_t *)"https://www.example.com", 23, (uint8_t *) "\x9d\x29\xad\x17\x18\x63\xc7\x8f\x0b\x97\xc8\xe9\xae\x82\xae\x43\xd3",
+   17}};
+
+void
+encode_test()
+{
+  for (uint64_t i = 0; i < sizeof(huffman_encode_test_data) / sizeof(huffman_encode_test_data[0]); ++i) {
+    uint8_t *dst = static_cast<uint8_t *>(malloc(huffman_encode_test_data[i].expect_len));
+    int64_t encoded_len = huffman_encode(dst, huffman_encode_test_data[i].src, huffman_encode_test_data[i].src_len);
+
+    assert(encoded_len == huffman_encode_test_data[i].expect_len);
+    assert(memcmp(huffman_encode_test_data[i].expect, dst, encoded_len) == 0);
+
+    free(dst);
+  }
+}
+
 int
 main()
 {
@@ -152,5 +181,7 @@ main()
   values_test();
 
   hpack_huffman_fin();
+
+  encode_test();
   return 0;
 }