#include "io/channel-socket.h"
#include "io/channel-watch.h"
#include "trace.h"
+#include "qapi/clone-visitor.h"
#define SOCKET_MAX_FDS 16
sioc->fd = -1;
ioc = QIO_CHANNEL(sioc);
- ioc->features |= (1 << QIO_CHANNEL_FEATURE_SHUTDOWN);
+ qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
#ifdef WIN32
ioc->event = CreateEvent(NULL, FALSE, FALSE, NULL);
#ifndef WIN32
if (sioc->localAddr.ss_family == AF_UNIX) {
QIOChannel *ioc = QIO_CHANNEL(sioc);
- ioc->features |= (1 << QIO_CHANNEL_FEATURE_FD_PASS);
+ qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS);
}
#endif /* WIN32 */
int fd;
trace_qio_channel_socket_connect_sync(ioc, addr);
- fd = socket_connect(addr, errp, NULL, NULL);
+ fd = socket_connect(addr, errp);
if (fd < 0) {
trace_qio_channel_socket_connect_fail(ioc);
return -1;
}
-static int qio_channel_socket_connect_worker(QIOTask *task,
- Error **errp,
- gpointer opaque)
+static void qio_channel_socket_connect_worker(QIOTask *task,
+ gpointer opaque)
{
QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
SocketAddress *addr = opaque;
- int ret;
+ Error *err = NULL;
- ret = qio_channel_socket_connect_sync(ioc,
- addr,
- errp);
+ qio_channel_socket_connect_sync(ioc, addr, &err);
- object_unref(OBJECT(ioc));
- return ret;
+ qio_task_set_error(task, err);
}
OBJECT(ioc), callback, opaque, destroy);
SocketAddress *addrCopy;
- qapi_copy_SocketAddress(&addrCopy, addr);
+ addrCopy = QAPI_CLONE(SocketAddress, addr);
/* socket_connect() does a non-blocking connect(), but it
* still blocks in DNS lookups, so we must use a thread */
close(fd);
return -1;
}
+ qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_LISTEN);
return 0;
}
-static int qio_channel_socket_listen_worker(QIOTask *task,
- Error **errp,
- gpointer opaque)
+static void qio_channel_socket_listen_worker(QIOTask *task,
+ gpointer opaque)
{
QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
SocketAddress *addr = opaque;
- int ret;
+ Error *err = NULL;
- ret = qio_channel_socket_listen_sync(ioc,
- addr,
- errp);
+ qio_channel_socket_listen_sync(ioc, addr, &err);
- object_unref(OBJECT(ioc));
- return ret;
+ qio_task_set_error(task, err);
}
OBJECT(ioc), callback, opaque, destroy);
SocketAddress *addrCopy;
- qapi_copy_SocketAddress(&addrCopy, addr);
+ addrCopy = QAPI_CLONE(SocketAddress, addr);
/* socket_listen() blocks in DNS lookups, so we must use a thread */
trace_qio_channel_socket_listen_async(ioc, addr);
g_free(data);
}
-static int qio_channel_socket_dgram_worker(QIOTask *task,
- Error **errp,
- gpointer opaque)
+static void qio_channel_socket_dgram_worker(QIOTask *task,
+ gpointer opaque)
{
QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
struct QIOChannelSocketDGramWorkerData *data = opaque;
- int ret;
+ Error *err = NULL;
/* socket_dgram() blocks in DNS lookups, so we must use a thread */
- ret = qio_channel_socket_dgram_sync(ioc,
- data->localAddr,
- data->remoteAddr,
- errp);
+ qio_channel_socket_dgram_sync(ioc, data->localAddr,
+ data->remoteAddr, &err);
- object_unref(OBJECT(ioc));
- return ret;
+ qio_task_set_error(task, err);
}
struct QIOChannelSocketDGramWorkerData *data = g_new0(
struct QIOChannelSocketDGramWorkerData, 1);
- qapi_copy_SocketAddress(&data->localAddr, localAddr);
- qapi_copy_SocketAddress(&data->remoteAddr, remoteAddr);
+ data->localAddr = QAPI_CLONE(SocketAddress, localAddr);
+ data->remoteAddr = QAPI_CLONE(SocketAddress, remoteAddr);
trace_qio_channel_socket_dgram_async(ioc, localAddr, remoteAddr);
qio_task_run_in_thread(task,
{
QIOChannelSocket *cioc;
- cioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET));
- cioc->fd = -1;
+ cioc = qio_channel_socket_new();
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 = qemu_accept(ioc->fd, (struct sockaddr *)&cioc->remoteAddr,
&cioc->remoteAddrLen);
if (cioc->fd < 0) {
- trace_qio_channel_socket_accept_fail(ioc);
if (errno == EINTR) {
goto retry;
}
+ error_setg_errno(errp, errno, "Unable to accept connection");
+ trace_qio_channel_socket_accept_fail(ioc);
goto error;
}
#ifndef WIN32
if (cioc->localAddr.ss_family == AF_UNIX) {
- QIO_CHANNEL(cioc)->features |= (1 << QIO_CHANNEL_FEATURE_FD_PASS);
+ QIOChannel *ioc_local = QIO_CHANNEL(cioc);
+ qio_channel_set_feature(ioc_local, QIO_CHANNEL_FEATURE_FD_PASS);
}
#endif /* WIN32 */
static void qio_channel_socket_finalize(Object *obj)
{
QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(obj);
+
if (ioc->fd != -1) {
+ QIOChannel *ioc_local = QIO_CHANNEL(ioc);
+ if (qio_channel_has_feature(ioc_local, QIO_CHANNEL_FEATURE_LISTEN)) {
+ Error *err = NULL;
+
+ socket_listen_cleanup(ioc->fd, &err);
+ if (err) {
+ error_report_err(err);
+ err = NULL;
+ }
+ }
#ifdef WIN32
WSAEventSelect(ioc->fd, NULL, 0);
#endif
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;
}
return 0;
}
+static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc,
+ AioContext *ctx,
+ IOHandler *io_read,
+ IOHandler *io_write,
+ void *opaque)
+{
+ QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
+ aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque);
+}
+
static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
GIOCondition condition)
{
ioc_klass->io_set_cork = qio_channel_socket_set_cork;
ioc_klass->io_set_delay = qio_channel_socket_set_delay;
ioc_klass->io_create_watch = qio_channel_socket_create_watch;
+ ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler;
}
static const TypeInfo qio_channel_socket_info = {