From a262e29d4c23324f84ea6f9784720dd001547323 Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Thu, 8 Apr 2021 22:23:39 -0500 Subject: [PATCH] minissl.rb - allow chaining with '<<', improve/simplify write --- lib/puma/minissl.rb | 46 +++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/lib/puma/minissl.rb b/lib/puma/minissl.rb index 64534872fb..fc93ce8582 100644 --- a/lib/puma/minissl.rb +++ b/lib/puma/minissl.rb @@ -21,6 +21,7 @@ class Socket def initialize(socket, engine) @socket = socket @engine = engine + @buffer = Puma::IOBuffer.new @peercert = nil end @@ -114,31 +115,40 @@ def read_nonblock(size, *_) end end + # When returning a large response body (2MB), Ubuntu works fine with + # `syswrite`, but macOS & Windows have OpenSSL errors on the client. + # def write(data) return 0 if data.empty? - - data_size = data.bytesize - need = data_size - - while true - wrote = @engine.write data - - enc_wr = ''.dup - while (enc = @engine.extract) - enc_wr << enc + write_size = 128 * 1024 + ttl = 0 + running = 0 + byte_size = data.bytesize + enc_wr = @buffer + enc = nil + + while ttl < byte_size + inc = @engine.write(ttl.zero? ? data : data.byteslice(ttl..-1)) + running += inc + ttl += inc + enc_wr.write(enc) while (enc = @engine.extract) + + if running > write_size + @socket.write enc_wr.read + running = 0 end - @socket.write enc_wr unless enc_wr.empty? - - need -= wrote - - return data_size if need == 0 - - data = data.byteslice(wrote..-1) end + @socket.write(enc_wr.read) unless enc_wr.empty? + enc.clear unless enc.nil? + byte_size end alias_method :syswrite, :write - alias_method :<<, :write + + def <<(data) + write data + self + end # This is a temporary fix to deal with websockets code using # write_nonblock.