[Spice-devel] [PATCH spice-server v5 06/18] sys-socket: Add socket_newpair utility

Frediano Ziglio fziglio at redhat.com
Fri Mar 29 09:00:02 UTC 2019


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 <fziglio at 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



More information about the Spice-devel mailing list