[Spice-devel] [PATCH spice-server v3 07/32] sys-socket: Add socket_newpair utility

Frediano Ziglio fziglio at redhat.com
Mon Jan 7 18:01:50 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.

Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 server/sys-socket.c | 75 +++++++++++++++++++++++++++++++++++++++++++++
 server/sys-socket.h |  7 +++++
 2 files changed, 82 insertions(+)

diff --git a/server/sys-socket.c b/server/sys-socket.c
index 7ce5dab1..af2f0b83 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, socket_t 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] = SOCKET_FROM_INT(pairs[0]);
+    sv[1] = SOCKET_FROM_INT(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 c4487b79..eea0b443 100644
--- a/server/sys-socket.h
+++ b/server/sys-socket.h
@@ -56,6 +56,11 @@ static inline void socket_win32_set_errno(void)
 {
 }
 
+static inline int socket_newpair(int type, int protocol, socket_t sv[2])
+{
+    return socketpair(AF_LOCAL, type, protocol, (int*) sv);
+}
+
 #define socket_read(sock, buf, len) read(socket_get_raw(sock), buf, len)
 #define socket_write(sock, buf, len) write(socket_get_raw(sock), buf, len)
 #define socket_writev(sock, iov, n) writev(socket_get_raw(sock), iov, n)
@@ -147,6 +152,8 @@ socket_listen(socket_t sock, int backlog)
     }
     return res;
 }
+
+int socket_newpair(int type, int protocol, socket_t sv[2]);
 #endif
 
 // common part
-- 
2.20.1



More information about the Spice-devel mailing list