Merge remote-tracking branch 'remotes/berrange/tags/pull-io-win32-2016-03-11-1' into staging

Merge I/O fixes for win32

# gpg: Signature made Fri 11 Mar 2016 10:03:20 GMT using RSA key ID 15104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"

* remotes/berrange/tags/pull-io-win32-2016-03-11-1:
  osdep: remove use of socket_error() from all code
  osdep: add wrappers for socket functions
  char: remove qemu_chr_open_socket_fd method
  char: remove socket_try_connect method
  char: remove qemu_chr_finish_socket_connection method
  io: implement socket watch for win32 using WSAEventSelect+select
  io: remove checking of EWOULDBLOCK
  io: use qemu_accept to ensure SOCK_CLOEXEC is set
  io: introduce qio_channel_create_socket_watch
  io: pass HANDLE to g_source_add_poll on Win32
  io: fix copy+paste mistake in socket error message
  io: assert errors before asserting content in I/O test
  io: set correct error object in background reader test thread
  io: wait for incoming client in socket test
  io: bind to socket before creating QIOChannelSocket
  io: initialize sockets in test program
  io: use bind() to check for IPv4/6 availability
  osdep: fix socket_error() to work with Mingw64

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2016-03-14 11:49:33 +00:00
24 changed files with 717 additions and 242 deletions
+2 -2
View File
@@ -238,7 +238,7 @@ qemu-img$(EXESUF): qemu-img.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-o
qemu-nbd$(EXESUF): qemu-nbd.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
qemu-io$(EXESUF): qemu-io.o $(block-obj-y) $(crypto-obj-y) $(io-obj-y) $(qom-obj-y) libqemuutil.a libqemustub.a
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o libqemuutil.a libqemustub.a
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o libqemuutil.a libqemustub.a
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
@@ -329,7 +329,7 @@ ifneq ($(EXESUF),)
qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
endif
ivshmem-client$(EXESUF): $(ivshmem-client-obj-y)
ivshmem-client$(EXESUF): $(ivshmem-client-obj-y) libqemuutil.a libqemustub.a
$(call LINK, $^)
ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a
$(call LINK, $^)
+2 -3
View File
@@ -615,14 +615,13 @@ static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
ret = qemu_co_send(sockfd, hdr, sizeof(*hdr));
if (ret != sizeof(*hdr)) {
error_report("failed to send a req, %s", strerror(errno));
ret = -socket_error();
return ret;
return -errno;
}
ret = qemu_co_send(sockfd, data, *wlen);
if (ret != *wlen) {
ret = -socket_error();
error_report("failed to send a req, %s", strerror(errno));
return -errno;
}
return ret;
+19 -1
View File
@@ -39,7 +39,7 @@
* monitor the file descriptor @fd for the
* I/O conditions in @condition. This is able
* monitor block devices, character devices,
* sockets, pipes but not plain files.
* pipes but not plain files or, on Win32, sockets.
*
* Returns: the new main loop source
*/
@@ -47,6 +47,24 @@ GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
int fd,
GIOCondition condition);
/**
* qio_channel_create_socket_watch:
* @ioc: the channel object
* @fd: the file descriptor
* @condition: the I/O condition
*
* Create a new main loop source that is able to
* monitor the file descriptor @fd for the
* I/O conditions in @condition. This is equivalent
* to qio_channel_create_fd_watch on POSIX systems
* but not on Windows.
*
* Returns: the new main loop source
*/
GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
int fd,
GIOCondition condition);
/**
* qio_channel_create_fd_pair_watch:
* @ioc: the channel object
+3
View File
@@ -78,6 +78,9 @@ typedef gboolean (*QIOChannelFunc)(QIOChannel *ioc,
struct QIOChannel {
Object parent;
unsigned int features; /* bitmask of QIOChannelFeatures */
#ifdef _WIN32
HANDLE event; /* For use with GSource on Win32 */
#endif
};
/**
-17
View File
@@ -3,26 +3,9 @@
#define QEMU_SOCKET_H
#ifdef _WIN32
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define socket_error() WSAGetLastError()
int inet_aton(const char *cp, struct in_addr *ia);
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>
#define socket_error() errno
#define closesocket(s) close(s)
#endif /* !_WIN32 */
#include "qapi-types.h"
+9
View File
@@ -26,6 +26,12 @@
#ifndef QEMU_OS_POSIX_H
#define QEMU_OS_POSIX_H
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>
void os_set_line_buffering(void);
void os_set_proc_name(const char *s);
@@ -34,6 +40,9 @@ void os_daemonize(void);
void os_setup_post(void);
int os_mlock(void);
#define closesocket(s) close(s)
#define ioctlsocket(s, r, v) ioctl(s, r, v)
typedef struct timeval qemu_timeval;
#define qemu_gettimeofday(tp) gettimeofday(tp, NULL)
+79 -27
View File
@@ -28,32 +28,7 @@
#include <winsock2.h>
#include <windows.h>
/* Workaround for older versions of MinGW. */
#ifndef ECONNREFUSED
# define ECONNREFUSED WSAECONNREFUSED
#endif
#ifndef EINPROGRESS
# define EINPROGRESS WSAEINPROGRESS
#endif
#ifndef EHOSTUNREACH
# define EHOSTUNREACH WSAEHOSTUNREACH
#endif
#ifndef EINTR
# define EINTR WSAEINTR
#endif
#ifndef EINPROGRESS
# define EINPROGRESS WSAEINPROGRESS
#endif
#ifndef ENETUNREACH
# define ENETUNREACH WSAENETUNREACH
#endif
#ifndef ENOTCONN
# define ENOTCONN WSAENOTCONN
#endif
#ifndef EWOULDBLOCK
# define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#include <ws2tcpip.h>
#if defined(_WIN64)
/* On w64, setjmp is implemented by _setjmp which needs a second parameter.
@@ -80,7 +55,6 @@ struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime_r(const time_t *timep, struct tm *result);
#endif /* CONFIG_LOCALTIME_R */
static inline void os_setup_signal_handling(void) {}
static inline void os_daemonize(void) {}
static inline void os_setup_post(void) {}
@@ -129,4 +103,82 @@ static inline char *realpath(const char *path, char *resolved_path)
return resolved_path;
}
/* We wrap all the sockets functions so that we can
* set errno based on WSAGetLastError()
*/
#undef connect
#define connect qemu_connect_wrap
int qemu_connect_wrap(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
#undef listen
#define listen qemu_listen_wrap
int qemu_listen_wrap(int sockfd, int backlog);
#undef bind
#define bind qemu_bind_wrap
int qemu_bind_wrap(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
#undef socket
#define socket qemu_socket_wrap
int qemu_socket_wrap(int domain, int type, int protocol);
#undef accept
#define accept qemu_accept_wrap
int qemu_accept_wrap(int sockfd, struct sockaddr *addr,
socklen_t *addrlen);
#undef shutdown
#define shutdown qemu_shutdown_wrap
int qemu_shutdown_wrap(int sockfd, int how);
#undef ioctlsocket
#define ioctlsocket qemu_ioctlsocket_wrap
int qemu_ioctlsocket_wrap(int fd, int req, void *val);
#undef closesocket
#define closesocket qemu_closesocket_wrap
int qemu_closesocket_wrap(int fd);
#undef getsockopt
#define getsockopt qemu_getsockopt_wrap
int qemu_getsockopt_wrap(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
#undef setsockopt
#define setsockopt qemu_setsockopt_wrap
int qemu_setsockopt_wrap(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
#undef getpeername
#define getpeername qemu_getpeername_wrap
int qemu_getpeername_wrap(int sockfd, struct sockaddr *addr,
socklen_t *addrlen);
#undef getsockname
#define getsockname qemu_getsockname_wrap
int qemu_getsockname_wrap(int sockfd, struct sockaddr *addr,
socklen_t *addrlen);
#undef send
#define send qemu_send_wrap
ssize_t qemu_send_wrap(int sockfd, const void *buf, size_t len, int flags);
#undef sendto
#define sendto qemu_sendto_wrap
ssize_t qemu_sendto_wrap(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *addr, socklen_t addrlen);
#undef recv
#define recv qemu_recv_wrap
ssize_t qemu_recv_wrap(int sockfd, void *buf, size_t len, int flags);
#undef recvfrom
#define recvfrom qemu_recvfrom_wrap
ssize_t qemu_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *addr, socklen_t *addrlen);
#endif
+2 -4
View File
@@ -236,8 +236,7 @@ static ssize_t qio_channel_command_readv(QIOChannel *ioc,
retry:
ret = readv(cioc->readfd, iov, niov);
if (ret < 0) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
if (errno == EAGAIN) {
return QIO_CHANNEL_ERR_BLOCK;
}
if (errno == EINTR) {
@@ -265,8 +264,7 @@ static ssize_t qio_channel_command_writev(QIOChannel *ioc,
retry:
ret = writev(cioc->writefd, iov, niov);
if (ret <= 0) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
if (errno == EAGAIN) {
return QIO_CHANNEL_ERR_BLOCK;
}
if (errno == EINTR) {
+2 -4
View File
@@ -96,8 +96,7 @@ static ssize_t qio_channel_file_readv(QIOChannel *ioc,
retry:
ret = readv(fioc->fd, iov, niov);
if (ret < 0) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
if (errno == EAGAIN) {
return QIO_CHANNEL_ERR_BLOCK;
}
if (errno == EINTR) {
@@ -125,8 +124,7 @@ static ssize_t qio_channel_file_writev(QIOChannel *ioc,
retry:
ret = writev(fioc->fd, iov, niov);
if (ret <= 0) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
if (errno == EAGAIN) {
return QIO_CHANNEL_ERR_BLOCK;
}
if (errno == EINTR) {
+52 -32
View File
@@ -55,6 +55,10 @@ qio_channel_socket_new(void)
ioc = QIO_CHANNEL(sioc);
ioc->features |= (1 << QIO_CHANNEL_FEATURE_SHUTDOWN);
#ifdef WIN32
ioc->event = CreateEvent(NULL, FALSE, FALSE, NULL);
#endif
trace_qio_channel_socket_new(sioc);
return sioc;
@@ -78,11 +82,11 @@ qio_channel_socket_set_fd(QIOChannelSocket *sioc,
if (getpeername(fd, (struct sockaddr *)&sioc->remoteAddr,
&sioc->remoteAddrLen) < 0) {
if (socket_error() == ENOTCONN) {
if (errno == ENOTCONN) {
memset(&sioc->remoteAddr, 0, sizeof(sioc->remoteAddr));
sioc->remoteAddrLen = sizeof(sioc->remoteAddr);
} else {
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to query remote socket address");
goto error;
}
@@ -90,7 +94,7 @@ qio_channel_socket_set_fd(QIOChannelSocket *sioc,
if (getsockname(fd, (struct sockaddr *)&sioc->localAddr,
&sioc->localAddrLen) < 0) {
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to query local socket address");
goto error;
}
@@ -341,13 +345,18 @@ qio_channel_socket_accept(QIOChannelSocket *ioc,
cioc->remoteAddrLen = sizeof(ioc->remoteAddr);
cioc->localAddrLen = sizeof(ioc->localAddr);
#ifdef WIN32
QIO_CHANNEL(cioc)->event = CreateEvent(NULL, FALSE, FALSE, NULL);
#endif
retry:
trace_qio_channel_socket_accept(ioc);
cioc->fd = accept(ioc->fd, (struct sockaddr *)&cioc->remoteAddr,
&cioc->remoteAddrLen);
cioc->fd = qemu_accept(ioc->fd, (struct sockaddr *)&cioc->remoteAddr,
&cioc->remoteAddrLen);
if (cioc->fd < 0) {
trace_qio_channel_socket_accept_fail(ioc);
if (socket_error() == EINTR) {
if (errno == EINTR) {
goto retry;
}
goto error;
@@ -355,7 +364,7 @@ qio_channel_socket_accept(QIOChannelSocket *ioc,
if (getsockname(cioc->fd, (struct sockaddr *)&cioc->localAddr,
&cioc->localAddrLen) < 0) {
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to query local socket address");
goto error;
}
@@ -384,7 +393,10 @@ static void qio_channel_socket_finalize(Object *obj)
{
QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
if (ioc->fd != -1) {
close(ioc->fd);
#ifdef WIN32
WSAEventSelect(ioc->fd, NULL, 0);
#endif
closesocket(ioc->fd);
ioc->fd = -1;
}
}
@@ -466,15 +478,14 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
retry:
ret = recvmsg(sioc->fd, &msg, sflags);
if (ret < 0) {
if (socket_error() == EAGAIN ||
socket_error() == EWOULDBLOCK) {
if (errno == EAGAIN) {
return QIO_CHANNEL_ERR_BLOCK;
}
if (socket_error() == EINTR) {
if (errno == EINTR) {
goto retry;
}
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to read from socket");
return -1;
}
@@ -526,14 +537,13 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
retry:
ret = sendmsg(sioc->fd, &msg, 0);
if (ret <= 0) {
if (socket_error() == EAGAIN ||
socket_error() == EWOULDBLOCK) {
if (errno == EAGAIN) {
return QIO_CHANNEL_ERR_BLOCK;
}
if (socket_error() == EINTR) {
if (errno == EINTR) {
goto retry;
}
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to write to socket");
return -1;
}
@@ -559,17 +569,17 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc,
iov[i].iov_len,
0);
if (ret < 0) {
if (socket_error() == EAGAIN) {
if (errno == EAGAIN) {
if (done) {
return done;
} else {
return QIO_CHANNEL_ERR_BLOCK;
}
} else if (socket_error() == EINTR) {
} else if (errno == EINTR) {
goto retry;
} else {
error_setg_errno(errp, socket_error(),
"Unable to write to socket");
error_setg_errno(errp, errno,
"Unable to read from socket");
return -1;
}
}
@@ -601,16 +611,16 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
iov[i].iov_len,
0);
if (ret < 0) {
if (socket_error() == EAGAIN) {
if (errno == EAGAIN) {
if (done) {
return done;
} else {
return QIO_CHANNEL_ERR_BLOCK;
}
} else if (socket_error() == EINTR) {
} else if (errno == EINTR) {
goto retry;
} else {
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to write to socket");
return -1;
}
@@ -636,6 +646,11 @@ qio_channel_socket_set_blocking(QIOChannel *ioc,
qemu_set_block(sioc->fd);
} else {
qemu_set_nonblock(sioc->fd);
#ifdef WIN32
WSAEventSelect(sioc->fd, ioc->event,
FD_READ | FD_ACCEPT | FD_CLOSE |
FD_CONNECT | FD_WRITE | FD_OOB);
#endif
}
return 0;
}
@@ -671,13 +686,18 @@ qio_channel_socket_close(QIOChannel *ioc,
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
if (closesocket(sioc->fd) < 0) {
if (sioc->fd != -1) {
#ifdef WIN32
WSAEventSelect(sioc->fd, NULL, 0);
#endif
if (closesocket(sioc->fd) < 0) {
sioc->fd = -1;
error_setg_errno(errp, errno,
"Unable to close socket");
return -1;
}
sioc->fd = -1;
error_setg_errno(errp, socket_error(),
"Unable to close socket");
return -1;
}
sioc->fd = -1;
return 0;
}
@@ -703,7 +723,7 @@ qio_channel_socket_shutdown(QIOChannel *ioc,
}
if (shutdown(sioc->fd, sockhow) < 0) {
error_setg_errno(errp, socket_error(),
error_setg_errno(errp, errno,
"Unable to shutdown socket");
return -1;
}
@@ -714,9 +734,9 @@ static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
GIOCondition condition)
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
return qio_channel_create_fd_watch(ioc,
sioc->fd,
condition);
return qio_channel_create_socket_watch(ioc,
sioc->fd,
condition);
}
static void qio_channel_socket_class_init(ObjectClass *klass,
+150 -2
View File
@@ -30,6 +30,20 @@ struct QIOChannelFDSource {
};
#ifdef CONFIG_WIN32
typedef struct QIOChannelSocketSource QIOChannelSocketSource;
struct QIOChannelSocketSource {
GSource parent;
GPollFD fd;
QIOChannel *ioc;
SOCKET socket;
int revents;
GIOCondition condition;
};
#endif
typedef struct QIOChannelFDPairSource QIOChannelFDPairSource;
struct QIOChannelFDPairSource {
GSource parent;
@@ -82,6 +96,97 @@ qio_channel_fd_source_finalize(GSource *source)
}
#ifdef CONFIG_WIN32
static gboolean
qio_channel_socket_source_prepare(GSource *source G_GNUC_UNUSED,
gint *timeout)
{
*timeout = -1;
return FALSE;
}
/*
* NB, this impl only works when the socket is in non-blocking
* mode on Win32
*/
static gboolean
qio_channel_socket_source_check(GSource *source)
{
static struct timeval tv0;
QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
WSANETWORKEVENTS ev;
fd_set rfds, wfds, xfds;
if (!ssource->condition) {
return 0;
}
WSAEnumNetworkEvents(ssource->socket, ssource->ioc->event, &ev);
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&xfds);
if (ssource->condition & G_IO_IN) {
FD_SET((SOCKET)ssource->socket, &rfds);
}
if (ssource->condition & G_IO_OUT) {
FD_SET((SOCKET)ssource->socket, &wfds);
}
if (ssource->condition & G_IO_PRI) {
FD_SET((SOCKET)ssource->socket, &xfds);
}
ssource->revents = 0;
if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) {
return 0;
}
if (FD_ISSET(ssource->socket, &rfds)) {
ssource->revents |= G_IO_IN;
}
if (FD_ISSET(ssource->socket, &wfds)) {
ssource->revents |= G_IO_OUT;
}
if (FD_ISSET(ssource->socket, &xfds)) {
ssource->revents |= G_IO_PRI;
}
return ssource->revents;
}
static gboolean
qio_channel_socket_source_dispatch(GSource *source,
GSourceFunc callback,
gpointer user_data)
{
QIOChannelFunc func = (QIOChannelFunc)callback;
QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
return (*func)(ssource->ioc, ssource->revents, user_data);
}
static void
qio_channel_socket_source_finalize(GSource *source)
{
QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
object_unref(OBJECT(ssource->ioc));
}
GSourceFuncs qio_channel_socket_source_funcs = {
qio_channel_socket_source_prepare,
qio_channel_socket_source_check,
qio_channel_socket_source_dispatch,
qio_channel_socket_source_finalize
};
#endif
static gboolean
qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED,
gint *timeout)
@@ -160,7 +265,11 @@ GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
ssource->condition = condition;
#ifdef CONFIG_WIN32
ssource->fd.fd = (gint64)_get_osfhandle(fd);
#else
ssource->fd.fd = fd;
#endif
ssource->fd.events = condition;
g_source_add_poll(source, &ssource->fd);
@@ -168,6 +277,40 @@ GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
return source;
}
#ifdef CONFIG_WIN32
GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
int socket,
GIOCondition condition)
{
GSource *source;
QIOChannelSocketSource *ssource;
source = g_source_new(&qio_channel_socket_source_funcs,
sizeof(QIOChannelSocketSource));
ssource = (QIOChannelSocketSource *)source;
ssource->ioc = ioc;
object_ref(OBJECT(ioc));
ssource->condition = condition;
ssource->socket = socket;
ssource->revents = 0;
ssource->fd.fd = (gintptr)ioc->event;
ssource->fd.events = G_IO_IN;
g_source_add_poll(source, &ssource->fd);
return source;
}
#else
GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
int socket,
GIOCondition condition)
{
return qio_channel_create_fd_watch(ioc, socket, condition);
}
#endif
GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
int fdread,
@@ -186,10 +329,15 @@ GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
ssource->condition = condition;
#ifdef CONFIG_WIN32
ssource->fdread.fd = (gint64)_get_osfhandle(fdread);
ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite);
#else
ssource->fdread.fd = fdread;
ssource->fdread.events = condition & G_IO_IN;
ssource->fdwrite.fd = fdwrite;
#endif
ssource->fdread.events = condition & G_IO_IN;
ssource->fdwrite.events = condition & G_IO_OUT;
g_source_add_poll(source, &ssource->fdread);
+14
View File
@@ -274,10 +274,24 @@ void qio_channel_wait(QIOChannel *ioc,
}
#ifdef _WIN32
static void qio_channel_finalize(Object *obj)
{
QIOChannel *ioc = QIO_CHANNEL(obj);
if (ioc->event) {
CloseHandle(ioc->event);
}
}
#endif
static const TypeInfo qio_channel_info = {
.parent = TYPE_OBJECT,
.name = TYPE_QIO_CHANNEL,
.instance_size = sizeof(QIOChannel),
#ifdef _WIN32
.instance_finalize = qio_channel_finalize,
#endif
.abstract = true,
.class_size = sizeof(QIOChannelClass),
};
-1
View File
@@ -38,7 +38,6 @@
#include "qemu.h"
#include "flat.h"
#define ntohl(x) be32_to_cpu(x)
#include <target_flat.h>
//#define DEBUG
+6 -8
View File
@@ -53,18 +53,16 @@ static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
}
if (size > 0) {
err = socket_error();
if (err != EAGAIN && err != EWOULDBLOCK) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
error_report("socket_writev_buffer: Got err=%d for (%zu/%zu)",
err, (size_t)size, (size_t)len);
errno, (size_t)size, (size_t)len);
/*
* If I've already sent some but only just got the error, I
* could return the amount validly sent so far and wait for the
* next call to report the error, but I'd rather flag the error
* immediately.
*/
return -err;
return -errno;
}
/* Emulate blocking */
@@ -99,15 +97,15 @@ static ssize_t socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
if (len != -1) {
break;
}
if (socket_error() == EAGAIN) {
if (errno == EAGAIN) {
yield_until_fd_readable(s->fd);
} else if (socket_error() != EINTR) {
} else if (errno != EINTR) {
break;
}
}
if (len == -1) {
len = -socket_error();
len = -errno;
}
return len;
}
+3 -4
View File
@@ -59,12 +59,11 @@ static void tcp_accept_incoming_migration(void *opaque)
socklen_t addrlen = sizeof(addr);
int s = (intptr_t)opaque;
QEMUFile *f;
int c, err;
int c;
do {
c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
err = socket_error();
} while (c < 0 && err == EINTR);
} while (c < 0 && errno == EINTR);
qemu_set_fd_handler(s, NULL, NULL, NULL);
closesocket(s);
@@ -72,7 +71,7 @@ static void tcp_accept_incoming_migration(void *opaque)
if (c < 0) {
error_report("could not accept migration connection (%s)",
strerror(err));
strerror(errno));
return;
}
+8 -11
View File
@@ -145,15 +145,14 @@ static void net_socket_send_completed(NetClientState *nc, ssize_t len)
static void net_socket_send(void *opaque)
{
NetSocketState *s = opaque;
int size, err;
int size;
unsigned l;
uint8_t buf1[NET_BUFSIZE];
const uint8_t *buf;
size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
if (size < 0) {
err = socket_error();
if (err != EWOULDBLOCK)
if (errno != EWOULDBLOCK)
goto eoc;
} else if (size == 0) {
/* end of connection */
@@ -566,7 +565,7 @@ static int net_socket_connect_init(NetClientState *peer,
const char *host_str)
{
NetSocketState *s;
int fd, connected, ret, err;
int fd, connected, ret;
struct sockaddr_in saddr;
if (parse_host_port(&saddr, host_str) < 0)
@@ -583,14 +582,12 @@ static int net_socket_connect_init(NetClientState *peer,
for(;;) {
ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
if (ret < 0) {
err = socket_error();
if (err == EINTR || err == EWOULDBLOCK) {
} else if (err == EINPROGRESS) {
if (errno == EINTR || errno == EWOULDBLOCK) {
/* continue */
} else if (errno == EINPROGRESS ||
errno == EALREADY ||
errno == EINVAL) {
break;
#ifdef _WIN32
} else if (err == WSAEALREADY || err == WSAEINVAL) {
break;
#endif
} else {
perror("connect");
closesocket(fd);
+35 -61
View File
@@ -3091,20 +3091,6 @@ static void tcp_chr_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
static void qemu_chr_finish_socket_connection(CharDriverState *chr,
QIOChannelSocket *sioc)
{
TCPCharDriver *s = chr->opaque;
if (s->is_listen) {
s->listen_ioc = sioc;
s->listen_tag = qio_channel_add_watch(
QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
} else {
tcp_chr_new_client(chr, sioc);
object_unref(OBJECT(sioc));
}
}
static void qemu_chr_socket_connected(Object *src, Error *err, void *opaque)
{
@@ -3119,37 +3105,11 @@ static void qemu_chr_socket_connected(Object *src, Error *err, void *opaque)
}
s->connect_err_reported = false;
qemu_chr_finish_socket_connection(chr, sioc);
}
static bool qemu_chr_open_socket_fd(CharDriverState *chr, Error **errp)
{
TCPCharDriver *s = chr->opaque;
QIOChannelSocket *sioc = qio_channel_socket_new();
if (s->is_listen) {
if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
goto fail;
}
qemu_chr_finish_socket_connection(chr, sioc);
} else if (s->reconnect_time) {
qio_channel_socket_connect_async(sioc, s->addr,
qemu_chr_socket_connected,
chr, NULL);
} else {
if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
goto fail;
}
qemu_chr_finish_socket_connection(chr, sioc);
}
return true;
fail:
tcp_chr_new_client(chr, sioc);
object_unref(OBJECT(sioc));
return false;
}
/*********************************************************/
/* Ring buffer chardev */
@@ -4258,19 +4218,11 @@ static CharDriverState *qmp_chardev_open_parallel(const char *id,
#endif /* WIN32 */
static void socket_try_connect(CharDriverState *chr)
{
Error *err = NULL;
if (!qemu_chr_open_socket_fd(chr, &err)) {
check_report_connect_error(chr, err);
}
}
static gboolean socket_reconnect_timeout(gpointer opaque)
{
CharDriverState *chr = opaque;
TCPCharDriver *s = chr->opaque;
QIOChannelSocket *sioc;
s->reconnect_timer = 0;
@@ -4278,7 +4230,10 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
return false;
}
socket_try_connect(chr);
sioc = qio_channel_socket_new();
qio_channel_socket_connect_async(sioc, s->addr,
qemu_chr_socket_connected,
chr, NULL);
return false;
}
@@ -4298,6 +4253,7 @@ static CharDriverState *qmp_chardev_open_socket(const char *id,
bool is_waitconnect = sock->has_wait ? sock->wait : false;
int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
ChardevCommon *common = qapi_ChardevSocket_base(sock);
QIOChannelSocket *sioc = NULL;
chr = qemu_chr_alloc(common, errp);
if (!chr) {
@@ -4367,22 +4323,40 @@ static CharDriverState *qmp_chardev_open_socket(const char *id,
s->reconnect_time = reconnect;
}
sioc = qio_channel_socket_new();
if (s->reconnect_time) {
socket_try_connect(chr);
} else if (!qemu_chr_open_socket_fd(chr, errp)) {
goto error;
}
if (is_listen && is_waitconnect) {
fprintf(stderr, "QEMU waiting for connection on: %s\n",
chr->filename);
tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
qio_channel_socket_connect_async(sioc, s->addr,
qemu_chr_socket_connected,
chr, NULL);
} else if (s->is_listen) {
if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
goto error;
}
s->listen_ioc = sioc;
if (is_waitconnect) {
fprintf(stderr, "QEMU waiting for connection on: %s\n",
chr->filename);
tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
}
qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
if (!s->ioc) {
s->listen_tag = qio_channel_add_watch(
QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
}
} else {
if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
goto error;
}
tcp_chr_new_client(chr, sioc);
object_unref(OBJECT(sioc));
}
return chr;
error:
if (sioc) {
object_unref(OBJECT(sioc));
}
if (s->tls_creds) {
object_unref(OBJECT(s->tls_creds));
}
-2
View File
@@ -14,8 +14,6 @@ typedef char *caddr_t;
# include <iphlpapi.h>
#else
# define ioctlsocket ioctl
# define closesocket(s) close(s)
# if !defined(__HAIKU__)
# define O_BINARY 0
# endif
-4
View File
@@ -586,11 +586,7 @@ findso:
}
if ((tcp_fconnect(so, so->so_ffamily) == -1) &&
#if defined(_WIN32)
socket_error() != WSAEWOULDBLOCK
#else
(errno != EINPROGRESS) && (errno != EWOULDBLOCK)
#endif
) {
u_char code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n",
+3 -3
View File
@@ -132,7 +132,7 @@ static gpointer test_io_thread_reader(gpointer opaque)
if (ret == QIO_CHANNEL_ERR_BLOCK) {
if (data->blocking) {
error_setg(&data->writeerr,
error_setg(&data->readerr,
"Unexpected I/O blocking");
break;
} else {
@@ -233,11 +233,11 @@ void qio_channel_test_run_reader(QIOChannelTest *test,
void qio_channel_test_validate(QIOChannelTest *test)
{
g_assert(test->readerr == NULL);
g_assert(test->writeerr == NULL);
g_assert_cmpint(memcmp(test->input,
test->output,
test->len), ==, 0);
g_assert(test->readerr == NULL);
g_assert(test->writeerr == NULL);
g_free(test->inputv);
g_free(test->outputv);

Some files were not shown because too many files have changed in this diff Show More