Class: Falcon::Hosts

Inherits:
Object
  • Object
show all
Defined in:
lib/falcon/hosts.rb

Constant Summary collapse

SERVER_CIPHERS =
"EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5".freeze

Instance Method Summary collapse

Constructor Details

#initialize(configuration) ⇒ Hosts

Returns a new instance of Hosts.



35
36
37
38
39
40
41
42
43
# File 'lib/falcon/hosts.rb', line 35

def initialize(configuration)
	@named = {}
	@server_context = nil
	@server_endpoint = nil
	
	configuration.each(:authority) do |environment|
		add(Host.new(environment))
	end
end

Instance Method Details

#add(host) ⇒ Object



88
89
90
# File 'lib/falcon/hosts.rb', line 88

def add(host)
	@named[host.authority] = host
end

#each(&block) ⇒ Object



45
46
47
# File 'lib/falcon/hosts.rb', line 45

def each(&block)
	@named.each_value(&block)
end

#endpointObject



49
50
51
52
53
54
55
# File 'lib/falcon/hosts.rb', line 49

def endpoint
	@server_endpoint ||= Async::HTTP::Endpoint.parse(
		'https://[::]',
		ssl_context: self.ssl_context,
		reuse_address: true
	)
end

#host_context(socket, hostname) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/falcon/hosts.rb', line 74

def host_context(socket, hostname)
	if host = @named[hostname]
		Async.logger.debug(self) {"Resolving #{hostname} -> #{host}"}
		
		socket.hostname = hostname
		
		return host.ssl_context
	else
		Async.logger.warn(self) {"Unable to resolve #{hostname}!"}
		
		return nil
	end
end

#proxyObject



92
93
94
# File 'lib/falcon/hosts.rb', line 92

def proxy
	Proxy.new(Falcon::BadRequest, @named)
end

#redirection(secure_endpoint) ⇒ Object



96
97
98
# File 'lib/falcon/hosts.rb', line 96

def redirection(secure_endpoint)
	Redirection.new(Falcon::BadRequest, @named, secure_endpoint)
end

#run(container = Async::Container.new, **options) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/falcon/hosts.rb', line 100

def run(container = Async::Container.new, **options)
	secure_endpoint = Async::HTTP::Endpoint.parse(options[:bind_secure], ssl_context: self.ssl_context)
	insecure_endpoint = Async::HTTP::Endpoint.parse(options[:bind_insecure])
	
	secure_endpoint_bound = insecure_endpoint_bound = nil
	
	Async::Reactor.run do
		secure_endpoint_bound = Async::IO::SharedEndpoint.bound(secure_endpoint)
		insecure_endpoint_bound = Async::IO::SharedEndpoint.bound(insecure_endpoint)
	end.wait
	
	container.run(name: "Falcon Proxy", restart: true) do |task, instance|
		proxy = self.proxy
		
		proxy_server = Falcon::Server.new(proxy, secure_endpoint_bound, secure_endpoint.protocol, secure_endpoint.scheme)
		
		proxy_server.run
	end
	
	container.run(name: "Falcon Redirector", restart: true) do |task, instance|
		redirection = self.redirection(secure_endpoint)
		
		redirection_server = Falcon::Server.new(redirection, insecure_endpoint_bound, insecure_endpoint.protocol, insecure_endpoint.scheme)
		
		redirection_server.run
	end
	
	container.attach do
		secure_endpoint_bound.close
		insecure_endpoint_bound.close
	end
	
	return container
end

#ssl_contextObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/falcon/hosts.rb', line 57

def ssl_context
	@server_context ||= OpenSSL::SSL::SSLContext.new.tap do |context|
		context.servername_cb = Proc.new do |socket, hostname|
			self.host_context(socket, hostname)
		end
		
		context.session_id_context = "falcon"
		
		context.set_params(
			ciphers: SERVER_CIPHERS,
			verify_mode: OpenSSL::SSL::VERIFY_NONE,
		)
		
		context.setup
	end
end