All arguments except for server_hostname, ssl_context, and ca_cert_dir have
    the same meaning as they do when using :func:`ssl.wrap_socket`.

    :param server_hostname:
        When SNI is supported, the expected hostname of the certificate
    :param ssl_context:
        A pre-made :class:`SSLContext` object. If none is provided, one will
        be created using :func:`create_urllib3_context`.
    :param ciphers:
        A string of ciphers we wish the client to support.
    :param ca_cert_dir:
        A directory containing CA certificates in multiple separate files, as
        supported by OpenSSL's -CApath flag or the capath argument to
        SSLContext.load_verify_locations().

def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
                    ca_certs=None, server_hostname=None,
                    ssl_version=None, ciphers=None, ssl_context=None,
                    ca_cert_dir=None):
    """
    All arguments except for server_hostname, ssl_context, and ca_cert_dir have
    the same meaning as they do when using :func:`ssl.wrap_socket`.

    :param server_hostname:
        When SNI is supported, the expected hostname of the certificate
    :param ssl_context:
        A pre-made :class:`SSLContext` object. If none is provided, one will
        be created using :func:`create_urllib3_context`.
    :param ciphers:
        A string of ciphers we wish the client to support.
    :param ca_cert_dir:
        A directory containing CA certificates in multiple separate files, as
        supported by OpenSSL's -CApath flag or the capath argument to
        SSLContext.load_verify_locations().
    """
    context = ssl_context
    if context is None:
        # Note: This branch of code and all the variables in it are no longer
        # used by urllib3 itself. We should consider deprecating and removing
        # this code.
        context = create_urllib3_context(ssl_version, cert_reqs,
                                         ciphers=ciphers)

    if ca_certs or ca_cert_dir:
        try:
            context.load_verify_locations(ca_certs, ca_cert_dir)
        except IOError as e:  # Platform-specific: Python 2.7
            raise SSLError(e)
        # Py33 raises FileNotFoundError which subclasses OSError
        # These are not equivalent unless we check the errno attribute
        except OSError as e:  # Platform-specific: Python 3.3 and beyond
            if e.errno == errno.ENOENT:
                raise SSLError(e)
            raise
    elif getattr(context, 'load_default_certs', None) is not None:
        # try to load OS default certs; works well on Windows (require Python3.4+)
        context.load_default_certs()

    if certfile:
        context.load_cert_chain(certfile, keyfile)

    # If we detect server_hostname is an IP address then the SNI
    # extension should not be used according to RFC3546 Section 3.1
    # We shouldn't warn the user if SNI isn't available but we would
    # not be using SNI anyways due to IP address for server_hostname.
    if ((server_hostname is not None and not is_ipaddress(server_hostname))
            or IS_SECURETRANSPORT):
        if HAS_SNI and server_hostname is not None:
            return context.wrap_socket(sock, server_hostname=server_hostname)

        warnings.warn(
            'An HTTPS request has been made, but the SNI (Server Name '
            'Indication) extension to TLS is not available on this platform. '
            'This may cause the server to present an incorrect TLS '
            'certificate, which can cause validation failures. You can upgrade to '
            'a newer version of Python to solve this. For more information, see '
            'https://urllib3.readthedocs.io/en/latest/advanced-usage.html'
            '#ssl-warnings',
            SNIMissingWarning
        )

    return context.wrap_socket(sock)