puma 5.5.2 → 5.6.0

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.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +51 -0
  3. data/LICENSE +0 -0
  4. data/README.md +5 -0
  5. data/bin/puma-wild +0 -0
  6. data/docs/architecture.md +4 -4
  7. data/docs/compile_options.md +0 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +0 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +0 -0
  17. data/docs/nginx.md +0 -0
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +0 -0
  21. data/docs/signals.md +1 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +0 -0
  24. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  25. data/ext/puma_http11/ext_help.h +0 -0
  26. data/ext/puma_http11/extconf.rb +12 -6
  27. data/ext/puma_http11/http11_parser.c +0 -0
  28. data/ext/puma_http11/http11_parser.h +0 -0
  29. data/ext/puma_http11/http11_parser.java.rl +0 -0
  30. data/ext/puma_http11/http11_parser.rl +0 -0
  31. data/ext/puma_http11/http11_parser_common.rl +0 -0
  32. data/ext/puma_http11/mini_ssl.c +54 -9
  33. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  34. data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
  35. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +28 -43
  37. data/ext/puma_http11/puma_http11.c +1 -1
  38. data/lib/puma/app/status.rb +0 -0
  39. data/lib/puma/binder.rb +19 -5
  40. data/lib/puma/cli.rb +9 -4
  41. data/lib/puma/client.rb +1 -1
  42. data/lib/puma/cluster/worker.rb +5 -5
  43. data/lib/puma/cluster/worker_handle.rb +4 -0
  44. data/lib/puma/cluster.rb +29 -11
  45. data/lib/puma/commonlogger.rb +0 -0
  46. data/lib/puma/configuration.rb +3 -0
  47. data/lib/puma/const.rb +2 -5
  48. data/lib/puma/control_cli.rb +0 -0
  49. data/lib/puma/detect.rb +8 -2
  50. data/lib/puma/dsl.rb +85 -8
  51. data/lib/puma/error_logger.rb +0 -0
  52. data/lib/puma/events.rb +0 -0
  53. data/lib/puma/io_buffer.rb +0 -0
  54. data/lib/puma/jruby_restart.rb +0 -0
  55. data/lib/puma/json_serialization.rb +0 -0
  56. data/lib/puma/launcher.rb +2 -1
  57. data/lib/puma/minissl/context_builder.rb +8 -6
  58. data/lib/puma/minissl.rb +18 -2
  59. data/lib/puma/null_io.rb +0 -0
  60. data/lib/puma/plugin/tmp_restart.rb +0 -0
  61. data/lib/puma/plugin.rb +1 -1
  62. data/lib/puma/queue_close.rb +0 -0
  63. data/lib/puma/rack/builder.rb +0 -0
  64. data/lib/puma/rack/urlmap.rb +0 -0
  65. data/lib/puma/rack_default.rb +0 -0
  66. data/lib/puma/reactor.rb +0 -0
  67. data/lib/puma/request.rb +47 -29
  68. data/lib/puma/runner.rb +3 -2
  69. data/lib/puma/server.rb +29 -33
  70. data/lib/puma/single.rb +0 -0
  71. data/lib/puma/state_file.rb +41 -7
  72. data/lib/puma/systemd.rb +0 -0
  73. data/lib/puma/thread_pool.rb +2 -2
  74. data/lib/puma/util.rb +0 -0
  75. data/lib/puma.rb +0 -0
  76. data/lib/rack/handler/puma.rb +0 -0
  77. data/tools/Dockerfile +1 -1
  78. data/tools/trickletest.rb +0 -0
  79. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f0ef12e973901d1ef05ea411057d82c5dc3e3c6fbe471402abfea5cb9e9a5da
4
- data.tar.gz: 32b6b9e7a34748bd8facf5d6bb2bb8fc0b3aedda83823b4db826d9b16fdf9290
3
+ metadata.gz: b26655d47e2cc0987b78174ca6f6f7f9e16cfc584d1925cee08b2c4fd8d8a63e
4
+ data.tar.gz: 48aaec83462461d40fba5791679f8a81a677ea11731337d05213f358e1e1df01
5
5
  SHA512:
6
- metadata.gz: a7792db683a263be5a0bd226578f98d55bcfb9ecab6fcdd1fc09da8b903f7960f149711b5174660ff6ebfa5402e2eb0e0d75ff1b5ce1110dfbec85e0532ed078
7
- data.tar.gz: 344ad1f7eae75c085e42e24583a77a2444e8a92386fa8ac66ad7ea8d35ae3a72d7db0c01da60a2d20bc04330608b260685eb934603c9440df7208f809a6994f1
6
+ metadata.gz: e09ac76431f64ef08f5be4da5d2792e6ff7a152235534cc3c9a9798bf2bb34041fc98d6050b489598b1a9625bb9af13af355e3d4c9689cc055ab2790adbbcc8e
7
+ data.tar.gz: a2609c1568543ce1b41f51eff668e59ccacc79582c447fed74aeb334403e8f9212bb19f676ee2cd949f5209d240ab735495a5d364e549c4ab24676f1941801d5
data/History.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 5.6.0 / 2022-01-25
2
+
3
+ * Features
4
+ * Support `localhost` integration in `ssl_bind` ([#2764], [#2708])
5
+ * Allow backlog parameter to be set with ssl_bind DSL ([#2780])
6
+ * Remove yaml (psych) requirement in StateFile ([#2784])
7
+ * Allow culling of oldest workers, previously was only youngest ([#2773], [#2794])
8
+ * Add worker_check_interval configuration option ([#2759])
9
+ * Always send lowlevel_error response to client ([#2731], [#2341])
10
+ * Support for cert_pem and key_pem with ssl_bind DSL ([#2728])
11
+
12
+ * Bugfixes
13
+ * Keep thread names under 15 characters, prevents breakage on some OSes ([#2733])
14
+ * Fix two 'old-style-definition' compile warning ([#2807], [#2806])
15
+ * Log environment correctly using option value ([#2799])
16
+ * Fix warning from Ruby master (will be 3.2.0) ([#2785])
17
+ * extconf.rb - fix openssl with old Windows builds ([#2757])
18
+ * server.rb - rescue handling (`Errno::EBADF`) for `@notify.close` ([#2745])
19
+
20
+ * Refactor
21
+ * server.rb - refactor code using @options[:remote_address] ([#2742])
22
+ * [jruby] a couple refactorings - avoid copy-ing bytes ([#2730])
23
+
1
24
  ## 5.5.2 / 2021-10-12
2
25
 
3
26
  * Bugfixes
@@ -5,6 +28,9 @@
5
28
 
6
29
  ## 5.5.1 / 2021-10-12
7
30
 
31
+ * Feature (added as mistake - we don't normally do this on bugfix releases, sorry!)
32
+ * Allow setting APP_ENV in preference to RACK_ENV or RAILS_ENV ([#2702])
33
+
8
34
  * Security
9
35
  * Do not allow LF as a line ending in a header (CVE-2021-41136)
10
36
 
@@ -261,6 +287,11 @@
261
287
  * Support parallel tests in verbose progress reporting ([#2223])
262
288
  * Refactor error handling in server accept loop ([#2239])
263
289
 
290
+ ## 4.3.10 / 2021-10-12
291
+
292
+ * Bugfixes
293
+ * Allow UTF-8 in HTTP header values
294
+
264
295
  ## 4.3.9 / 2021-10-12
265
296
 
266
297
  * Security
@@ -1799,6 +1830,26 @@ be added back in a future date when a java Puma::MiniSSL is added.
1799
1830
  * Bugfixes
1800
1831
  * Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
1801
1832
 
1833
+ [#2764]:https://github.com/puma/puma/pull/2764 "PR by @dentarg, merged 2022-01-18"
1834
+ [#2708]:https://github.com/puma/puma/issues/2708 "Issue by @erikaxel, closed 2022-01-18"
1835
+ [#2780]:https://github.com/puma/puma/pull/2780 "PR by @dalibor, merged 2022-01-01"
1836
+ [#2784]:https://github.com/puma/puma/pull/2784 "PR by @MSP-Greg, merged 2022-01-01"
1837
+ [#2773]:https://github.com/puma/puma/pull/2773 "PR by @ob-stripe, merged 2022-01-01"
1838
+ [#2794]:https://github.com/puma/puma/pull/2794 "PR by @johnnyshields, merged 2022-01-10"
1839
+ [#2759]:https://github.com/puma/puma/pull/2759 "PR by @ob-stripe, merged 2021-12-11"
1840
+ [#2731]:https://github.com/puma/puma/pull/2731 "PR by @baelter, merged 2021-11-02"
1841
+ [#2341]:https://github.com/puma/puma/issues/2341 "Issue by @cjlarose, closed 2021-11-02"
1842
+ [#2728]:https://github.com/puma/puma/pull/2728 "PR by @dalibor, merged 2021-10-31"
1843
+ [#2733]:https://github.com/puma/puma/pull/2733 "PR by @ob-stripe, merged 2021-12-12"
1844
+ [#2807]:https://github.com/puma/puma/pull/2807 "PR by @MSP-Greg, merged 2022-01-25"
1845
+ [#2806]:https://github.com/puma/puma/issues/2806 "Issue by @olleolleolle, closed 2022-01-25"
1846
+ [#2799]:https://github.com/puma/puma/pull/2799 "PR by @ags, merged 2022-01-22"
1847
+ [#2785]:https://github.com/puma/puma/pull/2785 "PR by @MSP-Greg, merged 2022-01-02"
1848
+ [#2757]:https://github.com/puma/puma/pull/2757 "PR by @MSP-Greg, merged 2021-11-24"
1849
+ [#2745]:https://github.com/puma/puma/pull/2745 "PR by @MSP-Greg, merged 2021-11-03"
1850
+ [#2742]:https://github.com/puma/puma/pull/2742 "PR by @MSP-Greg, merged 2021-12-12"
1851
+ [#2730]:https://github.com/puma/puma/pull/2730 "PR by @kares, merged 2021-11-01"
1852
+ [#2702]:https://github.com/puma/puma/pull/2702 "PR by @jacobherrington, merged 2021-09-21"
1802
1853
  [#2610]:https://github.com/puma/puma/pull/2610 "PR by @ye-lin-aung, merged 2021-08-18"
1803
1854
  [#2257]:https://github.com/puma/puma/issues/2257 "Issue by @nateberkopec, closed 2021-08-18"
1804
1855
  [#2654]:https://github.com/puma/puma/pull/2654 "PR by @Roguelazer, merged 2021-09-07"
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
@@ -137,6 +137,11 @@ This code can be used to setup the process before booting the application, allow
137
137
  you to do some Puma-specific things that you don't want to embed in your application.
138
138
  For instance, you could fire a log notification that a worker booted or send something to statsd. This can be called multiple times.
139
139
 
140
+ Constants loaded by your application (such as `Rails`) will not be available in `on_worker_boot`.
141
+ However, these constants _will_ be available if `preload_app!` is enabled, either explicitly in your `puma` config or automatically if
142
+ using 2 or more workers in cluster mode.
143
+ If `preload_app!` is not enabled and 1 worker is used, then `on_worker_boot` will fire, but your app will not be preloaded and constants will not be available.
144
+
140
145
  `before_fork` specifies a block to be run before workers are forked:
141
146
 
142
147
  ```ruby
data/bin/puma-wild CHANGED
File without changes
data/docs/architecture.md CHANGED
@@ -31,10 +31,10 @@ _workers_, and we sometimes call the threads created by Puma's
31
31
  ![https://bit.ly/2zwzhEK](images/puma-connection-flow.png)
32
32
 
33
33
  * Upon startup, Puma listens on a TCP or UNIX socket.
34
- * The backlog of this socket is configured (with a default of 1024). The
35
- backlog determines the size of the queue for unaccepted connections.
36
- Generally, you'll never hit the backlog cap in production. If the backlog is
37
- full, the operating system refuses new connections.
34
+ * The backlog of this socket is configured with a default of 1024, but the
35
+ actual backlog value is capped by the `net.core.somaxconn` sysctl value.
36
+ The backlog determines the size of the queue for unaccepted connections. If
37
+ the backlog is full, the operating system is not accepting new connections.
38
38
  * This socket backlog is distinct from the `backlog` of work as reported by
39
39
  `Puma.stats` or the control server. The backlog that `Puma.stats` refers to
40
40
  represents the number of connections in the process' `todo` set waiting for
File without changes
data/docs/deployment.md CHANGED
File without changes
data/docs/fork_worker.md CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/docs/kubernetes.md CHANGED
File without changes
data/docs/nginx.md CHANGED
File without changes
data/docs/plugins.md CHANGED
File without changes
File without changes
data/docs/restart.md CHANGED
File without changes
data/docs/signals.md CHANGED
@@ -42,6 +42,7 @@ Puma cluster responds to these signals:
42
42
  - `INT ` equivalent of sending Ctrl-C to cluster. Puma will attempt to finish then exit.
43
43
  - `CHLD`
44
44
  - `URG ` refork workers in phases from worker 0 if `fork_workers` option is enabled.
45
+ - `INFO` print backtraces of all puma threads
45
46
 
46
47
  ## Callbacks order in case of different signals
47
48
 
data/docs/stats.md CHANGED
File without changes
data/docs/systemd.md CHANGED
File without changes
File without changes
File without changes
@@ -11,7 +11,7 @@ end
11
11
  unless ENV["DISABLE_SSL"]
12
12
  dir_config("openssl")
13
13
 
14
- found_ssl = if pkg_config 'openssl'
14
+ found_ssl = if (!$mingw || RUBY_VERSION >= '2.4') && (t = pkg_config 'openssl')
15
15
  puts 'using OpenSSL pkgconfig (openssl.pc)'
16
16
  true
17
17
  elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
@@ -33,11 +33,14 @@ unless ENV["DISABLE_SSL"]
33
33
  have_func "SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h"
34
34
 
35
35
  have_func "X509_STORE_up_ref"
36
- have_func("SSL_CTX_set_ecdh_auto(NULL, 0)", "openssl/ssl.h")
36
+ have_func "SSL_CTX_set_ecdh_auto(NULL, 0)" , "openssl/ssl.h"
37
+
38
+ # below are yes for 3.0.0 & later, use for OpenSSL 3 detection
39
+ have_func "SSL_get1_peer_certificate" , "openssl/ssl.h"
37
40
 
38
41
  # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
39
42
  if Random.respond_to?(:bytes)
40
- $defs.push("-DHAVE_RANDOM_BYTES")
43
+ $defs.push "-DHAVE_RANDOM_BYTES"
41
44
  puts "checking for Random.bytes... yes"
42
45
  else
43
46
  puts "checking for Random.bytes... no"
@@ -48,11 +51,14 @@ end
48
51
  if ENV["MAKE_WARNINGS_INTO_ERRORS"]
49
52
  # Make all warnings into errors
50
53
  # Except `implicit-fallthrough` since most failures comes from ragel state machine generated code
51
- if respond_to? :append_cflags
52
- append_cflags config_string 'WERRORFLAG'
54
+ if respond_to?(:append_cflags, true) # Ruby 2.5 and later
55
+ append_cflags(config_string('WERRORFLAG') || '-Werror')
53
56
  append_cflags '-Wno-implicit-fallthrough'
54
57
  else
55
- $CFLAGS += ' ' << (config_string 'WERRORFLAG') << ' -Wno-implicit-fallthrough'
58
+ # flag may not exist on some platforms, -Werror may not be defined on some platforms, but
59
+ # works with all in current CI
60
+ $CFLAGS << " #{config_string('WERRORFLAG') || '-Werror'}"
61
+ $CFLAGS << ' -Wno-implicit-fallthrough'
56
62
  end
57
63
  end
58
64
 
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -49,7 +49,8 @@ const rb_data_type_t engine_data_type = {
49
49
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
50
50
  };
51
51
 
52
- DH *get_dh2048() {
52
+ #ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
53
+ DH *get_dh2048(void) {
53
54
  /* `openssl dhparam -C 2048`
54
55
  * -----BEGIN DH PARAMETERS-----
55
56
  * MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
@@ -119,6 +120,7 @@ DH *get_dh2048() {
119
120
 
120
121
  return dh;
121
122
  }
123
+ #endif
122
124
 
123
125
  static void
124
126
  sslctx_free(void *ptr) {
@@ -208,8 +210,13 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
208
210
  #endif
209
211
  int ssl_options;
210
212
  VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
211
- verification_flags, session_id_bytes;
213
+ verification_flags, session_id_bytes, cert_pem, key_pem;
214
+ #ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
212
215
  DH *dh;
216
+ #endif
217
+ BIO *bio;
218
+ X509 *x509;
219
+ EVP_PKEY *pkey;
213
220
 
214
221
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
215
222
  EC_KEY *ecdh;
@@ -218,13 +225,15 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
218
225
  TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
219
226
 
220
227
  key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
221
- StringValue(key);
222
228
 
223
229
  cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
224
- StringValue(cert);
225
230
 
226
231
  ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
227
232
 
233
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
234
+
235
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
236
+
228
237
  verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
229
238
 
230
239
  ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
@@ -233,8 +242,31 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
233
242
 
234
243
  no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
235
244
 
236
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
237
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
245
+ if (!NIL_P(cert)) {
246
+ StringValue(cert);
247
+ SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
248
+ }
249
+
250
+ if (!NIL_P(key)) {
251
+ StringValue(key);
252
+ SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
253
+ }
254
+
255
+ if (!NIL_P(cert_pem)) {
256
+ bio = BIO_new(BIO_s_mem());
257
+ BIO_puts(bio, RSTRING_PTR(cert_pem));
258
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
259
+
260
+ SSL_CTX_use_certificate(ctx, x509);
261
+ }
262
+
263
+ if (!NIL_P(key_pem)) {
264
+ bio = BIO_new(BIO_s_mem());
265
+ BIO_puts(bio, RSTRING_PTR(key_pem));
266
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
267
+
268
+ SSL_CTX_use_PrivateKey(ctx, pkey);
269
+ }
238
270
 
239
271
  verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
240
272
 
@@ -289,9 +321,6 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
289
321
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
290
322
  }
291
323
 
292
- dh = get_dh2048();
293
- SSL_CTX_set_tmp_dh(ctx, dh);
294
-
295
324
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
296
325
  // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
297
326
  // longer needed.
@@ -325,6 +354,15 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
325
354
  SSL_MAX_SSL_SESSION_ID_LENGTH);
326
355
 
327
356
  // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
357
+
358
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
359
+ // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
360
+ SSL_CTX_set_dh_auto(ctx, 1);
361
+ #else
362
+ dh = get_dh2048();
363
+ SSL_CTX_set_tmp_dh(ctx, dh);
364
+ #endif
365
+
328
366
  rb_obj_freeze(self);
329
367
  return self;
330
368
  }
@@ -523,7 +561,11 @@ VALUE engine_peercert(VALUE self) {
523
561
 
524
562
  TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
525
563
 
564
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
565
+ cert = SSL_get1_peer_certificate(conn->ssl);
566
+ #else
526
567
  cert = SSL_get_peer_certificate(conn->ssl);
568
+ #endif
527
569
  if(!cert) {
528
570
  /*
529
571
  * See if there was a failed certificate associated with this client.
@@ -580,7 +622,10 @@ void Init_mini_ssl(VALUE puma) {
580
622
  ERR_load_crypto_strings();
581
623
 
582
624
  mod = rb_define_module_under(puma, "MiniSSL");
625
+
583
626
  eng = rb_define_class_under(mod, "Engine", rb_cObject);
627
+ rb_undef_alloc_func(eng);
628
+
584
629
  sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
585
630
  rb_define_alloc_func(sslctx, sslctx_alloc);
586
631
  rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
File without changes
File without changes
File without changes
@@ -6,6 +6,7 @@ import org.jruby.RubyModule;
6
6
  import org.jruby.RubyObject;
7
7
  import org.jruby.RubyString;
8
8
  import org.jruby.anno.JRubyMethod;
9
+ import org.jruby.exceptions.RaiseException;
9
10
  import org.jruby.javasupport.JavaEmbedUtils;
10
11
  import org.jruby.runtime.Block;
11
12
  import org.jruby.runtime.ObjectAllocator;
@@ -80,11 +81,11 @@ public class MiniSSL extends RubyObject {
80
81
  /**
81
82
  * Writes bytes to the buffer after ensuring there's room
82
83
  */
83
- public void put(byte[] bytes) {
84
- if (buffer.remaining() < bytes.length) {
85
- resize(buffer.limit() + bytes.length);
84
+ private void put(byte[] bytes, final int offset, final int length) {
85
+ if (buffer.remaining() < length) {
86
+ resize(buffer.limit() + length);
86
87
  }
87
- buffer.put(bytes);
88
+ buffer.put(bytes, offset, length);
88
89
  }
89
90
 
90
91
  /**
@@ -115,7 +116,7 @@ public class MiniSSL extends RubyObject {
115
116
 
116
117
  buffer.get(bss);
117
118
  buffer.clear();
118
- return new ByteList(bss);
119
+ return new ByteList(bss, false);
119
120
  }
120
121
 
121
122
  @Override
@@ -174,8 +175,6 @@ public class MiniSSL extends RubyObject {
174
175
  @JRubyMethod
175
176
  public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
176
177
  throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
177
- KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
178
- KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
179
178
 
180
179
  String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
181
180
  KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
@@ -230,14 +229,9 @@ public class MiniSSL extends RubyObject {
230
229
 
231
230
  @JRubyMethod
232
231
  public IRubyObject inject(IRubyObject arg) {
233
- try {
234
- byte[] bytes = arg.convertToString().getBytes();
235
- inboundNetData.put(bytes);
236
- return this;
237
- } catch (Exception e) {
238
- e.printStackTrace();
239
- throw new RuntimeException(e);
240
- }
232
+ ByteList bytes = arg.convertToString().getByteList();
233
+ inboundNetData.put(bytes.unsafeBytes(), bytes.getBegin(), bytes.getRealSize());
234
+ return this;
241
235
  }
242
236
 
243
237
  private enum SSLOperation {
@@ -297,7 +291,7 @@ public class MiniSSL extends RubyObject {
297
291
  }
298
292
 
299
293
  @JRubyMethod
300
- public IRubyObject read() throws Exception {
294
+ public IRubyObject read() {
301
295
  try {
302
296
  inboundNetData.flip();
303
297
 
@@ -342,55 +336,46 @@ public class MiniSSL extends RubyObject {
342
336
  return getRuntime().getNil();
343
337
  }
344
338
 
345
- RubyString str = getRuntime().newString("");
346
- str.setValue(appDataByteList);
347
- return str;
348
- } catch (Exception e) {
349
- throw getRuntime().newEOFError(e.getMessage());
339
+ return RubyString.newString(getRuntime(), appDataByteList);
340
+ } catch (SSLException e) {
341
+ RaiseException re = getRuntime().newEOFError(e.getMessage());
342
+ re.initCause(e);
343
+ throw re;
350
344
  }
351
345
  }
352
346
 
353
347
  @JRubyMethod
354
348
  public IRubyObject write(IRubyObject arg) {
355
- try {
356
- byte[] bls = arg.convertToString().getBytes();
357
- outboundAppData = new MiniSSLBuffer(bls);
349
+ byte[] bls = arg.convertToString().getBytes();
350
+ outboundAppData = new MiniSSLBuffer(bls);
358
351
 
359
- return getRuntime().newFixnum(bls.length);
360
- } catch (Exception e) {
361
- e.printStackTrace();
362
- throw new RuntimeException(e);
363
- }
352
+ return getRuntime().newFixnum(bls.length);
364
353
  }
365
354
 
366
355
  @JRubyMethod
367
- public IRubyObject extract() throws SSLException {
356
+ public IRubyObject extract(ThreadContext context) {
368
357
  try {
369
358
  ByteList dataByteList = outboundNetData.asByteList();
370
359
  if (dataByteList != null) {
371
- RubyString str = getRuntime().newString("");
372
- str.setValue(dataByteList);
373
- return str;
360
+ return RubyString.newString(context.runtime, dataByteList);
374
361
  }
375
362
 
376
363
  if (!outboundAppData.hasRemaining()) {
377
- return getRuntime().getNil();
364
+ return context.nil;
378
365
  }
379
366
 
380
367
  outboundNetData.clear();
381
368
  doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
382
369
  dataByteList = outboundNetData.asByteList();
383
370
  if (dataByteList == null) {
384
- return getRuntime().getNil();
371
+ return context.nil;
385
372
  }
386
373
 
387
- RubyString str = getRuntime().newString("");
388
- str.setValue(dataByteList);
389
-
390
- return str;
391
- } catch (Exception e) {
392
- e.printStackTrace();
393
- throw new RuntimeException(e);
374
+ return RubyString.newString(context.runtime, dataByteList);
375
+ } catch (SSLException e) {
376
+ RaiseException ex = context.runtime.newRuntimeError(e.toString());
377
+ ex.initCause(e);
378
+ throw ex;
394
379
  }
395
380
  }
396
381
 
@@ -398,7 +383,7 @@ public class MiniSSL extends RubyObject {
398
383
  public IRubyObject peercert() throws CertificateEncodingException {
399
384
  try {
400
385
  return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
401
- } catch (SSLPeerUnverifiedException ex) {
386
+ } catch (SSLPeerUnverifiedException e) {
402
387
  return getRuntime().getNil();
403
388
  }
404
389
  }
@@ -451,7 +451,7 @@ VALUE HttpParser_body(VALUE self) {
451
451
  void Init_mini_ssl(VALUE mod);
452
452
  #endif
453
453
 
454
- void Init_puma_http11()
454
+ void Init_puma_http11(void)
455
455
  {
456
456
 
457
457
  VALUE mPuma = rb_define_module("Puma");
File without changes
data/lib/puma/binder.rb CHANGED
@@ -30,6 +30,7 @@ module Puma
30
30
 
31
31
  def initialize(events, conf = Configuration.new)
32
32
  @events = events
33
+ @conf = conf
33
34
  @listeners = []
34
35
  @inherited_fds = {}
35
36
  @activated_sockets = {}
@@ -167,9 +168,9 @@ module Puma
167
168
  params = Util.parse_query uri.query
168
169
 
169
170
  opt = params.key?('low_latency') && params['low_latency'] != 'false'
170
- bak = params.fetch('backlog', 1024).to_i
171
+ backlog = params.fetch('backlog', 1024).to_i
171
172
 
172
- io = add_tcp_listener uri.host, uri.port, opt, bak
173
+ io = add_tcp_listener uri.host, uri.port, opt, backlog
173
174
 
174
175
  @ios[ios_len..-1].each do |i|
175
176
  addr = loc_addr_str i
@@ -232,9 +233,21 @@ module Puma
232
233
  # If key and certs are not defined and localhost gem is required.
233
234
  # localhost gem will be used for self signed
234
235
  # Load localhost authority if not loaded.
235
- ctx = localhost_authority && localhost_authority_context if params.empty?
236
+ if params.values_at('cert', 'key').all? { |v| v.to_s.empty? }
237
+ ctx = localhost_authority && localhost_authority_context
238
+ end
236
239
 
237
- ctx ||= MiniSSL::ContextBuilder.new(params, @events).context
240
+ ctx ||=
241
+ begin
242
+ # Extract cert_pem and key_pem from options[:store] if present
243
+ ['cert', 'key'].each do |v|
244
+ if params[v] && params[v].start_with?('store:')
245
+ index = Integer(params.delete(v).split('store:').last)
246
+ params["#{v}_pem"] = @conf.options[:store][index]
247
+ end
248
+ end
249
+ MiniSSL::ContextBuilder.new(params, @events).context
250
+ end
238
251
 
239
252
  if fd = @inherited_fds.delete(str)
240
253
  logger.log "* Inherited #{str}"
@@ -244,7 +257,8 @@ module Puma
244
257
  logger.log "* Activated #{str}"
245
258
  else
246
259
  ios_len = @ios.length
247
- io = add_ssl_listener uri.host, uri.port, ctx
260
+ backlog = params.fetch('backlog', 1024).to_i
261
+ io = add_ssl_listener uri.host, uri.port, ctx, optimize_for_latency = true, backlog
248
262
 
249
263
  @ios[ios_len..-1].each do |i|
250
264
  addr = loc_addr_str i
data/lib/puma/cli.rb CHANGED
@@ -11,16 +11,17 @@ require 'puma/events'
11
11
 
12
12
  module Puma
13
13
  class << self
14
- # The CLI exports its Puma::Configuration object here to allow
15
- # apps to pick it up. An app needs to use it conditionally though
16
- # since it is not set if the app is launched via another
17
- # mechanism than the CLI class.
14
+ # The CLI exports a Puma::Configuration instance here to allow
15
+ # apps to pick it up. An app must load this object conditionally
16
+ # because it is not set if the app is launched via any mechanism
17
+ # other than the CLI class.
18
18
  attr_accessor :cli_config
19
19
  end
20
20
 
21
21
  # Handles invoke a Puma::Server in a command line style.
22
22
  #
23
23
  class CLI
24
+ # @deprecated 6.0.0
24
25
  KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE
25
26
 
26
27
  # Create a new CLI object using +argv+ as the command line
@@ -184,6 +185,10 @@ module Puma
184
185
  user_config.restart_command cmd
185
186
  end
186
187
 
188
+ o.on "-s", "--silent", "Do not log prompt messages other than errors" do
189
+ @events = Events.new NullIO.new, $stderr
190
+ end
191
+
187
192
  o.on "-S", "--state PATH", "Where to store the state details" do |arg|
188
193
  user_config.state_path arg
189
194
  end
data/lib/puma/client.rb CHANGED
@@ -161,7 +161,7 @@ module Puma
161
161
  def close
162
162
  begin
163
163
  @io.close
164
- rescue IOError
164
+ rescue IOError, Errno::EBADF
165
165
  Puma::Util.purge_interrupt_queue
166
166
  end
167
167
  end