@@ -590,16 +590,65 @@ def fromshare(info):
590590return socket (0 ,0 ,0 ,info )
591591__all__ .append ("fromshare" )
592592
593- if hasattr (_socket ,"socketpair" ):
593+ # Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
594+ # This is used if _socket doesn't natively provide socketpair. It's
595+ # always defined so that it can be patched in for testing purposes.
596+ def _fallback_socketpair (family = AF_INET ,type = SOCK_STREAM ,proto = 0 ):
597+ if family == AF_INET :
598+ host = _LOCALHOST
599+ elif family == AF_INET6 :
600+ host = _LOCALHOST_V6
601+ else :
602+ raise ValueError ("Only AF_INET and AF_INET6 socket address families "
603+ "are supported" )
604+ if type != SOCK_STREAM :
605+ raise ValueError ("Only SOCK_STREAM socket type is supported" )
606+ if proto != 0 :
607+ raise ValueError ("Only protocol zero is supported" )
608+
609+ # We create a connected TCP socket. Note the trick with
610+ # setblocking(False) that prevents us from having to create a thread.
611+ lsock = socket (family ,type ,proto )
612+ try :
613+ lsock .bind ((host ,0 ))
614+ lsock .listen ()
615+ # On IPv6, ignore flow_info and scope_id
616+ addr ,port = lsock .getsockname ()[:2 ]
617+ csock = socket (family ,type ,proto )
618+ try :
619+ csock .setblocking (False )
620+ try :
621+ csock .connect ((addr ,port ))
622+ except (BlockingIOError ,InterruptedError ):
623+ pass
624+ csock .setblocking (True )
625+ ssock ,_ = lsock .accept ()
626+ except :
627+ csock .close ()
628+ raise
629+ finally :
630+ lsock .close ()
594631
595- def socketpair (family = None ,type = SOCK_STREAM ,proto = 0 ):
596- """socketpair([family[, type[, proto]]]) -> (socket object, socket object)
632+ # Authenticating avoids using a connection from something else
633+ # able to connect to {host}:{port} instead of us.
634+ # We expect only AF_INET and AF_INET6 families.
635+ try :
636+ if (
637+ ssock .getsockname ()!= csock .getpeername ()
638+ or csock .getsockname ()!= ssock .getpeername ()
639+ ):
640+ raise ConnectionError ("Unexpected peer connection" )
641+ except :
642+ # getsockname() and getpeername() can fail
643+ # if either socket isn't connected.
644+ ssock .close ()
645+ csock .close ()
646+ raise
597647
598- Create a pair of socket objects from the sockets returned by the platform
599- socketpair() function.
600- The arguments are the same as for socket() except the default family is
601- AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
602- """
648+ return (ssock ,csock )
649+
650+ if hasattr (_socket ,"socketpair" ):
651+ def socketpair (family = None ,type = SOCK_STREAM ,proto = 0 ):
603652if family is None :
604653try :
605654family = AF_UNIX
@@ -611,61 +660,7 @@ def socketpair(family=None, type=SOCK_STREAM, proto=0):
611660return a ,b
612661
613662else :
614-
615- # Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain.
616- def socketpair (family = AF_INET ,type = SOCK_STREAM ,proto = 0 ):
617- if family == AF_INET :
618- host = _LOCALHOST
619- elif family == AF_INET6 :
620- host = _LOCALHOST_V6
621- else :
622- raise ValueError ("Only AF_INET and AF_INET6 socket address families "
623- "are supported" )
624- if type != SOCK_STREAM :
625- raise ValueError ("Only SOCK_STREAM socket type is supported" )
626- if proto != 0 :
627- raise ValueError ("Only protocol zero is supported" )
628-
629- # We create a connected TCP socket. Note the trick with
630- # setblocking(False) that prevents us from having to create a thread.
631- lsock = socket (family ,type ,proto )
632- try :
633- lsock .bind ((host ,0 ))
634- lsock .listen ()
635- # On IPv6, ignore flow_info and scope_id
636- addr ,port = lsock .getsockname ()[:2 ]
637- csock = socket (family ,type ,proto )
638- try :
639- csock .setblocking (False )
640- try :
641- csock .connect ((addr ,port ))
642- except (BlockingIOError ,InterruptedError ):
643- pass
644- csock .setblocking (True )
645- ssock ,_ = lsock .accept ()
646- except :
647- csock .close ()
648- raise
649- finally :
650- lsock .close ()
651-
652- # Authenticating avoids using a connection from something else
653- # able to connect to {host}:{port} instead of us.
654- # We expect only AF_INET and AF_INET6 families.
655- try :
656- if (
657- ssock .getsockname ()!= csock .getpeername ()
658- or csock .getsockname ()!= ssock .getpeername ()
659- ):
660- raise ConnectionError ("Unexpected peer connection" )
661- except :
662- # getsockname() and getpeername() can fail
663- # if either socket isn't connected.
664- ssock .close ()
665- csock .close ()
666- raise
667-
668- return (ssock ,csock )
663+ socketpair = _fallback_socketpair
669664__all__ .append ("socketpair" )
670665
671666socketpair .__doc__ = """socketpair([family[, type[, proto]]]) -> (socket object, socket object)