Spec-Zone.ru › Ruby 2.2

модуль OpenSSL::Buffering

Включенные модули:
Enumerable

OpenSSL IO буферизующий модуль.

Этот модуль позволяет OpenSSL::SSL::SSLSocket вести себя как IO.

Обычно вы не будете использовать этот модуль напрямую, вы можете увидеть его реализацию в OpenSSL::SSL::SSLSocket.

Константы

BLOCK_SIZE

Размер по умолчанию для чтения или записи в SSLSocket для операций с буфером.

Атрибуты

sync[RW]

«Режим синхронизации» SSLSocket.

Для получения подробной информации см. IO#sync.

Публичные методы класса

new(*) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 43
def initialize(*)
  super
  @eof = false
  @rbuffer = ""
  @sync = @io.sync
end

Создаёт экземпляр буферизующего модуля IO OpenSSL.

Вызывается метод суперкласса

Методы публичного экземпляра

<<(s) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 389
def << (s)
  do_write(s)
  self
end

Записывает s в поток. s будет преобразовано в строку с использованием String#to_s.

close() Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 452
def close
  flush rescue nil
  sysclose
end

Закрывает SSLSocket и сбрасывает все не записанные данные.

each(eol=$/) { |line| ... } Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 227
def each(eol=$/)
  while line = self.gets(eol)
    yield line
  end
end

Выполняет блок для каждой строки в потоке, где строки разделены eol.

См. также gets

Также алиас: each_line
each_byte() { |byte| ... } Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 268
def each_byte # :yields: byte
  while c = getc
    yield(c.ord)
  end
end

Вызывает заданный блок один раз для каждого байта в потоке.

each_line(eol=$/)
Псевдоним для: each
eof()
Псевдоним для: eof?
eof?() Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 299
def eof?
  fill_rbuff if !@eof && @rbuffer.empty?
  @eof && @rbuffer.empty?
end

Возвращает true, если поток находится в конце файла, что означает, что больше данных для чтения нет.

Также алиас: eof
flush() Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 440
def flush
  osync = @sync
  @sync = true
  do_write ""
  return self
ensure
  @sync = osync
end

Сбрасывает буферизованные данные в SSLSocket.

getc() Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 261
def getc
  read(1)
end

Считывает один символ из потока. Возвращает nil, если вызов осуществляется в конце файла.

gets(eol=$/, limit=nil) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 203
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 limit and limit >= 0
    size = [size, limit].min
  end
  consume_rbuff(size)
end

Считывает следующую «строку» из потока. Строки разделены eol. Если limit предоставлено, результат не будет длиннее указанного количества байтов.

eol может быть строкой или Regexp.

В отличие от IO#gets, считанная строка не будет назначена +$_+.

В отличие от IO#gets, разделитель должен быть предоставлен, если предоставлен предел.

print(*args) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 419
def print(*args)
  s = ""
  args.each{ |arg| s << arg.to_s }
  do_write(s)
  nil
end

Записывает args в поток.

См. IO#print для подробных сведений.

printf(s, *args) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 432
def printf(s, *args)
  do_write(s % args)
  nil
end

Форматирует и записывает в поток, преобразуя параметры в соответствии со строкой формата.

См. Kernel#sprintf для подробностей о строке формата.

puts(*args) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 399
def puts(*args)
  s = ""
  if args.empty?
    s << "\n"
  end
  args.each{|arg|
    s << arg.to_s
    if $/ && /\n\z/ !~ s
      s << "\n"
    end
  }
  do_write(s)
  nil
end

Записывает args в поток вместе с разделителем записей.

См. IO#puts для подробных сведений.

read(size=nil, buf=nil) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 90
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

Считывает size байтов из потока. Если buf предоставлен, он должен ссылаться на строку, которая получит данные.

См. IO#read для подробных сведений.

read_nonblock(maxlen, buf=nil, exception: true) Показать исходный код
# 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
  raise EOFError if ret.empty?
  ret
end

Считывает не более maxlen байтов в режиме без блокировки.

Когда данные не могут быть прочитаны без блокировки, генерируется OpenSSL::SSL::SSLError, дополненный IO::WaitReadable или IO::WaitWritable.

IO::WaitReadable означает, что SSL необходимо прочитать внутри, поэтому #read_nonblock следует вызвать снова, когда базовый IO доступен для чтения.

IO::WaitWritable означает, что SSL необходимо записать внутри, поэтому #read_nonblock следует вызвать снова после того, как базовый IO доступен для записи.

#read_nonblock требует двух блоков обработки исключений, как указано ниже:

# 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

Обратите внимание, что одной из причин, по которой #read_nonblock записывает в базовый IO, является запрос стороны о новом рукопожатии TLS/SSL. Дополнительные сведения см. в часто задаваемых вопросах OpenSSL. www.openssl.org/support/faq.html

readchar() Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 278
def readchar
  raise EOFError if eof?
  getc
end

Считывает строку из одного символа из потока. При достижении конца файла генерируется EOFError.

readline(eol=$/) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 252
def readline(eol=$/)
  raise EOFError if eof?
  gets(eol)
end

Считывает строку из потока, разделенную eol.

При достижении конца файла генерируется EOFError.

readlines(eol=$/) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 239
def readlines(eol=$/)
  ary = []
  while line = self.gets(eol)
    ary << line
  end
  ary
end

Считывает строки из потока, разделенные eol.

См. также gets

readpartial(maxlen, buf=nil) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 117
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
  raise EOFError if ret.empty?
  ret
end

Считывает не более maxlen байтов из потока. Если buf предоставлен, он должен ссылаться на строку, которая получит данные.

См. IO#readpartial для подробных сведений.

ungetc(c) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 291
def ungetc(c)
  @rbuffer[0,0] = c.chr
end

Возвращает символ c обратно в поток, таким образом, последующее чтение буферизованного символа вернёт его.

В отличие от IO#getc, может быть возвращено несколько байтов обратно в поток.

Не оказывает никакого влияния на операции чтения без буферизации (например, sysread).

write(s) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 342
def write(s)
  do_write(s)
  s.bytesize
end

Записывает s в поток. Если аргумент не является строкой, он будет преобразован с помощью String#to_s. Возвращает количество записанных байтов.

END_OF_DOCUMENT_MARKER
write_nonblock(s, exception: true) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 380
def write_nonblock(s, exception: true)
  flush
  syswrite_nonblock(s, exception: exception)
end

Записывает str в асинхронном режиме.

Если есть буферизованные данные, они сначала сбрасываются. Это может заблокировать выполнение.

#write_nonblock возвращает количество байтов, записанных в соединение SSL.

Если данные не могут быть записаны без блокировки, возникает исключение OpenSSL::SSL::SSLError, дополненное IO::WaitReadable или IO::WaitWritable.

IO::WaitReadable означает, что SSL требует внутреннего чтения, поэтому #write_nonblock следует вызвать снова после того, как подлежащий IO станет доступным для чтения.

IO::WaitWritable означает, что SSL требует внутреннего записи, поэтому #write_nonblock следует вызвать снова после того, как подлежащий IO станет доступным для записи.

Поэтому #write_nonblock требует двух блоков обработки исключений, как показано ниже.

# 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

Обратите внимание, что одна из причин, по которой #write_nonblock считывает данные из подлежащего IO, заключается в запросе со стороны клиента нового рукопожатия TLS/SSL. Более подробную информацию можно найти в FAQ OpenSSL. www.openssl.org/support/faq.html

Приватные методы экземпляра

consume_rbuff(size=nil) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 71
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

Потребляет size байта из буфера

do_write(s) Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 314
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

Записывает s в буфер. Когда буфер заполнен или sync имеет значение true, буфер сбрасывается в подлежащий сокет.

fill_rbuff() Показать исходный код
# File ext/openssl/lib/openssl/buffering.rb, line 58
def fill_rbuff
  begin
    @rbuffer << self.sysread(BLOCK_SIZE)
  rescue Errno::EAGAIN
    retry
  rescue EOFError
    @eof = true
  end
end

Заполняет буфер данными из подлежащего SSLSocket

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API