}
}
-int win_socketpair(int socks[2])
+int _win_socketpair(int socks[2])
{
- union {
- struct sockaddr_in inaddr;
- struct sockaddr addr;
- } a;
- int listener;
- int e;
- socklen_t addrlen = sizeof(a.inaddr);
- int reuse = 1;
-
- if (socks == 0) {
- errno = -EINVAL;
- return SOCKET_ERROR;
- }
+ union {
+ struct sockaddr_in inaddr;
+ struct sockaddr addr;
+ } a;
+ SOCKET listener;
+ int e;
+ socklen_t addrlen = sizeof(a.inaddr);
+ int reuse = 1;
+
+ if (socks == 0) {
+ WSASetLastError(WSAEINVAL);
+ return -1;
+ }
+
+ listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (listener == INVALID_SOCKET) {
+ return -1;
+ }
+
+ memset(&a, 0, sizeof(a));
+ a.inaddr.sin_family = AF_INET;
+ a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ a.inaddr.sin_port = 0;
+
+ socks[0] = socks[1] = -1;
+ SOCKET s[2] = { INVALID_SOCKET, INVALID_SOCKET };
+
+ do {
+ if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
+ (char*) &reuse, (socklen_t) sizeof(reuse)) == -1)
+ break;
+ if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
+ break;
+ if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
+ break;
+ if (listen(listener, 1) == SOCKET_ERROR)
+ break;
+ s[0] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (s[0] == INVALID_SOCKET)
+ break;
+ if (connect(s[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
+ break;
+ s[1] = accept(listener, NULL, NULL);
+ if (s[1] == INVALID_SOCKET)
+ break;
- listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (listener == INVALID_SOCKET)
- return SOCKET_ERROR;
-
- memset(&a, 0, sizeof(a));
- a.inaddr.sin_family = AF_INET;
- a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- a.inaddr.sin_port = 0;
-
- socks[0] = socks[1] = INVALID_SOCKET;
- do {
- if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
- (char*) &reuse, (socklen_t) sizeof(reuse)) == -1)
- break;
- if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
- break;
- if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
- break;
- if (listen(listener, 1) == SOCKET_ERROR)
- break;
- socks[0] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (socks[0] == INVALID_SOCKET)
- break;
- if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
- break;
- socks[1] = accept(listener, NULL, NULL);
- if (socks[1] == INVALID_SOCKET)
- break;
-
- closesocket(listener);
-
- return 0;
-
- } while (0);
-
- e = errno;
closesocket(listener);
- closesocket(socks[0]);
- closesocket(socks[1]);
- errno = e;
- return SOCKET_ERROR;
+
+ // The Windows socket API is mostly compatible with the Berkeley
+ // API, with a few exceptions. The Windows socket functions use
+ // SOCKET instead of int. The issue is that on x64 systems,
+ // SOCKET uses 64b while int uses 32b. There's been much debate
+ // whether casting a Windows socket to an int is safe or not.
+ // Worth noting that Windows kernel objects use 32b. For now,
+ // we're just adding a check.
+ //
+ // Ideally, we should update ceph to use the right type but this
+ // can be quite difficult, especially considering that there are
+ // a significant number of functions that accept both sockets and
+ // file descriptors.
+ if (s[0] >> 32 || s[1] >> 32) {
+ WSASetLastError(WSAENAMETOOLONG);
+ break;
+ }
+
+ socks[0] = s[0];
+ socks[1] = s[1];
+
+ return 0;
+
+ } while (0);
+
+ e = WSAGetLastError();
+ closesocket(listener);
+ closesocket(s[0]);
+ closesocket(s[1]);
+ WSASetLastError(e);
+ return -1;
+}
+
+int win_socketpair(int socks[2]) {
+ int r = 0;
+ for (int i = 0; i < 15; i++) {
+ r = _win_socketpair(socks);
+ if (r && WSAGetLastError() == WSAEADDRINUSE) {
+ sleep(2);
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ return r;
}
unsigned get_page_size() {