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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 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@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux Virtualization]     [Linux Virtualization]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]