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)
| 163 | |
| 164 | |
| 165 | async def _async_create_connection(address: _Address, options: PoolOptions) -> socket.socket: |
| 166 | """Given (host, port) and PoolOptions, connect and return a raw socket object. |
| 167 | |
| 168 | Can raise socket.error. |
| 169 | |
| 170 | This is a modified version of create_connection from CPython >= 2.7. |
| 171 | """ |
| 172 | host, port = address |
| 173 | |
| 174 | # Check if dealing with a unix domain socket |
| 175 | if host.endswith(".sock"): |
| 176 | if not hasattr(socket, "AF_UNIX"): |
| 177 | raise ConnectionFailure("UNIX-sockets are not supported on this system") |
| 178 | sock = socket.socket(socket.AF_UNIX) |
| 179 | # SOCK_CLOEXEC not supported for Unix sockets. |
| 180 | _set_non_inheritable_non_atomic(sock.fileno()) |
| 181 | try: |
| 182 | sock.setblocking(False) |
| 183 | await asyncio.get_running_loop().sock_connect(sock, host) |
| 184 | return sock |
| 185 | except OSError: |
| 186 | sock.close() |
| 187 | raise |
| 188 | |
| 189 | # Don't try IPv6 if we don't support it. Also skip it if host |
| 190 | # is 'localhost' (::1 is fine). Avoids slow connect issues |
| 191 | # like PYTHON-356. |
| 192 | family = socket.AF_INET |
| 193 | if socket.has_ipv6 and host != "localhost": |
| 194 | family = socket.AF_UNSPEC |
| 195 | |
| 196 | err = None |
| 197 | for res in await _getaddrinfo(host, port, family=family, type=socket.SOCK_STREAM): |
| 198 | af, socktype, proto, dummy, sa = res |
| 199 | # SOCK_CLOEXEC was new in CPython 3.2, and only available on a limited |
| 200 | # number of platforms (newer Linux and *BSD). Starting with CPython 3.4 |
| 201 | # all file descriptors are created non-inheritable. See PEP 446. |
| 202 | try: |
| 203 | sock = socket.socket(af, socktype | getattr(socket, "SOCK_CLOEXEC", 0), proto) |
| 204 | except OSError: |
| 205 | # Can SOCK_CLOEXEC be defined even if the kernel doesn't support |
| 206 | # it? |
| 207 | sock = socket.socket(af, socktype, proto) |
| 208 | # Fallback when SOCK_CLOEXEC isn't available. |
| 209 | _set_non_inheritable_non_atomic(sock.fileno()) |
| 210 | try: |
| 211 | sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) |
| 212 | # CSOT: apply timeout to socket connect. |
| 213 | timeout = _csot.remaining() |
| 214 | if timeout is None: |
| 215 | timeout = options.connect_timeout |
| 216 | elif timeout <= 0: |
| 217 | raise socket.timeout("timed out") |
| 218 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) |
| 219 | _set_keepalive_times(sock) |
| 220 | # Socket needs to be non-blocking during connection to not block the event loop |
| 221 | sock.setblocking(False) |
| 222 | await asyncio.wait_for( |
no test coverage detected