class Net::LDAP::Connection

def self.wrap_with_ssl(io, tls_options = {}, timeout=nil, hostname=nil)

def self.wrap_with_ssl(io, tls_options = {}, timeout=nil, hostname=nil)
  raise Net::LDAP::NoOpenSSLError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL
  ctx = OpenSSL::SSL::SSLContext.new
  # By default, we do not verify certificates. For a 1.0 release, this should probably be changed at some point.
  # See discussion in https://github.com/ruby-ldap/ruby-net-ldap/pull/161
  ctx.set_params(tls_options) unless tls_options.empty?
  conn = OpenSSL::SSL::SSLSocket.new(io, ctx)
  conn.hostname = hostname
  begin
    if timeout
      conn.connect_nonblock
    else
      conn.connect
    end
  rescue IO::WaitReadable
    raise Errno::ETIMEDOUT, "OpenSSL connection read timeout" unless
      IO.select([conn], nil, nil, timeout)
    retry
  rescue IO::WaitWritable
    raise Errno::ETIMEDOUT, "OpenSSL connection write timeout" unless
      IO.select(nil, [conn], nil, timeout)
    retry
  end
  # Doesn't work:
  # conn.sync_close = true
  conn.extend(GetbyteForSSLSocket) unless conn.respond_to?(:getbyte)
  conn.extend(FixSSLSocketSyncClose)
  conn
end