Module: OpenSSL::Buffering
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
self,
Enumerable
|
|
Defined in: | ext/openssl/lib/openssl/buffering.rb |
Overview
::OpenSSL IO buffering mix-in module.
This module allows an SSL::SSLSocket to behave like an ::IO.
You typically won't use this module directly, you can see it implemented in SSL::SSLSocket.
Constant Summary
-
BLOCK_SIZE =
Default size to read from or write to the SSLSocket for buffer operations.
1024*16
Instance Attribute Summary
Instance Method Summary
-
#<<(s)
Writes
s
to the stream. -
#close
Closes the SSLSocket and flushes any unwritten data.
-
#each(eol = $/)
(also: #each_line)
Executes the block for every line in the stream where lines are separated by
eol
. -
#each_byte
Calls the given block once for each byte in the stream.
-
#each_line(eol = $/)
Alias for #each.
-
#eof? ⇒ Boolean
(also: #eof)
readonly
Returns true if the stream is at file which means there is no more data to be read.
-
#flush
Flushes buffered data to the SSLSocket.
-
#getc
Reads one character from the stream.
-
#gets(eol = $/, limit = nil)
Reads the next “line” from the stream.
-
#initialize
Creates an instance of OpenSSL's buffering ::IO module.
-
#print(*args)
Writes
args
to the stream. -
#printf(s, *args)
Formats and writes to the stream converting parameters under control of the format string.
-
#puts(*args)
Writes
args
to the stream along with a record separator. -
#read(size = nil, buf = nil)
Reads
size
bytes from the stream. -
#read_nonblock(maxlen, buf = nil, exception: true)
Reads at most
maxlen
bytes in the non-blocking manner. -
#readchar
Reads a one-character string from the stream.
-
#readline(eol = $/)
Reads a line from the stream which is separated by
eol
. -
#readlines(eol = $/)
Reads lines from the stream which are separated by
eol
. -
#readpartial(maxlen, buf = nil)
Reads at most
maxlen
bytes from the stream. -
#ungetc(c)
Pushes character
c
back onto the stream such that a subsequent buffered character read will return it. -
#write(s)
Writes
s
to the stream. -
#write_nonblock(s, exception: true)
Writes
s
in the non-blocking manner. -
#consume_rbuff(size = nil)
private
Consumes
size
bytes from the buffer. -
#do_write(s)
private
Writes
s
to the buffer. -
#fill_rbuff
private
Fills the buffer from the underlying SSLSocket.
Instance Attribute Details
#eof (readonly)
Alias for #eof?.
# File 'ext/openssl/lib/openssl/buffering.rb', line 302
alias eof eof?
#sync (rw)
The “sync mode” of the SSLSocket.
See IO#sync
for full details.
# File 'ext/openssl/lib/openssl/buffering.rb', line 30
attr_accessor :sync
Instance Method Details
#<<(s)
Writes s
to the stream. s
will be converted to a String using String#to_s
.
# File 'ext/openssl/lib/openssl/buffering.rb', line 392
def <<(s) do_write(s) self end
#close
Closes the SSLSocket and flushes any unwritten data.
# File 'ext/openssl/lib/openssl/buffering.rb', line 455
def close flush rescue nil sysclose end
#consume_rbuff(size = nil) (private)
Consumes size
bytes from the buffer
# File 'ext/openssl/lib/openssl/buffering.rb', line 68
def consume_rbuff(size=nil) if @rbuffer.empty? nil else size = @rbuffer.size unless size ret = @rbuffer[0, size] @rbuffer[0, size] = "" ret end end
#do_write(s) (private)
Writes s
to the buffer. When the buffer is full or #sync is true the buffer is flushed to the underlying socket.
# File 'ext/openssl/lib/openssl/buffering.rb', line 313
def do_write(s) @wbuffer = "" unless defined? @wbuffer @wbuffer << s @wbuffer.force_encoding(Encoding::BINARY) @sync ||= false if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/) remain = idx ? idx + $/.size : @wbuffer.length nwritten = 0 while remain > 0 str = @wbuffer[nwritten,remain] begin nwrote = syswrite(str) rescue Errno::EAGAIN retry end remain -= nwrote nwritten += nwrote end @wbuffer[0,nwritten] = "" end end
#each(eol = $/) Also known as: #each_line
Executes the block for every line in the stream where lines are separated by eol
.
See also #gets
# File 'ext/openssl/lib/openssl/buffering.rb', line 226
def each(eol=$/) while line = self.gets(eol) yield line end end
#each_byte
Calls the given block once for each byte in the stream.
# File 'ext/openssl/lib/openssl/buffering.rb', line 267
def each_byte # :yields: byte while c = getc yield(c.ord) end end
#each_line(eol = $/)
Alias for #each.
# File 'ext/openssl/lib/openssl/buffering.rb', line 231
alias each_line each
#eof? ⇒ Boolean
(readonly)
Also known as: #eof
Returns true if the stream is at file which means there is no more data to be read.
# File 'ext/openssl/lib/openssl/buffering.rb', line 298
def eof? fill_rbuff if !@eof && @rbuffer.empty? @eof && @rbuffer.empty? end
#fill_rbuff (private)
Fills the buffer from the underlying SSLSocket
# File 'ext/openssl/lib/openssl/buffering.rb', line 55
def fill_rbuff begin @rbuffer << self.sysread(BLOCK_SIZE) rescue Errno::EAGAIN retry rescue EOFError @eof = true end end
#flush
Flushes buffered data to the SSLSocket.
# File 'ext/openssl/lib/openssl/buffering.rb', line 443
def flush osync = @sync @sync = true do_write "" return self ensure @sync = osync end
#getc
Reads one character from the stream. Returns nil if called at end of file.
# File 'ext/openssl/lib/openssl/buffering.rb', line 260
def getc read(1) end
#gets(eol = $/, limit = nil)
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 'ext/openssl/lib/openssl/buffering.rb', line 202
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
#initialize
Creates an instance of OpenSSL's buffering ::IO module.
# File 'ext/openssl/lib/openssl/buffering.rb', line 40
def initialize(*) super @eof = false @rbuffer = "" @sync = @io.sync end
#print(*args)
Writes args
to the stream.
See IO#print
for full details.
#printf(s, *args)
Formats and writes to the stream converting parameters under control of the format string.
See Kernel.sprintf
for format string details.
# File 'ext/openssl/lib/openssl/buffering.rb', line 435
def printf(s, *args) do_write(s % args) nil end
#puts(*args)
Writes args
to the stream along with a record separator.
See IO#puts
for full details.
#read(size = nil, buf = nil)
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 'ext/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
#read_nonblock(maxlen, buf = nil, exception: true)
Reads at most maxlen
bytes in the non-blocking manner.
When no data can be read without blocking it raises 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.
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 exception: false
, the options hash allows you to indicate that read_nonblock should not raise an IO::Wait*able exception, but return the symbol :wait_writable
or :wait_readable
instead.
# File 'ext/openssl/lib/openssl/buffering.rb', line 171
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
#readchar
Reads a one-character string from the stream. Raises an EOFError at end of file.
#readline(eol = $/)
Reads a line from the stream which is separated by eol
.
Raises EOFError if at end of file.
#readlines(eol = $/)
Reads lines from the stream which are separated by eol
.
See also #gets
# File 'ext/openssl/lib/openssl/buffering.rb', line 238
def readlines(eol=$/) ary = [] while line = self.gets(eol) ary << line end ary end
#readpartial(maxlen, buf = nil)
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 'ext/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
#ungetc(c)
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 'ext/openssl/lib/openssl/buffering.rb', line 290
def ungetc(c) @rbuffer[0,0] = c.chr end
#write(s)
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 'ext/openssl/lib/openssl/buffering.rb', line 341
def write(s) do_write(s) s.bytesize end
#write_nonblock(s, exception: true)
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 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 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 exception: false
, the options hash allows you to indicate that write_nonblock should not raise an IO::Wait*able exception, but return the symbol :wait_writable
or :wait_readable
instead.
# File 'ext/openssl/lib/openssl/buffering.rb', line 383
def write_nonblock(s, exception: true) flush syswrite_nonblock(s, exception: exception) end