Methods
Public Class
Public Instance
Constants
TLS_OPTIONS | = | { alpn_protocols: %w[h2 http/1.1].freeze } |
rubocop:disable Style/MutableConstant |
Attributes
ssl_session | [W] |
Public Class methods
new(_, _, options)
[show source]
# File lib/httpx/io/ssl.rb 19 def initialize(_, _, options) 20 super 21 22 ctx_options = TLS_OPTIONS.merge(options.ssl) 23 @sni_hostname = ctx_options.delete(:hostname) || @hostname 24 25 if @keep_open && @io.is_a?(OpenSSL::SSL::SSLSocket) 26 # externally initiated ssl socket 27 @ctx = @io.context 28 @state = :negotiated 29 else 30 @ctx = OpenSSL::SSL::SSLContext.new 31 @ctx.set_params(ctx_options) unless ctx_options.empty? 32 unless @ctx.session_cache_mode.nil? # a dummy method on JRuby 33 @ctx.session_cache_mode = 34 OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE 35 end 36 37 yield(self) if block_given? 38 end 39 40 @verify_hostname = @ctx.verify_hostname 41 end
Public Instance methods
can_verify_peer?()
[show source]
# File lib/httpx/io/ssl.rb 72 def can_verify_peer? 73 @ctx.verify_mode == OpenSSL::SSL::VERIFY_PEER 74 end
connect()
[show source]
# File lib/httpx/io/ssl.rb 95 def connect 96 return if @state == :negotiated 97 98 unless @state == :connected 99 super 100 return unless @state == :connected 101 end 102 103 unless @io.is_a?(OpenSSL::SSL::SSLSocket) 104 if (hostname_is_ip = (@ip == @sni_hostname)) 105 # IPv6 address would be "[::1]", must turn to "0000:0000:0000:0000:0000:0000:0000:0001" for cert SAN check 106 @sni_hostname = @ip.to_string 107 # IP addresses in SNI is not valid per RFC 6066, section 3. 108 @ctx.verify_hostname = false 109 end 110 111 @io = OpenSSL::SSL::SSLSocket.new(@io, @ctx) 112 113 @io.hostname = @sni_hostname unless hostname_is_ip 114 @io.session = @ssl_session unless ssl_session_expired? 115 @io.sync_close = true 116 end 117 try_ssl_connect 118 end
connected?()
[show source]
# File lib/httpx/io/ssl.rb 83 def connected? 84 @state == :negotiated 85 end
expired?()
[show source]
# File lib/httpx/io/ssl.rb 87 def expired? 88 super || ssl_session_expired? 89 end
protocol()
[show source]
# File lib/httpx/io/ssl.rb 52 def protocol 53 @io.alpn_protocol || super 54 rescue StandardError 55 super 56 end
session_new_cb(&pr)
[show source]
# File lib/httpx/io/ssl.rb 44 def session_new_cb(&pr) 45 @ctx.session_new_cb = proc { |_, sess| pr.call(sess) } 46 end
ssl_session_expired?()
[show source]
# File lib/httpx/io/ssl.rb 91 def ssl_session_expired? 92 @ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (@ssl_session.time.to_f + @ssl_session.timeout) 93 end
try_ssl_connect()
[show source]
# File lib/httpx/io/ssl.rb 120 def try_ssl_connect 121 ret = @io.connect_nonblock(exception: false) 122 log(level: 3, color: :cyan) { "TLS CONNECT: #{ret}..." } 123 case ret 124 when :wait_readable 125 @interests = :r 126 return 127 when :wait_writable 128 @interests = :w 129 return 130 end 131 @io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && @verify_hostname 132 transition(:negotiated) 133 @interests = :w 134 end
verify_hostname(host)
[show source]
# File lib/httpx/io/ssl.rb 76 def verify_hostname(host) 77 return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE 78 return false if !@io.respond_to?(:peer_cert) || @io.peer_cert.nil? 79 80 OpenSSL::SSL.verify_certificate_identity(@io.peer_cert, host) 81 end