|
14 | 14 |
|
15 | 15 | from __future__ import annotations |
16 | 16 |
|
17 | | -import asyncio |
18 | 17 | import collections |
19 | 18 | import contextlib |
20 | | -import functools |
21 | 19 | import logging |
22 | 20 | import os |
23 | | -import socket |
24 | | -import ssl |
25 | 21 | import sys |
26 | 22 | import time |
27 | 23 | import weakref |
|
40 | 36 | from bson import DEFAULT_CODEC_OPTIONS |
41 | 37 | from pymongo import _csot, helpers_shared |
42 | 38 | from pymongo.asynchronous.client_session import _validate_session_write_concern |
43 | | -from pymongo.asynchronous.helpers import _getaddrinfo, _handle_reauth |
| 39 | +from pymongo.asynchronous.helpers import _handle_reauth |
44 | 40 | from pymongo.asynchronous.network import command |
45 | 41 | from pymongo.common import ( |
46 | 42 | MAX_BSON_SIZE, |
|
52 | 48 | from pymongo.errors import ( # type:ignore[attr-defined] |
53 | 49 | AutoReconnect, |
54 | 50 | ConfigurationError, |
55 | | - ConnectionFailure, |
56 | 51 | DocumentTooLarge, |
57 | 52 | ExecutionTimeout, |
58 | 53 | InvalidOperation, |
59 | 54 | NotPrimaryError, |
60 | 55 | OperationFailure, |
61 | 56 | PyMongoError, |
62 | 57 | WaitQueueTimeoutError, |
63 | | - _CertificateError, |
64 | 58 | ) |
65 | 59 | from pymongo.hello import Hello, HelloCompat |
66 | 60 | from pymongo.lock import ( |
|
85 | 79 | _configured_protocol, |
86 | 80 | _get_timeout_details, |
87 | 81 | _raise_connection_failure, |
88 | | - _set_keepalive_times, |
89 | 82 | format_timeout_details, |
90 | 83 | ) |
91 | 84 | from pymongo.read_preferences import ReadPreference |
92 | 85 | from pymongo.server_api import _add_to_command |
93 | 86 | from pymongo.server_type import SERVER_TYPE |
94 | 87 | from pymongo.socket_checker import SocketChecker |
95 | | -from pymongo.ssl_support import HAS_SNI, SSLError |
| 88 | +from pymongo.ssl_support import SSLError |
96 | 89 |
|
97 | 90 | if TYPE_CHECKING: |
98 | 91 | from bson import CodecOptions |
|
106 | 99 | ZstdContext, |
107 | 100 | ) |
108 | 101 | from pymongo.message import _OpMsg, _OpReply |
109 | | - from pymongo.pyopenssl_context import _sslConn |
110 | 102 | from pymongo.read_concern import ReadConcern |
111 | 103 | from pymongo.read_preferences import _ServerMode |
112 | 104 | from pymongo.typings import ClusterTime, _Address, _CollationIn |
@@ -670,145 +662,6 @@ def __repr__(self) -> str: |
670 | 662 | ) |
671 | 663 |
|
672 | 664 |
|
673 | | -async def _async_create_connection(address: _Address, options: PoolOptions) -> socket.socket: |
674 | | - """Given (host, port) and PoolOptions, connect and return a socket object. |
675 | | -
|
676 | | - Can raise socket.error. |
677 | | -
|
678 | | - This is a modified version of create_connection from CPython >= 2.7. |
679 | | - """ |
680 | | - host, port = address |
681 | | - |
682 | | - # Check if dealing with a unix domain socket |
683 | | - if host.endswith(".sock"): |
684 | | - if not hasattr(socket, "AF_UNIX"): |
685 | | - raise ConnectionFailure("UNIX-sockets are not supported on this system") |
686 | | - sock = socket.socket(socket.AF_UNIX) |
687 | | - # SOCK_CLOEXEC not supported for Unix sockets. |
688 | | - _set_non_inheritable_non_atomic(sock.fileno()) |
689 | | - try: |
690 | | - sock.connect(host) |
691 | | - return sock |
692 | | - except OSError: |
693 | | - sock.close() |
694 | | - raise |
695 | | - |
696 | | - # Don't try IPv6 if we don't support it. Also skip it if host |
697 | | - # is 'localhost' (::1 is fine). Avoids slow connect issues |
698 | | - # like PYTHON-356. |
699 | | - family = socket.AF_INET |
700 | | - if socket.has_ipv6 and host != "localhost": |
701 | | - family = socket.AF_UNSPEC |
702 | | - |
703 | | - err = None |
704 | | - for res in await _getaddrinfo(host, port, family=family, type=socket.SOCK_STREAM): # type: ignore[attr-defined] |
705 | | - af, socktype, proto, dummy, sa = res |
706 | | - # SOCK_CLOEXEC was new in CPython 3.2, and only available on a limited |
707 | | - # number of platforms (newer Linux and *BSD). Starting with CPython 3.4 |
708 | | - # all file descriptors are created non-inheritable. See PEP 446. |
709 | | - try: |
710 | | - sock = socket.socket(af, socktype | getattr(socket, "SOCK_CLOEXEC", 0), proto) |
711 | | - except OSError: |
712 | | - # Can SOCK_CLOEXEC be defined even if the kernel doesn't support |
713 | | - # it? |
714 | | - sock = socket.socket(af, socktype, proto) |
715 | | - # Fallback when SOCK_CLOEXEC isn't available. |
716 | | - _set_non_inheritable_non_atomic(sock.fileno()) |
717 | | - try: |
718 | | - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) |
719 | | - # CSOT: apply timeout to socket connect. |
720 | | - timeout = _csot.remaining() |
721 | | - if timeout is None: |
722 | | - timeout = options.connect_timeout |
723 | | - elif timeout <= 0: |
724 | | - raise socket.timeout("timed out") |
725 | | - sock.settimeout(timeout) |
726 | | - sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) |
727 | | - _set_keepalive_times(sock) |
728 | | - sock.connect(sa) |
729 | | - return sock |
730 | | - except OSError as e: |
731 | | - err = e |
732 | | - sock.close() |
733 | | - |
734 | | - if err is not None: |
735 | | - raise err |
736 | | - else: |
737 | | - # This likely means we tried to connect to an IPv6 only |
738 | | - # host with an OS/kernel or Python interpreter that doesn't |
739 | | - # support IPv6. The test case is Jython2.5.1 which doesn't |
740 | | - # support IPv6 at all. |
741 | | - raise OSError("getaddrinfo failed") |
742 | | - |
743 | | - |
744 | | -async def _async_configured_socket( |
745 | | - address: _Address, options: PoolOptions |
746 | | -) -> Union[socket.socket, _sslConn]: |
747 | | - """Given (host, port) and PoolOptions, return a configured socket. |
748 | | -
|
749 | | - Can raise socket.error, ConnectionFailure, or _CertificateError. |
750 | | -
|
751 | | - Sets socket's SSL and timeout options. |
752 | | - """ |
753 | | - sock = await _async_create_connection(address, options) |
754 | | - ssl_context = options._ssl_context |
755 | | - |
756 | | - if ssl_context is None: |
757 | | - sock.settimeout(options.socket_timeout) |
758 | | - return sock |
759 | | - |
760 | | - host = address[0] |
761 | | - try: |
762 | | - # We have to pass hostname / ip address to wrap_socket |
763 | | - # to use SSLContext.check_hostname. |
764 | | - if HAS_SNI: |
765 | | - if _IS_SYNC: |
766 | | - ssl_sock = ssl_context.wrap_socket(sock, server_hostname=host) |
767 | | - else: |
768 | | - if hasattr(ssl_context, "a_wrap_socket"): |
769 | | - ssl_sock = await ssl_context.a_wrap_socket(sock, server_hostname=host) # type: ignore[assignment, misc] |
770 | | - else: |
771 | | - loop = asyncio.get_running_loop() |
772 | | - ssl_sock = await loop.run_in_executor( |
773 | | - None, |
774 | | - functools.partial(ssl_context.wrap_socket, sock, server_hostname=host), # type: ignore[assignment, misc] |
775 | | - ) |
776 | | - else: |
777 | | - if _IS_SYNC: |
778 | | - ssl_sock = ssl_context.wrap_socket(sock) |
779 | | - else: |
780 | | - if hasattr(ssl_context, "a_wrap_socket"): |
781 | | - ssl_sock = await ssl_context.a_wrap_socket(sock) # type: ignore[assignment, misc] |
782 | | - else: |
783 | | - loop = asyncio.get_running_loop() |
784 | | - ssl_sock = await loop.run_in_executor(None, ssl_context.wrap_socket, sock) # type: ignore[assignment, misc] |
785 | | - except _CertificateError: |
786 | | - sock.close() |
787 | | - # Raise _CertificateError directly like we do after match_hostname |
788 | | - # below. |
789 | | - raise |
790 | | - except (OSError, SSLError) as exc: |
791 | | - sock.close() |
792 | | - # We raise AutoReconnect for transient and permanent SSL handshake |
793 | | - # failures alike. Permanent handshake failures, like protocol |
794 | | - # mismatch, will be turned into ServerSelectionTimeoutErrors later. |
795 | | - details = _get_timeout_details(options) |
796 | | - _raise_connection_failure(address, exc, "SSL handshake failed: ", timeout_details=details) |
797 | | - if ( |
798 | | - ssl_context.verify_mode |
799 | | - and not ssl_context.check_hostname |
800 | | - and not options.tls_allow_invalid_hostnames |
801 | | - ): |
802 | | - try: |
803 | | - ssl.match_hostname(ssl_sock.getpeercert(), hostname=host) # type:ignore[attr-defined] |
804 | | - except _CertificateError: |
805 | | - ssl_sock.close() |
806 | | - raise |
807 | | - |
808 | | - ssl_sock.settimeout(options.socket_timeout) |
809 | | - return ssl_sock |
810 | | - |
811 | | - |
812 | 665 | class _PoolClosedError(PyMongoError): |
813 | 666 | """Internal error raised when a thread tries to get a connection from a |
814 | 667 | closed pool. |
|
0 commit comments