]> git.proxmox.com Git - mirror_qemu.git/blame - io/channel.c
include/qemu/osdep.h: Don't include qapi/error.h
[mirror_qemu.git] / io / channel.c
CommitLineData
666a3af9
DB
1/*
2 * QEMU I/O channels
3 *
4 * Copyright (c) 2015 Red Hat, Inc.
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
cae9fc56 21#include "qemu/osdep.h"
666a3af9 22#include "io/channel.h"
da34e65c 23#include "qapi/error.h"
666a3af9
DB
24#include "qemu/coroutine.h"
25
26bool qio_channel_has_feature(QIOChannel *ioc,
27 QIOChannelFeature feature)
28{
29 return ioc->features & (1 << feature);
30}
31
32
33ssize_t qio_channel_readv_full(QIOChannel *ioc,
34 const struct iovec *iov,
35 size_t niov,
36 int **fds,
37 size_t *nfds,
38 Error **errp)
39{
40 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
41
42 if ((fds || nfds) &&
43 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) {
44 error_setg_errno(errp, EINVAL,
45 "Channel does not support file descriptor passing");
46 return -1;
47 }
48
49 return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
50}
51
52
53ssize_t qio_channel_writev_full(QIOChannel *ioc,
54 const struct iovec *iov,
55 size_t niov,
56 int *fds,
57 size_t nfds,
58 Error **errp)
59{
60 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
61
62 if ((fds || nfds) &&
63 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) {
64 error_setg_errno(errp, EINVAL,
65 "Channel does not support file descriptor passing");
66 return -1;
67 }
68
69 return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
70}
71
72
73ssize_t qio_channel_readv(QIOChannel *ioc,
74 const struct iovec *iov,
75 size_t niov,
76 Error **errp)
77{
78 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
79}
80
81
82ssize_t qio_channel_writev(QIOChannel *ioc,
83 const struct iovec *iov,
84 size_t niov,
85 Error **errp)
86{
87 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
88}
89
90
91ssize_t qio_channel_read(QIOChannel *ioc,
92 char *buf,
93 size_t buflen,
94 Error **errp)
95{
96 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
97 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
98}
99
100
101ssize_t qio_channel_write(QIOChannel *ioc,
102 const char *buf,
103 size_t buflen,
104 Error **errp)
105{
106 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
107 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
108}
109
110
111int qio_channel_set_blocking(QIOChannel *ioc,
112 bool enabled,
113 Error **errp)
114{
115 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
116 return klass->io_set_blocking(ioc, enabled, errp);
117}
118
119
120int qio_channel_close(QIOChannel *ioc,
121 Error **errp)
122{
123 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
124 return klass->io_close(ioc, errp);
125}
126
127
128GSource *qio_channel_create_watch(QIOChannel *ioc,
129 GIOCondition condition)
130{
131 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
132 return klass->io_create_watch(ioc, condition);
133}
134
135
136guint qio_channel_add_watch(QIOChannel *ioc,
137 GIOCondition condition,
138 QIOChannelFunc func,
139 gpointer user_data,
140 GDestroyNotify notify)
141{
142 GSource *source;
143 guint id;
144
145 source = qio_channel_create_watch(ioc, condition);
146
147 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
148
149 id = g_source_attach(source, NULL);
150 g_source_unref(source);
151
152 return id;
153}
154
155
156int qio_channel_shutdown(QIOChannel *ioc,
157 QIOChannelShutdown how,
158 Error **errp)
159{
160 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
161
162 if (!klass->io_shutdown) {
163 error_setg(errp, "Data path shutdown not supported");
164 return -1;
165 }
166
167 return klass->io_shutdown(ioc, how, errp);
168}
169
170
171void qio_channel_set_delay(QIOChannel *ioc,
172 bool enabled)
173{
174 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
175
176 if (klass->io_set_delay) {
177 klass->io_set_delay(ioc, enabled);
178 }
179}
180
181
182void qio_channel_set_cork(QIOChannel *ioc,
183 bool enabled)
184{
185 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
186
187 if (klass->io_set_cork) {
188 klass->io_set_cork(ioc, enabled);
189 }
190}
191
192
193off_t qio_channel_io_seek(QIOChannel *ioc,
194 off_t offset,
195 int whence,
196 Error **errp)
197{
198 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
199
200 if (!klass->io_seek) {
201 error_setg(errp, "Channel does not support random access");
202 return -1;
203 }
204
205 return klass->io_seek(ioc, offset, whence, errp);
206}
207
208
209typedef struct QIOChannelYieldData QIOChannelYieldData;
210struct QIOChannelYieldData {
211 QIOChannel *ioc;
212 Coroutine *co;
213};
214
215
216static gboolean qio_channel_yield_enter(QIOChannel *ioc,
217 GIOCondition condition,
218 gpointer opaque)
219{
220 QIOChannelYieldData *data = opaque;
221 qemu_coroutine_enter(data->co, NULL);
222 return FALSE;
223}
224
225
226void coroutine_fn qio_channel_yield(QIOChannel *ioc,
227 GIOCondition condition)
228{
229 QIOChannelYieldData data;
230
231 assert(qemu_in_coroutine());
232 data.ioc = ioc;
233 data.co = qemu_coroutine_self();
234 qio_channel_add_watch(ioc,
235 condition,
236 qio_channel_yield_enter,
237 &data,
238 NULL);
239 qemu_coroutine_yield();
240}
241
242
243static gboolean qio_channel_wait_complete(QIOChannel *ioc,
244 GIOCondition condition,
245 gpointer opaque)
246{
247 GMainLoop *loop = opaque;
248
249 g_main_loop_quit(loop);
250 return FALSE;
251}
252
253
254void qio_channel_wait(QIOChannel *ioc,
255 GIOCondition condition)
256{
257 GMainContext *ctxt = g_main_context_new();
258 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
259 GSource *source;
260
261 source = qio_channel_create_watch(ioc, condition);
262
263 g_source_set_callback(source,
264 (GSourceFunc)qio_channel_wait_complete,
265 loop,
266 NULL);
267
268 g_source_attach(source, ctxt);
269
270 g_main_loop_run(loop);
271
272 g_source_unref(source);
273 g_main_loop_unref(loop);
274 g_main_context_unref(ctxt);
275}
276
277
a5897205
PB
278#ifdef _WIN32
279static void qio_channel_finalize(Object *obj)
280{
281 QIOChannel *ioc = QIO_CHANNEL(obj);
282
283 if (ioc->event) {
284 CloseHandle(ioc->event);
285 }
286}
287#endif
288
666a3af9
DB
289static const TypeInfo qio_channel_info = {
290 .parent = TYPE_OBJECT,
291 .name = TYPE_QIO_CHANNEL,
292 .instance_size = sizeof(QIOChannel),
a5897205
PB
293#ifdef _WIN32
294 .instance_finalize = qio_channel_finalize,
295#endif
666a3af9
DB
296 .abstract = true,
297 .class_size = sizeof(QIOChannelClass),
298};
299
300
301static void qio_channel_register_types(void)
302{
303 type_register_static(&qio_channel_info);
304}
305
306
307type_init(qio_channel_register_types);