11c809fa0SDaniel P. Berrange /* 21c809fa0SDaniel P. Berrange * QEMU I/O channels watch helper APIs 31c809fa0SDaniel P. Berrange * 41c809fa0SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc. 51c809fa0SDaniel P. Berrange * 61c809fa0SDaniel P. Berrange * This library is free software; you can redistribute it and/or 71c809fa0SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 81c809fa0SDaniel P. Berrange * License as published by the Free Software Foundation; either 9c8198bd5SChetan Pant * version 2.1 of the License, or (at your option) any later version. 101c809fa0SDaniel P. Berrange * 111c809fa0SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 121c809fa0SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 131c809fa0SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 141c809fa0SDaniel P. Berrange * Lesser General Public License for more details. 151c809fa0SDaniel P. Berrange * 161c809fa0SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 171c809fa0SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 181c809fa0SDaniel P. Berrange * 191c809fa0SDaniel P. Berrange */ 201c809fa0SDaniel P. Berrange 21cae9fc56SPeter Maydell #include "qemu/osdep.h" 221c809fa0SDaniel P. Berrange #include "io/channel-watch.h" 231c809fa0SDaniel P. Berrange 241c809fa0SDaniel P. Berrange typedef struct QIOChannelFDSource QIOChannelFDSource; 251c809fa0SDaniel P. Berrange struct QIOChannelFDSource { 261c809fa0SDaniel P. Berrange GSource parent; 271c809fa0SDaniel P. Berrange GPollFD fd; 281c809fa0SDaniel P. Berrange QIOChannel *ioc; 291c809fa0SDaniel P. Berrange GIOCondition condition; 301c809fa0SDaniel P. Berrange }; 311c809fa0SDaniel P. Berrange 321c809fa0SDaniel P. Berrange 33a5897205SPaolo Bonzini #ifdef CONFIG_WIN32 34a5897205SPaolo Bonzini typedef struct QIOChannelSocketSource QIOChannelSocketSource; 35a5897205SPaolo Bonzini struct QIOChannelSocketSource { 36a5897205SPaolo Bonzini GSource parent; 37a5897205SPaolo Bonzini GPollFD fd; 38a5897205SPaolo Bonzini QIOChannel *ioc; 39a5897205SPaolo Bonzini SOCKET socket; 40a5897205SPaolo Bonzini int revents; 41a5897205SPaolo Bonzini GIOCondition condition; 42a5897205SPaolo Bonzini }; 43a5897205SPaolo Bonzini 44a5897205SPaolo Bonzini #endif 45a5897205SPaolo Bonzini 46a5897205SPaolo Bonzini 471c809fa0SDaniel P. Berrange typedef struct QIOChannelFDPairSource QIOChannelFDPairSource; 481c809fa0SDaniel P. Berrange struct QIOChannelFDPairSource { 491c809fa0SDaniel P. Berrange GSource parent; 501c809fa0SDaniel P. Berrange GPollFD fdread; 511c809fa0SDaniel P. Berrange GPollFD fdwrite; 521c809fa0SDaniel P. Berrange QIOChannel *ioc; 531c809fa0SDaniel P. Berrange GIOCondition condition; 541c809fa0SDaniel P. Berrange }; 551c809fa0SDaniel P. Berrange 561c809fa0SDaniel P. Berrange 571c809fa0SDaniel P. Berrange static gboolean 581c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED, 591c809fa0SDaniel P. Berrange gint *timeout) 601c809fa0SDaniel P. Berrange { 611c809fa0SDaniel P. Berrange *timeout = -1; 621c809fa0SDaniel P. Berrange 631c809fa0SDaniel P. Berrange return FALSE; 641c809fa0SDaniel P. Berrange } 651c809fa0SDaniel P. Berrange 661c809fa0SDaniel P. Berrange 671c809fa0SDaniel P. Berrange static gboolean 681c809fa0SDaniel P. Berrange qio_channel_fd_source_check(GSource *source) 691c809fa0SDaniel P. Berrange { 701c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 711c809fa0SDaniel P. Berrange 721c809fa0SDaniel P. Berrange return ssource->fd.revents & ssource->condition; 731c809fa0SDaniel P. Berrange } 741c809fa0SDaniel P. Berrange 751c809fa0SDaniel P. Berrange 761c809fa0SDaniel P. Berrange static gboolean 771c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch(GSource *source, 781c809fa0SDaniel P. Berrange GSourceFunc callback, 791c809fa0SDaniel P. Berrange gpointer user_data) 801c809fa0SDaniel P. Berrange { 811c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 821c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 831c809fa0SDaniel P. Berrange 841c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 851c809fa0SDaniel P. Berrange ssource->fd.revents & ssource->condition, 861c809fa0SDaniel P. Berrange user_data); 871c809fa0SDaniel P. Berrange } 881c809fa0SDaniel P. Berrange 891c809fa0SDaniel P. Berrange 901c809fa0SDaniel P. Berrange static void 911c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize(GSource *source) 921c809fa0SDaniel P. Berrange { 931c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 941c809fa0SDaniel P. Berrange 951c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 961c809fa0SDaniel P. Berrange } 971c809fa0SDaniel P. Berrange 981c809fa0SDaniel P. Berrange 99a5897205SPaolo Bonzini #ifdef CONFIG_WIN32 100a5897205SPaolo Bonzini static gboolean 101a5897205SPaolo Bonzini qio_channel_socket_source_prepare(GSource *source G_GNUC_UNUSED, 102a5897205SPaolo Bonzini gint *timeout) 103a5897205SPaolo Bonzini { 104a5897205SPaolo Bonzini *timeout = -1; 105a5897205SPaolo Bonzini 106a5897205SPaolo Bonzini return FALSE; 107a5897205SPaolo Bonzini } 108a5897205SPaolo Bonzini 109a5897205SPaolo Bonzini 110a5897205SPaolo Bonzini /* 111a5897205SPaolo Bonzini * NB, this impl only works when the socket is in non-blocking 112a5897205SPaolo Bonzini * mode on Win32 113a5897205SPaolo Bonzini */ 114a5897205SPaolo Bonzini static gboolean 115a5897205SPaolo Bonzini qio_channel_socket_source_check(GSource *source) 116a5897205SPaolo Bonzini { 117a5897205SPaolo Bonzini static struct timeval tv0; 118a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 119a5897205SPaolo Bonzini fd_set rfds, wfds, xfds; 120a5897205SPaolo Bonzini 121a5897205SPaolo Bonzini if (!ssource->condition) { 122a5897205SPaolo Bonzini return 0; 123a5897205SPaolo Bonzini } 124a5897205SPaolo Bonzini 125a5897205SPaolo Bonzini FD_ZERO(&rfds); 126a5897205SPaolo Bonzini FD_ZERO(&wfds); 127a5897205SPaolo Bonzini FD_ZERO(&xfds); 128a5897205SPaolo Bonzini if (ssource->condition & G_IO_IN) { 1296c822a03SBin Meng FD_SET(ssource->socket, &rfds); 130a5897205SPaolo Bonzini } 131a5897205SPaolo Bonzini if (ssource->condition & G_IO_OUT) { 1326c822a03SBin Meng FD_SET(ssource->socket, &wfds); 133a5897205SPaolo Bonzini } 134a5897205SPaolo Bonzini if (ssource->condition & G_IO_PRI) { 1356c822a03SBin Meng FD_SET(ssource->socket, &xfds); 136a5897205SPaolo Bonzini } 137a5897205SPaolo Bonzini ssource->revents = 0; 138a5897205SPaolo Bonzini if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) { 139a5897205SPaolo Bonzini return 0; 140a5897205SPaolo Bonzini } 141a5897205SPaolo Bonzini 142a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &rfds)) { 143a5897205SPaolo Bonzini ssource->revents |= G_IO_IN; 144a5897205SPaolo Bonzini } 145a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &wfds)) { 146a5897205SPaolo Bonzini ssource->revents |= G_IO_OUT; 147a5897205SPaolo Bonzini } 148a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &xfds)) { 149a5897205SPaolo Bonzini ssource->revents |= G_IO_PRI; 150a5897205SPaolo Bonzini } 151a5897205SPaolo Bonzini 152a5897205SPaolo Bonzini return ssource->revents; 153a5897205SPaolo Bonzini } 154a5897205SPaolo Bonzini 155a5897205SPaolo Bonzini 156a5897205SPaolo Bonzini static gboolean 157a5897205SPaolo Bonzini qio_channel_socket_source_dispatch(GSource *source, 158a5897205SPaolo Bonzini GSourceFunc callback, 159a5897205SPaolo Bonzini gpointer user_data) 160a5897205SPaolo Bonzini { 161a5897205SPaolo Bonzini QIOChannelFunc func = (QIOChannelFunc)callback; 162a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 163a5897205SPaolo Bonzini 164a5897205SPaolo Bonzini return (*func)(ssource->ioc, ssource->revents, user_data); 165a5897205SPaolo Bonzini } 166a5897205SPaolo Bonzini 167a5897205SPaolo Bonzini 168a5897205SPaolo Bonzini static void 169a5897205SPaolo Bonzini qio_channel_socket_source_finalize(GSource *source) 170a5897205SPaolo Bonzini { 171a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 172a5897205SPaolo Bonzini 173a5897205SPaolo Bonzini object_unref(OBJECT(ssource->ioc)); 174a5897205SPaolo Bonzini } 175a5897205SPaolo Bonzini 176a5897205SPaolo Bonzini 177a5897205SPaolo Bonzini GSourceFuncs qio_channel_socket_source_funcs = { 178a5897205SPaolo Bonzini qio_channel_socket_source_prepare, 179a5897205SPaolo Bonzini qio_channel_socket_source_check, 180a5897205SPaolo Bonzini qio_channel_socket_source_dispatch, 181a5897205SPaolo Bonzini qio_channel_socket_source_finalize 182a5897205SPaolo Bonzini }; 183a5897205SPaolo Bonzini #endif 184a5897205SPaolo Bonzini 185a5897205SPaolo Bonzini 1861c809fa0SDaniel P. Berrange static gboolean 1871c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED, 1881c809fa0SDaniel P. Berrange gint *timeout) 1891c809fa0SDaniel P. Berrange { 1901c809fa0SDaniel P. Berrange *timeout = -1; 1911c809fa0SDaniel P. Berrange 1921c809fa0SDaniel P. Berrange return FALSE; 1931c809fa0SDaniel P. Berrange } 1941c809fa0SDaniel P. Berrange 1951c809fa0SDaniel P. Berrange 1961c809fa0SDaniel P. Berrange static gboolean 1971c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check(GSource *source) 1981c809fa0SDaniel P. Berrange { 1991c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 2001c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 2011c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 2021c809fa0SDaniel P. Berrange 2031c809fa0SDaniel P. Berrange return poll_condition & ssource->condition; 2041c809fa0SDaniel P. Berrange } 2051c809fa0SDaniel P. Berrange 2061c809fa0SDaniel P. Berrange 2071c809fa0SDaniel P. Berrange static gboolean 2081c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch(GSource *source, 2091c809fa0SDaniel P. Berrange GSourceFunc callback, 2101c809fa0SDaniel P. Berrange gpointer user_data) 2111c809fa0SDaniel P. Berrange { 2121c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 2131c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 2141c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 2151c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 2161c809fa0SDaniel P. Berrange 2171c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 2181c809fa0SDaniel P. Berrange poll_condition & ssource->condition, 2191c809fa0SDaniel P. Berrange user_data); 2201c809fa0SDaniel P. Berrange } 2211c809fa0SDaniel P. Berrange 2221c809fa0SDaniel P. Berrange 2231c809fa0SDaniel P. Berrange static void 2241c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize(GSource *source) 2251c809fa0SDaniel P. Berrange { 2261c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 2271c809fa0SDaniel P. Berrange 2281c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 2291c809fa0SDaniel P. Berrange } 2301c809fa0SDaniel P. Berrange 2311c809fa0SDaniel P. Berrange 2321c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_source_funcs = { 2331c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare, 2341c809fa0SDaniel P. Berrange qio_channel_fd_source_check, 2351c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch, 2361c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize 2371c809fa0SDaniel P. Berrange }; 2381c809fa0SDaniel P. Berrange 2391c809fa0SDaniel P. Berrange 2401c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_pair_source_funcs = { 2411c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare, 2421c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check, 2431c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch, 2441c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize 2451c809fa0SDaniel P. Berrange }; 2461c809fa0SDaniel P. Berrange 2471c809fa0SDaniel P. Berrange 2481c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_watch(QIOChannel *ioc, 2491c809fa0SDaniel P. Berrange int fd, 2501c809fa0SDaniel P. Berrange GIOCondition condition) 2511c809fa0SDaniel P. Berrange { 2521c809fa0SDaniel P. Berrange GSource *source; 2531c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource; 2541c809fa0SDaniel P. Berrange 2551c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_source_funcs, 2561c809fa0SDaniel P. Berrange sizeof(QIOChannelFDSource)); 2571c809fa0SDaniel P. Berrange ssource = (QIOChannelFDSource *)source; 2581c809fa0SDaniel P. Berrange 2591c809fa0SDaniel P. Berrange ssource->ioc = ioc; 2601c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 2611c809fa0SDaniel P. Berrange 2621c809fa0SDaniel P. Berrange ssource->condition = condition; 2631c809fa0SDaniel P. Berrange 264e560d141SPaolo Bonzini #ifdef CONFIG_WIN32 265e560d141SPaolo Bonzini ssource->fd.fd = (gint64)_get_osfhandle(fd); 266e560d141SPaolo Bonzini #else 2671c809fa0SDaniel P. Berrange ssource->fd.fd = fd; 268e560d141SPaolo Bonzini #endif 2691c809fa0SDaniel P. Berrange ssource->fd.events = condition; 2701c809fa0SDaniel P. Berrange 2711c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fd); 2721c809fa0SDaniel P. Berrange 2731c809fa0SDaniel P. Berrange return source; 2741c809fa0SDaniel P. Berrange } 2751c809fa0SDaniel P. Berrange 276b83b68a0SPaolo Bonzini #ifdef CONFIG_WIN32 277b83b68a0SPaolo Bonzini GSource *qio_channel_create_socket_watch(QIOChannel *ioc, 278b83b68a0SPaolo Bonzini int socket, 279b83b68a0SPaolo Bonzini GIOCondition condition) 280b83b68a0SPaolo Bonzini { 281a5897205SPaolo Bonzini GSource *source; 282a5897205SPaolo Bonzini QIOChannelSocketSource *ssource; 283a5897205SPaolo Bonzini 284*f5fd677aSMarc-André Lureau qemu_socket_select(socket, ioc->event, 285bf88c124SPaolo Bonzini FD_READ | FD_ACCEPT | FD_CLOSE | 286*f5fd677aSMarc-André Lureau FD_CONNECT | FD_WRITE | FD_OOB, NULL); 287bf88c124SPaolo Bonzini 288a5897205SPaolo Bonzini source = g_source_new(&qio_channel_socket_source_funcs, 289a5897205SPaolo Bonzini sizeof(QIOChannelSocketSource)); 290a5897205SPaolo Bonzini ssource = (QIOChannelSocketSource *)source; 291a5897205SPaolo Bonzini 292a5897205SPaolo Bonzini ssource->ioc = ioc; 293a5897205SPaolo Bonzini object_ref(OBJECT(ioc)); 294a5897205SPaolo Bonzini 295a5897205SPaolo Bonzini ssource->condition = condition; 296a5897205SPaolo Bonzini ssource->socket = socket; 297a5897205SPaolo Bonzini ssource->revents = 0; 298a5897205SPaolo Bonzini 299a5897205SPaolo Bonzini ssource->fd.fd = (gintptr)ioc->event; 300a5897205SPaolo Bonzini ssource->fd.events = G_IO_IN; 301a5897205SPaolo Bonzini 302a5897205SPaolo Bonzini g_source_add_poll(source, &ssource->fd); 303a5897205SPaolo Bonzini 304a5897205SPaolo Bonzini return source; 305b83b68a0SPaolo Bonzini } 306b83b68a0SPaolo Bonzini #else 307b83b68a0SPaolo Bonzini GSource *qio_channel_create_socket_watch(QIOChannel *ioc, 308b83b68a0SPaolo Bonzini int socket, 309b83b68a0SPaolo Bonzini GIOCondition condition) 310b83b68a0SPaolo Bonzini { 311b83b68a0SPaolo Bonzini return qio_channel_create_fd_watch(ioc, socket, condition); 312b83b68a0SPaolo Bonzini } 313b83b68a0SPaolo Bonzini #endif 3141c809fa0SDaniel P. Berrange 3151c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc, 3161c809fa0SDaniel P. Berrange int fdread, 3171c809fa0SDaniel P. Berrange int fdwrite, 3181c809fa0SDaniel P. Berrange GIOCondition condition) 3191c809fa0SDaniel P. Berrange { 3201c809fa0SDaniel P. Berrange GSource *source; 3211c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource; 3221c809fa0SDaniel P. Berrange 3231c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_pair_source_funcs, 3241c809fa0SDaniel P. Berrange sizeof(QIOChannelFDPairSource)); 3251c809fa0SDaniel P. Berrange ssource = (QIOChannelFDPairSource *)source; 3261c809fa0SDaniel P. Berrange 3271c809fa0SDaniel P. Berrange ssource->ioc = ioc; 3281c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 3291c809fa0SDaniel P. Berrange 3301c809fa0SDaniel P. Berrange ssource->condition = condition; 3311c809fa0SDaniel P. Berrange 332e560d141SPaolo Bonzini #ifdef CONFIG_WIN32 333e560d141SPaolo Bonzini ssource->fdread.fd = (gint64)_get_osfhandle(fdread); 334e560d141SPaolo Bonzini ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite); 335e560d141SPaolo Bonzini #else 3361c809fa0SDaniel P. Berrange ssource->fdread.fd = fdread; 3371c809fa0SDaniel P. Berrange ssource->fdwrite.fd = fdwrite; 338e560d141SPaolo Bonzini #endif 339e560d141SPaolo Bonzini 340e560d141SPaolo Bonzini ssource->fdread.events = condition & G_IO_IN; 3411c809fa0SDaniel P. Berrange ssource->fdwrite.events = condition & G_IO_OUT; 3421c809fa0SDaniel P. Berrange 3431c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdread); 3441c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdwrite); 3451c809fa0SDaniel P. Berrange 3461c809fa0SDaniel P. Berrange return source; 3471c809fa0SDaniel P. Berrange } 348