puma 2.8.2-java → 2.9.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/DEPLOYMENT.md +2 -2
- data/History.txt +24 -0
- data/README.md +2 -2
- data/Rakefile +2 -2
- data/bin/pumactl +1 -1
- data/ext/puma_http11/mini_ssl.c +7 -4
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +284 -192
- data/lib/puma/binder.rb +23 -23
- data/lib/puma/cluster.rb +1 -1
- data/lib/puma/const.rb +2 -2
- data/lib/puma/minissl.rb +24 -20
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/server.rb +4 -4
- data/puma.gemspec +1 -1
- data/test/test_minissl.rb +18 -14
- data/test/test_puma_server.rb +0 -35
- data/test/test_puma_server_ssl.rb +91 -0
- metadata +19 -17
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 606df9e31f26a18cd3e3a1219615c9f6ac80b634
         | 
| 4 | 
            +
              data.tar.gz: 0c94555a3f56ed48cece59cadeb49539727f1483
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1f766ef76252ad9271a3523c04287cce012676173511c834b8f73cb8dce29ea07ad414cc48de219b6635123781d2a7a88a56caaaa1f20488709b99ea3685609e
         | 
| 7 | 
            +
              data.tar.gz: 3b7dd8bc4f8f8102b907009ce1a8dae858a770ddc1c99b584942bb6d63578a893bc6e1763216bcd3a0d9d2817ac435f37e9b00fad587b84fc0dbf403a5b604b7
         | 
    
        data/DEPLOYMENT.md
    CHANGED
    
    | @@ -42,7 +42,7 @@ Here are some rules of thumb: | |
| 42 42 |  | 
| 43 43 | 
             
            **How do you know if you're got enough (or too many workers)?**
         | 
| 44 44 |  | 
| 45 | 
            -
            A good question. Due to MRI's GIL, only one thread can be executing at a time.
         | 
| 45 | 
            +
            A good question. Due to MRI's GIL, only one thread can be executing Ruby code at a time.
         | 
| 46 46 | 
             
            But since so many apps are waiting on IO from DBs, etc., they can utilize threads
         | 
| 47 47 | 
             
            to make better use of the process.
         | 
| 48 48 |  | 
| @@ -56,7 +56,7 @@ you've got capacity still but aren't starving threads. | |
| 56 56 |  | 
| 57 57 | 
             
            ## Daemonizing
         | 
| 58 58 |  | 
| 59 | 
            -
            I prefer to not daemonize my servers and use something like `runit` or ` | 
| 59 | 
            +
            I prefer to not daemonize my servers and use something like `runit` or `upstart` to
         | 
| 60 60 | 
             
            monitor them as child processes. This gives them fast response to crashes and
         | 
| 61 61 | 
             
            makes it easy to figure out what is going on. Additionally, unlike `unicorn`,
         | 
| 62 62 | 
             
            puma does not require daemonization to do zero-downtime restarts.
         | 
    
        data/History.txt
    CHANGED
    
    | @@ -1,3 +1,27 @@ | |
| 1 | 
            +
            === 2.9.0 / 2014-07-12
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * 1 minor feature:
         | 
| 4 | 
            +
              * Add SSL support for JRuby
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            * 3 bug fixes:
         | 
| 7 | 
            +
              * Typo BUNDLER_GEMFILE -> BUNDLE_GEMFILE
         | 
| 8 | 
            +
              * Use fast_write because we can't trust syswrite
         | 
| 9 | 
            +
              * pumactl - do not modify original ARGV
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * 4 doc fixes:
         | 
| 12 | 
            +
              * BSD-3-Clause over BSD to avoid confusion
         | 
| 13 | 
            +
              * Deploy doc: clarification of the GIL
         | 
| 14 | 
            +
              * Fix typo in DEPLOYMENT.md
         | 
| 15 | 
            +
              * Update README.md
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * 6 PRs merged:
         | 
| 18 | 
            +
              * Merge pull request #520 from misfo/patch-2
         | 
| 19 | 
            +
              * Merge pull request #530 from looker/jruby-ssl
         | 
| 20 | 
            +
              * Merge pull request #537 from vlmonk/patch-1
         | 
| 21 | 
            +
              * Merge pull request #540 from allaire/patch-1
         | 
| 22 | 
            +
              * Merge pull request #544 from chulkilee/bsd-3-clause
         | 
| 23 | 
            +
              * Merge pull request #551 from jcxplorer/patch-1
         | 
| 24 | 
            +
             | 
| 1 25 | 
             
            === 2.8.2 / 2014-04-12
         | 
| 2 26 |  | 
| 3 27 | 
             
            * 4 bug fixes:
         | 
    
        data/README.md
    CHANGED
    
    | @@ -117,7 +117,7 @@ If you're preloading your application and using ActiveRecord, it's recommend you | |
| 117 117 | 
             
                  end
         | 
| 118 118 | 
             
                end
         | 
| 119 119 |  | 
| 120 | 
            -
            When you use preload_app, your new code goes all in the master process, and is then copied in the workers (meaning it’s only compatible with cluster mode). General rule is to use preload_app when your workers die often and need fast starts. If you don’t have many workers, you should  | 
| 120 | 
            +
            When you use preload_app, your new code goes all in the master process, and is then copied in the workers (meaning it’s only compatible with cluster mode). General rule is to use preload_app when your workers die often and need fast starts. If you don’t have many workers, you probably should not use preload_app.
         | 
| 121 121 |  | 
| 122 122 | 
             
            Note that preload_app can’t be used with phased restart, since phased restart kills and restarts workers one-by-one, and preload_app is all about copying the code of master into the workers.
         | 
| 123 123 |  | 
| @@ -248,4 +248,4 @@ $ bundle exec rake | |
| 248 248 |  | 
| 249 249 | 
             
            ## License
         | 
| 250 250 |  | 
| 251 | 
            -
            Puma is copyright 2013 Evan Phoenix and contributors. It is licensed under the BSD license. See the include LICENSE file for details.
         | 
| 251 | 
            +
            Puma is copyright 2013 Evan Phoenix and contributors. It is licensed under the BSD 3-Clause license. See the include LICENSE file for details.
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -11,7 +11,7 @@ HOE = Hoe.spec "puma" do | |
| 11 11 | 
             
              self.readme_file    = "README.md"
         | 
| 12 12 | 
             
              self.urls = %w!http://puma.io https://github.com/puma/puma!
         | 
| 13 13 |  | 
| 14 | 
            -
              license "BSD"
         | 
| 14 | 
            +
              license "BSD-3-Clause"
         | 
| 15 15 | 
             
              developer 'Evan Phoenix', 'evan@phx.io'
         | 
| 16 16 |  | 
| 17 17 | 
             
              spec_extras[:extensions]  = ["ext/puma_http11/extconf.rb"]
         | 
| @@ -22,7 +22,7 @@ HOE = Hoe.spec "puma" do | |
| 22 22 |  | 
| 23 23 | 
             
              dependency "rack", [">= 1.1", "< 2.0"]
         | 
| 24 24 |  | 
| 25 | 
            -
              extra_dev_deps << ["rake-compiler", "~> 0.8 | 
| 25 | 
            +
              extra_dev_deps << ["rake-compiler", "~> 0.8"]
         | 
| 26 26 | 
             
            end
         | 
| 27 27 |  | 
| 28 28 | 
             
            task :prerelease => [:clobber, :check_manifest, :test]
         | 
    
        data/bin/pumactl
    CHANGED
    
    
    
        data/ext/puma_http11/mini_ssl.c
    CHANGED
    
    | @@ -36,15 +36,18 @@ ms_conn* engine_alloc(VALUE klass, VALUE* obj) { | |
| 36 36 | 
             
              return conn;
         | 
| 37 37 | 
             
            }
         | 
| 38 38 |  | 
| 39 | 
            -
            VALUE engine_init_server(VALUE self, VALUE  | 
| 39 | 
            +
            VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
         | 
| 40 40 | 
             
              VALUE obj;
         | 
| 41 41 | 
             
              SSL_CTX* ctx;
         | 
| 42 42 | 
             
              SSL* ssl;
         | 
| 43 43 |  | 
| 44 44 | 
             
              ms_conn* conn = engine_alloc(self, &obj);
         | 
| 45 45 |  | 
| 46 | 
            -
               | 
| 47 | 
            -
               | 
| 46 | 
            +
              ID sym_key = rb_intern("key");
         | 
| 47 | 
            +
              VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              ID sym_cert = rb_intern("cert");
         | 
| 50 | 
            +
              VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
         | 
| 48 51 |  | 
| 49 52 | 
             
              ctx = SSL_CTX_new(SSLv23_server_method());
         | 
| 50 53 | 
             
              conn->ctx = ctx;
         | 
| @@ -184,7 +187,7 @@ void Init_mini_ssl(VALUE puma) { | |
| 184 187 |  | 
| 185 188 | 
             
              eError = rb_define_class_under(mod, "SSLError", rb_eStandardError);
         | 
| 186 189 |  | 
| 187 | 
            -
              rb_define_singleton_method(eng, "server", engine_init_server,  | 
| 190 | 
            +
              rb_define_singleton_method(eng, "server", engine_init_server, 1);
         | 
| 188 191 | 
             
              rb_define_singleton_method(eng, "client", engine_init_client, 0);
         | 
| 189 192 |  | 
| 190 193 | 
             
              rb_define_method(eng, "inject", engine_inject, 1);
         | 
| @@ -2,29 +2,34 @@ package org.jruby.puma; | |
| 2 2 |  | 
| 3 3 | 
             
            import org.jruby.Ruby;
         | 
| 4 4 | 
             
            import org.jruby.RubyClass;
         | 
| 5 | 
            -
            import org.jruby.RubyHash;
         | 
| 6 5 | 
             
            import org.jruby.RubyModule;
         | 
| 7 | 
            -
            import org.jruby.RubyNumeric;
         | 
| 8 6 | 
             
            import org.jruby.RubyObject;
         | 
| 9 7 | 
             
            import org.jruby.RubyString;
         | 
| 10 | 
            -
             | 
| 11 8 | 
             
            import org.jruby.anno.JRubyMethod;
         | 
| 12 | 
            -
             | 
| 13 9 | 
             
            import org.jruby.runtime.Block;
         | 
| 14 10 | 
             
            import org.jruby.runtime.ObjectAllocator;
         | 
| 15 11 | 
             
            import org.jruby.runtime.ThreadContext;
         | 
| 16 12 | 
             
            import org.jruby.runtime.builtin.IRubyObject;
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            import org.jruby.exceptions.RaiseException;
         | 
| 19 | 
            -
             | 
| 20 13 | 
             
            import org.jruby.util.ByteList;
         | 
| 21 14 |  | 
| 22 | 
            -
             | 
| 23 | 
            -
            import javax.net.ssl | 
| 24 | 
            -
            import javax.net.ssl. | 
| 25 | 
            -
            import  | 
| 26 | 
            -
            import  | 
| 27 | 
            -
            import  | 
| 15 | 
            +
            import javax.net.ssl.KeyManagerFactory;
         | 
| 16 | 
            +
            import javax.net.ssl.SSLContext;
         | 
| 17 | 
            +
            import javax.net.ssl.SSLEngine;
         | 
| 18 | 
            +
            import javax.net.ssl.SSLEngineResult;
         | 
| 19 | 
            +
            import javax.net.ssl.SSLException;
         | 
| 20 | 
            +
            import javax.net.ssl.SSLSession;
         | 
| 21 | 
            +
            import java.io.FileInputStream;
         | 
| 22 | 
            +
            import java.io.IOException;
         | 
| 23 | 
            +
            import java.nio.ByteBuffer;
         | 
| 24 | 
            +
            import java.security.KeyManagementException;
         | 
| 25 | 
            +
            import java.security.KeyStore;
         | 
| 26 | 
            +
            import java.security.KeyStoreException;
         | 
| 27 | 
            +
            import java.security.NoSuchAlgorithmException;
         | 
| 28 | 
            +
            import java.security.UnrecoverableKeyException;
         | 
| 29 | 
            +
            import java.security.cert.CertificateException;
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            import static javax.net.ssl.SSLEngineResult.Status;
         | 
| 32 | 
            +
            import static javax.net.ssl.SSLEngineResult.HandshakeStatus;
         | 
| 28 33 |  | 
| 29 34 | 
             
            public class MiniSSL extends RubyObject {
         | 
| 30 35 | 
             
              private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
         | 
| @@ -33,9 +38,12 @@ public class MiniSSL extends RubyObject { | |
| 33 38 | 
             
                }
         | 
| 34 39 | 
             
              };
         | 
| 35 40 |  | 
| 41 | 
            +
              // set to true to switch on our low-fi trace logging
         | 
| 42 | 
            +
              private static boolean DEBUG = false;
         | 
| 43 | 
            +
             | 
| 36 44 | 
             
              public static void createMiniSSL(Ruby runtime) {
         | 
| 37 45 | 
             
                RubyModule mPuma = runtime.defineModule("Puma");
         | 
| 38 | 
            -
                RubyModule ssl = | 
| 46 | 
            +
                RubyModule ssl = mPuma.defineModuleUnder("MiniSSL");
         | 
| 39 47 |  | 
| 40 48 | 
             
                mPuma.defineClassUnder("SSLError",
         | 
| 41 49 | 
             
                                       runtime.getClass("IOError"),
         | 
| @@ -45,245 +53,329 @@ public class MiniSSL extends RubyObject { | |
| 45 53 | 
             
                eng.defineAnnotatedMethods(MiniSSL.class);
         | 
| 46 54 | 
             
              }
         | 
| 47 55 |  | 
| 48 | 
            -
               | 
| 49 | 
            -
             | 
| 56 | 
            +
              /**
         | 
| 57 | 
            +
               * Fairly transparent wrapper around {@link java.nio.ByteBuffer} which adds the enhancements we need
         | 
| 58 | 
            +
               */
         | 
| 59 | 
            +
              private static class MiniSSLBuffer {
         | 
| 60 | 
            +
                ByteBuffer buffer;
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                private MiniSSLBuffer(int capacity) { buffer = ByteBuffer.allocate(capacity); }
         | 
| 63 | 
            +
                private MiniSSLBuffer(byte[] initialContents) { buffer = ByteBuffer.wrap(initialContents); }
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                public void clear() { buffer.clear(); }
         | 
| 66 | 
            +
                public void compact() { buffer.compact(); }
         | 
| 67 | 
            +
                public void flip() { buffer.flip(); }
         | 
| 68 | 
            +
                public boolean hasRemaining() { return buffer.hasRemaining(); }
         | 
| 69 | 
            +
                public int position() { return buffer.position(); }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                public ByteBuffer getRawBuffer() {
         | 
| 72 | 
            +
                  return buffer;
         | 
| 73 | 
            +
                }
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                /**
         | 
| 76 | 
            +
                 * Writes bytes to the buffer after ensuring there's room
         | 
| 77 | 
            +
                 */
         | 
| 78 | 
            +
                public void put(byte[] bytes) {
         | 
| 79 | 
            +
                  if (buffer.remaining() < bytes.length) {
         | 
| 80 | 
            +
                    resize(buffer.limit() + bytes.length);
         | 
| 81 | 
            +
                  }
         | 
| 82 | 
            +
                  buffer.put(bytes);
         | 
| 83 | 
            +
                }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                /**
         | 
| 86 | 
            +
                 * Ensures that newCapacity bytes can be written to this buffer, only re-allocating if necessary
         | 
| 87 | 
            +
                 */
         | 
| 88 | 
            +
                public void resize(int newCapacity) {
         | 
| 89 | 
            +
                  if (newCapacity > buffer.capacity()) {
         | 
| 90 | 
            +
                    ByteBuffer dstTmp = ByteBuffer.allocate(newCapacity);
         | 
| 91 | 
            +
                    buffer.flip();
         | 
| 92 | 
            +
                    dstTmp.put(buffer);
         | 
| 93 | 
            +
                    buffer = dstTmp;
         | 
| 94 | 
            +
                  } else {
         | 
| 95 | 
            +
                    buffer.limit(newCapacity);
         | 
| 96 | 
            +
                  }
         | 
| 97 | 
            +
                }
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                /**
         | 
| 100 | 
            +
                 * Drains the buffer to a ByteList, or returns null for an empty buffer
         | 
| 101 | 
            +
                 */
         | 
| 102 | 
            +
                public ByteList asByteList() {
         | 
| 103 | 
            +
                  buffer.flip();
         | 
| 104 | 
            +
                  if (!buffer.hasRemaining()) {
         | 
| 105 | 
            +
                    buffer.clear();
         | 
| 106 | 
            +
                    return null;
         | 
| 107 | 
            +
                  }
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  byte[] bss = new byte[buffer.limit()];
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  buffer.get(bss);
         | 
| 112 | 
            +
                  buffer.clear();
         | 
| 113 | 
            +
                  return new ByteList(bss);
         | 
| 114 | 
            +
                }
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                @Override
         | 
| 117 | 
            +
                public String toString() { return buffer.toString(); }
         | 
| 118 | 
            +
              }
         | 
| 50 119 |  | 
| 51 | 
            -
              private SSLEngine | 
| 120 | 
            +
              private SSLEngine engine;
         | 
| 121 | 
            +
              private MiniSSLBuffer inboundNetData;
         | 
| 122 | 
            +
              private MiniSSLBuffer outboundAppData;
         | 
| 123 | 
            +
              private MiniSSLBuffer outboundNetData;
         | 
| 52 124 |  | 
| 53 | 
            -
              private ByteBuffer peerAppData;
         | 
| 54 | 
            -
              private ByteBuffer peerNetData;
         | 
| 55 | 
            -
              private ByteBuffer netData;
         | 
| 56 | 
            -
              private ByteBuffer dummy;
         | 
| 57 | 
            -
              
         | 
| 58 125 | 
             
              public MiniSSL(Ruby runtime, RubyClass klass) {
         | 
| 59 126 | 
             
                super(runtime, klass);
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                this.runtime = runtime;
         | 
| 62 127 | 
             
              }
         | 
| 63 128 |  | 
| 64 129 | 
             
              @JRubyMethod(meta = true)
         | 
| 65 | 
            -
              public static IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject  | 
| 66 | 
            -
             | 
| 67 | 
            -
                  IRubyObject newInstance = klass.newInstance(context,
         | 
| 68 | 
            -
                      new IRubyObject[] { key, cert },
         | 
| 69 | 
            -
                      Block.NULL_BLOCK);
         | 
| 130 | 
            +
              public static IRubyObject server(ThreadContext context, IRubyObject recv, IRubyObject miniSSLContext) {
         | 
| 131 | 
            +
                RubyClass klass = (RubyClass) recv;
         | 
| 70 132 |  | 
| 71 | 
            -
             | 
| 133 | 
            +
                return klass.newInstance(context,
         | 
| 134 | 
            +
                    new IRubyObject[] { miniSSLContext },
         | 
| 135 | 
            +
                    Block.NULL_BLOCK);
         | 
| 72 136 | 
             
              }
         | 
| 73 137 |  | 
| 74 138 | 
             
              @JRubyMethod
         | 
| 75 | 
            -
              public IRubyObject initialize( | 
| 76 | 
            -
                  throws  | 
| 77 | 
            -
                         java.io.FileNotFoundException,
         | 
| 78 | 
            -
                         java.io.IOException,
         | 
| 79 | 
            -
                         java.io.FileNotFoundException,
         | 
| 80 | 
            -
                         java.security.NoSuchAlgorithmException,
         | 
| 81 | 
            -
                         java.security.KeyManagementException,
         | 
| 82 | 
            -
                         java.security.cert.CertificateException,
         | 
| 83 | 
            -
                         java.security.UnrecoverableKeyException
         | 
| 84 | 
            -
              {
         | 
| 139 | 
            +
              public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLContext)
         | 
| 140 | 
            +
                  throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
         | 
| 85 141 | 
             
                KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
         | 
| 86 | 
            -
                KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                char[] pass = "blahblah".toCharArray();
         | 
| 89 142 |  | 
| 90 | 
            -
                 | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
                        pass);
         | 
| 143 | 
            +
                char[] password = miniSSLContext.callMethod(threadContext, "keystore_pass").convertToString().asJavaString().toCharArray();
         | 
| 144 | 
            +
                ks.load(new FileInputStream(miniSSLContext.callMethod(threadContext, "keystore").convertToString().asJavaString()),
         | 
| 145 | 
            +
                    password);
         | 
| 94 146 |  | 
| 95 147 | 
             
                KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
         | 
| 96 | 
            -
                kmf.init(ks,  | 
| 97 | 
            -
             | 
| 98 | 
            -
                TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
         | 
| 99 | 
            -
                tmf.init(ts);
         | 
| 148 | 
            +
                kmf.init(ks, password);
         | 
| 100 149 |  | 
| 101 150 | 
             
                SSLContext sslCtx = SSLContext.getInstance("TLS");
         | 
| 102 151 |  | 
| 103 | 
            -
                sslCtx.init(kmf.getKeyManagers(),  | 
| 104 | 
            -
             | 
| 105 | 
            -
                sslc = sslCtx;
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                engine = sslc.createSSLEngine();
         | 
| 152 | 
            +
                sslCtx.init(kmf.getKeyManagers(), null, null);
         | 
| 153 | 
            +
                engine = sslCtx.createSSLEngine();
         | 
| 108 154 | 
             
                engine.setUseClientMode(false);
         | 
| 109 | 
            -
                // engine.setNeedClientAuth(true);
         | 
| 110 155 |  | 
| 111 156 | 
             
                SSLSession session = engine.getSession();
         | 
| 112 | 
            -
                 | 
| 113 | 
            -
                 | 
| 114 | 
            -
                 | 
| 115 | 
            -
                 | 
| 116 | 
            -
             | 
| 117 | 
            -
                netData.limit(0);
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                peerNetData.clear();
         | 
| 120 | 
            -
                peerAppData.clear();
         | 
| 121 | 
            -
                netData.clear();
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                dummy = ByteBuffer.allocate(0);
         | 
| 124 | 
            -
                
         | 
| 157 | 
            +
                inboundNetData = new MiniSSLBuffer(session.getPacketBufferSize());
         | 
| 158 | 
            +
                outboundAppData = new MiniSSLBuffer(session.getApplicationBufferSize());
         | 
| 159 | 
            +
                outboundAppData.flip();
         | 
| 160 | 
            +
                outboundNetData = new MiniSSLBuffer(session.getPacketBufferSize());
         | 
| 161 | 
            +
             | 
| 125 162 | 
             
                return this;
         | 
| 126 163 | 
             
              }
         | 
| 127 164 |  | 
| 128 165 | 
             
              @JRubyMethod
         | 
| 129 166 | 
             
              public IRubyObject inject(IRubyObject arg) {
         | 
| 130 | 
            -
                 | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
                 | 
| 167 | 
            +
                try {
         | 
| 168 | 
            +
                  byte[] bytes = arg.convertToString().getBytes();
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                  log("Net Data post pre-inject: " + inboundNetData);
         | 
| 171 | 
            +
                  inboundNetData.put(bytes);
         | 
| 172 | 
            +
                  log("Net Data post post-inject: " + inboundNetData);
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                  log("inject(): " + bytes.length + " encrypted bytes from request");
         | 
| 175 | 
            +
                  return this;
         | 
| 176 | 
            +
                } catch (Exception e) {
         | 
| 177 | 
            +
                  e.printStackTrace();
         | 
| 178 | 
            +
                  throw new RuntimeException(e);
         | 
| 179 | 
            +
                }
         | 
| 140 180 | 
             
              }
         | 
| 141 181 |  | 
| 142 | 
            -
               | 
| 143 | 
            -
             | 
| 144 | 
            -
                 | 
| 145 | 
            -
             | 
| 146 | 
            -
                SSLEngineResult res;
         | 
| 182 | 
            +
              private enum SSLOperation {
         | 
| 183 | 
            +
                WRAP,
         | 
| 184 | 
            +
                UNWRAP
         | 
| 185 | 
            +
              }
         | 
| 147 186 |  | 
| 148 | 
            -
             | 
| 187 | 
            +
              private SSLEngineResult doOp(SSLOperation sslOp, MiniSSLBuffer src, MiniSSLBuffer dst) throws SSLException {
         | 
| 188 | 
            +
                SSLEngineResult res = null;
         | 
| 189 | 
            +
                boolean retryOp = true;
         | 
| 190 | 
            +
                while (retryOp) {
         | 
| 191 | 
            +
                  switch (sslOp) {
         | 
| 192 | 
            +
                    case WRAP:
         | 
| 193 | 
            +
                      res = engine.wrap(src.getRawBuffer(), dst.getRawBuffer());
         | 
| 194 | 
            +
                      break;
         | 
| 195 | 
            +
                    case UNWRAP:
         | 
| 196 | 
            +
                      res = engine.unwrap(src.getRawBuffer(), dst.getRawBuffer());
         | 
| 197 | 
            +
                      break;
         | 
| 198 | 
            +
                    default:
         | 
| 199 | 
            +
                      throw new IllegalStateException("Unknown SSLOperation: " + sslOp);
         | 
| 200 | 
            +
                  }
         | 
| 149 201 |  | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 202 | 
            +
                  switch (res.getStatus()) {
         | 
| 203 | 
            +
                    case BUFFER_OVERFLOW:
         | 
| 204 | 
            +
                      log("SSLOp#doRun(): overflow");
         | 
| 205 | 
            +
                      log("SSLOp#doRun(): dst data at overflow: " + dst);
         | 
| 206 | 
            +
                      // increase the buffer size to accommodate the overflowing data
         | 
| 207 | 
            +
                      int newSize = Math.max(engine.getSession().getPacketBufferSize(), engine.getSession().getApplicationBufferSize());
         | 
| 208 | 
            +
                      dst.resize(newSize + dst.position());
         | 
| 209 | 
            +
                      // retry the operation
         | 
| 210 | 
            +
                      retryOp = true;
         | 
| 211 | 
            +
                      break;
         | 
| 212 | 
            +
                    case BUFFER_UNDERFLOW:
         | 
| 213 | 
            +
                      log("SSLOp#doRun(): underflow");
         | 
| 214 | 
            +
                      log("SSLOp#doRun(): src data at underflow: " + src);
         | 
| 215 | 
            +
                      // need to wait for more data to come in before we retry
         | 
| 216 | 
            +
                      retryOp = false;
         | 
| 217 | 
            +
                      break;
         | 
| 218 | 
            +
                    default:
         | 
| 219 | 
            +
                      // other cases are OK and CLOSED.  We're done here.
         | 
| 220 | 
            +
                      retryOp = false;
         | 
| 221 | 
            +
                  }
         | 
| 152 222 | 
             
                }
         | 
| 153 223 |  | 
| 154 | 
            -
                 | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
                     | 
| 159 | 
            -
             | 
| 160 | 
            -
                log("read: ", res);
         | 
| 161 | 
            -
             | 
| 162 | 
            -
                if(peerNetData.hasRemaining()) {
         | 
| 163 | 
            -
                  log("STILL HAD peerNetData!");
         | 
| 224 | 
            +
                // after each op, run any delegated tasks if needed
         | 
| 225 | 
            +
                if(engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
         | 
| 226 | 
            +
                  Runnable runnable;
         | 
| 227 | 
            +
                  while ((runnable = engine.getDelegatedTask()) != null) {
         | 
| 228 | 
            +
                    runnable.run();
         | 
| 229 | 
            +
                  }
         | 
| 164 230 | 
             
                }
         | 
| 165 231 |  | 
| 166 | 
            -
                 | 
| 167 | 
            -
             | 
| 232 | 
            +
                return res;
         | 
| 233 | 
            +
              }
         | 
| 168 234 |  | 
| 169 | 
            -
             | 
| 235 | 
            +
              @JRubyMethod
         | 
| 236 | 
            +
              public IRubyObject read() throws Exception {
         | 
| 237 | 
            +
                try {
         | 
| 238 | 
            +
                  inboundNetData.flip();
         | 
| 170 239 |  | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 240 | 
            +
                  if(!inboundNetData.hasRemaining()) {
         | 
| 241 | 
            +
                    return getRuntime().getNil();
         | 
| 242 | 
            +
                  }
         | 
| 174 243 |  | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
                   | 
| 178 | 
            -
                   | 
| 179 | 
            -
                   | 
| 180 | 
            -
             | 
| 244 | 
            +
                  log("read(): inboundNetData prepped for read: " + inboundNetData);
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  MiniSSLBuffer inboundAppData = new MiniSSLBuffer(engine.getSession().getApplicationBufferSize());
         | 
| 247 | 
            +
                  SSLEngineResult res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
         | 
| 248 | 
            +
                  log("read(): after initial unwrap", engine, res);
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                  log("read(): Net Data post unwrap: " + inboundNetData);
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
         | 
| 253 | 
            +
                  boolean done = false;
         | 
| 254 | 
            +
                  while (!done) {
         | 
| 255 | 
            +
                    switch (handshakeStatus) {
         | 
| 256 | 
            +
                      case NEED_WRAP:
         | 
| 257 | 
            +
                        res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
         | 
| 258 | 
            +
                        log("read(): after handshake wrap", engine, res);
         | 
| 259 | 
            +
                        break;
         | 
| 260 | 
            +
                      case NEED_UNWRAP:
         | 
| 261 | 
            +
                        res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
         | 
| 262 | 
            +
                        log("read(): after handshake unwrap", engine, res);
         | 
| 263 | 
            +
                        if (res.getStatus() == Status.BUFFER_UNDERFLOW) {
         | 
| 264 | 
            +
                          // need more data before we can shake more hands
         | 
| 265 | 
            +
                          done = true;
         | 
| 266 | 
            +
                        }
         | 
| 267 | 
            +
                        break;
         | 
| 268 | 
            +
                      default:
         | 
| 269 | 
            +
                        done = true;
         | 
| 270 | 
            +
                    }
         | 
| 271 | 
            +
                    handshakeStatus = engine.getHandshakeStatus();
         | 
| 272 | 
            +
                  }
         | 
| 181 273 |  | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 274 | 
            +
                  if (inboundNetData.hasRemaining()) {
         | 
| 275 | 
            +
                    log("Net Data post pre-compact: " + inboundNetData);
         | 
| 276 | 
            +
                    inboundNetData.compact();
         | 
| 277 | 
            +
                    log("Net Data post post-compact: " + inboundNetData);
         | 
| 278 | 
            +
                  } else {
         | 
| 279 | 
            +
                    log("Net Data post pre-reset: " + inboundNetData);
         | 
| 280 | 
            +
                    inboundNetData.clear();
         | 
| 281 | 
            +
                    log("Net Data post post-reset: " + inboundNetData);
         | 
| 282 | 
            +
                  }
         | 
| 184 283 |  | 
| 185 | 
            -
                   | 
| 186 | 
            -
                   | 
| 284 | 
            +
                  ByteList appDataByteList = inboundAppData.asByteList();
         | 
| 285 | 
            +
                  if (appDataByteList == null) {
         | 
| 286 | 
            +
                    return getRuntime().getNil();
         | 
| 287 | 
            +
                  }
         | 
| 187 288 |  | 
| 188 | 
            -
                   | 
| 289 | 
            +
                  RubyString str = getRuntime().newString("");
         | 
| 290 | 
            +
                  str.setValue(appDataByteList);
         | 
| 189 291 |  | 
| 190 | 
            -
                   | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
                     | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
                   | 
| 292 | 
            +
                  logPlain("\n");
         | 
| 293 | 
            +
                  log("read(): begin dump of request data >>>>\n");
         | 
| 294 | 
            +
                  if (str.asJavaString().getBytes().length < 1000) {
         | 
| 295 | 
            +
                    logPlain(str.asJavaString() + "\n");
         | 
| 296 | 
            +
                  }
         | 
| 297 | 
            +
                  logPlain("Num bytes: " + str.asJavaString().getBytes().length + "\n");
         | 
| 298 | 
            +
                  log("read(): end dump of request data   <<<<\n");
         | 
| 299 | 
            +
                  return str;
         | 
| 300 | 
            +
                } catch (Exception e) {
         | 
| 301 | 
            +
                  e.printStackTrace();
         | 
| 302 | 
            +
                  throw new RuntimeException(e);
         | 
| 197 303 | 
             
                }
         | 
| 198 | 
            -
             | 
| 199 | 
            -
                // if(peerAppData.position() == 0 && 
         | 
| 200 | 
            -
                    // res.getStatus() == SSLEngineResult.Status.OK &&
         | 
| 201 | 
            -
                    // peerNetData.hasRemaining()) {
         | 
| 202 | 
            -
                  // res = engine.unwrap(peerNetData, peerAppData);
         | 
| 203 | 
            -
                // }
         | 
| 204 | 
            -
             | 
| 205 | 
            -
                byte[] bss = new byte[peerAppData.limit()];
         | 
| 206 | 
            -
             | 
| 207 | 
            -
                peerAppData.get(bss);
         | 
| 208 | 
            -
             | 
| 209 | 
            -
                RubyString str = getRuntime().newString("");
         | 
| 210 | 
            -
                str.setValue(new ByteList(bss));
         | 
| 211 | 
            -
             | 
| 212 | 
            -
                return str;
         | 
| 213 304 | 
             
              }
         | 
| 214 305 |  | 
| 215 | 
            -
              private static  | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
                if(hsStatus == HandshakeStatus.NEED_TASK) {
         | 
| 221 | 
            -
                  Runnable runnable;
         | 
| 222 | 
            -
                  while ((runnable = engine.getDelegatedTask()) != null) {
         | 
| 223 | 
            -
                    log("\trunning delegated task...");
         | 
| 224 | 
            -
                    runnable.run();
         | 
| 225 | 
            -
                  }
         | 
| 226 | 
            -
                  hsStatus = engine.getHandshakeStatus();
         | 
| 227 | 
            -
                  if (hsStatus == HandshakeStatus.NEED_TASK) {
         | 
| 228 | 
            -
                    throw new Exception(
         | 
| 229 | 
            -
                        "handshake shouldn't need additional tasks");
         | 
| 230 | 
            -
                  }
         | 
| 231 | 
            -
                  log("\tnew HandshakeStatus: " + hsStatus);
         | 
| 306 | 
            +
              private static void log(String str, SSLEngine engine, SSLEngineResult result) {
         | 
| 307 | 
            +
                if (DEBUG) {
         | 
| 308 | 
            +
                  log(str + " " + result.getStatus() + "/" + engine.getHandshakeStatus() +
         | 
| 309 | 
            +
                      "---bytes consumed: " + result.bytesConsumed() +
         | 
| 310 | 
            +
                      ", bytes produced: " + result.bytesProduced());
         | 
| 232 311 | 
             
                }
         | 
| 233 | 
            -
             | 
| 234 | 
            -
                return hsStatus;
         | 
| 235 312 | 
             
              }
         | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
                    "\t\"getStatus() / getHandshakeStatus()\" +\n" +
         | 
| 241 | 
            -
                    "\t\"bytesConsumed() / bytesProduced()\"\n");
         | 
| 242 | 
            -
             | 
| 243 | 
            -
                HandshakeStatus hsStatus = result.getHandshakeStatus();
         | 
| 244 | 
            -
                log(str +
         | 
| 245 | 
            -
                    result.getStatus() + "/" + hsStatus + ", " +
         | 
| 246 | 
            -
                    result.bytesConsumed() + "/" + result.bytesProduced() +
         | 
| 247 | 
            -
                    " bytes");
         | 
| 248 | 
            -
                if (hsStatus == HandshakeStatus.FINISHED) {
         | 
| 249 | 
            -
                  log("\t...ready for application data");
         | 
| 313 | 
            +
             | 
| 314 | 
            +
              private static void log(String str) {
         | 
| 315 | 
            +
                if (DEBUG) {
         | 
| 316 | 
            +
                  System.out.println("MiniSSL.java: " + str);
         | 
| 250 317 | 
             
                }
         | 
| 251 318 | 
             
              }
         | 
| 252 319 |  | 
| 253 | 
            -
              private static void  | 
| 254 | 
            -
                 | 
| 320 | 
            +
              private static void logPlain(String str) {
         | 
| 321 | 
            +
                if (DEBUG) {
         | 
| 322 | 
            +
                  System.out.println(str);
         | 
| 323 | 
            +
                }
         | 
| 255 324 | 
             
              }
         | 
| 256 | 
            -
              
         | 
| 257 | 
            -
              
         | 
| 258 325 |  | 
| 259 326 | 
             
              @JRubyMethod
         | 
| 260 | 
            -
              public IRubyObject write(IRubyObject arg)  | 
| 261 | 
            -
                 | 
| 262 | 
            -
             | 
| 263 | 
            -
             | 
| 264 | 
            -
             | 
| 327 | 
            +
              public IRubyObject write(IRubyObject arg) {
         | 
| 328 | 
            +
                try {
         | 
| 329 | 
            +
                  log("write(): begin dump of response data >>>>\n");
         | 
| 330 | 
            +
                  logPlain("\n");
         | 
| 331 | 
            +
                  if (arg.asJavaString().getBytes().length < 1000) {
         | 
| 332 | 
            +
                    logPlain(arg.asJavaString() + "\n");
         | 
| 333 | 
            +
                  }
         | 
| 334 | 
            +
                  logPlain("Num bytes: " + arg.asJavaString().getBytes().length + "\n");
         | 
| 335 | 
            +
                  log("write(): end dump of response data   <<<<\n");
         | 
| 265 336 |  | 
| 266 | 
            -
             | 
| 337 | 
            +
                  byte[] bls = arg.convertToString().getBytes();
         | 
| 338 | 
            +
                  outboundAppData = new MiniSSLBuffer(bls);
         | 
| 267 339 |  | 
| 268 | 
            -
             | 
| 340 | 
            +
                  return getRuntime().newFixnum(bls.length);
         | 
| 341 | 
            +
                } catch (Exception e) {
         | 
| 342 | 
            +
                  e.printStackTrace();
         | 
| 343 | 
            +
                  throw new RuntimeException(e);
         | 
| 344 | 
            +
                }
         | 
| 269 345 | 
             
              }
         | 
| 270 346 |  | 
| 271 347 | 
             
              @JRubyMethod
         | 
| 272 | 
            -
              public IRubyObject extract() {
         | 
| 273 | 
            -
                 | 
| 348 | 
            +
              public IRubyObject extract() throws SSLException {
         | 
| 349 | 
            +
                try {
         | 
| 350 | 
            +
                  ByteList dataByteList = outboundNetData.asByteList();
         | 
| 351 | 
            +
                  if (dataByteList != null) {
         | 
| 352 | 
            +
                    RubyString str = getRuntime().newString("");
         | 
| 353 | 
            +
                    str.setValue(dataByteList);
         | 
| 354 | 
            +
                    return str;
         | 
| 355 | 
            +
                  }
         | 
| 274 356 |  | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 357 | 
            +
                  if (!outboundAppData.hasRemaining()) {
         | 
| 358 | 
            +
                    return getRuntime().getNil();
         | 
| 359 | 
            +
                  }
         | 
| 278 360 |  | 
| 279 | 
            -
             | 
| 361 | 
            +
                  outboundNetData.clear();
         | 
| 362 | 
            +
                  SSLEngineResult res = doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
         | 
| 363 | 
            +
                  log("extract(): bytes consumed: " + res.bytesConsumed() + "\n");
         | 
| 364 | 
            +
                  log("extract(): bytes produced: " + res.bytesProduced() + "\n");
         | 
| 365 | 
            +
                  dataByteList = outboundNetData.asByteList();
         | 
| 366 | 
            +
                  if (dataByteList == null) {
         | 
| 367 | 
            +
                    return getRuntime().getNil();
         | 
| 368 | 
            +
                  }
         | 
| 280 369 |  | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 370 | 
            +
                  RubyString str = getRuntime().newString("");
         | 
| 371 | 
            +
                  str.setValue(dataByteList);
         | 
| 283 372 |  | 
| 284 | 
            -
             | 
| 285 | 
            -
                str.setValue(new ByteList(bss));
         | 
| 373 | 
            +
                  log("extract(): " + dataByteList.getRealSize() + " encrypted bytes for response");
         | 
| 286 374 |  | 
| 287 | 
            -
             | 
| 375 | 
            +
                  return str;
         | 
| 376 | 
            +
                } catch (Exception e) {
         | 
| 377 | 
            +
                  e.printStackTrace();
         | 
| 378 | 
            +
                  throw new RuntimeException(e);
         | 
| 379 | 
            +
                }
         | 
| 288 380 | 
             
              }
         | 
| 289 381 | 
             
            }
         | 
    
        data/lib/puma/binder.rb
    CHANGED
    
    | @@ -121,26 +121,36 @@ module Puma | |
| 121 121 |  | 
| 122 122 | 
             
                      @listeners << [str, io]
         | 
| 123 123 | 
             
                    when "ssl"
         | 
| 124 | 
            -
                      if IS_JRUBY
         | 
| 125 | 
            -
                        @events.error "SSL not supported on JRuby"
         | 
| 126 | 
            -
                        raise UnsupportedOption
         | 
| 127 | 
            -
                      end
         | 
| 128 | 
            -
             | 
| 129 124 | 
             
                      params = Rack::Utils.parse_query uri.query
         | 
| 130 125 | 
             
                      require 'puma/minissl'
         | 
| 131 126 |  | 
| 132 127 | 
             
                      ctx = MiniSSL::Context.new
         | 
| 133 | 
            -
                      unless params['key']
         | 
| 134 | 
            -
                        @events.error "Please specify the SSL key via 'key='"
         | 
| 135 | 
            -
                      end
         | 
| 136 128 |  | 
| 137 | 
            -
                       | 
| 129 | 
            +
                      if defined?(JRUBY_VERSION)
         | 
| 130 | 
            +
                        unless params['keystore']
         | 
| 131 | 
            +
                          @events.error "Please specify the Java keystore via 'keystore='"
         | 
| 132 | 
            +
                        end
         | 
| 138 133 |  | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 134 | 
            +
                        ctx.keystore = params['keystore']
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                        unless params['keystore-pass']
         | 
| 137 | 
            +
                          @events.error "Please specify the Java keystore password  via 'keystore-pass='"
         | 
| 138 | 
            +
                        end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                        ctx.keystore_pass = params['keystore-pass']
         | 
| 141 | 
            +
                      else
         | 
| 142 | 
            +
                        unless params['key']
         | 
| 143 | 
            +
                          @events.error "Please specify the SSL key via 'key='"
         | 
| 144 | 
            +
                        end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                        ctx.key = params['key']
         | 
| 142 147 |  | 
| 143 | 
            -
             | 
| 148 | 
            +
                        unless params['cert']
         | 
| 149 | 
            +
                          @events.error "Please specify the SSL cert via 'cert='"
         | 
| 150 | 
            +
                        end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                        ctx.cert = params['cert']
         | 
| 153 | 
            +
                      end
         | 
| 144 154 |  | 
| 145 155 | 
             
                      ctx.verify_mode = MiniSSL::VERIFY_NONE
         | 
| 146 156 |  | 
| @@ -215,11 +225,6 @@ module Puma | |
| 215 225 |  | 
| 216 226 | 
             
                def add_ssl_listener(host, port, ctx,
         | 
| 217 227 | 
             
                                     optimize_for_latency=true, backlog=1024)
         | 
| 218 | 
            -
                  if IS_JRUBY
         | 
| 219 | 
            -
                    @events.error "SSL not supported on JRuby"
         | 
| 220 | 
            -
                    raise UnsupportedOption
         | 
| 221 | 
            -
                  end
         | 
| 222 | 
            -
             | 
| 223 228 | 
             
                  require 'puma/minissl'
         | 
| 224 229 |  | 
| 225 230 | 
             
                  s = TCPServer.new(host, port)
         | 
| @@ -239,11 +244,6 @@ module Puma | |
| 239 244 | 
             
                end
         | 
| 240 245 |  | 
| 241 246 | 
             
                def inherited_ssl_listener(fd, ctx)
         | 
| 242 | 
            -
                  if IS_JRUBY
         | 
| 243 | 
            -
                    @events.error "SSL not supported on JRuby"
         | 
| 244 | 
            -
                    raise UnsupportedOption
         | 
| 245 | 
            -
                  end
         | 
| 246 | 
            -
             | 
| 247 247 | 
             
                  require 'puma/minissl'
         | 
| 248 248 | 
             
                  s = TCPServer.for_fd(fd)
         | 
| 249 249 | 
             
                  @ios << MiniSSL::Server.new(s, ctx)
         | 
    
        data/lib/puma/cluster.rb
    CHANGED
    
    | @@ -183,7 +183,7 @@ module Puma | |
| 183 183 |  | 
| 184 184 | 
             
                  # If we're not running under a Bundler context, then
         | 
| 185 185 | 
             
                  # report the info about the context we will be using
         | 
| 186 | 
            -
                  if !ENV[' | 
| 186 | 
            +
                  if !ENV['BUNDLE_GEMFILE'] and File.exist?("Gemfile")
         | 
| 187 187 | 
             
                    log "+ Gemfile in context: #{File.expand_path("Gemfile")}"
         | 
| 188 188 | 
             
                  end
         | 
| 189 189 |  | 
    
        data/lib/puma/const.rb
    CHANGED
    
    | @@ -28,8 +28,8 @@ module Puma | |
| 28 28 | 
             
              # too taxing on performance.
         | 
| 29 29 | 
             
              module Const
         | 
| 30 30 |  | 
| 31 | 
            -
                PUMA_VERSION = VERSION = "2. | 
| 32 | 
            -
                CODE_NAME = " | 
| 31 | 
            +
                PUMA_VERSION = VERSION = "2.9.0".freeze
         | 
| 32 | 
            +
                CODE_NAME = "Team High Five".freeze
         | 
| 33 33 |  | 
| 34 34 | 
             
                FAST_TRACK_KA_TIMEOUT = 0.2
         | 
| 35 35 |  | 
    
        data/lib/puma/minissl.rb
    CHANGED
    
    | @@ -69,7 +69,7 @@ module Puma | |
| 69 69 |  | 
| 70 70 | 
             
                      return data.bytesize if need == 0
         | 
| 71 71 |  | 
| 72 | 
            -
                      data = data[ | 
| 72 | 
            +
                      data = data[wrote..-1]
         | 
| 73 73 | 
             
                    end
         | 
| 74 74 | 
             
                  end
         | 
| 75 75 |  | 
| @@ -91,31 +91,35 @@ module Puma | |
| 91 91 | 
             
                class Context
         | 
| 92 92 | 
             
                  attr_accessor :verify_mode
         | 
| 93 93 |  | 
| 94 | 
            -
                   | 
| 95 | 
            -
             | 
| 94 | 
            +
                  if defined?(JRUBY_VERSION)
         | 
| 95 | 
            +
                    # jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
         | 
| 96 | 
            +
                    attr_reader :keystore
         | 
| 97 | 
            +
                    attr_accessor :keystore_pass
         | 
| 96 98 |  | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 99 | 
            +
                    def keystore=(keystore)
         | 
| 100 | 
            +
                      raise ArgumentError, "No such keystore file '#{keystore}'" unless File.exist? keystore
         | 
| 101 | 
            +
                      @keystore = keystore
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
                  else
         | 
| 104 | 
            +
                    # non-jruby Context properties
         | 
| 105 | 
            +
                    attr_reader :key
         | 
| 106 | 
            +
                    attr_reader :cert
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                    def key=(key)
         | 
| 109 | 
            +
                      raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
         | 
| 110 | 
            +
                      @key = key
         | 
| 111 | 
            +
                    end
         | 
| 101 112 |  | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 113 | 
            +
                    def cert=(cert)
         | 
| 114 | 
            +
                      raise ArgumentError, "No such cert file '#{cert}'" unless File.exist? cert
         | 
| 115 | 
            +
                      @cert = cert
         | 
| 116 | 
            +
                    end
         | 
| 105 117 | 
             
                  end
         | 
| 106 118 | 
             
                end
         | 
| 107 119 |  | 
| 108 120 | 
             
                VERIFY_NONE = 0
         | 
| 109 121 | 
             
                VERIFY_PEER = 1
         | 
| 110 122 |  | 
| 111 | 
            -
                #if defined?(JRUBY_VERSION)
         | 
| 112 | 
            -
                #class Engine
         | 
| 113 | 
            -
                #def self.server(key, cert)
         | 
| 114 | 
            -
                #new(key, cert)
         | 
| 115 | 
            -
                #end
         | 
| 116 | 
            -
                #end
         | 
| 117 | 
            -
                #end
         | 
| 118 | 
            -
             | 
| 119 123 | 
             
                class Server
         | 
| 120 124 | 
             
                  def initialize(socket, ctx)
         | 
| 121 125 | 
             
                    @socket = socket
         | 
| @@ -128,14 +132,14 @@ module Puma | |
| 128 132 |  | 
| 129 133 | 
             
                  def accept
         | 
| 130 134 | 
             
                    io = @socket.accept
         | 
| 131 | 
            -
                    engine = Engine.server @ctx | 
| 135 | 
            +
                    engine = Engine.server @ctx
         | 
| 132 136 |  | 
| 133 137 | 
             
                    Socket.new io, engine
         | 
| 134 138 | 
             
                  end
         | 
| 135 139 |  | 
| 136 140 | 
             
                  def accept_nonblock
         | 
| 137 141 | 
             
                    io = @socket.accept_nonblock
         | 
| 138 | 
            -
                    engine = Engine.server @ctx | 
| 142 | 
            +
                    engine = Engine.server @ctx
         | 
| 139 143 |  | 
| 140 144 | 
             
                    Socket.new io, engine
         | 
| 141 145 | 
             
                  end
         | 
    
        data/lib/puma/puma_http11.jar
    CHANGED
    
    | Binary file | 
    
        data/lib/puma/server.rb
    CHANGED
    
    | @@ -614,10 +614,10 @@ module Puma | |
| 614 614 | 
             
                    begin
         | 
| 615 615 | 
             
                      res_body.each do |part|
         | 
| 616 616 | 
             
                        if chunked
         | 
| 617 | 
            -
                          client | 
| 618 | 
            -
                          client | 
| 617 | 
            +
                          fast_write client, part.bytesize.to_s(16)
         | 
| 618 | 
            +
                          fast_write client, line_ending
         | 
| 619 619 | 
             
                          fast_write client, part
         | 
| 620 | 
            -
                          client | 
| 620 | 
            +
                          fast_write client, line_ending
         | 
| 621 621 | 
             
                        else
         | 
| 622 622 | 
             
                          fast_write client, part
         | 
| 623 623 | 
             
                        end
         | 
| @@ -626,7 +626,7 @@ module Puma | |
| 626 626 | 
             
                      end
         | 
| 627 627 |  | 
| 628 628 | 
             
                      if chunked
         | 
| 629 | 
            -
                        client | 
| 629 | 
            +
                        fast_write client, CLOSE_CHUNKED
         | 
| 630 630 | 
             
                        client.flush
         | 
| 631 631 | 
             
                      end
         | 
| 632 632 | 
             
                    rescue SystemCallError, IOError
         | 
    
        data/puma.gemspec
    CHANGED
    
    | @@ -23,7 +23,7 @@ Gem::Specification.new do |s| | |
| 23 23 | 
             
              s.extensions = ["ext/puma_http11/extconf.rb"]
         | 
| 24 24 | 
             
              s.files = `git ls-files`.split($/)
         | 
| 25 25 | 
             
              s.homepage = "http://puma.io"
         | 
| 26 | 
            -
              s.license = "BSD"
         | 
| 26 | 
            +
              s.license = "BSD-3-Clause"
         | 
| 27 27 | 
             
              s.rdoc_options = ["--main", "README.md"]
         | 
| 28 28 | 
             
              s.require_paths = ["lib"]
         | 
| 29 29 | 
             
              s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
         | 
    
        data/test/test_minissl.rb
    CHANGED
    
    | @@ -1,25 +1,29 @@ | |
| 1 1 | 
             
            require 'test/unit'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            unless defined? JRUBY_VERSION
         | 
| 4 | 
            -
             | 
| 5 2 | 
             
            require 'puma'
         | 
| 6 3 | 
             
            require 'puma/minissl'
         | 
| 7 4 |  | 
| 8 5 | 
             
            class TestMiniSSL < Test::Unit::TestCase
         | 
| 9 6 |  | 
| 10 | 
            -
               | 
| 11 | 
            -
                 | 
| 7 | 
            +
              if defined?(JRUBY_VERSION)
         | 
| 8 | 
            +
                def test_raises_with_invalid_keystore_file
         | 
| 9 | 
            +
                  ctx = Puma::MiniSSL::Context.new
         | 
| 12 10 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 11 | 
            +
                  exception = assert_raise(ArgumentError) { ctx.keystore = "/no/such/keystore" }
         | 
| 12 | 
            +
                  assert_equal("No such keystore file '/no/such/keystore'", exception.message)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              else
         | 
| 15 | 
            +
                def test_raises_with_invalid_key_file
         | 
| 16 | 
            +
                  ctx = Puma::MiniSSL::Context.new
         | 
| 16 17 |  | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 18 | 
            +
                  exception = assert_raise(ArgumentError) { ctx.key = "/no/such/key" }
         | 
| 19 | 
            +
                  assert_equal("No such key file '/no/such/key'", exception.message)
         | 
| 20 | 
            +
                end
         | 
| 19 21 |  | 
| 20 | 
            -
                 | 
| 21 | 
            -
             | 
| 22 | 
            -
              end
         | 
| 23 | 
            -
            end
         | 
| 22 | 
            +
                def test_raises_with_invalid_cert_file
         | 
| 23 | 
            +
                  ctx = Puma::MiniSSL::Context.new
         | 
| 24 24 |  | 
| 25 | 
            +
                  exception = assert_raise(ArgumentError) { ctx.cert = "/no/such/cert" }
         | 
| 26 | 
            +
                  assert_equal("No such cert file '/no/such/cert'", exception.message)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 25 29 | 
             
            end
         | 
    
        data/test/test_puma_server.rb
    CHANGED
    
    | @@ -18,47 +18,12 @@ class TestPumaServer < Test::Unit::TestCase | |
| 18 18 |  | 
| 19 19 | 
             
                @events = Puma::Events.new STDOUT, STDERR
         | 
| 20 20 | 
             
                @server = Puma::Server.new @app, @events
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                if defined?(JRUBY_VERSION)
         | 
| 23 | 
            -
                  @ssl_key =  File.expand_path "../../examples/puma/keystore.jks", __FILE__
         | 
| 24 | 
            -
                  @ssl_cert = @ssl_key
         | 
| 25 | 
            -
                else
         | 
| 26 | 
            -
                  @ssl_key =  File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
         | 
| 27 | 
            -
                  @ssl_cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
         | 
| 28 | 
            -
                end
         | 
| 29 21 | 
             
              end
         | 
| 30 22 |  | 
| 31 23 | 
             
              def teardown
         | 
| 32 24 | 
             
                @server.stop(true)
         | 
| 33 25 | 
             
              end
         | 
| 34 26 |  | 
| 35 | 
            -
              def test_url_scheme_for_https
         | 
| 36 | 
            -
                ctx = Puma::MiniSSL::Context.new
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                ctx.key = @ssl_key
         | 
| 39 | 
            -
                ctx.cert = @ssl_cert
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                @server.add_ssl_listener @host, @port, ctx
         | 
| 44 | 
            -
                @server.run
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                http = Net::HTTP.new @host, @port
         | 
| 47 | 
            -
                http.use_ssl = true
         | 
| 48 | 
            -
                http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                body = nil
         | 
| 51 | 
            -
                http.start do
         | 
| 52 | 
            -
                  req = Net::HTTP::Get.new "/", {}
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                  http.request(req) do |rep|
         | 
| 55 | 
            -
                    body = rep.body
         | 
| 56 | 
            -
                  end
         | 
| 57 | 
            -
                end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                assert_equal "https", body
         | 
| 60 | 
            -
              end unless defined? JRUBY_VERSION
         | 
| 61 | 
            -
             | 
| 62 27 | 
             
              def test_proper_stringio_body
         | 
| 63 28 | 
             
                data = nil
         | 
| 64 29 |  | 
| @@ -0,0 +1,91 @@ | |
| 1 | 
            +
            require "rbconfig"
         | 
| 2 | 
            +
            require 'test/unit'
         | 
| 3 | 
            +
            require 'socket'
         | 
| 4 | 
            +
            require 'openssl'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require 'puma/minissl'
         | 
| 7 | 
            +
            require 'puma/server'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require 'net/https'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            class TestPumaServerSSL < Test::Unit::TestCase
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def setup
         | 
| 14 | 
            +
                @port = 3212
         | 
| 15 | 
            +
                @host = "127.0.0.1"
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                @app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                ctx = Puma::MiniSSL::Context.new
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                if defined?(JRUBY_VERSION)
         | 
| 22 | 
            +
                  ctx.keystore =  File.expand_path "../../examples/puma/keystore.jks", __FILE__
         | 
| 23 | 
            +
                  ctx.keystore_pass = 'blahblah'
         | 
| 24 | 
            +
                else
         | 
| 25 | 
            +
                  ctx.key =  File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
         | 
| 26 | 
            +
                  ctx.cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                @events = Puma::Events.new STDOUT, STDERR
         | 
| 32 | 
            +
                @server = Puma::Server.new @app, @events
         | 
| 33 | 
            +
                @server.add_ssl_listener @host, @port, ctx
         | 
| 34 | 
            +
                @server.run
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                @http = Net::HTTP.new @host, @port
         | 
| 37 | 
            +
                @http.use_ssl = true
         | 
| 38 | 
            +
                @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              def teardown
         | 
| 42 | 
            +
                @server.stop(true)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def test_url_scheme_for_https
         | 
| 46 | 
            +
                body = nil
         | 
| 47 | 
            +
                @http.start do
         | 
| 48 | 
            +
                  req = Net::HTTP::Get.new "/", {}
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  @http.request(req) do |rep|
         | 
| 51 | 
            +
                    body = rep.body
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                assert_equal "https", body
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              def test_very_large_return
         | 
| 59 | 
            +
                giant = "x" * 2056610
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                @server.app = proc do
         | 
| 62 | 
            +
                  [200, {}, [giant]]
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                body = nil
         | 
| 66 | 
            +
                @http.start do
         | 
| 67 | 
            +
                  req = Net::HTTP::Get.new "/"
         | 
| 68 | 
            +
                  @http.request(req) do |rep|
         | 
| 69 | 
            +
                    body = rep.body
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                assert_equal giant.bytesize, body.bytesize
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              def test_form_submit
         | 
| 77 | 
            +
                body = nil
         | 
| 78 | 
            +
                @http.start do
         | 
| 79 | 
            +
                  req = Net::HTTP::Post.new '/'
         | 
| 80 | 
            +
                  req.set_form_data('a' => '1', 'b' => '2')
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  @http.request(req) do |rep|
         | 
| 83 | 
            +
                    body = rep.body
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                assert_equal "https", body
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: puma
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2. | 
| 4 | 
            +
              version: 2.9.0
         | 
| 5 5 | 
             
            platform: java
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Evan Phoenix
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014- | 
| 11 | 
            +
            date: 2014-07-13 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rack
         | 
| @@ -50,12 +50,12 @@ dependencies: | |
| 50 50 | 
             
                requirements:
         | 
| 51 51 | 
             
                - - ~>
         | 
| 52 52 | 
             
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            -
                    version: 0.8 | 
| 53 | 
            +
                    version: '0.8'
         | 
| 54 54 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 55 55 | 
             
                requirements:
         | 
| 56 56 | 
             
                - - ~>
         | 
| 57 57 | 
             
                  - !ruby/object:Gem::Version
         | 
| 58 | 
            -
                    version: 0.8 | 
| 58 | 
            +
                    version: '0.8'
         | 
| 59 59 | 
             
              prerelease: false
         | 
| 60 60 | 
             
              type: :development
         | 
| 61 61 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -64,12 +64,12 @@ dependencies: | |
| 64 64 | 
             
                requirements:
         | 
| 65 65 | 
             
                - - ~>
         | 
| 66 66 | 
             
                  - !ruby/object:Gem::Version
         | 
| 67 | 
            -
                    version: '3. | 
| 67 | 
            +
                    version: '3.12'
         | 
| 68 68 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 69 69 | 
             
                requirements:
         | 
| 70 70 | 
             
                - - ~>
         | 
| 71 71 | 
             
                  - !ruby/object:Gem::Version
         | 
| 72 | 
            -
                    version: '3. | 
| 72 | 
            +
                    version: '3.12'
         | 
| 73 73 | 
             
              prerelease: false
         | 
| 74 74 | 
             
              type: :development
         | 
| 75 75 | 
             
            description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production environments. In order to get the best throughput, it is highly recommended that you use a  Ruby implementation with real threads like Rubinius or JRuby.
         | 
| @@ -140,7 +140,6 @@ files: | |
| 140 140 | 
             
            - lib/puma/jruby_restart.rb
         | 
| 141 141 | 
             
            - lib/puma/minissl.rb
         | 
| 142 142 | 
             
            - lib/puma/null_io.rb
         | 
| 143 | 
            -
            - lib/puma/puma_http11.jar
         | 
| 144 143 | 
             
            - lib/puma/rack_default.rb
         | 
| 145 144 | 
             
            - lib/puma/rack_patch.rb
         | 
| 146 145 | 
             
            - lib/puma/reactor.rb
         | 
| @@ -152,6 +151,14 @@ files: | |
| 152 151 | 
             
            - lib/puma/util.rb
         | 
| 153 152 | 
             
            - lib/rack/handler/puma.rb
         | 
| 154 153 | 
             
            - puma.gemspec
         | 
| 154 | 
            +
            - tools/jungle/README.md
         | 
| 155 | 
            +
            - tools/jungle/init.d/README.md
         | 
| 156 | 
            +
            - tools/jungle/init.d/puma
         | 
| 157 | 
            +
            - tools/jungle/init.d/run-puma
         | 
| 158 | 
            +
            - tools/jungle/upstart/README.md
         | 
| 159 | 
            +
            - tools/jungle/upstart/puma-manager.conf
         | 
| 160 | 
            +
            - tools/jungle/upstart/puma.conf
         | 
| 161 | 
            +
            - tools/trickletest.rb
         | 
| 155 162 | 
             
            - test/test_app_status.rb
         | 
| 156 163 | 
             
            - test/test_cli.rb
         | 
| 157 164 | 
             
            - test/test_config.rb
         | 
| @@ -163,23 +170,17 @@ files: | |
| 163 170 | 
             
            - test/test_null_io.rb
         | 
| 164 171 | 
             
            - test/test_persistent.rb
         | 
| 165 172 | 
             
            - test/test_puma_server.rb
         | 
| 173 | 
            +
            - test/test_puma_server_ssl.rb
         | 
| 166 174 | 
             
            - test/test_rack_handler.rb
         | 
| 167 175 | 
             
            - test/test_rack_server.rb
         | 
| 168 176 | 
             
            - test/test_tcp_rack.rb
         | 
| 169 177 | 
             
            - test/test_thread_pool.rb
         | 
| 170 178 | 
             
            - test/test_unix_socket.rb
         | 
| 171 179 | 
             
            - test/test_ws.rb
         | 
| 172 | 
            -
            -  | 
| 173 | 
            -
            - tools/jungle/init.d/README.md
         | 
| 174 | 
            -
            - tools/jungle/init.d/puma
         | 
| 175 | 
            -
            - tools/jungle/init.d/run-puma
         | 
| 176 | 
            -
            - tools/jungle/upstart/README.md
         | 
| 177 | 
            -
            - tools/jungle/upstart/puma-manager.conf
         | 
| 178 | 
            -
            - tools/jungle/upstart/puma.conf
         | 
| 179 | 
            -
            - tools/trickletest.rb
         | 
| 180 | 
            +
            - lib/puma/puma_http11.jar
         | 
| 180 181 | 
             
            homepage: http://puma.io
         | 
| 181 182 | 
             
            licenses:
         | 
| 182 | 
            -
            - BSD
         | 
| 183 | 
            +
            - BSD-3-Clause
         | 
| 183 184 | 
             
            metadata: {}
         | 
| 184 185 | 
             
            post_install_message:
         | 
| 185 186 | 
             
            rdoc_options:
         | 
| @@ -199,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 199 200 | 
             
                  version: '0'
         | 
| 200 201 | 
             
            requirements: []
         | 
| 201 202 | 
             
            rubyforge_project:
         | 
| 202 | 
            -
            rubygems_version: 2. | 
| 203 | 
            +
            rubygems_version: 2.1.9
         | 
| 203 204 | 
             
            signing_key:
         | 
| 204 205 | 
             
            specification_version: 4
         | 
| 205 206 | 
             
            summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications
         | 
| @@ -215,6 +216,7 @@ test_files: | |
| 215 216 | 
             
            - test/test_null_io.rb
         | 
| 216 217 | 
             
            - test/test_persistent.rb
         | 
| 217 218 | 
             
            - test/test_puma_server.rb
         | 
| 219 | 
            +
            - test/test_puma_server_ssl.rb
         | 
| 218 220 | 
             
            - test/test_rack_handler.rb
         | 
| 219 221 | 
             
            - test/test_rack_server.rb
         | 
| 220 222 | 
             
            - test/test_tcp_rack.rb
         |