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:
parent
0777480af2
commit
92946d4474
2 changed files with 173 additions and 57 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue