Support for the Ruby 2.4 series has ended. See here for reference.
OpenSSL
IO
buffering mix-in module.
This module allows an OpenSSL::SSL::SSLSocket
to behave like an IO
.
You typically won't use this module directly, you can see it implemented in OpenSSL::SSL::SSLSocket
.
Default size to read from or write to the SSLSocket for buffer operations.
Creates an instance of OpenSSL's buffering IO
module.
# File openssl/lib/openssl/buffering.rb, line 40 def initialize(*) super @eof = false @rbuffer = "" @sync = @io.sync end
Writes s
to the stream. s
will be converted to a String using String#to_s.
# File openssl/lib/openssl/buffering.rb, line 393 def <<(s) do_write(s) self end
Closes the SSLSocket and flushes any unwritten data.
# File openssl/lib/openssl/buffering.rb, line 456 def close flush rescue nil sysclose end
Executes the block for every line in the stream where lines are separated by eol
.
See also gets
# File openssl/lib/openssl/buffering.rb, line 227 def each(eol=$/) while line = self.gets(eol) yield line end end
Calls the given block once for each byte in the stream.
# File openssl/lib/openssl/buffering.rb, line 268 def each_byte # :yields: byte while c = getc yield(c.ord) end end
Returns true if the stream is at file which means there is no more data to be read.
# File openssl/lib/openssl/buffering.rb, line 299 def eof? fill_rbuff if !@eof && @rbuffer.empty? @eof && @rbuffer.empty? end
Flushes buffered data to the SSLSocket.
# File openssl/lib/openssl/buffering.rb, line 444 def flush osync = @sync @sync = true do_write "" return self ensure @sync = osync end
Reads one character from the stream. Returns nil if called at end of file.
# File openssl/lib/openssl/buffering.rb, line 261 def getc read(1) end
Reads the next “line” from the stream. Lines are separated by eol
. If limit
is provided the result will not be longer than the given number of bytes.
eol
may be a String or Regexp.
Unlike IO#gets the line read will not be assigned to +$_+.
Unlike IO#gets the separator must be provided if a limit is provided.
# File openssl/lib/openssl/buffering.rb, line 203 def gets(eol=$/, limit=nil) idx = @rbuffer.index(eol) until @eof break if idx fill_rbuff idx = @rbuffer.index(eol) end if eol.is_a?(Regexp) size = idx ? idx+$&.size : nil else size = idx ? idx+eol.size : nil end if size && limit && limit >= 0 size = [size, limit].min end consume_rbuff(size) end
Writes args
to the stream.
See IO#print for full details.
# File openssl/lib/openssl/buffering.rb, line 423 def print(*args) s = "" args.each{ |arg| s << arg.to_s } do_write(s) nil end
Formats and writes to the stream converting parameters under control of the format string.
See Kernel#sprintf for format string details.
# File openssl/lib/openssl/buffering.rb, line 436 def printf(s, *args) do_write(s % args) nil end
Writes args
to the stream along with a record separator.
See IO#puts for full details.
# File openssl/lib/openssl/buffering.rb, line 403 def puts(*args) s = "" if args.empty? s << "\n" end args.each{|arg| s << arg.to_s if $/ && /\n\z/ !~ s s << "\n" end } do_write(s) nil end
Reads size
bytes from the stream. If buf
is provided it must reference a string which will receive the data.
See IO#read for full details.
# File openssl/lib/openssl/buffering.rb, line 87 def read(size=nil, buf=nil) if size == 0 if buf buf.clear return buf else return "" end end until @eof break if size && size <= @rbuffer.size fill_rbuff end ret = consume_rbuff(size) || "" if buf buf.replace(ret) ret = buf end (size && ret.empty?) ? nil : ret end
Reads at most maxlen
bytes in the non-blocking manner.
When no data can be read without blocking it raises OpenSSL::SSL::SSLError
extended by IO::WaitReadable
or IO::WaitWritable
.
IO::WaitReadable
means SSL
needs to read internally so read_nonblock
should be called again when the underlying IO
is readable.
IO::WaitWritable
means SSL
needs to write internally so read_nonblock
should be called again after the underlying IO
is writable.
OpenSSL::Buffering#read_nonblock
needs two rescue clause as follows:
# emulates blocking read (readpartial). begin result = ssl.read_nonblock(maxlen) rescue IO::WaitReadable IO.select([io]) retry rescue IO::WaitWritable IO.select(nil, [io]) retry end
Note that one reason that read_nonblock
writes to the underlying IO
is when the peer requests a new TLS/SSL handshake. See openssl the FAQ for more details. www.openssl.org/support/faq.html
By specifying a keyword argument exception to false
, you can indicate that read_nonblock
should not raise an IO::Wait*able exception, but return the symbol :wait_writable
or :wait_readable
instead. At EOF, it will return nil
instead of raising EOFError.
# File openssl/lib/openssl/buffering.rb, line 172 def read_nonblock(maxlen, buf=nil, exception: true) if maxlen == 0 if buf buf.clear return buf else return "" end end if @rbuffer.empty? return sysread_nonblock(maxlen, buf, exception: exception) end ret = consume_rbuff(maxlen) if buf buf.replace(ret) ret = buf end ret end
Reads a one-character string from the stream. Raises an EOFError at end of file.
# File openssl/lib/openssl/buffering.rb, line 278 def readchar raise EOFError if eof? getc end
Reads a line from the stream which is separated by eol
.
Raises EOFError if at end of file.
# File openssl/lib/openssl/buffering.rb, line 252 def readline(eol=$/) raise EOFError if eof? gets(eol) end
Reads lines from the stream which are separated by eol
.
See also gets
# File openssl/lib/openssl/buffering.rb, line 239 def readlines(eol=$/) ary = [] while line = self.gets(eol) ary << line end ary end
Reads at most maxlen
bytes from the stream. If buf
is provided it must reference a string which will receive the data.
See IO#readpartial for full details.
# File openssl/lib/openssl/buffering.rb, line 114 def readpartial(maxlen, buf=nil) if maxlen == 0 if buf buf.clear return buf else return "" end end if @rbuffer.empty? begin return sysread(maxlen, buf) rescue Errno::EAGAIN retry end end ret = consume_rbuff(maxlen) if buf buf.replace(ret) ret = buf end ret end
Pushes character c
back onto the stream such that a subsequent buffered character read will return it.
Unlike IO#getc multiple bytes may be pushed back onto the stream.
Has no effect on unbuffered reads (such as sysread).
# File openssl/lib/openssl/buffering.rb, line 291 def ungetc(c) @rbuffer[0,0] = c.chr end
Writes s
to the stream. If the argument is not a string it will be converted using String#to_s. Returns the number of bytes written.
# File openssl/lib/openssl/buffering.rb, line 342 def write(s) do_write(s) s.bytesize end
Writes s
in the non-blocking manner.
If there is buffered data, it is flushed first. This may block.
write_nonblock
returns number of bytes written to the SSL
connection.
When no data can be written without blocking it raises OpenSSL::SSL::SSLError
extended by IO::WaitReadable
or IO::WaitWritable
.
IO::WaitReadable
means SSL
needs to read internally so write_nonblock
should be called again after the underlying IO
is readable.
IO::WaitWritable
means SSL
needs to write internally so write_nonblock
should be called again after underlying IO
is writable.
So OpenSSL::Buffering#write_nonblock
needs two rescue clause as follows.
# emulates blocking write. begin result = ssl.write_nonblock(str) rescue IO::WaitReadable IO.select([io]) retry rescue IO::WaitWritable IO.select(nil, [io]) retry end
Note that one reason that write_nonblock
reads from the underlying IO
is when the peer requests a new TLS/SSL handshake. See the openssl FAQ for more details. www.openssl.org/support/faq.html
By specifying a keyword argument exception to false
, you can indicate that write_nonblock
should not raise an IO::Wait*able exception, but return the symbol :wait_writable
or :wait_readable
instead.
# File openssl/lib/openssl/buffering.rb, line 384 def write_nonblock(s, exception: true) flush syswrite_nonblock(s, exception: exception) end