2 * QEMU I/O channels watch helper APIs
4 * Copyright (c) 2015 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "io/channel-watch.h"
24 typedef struct QIOChannelFDSource QIOChannelFDSource
;
25 struct QIOChannelFDSource
{
29 GIOCondition condition
;
34 typedef struct QIOChannelSocketSource QIOChannelSocketSource
;
35 struct QIOChannelSocketSource
{
41 GIOCondition condition
;
47 typedef struct QIOChannelFDPairSource QIOChannelFDPairSource
;
48 struct QIOChannelFDPairSource
{
53 GIOCondition condition
;
58 qio_channel_fd_source_prepare(GSource
*source G_GNUC_UNUSED
,
68 qio_channel_fd_source_check(GSource
*source
)
70 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
72 return ssource
->fd
.revents
& ssource
->condition
;
77 qio_channel_fd_source_dispatch(GSource
*source
,
81 QIOChannelFunc func
= (QIOChannelFunc
)callback
;
82 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
84 return (*func
)(ssource
->ioc
,
85 ssource
->fd
.revents
& ssource
->condition
,
91 qio_channel_fd_source_finalize(GSource
*source
)
93 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
95 object_unref(OBJECT(ssource
->ioc
));
101 qio_channel_socket_source_prepare(GSource
*source G_GNUC_UNUSED
,
111 * NB, this impl only works when the socket is in non-blocking
115 qio_channel_socket_source_check(GSource
*source
)
117 static struct timeval tv0
;
119 QIOChannelSocketSource
*ssource
= (QIOChannelSocketSource
*)source
;
121 fd_set rfds
, wfds
, xfds
;
123 if (!ssource
->condition
) {
127 WSAEnumNetworkEvents(ssource
->socket
, ssource
->ioc
->event
, &ev
);
132 if (ssource
->condition
& G_IO_IN
) {
133 FD_SET((SOCKET
)ssource
->socket
, &rfds
);
135 if (ssource
->condition
& G_IO_OUT
) {
136 FD_SET((SOCKET
)ssource
->socket
, &wfds
);
138 if (ssource
->condition
& G_IO_PRI
) {
139 FD_SET((SOCKET
)ssource
->socket
, &xfds
);
141 ssource
->revents
= 0;
142 if (select(0, &rfds
, &wfds
, &xfds
, &tv0
) == 0) {
146 if (FD_ISSET(ssource
->socket
, &rfds
)) {
147 ssource
->revents
|= G_IO_IN
;
149 if (FD_ISSET(ssource
->socket
, &wfds
)) {
150 ssource
->revents
|= G_IO_OUT
;
152 if (FD_ISSET(ssource
->socket
, &xfds
)) {
153 ssource
->revents
|= G_IO_PRI
;
156 return ssource
->revents
;
161 qio_channel_socket_source_dispatch(GSource
*source
,
162 GSourceFunc callback
,
165 QIOChannelFunc func
= (QIOChannelFunc
)callback
;
166 QIOChannelSocketSource
*ssource
= (QIOChannelSocketSource
*)source
;
168 return (*func
)(ssource
->ioc
, ssource
->revents
, user_data
);
173 qio_channel_socket_source_finalize(GSource
*source
)
175 QIOChannelSocketSource
*ssource
= (QIOChannelSocketSource
*)source
;
177 object_unref(OBJECT(ssource
->ioc
));
181 GSourceFuncs qio_channel_socket_source_funcs
= {
182 qio_channel_socket_source_prepare
,
183 qio_channel_socket_source_check
,
184 qio_channel_socket_source_dispatch
,
185 qio_channel_socket_source_finalize
191 qio_channel_fd_pair_source_prepare(GSource
*source G_GNUC_UNUSED
,
201 qio_channel_fd_pair_source_check(GSource
*source
)
203 QIOChannelFDPairSource
*ssource
= (QIOChannelFDPairSource
*)source
;
204 GIOCondition poll_condition
= ssource
->fdread
.revents
|
205 ssource
->fdwrite
.revents
;
207 return poll_condition
& ssource
->condition
;
212 qio_channel_fd_pair_source_dispatch(GSource
*source
,
213 GSourceFunc callback
,
216 QIOChannelFunc func
= (QIOChannelFunc
)callback
;
217 QIOChannelFDPairSource
*ssource
= (QIOChannelFDPairSource
*)source
;
218 GIOCondition poll_condition
= ssource
->fdread
.revents
|
219 ssource
->fdwrite
.revents
;
221 return (*func
)(ssource
->ioc
,
222 poll_condition
& ssource
->condition
,
228 qio_channel_fd_pair_source_finalize(GSource
*source
)
230 QIOChannelFDPairSource
*ssource
= (QIOChannelFDPairSource
*)source
;
232 object_unref(OBJECT(ssource
->ioc
));
236 GSourceFuncs qio_channel_fd_source_funcs
= {
237 qio_channel_fd_source_prepare
,
238 qio_channel_fd_source_check
,
239 qio_channel_fd_source_dispatch
,
240 qio_channel_fd_source_finalize
244 GSourceFuncs qio_channel_fd_pair_source_funcs
= {
245 qio_channel_fd_pair_source_prepare
,
246 qio_channel_fd_pair_source_check
,
247 qio_channel_fd_pair_source_dispatch
,
248 qio_channel_fd_pair_source_finalize
252 GSource
*qio_channel_create_fd_watch(QIOChannel
*ioc
,
254 GIOCondition condition
)
257 QIOChannelFDSource
*ssource
;
259 source
= g_source_new(&qio_channel_fd_source_funcs
,
260 sizeof(QIOChannelFDSource
));
261 ssource
= (QIOChannelFDSource
*)source
;
264 object_ref(OBJECT(ioc
));
266 ssource
->condition
= condition
;
269 ssource
->fd
.fd
= (gint64
)_get_osfhandle(fd
);
273 ssource
->fd
.events
= condition
;
275 g_source_add_poll(source
, &ssource
->fd
);
281 GSource
*qio_channel_create_socket_watch(QIOChannel
*ioc
,
283 GIOCondition condition
)
286 QIOChannelSocketSource
*ssource
;
289 WSAEventSelect(socket
, ioc
->event
,
290 FD_READ
| FD_ACCEPT
| FD_CLOSE
|
291 FD_CONNECT
| FD_WRITE
| FD_OOB
);
294 source
= g_source_new(&qio_channel_socket_source_funcs
,
295 sizeof(QIOChannelSocketSource
));
296 ssource
= (QIOChannelSocketSource
*)source
;
299 object_ref(OBJECT(ioc
));
301 ssource
->condition
= condition
;
302 ssource
->socket
= socket
;
303 ssource
->revents
= 0;
305 ssource
->fd
.fd
= (gintptr
)ioc
->event
;
306 ssource
->fd
.events
= G_IO_IN
;
308 g_source_add_poll(source
, &ssource
->fd
);
313 GSource
*qio_channel_create_socket_watch(QIOChannel
*ioc
,
315 GIOCondition condition
)
317 return qio_channel_create_fd_watch(ioc
, socket
, condition
);
321 GSource
*qio_channel_create_fd_pair_watch(QIOChannel
*ioc
,
324 GIOCondition condition
)
327 QIOChannelFDPairSource
*ssource
;
329 source
= g_source_new(&qio_channel_fd_pair_source_funcs
,
330 sizeof(QIOChannelFDPairSource
));
331 ssource
= (QIOChannelFDPairSource
*)source
;
334 object_ref(OBJECT(ioc
));
336 ssource
->condition
= condition
;
339 ssource
->fdread
.fd
= (gint64
)_get_osfhandle(fdread
);
340 ssource
->fdwrite
.fd
= (gint64
)_get_osfhandle(fdwrite
);
342 ssource
->fdread
.fd
= fdread
;
343 ssource
->fdwrite
.fd
= fdwrite
;
346 ssource
->fdread
.events
= condition
& G_IO_IN
;
347 ssource
->fdwrite
.events
= condition
& G_IO_OUT
;
349 g_source_add_poll(source
, &ssource
->fdread
);
350 g_source_add_poll(source
, &ssource
->fdwrite
);