puma 4.1.1 → 5.0.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 +4 -4
- data/History.md +149 -10
- data/LICENSE +23 -20
- data/README.md +30 -46
- data/docs/architecture.md +3 -3
- data/docs/deployment.md +9 -3
- data/docs/fork_worker.md +31 -0
- data/docs/jungle/README.md +13 -0
- data/{tools → docs}/jungle/rc.d/README.md +0 -0
- data/{tools → docs}/jungle/rc.d/puma +0 -0
- data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/{tools → docs}/jungle/upstart/README.md +0 -0
- data/{tools → docs}/jungle/upstart/puma-manager.conf +0 -0
- data/{tools → docs}/jungle/upstart/puma.conf +0 -0
- data/docs/plugins.md +20 -10
- data/docs/signals.md +7 -6
- data/docs/systemd.md +1 -63
- data/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/extconf.rb +6 -0
- data/ext/puma_http11/http11_parser.c +40 -63
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser.rl +3 -1
- data/ext/puma_http11/http11_parser_common.rl +3 -3
- data/ext/puma_http11/mini_ssl.c +15 -2
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +91 -106
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +77 -18
- data/ext/puma_http11/puma_http11.c +9 -38
- data/lib/puma.rb +23 -0
- data/lib/puma/app/status.rb +46 -30
- data/lib/puma/binder.rb +112 -124
- data/lib/puma/cli.rb +11 -15
- data/lib/puma/client.rb +250 -209
- data/lib/puma/cluster.rb +203 -85
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +31 -42
- data/lib/puma/const.rb +24 -19
- data/lib/puma/control_cli.rb +46 -17
- data/lib/puma/detect.rb +17 -0
- data/lib/puma/dsl.rb +162 -70
- data/lib/puma/error_logger.rb +97 -0
- data/lib/puma/events.rb +35 -31
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/launcher.rb +117 -58
- data/lib/puma/minissl.rb +60 -18
- data/lib/puma/minissl/context_builder.rb +73 -0
- data/lib/puma/null_io.rb +1 -1
- data/lib/puma/plugin.rb +6 -12
- data/lib/puma/rack/builder.rb +0 -4
- data/lib/puma/reactor.rb +16 -9
- data/lib/puma/runner.rb +11 -32
- data/lib/puma/server.rb +173 -193
- data/lib/puma/single.rb +7 -64
- data/lib/puma/state_file.rb +6 -3
- data/lib/puma/thread_pool.rb +104 -81
- data/lib/rack/handler/puma.rb +1 -5
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +23 -24
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
@@ -2,6 +2,8 @@
|
|
2
2
|
// line 1 "ext/puma_http11/http11_parser.java.rl"
|
3
3
|
package org.jruby.puma;
|
4
4
|
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.RubyHash;
|
5
7
|
import org.jruby.util.ByteList;
|
6
8
|
|
7
9
|
public class Http11Parser {
|
@@ -9,12 +11,12 @@ public class Http11Parser {
|
|
9
11
|
/** Machine **/
|
10
12
|
|
11
13
|
|
12
|
-
// line
|
14
|
+
// line 58 "ext/puma_http11/http11_parser.java.rl"
|
13
15
|
|
14
16
|
|
15
17
|
/** Data **/
|
16
18
|
|
17
|
-
// line
|
19
|
+
// line 20 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
18
20
|
private static byte[] init__puma_parser_actions_0()
|
19
21
|
{
|
20
22
|
return new byte [] {
|
@@ -33,8 +35,8 @@ private static short[] init__puma_parser_key_offsets_0()
|
|
33
35
|
return new short [] {
|
34
36
|
0, 0, 8, 17, 27, 29, 30, 31, 32, 33, 34, 36,
|
35
37
|
39, 41, 44, 45, 61, 62, 78, 80, 81, 89, 97, 107,
|
36
|
-
115,
|
37
|
-
|
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
|
38
40
|
};
|
39
41
|
}
|
40
42
|
|
@@ -53,24 +55,23 @@ private static char[] init__puma_parser_trans_keys_0()
|
|
53
55
|
48, 57, 65, 90, 94, 122, 13, 32, 13, 32, 60, 62,
|
54
56
|
127, 0, 31, 34, 35, 32, 60, 62, 127, 0, 31, 34,
|
55
57
|
35, 43, 58, 45, 46, 48, 57, 65, 90, 97, 122, 32,
|
56
|
-
34, 35, 60, 62, 127, 0, 31, 32, 34, 35,
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
32, 0
|
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
|
74
75
|
};
|
75
76
|
}
|
76
77
|
|
@@ -82,8 +83,8 @@ private static byte[] init__puma_parser_single_lengths_0()
|
|
82
83
|
return new byte [] {
|
83
84
|
0, 2, 3, 4, 2, 1, 1, 1, 1, 1, 0, 1,
|
84
85
|
0, 1, 1, 4, 1, 4, 2, 1, 4, 4, 2, 6,
|
85
|
-
|
86
|
-
3, 3, 3, 3, 3, 3, 3, 3, 3,
|
86
|
+
7, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
87
|
+
3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 0
|
87
88
|
};
|
88
89
|
}
|
89
90
|
|
@@ -95,8 +96,8 @@ private static byte[] init__puma_parser_range_lengths_0()
|
|
95
96
|
return new byte [] {
|
96
97
|
0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 1, 1,
|
97
98
|
1, 1, 0, 6, 0, 6, 0, 0, 2, 2, 4, 1,
|
98
|
-
1, 1, 1,
|
99
|
-
3, 3, 3, 3, 3, 3, 3, 3, 3,
|
99
|
+
1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
100
|
+
3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0
|
100
101
|
};
|
101
102
|
}
|
102
103
|
|
@@ -108,8 +109,8 @@ private static short[] init__puma_parser_index_offsets_0()
|
|
108
109
|
return new short [] {
|
109
110
|
0, 0, 6, 13, 21, 24, 26, 28, 30, 32, 34, 36,
|
110
111
|
39, 41, 44, 46, 57, 59, 70, 73, 75, 82, 89, 96,
|
111
|
-
104,
|
112
|
-
|
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
|
113
114
|
};
|
114
115
|
}
|
115
116
|
|
@@ -127,21 +128,20 @@ private static byte[] init__puma_parser_indicies_0()
|
|
127
128
|
24, 23, 23, 23, 23, 23, 23, 23, 23, 1, 26, 27,
|
128
129
|
25, 29, 28, 30, 1, 1, 1, 1, 1, 31, 32, 1,
|
129
130
|
1, 1, 1, 1, 33, 34, 35, 34, 34, 34, 34, 1,
|
130
|
-
8, 1, 9, 1, 1, 1, 1, 35, 36, 1, 38,
|
131
|
-
1,
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
1, 2, 1, 1, 0
|
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
|
145
145
|
};
|
146
146
|
}
|
147
147
|
|
@@ -151,12 +151,12 @@ private static final byte _puma_parser_indicies[] = init__puma_parser_indicies_0
|
|
151
151
|
private static byte[] init__puma_parser_trans_targs_0()
|
152
152
|
{
|
153
153
|
return new byte [] {
|
154
|
-
2, 0, 3,
|
155
|
-
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
154
|
+
2, 0, 3, 27, 4, 22, 24, 23, 5, 20, 6, 7,
|
155
|
+
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 46, 17,
|
156
156
|
18, 19, 14, 18, 19, 14, 5, 21, 5, 21, 22, 23,
|
157
|
-
5, 24, 20, 25, 26,
|
158
|
-
|
159
|
-
|
157
|
+
5, 24, 20, 25, 5, 26, 20, 5, 26, 20, 28, 29,
|
158
|
+
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
159
|
+
42, 43, 44, 45
|
160
160
|
};
|
161
161
|
}
|
162
162
|
|
@@ -169,9 +169,9 @@ private static byte[] init__puma_parser_trans_actions_0()
|
|
169
169
|
1, 0, 11, 0, 1, 1, 1, 1, 13, 13, 1, 0,
|
170
170
|
0, 0, 0, 0, 0, 0, 19, 0, 0, 28, 23, 3,
|
171
171
|
5, 7, 31, 7, 0, 9, 25, 1, 15, 0, 0, 0,
|
172
|
-
37, 0, 37, 21,
|
173
|
-
|
174
|
-
0, 0, 0, 0
|
172
|
+
37, 0, 37, 21, 40, 17, 40, 34, 0, 34, 0, 0,
|
173
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
174
|
+
0, 0, 0, 0
|
175
175
|
};
|
176
176
|
}
|
177
177
|
|
@@ -179,17 +179,20 @@ private static final byte _puma_parser_trans_actions[] = init__puma_parser_trans
|
|
179
179
|
|
180
180
|
|
181
181
|
static final int puma_parser_start = 1;
|
182
|
-
static final int puma_parser_first_final =
|
182
|
+
static final int puma_parser_first_final = 46;
|
183
183
|
static final int puma_parser_error = 0;
|
184
184
|
|
185
|
-
|
185
|
+
static final int puma_parser_en_main = 1;
|
186
|
+
|
187
|
+
|
188
|
+
// line 62 "ext/puma_http11/http11_parser.java.rl"
|
186
189
|
|
187
190
|
public static interface ElementCB {
|
188
|
-
public void call(
|
191
|
+
public void call(Ruby runtime, RubyHash data, ByteList buffer, int at, int length);
|
189
192
|
}
|
190
193
|
|
191
194
|
public static interface FieldCB {
|
192
|
-
public void call(
|
195
|
+
public void call(Ruby runtime, RubyHash data, ByteList buffer, int field, int flen, int value, int vlen);
|
193
196
|
}
|
194
197
|
|
195
198
|
public static class HttpParser {
|
@@ -202,28 +205,19 @@ static final int puma_parser_error = 0;
|
|
202
205
|
int field_len;
|
203
206
|
int query_start;
|
204
207
|
|
205
|
-
|
208
|
+
RubyHash data;
|
206
209
|
ByteList buffer;
|
207
210
|
|
208
|
-
public FieldCB http_field;
|
209
|
-
public ElementCB request_method;
|
210
|
-
public ElementCB request_uri;
|
211
|
-
public ElementCB fragment;
|
212
|
-
public ElementCB request_path;
|
213
|
-
public ElementCB query_string;
|
214
|
-
public ElementCB http_version;
|
215
|
-
public ElementCB header_done;
|
216
|
-
|
217
211
|
public void init() {
|
218
212
|
cs = 0;
|
219
213
|
|
220
|
-
|
221
|
-
// line
|
214
|
+
|
215
|
+
// line 218 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
222
216
|
{
|
223
217
|
cs = puma_parser_start;
|
224
218
|
}
|
225
219
|
|
226
|
-
// line
|
220
|
+
// line 90 "ext/puma_http11/http11_parser.java.rl"
|
227
221
|
|
228
222
|
body_start = 0;
|
229
223
|
content_len = 0;
|
@@ -236,7 +230,7 @@ static final int puma_parser_error = 0;
|
|
236
230
|
|
237
231
|
public final HttpParser parser = new HttpParser();
|
238
232
|
|
239
|
-
public int execute(ByteList buffer, int off) {
|
233
|
+
public int execute(Ruby runtime, Http11 http, ByteList buffer, int off) {
|
240
234
|
int p, pe;
|
241
235
|
int cs = parser.cs;
|
242
236
|
int len = buffer.length();
|
@@ -249,8 +243,8 @@ static final int puma_parser_error = 0;
|
|
249
243
|
byte[] data = buffer.bytes();
|
250
244
|
parser.buffer = buffer;
|
251
245
|
|
252
|
-
|
253
|
-
// line
|
246
|
+
|
247
|
+
// line 250 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
254
248
|
{
|
255
249
|
int _klen;
|
256
250
|
int _trans = 0;
|
@@ -331,91 +325,82 @@ case 1:
|
|
331
325
|
switch ( _puma_parser_actions[_acts++] )
|
332
326
|
{
|
333
327
|
case 0:
|
334
|
-
// line
|
328
|
+
// line 15 "ext/puma_http11/http11_parser.java.rl"
|
335
329
|
{parser.mark = p; }
|
336
330
|
break;
|
337
331
|
case 1:
|
338
|
-
// line
|
332
|
+
// line 17 "ext/puma_http11/http11_parser.java.rl"
|
339
333
|
{ parser.field_start = p; }
|
340
334
|
break;
|
341
335
|
case 2:
|
342
|
-
// line
|
336
|
+
// line 18 "ext/puma_http11/http11_parser.java.rl"
|
343
337
|
{ /* FIXME stub */ }
|
344
338
|
break;
|
345
339
|
case 3:
|
346
|
-
// line
|
347
|
-
{
|
340
|
+
// line 19 "ext/puma_http11/http11_parser.java.rl"
|
341
|
+
{
|
348
342
|
parser.field_len = p-parser.field_start;
|
349
343
|
}
|
350
344
|
break;
|
351
345
|
case 4:
|
352
|
-
// line
|
346
|
+
// line 23 "ext/puma_http11/http11_parser.java.rl"
|
353
347
|
{ parser.mark = p; }
|
354
348
|
break;
|
355
349
|
case 5:
|
356
|
-
// line
|
350
|
+
// line 24 "ext/puma_http11/http11_parser.java.rl"
|
357
351
|
{
|
358
|
-
|
359
|
-
parser.http_field.call(parser.data, parser.field_start, parser.field_len, parser.mark, p-parser.mark);
|
360
|
-
}
|
352
|
+
Http11.http_field(runtime, parser.data, parser.buffer, parser.field_start, parser.field_len, parser.mark, p-parser.mark);
|
361
353
|
}
|
362
354
|
break;
|
363
355
|
case 6:
|
364
356
|
// line 27 "ext/puma_http11/http11_parser.java.rl"
|
365
357
|
{
|
366
|
-
|
367
|
-
parser.request_method.call(parser.data, parser.mark, p-parser.mark);
|
358
|
+
Http11.request_method(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
|
368
359
|
}
|
369
360
|
break;
|
370
361
|
case 7:
|
371
|
-
// line
|
362
|
+
// line 30 "ext/puma_http11/http11_parser.java.rl"
|
372
363
|
{
|
373
|
-
|
374
|
-
parser.request_uri.call(parser.data, parser.mark, p-parser.mark);
|
364
|
+
Http11.request_uri(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
|
375
365
|
}
|
376
366
|
break;
|
377
367
|
case 8:
|
378
|
-
// line
|
368
|
+
// line 33 "ext/puma_http11/http11_parser.java.rl"
|
379
369
|
{
|
380
|
-
|
381
|
-
parser.fragment.call(parser.data, parser.mark, p-parser.mark);
|
370
|
+
Http11.fragment(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
|
382
371
|
}
|
383
372
|
break;
|
384
373
|
case 9:
|
385
|
-
// line
|
374
|
+
// line 37 "ext/puma_http11/http11_parser.java.rl"
|
386
375
|
{parser.query_start = p; }
|
387
376
|
break;
|
388
377
|
case 10:
|
389
|
-
// line
|
378
|
+
// line 38 "ext/puma_http11/http11_parser.java.rl"
|
390
379
|
{
|
391
|
-
|
392
|
-
parser.query_string.call(parser.data, parser.query_start, p-parser.query_start);
|
380
|
+
Http11.query_string(runtime, parser.data, parser.buffer, parser.query_start, p-parser.query_start);
|
393
381
|
}
|
394
382
|
break;
|
395
383
|
case 11:
|
396
|
-
// line
|
384
|
+
// line 42 "ext/puma_http11/http11_parser.java.rl"
|
397
385
|
{
|
398
|
-
|
399
|
-
parser.http_version.call(parser.data, parser.mark, p-parser.mark);
|
386
|
+
Http11.http_version(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
|
400
387
|
}
|
401
388
|
break;
|
402
389
|
case 12:
|
403
|
-
// line
|
390
|
+
// line 46 "ext/puma_http11/http11_parser.java.rl"
|
404
391
|
{
|
405
|
-
|
406
|
-
parser.request_path.call(parser.data, parser.mark, p-parser.mark);
|
392
|
+
Http11.request_path(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
|
407
393
|
}
|
408
394
|
break;
|
409
395
|
case 13:
|
410
|
-
// line
|
411
|
-
{
|
396
|
+
// line 50 "ext/puma_http11/http11_parser.java.rl"
|
397
|
+
{
|
412
398
|
parser.body_start = p + 1;
|
413
|
-
|
414
|
-
parser.header_done.call(parser.data, p + 1, pe - p - 1);
|
399
|
+
http.header_done(runtime, parser.data, parser.buffer, p + 1, pe - p - 1);
|
415
400
|
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
|
416
401
|
}
|
417
402
|
break;
|
418
|
-
// line
|
403
|
+
// line 406 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
419
404
|
}
|
420
405
|
}
|
421
406
|
}
|
@@ -435,11 +420,11 @@ case 5:
|
|
435
420
|
break; }
|
436
421
|
}
|
437
422
|
|
438
|
-
// line
|
423
|
+
// line 116 "ext/puma_http11/http11_parser.java.rl"
|
439
424
|
|
440
425
|
parser.cs = cs;
|
441
426
|
parser.nread += (p - off);
|
442
|
-
|
427
|
+
|
443
428
|
assert p <= pe : "buffer overflow after parsing execute";
|
444
429
|
assert parser.nread <= len : "nread longer than length";
|
445
430
|
assert parser.body_start <= len : "body starts after buffer end";
|
@@ -22,6 +22,7 @@ import javax.net.ssl.SSLException;
|
|
22
22
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
23
23
|
import javax.net.ssl.SSLSession;
|
24
24
|
import java.io.FileInputStream;
|
25
|
+
import java.io.InputStream;
|
25
26
|
import java.io.IOException;
|
26
27
|
import java.nio.Buffer;
|
27
28
|
import java.nio.ByteBuffer;
|
@@ -32,6 +33,8 @@ import java.security.NoSuchAlgorithmException;
|
|
32
33
|
import java.security.UnrecoverableKeyException;
|
33
34
|
import java.security.cert.CertificateEncodingException;
|
34
35
|
import java.security.cert.CertificateException;
|
36
|
+
import java.util.concurrent.ConcurrentHashMap;
|
37
|
+
import java.util.Map;
|
35
38
|
|
36
39
|
import static javax.net.ssl.SSLEngineResult.Status;
|
37
40
|
import static javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
@@ -120,6 +123,8 @@ public class MiniSSL extends RubyObject {
|
|
120
123
|
}
|
121
124
|
|
122
125
|
private SSLEngine engine;
|
126
|
+
private boolean closed;
|
127
|
+
private boolean handshake;
|
123
128
|
private MiniSSLBuffer inboundNetData;
|
124
129
|
private MiniSSLBuffer outboundAppData;
|
125
130
|
private MiniSSLBuffer outboundNetData;
|
@@ -128,10 +133,39 @@ public class MiniSSL extends RubyObject {
|
|
128
133
|
super(runtime, klass);
|
129
134
|
}
|
130
135
|
|
136
|
+
private static Map<String, KeyManagerFactory> keyManagerFactoryMap = new ConcurrentHashMap<String, KeyManagerFactory>();
|
137
|
+
private static Map<String, TrustManagerFactory> trustManagerFactoryMap = new ConcurrentHashMap<String, TrustManagerFactory>();
|
138
|
+
|
131
139
|
@JRubyMethod(meta = true)
|
132
|
-
public static IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
|
133
|
-
|
140
|
+
public static synchronized IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
|
141
|
+
throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
|
142
|
+
// Create the KeyManagerFactory and TrustManagerFactory for this server
|
143
|
+
String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
|
144
|
+
char[] password = miniSSLContext.callMethod(context, "keystore_pass").convertToString().asJavaString().toCharArray();
|
134
145
|
|
146
|
+
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
147
|
+
InputStream is = new FileInputStream(keystoreFile);
|
148
|
+
try {
|
149
|
+
ks.load(is, password);
|
150
|
+
} finally {
|
151
|
+
is.close();
|
152
|
+
}
|
153
|
+
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
154
|
+
kmf.init(ks, password);
|
155
|
+
keyManagerFactoryMap.put(keystoreFile, kmf);
|
156
|
+
|
157
|
+
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
|
158
|
+
is = new FileInputStream(keystoreFile);
|
159
|
+
try {
|
160
|
+
ts.load(is, password);
|
161
|
+
} finally {
|
162
|
+
is.close();
|
163
|
+
}
|
164
|
+
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
165
|
+
tmf.init(ts);
|
166
|
+
trustManagerFactoryMap.put(keystoreFile, tmf);
|
167
|
+
|
168
|
+
RubyClass klass = (RubyClass) recv;
|
135
169
|
return klass.newInstance(context,
|
136
170
|
new IRubyObject[] { miniSSLContext },
|
137
171
|
Block.NULL_BLOCK);
|
@@ -139,24 +173,22 @@ public class MiniSSL extends RubyObject {
|
|
139
173
|
|
140
174
|
@JRubyMethod
|
141
175
|
public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
|
142
|
-
throws KeyStoreException,
|
176
|
+
throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
|
143
177
|
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
144
178
|
KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
|
145
179
|
|
146
|
-
char[] password = miniSSLContext.callMethod(threadContext, "keystore_pass").convertToString().asJavaString().toCharArray();
|
147
180
|
String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
|
155
|
-
tmf.init(ts);
|
181
|
+
KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
|
182
|
+
TrustManagerFactory tmf = trustManagerFactoryMap.get(keystoreFile);
|
183
|
+
if(kmf == null || tmf == null) {
|
184
|
+
throw new KeyStoreException("Could not find KeyManagerFactory/TrustManagerFactory for keystore: " + keystoreFile);
|
185
|
+
}
|
156
186
|
|
157
187
|
SSLContext sslCtx = SSLContext.getInstance("TLS");
|
158
188
|
|
159
189
|
sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
190
|
+
closed = false;
|
191
|
+
handshake = false;
|
160
192
|
engine = sslCtx.createSSLEngine();
|
161
193
|
|
162
194
|
String[] protocols;
|
@@ -173,7 +205,7 @@ public class MiniSSL extends RubyObject {
|
|
173
205
|
engine.setEnabledProtocols(protocols);
|
174
206
|
engine.setUseClientMode(false);
|
175
207
|
|
176
|
-
long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger().getLongValue();
|
208
|
+
long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger("to_i").getLongValue();
|
177
209
|
if ((verify_mode & 0x1) != 0) { // 'peer'
|
178
210
|
engine.setWantClientAuth(true);
|
179
211
|
}
|
@@ -240,14 +272,21 @@ public class MiniSSL extends RubyObject {
|
|
240
272
|
// need to wait for more data to come in before we retry
|
241
273
|
retryOp = false;
|
242
274
|
break;
|
275
|
+
case CLOSED:
|
276
|
+
closed = true;
|
277
|
+
retryOp = false;
|
278
|
+
break;
|
243
279
|
default:
|
244
|
-
// other
|
280
|
+
// other case is OK. We're done here.
|
245
281
|
retryOp = false;
|
246
282
|
}
|
283
|
+
if (res.getHandshakeStatus() == HandshakeStatus.FINISHED) {
|
284
|
+
handshake = true;
|
285
|
+
}
|
247
286
|
}
|
248
287
|
|
249
288
|
// after each op, run any delegated tasks if needed
|
250
|
-
if(
|
289
|
+
if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
|
251
290
|
Runnable runnable;
|
252
291
|
while ((runnable = engine.getDelegatedTask()) != null) {
|
253
292
|
runnable.run();
|
@@ -271,13 +310,14 @@ public class MiniSSL extends RubyObject {
|
|
271
310
|
|
272
311
|
HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
|
273
312
|
boolean done = false;
|
313
|
+
SSLEngineResult res = null;
|
274
314
|
while (!done) {
|
275
315
|
switch (handshakeStatus) {
|
276
316
|
case NEED_WRAP:
|
277
|
-
doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
|
317
|
+
res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
|
278
318
|
break;
|
279
319
|
case NEED_UNWRAP:
|
280
|
-
|
320
|
+
res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
|
281
321
|
if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
|
282
322
|
// need more data before we can shake more hands
|
283
323
|
done = true;
|
@@ -286,7 +326,9 @@ public class MiniSSL extends RubyObject {
|
|
286
326
|
default:
|
287
327
|
done = true;
|
288
328
|
}
|
289
|
-
|
329
|
+
if (!done) {
|
330
|
+
handshakeStatus = res.getHandshakeStatus();
|
331
|
+
}
|
290
332
|
}
|
291
333
|
|
292
334
|
if (inboundNetData.hasRemaining()) {
|
@@ -360,4 +402,21 @@ public class MiniSSL extends RubyObject {
|
|
360
402
|
return getRuntime().getNil();
|
361
403
|
}
|
362
404
|
}
|
405
|
+
|
406
|
+
@JRubyMethod(name = "init?")
|
407
|
+
public IRubyObject isInit(ThreadContext context) {
|
408
|
+
return handshake ? getRuntime().getFalse() : getRuntime().getTrue();
|
409
|
+
}
|
410
|
+
|
411
|
+
@JRubyMethod
|
412
|
+
public IRubyObject shutdown() {
|
413
|
+
if (closed || engine.isInboundDone() && engine.isOutboundDone()) {
|
414
|
+
if (engine.isOutboundDone()) {
|
415
|
+
engine.closeOutbound();
|
416
|
+
}
|
417
|
+
return getRuntime().getTrue();
|
418
|
+
} else {
|
419
|
+
return getRuntime().getFalse();
|
420
|
+
}
|
421
|
+
}
|
363
422
|
}
|