puma 3.12.0 → 5.3.1

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