about summary refs log tree commit homepage
path: root/lib/rainbows/revactor
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rainbows/revactor')
-rw-r--r--lib/rainbows/revactor/client.rb59
-rw-r--r--lib/rainbows/revactor/client/methods.rb (renamed from lib/rainbows/revactor/body.rb)29
-rw-r--r--lib/rainbows/revactor/client/tee_socket.rb (renamed from lib/rainbows/revactor/tee_socket.rb)2
3 files changed, 74 insertions, 16 deletions
diff --git a/lib/rainbows/revactor/client.rb b/lib/rainbows/revactor/client.rb
new file mode 100644
index 0000000..7c4b53d
--- /dev/null
+++ b/lib/rainbows/revactor/client.rb
@@ -0,0 +1,59 @@
+# -*- encoding: binary -*-
+# :enddoc:
+require 'fcntl'
+class Rainbows::Revactor::Client
+  autoload :TeeSocket, 'rainbows/revactor/client/tee_socket'
+  RD_ARGS = {}
+  RD_ARGS[:timeout] = Rainbows::G.kato if Rainbows::G.kato > 0
+  attr_reader :kgio_addr
+
+  def initialize(client)
+    @client, @rd_args, @ts = client, [ nil ], nil
+    io = client.instance_variable_get(:@_io)
+    io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+    @kgio_addr = if Revactor::TCP::Socket === client
+      @rd_args << RD_ARGS
+      client.remote_addr
+    else
+      Kgio::LOCALHOST
+    end
+  end
+
+  def kgio_read!(nr, buf)
+    buf.replace(@client.read)
+  end
+
+  def write(buf)
+    @client.write(buf)
+  end
+
+  def write_nonblock(buf) # only used for errors
+    @client.instance_variable_get(:@_io).write_nonblock(buf)
+  end
+
+  def timed_read(buf2)
+    buf2.replace(@client.read(*@rd_args))
+  end
+
+  def set_input(env, hp)
+    env[RACK_INPUT] = 0 == hp.content_length ?
+                      NULL_IO : IC.new(@ts = TeeSocket.new(@client), hp)
+    env[CLIENT_IO] = @client
+  end
+
+  def close
+    @client.close
+    @client = nil
+  end
+
+  def closed?
+    @client.nil?
+  end
+
+  def self.setup
+    self.const_set(:IC, Unicorn::HttpRequest.input_class)
+    include Rainbows::ProcessClient
+    include Methods
+  end
+end
+require 'rainbows/revactor/client/methods'
diff --git a/lib/rainbows/revactor/body.rb b/lib/rainbows/revactor/client/methods.rb
index 9820df3..e9b39a3 100644
--- a/lib/rainbows/revactor/body.rb
+++ b/lib/rainbows/revactor/client/methods.rb
@@ -1,15 +1,10 @@
 # -*- encoding: binary -*-
 # :enddoc:
-module Rainbows::Revactor::Body
-  # TODO non-blocking splice(2) under Linux
-  ALIASES = {
-    :write_body_stream => :write_body_each
-  }
-
+module Rainbows::Revactor::Client::Methods
   if IO.method_defined?(:sendfile_nonblock)
-    def write_body_file_sendfile_revactor(client, body, range)
-      body = body_to_io(body)
-      sock = client.instance_variable_get(:@_io)
+    def write_body_file(body, range)
+      body, client = body_to_io(body), @client
+      sock = @client.instance_variable_get(:@_io)
       pfx = Revactor::TCP::Socket === client ? :tcp : :unix
       write_complete = T[:"#{pfx}_write_complete", client]
       closed = T[:"#{pfx}_closed", client]
@@ -33,14 +28,18 @@ module Rainbows::Revactor::Body
       ensure
         close_if_private(body)
     end
-    ALIASES[:write_body_file] = :write_body_file_sendfile_revactor
-  else
-    ALIASES[:write_body] = :write_body_each
+  end
+
+  def handle_error(e)
+    Revactor::TCP::ReadError === e or super
+  end
+
+  def write_response(status, headers, body, alive)
+    super(status, headers, body, alive)
+    alive && @ts and @hp.buf << @ts.leftover
   end
 
   def self.included(klass)
-    ALIASES.each do |new_method, orig_method|
-      klass.__send__(:alias_method, new_method, orig_method)
-    end
+    klass.__send__ :alias_method, :write_body_stream, :write_body_each
   end
 end
diff --git a/lib/rainbows/revactor/tee_socket.rb b/lib/rainbows/revactor/client/tee_socket.rb
index 71aeb88..2f9f52e 100644
--- a/lib/rainbows/revactor/tee_socket.rb
+++ b/lib/rainbows/revactor/client/tee_socket.rb
@@ -5,7 +5,7 @@
 # enough to avoid mucking with TeeInput internals.  Fortunately
 # this code is not heavily used so we can usually avoid the overhead
 # of adding a userspace buffer.
-class Rainbows::Revactor::TeeSocket
+class Rainbows::Revactor::Client::TeeSocket
   def initialize(socket)
     # IO::Buffer is used internally by Rev which Revactor is based on
     # so we'll always have it available