module Rev::SSL

The easiest way to add SSL support to your Rev applications is to use the SSLSocket class. However, the SSL module is provided for cases where you’ve already subclassed TCPSocket and want to optionally provide SSL support in that class.

This module monkeypatches Rev::IO to include SSL support. This can be accomplished by extending any Rev:IO (or subclass) object with Rev::SSL after the connection has completed, e.g.

class MySocket < Rev::TCPSocket
  def on_connect
    extend Rev::SSL
    ssl_client_start
  end
end

Public Instance Methods

ssl_client_start() click to toggle source

Start SSL explicitly in client mode. After calling this, callbacks will fire for checking the peer certificate (ssl_peer_cert) and its validity (ssl_verify_result)

# File lib/rev/ssl.rb, line 30
def ssl_client_start
  raise "ssl already started" if @_ssl_socket
  
  context = respond_to?(:ssl_context) ? ssl_context : OpenSSL::SSL::SSLContext.new
  
  @_ssl_socket = SSL::IO.new(@_io, context)
  @_ssl_init = proc { @_ssl_socket.connect_nonblock }
  
  ssl_init
end
ssl_server_start() click to toggle source

Start SSL explicitly in server mode. After calling this, callbacks will fire for checking the peer certificate (ssl_peer_cert) and its validity (ssl_verify_result)

# File lib/rev/ssl.rb, line 44
def ssl_server_start
  raise "ssl already started" if @_ssl_socket
  
  @_ssl_socket = SSL::IO.new(@_io, ssl_context)
  @_ssl_init = proc { @_ssl_socket.accept_nonblock }
  
  ssl_init
end

Protected Instance Methods

on_readable() click to toggle source
# File lib/rev/ssl.rb, line 85
def on_readable
  if @_ssl_init
    disable
    ssl_init
    return
  end
  
  begin
    on_read @_ssl_socket.read_nonblock(Rev::IO::INPUT_SIZE)
  rescue Errno::EAGAIN, SSL::IO::ReadAgain
    return
  rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET, EOFError
    close
  end
end
on_writable() click to toggle source
# File lib/rev/ssl.rb, line 101
def on_writable
  if @_ssl_init
    disable_write_watcher
    ssl_init
    return
  end
  
  begin
    nbytes = @_ssl_socket.write_nonblock @_write_buffer.to_str
  rescue Errno::EAGAIN, SSL::IO::WriteAgain
    return
  rescue OpenSSL::SSL::SSLError, Errno::EPIPE, Errno::ECONNRESET
    close
    return
  end
  
  @_write_buffer.read(nbytes)
  
  if @_write_buffer.empty?
    disable_write_watcher
    on_write_complete
  end
end
ssl_init() click to toggle source
# File lib/rev/ssl.rb, line 57
def ssl_init
  begin
    @_ssl_init.call
    ssl_init_complete
  rescue SSL::IO::ReadAgain
    enable unless enabled?
  rescue SSL::IO::WriteAgain
    enable_write_watcher
  rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::EPIPE
    close
  rescue => ex
    if respond_to? :on_ssl_error
      on_ssl_error(ex)
    else raise ex
    end
  end
end
ssl_init_complete() click to toggle source
# File lib/rev/ssl.rb, line 75
def ssl_init_complete
  @_ssl_init = nil
  enable unless enabled?
  
  on_peer_cert(@_ssl_socket.peer_cert) if respond_to? :on_peer_cert
  # FIXME Rev::SSL::IO#verify_result needs to be adapted to non-blocking
  #on_ssl_result(@_ssl_socket.verify_result) if respond_to? :on_ssl_result
  on_ssl_connect if respond_to? :on_ssl_connect
end