Class: Baykit::BayServer::Docker::Fcgi::FcgWarpHandler

Inherits:
Object
  • Object
show all
Includes:
Agent, Common, Common::WarpHandler, Command, FcgHandler, Protocol, Tours, Util
Defined in:
lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb

Defined Under Namespace

Classes: WarpProtocolHandlerFactory

Constant Summary collapse

STATE_READ_HEADER =
1
STATE_READ_CONTENT =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFcgWarpHandler

Returns a new instance of FcgWarpHandler.



61
62
63
64
65
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 61

def initialize
  @cur_warp_id = 0
  @line_buf = SimpleBuffer.new
  reset()
end

Instance Attribute Details

#cur_warp_idObject (readonly)

Returns the value of attribute cur_warp_id.



53
54
55
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 53

def cur_warp_id
  @cur_warp_id
end

#dataObject (readonly)

Returns the value of attribute data.



59
60
61
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 59

def data
  @data
end

#lastObject (readonly)

Returns the value of attribute last.



58
59
60
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 58

def last
  @last
end

#line_bufObject (readonly)

Returns the value of attribute line_buf.



55
56
57
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 55

def line_buf
  @line_buf
end

#posObject (readonly)

Returns the value of attribute pos.



57
58
59
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 57

def pos
  @pos
end

#protocol_handlerObject (readonly)

Returns the value of attribute protocol_handler.



52
53
54
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 52

def protocol_handler
  @protocol_handler
end

#stateObject (readonly)

Returns the value of attribute state.



54
55
56
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 54

def state
  @state
end

Instance Method Details

#change_state(new_state) ⇒ Object



274
275
276
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 274

def change_state(new_state)
  @state = new_state
end

#end_req_content(tur) ⇒ Object



268
269
270
271
272
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 268

def end_req_content(tur)
  ship.end_warp_tour(tur, true)
  tur.res.end_res_content(Tour::TOUR_ID_NOCHECK)
  reset_state()
end

#handle_begin_request(cmd) ⇒ Object

Implements FcgCommandHandler

Raises:

  • (ProtocolException)


121
122
123
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 121

def handle_begin_request(cmd)
  raise ProtocolException.new("Invalid FCGI command: %d", cmd.type)
end

#handle_end_request(cmd) ⇒ Object



125
126
127
128
129
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 125

def handle_end_request(cmd) 
  tur = ship.get_tour(cmd.req_id)
  end_req_content(tur)
  NextSocketAction::CONTINUE
end

#handle_params(cmd) ⇒ Object

Raises:

  • (ProtocolException)


131
132
133
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 131

def handle_params(cmd)
  raise ProtocolException.new("Invalid FCGI command: %d", cmd.type)
end

#handle_stderr(cmd) ⇒ Object



135
136
137
138
139
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 135

def handle_stderr(cmd)
  msg = cmd.data[cmd.start .. cmd.start + cmd.length + 1]
  BayLog.error("%s server error: %s", self, msg)
  NextSocketAction::CONTINUE
end

#handle_stdin(cmd) ⇒ Object

Raises:

  • (ProtocolException)


141
142
143
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 141

def handle_stdin(cmd)
  raise ProtocolException.new("Invalid FCGI command: %d", cmd.type)
end

#handle_stdout(cmd) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 145

def handle_stdout(cmd)
  BayLog.debug("%s handle_stdout req_id=%d len=%d", ship, cmd.req_id, cmd.length)
  #BayLog.debug "#{self} handle_stdout data=#{cmd.data}"

  tur = ship.get_tour(cmd.req_id)
  if tur == nil
    raise Sink.new("Tour not found")
  end

  if cmd.length == 0
    # stdout end
    reset_state
    return NextSocketAction::CONTINUE
  end

  @data = cmd.data
  @pos = cmd.start
  @last = cmd.start + cmd.length

  if @state == STATE_READ_HEADER
    read_header(tur)
  end

  if @pos < @last
    BayLog.debug("%s fcgi: pos=%d last=%d len=%d", ship, @pos, @last, @last - @pos)
    if @state == STATE_READ_CONTENT
      available = tur.res.send_res_content(Tour::TOUR_ID_NOCHECK, @data, @pos, @last - @pos)
      if !available
        return NextSocketAction::SUSPEND
      end
    end
  end

  NextSocketAction::CONTINUE
end

#init(proto_handler) ⇒ Object



67
68
69
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 67

def init(proto_handler)
  @protocol_handler = proto_handler
end

#new_warp_data(warp_id) ⇒ Object



88
89
90
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 88

def new_warp_data(warp_id)
  return WarpData.new(ship, warp_id)
end

#next_warp_idObject

Implements WarpHandler



83
84
85
86
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 83

def next_warp_id
  @cur_warp_id += 1
  return @cur_warp_id
end

#on_protocol_error(e) ⇒ Object

Raises:

  • (Sink)


112
113
114
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 112

def on_protocol_error(e)
  raise Sink.new
end

#parse_header(headers) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 224

def parse_header(headers)

  while true
    if @pos == @last
      # no byte data
      break
    end

    c = @data[@pos]
    @pos += 1

    if c == CharUtil::CR
      next
    elsif c == CharUtil::LF
      line = @line_buf.buf

      if line.length == 0
        return true
      end

      colon_pos = line.index(':')
      if colon_pos == nil
        raise ProtocolException.new("fcgi: Header line of server is invalid: %s", line)
      else
        name = line[0 .. colon_pos - 1].strip
        value = line[colon_pos + 1 .. -1].strip

        if StringUtil.empty?(name) || StringUtil.empty?(value)
          raise ProtocolException("fcgi: Header line of server is invalid: %s", line)
        end

        headers.add(name, value)
        if BayServer.harbor.trace_header
          BayLog.info("%s fcgi_warp: resHeader: %s=%s", ship, name, value)
        end
      end
      @line_buf.reset()
    else
      @line_buf.put(c)
    end
  end
  false
end

#read_content(tur) ⇒ Object



220
221
222
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 220

def read_content(tur)
  tur.res.send_res_content(Tour::TOUR_ID_NOCHECK, @data, @pos, @last - @pos)
end

#read_header(tur) ⇒ Object

Custom methods



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 188

def read_header(tur)
  wdat = WarpData.get(tur)

  header_finished = parse_header(wdat.res_headers)
  if header_finished
    wdat.res_headers.copy_to(tur.res.headers)

    # Check HTTP Status from headers
    status = wdat.res_headers.get(Headers::STATUS)
    #BayLog.debug "#{self} fcgi: status=#{wdat.res_headers.headers}"
    #BayLog.debug "#{self} fcgi: status=#{status}"
    if StringUtil.set?(status)
      stlist = status.split(" ")
      #BayLog.debug("#{self} fcgi: status list=#{stlist}")
      tur.res.headers.status = stlist[0].to_i
      tur.res.headers.remove(Headers::STATUS)
    end

    BayLog.debug("%s fcgi: read header status=%d contlen=%d", ship, tur.res.headers.status, wdat.res_headers.content_length())
    sid = ship.ship_id
    tur.res.set_consume_listener do |len, resume|
      if resume
        ship.resume_read(sid)
      end
    end

    tur.res.send_headers(Tour::TOUR_ID_NOCHECK)
    change_state(STATE_READ_CONTENT)
  end

end

#resetObject



71
72
73
74
75
76
77
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 71

def reset
  reset_state
  @line_buf.reset
  @pos = 0
  @last = 0
  @data = nil
end

#reset_stateObject



278
279
280
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 278

def reset_state()
  change_state(STATE_READ_HEADER)
end

#send_begin_req(tur) ⇒ Object



288
289
290
291
292
293
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 288

def send_begin_req(tur)
  cmd = CmdBeginRequest.new(WarpData.get(tur).warp_id)
  cmd.role = CmdBeginRequest::FCGI_RESPONDER
  cmd.keep_conn = true
  ship.post(cmd)
end

#send_end_tour(tur, keep_alive, &callback) ⇒ Object



105
106
107
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 105

def send_end_tour(tur, keep_alive, &callback)
  send_stdin(tur, nil, 0, 0, &callback)
end

#send_params(tur) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 295

def send_params(tur)
  script_base = ship.docker.script_base
  if script_base == nil
    script_base = tur.town.location
  end

  if StringUtil.empty?(script_base)
    raise StandardError.new("#{tur.town} Could not create SCRIPT_FILENAME. Location of town not specified.")
  end

  doc_root = ship.docker.doc_root
  if doc_root == nil
    doc_root = tur.town.location
  end

  if StringUtil.empty?(doc_root)
    raise StandardError.new("#{tur.town} docRoot of fcgi docker or location of town is not specified.")
  end

  warp_id = WarpData.get(tur).warp_id
  cmd = CmdParams.new(warp_id)
  script_fname = nil
  CgiUtil.get_env(tur.town.name, doc_root, script_base, tur) do |name, value|
    if name == CgiUtil::SCRIPT_FILENAME
      script_fname = value
    else
      cmd.add_param(name, value)
    end
  end

  script_fname = "proxy:fcgi://#{ship.docker.host}:#{ship.docker.port}#{script_fname}"
  cmd.add_param(CgiUtil::SCRIPT_FILENAME, script_fname)

  # Add FCGI params
  cmd.add_param(FcgParams::CONTEXT_PREFIX, "")
  cmd.add_param(FcgParams::UNIQUE_ID, DateTime.now.to_s)
  #cmd.add_param(FcgParams::X_FORWARDED_FOR, tur.req.remote_address)
  #cmd.add_param(FcgParams::X_FORWARDED_PROTO, tur.is_secure ? "https" : "http")
  #cmd.add_param(FcgParams::X_FORWARDED_PORT, tur.req.req_port.to_s)

  if BayServer.harbor.trace_header
    cmd.params.each do |kv|
      BayLog.info("%s fcgi_warp: env: %s=%s", ship, kv[0], kv[1])
    end
  end

  ship.post(cmd)

  cmd_params_end = CmdParams.new(WarpData.get(tur).warp_id)
  ship.post(cmd_params_end)
end

#send_res_content(tur, buf, start, len, &callback) ⇒ Object



101
102
103
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 101

def send_res_content(tur, buf, start, len, &callback)
  send_stdin(tur, buf, start, len, &callback)
end

#send_res_headers(tur) ⇒ Object

Implements TourHandler



96
97
98
99
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 96

def send_res_headers(tur)
  send_begin_req(tur)
  send_params(tur)
end

#send_stdin(tur, data, ofs, len, &callback) ⇒ Object



283
284
285
286
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 283

def send_stdin(tur, data, ofs, len, &callback)
  cmd = CmdStdIn.new(WarpData.get(tur).warp_id, data, ofs, len)
  ship.post(cmd, &callback)
end

#shipObject



347
348
349
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 347

def ship
  return @protocol_handler.ship
end

#verify_protocol(proto) ⇒ Object



109
110
# File 'lib/baykit/bayserver/docker/fcgi/fcg_warp_handler.rb', line 109

def verify_protocol(proto)
end