aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2015-08-13 11:32:48 +0900
committerKazuki Yamaguchi <k@rhe.jp>2015-08-13 11:32:48 +0900
commitc8551ca9b98110322d48fb536b3fdcc65bcd423b (patch)
tree3a66a07a07d47fa5a80f35451131de780d5cdfc5
parentad75dffe59fabc40d8e28347b7a5aa1baf07d9ac (diff)
downloadplum-c8551ca9b98110322d48fb536b3fdcc65bcd423b.tar.gz
hpack: use tables on encoding
-rw-r--r--lib/plum/hpack/context.rb9
-rw-r--r--lib/plum/hpack/decoder.rb5
-rw-r--r--lib/plum/hpack/encoder.rb66
3 files changed, 66 insertions, 14 deletions
diff --git a/lib/plum/hpack/context.rb b/lib/plum/hpack/context.rb
index 0d0eb63..5973d94 100644
--- a/lib/plum/hpack/context.rb
+++ b/lib/plum/hpack/context.rb
@@ -33,6 +33,15 @@ module Plum
end
end
+ def search(name, value)
+ if value
+ i = STATIC_TABLE.index([name, value]) || @dynamic_table.index([name, value])
+ else
+ i = STATIC_TABLE.index {|n, _| n == name } || @dynamic_table.index {|n, _| n == name }
+ end
+ i && (i + 1) # index is >= 1
+ end
+
def evict
while @limit && @size > @limit
name, value = @dynamic_table.pop
diff --git a/lib/plum/hpack/decoder.rb b/lib/plum/hpack/decoder.rb
index 71c8be5..13833c1 100644
--- a/lib/plum/hpack/decoder.rb
+++ b/lib/plum/hpack/decoder.rb
@@ -55,7 +55,10 @@ module Plum
end
def read_string!(str)
- huffman = (str.uint8 >> 7) == 1
+ first_byte = str.uint8
+ raise HPACKError.new("string: end of buffer") unless first_byte
+
+ huffman = (first_byte >> 7) == 1
length = read_integer!(str, 7)
bin = str.byteshift(length)
diff --git a/lib/plum/hpack/encoder.rb b/lib/plum/hpack/encoder.rb
index 551ec58..58d13be 100644
--- a/lib/plum/hpack/encoder.rb
+++ b/lib/plum/hpack/encoder.rb
@@ -9,10 +9,24 @@ module Plum
super
end
- # currently only support 0x0000XXXX type (without indexing)
- # and not huffman
+ def encode(headers)
+ out = ""
+ headers.each do |name, value|
+ name = name.to_s; value = value.to_s
+ if index = search(name, value)
+ out << encode_indexed(index)
+ elsif index = search(name, nil)
+ out << encode_half_indexed(index, value, true) # incremental indexing
+ else
+ out << encode_literal(name, value, true) # incremental indexing
+ end
+ end
+ out.force_encoding(Encoding::BINARY)
+ end
+
+ private
# +---+---+---+---+---+---+---+---+
- # | 0 | 0 | 0 | 0 | 0 |
+ # | 0 | 1 | 0 |
# +---+---+-----------------------+
# | H | Name Length (7+) |
# +---+---------------------------+
@@ -22,17 +36,43 @@ module Plum
# +---+---------------------------+
# | Value String (Length octets) |
# +-------------------------------+
- def encode(headers)
- out = ""
- headers.each do |name, value|
- out << "\x00"
- out << encode_string(name.to_s)
- out << encode_string(value.to_s)
+ def encode_literal(name, value, indexing = true)
+ if indexing
+ store(name, value)
+ fb = "\x40"
+ else
+ fb = "\x00"
end
- out
+ fb << encode_string(name) << encode_string(value)
+ end
+
+ # +---+---+---+---+---+---+---+---+
+ # | 0 | 1 | Index (6+) |
+ # +---+---+-----------------------+
+ # | H | Value Length (7+) |
+ # +---+---------------------------+
+ # | Value String (Length octets) |
+ # +-------------------------------+
+ def encode_half_indexed(index, value, indexing = true)
+ if indexing
+ store(fetch(index)[0], value)
+ fb = encode_integer(index, 6)
+ fb.setbyte(0, fb.uint8 | 0b01000000)
+ else
+ fb = encode_integer(index, 4)
+ end
+ fb << encode_string(value)
+ end
+
+ # +---+---+---+---+---+---+---+---+
+ # | 1 | Index (7+) |
+ # +---+---------------------------+
+ def encode_indexed(index)
+ s = encode_integer(index, 7)
+ s.setbyte(0, s.uint8 | 0b10000000)
+ s
end
- private
def encode_integer(value, prefix_length)
mask = (1 << prefix_length) - 1
out = ""
@@ -51,9 +91,9 @@ module Plum
end
def encode_string(str)
- huffman_str = Huffman.encode(str)
+ huffman_str = Huffman.encode(str).force_encoding(__ENCODING__)
if huffman_str.bytesize < str.bytesize
- lenstr = encode_integer(huffman_str.bytesize, 7).force_encoding(Encoding::BINARY)
+ lenstr = encode_integer(huffman_str.bytesize, 7)
lenstr.setbyte(0, lenstr.uint8(0) | 0b10000000)
lenstr << huffman_str
else