1#
2#--
3#= $RCSfile$ -- Buffering mix-in module.
4#
5#= Info
6#  'OpenSSL for Ruby 2' project
7#  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
8#  All rights reserved.
9#
10#= Licence
11#  This program is licenced under the same licence as Ruby.
12#  (See the file 'LICENCE'.)
13#
14#= Version
15#  $Id: buffering.rb 45053 2014-02-19 17:14:45Z nagachika $
16#++
17
18##
19# OpenSSL IO buffering mix-in module.
20#
21# This module allows an OpenSSL::SSL::SSLSocket to behave like an IO.
22
23module OpenSSL::Buffering
24  include Enumerable
25
26  ##
27  # The "sync mode" of the SSLSocket.
28  #
29  # See IO#sync for full details.
30
31  attr_accessor :sync
32
33  ##
34  # Default size to read from or write to the SSLSocket for buffer operations.
35
36  BLOCK_SIZE = 1024*16
37
38  def initialize(*args)
39    @eof = false
40    @rbuffer = ""
41    @sync = @io.sync
42  end
43
44  #
45  # for reading.
46  #
47  private
48
49  ##
50  # Fills the buffer from the underlying SSLSocket
51
52  def fill_rbuff
53    begin
54      @rbuffer << self.sysread(BLOCK_SIZE)
55    rescue Errno::EAGAIN
56      retry
57    rescue EOFError
58      @eof = true
59    end
60  end
61
62  ##
63  # Consumes +size+ bytes from the buffer
64
65  def consume_rbuff(size=nil)
66    if @rbuffer.empty?
67      nil
68    else
69      size = @rbuffer.size unless size
70      ret = @rbuffer[0, size]
71      @rbuffer[0, size] = ""
72      ret
73    end
74  end
75
76  public
77
78  ##
79  # Reads +size+ bytes from the stream.  If +buf+ is provided it must
80  # reference a string which will receive the data.
81  #
82  # See IO#read for full details.
83
84  def read(size=nil, buf=nil)
85    if size == 0
86      if buf
87        buf.clear
88        return buf
89      else
90        return ""
91      end
92    end
93    until @eof
94      break if size && size <= @rbuffer.size
95      fill_rbuff
96    end
97    ret = consume_rbuff(size) || ""
98    if buf
99      buf.replace(ret)
100      ret = buf
101    end
102    (size && ret.empty?) ? nil : ret
103  end
104
105  ##
106  # Reads at most +maxlen+ bytes from the stream.  If +buf+ is provided it
107  # must reference a string which will receive the data.
108  #
109  # See IO#readpartial for full details.
110
111  def readpartial(maxlen, buf=nil)
112    if maxlen == 0
113      if buf
114        buf.clear
115        return buf
116      else
117        return ""
118      end
119    end
120    if @rbuffer.empty?
121      begin
122        return sysread(maxlen, buf)
123      rescue Errno::EAGAIN
124        retry
125      end
126    end
127    ret = consume_rbuff(maxlen)
128    if buf
129      buf.replace(ret)
130      ret = buf
131    end
132    raise EOFError if ret.empty?
133    ret
134  end
135
136  ##
137  # Reads at most +maxlen+ bytes in the non-blocking manner.
138  #
139  # When no data can be read without blocking it raises
140  # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
141  #
142  # IO::WaitReadable means SSL needs to read internally so read_nonblock
143  # should be called again when the underlying IO is readable.
144  #
145  # IO::WaitWritable means SSL needs to write internally so read_nonblock
146  # should be called again after the underlying IO is writable.
147  #
148  # OpenSSL::Buffering#read_nonblock needs two rescue clause as follows:
149  #
150  #   # emulates blocking read (readpartial).
151  #   begin
152  #     result = ssl.read_nonblock(maxlen)
153  #   rescue IO::WaitReadable
154  #     IO.select([io])
155  #     retry
156  #   rescue IO::WaitWritable
157  #     IO.select(nil, [io])
158  #     retry
159  #   end
160  #
161  # Note that one reason that read_nonblock writes to the underlying IO is
162  # when the peer requests a new TLS/SSL handshake.  See openssl the FAQ for
163  # more details.  http://www.openssl.org/support/faq.html
164
165  def read_nonblock(maxlen, buf=nil)
166    if maxlen == 0
167      if buf
168        buf.clear
169        return buf
170      else
171        return ""
172      end
173    end
174    if @rbuffer.empty?
175      return sysread_nonblock(maxlen, buf)
176    end
177    ret = consume_rbuff(maxlen)
178    if buf
179      buf.replace(ret)
180      ret = buf
181    end
182    raise EOFError if ret.empty?
183    ret
184  end
185
186  ##
187  # Reads the next "line+ from the stream.  Lines are separated by +eol+.  If
188  # +limit+ is provided the result will not be longer than the given number of
189  # bytes.
190  #
191  # +eol+ may be a String or Regexp.
192  #
193  # Unlike IO#gets the line read will not be assigned to +$_+.
194  #
195  # Unlike IO#gets the separator must be provided if a limit is provided.
196
197  def gets(eol=$/, limit=nil)
198    idx = @rbuffer.index(eol)
199    until @eof
200      break if idx
201      fill_rbuff
202      idx = @rbuffer.index(eol)
203    end
204    if eol.is_a?(Regexp)
205      size = idx ? idx+$&.size : nil
206    else
207      size = idx ? idx+eol.size : nil
208    end
209    if limit and limit >= 0
210      size = [size, limit].min
211    end
212    consume_rbuff(size)
213  end
214
215  ##
216  # Executes the block for every line in the stream where lines are separated
217  # by +eol+.
218  #
219  # See also #gets
220
221  def each(eol=$/)
222    while line = self.gets(eol)
223      yield line
224    end
225  end
226  alias each_line each
227
228  ##
229  # Reads lines from the stream which are separated by +eol+.
230  #
231  # See also #gets
232
233  def readlines(eol=$/)
234    ary = []
235    while line = self.gets(eol)
236      ary << line
237    end
238    ary
239  end
240
241  ##
242  # Reads a line from the stream which is separated by +eol+.
243  #
244  # Raises EOFError if at end of file.
245
246  def readline(eol=$/)
247    raise EOFError if eof?
248    gets(eol)
249  end
250
251  ##
252  # Reads one character from the stream.  Returns nil if called at end of
253  # file.
254
255  def getc
256    read(1)
257  end
258
259  ##
260  # Calls the given block once for each byte in the stream.
261
262  def each_byte # :yields: byte
263    while c = getc
264      yield(c.ord)
265    end
266  end
267
268  ##
269  # Reads a one-character string from the stream.  Raises an EOFError at end
270  # of file.
271
272  def readchar
273    raise EOFError if eof?
274    getc
275  end
276
277  ##
278  # Pushes character +c+ back onto the stream such that a subsequent buffered
279  # character read will return it.
280  #
281  # Unlike IO#getc multiple bytes may be pushed back onto the stream.
282  #
283  # Has no effect on unbuffered reads (such as #sysread).
284
285  def ungetc(c)
286    @rbuffer[0,0] = c.chr
287  end
288
289  ##
290  # Returns true if the stream is at file which means there is no more data to
291  # be read.
292
293  def eof?
294    fill_rbuff if !@eof && @rbuffer.empty?
295    @eof && @rbuffer.empty?
296  end
297  alias eof eof?
298
299  #
300  # for writing.
301  #
302  private
303
304  ##
305  # Writes +s+ to the buffer.  When the buffer is full or #sync is true the
306  # buffer is flushed to the underlying socket.
307
308  def do_write(s)
309    @wbuffer = "" unless defined? @wbuffer
310    @wbuffer << s
311    @wbuffer.force_encoding(Encoding::BINARY)
312    @sync ||= false
313    if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/)
314      remain = idx ? idx + $/.size : @wbuffer.length
315      nwritten = 0
316      while remain > 0
317        str = @wbuffer[nwritten,remain]
318        begin
319          nwrote = syswrite(str)
320        rescue Errno::EAGAIN
321          retry
322        end
323        remain -= nwrote
324        nwritten += nwrote
325      end
326      @wbuffer[0,nwritten] = ""
327    end
328  end
329
330  public
331
332  ##
333  # Writes +s+ to the stream.  If the argument is not a string it will be
334  # converted using String#to_s.  Returns the number of bytes written.
335
336  def write(s)
337    do_write(s)
338    s.bytesize
339  end
340
341  ##
342  # Writes +str+ in the non-blocking manner.
343  #
344  # If there is buffered data, it is flushed first.  This may block.
345  #
346  # write_nonblock returns number of bytes written to the SSL connection.
347  #
348  # When no data can be written without blocking it raises
349  # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable.
350  #
351  # IO::WaitReadable means SSL needs to read internally so write_nonblock
352  # should be called again after the underlying IO is readable.
353  #
354  # IO::WaitWritable means SSL needs to write internally so write_nonblock
355  # should be called again after underlying IO is writable.
356  #
357  # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows.
358  #
359  #   # emulates blocking write.
360  #   begin
361  #     result = ssl.write_nonblock(str)
362  #   rescue IO::WaitReadable
363  #     IO.select([io])
364  #     retry
365  #   rescue IO::WaitWritable
366  #     IO.select(nil, [io])
367  #     retry
368  #   end
369  #
370  # Note that one reason that write_nonblock reads from the underlying IO
371  # is when the peer requests a new TLS/SSL handshake.  See the openssl FAQ
372  # for more details.  http://www.openssl.org/support/faq.html
373
374  def write_nonblock(s)
375    flush
376    syswrite_nonblock(s)
377  end
378
379  ##
380  # Writes +s+ to the stream.  +s+ will be converted to a String using
381  # String#to_s.
382
383  def << (s)
384    do_write(s)
385    self
386  end
387
388  ##
389  # Writes +args+ to the stream along with a record separator.
390  #
391  # See IO#puts for full details.
392
393  def puts(*args)
394    s = ""
395    if args.empty?
396      s << "\n"
397    end
398    args.each{|arg|
399      s << arg.to_s
400      if $/ && /\n\z/ !~ s
401        s << "\n"
402      end
403    }
404    do_write(s)
405    nil
406  end
407
408  ##
409  # Writes +args+ to the stream.
410  #
411  # See IO#print for full details.
412
413  def print(*args)
414    s = ""
415    args.each{ |arg| s << arg.to_s }
416    do_write(s)
417    nil
418  end
419
420  ##
421  # Formats and writes to the stream converting parameters under control of
422  # the format string.
423  #
424  # See Kernel#sprintf for format string details.
425
426  def printf(s, *args)
427    do_write(s % args)
428    nil
429  end
430
431  ##
432  # Flushes buffered data to the SSLSocket.
433
434  def flush
435    osync = @sync
436    @sync = true
437    do_write ""
438    return self
439  ensure
440    @sync = osync
441  end
442
443  ##
444  # Closes the SSLSocket and flushes any unwritten data.
445
446  def close
447    flush rescue nil
448    sysclose
449  end
450end
451