puma 1.6.3 → 2.0.0.b1

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.

@@ -1,3 +1,16 @@
1
+ === 2.0.0.b1 / 2012-09-11
2
+
3
+ * 1 major feature:
4
+ * Optional worker process mode (-w) to allow for process scaling in
5
+ addition to thread scaling
6
+
7
+ * 1 bug fix:
8
+ * Introduce Puma::MiniSSL to be able to properly control doing
9
+ nonblocking SSL
10
+
11
+ NOTE: SSL support in JRuby is not supported at present. Support will
12
+ be added back in a future date when a java Puma::MiniSSL is added.
13
+
1
14
  === 1.6.3 / 2012-09-04
2
15
 
3
16
  * 1 bug fix:
@@ -9,6 +9,8 @@ Rakefile
9
9
  TODO
10
10
  bin/puma
11
11
  bin/pumactl
12
+ docs/config.md
13
+ docs/nginx.md
12
14
  examples/CA/cacert.pem
13
15
  examples/CA/newcerts/cert_1.pem
14
16
  examples/CA/newcerts/cert_2.pem
@@ -17,6 +19,7 @@ examples/CA/serial
17
19
  examples/config.rb
18
20
  examples/puma/cert_puma.pem
19
21
  examples/puma/csr_puma.pem
22
+ examples/puma/keystore.jks
20
23
  examples/puma/puma_keypair.pem
21
24
  examples/qc_config.rb
22
25
  ext/puma_http11/PumaHttp11Service.java
@@ -27,21 +30,32 @@ ext/puma_http11/http11_parser.h
27
30
  ext/puma_http11/http11_parser.java.rl
28
31
  ext/puma_http11/http11_parser.rl
29
32
  ext/puma_http11/http11_parser_common.rl
33
+ ext/puma_http11/io_buffer.c
34
+ ext/puma_http11/mini_ssl.c
30
35
  ext/puma_http11/org/jruby/puma/Http11.java
31
36
  ext/puma_http11/org/jruby/puma/Http11Parser.java
37
+ ext/puma_http11/org/jruby/puma/MiniSSL.java
32
38
  ext/puma_http11/puma_http11.c
33
39
  lib/puma.rb
40
+ lib/puma/accept_nonblock.rb
34
41
  lib/puma/app/status.rb
42
+ lib/puma/binder.rb
35
43
  lib/puma/cli.rb
36
44
  lib/puma/client.rb
37
45
  lib/puma/compat.rb
38
46
  lib/puma/configuration.rb
39
47
  lib/puma/const.rb
40
48
  lib/puma/control_cli.rb
49
+ lib/puma/delegation.rb
41
50
  lib/puma/detect.rb
42
51
  lib/puma/events.rb
52
+ lib/puma/io_buffer.rb
53
+ lib/puma/java_io_buffer.rb
43
54
  lib/puma/jruby_restart.rb
55
+ lib/puma/minissl.rb
44
56
  lib/puma/null_io.rb
57
+ lib/puma/puma_http11.bundle
58
+ lib/puma/puma_http11.jar
45
59
  lib/puma/rack_patch.rb
46
60
  lib/puma/reactor.rb
47
61
  lib/puma/server.rb
@@ -61,6 +75,7 @@ test/test_config.rb
61
75
  test/test_http10.rb
62
76
  test/test_http11.rb
63
77
  test/test_integration.rb
78
+ test/test_iobuffer.rb
64
79
  test/test_null_io.rb
65
80
  test/test_persistent.rb
66
81
  test/test_puma_server.rb
@@ -70,4 +85,7 @@ test/test_thread_pool.rb
70
85
  test/test_unix_socket.rb
71
86
  test/test_ws.rb
72
87
  test/testhelp.rb
88
+ tools/jungle/README.md
89
+ tools/jungle/puma
90
+ tools/jungle/run-puma
73
91
  tools/trickletest.rb
data/Rakefile CHANGED
@@ -60,6 +60,8 @@ file 'ext/puma_http11/org/jruby/puma/Http11Parser.java' => ['ext/puma_http11/htt
60
60
  end
61
61
  task :ragel => ['ext/puma_http11/org/jruby/puma/Http11Parser.java']
62
62
 
63
+ if !IS_JRUBY
64
+
63
65
  # compile extensions using rake-compiler
64
66
  # C (MRI, Rubinius)
65
67
  Rake::ExtensionTask.new("puma_http11", HOE.spec) do |ext|
@@ -77,11 +79,15 @@ Rake::ExtensionTask.new("puma_http11", HOE.spec) do |ext|
77
79
  CLEAN.include "lib/puma/puma_http11.rb"
78
80
  end
79
81
 
82
+ else
83
+
80
84
  # Java (JRuby)
81
85
  Rake::JavaExtensionTask.new("puma_http11", HOE.spec) do |ext|
82
86
  ext.lib_dir = "lib/puma"
83
87
  end
84
88
 
89
+ end
90
+
85
91
  # the following is a fat-binary stub that will be used when
86
92
  # require 'puma/puma_http11' and will use either 1.8 or 1.9 version depending
87
93
  # on RUBY_VERSION
File without changes
@@ -0,0 +1,85 @@
1
+ # Nginx configuration example file
2
+
3
+ This is a very common setup using an upstream. It was adapted from some Capistrano recipe I found on the Internet a while ago.
4
+
5
+ ```
6
+ upstream myapp {
7
+ server unix:///myapp/tmp/puma.sock;
8
+ }
9
+
10
+ server {
11
+ listen 80;
12
+ server_name myapp.com;
13
+
14
+ # ~2 seconds is often enough for most folks to parse HTML/CSS and
15
+ # retrieve needed images/icons/frames, connections are cheap in
16
+ # nginx so increasing this is generally safe...
17
+ keepalive_timeout 5;
18
+
19
+ # path for static files
20
+ root /myapp/public;
21
+ access_log /myapp/log/nginx.access.log;
22
+ error_log /myapp/log/nginx.error.log info;
23
+
24
+ # this rewrites all the requests to the maintenance.html
25
+ # page if it exists in the doc root. This is for capistrano's
26
+ # disable web task
27
+ if (-f $document_root/maintenance.html) {
28
+ rewrite ^(.*)$ /maintenance.html last;
29
+ break;
30
+ }
31
+
32
+ location / {
33
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
34
+ proxy_set_header Host $http_host;
35
+
36
+ # If the file exists as a static file serve it directly without
37
+ # running all the other rewite tests on it
38
+ if (-f $request_filename) {
39
+ break;
40
+ }
41
+
42
+ # check for index.html for directory index
43
+ # if its there on the filesystem then rewite
44
+ # the url to add /index.html to the end of it
45
+ # and then break to send it to the next config rules.
46
+ if (-f $request_filename/index.html) {
47
+ rewrite (.*) $1/index.html break;
48
+ }
49
+
50
+ # this is the meat of the rack page caching config
51
+ # it adds .html to the end of the url and then checks
52
+ # the filesystem for that file. If it exists, then we
53
+ # rewite the url to have explicit .html on the end
54
+ # and then send it on its way to the next config rule.
55
+ # if there is no file on the fs then it sets all the
56
+ # necessary headers and proxies to our upstream mongrels
57
+ if (-f $request_filename.html) {
58
+ rewrite (.*) $1.html break;
59
+ }
60
+
61
+ if (!-f $request_filename) {
62
+ proxy_pass http://myapp;
63
+ break;
64
+ }
65
+ }
66
+
67
+ # Now this supposedly should work as it gets the filenames with querystrings that Rails provides.
68
+ # BUT there's a chance it could break the ajax calls.
69
+ location ~* \.(ico|css|gif|jpe?g|png)(\?[0-9]+)?$ {
70
+ expires max;
71
+ break;
72
+ }
73
+
74
+ location ~ ^/javascripts/.*\.js(\?[0-9]+)?$ {
75
+ expires max;
76
+ break;
77
+ }
78
+
79
+ # Error pages
80
+ # error_page 500 502 503 504 /500.html;
81
+ location = /500.html {
82
+ root /myapp/current/public;
83
+ }
84
+ }
85
+ ```
@@ -6,10 +6,12 @@ import org.jruby.Ruby;
6
6
  import org.jruby.runtime.load.BasicLibraryService;
7
7
 
8
8
  import org.jruby.puma.Http11;
9
+ import org.jruby.puma.MiniSSL;
9
10
 
10
11
  public class PumaHttp11Service implements BasicLibraryService {
11
12
  public boolean basicLoad(final Ruby runtime) throws IOException {
12
13
  Http11.createHttp11(runtime);
14
+ MiniSSL.createMiniSSL(runtime);
13
15
  return true;
14
16
  }
15
17
  }
@@ -2,4 +2,7 @@ require 'mkmf'
2
2
 
3
3
  dir_config("puma_http11")
4
4
 
5
+ $defs.push "-Wno-deprecated-declarations"
6
+ $libs += " -lssl -lcrypto "
7
+
5
8
  create_makefile("puma/puma_http11")
@@ -0,0 +1,146 @@
1
+ #include "ruby.h"
2
+
3
+ #include <sys/types.h>
4
+
5
+ struct buf_int {
6
+ uint8_t* top;
7
+ uint8_t* cur;
8
+
9
+ size_t size;
10
+ };
11
+
12
+ #define BUF_DEFAULT_SIZE 4096
13
+ #define BUF_TOLERANCE 32
14
+
15
+ static void buf_free(struct buf_int* internal) {
16
+ free(internal->top);
17
+ free(internal);
18
+ }
19
+
20
+ static VALUE buf_alloc(VALUE self) {
21
+ VALUE buf;
22
+ struct buf_int* internal;
23
+
24
+ buf = Data_Make_Struct(self, struct buf_int, 0, buf_free, internal);
25
+
26
+ internal->size = BUF_DEFAULT_SIZE;
27
+ internal->top = malloc(BUF_DEFAULT_SIZE);
28
+ internal->cur = internal->top;
29
+
30
+ return buf;
31
+ }
32
+
33
+ static VALUE buf_append(VALUE self, VALUE str) {
34
+ struct buf_int* b;
35
+ size_t used, str_len, new_size;
36
+
37
+ Data_Get_Struct(self, struct buf_int, b);
38
+
39
+ used = b->cur - b->top;
40
+
41
+ StringValue(str);
42
+ str_len = RSTRING_LEN(str);
43
+
44
+ new_size = used + str_len;
45
+
46
+ if(new_size > b->size) {
47
+ size_t n = b->size + (b->size / 2);
48
+ uint8_t* top;
49
+
50
+ new_size = (n > new_size ? n : new_size + BUF_TOLERANCE);
51
+
52
+ top = malloc(new_size);
53
+ memcpy(top, b->top, used);
54
+ b->top = top;
55
+ b->cur = top + used;
56
+ b->size = new_size;
57
+ }
58
+
59
+ memcpy(b->cur, RSTRING_PTR(str), str_len);
60
+ b->cur += str_len;
61
+
62
+ return self;
63
+ }
64
+
65
+ static VALUE buf_append2(int argc, VALUE* argv, VALUE self) {
66
+ struct buf_int* b;
67
+ size_t used, new_size;
68
+ int i;
69
+ VALUE str;
70
+
71
+ Data_Get_Struct(self, struct buf_int, b);
72
+
73
+ used = b->cur - b->top;
74
+ new_size = used;
75
+
76
+ for(i = 0; i < argc; i++) {
77
+ StringValue(argv[i]);
78
+
79
+ str = argv[i];
80
+
81
+ new_size += RSTRING_LEN(str);
82
+ }
83
+
84
+ if(new_size > b->size) {
85
+ size_t n = b->size + (b->size / 2);
86
+ uint8_t* top;
87
+
88
+ new_size = (n > new_size ? n : new_size + BUF_TOLERANCE);
89
+
90
+ top = malloc(new_size);
91
+ memcpy(top, b->top, used);
92
+ b->top = top;
93
+ b->cur = top + used;
94
+ b->size = new_size;
95
+ }
96
+
97
+ for(i = 0; i < argc; i++) {
98
+ long str_len;
99
+ str = argv[i];
100
+ str_len = RSTRING_LEN(str);
101
+ memcpy(b->cur, RSTRING_PTR(str), str_len);
102
+ b->cur += str_len;
103
+ }
104
+ }
105
+
106
+ static VALUE buf_to_str(VALUE self) {
107
+ struct buf_int* b;
108
+ Data_Get_Struct(self, struct buf_int, b);
109
+
110
+ return rb_str_new(b->top, b->cur - b->top);
111
+ }
112
+
113
+ static VALUE buf_used(VALUE self) {
114
+ struct buf_int* b;
115
+ Data_Get_Struct(self, struct buf_int, b);
116
+
117
+ return INT2FIX(b->cur - b->top);
118
+ }
119
+
120
+ static VALUE buf_capa(VALUE self) {
121
+ struct buf_int* b;
122
+ Data_Get_Struct(self, struct buf_int, b);
123
+
124
+ return INT2FIX(b->size);
125
+ }
126
+
127
+ static VALUE buf_reset(VALUE self) {
128
+ struct buf_int* b;
129
+ Data_Get_Struct(self, struct buf_int, b);
130
+
131
+ b->cur = b->top;
132
+ return self;
133
+ }
134
+
135
+ void Init_io_buffer(VALUE puma) {
136
+ VALUE buf = rb_define_class_under(puma, "IOBuffer", rb_cObject);
137
+
138
+ rb_define_alloc_func(buf, buf_alloc);
139
+ rb_define_method(buf, "<<", buf_append, 1);
140
+ rb_define_method(buf, "append", buf_append2, -1);
141
+ rb_define_method(buf, "to_str", buf_to_str, 0);
142
+ rb_define_method(buf, "to_s", buf_to_str, 0);
143
+ rb_define_method(buf, "used", buf_used, 0);
144
+ rb_define_method(buf, "capacity", buf_capa, 0);
145
+ rb_define_method(buf, "reset", buf_reset, 0);
146
+ }
@@ -0,0 +1,189 @@
1
+ #include <ruby.h>
2
+ #include <rubyio.h>
3
+ #include <openssl/bio.h>
4
+ #include <openssl/ssl.h>
5
+ #include <openssl/err.h>
6
+
7
+ typedef struct {
8
+ BIO* read;
9
+ BIO* write;
10
+ SSL* ssl;
11
+ SSL_CTX* ctx;
12
+ } ms_conn;
13
+
14
+ void engine_free(ms_conn* conn) {
15
+ BIO_free(conn->read);
16
+ BIO_free(conn->write);
17
+
18
+ free(conn);
19
+ }
20
+
21
+ ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
22
+ ms_conn* conn;
23
+
24
+ *obj = Data_Make_Struct(klass, ms_conn, 0, engine_free, conn);
25
+
26
+ conn->read = BIO_new(BIO_s_mem());
27
+ BIO_set_nbio(conn->read, 1);
28
+
29
+ conn->write = BIO_new(BIO_s_mem());
30
+ BIO_set_nbio(conn->write, 1);
31
+
32
+ conn->ssl = 0;
33
+ conn->ctx = 0;
34
+
35
+ return conn;
36
+ }
37
+
38
+ VALUE engine_init_server(VALUE self, VALUE key, VALUE cert) {
39
+ VALUE obj;
40
+ ms_conn* conn = engine_alloc(self, &obj);
41
+
42
+ StringValue(key);
43
+ StringValue(cert);
44
+
45
+ SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
46
+ conn->ctx = ctx;
47
+
48
+ SSL_CTX_use_certificate_file(ctx, RSTRING_PTR(cert), SSL_FILETYPE_PEM);
49
+ SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
50
+ /* SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); */
51
+
52
+ SSL* ssl = SSL_new(ctx);
53
+ conn->ssl = ssl;
54
+
55
+ /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
56
+
57
+ SSL_set_bio(ssl, conn->read, conn->write);
58
+
59
+ SSL_set_accept_state(ssl);
60
+ return obj;
61
+ }
62
+
63
+ VALUE engine_init_client(VALUE klass) {
64
+ VALUE obj;
65
+ ms_conn* conn = engine_alloc(klass, &obj);
66
+
67
+ conn->ctx = SSL_CTX_new(DTLSv1_method());
68
+ conn->ssl = SSL_new(conn->ctx);
69
+ SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
70
+
71
+ SSL_set_bio(conn->ssl, conn->read, conn->write);
72
+
73
+ SSL_set_connect_state(conn->ssl);
74
+ return obj;
75
+ }
76
+
77
+ VALUE engine_inject(VALUE self, VALUE str) {
78
+ ms_conn* conn;
79
+ long used;
80
+
81
+ Data_Get_Struct(self, ms_conn, conn);
82
+
83
+ StringValue(str);
84
+
85
+ used = BIO_write(conn->read, RSTRING_PTR(str), RSTRING_LEN(str));
86
+
87
+ if(used == 0 || used == -1) {
88
+ return Qfalse;
89
+ }
90
+
91
+ return INT2FIX(used);
92
+ }
93
+
94
+ static VALUE eError;
95
+
96
+ void raise_error(SSL* ssl, int result) {
97
+ int error = SSL_get_error(ssl, result);
98
+ char* msg = ERR_error_string(error, NULL);
99
+
100
+ ERR_clear_error();
101
+ rb_raise(eError, "OpenSSL error: %s - %d", msg, error);
102
+ }
103
+
104
+ VALUE engine_read(VALUE self) {
105
+ ms_conn* conn;
106
+ char buf[512];
107
+ int bytes, n;
108
+
109
+ Data_Get_Struct(self, ms_conn, conn);
110
+
111
+ bytes = SSL_read(conn->ssl, (void*)buf, sizeof(buf));
112
+
113
+ if(bytes > 0) {
114
+ return rb_str_new(buf, bytes);
115
+ }
116
+
117
+ if(SSL_want_read(conn->ssl)) return Qnil;
118
+
119
+ if(SSL_get_error(conn->ssl, bytes) == SSL_ERROR_ZERO_RETURN) {
120
+ rb_eof_error();
121
+ }
122
+
123
+ raise_error(conn->ssl, bytes);
124
+
125
+ return Qnil;
126
+ }
127
+
128
+ VALUE engine_write(VALUE self, VALUE str) {
129
+ ms_conn* conn;
130
+ char buf[512];
131
+ int bytes;
132
+
133
+ Data_Get_Struct(self, ms_conn, conn);
134
+
135
+ StringValue(str);
136
+
137
+ bytes = SSL_write(conn->ssl, (void*)RSTRING_PTR(str), RSTRING_LEN(str));
138
+ if(bytes > 0) {
139
+ return INT2FIX(bytes);
140
+ }
141
+
142
+ if(SSL_want_write(conn->ssl)) return Qnil;
143
+
144
+ raise_error(conn->ssl, bytes);
145
+
146
+ return Qnil;
147
+ }
148
+
149
+ VALUE engine_extract(VALUE self) {
150
+ ms_conn* conn;
151
+ int bytes;
152
+ size_t pending;
153
+ char buf[512];
154
+
155
+ Data_Get_Struct(self, ms_conn, conn);
156
+
157
+ pending = BIO_pending(conn->write);
158
+ if(pending > 0) {
159
+ bytes = BIO_read(conn->write, buf, sizeof(buf));
160
+ if(bytes > 0) {
161
+ return rb_str_new(buf, bytes);
162
+ } else if(!BIO_should_retry(conn->write)) {
163
+ raise_error(conn->ssl, bytes);
164
+ }
165
+ }
166
+
167
+ return Qnil;
168
+ }
169
+
170
+ void Init_mini_ssl(VALUE puma) {
171
+ SSL_library_init();
172
+ OpenSSL_add_ssl_algorithms();
173
+ SSL_load_error_strings();
174
+ ERR_load_crypto_strings();
175
+
176
+ VALUE mod = rb_define_module_under(puma, "MiniSSL");
177
+ VALUE eng = rb_define_class_under(mod, "Engine", rb_cObject);
178
+
179
+ eError = rb_define_class_under(mod, "SSLError", rb_eStandardError);
180
+
181
+ rb_define_singleton_method(eng, "server", engine_init_server, 2);
182
+ rb_define_singleton_method(eng, "client", engine_init_client, 0);
183
+
184
+ rb_define_method(eng, "inject", engine_inject, 1);
185
+ rb_define_method(eng, "read", engine_read, 0);
186
+
187
+ rb_define_method(eng, "write", engine_write, 1);
188
+ rb_define_method(eng, "extract", engine_extract, 0);
189
+ }