bayserver-docker-http 3.0.3 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/baykit/bayserver/docker/http/h1/h1_inbound_handler.rb +3 -3
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_continuation.rb +58 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_headers.rb +14 -26
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_preface.rb +1 -1
- data/lib/baykit/bayserver/docker/http/h2/command/package.rb +1 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_command_handler.rb +4 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_command_unpacker.rb +3 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_inbound_handler.rb +145 -81
- data/lib/baykit/bayserver/docker/http/h2/h2_packet.rb +11 -109
- data/lib/baykit/bayserver/docker/http/h2/header_block.rb +0 -159
- data/lib/baykit/bayserver/docker/http/h2/header_block_parser.rb +240 -0
- data/lib/baykit/bayserver/docker/http/h2/header_block_renderer.rb +101 -0
- data/lib/baykit/bayserver/docker/http/h2/package.rb +2 -0
- data/lib/baykit/bayserver/docker/http/htp_docker.rb +0 -1
- data/lib/baykit/bayserver/docker/http/htp_port_docker.rb +0 -2
- data/lib/baykit/bayserver/docker/http/htp_warp_docker.rb +0 -2
- metadata +11 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a4d46496d23a37a8c5bc5f5852b379d0a901f5599aaaa502d949646c134e921
|
|
4
|
+
data.tar.gz: b44a1b58fe21107515516a280654801e24f6cde5f7130b089f4c5d4882377259
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f66955666f1fce85453badd1b76db78a3d3982c0a238e7a3c42c7acfdc8b2ec9420de309031212fa479b47dde6da288faacdafacbde87fb8ea4313a4ff13779d
|
|
7
|
+
data.tar.gz: f304c2c88516c98712406769238d4c261bb637fc21d1d88b9f6d6701c20de967f4def4e1af3f6793015d6d7ac8e78d3a050dbb35db6bea7ab4eb413305238ccf
|
|
@@ -99,13 +99,13 @@ module Baykit
|
|
|
99
99
|
def send_res_headers(tur)
|
|
100
100
|
|
|
101
101
|
# determine Connection header value
|
|
102
|
-
if tur.req.headers.get_connection() != Headers::CONNECTION_KEEP_ALIVE
|
|
102
|
+
if tur.req.headers.get_connection() != Headers::CONNECTION_KEEP_ALIVE && tur.req.headers.get_connection() != Headers::CONNECTION_UNKNOWN
|
|
103
103
|
# If client doesn't support "Keep-Alive", set "Close"
|
|
104
104
|
res_con = "Close"
|
|
105
105
|
else
|
|
106
106
|
res_con = "Keep-Alive"
|
|
107
107
|
# Client supports "Keep-Alive"
|
|
108
|
-
if tur.res.headers.get_connection() != Headers::CONNECTION_KEEP_ALIVE
|
|
108
|
+
if tur.res.headers.get_connection() != Headers::CONNECTION_KEEP_ALIVE && tur.res.headers.get_connection() != Headers::CONNECTION_UNKNOWN
|
|
109
109
|
# If tours doesn't need "Keep-Alive"
|
|
110
110
|
if tur.res.headers.content_length() == -1
|
|
111
111
|
# If content-length not specified
|
|
@@ -175,7 +175,7 @@ module Baykit
|
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus::BAD_REQUEST, err.message, err)
|
|
178
|
-
|
|
178
|
+
false
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
######################################################
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'baykit/bayserver/docker/http/h2/package'
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# HTTP/2 Continuation payload format
|
|
5
|
+
#
|
|
6
|
+
# +---------------------------------------------------------------+
|
|
7
|
+
# | Header Block Fragment (*) ...
|
|
8
|
+
# +---------------------------------------------------------------+
|
|
9
|
+
#
|
|
10
|
+
module Baykit
|
|
11
|
+
module BayServer
|
|
12
|
+
module Docker
|
|
13
|
+
module Http
|
|
14
|
+
module H2
|
|
15
|
+
module Command
|
|
16
|
+
|
|
17
|
+
class CmdContinuation < Baykit::BayServer::Docker::Http::H2::H2Command
|
|
18
|
+
include Baykit::BayServer::Docker::Http::H2
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# This class refers external byte array, so this IS NOT mutable
|
|
22
|
+
#
|
|
23
|
+
attr :start
|
|
24
|
+
attr :length
|
|
25
|
+
attr :data
|
|
26
|
+
|
|
27
|
+
def initialize(stream_id, flags = nil)
|
|
28
|
+
super(H2Type::CONTINUATION, stream_id, flags)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def unpack(pkt)
|
|
32
|
+
super
|
|
33
|
+
@data = pkt.buf
|
|
34
|
+
@start = pkt.header_len
|
|
35
|
+
@length = pkt.data_len()
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def pack(pkt)
|
|
39
|
+
acc = pkt.new_data_accessor()
|
|
40
|
+
if @flags.padded?
|
|
41
|
+
raise RuntimeError.new("Padding not supported")
|
|
42
|
+
end
|
|
43
|
+
acc.put_bytes(@data, @start, @length)
|
|
44
|
+
super
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def handle(cmd_handler)
|
|
48
|
+
return cmd_handler.handle_continuation(self)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
@@ -25,6 +25,13 @@ module Baykit
|
|
|
25
25
|
class CmdHeaders < Baykit::BayServer::Docker::Http::H2::H2Command
|
|
26
26
|
include Baykit::BayServer::Docker::Http::H2
|
|
27
27
|
|
|
28
|
+
#
|
|
29
|
+
# This class refers external byte array, so this IS NOT mutable
|
|
30
|
+
#
|
|
31
|
+
attr_accessor :start
|
|
32
|
+
attr_accessor :length
|
|
33
|
+
attr_accessor :data
|
|
34
|
+
|
|
28
35
|
attr :pad_length
|
|
29
36
|
attr_accessor :excluded
|
|
30
37
|
attr :stream_dependency
|
|
@@ -42,7 +49,7 @@ module Baykit
|
|
|
42
49
|
|
|
43
50
|
def unpack(pkt)
|
|
44
51
|
super
|
|
45
|
-
acc = pkt.
|
|
52
|
+
acc = pkt.new_data_accessor
|
|
46
53
|
|
|
47
54
|
if pkt.flags.padded?
|
|
48
55
|
@pad_length = acc.get_byte
|
|
@@ -53,11 +60,13 @@ module Baykit
|
|
|
53
60
|
@stream_dependency = H2Packet.extract_int31(val)
|
|
54
61
|
@weight = acc.get_byte
|
|
55
62
|
end
|
|
56
|
-
|
|
63
|
+
@data = pkt.buf
|
|
64
|
+
@start = pkt.header_len + acc.pos
|
|
65
|
+
@length = pkt.data_len - acc.pos
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
def pack(pkt)
|
|
60
|
-
acc = pkt.
|
|
69
|
+
acc = pkt.new_data_accessor
|
|
61
70
|
|
|
62
71
|
if @flags.padded?
|
|
63
72
|
acc.put_byte(@pad_length)
|
|
@@ -67,7 +76,8 @@ module Baykit
|
|
|
67
76
|
acc.put_int(H2Packet.make_stream_dependency32(@excluded, @stream_dependency))
|
|
68
77
|
acc.put_byte(@weight)
|
|
69
78
|
end
|
|
70
|
-
|
|
79
|
+
|
|
80
|
+
acc.put_bytes(@data, @start, @length)
|
|
71
81
|
super
|
|
72
82
|
end
|
|
73
83
|
|
|
@@ -75,28 +85,6 @@ module Baykit
|
|
|
75
85
|
return cmd_handler.handle_headers(self)
|
|
76
86
|
end
|
|
77
87
|
|
|
78
|
-
def read_header_block(acc, len)
|
|
79
|
-
while acc.pos < len
|
|
80
|
-
blk = HeaderBlock.unpack(acc)
|
|
81
|
-
#if(BayLog.trace_mode?)
|
|
82
|
-
# BayLog.trace "h2: Read header block: #{blk}"
|
|
83
|
-
#end
|
|
84
|
-
@header_blocks << blk
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def write_header_block(acc)
|
|
89
|
-
@header_blocks.each do |blk|
|
|
90
|
-
#if(BayLog.trace_mode?)
|
|
91
|
-
# BayLog.trace "h2: Write header block: #{blk}"
|
|
92
|
-
#end
|
|
93
|
-
HeaderBlock.pack(blk, acc)
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def add_header_block(blk)
|
|
98
|
-
@header_blocks.append(blk)
|
|
99
|
-
end
|
|
100
88
|
end
|
|
101
89
|
end
|
|
102
90
|
end
|
|
@@ -7,3 +7,4 @@ require 'baykit/bayserver/docker/http/h2/command/cmd_priority'
|
|
|
7
7
|
require 'baykit/bayserver/docker/http/h2/command/cmd_rst_stream'
|
|
8
8
|
require 'baykit/bayserver/docker/http/h2/command/cmd_settings'
|
|
9
9
|
require 'baykit/bayserver/docker/http/h2/command/cmd_window_update'
|
|
10
|
+
require 'baykit/bayserver/docker/http/h2/command/cmd_continuation'
|
|
@@ -45,7 +45,6 @@ module Baykit
|
|
|
45
45
|
|
|
46
46
|
include Baykit::BayServer::Agent
|
|
47
47
|
include Baykit::BayServer::Protocol
|
|
48
|
-
include Baykit::BayServer::WaterCraft
|
|
49
48
|
include Baykit::BayServer::Tours
|
|
50
49
|
include Baykit::BayServer::Util
|
|
51
50
|
include Baykit::BayServer::Docker::Http::H2::Command
|
|
@@ -60,6 +59,7 @@ module Baykit
|
|
|
60
59
|
attr :http_protocol
|
|
61
60
|
attr :req_header_tbl
|
|
62
61
|
attr :res_header_tbl
|
|
62
|
+
attr :header_buffer
|
|
63
63
|
|
|
64
64
|
def initialize
|
|
65
65
|
@window_size = BayServer.harbor.tour_buffer_size
|
|
@@ -67,6 +67,7 @@ module Baykit
|
|
|
67
67
|
@analyzer = HeaderBlockAnalyzer.new
|
|
68
68
|
@req_header_tbl = HeaderTable.create_dynamic_table()
|
|
69
69
|
@res_header_tbl = HeaderTable.create_dynamic_table()
|
|
70
|
+
@header_buffer = SimpleBuffer.new
|
|
70
71
|
end
|
|
71
72
|
|
|
72
73
|
######################################################
|
|
@@ -77,6 +78,7 @@ module Baykit
|
|
|
77
78
|
@header_read = false
|
|
78
79
|
@req_cont_len = 0
|
|
79
80
|
@req_cont_read = 0
|
|
81
|
+
@header_buffer.reset
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
def init(proto_handler)
|
|
@@ -88,10 +90,12 @@ module Baykit
|
|
|
88
90
|
######################################################
|
|
89
91
|
|
|
90
92
|
def send_res_headers(tur)
|
|
91
|
-
cmd = CmdHeaders.new(tur.req.key)
|
|
92
93
|
bld = HeaderBlockBuilder.new()
|
|
94
|
+
|
|
95
|
+
header_blocks = []
|
|
96
|
+
|
|
93
97
|
blk = bld.build_header_block(":status", tur.res.headers.status.to_s, @res_header_tbl)
|
|
94
|
-
|
|
98
|
+
header_blocks << blk
|
|
95
99
|
|
|
96
100
|
# headers
|
|
97
101
|
if BayServer.harbor.trace_header
|
|
@@ -106,15 +110,46 @@ module Baykit
|
|
|
106
110
|
BayLog.info("%s H2 res header: %s=%s", tur, name, value)
|
|
107
111
|
end
|
|
108
112
|
blk = bld.build_header_block(name, value, @res_header_tbl)
|
|
109
|
-
|
|
113
|
+
header_blocks.append(blk)
|
|
110
114
|
end
|
|
111
115
|
end
|
|
112
116
|
end
|
|
113
117
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
buf = SimpleBuffer.new
|
|
119
|
+
HeaderBlockRenderer.new(buf).render_header_blocks(header_blocks)
|
|
120
|
+
|
|
121
|
+
pos = 0
|
|
122
|
+
len = buf.length
|
|
123
|
+
while len > 0
|
|
124
|
+
chunk_len = [len, H2Packet::DEFAULT_PAYLOAD_MAXLEN].min
|
|
125
|
+
|
|
126
|
+
if pos == 0
|
|
127
|
+
hcmd = CmdHeaders.new(tur.req.key)
|
|
128
|
+
hcmd.excluded = false
|
|
129
|
+
hcmd.data = buf.bytes
|
|
130
|
+
hcmd.start = pos
|
|
131
|
+
hcmd.length = len
|
|
132
|
+
cmd = hcmd
|
|
133
|
+
|
|
134
|
+
else
|
|
135
|
+
ccmd = CmdContinuation.new(tur.req.key)
|
|
136
|
+
ccmd.data = buf.bytes
|
|
137
|
+
ccmd.start = pos
|
|
138
|
+
ccmd.length = len
|
|
139
|
+
cmd = ccmd
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
cmd.flags.set_padded(false)
|
|
144
|
+
|
|
145
|
+
pos += chunk_len
|
|
146
|
+
len -= chunk_len
|
|
147
|
+
if len == 0
|
|
148
|
+
cmd.flags.set_end_headers(true)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
@protocol_handler.post(cmd)
|
|
152
|
+
end
|
|
118
153
|
end
|
|
119
154
|
|
|
120
155
|
def send_res_content(tur, bytes, ofs, len, &callback)
|
|
@@ -132,14 +167,14 @@ module Baykit
|
|
|
132
167
|
|
|
133
168
|
def on_protocol_error(err)
|
|
134
169
|
BayLog.error_e err
|
|
135
|
-
cmd = CmdGoAway.new(CTL_STREAM_ID)
|
|
136
|
-
cmd.stream_id = CTL_STREAM_ID
|
|
137
|
-
cmd.last_stream_id = CTL_STREAM_ID
|
|
170
|
+
cmd = CmdGoAway.new(H2ProtocolHandler::CTL_STREAM_ID)
|
|
171
|
+
cmd.stream_id = H2ProtocolHandler::CTL_STREAM_ID
|
|
172
|
+
cmd.last_stream_id = H2ProtocolHandler::CTL_STREAM_ID
|
|
138
173
|
cmd.error_code = H2ErrorCode::PROTOCOL_ERROR
|
|
139
174
|
cmd.debug_data = "Thank you!"
|
|
140
175
|
begin
|
|
141
176
|
@protocol_handler.post(cmd)
|
|
142
|
-
@protocol_handler.
|
|
177
|
+
@protocol_handler.ship.post_close()
|
|
143
178
|
rescue IOError => e
|
|
144
179
|
BayLog.error_e(e)
|
|
145
180
|
end
|
|
@@ -180,70 +215,14 @@ module Baykit
|
|
|
180
215
|
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus::SERVICE_UNAVAILABLE, "No available tours")
|
|
181
216
|
return NextSocketAction::CONTINUE
|
|
182
217
|
end
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if blk.op == HeaderBlock::UPDATE_DYNAMIC_TABLE_SIZE
|
|
186
|
-
BayLog.trace("%s header block update table size: %d", tur, blk.size)
|
|
187
|
-
@req_header_tbl.set_size(blk.size)
|
|
188
|
-
next
|
|
189
|
-
end
|
|
190
|
-
@analyzer.analyze_header_block(blk, @req_header_tbl)
|
|
191
|
-
if BayServer.harbor.trace_header
|
|
192
|
-
BayLog.info("%s req header: %s=%s :%s", tur, @analyzer.name, @analyzer.value, blk);
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
if @analyzer.name == nil
|
|
196
|
-
next
|
|
197
|
-
|
|
198
|
-
elsif @analyzer.name[0] != ":"
|
|
199
|
-
tur.req.headers.add(@analyzer.name, @analyzer.value)
|
|
200
|
-
|
|
201
|
-
elsif @analyzer.method != nil
|
|
202
|
-
tur.req.method = @analyzer.method
|
|
203
|
-
|
|
204
|
-
elsif @analyzer.path != nil
|
|
205
|
-
tur.req.uri = @analyzer.path
|
|
206
|
-
|
|
207
|
-
elsif @analyzer.scheme != nil
|
|
208
|
-
|
|
209
|
-
elsif @analyzer.status != nil
|
|
210
|
-
raise RuntimeError.new("Illegal State")
|
|
211
|
-
end
|
|
218
|
+
if !tur.preparing?
|
|
219
|
+
raise ProtocolException.new("%s Tour is not preparing.", tur)
|
|
212
220
|
end
|
|
213
221
|
|
|
214
222
|
if cmd.flags.end_headers?
|
|
215
|
-
tur.
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
req_cont_len = tur.req.headers.content_length()
|
|
220
|
-
|
|
221
|
-
if req_cont_len > 0
|
|
222
|
-
tur.req.set_limit(req_cont_len)
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
begin
|
|
226
|
-
start_tour tur
|
|
227
|
-
|
|
228
|
-
if tur.req.headers.content_length <= 0
|
|
229
|
-
end_req_content(Tour::TOUR_ID_NOCHECK, tur)
|
|
230
|
-
end
|
|
231
|
-
rescue HttpException => e
|
|
232
|
-
BayLog.debug("%s Http error occurred: %s", self, e);
|
|
233
|
-
if req_cont_len <= 0
|
|
234
|
-
# no post data
|
|
235
|
-
tur.req.abort
|
|
236
|
-
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
|
237
|
-
|
|
238
|
-
return NextSocketAction::CONTINUE
|
|
239
|
-
else
|
|
240
|
-
# Delay send
|
|
241
|
-
tur.error = e
|
|
242
|
-
tur.req.set_content_handler(ReqContentHandler::DEV_NULL)
|
|
243
|
-
return NextSocketAction::CONTINUE
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
|
223
|
+
return on_end_header(tur, cmd.data, cmd.start, cmd.length)
|
|
224
|
+
else
|
|
225
|
+
@header_buffer.put(cmd.data, cmd.start, cmd.length)
|
|
247
226
|
end
|
|
248
227
|
|
|
249
228
|
NextSocketAction::CONTINUE
|
|
@@ -256,8 +235,8 @@ module Baykit
|
|
|
256
235
|
if tur == nil
|
|
257
236
|
raise RuntimeError.new("Invalid stream id: #{cmd.stream_id}")
|
|
258
237
|
end
|
|
259
|
-
if tur.
|
|
260
|
-
raise ProtocolException.new("
|
|
238
|
+
if !tur.reading?
|
|
239
|
+
raise ProtocolException.new("%s Tour is not reading.", tur)
|
|
261
240
|
end
|
|
262
241
|
|
|
263
242
|
begin
|
|
@@ -388,13 +367,22 @@ module Baykit
|
|
|
388
367
|
def handle_rst_stream(cmd)
|
|
389
368
|
BayLog.warn("%s received RstStream: stmid=%d code=%d desc=%s",
|
|
390
369
|
ship, cmd.stream_id, cmd.error_code, H2ErrorCode.msg.get(cmd.error_code.to_s.to_sym))
|
|
370
|
+
return NextSocketAction::CONTINUE
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def handle_continuation(cmd)
|
|
374
|
+
BayLog.debug("%s handle_continuation: stm=%d", ship, cmd.stream_id)
|
|
391
375
|
tur = get_tour(cmd.stream_id)
|
|
392
376
|
if tur == nil
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
377
|
+
raise ArgumentError("Invalid stream id: " + cmd.stream_id)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
@header_buffer.put(cmd.data, cmd.start, cmd.length)
|
|
381
|
+
if cmd.flags.end_headers?
|
|
382
|
+
return on_end_header(tur, @header_buffer.bytes, 0, @header_buffer.length)
|
|
397
383
|
end
|
|
384
|
+
|
|
385
|
+
return NextSocketAction::CONTINUE
|
|
398
386
|
end
|
|
399
387
|
|
|
400
388
|
private
|
|
@@ -427,8 +415,15 @@ module Baykit
|
|
|
427
415
|
tur.req.remote_address = client_adr
|
|
428
416
|
tur.req.remote_port = nil
|
|
429
417
|
else
|
|
430
|
-
|
|
431
|
-
|
|
418
|
+
begin
|
|
419
|
+
remote_addr = skt.getpeername()
|
|
420
|
+
rescue SystemCallError => e
|
|
421
|
+
BayLog.debug_e(e)
|
|
422
|
+
remote_addr = nil
|
|
423
|
+
end
|
|
424
|
+
if remote_addr
|
|
425
|
+
tur.req.remote_port, tur.req.remote_address = Socket.unpack_sockaddr_in(remote_addr)
|
|
426
|
+
end
|
|
432
427
|
end
|
|
433
428
|
|
|
434
429
|
tur.req.remote_host_func = lambda { HttpUtil.resolve_remote_host(tur.req.remote_address) }
|
|
@@ -451,6 +446,75 @@ module Baykit
|
|
|
451
446
|
tur.go
|
|
452
447
|
end
|
|
453
448
|
|
|
449
|
+
def on_end_header(tur, buf, start, len)
|
|
450
|
+
|
|
451
|
+
header_blocks = HeaderBlockParser.new(buf, start, len).parse_header_blocks()
|
|
452
|
+
|
|
453
|
+
header_blocks.each do |blk|
|
|
454
|
+
if blk.op == HeaderBlock::UPDATE_DYNAMIC_TABLE_SIZE
|
|
455
|
+
BayLog.trace("%s header block update table size: %d", tur, blk.size)
|
|
456
|
+
@req_header_tbl.set_size(blk.size)
|
|
457
|
+
next
|
|
458
|
+
end
|
|
459
|
+
@analyzer.analyze_header_block(blk, @req_header_tbl)
|
|
460
|
+
if BayServer.harbor.trace_header
|
|
461
|
+
BayLog.info("%s req header: %s=%s :%s", tur, @analyzer.name, @analyzer.value, blk);
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
if @analyzer.name == nil
|
|
465
|
+
next
|
|
466
|
+
|
|
467
|
+
elsif @analyzer.name[0] != ":"
|
|
468
|
+
tur.req.headers.add(@analyzer.name, @analyzer.value)
|
|
469
|
+
|
|
470
|
+
elsif @analyzer.method != nil
|
|
471
|
+
tur.req.method = @analyzer.method
|
|
472
|
+
|
|
473
|
+
elsif @analyzer.path != nil
|
|
474
|
+
tur.req.uri = @analyzer.path
|
|
475
|
+
|
|
476
|
+
elsif @analyzer.scheme != nil
|
|
477
|
+
|
|
478
|
+
elsif @analyzer.status != nil
|
|
479
|
+
raise RuntimeError.new("Illegal State")
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
tur.req.protocol = "HTTP/2.0"
|
|
484
|
+
BayLog.debug("%s H2 read header method=%s protocol=%s uri=%s contlen=%d",
|
|
485
|
+
ship, tur.req.method, tur.req.protocol, tur.req.uri, tur.req.headers.content_length)
|
|
486
|
+
|
|
487
|
+
HttpUtil.check_uri(tur.req.uri)
|
|
488
|
+
req_cont_len = tur.req.headers.content_length
|
|
489
|
+
|
|
490
|
+
if req_cont_len > 0
|
|
491
|
+
tur.req.set_limit(req_cont_len)
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
begin
|
|
495
|
+
start_tour tur
|
|
496
|
+
|
|
497
|
+
if tur.req.headers.content_length <= 0
|
|
498
|
+
end_req_content(Tour::TOUR_ID_NOCHECK, tur)
|
|
499
|
+
end
|
|
500
|
+
rescue HttpException => e
|
|
501
|
+
BayLog.debug("%s Http error occurred: %s", self, e);
|
|
502
|
+
if req_cont_len <= 0
|
|
503
|
+
# no post data
|
|
504
|
+
tur.req.abort
|
|
505
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
|
506
|
+
|
|
507
|
+
return NextSocketAction::CONTINUE
|
|
508
|
+
else
|
|
509
|
+
# Delay send
|
|
510
|
+
tur.error = e
|
|
511
|
+
tur.req.set_content_handler(ReqContentHandler::DEV_NULL)
|
|
512
|
+
return NextSocketAction::CONTINUE
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
return NextSocketAction::CONTINUE
|
|
517
|
+
end
|
|
454
518
|
end
|
|
455
519
|
end
|
|
456
520
|
end
|
|
@@ -26,105 +26,6 @@ module Baykit
|
|
|
26
26
|
include Baykit::BayServer::Protocol
|
|
27
27
|
include Baykit::BayServer::Docker::Http::H2
|
|
28
28
|
|
|
29
|
-
class H2HeaderAccessor < PacketPartAccessor
|
|
30
|
-
def initialize(pkt, start, max_len)
|
|
31
|
-
super
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def put_int24(len)
|
|
35
|
-
b1 = (len >> 16) & 0xFF
|
|
36
|
-
b2 = (len >> 8) & 0xFF
|
|
37
|
-
b3 = len & 0xFF
|
|
38
|
-
buf = StringUtil.alloc(3)
|
|
39
|
-
buf << b1 << b2 << b3
|
|
40
|
-
put_bytes buf
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
class H2DataAccessor < PacketPartAccessor
|
|
45
|
-
include Baykit::BayServer::Docker::Http::H2::Huffman
|
|
46
|
-
|
|
47
|
-
def initialize(pkt, start, max_len)
|
|
48
|
-
super
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def get_hpack_int(prefix, head)
|
|
52
|
-
max_val = 0xFF >> (8 - prefix)
|
|
53
|
-
|
|
54
|
-
first_byte = get_byte
|
|
55
|
-
first_val = first_byte & max_val
|
|
56
|
-
head[0] = first_byte >> prefix
|
|
57
|
-
if first_val != max_val
|
|
58
|
-
first_val
|
|
59
|
-
else
|
|
60
|
-
max_val + get_hpack_int_rest
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def get_hpack_int_rest
|
|
65
|
-
rest = 0
|
|
66
|
-
i = 0
|
|
67
|
-
while true
|
|
68
|
-
data = get_byte
|
|
69
|
-
cont = (data & 0x80) != 0
|
|
70
|
-
value = data & 0x7F
|
|
71
|
-
rest = rest + (value << (i*7))
|
|
72
|
-
if !cont
|
|
73
|
-
break
|
|
74
|
-
end
|
|
75
|
-
i += 1
|
|
76
|
-
end
|
|
77
|
-
return rest
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def get_hpack_string
|
|
81
|
-
is_huffman = [nil]
|
|
82
|
-
len = get_hpack_int(7, is_huffman)
|
|
83
|
-
data = StringUtil.alloc(len)
|
|
84
|
-
get_bytes data, 0, len
|
|
85
|
-
if is_huffman[0] == 1
|
|
86
|
-
return HTree.decode(data)
|
|
87
|
-
else
|
|
88
|
-
# ASCII
|
|
89
|
-
return data
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def put_hpack_int(val, prefix, head)
|
|
94
|
-
max_val = 0xFF >> (8 -prefix)
|
|
95
|
-
head_val = (head << prefix) & 0xFF
|
|
96
|
-
if val < max_val
|
|
97
|
-
put_byte (val | head_val)
|
|
98
|
-
else
|
|
99
|
-
put_byte (head_val | max_val)
|
|
100
|
-
put_hpack_int_rest(val - max_val)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def put_hpack_int_rest(val)
|
|
105
|
-
while true
|
|
106
|
-
data = val & 0x7F
|
|
107
|
-
next_val = val >> 7
|
|
108
|
-
if next_val == 0
|
|
109
|
-
put_byte(data)
|
|
110
|
-
break
|
|
111
|
-
else
|
|
112
|
-
put_byte(data | 0x80)
|
|
113
|
-
val = next_val
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def put_hpack_string(value, is_haffman)
|
|
119
|
-
if is_haffman
|
|
120
|
-
raise RuntimeError.new "Illegal State"
|
|
121
|
-
else
|
|
122
|
-
put_hpack_int(value.length, 7, 0)
|
|
123
|
-
put_bytes(value)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
29
|
MAX_PAYLOAD_LEN = 0x00FFFFFF # = 2^24-1 = 16777215 = 16MB-1
|
|
129
30
|
DEFAULT_PAYLOAD_MAXLEN = 0x00004000 # = 2^14 = 16384 = 16KB
|
|
130
31
|
FRAME_HEADER_LEN = 9
|
|
@@ -160,21 +61,13 @@ module Baykit
|
|
|
160
61
|
end
|
|
161
62
|
|
|
162
63
|
def pack_header
|
|
163
|
-
acc =
|
|
164
|
-
|
|
64
|
+
acc = new_header_accessor
|
|
65
|
+
put_int24(acc, data_len)
|
|
165
66
|
acc.put_byte(@type)
|
|
166
67
|
acc.put_byte(@flags.flags)
|
|
167
68
|
acc.put_int(H2Packet.extract_int31(stream_id))
|
|
168
69
|
end
|
|
169
70
|
|
|
170
|
-
def new_h2_header_accessor
|
|
171
|
-
H2HeaderAccessor.new(self, 0, @header_len)
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def new_h2_data_accessor
|
|
175
|
-
H2DataAccessor.new(self, @header_len, -1)
|
|
176
|
-
end
|
|
177
|
-
|
|
178
71
|
def self.extract_int31(val)
|
|
179
72
|
val & 0x7FFFFFFF
|
|
180
73
|
end
|
|
@@ -191,6 +84,15 @@ module Baykit
|
|
|
191
84
|
(excluded ? 1 : 0) << 31 | extract_int31(dep)
|
|
192
85
|
end
|
|
193
86
|
|
|
87
|
+
def put_int24(acc, len)
|
|
88
|
+
b1 = (len >> 16) & 0xFF
|
|
89
|
+
b2 = (len >> 8) & 0xFF
|
|
90
|
+
b3 = len & 0xFF
|
|
91
|
+
buf = StringUtil.alloc(3)
|
|
92
|
+
buf << b1 << b2 << b3
|
|
93
|
+
acc.put_bytes buf
|
|
94
|
+
end
|
|
95
|
+
|
|
194
96
|
def to_s
|
|
195
97
|
"H2Packet(#{@type}) headerLen=#{@header_len} dataLen=#{data_len()} stm=#{@stream_id} flags=#{@flags}"
|
|
196
98
|
end
|
|
@@ -18,165 +18,6 @@ module Baykit
|
|
|
18
18
|
attr_accessor :value
|
|
19
19
|
attr_accessor :size
|
|
20
20
|
|
|
21
|
-
def self.pack(blk, acc)
|
|
22
|
-
case blk.op
|
|
23
|
-
when INDEX
|
|
24
|
-
acc.put_hpack_int(blk.index, 7, 1)
|
|
25
|
-
|
|
26
|
-
when OVERLOAD_KNOWN_HEADER
|
|
27
|
-
raise RuntimeError.new("IllegalState")
|
|
28
|
-
|
|
29
|
-
when NEW_HEADER
|
|
30
|
-
raise RuntimeError.new("Illegal State")
|
|
31
|
-
|
|
32
|
-
when KNOWN_HEADER
|
|
33
|
-
acc.put_hpack_int(blk.index, 4, 0)
|
|
34
|
-
acc.put_hpack_string(blk.value, false)
|
|
35
|
-
|
|
36
|
-
when UNKNOWN_HEADER
|
|
37
|
-
acc.put_byte(0)
|
|
38
|
-
acc.put_hpack_string(blk.name, false)
|
|
39
|
-
acc.put_hpack_string(blk.value, false)
|
|
40
|
-
|
|
41
|
-
when UPDATE_DYNAMIC_TABLE_SIZE
|
|
42
|
-
raise RuntimeError.new("Illegal state")
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def self.unpack(acc)
|
|
48
|
-
blk = HeaderBlock.new
|
|
49
|
-
index = acc.get_byte
|
|
50
|
-
is_index_header_field = (index & 0x80) != 0
|
|
51
|
-
if is_index_header_field
|
|
52
|
-
# index header field
|
|
53
|
-
# 0 1 2 3 4 5 6 7
|
|
54
|
-
# +---+---+---+---+---+---+---+---+
|
|
55
|
-
# | 1 | Index (7+) |
|
|
56
|
-
# +---+---------------------------+
|
|
57
|
-
blk.op = INDEX
|
|
58
|
-
blk.index = index & 0x7F
|
|
59
|
-
else
|
|
60
|
-
# literal header field
|
|
61
|
-
update_index = (index & 0x40) != 0
|
|
62
|
-
if update_index
|
|
63
|
-
index = index & 0x3F
|
|
64
|
-
overload_index = (index != 0)
|
|
65
|
-
if overload_index
|
|
66
|
-
if index == 0x3F
|
|
67
|
-
index = index + acc.get_hpack_int_rest
|
|
68
|
-
end
|
|
69
|
-
blk.op = OVERLOAD_KNOWN_HEADER
|
|
70
|
-
blk.index = index
|
|
71
|
-
# 0 1 2 3 4 5 6 7
|
|
72
|
-
# +---+---+---+---+---+---+---+---+
|
|
73
|
-
# | 0 | 1 | Index (6+) |
|
|
74
|
-
# +---+---+-----------------------+
|
|
75
|
-
# | H | Value Length (7+) |
|
|
76
|
-
# +---+---------------------------+
|
|
77
|
-
# | Value String (Length octets) |
|
|
78
|
-
# +-------------------------------+
|
|
79
|
-
blk.value = acc.get_hpack_string
|
|
80
|
-
else
|
|
81
|
-
# new header name
|
|
82
|
-
# 0 1 2 3 4 5 6 7
|
|
83
|
-
# +---+---+---+---+---+---+---+---+
|
|
84
|
-
# | 0 | 1 | 0 |
|
|
85
|
-
# +---+---+-----------------------+
|
|
86
|
-
# | H | Name Length (7+) |
|
|
87
|
-
# +---+---------------------------+
|
|
88
|
-
# | Name String (Length octets) |
|
|
89
|
-
# +---+---------------------------+
|
|
90
|
-
# | H | Value Length (7+) |
|
|
91
|
-
# +---+---------------------------+
|
|
92
|
-
# | Value String (Length octets) |
|
|
93
|
-
# +-------------------------------+
|
|
94
|
-
blk.op = NEW_HEADER
|
|
95
|
-
blk.name = acc.get_hpack_string
|
|
96
|
-
blk.value = acc.get_hpack_string
|
|
97
|
-
end
|
|
98
|
-
else
|
|
99
|
-
update_dynamic_table_size = (index & 0x20) != 0
|
|
100
|
-
if update_dynamic_table_size
|
|
101
|
-
# 0 1 2 3 4 5 6 7
|
|
102
|
-
# +---+---+---+---+---+---+---+---+
|
|
103
|
-
# | 0 | 0 | 1 | Max size (5+) |
|
|
104
|
-
# +---+---------------------------+
|
|
105
|
-
size = index & 0x1F
|
|
106
|
-
if size == 0x1F
|
|
107
|
-
size = size + acc.get_hpack_int_rest
|
|
108
|
-
end
|
|
109
|
-
blk.op = UPDATE_DYNAMIC_TABLE_SIZE
|
|
110
|
-
blk.size = size
|
|
111
|
-
else
|
|
112
|
-
# not update index
|
|
113
|
-
index = (index & 0xF)
|
|
114
|
-
if index != 0
|
|
115
|
-
# 0 1 2 3 4 5 6 7
|
|
116
|
-
# +---+---+---+---+---+---+---+---+
|
|
117
|
-
# | 0 | 0 | 0 | 0 | Index (4+) |
|
|
118
|
-
# +---+---+-----------------------+
|
|
119
|
-
# | H | Value Length (7+) |
|
|
120
|
-
# +---+---------------------------+
|
|
121
|
-
# | Value String (Length octets) |
|
|
122
|
-
# +-------------------------------+
|
|
123
|
-
#
|
|
124
|
-
# OR
|
|
125
|
-
#
|
|
126
|
-
# 0 1 2 3 4 5 6 7
|
|
127
|
-
# +---+---+---+---+---+---+---+---+
|
|
128
|
-
# | 0 | 0 | 0 | 1 | Index (4+) |
|
|
129
|
-
# +---+---+-----------------------+
|
|
130
|
-
# | H | Value Length (7+) |
|
|
131
|
-
# +---+---------------------------+
|
|
132
|
-
# | Value String (Length octets) |
|
|
133
|
-
# +-------------------------------+
|
|
134
|
-
if index == 0xF
|
|
135
|
-
index = index + acc.get_hpack_int_rest
|
|
136
|
-
end
|
|
137
|
-
blk.op = KNOWN_HEADER
|
|
138
|
-
blk.index = index
|
|
139
|
-
blk.value = acc.get_hpack_string
|
|
140
|
-
else
|
|
141
|
-
# literal header field
|
|
142
|
-
# 0 1 2 3 4 5 6 7
|
|
143
|
-
# +---+---+---+---+---+---+---+---+
|
|
144
|
-
# | 0 | 0 | 0 | 0 | 0 |
|
|
145
|
-
# +---+---+-----------------------+
|
|
146
|
-
# | H | Name Length (7+) |
|
|
147
|
-
# +---+---------------------------+
|
|
148
|
-
# | Name String (Length octets) |
|
|
149
|
-
# +---+---------------------------+
|
|
150
|
-
# | H | Value Length (7+) |
|
|
151
|
-
# +---+---------------------------+
|
|
152
|
-
# | Value String (Length octets) |
|
|
153
|
-
# +-------------------------------+
|
|
154
|
-
#
|
|
155
|
-
# OR
|
|
156
|
-
#
|
|
157
|
-
# 0 1 2 3 4 5 6 7
|
|
158
|
-
# +---+---+---+---+---+---+---+---+
|
|
159
|
-
# | 0 | 0 | 0 | 1 | 0 |
|
|
160
|
-
# +---+---+-----------------------+
|
|
161
|
-
# | H | Name Length (7+) |
|
|
162
|
-
# +---+---------------------------+
|
|
163
|
-
# | Name String (Length octets) |
|
|
164
|
-
# +---+---------------------------+
|
|
165
|
-
# | H | Value Length (7+) |
|
|
166
|
-
# +---+---------------------------+
|
|
167
|
-
# | Value String (Length octets) |
|
|
168
|
-
# +-------------------------------+
|
|
169
|
-
#
|
|
170
|
-
blk.op = UNKNOWN_HEADER
|
|
171
|
-
blk.name = acc.get_hpack_string
|
|
172
|
-
blk.value = acc.get_hpack_string
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
blk
|
|
179
|
-
end
|
|
180
21
|
|
|
181
22
|
def to_s
|
|
182
23
|
"#{op} index=#{index} name=#{name} value=#{value}"
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
require 'baykit/bayserver/docker/http/h2/header_block'
|
|
2
|
+
require 'baykit/bayserver/docker/http/h2/huffman/htree'
|
|
3
|
+
require 'baykit/bayserver/util/string_util'
|
|
4
|
+
|
|
5
|
+
module Baykit
|
|
6
|
+
module BayServer
|
|
7
|
+
module Docker
|
|
8
|
+
module Http
|
|
9
|
+
module H2
|
|
10
|
+
class HeaderBlockParser
|
|
11
|
+
|
|
12
|
+
include Baykit::BayServer::Util
|
|
13
|
+
include Baykit::BayServer::Docker::Http::H2::Huffman
|
|
14
|
+
|
|
15
|
+
attr :buf
|
|
16
|
+
attr :start
|
|
17
|
+
attr :pos
|
|
18
|
+
attr :length
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def initialize(buf, start, length)
|
|
22
|
+
@buf = buf
|
|
23
|
+
@start = start
|
|
24
|
+
@pos = 0
|
|
25
|
+
@length = length
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def parse_header_blocks
|
|
29
|
+
|
|
30
|
+
header_blocks = []
|
|
31
|
+
|
|
32
|
+
while @pos < @length
|
|
33
|
+
blk = parse_header_block()
|
|
34
|
+
BayLog.trace("h2: header block read: %s", blk)
|
|
35
|
+
header_blocks << blk
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return header_blocks
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
def parse_header_block()
|
|
44
|
+
blk = HeaderBlock.new
|
|
45
|
+
index = get_byte
|
|
46
|
+
is_index_header_field = (index & 0x80) != 0
|
|
47
|
+
if is_index_header_field
|
|
48
|
+
# index header field
|
|
49
|
+
# 0 1 2 3 4 5 6 7
|
|
50
|
+
# +---+---+---+---+---+---+---+---+
|
|
51
|
+
# | 1 | Index (7+) |
|
|
52
|
+
# +---+---------------------------+
|
|
53
|
+
blk.op = HeaderBlock::INDEX
|
|
54
|
+
blk.index = index & 0x7F
|
|
55
|
+
else
|
|
56
|
+
# literal header field
|
|
57
|
+
update_index = (index & 0x40) != 0
|
|
58
|
+
if update_index
|
|
59
|
+
index = index & 0x3F
|
|
60
|
+
overload_index = (index != 0)
|
|
61
|
+
if overload_index
|
|
62
|
+
if index == 0x3F
|
|
63
|
+
index = index + get_hpack_int_rest
|
|
64
|
+
end
|
|
65
|
+
blk.op = HeaderBlock::OVERLOAD_KNOWN_HEADER
|
|
66
|
+
blk.index = index
|
|
67
|
+
# 0 1 2 3 4 5 6 7
|
|
68
|
+
# +---+---+---+---+---+---+---+---+
|
|
69
|
+
# | 0 | 1 | Index (6+) |
|
|
70
|
+
# +---+---+-----------------------+
|
|
71
|
+
# | H | Value Length (7+) |
|
|
72
|
+
# +---+---------------------------+
|
|
73
|
+
# | Value String (Length octets) |
|
|
74
|
+
# +-------------------------------+
|
|
75
|
+
blk.value = get_hpack_string
|
|
76
|
+
else
|
|
77
|
+
# new header name
|
|
78
|
+
# 0 1 2 3 4 5 6 7
|
|
79
|
+
# +---+---+---+---+---+---+---+---+
|
|
80
|
+
# | 0 | 1 | 0 |
|
|
81
|
+
# +---+---+-----------------------+
|
|
82
|
+
# | H | Name Length (7+) |
|
|
83
|
+
# +---+---------------------------+
|
|
84
|
+
# | Name String (Length octets) |
|
|
85
|
+
# +---+---------------------------+
|
|
86
|
+
# | H | Value Length (7+) |
|
|
87
|
+
# +---+---------------------------+
|
|
88
|
+
# | Value String (Length octets) |
|
|
89
|
+
# +-------------------------------+
|
|
90
|
+
blk.op = HeaderBlock::NEW_HEADER
|
|
91
|
+
blk.name = get_hpack_string
|
|
92
|
+
blk.value = get_hpack_string
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
update_dynamic_table_size = (index & 0x20) != 0
|
|
96
|
+
if update_dynamic_table_size
|
|
97
|
+
# 0 1 2 3 4 5 6 7
|
|
98
|
+
# +---+---+---+---+---+---+---+---+
|
|
99
|
+
# | 0 | 0 | 1 | Max size (5+) |
|
|
100
|
+
# +---+---------------------------+
|
|
101
|
+
size = index & 0x1F
|
|
102
|
+
if size == 0x1F
|
|
103
|
+
size = size + get_hpack_int_rest
|
|
104
|
+
end
|
|
105
|
+
blk.op = HeaderBlock::UPDATE_DYNAMIC_TABLE_SIZE
|
|
106
|
+
blk.size = size
|
|
107
|
+
else
|
|
108
|
+
# not update index
|
|
109
|
+
index = (index & 0xF)
|
|
110
|
+
if index != 0
|
|
111
|
+
# 0 1 2 3 4 5 6 7
|
|
112
|
+
# +---+---+---+---+---+---+---+---+
|
|
113
|
+
# | 0 | 0 | 0 | 0 | Index (4+) |
|
|
114
|
+
# +---+---+-----------------------+
|
|
115
|
+
# | H | Value Length (7+) |
|
|
116
|
+
# +---+---------------------------+
|
|
117
|
+
# | Value String (Length octets) |
|
|
118
|
+
# +-------------------------------+
|
|
119
|
+
#
|
|
120
|
+
# OR
|
|
121
|
+
#
|
|
122
|
+
# 0 1 2 3 4 5 6 7
|
|
123
|
+
# +---+---+---+---+---+---+---+---+
|
|
124
|
+
# | 0 | 0 | 0 | 1 | Index (4+) |
|
|
125
|
+
# +---+---+-----------------------+
|
|
126
|
+
# | H | Value Length (7+) |
|
|
127
|
+
# +---+---------------------------+
|
|
128
|
+
# | Value String (Length octets) |
|
|
129
|
+
# +-------------------------------+
|
|
130
|
+
if index == 0xF
|
|
131
|
+
index = index + get_hpack_int_rest
|
|
132
|
+
end
|
|
133
|
+
blk.op = HeaderBlock::KNOWN_HEADER
|
|
134
|
+
blk.index = index
|
|
135
|
+
blk.value = get_hpack_string
|
|
136
|
+
else
|
|
137
|
+
# literal header field
|
|
138
|
+
# 0 1 2 3 4 5 6 7
|
|
139
|
+
# +---+---+---+---+---+---+---+---+
|
|
140
|
+
# | 0 | 0 | 0 | 0 | 0 |
|
|
141
|
+
# +---+---+-----------------------+
|
|
142
|
+
# | H | Name Length (7+) |
|
|
143
|
+
# +---+---------------------------+
|
|
144
|
+
# | Name String (Length octets) |
|
|
145
|
+
# +---+---------------------------+
|
|
146
|
+
# | H | Value Length (7+) |
|
|
147
|
+
# +---+---------------------------+
|
|
148
|
+
# | Value String (Length octets) |
|
|
149
|
+
# +-------------------------------+
|
|
150
|
+
#
|
|
151
|
+
# OR
|
|
152
|
+
#
|
|
153
|
+
# 0 1 2 3 4 5 6 7
|
|
154
|
+
# +---+---+---+---+---+---+---+---+
|
|
155
|
+
# | 0 | 0 | 0 | 1 | 0 |
|
|
156
|
+
# +---+---+-----------------------+
|
|
157
|
+
# | H | Name Length (7+) |
|
|
158
|
+
# +---+---------------------------+
|
|
159
|
+
# | Name String (Length octets) |
|
|
160
|
+
# +---+---------------------------+
|
|
161
|
+
# | H | Value Length (7+) |
|
|
162
|
+
# +---+---------------------------+
|
|
163
|
+
# | Value String (Length octets) |
|
|
164
|
+
# +-------------------------------+
|
|
165
|
+
#
|
|
166
|
+
blk.op = HeaderBlock::UNKNOWN_HEADER
|
|
167
|
+
blk.name = get_hpack_string
|
|
168
|
+
blk.value = get_hpack_string
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
blk
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def get_hpack_int(prefix, head)
|
|
178
|
+
max_val = 0xFF >> (8 - prefix)
|
|
179
|
+
|
|
180
|
+
first_byte = get_byte
|
|
181
|
+
first_val = first_byte & max_val
|
|
182
|
+
head[0] = first_byte >> prefix
|
|
183
|
+
if first_val != max_val
|
|
184
|
+
first_val
|
|
185
|
+
else
|
|
186
|
+
max_val + get_hpack_int_rest
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def get_hpack_int_rest
|
|
191
|
+
rest = 0
|
|
192
|
+
i = 0
|
|
193
|
+
while true
|
|
194
|
+
data = get_byte
|
|
195
|
+
cont = (data & 0x80) != 0
|
|
196
|
+
value = data & 0x7F
|
|
197
|
+
rest = rest + (value << (i*7))
|
|
198
|
+
if !cont
|
|
199
|
+
break
|
|
200
|
+
end
|
|
201
|
+
i += 1
|
|
202
|
+
end
|
|
203
|
+
return rest
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def get_hpack_string
|
|
207
|
+
is_huffman = [nil]
|
|
208
|
+
len = get_hpack_int(7, is_huffman)
|
|
209
|
+
data = StringUtil.alloc(len)
|
|
210
|
+
get_bytes data, len
|
|
211
|
+
if is_huffman[0] == 1
|
|
212
|
+
return HTree.decode(data)
|
|
213
|
+
else
|
|
214
|
+
# ASCII
|
|
215
|
+
return data
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def get_byte
|
|
220
|
+
if @pos >= @length
|
|
221
|
+
raise ArgumentError.new("@pos=#{@pos} @len=#{@length}")
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
b = @buf[@start + @pos].ord & 0xff
|
|
225
|
+
@pos += 1
|
|
226
|
+
return b
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def get_bytes(buf, len)
|
|
230
|
+
buf.replace(@buf[@start + @pos, len])
|
|
231
|
+
@pos += len
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'baykit/bayserver/docker/http/h2/header_block'
|
|
2
|
+
require 'baykit/bayserver/util/string_util'
|
|
3
|
+
|
|
4
|
+
module Baykit
|
|
5
|
+
module BayServer
|
|
6
|
+
module Docker
|
|
7
|
+
module Http
|
|
8
|
+
module H2
|
|
9
|
+
class HeaderBlockRenderer
|
|
10
|
+
|
|
11
|
+
include Baykit::BayServer::Util
|
|
12
|
+
|
|
13
|
+
attr :buf
|
|
14
|
+
|
|
15
|
+
def initialize(buf)
|
|
16
|
+
@buf = buf
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def render_header_blocks(header_blocks)
|
|
20
|
+
|
|
21
|
+
header_blocks.each do |blk|
|
|
22
|
+
render_header_block(blk)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def render_header_block(blk)
|
|
29
|
+
case blk.op
|
|
30
|
+
when HeaderBlock::INDEX
|
|
31
|
+
put_hpack_int(blk.index, 7, 1)
|
|
32
|
+
|
|
33
|
+
when HeaderBlock::OVERLOAD_KNOWN_HEADER
|
|
34
|
+
raise RuntimeError.new("IllegalState")
|
|
35
|
+
|
|
36
|
+
when HeaderBlock::NEW_HEADER
|
|
37
|
+
raise RuntimeError.new("Illegal State")
|
|
38
|
+
|
|
39
|
+
when HeaderBlock::KNOWN_HEADER
|
|
40
|
+
put_hpack_int(blk.index, 4, 0)
|
|
41
|
+
put_hpack_string(blk.value, false)
|
|
42
|
+
|
|
43
|
+
when HeaderBlock::UNKNOWN_HEADER
|
|
44
|
+
put_byte(0)
|
|
45
|
+
put_hpack_string(blk.name, false)
|
|
46
|
+
put_hpack_string(blk.value, false)
|
|
47
|
+
|
|
48
|
+
when HeaderBlock::UPDATE_DYNAMIC_TABLE_SIZE
|
|
49
|
+
raise RuntimeError.new("Illegal state")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def put_hpack_int(val, prefix, head)
|
|
54
|
+
max_val = 0xFF >> (8 -prefix)
|
|
55
|
+
head_val = (head << prefix) & 0xFF
|
|
56
|
+
if val < max_val
|
|
57
|
+
put_byte (val | head_val)
|
|
58
|
+
else
|
|
59
|
+
put_byte (head_val | max_val)
|
|
60
|
+
put_hpack_int_rest(val - max_val)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def put_hpack_int_rest(val)
|
|
65
|
+
while true
|
|
66
|
+
data = val & 0x7F
|
|
67
|
+
next_val = val >> 7
|
|
68
|
+
if next_val == 0
|
|
69
|
+
put_byte(data)
|
|
70
|
+
break
|
|
71
|
+
else
|
|
72
|
+
put_byte(data | 0x80)
|
|
73
|
+
val = next_val
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def put_hpack_string(value, is_haffman)
|
|
79
|
+
if is_haffman
|
|
80
|
+
raise RuntimeError.new "Illegal State"
|
|
81
|
+
else
|
|
82
|
+
put_hpack_int(value.length, 7, 0)
|
|
83
|
+
put_bytes(value)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def put_byte(val)
|
|
88
|
+
@buf.put_byte(val)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def put_bytes(data)
|
|
92
|
+
@buf.put(data)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
@@ -14,4 +14,6 @@ require 'baykit/bayserver/docker/http/h2/h2_warp_handler'
|
|
|
14
14
|
require 'baykit/bayserver/docker/http/h2/header_block'
|
|
15
15
|
require 'baykit/bayserver/docker/http/h2/header_block_analyzer'
|
|
16
16
|
require 'baykit/bayserver/docker/http/h2/header_block_builder'
|
|
17
|
+
require 'baykit/bayserver/docker/http/h2/header_block_parser'
|
|
18
|
+
require 'baykit/bayserver/docker/http/h2/header_block_renderer'
|
|
17
19
|
require 'baykit/bayserver/docker/http/h2/header_table'
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require 'baykit/bayserver/agent/transporter/package'
|
|
2
1
|
require 'baykit/bayserver/protocol/packet_store'
|
|
3
2
|
require 'baykit/bayserver/util/io_util'
|
|
4
3
|
require 'baykit/bayserver/util/string_util'
|
|
@@ -17,7 +16,6 @@ module Baykit
|
|
|
17
16
|
|
|
18
17
|
include Baykit::BayServer::Bcf
|
|
19
18
|
include Baykit::BayServer::Protocol
|
|
20
|
-
include Baykit::BayServer::WaterCraft
|
|
21
19
|
include Baykit::BayServer::Util
|
|
22
20
|
include Baykit::BayServer::Docker::Base
|
|
23
21
|
include Baykit::BayServer::Docker::Http
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require 'openssl'
|
|
2
2
|
|
|
3
|
-
require 'baykit/bayserver/agent/transporter/package'
|
|
4
3
|
require 'baykit/bayserver/docker/base/port_base'
|
|
5
4
|
require 'baykit/bayserver/docker/base/warp_base'
|
|
6
5
|
require 'baykit/bayserver/protocol/packet_store'
|
|
@@ -16,7 +15,6 @@ module Baykit
|
|
|
16
15
|
include Baykit::BayServer::Docker::Http::HtpDocker # implements
|
|
17
16
|
|
|
18
17
|
include OpenSSL
|
|
19
|
-
include Baykit::BayServer::Agent::Transporter
|
|
20
18
|
include Baykit::BayServer::Protocol
|
|
21
19
|
include Baykit::BayServer::Docker::Http::H1
|
|
22
20
|
include Baykit::BayServer::Docker::Http::H2
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bayserver-docker-http
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michisuke-P
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-02-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bayserver-core
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - '='
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 3.
|
|
19
|
+
version: 3.3.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - '='
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 3.
|
|
26
|
+
version: 3.3.1
|
|
27
27
|
description: BayServer is one of the high-speed web servers. It operates as a single-threaded,
|
|
28
28
|
asynchronous server, which makes it exceptionally fast. It also supports multi-core
|
|
29
29
|
processors, harnessing the full potential of the CPU's capabilities.
|
|
@@ -50,6 +50,7 @@ files:
|
|
|
50
50
|
- lib/baykit/bayserver/docker/http/h1/h1_type.rb
|
|
51
51
|
- lib/baykit/bayserver/docker/http/h1/h1_warp_handler.rb
|
|
52
52
|
- lib/baykit/bayserver/docker/http/h1/package.rb
|
|
53
|
+
- lib/baykit/bayserver/docker/http/h2/command/cmd_continuation.rb
|
|
53
54
|
- lib/baykit/bayserver/docker/http/h2/command/cmd_data.rb
|
|
54
55
|
- lib/baykit/bayserver/docker/http/h2/command/cmd_go_away.rb
|
|
55
56
|
- lib/baykit/bayserver/docker/http/h2/command/cmd_headers.rb
|
|
@@ -77,6 +78,8 @@ files:
|
|
|
77
78
|
- lib/baykit/bayserver/docker/http/h2/header_block.rb
|
|
78
79
|
- lib/baykit/bayserver/docker/http/h2/header_block_analyzer.rb
|
|
79
80
|
- lib/baykit/bayserver/docker/http/h2/header_block_builder.rb
|
|
81
|
+
- lib/baykit/bayserver/docker/http/h2/header_block_parser.rb
|
|
82
|
+
- lib/baykit/bayserver/docker/http/h2/header_block_renderer.rb
|
|
80
83
|
- lib/baykit/bayserver/docker/http/h2/header_table.rb
|
|
81
84
|
- lib/baykit/bayserver/docker/http/h2/huffman/hnode.rb
|
|
82
85
|
- lib/baykit/bayserver/docker/http/h2/huffman/htree.rb
|
|
@@ -90,7 +93,7 @@ homepage: https://baykit.yokohama
|
|
|
90
93
|
licenses:
|
|
91
94
|
- MIT
|
|
92
95
|
metadata: {}
|
|
93
|
-
post_install_message:
|
|
96
|
+
post_install_message:
|
|
94
97
|
rdoc_options: []
|
|
95
98
|
require_paths:
|
|
96
99
|
- lib
|
|
@@ -105,8 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
105
108
|
- !ruby/object:Gem::Version
|
|
106
109
|
version: '0'
|
|
107
110
|
requirements: []
|
|
108
|
-
rubygems_version: 3.
|
|
109
|
-
signing_key:
|
|
111
|
+
rubygems_version: 3.4.19
|
|
112
|
+
signing_key:
|
|
110
113
|
specification_version: 4
|
|
111
114
|
summary: HTTP docker of BayServer
|
|
112
115
|
test_files: []
|