bayserver-docker-http 2.2.0
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 +7 -0
- data/lib/baykit/bayserver/docker/http/h1/command/cmd_content.rb +46 -0
- data/lib/baykit/bayserver/docker/http/h1/command/cmd_end_content.rb +37 -0
- data/lib/baykit/bayserver/docker/http/h1/command/cmd_header.rb +306 -0
- data/lib/baykit/bayserver/docker/http/h1/command/package.rb +3 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_command.rb +19 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_command_handler.rb +31 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_command_unpacker.rb +58 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_inbound_handler.rb +371 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_packet.rb +28 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_packet_factory.rb +21 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb +180 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_protocol_handler.rb +66 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_type.rb +18 -0
- data/lib/baykit/bayserver/docker/http/h1/h1_warp_handler.rb +228 -0
- data/lib/baykit/bayserver/docker/http/h1/package.rb +11 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_data.rb +65 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_go_away.rb +67 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_headers.rb +108 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_ping.rb +50 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_preface.rb +51 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_priority.rb +59 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_rst_stream.rb +50 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_settings.rb +98 -0
- data/lib/baykit/bayserver/docker/http/h2/command/cmd_window_update.rb +53 -0
- data/lib/baykit/bayserver/docker/http/h2/command/package.rb +9 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_command.rb +42 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_command_handler.rb +29 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_command_unpacker.rb +73 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_error_code.rb +53 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_flags.rb +82 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_inbound_handler.rb +417 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_packet.rb +204 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_packet_factory.rb +21 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_packet_unpacker.rb +224 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_protocol_handler.rb +58 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_settings.rb +42 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_type.rb +26 -0
- data/lib/baykit/bayserver/docker/http/h2/h2_warp_handler.rb +142 -0
- data/lib/baykit/bayserver/docker/http/h2/header_block.rb +191 -0
- data/lib/baykit/bayserver/docker/http/h2/header_block_analyzer.rb +88 -0
- data/lib/baykit/bayserver/docker/http/h2/header_block_builder.rb +68 -0
- data/lib/baykit/bayserver/docker/http/h2/header_table.rb +167 -0
- data/lib/baykit/bayserver/docker/http/h2/huffman/hnode.rb +28 -0
- data/lib/baykit/bayserver/docker/http/h2/huffman/htree.rb +339 -0
- data/lib/baykit/bayserver/docker/http/h2/package.rb +17 -0
- data/lib/baykit/bayserver/docker/http/htp_docker.rb +23 -0
- data/lib/baykit/bayserver/docker/http/htp_port_docker.rb +107 -0
- data/lib/baykit/bayserver/docker/http/htp_warp_docker.rb +125 -0
- data/lib/baykit/bayserver/docker/http/htp_warp_ship_helper.rb +19 -0
- data/lib/baykit/bayserver/docker/http/package.rb +6 -0
- metadata +106 -0
@@ -0,0 +1,417 @@
|
|
1
|
+
require 'baykit/bayserver/docker/base/inbound_handler'
|
2
|
+
|
3
|
+
require 'baykit/bayserver/docker/http/h2/package'
|
4
|
+
require 'baykit/bayserver/docker/http/h2/h2_protocol_handler'
|
5
|
+
require 'baykit/bayserver/docker/http/h2/command/package'
|
6
|
+
require 'baykit/bayserver/protocol/package'
|
7
|
+
require 'baykit/bayserver/tours/req_content_handler'
|
8
|
+
require 'baykit/bayserver/tours/tour_req'
|
9
|
+
require 'baykit/bayserver/util/http_status'
|
10
|
+
require 'baykit/bayserver/util/url_encoder'
|
11
|
+
require 'baykit/bayserver/util/http_util'
|
12
|
+
|
13
|
+
module Baykit
|
14
|
+
module BayServer
|
15
|
+
module Docker
|
16
|
+
module Http
|
17
|
+
module H2
|
18
|
+
class H2InboundHandler < Baykit::BayServer::Docker::Http::H2::H2ProtocolHandler
|
19
|
+
|
20
|
+
class InboundProtocolHandlerFactory
|
21
|
+
include Baykit::BayServer::Protocol::ProtocolHandlerFactory # implements
|
22
|
+
|
23
|
+
def create_protocol_handler(pkt_store)
|
24
|
+
return H2InboundHandler.new(pkt_store)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
include Baykit::BayServer::Docker::Base::InboundHandler # implements
|
29
|
+
include Baykit::BayServer::Agent
|
30
|
+
include Baykit::BayServer::Protocol
|
31
|
+
include Baykit::BayServer::WaterCraft
|
32
|
+
include Baykit::BayServer::Tours
|
33
|
+
include Baykit::BayServer::Util
|
34
|
+
include Baykit::BayServer::Docker::Http::H2::Command
|
35
|
+
|
36
|
+
attr :req_cont_len
|
37
|
+
attr :req_cont_read
|
38
|
+
attr :header_read
|
39
|
+
attr :window_size
|
40
|
+
attr :settings
|
41
|
+
attr :analyzer
|
42
|
+
attr :http_protocol
|
43
|
+
|
44
|
+
def initialize(pkt_store)
|
45
|
+
super(pkt_store, true)
|
46
|
+
@window_size = BayServer.harbor.tour_buffer_size
|
47
|
+
@settings = H2Settings.new
|
48
|
+
@analyzer = HeaderBlockAnalyzer.new
|
49
|
+
end
|
50
|
+
|
51
|
+
######################################################
|
52
|
+
# implements Reusable
|
53
|
+
######################################################
|
54
|
+
|
55
|
+
def reset()
|
56
|
+
super
|
57
|
+
@header_read = false
|
58
|
+
@req_cont_len = 0
|
59
|
+
@req_cont_read = 0
|
60
|
+
end
|
61
|
+
|
62
|
+
######################################################
|
63
|
+
# implements InboundHandler
|
64
|
+
######################################################
|
65
|
+
|
66
|
+
def send_res_headers(tur)
|
67
|
+
cmd = CmdHeaders.new(tur.req.key)
|
68
|
+
bld = HeaderBlockBuilder.new()
|
69
|
+
blk = bld.build_header_block(":status", tur.res.headers.status.to_s, @res_header_tbl)
|
70
|
+
cmd.header_blocks << blk
|
71
|
+
|
72
|
+
# headers
|
73
|
+
if BayServer.harbor.trace_header?
|
74
|
+
BayLog.info("%s res status: %d", tur, tur.res.headers.status)
|
75
|
+
end
|
76
|
+
tur.res.headers.names.each do |name|
|
77
|
+
if name.casecmp?("connection")
|
78
|
+
BayLog.trace("%s Connection header is discarded", tur)
|
79
|
+
else
|
80
|
+
tur.res.headers.values(name).each do |value|
|
81
|
+
if BayServer.harbor.trace_header?
|
82
|
+
BayLog.info("%s H2 res header: %s=%s", tur, name, value)
|
83
|
+
end
|
84
|
+
blk = bld.build_header_block(name, value, @res_header_tbl)
|
85
|
+
cmd.header_blocks.append(blk)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
cmd.flags.set_end_headers(true)
|
91
|
+
cmd.excluded = true
|
92
|
+
cmd.flags.set_padded(false)
|
93
|
+
@command_packer.post(@ship, cmd)
|
94
|
+
end
|
95
|
+
|
96
|
+
def send_res_content(tur, bytes, ofs, len, &lis)
|
97
|
+
cmd = CmdData.new(tur.req.key, nil, bytes, ofs, len);
|
98
|
+
@command_packer.post(@ship, cmd, &lis)
|
99
|
+
end
|
100
|
+
|
101
|
+
def send_end_tour(tur, keep_alive, &callback)
|
102
|
+
cmd = CmdData.new(tur.req.key, nil, [], 0, 0)
|
103
|
+
cmd.flags.set_end_stream(true)
|
104
|
+
@command_packer.post(@ship, cmd, &callback)
|
105
|
+
end
|
106
|
+
|
107
|
+
def send_req_protocol_error(err)
|
108
|
+
BayLog.error_e err
|
109
|
+
cmd = CmdGoAway.new(CTL_STREAM_ID)
|
110
|
+
cmd.stream_id = CTL_STREAM_ID
|
111
|
+
cmd.last_stream_id = CTL_STREAM_ID
|
112
|
+
cmd.error_code = H2ErrorCode::PROTOCOL_ERROR
|
113
|
+
cmd.debug_data = "Thank you!"
|
114
|
+
begin
|
115
|
+
@command_packer.post(@ship, cmd)
|
116
|
+
@command_packer.end(@ship)
|
117
|
+
rescue IOError => e
|
118
|
+
BayLog.error_e(e)
|
119
|
+
end
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
######################################################
|
125
|
+
# implements H2CommandHandler
|
126
|
+
######################################################
|
127
|
+
|
128
|
+
def handle_preface(cmd)
|
129
|
+
BayLog.debug("%s h2: handle_preface: proto=%s", @ship, cmd.protocol)
|
130
|
+
|
131
|
+
@http_protocol = cmd.protocol
|
132
|
+
|
133
|
+
set = CmdSettings.new(H2ProtocolHandler::CTL_STREAM_ID)
|
134
|
+
set.stream_id = 0
|
135
|
+
set.items.append(CmdSettings::Item.new(CmdSettings::MAX_CONCURRENT_STREAMS, TourStore::MAX_TOURS))
|
136
|
+
set.items.append(CmdSettings::Item.new(CmdSettings::INITIAL_WINDOW_SIZE, @window_size))
|
137
|
+
@command_packer.post(@ship, set)
|
138
|
+
|
139
|
+
set = CmdSettings.new(H2ProtocolHandler::CTL_STREAM_ID)
|
140
|
+
set.stream_id = 0
|
141
|
+
set.flags.set_ack(true)
|
142
|
+
|
143
|
+
return NextSocketAction::CONTINUE
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def handle_headers(cmd)
|
148
|
+
BayLog.debug("%s handle_headers: stm=%d dep=%d weight=%d", @ship, cmd.stream_id, cmd.stream_dependency, cmd.weight)
|
149
|
+
|
150
|
+
tur = get_tour(cmd.stream_id)
|
151
|
+
if tur == nil
|
152
|
+
BayLog.error(BayMessage.get(:INT_NO_MORE_TOURS))
|
153
|
+
tur = @ship.get_tour(cmd.stream_id, true)
|
154
|
+
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus::SERVICE_UNAVAILABLE, "No available tours")
|
155
|
+
return NextSocketAction::CONTINUE
|
156
|
+
end
|
157
|
+
|
158
|
+
cmd.header_blocks.each do |blk|
|
159
|
+
if blk.op == HeaderBlock::UPDATE_DYNAMIC_TABLE_SIZE
|
160
|
+
BayLog.trace("%s header block update table size: %d", tur, blk.size)
|
161
|
+
@req_header_tbl.set_size(blk.size)
|
162
|
+
next
|
163
|
+
end
|
164
|
+
@analyzer.analyze_header_block(blk, @req_header_tbl)
|
165
|
+
if BayServer.harbor.trace_header?
|
166
|
+
BayLog.info("%s req header: %s=%s :%s", tur, @analyzer.name, @analyzer.value, blk);
|
167
|
+
end
|
168
|
+
|
169
|
+
if @analyzer.name == nil
|
170
|
+
next
|
171
|
+
|
172
|
+
elsif @analyzer.name[0] != ":"
|
173
|
+
tur.req.headers.add(@analyzer.name, @analyzer.value)
|
174
|
+
|
175
|
+
elsif @analyzer.method != nil
|
176
|
+
tur.req.method = @analyzer.method
|
177
|
+
|
178
|
+
elsif @analyzer.path != nil
|
179
|
+
tur.req.uri = @analyzer.path
|
180
|
+
|
181
|
+
elsif @analyzer.scheme != nil
|
182
|
+
|
183
|
+
elsif @analyzer.status != nil
|
184
|
+
raise RuntimeError.new("Illegal State")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
if cmd.flags.end_headers?
|
189
|
+
tur.req.protocol = "HTTP/2.0"
|
190
|
+
BayLog.debug("%s H2 read header method=%s protocol=%s uri=%s contlen=%d",
|
191
|
+
@ship, tur.req.method, tur.req.protocol, tur.req.uri, tur.req.headers.content_length)
|
192
|
+
|
193
|
+
req_cont_len = tur.req.headers.content_length()
|
194
|
+
|
195
|
+
if req_cont_len > 0
|
196
|
+
sid = @ship.ship_id
|
197
|
+
tur.req.set_consume_listener(req_cont_len) do |len, resume|
|
198
|
+
@ship.check_ship_id(sid)
|
199
|
+
if len > 0
|
200
|
+
upd = CmdWindowUpdate.new(cmd.stream_id)
|
201
|
+
upd.window_size_increment = len
|
202
|
+
upd2 = CmdWindowUpdate.new( 0)
|
203
|
+
upd2.window_size_increment = len
|
204
|
+
cmd_packer = @command_packer
|
205
|
+
begin
|
206
|
+
cmd_packer.post(@ship, upd)
|
207
|
+
cmd_packer.post(@ship, upd2)
|
208
|
+
rescue IOError => e
|
209
|
+
BayLog.error_e(e)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
if resume
|
214
|
+
@ship.resume(Ship::SHIP_ID_NOCHECK)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
begin
|
221
|
+
start_tour tur
|
222
|
+
|
223
|
+
if tur.req.headers.content_length <= 0
|
224
|
+
end_req_content(Tour::TOUR_ID_NOCHECK, tur)
|
225
|
+
end
|
226
|
+
rescue HttpException => e
|
227
|
+
BayLog.debug("%s Http error occurred: %s", self, e);
|
228
|
+
if req_cont_len <= 0
|
229
|
+
# no post data
|
230
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
231
|
+
|
232
|
+
return NextSocketAction::CONTINUE
|
233
|
+
else
|
234
|
+
# Delay send
|
235
|
+
tur.error = e
|
236
|
+
tur.req.set_content_handler(ReqContentHandler::DEV_NULL)
|
237
|
+
return NextSocketAction::CONTINUE
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
NextSocketAction::CONTINUE
|
244
|
+
end
|
245
|
+
|
246
|
+
def handle_data(cmd)
|
247
|
+
BayLog.debug("%s handle_data: stm=%d len=%d", @ship, cmd.stream_id, cmd.length)
|
248
|
+
|
249
|
+
tur = get_tour(cmd.stream_id)
|
250
|
+
if tur == nil
|
251
|
+
raise RuntimeError.new("Invalid stream id: #{cmd.stream_id}")
|
252
|
+
end
|
253
|
+
if tur.req.headers.content_length <= 0
|
254
|
+
raise ProtocolException.new("Post content not allowed")
|
255
|
+
end
|
256
|
+
|
257
|
+
success = false
|
258
|
+
if cmd.length > 0
|
259
|
+
success = tur.req.post_content(Tour::TOUR_ID_NOCHECK, cmd.data, cmd.start, cmd.length)
|
260
|
+
if tur.req.bytes_posted >= tur.req.headers.content_length
|
261
|
+
if tur.error != nil
|
262
|
+
# Error has occurred on header completed
|
263
|
+
|
264
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, tur.error)
|
265
|
+
return NextSocketAction::CONTINUE
|
266
|
+
else
|
267
|
+
begin
|
268
|
+
end_req_content(tur.id(), tur)
|
269
|
+
rescue HttpException => e
|
270
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
271
|
+
return NextSocketAction::CONTINUE
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
if !success
|
278
|
+
return NextSocketAction::SUSPEND
|
279
|
+
else
|
280
|
+
return NextSocketAction::CONTINUE
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
def handle_priority(cmd)
|
286
|
+
if cmd.stream_id == 0
|
287
|
+
raise ProtocolException.new("Invalid stream id")
|
288
|
+
end
|
289
|
+
|
290
|
+
BayLog.debug("%s handlePriority: stmid=%d dep=%d, wgt=%d",
|
291
|
+
@ship, cmd.stream_id, cmd.stream_dependency, cmd.weight);
|
292
|
+
|
293
|
+
return NextSocketAction::CONTINUE
|
294
|
+
end
|
295
|
+
|
296
|
+
def handle_settings(cmd)
|
297
|
+
BayLog.debug("%s handleSettings: stmid=%d", @ship, cmd.stream_id);
|
298
|
+
|
299
|
+
if cmd.flags.ack?
|
300
|
+
return NextSocketAction::CONTINUE
|
301
|
+
end
|
302
|
+
|
303
|
+
cmd.items.each do |item|
|
304
|
+
BayLog.debug("%s handle: Setting id=%d, value=%d", @ship, item.id, item.value);
|
305
|
+
case item.id
|
306
|
+
when CmdSettings::HEADER_TABLE_SIZE
|
307
|
+
@settings.header_table_size = item.value
|
308
|
+
|
309
|
+
when CmdSettings::ENABLE_PUSH
|
310
|
+
@settings.enable_push = (item.value != 0)
|
311
|
+
|
312
|
+
when CmdSettings::MAX_CONCURRENT_STREAMS
|
313
|
+
@settings.max_concurrent_streams = item.value
|
314
|
+
|
315
|
+
when CmdSettings::INITIAL_WINDOW_SIZE
|
316
|
+
@settings.initial_window_size = item.value
|
317
|
+
|
318
|
+
when CmdSettings::MAX_FRAME_SIZE
|
319
|
+
@settings.max_frame_size = item.value
|
320
|
+
|
321
|
+
when CmdSettings::MAX_HEADER_LIST_SIZE
|
322
|
+
@settings.max_header_list_size = item.value
|
323
|
+
|
324
|
+
else
|
325
|
+
BayLog.debug("Invalid settings id (Ignore): %d", item.id)
|
326
|
+
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
res = CmdSettings.new(0, H2Flags.new(H2Flags::FLAGS_ACK))
|
331
|
+
@command_packer.post(@ship, res)
|
332
|
+
return NextSocketAction::CONTINUE
|
333
|
+
end
|
334
|
+
|
335
|
+
def handle_window_update(cmd)
|
336
|
+
BayLog.debug("%s handleWindowUpdate: stmid=%d siz=%d", @ship, cmd.stream_id, cmd.window_size_increment);
|
337
|
+
|
338
|
+
if cmd.window_size_increment == 0
|
339
|
+
raise ProtocolException.new("Invalid increment value")
|
340
|
+
end
|
341
|
+
|
342
|
+
window_size = cmd.window_size_increment
|
343
|
+
return NextSocketAction::CONTINUE
|
344
|
+
end
|
345
|
+
|
346
|
+
def handle_go_away(cmd)
|
347
|
+
BayLog.debug("%s received GoAway: lastStm=%d code=%d desc=%s debug=%s",
|
348
|
+
@ship, cmd.last_stream_id, cmd.error_code, H2ErrorCode.msg.get(cmd.error_code.to_s.to_sym), cmd.debug_data);
|
349
|
+
return NextSocketAction::CLOSE
|
350
|
+
end
|
351
|
+
|
352
|
+
def handle_ping(cmd)
|
353
|
+
BayLog.debug("%s handle_ping: stm=%d", @ship, cmd.stream_id)
|
354
|
+
|
355
|
+
res = CmdPing.new(cmd.stream_id, H2Flags.new(H2Flags::FLAGS_ACK), cmd.opaque_data)
|
356
|
+
@command_packer.post(@ship, res)
|
357
|
+
return NextSocketAction::CONTINUE
|
358
|
+
end
|
359
|
+
|
360
|
+
def handle_rst_stream(cmd)
|
361
|
+
BayLog.debug("%s received RstStream: stmid=%d code=%d desc=%s",
|
362
|
+
@ship, cmd.stream_id, cmd.error_code, H2ErrorCode.msg.get(cmd.error_code.to_s.to_sym))
|
363
|
+
return NextSocketAction::CONTINUE
|
364
|
+
end
|
365
|
+
|
366
|
+
private
|
367
|
+
def get_tour(key)
|
368
|
+
@ship.get_tour(key)
|
369
|
+
end
|
370
|
+
|
371
|
+
def end_req_content(check_id, tur)
|
372
|
+
tur.req.end_content check_id
|
373
|
+
end
|
374
|
+
|
375
|
+
def start_tour(tur)
|
376
|
+
HttpUtil.parse_host_port(tur, @ship.port_docker.secure ? 443 : 80)
|
377
|
+
HttpUtil.parse_authorization(tur)
|
378
|
+
|
379
|
+
tur.req.protocol = @http_protocol
|
380
|
+
|
381
|
+
skt = @ship.socket
|
382
|
+
|
383
|
+
client_adr = tur.req.headers.get(Headers::X_FORWARDED_FOR)
|
384
|
+
if client_adr
|
385
|
+
tur.req.remote_address = client_adr
|
386
|
+
tur.req.remote_port = nil
|
387
|
+
else
|
388
|
+
remote_addr = skt.getpeername()
|
389
|
+
tur.req.remote_port, tur.req.remote_address = Socket.unpack_sockaddr_in(remote_addr)
|
390
|
+
end
|
391
|
+
|
392
|
+
tur.req.remote_host_func = lambda { HttpUtil.resolve_remote_host(tur.req.remote_address) }
|
393
|
+
|
394
|
+
|
395
|
+
|
396
|
+
|
397
|
+
begin
|
398
|
+
server_addr = skt.getsockname
|
399
|
+
server_port, tur.req.server_address = Socket.unpack_sockaddr_in(server_addr)
|
400
|
+
rescue => e
|
401
|
+
BayLog.error_e(e)
|
402
|
+
BayLog.debug("%s Caught error (Continue)", @ship)
|
403
|
+
end
|
404
|
+
|
405
|
+
tur.req.server_port = tur.req.req_port
|
406
|
+
tur.req.server_name = tur.req.req_host
|
407
|
+
tur.is_secure = @ship.port_docker.secure
|
408
|
+
|
409
|
+
tur.go
|
410
|
+
end
|
411
|
+
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/package'
|
2
|
+
require 'baykit/bayserver/docker/http/h2/huffman/htree'
|
3
|
+
|
4
|
+
#
|
5
|
+
# Http2 spec
|
6
|
+
# https://www.rfc-editor.org/rfc/rfc7540.txt
|
7
|
+
#
|
8
|
+
# Http2 Frame format
|
9
|
+
# +-----------------------------------------------+
|
10
|
+
# | Length (24) |
|
11
|
+
# +---------------+---------------+---------------+
|
12
|
+
# | Type (8) | Flags (8) |
|
13
|
+
# +-+-+-----------+---------------+-------------------------------+
|
14
|
+
# |R| Stream Identifier (31) |
|
15
|
+
# +=+=============================================================+
|
16
|
+
# | Frame Payload (0...) ...
|
17
|
+
# +---------------------------------------------------------------+
|
18
|
+
#
|
19
|
+
module Baykit
|
20
|
+
module BayServer
|
21
|
+
module Docker
|
22
|
+
module Http
|
23
|
+
module H2
|
24
|
+
class H2Packet < Baykit::BayServer::Protocol::Packet
|
25
|
+
|
26
|
+
include Baykit::BayServer::Protocol
|
27
|
+
include Baykit::BayServer::Docker::Http::H2
|
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
|
+
MAX_PAYLOAD_LEN = 0x00FFFFFF # = 2^24-1 = 16777215 = 16MB-1
|
129
|
+
DEFAULT_PAYLOAD_MAXLEN = 0x00004000 # = 2^14 = 16384 = 16KB
|
130
|
+
FRAME_HEADER_LEN = 9
|
131
|
+
|
132
|
+
NO_ERROR = 0x0
|
133
|
+
PROTOCOL_ERROR = 0x1
|
134
|
+
INTERNAL_ERROR = 0x2
|
135
|
+
FLOW_CONTROL_ERROR = 0x3
|
136
|
+
SETTINGS_TIMEOUT = 0x4
|
137
|
+
STREAM_CLOSED = 0x5
|
138
|
+
FRAME_SIZE_ERROR = 0x6
|
139
|
+
REFUSED_STREAM = 0x7
|
140
|
+
CANCEL = 0x8
|
141
|
+
COMPRESSION_ERROR = 0x9
|
142
|
+
CONNECT_ERROR = 0xa
|
143
|
+
ENHANCE_YOUR_CALM = 0xb
|
144
|
+
INADEQUATE_SECURITY = 0xc
|
145
|
+
HTTP_1_1_REQUIRED = 0xd
|
146
|
+
|
147
|
+
attr_accessor :flags
|
148
|
+
attr_accessor :stream_id
|
149
|
+
|
150
|
+
def initialize(type)
|
151
|
+
super(type, FRAME_HEADER_LEN, DEFAULT_PAYLOAD_MAXLEN)
|
152
|
+
@flags = H2Flags::FLAGS_NONE
|
153
|
+
@stream_id = -1
|
154
|
+
end
|
155
|
+
|
156
|
+
def reset
|
157
|
+
@flags = H2Flags::FLAGS_NONE
|
158
|
+
@stream_id = -1
|
159
|
+
super
|
160
|
+
end
|
161
|
+
|
162
|
+
def pack_header
|
163
|
+
acc = new_h2_header_accessor()
|
164
|
+
acc.put_int24(data_len())
|
165
|
+
acc.put_byte(@type)
|
166
|
+
acc.put_byte(@flags.flags)
|
167
|
+
acc.put_int(H2Packet.extract_int31(stream_id))
|
168
|
+
end
|
169
|
+
|
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
|
+
def self.extract_int31(val)
|
179
|
+
val & 0x7FFFFFFF
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.extract_flag(val)
|
183
|
+
(val & 0x80000000) >> 31 & 1
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.consolidate_flag_and_int32(flag, val)
|
187
|
+
((flag & 1) << 31) | (val & 0x7FFFFFFF)
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.make_stream_dependency32(excluded, dep)
|
191
|
+
(excluded ? 1 : 0) << 31 | extract_int31(dep)
|
192
|
+
end
|
193
|
+
|
194
|
+
def to_s
|
195
|
+
"H2Packet(#{@type}) headerLen=#{@header_len} dataLen=#{data_len()} stm=#{@stream_id} flags=#{@flags}"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/packet_factory'
|
2
|
+
|
3
|
+
module Baykit
|
4
|
+
module BayServer
|
5
|
+
module Docker
|
6
|
+
module Http
|
7
|
+
module H2
|
8
|
+
class H2PacketFactory <Baykit::BayServer::Protocol::PacketFactory
|
9
|
+
|
10
|
+
def create_packet(type)
|
11
|
+
H2Packet.new(type)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|