Path: blob/master/venv/Lib/site-packages/urllib3/util/connection.py
811 views
from __future__ import absolute_import1import socket2from .wait import NoWayToWaitForSocketError, wait_for_read3from ..contrib import _appengine_environ456def is_connection_dropped(conn): # Platform-specific7"""8Returns True if the connection is dropped and should be closed.910:param conn:11:class:`httplib.HTTPConnection` object.1213Note: For platforms like AppEngine, this will always return ``False`` to14let the platform handle connection recycling transparently for us.15"""16sock = getattr(conn, "sock", False)17if sock is False: # Platform-specific: AppEngine18return False19if sock is None: # Connection already closed (such as by httplib).20return True21try:22# Returns True if readable, which here means it's been dropped23return wait_for_read(sock, timeout=0.0)24except NoWayToWaitForSocketError: # Platform-specific: AppEngine25return False262728# This function is copied from socket.py in the Python 2.7 standard29# library test suite. Added to its signature is only `socket_options`.30# One additional modification is that we avoid binding to IPv6 servers31# discovered in DNS if the system doesn't have IPv6 functionality.32def create_connection(33address,34timeout=socket._GLOBAL_DEFAULT_TIMEOUT,35source_address=None,36socket_options=None,37):38"""Connect to *address* and return the socket object.3940Convenience function. Connect to *address* (a 2-tuple ``(host,41port)``) and return the socket object. Passing the optional42*timeout* parameter will set the timeout on the socket instance43before attempting to connect. If no *timeout* is supplied, the44global default timeout setting returned by :func:`getdefaulttimeout`45is used. If *source_address* is set it must be a tuple of (host, port)46for the socket to bind as a source address before making the connection.47An host of '' or port 0 tells the OS to use the default.48"""4950host, port = address51if host.startswith("["):52host = host.strip("[]")53err = None5455# Using the value from allowed_gai_family() in the context of getaddrinfo lets56# us select whether to work with IPv4 DNS records, IPv6 records, or both.57# The original create_connection function always returns all records.58family = allowed_gai_family()5960for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):61af, socktype, proto, canonname, sa = res62sock = None63try:64sock = socket.socket(af, socktype, proto)6566# If provided, set socket level options before connecting.67_set_socket_options(sock, socket_options)6869if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:70sock.settimeout(timeout)71if source_address:72sock.bind(source_address)73sock.connect(sa)74return sock7576except socket.error as e:77err = e78if sock is not None:79sock.close()80sock = None8182if err is not None:83raise err8485raise socket.error("getaddrinfo returns an empty list")868788def _set_socket_options(sock, options):89if options is None:90return9192for opt in options:93sock.setsockopt(*opt)949596def allowed_gai_family():97"""This function is designed to work in the context of98getaddrinfo, where family=socket.AF_UNSPEC is the default and99will perform a DNS search for both IPv6 and IPv4 records."""100101family = socket.AF_INET102if HAS_IPV6:103family = socket.AF_UNSPEC104return family105106107def _has_ipv6(host):108""" Returns True if the system can bind an IPv6 address. """109sock = None110has_ipv6 = False111112# App Engine doesn't support IPV6 sockets and actually has a quota on the113# number of sockets that can be used, so just early out here instead of114# creating a socket needlessly.115# See https://github.com/urllib3/urllib3/issues/1446116if _appengine_environ.is_appengine_sandbox():117return False118119if socket.has_ipv6:120# has_ipv6 returns true if cPython was compiled with IPv6 support.121# It does not tell us if the system has IPv6 support enabled. To122# determine that we must bind to an IPv6 address.123# https://github.com/urllib3/urllib3/pull/611124# https://bugs.python.org/issue658327125try:126sock = socket.socket(socket.AF_INET6)127sock.bind((host, 0))128has_ipv6 = True129except Exception:130pass131132if sock:133sock.close()134return has_ipv6135136137HAS_IPV6 = _has_ipv6("::1")138139140