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