hpack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b6783e15162742ae6a5234b6246e5e6a3e79a62d
4
+ data.tar.gz: 706528046402ce381f19218dd67155f705b96028
5
+ SHA512:
6
+ metadata.gz: 17e698d980a2a6db5c6fe473d057694e131483539917a3ecd1c8cc922eedf25fa951b204f5c0fcf67239af34f691d7367bf2ba4c7bf4d4da6d771cb521028ca3
7
+ data.tar.gz: 89b6189be4973cc58e71620f1b8119b70d8004af34033a590674bd896ce768f7b8c84267ddae0bcb24c4ce89ed48c786478941e8640c829c9ef2a1c9301072a1
@@ -0,0 +1,2 @@
1
+ /*.gem
2
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --require hpack
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hpack.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Konstantin Burnaev
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,40 @@
1
+ # Hpack
2
+
3
+ Ruby implementation of the HPACK (Header Compression for HTTP/2) standard.
4
+
5
+ http://http2.github.io/http2-spec/compression.html
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'hpack'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install hpack
20
+
21
+ ## Usage
22
+
23
+ ```
24
+ require 'hpack'
25
+
26
+ io_stream = ... something which gives you IO object with data to be processed ...
27
+
28
+ decoder = Hpack::Decoder.new
29
+ decoder.decode io_stream do |header, value, metadata|
30
+ ...
31
+ end
32
+ ```
33
+
34
+ ## Contributing
35
+
36
+ 1. Fork it ( https://github.com/[my-github-username]/hpack/fork )
37
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
38
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
39
+ 4. Push to the branch (`git push origin my-new-feature`)
40
+ 5. Create a new Pull Request
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ # If you want to make this the default task
7
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hpack/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hpack"
8
+ spec.version = Hpack::VERSION
9
+ spec.authors = ["Konstantin Burnaev"]
10
+ spec.email = ["kbourn@gmail.com"]
11
+ spec.summary = %q{HPACK implementation for Ruby.}
12
+ spec.description = """Ruby implementation of the HPACK (Header Compression for HTTP/2) standard available at http://http2.github.io/http2-spec/compression.html"""
13
+ spec.homepage = "https://github.com/bkon/hpack"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake", "~> 10.4", ">= 10.4.2"
23
+ spec.add_development_dependency "simplecov", "~> 0.9", ">= 0.9.1"
24
+ spec.add_development_dependency "rspec", "~> 3.1", ">= 3.1.0"
25
+ end
@@ -0,0 +1,10 @@
1
+ require "hpack/version"
2
+ require "hpack/decoder"
3
+ require "hpack/field"
4
+ require "hpack/huffman"
5
+ require "hpack/integer_reader"
6
+ require "hpack/lookup_table"
7
+
8
+ module Hpack
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,110 @@
1
+ module Hpack
2
+ class Decoder
3
+ class DecodingError < StandardError; end
4
+ class ZeroIndexedFieldIndex < DecodingError; end
5
+
6
+ attr_reader :lookup_table
7
+
8
+ def initialize lookup_table_size: LookupTable::SETTINGS_HEADER_TABLE_SIZE
9
+ @lookup_table = LookupTable.new max_size: lookup_table_size
10
+ end
11
+
12
+ def decode input
13
+ read_fields_from input do |field|
14
+ yield field.header, field.value, field
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def read_fields_from input
21
+ while not input.eof?
22
+ header_byte = input.readbyte
23
+
24
+ # indexed
25
+ if header_byte & 0b1000_0000 == 0b1000_0000
26
+ index = read_integer_with_prefix length: 7, input: input, start_with: header_byte
27
+
28
+ if index == 0
29
+ raise ZeroIndexedFieldIndex
30
+ end
31
+
32
+ header = @lookup_table[index].name
33
+ value = @lookup_table[index].value
34
+
35
+ yield Field.new header, value
36
+
37
+ # literal indexed
38
+ elsif header_byte & 0b1100_0000 == 0b0100_0000
39
+ name_index = read_integer_with_prefix length: 6, input: input, start_with: header_byte
40
+ if name_index == 0
41
+ header = read_string input
42
+ else
43
+ header = @lookup_table[name_index].name
44
+ end
45
+
46
+ value = read_string input
47
+
48
+ @lookup_table << LookupTable::Entry.new(header, value)
49
+
50
+ yield Field.new header, value
51
+
52
+ elsif header_byte & 0b1111_0000 == 0b0000_0000
53
+ name_index = read_integer_with_prefix length: 4, input: input, start_with: header_byte
54
+
55
+ if name_index == 0
56
+ header = read_string input
57
+ else
58
+ header = @lookup_table[name_index].name
59
+ end
60
+
61
+ value = read_string input
62
+
63
+ yield Field.new header, value
64
+
65
+ elsif header_byte & 0b1111_0000 == 0b0001_0000
66
+ name_index = read_integer_with_prefix length: 4, input: input, start_with: header_byte
67
+
68
+ if name_index == 0
69
+ header = read_string input
70
+ else
71
+ header = @lookup_table[name_index].name
72
+ end
73
+
74
+ value = read_string input
75
+
76
+ yield Field.new header, value
77
+
78
+ elsif header_byte & 0b1110_0000 == 0b0010_0000
79
+ new_size = read_integer_with_prefix length: 5, input: input, start_with: header_byte
80
+
81
+ @lookup_table.max_size = new_size
82
+ end
83
+ end
84
+ end
85
+
86
+ def read_integer_with_prefix *options
87
+ integer_reader.read(*options)
88
+ end
89
+
90
+ def read_string input
91
+ header_byte = input.readbyte
92
+ huffman = (header_byte & 0b1000_0000 != 0)
93
+ length = read_integer_with_prefix length: 7, input: input, start_with: header_byte
94
+
95
+ if huffman
96
+ huffman_decoder.decode input: input, length: length
97
+ else
98
+ input.read length
99
+ end
100
+ end
101
+
102
+ def huffman_decoder
103
+ @huffman_decode ||= Hpack::Huffman.new
104
+ end
105
+
106
+ def integer_reader
107
+ @integer_reader ||= Hpack::IntegerReader.new
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,4 @@
1
+ module Hpack
2
+ class Encoder
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module Hpack
2
+ class Field
3
+ attr_reader :header
4
+ attr_reader :value
5
+
6
+ def initialize header, value
7
+ @header = header
8
+ @value = value
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,326 @@
1
+ module Hpack
2
+ class Huffman
3
+ HUFFMAN = [
4
+ "1111111111000",
5
+ "11111111111111111011000",
6
+ "1111111111111111111111100010",
7
+ "1111111111111111111111100011",
8
+ "1111111111111111111111100100",
9
+ "1111111111111111111111100101",
10
+ "1111111111111111111111100110",
11
+ "1111111111111111111111100111",
12
+ "1111111111111111111111101000",
13
+ "111111111111111111101010",
14
+ "111111111111111111111111111100",
15
+ "1111111111111111111111101001",
16
+ "1111111111111111111111101010",
17
+ "111111111111111111111111111101",
18
+ "1111111111111111111111101011",
19
+ "1111111111111111111111101100",
20
+ "1111111111111111111111101101",
21
+ "1111111111111111111111101110",
22
+ "1111111111111111111111101111",
23
+ "1111111111111111111111110000",
24
+ "1111111111111111111111110001",
25
+ "1111111111111111111111110010",
26
+ "111111111111111111111111111110",
27
+ "1111111111111111111111110011",
28
+ "1111111111111111111111110100",
29
+ "1111111111111111111111110101",
30
+ "1111111111111111111111110110",
31
+ "1111111111111111111111110111",
32
+ "1111111111111111111111111000",
33
+ "1111111111111111111111111001",
34
+ "1111111111111111111111111010",
35
+ "1111111111111111111111111011",
36
+ "010100",
37
+ "1111111000",
38
+ "1111111001",
39
+ "111111111010",
40
+ "1111111111001",
41
+ "010101",
42
+ "11111000",
43
+ "11111111010",
44
+ "1111111010",
45
+ "1111111011",
46
+ "11111001",
47
+ "11111111011",
48
+ "11111010",
49
+ "010110",
50
+ "010111",
51
+ "011000",
52
+ "00000",
53
+ "00001",
54
+ "00010",
55
+ "011001",
56
+ "011010",
57
+ "011011",
58
+ "011100",
59
+ "011101",
60
+ "011110",
61
+ "011111",
62
+ "1011100",
63
+ "11111011",
64
+ "111111111111100",
65
+ "100000",
66
+ "111111111011",
67
+ "1111111100",
68
+ "1111111111010",
69
+ "100001",
70
+ "1011101",
71
+ "1011110",
72
+ "1011111",
73
+ "1100000",
74
+ "1100001",
75
+ "1100010",
76
+ "1100011",
77
+ "1100100",
78
+ "1100101",
79
+ "1100110",
80
+ "1100111",
81
+ "1101000",
82
+ "1101001",
83
+ "1101010",
84
+ "1101011",
85
+ "1101100",
86
+ "1101101",
87
+ "1101110",
88
+ "1101111",
89
+ "1110000",
90
+ "1110001",
91
+ "1110010",
92
+ "11111100",
93
+ "1110011",
94
+ "11111101",
95
+ "1111111111011",
96
+ "1111111111111110000",
97
+ "1111111111100",
98
+ "11111111111100",
99
+ "100010",
100
+ "111111111111101",
101
+ "00011",
102
+ "100011",
103
+ "00100",
104
+ "100100",
105
+ "00101",
106
+ "100101",
107
+ "100110",
108
+ "100111",
109
+ "00110",
110
+ "1110100",
111
+ "1110101",
112
+ "101000",
113
+ "101001",
114
+ "101010",
115
+ "00111",
116
+ "101011",
117
+ "1110110",
118
+ "101100",
119
+ "01000",
120
+ "01001",
121
+ "101101",
122
+ "1110111",
123
+ "1111000",
124
+ "1111001",
125
+ "1111010",
126
+ "1111011",
127
+ "111111111111110",
128
+ "11111111100",
129
+ "11111111111101",
130
+ "1111111111101",
131
+ "1111111111111111111111111100",
132
+ "11111111111111100110",
133
+ "1111111111111111010010",
134
+ "11111111111111100111",
135
+ "11111111111111101000",
136
+ "1111111111111111010011",
137
+ "1111111111111111010100",
138
+ "1111111111111111010101",
139
+ "11111111111111111011001",
140
+ "1111111111111111010110",
141
+ "11111111111111111011010",
142
+ "11111111111111111011011",
143
+ "11111111111111111011100",
144
+ "11111111111111111011101",
145
+ "11111111111111111011110",
146
+ "111111111111111111101011",
147
+ "11111111111111111011111",
148
+ "111111111111111111101100",
149
+ "111111111111111111101101",
150
+ "1111111111111111010111",
151
+ "11111111111111111100000",
152
+ "111111111111111111101110",
153
+ "11111111111111111100001",
154
+ "11111111111111111100010",
155
+ "11111111111111111100011",
156
+ "11111111111111111100100",
157
+ "111111111111111011100",
158
+ "1111111111111111011000",
159
+ "11111111111111111100101",
160
+ "1111111111111111011001",
161
+ "11111111111111111100110",
162
+ "11111111111111111100111",
163
+ "111111111111111111101111",
164
+ "1111111111111111011010",
165
+ "111111111111111011101",
166
+ "11111111111111101001",
167
+ "1111111111111111011011",
168
+ "1111111111111111011100",
169
+ "11111111111111111101000",
170
+ "11111111111111111101001",
171
+ "111111111111111011110",
172
+ "11111111111111111101010",
173
+ "1111111111111111011101",
174
+ "1111111111111111011110",
175
+ "111111111111111111110000",
176
+ "111111111111111011111",
177
+ "1111111111111111011111",
178
+ "11111111111111111101011",
179
+ "11111111111111111101100",
180
+ "111111111111111100000",
181
+ "111111111111111100001",
182
+ "1111111111111111100000",
183
+ "111111111111111100010",
184
+ "11111111111111111101101",
185
+ "1111111111111111100001",
186
+ "11111111111111111101110",
187
+ "11111111111111111101111",
188
+ "11111111111111101010",
189
+ "1111111111111111100010",
190
+ "1111111111111111100011",
191
+ "1111111111111111100100",
192
+ "11111111111111111110000",
193
+ "1111111111111111100101",
194
+ "1111111111111111100110",
195
+ "11111111111111111110001",
196
+ "11111111111111111111100000",
197
+ "11111111111111111111100001",
198
+ "11111111111111101011",
199
+ "1111111111111110001",
200
+ "1111111111111111100111",
201
+ "11111111111111111110010",
202
+ "1111111111111111101000",
203
+ "1111111111111111111101100",
204
+ "11111111111111111111100010",
205
+ "11111111111111111111100011",
206
+ "11111111111111111111100100",
207
+ "111111111111111111111011110",
208
+ "111111111111111111111011111",
209
+ "11111111111111111111100101",
210
+ "111111111111111111110001",
211
+ "1111111111111111111101101",
212
+ "1111111111111110010",
213
+ "111111111111111100011",
214
+ "11111111111111111111100110",
215
+ "111111111111111111111100000",
216
+ "111111111111111111111100001",
217
+ "11111111111111111111100111",
218
+ "111111111111111111111100010",
219
+ "111111111111111111110010",
220
+ "111111111111111100100",
221
+ "111111111111111100101",
222
+ "11111111111111111111101000",
223
+ "11111111111111111111101001",
224
+ "1111111111111111111111111101",
225
+ "111111111111111111111100011",
226
+ "111111111111111111111100100",
227
+ "111111111111111111111100101",
228
+ "11111111111111101100",
229
+ "111111111111111111110011",
230
+ "11111111111111101101",
231
+ "111111111111111100110",
232
+ "1111111111111111101001",
233
+ "111111111111111100111",
234
+ "111111111111111101000",
235
+ "11111111111111111110011",
236
+ "1111111111111111101010",
237
+ "1111111111111111101011",
238
+ "1111111111111111111101110",
239
+ "1111111111111111111101111",
240
+ "111111111111111111110100",
241
+ "111111111111111111110101",
242
+ "11111111111111111111101010",
243
+ "11111111111111111110100",
244
+ "11111111111111111111101011",
245
+ "111111111111111111111100110",
246
+ "11111111111111111111101100",
247
+ "11111111111111111111101101",
248
+ "111111111111111111111100111",
249
+ "111111111111111111111101000",
250
+ "111111111111111111111101001",
251
+ "111111111111111111111101010",
252
+ "111111111111111111111101011",
253
+ "1111111111111111111111111110",
254
+ "111111111111111111111101100",
255
+ "111111111111111111111101101",
256
+ "111111111111111111111101110",
257
+ "111111111111111111111101111",
258
+ "111111111111111111111110000",
259
+ "11111111111111111111101110",
260
+ "111111111111111111111111111111" # EOS
261
+ ]
262
+
263
+ def initialize
264
+ @root = {}
265
+ HUFFMAN.each_with_index do |code, terminal|
266
+ load_terminal code, terminal
267
+ end
268
+ end
269
+
270
+ def load_terminal code, terminal
271
+ node = @root
272
+
273
+ code.each_char do |bit_sym|
274
+ bit = bit_sym.to_i
275
+ unless node.include? bit
276
+ node[bit] = {}
277
+ end
278
+
279
+ node = node[bit]
280
+ end
281
+
282
+ node[:value] = terminal
283
+ end
284
+
285
+ def decode input: nil, length: 0
286
+ node = @root
287
+
288
+ decode_bits input, length do |bit|
289
+ node = node[bit]
290
+
291
+ next nil unless node.include? :value
292
+
293
+ char = node[:value]
294
+ node = @root
295
+ char
296
+ end
297
+ end
298
+
299
+ def decode_bits input, length
300
+ data = ""
301
+ padding = []
302
+
303
+ length.times do |i|
304
+ byte = input.readbyte
305
+
306
+ 8.times do
307
+ bit = (byte & 0b1000_0000 == 0) && 0 || 1
308
+ char = yield bit
309
+
310
+ if char
311
+ data << char
312
+ padding = []
313
+ else
314
+ padding << bit
315
+ end
316
+
317
+ byte <<= 1
318
+ end
319
+ end
320
+
321
+ # TODO: padding check
322
+
323
+ data
324
+ end
325
+ end
326
+ end