puma 5.5.0 → 5.6.7

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.

Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +140 -3
  3. data/README.md +28 -6
  4. data/docs/architecture.md +49 -16
  5. data/docs/compile_options.md +4 -2
  6. data/docs/deployment.md +53 -52
  7. data/docs/plugins.md +15 -15
  8. data/docs/rails_dev_mode.md +2 -3
  9. data/docs/restart.md +6 -6
  10. data/docs/signals.md +11 -10
  11. data/docs/stats.md +8 -8
  12. data/docs/systemd.md +63 -67
  13. data/ext/puma_http11/extconf.rb +18 -7
  14. data/ext/puma_http11/http11_parser.c +23 -10
  15. data/ext/puma_http11/http11_parser_common.rl +1 -1
  16. data/ext/puma_http11/mini_ssl.c +75 -12
  17. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +49 -47
  18. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +38 -55
  19. data/ext/puma_http11/puma_http11.c +1 -1
  20. data/lib/puma/app/status.rb +3 -0
  21. data/lib/puma/binder.rb +20 -6
  22. data/lib/puma/cli.rb +9 -4
  23. data/lib/puma/client.rb +68 -18
  24. data/lib/puma/cluster/worker.rb +7 -17
  25. data/lib/puma/cluster/worker_handle.rb +4 -0
  26. data/lib/puma/cluster.rb +29 -21
  27. data/lib/puma/configuration.rb +4 -1
  28. data/lib/puma/const.rb +7 -8
  29. data/lib/puma/control_cli.rb +19 -13
  30. data/lib/puma/detect.rb +8 -2
  31. data/lib/puma/dsl.rb +91 -10
  32. data/lib/puma/launcher.rb +13 -1
  33. data/lib/puma/minissl/context_builder.rb +8 -6
  34. data/lib/puma/minissl.rb +28 -7
  35. data/lib/puma/null_io.rb +5 -0
  36. data/lib/puma/plugin.rb +1 -1
  37. data/lib/puma/request.rb +15 -6
  38. data/lib/puma/runner.rb +22 -8
  39. data/lib/puma/server.rb +29 -30
  40. data/lib/puma/state_file.rb +42 -7
  41. data/lib/puma/thread_pool.rb +2 -2
  42. data/lib/puma/util.rb +19 -3
  43. data/lib/puma.rb +5 -3
  44. data/lib/rack/version_restriction.rb +15 -0
  45. data/tools/Dockerfile +1 -1
  46. metadata +4 -3
@@ -30,6 +30,12 @@ typedef struct {
30
30
 
31
31
  VALUE eError;
32
32
 
33
+ NORETURN(void raise_file_error(const char* caller, const char *filename));
34
+
35
+ void raise_file_error(const char* caller, const char *filename) {
36
+ rb_raise(eError, "%s: error in file '%s': %s", caller, filename, ERR_error_string(ERR_get_error(), NULL));
37
+ }
38
+
33
39
  void engine_free(void *ptr) {
34
40
  ms_conn *conn = ptr;
35
41
  ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
@@ -49,7 +55,8 @@ const rb_data_type_t engine_data_type = {
49
55
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
50
56
  };
51
57
 
52
- DH *get_dh2048() {
58
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
59
+ DH *get_dh2048(void) {
53
60
  /* `openssl dhparam -C 2048`
54
61
  * -----BEGIN DH PARAMETERS-----
55
62
  * MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
@@ -91,13 +98,13 @@ DH *get_dh2048() {
91
98
  static unsigned char dh2048_g[] = { 0x02 };
92
99
 
93
100
  DH *dh;
94
- #if !(OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER))
101
+ #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
95
102
  BIGNUM *p, *g;
96
103
  #endif
97
104
 
98
105
  dh = DH_new();
99
106
 
100
- #if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
107
+ #if OPENSSL_VERSION_NUMBER < 0x10100005L
101
108
  dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
102
109
  dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
103
110
 
@@ -119,6 +126,7 @@ DH *get_dh2048() {
119
126
 
120
127
  return dh;
121
128
  }
129
+ #endif
122
130
 
123
131
  static void
124
132
  sslctx_free(void *ptr) {
@@ -208,8 +216,13 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
208
216
  #endif
209
217
  int ssl_options;
210
218
  VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
211
- verification_flags, session_id_bytes;
219
+ verification_flags, session_id_bytes, cert_pem, key_pem;
220
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
212
221
  DH *dh;
222
+ #endif
223
+ BIO *bio;
224
+ X509 *x509;
225
+ EVP_PKEY *pkey;
213
226
 
214
227
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
215
228
  EC_KEY *ecdh;
@@ -218,13 +231,15 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
218
231
  TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
219
232
 
220
233
  key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
221
- StringValue(key);
222
234
 
223
235
  cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
224
- StringValue(cert);
225
236
 
226
237
  ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
227
238
 
239
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
240
+
241
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
242
+
228
243
  verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
229
244
 
230
245
  ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
@@ -233,8 +248,41 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
233
248
 
234
249
  no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
235
250
 
236
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
237
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
251
+ if (!NIL_P(cert)) {
252
+ StringValue(cert);
253
+
254
+ if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
255
+ raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
256
+ }
257
+ }
258
+
259
+ if (!NIL_P(key)) {
260
+ StringValue(key);
261
+
262
+ if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
263
+ raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
264
+ }
265
+ }
266
+
267
+ if (!NIL_P(cert_pem)) {
268
+ bio = BIO_new(BIO_s_mem());
269
+ BIO_puts(bio, RSTRING_PTR(cert_pem));
270
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
271
+
272
+ if (SSL_CTX_use_certificate(ctx, x509) != 1) {
273
+ raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
274
+ }
275
+ }
276
+
277
+ if (!NIL_P(key_pem)) {
278
+ bio = BIO_new(BIO_s_mem());
279
+ BIO_puts(bio, RSTRING_PTR(key_pem));
280
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
281
+
282
+ if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
283
+ raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
284
+ }
285
+ }
238
286
 
239
287
  verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
240
288
 
@@ -246,7 +294,9 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
246
294
 
247
295
  if (!NIL_P(ca)) {
248
296
  StringValue(ca);
249
- SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
297
+ if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
298
+ raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
299
+ }
250
300
  }
251
301
 
252
302
  ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
@@ -289,9 +339,6 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
289
339
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
290
340
  }
291
341
 
292
- dh = get_dh2048();
293
- SSL_CTX_set_tmp_dh(ctx, dh);
294
-
295
342
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
296
343
  // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
297
344
  // longer needed.
@@ -325,6 +372,15 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
325
372
  SSL_MAX_SSL_SESSION_ID_LENGTH);
326
373
 
327
374
  // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
375
+
376
+ #ifdef HAVE_SSL_CTX_SET_DH_AUTO
377
+ // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
378
+ SSL_CTX_set_dh_auto(ctx, 1);
379
+ #else
380
+ dh = get_dh2048();
381
+ SSL_CTX_set_tmp_dh(ctx, dh);
382
+ #endif
383
+
328
384
  rb_obj_freeze(self);
329
385
  return self;
330
386
  }
@@ -523,7 +579,11 @@ VALUE engine_peercert(VALUE self) {
523
579
 
524
580
  TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
525
581
 
582
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
583
+ cert = SSL_get1_peer_certificate(conn->ssl);
584
+ #else
526
585
  cert = SSL_get_peer_certificate(conn->ssl);
586
+ #endif
527
587
  if(!cert) {
528
588
  /*
529
589
  * See if there was a failed certificate associated with this client.
@@ -580,7 +640,10 @@ void Init_mini_ssl(VALUE puma) {
580
640
  ERR_load_crypto_strings();
581
641
 
582
642
  mod = rb_define_module_under(puma, "MiniSSL");
643
+
583
644
  eng = rb_define_class_under(mod, "Engine", rb_cObject);
645
+ rb_undef_alloc_func(eng);
646
+
584
647
  sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
585
648
  rb_define_alloc_func(sslctx, sslctx_alloc);
586
649
  rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
@@ -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 {
@@ -285,19 +279,11 @@ public class MiniSSL extends RubyObject {
285
279
  }
286
280
  }
287
281
 
288
- // after each op, run any delegated tasks if needed
289
- if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
290
- Runnable runnable;
291
- while ((runnable = engine.getDelegatedTask()) != null) {
292
- runnable.run();
293
- }
294
- }
295
-
296
282
  return res;
297
283
  }
298
284
 
299
285
  @JRubyMethod
300
- public IRubyObject read() throws Exception {
286
+ public IRubyObject read() {
301
287
  try {
302
288
  inboundNetData.flip();
303
289
 
@@ -310,11 +296,12 @@ public class MiniSSL extends RubyObject {
310
296
 
311
297
  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
312
298
  boolean done = false;
313
- SSLEngineResult res = null;
314
299
  while (!done) {
300
+ SSLEngineResult res;
315
301
  switch (handshakeStatus) {
316
302
  case NEED_WRAP:
317
303
  res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
304
+ handshakeStatus = res.getHandshakeStatus();
318
305
  break;
319
306
  case NEED_UNWRAP:
320
307
  res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
@@ -322,13 +309,18 @@ public class MiniSSL extends RubyObject {
322
309
  // need more data before we can shake more hands
323
310
  done = true;
324
311
  }
312
+ handshakeStatus = res.getHandshakeStatus();
313
+ break;
314
+ case NEED_TASK:
315
+ Runnable runnable;
316
+ while ((runnable = engine.getDelegatedTask()) != null) {
317
+ runnable.run();
318
+ }
319
+ handshakeStatus = engine.getHandshakeStatus();
325
320
  break;
326
321
  default:
327
322
  done = true;
328
323
  }
329
- if (!done) {
330
- handshakeStatus = res.getHandshakeStatus();
331
- }
332
324
  }
333
325
 
334
326
  if (inboundNetData.hasRemaining()) {
@@ -342,55 +334,46 @@ public class MiniSSL extends RubyObject {
342
334
  return getRuntime().getNil();
343
335
  }
344
336
 
345
- RubyString str = getRuntime().newString("");
346
- str.setValue(appDataByteList);
347
- return str;
348
- } catch (Exception e) {
349
- throw getRuntime().newEOFError(e.getMessage());
337
+ return RubyString.newString(getRuntime(), appDataByteList);
338
+ } catch (SSLException e) {
339
+ RaiseException re = getRuntime().newEOFError(e.getMessage());
340
+ re.initCause(e);
341
+ throw re;
350
342
  }
351
343
  }
352
344
 
353
345
  @JRubyMethod
354
346
  public IRubyObject write(IRubyObject arg) {
355
- try {
356
- byte[] bls = arg.convertToString().getBytes();
357
- outboundAppData = new MiniSSLBuffer(bls);
347
+ byte[] bls = arg.convertToString().getBytes();
348
+ outboundAppData = new MiniSSLBuffer(bls);
358
349
 
359
- return getRuntime().newFixnum(bls.length);
360
- } catch (Exception e) {
361
- e.printStackTrace();
362
- throw new RuntimeException(e);
363
- }
350
+ return getRuntime().newFixnum(bls.length);
364
351
  }
365
352
 
366
353
  @JRubyMethod
367
- public IRubyObject extract() throws SSLException {
354
+ public IRubyObject extract(ThreadContext context) {
368
355
  try {
369
356
  ByteList dataByteList = outboundNetData.asByteList();
370
357
  if (dataByteList != null) {
371
- RubyString str = getRuntime().newString("");
372
- str.setValue(dataByteList);
373
- return str;
358
+ return RubyString.newString(context.runtime, dataByteList);
374
359
  }
375
360
 
376
361
  if (!outboundAppData.hasRemaining()) {
377
- return getRuntime().getNil();
362
+ return context.nil;
378
363
  }
379
364
 
380
365
  outboundNetData.clear();
381
366
  doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
382
367
  dataByteList = outboundNetData.asByteList();
383
368
  if (dataByteList == null) {
384
- return getRuntime().getNil();
369
+ return context.nil;
385
370
  }
386
371
 
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);
372
+ return RubyString.newString(context.runtime, dataByteList);
373
+ } catch (SSLException e) {
374
+ RaiseException ex = context.runtime.newRuntimeError(e.toString());
375
+ ex.initCause(e);
376
+ throw ex;
394
377
  }
395
378
  }
396
379
 
@@ -398,7 +381,7 @@ public class MiniSSL extends RubyObject {
398
381
  public IRubyObject peercert() throws CertificateEncodingException {
399
382
  try {
400
383
  return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
401
- } catch (SSLPeerUnverifiedException ex) {
384
+ } catch (SSLPeerUnverifiedException e) {
402
385
  return getRuntime().getNil();
403
386
  }
404
387
  }
@@ -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");
@@ -39,6 +39,9 @@ module Puma
39
39
  when 'phased-restart'
40
40
  @launcher.phased_restart ? 200 : 404
41
41
 
42
+ when 'refork'
43
+ @launcher.refork ? 200 : 404
44
+
42
45
  when 'reload-worker-directory'
43
46
  @launcher.send(:reload_worker_directory) ? 200 : 404
44
47
 
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
@@ -188,7 +189,7 @@ module Puma
188
189
  end
189
190
 
190
191
  if fd = @inherited_fds.delete(str)
191
- @unix_paths << path unless abstract
192
+ @unix_paths << path unless abstract || File.exist?(path)
192
193
  io = inherit_unix_listener path, fd
193
194
  logger.log "* Inherited #{str}"
194
195
  elsif sock = @activated_sockets.delete([ :unix, path ]) ||
@@ -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