mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 14:41:25 +00:00
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@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
140 lines
3.4 KiB
C
140 lines
3.4 KiB
C
/*
|
|
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)
|
|
|
|
#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_
|