QIOChannelSocket * qio_channel_socket_accept(QIOChannelSocket *ioc, Error **errp) { QIOChannelSocket *cioc; cioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET)); cioc->fd = -1; 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; } goto error; } if (getsockname(cioc->fd, (struct sockaddr *)&cioc->localAddr, &cioc->localAddrLen) < 0) { error_setg_errno(errp, errno, "Unable to query local socket address"); goto error; } #ifndef WIN32 if (cioc->localAddr.ss_family == AF_UNIX) { QIOChannel *ioc_local = QIO_CHANNEL(cioc); qio_channel_set_feature(ioc_local, QIO_CHANNEL_FEATURE_FD_PASS); } #endif /* WIN32 */ trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd); return cioc; error: object_unref(OBJECT(cioc)); return NULL; }
static int qio_channel_socket_set_fd(QIOChannelSocket *sioc, int fd, Error **errp) { if (sioc->fd != -1) { error_setg(errp, "Socket is already open"); return -1; } sioc->fd = fd; sioc->remoteAddrLen = sizeof(sioc->remoteAddr); sioc->localAddrLen = sizeof(sioc->localAddr); if (getpeername(fd, (struct sockaddr *)&sioc->remoteAddr, &sioc->remoteAddrLen) < 0) { if (errno == ENOTCONN) { memset(&sioc->remoteAddr, 0, sizeof(sioc->remoteAddr)); sioc->remoteAddrLen = sizeof(sioc->remoteAddr); } else { error_setg_errno(errp, errno, "Unable to query remote socket address"); goto error; } } if (getsockname(fd, (struct sockaddr *)&sioc->localAddr, &sioc->localAddrLen) < 0) { error_setg_errno(errp, errno, "Unable to query local socket address"); goto error; } #ifndef WIN32 if (sioc->localAddr.ss_family == AF_UNIX) { QIOChannel *ioc = QIO_CHANNEL(sioc); qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS); } #endif /* WIN32 */ return 0; error: sioc->fd = -1; /* Let the caller close FD on failure */ return -1; }
QIOChannelWebsock * qio_channel_websock_new_server(QIOChannel *master) { QIOChannelWebsock *wioc; QIOChannel *ioc; wioc = QIO_CHANNEL_WEBSOCK(object_new(TYPE_QIO_CHANNEL_WEBSOCK)); ioc = QIO_CHANNEL(wioc); wioc->master = master; if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) { qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); } object_ref(OBJECT(master)); trace_qio_channel_websock_new_server(wioc, master); return wioc; }
QIOChannelSocket * qio_channel_socket_new(void) { QIOChannelSocket *sioc; QIOChannel *ioc; sioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET)); sioc->fd = -1; ioc = QIO_CHANNEL(sioc); qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); #ifdef WIN32 ioc->event = CreateEvent(NULL, FALSE, FALSE, NULL); #endif trace_qio_channel_socket_new(sioc); return sioc; }
int qio_channel_socket_listen_sync(QIOChannelSocket *ioc, SocketAddress *addr, Error **errp) { int fd; trace_qio_channel_socket_listen_sync(ioc, addr); fd = socket_listen(addr, errp); if (fd < 0) { trace_qio_channel_socket_listen_fail(ioc); return -1; } trace_qio_channel_socket_listen_complete(ioc, fd); if (qio_channel_socket_set_fd(ioc, fd, errp) < 0) { close(fd); return -1; } qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_LISTEN); return 0; }