Skip to content

Commit ea7b9bf

Browse files
committed
Upgraee socket from 3.13.11
1 parent 21d7bc2 commit ea7b9bf

File tree

2 files changed

+528
-160
lines changed

2 files changed

+528
-160
lines changed

Lib/socket.py

Lines changed: 72 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,8 @@ def makefile(self, mode="r", buffering=None, *,
306306
"""makefile(...) -> an I/O stream connected to the socket
307307
308308
The arguments are as for io.open() after the filename, except the only
309-
supported mode values are 'r' (default), 'w' and 'b'.
309+
supported mode values are 'r' (default), 'w', 'b', or a combination of
310+
those.
310311
"""
311312
# XXX refactor to share code?
312313
if not set(mode) <= {"r", "w", "b"}:
@@ -591,16 +592,65 @@ def fromshare(info):
591592
return socket(0, 0, 0, info)
592593
__all__.append("fromshare")
593594

594-
if hasattr(_socket, "socketpair"):
595+
# Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
596+
# This is used if _socket doesn't natively provide socketpair. It's
597+
# always defined so that it can be patched in for testing purposes.
598+
def _fallback_socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
599+
if family == AF_INET:
600+
host = _LOCALHOST
601+
elif family == AF_INET6:
602+
host = _LOCALHOST_V6
603+
else:
604+
raise ValueError("Only AF_INET and AF_INET6 socket address families "
605+
"are supported")
606+
if type != SOCK_STREAM:
607+
raise ValueError("Only SOCK_STREAM socket type is supported")
608+
if proto != 0:
609+
raise ValueError("Only protocol zero is supported")
610+
611+
# We create a connected TCP socket. Note the trick with
612+
# setblocking(False) that prevents us from having to create a thread.
613+
lsock = socket(family, type, proto)
614+
try:
615+
lsock.bind((host, 0))
616+
lsock.listen()
617+
# On IPv6, ignore flow_info and scope_id
618+
addr, port = lsock.getsockname()[:2]
619+
csock = socket(family, type, proto)
620+
try:
621+
csock.setblocking(False)
622+
try:
623+
csock.connect((addr, port))
624+
except (BlockingIOError, InterruptedError):
625+
pass
626+
csock.setblocking(True)
627+
ssock, _ = lsock.accept()
628+
except:
629+
csock.close()
630+
raise
631+
finally:
632+
lsock.close()
595633

596-
def socketpair(family=None, type=SOCK_STREAM, proto=0):
597-
"""socketpair([family[, type[, proto]]]) -> (socket object, socket object)
634+
# Authenticating avoids using a connection from something else
635+
# able to connect to {host}:{port} instead of us.
636+
# We expect only AF_INET and AF_INET6 families.
637+
try:
638+
if (
639+
ssock.getsockname() != csock.getpeername()
640+
or csock.getsockname() != ssock.getpeername()
641+
):
642+
raise ConnectionError("Unexpected peer connection")
643+
except:
644+
# getsockname() and getpeername() can fail
645+
# if either socket isn't connected.
646+
ssock.close()
647+
csock.close()
648+
raise
598649

599-
Create a pair of socket objects from the sockets returned by the platform
600-
socketpair() function.
601-
The arguments are the same as for socket() except the default family is
602-
AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
603-
"""
650+
return (ssock, csock)
651+
652+
if hasattr(_socket, "socketpair"):
653+
def socketpair(family=None, type=SOCK_STREAM, proto=0):
604654
if family is None:
605655
try:
606656
family = AF_UNIX
@@ -612,44 +662,7 @@ def socketpair(family=None, type=SOCK_STREAM, proto=0):
612662
return a, b
613663

614664
else:
615-
616-
# Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
617-
def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
618-
if family == AF_INET:
619-
host = _LOCALHOST
620-
elif family == AF_INET6:
621-
host = _LOCALHOST_V6
622-
else:
623-
raise ValueError("Only AF_INET and AF_INET6 socket address families "
624-
"are supported")
625-
if type != SOCK_STREAM:
626-
raise ValueError("Only SOCK_STREAM socket type is supported")
627-
if proto != 0:
628-
raise ValueError("Only protocol zero is supported")
629-
630-
# We create a connected TCP socket. Note the trick with
631-
# setblocking(False) that prevents us from having to create a thread.
632-
lsock = socket(family, type, proto)
633-
try:
634-
lsock.bind((host, 0))
635-
lsock.listen()
636-
# On IPv6, ignore flow_info and scope_id
637-
addr, port = lsock.getsockname()[:2]
638-
csock = socket(family, type, proto)
639-
try:
640-
csock.setblocking(False)
641-
try:
642-
csock.connect((addr, port))
643-
except (BlockingIOError, InterruptedError):
644-
pass
645-
csock.setblocking(True)
646-
ssock, _ = lsock.accept()
647-
except:
648-
csock.close()
649-
raise
650-
finally:
651-
lsock.close()
652-
return (ssock, csock)
665+
socketpair = _fallback_socketpair
653666
__all__.append("socketpair")
654667

655668
socketpair.__doc__ = """socketpair([family[, type[, proto]]]) -> (socket object, socket object)
@@ -702,16 +715,15 @@ def readinto(self, b):
702715
self._checkReadable()
703716
if self._timeout_occurred:
704717
raise OSError("cannot read from timed out object")
705-
while True:
706-
try:
707-
return self._sock.recv_into(b)
708-
except timeout:
709-
self._timeout_occurred = True
710-
raise
711-
except error as e:
712-
if e.errno in _blocking_errnos:
713-
return None
714-
raise
718+
try:
719+
return self._sock.recv_into(b)
720+
except timeout:
721+
self._timeout_occurred = True
722+
raise
723+
except error as e:
724+
if e.errno in _blocking_errnos:
725+
return None
726+
raise
715727

716728
def write(self, b):
717729
"""Write the given bytes or bytearray object *b* to the socket
@@ -919,7 +931,9 @@ def create_server(address, *, family=AF_INET, backlog=None, reuse_port=False,
919931
# Fail later on bind(), for platforms which may not
920932
# support this option.
921933
pass
922-
if reuse_port:
934+
# Since Linux 6.12.9, SO_REUSEPORT is not allowed
935+
# on other address families than AF_INET/AF_INET6.
936+
if reuse_port and family in (AF_INET, AF_INET6):
923937
sock.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
924938
if has_ipv6 and family == AF_INET6:
925939
if dualstack_ipv6:

0 commit comments

Comments
 (0)