Hi On Wed, Feb 6, 2019 at 2:59 PM Frediano Ziglio <fziglio@xxxxxxxxxx> wrote: > > Between Unix and Windows socket are quite different: > - on Windows sockets have a different namespace from C file > descriptors so you can't use read/write/close or similar functions; > - errors are not stored in errno but you must be read/write the > errors with specific function; > - sometimes sockets are put in non-blocking mode automatically > calling some functions; > - SOCKET type is 64 bit on Windows 64 which does not fit technically > in an int. Is however safe to assume them to fit in an int. > > So encapsulate the socket APIs in some definition to make easier > and more safe to deal with them. > Where the portability to Windows would make to code more offuscated a Unix > style was preferred. For instance if errors are detected errno is set from > Windows socket error instead of changing all code handling. > Fortunately on Windows Qemu core interface accepts socket (but not > other types like C file descriptors!). > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> Reviewed-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> > --- > server/Makefile.am | 2 + > server/sys-socket.c | 212 ++++++++++++++++++++++++++++++++++++++++++++ > server/sys-socket.h | 139 +++++++++++++++++++++++++++++ > 3 files changed, 353 insertions(+) > create mode 100644 server/sys-socket.c > create mode 100644 server/sys-socket.h > > 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/sys-socket.c b/server/sys-socket.c > new file mode 100644 > index 00000000..7ce5dab1 > --- /dev/null > +++ b/server/sys-socket.c > @@ -0,0 +1,212 @@ > +/* -*- 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 <http://www.gnu.org/licenses/>. > +*/ > +#ifdef HAVE_CONFIG_H > +#include <config.h> > +#endif > + > +#include <errno.h> > +#include <fcntl.h> > +#include <stdbool.h> > +#include <string.h> > +#include <sys/types.h> > +#ifndef _WIN32 > +#include <arpa/inet.h> > +#include <netinet/in.h> > +#include <netinet/ip.h> > +#include <netinet/tcp.h> > +#include <sys/socket.h> > +#endif > + > +#include <common/log.h> > + > +#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 <http://www.gnu.org/licenses/>. > +*/ > + > +/* 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 <sys/socket.h> > + > +#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) > + That's weird indentation, why not be consistent? > +#else > +# include <winsock2.h> > +# include <windows.h> > +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_ > -- > 2.20.1 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/spice-devel -- Marc-André Lureau _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel