class Puma::Binder

def parse(binds, log_writer = nil, log_msg = 'Listening')

def parse(binds, log_writer = nil, log_msg = 'Listening')
  log_writer ||= @log_writer
  binds.each do |str|
    uri = URI.parse str
    case uri.scheme
    when "tcp"
      if fd = @inherited_fds.delete(str)
        io = inherit_tcp_listener uri.host, uri.port, fd
        log_writer.log "* Inherited #{str}"
      elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
        io = inherit_tcp_listener uri.host, uri.port, sock
        log_writer.log "* Activated #{str}"
      else
        ios_len = @ios.length
        params = Util.parse_query uri.query
        low_latency = params.key?('low_latency') && params['low_latency'] != 'false'
        backlog = params.fetch('backlog', 1024).to_i
        io = add_tcp_listener uri.host, uri.port, low_latency, backlog
        @ios[ios_len..-1].each do |i|
          addr = loc_addr_str i
          log_writer.log "* #{log_msg} on http://#{addr}"
        end
      end
      @listeners << [str, io] if io
    when "unix"
      path = "#{uri.host}#{uri.path}".gsub("%20", " ")
      abstract = false
      if str.start_with? 'unix://@'
        raise "OS does not support abstract UNIXSockets" unless Puma.abstract_unix_socket?
        abstract = true
        path = "@#{path}"
      end
      if fd = @inherited_fds.delete(str)
        @unix_paths << path unless abstract || File.exist?(path)
        io = inherit_unix_listener path, fd
        log_writer.log "* Inherited #{str}"
      elsif sock = @activated_sockets.delete([ :unix, path ]) ||
          @activated_sockets.delete([ :unix, File.realdirpath(path) ])
        @unix_paths << path unless abstract || File.exist?(path)
        io = inherit_unix_listener path, sock
        log_writer.log "* Activated #{str}"
      else
        umask = nil
        mode = nil
        backlog = 1024
        if uri.query
          params = Util.parse_query uri.query
          if u = params['umask']
            # Use Integer() to respect the 0 prefix as octal
            umask = Integer(u)
          end
          if u = params['mode']
            mode = Integer('0'+u)
          end
          if u = params['backlog']
            backlog = Integer(u)
          end
        end
        @unix_paths << path unless abstract || File.exist?(path)
        io = add_unix_listener path, umask, mode, backlog
        log_writer.log "* #{log_msg} on #{str}"
      end
      @listeners << [str, io]
    when "ssl"
      cert_key = %w[cert key]
      raise "Puma compiled without SSL support" unless HAS_SSL
      params = Util.parse_query uri.query
      # If key and certs are not defined and localhost gem is required.
      # localhost gem will be used for self signed
      # Load localhost authority if not loaded.
      # Ruby 3 `values_at` accepts an array, earlier do not
      if params.values_at(*cert_key).all? { |v| v.to_s.empty? }
        ctx = localhost_authority && localhost_authority_context
      end
      ctx ||=
        begin
          # Extract cert_pem and key_pem from options[:store] if present
          cert_key.each do |v|
            if params[v]&.start_with?('store:')
              index = Integer(params.delete(v).split('store:').last)
              params["#{v}_pem"] = @conf.options[:store][index]
            end
          end
          MiniSSL::ContextBuilder.new(params, @log_writer).context
        end
      if fd = @inherited_fds.delete(str)
        log_writer.log "* Inherited #{str}"
        io = inherit_ssl_listener fd, ctx
      elsif sock = @activated_sockets.delete([ :tcp, uri.host, uri.port ])
        io = inherit_ssl_listener sock, ctx
        log_writer.log "* Activated #{str}"
      else
        ios_len = @ios.length
        backlog = params.fetch('backlog', 1024).to_i
        low_latency = params['low_latency'] != 'false'
        io = add_ssl_listener uri.host, uri.port, ctx, low_latency, backlog
        @ios[ios_len..-1].each do |i|
          addr = loc_addr_str i
          log_writer.log "* #{log_msg} on ssl://#{addr}?#{uri.query}"
        end
      end
      @listeners << [str, io] if io
    else
      log_writer.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|
    log_writer.log "* Closing unused inherited connection: #{str}"
    begin
      IO.for_fd(fd).close
    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
  # 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
      log_writer.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