aboutsummaryrefslogtreecommitdiffstats
path: root/util/network/pair.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/network/pair.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/network/pair.cpp')
-rw-r--r--util/network/pair.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/util/network/pair.cpp b/util/network/pair.cpp
new file mode 100644
index 0000000000..9751ef5c96
--- /dev/null
+++ b/util/network/pair.cpp
@@ -0,0 +1,97 @@
+#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
+}