puma 4.3.6 → 5.6.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1486 -518
  3. data/LICENSE +23 -20
  4. data/README.md +120 -36
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +63 -26
  7. data/docs/compile_options.md +21 -0
  8. data/docs/deployment.md +60 -69
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +9 -0
  14. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  15. data/{tools → docs}/jungle/rc.d/puma +2 -2
  16. data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
  17. data/docs/kubernetes.md +66 -0
  18. data/docs/nginx.md +1 -1
  19. data/docs/plugins.md +15 -15
  20. data/docs/rails_dev_mode.md +28 -0
  21. data/docs/restart.md +46 -23
  22. data/docs/signals.md +13 -11
  23. data/docs/stats.md +142 -0
  24. data/docs/systemd.md +85 -128
  25. data/ext/puma_http11/PumaHttp11Service.java +2 -4
  26. data/ext/puma_http11/ext_help.h +1 -1
  27. data/ext/puma_http11/extconf.rb +46 -9
  28. data/ext/puma_http11/http11_parser.c +68 -57
  29. data/ext/puma_http11/http11_parser.h +1 -1
  30. data/ext/puma_http11/http11_parser.java.rl +1 -1
  31. data/ext/puma_http11/http11_parser.rl +1 -1
  32. data/ext/puma_http11/http11_parser_common.rl +1 -1
  33. data/ext/puma_http11/mini_ssl.c +275 -122
  34. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  35. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  36. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +51 -51
  37. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +105 -61
  38. data/ext/puma_http11/puma_http11.c +32 -51
  39. data/lib/puma/app/status.rb +47 -36
  40. data/lib/puma/binder.rb +225 -106
  41. data/lib/puma/cli.rb +24 -18
  42. data/lib/puma/client.rb +174 -91
  43. data/lib/puma/cluster/worker.rb +173 -0
  44. data/lib/puma/cluster/worker_handle.rb +94 -0
  45. data/lib/puma/cluster.rb +212 -220
  46. data/lib/puma/commonlogger.rb +2 -2
  47. data/lib/puma/configuration.rb +58 -49
  48. data/lib/puma/const.rb +18 -9
  49. data/lib/puma/control_cli.rb +93 -76
  50. data/lib/puma/detect.rb +29 -2
  51. data/lib/puma/dsl.rb +364 -96
  52. data/lib/puma/error_logger.rb +104 -0
  53. data/lib/puma/events.rb +55 -34
  54. data/lib/puma/io_buffer.rb +9 -2
  55. data/lib/puma/jruby_restart.rb +0 -58
  56. data/lib/puma/json_serialization.rb +96 -0
  57. data/lib/puma/launcher.rb +117 -46
  58. data/lib/puma/minissl/context_builder.rb +14 -9
  59. data/lib/puma/minissl.rb +128 -46
  60. data/lib/puma/null_io.rb +13 -1
  61. data/lib/puma/plugin/tmp_restart.rb +0 -0
  62. data/lib/puma/plugin.rb +3 -12
  63. data/lib/puma/queue_close.rb +26 -0
  64. data/lib/puma/rack/builder.rb +1 -5
  65. data/lib/puma/rack/urlmap.rb +0 -0
  66. data/lib/puma/rack_default.rb +0 -0
  67. data/lib/puma/reactor.rb +85 -369
  68. data/lib/puma/request.rb +472 -0
  69. data/lib/puma/runner.rb +46 -61
  70. data/lib/puma/server.rb +287 -743
  71. data/lib/puma/single.rb +9 -65
  72. data/lib/puma/state_file.rb +47 -8
  73. data/lib/puma/systemd.rb +46 -0
  74. data/lib/puma/thread_pool.rb +125 -57
  75. data/lib/puma/util.rb +20 -1
  76. data/lib/puma.rb +46 -0
  77. data/lib/rack/handler/puma.rb +2 -3
  78. data/tools/{docker/Dockerfile → Dockerfile} +1 -1
  79. data/tools/trickletest.rb +0 -0
  80. metadata +28 -24
  81. data/docs/tcp_mode.md +0 -96
  82. data/ext/puma_http11/io_buffer.c +0 -155
  83. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
  84. data/lib/puma/accept_nonblock.rb +0 -29
  85. data/lib/puma/tcp_logger.rb +0 -41
  86. data/tools/jungle/README.md +0 -19
  87. data/tools/jungle/init.d/README.md +0 -61
  88. data/tools/jungle/init.d/puma +0 -421
  89. data/tools/jungle/init.d/run-puma +0 -18
  90. data/tools/jungle/upstart/README.md +0 -61
  91. data/tools/jungle/upstart/puma-manager.conf +0 -31
  92. data/tools/jungle/upstart/puma.conf +0 -69
@@ -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
 
@@ -182,8 +184,6 @@ static final int puma_parser_start = 1;
182
184
  static final int puma_parser_first_final = 46;
183
185
  static final int puma_parser_error = 0;
184
186
 
185
- static final int puma_parser_en_main = 1;
186
-
187
187
 
188
188
  // line 62 "ext/puma_http11/http11_parser.java.rl"
189
189
 
@@ -212,12 +212,12 @@ static final int puma_parser_en_main = 1;
212
212
  cs = 0;
213
213
 
214
214
 
215
- // line 218 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
215
+ // line 216 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
216
216
  {
217
217
  cs = puma_parser_start;
218
218
  }
219
219
 
220
- // line 90 "ext/puma_http11/http11_parser.java.rl"
220
+ // line 88 "ext/puma_http11/http11_parser.java.rl"
221
221
 
222
222
  body_start = 0;
223
223
  content_len = 0;
@@ -244,7 +244,7 @@ static final int puma_parser_en_main = 1;
244
244
  parser.buffer = buffer;
245
245
 
246
246
 
247
- // line 250 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
247
+ // line 248 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
248
248
  {
249
249
  int _klen;
250
250
  int _trans = 0;
@@ -400,7 +400,7 @@ case 1:
400
400
  { p += 1; _goto_targ = 5; if (true) continue _goto;}
401
401
  }
402
402
  break;
403
- // line 406 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
403
+ // line 404 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
404
404
  }
405
405
  }
406
406
  }
@@ -420,7 +420,7 @@ case 5:
420
420
  break; }
421
421
  }
422
422
 
423
- // line 116 "ext/puma_http11/http11_parser.java.rl"
423
+ // line 114 "ext/puma_http11/http11_parser.java.rl"
424
424
 
425
425
  parser.cs = cs;
426
426
  parser.nread += (p - off);
@@ -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;
@@ -22,6 +23,7 @@ import javax.net.ssl.SSLException;
22
23
  import javax.net.ssl.SSLPeerUnverifiedException;
23
24
  import javax.net.ssl.SSLSession;
24
25
  import java.io.FileInputStream;
26
+ import java.io.InputStream;
25
27
  import java.io.IOException;
26
28
  import java.nio.Buffer;
27
29
  import java.nio.ByteBuffer;
@@ -32,6 +34,8 @@ import java.security.NoSuchAlgorithmException;
32
34
  import java.security.UnrecoverableKeyException;
33
35
  import java.security.cert.CertificateEncodingException;
34
36
  import java.security.cert.CertificateException;
37
+ import java.util.concurrent.ConcurrentHashMap;
38
+ import java.util.Map;
35
39
 
36
40
  import static javax.net.ssl.SSLEngineResult.Status;
37
41
  import static javax.net.ssl.SSLEngineResult.HandshakeStatus;
@@ -77,11 +81,11 @@ public class MiniSSL extends RubyObject {
77
81
  /**
78
82
  * Writes bytes to the buffer after ensuring there's room
79
83
  */
80
- public void put(byte[] bytes) {
81
- if (buffer.remaining() < bytes.length) {
82
- 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);
83
87
  }
84
- buffer.put(bytes);
88
+ buffer.put(bytes, offset, length);
85
89
  }
86
90
 
87
91
  /**
@@ -112,7 +116,7 @@ public class MiniSSL extends RubyObject {
112
116
 
113
117
  buffer.get(bss);
114
118
  buffer.clear();
115
- return new ByteList(bss);
119
+ return new ByteList(bss, false);
116
120
  }
117
121
 
118
122
  @Override
@@ -120,6 +124,8 @@ public class MiniSSL extends RubyObject {
120
124
  }
121
125
 
122
126
  private SSLEngine engine;
127
+ private boolean closed;
128
+ private boolean handshake;
123
129
  private MiniSSLBuffer inboundNetData;
124
130
  private MiniSSLBuffer outboundAppData;
125
131
  private MiniSSLBuffer outboundNetData;
@@ -128,10 +134,39 @@ public class MiniSSL extends RubyObject {
128
134
  super(runtime, klass);
129
135
  }
130
136
 
137
+ private static Map<String, KeyManagerFactory> keyManagerFactoryMap = new ConcurrentHashMap<String, KeyManagerFactory>();
138
+ private static Map<String, TrustManagerFactory> trustManagerFactoryMap = new ConcurrentHashMap<String, TrustManagerFactory>();
139
+
131
140
  @JRubyMethod(meta = true)
132
- public static IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext) {
133
- RubyClass klass = (RubyClass) recv;
141
+ public static synchronized IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext)
142
+ throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
143
+ // Create the KeyManagerFactory and TrustManagerFactory for this server
144
+ String keystoreFile = miniSSLContext.callMethod(context, "keystore").convertToString().asJavaString();
145
+ char[] password = miniSSLContext.callMethod(context, "keystore_pass").convertToString().asJavaString().toCharArray();
146
+
147
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
148
+ InputStream is = new FileInputStream(keystoreFile);
149
+ try {
150
+ ks.load(is, password);
151
+ } finally {
152
+ is.close();
153
+ }
154
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
155
+ kmf.init(ks, password);
156
+ keyManagerFactoryMap.put(keystoreFile, kmf);
157
+
158
+ KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
159
+ is = new FileInputStream(keystoreFile);
160
+ try {
161
+ ts.load(is, password);
162
+ } finally {
163
+ is.close();
164
+ }
165
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
166
+ tmf.init(ts);
167
+ trustManagerFactoryMap.put(keystoreFile, tmf);
134
168
 
169
+ RubyClass klass = (RubyClass) recv;
135
170
  return klass.newInstance(context,
136
171
  new IRubyObject[] { miniSSLContext },
137
172
  Block.NULL_BLOCK);
@@ -139,24 +174,20 @@ public class MiniSSL extends RubyObject {
139
174
 
140
175
  @JRubyMethod
141
176
  public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
142
- throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
143
- KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
144
- KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
177
+ throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
145
178
 
146
- char[] password = miniSSLContext.callMethod(threadContext, "keystore_pass").convertToString().asJavaString().toCharArray();
147
179
  String keystoreFile = miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString();
148
- ks.load(new FileInputStream(keystoreFile), password);
149
- ts.load(new FileInputStream(keystoreFile), password);
150
-
151
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
152
- kmf.init(ks, password);
153
-
154
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
155
- tmf.init(ts);
180
+ KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
181
+ TrustManagerFactory tmf = trustManagerFactoryMap.get(keystoreFile);
182
+ if(kmf == null || tmf == null) {
183
+ throw new KeyStoreException("Could not find KeyManagerFactory/TrustManagerFactory for keystore: " + keystoreFile);
184
+ }
156
185
 
157
186
  SSLContext sslCtx = SSLContext.getInstance("TLS");
158
187
 
159
188
  sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
189
+ closed = false;
190
+ handshake = false;
160
191
  engine = sslCtx.createSSLEngine();
161
192
 
162
193
  String[] protocols;
@@ -173,7 +204,7 @@ public class MiniSSL extends RubyObject {
173
204
  engine.setEnabledProtocols(protocols);
174
205
  engine.setUseClientMode(false);
175
206
 
176
- long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger().getLongValue();
207
+ long verify_mode = miniSSLContext.callMethod(threadContext, "verify_mode").convertToInteger("to_i").getLongValue();
177
208
  if ((verify_mode & 0x1) != 0) { // 'peer'
178
209
  engine.setWantClientAuth(true);
179
210
  }
@@ -198,14 +229,9 @@ public class MiniSSL extends RubyObject {
198
229
 
199
230
  @JRubyMethod
200
231
  public IRubyObject inject(IRubyObject arg) {
201
- try {
202
- byte[] bytes = arg.convertToString().getBytes();
203
- inboundNetData.put(bytes);
204
- return this;
205
- } catch (Exception e) {
206
- e.printStackTrace();
207
- throw new RuntimeException(e);
208
- }
232
+ ByteList bytes = arg.convertToString().getByteList();
233
+ inboundNetData.put(bytes.unsafeBytes(), bytes.getBegin(), bytes.getRealSize());
234
+ return this;
209
235
  }
210
236
 
211
237
  private enum SSLOperation {
@@ -240,14 +266,21 @@ public class MiniSSL extends RubyObject {
240
266
  // need to wait for more data to come in before we retry
241
267
  retryOp = false;
242
268
  break;
269
+ case CLOSED:
270
+ closed = true;
271
+ retryOp = false;
272
+ break;
243
273
  default:
244
- // other cases are OK and CLOSED. We're done here.
274
+ // other case is OK. We're done here.
245
275
  retryOp = false;
246
276
  }
277
+ if (res.getHandshakeStatus() == HandshakeStatus.FINISHED) {
278
+ handshake = true;
279
+ }
247
280
  }
248
281
 
249
282
  // after each op, run any delegated tasks if needed
250
- if(engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
283
+ if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
251
284
  Runnable runnable;
252
285
  while ((runnable = engine.getDelegatedTask()) != null) {
253
286
  runnable.run();
@@ -258,7 +291,7 @@ public class MiniSSL extends RubyObject {
258
291
  }
259
292
 
260
293
  @JRubyMethod
261
- public IRubyObject read() throws Exception {
294
+ public IRubyObject read() {
262
295
  try {
263
296
  inboundNetData.flip();
264
297
 
@@ -271,13 +304,14 @@ public class MiniSSL extends RubyObject {
271
304
 
272
305
  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
273
306
  boolean done = false;
307
+ SSLEngineResult res = null;
274
308
  while (!done) {
275
309
  switch (handshakeStatus) {
276
310
  case NEED_WRAP:
277
- doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
311
+ res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
278
312
  break;
279
313
  case NEED_UNWRAP:
280
- SSLEngineResult res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
314
+ res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
281
315
  if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
282
316
  // need more data before we can shake more hands
283
317
  done = true;
@@ -286,7 +320,9 @@ public class MiniSSL extends RubyObject {
286
320
  default:
287
321
  done = true;
288
322
  }
289
- handshakeStatus = engine.getHandshakeStatus();
323
+ if (!done) {
324
+ handshakeStatus = res.getHandshakeStatus();
325
+ }
290
326
  }
291
327
 
292
328
  if (inboundNetData.hasRemaining()) {
@@ -300,55 +336,46 @@ public class MiniSSL extends RubyObject {
300
336
  return getRuntime().getNil();
301
337
  }
302
338
 
303
- RubyString str = getRuntime().newString("");
304
- str.setValue(appDataByteList);
305
- return str;
306
- } catch (Exception e) {
307
- throw getRuntime().newEOFError(e.getMessage());
339
+ return RubyString.newString(getRuntime(), appDataByteList);
340
+ } catch (SSLException e) {
341
+ RaiseException re = getRuntime().newEOFError(e.getMessage());
342
+ re.initCause(e);
343
+ throw re;
308
344
  }
309
345
  }
310
346
 
311
347
  @JRubyMethod
312
348
  public IRubyObject write(IRubyObject arg) {
313
- try {
314
- byte[] bls = arg.convertToString().getBytes();
315
- outboundAppData = new MiniSSLBuffer(bls);
349
+ byte[] bls = arg.convertToString().getBytes();
350
+ outboundAppData = new MiniSSLBuffer(bls);
316
351
 
317
- return getRuntime().newFixnum(bls.length);
318
- } catch (Exception e) {
319
- e.printStackTrace();
320
- throw new RuntimeException(e);
321
- }
352
+ return getRuntime().newFixnum(bls.length);
322
353
  }
323
354
 
324
355
  @JRubyMethod
325
- public IRubyObject extract() throws SSLException {
356
+ public IRubyObject extract(ThreadContext context) {
326
357
  try {
327
358
  ByteList dataByteList = outboundNetData.asByteList();
328
359
  if (dataByteList != null) {
329
- RubyString str = getRuntime().newString("");
330
- str.setValue(dataByteList);
331
- return str;
360
+ return RubyString.newString(context.runtime, dataByteList);
332
361
  }
333
362
 
334
363
  if (!outboundAppData.hasRemaining()) {
335
- return getRuntime().getNil();
364
+ return context.nil;
336
365
  }
337
366
 
338
367
  outboundNetData.clear();
339
368
  doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
340
369
  dataByteList = outboundNetData.asByteList();
341
370
  if (dataByteList == null) {
342
- return getRuntime().getNil();
371
+ return context.nil;
343
372
  }
344
373
 
345
- RubyString str = getRuntime().newString("");
346
- str.setValue(dataByteList);
347
-
348
- return str;
349
- } catch (Exception e) {
350
- e.printStackTrace();
351
- throw new RuntimeException(e);
374
+ return RubyString.newString(context.runtime, dataByteList);
375
+ } catch (SSLException e) {
376
+ RaiseException ex = context.runtime.newRuntimeError(e.toString());
377
+ ex.initCause(e);
378
+ throw ex;
352
379
  }
353
380
  }
354
381
 
@@ -356,8 +383,25 @@ public class MiniSSL extends RubyObject {
356
383
  public IRubyObject peercert() throws CertificateEncodingException {
357
384
  try {
358
385
  return JavaEmbedUtils.javaToRuby(getRuntime(), engine.getSession().getPeerCertificates()[0].getEncoded());
359
- } catch (SSLPeerUnverifiedException ex) {
386
+ } catch (SSLPeerUnverifiedException e) {
360
387
  return getRuntime().getNil();
361
388
  }
362
389
  }
390
+
391
+ @JRubyMethod(name = "init?")
392
+ public IRubyObject isInit(ThreadContext context) {
393
+ return handshake ? getRuntime().getFalse() : getRuntime().getTrue();
394
+ }
395
+
396
+ @JRubyMethod
397
+ public IRubyObject shutdown() {
398
+ if (closed || engine.isInboundDone() && engine.isOutboundDone()) {
399
+ if (engine.isOutboundDone()) {
400
+ engine.closeOutbound();
401
+ }
402
+ return getRuntime().getTrue();
403
+ } else {
404
+ return getRuntime().getFalse();
405
+ }
406
+ }
363
407
  }