Allows to easier port socketpair. Windows does not have this function, we need to create a pair using 2 internet sockets and connecting one to the other. The SPICE core interface implementation provided by Qemu under Windows requires, under Windows, to provide SOCKET handles so pipes or other Windows handles won't work. Windows does not provide a socketpair function so use this replacement.
Signed-off-by: Frediano Ziglio <fzig...@redhat.com> --- server/sys-socket.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ server/sys-socket.h | 3 ++ 2 files changed, 78 insertions(+) diff --git a/server/sys-socket.c b/server/sys-socket.c index 7ce5dab1a..837da18e3 100644 --- a/server/sys-socket.c +++ b/server/sys-socket.c @@ -209,4 +209,79 @@ SPICE_CONSTRUCTOR_FUNC(socket_win32_init) WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); } + +int socket_newpair(int type, int protocol, int sv[2]) +{ + struct sockaddr_in sa, sa2; + socklen_t addrlen; + SOCKET s, pairs[2]; + + if (!sv) { + return -1; + } + + /* create a listener */ + s = socket(AF_INET, type, 0); + if (s == INVALID_SOCKET) { + return -1; + } + + pairs[1] = INVALID_SOCKET; + + pairs[0] = socket(AF_INET, type, 0); + if (pairs[0] == INVALID_SOCKET) { + goto cleanup; + } + + /* bind to a random port */ + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sa.sin_port = 0; + if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0) { + goto cleanup; + } + if (listen(s, 1) < 0) { + goto cleanup; + } + + /* connect to kernel choosen port */ + addrlen = sizeof(sa); + if (getsockname(s, (struct sockaddr*) &sa, &addrlen) < 0) { + goto cleanup; + } + if (connect(pairs[0], (struct sockaddr*) &sa, sizeof(sa)) < 0) { + goto cleanup; + } + addrlen = sizeof(sa2); + pairs[1] = accept(s, (struct sockaddr*) &sa2, &addrlen); + if (pairs[1] == INVALID_SOCKET) { + goto cleanup; + } + + /* check proper connection */ + addrlen = sizeof(sa); + if (getsockname(pairs[0], (struct sockaddr*) &sa, &addrlen) < 0) { + goto cleanup; + } + addrlen = sizeof(sa2); + if (getpeername(pairs[1], (struct sockaddr*) &sa2, &addrlen) < 0) { + goto cleanup; + } + if (sa.sin_family != sa2.sin_family || sa.sin_port != sa2.sin_port + || sa.sin_addr.s_addr != sa2.sin_addr.s_addr) { + goto cleanup; + } + + closesocket(s); + sv[0] = pairs[0]; + sv[1] = pairs[1]; + return 0; + +cleanup: + socket_win32_set_errno(); + closesocket(s); + closesocket(pairs[0]); + closesocket(pairs[1]); + return -1; +} #endif diff --git a/server/sys-socket.h b/server/sys-socket.h index 650625711..3a3b78789 100644 --- a/server/sys-socket.h +++ b/server/sys-socket.h @@ -134,6 +134,9 @@ socket_accept(int sock, struct sockaddr *addr, int *addrlen) } #undef accept #define accept socket_accept + +int socket_newpair(int type, int protocol, int sv[2]); +#define socketpair(family, type, protocol, sv) socket_newpair(type, protocol, sv) #endif #endif // RED_SYS_SOCKET_H_ -- 2.20.1 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel