Given (host, port) and PoolOptions, connect and return a raw socket object. Can raise socket.error. This is a modified version of create_connection from CPython >= 2.7.
(address: _Address, options: PoolOptions)
| 352 | |
| 353 | |
| 354 | def _create_connection(address: _Address, options: PoolOptions) -> socket.socket: |
| 355 | """Given (host, port) and PoolOptions, connect and return a raw socket object. |
| 356 | |
| 357 | Can raise socket.error. |
| 358 | |
| 359 | This is a modified version of create_connection from CPython >= 2.7. |
| 360 | """ |
| 361 | host, port = address |
| 362 | |
| 363 | # Check if dealing with a unix domain socket |
| 364 | if host.endswith(".sock"): |
| 365 | if not hasattr(socket, "AF_UNIX"): |
| 366 | raise ConnectionFailure("UNIX-sockets are not supported on this system") |
| 367 | sock = socket.socket(socket.AF_UNIX) |
| 368 | # SOCK_CLOEXEC not supported for Unix sockets. |
| 369 | _set_non_inheritable_non_atomic(sock.fileno()) |
| 370 | try: |
| 371 | sock.connect(host) |
| 372 | return sock |
| 373 | except OSError: |
| 374 | sock.close() |
| 375 | raise |
| 376 | |
| 377 | # Don't try IPv6 if we don't support it. Also skip it if host |
| 378 | # is 'localhost' (::1 is fine). Avoids slow connect issues |
| 379 | # like PYTHON-356. |
| 380 | family = socket.AF_INET |
| 381 | if socket.has_ipv6 and host != "localhost": |
| 382 | family = socket.AF_UNSPEC |
| 383 | |
| 384 | err = None |
| 385 | for res in socket.getaddrinfo(host, port, family=family, type=socket.SOCK_STREAM): # type: ignore[attr-defined, unused-ignore] |
| 386 | af, socktype, proto, dummy, sa = res |
| 387 | # SOCK_CLOEXEC was new in CPython 3.2, and only available on a limited |
| 388 | # number of platforms (newer Linux and *BSD). Starting with CPython 3.4 |
| 389 | # all file descriptors are created non-inheritable. See PEP 446. |
| 390 | try: |
| 391 | sock = socket.socket(af, socktype | getattr(socket, "SOCK_CLOEXEC", 0), proto) |
| 392 | except OSError: |
| 393 | # Can SOCK_CLOEXEC be defined even if the kernel doesn't support |
| 394 | # it? |
| 395 | sock = socket.socket(af, socktype, proto) |
| 396 | # Fallback when SOCK_CLOEXEC isn't available. |
| 397 | _set_non_inheritable_non_atomic(sock.fileno()) |
| 398 | try: |
| 399 | sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) |
| 400 | # CSOT: apply timeout to socket connect. |
| 401 | timeout = _csot.remaining() |
| 402 | if timeout is None: |
| 403 | timeout = options.connect_timeout |
| 404 | elif timeout <= 0: |
| 405 | raise socket.timeout("timed out") |
| 406 | sock.settimeout(timeout) |
| 407 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) |
| 408 | _set_keepalive_times(sock) |
| 409 | sock.connect(sa) |
| 410 | return sock |
| 411 | except OSError as e: |
no test coverage detected