Class: Async::IO::SSLSocket

Inherits:
Generic
  • Object
show all
Includes:
Peer
Defined in:
lib/async/io/ssl_socket.rb

Overview

Asynchronous TCP socket wrapper.

Constant Summary

Constants inherited from Generic

Generic::WRAPPERS

Instance Attribute Summary

Attributes inherited from Generic

#timeout

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Peer

#connected?, #eof, #eof?, #protocol, #sync, #sync=, #type

Methods inherited from Generic

#<<, #connected?, #dup, #nonblock, #nonblock=, #nonblock?, #read, #readable?, #sysread, #syswrite, #wait, wrap, wrap_blocking_method, wraps, #write

Constructor Details

#initialize(socket, context) ⇒ SSLSocket

Returns a new instance of SSLSocket.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/async/io/ssl_socket.rb', line 49

def initialize(socket, context)
  if socket.is_a?(self.class.wrapped_klass)
    super
  else
    io = self.class.wrapped_klass.new(socket.to_io, context)
    if socket.respond_to?(:reactor)
      super(io, socket.reactor)
      
      # We detach the socket from the reactor, otherwise it's possible to add the file descriptor to the selector twice, which is bad.
      socket.reactor = nil
    else
      super(io)
    end
    
    # This ensures that when the internal IO is closed, it also closes the internal socket:
    io.sync_close = true
    
    if socket.respond_to?(:timeout)
      @timeout = socket.timeout
    end
  end
end

Class Method Details

.connect(socket, context, hostname = nil, &block) ⇒ Object



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
# File 'lib/async/io/ssl_socket.rb', line 21

def self.connect(socket, context, hostname = nil, &block)
  client = self.new(socket, context)
  
  # Used for SNI:
  if hostname
    client.hostname = hostname
  end
  
  begin
    client.connect
  rescue
    # If the connection fails (e.g. certificates are invalid), the caller never sees the socket, so we close it and raise the exception up the chain.
    client.close
    
    raise
  end
  
  return client unless block_given?
  
  begin
    yield client
  ensure
    client.close
  end
end

Instance Method Details

#acceptObject

Invokes accept_nonblock on the underlying io. If the operation would block, the current task is paused until the operation can succeed, at which point it’s resumed and the operation is completed.



18
# File 'lib/async/io/ssl_socket.rb', line 18

wrap_blocking_method :accept, :accept_nonblock

#close_readObject



85
86
87
# File 'lib/async/io/ssl_socket.rb', line 85

def close_read
  @io.to_io.shutdown(Socket::SHUT_RD)
end

#close_writeObject



80
81
82
83
# File 'lib/async/io/ssl_socket.rb', line 80

def close_write
  # Invokes SSL_shutdown, which sends a close_notify message to the peer.
  @io.__send__(:stop)
end

#connectObject

Invokes connect_nonblock on the underlying io. If the operation would block, the current task is paused until the operation can succeed, at which point it’s resumed and the operation is completed.



19
# File 'lib/async/io/ssl_socket.rb', line 19

wrap_blocking_method :connect, :connect_nonblock

#local_addressObject



72
73
74
# File 'lib/async/io/ssl_socket.rb', line 72

def local_address
  @io.to_io.local_address
end

#remote_addressObject



76
77
78
# File 'lib/async/io/ssl_socket.rb', line 76

def remote_address
  @io.to_io.remote_address
end

#shutdown(how) ⇒ Object



89
90
91
92
# File 'lib/async/io/ssl_socket.rb', line 89

def shutdown(how)
  @io.flush
  @io.to_io.shutdown(how)
end