diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..21ab797b32cf9f0a1b6c5d7f585aeef4d4457ffe
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,15 @@
+---
+after_script:
+- rake travis:after -t
+before_script:
+- gem install hoe-travis --no-rdoc --no-ri
+- rake travis:before -t
+language: ruby
+notifications:
+  email:
+  - drbrain@segment7.net
+rvm:
+- 2.1.10
+- 2.2.5
+- 2.3.1
+script: rake travis
diff --git a/History.txt b/History.txt
index e16c69a9be7d770bb50c0970956cdb9e3ccc2a96..7cff8904c77845ff414adb6b926a325cdb8dd2e4 100644
--- a/History.txt
+++ b/History.txt
@@ -1,3 +1,22 @@
+=== 3.0
+
+Breaking changes:
+
+* No longer supports ruby 2.0 and earlier
+* Net::HTTP::Persistent::new now uses keyword arguments for +name+ and
+  +proxy+.
+* Removed #max_age, use #expired?
+
+New features:
+
+* Uses connection_pool to manage all connections for a Net::HTTP::Persistent
+  instance.
+
+Bug fixes:
+
+* Add missing SSL options ca_path, ciphers, ssl_timeout, verify_depth.
+  Issue #63 by Johnneylee Jack Rollins.
+
 === 2.9.4 / 2014-02-10
 
 * Bug fixes
diff --git a/Manifest.txt b/Manifest.txt
index bc4063f773c78e502cb248b659c4cb7655c43124..e94aa627a8bb53c0d8e900213a62b22a4c223445 100644
--- a/Manifest.txt
+++ b/Manifest.txt
@@ -1,11 +1,13 @@
 .autotest
 .gemtest
+.travis.yml
 History.txt
 Manifest.txt
 README.rdoc
 Rakefile
-lib/net/http/faster.rb
 lib/net/http/persistent.rb
-lib/net/http/persistent/ssl_reuse.rb
+lib/net/http/persistent/connection.rb
+lib/net/http/persistent/pool.rb
+lib/net/http/persistent/timed_stack_multi.rb
 test/test_net_http_persistent.rb
-test/test_net_http_persistent_ssl_reuse.rb
+test/test_net_http_persistent_timed_stack_multi.rb
diff --git a/Rakefile b/Rakefile
index 9dfd9ba3c19711a3e3a5b834ec2aab445d93973d..499d4651febdb6a6526b7ba497193048310a06ff 100644
--- a/Rakefile
+++ b/Rakefile
@@ -13,12 +13,15 @@ Hoe.spec 'net-http-persistent' do
   self.readme_file      = 'README.rdoc'
   self.extra_rdoc_files += Dir['*.rdoc']
 
+  self.require_ruby_version '~> 2.1'
+
   license 'MIT'
 
   rdoc_locations <<
     'docs.seattlerb.org:/data/www/docs.seattlerb.org/net-http-persistent/'
 
-  dependency 'minitest', '~> 5.2', :development
+  dependency 'connection_pool', '~> 2.2'
+  dependency 'minitest',        '~> 5.2', :development
 end
 
 # vim: syntax=Ruby
diff --git a/checksums.yaml.gz b/checksums.yaml.gz
deleted file mode 100644
index abf74fa0cdbf95e427d6ea8d0d6d857e5d83f1ea..0000000000000000000000000000000000000000
Binary files a/checksums.yaml.gz and /dev/null differ
diff --git a/checksums.yaml.gz.sig b/checksums.yaml.gz.sig
index 2c41b0758ed6eca39c0298d005764cddce8f974f..b4adf6ed57ea5b9de34de7d6691f161acec3e9e7 100644
Binary files a/checksums.yaml.gz.sig and b/checksums.yaml.gz.sig differ
diff --git a/data.tar.gz.sig b/data.tar.gz.sig
index a93de4860225df3bdf99294a6938db125a1e76b5..01ac4e1cca19dbeb8f5debe5dd3795110e67425b 100644
Binary files a/data.tar.gz.sig and b/data.tar.gz.sig differ
diff --git a/lib/net/http/faster.rb b/lib/net/http/faster.rb
deleted file mode 100644
index e5e09080c27a45d84afa15d9bd0cbba9abcf5328..0000000000000000000000000000000000000000
--- a/lib/net/http/faster.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require 'net/protocol'
-
-##
-# Aaron Patterson's monkeypatch (accepted into 1.9.1) to fix Net::HTTP's speed
-# problems.
-#
-# http://gist.github.com/251244
-
-class Net::BufferedIO #:nodoc:
-  alias :old_rbuf_fill :rbuf_fill
-
-  def rbuf_fill
-    if @io.respond_to? :read_nonblock then
-      begin
-        @rbuf << @io.read_nonblock(65536)
-      rescue Errno::EWOULDBLOCK, Errno::EAGAIN => e
-        retry if IO.select [@io], nil, nil, @read_timeout
-        raise Timeout::Error, e.message
-      end
-    else # SSL sockets do not have read_nonblock
-      timeout @read_timeout do
-        @rbuf << @io.sysread(65536)
-      end
-    end
-  end
-end if RUBY_VERSION < '1.9'
-
diff --git a/lib/net/http/persistent.rb b/lib/net/http/persistent.rb
index 98e149004117f92e41390040e4c3fb2a5be18e1e..e6a110cd9db290a9a18d4c9c0f9dc6db3013b409 100644
--- a/lib/net/http/persistent.rb
+++ b/lib/net/http/persistent.rb
@@ -1,12 +1,7 @@
 require 'net/http'
-begin
-  require 'net/https'
-rescue LoadError
-  # net/https or openssl
-end if RUBY_VERSION < '1.9' # but only for 1.8
-require 'net/http/faster'
 require 'uri'
 require 'cgi' # for escaping
+require 'connection_pool'
 
 begin
   require 'net/http/pipeline'
@@ -70,13 +65,17 @@ autoload :OpenSSL, 'openssl'
 # Here are the SSL settings, see the individual methods for documentation:
 #
 # #certificate        :: This client's certificate
-# #ca_file            :: The certificate-authority
+# #ca_file            :: The certificate-authorities
+# #ca_path            :: Directory with certificate-authorities
 # #cert_store         :: An SSL certificate store
+# #ciphers            :: List of SSl ciphers allowed
 # #private_key        :: The client's SSL private key
 # #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new
 #                        connection
+# #ssl_timeout        :: SSL session lifetime
 # #ssl_version        :: Which specific SSL version to use
 # #verify_callback    :: For server certificate verification
+# #verify_depth       :: Depth of certificate verification
 # #verify_mode        :: How connections should be verified
 #
 # == Proxies
@@ -200,10 +199,15 @@ class Net::HTTP::Persistent
 
   HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc:
 
+  ##
+  # The default connection pool size is 1/4 the allowed open files.
+
+  DEFAULT_POOL_SIZE = Process.getrlimit(Process::RLIMIT_NOFILE).first / 4
+
   ##
   # The version of Net::HTTP::Persistent you are using
 
-  VERSION = '2.9.4'
+  VERSION = '3.0.0'
 
   ##
   # Exceptions rescued for automatic retry on ruby 2.0.0.  This overlaps with
@@ -248,31 +252,31 @@ class Net::HTTP::Persistent
 
     http = new 'net-http-persistent detect_idle_timeout'
 
-    connection = http.connection_for uri
+    http.connection_for uri do |connection|
+      sleep_time = 0
 
-    sleep_time = 0
+      http = connection.http
 
-    loop do
-      response = connection.request req
+      loop do
+        response = http.request req
 
-      $stderr.puts "HEAD #{uri} => #{response.code}" if $DEBUG
+        $stderr.puts "HEAD #{uri} => #{response.code}" if $DEBUG
 
-      unless Net::HTTPOK === response then
-        raise Error, "bad response code #{response.code} detecting idle timeout"
-      end
+        unless Net::HTTPOK === response then
+          raise Error, "bad response code #{response.code} detecting idle timeout"
+        end
 
-      break if sleep_time >= max
+        break if sleep_time >= max
 
-      sleep_time += 1
+        sleep_time += 1
 
-      $stderr.puts "sleeping #{sleep_time}" if $DEBUG
-      sleep sleep_time
+        $stderr.puts "sleeping #{sleep_time}" if $DEBUG
+        sleep sleep_time
+      end
     end
   rescue
     # ignore StandardErrors, we've probably found the idle timeout.
   ensure
-    http.shutdown
-
     return sleep_time unless $!
   end
 
@@ -281,7 +285,9 @@ class Net::HTTP::Persistent
 
   attr_reader :certificate
 
+  ##
   # For Net::HTTP parity
+
   alias cert certificate
 
   ##
@@ -290,12 +296,23 @@ class Net::HTTP::Persistent
 
   attr_reader :ca_file
 
+  ##
+  # A directory of SSL certificates to be used as certificate authorities.
+  # Setting this will set verify_mode to VERIFY_PEER.
+
+  attr_reader :ca_path
+
   ##
   # An SSL certificate store.  Setting this will override the default
   # certificate store.  See verify_mode for more information.
 
   attr_reader :cert_store
 
+  ##
+  # The ciphers allowed for SSL connections
+
+  attr_reader :ciphers
+
   ##
   # Sends debug_output to this IO via Net::HTTP#set_debug_output.
   #
@@ -309,11 +326,6 @@ class Net::HTTP::Persistent
 
   attr_reader :generation # :nodoc:
 
-  ##
-  # Where this instance's connections live in the thread local variables
-
-  attr_reader :generation_key # :nodoc:
-
   ##
   # Headers that are added to every request using Net::HTTP#add_field
 
@@ -369,7 +381,9 @@ class Net::HTTP::Persistent
 
   attr_reader :private_key
 
+  ##
   # For Net::HTTP parity
+
   alias key private_key
 
   ##
@@ -383,14 +397,14 @@ class Net::HTTP::Persistent
   attr_reader :no_proxy
 
   ##
-  # Seconds to wait until reading one block.  See Net::HTTP#read_timeout
+  # Test-only accessor for the connection pool
 
-  attr_accessor :read_timeout
+  attr_reader :pool # :nodoc:
 
   ##
-  # Where this instance's request counts live in the thread local variables
+  # Seconds to wait until reading one block.  See Net::HTTP#read_timeout
 
-  attr_reader :request_key # :nodoc:
+  attr_accessor :read_timeout
 
   ##
   # By default SSL sessions are reused to avoid extra SSL handshakes.  Set
@@ -418,9 +432,9 @@ class Net::HTTP::Persistent
   attr_reader :ssl_generation # :nodoc:
 
   ##
-  # Where this instance's SSL connections live in the thread local variables
+  # SSL session lifetime
 
-  attr_reader :ssl_generation_key # :nodoc:
+  attr_reader :ssl_timeout
 
   ##
   # SSL version to use.
@@ -428,7 +442,7 @@ class Net::HTTP::Persistent
   # By default, the version will be negotiated automatically between client
   # and server.  Ruby 1.9 and newer only.
 
-  attr_reader :ssl_version if RUBY_VERSION > '1.9'
+  attr_reader :ssl_version
 
   ##
   # Where this instance's last-use times live in the thread local variables
@@ -436,16 +450,21 @@ class Net::HTTP::Persistent
   attr_reader :timeout_key # :nodoc:
 
   ##
-  # SSL verification callback.  Used when ca_file is set.
+  # SSL verification callback.  Used when ca_file or ca_path is set.
 
   attr_reader :verify_callback
 
+  ##
+  # Sets the depth of SSL certificate verification
+
+  attr_reader :verify_depth
+
   ##
   # HTTPS verify mode.  Defaults to OpenSSL::SSL::VERIFY_PEER which verifies
   # the server certificate.
   #
-  # If no ca_file or cert_store is set the default system certificate store is
-  # used.
+  # If no ca_file, ca_path or cert_store is set the default system certificate
+  # store is used.
   #
   # You can use +verify_mode+ to override any default values.
 
@@ -478,8 +497,12 @@ class Net::HTTP::Persistent
   #   proxy = URI 'http://proxy.example'
   #   proxy.user     = 'AzureDiamond'
   #   proxy.password = 'hunter2'
+  #
+  # Set +pool_size+ to limit the maximum number of connections allowed.
+  # Defaults to 1/4 the number of allowed file handles.  You can have no more
+  # than this many threads with active HTTP transactions.
 
-  def initialize name = nil, proxy = nil
+  def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE
     @name = name
 
     @debug_output     = nil
@@ -494,26 +517,28 @@ class Net::HTTP::Persistent
     @idle_timeout     = 5
     @max_requests     = nil
     @socket_options   = []
+    @ssl_generation   = 0 # incremented when SSL session variables change
 
     @socket_options << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if
       Socket.const_defined? :TCP_NODELAY
 
-    key = ['net_http_persistent', name].compact
-    @generation_key     = [key, 'generations'    ].join('_').intern
-    @ssl_generation_key = [key, 'ssl_generations'].join('_').intern
-    @request_key        = [key, 'requests'       ].join('_').intern
-    @timeout_key        = [key, 'timeouts'       ].join('_').intern
+    @pool = Net::HTTP::Persistent::Pool.new size: pool_size do |http_args|
+      Net::HTTP::Persistent::Connection.new Net::HTTP, http_args, @ssl_generation
+    end
 
     @certificate        = nil
     @ca_file            = nil
+    @ca_path            = nil
+    @ciphers            = nil
     @private_key        = nil
+    @ssl_timeout        = nil
     @ssl_version        = nil
     @verify_callback    = nil
+    @verify_depth       = nil
     @verify_mode        = nil
     @cert_store         = nil
 
     @generation         = 0 # incremented when proxy URI changes
-    @ssl_generation     = 0 # incremented when SSL session variables change
 
     if HAVE_OPENSSL then
       @verify_mode        = OpenSSL::SSL::VERIFY_PEER
@@ -522,9 +547,6 @@ class Net::HTTP::Persistent
 
     @retry_change_requests = false
 
-    @ruby_1 = RUBY_VERSION < '2'
-    @retried_on_ruby_2 = !@ruby_1
-
     self.proxy = proxy if proxy
   end
 
@@ -549,6 +571,15 @@ class Net::HTTP::Persistent
     reconnect_ssl
   end
 
+  ##
+  # Sets the SSL certificate authority path.
+
+  def ca_path= path
+    @ca_path = path
+
+    reconnect_ssl
+  end
+
   ##
   # Overrides the default SSL certificate store used for verifying
   # connections.
@@ -560,90 +591,55 @@ class Net::HTTP::Persistent
   end
 
   ##
-  # Finishes all connections on the given +thread+ that were created before
-  # the given +generation+ in the threads +generation_key+ list.
-  #
-  # See #shutdown for a bunch of scary warning about misusing this method.
-
-  def cleanup(generation, thread = Thread.current,
-              generation_key = @generation_key) # :nodoc:
-    timeouts = thread[@timeout_key]
+  # The ciphers allowed for SSL connections
 
-    (0...generation).each do |old_generation|
-      next unless thread[generation_key]
+  def ciphers= ciphers
+    @ciphers = ciphers
 
-      conns = thread[generation_key].delete old_generation
-
-      conns.each_value do |conn|
-        finish conn, thread
-
-        timeouts.delete conn.object_id if timeouts
-      end if conns
-    end
+    reconnect_ssl
   end
 
   ##
   # Creates a new connection for +uri+
 
   def connection_for uri
-    Thread.current[@generation_key]     ||= Hash.new { |h,k| h[k] = {} }
-    Thread.current[@ssl_generation_key] ||= Hash.new { |h,k| h[k] = {} }
-    Thread.current[@request_key]        ||= Hash.new 0
-    Thread.current[@timeout_key]        ||= Hash.new EPOCH
-
     use_ssl = uri.scheme.downcase == 'https'
 
-    if use_ssl then
-      raise Net::HTTP::Persistent::Error, 'OpenSSL is not available' unless
-        HAVE_OPENSSL
-
-      ssl_generation = @ssl_generation
-
-      ssl_cleanup ssl_generation
+    net_http_args = [uri.host, uri.port]
 
-      connections = Thread.current[@ssl_generation_key][ssl_generation]
-    else
-      generation = @generation
+    net_http_args.concat @proxy_args if
+      @proxy_uri and not proxy_bypass? uri.host, uri.port
 
-      cleanup generation
+    connection = @pool.checkout net_http_args
 
-      connections = Thread.current[@generation_key][generation]
-    end
+    http = connection.http
 
-    net_http_args = [uri.host, uri.port]
-    connection_id = net_http_args.join ':'
+    connection.ressl @ssl_generation if
+      connection.ssl_generation != @ssl_generation
 
-    if @proxy_uri and not proxy_bypass? uri.host, uri.port then
-      connection_id << @proxy_connection_id
-      net_http_args.concat @proxy_args
-    end
-
-    connection = connections[connection_id]
-
-    unless connection = connections[connection_id] then
-      connections[connection_id] = http_class.new(*net_http_args)
-      connection = connections[connection_id]
-      ssl connection if use_ssl
-    else
-      reset connection if expired? connection
+    if not http.started? then
+      ssl   http if use_ssl
+      start http
+    elsif expired? connection then
+      reset connection
     end
 
-    start connection unless connection.started?
-
-    connection.read_timeout = @read_timeout if @read_timeout
-    connection.keep_alive_timeout = @idle_timeout if @idle_timeout && connection.respond_to?(:keep_alive_timeout=)
+    http.read_timeout = @read_timeout if @read_timeout
+    http.keep_alive_timeout = @idle_timeout if @idle_timeout
 
-    connection
+    return yield connection
   rescue Errno::ECONNREFUSED
-    address = connection.proxy_address || connection.address
-    port    = connection.proxy_port    || connection.port
+    address = http.proxy_address || http.address
+    port    = http.proxy_port    || http.port
 
     raise Error, "connection refused: #{address}:#{port}"
   rescue Errno::EHOSTDOWN
-    address = connection.proxy_address || connection.address
-    port    = connection.proxy_port    || connection.port
+    address = http.proxy_address || http.address
+    port    = http.proxy_port    || http.port
 
     raise Error, "host down: #{address}:#{port}"
+  ensure
+    @pool.checkin net_http_args
   end
 
   ##
@@ -651,12 +647,11 @@ class Net::HTTP::Persistent
   # this connection
 
   def error_message connection
-    requests = Thread.current[@request_key][connection.object_id] - 1 # fixup
-    last_use = Thread.current[@timeout_key][connection.object_id]
+    connection.requests -= 1 # fixup
 
-    age = Time.now - last_use
+    age = Time.now - connection.last_use
 
-    "after #{requests} requests on #{connection.object_id}, " \
+    "after #{connection.requests} requests on #{connection.http.object_id}, " \
       "last used #{age} seconds ago"
   end
 
@@ -680,26 +675,23 @@ class Net::HTTP::Persistent
   # maximum request count, false otherwise.
 
   def expired? connection
-    requests = Thread.current[@request_key][connection.object_id]
-    return true  if     @max_requests && requests >= @max_requests
+    return true  if     @max_requests && connection.requests >= @max_requests
     return false unless @idle_timeout
     return true  if     @idle_timeout.zero?
 
-    last_used = Thread.current[@timeout_key][connection.object_id]
-
-    Time.now - last_used > @idle_timeout
+    Time.now - connection.last_use > @idle_timeout
   end
 
   ##
   # Starts the Net::HTTP +connection+
 
-  def start connection
-    connection.set_debug_output @debug_output if @debug_output
-    connection.open_timeout = @open_timeout if @open_timeout
+  def start http
+    http.set_debug_output @debug_output if @debug_output
+    http.open_timeout = @open_timeout if @open_timeout
 
-    connection.start
+    http.start
 
-    socket = connection.instance_variable_get :@socket
+    socket = http.instance_variable_get :@socket
 
     if socket then # for fakeweb
       @socket_options.each do |option|
@@ -711,25 +703,11 @@ class Net::HTTP::Persistent
   ##
   # Finishes the Net::HTTP +connection+
 
-  def finish connection, thread = Thread.current
-    if requests = thread[@request_key] then
-      requests.delete connection.object_id
-    end
-
+  def finish connection
     connection.finish
-  rescue IOError
-  end
 
-  def http_class # :nodoc:
-    if RUBY_VERSION > '2.0' then
-      Net::HTTP
-    elsif [:Artifice, :FakeWeb, :WebMock].any? { |klass|
-             Object.const_defined?(klass)
-          } or not @reuse_ssl_sessions then
-        Net::HTTP
-    else
-      Net::HTTP::Persistent::SSLReuse
-    end
+    connection.http.instance_variable_set :@ssl_session, nil unless
+      @reuse_ssl_sessions
   end
 
   ##
@@ -752,55 +730,9 @@ class Net::HTTP::Persistent
 
   ##
   # Is the request +req+ idempotent or is retry_change_requests allowed.
-  #
-  # If +retried_on_ruby_2+ is true, true will be returned if we are on ruby,
-  # retry_change_requests is allowed and the request is not idempotent.
-
-  def can_retry? req, retried_on_ruby_2 = false
-    return @retry_change_requests && !idempotent?(req) if retried_on_ruby_2
 
-    @retry_change_requests || idempotent?(req)
-  end
-
-  if RUBY_VERSION > '1.9' then
-    ##
-    # Workaround for missing Net::HTTPHeader#connection_close? on Ruby 1.8
-
-    def connection_close? header
-      header.connection_close?
-    end
-
-    ##
-    # Workaround for missing Net::HTTPHeader#connection_keep_alive? on Ruby 1.8
-
-    def connection_keep_alive? header
-      header.connection_keep_alive?
-    end
-  else
-    ##
-    # Workaround for missing Net::HTTPRequest#connection_close? on Ruby 1.8
-
-    def connection_close? header
-      header['connection'] =~ /close/ or header['proxy-connection'] =~ /close/
-    end
-
-    ##
-    # Workaround for missing Net::HTTPRequest#connection_keep_alive? on Ruby
-    # 1.8
-
-    def connection_keep_alive? header
-      header['connection'] =~ /keep-alive/ or
-        header['proxy-connection'] =~ /keep-alive/
-    end
-  end
-
-  ##
-  # Deprecated in favor of #expired?
-
-  def max_age # :nodoc:
-    return Time.now + 1 unless @idle_timeout
-
-    Time.now - @idle_timeout
+  def can_retry? req
+    @retry_change_requests && !idempotent?(req)
   end
 
   ##
@@ -822,9 +754,9 @@ class Net::HTTP::Persistent
   # <tt>net-http-persistent</tt> #pipeline will be present.
 
   def pipeline uri, requests, &block # :yields: responses
-    connection = connection_for uri
-
-    connection.pipeline requests, &block
+    connection_for uri do |connection|
+      connection.http.pipeline requests, &block
+    end
   end
 
   ##
@@ -957,18 +889,17 @@ class Net::HTTP::Persistent
   # Finishes then restarts the Net::HTTP +connection+
 
   def reset connection
-    Thread.current[@request_key].delete connection.object_id
-    Thread.current[@timeout_key].delete connection.object_id
+    http = connection.http
 
     finish connection
 
-    start connection
+    start http
   rescue Errno::ECONNREFUSED
-    e = Error.new "connection refused: #{connection.address}:#{connection.port}"
+    e = Error.new "connection refused: #{http.address}:#{http.port}"
     e.set_backtrace $@
     raise e
   rescue Errno::EHOSTDOWN
-    e = Error.new "host down: #{connection.address}:#{connection.port}"
+    e = Error.new "host down: #{http.address}:#{http.port}"
     e.set_backtrace $@
     raise e
   end
@@ -989,52 +920,56 @@ class Net::HTTP::Persistent
     retried      = false
     bad_response = false
 
-    req = request_setup req || uri
+    uri      = URI uri
+    req      = request_setup req || uri
+    response = nil
 
-    connection = connection_for uri
-    connection_id = connection.object_id
+    connection_for uri do |connection|
+      http = connection.http
 
-    begin
-      Thread.current[@request_key][connection_id] += 1
-      response = connection.request req, &block
+      begin
+        connection.requests += 1
 
-      if connection_close?(req) or
-         (response.http_version <= '1.0' and
-          not connection_keep_alive?(response)) or
-         connection_close?(response) then
-        connection.finish
-      end
-    rescue Net::HTTPBadResponse => e
-      message = error_message connection
+        response = http.request req, &block
 
-      finish connection
+        if req.connection_close? or
+           (response.http_version <= '1.0' and
+            not response.connection_keep_alive?) or
+           response.connection_close? then
+          finish connection
+        end
+      rescue Net::HTTPBadResponse => e
+        message = error_message connection
 
-      raise Error, "too many bad responses #{message}" if
+        finish connection
+
+        raise Error, "too many bad responses #{message}" if
         bad_response or not can_retry? req
 
-      bad_response = true
-      retry
-    rescue *RETRIED_EXCEPTIONS => e # retried on ruby 2
-      request_failed e, req, connection if
-        retried or not can_retry? req, @retried_on_ruby_2
+        bad_response = true
+        retry
+      rescue *RETRIED_EXCEPTIONS => e
+        request_failed e, req, connection if
+          retried or not can_retry? req
 
-      reset connection
+        reset connection
 
-      retried = true
-      retry
-    rescue Errno::EINVAL, Errno::ETIMEDOUT => e # not retried on ruby 2
-      request_failed e, req, connection if retried or not can_retry? req
+        retried = true
+        retry
+      rescue Errno::EINVAL, Errno::ETIMEDOUT => e # not retried on ruby 2
+        request_failed e, req, connection if retried or not can_retry? req
 
-      reset connection
+        reset connection
 
-      retried = true
-      retry
-    rescue Exception => e
-      finish connection
+        retried = true
+        retry
+      rescue Exception => e
+        finish connection
 
-      raise
-    ensure
-      Thread.current[@timeout_key][connection_id] = Time.now
+        raise
+      ensure
+        connection.last_use = Time.now
+      end
     end
 
     @http_versions["#{uri.host}:#{uri.port}"] ||= response.http_version
@@ -1054,7 +989,6 @@ class Net::HTTP::Persistent
 
     finish connection
 
-
     raise Error, message, exception.backtrace
   end
 
@@ -1088,45 +1022,17 @@ class Net::HTTP::Persistent
   end
 
   ##
-  # Shuts down all connections for +thread+.
-  #
-  # Uses the current thread by default.
-  #
-  # If you've used Net::HTTP::Persistent across multiple threads you should
-  # call this in each thread when you're done making HTTP requests.
+  # Shuts down all connections
   #
-  # *NOTE*: Calling shutdown for another thread can be dangerous!
+  # *NOTE*: Calling shutdown for can be dangerous!
   #
-  # If the thread is still using the connection it may cause an error!  It is
-  # best to call #shutdown in the thread at the appropriate time instead!
+  # If any thread is still using a connection it may cause an error!  Call
+  # #shutdown when you are completely done making requests!
 
-  def shutdown thread = Thread.current
-    generation = reconnect
-    cleanup generation, thread, @generation_key
-
-    ssl_generation = reconnect_ssl
-    cleanup ssl_generation, thread, @ssl_generation_key
-
-    thread[@request_key] = nil
-    thread[@timeout_key] = nil
-  end
-
-  ##
-  # Shuts down all connections in all threads
-  #
-  # *NOTE*: THIS METHOD IS VERY DANGEROUS!
-  #
-  # Do not call this method if other threads are still using their
-  # connections!  Call #shutdown at the appropriate time instead!
-  #
-  # Use this method only as a last resort!
-
-  def shutdown_in_all_threads
-    Thread.list.each do |thread|
-      shutdown thread
+  def shutdown
+    @pool.available.shutdown do |http|
+      http.finish
     end
-
-    nil
   end
 
   ##
@@ -1135,9 +1041,12 @@ class Net::HTTP::Persistent
   def ssl connection
     connection.use_ssl = true
 
+    connection.ciphers     = @ciphers     if @ciphers
+    connection.ssl_timeout = @ssl_timeout if @ssl_timeout
     connection.ssl_version = @ssl_version if @ssl_version
 
-    connection.verify_mode = @verify_mode
+    connection.verify_depth = @verify_depth
+    connection.verify_mode  = @verify_mode
 
     if OpenSSL::SSL::VERIFY_PEER == OpenSSL::SSL::VERIFY_NONE and
        not Object.const_defined?(:I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG) then
@@ -1166,8 +1075,10 @@ application:
       WARNING
     end
 
-    if @ca_file then
-      connection.ca_file = @ca_file
+    connection.ca_file = @ca_file if @ca_file
+    connection.ca_path = @ca_path if @ca_path
+
+    if @ca_file or @ca_path then
       connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
       connection.verify_callback = @verify_callback if @verify_callback
     end
@@ -1187,11 +1098,12 @@ application:
   end
 
   ##
-  # Finishes all connections that existed before the given SSL parameter
-  # +generation+.
+  # SSL session lifetime
 
-  def ssl_cleanup generation # :nodoc:
-    cleanup generation, Thread.current, @ssl_generation_key
+  def ssl_timeout= ssl_timeout
+    @ssl_timeout = ssl_timeout
+
+    reconnect_ssl
   end
 
   ##
@@ -1201,7 +1113,16 @@ application:
     @ssl_version = ssl_version
 
     reconnect_ssl
-  end if RUBY_VERSION > '1.9'
+  end
+
+  ##
+  # Sets the depth of SSL certificate verification
+
+  def verify_depth= verify_depth
+    @verify_depth = verify_depth
+
+    reconnect_ssl
+  end
 
   ##
   # Sets the HTTPS verify mode.  Defaults to OpenSSL::SSL::VERIFY_PEER.
@@ -1227,5 +1148,6 @@ application:
 
 end
 
-require 'net/http/persistent/ssl_reuse'
+require 'net/http/persistent/connection'
+require 'net/http/persistent/pool'
 
diff --git a/lib/net/http/persistent/connection.rb b/lib/net/http/persistent/connection.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4e1c6018af0a5fa0059bc8d2c571f87dc2b8bb6f
--- /dev/null
+++ b/lib/net/http/persistent/connection.rb
@@ -0,0 +1,40 @@
+##
+# A Net::HTTP connection wrapper that holds extra information for managing the
+# connection's lifetime.
+
+class Net::HTTP::Persistent::Connection # :nodoc:
+
+  attr_accessor :http
+
+  attr_accessor :last_use
+
+  attr_accessor :requests
+
+  attr_accessor :ssl_generation
+
+  def initialize http_class, http_args, ssl_generation
+    @http           = http_class.new(*http_args)
+    @ssl_generation = ssl_generation
+
+    reset
+  end
+
+  def finish
+    @http.finish
+  rescue IOError
+  ensure
+    reset
+  end
+
+  def reset
+    @last_use = Net::HTTP::Persistent::EPOCH
+    @requests = 0
+  end
+
+  def ressl ssl_generation
+    @ssl_generation = ssl_generation
+
+    finish
+  end
+
+end
diff --git a/lib/net/http/persistent/pool.rb b/lib/net/http/persistent/pool.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b88dd592a43ccf7877691dc556e96d34406278ea
--- /dev/null
+++ b/lib/net/http/persistent/pool.rb
@@ -0,0 +1,46 @@
+class Net::HTTP::Persistent::Pool < ConnectionPool # :nodoc:
+
+  attr_reader :available # :nodoc:
+  attr_reader :key # :nodoc:
+
+  def initialize(options = {}, &block)
+    super
+
+    @available = Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
+    @key = :"current-#{@available.object_id}"
+  end
+
+  def checkin net_http_args
+    stack = Thread.current[@key][net_http_args]
+
+    raise ConnectionPool::Error, 'no connections are checked out' if
+      stack.empty?
+
+    conn = stack.pop
+
+    if stack.empty?
+      @available.push conn, connection_args: net_http_args
+    end
+
+    nil
+  end
+
+  def checkout net_http_args
+    stacks = Thread.current[@key] ||= Hash.new { |h, k| h[k] = [] }
+    stack  = stacks[net_http_args]
+
+    if stack.empty? then
+      conn = @available.pop connection_args: net_http_args
+    else
+      conn = stack.last
+    end
+
+    stack.push conn
+
+    conn
+  end
+
+end
+
+require 'net/http/persistent/timed_stack_multi'
+
diff --git a/lib/net/http/persistent/ssl_reuse.rb b/lib/net/http/persistent/ssl_reuse.rb
deleted file mode 100644
index 05139703cfb30e32a324b358b98319ab2678cf13..0000000000000000000000000000000000000000
--- a/lib/net/http/persistent/ssl_reuse.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-##
-# This Net::HTTP subclass adds SSL session reuse and Server Name Indication
-# (SNI) RFC 3546.
-#
-# DO NOT DEPEND UPON THIS CLASS
-#
-# This class is an implementation detail and is subject to change or removal
-# at any time.
-
-class Net::HTTP::Persistent::SSLReuse < Net::HTTP
-
-  @is_proxy_class = false
-  @proxy_addr = nil
-  @proxy_port = nil
-  @proxy_user = nil
-  @proxy_pass = nil
-
-  def initialize address, port = nil # :nodoc:
-    super
-
-    @ssl_session = nil
-  end
-
-  ##
-  # From ruby trunk r33086 including http://redmine.ruby-lang.org/issues/5341
-
-  def connect # :nodoc:
-    D "opening connection to #{conn_address()}..."
-    s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
-    D "opened"
-    if use_ssl?
-      ssl_parameters = Hash.new
-      iv_list = instance_variables
-      SSL_ATTRIBUTES.each do |name|
-        ivname = "@#{name}".intern
-        if iv_list.include?(ivname) and
-           value = instance_variable_get(ivname)
-          ssl_parameters[name] = value
-        end
-      end
-      unless @ssl_context then
-        @ssl_context = OpenSSL::SSL::SSLContext.new
-        @ssl_context.set_params(ssl_parameters)
-      end
-      s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
-      s.sync_close = true
-    end
-    @socket = Net::BufferedIO.new(s)
-    @socket.read_timeout = @read_timeout
-    @socket.continue_timeout = @continue_timeout if
-      @socket.respond_to? :continue_timeout
-    @socket.debug_output = @debug_output
-    if use_ssl?
-      begin
-        if proxy?
-          @socket.writeline sprintf('CONNECT %s:%s HTTP/%s',
-                                    @address, @port, HTTPVersion)
-          @socket.writeline "Host: #{@address}:#{@port}"
-          if proxy_user
-            credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
-            credential.delete!("\r\n")
-            @socket.writeline "Proxy-Authorization: Basic #{credential}"
-          end
-          @socket.writeline ''
-          Net::HTTPResponse.read_new(@socket).value
-        end
-        s.session = @ssl_session if @ssl_session
-        # Server Name Indication (SNI) RFC 3546
-        s.hostname = @address if s.respond_to? :hostname=
-        timeout(@open_timeout) { s.connect }
-        if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
-          s.post_connection_check(@address)
-        end
-        @ssl_session = s.session
-      rescue => exception
-        D "Conn close because of connect error #{exception}"
-        @socket.close if @socket and not @socket.closed?
-        raise exception
-      end
-    end
-    on_connect
-  end if RUBY_VERSION > '1.9'
-
-  ##
-  # From ruby_1_8_7 branch r29865 including a modified
-  # http://redmine.ruby-lang.org/issues/5341
-
-  def connect # :nodoc:
-    D "opening connection to #{conn_address()}..."
-    s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
-    D "opened"
-    if use_ssl?
-      unless @ssl_context.verify_mode
-        warn "warning: peer certificate won't be verified in this SSL session"
-        @ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
-      end
-      s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
-      s.sync_close = true
-    end
-    @socket = Net::BufferedIO.new(s)
-    @socket.read_timeout = @read_timeout
-    @socket.debug_output = @debug_output
-    if use_ssl?
-      if proxy?
-        @socket.writeline sprintf('CONNECT %s:%s HTTP/%s',
-                                  @address, @port, HTTPVersion)
-        @socket.writeline "Host: #{@address}:#{@port}"
-        if proxy_user
-          credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
-          credential.delete!("\r\n")
-          @socket.writeline "Proxy-Authorization: Basic #{credential}"
-        end
-        @socket.writeline ''
-        Net::HTTPResponse.read_new(@socket).value
-      end
-      s.session = @ssl_session if @ssl_session
-      s.connect
-      if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
-        s.post_connection_check(@address)
-      end
-      @ssl_session = s.session
-    end
-    on_connect
-  end if RUBY_VERSION < '1.9'
-
-  private :connect
-
-end
-
diff --git a/lib/net/http/persistent/timed_stack_multi.rb b/lib/net/http/persistent/timed_stack_multi.rb
new file mode 100644
index 0000000000000000000000000000000000000000..991387d2e1959f679ac90e4bb0e4e89c3c503903
--- /dev/null
+++ b/lib/net/http/persistent/timed_stack_multi.rb
@@ -0,0 +1,69 @@
+class Net::HTTP::Persistent::TimedStackMulti < ConnectionPool::TimedStack # :nodoc:
+
+  def initialize(size = 0, &block)
+    super
+
+    @enqueued = 0
+    @ques = Hash.new { |h, k| h[k] = [] }
+    @lru = {}
+    @key = :"connection_args-#{object_id}"
+  end
+
+  def empty?
+    (@created - @enqueued) >= @max
+  end
+
+  def length
+    @max - @created + @enqueued
+  end
+
+  private
+
+  def connection_stored? options = {} # :nodoc:
+    !@ques[options[:connection_args]].empty?
+  end
+
+  def fetch_connection options = {} # :nodoc:
+    connection_args = options[:connection_args]
+
+    @enqueued -= 1
+    lru_update connection_args
+    @ques[connection_args].pop
+  end
+
+  def lru_update connection_args # :nodoc:
+    @lru.delete connection_args
+    @lru[connection_args] = true
+  end
+
+  def shutdown_connections # :nodoc:
+    @ques.each_key do |key|
+      super connection_args: key
+    end
+  end
+
+  def store_connection obj, options = {} # :nodoc:
+    @ques[options[:connection_args]].push obj
+    @enqueued += 1
+  end
+
+  def try_create options = {} # :nodoc:
+    connection_args = options[:connection_args]
+
+    if @created >= @max && @enqueued >= 1
+      oldest, = @lru.first
+      @lru.delete oldest
+      @ques[oldest].pop
+
+      @created -= 1
+    end
+
+    if @created < @max
+      @created += 1
+      lru_update connection_args
+      return @create_block.call(connection_args)
+    end
+  end
+
+end
+
diff --git a/metadata.gz.sig b/metadata.gz.sig
index 9ee352956a08b79d7ab0ee4bfa61dc3440f6b92c..379b94c1e578e31d9e2166e0478b0014aeb9ab3c 100644
Binary files a/metadata.gz.sig and b/metadata.gz.sig differ
diff --git a/metadata.yml b/metadata.yml
deleted file mode 100644
index 12fb19d10424a7317e94a70d4d1204d4a4b3de27..0000000000000000000000000000000000000000
--- a/metadata.yml
+++ /dev/null
@@ -1,137 +0,0 @@
---- !ruby/object:Gem::Specification
-name: net-http-persistent
-version: !ruby/object:Gem::Version
-  version: 2.9.4
-platform: ruby
-authors:
-- Eric Hodel
-autorequire: 
-bindir: bin
-cert_chain:
-- |
-  -----BEGIN CERTIFICATE-----
-  MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
-  YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
-  ZXQwHhcNMTMwMjI4MDUyMjA4WhcNMTQwMjI4MDUyMjA4WjBBMRAwDgYDVQQDDAdk
-  cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
-  FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
-  LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
-  U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
-  Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
-  mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
-  g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
-  sCANiQ8BAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
-  BBS5k4Z75VSpdM0AclG2UvzFA/VW5DAfBgNVHREEGDAWgRRkcmJyYWluQHNlZ21l
-  bnQ3Lm5ldDAfBgNVHRIEGDAWgRRkcmJyYWluQHNlZ21lbnQ3Lm5ldDANBgkqhkiG
-  9w0BAQUFAAOCAQEAOflo4Md5aJF//EetzXIGZ2EI5PzKWX/mMpp7cxFyDcVPtTv0
-  js/6zWrWSbd60W9Kn4ch3nYiATFKhisgeYotDDz2/pb/x1ivJn4vEvs9kYKVvbF8
-  V7MV/O5HDW8Q0pA1SljI6GzcOgejtUMxZCyyyDdbUpyAMdt9UpqTZkZ5z1sicgQk
-  5o2XJ+OhceOIUVqVh1r6DNY5tLVaGJabtBmJAYFVznDcHiSFybGKBa5n25Egql1t
-  KDyY1VIazVgoC8XvR4h/95/iScPiuglzA+DBG1hip1xScAtw05BrXyUNrc9CEMYU
-  wgF94UVoHRp6ywo8I7NP3HcwFQDFNEZPNGXsng==
-  -----END CERTIFICATE-----
-date: 2014-02-10 00:00:00.000000000 Z
-dependencies:
-- !ruby/object:Gem::Dependency
-  name: minitest
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '5.2'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '5.2'
-- !ruby/object:Gem::Dependency
-  name: rdoc
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '4.0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '4.0'
-- !ruby/object:Gem::Dependency
-  name: hoe
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '3.7'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '3.7'
-description: |-
-  Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8.
-  It's thread-safe too!
-
-  Using persistent HTTP connections can dramatically increase the speed of HTTP.
-  Creating a new HTTP connection for every request involves an extra TCP
-  round-trip and causes TCP congestion avoidance negotiation to start over.
-
-  Net::HTTP supports persistent connections with some API methods but does not
-  handle reconnection gracefully.  Net::HTTP::Persistent supports reconnection
-  and retry according to RFC 2616.
-email:
-- drbrain@segment7.net
-executables: []
-extensions: []
-extra_rdoc_files:
-- History.txt
-- Manifest.txt
-- README.rdoc
-files:
-- ".autotest"
-- ".gemtest"
-- History.txt
-- Manifest.txt
-- README.rdoc
-- Rakefile
-- lib/net/http/faster.rb
-- lib/net/http/persistent.rb
-- lib/net/http/persistent/ssl_reuse.rb
-- test/test_net_http_persistent.rb
-- test/test_net_http_persistent_ssl_reuse.rb
-homepage: http://docs.seattlerb.org/net-http-persistent
-licenses:
-- MIT
-metadata: {}
-post_install_message: 
-rdoc_options:
-- "--main"
-- README.rdoc
-require_paths:
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement
-  requirements:
-  - - ">="
-    - !ruby/object:Gem::Version
-      version: '0'
-required_rubygems_version: !ruby/object:Gem::Requirement
-  requirements:
-  - - ">="
-    - !ruby/object:Gem::Version
-      version: '0'
-requirements: []
-rubyforge_project: net-http-persistent
-rubygems_version: 2.2.1
-signing_key: 
-specification_version: 4
-summary: Manages persistent connections using Net::HTTP plus a speed fix for Ruby
-  1.8
-test_files:
-- test/test_net_http_persistent.rb
-- test/test_net_http_persistent_ssl_reuse.rb
diff --git a/net-http-persistent.gemspec b/net-http-persistent.gemspec
new file mode 100644
index 0000000000000000000000000000000000000000..e1c08eaf6e55b15573d926ec526fc8ad47bfdd0a
--- /dev/null
+++ b/net-http-persistent.gemspec
@@ -0,0 +1,47 @@
+#########################################################
+# This file has been automatically generated by gem2tgz #
+#########################################################
+# -*- encoding: utf-8 -*-
+# stub: net-http-persistent 3.0.0 ruby lib
+
+Gem::Specification.new do |s|
+  s.name = "net-http-persistent".freeze
+  s.version = "3.0.0"
+
+  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
+  s.require_paths = ["lib".freeze]
+  s.authors = ["Eric Hodel".freeze]
+  s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDNjCCAh6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy\nYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu\nZXQwHhcNMTYxMDA1MDQyNTQ0WhcNMTcxMDA1MDQyNTQ0WjBBMRAwDgYDVQQDDAdk\ncmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ\nFgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76\nLV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J\nU5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm\nGj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY\nmUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd\ng62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh\nsCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW\nBBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAFz46xasn\n5Jx0lPqq6EGpijLIWv+jk+m2v3Ps38M2ZmNpiThmYFBHIqfDCS0UJWDPTj6FJX0A\nrspSuifsHq3CQ3RJImdO9Gewvx6p3WL/xZD1LmuRo6ktWH9gZWiZpA38GfFGj3SZ\n2u6n3qOEsaxIfwYcU4lCgeZ61JdVU+WWK+GfZpCz4BnjA5hgwdFaf5Zb560RtW7S\n77pi/SZtblyK/jqz1hgoMcaYZvIJTqZnen0pHaq+lKY1KzGdTuVbwD3DO+Fi1Vu8\nBOJAX2VNKk4wthxdCu0SvPe7e+QMP2rmaZOyuX4ztiDQiGuoJxyeqoG1WiOttINU\nU76tHMFuL0FUYw==\n-----END CERTIFICATE-----\n".freeze]
+  s.date = "2016-10-06"
+  s.description = "Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8.\nIt's thread-safe too!\n\nUsing persistent HTTP connections can dramatically increase the speed of HTTP.\nCreating a new HTTP connection for every request involves an extra TCP\nround-trip and causes TCP congestion avoidance negotiation to start over.\n\nNet::HTTP supports persistent connections with some API methods but does not\nhandle reconnection gracefully.  Net::HTTP::Persistent supports reconnection\nand retry according to RFC 2616.".freeze
+  s.email = ["drbrain@segment7.net".freeze]
+  s.extra_rdoc_files = ["History.txt".freeze, "Manifest.txt".freeze, "README.rdoc".freeze]
+  s.files = [".autotest".freeze, ".gemtest".freeze, ".travis.yml".freeze, "History.txt".freeze, "Manifest.txt".freeze, "README.rdoc".freeze, "Rakefile".freeze, "lib/net/http/persistent.rb".freeze, "lib/net/http/persistent/connection.rb".freeze, "lib/net/http/persistent/pool.rb".freeze, "lib/net/http/persistent/timed_stack_multi.rb".freeze, "test/test_net_http_persistent.rb".freeze, "test/test_net_http_persistent_timed_stack_multi.rb".freeze]
+  s.homepage = "http://docs.seattlerb.org/net-http-persistent".freeze
+  s.licenses = ["MIT".freeze]
+  s.rdoc_options = ["--main".freeze, "README.rdoc".freeze]
+  s.required_ruby_version = Gem::Requirement.new("~> 2.1".freeze)
+  s.rubygems_version = "2.5.2.1".freeze
+  s.summary = "Manages persistent connections using Net::HTTP plus a speed fix for Ruby 1.8".freeze
+
+  if s.respond_to? :specification_version then
+    s.specification_version = 4
+
+    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+      s.add_runtime_dependency(%q<connection_pool>.freeze, ["~> 2.2"])
+      s.add_development_dependency(%q<hoe>.freeze, ["~> 3.15"])
+      s.add_development_dependency(%q<minitest>.freeze, ["~> 5.8"])
+      s.add_development_dependency(%q<rdoc>.freeze, ["~> 4.0"])
+    else
+      s.add_dependency(%q<connection_pool>.freeze, ["~> 2.2"])
+      s.add_dependency(%q<hoe>.freeze, ["~> 3.15"])
+      s.add_dependency(%q<minitest>.freeze, ["~> 5.8"])
+      s.add_dependency(%q<rdoc>.freeze, ["~> 4.0"])
+    end
+  else
+    s.add_dependency(%q<connection_pool>.freeze, ["~> 2.2"])
+    s.add_dependency(%q<hoe>.freeze, ["~> 3.15"])
+    s.add_dependency(%q<minitest>.freeze, ["~> 5.8"])
+    s.add_dependency(%q<rdoc>.freeze, ["~> 4.0"])
+  end
+end
diff --git a/test/test_net_http_persistent.rb b/test/test_net_http_persistent.rb
index 2cc5f89994499b79af698d014ce441389f8a8846..fa64570ac3ffb9babacc7dd03b7198886d2e5fd5 100644
--- a/test/test_net_http_persistent.rb
+++ b/test/test_net_http_persistent.rb
@@ -51,21 +51,9 @@ class Net::HTTP
   include Net::HTTP::Persistent::TestConnect
 end
 
-class Net::HTTP::Persistent::SSLReuse
-  include Net::HTTP::Persistent::TestConnect
-end
-
 class TestNetHttpPersistent < Minitest::Test
 
-  RUBY_1 = RUBY_VERSION < '2'
-
   def setup
-    @http_class = if RUBY_1 and HAVE_OPENSSL then
-                    Net::HTTP::Persistent::SSLReuse
-                  else
-                    Net::HTTP
-                  end
-
     @http = Net::HTTP::Persistent.new
 
     @uri  = URI.parse 'http://example.com/path'
@@ -80,25 +68,23 @@ class TestNetHttpPersistent < Minitest::Test
     ENV.delete 'NO_PROXY'
 
     Net::HTTP.use_connect :test_connect
-    Net::HTTP::Persistent::SSLReuse.use_connect :test_connect
   end
 
   def teardown
-    Thread.current.keys.each do |key|
-      Thread.current[key] = nil
-    end
-
     Net::HTTP.use_connect :orig_connect
-    Net::HTTP::Persistent::SSLReuse.use_connect :orig_connect
   end
 
   class BasicConnection
-    attr_accessor :started, :finished, :address, :port,
-                  :read_timeout, :open_timeout
+    attr_accessor :started, :finished, :address, :port, :use_ssl,
+                  :read_timeout, :open_timeout, :keep_alive_timeout
+    attr_accessor :ciphers, :ssl_timeout, :ssl_version,
+                  :verify_depth, :verify_mode, :cert_store,
+                  :ca_file, :ca_path, :cert, :key
     attr_reader :req, :debug_output
     def initialize
       @started, @finished = 0, 0
       @address, @port = 'example.com', 80
+      @use_ssl = false
     end
     def finish
       @finished += 1
@@ -125,21 +111,32 @@ class TestNetHttpPersistent < Minitest::Test
     def started?
       @started >= 1
     end
+    def proxy_address
+    end
+    def proxy_port
+    end
   end
 
   def basic_connection
     raise "#{@uri} is not HTTP" unless @uri.scheme.downcase == 'http'
 
-    c = BasicConnection.new
-    conns[0]["#{@uri.host}:#{@uri.port}"] = c
-    c
+    net_http_args = [@uri.host, @uri.port]
+
+    connection = Net::HTTP::Persistent::Connection.allocate
+    connection.ssl_generation = @http.ssl_generation
+    connection.http = BasicConnection.new
+    connection.reset
+
+    @http.pool.available.push connection, connection_args: net_http_args
+
+    connection
   end
 
   def connection
-    c = basic_connection
-    touts[c.object_id] = Time.now
+    connection = basic_connection
+    connection.last_use = Time.now
 
-    def c.request(req)
+    def (connection.http).request(req)
       @req = req
       r = Net::HTTPResponse.allocate
       r.instance_variable_set :@header, {}
@@ -149,30 +146,22 @@ class TestNetHttpPersistent < Minitest::Test
       r
     end
 
-    c
+    connection
   end
 
-  def conns
-    Thread.current[@http.generation_key] ||= Hash.new { |h,k| h[k] = {} }
-  end
+  def ssl_connection
+    raise "#{@uri} is not HTTPS" unless @uri.scheme.downcase == 'https'
 
-  def reqs
-    Thread.current[@http.request_key] ||= Hash.new 0
-  end
+    net_http_args = [@uri.host, @uri.port]
 
-  def ssl_conns
-    Thread.current[@http.ssl_generation_key] ||= Hash.new { |h,k| h[k] = {} }
-  end
+    connection = Net::HTTP::Persistent::Connection.allocate
+    connection.ssl_generation = @http.ssl_generation
+    connection.http = BasicConnection.new
+    connection.reset
 
-  def ssl_connection generation = 0
-    raise "#{@uri} is not HTTPS" unless @uri.scheme.downcase == 'https'
-    c = BasicConnection.new
-    ssl_conns[generation]["#{@uri.host}:#{@uri.port}"] = c
-    c
-  end
+    @http.pool.available.push connection, connection_args: net_http_args
 
-  def touts
-    Thread.current[@http.timeout_key] ||= Hash.new Net::HTTP::Persistent::EPOCH
+    connection
   end
 
   def test_initialize
@@ -188,7 +177,7 @@ class TestNetHttpPersistent < Minitest::Test
   end
 
   def test_initialize_name
-    http = Net::HTTP::Persistent.new 'name'
+    http = Net::HTTP::Persistent.new name: 'name'
     assert_equal 'name', http.name
   end
 
@@ -212,7 +201,7 @@ class TestNetHttpPersistent < Minitest::Test
   def test_initialize_proxy
     proxy_uri = URI.parse 'http://proxy.example'
 
-    http = Net::HTTP::Persistent.new nil, proxy_uri
+    http = Net::HTTP::Persistent.new proxy: proxy_uri
 
     assert_equal proxy_uri, http.proxy_uri
   end
@@ -224,6 +213,13 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 1, @http.ssl_generation
   end
 
+  def test_ca_path_equals
+    @http.ca_path = :ca_path
+
+    assert_equal :ca_path, @http.ca_path
+    assert_equal 1, @http.ssl_generation
+  end
+
   def test_can_retry_eh_change_requests
     post = Net::HTTP::Post.new '/'
 
@@ -234,27 +230,14 @@ class TestNetHttpPersistent < Minitest::Test
     assert @http.can_retry? post
   end
 
-  if RUBY_1 then
-    def test_can_retry_eh_idempotent
-      head = Net::HTTP::Head.new '/'
+  def test_can_retry_eh_idempotent
+    head = Net::HTTP::Head.new '/'
 
-      assert @http.can_retry? head
+    refute @http.can_retry? head
 
-      post = Net::HTTP::Post.new '/'
-
-      refute @http.can_retry? post
-    end
-  else
-    def test_can_retry_eh_idempotent
-      head = Net::HTTP::Head.new '/'
-
-      assert @http.can_retry? head
-      refute @http.can_retry? head, true
-
-      post = Net::HTTP::Post.new '/'
+    post = Net::HTTP::Post.new '/'
 
-      refute @http.can_retry? post
-    end
+    refute @http.can_retry? post
   end
 
   def test_cert_store_equals
@@ -271,168 +254,154 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 1, @http.ssl_generation
   end
 
+  def test_ciphers_equals
+    @http.ciphers = :ciphers
+
+    assert_equal :ciphers, @http.ciphers
+    assert_equal 1, @http.ssl_generation
+  end
+
   def test_connection_for
     @http.open_timeout = 123
     @http.read_timeout = 321
     @http.idle_timeout = 42
-    c = @http.connection_for @uri
 
-    assert_kind_of @http_class, c
+    used = @http.connection_for @uri do |c|
+      assert_kind_of Net::HTTP, c.http
 
-    assert c.started?
-    refute c.proxy?
+      assert c.http.started?
+      refute c.http.proxy?
 
-    assert_equal 123, c.open_timeout
-    assert_equal 321, c.read_timeout
-    assert_equal 42, c.keep_alive_timeout unless RUBY_1
+      assert_equal 123, c.http.open_timeout
+      assert_equal 321, c.http.read_timeout
+      assert_equal 42, c.http.keep_alive_timeout
 
-    assert_includes conns[0].keys, 'example.com:80'
-    assert_same c, conns[0]['example.com:80']
+      c
+    end
+
+    stored = @http.pool.checkout ['example.com', 80]
+
+    assert_same used, stored
   end
 
   def test_connection_for_cached
     cached = basic_connection
-    cached.start
-    conns[0]['example.com:80'] = cached
+    cached.http.start
 
     @http.read_timeout = 5
 
-    c = @http.connection_for @uri
-
-    assert c.started?
+    @http.connection_for @uri do |c|
+      assert c.http.started?
 
-    assert_equal 5,       c.read_timeout
+      assert_equal 5, c.http.read_timeout
 
-    assert_same cached, c
+      assert_same cached, c
+    end
   end
 
   def test_connection_for_closed
     cached = basic_connection
-    cached.start
+    cached.http.start
     if Socket.const_defined? :TCP_NODELAY then
       io = Object.new
       def io.setsockopt(*a) raise IOError, 'closed stream' end
       cached.instance_variable_set :@socket, Net::BufferedIO.new(io)
     end
-    conns['example.com:80'] = cached
-
-    c = @http.connection_for @uri
-
-    assert c.started?
 
-    assert_includes conns.keys, 'example.com:80'
-    assert_same c, conns[0]['example.com:80']
+    @http.connection_for @uri do |c|
+      assert c.http.started?
 
-    socket = c.instance_variable_get :@socket
+      socket = c.http.instance_variable_get :@socket
 
-    refute_includes socket.io.instance_variables, :@setsockopt
-    refute_includes socket.io.instance_variables, '@setsockopt'
+      refute_includes socket.io.instance_variables, :@setsockopt
+      refute_includes socket.io.instance_variables, '@setsockopt'
+    end
   end
 
   def test_connection_for_debug_output
     io = StringIO.new
     @http.debug_output = io
 
-    c = @http.connection_for @uri
-
-    assert c.started?
-    assert_equal io, c.instance_variable_get(:@debug_output)
-
-    assert_includes conns[0].keys, 'example.com:80'
-    assert_same c, conns[0]['example.com:80']
+    @http.connection_for @uri do |c|
+      assert c.http.started?
+      assert_equal io, c.http.instance_variable_get(:@debug_output)
+    end
   end
 
   def test_connection_for_cached_expire_always
     cached = basic_connection
-    cached.start
-    conns[0]['example.com:80'] = cached
-    reqs[cached.object_id] = 10
-    touts[cached.object_id] = Time.now # last used right now
+    cached.http.start
+    cached.requests = 10
+    cached.last_use = Time.now # last used right now
 
     @http.idle_timeout = 0
 
-    c = @http.connection_for @uri
+    @http.connection_for @uri do |c|
+      assert c.http.started?
 
-    assert c.started?
+      assert_same cached, c
 
-    assert_same cached, c
-
-    assert_equal 0, reqs[cached.object_id],
-                 'connection reset due to timeout'
+      assert_equal 0, c.requests, 'connection reset due to timeout'
+    end
   end
 
   def test_connection_for_cached_expire_never
     cached = basic_connection
-    cached.start
-    conns[0]['example.com:80'] = cached
-    reqs[cached.object_id] = 10
-    touts[cached.object_id] = Time.now # last used right now
+    cached.http.start
+    cached.requests = 10
+    cached.last_use = Time.now # last used right now
 
     @http.idle_timeout = nil
 
-    c = @http.connection_for @uri
-
-    assert c.started?
+    @http.connection_for @uri do |c|
+      assert c.http.started?
 
-    assert_same cached, c
+      assert_same cached, c
 
-    assert_equal 10, reqs[cached.object_id],
-                 'connection reset despite no timeout'
+      assert_equal 10, c.requests, 'connection reset despite no timeout'
+    end
   end
 
   def test_connection_for_cached_expired
     cached = basic_connection
-    cached.start
-    conns[0]['example.com:80'] = cached
-    reqs[cached.object_id] = 10
-    touts[cached.object_id] = Time.now - 3600
+    cached.http.start
+    cached.requests = 10
+    cached.last_use = Time.now - 3600
 
-    c = @http.connection_for @uri
+    @http.connection_for @uri do |c|
+      assert c.http.started?
 
-    assert c.started?
-
-    assert_same cached, c
-    assert_equal 0, reqs[cached.object_id],
-                 'connection not reset due to timeout'
-  end
-
-  def test_connection_for_refused
-    Net::HTTP.use_connect :refused_connect
-    Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
-
-    e = assert_raises Net::HTTP::Persistent::Error do
-      @http.connection_for @uri
+      assert_same cached, c
+      assert_equal 0, cached.requests, 'connection not reset due to timeout'
     end
-
-    assert_equal 'connection refused: example.com:80', e.message
   end
 
   def test_connection_for_finished_ssl
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
     uri = URI.parse 'https://example.com/path'
-    c = @http.connection_for uri
 
-    assert c.started?
-    assert c.use_ssl?
+    @http.connection_for uri do |c|
+      assert c.http.started?
+      assert c.http.use_ssl?
 
-    @http.finish c
+      @http.finish c
 
-    refute c.started?
-
-    c2 = @http.connection_for uri
+      refute c.http.started?
+    end
 
-    assert c2.started?
+    @http.connection_for uri do |c2|
+      assert c2.http.started?
+    end
   end
 
   def test_connection_for_host_down
-    cached = basic_connection
-    def cached.start; raise Errno::EHOSTDOWN end
-    def cached.started?; false end
-    conns[0]['example.com:80'] = cached
+    c = basic_connection
+    def (c.http).start; raise Errno::EHOSTDOWN end
+    def (c.http).started?; false end
 
     e = assert_raises Net::HTTP::Persistent::Error do
-      @http.connection_for @uri
+      @http.connection_for @uri do end
     end
 
     assert_equal 'host down: example.com:80', e.message
@@ -440,8 +409,10 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_connection_for_http_class_with_fakeweb
     Object.send :const_set, :FakeWeb, nil
-    c = @http.connection_for @uri
-    assert_instance_of Net::HTTP, c
+
+    @http.connection_for @uri do |c|
+      assert_instance_of Net::HTTP, c.http
+    end
   ensure
     if Object.const_defined?(:FakeWeb) then
       Object.send :remove_const, :FakeWeb
@@ -450,8 +421,9 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_connection_for_http_class_with_webmock
     Object.send :const_set, :WebMock, nil
-    c = @http.connection_for @uri
-    assert_instance_of Net::HTTP, c
+    @http.connection_for @uri do |c|
+      assert_instance_of Net::HTTP, c.http
+    end
   ensure
     if Object.const_defined?(:WebMock) then
       Object.send :remove_const, :WebMock
@@ -460,8 +432,9 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_connection_for_http_class_with_artifice
     Object.send :const_set, :Artifice, nil
-    c = @http.connection_for @uri
-    assert_instance_of Net::HTTP, c
+    @http.connection_for @uri do |c|
+      assert_instance_of Net::HTTP, c.http
+    end
   ensure
     if Object.const_defined?(:Artifice) then
       Object.send :remove_const, :Artifice
@@ -469,23 +442,12 @@ class TestNetHttpPersistent < Minitest::Test
   end
 
   def test_connection_for_name
-    http = Net::HTTP::Persistent.new 'name'
+    http = Net::HTTP::Persistent.new name: 'name'
     uri = URI.parse 'http://example/'
 
-    c = http.connection_for uri
-
-    assert c.started?
-
-    refute_includes conns.keys, 'example:80'
-  end
-
-  def test_connection_for_no_ssl_reuse
-    @http.reuse_ssl_sessions = false
-    @http.open_timeout = 123
-    @http.read_timeout = 321
-    c = @http.connection_for @uri
-
-    assert_instance_of Net::HTTP, c
+    http.connection_for uri do |c|
+      assert c.http.started?
+    end
   end
 
   def test_connection_for_proxy
@@ -493,16 +455,20 @@ class TestNetHttpPersistent < Minitest::Test
     uri.user     = 'johndoe'
     uri.password = 'muffins'
 
-    http = Net::HTTP::Persistent.new nil, uri
+    http = Net::HTTP::Persistent.new proxy: uri
 
-    c = http.connection_for @uri
+    used = http.connection_for @uri do |c|
+      assert c.http.started?
+      assert c.http.proxy?
 
-    assert c.started?
-    assert c.proxy?
+      c
+    end
+
+    stored = http.pool.checkout ['example.com', 80,
+                                 'proxy.example', 80,
+                                 'johndoe', 'muffins']
 
-    assert_includes conns[1].keys,
-                    'example.com:80:proxy.example:80:johndoe:muffins'
-    assert_same c, conns[1]['example.com:80:proxy.example:80:johndoe:muffins']
+    assert_same used, stored
   end
 
   def test_connection_for_proxy_unescaped
@@ -511,25 +477,28 @@ class TestNetHttpPersistent < Minitest::Test
     uri.password = 'muf%3Afins'
     uri.freeze
 
-    http = Net::HTTP::Persistent.new nil, uri
-    c = http.connection_for @uri
+    http = Net::HTTP::Persistent.new proxy: uri
+
+    http.connection_for @uri do end
+
+    stored = http.pool.checkout ['example.com', 80,
+                                 'proxy.example', 80,
+                                 'john@doe', 'muf:fins']
 
-    assert_includes conns[1].keys,
-                    'example.com:80:proxy.example:80:john@doe:muf:fins'
+    assert stored
   end
 
   def test_connection_for_proxy_host_down
     Net::HTTP.use_connect :host_down_connect
-    Net::HTTP::Persistent::SSLReuse.use_connect :host_down_connect
 
     uri = URI.parse 'http://proxy.example'
     uri.user     = 'johndoe'
     uri.password = 'muffins'
 
-    http = Net::HTTP::Persistent.new nil, uri
+    http = Net::HTTP::Persistent.new proxy: uri
 
     e = assert_raises Net::HTTP::Persistent::Error do
-      http.connection_for @uri
+      http.connection_for @uri do end
     end
 
     assert_equal 'host down: proxy.example:80', e.message
@@ -537,16 +506,15 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_connection_for_proxy_refused
     Net::HTTP.use_connect :refused_connect
-    Net::HTTP::Persistent::SSLReuse.use_connect :refused_connect
 
     uri = URI.parse 'http://proxy.example'
     uri.user     = 'johndoe'
     uri.password = 'muffins'
 
-    http = Net::HTTP::Persistent.new nil, uri
+    http = Net::HTTP::Persistent.new proxy: uri
 
     e = assert_raises Net::HTTP::Persistent::Error do
-      http.connection_for @uri
+      http.connection_for @uri do end
     end
 
     assert_equal 'connection refused: proxy.example:80', e.message
@@ -558,38 +526,37 @@ class TestNetHttpPersistent < Minitest::Test
     uri.password = 'muffins'
     uri.query    = 'no_proxy=example.com'
 
-    http = Net::HTTP::Persistent.new nil, uri
+    http = Net::HTTP::Persistent.new proxy: uri
 
-    c = http.connection_for @uri
+    http.connection_for @uri do |c|
+      assert c.http.started?
+      refute c.http.proxy?
+    end
 
-    assert c.started?
-    refute c.proxy?
+    stored = http.pool.checkout ['example.com', 80]
 
-    assert_includes conns[1].keys, 'example.com:80'
-    assert_same c, conns[1]['example.com:80']
+    assert stored
   end
 
   def test_connection_for_refused
-    cached = basic_connection
-    def cached.start; raise Errno::ECONNREFUSED end
-    def cached.started?; false end
-    conns[0]['example.com:80'] = cached
+    Net::HTTP.use_connect :refused_connect
 
     e = assert_raises Net::HTTP::Persistent::Error do
-      @http.connection_for @uri
+      @http.connection_for @uri do end
     end
 
-    assert_match %r%connection refused%, e.message
+    assert_equal 'connection refused: example.com:80', e.message
   end
 
   def test_connection_for_ssl
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
     uri = URI.parse 'https://example.com/path'
-    c = @http.connection_for uri
 
-    assert c.started?
-    assert c.use_ssl?
+    @http.connection_for uri do |c|
+      assert c.http.started?
+      assert c.http.use_ssl?
+    end
   end
 
   def test_connection_for_ssl_cached
@@ -597,11 +564,11 @@ class TestNetHttpPersistent < Minitest::Test
 
     @uri = URI.parse 'https://example.com/path'
 
-    cached = ssl_connection 0
-
-    c = @http.connection_for @uri
+    cached = ssl_connection
 
-    assert_same cached, c
+    @http.connection_for @uri do |c|
+      assert_same cached, c
+    end
   end
 
   def test_connection_for_ssl_cached_reconnect
@@ -611,45 +578,47 @@ class TestNetHttpPersistent < Minitest::Test
 
     cached = ssl_connection
 
-    @http.reconnect_ssl
+    ssl_generation = @http.ssl_generation
 
-    c = @http.connection_for @uri
+    @http.reconnect_ssl
 
-    refute_same cached, c
+    @http.connection_for @uri do |c|
+      assert_same cached, c
+      refute_equal ssl_generation, c.ssl_generation
+    end
   end
 
   def test_connection_for_ssl_case
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
     uri = URI.parse 'HTTPS://example.com/path'
-    c = @http.connection_for uri
-
-    assert c.started?
-    assert c.use_ssl?
+    @http.connection_for uri do |c|
+      assert c.http.started?
+      assert c.http.use_ssl?
+    end
   end
 
   def test_connection_for_timeout
     cached = basic_connection
-    cached.start
-    reqs[cached.object_id] = 10
-    touts[cached.object_id] = Time.now - 6
-    conns[0]['example.com:80'] = cached
+    cached.http.start
+    cached.requests = 10
+    cached.last_use = Time.now - 6
 
-    c = @http.connection_for @uri
+    @http.connection_for @uri do |c|
+      assert c.http.started?
+      assert_equal 0, c.requests
 
-    assert c.started?
-    assert_equal 0, reqs[c.object_id]
-
-    assert_same cached, c
+      assert_same cached, c
+    end
   end
 
   def test_error_message
     c = basic_connection
-    touts[c.object_id] = Time.now - 1
-    reqs[c.object_id] = 5
+    c.last_use = Time.now - 1
+    c.requests = 5
 
-    message = @http.error_message(c)
-    assert_match %r%after 4 requests on #{c.object_id}%, message
+    message = @http.error_message c
+    assert_match %r%after 4 requests on #{c.http.object_id}%, message
     assert_match %r%, last used [\d.]+ seconds ago%, message
   end
 
@@ -667,8 +636,8 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_expired_eh
     c = basic_connection
-    reqs[c.object_id] = 0
-    touts[c.object_id] = Time.now - 11
+    c.requests = 0
+    c.last_use = Time.now - 11
 
     @http.idle_timeout = 0
     assert @http.expired? c
@@ -688,41 +657,57 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_expired_due_to_max_requests
     c = basic_connection
-    reqs[c.object_id] = 0
-    touts[c.object_id] = Time.now
+    c.requests = 0
+    c.last_use = Time.now
 
     refute @http.expired? c
 
-    reqs[c.object_id] = 10
+    c.requests = 10
     refute @http.expired? c
 
     @http.max_requests = 10
     assert @http.expired? c
 
-    reqs[c.object_id] = 9
+    c.requests = 9
     refute @http.expired? c
   end
 
   def test_finish
     c = basic_connection
-    reqs[c.object_id] = 5
+    c.requests = 5
 
     @http.finish c
 
-    refute c.started?
-    assert c.finished?
-    assert_equal 0, reqs[c.object_id]
+    refute c.http.started?
+    assert c.http.finished?
+
+    assert_equal 0, c.requests
+    assert_equal Net::HTTP::Persistent::EPOCH, c.last_use
   end
 
   def test_finish_io_error
     c = basic_connection
-    def c.finish; @finished += 1; raise IOError end
-    reqs[c.object_id] = 5
+    def (c.http).finish; @finished += 1; raise IOError end
+    c.requests = 5
 
     @http.finish c
 
-    refute c.started?
-    assert c.finished?
+    refute c.http.started?
+    assert c.http.finished?
+  end
+
+  def test_finish_ssl_no_session_reuse
+    http = Net::HTTP.new 'localhost', 443, ssl: true
+    http.instance_variable_set :@ssl_session, :something
+
+    c = Net::HTTP::Persistent::Connection.allocate
+    c.instance_variable_set :@http, http
+
+    @http.reuse_ssl_sessions = false
+
+    @http.finish c
+
+    assert_nil c.http.instance_variable_get :@ssl_session
   end
 
   def test_http_version
@@ -746,14 +731,6 @@ class TestNetHttpPersistent < Minitest::Test
     refute @http.idempotent? Net::HTTP::Post.new '/'
   end
 
-  def test_max_age
-    assert_in_delta Time.now - 5, @http.max_age
-
-    @http.idle_timeout = nil
-
-    assert_in_delta Time.now + 1, @http.max_age
-  end
-
   def test_normalize_uri
     assert_equal 'http://example',  @http.normalize_uri('example')
     assert_equal 'http://example',  @http.normalize_uri('http://example')
@@ -775,7 +752,6 @@ class TestNetHttpPersistent < Minitest::Test
 
     cached = basic_connection
     cached.start
-    conns['example.com:80'] = cached
 
     requests = [
       Net::HTTP::Get.new((@uri + '1').request_uri),
@@ -935,9 +911,38 @@ class TestNetHttpPersistent < Minitest::Test
   end
 
   def test_reconnect_ssl
-    result = @http.reconnect_ssl
+    skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
-    assert_equal 1, result
+    @uri = URI 'https://example.com'
+    now = Time.now
+
+    ssl_http = ssl_connection
+
+    def (ssl_http.http).finish
+      @started = 0
+    end
+
+    used1 = @http.connection_for @uri do |c|
+      c.requests = 1
+      c.last_use = now
+      c
+    end
+
+    assert_equal OpenSSL::SSL::VERIFY_PEER, used1.http.verify_mode
+
+    @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+    @http.reconnect_ssl
+
+    used2 = @http.connection_for @uri do |c|
+      c
+    end
+
+    assert_same used1, used2
+
+    assert_equal OpenSSL::SSL::VERIFY_NONE, used2.http.verify_mode,
+                 'verify mode must change'
+    assert_equal 0, used2.requests
+    assert_equal Net::HTTP::Persistent::EPOCH, used2.last_use
   end
 
   def test_request
@@ -946,7 +951,7 @@ class TestNetHttpPersistent < Minitest::Test
     c = connection
 
     res = @http.request @uri
-    req = c.req
+    req = c.http.req
 
     assert_kind_of Net::HTTPResponse, res
 
@@ -959,72 +964,51 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 'keep-alive', req['connection']
     assert_equal '30',         req['keep-alive']
 
-    assert_in_delta Time.now, touts[c.object_id]
+    assert_in_delta Time.now, c.last_use
 
-    assert_equal 1, reqs[c.object_id]
+    assert_equal 1, c.requests
   end
 
   def test_request_ETIMEDOUT
     c = basic_connection
-    def c.request(*a) raise Errno::ETIMEDOUT, "timed out" end
+    def (c.http).request(*a) raise Errno::ETIMEDOUT, "timed out" end
 
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.request @uri
     end
 
-    assert_equal 0, reqs[c.object_id]
+    assert_equal 0, c.requests
     assert_match %r%too many connection resets%, e.message
   end
 
   def test_request_bad_response
     c = basic_connection
-    def c.request(*a) raise Net::HTTPBadResponse end
+    def (c.http).request(*a) raise Net::HTTPBadResponse end
 
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.request @uri
     end
 
-    assert_equal 0, reqs[c.object_id]
+    assert_equal 0, c.requests
     assert_match %r%too many bad responses%, e.message
   end
 
-  if RUBY_1 then
-    def test_request_bad_response_retry
-      c = basic_connection
-      def c.request(*a)
-        if defined? @called then
-          r = Net::HTTPResponse.allocate
-          r.instance_variable_set :@header, {}
-          def r.http_version() '1.1' end
-          r
-        else
-          @called = true
-          raise Net::HTTPBadResponse
-        end
-      end
+  def test_request_bad_response_retry
+    c = basic_connection
+    def (c.http).request(*a)
+      raise Net::HTTPBadResponse
+    end
 
+    assert_raises Net::HTTP::Persistent::Error do
       @http.request @uri
-
-      assert c.finished?
     end
-  else
-    def test_request_bad_response_retry
-      c = basic_connection
-      def c.request(*a)
-        raise Net::HTTPBadResponse
-      end
-
-      assert_raises Net::HTTP::Persistent::Error do
-        @http.request @uri
-      end
 
-      assert c.finished?
-    end
+    assert c.http.finished?
   end
 
   def test_request_bad_response_unsafe
     c = basic_connection
-    def c.request(*a)
+    def (c.http).request(*a)
       if instance_variable_defined? :@request then
         raise 'POST must not be retried'
       else
@@ -1037,7 +1021,7 @@ class TestNetHttpPersistent < Minitest::Test
       @http.request @uri, Net::HTTP::Post.new(@uri.path)
     end
 
-    assert_equal 0, reqs[c.object_id]
+    assert_equal 0, c.requests
     assert_match %r%too many bad responses%, e.message
   end
 
@@ -1050,7 +1034,7 @@ class TestNetHttpPersistent < Minitest::Test
       body = r.read_body
     end
 
-    req = c.req
+    req = c.http.req
 
     assert_kind_of Net::HTTPResponse, res
     refute_nil body
@@ -1061,17 +1045,17 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal '30',         req['keep-alive']
     assert_match %r%test ua%,  req['user-agent']
 
-    assert_equal 1, reqs[c.object_id]
+    assert_equal 1, c.requests
   end
 
   def test_request_close_1_0
     c = connection
 
-    class << c
+    class << c.http
       remove_method :request
     end
 
-    def c.request req
+    def (c.http).request req
       @req = req
       r = Net::HTTPResponse.allocate
       r.instance_variable_set :@header, {}
@@ -1084,7 +1068,7 @@ class TestNetHttpPersistent < Minitest::Test
     request = Net::HTTP::Get.new @uri.request_uri
 
     res = @http.request @uri, request
-    req = c.req
+    req = c.http.req
 
     assert_kind_of Net::HTTPResponse, res
 
@@ -1093,7 +1077,7 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 'keep-alive', req['connection']
     assert_equal '30',         req['keep-alive']
 
-    assert c.finished?
+    assert c.http.finished?
   end
 
   def test_request_connection_close_request
@@ -1103,7 +1087,7 @@ class TestNetHttpPersistent < Minitest::Test
     request['connection'] = 'close'
 
     res = @http.request @uri, request
-    req = c.req
+    req = c.http.req
 
     assert_kind_of Net::HTTPResponse, res
 
@@ -1112,17 +1096,17 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 'close',      req['connection']
     assert_equal nil,          req['keep-alive']
 
-    assert c.finished?
+    assert c.http.finished?
   end
 
   def test_request_connection_close_response
     c = connection
 
-    class << c
+    class << c.http
       remove_method :request
     end
 
-    def c.request req
+    def (c.http).request req
       @req = req
       r = Net::HTTPResponse.allocate
       r.instance_variable_set :@header, {}
@@ -1136,7 +1120,7 @@ class TestNetHttpPersistent < Minitest::Test
     request = Net::HTTP::Get.new @uri.request_uri
 
     res = @http.request @uri, request
-    req = c.req
+    req = c.http.req
 
     assert_kind_of Net::HTTPResponse, res
 
@@ -1145,120 +1129,77 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 'keep-alive', req['connection']
     assert_equal '30',         req['keep-alive']
 
-    assert c.finished?
+    assert c.http.finished?
   end
 
   def test_request_exception
     c = basic_connection
-    def c.request(*a) raise Exception, "very bad things happened" end
+    def (c.http).request(*a)
+      raise Exception, "very bad things happened"
+    end
 
     assert_raises Exception do
       @http.request @uri
     end
 
-    assert_equal 0, reqs[c.object_id]
-    assert c.finished?
+    assert_equal 0, c.requests
+    assert c.http.finished?
   end
 
   def test_request_invalid
     c = basic_connection
-    def c.request(*a) raise Errno::EINVAL, "write" end
+    def (c.http).request(*a) raise Errno::EINVAL, "write" end
 
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.request @uri
     end
 
-    assert_equal 0, reqs[c.object_id]
+    assert_equal 0, c.requests
     assert_match %r%too many connection resets%, e.message
   end
 
-  def test_request_invalid_retry
-    c = basic_connection
-    touts[c.object_id] = Time.now
-
-    def c.request(*a)
-      if defined? @called then
-        r = Net::HTTPResponse.allocate
-        r.instance_variable_set :@header, {}
-        def r.http_version() '1.1' end
-        r
-      else
-        @called = true
-        raise Errno::EINVAL, "write"
-      end
-    end
-
-    @http.request @uri
-
-    assert c.reset?
-    assert c.finished?
-  end
-
   def test_request_post
     c = connection
 
     post = Net::HTTP::Post.new @uri.path
 
     @http.request @uri, post
-    req = c.req
+    req = c.http.req
 
     assert_same post, req
   end
 
   def test_request_reset
     c = basic_connection
-    def c.request(*a) raise Errno::ECONNRESET end
+    def (c.http).request(*a) raise Errno::ECONNRESET end
 
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.request @uri
     end
 
-    assert_equal 0, reqs[c.object_id]
+    assert_equal 0, c.requests
     assert_match %r%too many connection resets%, e.message
   end
 
-  if RUBY_1 then
-    def test_request_reset_retry
-      c = basic_connection
-      touts[c.object_id] = Time.now
-      def c.request(*a)
-        if defined? @called then
-          r = Net::HTTPResponse.allocate
-          r.instance_variable_set :@header, {}
-          def r.http_version() '1.1' end
-          r
-        else
-          @called = true
-          raise Errno::ECONNRESET
-        end
-      end
-
-      @http.request @uri
+  def test_request_reset_retry
+    c = basic_connection
+    c.last_use = Time.now
 
-      assert c.reset?
-      assert c.finished?
+    def (c.http).request(*a)
+      raise Errno::ECONNRESET
     end
-  else
-    def test_request_reset_retry
-      c = basic_connection
-      touts[c.object_id] = Time.now
 
-      def c.request(*a)
-        raise Errno::ECONNRESET
-      end
-
-      assert_raises Net::HTTP::Persistent::Error do
-        @http.request @uri
-      end
-
-      refute c.reset?
-      assert c.finished?
+    assert_raises Net::HTTP::Persistent::Error do
+      @http.request @uri
     end
+
+    refute (c.http).reset?
+    assert (c.http).finished?
   end
 
   def test_request_reset_unsafe
     c = basic_connection
-    def c.request(*a)
+    def (c.http).request(*a)
       if instance_variable_defined? :@request then
         raise 'POST must not be retried'
       else
@@ -1271,7 +1212,7 @@ class TestNetHttpPersistent < Minitest::Test
       @http.request @uri, Net::HTTP::Post.new(@uri.path)
     end
 
-    assert_equal 0, reqs[c.object_id]
+    assert_equal 0, c.requests
     assert_match %r%too many connection resets%, e.message
   end
 
@@ -1279,15 +1220,16 @@ class TestNetHttpPersistent < Minitest::Test
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
     uri = URI.parse 'https://example.com/path'
-    c = @http.connection_for uri
-    def c.request(*)
-      raise OpenSSL::SSL::SSLError, "SSL3_WRITE_PENDING:bad write retry"
-    end
+    @http.connection_for uri do |c|
+      def (c.http).request(*)
+        raise OpenSSL::SSL::SSLError, "SSL3_WRITE_PENDING:bad write retry"
+      end
 
-    e = assert_raises Net::HTTP::Persistent::Error do
-      @http.request uri
+      e = assert_raises Net::HTTP::Persistent::Error do
+        @http.request uri
+      end
+      assert_match %r%bad write retry%, e.message
     end
-    assert_match %r%bad write retry%, e.message
   end
 
   def test_request_setup
@@ -1308,6 +1250,22 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal '30',         req['keep-alive']
   end
 
+  def test_request_string
+    @http.override_headers['user-agent'] = 'test ua'
+    @http.headers['accept'] = 'text/*'
+    c = connection
+
+    res = @http.request @uri.to_s
+    req = c.http.req
+
+    assert_kind_of Net::HTTPResponse, res
+
+    assert_kind_of Net::HTTP::Get, req
+    assert_equal '/path',      req.path
+
+    assert_equal 1, c.requests
+  end
+
   def test_request_setup_uri
     uri = @uri + '?a=b'
 
@@ -1319,8 +1277,8 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_request_failed
     c = basic_connection
-    reqs[c.object_id] = 1
-    touts[c.object_id] = Time.now
+    c.requests = 1
+    c.last_use = Time.now
 
     original = nil
 
@@ -1330,7 +1288,7 @@ class TestNetHttpPersistent < Minitest::Test
     end
 
     req = Net::HTTP::Get.new '/'
-      
+
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.request_failed original, req, c
     end
@@ -1343,24 +1301,24 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_reset
     c = basic_connection
-    c.start
-    touts[c.object_id] = Time.now
-    reqs[c.object_id]  = 5
+    c.http.start
+    c.last_use = Time.now
+    c.requests  = 5
 
     @http.reset c
 
-    assert c.started?
-    assert c.finished?
-    assert c.reset?
-    assert_equal 0, reqs[c.object_id]
-    assert_equal Net::HTTP::Persistent::EPOCH, touts[c.object_id]
+    assert c.http.started?
+    assert c.http.finished?
+    assert c.http.reset?
+    assert_equal 0, c.requests
+    assert_equal Net::HTTP::Persistent::EPOCH, c.last_use
   end
 
   def test_reset_host_down
     c = basic_connection
-    touts[c.object_id] = Time.now
-    def c.start; raise Errno::EHOSTDOWN end
-    reqs[c.object_id] = 5
+    c.last_use = Time.now
+    def (c.http).start; raise Errno::EHOSTDOWN end
+    c.requests = 5
 
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.reset c
@@ -1372,20 +1330,20 @@ class TestNetHttpPersistent < Minitest::Test
 
   def test_reset_io_error
     c = basic_connection
-    touts[c.object_id] = Time.now
-    reqs[c.object_id] = 5
+    c.last_use = Time.now
+    c.requests = 5
 
     @http.reset c
 
-    assert c.started?
-    assert c.finished?
+    assert c.http.started?
+    assert c.http.finished?
   end
 
   def test_reset_refused
     c = basic_connection
-    touts[c.object_id] = Time.now
-    def c.start; raise Errno::ECONNREFUSED end
-    reqs[c.object_id] = 5
+    c.last_use = Time.now
+    def (c.http).start; raise Errno::ECONNREFUSED end
+    c.requests = 5
 
     e = assert_raises Net::HTTP::Persistent::Error do
       @http.reset c
@@ -1401,161 +1359,50 @@ class TestNetHttpPersistent < Minitest::Test
 
     refute @http.retry_change_requests
 
-    if RUBY_1 then
-      assert @http.can_retry?(get)
-    else
-      assert @http.can_retry?(get)
-    end
-    refute @http.can_retry?(get, true)
+    refute @http.can_retry?(get)
     refute @http.can_retry?(post)
 
     @http.retry_change_requests = true
 
     assert @http.retry_change_requests
 
-    if RUBY_1 then
-      assert @http.can_retry?(get)
-    else
-      assert @http.can_retry?(get)
-      refute @http.can_retry?(get, true)
-    end
-
+    refute @http.can_retry?(get)
     assert @http.can_retry?(post)
   end
 
   def test_shutdown
-    ssl_conns
     c = connection
-    rs = reqs
-    ts = touts
 
     orig = @http
-    @http = Net::HTTP::Persistent.new 'name'
+    @http = Net::HTTP::Persistent.new name: 'name'
     c2 = connection
 
     orig.shutdown
 
     @http = orig
 
-    assert c.finished?, 'last-generation connection must be finished'
-    refute c2.finished?, 'present generation connection must not be finished'
-
-    refute_same rs, reqs
-    refute_same ts, touts
-
-    assert_empty conns
-    assert_empty ssl_conns
-
-    assert_empty reqs
-    assert_empty touts
-  end
-
-  def test_shutdown_in_all_threads
-    conns
-    ssl_conns
-
-    t = Thread.new do
-      c = connection
-      ssl_conns
-      conns
-      reqs
-
-      Thread.stop
-
-      c
-    end
-
-    Thread.pass until t.status == 'sleep'
-
-    c = connection
-
-    assert_nil @http.shutdown_in_all_threads
-
-    assert c.finished?, 'connection in same thread must be finished'
-
-    assert_empty Thread.current[@http.generation_key]
-
-    assert_nil Thread.current[@http.request_key]
-
-    t.run
-    assert t.value.finished?, 'connection in other thread must be finished'
-
-    assert_empty t[@http.generation_key]
-
-    assert_nil t[@http.request_key]
-  end
-
-  def test_shutdown_no_connections
-    @http.shutdown
-
-    assert_nil Thread.current[@http.generation_key]
-    assert_nil Thread.current[@http.ssl_generation_key]
-
-    assert_nil Thread.current[@http.request_key]
-    assert_nil Thread.current[@http.timeout_key]
-  end
-
-  def test_shutdown_not_started
-    ssl_conns
-
-    c = basic_connection
-    def c.finish() raise IOError end
-
-    conns[0]["#{@uri.host}:#{@uri.port}"] = c
-
-    @http.shutdown
-
-    assert_empty Thread.current[@http.generation_key]
-    assert_empty Thread.current[@http.ssl_generation_key]
-
-    assert_nil Thread.current[@http.request_key]
-    assert_nil Thread.current[@http.timeout_key]
+    assert c.http.finished?, 'last-generation connection must be finished'
+    refute c2.http.finished?, 'present generation connection must not be finished'
   end
 
-  def test_shutdown_ssl
+  def test_ssl
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
-    @uri = URI 'https://example'
-
-    @http.connection_for @uri
-
-    @http.shutdown
-
-    assert_empty ssl_conns
-  end
-
-  def test_shutdown_thread
-    t = Thread.new do
-      c = connection
-      conns
-      ssl_conns
-
-      reqs
-
-      Thread.stop
-
-      c
-    end
-
-    Thread.pass until t.status == 'sleep'
-
-    c = connection
-
-    @http.shutdown t
+    @http.verify_callback = :callback
+    c = Net::HTTP.new 'localhost', 80
 
-    refute c.finished?
+    @http.ssl c
 
-    t.run
-    assert t.value.finished?
-    assert_empty t[@http.generation_key]
-    assert_empty t[@http.ssl_generation_key]
-    assert_nil t[@http.request_key]
-    assert_nil t[@http.timeout_key]
+    assert c.use_ssl?
+    assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
+    assert_kind_of OpenSSL::X509::Store,    c.cert_store
+    assert_nil c.verify_callback
   end
 
-  def test_ssl
+  def test_ssl_ca_file
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
+    @http.ca_file = 'ca_file'
     @http.verify_callback = :callback
     c = Net::HTTP.new 'localhost', 80
 
@@ -1563,14 +1410,13 @@ class TestNetHttpPersistent < Minitest::Test
 
     assert c.use_ssl?
     assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
-    assert_kind_of OpenSSL::X509::Store,    c.cert_store
-    assert_nil c.verify_callback
+    assert_equal :callback, c.verify_callback
   end
 
-  def test_ssl_ca_file
+  def test_ssl_ca_path
     skip 'OpenSSL is missing' unless HAVE_OPENSSL
 
-    @http.ca_file = 'ca_file'
+    @http.ca_path = 'ca_path'
     @http.verify_callback = :callback
     c = Net::HTTP.new 'localhost', 80
 
@@ -1667,23 +1513,11 @@ class TestNetHttpPersistent < Minitest::Test
     end
   end
 
-  def test_ssl_cleanup
-    skip 'OpenSSL is missing' unless HAVE_OPENSSL
-
-    uri1 = URI.parse 'https://one.example'
-
-    c1 = @http.connection_for uri1
-
-    touts[c1.object_id] = Time.now
-    reqs[c1.object_id] = 5
-
-    @http.reconnect_ssl
-
-    @http.ssl_cleanup @http.ssl_generation
+  def test_ssl_timeout_equals
+    @http.ssl_timeout = :ssl_timeout
 
-    assert_empty ssl_conns
-    assert_empty touts
-    assert_empty reqs # sanity check, performed by #finish
+    assert_equal :ssl_timeout, @http.ssl_timeout
+    assert_equal 1, @http.ssl_generation
   end
 
   def test_ssl_version_equals
@@ -1691,10 +1525,11 @@ class TestNetHttpPersistent < Minitest::Test
 
     assert_equal :ssl_version, @http.ssl_version
     assert_equal 1, @http.ssl_generation
-  end unless RUBY_1
+  end
 
   def test_start
     c = basic_connection
+    c = c.http
 
     @http.socket_options << [Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1]
     @http.debug_output = $stderr
@@ -1722,6 +1557,13 @@ class TestNetHttpPersistent < Minitest::Test
     assert_equal 1, @http.ssl_generation
   end
 
+  def test_verify_depth_equals
+    @http.verify_depth = :verify_depth
+
+    assert_equal :verify_depth, @http.verify_depth
+    assert_equal 1, @http.ssl_generation
+  end
+
   def test_verify_mode_equals
     @http.verify_mode = :verify_mode
 
diff --git a/test/test_net_http_persistent_ssl_reuse.rb b/test/test_net_http_persistent_ssl_reuse.rb
deleted file mode 100644
index b231899707c696bf1700150a2c4b0deec0275357..0000000000000000000000000000000000000000
--- a/test/test_net_http_persistent_ssl_reuse.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-require 'rubygems'
-require 'minitest/autorun'
-require 'net/http/persistent'
-have_ssl =
-  begin
-    require 'openssl'
-    require 'webrick'
-    require 'webrick/ssl'
-    true
-  rescue LoadError
-    false
-  end
-
-##
-# This test is based on (and contains verbatim code from) the Net::HTTP tests
-# in ruby
-
-class TestNetHttpPersistentSSLReuse < Minitest::Test
-
-  class NullWriter
-    def <<(s) end
-    def puts(*args) end
-    def print(*args) end
-    def printf(*args) end
-  end
-
-  def setup
-    @name = OpenSSL::X509::Name.parse 'CN=localhost/DC=localdomain'
-
-    @key = OpenSSL::PKey::RSA.new 1024
-
-    @cert = OpenSSL::X509::Certificate.new
-    @cert.version = 2
-    @cert.serial = 0
-    @cert.not_before = Time.now
-    @cert.not_after = Time.now + 300
-    @cert.public_key = @key.public_key
-    @cert.subject = @name
-    @cert.issuer = @name
-
-    @cert.sign @key, OpenSSL::Digest::SHA1.new
-
-    @host = 'localhost'
-    @port = 10082
-
-    config = {
-      :BindAddress                => @host,
-      :Port                       => @port,
-      :Logger                     => WEBrick::Log.new(NullWriter.new),
-      :AccessLog                  => [],
-      :ShutDownSocketWithoutClose => true,
-      :ServerType                 => Thread,
-      :SSLEnable                  => true,
-      :SSLCertificate             => @cert,
-      :SSLPrivateKey              => @key,
-      :SSLStartImmediately        => true,
-    }
-
-    @server = WEBrick::HTTPServer.new config
-
-    @server.mount_proc '/' do |req, res|
-      res.body = "ok"
-    end
-
-    @server.start
-
-    begin
-      TCPSocket.open(@host, @port).close
-    rescue Errno::ECONNREFUSED
-      sleep 0.2
-      n_try_max -= 1
-      raise 'cannot spawn server; give up' if n_try_max < 0
-      retry
-    end
-  end
-
-  def teardown
-    if @server then
-      @server.shutdown
-      sleep 0.01 until @server.status == :Stop
-    end
-  end
-
-  def test_ssl_connection_reuse
-    store = OpenSSL::X509::Store.new
-    store.add_cert @cert
-
-    @http = Net::HTTP::Persistent::SSLReuse.new @host, @port
-    @http.cert_store = store
-    @http.ssl_version = :SSLv3 if @http.respond_to? :ssl_version=
-    @http.use_ssl = true
-    @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
-
-    @http.start
-    @http.get '/'
-    @http.finish
-
-    @http.start
-    @http.get '/'
-    @http.finish
-
-    @http.start
-    @http.get '/'
-
-    socket = @http.instance_variable_get :@socket
-    ssl_socket = socket.io
-
-    assert ssl_socket.session_reused?
-  end
-
-end if have_ssl
-
diff --git a/test/test_net_http_persistent_timed_stack_multi.rb b/test/test_net_http_persistent_timed_stack_multi.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ae3e34ba70fdecafb580354fc8a0efc2f5d826ab
--- /dev/null
+++ b/test/test_net_http_persistent_timed_stack_multi.rb
@@ -0,0 +1,151 @@
+require 'minitest/autorun'
+require 'net/http/persistent'
+
+class TestNetHttpPersistentTimedStackMulti < Minitest::Test
+
+  class Connection
+    attr_reader :host
+
+    def initialize(host)
+      @host = host
+    end
+  end
+
+  def setup
+    @stack = Net::HTTP::Persistent::TimedStackMulti.new { Object.new }
+  end
+
+  def test_empty_eh
+    stack = Net::HTTP::Persistent::TimedStackMulti.new(1) { Object.new }
+
+    refute_empty stack
+
+    popped = stack.pop
+
+    assert_empty stack
+
+    stack.push connection_args: popped
+
+    refute_empty stack
+  end
+
+  def test_length
+    stack = Net::HTTP::Persistent::TimedStackMulti.new(1) { Object.new }
+
+    assert_equal 1, stack.length
+
+    popped = stack.pop
+
+    assert_equal 0, stack.length
+
+    stack.push connection_args: popped
+
+    assert_equal 1, stack.length
+  end
+
+  def test_pop
+    object = Object.new
+    @stack.push object
+
+    popped = @stack.pop
+
+    assert_same object, popped
+  end
+
+  def test_pop_empty
+    e = assert_raises Timeout::Error do
+      @stack.pop timeout: 0
+    end
+
+    assert_equal 'Waited 0 sec', e.message
+  end
+
+  def test_pop_full
+    stack = Net::HTTP::Persistent::TimedStackMulti.new(1) { Object.new }
+
+    popped = stack.pop
+
+    refute_nil popped
+    assert_empty stack
+  end
+
+  def test_pop_wait
+    thread = Thread.start do
+      @stack.pop
+    end
+
+    Thread.pass while thread.status == 'run'
+
+    object = Object.new
+
+    @stack.push object
+
+    assert_same object, thread.value
+  end
+
+  def test_pop_shutdown
+    @stack.shutdown { }
+
+    assert_raises ConnectionPool::PoolShuttingDownError do
+      @stack.pop
+    end
+  end
+
+  def test_push
+    stack = Net::HTTP::Persistent::TimedStackMulti.new(1) { Object.new }
+
+    conn = stack.pop
+
+    stack.push connection_args: conn
+
+    refute_empty stack
+  end
+
+  def test_push_shutdown
+    called = []
+
+    @stack.shutdown do |object|
+      called << object
+    end
+
+    @stack.push connection_args: Object.new
+
+    refute_empty called
+    assert_empty @stack
+  end
+
+  def test_shutdown
+    @stack.push connection_args: Object.new
+
+    called = []
+
+    @stack.shutdown do |object|
+      called << object
+    end
+
+    refute_empty called
+    assert_empty @stack
+  end
+
+  def test_pop_recycle
+    stack = Net::HTTP::Persistent::TimedStackMulti.new(2) { |host| Connection.new(host) }
+
+    a_conn = stack.pop connection_args: 'a.example'
+    stack.push a_conn, connection_args: 'a.example'
+
+    b_conn = stack.pop connection_args: 'b.example'
+    stack.push b_conn, connection_args: 'b.example'
+
+    c_conn = stack.pop connection_args: 'c.example'
+
+    assert_equal 'c.example', c_conn.host
+
+    stack.push c_conn, connection_args: 'c.example'
+
+    recreated = stack.pop connection_args: 'a.example'
+
+    refute_same a_conn, recreated
+  end
+
+end
+