codekingpro/portable-devtools
114k
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 