vnc: fix unalignment access in tight_pack24
[qemu/ar7.git] / io / channel.c
blob2a26c2a2c0b948be6ab015cd833efd048913c731
1 /*
2 * QEMU I/O channels
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 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.h"
23 #include "qapi/error.h"
24 #include "qemu/main-loop.h"
25 #include "qemu/iov.h"
27 bool qio_channel_has_feature(QIOChannel *ioc,
28 QIOChannelFeature feature)
30 return ioc->features & (1 << feature);
34 void qio_channel_set_feature(QIOChannel *ioc,
35 QIOChannelFeature feature)
37 ioc->features |= (1 << feature);
41 void qio_channel_set_name(QIOChannel *ioc,
42 const char *name)
44 g_free(ioc->name);
45 ioc->name = g_strdup(name);
49 ssize_t qio_channel_readv_full(QIOChannel *ioc,
50 const struct iovec *iov,
51 size_t niov,
52 int **fds,
53 size_t *nfds,
54 Error **errp)
56 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
58 if ((fds || nfds) &&
59 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
60 error_setg_errno(errp, EINVAL,
61 "Channel does not support file descriptor passing");
62 return -1;
65 return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
69 ssize_t qio_channel_writev_full(QIOChannel *ioc,
70 const struct iovec *iov,
71 size_t niov,
72 int *fds,
73 size_t nfds,
74 Error **errp)
76 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
78 if ((fds || nfds) &&
79 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
80 error_setg_errno(errp, EINVAL,
81 "Channel does not support file descriptor passing");
82 return -1;
85 return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
89 int qio_channel_readv_all_eof(QIOChannel *ioc,
90 const struct iovec *iov,
91 size_t niov,
92 Error **errp)
94 int ret = -1;
95 struct iovec *local_iov = g_new(struct iovec, niov);
96 struct iovec *local_iov_head = local_iov;
97 unsigned int nlocal_iov = niov;
98 bool partial = false;
100 nlocal_iov = iov_copy(local_iov, nlocal_iov,
101 iov, niov,
102 0, iov_size(iov, niov));
104 while (nlocal_iov > 0) {
105 ssize_t len;
106 len = qio_channel_readv(ioc, local_iov, nlocal_iov, errp);
107 if (len == QIO_CHANNEL_ERR_BLOCK) {
108 if (qemu_in_coroutine()) {
109 qio_channel_yield(ioc, G_IO_IN);
110 } else {
111 qio_channel_wait(ioc, G_IO_IN);
113 continue;
114 } else if (len < 0) {
115 goto cleanup;
116 } else if (len == 0) {
117 if (partial) {
118 error_setg(errp,
119 "Unexpected end-of-file before all bytes were read");
120 } else {
121 ret = 0;
123 goto cleanup;
126 partial = true;
127 iov_discard_front(&local_iov, &nlocal_iov, len);
130 ret = 1;
132 cleanup:
133 g_free(local_iov_head);
134 return ret;
137 int qio_channel_readv_all(QIOChannel *ioc,
138 const struct iovec *iov,
139 size_t niov,
140 Error **errp)
142 int ret = qio_channel_readv_all_eof(ioc, iov, niov, errp);
144 if (ret == 0) {
145 ret = -1;
146 error_setg(errp,
147 "Unexpected end-of-file before all bytes were read");
148 } else if (ret == 1) {
149 ret = 0;
151 return ret;
154 int qio_channel_writev_all(QIOChannel *ioc,
155 const struct iovec *iov,
156 size_t niov,
157 Error **errp)
159 int ret = -1;
160 struct iovec *local_iov = g_new(struct iovec, niov);
161 struct iovec *local_iov_head = local_iov;
162 unsigned int nlocal_iov = niov;
164 nlocal_iov = iov_copy(local_iov, nlocal_iov,
165 iov, niov,
166 0, iov_size(iov, niov));
168 while (nlocal_iov > 0) {
169 ssize_t len;
170 len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
171 if (len == QIO_CHANNEL_ERR_BLOCK) {
172 if (qemu_in_coroutine()) {
173 qio_channel_yield(ioc, G_IO_OUT);
174 } else {
175 qio_channel_wait(ioc, G_IO_OUT);
177 continue;
179 if (len < 0) {
180 goto cleanup;
183 iov_discard_front(&local_iov, &nlocal_iov, len);
186 ret = 0;
187 cleanup:
188 g_free(local_iov_head);
189 return ret;
192 ssize_t qio_channel_readv(QIOChannel *ioc,
193 const struct iovec *iov,
194 size_t niov,
195 Error **errp)
197 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
201 ssize_t qio_channel_writev(QIOChannel *ioc,
202 const struct iovec *iov,
203 size_t niov,
204 Error **errp)
206 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
210 ssize_t qio_channel_read(QIOChannel *ioc,
211 char *buf,
212 size_t buflen,
213 Error **errp)
215 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
216 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
220 ssize_t qio_channel_write(QIOChannel *ioc,
221 const char *buf,
222 size_t buflen,
223 Error **errp)
225 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
226 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
230 int qio_channel_read_all_eof(QIOChannel *ioc,
231 char *buf,
232 size_t buflen,
233 Error **errp)
235 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
236 return qio_channel_readv_all_eof(ioc, &iov, 1, errp);
240 int qio_channel_read_all(QIOChannel *ioc,
241 char *buf,
242 size_t buflen,
243 Error **errp)
245 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
246 return qio_channel_readv_all(ioc, &iov, 1, errp);
250 int qio_channel_write_all(QIOChannel *ioc,
251 const char *buf,
252 size_t buflen,
253 Error **errp)
255 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
256 return qio_channel_writev_all(ioc, &iov, 1, errp);
260 int qio_channel_set_blocking(QIOChannel *ioc,
261 bool enabled,
262 Error **errp)
264 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
265 return klass->io_set_blocking(ioc, enabled, errp);
269 int qio_channel_close(QIOChannel *ioc,
270 Error **errp)
272 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
273 return klass->io_close(ioc, errp);
277 GSource *qio_channel_create_watch(QIOChannel *ioc,
278 GIOCondition condition)
280 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
281 GSource *ret = klass->io_create_watch(ioc, condition);
283 if (ioc->name) {
284 g_source_set_name(ret, ioc->name);
287 return ret;
291 void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
292 AioContext *ctx,
293 IOHandler *io_read,
294 IOHandler *io_write,
295 void *opaque)
297 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
299 klass->io_set_aio_fd_handler(ioc, ctx, io_read, io_write, opaque);
302 guint qio_channel_add_watch_full(QIOChannel *ioc,
303 GIOCondition condition,
304 QIOChannelFunc func,
305 gpointer user_data,
306 GDestroyNotify notify,
307 GMainContext *context)
309 GSource *source;
310 guint id;
312 source = qio_channel_create_watch(ioc, condition);
314 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
316 id = g_source_attach(source, context);
317 g_source_unref(source);
319 return id;
322 guint qio_channel_add_watch(QIOChannel *ioc,
323 GIOCondition condition,
324 QIOChannelFunc func,
325 gpointer user_data,
326 GDestroyNotify notify)
328 return qio_channel_add_watch_full(ioc, condition, func,
329 user_data, notify, NULL);
332 GSource *qio_channel_add_watch_source(QIOChannel *ioc,
333 GIOCondition condition,
334 QIOChannelFunc func,
335 gpointer user_data,
336 GDestroyNotify notify,
337 GMainContext *context)
339 GSource *source;
340 guint id;
342 id = qio_channel_add_watch_full(ioc, condition, func,
343 user_data, notify, context);
344 source = g_main_context_find_source_by_id(context, id);
345 g_source_ref(source);
346 return source;
350 int qio_channel_shutdown(QIOChannel *ioc,
351 QIOChannelShutdown how,
352 Error **errp)
354 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
356 if (!klass->io_shutdown) {
357 error_setg(errp, "Data path shutdown not supported");
358 return -1;
361 return klass->io_shutdown(ioc, how, errp);
365 void qio_channel_set_delay(QIOChannel *ioc,
366 bool enabled)
368 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
370 if (klass->io_set_delay) {
371 klass->io_set_delay(ioc, enabled);
376 void qio_channel_set_cork(QIOChannel *ioc,
377 bool enabled)
379 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
381 if (klass->io_set_cork) {
382 klass->io_set_cork(ioc, enabled);
387 off_t qio_channel_io_seek(QIOChannel *ioc,
388 off_t offset,
389 int whence,
390 Error **errp)
392 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
394 if (!klass->io_seek) {
395 error_setg(errp, "Channel does not support random access");
396 return -1;
399 return klass->io_seek(ioc, offset, whence, errp);
403 static void qio_channel_restart_read(void *opaque)
405 QIOChannel *ioc = opaque;
406 Coroutine *co = ioc->read_coroutine;
408 /* Assert that aio_co_wake() reenters the coroutine directly */
409 assert(qemu_get_current_aio_context() ==
410 qemu_coroutine_get_aio_context(co));
411 aio_co_wake(co);
414 static void qio_channel_restart_write(void *opaque)
416 QIOChannel *ioc = opaque;
417 Coroutine *co = ioc->write_coroutine;
419 /* Assert that aio_co_wake() reenters the coroutine directly */
420 assert(qemu_get_current_aio_context() ==
421 qemu_coroutine_get_aio_context(co));
422 aio_co_wake(co);
425 static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
427 IOHandler *rd_handler = NULL, *wr_handler = NULL;
428 AioContext *ctx;
430 if (ioc->read_coroutine) {
431 rd_handler = qio_channel_restart_read;
433 if (ioc->write_coroutine) {
434 wr_handler = qio_channel_restart_write;
437 ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
438 qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
441 void qio_channel_attach_aio_context(QIOChannel *ioc,
442 AioContext *ctx)
444 assert(!ioc->read_coroutine);
445 assert(!ioc->write_coroutine);
446 ioc->ctx = ctx;
449 void qio_channel_detach_aio_context(QIOChannel *ioc)
451 ioc->read_coroutine = NULL;
452 ioc->write_coroutine = NULL;
453 qio_channel_set_aio_fd_handlers(ioc);
454 ioc->ctx = NULL;
457 void coroutine_fn qio_channel_yield(QIOChannel *ioc,
458 GIOCondition condition)
460 assert(qemu_in_coroutine());
461 if (condition == G_IO_IN) {
462 assert(!ioc->read_coroutine);
463 ioc->read_coroutine = qemu_coroutine_self();
464 } else if (condition == G_IO_OUT) {
465 assert(!ioc->write_coroutine);
466 ioc->write_coroutine = qemu_coroutine_self();
467 } else {
468 abort();
470 qio_channel_set_aio_fd_handlers(ioc);
471 qemu_coroutine_yield();
473 /* Allow interrupting the operation by reentering the coroutine other than
474 * through the aio_fd_handlers. */
475 if (condition == G_IO_IN && ioc->read_coroutine) {
476 ioc->read_coroutine = NULL;
477 qio_channel_set_aio_fd_handlers(ioc);
478 } else if (condition == G_IO_OUT && ioc->write_coroutine) {
479 ioc->write_coroutine = NULL;
480 qio_channel_set_aio_fd_handlers(ioc);
485 static gboolean qio_channel_wait_complete(QIOChannel *ioc,
486 GIOCondition condition,
487 gpointer opaque)
489 GMainLoop *loop = opaque;
491 g_main_loop_quit(loop);
492 return FALSE;
496 void qio_channel_wait(QIOChannel *ioc,
497 GIOCondition condition)
499 GMainContext *ctxt = g_main_context_new();
500 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
501 GSource *source;
503 source = qio_channel_create_watch(ioc, condition);
505 g_source_set_callback(source,
506 (GSourceFunc)qio_channel_wait_complete,
507 loop,
508 NULL);
510 g_source_attach(source, ctxt);
512 g_main_loop_run(loop);
514 g_source_unref(source);
515 g_main_loop_unref(loop);
516 g_main_context_unref(ctxt);
520 static void qio_channel_finalize(Object *obj)
522 QIOChannel *ioc = QIO_CHANNEL(obj);
524 g_free(ioc->name);
526 #ifdef _WIN32
527 if (ioc->event) {
528 CloseHandle(ioc->event);
530 #endif
533 static const TypeInfo qio_channel_info = {
534 .parent = TYPE_OBJECT,
535 .name = TYPE_QIO_CHANNEL,
536 .instance_size = sizeof(QIOChannel),
537 .instance_finalize = qio_channel_finalize,
538 .abstract = true,
539 .class_size = sizeof(QIOChannelClass),
543 static void qio_channel_register_types(void)
545 type_register_static(&qio_channel_info);
549 type_init(qio_channel_register_types);