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 91c809fa0SDaniel P. Berrange * version 2 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 119a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 120a5897205SPaolo Bonzini WSANETWORKEVENTS ev; 121a5897205SPaolo Bonzini fd_set rfds, wfds, xfds; 122a5897205SPaolo Bonzini 123a5897205SPaolo Bonzini if (!ssource->condition) { 124a5897205SPaolo Bonzini return 0; 125a5897205SPaolo Bonzini } 126a5897205SPaolo Bonzini 127a5897205SPaolo Bonzini WSAEnumNetworkEvents(ssource->socket, ssource->ioc->event, &ev); 128a5897205SPaolo Bonzini 129a5897205SPaolo Bonzini FD_ZERO(&rfds); 130a5897205SPaolo Bonzini FD_ZERO(&wfds); 131a5897205SPaolo Bonzini FD_ZERO(&xfds); 132a5897205SPaolo Bonzini if (ssource->condition & G_IO_IN) { 133a5897205SPaolo Bonzini FD_SET((SOCKET)ssource->socket, &rfds); 134a5897205SPaolo Bonzini } 135a5897205SPaolo Bonzini if (ssource->condition & G_IO_OUT) { 136a5897205SPaolo Bonzini FD_SET((SOCKET)ssource->socket, &wfds); 137a5897205SPaolo Bonzini } 138a5897205SPaolo Bonzini if (ssource->condition & G_IO_PRI) { 139a5897205SPaolo Bonzini FD_SET((SOCKET)ssource->socket, &xfds); 140a5897205SPaolo Bonzini } 141a5897205SPaolo Bonzini ssource->revents = 0; 142a5897205SPaolo Bonzini if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) { 143a5897205SPaolo Bonzini return 0; 144a5897205SPaolo Bonzini } 145a5897205SPaolo Bonzini 146a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &rfds)) { 147a5897205SPaolo Bonzini ssource->revents |= G_IO_IN; 148a5897205SPaolo Bonzini } 149a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &wfds)) { 150a5897205SPaolo Bonzini ssource->revents |= G_IO_OUT; 151a5897205SPaolo Bonzini } 152a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &xfds)) { 153a5897205SPaolo Bonzini ssource->revents |= G_IO_PRI; 154a5897205SPaolo Bonzini } 155a5897205SPaolo Bonzini 156a5897205SPaolo Bonzini return ssource->revents; 157a5897205SPaolo Bonzini } 158a5897205SPaolo Bonzini 159a5897205SPaolo Bonzini 160a5897205SPaolo Bonzini static gboolean 161a5897205SPaolo Bonzini qio_channel_socket_source_dispatch(GSource *source, 162a5897205SPaolo Bonzini GSourceFunc callback, 163a5897205SPaolo Bonzini gpointer user_data) 164a5897205SPaolo Bonzini { 165a5897205SPaolo Bonzini QIOChannelFunc func = (QIOChannelFunc)callback; 166a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 167a5897205SPaolo Bonzini 168a5897205SPaolo Bonzini return (*func)(ssource->ioc, ssource->revents, user_data); 169a5897205SPaolo Bonzini } 170a5897205SPaolo Bonzini 171a5897205SPaolo Bonzini 172a5897205SPaolo Bonzini static void 173a5897205SPaolo Bonzini qio_channel_socket_source_finalize(GSource *source) 174a5897205SPaolo Bonzini { 175a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 176a5897205SPaolo Bonzini 177a5897205SPaolo Bonzini object_unref(OBJECT(ssource->ioc)); 178a5897205SPaolo Bonzini } 179a5897205SPaolo Bonzini 180a5897205SPaolo Bonzini 181a5897205SPaolo Bonzini GSourceFuncs qio_channel_socket_source_funcs = { 182a5897205SPaolo Bonzini qio_channel_socket_source_prepare, 183a5897205SPaolo Bonzini qio_channel_socket_source_check, 184a5897205SPaolo Bonzini qio_channel_socket_source_dispatch, 185a5897205SPaolo Bonzini qio_channel_socket_source_finalize 186a5897205SPaolo Bonzini }; 187a5897205SPaolo Bonzini #endif 188a5897205SPaolo Bonzini 189a5897205SPaolo Bonzini 1901c809fa0SDaniel P. Berrange static gboolean 1911c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED, 1921c809fa0SDaniel P. Berrange gint *timeout) 1931c809fa0SDaniel P. Berrange { 1941c809fa0SDaniel P. Berrange *timeout = -1; 1951c809fa0SDaniel P. Berrange 1961c809fa0SDaniel P. Berrange return FALSE; 1971c809fa0SDaniel P. Berrange } 1981c809fa0SDaniel P. Berrange 1991c809fa0SDaniel P. Berrange 2001c809fa0SDaniel P. Berrange static gboolean 2011c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check(GSource *source) 2021c809fa0SDaniel P. Berrange { 2031c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 2041c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 2051c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 2061c809fa0SDaniel P. Berrange 2071c809fa0SDaniel P. Berrange return poll_condition & ssource->condition; 2081c809fa0SDaniel P. Berrange } 2091c809fa0SDaniel P. Berrange 2101c809fa0SDaniel P. Berrange 2111c809fa0SDaniel P. Berrange static gboolean 2121c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch(GSource *source, 2131c809fa0SDaniel P. Berrange GSourceFunc callback, 2141c809fa0SDaniel P. Berrange gpointer user_data) 2151c809fa0SDaniel P. Berrange { 2161c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 2171c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 2181c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 2191c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 2201c809fa0SDaniel P. Berrange 2211c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 2221c809fa0SDaniel P. Berrange poll_condition & ssource->condition, 2231c809fa0SDaniel P. Berrange user_data); 2241c809fa0SDaniel P. Berrange } 2251c809fa0SDaniel P. Berrange 2261c809fa0SDaniel P. Berrange 2271c809fa0SDaniel P. Berrange static void 2281c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize(GSource *source) 2291c809fa0SDaniel P. Berrange { 2301c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 2311c809fa0SDaniel P. Berrange 2321c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 2331c809fa0SDaniel P. Berrange } 2341c809fa0SDaniel P. Berrange 2351c809fa0SDaniel P. Berrange 2361c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_source_funcs = { 2371c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare, 2381c809fa0SDaniel P. Berrange qio_channel_fd_source_check, 2391c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch, 2401c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize 2411c809fa0SDaniel P. Berrange }; 2421c809fa0SDaniel P. Berrange 2431c809fa0SDaniel P. Berrange 2441c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_pair_source_funcs = { 2451c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare, 2461c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check, 2471c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch, 2481c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize 2491c809fa0SDaniel P. Berrange }; 2501c809fa0SDaniel P. Berrange 2511c809fa0SDaniel P. Berrange 2521c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_watch(QIOChannel *ioc, 2531c809fa0SDaniel P. Berrange int fd, 2541c809fa0SDaniel P. Berrange GIOCondition condition) 2551c809fa0SDaniel P. Berrange { 2561c809fa0SDaniel P. Berrange GSource *source; 2571c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource; 2581c809fa0SDaniel P. Berrange 2591c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_source_funcs, 2601c809fa0SDaniel P. Berrange sizeof(QIOChannelFDSource)); 2611c809fa0SDaniel P. Berrange ssource = (QIOChannelFDSource *)source; 2621c809fa0SDaniel P. Berrange 2631c809fa0SDaniel P. Berrange ssource->ioc = ioc; 2641c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 2651c809fa0SDaniel P. Berrange 2661c809fa0SDaniel P. Berrange ssource->condition = condition; 2671c809fa0SDaniel P. Berrange 268e560d141SPaolo Bonzini #ifdef CONFIG_WIN32 269e560d141SPaolo Bonzini ssource->fd.fd = (gint64)_get_osfhandle(fd); 270e560d141SPaolo Bonzini #else 2711c809fa0SDaniel P. Berrange ssource->fd.fd = fd; 272e560d141SPaolo Bonzini #endif 2731c809fa0SDaniel P. Berrange ssource->fd.events = condition; 2741c809fa0SDaniel P. Berrange 2751c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fd); 2761c809fa0SDaniel P. Berrange 2771c809fa0SDaniel P. Berrange return source; 2781c809fa0SDaniel P. Berrange } 2791c809fa0SDaniel P. Berrange 280b83b68a0SPaolo Bonzini #ifdef CONFIG_WIN32 281b83b68a0SPaolo Bonzini GSource *qio_channel_create_socket_watch(QIOChannel *ioc, 282b83b68a0SPaolo Bonzini int socket, 283b83b68a0SPaolo Bonzini GIOCondition condition) 284b83b68a0SPaolo Bonzini { 285a5897205SPaolo Bonzini GSource *source; 286a5897205SPaolo Bonzini QIOChannelSocketSource *ssource; 287a5897205SPaolo Bonzini 288*bf88c124SPaolo Bonzini #ifdef WIN32 289*bf88c124SPaolo Bonzini WSAEventSelect(socket, ioc->event, 290*bf88c124SPaolo Bonzini FD_READ | FD_ACCEPT | FD_CLOSE | 291*bf88c124SPaolo Bonzini FD_CONNECT | FD_WRITE | FD_OOB); 292*bf88c124SPaolo Bonzini #endif 293*bf88c124SPaolo Bonzini 294a5897205SPaolo Bonzini source = g_source_new(&qio_channel_socket_source_funcs, 295a5897205SPaolo Bonzini sizeof(QIOChannelSocketSource)); 296a5897205SPaolo Bonzini ssource = (QIOChannelSocketSource *)source; 297a5897205SPaolo Bonzini 298a5897205SPaolo Bonzini ssource->ioc = ioc; 299a5897205SPaolo Bonzini object_ref(OBJECT(ioc)); 300a5897205SPaolo Bonzini 301a5897205SPaolo Bonzini ssource->condition = condition; 302a5897205SPaolo Bonzini ssource->socket = socket; 303a5897205SPaolo Bonzini ssource->revents = 0; 304a5897205SPaolo Bonzini 305a5897205SPaolo Bonzini ssource->fd.fd = (gintptr)ioc->event; 306a5897205SPaolo Bonzini ssource->fd.events = G_IO_IN; 307a5897205SPaolo Bonzini 308a5897205SPaolo Bonzini g_source_add_poll(source, &ssource->fd); 309a5897205SPaolo Bonzini 310a5897205SPaolo Bonzini return source; 311b83b68a0SPaolo Bonzini } 312b83b68a0SPaolo Bonzini #else 313b83b68a0SPaolo Bonzini GSource *qio_channel_create_socket_watch(QIOChannel *ioc, 314b83b68a0SPaolo Bonzini int socket, 315b83b68a0SPaolo Bonzini GIOCondition condition) 316b83b68a0SPaolo Bonzini { 317b83b68a0SPaolo Bonzini return qio_channel_create_fd_watch(ioc, socket, condition); 318b83b68a0SPaolo Bonzini } 319b83b68a0SPaolo Bonzini #endif 3201c809fa0SDaniel P. Berrange 3211c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc, 3221c809fa0SDaniel P. Berrange int fdread, 3231c809fa0SDaniel P. Berrange int fdwrite, 3241c809fa0SDaniel P. Berrange GIOCondition condition) 3251c809fa0SDaniel P. Berrange { 3261c809fa0SDaniel P. Berrange GSource *source; 3271c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource; 3281c809fa0SDaniel P. Berrange 3291c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_pair_source_funcs, 3301c809fa0SDaniel P. Berrange sizeof(QIOChannelFDPairSource)); 3311c809fa0SDaniel P. Berrange ssource = (QIOChannelFDPairSource *)source; 3321c809fa0SDaniel P. Berrange 3331c809fa0SDaniel P. Berrange ssource->ioc = ioc; 3341c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 3351c809fa0SDaniel P. Berrange 3361c809fa0SDaniel P. Berrange ssource->condition = condition; 3371c809fa0SDaniel P. Berrange 338e560d141SPaolo Bonzini #ifdef CONFIG_WIN32 339e560d141SPaolo Bonzini ssource->fdread.fd = (gint64)_get_osfhandle(fdread); 340e560d141SPaolo Bonzini ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite); 341e560d141SPaolo Bonzini #else 3421c809fa0SDaniel P. Berrange ssource->fdread.fd = fdread; 3431c809fa0SDaniel P. Berrange ssource->fdwrite.fd = fdwrite; 344e560d141SPaolo Bonzini #endif 345e560d141SPaolo Bonzini 346e560d141SPaolo Bonzini ssource->fdread.events = condition & G_IO_IN; 3471c809fa0SDaniel P. Berrange ssource->fdwrite.events = condition & G_IO_OUT; 3481c809fa0SDaniel P. Berrange 3491c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdread); 3501c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdwrite); 3511c809fa0SDaniel P. Berrange 3521c809fa0SDaniel P. Berrange return source; 3531c809fa0SDaniel P. Berrange } 354