1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00
puma--puma/lib/puma/minissl.rb
Colin J. Fuller 6e914cf02d Fix for issue 350.
Within MiniSSL#read_nonblock it was possible for all data to be read from the
network connection but only partially read from the engine on the first
attempt.  This could lead to a hang during a later IO.select call because no more data
was being sent over the socket but the request could not be processed because
all the data hadn't been read from the engine.

Changed read nonblock to repeatedly attempt to read from the engine until there
is nothing more ready to read.
2013-11-24 19:57:12 -08:00

148 lines
2.7 KiB
Ruby

module Puma
module MiniSSL
class Socket
def initialize(socket, engine)
@socket = socket
@engine = engine
end
def to_io
@socket
end
def readpartial(size)
while true
output = @engine.read
return output if output
data = @socket.readpartial(size)
@engine.inject(data)
output = @engine.read
return output if output
while neg_data = @engine.extract
@socket.write neg_data
end
end
end
def engine_read_all
output = @engine.read
while output and additional_output = @engine.read
output << additional_output
end
output
end
def read_nonblock(size)
while true
output = engine_read_all
return output if output
data = @socket.read_nonblock(size)
@engine.inject(data)
output = engine_read_all
return output if output
while neg_data = @engine.extract
@socket.write neg_data
end
end
end
def write(data)
need = data.bytesize
while true
wrote = @engine.write data
enc = @engine.extract
while enc
@socket.write enc
enc = @engine.extract
end
need -= wrote
return data.bytesize if need == 0
data = data[need..-1]
end
end
alias_method :syswrite, :write
def flush
@socket.flush
end
def close
@socket.close
end
def peeraddr
@socket.peeraddr
end
end
class Context
attr_accessor :verify_mode
attr_reader :key
attr_reader :cert
def key=(key)
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
@key = key
end
def cert=(cert)
raise ArgumentError, "No such cert file '#{cert}'" unless File.exist? cert
@cert = cert
end
end
VERIFY_NONE = 0
VERIFY_PEER = 1
#if defined?(JRUBY_VERSION)
#class Engine
#def self.server(key, cert)
#new(key, cert)
#end
#end
#end
class Server
def initialize(socket, ctx)
@socket = socket
@ctx = ctx
end
def to_io
@socket
end
def accept
io = @socket.accept
engine = Engine.server @ctx.key, @ctx.cert
Socket.new io, engine
end
def accept_nonblock
io = @socket.accept_nonblock
engine = Engine.server @ctx.key, @ctx.cert
Socket.new io, engine
end
def close
@socket.close
end
end
end
end