Repository: puma/puma
File: lib/puma/binder.rb (Ruby)

Code before:
        end
      end
    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.
    #
    def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
      if host == "localhost"
        loopback_addresses.each do |addr|
          add_tcp_listener addr, port, optimize_for_latency, backlog
        end
        return
      end

      host = host[1..-2] if host and host[0..0] == '['
      tcp_server = TCPServer.new(host, port)

      if defined? Localhost::Authority
        raise "Puma compiled without SSL support" unless HAS_SSL
        if ENV['RACK_ENV'] == "development" || ENV['RACK_ENV'] == "test"
          authority = Localhost::Authority.fetch
          tcp_server = OpenSSL::SSL::SSLServer.new(tcp_server,  authority.server_context)
          env = @proto_env.dup
          env[HTTPS_KEY] = HTTPS
          @envs[tcp_server] = env
        end
      end


      if optimize_for_latency
        tcp_server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
      end
      tcp_server.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
      tcp_server.listen backlog

      @ios << tcp_server
      tcp_server
    end

    def inherit_tcp_listener(host, port, fd)
      s = fd.kind_of?(::TCPServer) ? fd : ::TCPServer.for_fd(fd)

      @ios << s
      s
    end


Review comment (bug):
Try to do this in the top level process (I assume this is) because there are some race conditions which I need to fix - if multiple processes try to get the same certificate at the same time, they may clobber each other - in theory not a big problem (especially for development) but you can simply avoid it by ensuring it's only called once per session and at some point I'll make sure it's more robust. See https://github.com/socketry/localhost/issues/1 for more details.

Code after:
        uri = URI.parse str
        if uri.scheme == "unix"
          path = "#{uri.host}#{uri.path}"
          File.unlink path
        end
      end

      # Also close any unused activated sockets
      unless @activated_sockets.empty?
        fds = @ios.map(&:to_i)
        @activated_sockets.each do |key, sock|
          next if fds.include? sock.to_i
          logger.log "* Closing unused activated socket: #{key.first}://#{key[1..-1].join ':'}"
          begin
            sock.close
          rescue SystemCallError
          end
          # We have to unlink a unix socket path that's not being used
          File.unlink key[1] if key.first == :unix
        end
      end
    end

    def localhost_authority
      @localhost_authority ||= Localhost::Authority.fetch if defined?(Localhost::Authority) && !Puma::IS_JRUBY
    end

    def localhost_authority_context
      return unless localhost_authority

      key_path, crt_path = if [:key_path, :certificate_path].all? { |m| localhost_authority.respond_to?(m) }
        [localhost_authority.key_path, localhost_authority.certificate_path]
      else
        local_certificates_path = File.expand_path("~/.localhost")
        [File.join(local_certificates_path, "localhost.key"), File.join(local_certificates_path, "localhost.crt")]
      end
      MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @events).context
    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.
    #
    def add_tcp_listener(host, port, optimize_for_latency=true, backlog=1024)
      if host == "localhost"
        loopback_addresses.each do |addr|
          add_tcp_listener addr, port, optimize_for_latency, backlog
        end