@@ -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
614664else :
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
655668socketpair .__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