puma 5.3.1 → 5.6.4

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 +152 -5
  3. data/LICENSE +0 -0
  4. data/README.md +47 -6
  5. data/bin/puma-wild +0 -0
  6. data/docs/architecture.md +49 -16
  7. data/docs/compile_options.md +4 -2
  8. data/docs/deployment.md +53 -67
  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 +15 -15
  19. data/docs/rails_dev_mode.md +2 -3
  20. data/docs/restart.md +6 -6
  21. data/docs/signals.md +11 -10
  22. data/docs/stats.md +8 -8
  23. data/docs/systemd.md +64 -67
  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 +28 -5
  27. data/ext/puma_http11/http11_parser.c +23 -10
  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 +1 -1
  32. data/ext/puma_http11/mini_ssl.c +69 -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 +49 -47
  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 +4 -4
  39. data/lib/puma/binder.rb +51 -6
  40. data/lib/puma/cli.rb +14 -4
  41. data/lib/puma/client.rb +106 -21
  42. data/lib/puma/cluster/worker.rb +14 -17
  43. data/lib/puma/cluster/worker_handle.rb +4 -0
  44. data/lib/puma/cluster.rb +30 -24
  45. data/lib/puma/commonlogger.rb +0 -0
  46. data/lib/puma/configuration.rb +6 -1
  47. data/lib/puma/const.rb +9 -8
  48. data/lib/puma/control_cli.rb +1 -1
  49. data/lib/puma/detect.rb +8 -2
  50. data/lib/puma/dsl.rb +106 -12
  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.rb → json_serialization.rb} +1 -1
  56. data/lib/puma/launcher.rb +4 -1
  57. data/lib/puma/minissl/context_builder.rb +8 -6
  58. data/lib/puma/minissl.rb +24 -23
  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 +2 -2
  62. data/lib/puma/queue_close.rb +0 -0
  63. data/lib/puma/rack/builder.rb +1 -1
  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 +27 -11
  68. data/lib/puma/runner.rb +22 -8
  69. data/lib/puma/server.rb +45 -44
  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 +7 -5
  74. data/lib/puma/util.rb +8 -1
  75. data/lib/puma.rb +2 -2
  76. data/lib/rack/handler/puma.rb +0 -0
  77. data/tools/Dockerfile +1 -1
  78. data/tools/trickletest.rb +0 -0
  79. metadata +7 -7
@@ -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;
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.
@@ -309,7 +338,31 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
309
338
  } else {
310
339
  SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
311
340
  }
341
+
342
+ // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
343
+ session_id_bytes = rb_funcall(
344
+ #ifdef HAVE_RANDOM_BYTES
345
+ rb_cRandom,
346
+ #else
347
+ rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
348
+ #endif
349
+ rb_intern_const("bytes"),
350
+ 1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
351
+
352
+ SSL_CTX_set_session_id_context(ctx,
353
+ (unsigned char *) RSTRING_PTR(session_id_bytes),
354
+ SSL_MAX_SSL_SESSION_ID_LENGTH);
355
+
312
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
+
313
366
  rb_obj_freeze(self);
314
367
  return self;
315
368
  }
@@ -508,7 +561,11 @@ VALUE engine_peercert(VALUE self) {
508
561
 
509
562
  TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
510
563
 
564
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
565
+ cert = SSL_get1_peer_certificate(conn->ssl);
566
+ #else
511
567
  cert = SSL_get_peer_certificate(conn->ssl);
568
+ #endif
512
569
  if(!cert) {
513
570
  /*
514
571
  * See if there was a failed certificate associated with this client.
@@ -565,7 +622,10 @@ void Init_mini_ssl(VALUE puma) {
565
622
  ERR_load_crypto_strings();
566
623
 
567
624
  mod = rb_define_module_under(puma, "MiniSSL");
625
+
568
626
  eng = rb_define_class_under(mod, "Engine", rb_cObject);
627
+ rb_undef_alloc_func(eng);
628
+
569
629
  sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
570
630
  rb_define_alloc_func(sslctx, sslctx_alloc);
571
631
  rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
File without changes
File without changes
@@ -34,9 +34,9 @@ private static short[] init__puma_parser_key_offsets_0()
34
34
  {
35
35
  return new short [] {
36
36
  0, 0, 8, 17, 27, 29, 30, 31, 32, 33, 34, 36,
37
- 39, 41, 44, 45, 61, 62, 78, 80, 81, 89, 97, 107,
38
- 115, 124, 132, 140, 149, 158, 167, 176, 185, 194, 203, 212,
39
- 221, 230, 239, 248, 257, 266, 275, 284, 293, 302, 303
37
+ 39, 41, 44, 45, 61, 62, 78, 85, 91, 99, 107, 117,
38
+ 125, 134, 142, 150, 159, 168, 177, 186, 195, 204, 213, 222,
39
+ 231, 240, 249, 258, 267, 276, 285, 294, 303, 312, 313
40
40
  };
41
41
  }
42
42
 
@@ -52,26 +52,27 @@ private static char[] init__puma_parser_trans_keys_0()
52
52
  46, 48, 57, 48, 57, 13, 48, 57, 10, 13, 33, 124,
53
53
  126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94,
54
54
  122, 10, 33, 58, 124, 126, 35, 39, 42, 43, 45, 46,
55
- 48, 57, 65, 90, 94, 122, 13, 32, 13, 32, 60, 62,
56
- 127, 0, 31, 34, 35, 32, 60, 62, 127, 0, 31, 34,
57
- 35, 43, 58, 45, 46, 48, 57, 65, 90, 97, 122, 32,
58
- 34, 35, 60, 62, 127, 0, 31, 32, 34, 35, 60, 62,
59
- 63, 127, 0, 31, 32, 34, 35, 60, 62, 127, 0, 31,
60
- 32, 34, 35, 60, 62, 127, 0, 31, 32, 36, 95, 45,
61
- 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
62
- 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
63
- 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
64
- 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
65
- 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
66
- 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
67
- 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
68
- 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
69
- 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
70
- 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
71
- 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90, 32,
72
- 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95, 45,
73
- 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48, 57,
74
- 65, 90, 32, 0
55
+ 48, 57, 65, 90, 94, 122, 13, 32, 127, 0, 8, 10,
56
+ 31, 13, 127, 0, 8, 10, 31, 32, 60, 62, 127, 0,
57
+ 31, 34, 35, 32, 60, 62, 127, 0, 31, 34, 35, 43,
58
+ 58, 45, 46, 48, 57, 65, 90, 97, 122, 32, 34, 35,
59
+ 60, 62, 127, 0, 31, 32, 34, 35, 60, 62, 63, 127,
60
+ 0, 31, 32, 34, 35, 60, 62, 127, 0, 31, 32, 34,
61
+ 35, 60, 62, 127, 0, 31, 32, 36, 95, 45, 46, 48,
62
+ 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
63
+ 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
64
+ 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
65
+ 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
66
+ 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
67
+ 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
68
+ 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
69
+ 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
70
+ 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
71
+ 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
72
+ 32, 36, 95, 45, 46, 48, 57, 65, 90, 32, 36, 95,
73
+ 45, 46, 48, 57, 65, 90, 32, 36, 95, 45, 46, 48,
74
+ 57, 65, 90, 32, 36, 95, 45, 46, 48, 57, 65, 90,
75
+ 32, 0
75
76
  };
76
77
  }
77
78
 
@@ -82,7 +83,7 @@ private static byte[] init__puma_parser_single_lengths_0()
82
83
  {
83
84
  return new byte [] {
84
85
  0, 2, 3, 4, 2, 1, 1, 1, 1, 1, 0, 1,
85
- 0, 1, 1, 4, 1, 4, 2, 1, 4, 4, 2, 6,
86
+ 0, 1, 1, 4, 1, 4, 3, 2, 4, 4, 2, 6,
86
87
  7, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
87
88
  3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0
88
89
  };
@@ -95,7 +96,7 @@ private static byte[] init__puma_parser_range_lengths_0()
95
96
  {
96
97
  return new byte [] {
97
98
  0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1,
98
- 1, 1, 0, 6, 0, 6, 0, 0, 2, 2, 4, 1,
99
+ 1, 1, 0, 6, 0, 6, 2, 2, 2, 2, 4, 1,
99
100
  1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
100
101
  3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0
101
102
  };
@@ -108,9 +109,9 @@ private static short[] init__puma_parser_index_offsets_0()
108
109
  {
109
110
  return new short [] {
110
111
  0, 0, 6, 13, 21, 24, 26, 28, 30, 32, 34, 36,
111
- 39, 41, 44, 46, 57, 59, 70, 73, 75, 82, 89, 96,
112
- 104, 113, 121, 129, 136, 143, 150, 157, 164, 171, 178, 185,
113
- 192, 199, 206, 213, 220, 227, 234, 241, 248, 255, 257
112
+ 39, 41, 44, 46, 57, 59, 70, 76, 81, 88, 95, 102,
113
+ 110, 119, 127, 135, 142, 149, 156, 163, 170, 177, 184, 191,
114
+ 198, 205, 212, 219, 226, 233, 240, 247, 254, 261, 263
114
115
  };
115
116
  }
116
117
 
@@ -126,22 +127,23 @@ private static byte[] init__puma_parser_indicies_0()
126
127
  16, 15, 1, 17, 1, 18, 17, 1, 19, 1, 20, 21,
127
128
  21, 21, 21, 21, 21, 21, 21, 21, 1, 22, 1, 23,
128
129
  24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 26, 27,
129
- 25, 29, 28, 30, 1, 1, 1, 1, 1, 31, 32, 1,
130
- 1, 1, 1, 1, 33, 34, 35, 34, 34, 34, 34, 1,
131
- 8, 1, 9, 1, 1, 1, 1, 35, 36, 1, 38, 1,
132
- 1, 39, 1, 1, 37, 40, 1, 42, 1, 1, 1, 1,
133
- 41, 43, 1, 45, 1, 1, 1, 1, 44, 2, 46, 46,
134
- 46, 46, 46, 1, 2, 47, 47, 47, 47, 47, 1, 2,
135
- 48, 48, 48, 48, 48, 1, 2, 49, 49, 49, 49, 49,
136
- 1, 2, 50, 50, 50, 50, 50, 1, 2, 51, 51, 51,
137
- 51, 51, 1, 2, 52, 52, 52, 52, 52, 1, 2, 53,
138
- 53, 53, 53, 53, 1, 2, 54, 54, 54, 54, 54, 1,
139
- 2, 55, 55, 55, 55, 55, 1, 2, 56, 56, 56, 56,
140
- 56, 1, 2, 57, 57, 57, 57, 57, 1, 2, 58, 58,
141
- 58, 58, 58, 1, 2, 59, 59, 59, 59, 59, 1, 2,
142
- 60, 60, 60, 60, 60, 1, 2, 61, 61, 61, 61, 61,
143
- 1, 2, 62, 62, 62, 62, 62, 1, 2, 63, 63, 63,
144
- 63, 63, 1, 2, 1, 1, 0
130
+ 1, 1, 1, 25, 29, 1, 1, 1, 28, 30, 1, 1,
131
+ 1, 1, 1, 31, 32, 1, 1, 1, 1, 1, 33, 34,
132
+ 35, 34, 34, 34, 34, 1, 8, 1, 9, 1, 1, 1,
133
+ 1, 35, 36, 1, 38, 1, 1, 39, 1, 1, 37, 40,
134
+ 1, 42, 1, 1, 1, 1, 41, 43, 1, 45, 1, 1,
135
+ 1, 1, 44, 2, 46, 46, 46, 46, 46, 1, 2, 47,
136
+ 47, 47, 47, 47, 1, 2, 48, 48, 48, 48, 48, 1,
137
+ 2, 49, 49, 49, 49, 49, 1, 2, 50, 50, 50, 50,
138
+ 50, 1, 2, 51, 51, 51, 51, 51, 1, 2, 52, 52,
139
+ 52, 52, 52, 1, 2, 53, 53, 53, 53, 53, 1, 2,
140
+ 54, 54, 54, 54, 54, 1, 2, 55, 55, 55, 55, 55,
141
+ 1, 2, 56, 56, 56, 56, 56, 1, 2, 57, 57, 57,
142
+ 57, 57, 1, 2, 58, 58, 58, 58, 58, 1, 2, 59,
143
+ 59, 59, 59, 59, 1, 2, 60, 60, 60, 60, 60, 1,
144
+ 2, 61, 61, 61, 61, 61, 1, 2, 62, 62, 62, 62,
145
+ 62, 1, 2, 63, 63, 63, 63, 63, 1, 2, 1, 1,
146
+ 0
145
147
  };
146
148
  }
147
149
 
@@ -210,7 +212,7 @@ static final int puma_parser_error = 0;
210
212
  cs = 0;
211
213
 
212
214
 
213
- // line 214 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
215
+ // line 216 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
214
216
  {
215
217
  cs = puma_parser_start;
216
218
  }
@@ -242,7 +244,7 @@ static final int puma_parser_error = 0;
242
244
  parser.buffer = buffer;
243
245
 
244
246
 
245
- // line 246 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
247
+ // line 248 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
246
248
  {
247
249
  int _klen;
248
250
  int _trans = 0;
@@ -398,7 +400,7 @@ case 1:
398
400
  { p += 1; _goto_targ = 5; if (true) continue _goto;}
399
401
  }
400
402
  break;
401
- // line 402 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
403
+ // line 404 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
402
404
  }
403
405
  }
404
406
  }
@@ -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");
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'puma/json'
2
+ require 'puma/json_serialization'
3
3
 
4
4
  module Puma
5
5
  module App
@@ -46,17 +46,17 @@ module Puma
46
46
  GC.start ; 200
47
47
 
48
48
  when 'gc-stats'
49
- Puma::JSON.generate GC.stat
49
+ Puma::JSONSerialization.generate GC.stat
50
50
 
51
51
  when 'stats'
52
- Puma::JSON.generate @launcher.stats
52
+ Puma::JSONSerialization.generate @launcher.stats
53
53
 
54
54
  when 'thread-backtraces'
55
55
  backtraces = []
56
56
  @launcher.thread_status do |name, backtrace|
57
57
  backtraces << { name: name, backtrace: backtrace }
58
58
  end
59
- Puma::JSON.generate backtraces
59
+ Puma::JSONSerialization.generate backtraces
60
60
 
61
61
  else
62
62
  return rack_response(404, "Unsupported action", 'text/plain')
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 = {}
@@ -41,6 +42,7 @@ module Puma
41
42
  "rack.multithread".freeze => conf.options[:max_threads] > 1,
42
43
  "rack.multiprocess".freeze => conf.options[:workers] >= 1,
43
44
  "rack.run_once".freeze => false,
45
+ RACK_URL_SCHEME => conf.options[:rack_url_scheme],
44
46
  "SCRIPT_NAME".freeze => ENV['SCRIPT_NAME'] || "",
45
47
 
46
48
  # I'd like to set a default CONTENT_TYPE here but some things
@@ -56,6 +58,7 @@ module Puma
56
58
 
57
59
  @envs = {}
58
60
  @ios = []
61
+ localhost_authority
59
62
  end
60
63
 
61
64
  attr_reader :ios
@@ -95,6 +98,7 @@ module Puma
95
98
  # @version 5.0.0
96
99
  #
97
100
  def create_activated_fds(env_hash)
101
+ @events.debug "ENV['LISTEN_FDS'] #{ENV['LISTEN_FDS'].inspect} env_hash['LISTEN_PID'] #{env_hash['LISTEN_PID'].inspect}"
98
102
  return [] unless env_hash['LISTEN_FDS'] && env_hash['LISTEN_PID'].to_i == $$
99
103
  env_hash['LISTEN_FDS'].to_i.times do |index|
100
104
  sock = TCPServer.for_fd(socket_activation_fd(index))
@@ -163,10 +167,10 @@ module Puma
163
167
  ios_len = @ios.length
164
168
  params = Util.parse_query uri.query
165
169
 
166
- opt = params.key?('low_latency')
167
- bak = params.fetch('backlog', 1024).to_i
170
+ opt = params.key?('low_latency') && params['low_latency'] != 'false'
171
+ backlog = params.fetch('backlog', 1024).to_i
168
172
 
169
- io = add_tcp_listener uri.host, uri.port, opt, bak
173
+ io = add_tcp_listener uri.host, uri.port, opt, backlog
170
174
 
171
175
  @ios[ios_len..-1].each do |i|
172
176
  addr = loc_addr_str i
@@ -188,7 +192,8 @@ module Puma
188
192
  @unix_paths << path unless abstract
189
193
  io = inherit_unix_listener path, fd
190
194
  logger.log "* Inherited #{str}"
191
- elsif sock = @activated_sockets.delete([ :unix, path ])
195
+ elsif sock = @activated_sockets.delete([ :unix, path ]) ||
196
+ @activated_sockets.delete([ :unix, File.realdirpath(path) ])
192
197
  @unix_paths << path unless abstract || File.exist?(path)
193
198
  io = inherit_unix_listener path, sock
194
199
  logger.log "* Activated #{str}"
@@ -224,7 +229,25 @@ module Puma
224
229
  raise "Puma compiled without SSL support" unless HAS_SSL
225
230
 
226
231
  params = Util.parse_query uri.query
227
- ctx = MiniSSL::ContextBuilder.new(params, @events).context
232
+
233
+ # If key and certs are not defined and localhost gem is required.
234
+ # localhost gem will be used for self signed
235
+ # Load localhost authority if not loaded.
236
+ if params.values_at('cert', 'key').all? { |v| v.to_s.empty? }
237
+ ctx = localhost_authority && localhost_authority_context
238
+ end
239
+
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
228
251
 
229
252
  if fd = @inherited_fds.delete(str)
230
253
  logger.log "* Inherited #{str}"
@@ -234,7 +257,8 @@ module Puma
234
257
  logger.log "* Activated #{str}"
235
258
  else
236
259
  ios_len = @ios.length
237
- 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
238
262
 
239
263
  @ios[ios_len..-1].each do |i|
240
264
  addr = loc_addr_str i
@@ -282,6 +306,22 @@ module Puma
282
306
  end
283
307
  end
284
308
 
309
+ def localhost_authority
310
+ @localhost_authority ||= Localhost::Authority.fetch if defined?(Localhost::Authority) && !Puma::IS_JRUBY
311
+ end
312
+
313
+ def localhost_authority_context
314
+ return unless localhost_authority
315
+
316
+ key_path, crt_path = if [:key_path, :certificate_path].all? { |m| localhost_authority.respond_to?(m) }
317
+ [localhost_authority.key_path, localhost_authority.certificate_path]
318
+ else
319
+ local_certificates_path = File.expand_path("~/.localhost")
320
+ [File.join(local_certificates_path, "localhost.key"), File.join(local_certificates_path, "localhost.crt")]
321
+ end
322
+ MiniSSL::ContextBuilder.new({ "key" => key_path, "cert" => crt_path }, @events).context
323
+ end
324
+
285
325
  # Tell the server to listen on host +host+, port +port+.
286
326
  # If +optimize_for_latency+ is true (the default) then clients connecting
287
327
  # will be optimized for latency over throughput.
@@ -299,6 +339,7 @@ module Puma
299
339
 
300
340
  host = host[1..-2] if host and host[0..0] == '['
301
341
  tcp_server = TCPServer.new(host, port)
342
+
302
343
  if optimize_for_latency
303
344
  tcp_server.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
304
345
  end
@@ -320,6 +361,8 @@ module Puma
320
361
  optimize_for_latency=true, backlog=1024)
321
362
 
322
363
  raise "Puma compiled without SSL support" unless HAS_SSL
364
+ # Puma will try to use local authority context if context is supplied nil
365
+ ctx ||= localhost_authority_context
323
366
 
324
367
  if host == "localhost"
325
368
  loopback_addresses.each do |addr|
@@ -347,6 +390,8 @@ module Puma
347
390
 
348
391
  def inherit_ssl_listener(fd, ctx)
349
392
  raise "Puma compiled without SSL support" unless HAS_SSL
393
+ # Puma will try to use local authority context if context is supplied nil
394
+ ctx ||= localhost_authority_context
350
395
 
351
396
  s = fd.kind_of?(::TCPServer) ? fd : ::TCPServer.for_fd(fd)
352
397