| 73 | */ |
| 74 | |
| 75 | int dumb_socketpair(SOCKET socks[2], int make_overlapped) |
| 76 | { |
| 77 | union { |
| 78 | struct sockaddr_in inaddr; |
| 79 | struct sockaddr addr; |
| 80 | } a; |
| 81 | SOCKET listener; |
| 82 | int e; |
| 83 | socklen_t addrlen = sizeof(a.inaddr); |
| 84 | DWORD flags = (make_overlapped ? WSA_FLAG_OVERLAPPED : 0); |
| 85 | int reuse = 1; |
| 86 | |
| 87 | if (socks == 0) { |
| 88 | WSASetLastError(WSAEINVAL); |
| 89 | return SOCKET_ERROR; |
| 90 | } |
| 91 | socks[0] = socks[1] = -1; |
| 92 | |
| 93 | listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 94 | if (listener == -1) |
| 95 | return SOCKET_ERROR; |
| 96 | |
| 97 | memset(&a, 0, sizeof(a)); |
| 98 | a.inaddr.sin_family = AF_INET; |
| 99 | a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 100 | a.inaddr.sin_port = 0; |
| 101 | |
| 102 | for (;;) { |
| 103 | if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, |
| 104 | (char*) &reuse, (socklen_t) sizeof(reuse)) == -1) |
| 105 | break; |
| 106 | if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) |
| 107 | break; |
| 108 | |
| 109 | memset(&a, 0, sizeof(a)); |
| 110 | if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) |
| 111 | break; |
| 112 | // win32 getsockname may only set the port number, p=0.0005. |
| 113 | // ( http://msdn.microsoft.com/library/ms738543.aspx ): |
| 114 | a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 115 | a.inaddr.sin_family = AF_INET; |
| 116 | |
| 117 | if (listen(listener, 1) == SOCKET_ERROR) |
| 118 | break; |
| 119 | |
| 120 | socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags); |
| 121 | if (socks[0] == -1) |
| 122 | break; |
| 123 | if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) |
| 124 | break; |
| 125 | |
| 126 | socks[1] = accept(listener, NULL, NULL); |
| 127 | if (socks[1] == -1) |
| 128 | break; |
| 129 | |
| 130 | closesocket(listener); |
| 131 | return 0; |
| 132 | } |