Class: IO::Endpoint::SSLEndpoint

Inherits:
Generic
  • Object
show all
Defined in:
lib/io/endpoint/ssl_endpoint.rb

Overview

Represents an SSL/TLS endpoint that wraps another endpoint.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Generic

#accept, #bound, #connected, #linger, #local_address, parse, #reuse_address?, #reuse_port?, #timeout, #with, #wrapper

Constructor Details

#initialize(endpoint, **options) ⇒ SSLEndpoint

Initialize a new SSL endpoint.

Parameters:

  • ssl_context (Hash)

    a customizable set of options

  • tls_configuration (Hash)

    a customizable set of options



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/io/endpoint/ssl_endpoint.rb', line 37

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

Instance Attribute Details

#endpointObject (readonly)

Returns the value of attribute endpoint.



74
75
76
# File 'lib/io/endpoint/ssl_endpoint.rb', line 74

def endpoint
  @endpoint
end

#optionsObject (readonly)

Returns the value of attribute options.



76
77
78
# File 'lib/io/endpoint/ssl_endpoint.rb', line 76

def options
  @options
end

#The underlying endpoint.(underlyingendpoint.) ⇒ Object (readonly)



74
# File 'lib/io/endpoint/ssl_endpoint.rb', line 74

attr :endpoint

Instance Method Details

#addressObject

Get the address from the underlying endpoint.



63
64
65
# File 'lib/io/endpoint/ssl_endpoint.rb', line 63

def address
	@endpoint.address
end

#bind(*arguments, **options, &block) ⇒ Object

Connect to the underlying endpoint and establish a SSL connection.



137
138
139
140
141
142
143
144
145
146
147
# File 'lib/io/endpoint/ssl_endpoint.rb', line 137

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

#build_context(context = ::OpenSSL::SSL::SSLContext.new) ⇒ Object

Build an SSL context with configured parameters.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/io/endpoint/ssl_endpoint.rb', line 93

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

#connect(&block) ⇒ Object

Connect to the underlying endpoint and establish a SSL connection.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/io/endpoint/ssl_endpoint.rb', line 153

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

#contextObject

Get or build the SSL context.



110
111
112
# File 'lib/io/endpoint/ssl_endpoint.rb', line 110

def context
	@context ||= build_context
end

#eachObject

Enumerate all endpoints by wrapping each underlying endpoint with SSL.



179
180
181
182
183
184
185
# File 'lib/io/endpoint/ssl_endpoint.rb', line 179

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

#hostnameObject

Get the hostname for SSL verification.



69
70
71
# File 'lib/io/endpoint/ssl_endpoint.rb', line 69

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

#inspectObject

Get a detailed string representation of the SSL endpoint.



57
58
59
# File 'lib/io/endpoint/ssl_endpoint.rb', line 57

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

#make_server(io) ⇒ Object

Create an SSL server socket from an IO object.



117
118
119
120
121
# File 'lib/io/endpoint/ssl_endpoint.rb', line 117

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

#make_socket(io) ⇒ Object

Create an SSL client socket from an IO object.



126
127
128
129
130
131
# File 'lib/io/endpoint/ssl_endpoint.rb', line 126

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

#paramsObject

Get SSL parameters from options.



80
81
82
# File 'lib/io/endpoint/ssl_endpoint.rb', line 80

def params
	@options[:ssl_params]
end

#The options hash.=(optionshash. = (value)) ⇒ Object



76
# File 'lib/io/endpoint/ssl_endpoint.rb', line 76

attr :options

#tls_configurationObject

Get the transport-neutral TLS configuration from options.



86
87
88
# File 'lib/io/endpoint/ssl_endpoint.rb', line 86

def tls_configuration
	@options[:tls_configuration]
end

#to_sObject

Get a string representation of the SSL endpoint.



51
52
53
# File 'lib/io/endpoint/ssl_endpoint.rb', line 51

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