yahns Ruby server user/dev discussion
 help / color / mirror / code / Atom feed
4587483e7048e984cc2a594b5c9c02e55b9d83fd blob 3197 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
 
# Copyright (C) 2013-2016 all contributors <yahns-public@yhbt.net>
# License: GPL-3.0+ (https://www.gnu.org/licenses/gpl-3.0.txt)
# frozen_string_literal: true

require_relative 'sendfile_compat'

# this is to be included into a Kgio::Socket-derived class
# this requires Ruby 2.1 and later for "exception: false"
module Yahns::OpenSSLClient # :nodoc:
  include Yahns::SendfileCompat

  def self.included(cls)
    # Forward these methods to OpenSSL::SSL::SSLSocket so hijackers
    # can rely on stdlib methods instead of ugly kgio stuff that
    # we hope to phase out.
    # This is a bit weird, since OpenSSL::SSL::SSLSocket wraps
    # our actual socket, too, so we must take care to not blindly
    # use method_missing and cause infinite recursion
    %w(sync= read write readpartial write_nonblock read_nonblock
       print printf puts gets readlines readline getc
       readchar ungetc eof eof? << flush
       sysread syswrite).map!(&:to_sym).each do |m|
      cls.__send__(:define_method, m) { |*a| @ssl.__send__(m, *a) }
    end

    # block captures, ugh, but nobody really uses them
    %w(each each_line each_byte).map!(&:to_sym).each do |m|
      cls.__send__(:define_method, m) { |*a, &b| @ssl.__send__(m, *a, &b) }
    end
  end

  # this is special, called during IO initialization in Ruby
  def sync
    defined?(@ssl) ? @ssl.sync : super
  end

  def yahns_init_ssl(ssl_ctx)
    @need_accept = true
    @ssl = OpenSSL::SSL::SSLSocket.new(self, ssl_ctx)
    @ssl_blocked = ''.dup
  end

  def kgio_trywrite(buf)
    ssl_blocked = @ssl_blocked
    if ! ssl_blocked.empty? && ssl_blocked.object_id != buf.object_id
      warn "bk: #{ssl_blocked.inspect}\n!= #{buf.inspect}"
    end
    warn "buf: #{buf.inspect}" if buf.bytesize <= 23
    #warn "b: #{buf.object_id} #{buf.object_id == ssl_blocked.object_id}"
    buf = ssl_blocked.replace(buf) # buf and ssl_blocked may be the same obj
    buf.force_encoding Encoding::BINARY
    rv = @ssl.write_nonblock(buf, exception: false)
    case rv
    when :wait_readable, :wait_writable
      #warn "#{fileno} blocking #{buf.bytesize} #{buf.object_id}"
      return rv # do not clear ssl_blocked
    when Integer
      rv = buf.bytesize == rv ? nil : buf.byteslice(rv, buf.bytesize)
    end
    ssl_blocked.clear
    rv
  end

  def kgio_trywritev(buf)
    abort 'BUG: we cannot use writev with OpenSSL'
  end

  def kgio_syssend(buf, flags)
    kgio_trywrite(buf)
  end

  def kgio_tryread(len, buf)
    if @need_accept
      # most protocols require read before write, so we start the negotiation
      # process here:
      case rv = accept_nonblock(@ssl)
      when :wait_readable, :wait_writable, nil
        return rv
      end
      @need_accept = false
    end
    @ssl.read_nonblock(len, buf, exception: false)
  end

  def close
    @ssl.close # flushes SSLSocket
    super # IO#close
  end

  if RUBY_VERSION.to_f >= 2.3
    def accept_nonblock(ssl)
      ssl.accept_nonblock(exception: false)
    end
  else
    def accept_nonblock(ssl)
      ssl.accept_nonblock
    rescue IO::WaitReadable
      :wait_readable
    rescue IO::WaitWritable
      :wait_writable
    rescue OpenSSL::SSL::SSLError
      nil
    end
  end
end
debug log:

solving 4587483 ...
found 4587483 in https://yhbt.net/yahns-public/20160216111411.GA24123@dcvr.yhbt.net/
found bf64255 in https://yhbt.net/yahns.git
preparing index
index prepared:
100644 bf642556758093262c4244b5c4b17912ed1e1ae4	lib/yahns/openssl_client.rb

applying [1/1] https://yhbt.net/yahns-public/20160216111411.GA24123@dcvr.yhbt.net/
diff --git a/lib/yahns/openssl_client.rb b/lib/yahns/openssl_client.rb
index bf64255..4587483 100644

Checking patch lib/yahns/openssl_client.rb...
Applied patch lib/yahns/openssl_client.rb cleanly.

index at:
100644 4587483e7048e984cc2a594b5c9c02e55b9d83fd	lib/yahns/openssl_client.rb

Code repositories for project(s) associated with this inbox:

	../../../yahns.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).