about summary refs log tree commit homepage
path: root/lib/rainbows/fiber.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-11-25 01:44:34 -0800
committerEric Wong <normalperson@yhbt.net>2009-11-25 03:13:12 -0800
commit4d8304bf0aa5665e8f8474dfb96019297fa0c2b9 (patch)
tree676418a49b5575209c00fb3bcb83db10df8834bc /lib/rainbows/fiber.rb
parent2bc6e7a3c4e972ee3227d931e79bc4057ba278ca (diff)
downloadrainbows-4d8304bf0aa5665e8f8474dfb96019297fa0c2b9.tar.gz
This one seems a easy to get working and supports everything we
need to support from the server perspective.  Apps will need
modified drivers, but it doesn't seem too hard to add
more/better support for wrapping IO objects with Fiber::IO.
Diffstat (limited to 'lib/rainbows/fiber.rb')
-rw-r--r--lib/rainbows/fiber.rb53
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/rainbows/fiber.rb b/lib/rainbows/fiber.rb
new file mode 100644
index 0000000..e7d64ca
--- /dev/null
+++ b/lib/rainbows/fiber.rb
@@ -0,0 +1,53 @@
+# -*- encoding: binary -*-
+require 'fiber'
+require 'rainbows/fiber/io'
+
+module Rainbows
+  module Fiber
+    RD = {}
+    WR = {}
+
+    module Base
+      include Rainbows::Base
+
+      def process_client(client)
+        G.cur += 1
+        io = client.to_io
+        buf = client.read_timeout or return
+        hp = HttpParser.new
+        env = {}
+        alive = true
+        remote_addr = TCPSocket === io ? io.peeraddr.last : LOCALHOST
+
+        begin # loop
+          while ! hp.headers(env, buf)
+            buf << client.read_timeout or return
+          end
+
+          env[RACK_INPUT] = 0 == hp.content_length ?
+                    HttpRequest::NULL_IO : TeeInput.new(client, env, hp, buf)
+          env[REMOTE_ADDR] = remote_addr
+          response = APP.call(env.update(RACK_DEFAULTS))
+
+          if 100 == response.first.to_i
+            client.write(EXPECT_100_RESPONSE)
+            env.delete(HTTP_EXPECT)
+            response = APP.call(env)
+          end
+
+          alive = hp.keepalive? && G.alive
+          out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if hp.headers?
+          HttpResponse.write(client, response, out)
+        end while alive and hp.reset.nil? and env.clear
+        io.close
+      rescue => e
+        handle_error(io, e)
+      ensure
+        G.cur -= 1
+        RD.delete(client)
+        WR.delete(client)
+      end
+
+    end
+  end
+end