Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
socket.py989 linesDownload Raw Back to Lib
1# Wrapper module for _socket, providing some additional facilities2# implemented in Python.3 4"""\5This module provides socket operations and some related functions.6On Unix, it supports IP (Internet Protocol) and Unix domain sockets.7On other systems, it only supports IP. Functions specific for a8socket are available as methods of the socket object.9 10Functions:11 12socket() -- create a new socket object13socketpair() -- create a pair of new socket objects [*]14fromfd() -- create a socket object from an open file descriptor [*]15send_fds() -- Send file descriptor to the socket.16recv_fds() -- Receive file descriptors from the socket.17fromshare() -- create a socket object from data received from socket.share() [*]18gethostname() -- return the current hostname19gethostbyname() -- map a hostname to its IP number20gethostbyaddr() -- map an IP number or hostname to DNS info21getservbyname() -- map a service name and a protocol name to a port number22getprotobyname() -- map a protocol name (e.g. 'tcp') to a number23ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order24htons(), htonl() -- convert 16, 32 bit int from host to network byte order25inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format26inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)27socket.getdefaulttimeout() -- get the default timeout value28socket.setdefaulttimeout() -- set the default timeout value29create_connection() -- connects to an address, with an optional timeout and30                       optional source address.31create_server() -- create a TCP socket and bind it to a specified address.32 33 [*] not available on all platforms!34 35Special objects:36 37SocketType -- type object for socket objects38error -- exception raised for I/O errors39has_ipv6 -- boolean value indicating if IPv6 is supported40 41IntEnum constants:42 43AF_INET, AF_UNIX -- socket domains (first argument to socket() call)44SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)45 46Integer constants:47 48Many other constants may be defined; these may be used in calls to49the setsockopt() and getsockopt() methods.50"""51 52import _socket53from _socket import *54 55import io56import os57import sys58from enum import IntEnum, IntFlag59 60try:61    import errno62except ImportError:63    errno = None64EBADF = getattr(errno, 'EBADF', 9)65EAGAIN = getattr(errno, 'EAGAIN', 11)66EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)67 68__all__ = ["fromfd", "getfqdn", "create_connection", "create_server",69           "has_dualstack_ipv6", "AddressFamily", "SocketKind"]70__all__.extend(os._get_exports_list(_socket))71 72# Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for73# nicer string representations.74# Note that _socket only knows about the integer values. The public interface75# in this module understands the enums and translates them back from integers76# where needed (e.g. .family property of a socket object).77 78IntEnum._convert_(79        'AddressFamily',80        __name__,81        lambda C: C.isupper() and C.startswith('AF_'))82 83IntEnum._convert_(84        'SocketKind',85        __name__,86        lambda C: C.isupper() and C.startswith('SOCK_'))87 88IntFlag._convert_(89        'MsgFlag',90        __name__,91        lambda C: C.isupper() and C.startswith('MSG_'))92 93IntFlag._convert_(94        'AddressInfo',95        __name__,96        lambda C: C.isupper() and C.startswith('AI_'))97 98_LOCALHOST    = '127.0.0.1'99_LOCALHOST_V6 = '::1'100 101 102def _intenum_converter(value, enum_klass):103    """Convert a numeric family value to an IntEnum member.104 105    If it's not a known member, return the numeric value itself.106    """107    try:108        return enum_klass(value)109    except ValueError:110        return value111 112 113# WSA error codes114if sys.platform.lower().startswith("win"):115    errorTab = {116        6: "Specified event object handle is invalid.",117        8: "Insufficient memory available.",118        87: "One or more parameters are invalid.",119        995: "Overlapped operation aborted.",120        996: "Overlapped I/O event object not in signaled state.",121        997: "Overlapped operation will complete later.",122        10004: "The operation was interrupted.",123        10009: "A bad file handle was passed.",124        10013: "Permission denied.",125        10014: "A fault occurred on the network??",126        10022: "An invalid operation was attempted.",127        10024: "Too many open files.",128        10035: "The socket operation would block.",129        10036: "A blocking operation is already in progress.",130        10037: "Operation already in progress.",131        10038: "Socket operation on nonsocket.",132        10039: "Destination address required.",133        10040: "Message too long.",134        10041: "Protocol wrong type for socket.",135        10042: "Bad protocol option.",136        10043: "Protocol not supported.",137        10044: "Socket type not supported.",138        10045: "Operation not supported.",139        10046: "Protocol family not supported.",140        10047: "Address family not supported by protocol family.",141        10048: "The network address is in use.",142        10049: "Cannot assign requested address.",143        10050: "Network is down.",144        10051: "Network is unreachable.",145        10052: "Network dropped connection on reset.",146        10053: "Software caused connection abort.",147        10054: "The connection has been reset.",148        10055: "No buffer space available.",149        10056: "Socket is already connected.",150        10057: "Socket is not connected.",151        10058: "The network has been shut down.",152        10059: "Too many references.",153        10060: "The operation timed out.",154        10061: "Connection refused.",155        10062: "Cannot translate name.",156        10063: "The name is too long.",157        10064: "The host is down.",158        10065: "The host is unreachable.",159        10066: "Directory not empty.",160        10067: "Too many processes.",161        10068: "User quota exceeded.",162        10069: "Disk quota exceeded.",163        10070: "Stale file handle reference.",164        10071: "Item is remote.",165        10091: "Network subsystem is unavailable.",166        10092: "Winsock.dll version out of range.",167        10093: "Successful WSAStartup not yet performed.",168        10101: "Graceful shutdown in progress.",169        10102: "No more results from WSALookupServiceNext.",170        10103: "Call has been canceled.",171        10104: "Procedure call table is invalid.",172        10105: "Service provider is invalid.",173        10106: "Service provider failed to initialize.",174        10107: "System call failure.",175        10108: "Service not found.",176        10109: "Class type not found.",177        10110: "No more results from WSALookupServiceNext.",178        10111: "Call was canceled.",179        10112: "Database query was refused.",180        11001: "Host not found.",181        11002: "Nonauthoritative host not found.",182        11003: "This is a nonrecoverable error.",183        11004: "Valid name, no data record requested type.",184        11005: "QoS receivers.",185        11006: "QoS senders.",186        11007: "No QoS senders.",187        11008: "QoS no receivers.",188        11009: "QoS request confirmed.",189        11010: "QoS admission error.",190        11011: "QoS policy failure.",191        11012: "QoS bad style.",192        11013: "QoS bad object.",193        11014: "QoS traffic control error.",194        11015: "QoS generic error.",195        11016: "QoS service type error.",196        11017: "QoS flowspec error.",197        11018: "Invalid QoS provider buffer.",198        11019: "Invalid QoS filter style.",199        11020: "Invalid QoS filter style.",200        11021: "Incorrect QoS filter count.",201        11022: "Invalid QoS object length.",202        11023: "Incorrect QoS flow count.",203        11024: "Unrecognized QoS object.",204        11025: "Invalid QoS policy object.",205        11026: "Invalid QoS flow descriptor.",206        11027: "Invalid QoS provider-specific flowspec.",207        11028: "Invalid QoS provider-specific filterspec.",208        11029: "Invalid QoS shape discard mode object.",209        11030: "Invalid QoS shaping rate object.",210        11031: "Reserved policy QoS element type."211    }212    __all__.append("errorTab")213 214 215class _GiveupOnSendfile(Exception): pass216 217 218class socket(_socket.socket):219 220    """A subclass of _socket.socket adding the makefile() method."""221 222    __slots__ = ["__weakref__", "_io_refs", "_closed"]223 224    def __init__(self, family=-1, type=-1, proto=-1, fileno=None):225        # For user code address family and type values are IntEnum members, but226        # for the underlying _socket.socket they're just integers. The227        # constructor of _socket.socket converts the given argument to an228        # integer automatically.229        if fileno is None:230            if family == -1:231                family = AF_INET232            if type == -1:233                type = SOCK_STREAM234            if proto == -1:235                proto = 0236        _socket.socket.__init__(self, family, type, proto, fileno)237        self._io_refs = 0238        self._closed = False239 240    def __enter__(self):241        return self242 243    def __exit__(self, *args):244        if not self._closed:245            self.close()246 247    def __repr__(self):248        """Wrap __repr__() to reveal the real class name and socket249        address(es).250        """251        closed = getattr(self, '_closed', False)252        s = "<%s.%s%s fd=%i, family=%s, type=%s, proto=%i" \253            % (self.__class__.__module__,254               self.__class__.__qualname__,255               " [closed]" if closed else "",256               self.fileno(),257               self.family,258               self.type,259               self.proto)260        if not closed:261            # getsockname and getpeername may not be available on WASI.262            try:263                laddr = self.getsockname()264                if laddr:265                    s += ", laddr=%s" % str(laddr)266            except (error, AttributeError):267                pass268            try:269                raddr = self.getpeername()270                if raddr:271                    s += ", raddr=%s" % str(raddr)272            except (error, AttributeError):273                pass274        s += '>'275        return s276 277    def __getstate__(self):278        raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")279 280    def dup(self):281        """dup() -> socket object282 283        Duplicate the socket. Return a new socket object connected to the same284        system resource. The new socket is non-inheritable.285        """286        fd = dup(self.fileno())287        sock = self.__class__(self.family, self.type, self.proto, fileno=fd)288        sock.settimeout(self.gettimeout())289        return sock290 291    def accept(self):292        """accept() -> (socket object, address info)293 294        Wait for an incoming connection.  Return a new socket295        representing the connection, and the address of the client.296        For IP sockets, the address info is a pair (hostaddr, port).297        """298        fd, addr = self._accept()299        sock = socket(self.family, self.type, self.proto, fileno=fd)300        # Issue #7995: if no default timeout is set and the listening301        # socket had a (non-zero) timeout, force the new socket in blocking302        # mode to override platform-specific socket flags inheritance.303        if getdefaulttimeout() is None and self.gettimeout():304            sock.setblocking(True)305        return sock, addr306 307    def makefile(self, mode="r", buffering=None, *,308                 encoding=None, errors=None, newline=None):309        """makefile(...) -> an I/O stream connected to the socket310 311        The arguments are as for io.open() after the filename, except the only312        supported mode values are 'r' (default), 'w', 'b', or a combination of313        those.314        """315        # XXX refactor to share code?316        if not set(mode) <= {"r", "w", "b"}:317            raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))318        writing = "w" in mode319        reading = "r" in mode or not writing320        assert reading or writing321        binary = "b" in mode322        rawmode = ""323        if reading:324            rawmode += "r"325        if writing:326            rawmode += "w"327        raw = SocketIO(self, rawmode)328        self._io_refs += 1329        if buffering is None:330            buffering = -1331        if buffering < 0:332            buffering = io.DEFAULT_BUFFER_SIZE333        if buffering == 0:334            if not binary:335                raise ValueError("unbuffered streams must be binary")336            return raw337        if reading and writing:338            buffer = io.BufferedRWPair(raw, raw, buffering)339        elif reading:340            buffer = io.BufferedReader(raw, buffering)341        else:342            assert writing343            buffer = io.BufferedWriter(raw, buffering)344        if binary:345            return buffer346        encoding = io.text_encoding(encoding)347        text = io.TextIOWrapper(buffer, encoding, errors, newline)348        text.mode = mode349        return text350 351    if hasattr(os, 'sendfile'):352 353        def _sendfile_use_sendfile(self, file, offset=0, count=None):354            # Lazy import to improve module import time355            import selectors356 357            self._check_sendfile_params(file, offset, count)358            sockno = self.fileno()359            try:360                fileno = file.fileno()361            except (AttributeError, io.UnsupportedOperation) as err:362                raise _GiveupOnSendfile(err)  # not a regular file363            try:364                fsize = os.fstat(fileno).st_size365            except OSError as err:366                raise _GiveupOnSendfile(err)  # not a regular file367            if not fsize:368                return 0  # empty file369            # Truncate to 1GiB to avoid OverflowError, see bpo-38319.370            blocksize = min(count or fsize, 2 ** 30)371            timeout = self.gettimeout()372            if timeout == 0:373                raise ValueError("non-blocking sockets are not supported")374            # poll/select have the advantage of not requiring any375            # extra file descriptor, contrarily to epoll/kqueue376            # (also, they require a single syscall).377            if hasattr(selectors, 'PollSelector'):378                selector = selectors.PollSelector()379            else:380                selector = selectors.SelectSelector()381            selector.register(sockno, selectors.EVENT_WRITE)382 383            total_sent = 0384            # localize variable access to minimize overhead385            selector_select = selector.select386            os_sendfile = os.sendfile387            try:388                while True:389                    if timeout and not selector_select(timeout):390                        raise TimeoutError('timed out')391                    if count:392                        blocksize = min(count - total_sent, blocksize)393                        if blocksize <= 0:394                            break395                    try:396                        sent = os_sendfile(sockno, fileno, offset, blocksize)397                    except BlockingIOError:398                        if not timeout:399                            # Block until the socket is ready to send some400                            # data; avoids hogging CPU resources.401                            selector_select()402                        continue403                    except OSError as err:404                        if total_sent == 0:405                            # We can get here for different reasons, the main406                            # one being 'file' is not a regular mmap(2)-like407                            # file, in which case we'll fall back on using408                            # plain send().409                            raise _GiveupOnSendfile(err)410                        raise err from None411                    else:412                        if sent == 0:413                            break  # EOF414                        offset += sent415                        total_sent += sent416                return total_sent417            finally:418                if total_sent > 0 and hasattr(file, 'seek'):419                    file.seek(offset)420    else:421        def _sendfile_use_sendfile(self, file, offset=0, count=None):422            raise _GiveupOnSendfile(423                "os.sendfile() not available on this platform")424 425    def _sendfile_use_send(self, file, offset=0, count=None):426        self._check_sendfile_params(file, offset, count)427        if self.gettimeout() == 0:428            raise ValueError("non-blocking sockets are not supported")429        if offset:430            file.seek(offset)431        blocksize = min(count, 8192) if count else 8192432        total_sent = 0433        # localize variable access to minimize overhead434        file_read = file.read435        sock_send = self.send436        try:437            while True:438                if count:439                    blocksize = min(count - total_sent, blocksize)440                    if blocksize <= 0:441                        break442                data = memoryview(file_read(blocksize))443                if not data:444                    break  # EOF445                while True:446                    try:447                        sent = sock_send(data)448                    except BlockingIOError:449                        continue450                    else:451                        total_sent += sent452                        if sent < len(data):453                            data = data[sent:]454                        else:455                            break456            return total_sent457        finally:458            if total_sent > 0 and hasattr(file, 'seek'):459                file.seek(offset + total_sent)460 461    def _check_sendfile_params(self, file, offset, count):462        if 'b' not in getattr(file, 'mode', 'b'):463            raise ValueError("file should be opened in binary mode")464        if not self.type & SOCK_STREAM:465            raise ValueError("only SOCK_STREAM type sockets are supported")466        if count is not None:467            if not isinstance(count, int):468                raise TypeError(469                    "count must be a positive integer (got {!r})".format(count))470            if count <= 0:471                raise ValueError(472                    "count must be a positive integer (got {!r})".format(count))473 474    def sendfile(self, file, offset=0, count=None):475        """sendfile(file[, offset[, count]]) -> sent476 477        Send a file until EOF is reached by using high-performance478        os.sendfile() and return the total number of bytes which479        were sent.480        *file* must be a regular file object opened in binary mode.481        If os.sendfile() is not available (e.g. Windows) or file is482        not a regular file socket.send() will be used instead.483        *offset* tells from where to start reading the file.484        If specified, *count* is the total number of bytes to transmit485        as opposed to sending the file until EOF is reached.486        File position is updated on return or also in case of error in487        which case file.tell() can be used to figure out the number of488        bytes which were sent.489        The socket must be of SOCK_STREAM type.490        Non-blocking sockets are not supported.491        """492        try:493            return self._sendfile_use_sendfile(file, offset, count)494        except _GiveupOnSendfile:495            return self._sendfile_use_send(file, offset, count)496 497    def _decref_socketios(self):498        if self._io_refs > 0:499            self._io_refs -= 1500        if self._closed:501            self.close()502 503    def _real_close(self, _ss=_socket.socket):504        # This function should not reference any globals. See issue #808164.505        _ss.close(self)506 507    def close(self):508        # This function should not reference any globals. See issue #808164.509        self._closed = True510        if self._io_refs <= 0:511            self._real_close()512 513    def detach(self):514        """detach() -> file descriptor515 516        Close the socket object without closing the underlying file descriptor.517        The object cannot be used after this call, but the file descriptor518        can be reused for other purposes.  The file descriptor is returned.519        """520        self._closed = True521        return super().detach()522 523    @property524    def family(self):525        """Read-only access to the address family for this socket.526        """527        return _intenum_converter(super().family, AddressFamily)528 529    @property530    def type(self):531        """Read-only access to the socket type.532        """533        return _intenum_converter(super().type, SocketKind)534 535    if os.name == 'nt':536        def get_inheritable(self):537            return os.get_handle_inheritable(self.fileno())538        def set_inheritable(self, inheritable):539            os.set_handle_inheritable(self.fileno(), inheritable)540    else:541        def get_inheritable(self):542            return os.get_inheritable(self.fileno())543        def set_inheritable(self, inheritable):544            os.set_inheritable(self.fileno(), inheritable)545    get_inheritable.__doc__ = "Get the inheritable flag of the socket"546    set_inheritable.__doc__ = "Set the inheritable flag of the socket"547 548def fromfd(fd, family, type, proto=0):549    """ fromfd(fd, family, type[, proto]) -> socket object550 551    Create a socket object from a duplicate of the given file552    descriptor.  The remaining arguments are the same as for socket().553    """554    nfd = dup(fd)555    return socket(family, type, proto, nfd)556 557if hasattr(_socket.socket, "sendmsg"):558    def send_fds(sock, buffers, fds, flags=0, address=None):559        """ send_fds(sock, buffers, fds[, flags[, address]]) -> integer560 561        Send the list of file descriptors fds over an AF_UNIX socket.562        """563        import array564 565        return sock.sendmsg(buffers, [(_socket.SOL_SOCKET,566            _socket.SCM_RIGHTS, array.array("i", fds))])567    __all__.append("send_fds")568 569if hasattr(_socket.socket, "recvmsg"):570    def recv_fds(sock, bufsize, maxfds, flags=0):571        """ recv_fds(sock, bufsize, maxfds[, flags]) -> (data, list of file572        descriptors, msg_flags, address)573 574        Receive up to maxfds file descriptors returning the message575        data and a list containing the descriptors.576        """577        import array578 579        # Array of ints580        fds = array.array("i")581        msg, ancdata, flags, addr = sock.recvmsg(bufsize,582            _socket.CMSG_LEN(maxfds * fds.itemsize))583        for cmsg_level, cmsg_type, cmsg_data in ancdata:584            if (cmsg_level == _socket.SOL_SOCKET and cmsg_type == _socket.SCM_RIGHTS):585                fds.frombytes(cmsg_data[:586                        len(cmsg_data) - (len(cmsg_data) % fds.itemsize)])587 588        return msg, list(fds), flags, addr589    __all__.append("recv_fds")590 591if hasattr(_socket.socket, "share"):592    def fromshare(info):593        """ fromshare(info) -> socket object594 595        Create a socket object from the bytes object returned by596        socket.share(pid).597        """598        return socket(0, 0, 0, info)599    __all__.append("fromshare")600 601# Origin: https://gist.github.com/4325783, by Geert Jansen.  Public domain.602# This is used if _socket doesn't natively provide socketpair. It's603# always defined so that it can be patched in for testing purposes.604def _fallback_socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):605    if family == AF_INET:606        host = _LOCALHOST607    elif family == AF_INET6:608        host = _LOCALHOST_V6609    else:610        raise ValueError("Only AF_INET and AF_INET6 socket address families "611                         "are supported")612    if type != SOCK_STREAM:613        raise ValueError("Only SOCK_STREAM socket type is supported")614    if proto != 0:615        raise ValueError("Only protocol zero is supported")616 617    # We create a connected TCP socket. Note the trick with618    # setblocking(False) that prevents us from having to create a thread.619    lsock = socket(family, type, proto)620    try:621        lsock.bind((host, 0))622        lsock.listen()623        # On IPv6, ignore flow_info and scope_id624        addr, port = lsock.getsockname()[:2]625        csock = socket(family, type, proto)626        try:627            csock.setblocking(False)628            try:629                csock.connect((addr, port))630            except (BlockingIOError, InterruptedError):631                pass632            csock.setblocking(True)633            ssock, _ = lsock.accept()634        except:635            csock.close()636            raise637    finally:638        lsock.close()639 640    # Authenticating avoids using a connection from something else641    # able to connect to {host}:{port} instead of us.642    # We expect only AF_INET and AF_INET6 families.643    try:644        if (645            ssock.getsockname() != csock.getpeername()646            or csock.getsockname() != ssock.getpeername()647        ):648            raise ConnectionError("Unexpected peer connection")649    except:650        # getsockname() and getpeername() can fail651        # if either socket isn't connected.652        ssock.close()653        csock.close()654        raise655 656    return (ssock, csock)657 658if hasattr(_socket, "socketpair"):659    def socketpair(family=None, type=SOCK_STREAM, proto=0):660        if family is None:661            try:662                family = AF_UNIX663            except NameError:664                family = AF_INET665        a, b = _socket.socketpair(family, type, proto)666        a = socket(family, type, proto, a.detach())667        b = socket(family, type, proto, b.detach())668        return a, b669 670else:671    socketpair = _fallback_socketpair672    __all__.append("socketpair")673 674socketpair.__doc__ = """socketpair([family[, type[, proto]]]) -> (socket object, socket object)675Create a pair of socket objects from the sockets returned by the platform676socketpair() function.677The arguments are the same as for socket() except the default family is AF_UNIX678if defined on the platform; otherwise, the default is AF_INET.679"""680 681_blocking_errnos = { EAGAIN, EWOULDBLOCK }682 683class SocketIO(io.RawIOBase):684 685    """Raw I/O implementation for stream sockets.686 687    This class supports the makefile() method on sockets.  It provides688    the raw I/O interface on top of a socket object.689    """690 691    # One might wonder why not let FileIO do the job instead.  There are two692    # main reasons why FileIO is not adapted:693    # - it wouldn't work under Windows (where you can't used read() and694    #   write() on a socket handle)695    # - it wouldn't work with socket timeouts (FileIO would ignore the696    #   timeout and consider the socket non-blocking)697 698    # XXX More docs699 700    def __init__(self, sock, mode):701        if mode not in ("r", "w", "rw", "rb", "wb", "rwb"):702            raise ValueError("invalid mode: %r" % mode)703        io.RawIOBase.__init__(self)704        self._sock = sock705        if "b" not in mode:706            mode += "b"707        self._mode = mode708        self._reading = "r" in mode709        self._writing = "w" in mode710        self._timeout_occurred = False711 712    def readinto(self, b):713        """Read up to len(b) bytes into the writable buffer *b* and return714        the number of bytes read.  If the socket is non-blocking and no bytes715        are available, None is returned.716 717        If *b* is non-empty, a 0 return value indicates that the connection718        was shutdown at the other end.719        """720        self._checkClosed()721        self._checkReadable()722        if self._timeout_occurred:723            raise OSError("cannot read from timed out object")724        try:725            return self._sock.recv_into(b)726        except timeout:727            self._timeout_occurred = True728            raise729        except error as e:730            if e.errno in _blocking_errnos:731                return None732            raise733 734    def write(self, b):735        """Write the given bytes or bytearray object *b* to the socket736        and return the number of bytes written.  This can be less than737        len(b) if not all data could be written.  If the socket is738        non-blocking and no bytes could be written None is returned.739        """740        self._checkClosed()741        self._checkWritable()742        try:743            return self._sock.send(b)744        except error as e:745            # XXX what about EINTR?746            if e.errno in _blocking_errnos:747                return None748            raise749 750    def readable(self):751        """True if the SocketIO is open for reading.752        """753        if self.closed:754            raise ValueError("I/O operation on closed socket.")755        return self._reading756 757    def writable(self):758        """True if the SocketIO is open for writing.759        """760        if self.closed:761            raise ValueError("I/O operation on closed socket.")762        return self._writing763 764    def seekable(self):765        """True if the SocketIO is open for seeking.766        """767        if self.closed:768            raise ValueError("I/O operation on closed socket.")769        return super().seekable()770 771    def fileno(self):772        """Return the file descriptor of the underlying socket.773        """774        self._checkClosed()775        return self._sock.fileno()776 777    @property778    def name(self):779        if not self.closed:780            return self.fileno()781        else:782            return -1783 784    @property785    def mode(self):786        return self._mode787 788    def close(self):789        """Close the SocketIO object.  This doesn't close the underlying790        socket, except if all references to it have disappeared.791        """792        if self.closed:793            return794        io.RawIOBase.close(self)795        self._sock._decref_socketios()796        self._sock = None797 798 799def getfqdn(name=''):800    """Get fully qualified domain name from name.801 802    An empty argument is interpreted as meaning the local host.803 804    First the hostname returned by gethostbyaddr() is checked, then805    possibly existing aliases. In case no FQDN is available and `name`806    was given, it is returned unchanged. If `name` was empty, '0.0.0.0' or '::',807    hostname from gethostname() is returned.808    """809    name = name.strip()810    if not name or name in ('0.0.0.0', '::'):811        name = gethostname()812    try:813        hostname, aliases, ipaddrs = gethostbyaddr(name)814    except error:815        pass816    else:817        aliases.insert(0, hostname)818        for name in aliases:819            if '.' in name:820                break821        else:822            name = hostname823    return name824 825 826_GLOBAL_DEFAULT_TIMEOUT = object()827 828def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,829                      source_address=None, *, all_errors=False):830    """Connect to *address* and return the socket object.831 832    Convenience function.  Connect to *address* (a 2-tuple ``(host,833    port)``) and return the socket object.  Passing the optional834    *timeout* parameter will set the timeout on the socket instance835    before attempting to connect.  If no *timeout* is supplied, the836    global default timeout setting returned by :func:`getdefaulttimeout`837    is used.  If *source_address* is set it must be a tuple of (host, port)838    for the socket to bind as a source address before making the connection.839    A host of '' or port 0 tells the OS to use the default. When a connection840    cannot be created, raises the last error if *all_errors* is False,841    and an ExceptionGroup of all errors if *all_errors* is True.842    """843 844    host, port = address845    exceptions = []846    for res in getaddrinfo(host, port, 0, SOCK_STREAM):847        af, socktype, proto, canonname, sa = res848        sock = None849        try:850            sock = socket(af, socktype, proto)851            if timeout is not _GLOBAL_DEFAULT_TIMEOUT:852                sock.settimeout(timeout)853            if source_address:854                sock.bind(source_address)855            sock.connect(sa)856            # Break explicitly a reference cycle857            exceptions.clear()858            return sock859 860        except error as exc:861            if not all_errors:862                exceptions.clear()  # raise only the last error863            exceptions.append(exc)864            if sock is not None:865                sock.close()866 867    if len(exceptions):868        try:869            if not all_errors:870                raise exceptions[0]871            raise ExceptionGroup("create_connection failed", exceptions)872        finally:873            # Break explicitly a reference cycle874            exceptions.clear()875    else:876        raise error("getaddrinfo returns an empty list")877 878 879def has_dualstack_ipv6():880    """Return True if the platform supports creating a SOCK_STREAM socket881    which can handle both AF_INET and AF_INET6 (IPv4 / IPv6) connections.882    """883    if not has_ipv6 \884            or not hasattr(_socket, 'IPPROTO_IPV6') \885            or not hasattr(_socket, 'IPV6_V6ONLY'):886        return False887    try:888        with socket(AF_INET6, SOCK_STREAM) as sock:889            sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)890            return True891    except error:892        return False893 894 895def create_server(address, *, family=AF_INET, backlog=None, reuse_port=False,896                  dualstack_ipv6=False):897    """Convenience function which creates a SOCK_STREAM type socket898    bound to *address* (a 2-tuple (host, port)) and return the socket899    object.900 901    *family* should be either AF_INET or AF_INET6.902    *backlog* is the queue size passed to socket.listen().903    *reuse_port* dictates whether to use the SO_REUSEPORT socket option.904    *dualstack_ipv6*: if true and the platform supports it, it will905    create an AF_INET6 socket able to accept both IPv4 or IPv6906    connections. When false it will explicitly disable this option on907    platforms that enable it by default (e.g. Linux).908 909    >>> with create_server(('', 8000)) as server:910    ...     while True:911    ...         conn, addr = server.accept()912    ...         # handle new connection913    """914    if reuse_port and not hasattr(_socket, "SO_REUSEPORT"):915        raise ValueError("SO_REUSEPORT not supported on this platform")916    if dualstack_ipv6:917        if not has_dualstack_ipv6():918            raise ValueError("dualstack_ipv6 not supported on this platform")919        if family != AF_INET6:920            raise ValueError("dualstack_ipv6 requires AF_INET6 family")921    sock = socket(family, SOCK_STREAM)922    try:923        # Note about Windows. We don't set SO_REUSEADDR because:924        # 1) It's unnecessary: bind() will succeed even in case of a925        # previous closed socket on the same address and still in926        # TIME_WAIT state.927        # 2) If set, another socket is free to bind() on the same928        # address, effectively preventing this one from accepting929        # connections. Also, it may set the process in a state where930        # it'll no longer respond to any signals or graceful kills.931        # See: https://learn.microsoft.com/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse932        if os.name not in ('nt', 'cygwin') and \933                hasattr(_socket, 'SO_REUSEADDR'):934            try:935                sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)936            except error:937                # Fail later on bind(), for platforms which may not938                # support this option.939                pass940        # Since Linux 6.12.9, SO_REUSEPORT is not allowed941        # on other address families than AF_INET/AF_INET6.942        if reuse_port and family in (AF_INET, AF_INET6):943            sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)944        if has_ipv6 and family == AF_INET6:945            if dualstack_ipv6:946                sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)947            elif hasattr(_socket, "IPV6_V6ONLY") and \948                    hasattr(_socket, "IPPROTO_IPV6"):949                sock.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 1)950        try:951            sock.bind(address)952        except error as err:953            msg = '%s (while attempting to bind on address %r)' % \954                (err.strerror, address)955            raise error(err.errno, msg) from None956        if backlog is None:957            sock.listen()958        else:959            sock.listen(backlog)960        return sock961    except error:962        sock.close()963        raise964 965 966def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):967    """Resolve host and port into list of address info entries.968 969    Translate the host/port argument into a sequence of 5-tuples that contain970    all the necessary arguments for creating a socket connected to that service.971    host is a domain name, a string representation of an IPv4/v6 address or972    None. port is a string service name such as 'http', a numeric port number or973    None. By passing None as the value of host and port, you can pass NULL to974    the underlying C API.975 976    The family, type and proto arguments can be optionally specified in order to977    narrow the list of addresses returned. Passing zero as a value for each of978    these arguments selects the full range of results.979    """980    # We override this function since we want to translate the numeric family981    # and socket type values to enum constants.982    addrlist = []983    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):984        af, socktype, proto, canonname, sa = res985        addrlist.append((_intenum_converter(af, AddressFamily),986                         _intenum_converter(socktype, SocketKind),987                         proto, canonname, sa))988    return addrlist989 
codekingpro/portable-devtools · Team Ai