Project

General

Profile

Download (4.11 KB) Statistics
| Branch: | Tag: | Revision:
require 'proxy/log'
require 'proxy/settings'

module Proxy
class Launcher
include ::Proxy::Log

def pid_path
SETTINGS.daemon_pid
end

def https_enabled?
SETTINGS.ssl_private_key && SETTINGS.ssl_certificate && SETTINGS.ssl_ca_file
end

def http_app
return nil if SETTINGS.http_port.nil?
app = Rack::Builder.new do
::Proxy::Plugins.enabled_plugins.each do |p|
instance_eval(p.http_rackup)
end
end

Rack::Server.new(
:app => app,
:server => :webrick,
:Host => SETTINGS.bind_host,
:Port => SETTINGS.http_port,
:daemonize => false)
end

def https_app
unless https_enabled?
logger.warn "Missing SSL setup, https is disabled."
nil
else
app = Rack::Builder.new do
::Proxy::Plugins.enabled_plugins.each {|p| instance_eval(p.https_rackup)}
end

Rack::Server.new(
:app => app,
:server => :webrick,
:Host => SETTINGS.bind_host,
:Port => SETTINGS.https_port,
:SSLEnable => true,
:SSLVerifyClient => OpenSSL::SSL::VERIFY_PEER,
:SSLPrivateKey => load_ssl_private_key(SETTINGS.ssl_private_key),
:SSLCertificate => load_ssl_certificate(SETTINGS.ssl_certificate),
:SSLCACertificateFile => SETTINGS.ssl_ca_file,
:daemonize => false)
end
end

def load_ssl_private_key(path)
OpenSSL::PKey::RSA.new(File.read(path))
rescue Exception => e
logger.error "Unable to load private SSL key. Are the values correct in settings.yml and do permissions allow reading?: #{e}"
raise e
end

def load_ssl_certificate(path)
OpenSSL::X509::Certificate.new(File.read(path))
rescue Exception => e
logger.error "Unable to load SSL certificate. Are the values correct in settings.yml and do permissions allow reading?: #{e}"
raise e
end

def pid_status
return :exited unless File.exist?(pid_path)
pid = ::File.read(pid_path).to_i
return :dead if pid == 0
Process.kill(0, pid)
:running
rescue Errno::ESRCH
:dead
rescue Errno::EPERM
:not_owned
end

def check_pid
case pid_status
when :running, :not_owned
logger.error "A server is already running. Check #{pid_path}"
exit(2)
when :dead
File.delete(pid_path)
end
end

def write_pid
FileUtils.mkdir_p(File.dirname(pid_path)) unless File.exist?(pid_path)
File.open(pid_path, ::File::CREAT | ::File::EXCL | ::File::WRONLY){|f| f.write("#{Process.pid}") }
at_exit { File.delete(pid_path) if File.exist?(pid_path) }
rescue Errno::EEXIST
check_pid
retry
end

def launch
::Proxy::Plugins.configure_loaded_plugins

http_app = http_app()
https_app = https_app()
raise Exception.new("Both http and https are disabled, unable to start.") if http_app.nil? && https_app.nil?

if SETTINGS.daemon
check_pid
Process.daemon
write_pid
end

t1 = Thread.new { https_app.start } unless https_app.nil?
t2 = Thread.new { http_app.start } unless http_app.nil?

begin
if Gem.loaded_specs['rack'].version < Gem::Version.create('1.6.4')
# Rack installs its own trap; Sleeping for 5 secs insures we overwrite it with our own
sleep 5
trap(:INT) do
exit(0)
end
end
rescue Exception => e
logger.warn "Unable to overwrite interrupt trap: #{e}"
end

(t1 || t2).join
rescue SignalException => e
# This is to prevent the exception handler below from catching SignalException exceptions.
logger.info("Caught #{e}. Exiting")
raise
rescue SystemExit
# do nothing. This is to prevent the exception handler below from catching SystemExit exceptions.
raise
rescue Exception => e
logger.error("Error during startup, terminating. #{e}")
logger.debug("#{e}:#{e.backtrace.join("\n")}")

puts "Errors detected on startup, see log for details. Exiting: #{e}"
exit(1)
end
end
end
(4-4/10)