1 # -*- encoding: binary -*-
3 require 'rainbows/fiber'
4 require 'rainbows/fiber/io'
10 # keep-alive timeout class
11 class Kato < ::Rev::TimerWatcher
19 enable unless enabled?
24 while f = @watch.shift
31 class Heartbeat < ::Rev::TimerWatcher
33 exit if (! G.tick && G.cur <= 0)
37 class Sleeper < ::Rev::TimerWatcher
39 def initialize(seconds)
42 attach(::Rev::Loop.default)
51 class Server < ::Rev::IOWatcher
54 include Rainbows::Const
55 include Rainbows::Response
56 FIO = Rainbows::Fiber::IO
73 return if G.cur >= MAX
74 c = Rainbows.accept(@io) and ::Fiber.new { process(c) }.resume
79 client = FIO.new(io, ::Fiber.current)
80 buf = client.read_timeout or return
84 remote_addr = Rainbows.addr(io)
87 buf << (client.read_timeout or return) until hp.headers(env, buf)
89 env[CLIENT_IO] = client
90 env[RACK_INPUT] = 0 == hp.content_length ?
91 HttpRequest::NULL_IO : TeeInput.new(client, env, hp, buf)
92 env[REMOTE_ADDR] = remote_addr
93 response = APP.call(env.update(RACK_DEFAULTS))
95 if 100 == response[0].to_i
96 client.write(EXPECT_100_RESPONSE)
97 env.delete(HTTP_EXPECT)
98 response = APP.call(env)
101 alive = hp.keepalive? && G.alive
102 out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if hp.headers?
103 write_response(client, response, out)
104 end while alive and hp.reset.nil? and env.clear
114 class IO # see rainbows/fiber/io for original definition
116 class Watcher < ::Rev::IOWatcher
117 def initialize(fio, flag)
120 attach(::Rev::Loop.default)
127 alias on_writable on_readable
130 undef_method :wait_readable
131 undef_method :wait_writable
134 def initialize(*args)
143 to_io.close unless to_io.closed?
147 @w ||= Watcher.new(self, :w)
148 @w.enable unless @w.enabled?
154 @r ||= Watcher.new(self, :r)
155 @r.enable unless @r.enabled?