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 33*a5897205SPaolo Bonzini #ifdef CONFIG_WIN32 34*a5897205SPaolo Bonzini typedef struct QIOChannelSocketSource QIOChannelSocketSource; 35*a5897205SPaolo Bonzini struct QIOChannelSocketSource { 36*a5897205SPaolo Bonzini GSource parent; 37*a5897205SPaolo Bonzini GPollFD fd; 38*a5897205SPaolo Bonzini QIOChannel *ioc; 39*a5897205SPaolo Bonzini SOCKET socket; 40*a5897205SPaolo Bonzini int revents; 41*a5897205SPaolo Bonzini GIOCondition condition; 42*a5897205SPaolo Bonzini }; 43*a5897205SPaolo Bonzini 44*a5897205SPaolo Bonzini #endif 45*a5897205SPaolo Bonzini 46*a5897205SPaolo 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 99*a5897205SPaolo Bonzini #ifdef CONFIG_WIN32 100*a5897205SPaolo Bonzini static gboolean 101*a5897205SPaolo Bonzini qio_channel_socket_source_prepare(GSource *source G_GNUC_UNUSED, 102*a5897205SPaolo Bonzini gint *timeout) 103*a5897205SPaolo Bonzini { 104*a5897205SPaolo Bonzini *timeout = -1; 105*a5897205SPaolo Bonzini 106*a5897205SPaolo Bonzini return FALSE; 107*a5897205SPaolo Bonzini } 108*a5897205SPaolo Bonzini 109*a5897205SPaolo Bonzini 110*a5897205SPaolo Bonzini /* 111*a5897205SPaolo Bonzini * NB, this impl only works when the socket is in non-blocking 112*a5897205SPaolo Bonzini * mode on Win32 113*a5897205SPaolo Bonzini */ 114*a5897205SPaolo Bonzini static gboolean 115*a5897205SPaolo Bonzini qio_channel_socket_source_check(GSource *source) 116*a5897205SPaolo Bonzini { 117*a5897205SPaolo Bonzini static struct timeval tv0; 118*a5897205SPaolo Bonzini 119*a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 120*a5897205SPaolo Bonzini WSANETWORKEVENTS ev; 121*a5897205SPaolo Bonzini fd_set rfds, wfds, xfds; 122*a5897205SPaolo Bonzini 123*a5897205SPaolo Bonzini if (!ssource->condition) { 124*a5897205SPaolo Bonzini return 0; 125*a5897205SPaolo Bonzini } 126*a5897205SPaolo Bonzini 127*a5897205SPaolo Bonzini WSAEnumNetworkEvents(ssource->socket, ssource->ioc->event, &ev); 128*a5897205SPaolo Bonzini 129*a5897205SPaolo Bonzini FD_ZERO(&rfds); 130*a5897205SPaolo Bonzini FD_ZERO(&wfds); 131*a5897205SPaolo Bonzini FD_ZERO(&xfds); 132*a5897205SPaolo Bonzini if (ssource->condition & G_IO_IN) { 133*a5897205SPaolo Bonzini FD_SET((SOCKET)ssource->socket, &rfds); 134*a5897205SPaolo Bonzini } 135*a5897205SPaolo Bonzini if (ssource->condition & G_IO_OUT) { 136*a5897205SPaolo Bonzini FD_SET((SOCKET)ssource->socket, &wfds); 137*a5897205SPaolo Bonzini } 138*a5897205SPaolo Bonzini if (ssource->condition & G_IO_PRI) { 139*a5897205SPaolo Bonzini FD_SET((SOCKET)ssource->socket, &xfds); 140*a5897205SPaolo Bonzini } 141*a5897205SPaolo Bonzini ssource->revents = 0; 142*a5897205SPaolo Bonzini if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) { 143*a5897205SPaolo Bonzini return 0; 144*a5897205SPaolo Bonzini } 145*a5897205SPaolo Bonzini 146*a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &rfds)) { 147*a5897205SPaolo Bonzini ssource->revents |= G_IO_IN; 148*a5897205SPaolo Bonzini } 149*a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &wfds)) { 150*a5897205SPaolo Bonzini ssource->revents |= G_IO_OUT; 151*a5897205SPaolo Bonzini } 152*a5897205SPaolo Bonzini if (FD_ISSET(ssource->socket, &xfds)) { 153*a5897205SPaolo Bonzini ssource->revents |= G_IO_PRI; 154*a5897205SPaolo Bonzini } 155*a5897205SPaolo Bonzini 156*a5897205SPaolo Bonzini return ssource->revents; 157*a5897205SPaolo Bonzini } 158*a5897205SPaolo Bonzini 159*a5897205SPaolo Bonzini 160*a5897205SPaolo Bonzini static gboolean 161*a5897205SPaolo Bonzini qio_channel_socket_source_dispatch(GSource *source, 162*a5897205SPaolo Bonzini GSourceFunc callback, 163*a5897205SPaolo Bonzini gpointer user_data) 164*a5897205SPaolo Bonzini { 165*a5897205SPaolo Bonzini QIOChannelFunc func = (QIOChannelFunc)callback; 166*a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 167*a5897205SPaolo Bonzini 168*a5897205SPaolo Bonzini return (*func)(ssource->ioc, ssource->revents, user_data); 169*a5897205SPaolo Bonzini } 170*a5897205SPaolo Bonzini 171*a5897205SPaolo Bonzini 172*a5897205SPaolo Bonzini static void 173*a5897205SPaolo Bonzini qio_channel_socket_source_finalize(GSource *source) 174*a5897205SPaolo Bonzini { 175*a5897205SPaolo Bonzini QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source; 176*a5897205SPaolo Bonzini 177*a5897205SPaolo Bonzini object_unref(OBJECT(ssource->ioc)); 178*a5897205SPaolo Bonzini } 179*a5897205SPaolo Bonzini 180*a5897205SPaolo Bonzini 181*a5897205SPaolo Bonzini GSourceFuncs qio_channel_socket_source_funcs = { 182*a5897205SPaolo Bonzini qio_channel_socket_source_prepare, 183*a5897205SPaolo Bonzini qio_channel_socket_source_check, 184*a5897205SPaolo Bonzini qio_channel_socket_source_dispatch, 185*a5897205SPaolo Bonzini qio_channel_socket_source_finalize 186*a5897205SPaolo Bonzini }; 187*a5897205SPaolo Bonzini #endif 188*a5897205SPaolo Bonzini 189*a5897205SPaolo 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 { 285*a5897205SPaolo Bonzini GSource *source; 286*a5897205SPaolo Bonzini QIOChannelSocketSource *ssource; 287*a5897205SPaolo Bonzini 288*a5897205SPaolo Bonzini source = g_source_new(&qio_channel_socket_source_funcs, 289*a5897205SPaolo Bonzini sizeof(QIOChannelSocketSource)); 290*a5897205SPaolo Bonzini ssource = (QIOChannelSocketSource *)source; 291*a5897205SPaolo Bonzini 292*a5897205SPaolo Bonzini ssource->ioc = ioc; 293*a5897205SPaolo Bonzini object_ref(OBJECT(ioc)); 294*a5897205SPaolo Bonzini 295*a5897205SPaolo Bonzini ssource->condition = condition; 296*a5897205SPaolo Bonzini ssource->socket = socket; 297*a5897205SPaolo Bonzini ssource->revents = 0; 298*a5897205SPaolo Bonzini 299*a5897205SPaolo Bonzini ssource->fd.fd = (gintptr)ioc->event; 300*a5897205SPaolo Bonzini ssource->fd.events = G_IO_IN; 301*a5897205SPaolo Bonzini 302*a5897205SPaolo Bonzini g_source_add_poll(source, &ssource->fd); 303*a5897205SPaolo Bonzini 304*a5897205SPaolo 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