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 ssize_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 53 ssize_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 73 ssize_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 82 ssize_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 91 ssize_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 101 ssize_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 111 int 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 120 int 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 128 GSource *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 136 guint 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 156 int 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 171 void 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 182 void 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 193 off_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 209 typedef struct QIOChannelYieldData QIOChannelYieldData; 210 struct QIOChannelYieldData { 211 QIOChannel *ioc; 212 Coroutine *co; 213 }; 214 215 216 static gboolean qio_channel_yield_enter(QIOChannel *ioc, 217 GIOCondition condition, 218 gpointer opaque) 219 { 220 QIOChannelYieldData *data = opaque; 221 qemu_coroutine_enter(data->co); 222 return FALSE; 223 } 224 225 226 void 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 243 static 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 254 void 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 278 #ifdef _WIN32 279 static 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 289 static const TypeInfo qio_channel_info = { 290 .parent = TYPE_OBJECT, 291 .name = TYPE_QIO_CHANNEL, 292 .instance_size = sizeof(QIOChannel), 293 #ifdef _WIN32 294 .instance_finalize = qio_channel_finalize, 295 #endif 296 .abstract = true, 297 .class_size = sizeof(QIOChannelClass), 298 }; 299 300 301 static void qio_channel_register_types(void) 302 { 303 type_register_static(&qio_channel_info); 304 } 305 306 307 type_init(qio_channel_register_types); 308