about summary refs log tree commit homepage
path: root/lib/yahns/http_client.rb
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2016-07-12 21:11:33 +0000
committerEric Wong <e@80x24.org>2016-07-12 21:13:20 +0000
commit946171bbc2e681cbab93863069767dd0fa4b6844 (patch)
treec2e2326ed3ac6df4ae04dd660b75cd05394e2fcf /lib/yahns/http_client.rb
parente6b13ef8ba6eaa3efe3808845ddfe7e0b7b1c46b (diff)
downloadyahns-946171bbc2e681cbab93863069767dd0fa4b6844.tar.gz
This allows us to work transparently with our OpenSSL
workaround[*] while allowing us to reuse our non-sendfile
compatibility code.  Unfortunately, this means we duplicate a
lot of code from the normal wbuf code for now; but that should
be fairly stable at this point.

[*] https://bugs.ruby-lang.org/issues/12085
Diffstat (limited to 'lib/yahns/http_client.rb')
-rw-r--r--lib/yahns/http_client.rb26
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/yahns/http_client.rb b/lib/yahns/http_client.rb
index 1d64e08..1cdaa0f 100644
--- a/lib/yahns/http_client.rb
+++ b/lib/yahns/http_client.rb
@@ -2,6 +2,12 @@
 # Copyright (C) 2013-2016 all contributors <yahns-public@yhbt.net>
 # License: GPL-3.0+ (https://www.gnu.org/licenses/gpl-3.0.txt)
 # frozen_string_literal: true
+begin
+  raise LoadError, 'SENDFILE_BROKEN env set' if ENV['SENDFILE_BROKEN']
+  require 'sendfile'
+rescue LoadError
+end
+
 class Yahns::HttpClient < Kgio::Socket # :nodoc:
   NULL_IO = StringIO.new(''.dup) # :nodoc:
 
@@ -304,4 +310,24 @@ class Yahns::HttpClient < Kgio::Socket # :nodoc:
     body.close if body.respond_to?(:close)
     true
   end
+
+  def trysendio(io, offset, count)
+    return 0 if count == 0
+    count = 0x4000 if count > 0x4000
+    buf = Thread.current[:yahns_sfbuf] ||= ''.dup
+    io.pos = offset
+    str = io.read(count, buf) or return # nil for EOF
+    n = 0
+    case rv = kgio_trywrite(str)
+    when String # partial write, keep trying
+      n += (str.size - rv.size)
+      str = rv
+    when :wait_writable, :wait_readable
+      return n > 0 ? n : rv
+    when nil
+      return n + str.size # yay!
+    end while true
+  end
+
+  alias trysendfile trysendio unless IO.instance_methods.include?(:trysendfile)
 end