|
76 | 76 | if name.isupper() and name.startswith('SOCK_')}) |
77 | 77 | globals().update(SocketType.__members__) |
78 | 78 |
|
| 79 | + |
| 80 | +_LOCALHOST = '127.0.0.1' |
| 81 | +_LOCALHOST_V6 = '::1' |
| 82 | + |
| 83 | + |
79 | 84 | def _intenum_converter(value, enum_klass): |
80 | 85 | """Convert a numeric family value to an IntEnum member. |
81 | 86 |
|
@@ -468,6 +473,52 @@ def socketpair(family=None, type=SOCK_STREAM, proto=0): |
468 | 473 | b = socket(family, type, proto, b.detach()) |
469 | 474 | return a, b |
470 | 475 |
|
| 476 | +else: |
| 477 | + |
| 478 | + # Origin: https://gist.github.com/4325783, by Geert Jansen. Public domain. |
| 479 | + def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0): |
| 480 | + if family == AF_INET: |
| 481 | + host = _LOCALHOST |
| 482 | + elif family == AF_INET6: |
| 483 | + host = _LOCALHOST_V6 |
| 484 | + else: |
| 485 | + raise ValueError("Only AF_INET and AF_INET6 socket address families " |
| 486 | + "are supported") |
| 487 | + if type != SOCK_STREAM: |
| 488 | + raise ValueError("Only SOCK_STREAM socket type is supported") |
| 489 | + if proto != 0: |
| 490 | + raise ValueError("Only protocol zero is supported") |
| 491 | + |
| 492 | + # We create a connected TCP socket. Note the trick with |
| 493 | + # setblocking(False) that prevents us from having to create a thread. |
| 494 | + lsock = socket(family, type, proto) |
| 495 | + try: |
| 496 | + lsock.bind((host, 0)) |
| 497 | + lsock.listen() |
| 498 | + # On IPv6, ignore flow_info and scope_id |
| 499 | + addr, port = lsock.getsockname()[:2] |
| 500 | + csock = socket(family, type, proto) |
| 501 | + try: |
| 502 | + csock.setblocking(False) |
| 503 | + try: |
| 504 | + csock.connect((addr, port)) |
| 505 | + except (BlockingIOError, InterruptedError): |
| 506 | + pass |
| 507 | + csock.setblocking(True) |
| 508 | + ssock, _ = lsock.accept() |
| 509 | + except: |
| 510 | + csock.close() |
| 511 | + raise |
| 512 | + finally: |
| 513 | + lsock.close() |
| 514 | + return (ssock, csock) |
| 515 | + |
| 516 | +socketpair.__doc__ = """socketpair([family[, type[, proto]]]) -> (socket object, socket object) |
| 517 | +Create a pair of socket objects from the sockets returned by the platform |
| 518 | +socketpair() function. |
| 519 | +The arguments are the same as for socket() except the default family is AF_UNIX |
| 520 | +if defined on the platform; otherwise, the default is AF_INET. |
| 521 | +""" |
471 | 522 |
|
472 | 523 | _blocking_errnos = { EAGAIN, EWOULDBLOCK } |
473 | 524 |
|
|
0 commit comments