bayserver-docker-fcgi 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/fcgi/command/cmd_begin_request.rb +66 -0
- data/lib/baykit/bayserver/docker/fcgi/command/cmd_end_request.rb +66 -0
- data/lib/baykit/bayserver/docker/fcgi/command/cmd_params.rb +160 -0
- data/lib/baykit/bayserver/docker/fcgi/command/cmd_stderr.rb +31 -0
- data/lib/baykit/bayserver/docker/fcgi/command/cmd_stdin.rb +33 -0
- data/lib/baykit/bayserver/docker/fcgi/command/cmd_stdout.rb +31 -0
- data/lib/baykit/bayserver/docker/fcgi/command/in_out_command_base.rb +57 -0
- data/lib/baykit/bayserver/docker/fcgi/command/package.rb +6 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_command.rb +40 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_command_handler.rb +24 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_command_unpacker.rb +56 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_docker.rb +14 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_inbound_handler.rb +354 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_packet.rb +56 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_packet_factory.rb +17 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_packet_unpacker.rb +201 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_params.rb +46 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_port_docker.rb +52 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_protocol_handler.rb +54 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_type.rb +23 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_warp_docker.rb +81 -0
- data/lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb +324 -0
- data/lib/baykit/bayserver/docker/fcgi/package.rb +12 -0
- metadata +79 -0
@@ -0,0 +1,354 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/protocol_exception'
|
2
|
+
require 'baykit/bayserver/docker/base/inbound_handler'
|
3
|
+
require 'baykit/bayserver/tours/req_content_handler'
|
4
|
+
require 'baykit/bayserver/util/cgi_util'
|
5
|
+
|
6
|
+
require 'baykit/bayserver/docker/fcgi/fcg_protocol_handler'
|
7
|
+
|
8
|
+
module Baykit
|
9
|
+
module BayServer
|
10
|
+
module Docker
|
11
|
+
module Fcgi
|
12
|
+
class FcgInboundHandler < Baykit::BayServer::Docker::Fcgi::FcgProtocolHandler
|
13
|
+
|
14
|
+
class InboundProtocolHandlerFactory
|
15
|
+
include Baykit::BayServer::Protocol::ProtocolHandlerFactory # implements
|
16
|
+
|
17
|
+
def create_protocol_handler(pkt_store)
|
18
|
+
return FcgInboundHandler.new(pkt_store)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
include Baykit::BayServer::Docker::Base::InboundHandler # implements
|
23
|
+
include Baykit::BayServer::Agent
|
24
|
+
include Baykit::BayServer::Tours
|
25
|
+
include Baykit::BayServer::Protocol
|
26
|
+
include Baykit::BayServer::Util
|
27
|
+
|
28
|
+
STATE_BEGIN_REQUEST = 1
|
29
|
+
STATE_READ_PARAMS = 2
|
30
|
+
STATE_READ_STDIN = 3
|
31
|
+
|
32
|
+
attr :state
|
33
|
+
attr :cont_len
|
34
|
+
|
35
|
+
attr :env
|
36
|
+
attr :req_id
|
37
|
+
attr :req_keep_alive
|
38
|
+
|
39
|
+
def initialize(pkt_store)
|
40
|
+
super(pkt_store, true)
|
41
|
+
@env = {}
|
42
|
+
reset_state()
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s()
|
46
|
+
return ClassUtil.get_local_name(self.class)
|
47
|
+
end
|
48
|
+
|
49
|
+
######################################################
|
50
|
+
# implements Reusable
|
51
|
+
######################################################
|
52
|
+
def reset
|
53
|
+
super
|
54
|
+
@env.clear()
|
55
|
+
reset_state()
|
56
|
+
end
|
57
|
+
|
58
|
+
######################################################
|
59
|
+
# implements InboundHandler
|
60
|
+
######################################################
|
61
|
+
|
62
|
+
def send_res_headers(tur)
|
63
|
+
BayLog.debug("%s PH:sendHeaders: tur=%s", @ship, tur)
|
64
|
+
|
65
|
+
scode = tur.res.headers.status
|
66
|
+
status = "#{scode} #{HttpStatus.description(scode)}"
|
67
|
+
tur.res.headers.set(Headers::STATUS, status)
|
68
|
+
|
69
|
+
if BayServer.harbor.trace_header?
|
70
|
+
BayLog.info("%s resStatus:%d", tur, tur.res.headers.status)
|
71
|
+
tur.res.headers.names().each do |name|
|
72
|
+
tur.res.headers.values(name) do |value|
|
73
|
+
BayLog.info("%s resHeader:%s=%s", tur, name, value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
buf = SimpleBuffer.new
|
79
|
+
HttpUtil.send_mime_headers(tur.res.headers, buf)
|
80
|
+
HttpUtil.send_new_line(buf)
|
81
|
+
cmd = CmdStdOut.new(tur.req.key, buf.buf, 0, buf.length)
|
82
|
+
@command_packer.post(@ship, cmd)
|
83
|
+
end
|
84
|
+
|
85
|
+
def send_res_content(tur, bytes, ofs, len, &callback)
|
86
|
+
cmd = CmdStdOut.new(tur.req.key, bytes, ofs, len);
|
87
|
+
@command_packer.post(@ship, cmd, &callback)
|
88
|
+
end
|
89
|
+
|
90
|
+
def send_end_tour(tur, keep_alive, &callback)
|
91
|
+
BayLog.debug("%s PH:endTour: tur=%s keep=%s", @ship, tur, keep_alive)
|
92
|
+
|
93
|
+
# Send empty stdout command
|
94
|
+
cmd = CmdStdOut.new(tur.req.key)
|
95
|
+
@command_packer.post(@ship, cmd)
|
96
|
+
|
97
|
+
# Send end request command
|
98
|
+
cmd = CmdEndRequest.new(tur.req.key)
|
99
|
+
|
100
|
+
ensure_func = lambda do
|
101
|
+
if !keep_alive
|
102
|
+
@command_packer.end(@ship)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
begin
|
107
|
+
@command_packer.post(@ship, cmd) do
|
108
|
+
BayLog.debug("%s call back in sendEndTour: tur=%s keep=%s", self, tur, keep_alive)
|
109
|
+
ensure_func.call()
|
110
|
+
callback.call()
|
111
|
+
end
|
112
|
+
rescue IOError => e
|
113
|
+
BayLog.debug("%s post failed in sendEndTour: tur=%s keep=%s", self, tur, keep_alive)
|
114
|
+
ensure_func.call()
|
115
|
+
raise e
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def send_req_protocol_error(err)
|
120
|
+
tur = @ship.get_error_tour()
|
121
|
+
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus::BAD_REQUEST, err.message, err)
|
122
|
+
true
|
123
|
+
end
|
124
|
+
|
125
|
+
######################################################
|
126
|
+
# implements FcgCommandHandler
|
127
|
+
######################################################
|
128
|
+
def handle_begin_request(cmd)
|
129
|
+
sip = ship()
|
130
|
+
BayLog.debug("%s handle_begin_request req_id=%d} keep=%s", sip, cmd.req_id, cmd.keep_conn)
|
131
|
+
|
132
|
+
if state != STATE_BEGIN_REQUEST
|
133
|
+
raise ProtocolException.new("Invalid FCGI command: %d state=%d", cmd.type, @state)
|
134
|
+
end
|
135
|
+
|
136
|
+
check_req_id(cmd.req_id)
|
137
|
+
|
138
|
+
@req_id = cmd.req_id
|
139
|
+
BayLog.debug("%s begin_req get_tour req_id=%d", sip, cmd.req_id)
|
140
|
+
tur = sip.get_tour(cmd.req_id)
|
141
|
+
if tur == nil
|
142
|
+
BayLog.error(BayMessage.get(:INT_NO_MORE_TOURS))
|
143
|
+
tur = sip.ship.get_tour(cmd.req_id, true)
|
144
|
+
tur.res.send_error(Tour::TOUR_ID_NOCHECK, HttpStatus.SERVICE_UNAVAILABLE, "No available tours")
|
145
|
+
sip.agent.shutdown(false)
|
146
|
+
return NextSocketAction::CONTINUE
|
147
|
+
end
|
148
|
+
|
149
|
+
@req_keep_alive = cmd.keep_conn
|
150
|
+
change_state(STATE_READ_PARAMS)
|
151
|
+
NextSocketAction::CONTINUE
|
152
|
+
end
|
153
|
+
|
154
|
+
def handle_end_request(cmd)
|
155
|
+
raise ProtocolException("Invalid FCGI command: %d", cmd.type)
|
156
|
+
end
|
157
|
+
|
158
|
+
def handle_params(cmd)
|
159
|
+
BayLog.debug("%s handle_params req_id=%d", @ship, cmd.req_id)
|
160
|
+
|
161
|
+
if state != STATE_READ_PARAMS
|
162
|
+
raise ProtocolException.new("Invalid FCGI command: %d state=%d", cmd.type, @state)
|
163
|
+
end
|
164
|
+
|
165
|
+
check_req_id(cmd.req_id)
|
166
|
+
|
167
|
+
BayLog.debug("%s handle_param get_tour req_id=%d", @ship, cmd.req_id)
|
168
|
+
tur = @ship.get_tour(cmd.req_id)
|
169
|
+
|
170
|
+
if cmd.params.empty?
|
171
|
+
# Header completed
|
172
|
+
|
173
|
+
# check keep-alive
|
174
|
+
# keep-alive flag of BeginRequest has high priority
|
175
|
+
if @req_keep_alive
|
176
|
+
if !tur.req.headers.contains(Headers::CONNECTION)
|
177
|
+
tur.req.headers.set(Headers::CONNECTION, "Keep-Alive")
|
178
|
+
else
|
179
|
+
tur.req.headers.set(Headers::CONNECTION, "Close")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
req_cont_len = tur.req.headers.content_length()
|
184
|
+
|
185
|
+
BayLog.debug("%s read header method=%s protocol=%s uri=%s contlen=%d",
|
186
|
+
@ship, tur.req.method, tur.req.protocol, tur.req.uri, @cont_len)
|
187
|
+
|
188
|
+
if BayServer.harbor.trace_header?
|
189
|
+
cmd.params.each do |nv|
|
190
|
+
BayLog.info("%s reqHeader: %s=%s", tur, nv[0], nv[1])
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
if req_cont_len > 0
|
195
|
+
tur.req.set_consume_listener(req_cont_len) do |len, resume|
|
196
|
+
sid = @ship.ship_id
|
197
|
+
if resume
|
198
|
+
@ship.resume(sid)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
change_state(STATE_READ_STDIN)
|
204
|
+
begin
|
205
|
+
start_tour(tur)
|
206
|
+
rescue HttpException => e
|
207
|
+
BayLog.debug("%s Http error occurred: %s", @ship, e)
|
208
|
+
|
209
|
+
if req_cont_len <= 0
|
210
|
+
# no post data
|
211
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
212
|
+
change_state(STATE_READ_STDIN)
|
213
|
+
return NextSocketAction::CONTINUE
|
214
|
+
else
|
215
|
+
# Delay send
|
216
|
+
change_state(STATE_READ_STDIN)
|
217
|
+
tur.error = e
|
218
|
+
tur.req.set_content_handler(ReqContentHandler.dev_null())
|
219
|
+
return NextSocketAction::CONTINUE
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
else
|
224
|
+
if BayServer.harbor.trace_header?
|
225
|
+
BayLog.info("%s Read FcgiParam", tur)
|
226
|
+
end
|
227
|
+
|
228
|
+
cmd.params.each do |nv|
|
229
|
+
name = nv[0]
|
230
|
+
value = nv[1]
|
231
|
+
if BayServer.harbor.trace_header?
|
232
|
+
BayLog.info("%s param: %s=%s", tur, name, value);
|
233
|
+
end
|
234
|
+
@env[name] = value
|
235
|
+
|
236
|
+
if name.start_with?("HTTP_")
|
237
|
+
hname = name[5 .. -1]
|
238
|
+
tur.req.headers.add(hname, value)
|
239
|
+
elsif name == "CONTENT_TYPE"
|
240
|
+
tur.req.headers.add(Headers::CONTENT_TYPE, value)
|
241
|
+
elsif name == "CONTENT_LENGTH"
|
242
|
+
tur.req.headers.add(Headers::CONTENT_LENGTH, value)
|
243
|
+
elsif name == "HTTPS"
|
244
|
+
tur.is_secure = value.downcase.casecmp? "on"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
tur.req.uri = @env["REQUEST_URI"]
|
249
|
+
tur.req.protocol = @env["SERVER_PROTOCOL"]
|
250
|
+
tur.req.method = @env["REQUEST_METHOD"]
|
251
|
+
|
252
|
+
return NextSocketAction::CONTINUE
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def handle_stderr(cmd)
|
257
|
+
raise ProtocolException.new("Invalid FCGI command: %d", cmd.type)
|
258
|
+
end
|
259
|
+
|
260
|
+
def handle_stdin(cmd)
|
261
|
+
BayLog.debug("%s handle_stdin req_id=%d len=%d", @ship, cmd.req_id, cmd.length)
|
262
|
+
|
263
|
+
if @state != STATE_READ_STDIN
|
264
|
+
raise ProtocolException.new("Invalid FCGI command: %d state=%d", cmd.type, @state)
|
265
|
+
end
|
266
|
+
|
267
|
+
check_req_id(cmd.req_id)
|
268
|
+
|
269
|
+
tur = @ship.get_tour(cmd.req_id)
|
270
|
+
if cmd.length == 0
|
271
|
+
# request content completed
|
272
|
+
if tur.error != nil
|
273
|
+
# Error has occurred on header completed
|
274
|
+
tur.res.set_consume_listener do |len, resume|
|
275
|
+
end
|
276
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, tur.error)
|
277
|
+
reset_state()
|
278
|
+
return NextSocketAction::WRITE
|
279
|
+
else
|
280
|
+
begin
|
281
|
+
end_req_content(Tour::TOUR_ID_NOCHECK, tur)
|
282
|
+
return NextSocketAction::CONTINUE
|
283
|
+
rescue HttpException => e
|
284
|
+
tur.res.send_http_exception(Tour::TOUR_ID_NOCHECK, e)
|
285
|
+
return NextSocketAction::WRITE
|
286
|
+
end
|
287
|
+
end
|
288
|
+
else
|
289
|
+
success = tur.req.post_content(Tour::TOUR_ID_NOCHECK, cmd.data, cmd.start, cmd.length)
|
290
|
+
|
291
|
+
if !success
|
292
|
+
return NextSocketAction::SUSPEND
|
293
|
+
else
|
294
|
+
return NextSocketAction::CONTINUE
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def handle_stdout(cmd)
|
300
|
+
raise ProtocolException.new("Invalid FCGI command: %d", cmd.type)
|
301
|
+
end
|
302
|
+
|
303
|
+
private
|
304
|
+
def check_req_id(received_id)
|
305
|
+
if received_id == FcgPacket::FCGI_NULL_REQUEST_ID
|
306
|
+
raise ProtocolException.new("Invalid request id: %d", received_id)
|
307
|
+
end
|
308
|
+
|
309
|
+
if @req_id == FcgPacket::FCGI_NULL_REQUEST_ID
|
310
|
+
@req_id = received_id
|
311
|
+
end
|
312
|
+
|
313
|
+
if @req_id != received_id
|
314
|
+
BayLog.error("%s invalid request id: received=%d reqId=%d", @ship, received_id, req_id)
|
315
|
+
raise ProtocolException.new("Invalid request id: %d", received_id)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def change_state(new_state)
|
320
|
+
@state = new_state
|
321
|
+
end
|
322
|
+
|
323
|
+
def reset_state
|
324
|
+
change_state(STATE_BEGIN_REQUEST)
|
325
|
+
@req_id = FcgPacket::FCGI_NULL_REQUEST_ID
|
326
|
+
@cont_len = 0
|
327
|
+
end
|
328
|
+
|
329
|
+
def end_req_content(check_id, tur)
|
330
|
+
tur.req.end_content(check_id)
|
331
|
+
reset_state()
|
332
|
+
end
|
333
|
+
|
334
|
+
def start_tour(tur)
|
335
|
+
HttpUtil.parse_host_port(tur, tur.is_secure ? 443 : 80)
|
336
|
+
HttpUtil.parse_authorization(tur)
|
337
|
+
|
338
|
+
tur.req.remote_port = @env[CgiUtil::REMOTE_PORT].to_i
|
339
|
+
tur.req.remote_address = @env[CgiUtil::REMOTE_ADDR]
|
340
|
+
tur.req.remote_host_func = lambda { @req_command.remote_host }
|
341
|
+
|
342
|
+
tur.req.server_name = @env[CgiUtil::SERVER_NAME]
|
343
|
+
tur.req.server_address = @env[CgiUtil::SERVER_ADDR]
|
344
|
+
tur.req.server_port = @env[CgiUtil::SERVER_PORT].to_i
|
345
|
+
|
346
|
+
|
347
|
+
tur.go
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/packet'
|
2
|
+
|
3
|
+
#
|
4
|
+
# FCGI spec
|
5
|
+
# http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html
|
6
|
+
#
|
7
|
+
# FCGI Packet (Record) format
|
8
|
+
# typedef struct {
|
9
|
+
# unsigned char version;
|
10
|
+
# unsigned char type;
|
11
|
+
# unsigned char requestIdB1;
|
12
|
+
# unsigned char requestIdB0;
|
13
|
+
# unsigned char contentLengthB1;
|
14
|
+
# unsigned char contentLengthB0;
|
15
|
+
# unsigned char paddingLength;
|
16
|
+
# unsigned char reserved;
|
17
|
+
# unsigned char contentData[contentLength];
|
18
|
+
# unsigned char paddingData[paddingLength];
|
19
|
+
# } FCGI_Record;
|
20
|
+
#
|
21
|
+
module Baykit
|
22
|
+
module BayServer
|
23
|
+
module Docker
|
24
|
+
module Fcgi
|
25
|
+
class FcgPacket < Baykit::BayServer::Protocol::Packet
|
26
|
+
|
27
|
+
PREAMBLE_SIZE = 8
|
28
|
+
|
29
|
+
VERSION = 1
|
30
|
+
MAXLEN = 65535
|
31
|
+
|
32
|
+
FCGI_NULL_REQUEST_ID = 0
|
33
|
+
|
34
|
+
attr :version
|
35
|
+
attr_accessor :req_id
|
36
|
+
|
37
|
+
def initialize(type)
|
38
|
+
super(type, PREAMBLE_SIZE, MAXLEN)
|
39
|
+
@version = VERSION
|
40
|
+
end
|
41
|
+
|
42
|
+
def reset()
|
43
|
+
super
|
44
|
+
@version = VERSION
|
45
|
+
@req_id = 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
"FcgPacket(#{@type}) id=#{@req_id}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/packet_factory'
|
2
|
+
|
3
|
+
module Baykit
|
4
|
+
module BayServer
|
5
|
+
module Docker
|
6
|
+
module Fcgi
|
7
|
+
class FcgPacketFactory < Baykit::BayServer::Protocol::PacketFactory
|
8
|
+
|
9
|
+
def create_packet(type)
|
10
|
+
FcgPacket.new(type)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'baykit/bayserver/protocol/packet_unpacker'
|
2
|
+
require 'baykit/bayserver/util/simple_buffer'
|
3
|
+
require 'baykit/bayserver/agent/next_socket_action'
|
4
|
+
|
5
|
+
|
6
|
+
module Baykit
|
7
|
+
module BayServer
|
8
|
+
module Docker
|
9
|
+
module Fcgi
|
10
|
+
class FcgPacketUnPacker < Baykit::BayServer::Protocol::PacketUnPacker
|
11
|
+
include Baykit::BayServer::Util
|
12
|
+
include Baykit::BayServer::Agent
|
13
|
+
|
14
|
+
attr :header_buf
|
15
|
+
attr :data_buf
|
16
|
+
|
17
|
+
attr :version
|
18
|
+
attr :type
|
19
|
+
attr :req_id
|
20
|
+
attr :length
|
21
|
+
attr :padding
|
22
|
+
attr :padding_read_bytes
|
23
|
+
|
24
|
+
STATE_REQD_PREAMBLE = 1 # #state for reading first 8 bytes (from version to reserved)
|
25
|
+
STATE_READ_CONTENT = 2 #state for reading content data
|
26
|
+
STATE_READ_PADDING = 3 # state for reading padding data
|
27
|
+
STATE_END = 4 # End
|
28
|
+
|
29
|
+
attr :state
|
30
|
+
|
31
|
+
attr :cmd_unpacker
|
32
|
+
attr :pkt_store
|
33
|
+
attr :cont_len
|
34
|
+
attr :read_bytes
|
35
|
+
|
36
|
+
def initialize(pkt_store, cmd_unpacker)
|
37
|
+
@cmd_unpacker = cmd_unpacker
|
38
|
+
@pkt_store = pkt_store
|
39
|
+
@header_buf = SimpleBuffer.new
|
40
|
+
@data_buf = SimpleBuffer.new
|
41
|
+
reset()
|
42
|
+
end
|
43
|
+
|
44
|
+
def reset
|
45
|
+
@state = STATE_REQD_PREAMBLE
|
46
|
+
@version = 0
|
47
|
+
@type = nil
|
48
|
+
@req_id = 0
|
49
|
+
@length = 0
|
50
|
+
@padding = 0
|
51
|
+
@padding_read_bytes = 0
|
52
|
+
@cont_len = 0
|
53
|
+
@read_bytes = 0
|
54
|
+
@header_buf.reset
|
55
|
+
@data_buf.reset
|
56
|
+
end
|
57
|
+
|
58
|
+
def bytes_received(buf)
|
59
|
+
next_suspend = false
|
60
|
+
next_write = false
|
61
|
+
pos = 0
|
62
|
+
|
63
|
+
while pos < buf.length
|
64
|
+
while @state != STATE_END && pos < buf.length
|
65
|
+
|
66
|
+
case @state
|
67
|
+
|
68
|
+
when STATE_REQD_PREAMBLE
|
69
|
+
# preamble read mode
|
70
|
+
len = FcgPacket::PREAMBLE_SIZE - @header_buf.length
|
71
|
+
if buf.length - pos < len
|
72
|
+
len = buf.length - pos
|
73
|
+
end
|
74
|
+
|
75
|
+
@header_buf.put(buf, pos, len)
|
76
|
+
pos += len
|
77
|
+
|
78
|
+
if @header_buf.length == FcgPacket::PREAMBLE_SIZE
|
79
|
+
header_read_done()
|
80
|
+
if @length == 0
|
81
|
+
if @padding == 0
|
82
|
+
change_state(STATE_END)
|
83
|
+
else
|
84
|
+
change_state(STATE_READ_PADDING)
|
85
|
+
end
|
86
|
+
else
|
87
|
+
change_state(STATE_READ_CONTENT)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
when STATE_READ_CONTENT
|
92
|
+
# content read mode
|
93
|
+
len = @length - @data_buf.length
|
94
|
+
if len > buf.length - pos
|
95
|
+
len = buf.length - pos
|
96
|
+
end
|
97
|
+
|
98
|
+
if len > 0
|
99
|
+
@data_buf.put(buf, pos, len)
|
100
|
+
pos += len
|
101
|
+
|
102
|
+
if @data_buf.length == @length
|
103
|
+
if @padding == 0
|
104
|
+
change_state(STATE_END)
|
105
|
+
else
|
106
|
+
change_state(STATE_READ_PADDING)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
when STATE_READ_PADDING
|
112
|
+
# padding read mode
|
113
|
+
len = @padding - @padding_read_bytes
|
114
|
+
|
115
|
+
if len > buf.length - pos
|
116
|
+
len = buf.length - pos
|
117
|
+
end
|
118
|
+
|
119
|
+
#@data_buf.put(buf, pos, len)
|
120
|
+
pos += len
|
121
|
+
|
122
|
+
if len > 0
|
123
|
+
@padding_read_bytes += len
|
124
|
+
|
125
|
+
if @padding_read_bytes == @padding
|
126
|
+
change_state(STATE_END)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
else
|
131
|
+
raise RuntimeError.new("IllegalState")
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
if state == STATE_END
|
137
|
+
pkt = @pkt_store.rent(@type)
|
138
|
+
pkt.req_id = @req_id
|
139
|
+
pkt.new_header_accessor.put_bytes(@header_buf.buf, 0, @header_buf.length)
|
140
|
+
pkt.new_data_accessor.put_bytes(@data_buf.buf, 0, @data_buf.length)
|
141
|
+
|
142
|
+
begin
|
143
|
+
state = @cmd_unpacker.packet_received(pkt)
|
144
|
+
ensure
|
145
|
+
@pkt_store.Return(pkt)
|
146
|
+
end
|
147
|
+
|
148
|
+
reset()
|
149
|
+
|
150
|
+
case state
|
151
|
+
when NextSocketAction::SUSPEND
|
152
|
+
next_suspend = true
|
153
|
+
when NextSocketAction::CONTINUE
|
154
|
+
nil
|
155
|
+
when NextSocketAction::WRITE
|
156
|
+
next_write = true
|
157
|
+
when NextSocketAction::CLOSE
|
158
|
+
return state
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
if next_write
|
165
|
+
return NextSocketAction::WRITE
|
166
|
+
elsif next_suspend
|
167
|
+
return NextSocketAction::SUSPEND
|
168
|
+
else
|
169
|
+
return NextSocketAction::CONTINUE
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def change_state(new_state)
|
174
|
+
@state = new_state
|
175
|
+
end
|
176
|
+
|
177
|
+
def header_read_done
|
178
|
+
pre = @header_buf.buf.codepoints
|
179
|
+
@version = byte_to_int(pre[0])
|
180
|
+
@type = byte_to_int(pre[1])
|
181
|
+
@req_id = bytes_to_int(pre[2], pre[3])
|
182
|
+
@length = bytes_to_int(pre[4], pre[5])
|
183
|
+
@padding = byte_to_int(pre[6])
|
184
|
+
reserved = byte_to_int(pre[7])
|
185
|
+
BayLog.debug("fcg: read packet header: version=%s type=%d reqId=%d length=%d padding=%d",
|
186
|
+
@version, @type, @req_id, @length, @padding)
|
187
|
+
end
|
188
|
+
|
189
|
+
def byte_to_int(b)
|
190
|
+
return b & 0xff
|
191
|
+
end
|
192
|
+
|
193
|
+
def bytes_to_int(b1, b2)
|
194
|
+
return byte_to_int(b1) << 8 | byte_to_int(b2)
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Baykit
|
2
|
+
module BayServer
|
3
|
+
module Docker
|
4
|
+
module Fcgi
|
5
|
+
class FcgParams
|
6
|
+
PATH = "PATH"
|
7
|
+
CONTEXT_DOCUMENT_ROOT = "CONTEXT_DOCUMENT_ROOT"
|
8
|
+
CONTEXT_PREFIX = "CONTEXT_PREFIX"
|
9
|
+
CONTENT_TYPE = "CONTENT_TYPE"
|
10
|
+
CONTENT_LENGTH = "CONTENT_LENGTH"
|
11
|
+
DOCUMENT_ROOT = "DOCUMENT_ROOT"
|
12
|
+
GATEWAY_INTERFACE = "GATEWAY_INTERFACE"
|
13
|
+
HTTP_ACCEPT = "HTTP_ACCEPT"
|
14
|
+
HTTP_ACCEPT_ENCODING = "HTTP_ACCEPT_ENCODING"
|
15
|
+
HTTP_ACCEPT_LANGUAGE = "HTTP_ACCEPT_LANGUAGE"
|
16
|
+
HTTP_CACHE_CONTROL = "HTTP_CACHE_CONTROL"
|
17
|
+
HTTP_COOKIE = "HTTP_COOKIE"
|
18
|
+
HTTP_CONNECTION = "HTTP_CONNECTION"
|
19
|
+
HTTP_HOST= "HTTP_HOST"
|
20
|
+
HTTP_USER_AGENT = "HTTP_USER_AGENT"
|
21
|
+
HTTP_UPGRADE_INSECURE_REQUESTS = "HTTP_UPGRADE_INSECURE_REQUESTS"
|
22
|
+
QUERY_STRING = "QUERY_STRING"
|
23
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
24
|
+
REQUEST_SCHEME = "REQUEST_SCHEME"
|
25
|
+
REQUEST_URI = "REQUEST_URI"
|
26
|
+
REMOTE_PORT = "REMOTE_PORT"
|
27
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
28
|
+
SCRIPT_NAME = "SCRIPT_NAME"
|
29
|
+
SCRIPT_FILENAME = "SCRIPT_FILENAME"
|
30
|
+
SERVER_ADDR = "SERVER_ADDR"
|
31
|
+
SERVER_ADMIN = "SERVER_ADMIN"
|
32
|
+
SERVER_NAME = "SERVER_NAME"
|
33
|
+
SERVER_PORT = "SERVER_PORT"
|
34
|
+
SERVER_PROTOCOL = "SERVER_PROTOCOL"
|
35
|
+
SERVER_SIGNATURE = "SERVER_SIGNATURE"
|
36
|
+
SERVER_SOFTWARE = "SERVER_SOFTWARE"
|
37
|
+
UNIQUE_ID = "UNIQUE_ID"
|
38
|
+
X_FORWARDED_FOR = "X-Forwarded-For"
|
39
|
+
X_FORWARDED_PROTO = "X-Forwarded-Proto"
|
40
|
+
X_FORWARDED_PORT = "X-Forwarded-Port"
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|