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,371 @@
|
|
1
|
+
require 'baykit/bayserver/agent/upgrade_exception'
|
2
|
+
|
3
|
+
require 'baykit/bayserver/docker/base/inbound_handler'
|
4
|
+
|
5
|
+
require 'baykit/bayserver/protocol/package'
|
6
|
+
require 'baykit/bayserver/tours/req_content_handler'
|
7
|
+
require 'baykit/bayserver/tours/tour_req'
|
8
|
+
require 'baykit/bayserver/util/http_status'
|
9
|
+
require 'baykit/bayserver/util/url_encoder'
|
10
|
+
require 'baykit/bayserver/util/http_util'
|
11
|
+
require 'baykit/bayserver/util/headers'
|
12
|
+
|
13
|
+
require 'baykit/bayserver/docker/http/h1/h1_command_handler'
|
14
|
+
require 'baykit/bayserver/docker/http/h1/h1_protocol_handler'
|
15
|
+
require 'baykit/bayserver/docker/http/h2/package'
|
16
|
+
|
17
|
+
module Baykit
|
18
|
+
module BayServer
|
19
|
+
module Docker
|
20
|
+
module Http
|
21
|
+
module H1
|
22
|
+
class H1InboundHandler < Baykit::BayServer::Docker::Http::H1::H1ProtocolHandler
|
23
|
+
|
24
|
+
class InboundProtocolHandlerFactory
|
25
|
+
include Baykit::BayServer::Protocol::ProtocolHandlerFactory # implements
|
26
|
+
|
27
|
+
def create_protocol_handler(pkt_store)
|
28
|
+
return H1InboundHandler.new(pkt_store)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
include Baykit::BayServer::Docker::Base::InboundHandler # implements
|
33
|
+
include Baykit::BayServer::Agent
|
34
|
+
include Baykit::BayServer::Protocol
|
35
|
+
include Baykit::BayServer::Tours
|
36
|
+
include Baykit::BayServer::Util
|
37
|
+
include Baykit::BayServer::Docker::Http::H2
|
38
|
+
|
39
|
+
STATE_READ_HEADER = 1
|
40
|
+
STATE_READ_CONTENT = 2
|
41
|
+
STATE_FINISHED = 3
|
42
|
+
|
43
|
+
FIXED_REQ_ID = 1
|
44
|
+
|
45
|
+
attr :header_read
|
46
|
+
attr :state
|
47
|
+
attr :cur_req_id
|
48
|
+
attr :cur_tour
|
49
|
+
attr :cur_tour_id
|
50
|
+
attr :http_protocol
|
51
|
+
|
52
|
+
def initialize(pkt_store)
|
53
|
+
super(pkt_store, true)
|
54
|
+
reset()
|
55
|
+
end
|
56
|
+
|
57
|
+
######################################################
|
58
|
+
# implements Reusable
|
59
|
+
######################################################
|
60
|
+
def reset()
|
61
|
+
super
|
62
|
+
@cur_req_id = 1
|
63
|
+
reset_state()
|
64
|
+
|
65
|
+
@header_read = false
|
66
|
+
@http_protocol = nil
|
67
|
+
@cur_req_id = 1
|
68
|
+
@cur_tour = nil
|
69
|
+
@cur_req_id = 0
|
70
|
+
end
|
71
|
+
|
72
|
+
######################################################
|
73
|
+
# implements InboundHandler
|
74
|
+
######################################################
|
75
|
+
def send_res_headers(tur)
|
76
|
+
|
77
|
+
# determine Connection header value
|
78
|
+
if tur.req.headers.get_connection() != Headers::CONNECTION_KEEP_ALIVE
|
79
|
+
# If client doesn't support "Keep-Alive", set "Close"
|
80
|
+
res_con = "Close"
|
81
|
+
else
|
82
|
+
res_con = "Keep-Alive"
|
83
|
+
# Client supports "Keep-Alive"
|
84
|
+
if tur.res.headers.get_connection() != Headers::CONNECTION_KEEP_ALIVE
|
85
|
+
# If tours doesn't need "Keep-Alive"
|
86
|
+
if tur.res.headers.content_length() == -1
|
87
|
+
# If content-length not specified
|
88
|
+
if tur.res.headers.content_type() != nil &&
|
89
|
+
tur.res.headers.content_type().start_with?("text/")
|
90
|
+
# If content is text, connection must be closed
|
91
|
+
res_con = "Close"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
tur.res.headers.set(Headers::CONNECTION, res_con)
|
98
|
+
|
99
|
+
if BayServer.harbor.trace_header?
|
100
|
+
BayLog.info("%s resStatus:%d", tur, tur.res.headers.status)
|
101
|
+
tur.res.headers.names.each do |name|
|
102
|
+
tur.res.headers.values(name).each do |value|
|
103
|
+
BayLog.info("%s resHeader:%s=%s", tur, name, value)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
cmd = CmdHeader.new_res_header(tur.res.headers, tur.req.protocol)
|
109
|
+
@command_packer.post(@ship, cmd)
|
110
|
+
end
|
111
|
+
|
112
|
+
def send_res_content(tur, bytes, ofs, len, &callback)
|
113
|
+
BayLog.debug("%s H1 send_res_content len=%d", self, len)
|
114
|
+
cmd = CmdContent.new(bytes, ofs, len)
|
115
|
+
@command_packer.post(@ship, cmd, &callback)
|
116
|
+
end
|
117
|
+
|
118
|
+
def send_end_tour(tur, keep_alive, &callback)
|
119
|
+
BayLog.trace("%s sendEndTour: tur=%s keep=%s", @ship, tur, keep_alive)
|
120
|
+
|
121
|
+
# Send dummy end request command
|
122
|
+
cmd = CmdEndContent.new()
|
123
|
+
|
124
|
+
sid = @ship.ship_id
|
125
|
+
ensure_func = lambda do
|
126
|
+
if keep_alive && !@ship.postman.zombie?
|
127
|
+
@ship.keeping = true
|
128
|
+
@ship.resume(sid)
|
129
|
+
else
|
130
|
+
@command_packer.end(@ship)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
begin
|
135
|
+
@command_packer.post(@ship, cmd) do
|
136
|
+
BayLog.debug("%s call back of end content command: tur=%s", @ship, tur)
|
137
|
+
ensure_func.call()
|
138
|
+
callback.call()
|
139
|
+
end
|
140
|
+
rescue IOError => e
|
141
|
+
ensure_func.call()
|
142
|
+
raise e
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def send_req_protocol_error(err)
|
147
|
+
if @cur_tour == nil
|
148
|
+
tur = @ship.get_error_tour()
|
149
|
+
else
|
150
|
+
tur = @cur_tour
|
151
|
+
end
|
152
|
+
|
153
|
+
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus::BAD_REQUEST, err.message, err)
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
157
|
+
######################################################
|
158
|
+
# implements H1CommandHandler
|
159
|
+
######################################################
|
160
|
+
def handle_header(cmd)
|
161
|
+
BayLog.debug("%s handleHeader: method=%s uri=%s proto=", @ship, cmd.method, cmd.uri, cmd.version);
|
162
|
+
|
163
|
+
if @state == STATE_FINISHED
|
164
|
+
change_state(STATE_READ_HEADER)
|
165
|
+
end
|
166
|
+
|
167
|
+
if @state != STATE_READ_HEADER || @cur_tour != nil
|
168
|
+
msg = "Header command not expected: state=#{@state} curTur=#{@cur_tour}"
|
169
|
+
BayLog.error(msg)
|
170
|
+
self.reset_state();
|
171
|
+
raise ProtocolException.new(msg)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Check HTTP2
|
175
|
+
protocol = cmd.version.upcase
|
176
|
+
if protocol == "HTTP/2.0"
|
177
|
+
if @ship.port_docker.support_h2
|
178
|
+
@ship.port_docker.return_protocol_handler(@ship.agent, self)
|
179
|
+
new_hnd = ProtocolHandlerStore.get_store(HtpDocker::H2_PROTO_NAME, true, @ship.agent.agent_id).rent()
|
180
|
+
@ship.set_protocol_handler(new_hnd)
|
181
|
+
raise UpgradeException.new()
|
182
|
+
else
|
183
|
+
raise ProtocolException.new(
|
184
|
+
BayMessage.get(:HTP_UNSUPPORTED_PROTOCOL, protocol))
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
tur = @ship.get_tour(@cur_req_id)
|
189
|
+
@cur_tour = tur
|
190
|
+
@cur_tour_id = tur.id()
|
191
|
+
@cur_req_id += 1
|
192
|
+
|
193
|
+
if tur == nil
|
194
|
+
BayLog.error(BayMessage.get(:INT_NO_MORE_TOURS))
|
195
|
+
tur = @ship.get_tour(self.cur_req_id, true)
|
196
|
+
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus::SERVICE_UNAVAILABLE, "No available tours")
|
197
|
+
@ship.agent.shutdown(false)
|
198
|
+
return NextSocketAction::CONTINUE
|
199
|
+
end
|
200
|
+
|
201
|
+
@ship.keeping = false
|
202
|
+
|
203
|
+
@http_protocol = protocol
|
204
|
+
|
205
|
+
tur.req.uri = URLEncoder.encode_tilde(cmd.uri)
|
206
|
+
tur.req.method = cmd.method.upcase
|
207
|
+
tur.req.protocol = protocol
|
208
|
+
|
209
|
+
if !(tur.req.protocol == "HTTP/1.1" ||
|
210
|
+
tur.req.protocol == "HTTP/1.0" ||
|
211
|
+
tur.req.protocol == "HTTP/0.9")
|
212
|
+
|
213
|
+
raise ProtocolException.new(BayMessage.get(:HTP_UNSUPPORTED_PROTOCOL, tur.req.protocol))
|
214
|
+
end
|
215
|
+
|
216
|
+
cmd.headers.each do |nv|
|
217
|
+
tur.req.headers.add(nv[0], nv[1])
|
218
|
+
end
|
219
|
+
|
220
|
+
req_cont_len = tur.req.headers.content_length
|
221
|
+
BayLog.debug("%s read header method=%s protocol=%s uri=%s contlen=%d",
|
222
|
+
@ship, tur.req.method, tur.req.protocol, tur.req.uri, tur.req.headers.content_length)
|
223
|
+
|
224
|
+
if BayServer.harbor.trace_header?
|
225
|
+
cmd.headers.each do |item|
|
226
|
+
BayLog.info("%s h1: reqHeader: %s=%s", tur, item[0], item[1])
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
if req_cont_len > 0
|
231
|
+
sid = @ship.ship_id
|
232
|
+
tur.req.set_consume_listener(req_cont_len) do |len, resume|
|
233
|
+
if resume
|
234
|
+
@ship.resume(sid)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
begin
|
240
|
+
start_tour(tur)
|
241
|
+
|
242
|
+
if req_cont_len <= 0
|
243
|
+
end_req_content(@cur_tour_id, tur)
|
244
|
+
return NextSocketAction::SUSPEND # end reading
|
245
|
+
else
|
246
|
+
change_state(STATE_READ_CONTENT)
|
247
|
+
return NextSocketAction::CONTINUE
|
248
|
+
end
|
249
|
+
rescue HttpException => e
|
250
|
+
BayLog.debug("%s Http error occurred: %s", self, e)
|
251
|
+
if req_cont_len <= 0
|
252
|
+
# no post data
|
253
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
254
|
+
|
255
|
+
reset_state() # next: read empty stdin command
|
256
|
+
return NextSocketAction::CONTINUE
|
257
|
+
else
|
258
|
+
# Delay send
|
259
|
+
BayLog.trace("%s error sending is delayed", self)
|
260
|
+
change_state(STATE_READ_CONTENT)
|
261
|
+
tur.error = e
|
262
|
+
tur.req.set_content_handler(ReqContentHandler::DEV_NULL)
|
263
|
+
return NextSocketAction::CONTINUE
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def handle_content(cmd)
|
269
|
+
BayLog.debug("%s handleContent: len=%s", @ship, cmd.len)
|
270
|
+
|
271
|
+
if @state != STATE_READ_CONTENT
|
272
|
+
s = @state
|
273
|
+
reset_state()
|
274
|
+
raise ProtocolException.new("Content command not expected: state=#{s}")
|
275
|
+
end
|
276
|
+
|
277
|
+
tur = @cur_tour
|
278
|
+
tur_id = @cur_tour_id
|
279
|
+
success = tur.req.post_content(tur_id, cmd.buf, cmd.start, cmd.len)
|
280
|
+
|
281
|
+
if tur.req.bytes_posted == tur.req.bytes_limit
|
282
|
+
if tur.error != nil
|
283
|
+
# Error has occurred on header completed
|
284
|
+
tur.res.send_http_exception(tur_id, tur.error)
|
285
|
+
reset_state()
|
286
|
+
return NextSocketAction::WRITE
|
287
|
+
else
|
288
|
+
begin
|
289
|
+
end_req_content(tur_id, tur)
|
290
|
+
return NextSocketAction::SUSPEND # end reading
|
291
|
+
rescue HttpException => e
|
292
|
+
tur.res.send_http_exception(tur_id, e)
|
293
|
+
reset_state()
|
294
|
+
return NextSocketAction::WRITE
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
if !success
|
300
|
+
return NextSocketAction::SUSPEND
|
301
|
+
else
|
302
|
+
return NextSocketAction::CONTINUE
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def handle_end_content(cmd)
|
307
|
+
raise Sink.new()
|
308
|
+
end
|
309
|
+
|
310
|
+
def finished()
|
311
|
+
return @state == STATE_FINISHED
|
312
|
+
end
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
private
|
317
|
+
def change_state(new_state)
|
318
|
+
@state = new_state
|
319
|
+
end
|
320
|
+
|
321
|
+
def reset_state
|
322
|
+
@header_read = false
|
323
|
+
change_state STATE_FINISHED
|
324
|
+
@cur_tour = nil
|
325
|
+
end
|
326
|
+
|
327
|
+
def end_req_content(chk_tur_id, tur)
|
328
|
+
tur.req.end_content(chk_tur_id)
|
329
|
+
reset_state()
|
330
|
+
end
|
331
|
+
|
332
|
+
def start_tour(tur)
|
333
|
+
secure = @ship.port_docker.secure
|
334
|
+
HttpUtil.parse_host_port(tur, secure ? 443 : 80)
|
335
|
+
HttpUtil.parse_authorization(tur)
|
336
|
+
|
337
|
+
skt = @ship.socket
|
338
|
+
|
339
|
+
client_adr = tur.req.headers.get(Headers::X_FORWARDED_FOR)
|
340
|
+
if client_adr
|
341
|
+
tur.req.remote_address = client_adr
|
342
|
+
tur.req.remote_port = nil
|
343
|
+
else
|
344
|
+
begin
|
345
|
+
remote_addr = skt.getpeername()
|
346
|
+
tur.req.remote_port, tur.req.remote_address = Socket.unpack_sockaddr_in(remote_addr)
|
347
|
+
rescue => e
|
348
|
+
BayLog.error_e(e, "%s Cannot get remote address (Ignore): %s", tur, e)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
tur.req.remote_host_func = lambda do
|
353
|
+
HttpUtil.resolve_remote_host(tur.req.remote_address)
|
354
|
+
end
|
355
|
+
|
356
|
+
server_addr = skt.getsockname
|
357
|
+
server_port, tur.req.server_address = Socket.unpack_sockaddr_in(server_addr)
|
358
|
+
|
359
|
+
tur.req.server_port = tur.req.req_port
|
360
|
+
tur.req.server_name = tur.req.req_host
|
361
|
+
tur.is_secure = secure
|
362
|
+
|
363
|
+
tur.go()
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/packet'
|
2
|
+
|
3
|
+
module Baykit
|
4
|
+
module BayServer
|
5
|
+
module Docker
|
6
|
+
module Http
|
7
|
+
module H1
|
8
|
+
class H1Packet < Baykit::BayServer::Protocol::Packet
|
9
|
+
|
10
|
+
MAX_HEADER_LEN = 0 # H1 packet does not have packet header
|
11
|
+
MAX_DATA_LEN = 65536
|
12
|
+
|
13
|
+
|
14
|
+
def initialize(type)
|
15
|
+
super type, MAX_HEADER_LEN, MAX_DATA_LEN
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"H1Packet(#{@type}) len=#{data_len()}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -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 H1
|
8
|
+
class H1PacketFactory < Baykit::BayServer::Protocol::PacketFactory
|
9
|
+
|
10
|
+
def create_packet(type)
|
11
|
+
H1Packet.new(type)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/packet_unpacker'
|
2
|
+
require 'baykit/bayserver/agent/next_socket_action'
|
3
|
+
require 'baykit/bayserver/agent/upgrade_exception'
|
4
|
+
require 'baykit/bayserver/util/simple_buffer'
|
5
|
+
|
6
|
+
# HTTP/1.x has no packet format. So we make HTTP header and content pretend to be packet
|
7
|
+
#
|
8
|
+
# From RFC2616
|
9
|
+
# generic-message : start-line
|
10
|
+
# (message-header CRLF)*
|
11
|
+
# CRLF
|
12
|
+
# [message-body]
|
13
|
+
#
|
14
|
+
#
|
15
|
+
#
|
16
|
+
module Baykit
|
17
|
+
module BayServer
|
18
|
+
module Docker
|
19
|
+
module Http
|
20
|
+
module H1
|
21
|
+
class H1PacketUnPacker < Baykit::BayServer::Protocol::PacketUnPacker
|
22
|
+
|
23
|
+
include Baykit::BayServer::Agent
|
24
|
+
include Baykit::BayServer::Protocol
|
25
|
+
include Baykit::BayServer::Docker::Http
|
26
|
+
include Baykit::BayServer::Util
|
27
|
+
|
28
|
+
STATE_READ_HEADERS = 1
|
29
|
+
STATE_READ_CONTENT = 2
|
30
|
+
STATE_END = 3
|
31
|
+
|
32
|
+
MAX_LINE_LEN = 8192
|
33
|
+
|
34
|
+
attr :state
|
35
|
+
attr :cmd_upacker
|
36
|
+
attr :pkt_store
|
37
|
+
attr :tmp_buf
|
38
|
+
|
39
|
+
def initialize(cmd_upacker, pkt_store)
|
40
|
+
@cmd_upacker = cmd_upacker
|
41
|
+
@pkt_store = pkt_store
|
42
|
+
@tmp_buf = SimpleBuffer.new()
|
43
|
+
reset_state()
|
44
|
+
end
|
45
|
+
|
46
|
+
######################################################
|
47
|
+
# implements Reusable
|
48
|
+
######################################################
|
49
|
+
|
50
|
+
def reset()
|
51
|
+
reset_state()
|
52
|
+
end
|
53
|
+
|
54
|
+
######################################################
|
55
|
+
# Other methods
|
56
|
+
######################################################
|
57
|
+
|
58
|
+
def bytes_received(buf)
|
59
|
+
if @state == STATE_END
|
60
|
+
reset
|
61
|
+
raise RuntimeError.new("IllegalState")
|
62
|
+
end
|
63
|
+
|
64
|
+
BayLog.debug("H1: bytes_received len=%d", buf.length)
|
65
|
+
pos = 0
|
66
|
+
buf_start = 0
|
67
|
+
line_len = 0
|
68
|
+
suspend = false
|
69
|
+
|
70
|
+
if @state == STATE_READ_HEADERS
|
71
|
+
while pos < buf.length
|
72
|
+
b = buf[pos]
|
73
|
+
@tmp_buf.put_byte(b)
|
74
|
+
pos += 1
|
75
|
+
#@BayServer.info b + " " + b.codepoints[0].to_s + " pos=" + pos.to_s
|
76
|
+
if b == CharUtil::CR
|
77
|
+
next
|
78
|
+
elsif b == CharUtil::LF
|
79
|
+
if line_len == 0
|
80
|
+
# empty line (all headers are read)
|
81
|
+
pkt = @pkt_store.rent(H1Type::HEADER)
|
82
|
+
pkt.new_data_accessor.put_bytes(@tmp_buf.bytes, 0, @tmp_buf.length)
|
83
|
+
|
84
|
+
begin
|
85
|
+
next_act = @cmd_upacker.packet_received(pkt)
|
86
|
+
ensure
|
87
|
+
@pkt_store.Return pkt
|
88
|
+
end
|
89
|
+
|
90
|
+
case next_act
|
91
|
+
when NextSocketAction::CONTINUE, NextSocketAction::SUSPEND
|
92
|
+
if @cmd_upacker.finished()
|
93
|
+
change_state(STATE_END)
|
94
|
+
else
|
95
|
+
change_state(STATE_READ_CONTENT)
|
96
|
+
end
|
97
|
+
when NextSocketAction::CLOSE
|
98
|
+
# Maybe error
|
99
|
+
reset_state()
|
100
|
+
return next_act
|
101
|
+
else
|
102
|
+
raise RuntimeError.new("Invalid next action: #{next_act}")
|
103
|
+
end
|
104
|
+
|
105
|
+
suspend = (next_act == NextSocketAction::SUSPEND)
|
106
|
+
break
|
107
|
+
end
|
108
|
+
line_len = 0
|
109
|
+
else
|
110
|
+
line_len += 1
|
111
|
+
end
|
112
|
+
if line_len >= MAX_LINE_LEN
|
113
|
+
raise ProtocolException.new("Http/1 Line is too long")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if @state == STATE_READ_CONTENT
|
119
|
+
while pos < buf.length
|
120
|
+
pkt = @pkt_store.rent(H1Type::CONTENT)
|
121
|
+
|
122
|
+
len = buf.length - pos
|
123
|
+
if len > H1Packet::MAX_DATA_LEN
|
124
|
+
len = H1Packet::MAX_DATA_LEN
|
125
|
+
end
|
126
|
+
|
127
|
+
#BayLog.debug("remain=#{buf.length - pos} len=#{len}")
|
128
|
+
pkt.new_data_accessor.put_bytes(buf, pos, len)
|
129
|
+
pos += len
|
130
|
+
|
131
|
+
begin
|
132
|
+
next_act = @cmd_upacker.packet_received(pkt)
|
133
|
+
ensure
|
134
|
+
@pkt_store.Return(pkt)
|
135
|
+
end
|
136
|
+
|
137
|
+
case next_act
|
138
|
+
when NextSocketAction::CONTINUE
|
139
|
+
if @cmd_upacker.finished()
|
140
|
+
change_state(STATE_END)
|
141
|
+
end
|
142
|
+
when NextSocketAction::SUSPEND
|
143
|
+
suspend = true
|
144
|
+
when NextSocketAction::CLOSE
|
145
|
+
reset_state
|
146
|
+
return next_act
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
if @state == STATE_END
|
152
|
+
reset_state()
|
153
|
+
end
|
154
|
+
|
155
|
+
if suspend
|
156
|
+
BayLog.debug("H1 Read suspend")
|
157
|
+
return NextSocketAction::SUSPEND
|
158
|
+
else
|
159
|
+
return NextSocketAction::CONTINUE
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
def change_state new_state
|
167
|
+
@state = new_state
|
168
|
+
end
|
169
|
+
|
170
|
+
def reset_state
|
171
|
+
change_state STATE_READ_HEADERS
|
172
|
+
@tmp_buf.reset()
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/protocol_handler'
|
2
|
+
require 'baykit/bayserver/protocol/packet_store'
|
3
|
+
require 'baykit/bayserver/util/headers'
|
4
|
+
require 'baykit/bayserver/docker/http/h1/command/package'
|
5
|
+
require 'baykit/bayserver/docker/http/h1/h1_packet'
|
6
|
+
|
7
|
+
module Baykit
|
8
|
+
module BayServer
|
9
|
+
module Docker
|
10
|
+
module Http
|
11
|
+
module H1
|
12
|
+
class H1ProtocolHandler < Baykit::BayServer::Protocol::ProtocolHandler
|
13
|
+
include Baykit::BayServer::Docker::Http::H1::H1CommandHandler # implements
|
14
|
+
|
15
|
+
include Baykit::BayServer::Agent
|
16
|
+
include Baykit::BayServer::Protocol
|
17
|
+
include Baykit::BayServer::Util
|
18
|
+
include Baykit::BayServer::Docker::Http::H1
|
19
|
+
include Baykit::BayServer::Docker::Http::H1::Command
|
20
|
+
|
21
|
+
attr :keeping
|
22
|
+
|
23
|
+
def initialize(pkt_store, svr_mode)
|
24
|
+
@command_unpacker = H1CommandUnPacker.new(self, svr_mode)
|
25
|
+
@packet_unpacker = H1PacketUnPacker.new(@command_unpacker, pkt_store)
|
26
|
+
@packet_packer = PacketPacker.new()
|
27
|
+
@command_packer = CommandPacker.new(@packet_packer, pkt_store)
|
28
|
+
@server_mode = svr_mode
|
29
|
+
@keeping = false
|
30
|
+
end
|
31
|
+
|
32
|
+
def inspect()
|
33
|
+
return @ship.inspect()
|
34
|
+
end
|
35
|
+
|
36
|
+
######################################################
|
37
|
+
# Implements Reusable
|
38
|
+
######################################################
|
39
|
+
|
40
|
+
def reset
|
41
|
+
super
|
42
|
+
@keeping = false
|
43
|
+
end
|
44
|
+
|
45
|
+
######################################################
|
46
|
+
# Implements ProtocolHandler
|
47
|
+
######################################################
|
48
|
+
|
49
|
+
def max_req_packet_data_size
|
50
|
+
return H1Packet::MAX_DATA_LEN
|
51
|
+
end
|
52
|
+
|
53
|
+
def max_res_packet_data_size
|
54
|
+
return H1Packet::MAX_DATA_LEN
|
55
|
+
end
|
56
|
+
|
57
|
+
def protocol
|
58
|
+
return HtpPortDocker::H1_PROTO_NAME
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|