#include "pair.h" int SocketPair(SOCKET socks[2], bool overlapped, bool cloexec) { #if defined(_win_) struct sockaddr_in addr; SOCKET listener; int e; int addrlen = sizeof(addr); DWORD flags = (overlapped ? WSA_FLAG_OVERLAPPED : 0) | (cloexec ? WSA_FLAG_NO_HANDLE_INHERIT : 0); if (socks == 0) { WSASetLastError(WSAEINVAL); return SOCKET_ERROR; } socks[0] = INVALID_SOCKET; socks[1] = INVALID_SOCKET; if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { return SOCKET_ERROR; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(0x7f000001); addr.sin_port = 0; e = bind(listener, (const struct sockaddr*)&addr, sizeof(addr)); if (e == SOCKET_ERROR) { e = WSAGetLastError(); closesocket(listener); WSASetLastError(e); return SOCKET_ERROR; } e = getsockname(listener, (struct sockaddr*)&addr, &addrlen); if (e == SOCKET_ERROR) { e = WSAGetLastError(); closesocket(listener); WSASetLastError(e); return SOCKET_ERROR; } do { if (listen(listener, 1) == SOCKET_ERROR) break; if ((socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, nullptr, 0, flags)) == INVALID_SOCKET) break; if (connect(socks[0], (const struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) break; if ((socks[1] = accept(listener, nullptr, nullptr)) == INVALID_SOCKET) break; closesocket(listener); return 0; } while (0); e = WSAGetLastError(); closesocket(listener); closesocket(socks[0]); closesocket(socks[1]); WSASetLastError(e); return SOCKET_ERROR; #else (void)overlapped; #if defined(_linux_) return socketpair(AF_LOCAL, SOCK_STREAM | (cloexec ? SOCK_CLOEXEC : 0), 0, socks); #else int r = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks); // Non-atomic wrt exec if (r == 0 && cloexec) { for (int i = 0; i < 2; ++i) { int flags = fcntl(socks[i], F_GETFD, 0); if (flags < 0) { return flags; } r = fcntl(socks[i], F_SETFD, flags | FD_CLOEXEC); if (r < 0) { return r; } } } return r; #endif #endif }