IO::EndpointSourceIOEndpointSSLEndpoint

class SSLEndpoint

Represents an SSL/TLS endpoint that wraps another endpoint.

Definitions

def initialize(endpoint, **options)

Initialize a new SSL endpoint.

Signature

parameter endpoint Generic

The underlying endpoint to wrap with SSL.

option ssl_context OpenSSL::SSL::SSLContext, nil

An optional SSL context to use.

parameter options Hash

Additional options including :ssl_params and :hostname.

Implementation

def initialize(endpoint, **options)
	super(**options)
	
	@endpoint = endpoint
	
	if ssl_context = options[:ssl_context]
		@context = build_context(ssl_context)
	else
		@context = nil
	end
end

def to_s

Get a string representation of the SSL endpoint.

Signature

returns String

A string representation showing the underlying endpoint.

Implementation

def to_s
	"ssl:#{@endpoint}"
end

def inspect

Get a detailed string representation of the SSL endpoint.

Signature

returns String

A detailed string representation including the underlying endpoint.

Implementation

def inspect
	"\#<#{self.class} endpoint=#{@endpoint.inspect}>"
end

def address

Get the address from the underlying endpoint.

Signature

returns Address, nil

The address from the underlying endpoint.

Implementation

def address
	@endpoint.address
end

def hostname

Get the hostname for SSL verification.

Signature

returns String, nil

The hostname from options or the underlying endpoint.

Implementation

def hostname
	@options[:hostname] || @endpoint.hostname
end

attr :endpoint

Signature

attribute Generic

The underlying endpoint.

attr :options

Signature

attribute Hash

The options hash.

def params

Get SSL parameters from options.

Signature

returns Hash, nil

SSL parameters if specified in options.

Implementation

def params
	@options[:ssl_params]
end

def build_context(context = ::OpenSSL::SSL::SSLContext.new)

Build an SSL context with configured parameters.

Signature

parameter context OpenSSL::SSL::SSLContext

An optional SSL context to configure.

returns OpenSSL::SSL::SSLContext

The configured SSL context.

Implementation

def build_context(context = ::OpenSSL::SSL::SSLContext.new)
	if params = self.params
		context.set_params(params)
	end
	
	# context.setup
	# context.freeze
	
	return context
end

def context

Get or build the SSL context.

Signature

returns OpenSSL::SSL::SSLContext

The SSL context.

Implementation

def context
	@context ||= build_context
end

def make_server(io)

Create an SSL server socket from an IO object.

Signature

parameter io IO

The underlying IO object.

returns OpenSSL::SSL::SSLServer

A new SSL server socket.

Implementation

def make_server(io)
	::OpenSSL::SSL::SSLServer.new(io, self.context).tap do |server|
		server.start_immediately = false
	end
end

def make_socket(io)

Create an SSL client socket from an IO object.

Signature

parameter io IO

The underlying IO object.

returns OpenSSL::SSL::SSLSocket

A new SSL client socket.

Implementation

def make_socket(io)
	::OpenSSL::SSL::SSLSocket.new(io, self.context).tap do |socket|
		# We consider the underlying IO is owned by the SSL socket:
		socket.sync_close = true
	end
end

def bind(*arguments, **options, &block)

Connect to the underlying endpoint and establish a SSL connection.

Signature

yields {|socket| ...}

If a block is given, yields the SSL server socket.

parameter socket Socket

The SSL server socket.

returns Socket

the connected socket

Implementation

def bind(*arguments, **options, &block)
	if block_given?
		@endpoint.bind(*arguments, **options) do |server|
			yield self.make_server(server)
		end
	else
		@endpoint.bind(*arguments, **options).map do |server|
			self.make_server(server)
		end
	end
end

def connect(&block)

Connect to the underlying endpoint and establish a SSL connection.

Signature

yields {|socket| ...}

If a block is given, yields the connected SSL socket.

parameter socket Socket

The connected SSL socket.

returns Socket

the connected socket

Implementation

def connect(&block)
	socket = self.make_socket(@endpoint.connect)
	
	if hostname = self.hostname
		socket.hostname = hostname
	end
	
	begin
		socket.connect
	rescue
		socket.close
		raise
	end
	
	return socket unless block_given?
	
	begin
		yield socket
	ensure
		socket.close
	end
end

def each

Enumerate all endpoints by wrapping each underlying endpoint with SSL.

Signature

yields {|endpoint| ...}

For each underlying endpoint, yields an SSL-wrapped endpoint.

parameter endpoint SSLEndpoint

An SSL endpoint.

Implementation

def each
	return to_enum unless block_given?
	
	@endpoint.each do |endpoint|
		yield self.class.new(endpoint, **@options)
	end
end