puma 5.1.1-java → 5.2.0-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

@@ -182,8 +182,6 @@ static final int puma_parser_start = 1;
182
182
  static final int puma_parser_first_final = 46;
183
183
  static final int puma_parser_error = 0;
184
184
 
185
- static final int puma_parser_en_main = 1;
186
-
187
185
 
188
186
  // line 62 "ext/puma_http11/http11_parser.java.rl"
189
187
 
@@ -212,12 +210,12 @@ static final int puma_parser_en_main = 1;
212
210
  cs = 0;
213
211
 
214
212
 
215
- // line 218 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
213
+ // line 214 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
216
214
  {
217
215
  cs = puma_parser_start;
218
216
  }
219
217
 
220
- // line 90 "ext/puma_http11/http11_parser.java.rl"
218
+ // line 88 "ext/puma_http11/http11_parser.java.rl"
221
219
 
222
220
  body_start = 0;
223
221
  content_len = 0;
@@ -244,7 +242,7 @@ static final int puma_parser_en_main = 1;
244
242
  parser.buffer = buffer;
245
243
 
246
244
 
247
- // line 250 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
245
+ // line 246 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
248
246
  {
249
247
  int _klen;
250
248
  int _trans = 0;
@@ -400,7 +398,7 @@ case 1:
400
398
  { p += 1; _goto_targ = 5; if (true) continue _goto;}
401
399
  }
402
400
  break;
403
- // line 406 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
401
+ // line 402 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
404
402
  }
405
403
  }
406
404
  }
@@ -420,7 +418,7 @@ case 5:
420
418
  break; }
421
419
  }
422
420
 
423
- // line 116 "ext/puma_http11/http11_parser.java.rl"
421
+ // line 114 "ext/puma_http11/http11_parser.java.rl"
424
422
 
425
423
  parser.cs = cs;
426
424
  parser.nread += (p - off);
@@ -41,8 +41,8 @@ static VALUE global_request_path;
41
41
 
42
42
  /** Defines common length and error messages for input length validation. */
43
43
  #define QUOTE(s) #s
44
- #define EXPLAND_MAX_LENGHT_VALUE(s) QUOTE(s)
45
- #define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " EXPLAND_MAX_LENGHT_VALUE(length) " allowed length (was %d)"
44
+ #define EXPLAIN_MAX_LENGTH_VALUE(s) QUOTE(s)
45
+ #define DEF_MAX_LENGTH(N,length) const size_t MAX_##N##_LENGTH = length; const char *MAX_##N##_LENGTH_ERR = "HTTP element " # N " is longer than the " EXPLAIN_MAX_LENGTH_VALUE(length) " allowed length (was %d)"
46
46
 
47
47
  /** Validates the max length of given input and throws an HttpParserError exception if over. */
48
48
  #define VALIDATE_MAX_LENGTH(len, N) if(len > MAX_##N##_LENGTH) { rb_raise(eHttpParserError, MAX_##N##_LENGTH_ERR, len); }
@@ -160,6 +160,7 @@ module Puma
160
160
  io = inherit_tcp_listener uri.host, uri.port, sock
161
161
  logger.log "* Activated #{str}"
162
162
  else
163
+ ios_len = @ios.length
163
164
  params = Util.parse_query uri.query
164
165
 
165
166
  opt = params.key?('low_latency')
@@ -167,14 +168,8 @@ module Puma
167
168
 
168
169
  io = add_tcp_listener uri.host, uri.port, opt, bak
169
170
 
170
- @ios.each do |i|
171
- next unless TCPServer === i
172
- addr = if i.local_address.ipv6?
173
- "[#{i.local_address.ip_unpack[0]}]:#{i.local_address.ip_unpack[1]}"
174
- else
175
- i.local_address.ip_unpack.join(':')
176
- end
177
-
171
+ @ios[ios_len..-1].each do |i|
172
+ addr = loc_addr_str i
178
173
  logger.log "* #{log_msg} on http://#{addr}"
179
174
  end
180
175
  end
@@ -229,8 +224,13 @@ module Puma
229
224
  io = inherit_ssl_listener sock, ctx
230
225
  logger.log "* Activated #{str}"
231
226
  else
227
+ ios_len = @ios.length
232
228
  io = add_ssl_listener uri.host, uri.port, ctx
233
- logger.log "* Listening on #{str}"
229
+
230
+ @ios[ios_len..-1].each do |i|
231
+ addr = loc_addr_str i
232
+ logger.log "* #{log_msg} on ssl://#{addr}?#{uri.query}"
233
+ end
234
234
  end
235
235
 
236
236
  @listeners << [str, io] if io
@@ -297,11 +297,7 @@ module Puma
297
297
  end
298
298
 
299
299
  def inherit_tcp_listener(host, port, fd)
300
- if fd.kind_of? TCPServer
301
- s = fd
302
- else
303
- s = TCPServer.for_fd(fd)
304
- end
300
+ s = fd.kind_of?(::TCPServer) ? fd : ::TCPServer.for_fd(fd)
305
301
 
306
302
  @ios << s
307
303
  s
@@ -339,11 +335,8 @@ module Puma
339
335
  def inherit_ssl_listener(fd, ctx)
340
336
  raise "Puma compiled without SSL support" unless HAS_SSL
341
337
 
342
- if fd.kind_of? TCPServer
343
- s = fd
344
- else
345
- s = TCPServer.for_fd(fd)
346
- end
338
+ s = fd.kind_of?(::TCPServer) ? fd : ::TCPServer.for_fd(fd)
339
+
347
340
  ssl = MiniSSL::Server.new(s, ctx)
348
341
 
349
342
  env = @proto_env.dup
@@ -398,11 +391,8 @@ module Puma
398
391
  def inherit_unix_listener(path, fd)
399
392
  @unix_paths << path unless File.exist? path
400
393
 
401
- if fd.kind_of? TCPServer
402
- s = fd
403
- else
404
- s = UNIXServer.for_fd fd
405
- end
394
+ s = fd.kind_of?(::TCPServer) ? fd : ::UNIXServer.for_fd(fd)
395
+
406
396
  @ios << s
407
397
 
408
398
  env = @proto_env.dup
@@ -444,6 +434,15 @@ module Puma
444
434
  end.map { |addrinfo| addrinfo.ip_address }.uniq
445
435
  end
446
436
 
437
+ def loc_addr_str(io)
438
+ loc_addr = io.to_io.local_address
439
+ if loc_addr.ipv6?
440
+ "[#{loc_addr.ip_unpack[0]}]:#{loc_addr.ip_unpack[1]}"
441
+ else
442
+ loc_addr.ip_unpack.join(':')
443
+ end
444
+ end
445
+
447
446
  # @version 5.0.0
448
447
  def socket_activation_fd(int)
449
448
  int + 3 # 3 is the magic number you add to follow the SA protocol
@@ -205,7 +205,8 @@ module Puma
205
205
  :persistent_timeout => Const::PERSISTENT_TIMEOUT,
206
206
  :first_data_timeout => Const::FIRST_DATA_TIMEOUT,
207
207
  :raise_exception_on_sigterm => true,
208
- :max_fast_inline => Const::MAX_FAST_INLINE
208
+ :max_fast_inline => Const::MAX_FAST_INLINE,
209
+ :io_selector_backend => :auto
209
210
  }
210
211
  end
211
212
 
@@ -100,8 +100,8 @@ module Puma
100
100
  # too taxing on performance.
101
101
  module Const
102
102
 
103
- PUMA_VERSION = VERSION = "5.1.1".freeze
104
- CODE_NAME = "At Your Service".freeze
103
+ PUMA_VERSION = VERSION = "5.2.0".freeze
104
+ CODE_NAME = "Fettisdagsbulle".freeze
105
105
 
106
106
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
107
107
 
@@ -237,6 +237,7 @@ module Puma
237
237
 
238
238
  if sig.nil?
239
239
  @stdout.puts "'#{@command}' not available via pid only"
240
+ @stdout.flush unless @stdout.sync
240
241
  return
241
242
  elsif sig.start_with? 'SIG'
242
243
  Process.kill sig, @pid
@@ -244,6 +245,7 @@ module Puma
244
245
  begin
245
246
  Process.kill 0, @pid
246
247
  @stdout.puts 'Puma is started'
248
+ @stdout.flush unless @stdout.sync
247
249
  rescue Errno::ESRCH
248
250
  raise 'Puma is not running'
249
251
  end
@@ -51,14 +51,20 @@ module Puma
51
51
  if defined?(JRUBY_VERSION)
52
52
  ssl_cipher_list = opts[:ssl_cipher_list] ?
53
53
  "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
54
+
54
55
  keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
56
+
55
57
  "ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
56
58
  "&verify_mode=#{verify}#{tls_str}#{ca_additions}"
57
59
  else
58
60
  ssl_cipher_filter = opts[:ssl_cipher_filter] ?
59
61
  "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
62
+
63
+ v_flags = (ary = opts[:verification_flags]) ?
64
+ "&verification_flags=#{Array(ary).join ','}" : nil
65
+
60
66
  "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
61
- "#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}"
67
+ "#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
62
68
  end
63
69
  end
64
70
 
@@ -251,7 +257,7 @@ module Puma
251
257
  # port 9292
252
258
  def port(port, host=nil)
253
259
  host ||= default_host
254
- bind "tcp://#{host}:#{port}"
260
+ bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
255
261
  end
256
262
 
257
263
  # Define how long persistent connections can be idle before Puma closes them.
@@ -399,7 +405,10 @@ module Puma
399
405
  # Configure +min+ to be the minimum number of threads to use to answer
400
406
  # requests and +max+ the maximum.
401
407
  #
402
- # The default is "0, 16".
408
+ # The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+
409
+ # (or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
410
+ #
411
+ # If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.
403
412
  #
404
413
  # @example
405
414
  # threads 0, 16
@@ -429,6 +438,7 @@ module Puma
429
438
  # key: path_to_key,
430
439
  # ssl_cipher_filter: cipher_filter, # optional
431
440
  # verify_mode: verify_mode, # default 'none'
441
+ # verification_flags: flags, # optional, not supported by JRuby
432
442
  # }
433
443
  # @example For JRuby, two keys are required: keystore & keystore_pass.
434
444
  # ssl_bind '127.0.0.1', '9292', {
@@ -463,7 +473,8 @@ module Puma
463
473
  # How many worker processes to run. Typically this is set to
464
474
  # the number of available cores.
465
475
  #
466
- # The default is 0.
476
+ # The default is the value of the environment variable +WEB_CONCURRENCY+ if
477
+ # set, otherwise 0.
467
478
  #
468
479
  # @note Cluster mode only.
469
480
  # @see Puma::Cluster
@@ -858,5 +869,24 @@ module Puma
858
869
  def max_fast_inline(num_of_requests)
859
870
  @options[:max_fast_inline] = Float(num_of_requests)
860
871
  end
872
+
873
+ # Specify the backend for the IO selector.
874
+ #
875
+ # Provided values will be passed directly to +NIO::Selector.new+, with the
876
+ # exception of +:auto+ which will let nio4r choose the backend.
877
+ #
878
+ # Check the documentation of +NIO::Selector.backends+ for the list of valid
879
+ # options. Note that the available options on your system will depend on the
880
+ # operating system. If you want to use the pure Ruby backend (not
881
+ # recommended due to its comparatively low performance), set environment
882
+ # variable +NIO4R_PURE+ to +true+.
883
+ #
884
+ # The default is +:auto+.
885
+ #
886
+ # @see https://github.com/socketry/nio4r/blob/master/lib/nio/selector.rb
887
+ #
888
+ def io_selector_backend(backend)
889
+ @options[:io_selector_backend] = backend.to_sym
890
+ end
861
891
  end
862
892
  end
@@ -15,7 +15,6 @@ module Puma
15
15
 
16
16
  def initialize(ioerr)
17
17
  @ioerr = ioerr
18
- @ioerr.sync = true
19
18
 
20
19
  @debug = ENV.key? 'PUMA_DEBUG'
21
20
  end
@@ -32,7 +31,7 @@ module Puma
32
31
  # and before all remaining info.
33
32
  #
34
33
  def info(options={})
35
- ioerr.puts title(options)
34
+ log title(options)
36
35
  end
37
36
 
38
37
  # Print occured error details only if
@@ -54,7 +53,7 @@ module Puma
54
53
  string_block << request_dump(req) if request_parsed?(req)
55
54
  string_block << error.backtrace if error
56
55
 
57
- ioerr.puts string_block.join("\n")
56
+ log string_block.join("\n")
58
57
  end
59
58
 
60
59
  def title(options={})
@@ -93,5 +92,13 @@ module Puma
93
92
  def request_parsed?(req)
94
93
  req && req.env[REQUEST_METHOD]
95
94
  end
95
+
96
+ private
97
+
98
+ def log(str)
99
+ ioerr.puts str
100
+
101
+ ioerr.flush unless ioerr.sync
102
+ end
96
103
  end
97
104
  end
@@ -30,9 +30,6 @@ module Puma
30
30
  @stdout = stdout
31
31
  @stderr = stderr
32
32
 
33
- @stdout.sync = true
34
- @stderr.sync = true
35
-
36
33
  @debug = ENV.key? 'PUMA_DEBUG'
37
34
  @error_logger = ErrorLogger.new(@stderr)
38
35
 
@@ -66,6 +63,8 @@ module Puma
66
63
  #
67
64
  def log(str)
68
65
  @stdout.puts format(str) if @stdout.respond_to? :puts
66
+
67
+ @stdout.flush unless @stdout.sync
69
68
  rescue Errno::EPIPE
70
69
  end
71
70
 
@@ -139,7 +139,6 @@ module Puma
139
139
 
140
140
  # Begin async shutdown of the server gracefully
141
141
  def stop
142
- @events.fire_on_stopped!
143
142
  @status = :stop
144
143
  @runner.stop
145
144
  end
@@ -218,6 +217,10 @@ module Puma
218
217
  def close_binder_listeners
219
218
  @runner.close_control_listeners
220
219
  @binder.close_listeners
220
+ unless @status == :restart
221
+ log "=== puma shutdown: #{Time.now} ==="
222
+ log "- Goodbye!"
223
+ end
221
224
  end
222
225
 
223
226
  # @!attribute [r] thread_status
@@ -375,8 +378,6 @@ module Puma
375
378
  def graceful_stop
376
379
  @events.fire_on_stopped!
377
380
  @runner.stop_blocked
378
- log "=== puma shutdown: #{Time.now} ==="
379
- log "- Goodbye!"
380
381
  end
381
382
 
382
383
  def set_process_title
@@ -73,7 +73,6 @@ module Puma
73
73
 
74
74
  def engine_read_all
75
75
  output = @engine.read
76
- raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
77
76
  while output and additional_output = @engine.read
78
77
  output << additional_output
79
78
  end
@@ -100,6 +99,7 @@ module Puma
100
99
  # ourselves.
101
100
  raise IO::EAGAINWaitReadable
102
101
  elsif data.nil?
102
+ raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
103
103
  return nil
104
104
  end
105
105
 
@@ -117,20 +117,21 @@ module Puma
117
117
  def write(data)
118
118
  return 0 if data.empty?
119
119
 
120
- need = data.bytesize
120
+ data_size = data.bytesize
121
+ need = data_size
121
122
 
122
123
  while true
123
124
  wrote = @engine.write data
124
- enc = @engine.extract
125
125
 
126
- while enc
127
- @socket.write enc
128
- enc = @engine.extract
126
+ enc_wr = ''.dup
127
+ while (enc = @engine.extract)
128
+ enc_wr << enc
129
129
  end
130
+ @socket.write enc_wr unless enc_wr.empty?
130
131
 
131
132
  need -= wrote
132
133
 
133
- return data.bytesize if need == 0
134
+ return data_size if need == 0
134
135
 
135
136
  data = data[wrote..-1]
136
137
  end
@@ -245,6 +246,7 @@ module Puma
245
246
  attr_reader :cert
246
247
  attr_reader :ca
247
248
  attr_accessor :ssl_cipher_filter
249
+ attr_accessor :verification_flags
248
250
 
249
251
  def key=(key)
250
252
  raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
@@ -287,33 +289,58 @@ module Puma
287
289
  VERIFY_PEER = 1
288
290
  VERIFY_FAIL_IF_NO_PEER_CERT = 2
289
291
 
292
+ # https://github.com/openssl/openssl/blob/master/include/openssl/x509_vfy.h.in
293
+ # /* Certificate verify flags */
294
+ VERIFICATION_FLAGS = {
295
+ "USE_CHECK_TIME" => 0x2,
296
+ "CRL_CHECK" => 0x4,
297
+ "CRL_CHECK_ALL" => 0x8,
298
+ "IGNORE_CRITICAL" => 0x10,
299
+ "X509_STRICT" => 0x20,
300
+ "ALLOW_PROXY_CERTS" => 0x40,
301
+ "POLICY_CHECK" => 0x80,
302
+ "EXPLICIT_POLICY" => 0x100,
303
+ "INHIBIT_ANY" => 0x200,
304
+ "INHIBIT_MAP" => 0x400,
305
+ "NOTIFY_POLICY" => 0x800,
306
+ "EXTENDED_CRL_SUPPORT" => 0x1000,
307
+ "USE_DELTAS" => 0x2000,
308
+ "CHECK_SS_SIGNATURE" => 0x4000,
309
+ "TRUSTED_FIRST" => 0x8000,
310
+ "SUITEB_128_LOS_ONLY" => 0x10000,
311
+ "SUITEB_192_LOS" => 0x20000,
312
+ "SUITEB_128_LOS" => 0x30000,
313
+ "PARTIAL_CHAIN" => 0x80000,
314
+ "NO_ALT_CHAINS" => 0x100000,
315
+ "NO_CHECK_TIME" => 0x200000
316
+ }.freeze
317
+
290
318
  class Server
291
319
  def initialize(socket, ctx)
292
320
  @socket = socket
293
321
  @ctx = ctx
294
- end
295
-
296
- # @!attribute [r] to_io
297
- def to_io
298
- @socket
322
+ @eng_ctx = IS_JRUBY ? @ctx : SSLContext.new(ctx)
299
323
  end
300
324
 
301
325
  def accept
302
326
  @ctx.check
303
327
  io = @socket.accept
304
- engine = Engine.server @ctx
305
-
328
+ engine = Engine.server @eng_ctx
306
329
  Socket.new io, engine
307
330
  end
308
331
 
309
332
  def accept_nonblock
310
333
  @ctx.check
311
334
  io = @socket.accept_nonblock
312
- engine = Engine.server @ctx
313
-
335
+ engine = Engine.server @eng_ctx
314
336
  Socket.new io, engine
315
337
  end
316
338
 
339
+ # @!attribute [r] to_io
340
+ def to_io
341
+ @socket
342
+ end
343
+
317
344
  # @!attribute [r] addr
318
345
  # @version 5.0.0
319
346
  def addr
@@ -323,6 +350,10 @@ module Puma
323
350
  def close
324
351
  @socket.close unless @socket.closed? # closed? call is for Windows
325
352
  end
353
+
354
+ def closed?
355
+ @socket.closed?
356
+ end
326
357
  end
327
358
  end
328
359
  end