# File lib/puma/binder.rb, line 7 def initialize(events) @events = events @listeners = [] @inherited_fds = {} @unix_paths = [] @proto_env = { "rack.version".freeze => Rack::VERSION, "rack.errors".freeze => events.stderr, "rack.multithread".freeze => true, "rack.multiprocess".freeze => false, "rack.run_once".freeze => false, "SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "", # Rack blows up if this is an empty string, and Rack::Lint # blows up if it's nil. So 'text/plain' seems like the most # sensible default value. "CONTENT_TYPE".freeze => "text/plain", "QUERY_STRING".freeze => "", SERVER_PROTOCOL => HTTP_11, SERVER_SOFTWARE => PUMA_VERSION, GATEWAY_INTERFACE => CGI_VER } @envs = {} @ios = [] end
# File lib/puma/binder.rb, line 216 def add_ssl_listener(host, port, ctx, optimize_for_latency=true, backlog=1024) if IS_JRUBY @events.error "SSL not supported on JRuby" raise UnsupportedOption end require 'puma/minissl' s = TCPServer.new(host, port) if optimize_for_latency s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) end s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) s.listen backlog ssl = MiniSSL::Server.new s, ctx env = @proto_env.dup env[HTTPS_KEY] = HTTPS @envs[ssl] = env @ios << ssl s end
Tell the server to listen on host host, port port. If optimize_for_latency is true (the default) then clients connecting will be optimized for latency over throughput.
backlog indicates how many unaccepted connections the kernel should allow to accumulate before returning connection refused.
# File lib/puma/binder.rb, line 193 def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024) host = host[1..-2] if host[0..0] == '[' s = TCPServer.new(host, port) if optimize_for_latency s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) end s.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) s.listen backlog @ios << s s end
Tell the server to listen on path as a UNIX domain socket.
# File lib/puma/binder.rb, line 255 def add_unix_listener(path, umask=nil) @unix_paths << path # Let anyone connect by default umask ||= 0 begin old_mask = File.umask(umask) if File.exist? path begin old = UNIXSocket.new path rescue SystemCallError, IOError File.unlink path else old.close raise "There is already a server bound to: #{path}" end end s = UNIXServer.new(path) @ios << s ensure File.umask old_mask end s end
# File lib/puma/binder.rb, line 42 def close @ios.each { |i| i.close } @unix_paths.each { |i| File.unlink i } end
# File lib/puma/binder.rb, line 38 def env(sock) @envs.fetch(sock, @proto_env) end
# File lib/puma/binder.rb, line 47 def import_from_env remove = [] ENV.each do |k,v| if k =~ /PUMA_INHERIT_\d+/ fd, url = v.split(":", 2) @inherited_fds[url] = fd.to_i remove << k end if k =~ /LISTEN_FDS/ && ENV['LISTEN_PID'].to_i == $$ v.to_i.times do |num| fd = num + 3 sock = TCPServer.for_fd(fd) begin url = "unix://" + Socket.unpack_sockaddr_un(sock.getsockname) rescue ArgumentError port, addr = Socket.unpack_sockaddr_in(sock.getsockname) if addr =~ /\:/ addr = "[#{addr}]" end url = "tcp://#{addr}:#{port}" end @inherited_fds[url] = sock end ENV.delete k ENV.delete 'LISTEN_PID' end end remove.each do |k| ENV.delete k end end
# File lib/puma/binder.rb, line 205 def inherit_tcp_listener(host, port, fd) if fd.kind_of? TCPServer s = fd else s = TCPServer.for_fd(fd) end @ios << s s end
# File lib/puma/binder.rb, line 284 def inherit_unix_listener(path, fd) @unix_paths << path if fd.kind_of? TCPServer s = fd else s = UNIXServer.for_fd fd end @ios << s s end
# File lib/puma/binder.rb, line 241 def inherited_ssl_listener(fd, ctx) if IS_JRUBY @events.error "SSL not supported on JRuby" raise UnsupportedOption end require 'puma/minissl' s = TCPServer.for_fd(fd) @ios << MiniSSL::Server.new(s, ctx) s end
# File lib/puma/binder.rb, line 81 def parse(binds, logger) binds.each do |str| uri = URI.parse str case uri.scheme when "tcp" if fd = @inherited_fds.delete(str) logger.log "* Inherited #{str}" io = inherit_tcp_listener uri.host, uri.port, fd else params = Rack::Utils.parse_query uri.query opt = params.key?('low_latency') bak = params.fetch('backlog', 1024).to_i logger.log "* Listening on #{str}" io = add_tcp_listener uri.host, uri.port, opt, bak end @listeners << [str, io] when "unix" path = "#{uri.host}#{uri.path}" if fd = @inherited_fds.delete(str) logger.log "* Inherited #{str}" io = inherit_unix_listener path, fd else logger.log "* Listening on #{str}" umask = nil if uri.query params = Rack::Utils.parse_query uri.query if u = params['umask'] # Use Integer() to respect the 0 prefix as octal umask = Integer(u) end end io = add_unix_listener path, umask end @listeners << [str, io] when "ssl" if IS_JRUBY @events.error "SSL not supported on JRuby" raise UnsupportedOption end params = Rack::Utils.parse_query uri.query require 'puma/minissl' ctx = MiniSSL::Context.new unless params['key'] @events.error "Please specify the SSL key via 'key='" end ctx.key = params['key'] unless params['cert'] @events.error "Please specify the SSL cert via 'cert='" end ctx.cert = params['cert'] ctx.verify_mode = MiniSSL::VERIFY_NONE if fd = @inherited_fds.delete(str) logger.log "* Inherited #{str}" io = inherited_ssl_listener fd, ctx else logger.log "* Listening on #{str}" io = add_ssl_listener uri.host, uri.port, ctx end @listeners << [str, io] else logger.error "Invalid URI: #{str}" end end # If we inherited fds but didn't use them (because of a # configuration change), then be sure to close them. @inherited_fds.each do |str, fd| logger.log "* Closing unused inherited connection: #{str}" begin if fd.kind_of? TCPServer fd.close else IO.for_fd(fd).close end rescue SystemCallError end # We have to unlink a unix socket path that's not being used uri = URI.parse str if uri.scheme == "unix" path = "#{uri.host}#{uri.path}" File.unlink path end end end
Generated with the Darkfish Rdoc Generator 2.