about summary refs log tree commit homepage
path: root/lib/unicorn/ssl_server.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unicorn/ssl_server.rb')
-rw-r--r--lib/unicorn/ssl_server.rb42
1 files changed, 42 insertions, 0 deletions
diff --git a/lib/unicorn/ssl_server.rb b/lib/unicorn/ssl_server.rb
new file mode 100644
index 0000000..c00c3ae
--- /dev/null
+++ b/lib/unicorn/ssl_server.rb
@@ -0,0 +1,42 @@
+# -*- encoding: binary -*-
+# :stopdoc:
+# this module is meant to be included in Unicorn::HttpServer
+# It is an implementation detail and NOT meant for users.
+module Unicorn::SSLServer
+  attr_accessor :ssl_engine
+
+  def ssl_enable!
+    sni_hostnames = rack_sni_hostnames(@app)
+    seen = {} # we map a single SSLContext to multiple listeners
+    listener_ctx = {}
+    @listener_opts.each do |address, address_opts|
+      ssl_opts = address_opts[:ssl_opts] or next
+      listener_ctx[address] = seen[ssl_opts.object_id] ||= begin
+        unless sni_hostnames.empty?
+          ssl_opts = ssl_opts.dup
+          ssl_opts[:sni_hostnames] = sni_hostnames
+        end
+        ctx = Flipper.ssl_context(ssl_opts)
+        # FIXME: make configurable
+        ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
+        ctx
+      end
+    end
+    Unicorn::HttpServer::LISTENERS.each do |listener|
+      ctx = listener_ctx[sock_name(listener)] or next
+      listener.extend(Kgio::SSLServer)
+      listener.ssl_ctx = ctx
+      listener.kgio_ssl_class = Unicorn::SSLClient
+    end
+  end
+
+  # ugh, this depends on Rack internals...
+  def rack_sni_hostnames(rack_app) # :nodoc:
+    hostnames = {}
+    if Rack::URLMap === rack_app
+      mapping = rack_app.instance_variable_get(:@mapping)
+      mapping.each { |hostname,_,_,_| hostnames[hostname] = true }
+    end
+    hostnames.keys
+  end
+end