12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- #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
- }
|