puma 5.0.0.beta1 → 5.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +23 -1
- data/README.md +3 -3
- data/docs/architecture.md +3 -3
- data/docs/deployment.md +6 -2
- data/docs/signals.md +4 -4
- data/ext/puma_http11/http11_parser.c +3 -1
- data/ext/puma_http11/http11_parser.rl +3 -1
- data/ext/puma_http11/mini_ssl.c +12 -2
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +37 -6
- data/ext/puma_http11/puma_http11.c +1 -1
- data/lib/puma.rb +1 -0
- data/lib/puma/app/status.rb +4 -2
- data/lib/puma/binder.rb +5 -4
- data/lib/puma/client.rb +36 -9
- data/lib/puma/cluster.rb +8 -4
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/const.rb +1 -1
- data/lib/puma/dsl.rb +3 -3
- data/lib/puma/error_logger.rb +96 -0
- data/lib/puma/events.rb +33 -31
- data/lib/puma/launcher.rb +5 -2
- data/lib/puma/minissl.rb +34 -2
- data/lib/puma/reactor.rb +2 -2
- data/lib/puma/runner.rb +1 -1
- data/lib/puma/server.rb +84 -44
- data/lib/puma/state_file.rb +1 -1
- data/lib/puma/thread_pool.rb +5 -2
- metadata +8 -7
    
        data/lib/puma/cluster.rb
    CHANGED
    
    | @@ -5,7 +5,6 @@ require 'puma/util' | |
| 5 5 | 
             
            require 'puma/plugin'
         | 
| 6 6 |  | 
| 7 7 | 
             
            require 'time'
         | 
| 8 | 
            -
            require 'json'
         | 
| 9 8 |  | 
| 10 9 | 
             
            module Puma
         | 
| 11 10 | 
             
              # This class is instantiated by the `Puma::Launcher` and used
         | 
| @@ -95,6 +94,7 @@ module Puma | |
| 95 94 |  | 
| 96 95 | 
             
                  def ping!(status)
         | 
| 97 96 | 
             
                    @last_checkin = Time.now
         | 
| 97 | 
            +
                    require 'json'
         | 
| 98 98 | 
             
                    @last_status = JSON.parse(status, symbolize_names: true)
         | 
| 99 99 | 
             
                  end
         | 
| 100 100 |  | 
| @@ -248,6 +248,7 @@ module Puma | |
| 248 248 | 
             
                  $0 = title
         | 
| 249 249 |  | 
| 250 250 | 
             
                  Signal.trap "SIGINT", "IGNORE"
         | 
| 251 | 
            +
                  Signal.trap "SIGCHLD", "DEFAULT"
         | 
| 251 252 |  | 
| 252 253 | 
             
                  fork_worker = @options[:fork_worker] && index == 0
         | 
| 253 254 |  | 
| @@ -284,9 +285,11 @@ module Puma | |
| 284 285 |  | 
| 285 286 | 
             
                  if fork_worker
         | 
| 286 287 | 
             
                    restart_server.clear
         | 
| 288 | 
            +
                    worker_pids = []
         | 
| 287 289 | 
             
                    Signal.trap "SIGCHLD" do
         | 
| 288 | 
            -
                       | 
| 289 | 
            -
             | 
| 290 | 
            +
                      wakeup! if worker_pids.reject! do |p|
         | 
| 291 | 
            +
                        Process.wait(p, Process::WNOHANG) rescue true
         | 
| 292 | 
            +
                      end
         | 
| 290 293 | 
             
                    end
         | 
| 291 294 |  | 
| 292 295 | 
             
                    Thread.new do
         | 
| @@ -303,7 +306,7 @@ module Puma | |
| 303 306 | 
             
                        elsif idx == 0 # restart server
         | 
| 304 307 | 
             
                          restart_server << true << false
         | 
| 305 308 | 
             
                        else # fork worker
         | 
| 306 | 
            -
                          pid = spawn_worker(idx, master)
         | 
| 309 | 
            +
                          worker_pids << pid = spawn_worker(idx, master)
         | 
| 307 310 | 
             
                          @worker_write << "f#{pid}:#{idx}\n" rescue nil
         | 
| 308 311 | 
             
                        end
         | 
| 309 312 | 
             
                      end
         | 
| @@ -330,6 +333,7 @@ module Puma | |
| 330 333 | 
             
                    while true
         | 
| 331 334 | 
             
                      sleep Const::WORKER_CHECK_INTERVAL
         | 
| 332 335 | 
             
                      begin
         | 
| 336 | 
            +
                        require 'json'
         | 
| 333 337 | 
             
                        io << "p#{Process.pid}#{server.stats.to_json}\n"
         | 
| 334 338 | 
             
                      rescue IOError
         | 
| 335 339 | 
             
                        Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
         | 
    
        data/lib/puma/commonlogger.rb
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 | 
             
            module Puma
         | 
| 4 4 | 
             
              # Rack::CommonLogger forwards every request to the given +app+, and
         | 
| 5 5 | 
             
              # logs a line in the
         | 
| 6 | 
            -
              # {Apache common log format}[ | 
| 6 | 
            +
              # {Apache common log format}[https://httpd.apache.org/docs/1.3/logs.html#common]
         | 
| 7 7 | 
             
              # to the +logger+.
         | 
| 8 8 | 
             
              #
         | 
| 9 9 | 
             
              # If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
         | 
| @@ -16,7 +16,7 @@ module Puma | |
| 16 16 | 
             
              # (which is called without arguments in order to make the error appear for
         | 
| 17 17 | 
             
              # sure)
         | 
| 18 18 | 
             
              class CommonLogger
         | 
| 19 | 
            -
                # Common Log Format:  | 
| 19 | 
            +
                # Common Log Format: https://httpd.apache.org/docs/1.3/logs.html#common
         | 
| 20 20 | 
             
                #
         | 
| 21 21 | 
             
                #   lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
         | 
| 22 22 | 
             
                #
         | 
    
        data/lib/puma/const.rb
    CHANGED
    
    | @@ -100,7 +100,7 @@ module Puma | |
| 100 100 | 
             
              # too taxing on performance.
         | 
| 101 101 | 
             
              module Const
         | 
| 102 102 |  | 
| 103 | 
            -
                PUMA_VERSION = VERSION = "5.0.0. | 
| 103 | 
            +
                PUMA_VERSION = VERSION = "5.0.0.beta2".freeze
         | 
| 104 104 | 
             
                CODE_NAME = "Spoony Bard".freeze
         | 
| 105 105 | 
             
                PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
         | 
| 106 106 |  | 
    
        data/lib/puma/dsl.rb
    CHANGED
    
    | @@ -443,8 +443,8 @@ module Puma | |
| 443 443 | 
             
                #
         | 
| 444 444 | 
             
                # @note Cluster mode only.
         | 
| 445 445 | 
             
                # @example
         | 
| 446 | 
            -
                #    | 
| 447 | 
            -
                #     puts 'Before worker  | 
| 446 | 
            +
                #   on_worker_boot do
         | 
| 447 | 
            +
                #     puts 'Before worker boot...'
         | 
| 448 448 | 
             
                #   end
         | 
| 449 449 | 
             
                def on_worker_boot(&block)
         | 
| 450 450 | 
             
                  @options[:before_worker_boot] ||= []
         | 
| @@ -769,7 +769,7 @@ module Puma | |
| 769 769 | 
             
                # also increase time to boot and fork. See your logs for details on how much
         | 
| 770 770 | 
             
                # time this adds to your boot process. For most apps, it will be less than one
         | 
| 771 771 | 
             
                # second.
         | 
| 772 | 
            -
                def nakayoshi_fork(enabled= | 
| 772 | 
            +
                def nakayoshi_fork(enabled=true)
         | 
| 773 773 | 
             
                  @options[:nakayoshi_fork] = enabled
         | 
| 774 774 | 
             
                end
         | 
| 775 775 | 
             
              end
         | 
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'puma/const'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Puma
         | 
| 6 | 
            +
              # The implementation of a detailed error logging.
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              class ErrorLogger
         | 
| 9 | 
            +
                include Const
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                attr_reader :ioerr
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                REQUEST_FORMAT = %{"%s %s%s" - (%s)}
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def initialize(ioerr)
         | 
| 16 | 
            +
                  @ioerr = ioerr
         | 
| 17 | 
            +
                  @ioerr.sync = true
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  @debug = ENV.key? 'PUMA_DEBUG'
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def self.stdio
         | 
| 23 | 
            +
                  new $stderr
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # Print occured error details.
         | 
| 27 | 
            +
                # +options+ hash with additional options:
         | 
| 28 | 
            +
                # - +error+ is an exception object
         | 
| 29 | 
            +
                # - +req+ the http request
         | 
| 30 | 
            +
                # - +text+ (default nil) custom string to print in title
         | 
| 31 | 
            +
                #   and before all remaining info.
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                def info(options={})
         | 
| 34 | 
            +
                  ioerr.puts title(options)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # Print occured error details only if
         | 
| 38 | 
            +
                # environment variable PUMA_DEBUG is defined.
         | 
| 39 | 
            +
                # +options+ hash with additional options:
         | 
| 40 | 
            +
                # - +error+ is an exception object
         | 
| 41 | 
            +
                # - +req+ the http request
         | 
| 42 | 
            +
                # - +text+ (default nil) custom string to print in title
         | 
| 43 | 
            +
                #   and before all remaining info.
         | 
| 44 | 
            +
                #
         | 
| 45 | 
            +
                def debug(options={})
         | 
| 46 | 
            +
                  return unless @debug
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  error = options[:error]
         | 
| 49 | 
            +
                  req = options[:req]
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  string_block = []
         | 
| 52 | 
            +
                  string_block << title(options)
         | 
| 53 | 
            +
                  string_block << request_dump(req) if req
         | 
| 54 | 
            +
                  string_block << error_backtrace(options) if error
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  ioerr.puts string_block.join("\n")
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def title(options={})
         | 
| 60 | 
            +
                  text = options[:text]
         | 
| 61 | 
            +
                  req = options[:req]
         | 
| 62 | 
            +
                  error = options[:error]
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  string_block = ["#{Time.now}"]
         | 
| 65 | 
            +
                  string_block << " #{text}" if text
         | 
| 66 | 
            +
                  string_block << " (#{request_title(req)})" if request_parsed?(req)
         | 
| 67 | 
            +
                  string_block << ": #{error.inspect}" if error
         | 
| 68 | 
            +
                  string_block.join('')
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def request_dump(req)
         | 
| 72 | 
            +
                  "Headers: #{request_headers(req)}\n" \
         | 
| 73 | 
            +
                  "Body: #{req.body}"
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def request_title(req)
         | 
| 77 | 
            +
                  env = req.env
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  REQUEST_FORMAT % [
         | 
| 80 | 
            +
                    env[REQUEST_METHOD],
         | 
| 81 | 
            +
                    env[REQUEST_PATH] || env[PATH_INFO],
         | 
| 82 | 
            +
                    env[QUERY_STRING] || "",
         | 
| 83 | 
            +
                    env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-"
         | 
| 84 | 
            +
                  ]
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                def request_headers(req)
         | 
| 88 | 
            +
                  headers = req.env.select { |key, _| key.start_with?('HTTP_') }
         | 
| 89 | 
            +
                  headers.map { |key, value| [key[5..-1], value] }.to_h.inspect
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                def request_parsed?(req)
         | 
| 93 | 
            +
                  req && req.env[REQUEST_METHOD]
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
            end
         | 
    
        data/lib/puma/events.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require 'puma/const'
         | 
| 4 3 | 
             
            require "puma/null_io"
         | 
| 4 | 
            +
            require 'puma/error_logger'
         | 
| 5 5 | 
             
            require 'stringio'
         | 
| 6 6 |  | 
| 7 7 | 
             
            module Puma
         | 
| @@ -23,8 +23,6 @@ module Puma | |
| 23 23 | 
             
                  end
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
| 26 | 
            -
                include Const
         | 
| 27 | 
            -
             | 
| 28 26 | 
             
                # Create an Events object that prints to +stdout+ and +stderr+.
         | 
| 29 27 | 
             
                #
         | 
| 30 28 | 
             
                def initialize(stdout, stderr)
         | 
| @@ -36,6 +34,7 @@ module Puma | |
| 36 34 | 
             
                  @stderr.sync = true
         | 
| 37 35 |  | 
| 38 36 | 
             
                  @debug = ENV.key? 'PUMA_DEBUG'
         | 
| 37 | 
            +
                  @error_logger = ErrorLogger.new(@stderr)
         | 
| 39 38 |  | 
| 40 39 | 
             
                  @hooks = Hash.new { |h,k| h[k] = [] }
         | 
| 41 40 | 
             
                end
         | 
| @@ -66,7 +65,8 @@ module Puma | |
| 66 65 | 
             
                # Write +str+ to +@stdout+
         | 
| 67 66 | 
             
                #
         | 
| 68 67 | 
             
                def log(str)
         | 
| 69 | 
            -
                  @stdout.puts format(str)
         | 
| 68 | 
            +
                  @stdout.puts format(str) if @stdout.respond_to? :puts
         | 
| 69 | 
            +
                rescue Errno::EPIPE
         | 
| 70 70 | 
             
                end
         | 
| 71 71 |  | 
| 72 72 | 
             
                def write(str)
         | 
| @@ -80,7 +80,7 @@ module Puma | |
| 80 80 | 
             
                # Write +str+ to +@stderr+
         | 
| 81 81 | 
             
                #
         | 
| 82 82 | 
             
                def error(str)
         | 
| 83 | 
            -
                  @ | 
| 83 | 
            +
                  @error_logger.info(text: format("ERROR: #{str}"))
         | 
| 84 84 | 
             
                  exit 1
         | 
| 85 85 | 
             
                end
         | 
| 86 86 |  | 
| @@ -88,43 +88,45 @@ module Puma | |
| 88 88 | 
             
                  formatter.call(str)
         | 
| 89 89 | 
             
                end
         | 
| 90 90 |  | 
| 91 | 
            +
                # An HTTP connection error has occurred.
         | 
| 92 | 
            +
                # +error+ a connection exception, +req+ the request,
         | 
| 93 | 
            +
                # and +text+ additional info
         | 
| 94 | 
            +
                #
         | 
| 95 | 
            +
                def connection_error(error, req, text="HTTP connection error")
         | 
| 96 | 
            +
                  @error_logger.info(error: error, req: req, text: text)
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 91 99 | 
             
                # An HTTP parse error has occurred.
         | 
| 92 | 
            -
                # + | 
| 93 | 
            -
                #  | 
| 100 | 
            +
                # +error+ a parsing exception,
         | 
| 101 | 
            +
                # and +req+ the request.
         | 
| 94 102 | 
             
                #
         | 
| 95 | 
            -
                def parse_error( | 
| 96 | 
            -
                  @ | 
| 97 | 
            -
                    "(#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}#{env[REQUEST_PATH]}): " \
         | 
| 98 | 
            -
                    "#{error.inspect}" \
         | 
| 99 | 
            -
                    "\n---\n"
         | 
| 103 | 
            +
                def parse_error(error, req)
         | 
| 104 | 
            +
                  @error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
         | 
| 100 105 | 
             
                end
         | 
| 101 106 |  | 
| 102 107 | 
             
                # An SSL error has occurred.
         | 
| 103 | 
            -
                # + | 
| 104 | 
            -
                # any peer certificate (if present) | 
| 108 | 
            +
                # +error+ an exception object, +peeraddr+ peer address,
         | 
| 109 | 
            +
                # and +peercert+ any peer certificate (if present).
         | 
| 105 110 | 
             
                #
         | 
| 106 | 
            -
                def ssl_error( | 
| 111 | 
            +
                def ssl_error(error, peeraddr, peercert)
         | 
| 107 112 | 
             
                  subject = peercert ? peercert.subject : nil
         | 
| 108 | 
            -
                  @ | 
| 113 | 
            +
                  @error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
         | 
| 109 114 | 
             
                end
         | 
| 110 115 |  | 
| 111 116 | 
             
                # An unknown error has occurred.
         | 
| 112 | 
            -
                # + | 
| 113 | 
            -
                # + | 
| 117 | 
            +
                # +error+ an exception object, +req+ the request,
         | 
| 118 | 
            +
                # and +text+ additional info
         | 
| 114 119 | 
             
                #
         | 
| 115 | 
            -
                def unknown_error( | 
| 116 | 
            -
                   | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
                    string_block << error.backtrace
         | 
| 126 | 
            -
                    @stderr.puts string_block.join("\n")
         | 
| 127 | 
            -
                  end
         | 
| 120 | 
            +
                def unknown_error(error, req=nil, text="Unknown error")
         | 
| 121 | 
            +
                  @error_logger.info(error: error, req: req, text: text)
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                # Log occurred error debug dump.
         | 
| 125 | 
            +
                # +error+ an exception object, +req+ the request,
         | 
| 126 | 
            +
                # and +text+ additional info
         | 
| 127 | 
            +
                #
         | 
| 128 | 
            +
                def debug_error(error, req=nil, text="")
         | 
| 129 | 
            +
                  @error_logger.debug(error: error, req: req, text: text)
         | 
| 128 130 | 
             
                end
         | 
| 129 131 |  | 
| 130 132 | 
             
                def on_booted(&block)
         | 
    
        data/lib/puma/launcher.rb
    CHANGED
    
    | @@ -47,7 +47,7 @@ module Puma | |
| 47 47 | 
             
                  @original_argv = @argv.dup
         | 
| 48 48 | 
             
                  @config        = conf
         | 
| 49 49 |  | 
| 50 | 
            -
                  @binder        = Binder.new(@events)
         | 
| 50 | 
            +
                  @binder        = Binder.new(@events, conf)
         | 
| 51 51 | 
             
                  @binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
         | 
| 52 52 | 
             
                  @binder.create_activated_fds(ENV).each { |k| ENV.delete k }
         | 
| 53 53 |  | 
| @@ -111,6 +111,7 @@ module Puma | |
| 111 111 | 
             
                  sf.pid = Process.pid
         | 
| 112 112 | 
             
                  sf.control_url = @options[:control_url]
         | 
| 113 113 | 
             
                  sf.control_auth_token = @options[:control_auth_token]
         | 
| 114 | 
            +
                  sf.running_from = File.expand_path('.')
         | 
| 114 115 |  | 
| 115 116 | 
             
                  sf.save path, permission
         | 
| 116 117 | 
             
                end
         | 
| @@ -172,12 +173,13 @@ module Puma | |
| 172 173 | 
             
                  case @status
         | 
| 173 174 | 
             
                  when :halt
         | 
| 174 175 | 
             
                    log "* Stopping immediately!"
         | 
| 176 | 
            +
                    @runner.stop_control
         | 
| 175 177 | 
             
                  when :run, :stop
         | 
| 176 178 | 
             
                    graceful_stop
         | 
| 177 179 | 
             
                  when :restart
         | 
| 178 180 | 
             
                    log "* Restarting..."
         | 
| 179 181 | 
             
                    ENV.replace(previous_env)
         | 
| 180 | 
            -
                    @runner. | 
| 182 | 
            +
                    @runner.stop_control
         | 
| 181 183 | 
             
                    restart!
         | 
| 182 184 | 
             
                  when :exit
         | 
| 183 185 | 
             
                    # nothing
         | 
| @@ -286,6 +288,7 @@ module Puma | |
| 286 288 | 
             
                end
         | 
| 287 289 |  | 
| 288 290 | 
             
                def prune_bundler
         | 
| 291 | 
            +
                  return if ENV['PUMA_BUNDLER_PRUNED']
         | 
| 289 292 | 
             
                  return unless defined?(Bundler)
         | 
| 290 293 | 
             
                  require_rubygems_min_version!(Gem::Version.new("2.2"), "prune_bundler")
         | 
| 291 294 | 
             
                  unless puma_wild_location
         | 
    
        data/lib/puma/minissl.rb
    CHANGED
    
    | @@ -5,8 +5,18 @@ begin | |
| 5 5 | 
             
            rescue LoadError
         | 
| 6 6 | 
             
            end
         | 
| 7 7 |  | 
| 8 | 
            +
            # need for Puma::MiniSSL::OPENSSL constants used in `HAS_TLS1_3`
         | 
| 9 | 
            +
            require 'puma/puma_http11'
         | 
| 10 | 
            +
             | 
| 8 11 | 
             
            module Puma
         | 
| 9 12 | 
             
              module MiniSSL
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # define constant at runtime, as it's easy to determine at built time,
         | 
| 15 | 
            +
                # but Puma could (it shouldn't) be loaded with an older OpenSSL version
         | 
| 16 | 
            +
                HAS_TLS1_3 = !IS_JRUBY &&
         | 
| 17 | 
            +
                  (OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 &&
         | 
| 18 | 
            +
                  (OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1
         | 
| 19 | 
            +
             | 
| 10 20 | 
             
                class Socket
         | 
| 11 21 | 
             
                  def initialize(socket, engine)
         | 
| 12 22 | 
             
                    @socket = socket
         | 
| @@ -22,6 +32,24 @@ module Puma | |
| 22 32 | 
             
                    @socket.closed?
         | 
| 23 33 | 
             
                  end
         | 
| 24 34 |  | 
| 35 | 
            +
                  # returns a two element array
         | 
| 36 | 
            +
                  # first is protocol version (SSL_get_version)
         | 
| 37 | 
            +
                  # second is 'handshake' state (SSL_state_string)
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  # used for dropping tcp connections to ssl
         | 
| 40 | 
            +
                  # see OpenSSL ssl/ssl_stat.c SSL_state_string for info
         | 
| 41 | 
            +
                  #
         | 
| 42 | 
            +
                  def ssl_version_state
         | 
| 43 | 
            +
                    IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  # used to check the handshake status, in particular when a TCP connection
         | 
| 47 | 
            +
                  # is made with TLSv1.3 as an available protocol
         | 
| 48 | 
            +
                  def bad_tlsv1_3?
         | 
| 49 | 
            +
                    HAS_TLS1_3 && @engine.ssl_vers_st == ['TLSv1.3', 'SSLERR']
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                  private :bad_tlsv1_3?
         | 
| 52 | 
            +
             | 
| 25 53 | 
             
                  def readpartial(size)
         | 
| 26 54 | 
             
                    while true
         | 
| 27 55 | 
             
                      output = @engine.read
         | 
| @@ -41,6 +69,7 @@ module Puma | |
| 41 69 |  | 
| 42 70 | 
             
                  def engine_read_all
         | 
| 43 71 | 
             
                    output = @engine.read
         | 
| 72 | 
            +
                    raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
         | 
| 44 73 | 
             
                    while output and additional_output = @engine.read
         | 
| 45 74 | 
             
                      output << additional_output
         | 
| 46 75 | 
             
                    end
         | 
| @@ -167,7 +196,10 @@ module Puma | |
| 167 196 | 
             
                  end
         | 
| 168 197 | 
             
                end
         | 
| 169 198 |  | 
| 170 | 
            -
                if  | 
| 199 | 
            +
                if IS_JRUBY
         | 
| 200 | 
            +
                  OPENSSL_NO_SSL3 = false
         | 
| 201 | 
            +
                  OPENSSL_NO_TLS1 = false
         | 
| 202 | 
            +
             | 
| 171 203 | 
             
                  class SSLError < StandardError
         | 
| 172 204 | 
             
                    # Define this for jruby even though it isn't used.
         | 
| 173 205 | 
             
                  end
         | 
| @@ -184,7 +216,7 @@ module Puma | |
| 184 216 | 
             
                    @no_tlsv1_1 = false
         | 
| 185 217 | 
             
                  end
         | 
| 186 218 |  | 
| 187 | 
            -
                  if  | 
| 219 | 
            +
                  if IS_JRUBY
         | 
| 188 220 | 
             
                    # jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
         | 
| 189 221 | 
             
                    attr_reader :keystore
         | 
| 190 222 | 
             
                    attr_accessor :keystore_pass
         | 
    
        data/lib/puma/reactor.rb
    CHANGED
    
    | @@ -252,7 +252,7 @@ module Puma | |
| 252 252 | 
             
                            c.close
         | 
| 253 253 | 
             
                            clear_monitor mon
         | 
| 254 254 |  | 
| 255 | 
            -
                            @events.ssl_error  | 
| 255 | 
            +
                            @events.ssl_error e, addr, cert
         | 
| 256 256 |  | 
| 257 257 | 
             
                          # The client doesn't know HTTP well
         | 
| 258 258 | 
             
                          rescue HttpParserError => e
         | 
| @@ -263,7 +263,7 @@ module Puma | |
| 263 263 |  | 
| 264 264 | 
             
                            clear_monitor mon
         | 
| 265 265 |  | 
| 266 | 
            -
                            @events.parse_error  | 
| 266 | 
            +
                            @events.parse_error e, c
         | 
| 267 267 | 
             
                          rescue StandardError => e
         | 
| 268 268 | 
             
                            @server.lowlevel_error(e, c.env)
         | 
| 269 269 |  |