1 # -*- encoding: binary -*-
3 # this module is meant to be included in Unicorn::HttpServer
4 # It is an implementation detail and NOT meant for users.
5 module Unicorn::SSLServer
6 attr_accessor :ssl_engine
9 sni_hostnames = rack_sni_hostnames(@app)
10 seen = {} # we map a single SSLContext to multiple listeners
12 @listener_opts.each do |address, address_opts|
13 ssl_opts = address_opts[:ssl_opts] or next
14 listener_ctx[address] = seen[ssl_opts.object_id] ||= begin
15 unless sni_hostnames.empty?
16 ssl_opts = ssl_opts.dup
17 ssl_opts[:sni_hostnames] = sni_hostnames
19 ctx = Flipper.ssl_context(ssl_opts)
20 # FIXME: make configurable
21 ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
25 Unicorn::HttpServer::LISTENERS.each do |listener|
26 ctx = listener_ctx[sock_name(listener)] or next
27 listener.extend(Kgio::SSLServer)
28 listener.ssl_ctx = ctx
29 listener.kgio_ssl_class = Unicorn::SSLClient
33 # ugh, this depends on Rack internals...
34 def rack_sni_hostnames(rack_app) # :nodoc:
36 if Rack::URLMap === rack_app
37 mapping = rack_app.instance_variable_get(:@mapping)
38 mapping.each { |hostname,_,_,_| hostnames[hostname] = true }