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