1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "chardev/char.h" 27 #include "io/channel-socket.h" 28 #include "qapi/error.h" 29 #include "qemu/module.h" 30 #include "qemu/option.h" 31 32 #include "chardev/char-io.h" 33 34 /***********************************************************/ 35 /* UDP Net console */ 36 37 typedef struct { 38 Chardev parent; 39 QIOChannel *ioc; 40 uint8_t buf[CHR_READ_BUF_LEN]; 41 int bufcnt; 42 int bufptr; 43 int max_size; 44 } UdpChardev; 45 46 #define UDP_CHARDEV(obj) OBJECT_CHECK(UdpChardev, (obj), TYPE_CHARDEV_UDP) 47 48 /* Called with chr_write_lock held. */ 49 static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len) 50 { 51 UdpChardev *s = UDP_CHARDEV(chr); 52 53 return qio_channel_write( 54 s->ioc, (const char *)buf, len, NULL); 55 } 56 57 static void udp_chr_flush_buffer(UdpChardev *s) 58 { 59 Chardev *chr = CHARDEV(s); 60 61 while (s->max_size > 0 && s->bufptr < s->bufcnt) { 62 int n = MIN(s->max_size, s->bufcnt - s->bufptr); 63 qemu_chr_be_write(chr, &s->buf[s->bufptr], n); 64 s->bufptr += n; 65 s->max_size = qemu_chr_be_can_write(chr); 66 } 67 } 68 69 static int udp_chr_read_poll(void *opaque) 70 { 71 Chardev *chr = CHARDEV(opaque); 72 UdpChardev *s = UDP_CHARDEV(opaque); 73 74 s->max_size = qemu_chr_be_can_write(chr); 75 76 /* If there were any stray characters in the queue process them 77 * first 78 */ 79 udp_chr_flush_buffer(s); 80 81 return s->max_size; 82 } 83 84 static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque) 85 { 86 Chardev *chr = CHARDEV(opaque); 87 UdpChardev *s = UDP_CHARDEV(opaque); 88 ssize_t ret; 89 90 if (s->max_size == 0) { 91 return TRUE; 92 } 93 ret = qio_channel_read( 94 s->ioc, (char *)s->buf, sizeof(s->buf), NULL); 95 if (ret <= 0) { 96 remove_fd_in_watch(chr); 97 return FALSE; 98 } 99 s->bufcnt = ret; 100 s->bufptr = 0; 101 udp_chr_flush_buffer(s); 102 103 return TRUE; 104 } 105 106 static void udp_chr_update_read_handler(Chardev *chr) 107 { 108 UdpChardev *s = UDP_CHARDEV(chr); 109 110 remove_fd_in_watch(chr); 111 if (s->ioc) { 112 chr->gsource = io_add_watch_poll(chr, s->ioc, 113 udp_chr_read_poll, 114 udp_chr_read, chr, 115 chr->gcontext); 116 } 117 } 118 119 static void char_udp_finalize(Object *obj) 120 { 121 Chardev *chr = CHARDEV(obj); 122 UdpChardev *s = UDP_CHARDEV(obj); 123 124 remove_fd_in_watch(chr); 125 if (s->ioc) { 126 object_unref(OBJECT(s->ioc)); 127 } 128 qemu_chr_be_event(chr, CHR_EVENT_CLOSED); 129 } 130 131 static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend, 132 Error **errp) 133 { 134 const char *host = qemu_opt_get(opts, "host"); 135 const char *port = qemu_opt_get(opts, "port"); 136 const char *localaddr = qemu_opt_get(opts, "localaddr"); 137 const char *localport = qemu_opt_get(opts, "localport"); 138 bool has_local = false; 139 SocketAddressLegacy *addr; 140 ChardevUdp *udp; 141 142 backend->type = CHARDEV_BACKEND_KIND_UDP; 143 if (host == NULL || strlen(host) == 0) { 144 host = "localhost"; 145 } 146 if (port == NULL || strlen(port) == 0) { 147 error_setg(errp, "chardev: udp: remote port not specified"); 148 return; 149 } 150 if (localport == NULL || strlen(localport) == 0) { 151 localport = "0"; 152 } else { 153 has_local = true; 154 } 155 if (localaddr == NULL || strlen(localaddr) == 0) { 156 localaddr = ""; 157 } else { 158 has_local = true; 159 } 160 161 udp = backend->u.udp.data = g_new0(ChardevUdp, 1); 162 qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp)); 163 164 addr = g_new0(SocketAddressLegacy, 1); 165 addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; 166 addr->u.inet.data = g_new(InetSocketAddress, 1); 167 *addr->u.inet.data = (InetSocketAddress) { 168 .host = g_strdup(host), 169 .port = g_strdup(port), 170 .has_ipv4 = qemu_opt_get(opts, "ipv4"), 171 .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0), 172 .has_ipv6 = qemu_opt_get(opts, "ipv6"), 173 .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0), 174 }; 175 udp->remote = addr; 176 177 if (has_local) { 178 udp->has_local = true; 179 addr = g_new0(SocketAddressLegacy, 1); 180 addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; 181 addr->u.inet.data = g_new(InetSocketAddress, 1); 182 *addr->u.inet.data = (InetSocketAddress) { 183 .host = g_strdup(localaddr), 184 .port = g_strdup(localport), 185 }; 186 udp->local = addr; 187 } 188 } 189 190 static void qmp_chardev_open_udp(Chardev *chr, 191 ChardevBackend *backend, 192 bool *be_opened, 193 Error **errp) 194 { 195 ChardevUdp *udp = backend->u.udp.data; 196 SocketAddress *local_addr = socket_address_flatten(udp->local); 197 SocketAddress *remote_addr = socket_address_flatten(udp->remote); 198 QIOChannelSocket *sioc = qio_channel_socket_new(); 199 char *name; 200 UdpChardev *s = UDP_CHARDEV(chr); 201 int ret; 202 203 ret = qio_channel_socket_dgram_sync(sioc, local_addr, remote_addr, errp); 204 qapi_free_SocketAddress(local_addr); 205 qapi_free_SocketAddress(remote_addr); 206 if (ret < 0) { 207 object_unref(OBJECT(sioc)); 208 return; 209 } 210 211 name = g_strdup_printf("chardev-udp-%s", chr->label); 212 qio_channel_set_name(QIO_CHANNEL(sioc), name); 213 g_free(name); 214 215 s->ioc = QIO_CHANNEL(sioc); 216 /* be isn't opened until we get a connection */ 217 *be_opened = false; 218 } 219 220 static void char_udp_class_init(ObjectClass *oc, void *data) 221 { 222 ChardevClass *cc = CHARDEV_CLASS(oc); 223 224 cc->parse = qemu_chr_parse_udp; 225 cc->open = qmp_chardev_open_udp; 226 cc->chr_write = udp_chr_write; 227 cc->chr_update_read_handler = udp_chr_update_read_handler; 228 } 229 230 static const TypeInfo char_udp_type_info = { 231 .name = TYPE_CHARDEV_UDP, 232 .parent = TYPE_CHARDEV, 233 .instance_size = sizeof(UdpChardev), 234 .instance_finalize = char_udp_finalize, 235 .class_init = char_udp_class_init, 236 }; 237 238 static void register_types(void) 239 { 240 type_register_static(&char_udp_type_info); 241 } 242 243 type_init(register_types); 244