puma 3.7.1 → 4.1.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.
- checksums.yaml +5 -5
- data/History.md +229 -1
- data/README.md +179 -212
- data/docs/architecture.md +37 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +24 -4
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/plugins.md +28 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +130 -37
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +8 -0
- data/ext/puma_http11/http11_parser.c +84 -84
- data/ext/puma_http11/http11_parser.rl +9 -9
- data/ext/puma_http11/mini_ssl.c +105 -9
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +13 -16
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +30 -6
- data/lib/puma.rb +10 -0
- data/lib/puma/accept_nonblock.rb +2 -0
- data/lib/puma/app/status.rb +13 -0
- data/lib/puma/binder.rb +33 -18
- data/lib/puma/cli.rb +48 -33
- data/lib/puma/client.rb +94 -22
- data/lib/puma/cluster.rb +69 -21
- data/lib/puma/commonlogger.rb +2 -0
- data/lib/puma/configuration.rb +134 -136
- data/lib/puma/const.rb +16 -2
- data/lib/puma/control_cli.rb +31 -18
- data/lib/puma/convenient.rb +5 -3
- data/lib/puma/daemon_ext.rb +2 -0
- data/lib/puma/delegation.rb +2 -0
- data/lib/puma/detect.rb +2 -0
- data/lib/puma/dsl.rb +349 -113
- data/lib/puma/events.rb +8 -4
- data/lib/puma/io_buffer.rb +3 -6
- data/lib/puma/jruby_restart.rb +2 -1
- data/lib/puma/launcher.rb +60 -36
- data/lib/puma/minissl.rb +85 -28
- data/lib/puma/null_io.rb +2 -0
- data/lib/puma/plugin.rb +2 -0
- data/lib/puma/plugin/tmp_restart.rb +3 -2
- data/lib/puma/rack/builder.rb +4 -1
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +218 -30
- data/lib/puma/runner.rb +18 -4
- data/lib/puma/server.rb +149 -56
- data/lib/puma/single.rb +16 -5
- data/lib/puma/state_file.rb +2 -0
- data/lib/puma/tcp_logger.rb +2 -0
- data/lib/puma/thread_pool.rb +59 -6
- data/lib/puma/util.rb +2 -6
- data/lib/rack/handler/puma.rb +58 -19
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +2 -0
- data/tools/jungle/init.d/puma +8 -8
- data/tools/jungle/init.d/run-puma +1 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/trickletest.rb +1 -1
- metadata +25 -85
- data/.github/issue_template.md +0 -20
- data/Gemfile +0 -12
- data/Manifest.txt +0 -77
- data/Rakefile +0 -158
- data/gemfiles/2.1-Gemfile +0 -12
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/puma.gemspec +0 -52
@@ -29,7 +29,7 @@ static void snake_upcase_char(char *c)
|
|
29
29
|
/** Machine **/
|
30
30
|
|
31
31
|
%%{
|
32
|
-
|
32
|
+
|
33
33
|
machine puma_parser;
|
34
34
|
|
35
35
|
action mark { MARK(mark, fpc); }
|
@@ -37,7 +37,7 @@ static void snake_upcase_char(char *c)
|
|
37
37
|
|
38
38
|
action start_field { MARK(field_start, fpc); }
|
39
39
|
action snake_upcase_field { snake_upcase_char((char *)fpc); }
|
40
|
-
action write_field {
|
40
|
+
action write_field {
|
41
41
|
parser->field_len = LEN(field_start, fpc);
|
42
42
|
}
|
43
43
|
|
@@ -45,10 +45,10 @@ static void snake_upcase_char(char *c)
|
|
45
45
|
action write_value {
|
46
46
|
parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
|
47
47
|
}
|
48
|
-
action request_method {
|
48
|
+
action request_method {
|
49
49
|
parser->request_method(parser, PTR_TO(mark), LEN(mark, fpc));
|
50
50
|
}
|
51
|
-
action request_uri {
|
51
|
+
action request_uri {
|
52
52
|
parser->request_uri(parser, PTR_TO(mark), LEN(mark, fpc));
|
53
53
|
}
|
54
54
|
action fragment {
|
@@ -56,11 +56,11 @@ static void snake_upcase_char(char *c)
|
|
56
56
|
}
|
57
57
|
|
58
58
|
action start_query { MARK(query_start, fpc); }
|
59
|
-
action query_string {
|
59
|
+
action query_string {
|
60
60
|
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, fpc));
|
61
61
|
}
|
62
62
|
|
63
|
-
action http_version {
|
63
|
+
action http_version {
|
64
64
|
parser->http_version(parser, PTR_TO(mark), LEN(mark, fpc));
|
65
65
|
}
|
66
66
|
|
@@ -68,8 +68,8 @@ static void snake_upcase_char(char *c)
|
|
68
68
|
parser->request_path(parser, PTR_TO(mark), LEN(mark,fpc));
|
69
69
|
}
|
70
70
|
|
71
|
-
action done {
|
72
|
-
parser->body_start = fpc - buffer + 1;
|
71
|
+
action done {
|
72
|
+
parser->body_start = fpc - buffer + 1;
|
73
73
|
parser->header_done(parser, fpc + 1, pe - fpc - 1);
|
74
74
|
fbreak;
|
75
75
|
}
|
@@ -109,7 +109,7 @@ size_t puma_parser_execute(puma_parser *parser, const char *buffer, size_t len,
|
|
109
109
|
pe = buffer+len;
|
110
110
|
|
111
111
|
/* assert(*pe == '\0' && "pointer does not end on NUL"); */
|
112
|
-
assert(pe - p == len - off && "pointers aren't same distance");
|
112
|
+
assert((size_t) (pe - p) == len - off && "pointers aren't same distance");
|
113
113
|
|
114
114
|
%% write exec;
|
115
115
|
|
data/ext/puma_http11/mini_ssl.c
CHANGED
@@ -88,7 +88,7 @@ DH *get_dh1024() {
|
|
88
88
|
DH *dh;
|
89
89
|
dh = DH_new();
|
90
90
|
|
91
|
-
#if OPENSSL_VERSION_NUMBER < 0x10100005L
|
91
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
|
92
92
|
dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
|
93
93
|
dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
|
94
94
|
|
@@ -142,6 +142,7 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
142
142
|
VALUE obj;
|
143
143
|
SSL_CTX* ctx;
|
144
144
|
SSL* ssl;
|
145
|
+
int min, ssl_options;
|
145
146
|
|
146
147
|
ms_conn* conn = engine_alloc(self, &obj);
|
147
148
|
|
@@ -161,7 +162,20 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
161
162
|
ID sym_verify_mode = rb_intern("verify_mode");
|
162
163
|
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
163
164
|
|
165
|
+
ID sym_ssl_cipher_filter = rb_intern("ssl_cipher_filter");
|
166
|
+
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
167
|
+
|
168
|
+
ID sym_no_tlsv1 = rb_intern("no_tlsv1");
|
169
|
+
VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
|
170
|
+
|
171
|
+
ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1");
|
172
|
+
VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
|
173
|
+
|
174
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
175
|
+
ctx = SSL_CTX_new(TLS_server_method());
|
176
|
+
#else
|
164
177
|
ctx = SSL_CTX_new(SSLv23_server_method());
|
178
|
+
#endif
|
165
179
|
conn->ctx = ctx;
|
166
180
|
|
167
181
|
SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
|
@@ -172,20 +186,61 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
172
186
|
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
|
173
187
|
}
|
174
188
|
|
175
|
-
|
189
|
+
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
190
|
+
|
191
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
192
|
+
if (RTEST(no_tlsv1_1)) {
|
193
|
+
min = TLS1_2_VERSION;
|
194
|
+
}
|
195
|
+
else if (RTEST(no_tlsv1)) {
|
196
|
+
min = TLS1_1_VERSION;
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
min = TLS1_VERSION;
|
200
|
+
}
|
201
|
+
|
202
|
+
SSL_CTX_set_min_proto_version(ctx, min);
|
203
|
+
|
204
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
205
|
+
|
206
|
+
#else
|
207
|
+
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
208
|
+
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
209
|
+
|
210
|
+
if (RTEST(no_tlsv1)) {
|
211
|
+
ssl_options |= SSL_OP_NO_TLSv1;
|
212
|
+
}
|
213
|
+
if(RTEST(no_tlsv1_1)) {
|
214
|
+
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
215
|
+
}
|
216
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
217
|
+
#endif
|
218
|
+
|
176
219
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
177
220
|
|
178
|
-
|
221
|
+
if (!NIL_P(ssl_cipher_filter)) {
|
222
|
+
StringValue(ssl_cipher_filter);
|
223
|
+
SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(ssl_cipher_filter));
|
224
|
+
}
|
225
|
+
else {
|
226
|
+
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
227
|
+
}
|
179
228
|
|
180
229
|
DH *dh = get_dh1024();
|
181
230
|
SSL_CTX_set_tmp_dh(ctx, dh);
|
182
231
|
|
183
|
-
#
|
184
|
-
|
232
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
233
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no
|
234
|
+
// longer needed.
|
235
|
+
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
185
236
|
if (ecdh) {
|
186
237
|
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
187
238
|
EC_KEY_free(ecdh);
|
188
239
|
}
|
240
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
241
|
+
// Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH
|
242
|
+
// negotiation.
|
243
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
189
244
|
#endif
|
190
245
|
|
191
246
|
ssl = SSL_new(ctx);
|
@@ -207,8 +262,11 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
207
262
|
VALUE engine_init_client(VALUE klass) {
|
208
263
|
VALUE obj;
|
209
264
|
ms_conn* conn = engine_alloc(klass, &obj);
|
210
|
-
|
265
|
+
#ifdef HAVE_DTLS_METHOD
|
266
|
+
conn->ctx = SSL_CTX_new(DTLS_method());
|
267
|
+
#else
|
211
268
|
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
269
|
+
#endif
|
212
270
|
conn->ssl = SSL_new(conn->ctx);
|
213
271
|
SSL_set_app_data(conn->ssl, NULL);
|
214
272
|
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
@@ -244,7 +302,7 @@ void raise_error(SSL* ssl, int result) {
|
|
244
302
|
const char* err_str;
|
245
303
|
int err = errno;
|
246
304
|
int ssl_err = SSL_get_error(ssl, result);
|
247
|
-
int verify_err = SSL_get_verify_result(ssl);
|
305
|
+
int verify_err = (int) SSL_get_verify_result(ssl);
|
248
306
|
|
249
307
|
if(SSL_ERROR_SYSCALL == ssl_err) {
|
250
308
|
snprintf(msg, sizeof(msg), "System error: %s - %d", strerror(err), err);
|
@@ -257,7 +315,7 @@ void raise_error(SSL* ssl, int result) {
|
|
257
315
|
err_str, verify_err);
|
258
316
|
|
259
317
|
} else {
|
260
|
-
err = ERR_get_error();
|
318
|
+
err = (int) ERR_get_error();
|
261
319
|
ERR_error_string_n(err, buf, sizeof(buf));
|
262
320
|
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
263
321
|
|
@@ -411,6 +469,11 @@ VALUE noop(VALUE self) {
|
|
411
469
|
void Init_mini_ssl(VALUE puma) {
|
412
470
|
VALUE mod, eng;
|
413
471
|
|
472
|
+
/* Fake operation for documentation (RDoc, YARD) */
|
473
|
+
#if 0 == 1
|
474
|
+
puma = rb_define_module("Puma");
|
475
|
+
#endif
|
476
|
+
|
414
477
|
SSL_library_init();
|
415
478
|
OpenSSL_add_ssl_algorithms();
|
416
479
|
SSL_load_error_strings();
|
@@ -419,6 +482,39 @@ void Init_mini_ssl(VALUE puma) {
|
|
419
482
|
mod = rb_define_module_under(puma, "MiniSSL");
|
420
483
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
421
484
|
|
485
|
+
// OpenSSL Build / Runtime/Load versions
|
486
|
+
|
487
|
+
/* Version of OpenSSL that Puma was compiled with */
|
488
|
+
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
489
|
+
|
490
|
+
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
491
|
+
/* Version of OpenSSL that Puma loaded with */
|
492
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
493
|
+
#else
|
494
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
495
|
+
#endif
|
496
|
+
|
497
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
498
|
+
/* True if SSL3 is not available */
|
499
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
500
|
+
#else
|
501
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
502
|
+
#endif
|
503
|
+
|
504
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
505
|
+
/* True if TLS1 is not available */
|
506
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
507
|
+
#else
|
508
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
509
|
+
#endif
|
510
|
+
|
511
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
512
|
+
/* True if TLS1_1 is not available */
|
513
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
514
|
+
#else
|
515
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
516
|
+
#endif
|
517
|
+
|
422
518
|
rb_define_singleton_method(mod, "check", noop, 0);
|
423
519
|
|
424
520
|
eError = rb_define_class_under(mod, "SSLError", rb_eStandardError);
|
@@ -447,7 +543,7 @@ VALUE raise_error(VALUE self) {
|
|
447
543
|
}
|
448
544
|
|
449
545
|
void Init_mini_ssl(VALUE puma) {
|
450
|
-
VALUE mod
|
546
|
+
VALUE mod;
|
451
547
|
|
452
548
|
mod = rb_define_module_under(puma, "MiniSSL");
|
453
549
|
rb_define_class_under(mod, "SSLError", rb_eStandardError);
|
@@ -182,9 +182,6 @@ static final int puma_parser_start = 1;
|
|
182
182
|
static final int puma_parser_first_final = 47;
|
183
183
|
static final int puma_parser_error = 0;
|
184
184
|
|
185
|
-
static final int puma_parser_en_main = 1;
|
186
|
-
|
187
|
-
|
188
185
|
// line 69 "ext/puma_http11/http11_parser.java.rl"
|
189
186
|
|
190
187
|
public static interface ElementCB {
|
@@ -220,7 +217,7 @@ static final int puma_parser_en_main = 1;
|
|
220
217
|
public void init() {
|
221
218
|
cs = 0;
|
222
219
|
|
223
|
-
|
220
|
+
|
224
221
|
// line 225 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
225
222
|
{
|
226
223
|
cs = puma_parser_start;
|
@@ -252,7 +249,7 @@ static final int puma_parser_en_main = 1;
|
|
252
249
|
byte[] data = buffer.bytes();
|
253
250
|
parser.buffer = buffer;
|
254
251
|
|
255
|
-
|
252
|
+
|
256
253
|
// line 257 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
257
254
|
{
|
258
255
|
int _klen;
|
@@ -347,7 +344,7 @@ case 1:
|
|
347
344
|
break;
|
348
345
|
case 3:
|
349
346
|
// line 17 "ext/puma_http11/http11_parser.java.rl"
|
350
|
-
{
|
347
|
+
{
|
351
348
|
parser.field_len = p-parser.field_start;
|
352
349
|
}
|
353
350
|
break;
|
@@ -357,7 +354,7 @@ case 1:
|
|
357
354
|
break;
|
358
355
|
case 5:
|
359
356
|
// line 22 "ext/puma_http11/http11_parser.java.rl"
|
360
|
-
{
|
357
|
+
{
|
361
358
|
if(parser.http_field != null) {
|
362
359
|
parser.http_field.call(parser.data, parser.field_start, parser.field_len, parser.mark, p-parser.mark);
|
363
360
|
}
|
@@ -365,21 +362,21 @@ case 1:
|
|
365
362
|
break;
|
366
363
|
case 6:
|
367
364
|
// line 27 "ext/puma_http11/http11_parser.java.rl"
|
368
|
-
{
|
369
|
-
if(parser.request_method != null)
|
365
|
+
{
|
366
|
+
if(parser.request_method != null)
|
370
367
|
parser.request_method.call(parser.data, parser.mark, p-parser.mark);
|
371
368
|
}
|
372
369
|
break;
|
373
370
|
case 7:
|
374
371
|
// line 31 "ext/puma_http11/http11_parser.java.rl"
|
375
|
-
{
|
372
|
+
{
|
376
373
|
if(parser.request_uri != null)
|
377
374
|
parser.request_uri.call(parser.data, parser.mark, p-parser.mark);
|
378
375
|
}
|
379
376
|
break;
|
380
377
|
case 8:
|
381
378
|
// line 35 "ext/puma_http11/http11_parser.java.rl"
|
382
|
-
{
|
379
|
+
{
|
383
380
|
if(parser.fragment != null)
|
384
381
|
parser.fragment.call(parser.data, parser.mark, p-parser.mark);
|
385
382
|
}
|
@@ -390,14 +387,14 @@ case 1:
|
|
390
387
|
break;
|
391
388
|
case 10:
|
392
389
|
// line 41 "ext/puma_http11/http11_parser.java.rl"
|
393
|
-
{
|
390
|
+
{
|
394
391
|
if(parser.query_string != null)
|
395
392
|
parser.query_string.call(parser.data, parser.query_start, p-parser.query_start);
|
396
393
|
}
|
397
394
|
break;
|
398
395
|
case 11:
|
399
396
|
// line 46 "ext/puma_http11/http11_parser.java.rl"
|
400
|
-
{
|
397
|
+
{
|
401
398
|
if(parser.http_version != null)
|
402
399
|
parser.http_version.call(parser.data, parser.mark, p-parser.mark);
|
403
400
|
}
|
@@ -411,8 +408,8 @@ case 1:
|
|
411
408
|
break;
|
412
409
|
case 13:
|
413
410
|
// line 56 "ext/puma_http11/http11_parser.java.rl"
|
414
|
-
{
|
415
|
-
parser.body_start = p + 1;
|
411
|
+
{
|
412
|
+
parser.body_start = p + 1;
|
416
413
|
if(parser.header_done != null)
|
417
414
|
parser.header_done.call(parser.data, p + 1, pe - p - 1);
|
418
415
|
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
|
@@ -442,7 +439,7 @@ case 5:
|
|
442
439
|
|
443
440
|
parser.cs = cs;
|
444
441
|
parser.nread += (p - off);
|
445
|
-
|
442
|
+
|
446
443
|
assert p <= pe : "buffer overflow after parsing execute";
|
447
444
|
assert parser.nread <= len : "nread longer than length";
|
448
445
|
assert parser.body_start <= len : "body starts after buffer end";
|
@@ -0,0 +1,72 @@
|
|
1
|
+
package org.jruby.puma;
|
2
|
+
|
3
|
+
import org.jruby.*;
|
4
|
+
import org.jruby.anno.JRubyMethod;
|
5
|
+
import org.jruby.runtime.ObjectAllocator;
|
6
|
+
import org.jruby.runtime.ThreadContext;
|
7
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
8
|
+
import org.jruby.util.ByteList;
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @author kares
|
12
|
+
*/
|
13
|
+
public class IOBuffer extends RubyObject {
|
14
|
+
|
15
|
+
private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
16
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
17
|
+
return new IOBuffer(runtime, klass);
|
18
|
+
}
|
19
|
+
};
|
20
|
+
|
21
|
+
public static void createIOBuffer(Ruby runtime) {
|
22
|
+
RubyModule mPuma = runtime.defineModule("Puma");
|
23
|
+
RubyClass cIOBuffer = mPuma.defineClassUnder("IOBuffer", runtime.getObject(), ALLOCATOR);
|
24
|
+
cIOBuffer.defineAnnotatedMethods(IOBuffer.class);
|
25
|
+
}
|
26
|
+
|
27
|
+
private static final int DEFAULT_SIZE = 4096;
|
28
|
+
|
29
|
+
final ByteList buffer = new ByteList(DEFAULT_SIZE);
|
30
|
+
|
31
|
+
IOBuffer(Ruby runtime, RubyClass klass) {
|
32
|
+
super(runtime, klass);
|
33
|
+
}
|
34
|
+
|
35
|
+
@JRubyMethod
|
36
|
+
public RubyInteger used(ThreadContext context) {
|
37
|
+
return context.runtime.newFixnum(buffer.getRealSize());
|
38
|
+
}
|
39
|
+
|
40
|
+
@JRubyMethod
|
41
|
+
public RubyInteger capacity(ThreadContext context) {
|
42
|
+
return context.runtime.newFixnum(buffer.unsafeBytes().length);
|
43
|
+
}
|
44
|
+
|
45
|
+
@JRubyMethod
|
46
|
+
public IRubyObject reset() {
|
47
|
+
buffer.setRealSize(0);
|
48
|
+
return this;
|
49
|
+
}
|
50
|
+
|
51
|
+
@JRubyMethod(name = { "to_s", "to_str" })
|
52
|
+
public RubyString to_s(ThreadContext context) {
|
53
|
+
return RubyString.newStringShared(context.runtime, buffer.unsafeBytes(), 0, buffer.getRealSize());
|
54
|
+
}
|
55
|
+
|
56
|
+
@JRubyMethod(name = "<<")
|
57
|
+
public IRubyObject add(IRubyObject str) {
|
58
|
+
addImpl(str.convertToString());
|
59
|
+
return this;
|
60
|
+
}
|
61
|
+
|
62
|
+
@JRubyMethod(rest = true)
|
63
|
+
public IRubyObject append(IRubyObject[] strs) {
|
64
|
+
for (IRubyObject str : strs) addImpl(str.convertToString());
|
65
|
+
return this;
|
66
|
+
}
|
67
|
+
|
68
|
+
private void addImpl(RubyString str) {
|
69
|
+
buffer.append(str.getByteList());
|
70
|
+
}
|
71
|
+
|
72
|
+
}
|
@@ -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.javasupport.JavaEmbedUtils;
|
9
10
|
import org.jruby.runtime.Block;
|
10
11
|
import org.jruby.runtime.ObjectAllocator;
|
11
12
|
import org.jruby.runtime.ThreadContext;
|
@@ -18,15 +19,18 @@ import javax.net.ssl.SSLContext;
|
|
18
19
|
import javax.net.ssl.SSLEngine;
|
19
20
|
import javax.net.ssl.SSLEngineResult;
|
20
21
|
import javax.net.ssl.SSLException;
|
22
|
+
import javax.net.ssl.SSLPeerUnverifiedException;
|
21
23
|
import javax.net.ssl.SSLSession;
|
22
24
|
import java.io.FileInputStream;
|
23
25
|
import java.io.IOException;
|
26
|
+
import java.nio.Buffer;
|
24
27
|
import java.nio.ByteBuffer;
|
25
28
|
import java.security.KeyManagementException;
|
26
29
|
import java.security.KeyStore;
|
27
30
|
import java.security.KeyStoreException;
|
28
31
|
import java.security.NoSuchAlgorithmException;
|
29
32
|
import java.security.UnrecoverableKeyException;
|
33
|
+
import java.security.cert.CertificateEncodingException;
|
30
34
|
import java.security.cert.CertificateException;
|
31
35
|
|
32
36
|
import static javax.net.ssl.SSLEngineResult.Status;
|
@@ -62,7 +66,7 @@ public class MiniSSL extends RubyObject {
|
|
62
66
|
|
63
67
|
public void clear() { buffer.clear(); }
|
64
68
|
public void compact() { buffer.compact(); }
|
65
|
-
public void flip() { buffer.flip(); }
|
69
|
+
public void flip() { ((Buffer) buffer).flip(); }
|
66
70
|
public boolean hasRemaining() { return buffer.hasRemaining(); }
|
67
71
|
public int position() { return buffer.position(); }
|
68
72
|
|
@@ -86,7 +90,7 @@ public class MiniSSL extends RubyObject {
|
|
86
90
|
public void resize(int newCapacity) {
|
87
91
|
if (newCapacity > buffer.capacity()) {
|
88
92
|
ByteBuffer dstTmp = ByteBuffer.allocate(newCapacity);
|
89
|
-
|
93
|
+
flip();
|
90
94
|
dstTmp.put(buffer);
|
91
95
|
buffer = dstTmp;
|
92
96
|
} else {
|
@@ -98,7 +102,7 @@ public class MiniSSL extends RubyObject {
|
|
98
102
|
* Drains the buffer to a ByteList, or returns null for an empty buffer
|
99
103
|
*/
|
100
104
|
public ByteList asByteList() {
|
101
|
-
|
105
|
+
flip();
|
102
106
|
if (!buffer.hasRemaining()) {
|
103
107
|
buffer.clear();
|
104
108
|
return null;
|
@@ -155,7 +159,17 @@ public class MiniSSL extends RubyObject {
|
|
155
159
|
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
156
160
|
engine = sslCtx.createSSLEngine();
|
157
161
|
|
158
|
-
String[] protocols
|
162
|
+
String[] protocols;
|
163
|
+
if(miniSSLContext.callMethod(threadContext, "no_tlsv1").isTrue()) {
|
164
|
+
protocols = new String[] { "TLSv1.1", "TLSv1.2" };
|
165
|
+
} else {
|
166
|
+
protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
|
167
|
+
}
|
168
|
+
|
169
|
+
if(miniSSLContext.callMethod(threadContext, "no_tlsv1_1").isTrue()) {
|
170
|
+
protocols = new String[] { "TLSv1.2" };
|
171
|
+
}
|
172
|
+
|
159
173
|
engine.setEnabledProtocols(protocols);
|
160
174
|
engine.setUseClientMode(false);
|
161
175
|
|
@@ -167,6 +181,12 @@ public class MiniSSL extends RubyObject {
|
|
167
181
|
engine.setNeedClientAuth(true);
|
168
182
|
}
|
169
183
|
|
184
|
+
IRubyObject sslCipherListObject = miniSSLContext.callMethod(threadContext, "ssl_cipher_list");
|
185
|
+
if (!sslCipherListObject.isNil()) {
|
186
|
+
String[] sslCipherList = sslCipherListObject.convertToString().asJavaString().split(",");
|
187
|
+
engine.setEnabledCipherSuites(sslCipherList);
|
188
|
+
}
|
189
|
+
|
170
190
|
SSLSession session = engine.getSession();
|
171
191
|
inboundNetData = new MiniSSLBuffer(session.getPacketBufferSize());
|
172
192
|
outboundAppData = new MiniSSLBuffer(session.getApplicationBufferSize());
|
@@ -333,7 +353,11 @@ public class MiniSSL extends RubyObject {
|
|
333
353
|
}
|
334
354
|
|
335
355
|
@JRubyMethod
|
336
|
-
public IRubyObject peercert() {
|
337
|
-
|
356
|
+
public IRubyObject peercert() throws CertificateEncodingException {
|
357
|
+
try {
|
358
|
+
return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
|
359
|
+
} catch (SSLPeerUnverifiedException ex) {
|
360
|
+
return getRuntime().getNil();
|
361
|
+
}
|
338
362
|
}
|
339
363
|
}
|