bayserver-docker-http 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|