Given (host, port) and PoolOptions, return a raw configured socket. Can raise socket.error, ConnectionFailure, or _CertificateError. Sets socket's SSL and timeout options.
(
address: _Address, options: PoolOptions
)
| 242 | |
| 243 | |
| 244 | async def _async_configured_socket( |
| 245 | address: _Address, options: PoolOptions |
| 246 | ) -> Union[socket.socket, _sslConn]: |
| 247 | """Given (host, port) and PoolOptions, return a raw configured socket. |
| 248 | |
| 249 | Can raise socket.error, ConnectionFailure, or _CertificateError. |
| 250 | |
| 251 | Sets socket's SSL and timeout options. |
| 252 | """ |
| 253 | sock = await _async_create_connection(address, options) |
| 254 | ssl_context = options._ssl_context |
| 255 | |
| 256 | if ssl_context is None: |
| 257 | sock.settimeout(options.socket_timeout) |
| 258 | return sock |
| 259 | |
| 260 | host = address[0] |
| 261 | try: |
| 262 | # We have to pass hostname / ip address to wrap_socket |
| 263 | # to use SSLContext.check_hostname. |
| 264 | if _has_sni(False): |
| 265 | loop = asyncio.get_running_loop() |
| 266 | ssl_sock = await loop.run_in_executor( |
| 267 | None, |
| 268 | functools.partial(ssl_context.wrap_socket, sock, server_hostname=host), # type: ignore[assignment, misc, unused-ignore] |
| 269 | ) |
| 270 | else: |
| 271 | loop = asyncio.get_running_loop() |
| 272 | ssl_sock = await loop.run_in_executor(None, ssl_context.wrap_socket, sock) # type: ignore[assignment, misc, unused-ignore] |
| 273 | except _CertificateError: |
| 274 | sock.close() |
| 275 | # Raise _CertificateError directly like we do after match_hostname |
| 276 | # below. |
| 277 | raise |
| 278 | except (OSError, *SSLErrors) as exc: |
| 279 | sock.close() |
| 280 | # We raise AutoReconnect for transient and permanent SSL handshake |
| 281 | # failures alike. Permanent handshake failures, like protocol |
| 282 | # mismatch, will be turned into ServerSelectionTimeoutErrors later. |
| 283 | details = _get_timeout_details(options) |
| 284 | _raise_connection_failure(address, exc, "SSL handshake failed: ", timeout_details=details) |
| 285 | if ( |
| 286 | ssl_context.verify_mode |
| 287 | and not ssl_context.check_hostname |
| 288 | and not options.tls_allow_invalid_hostnames |
| 289 | ): |
| 290 | try: |
| 291 | ssl.match_hostname(ssl_sock.getpeercert(), hostname=host) # type:ignore[attr-defined, unused-ignore] |
| 292 | except _CertificateError: |
| 293 | ssl_sock.close() |
| 294 | raise |
| 295 | |
| 296 | ssl_sock.settimeout(options.socket_timeout) |
| 297 | return ssl_sock |
| 298 | |
| 299 | |
| 300 | async def _configured_protocol_interface( |
no test coverage detected