diff --git a/server/Makefile.am b/server/Makefile.am
index 34ec22ad..7f260612 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -166,6 +166,8 @@ libserver_la_SOURCES = \
stat.h \
stream-channel.c \
stream-channel.h \
+ sys-socket.h \
+ sys-socket.c \
red-stream-device.c \
red-stream-device.h \
sw-canvas.c \
diff --git a/server/meson.build b/server/meson.build
index 63191d79..34d8eef1 100644
--- a/server/meson.build
+++ b/server/meson.build
@@ -133,6 +133,8 @@ spice_server_sources = [
'stat.h',
'stream-channel.c',
'stream-channel.h',
+ 'sys-socket.c',
+ 'sys-socket.h',
'red-stream-device.c',
'red-stream-device.h',
'sw-canvas.c',
diff --git a/server/sys-socket.c b/server/sys-socket.c
new file mode 100644
index 00000000..5ac627b4
--- /dev/null
+++ b/server/sys-socket.c
@@ -0,0 +1,210 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2018 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see .
+*/
+#include
+
+#include
+#include
+#include
+#include
+#include
+#ifndef _WIN32
+#include
+#include
+#include
+#include
+#include
+#endif
+
+#include
+
+#include "sys-socket.h"
+
+#ifdef _WIN32
+// Map Windows socket errors to standard C ones
+// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
+void socket_win32_set_errno(void)
+{
+ int err = EPIPE; // default
+ switch (WSAGetLastError()) {
+ case WSAEWOULDBLOCK:
+ case WSAEINPROGRESS:
+ err = EAGAIN;
+ break;
+ case WSAEINTR:
+ err = EINTR;
+ break;
+ case WSAEBADF:
+ err = EBADF;
+ break;
+ case WSA_INVALID_HANDLE:
+ case WSA_INVALID_PARAMETER:
+ case WSAEINVAL:
+ err = EINVAL;
+ break;
+ case WSAENOTSOCK:
+ err = ENOTSOCK;
+ break;
+ case WSA_NOT_ENOUGH_MEMORY:
+ err = ENOMEM;
+ break;
+ case WSAEPROTONOSUPPORT:
+ case WSAESOCKTNOSUPPORT:
+ case WSAEOPNOTSUPP:
+ case WSAEPFNOSUPPORT:
+ case WSAEAFNOSUPPORT:
+ case WSAVERNOTSUPPORTED:
+ err = ENOTSUP;
+ break;
+ case WSAEFAULT:
+ err = EFAULT;
+ break;
+ case WSAEACCES:
+ err = EACCES;
+ break;
+ case WSAEMFILE:
+ err = EMFILE;
+ break;
+ case WSAENAMETOOLONG:
+ err = ENAMETOOLONG;
+ break;
+ case WSAENOTEMPTY:
+ err = ENOTEMPTY;
+ break;
+ case WSA_OPERATION_ABORTED:
+ case WSAECANCELLED:
+ case WSA_E_CANCELLED:
+ err = ECANCELED;
+ break;
+ case WSAEADDRINUSE:
+ err = EADDRINUSE;
+ break;
+ case WSAENETDOWN:
+ err = ENETDOWN;
+ break;
+ case WSAENETUNREACH:
+ err = ENETUNREACH;
+ break;
+ case WSAENETRESET:
+ err = ENETRESET;
+ break;
+ case WSAECONNABORTED:
+ err = ECONNABORTED;
+ break;
+ case WSAECONNRESET:
+ err = ECONNRESET;
+ break;
+ case WSAEISCONN:
+ err = EISCONN;
+ break;
+ case WSAENOTCONN:
+ err = ENOTCONN;
+ break;
+ case WSAETIMEDOUT:
+ err = ETIMEDOUT;
+ break;
+ case WSAECONNREFUSED:
+ err = ECONNREFUSED;
+ break;
+ case WSAEHOSTUNREACH:
+ err = EHOSTUNREACH;
+ break;
+ case WSAEDESTADDRREQ:
+ err = EDESTADDRREQ;
+ break;
+ case WSAEMSGSIZE:
+ err = EMSGSIZE;
+ break;
+ case WSAEPROTOTYPE:
+ err = EPROTOTYPE;
+ break;
+ case WSAENOPROTOOPT:
+ err = ENOPROTOOPT;
+ break;
+ case WSAEADDRNOTAVAIL:
+ err = EADDRNOTAVAIL;
+ break;
+ case WSAENOBUFS:
+ err = ENOBUFS;
+ break;
+ // TODO
+ case WSAESTALE:
+ case WSAEDISCON:
+ case WSA_IO_INCOMPLETE:
+ case WSA_IO_PENDING:
+ case WSAEALREADY:
+ case WSAESHUTDOWN:
+ case WSAETOOMANYREFS:
+ case WSAELOOP:
+ case WSAEHOSTDOWN:
+ case WSAEPROCLIM:
+ case WSAEUSERS:
+ case WSAEDQUOT:
+ case WSAEREMOTE:
+ case WSASYSNOTREADY:
+ case WSANOTINITIALISED:
+ case WSAENOMORE:
+ case WSAEINVALIDPROCTABLE:
+ case WSAEINVALIDPROVIDER:
+ case WSAEPROVIDERFAILEDINIT:
+ case WSASYSCALLFAILURE:
+ case WSASERVICE_NOT_FOUND:
+ case WSATYPE_NOT_FOUND:
+ case WSA_E_NO_MORE:
+ case WSAEREFUSED:
+ case WSAHOST_NOT_FOUND:
+ case WSATRY_AGAIN:
+ case WSANO_RECOVERY:
+ case WSANO_DATA:
+ case WSA_QOS_RECEIVERS:
+ case WSA_QOS_SENDERS:
+ case WSA_QOS_NO_SENDERS:
+ case WSA_QOS_NO_RECEIVERS:
+ case WSA_QOS_REQUEST_CONFIRMED:
+ case WSA_QOS_ADMISSION_FAILURE:
+ case WSA_QOS_POLICY_FAILURE:
+ case WSA_QOS_BAD_STYLE:
+ case WSA_QOS_BAD_OBJECT:
+ case WSA_QOS_TRAFFIC_CTRL_ERROR:
+ case WSA_QOS_GENERIC_ERROR:
+ case WSA_QOS_ESERVICETYPE:
+ case WSA_QOS_EFLOWSPEC:
+ case WSA_QOS_EPROVSPECBUF:
+ case WSA_QOS_EFILTERSTYLE:
+ case WSA_QOS_EFILTERTYPE:
+ case WSA_QOS_EFILTERCOUNT:
+ case WSA_QOS_EOBJLENGTH:
+ case WSA_QOS_EFLOWCOUNT:
+ case WSA_QOS_EUNKOWNPSOBJ:
+ case WSA_QOS_EPOLICYOBJ:
+ case WSA_QOS_EFLOWDESC:
+ case WSA_QOS_EPSFLOWSPEC:
+ case WSA_QOS_EPSFILTERSPEC:
+ case WSA_QOS_ESDMODEOBJ:
+ case WSA_QOS_ESHAPERATEOBJ:
+ case WSA_QOS_RESERVED_PETYPE:
+ break;
+ }
+ errno = err;
+}
+
+SPICE_CONSTRUCTOR_FUNC(socket_win32_init)
+{
+ WSADATA wsaData;
+ WSAStartup(MAKEWORD(2, 2), &wsaData);
+}
+#endif
diff --git a/server/sys-socket.h b/server/sys-socket.h
new file mode 100644
index 00000000..65062571
--- /dev/null
+++ b/server/sys-socket.h
@@ -0,0 +1,139 @@
+/*
+ Copyright (C) 2018 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see .
+*/
+
+/* Small compatibility layer for sockets, mostly to make easier portability
+ * for Windows but without loosing performances under Unix, the most supported
+ * system */
+#ifndef RED_SYS_SOCKET_H_
+#define RED_SYS_SOCKET_H_
+
+#ifndef _WIN32
+# include
+
+#define socket_read(sock, buf, len) read(sock, buf, len)
+#define socket_write(sock, buf, len) write(sock, buf, len)
+#define socket_writev(sock, iov, n) writev(sock, iov, n)
+#define socket_close(sock) close(sock)
+
+#else
+# include
+# include
+typedef int socklen_t;
+
+// this definition is ABI compatible with WSABUF
+struct iovec {
+ u_long iov_len;
+ void FAR *iov_base;
+};
+
+void socket_win32_set_errno(void);
+
+static inline ssize_t socket_read(int sock, void *buf, size_t count)
+{
+ ssize_t res = recv(sock, buf, count, 0);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+
+static inline ssize_t socket_write(int sock, const void *buf, size_t count)
+{
+ ssize_t res = send(sock, buf, count, 0);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+
+static inline ssize_t socket_writev(int sock, const struct iovec *iov, int n_iov)
+{
+ DWORD sent;
+ int res = WSASend(sock, (LPWSABUF) iov, n_iov, &sent, 0, NULL, NULL);
+ if (res) {
+ socket_win32_set_errno();
+ return -1;
+ }
+ return sent;
+}
+
+#define socket_close(sock) closesocket(sock)
+
+#define SHUT_RDWR SD_BOTH
+
+static inline int
+socket_getsockopt(int sock, int lvl, int type, void *value, socklen_t *len)
+{
+ int res = getsockopt(sock, lvl, type, value, len);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+#undef getsockopt
+#define getsockopt socket_getsockopt
+
+static inline int
+socket_setsockopt(int sock, int lvl, int type, const void *value, socklen_t len)
+{
+ int res = setsockopt(sock, lvl, type, value, len);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+#undef setsockopt
+#define setsockopt socket_setsockopt
+
+static inline int
+socket_listen(int sock, int backlog)
+{
+ int res = listen(sock, backlog);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+#undef listen
+#define listen socket_listen
+
+static inline int
+socket_bind(int sock, const struct sockaddr *addr, int addrlen)
+{
+ int res = bind(sock, addr, addrlen);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+#undef bind
+#define bind socket_bind
+
+static inline int
+socket_accept(int sock, struct sockaddr *addr, int *addrlen)
+{
+ int res = accept(sock, addr, addrlen);
+ if (res < 0) {
+ socket_win32_set_errno();
+ }
+ return res;
+}
+#undef accept
+#define accept socket_accept
+#endif
+
+#endif // RED_SYS_SOCKET_H_