From 92946d44742ee9c48f418f6ff583b1bf35da9d1f Mon Sep 17 00:00:00 2001 From: drbrain Date: Wed, 16 Mar 2011 04:47:18 +0000 Subject: 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 --- ext/openssl/lib/openssl/buffering.rb | 236 +++++++++++++++++++++++++---------- 1 file changed, 173 insertions(+), 63 deletions(-) (limited to 'ext/openssl/lib/openssl') diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index 3028fe5b52..a9c60fb512 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -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. - # - # 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::WaitWritable means SSL needs to write internally. - # So read_nonblock should be called again after - # 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 - # - # 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 + ## + # 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. 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 -- cgit v1.2.3