1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

de-nest the Buffering module

add RDoc for OpenSSL::Buffering


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31112 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
drbrain 2011-03-16 04:47:18 +00:00
parent 0777480af2
commit 92946d4474
2 changed files with 173 additions and 57 deletions

View file

@ -1,3 +1,9 @@
Wed Mar 16 13:45:28 2011 Eric Hodel <drbrain@segment7.net>
* ext/openss/lib/openssl/bufering.rb: de-nest Buffering module
* ext/openss/lib/openssl/bufering.rb: add RDoc
Wed Mar 16 08:40:39 2011 Tanaka Akira <akr@fsij.org>
* ext/openssl/ossl_x509ext.c: parenthesize macro arguments.

View file

@ -14,10 +14,26 @@
$Id$
=end
module OpenSSL
module Buffering
require 'openssl'
##
# OpenSSL IO buffering mix-in module.
#
# This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
module OpenSSL::Buffering
include Enumerable
##
# The "sync mode" of the SSLSocket.
#
# See IO#sync for full details.
attr_accessor :sync
##
# Default size to read from or write to the SSLSocket for buffer operations.
BLOCK_SIZE = 1024*16
def initialize(*args)
@ -31,6 +47,9 @@ module Buffering
#
private
##
# Fills the buffer from the underlying SSLSocket
def fill_rbuff
begin
@rbuffer << self.sysread(BLOCK_SIZE)
@ -41,6 +60,9 @@ module Buffering
end
end
##
# Consumes +size+ bytes from the buffer
def consume_rbuff(size=nil)
if @rbuffer.empty?
nil
@ -54,6 +76,12 @@ module Buffering
public
##
# 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.
def read(size=nil, buf=nil)
if size == 0
if buf
@ -75,6 +103,12 @@ module Buffering
(size && ret.empty?) ? nil : ret
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.
def readpartial(maxlen, buf=nil)
if maxlen == 0
if buf
@ -100,38 +134,35 @@ module Buffering
ret
end
# Reads at most _maxlen_ bytes in the non-blocking manner.
##
# 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.
# 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 after
# underlying IO is readable.
# 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
# underlying IO is writable.
# IO::WaitWritable means SSL needs to write internally so read_nonblock
# should be called again after the underlying IO is writable.
#
# So 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
# OpenSSL::Buffering#read_nonblock needs two rescue clause as follows:
#
# Note that one reason that read_nonblock write to a underlying IO
# is the peer requests a new TLS/SSL handshake.
# See openssl FAQ for more details.
# http://www.openssl.org/support/faq.html
# # 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. http://www.openssl.org/support/faq.html
def read_nonblock(maxlen, buf=nil)
if maxlen == 0
if buf
@ -153,6 +184,17 @@ module Buffering
ret
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.
def gets(eol=$/, limit=nil)
idx = @rbuffer.index(eol)
until @eof
@ -171,6 +213,12 @@ module Buffering
consume_rbuff(size)
end
##
# Executes the block for every line in the stream where lines are separated
# by +eol+.
#
# See also #gets
def each(eol=$/)
while line = self.gets(eol)
yield line
@ -178,6 +226,11 @@ module Buffering
end
alias each_line each
##
# Reads lines from the stream which are separated by +eol+.
#
# See also #gets
def readlines(eol=$/)
ary = []
while line = self.gets(eol)
@ -186,31 +239,59 @@ module Buffering
ary
end
##
# Reads a line from the stream which is separated by +eol+.
#
# Raises EOFError if at end of file.
def readline(eol=$/)
raise EOFError if eof?
gets(eol)
end
##
# Reads one character from the stream. Returns nil if called at end of
# file.
def getc
c = read(1)
c ? c[0] : nil
end
def each_byte
##
# Calls the given block once for each byte in the stream.
def each_byte # :yields: byte
while c = getc
yield(c)
end
end
##
# Reads a one-character string from the stream. Raises an EOFError at end
# of file.
def readchar
raise EOFError if eof?
getc
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).
def ungetc(c)
@rbuffer[0,0] = c.chr
end
##
# Returns true if the stream is at file which means there is no more data to
# be read.
def eof?
fill_rbuff if !@eof && @rbuffer.empty?
@eof && @rbuffer.empty?
@ -222,6 +303,10 @@ module Buffering
#
private
##
# Writes +s+ to the buffer. When the buffer is full or #sync is true the
# buffer is flushed to the underlying socket.
def do_write(s)
@wbuffer = "" unless defined? @wbuffer
@wbuffer << s
@ -245,58 +330,67 @@ module Buffering
public
##
# 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.
def write(s)
do_write(s)
s.length
end
# Writes _str_ in the non-blocking manner.
##
# Writes +str+ in the non-blocking manner.
#
# If there are buffered data, it is flushed at first.
# This may block.
# 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.
# 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
# underlying IO is readable.
# 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.
# 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 read from a underlying IO
# is the peer requests a new TLS/SSL handshake.
# See openssl FAQ for more details.
# http://www.openssl.org/support/faq.html
# # 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. http://www.openssl.org/support/faq.html
def write_nonblock(s)
flush
syswrite_nonblock(s)
end
##
# Writes +s+ to the stream. +s+ will be converted to a String using
# String#to_s.
def << (s)
do_write(s)
self
end
##
# Writes +args+ to the stream along with a record separator.
#
# See IO#puts for full details.
def puts(*args)
s = ""
if args.empty?
@ -312,6 +406,11 @@ module Buffering
nil
end
##
# Writes +args+ to the stream.
#
# See IO#print for full details.
def print(*args)
s = ""
args.each{ |arg| s << arg.to_s }
@ -319,11 +418,20 @@ module Buffering
nil
end
##
# Formats and writes to the stream converting parameters under control of
# the format string.
#
# See Kernel#sprintf for format string details.
def printf(s, *args)
do_write(s % args)
nil
end
##
# Flushes buffered data to the SSLSocket.
def flush
osync = @sync
@sync = true
@ -331,9 +439,11 @@ module Buffering
@sync = osync
end
##
# Closes the SSLSocket and flushes any unwritten data.
def close
flush rescue nil
sysclose
end
end
end