pci-bridge/i82801b11: clear bridge registers on platform reset
[qemu/ar7.git] / chardev / char-socket.c
bloba340af6cd3a053345fd2e47f58091cf00b4e4ac6
1 /*
2 * QEMU System Emulator
4 * Copyright (c) 2003-2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu/osdep.h"
25 #include "chardev/char.h"
26 #include "io/channel-socket.h"
27 #include "io/channel-tls.h"
28 #include "io/net-listener.h"
29 #include "qemu/error-report.h"
30 #include "qapi/error.h"
31 #include "qapi/clone-visitor.h"
33 #include "chardev/char-io.h"
35 /***********************************************************/
36 /* TCP Net console */
38 #define TCP_MAX_FDS 16
40 typedef struct {
41 Chardev parent;
42 QIOChannel *ioc; /* Client I/O channel */
43 QIOChannelSocket *sioc; /* Client master channel */
44 QIONetListener *listener;
45 GSource *hup_source;
46 QCryptoTLSCreds *tls_creds;
47 int connected;
48 int max_size;
49 int do_telnetopt;
50 int do_nodelay;
51 int *read_msgfds;
52 size_t read_msgfds_num;
53 int *write_msgfds;
54 size_t write_msgfds_num;
56 SocketAddress *addr;
57 bool is_listen;
58 bool is_telnet;
59 bool is_tn3270;
61 GSource *reconnect_timer;
62 int64_t reconnect_time;
63 bool connect_err_reported;
64 } SocketChardev;
66 #define SOCKET_CHARDEV(obj) \
67 OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
69 static gboolean socket_reconnect_timeout(gpointer opaque);
71 static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
73 if (s->reconnect_timer) {
74 g_source_destroy(s->reconnect_timer);
75 g_source_unref(s->reconnect_timer);
76 s->reconnect_timer = NULL;
80 static void qemu_chr_socket_restart_timer(Chardev *chr)
82 SocketChardev *s = SOCKET_CHARDEV(chr);
83 char *name;
85 assert(s->connected == 0);
86 name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
87 s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
88 s->reconnect_time * 1000,
89 socket_reconnect_timeout,
90 chr);
91 g_source_set_name(s->reconnect_timer, name);
92 g_free(name);
95 static void check_report_connect_error(Chardev *chr,
96 Error *err)
98 SocketChardev *s = SOCKET_CHARDEV(chr);
100 if (!s->connect_err_reported) {
101 error_report("Unable to connect character device %s: %s",
102 chr->label, error_get_pretty(err));
103 s->connect_err_reported = true;
105 qemu_chr_socket_restart_timer(chr);
108 static void tcp_chr_accept(QIONetListener *listener,
109 QIOChannelSocket *cioc,
110 void *opaque);
112 static int tcp_chr_read_poll(void *opaque);
113 static void tcp_chr_disconnect(Chardev *chr);
115 /* Called with chr_write_lock held. */
116 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
118 SocketChardev *s = SOCKET_CHARDEV(chr);
120 if (s->connected) {
121 int ret = io_channel_send_full(s->ioc, buf, len,
122 s->write_msgfds,
123 s->write_msgfds_num);
125 /* free the written msgfds, no matter what */
126 if (s->write_msgfds_num) {
127 g_free(s->write_msgfds);
128 s->write_msgfds = 0;
129 s->write_msgfds_num = 0;
132 if (ret < 0 && errno != EAGAIN) {
133 if (tcp_chr_read_poll(chr) <= 0) {
134 tcp_chr_disconnect(chr);
135 return len;
136 } /* else let the read handler finish it properly */
139 return ret;
140 } else {
141 /* XXX: indicate an error ? */
142 return len;
146 static int tcp_chr_read_poll(void *opaque)
148 Chardev *chr = CHARDEV(opaque);
149 SocketChardev *s = SOCKET_CHARDEV(opaque);
150 if (!s->connected) {
151 return 0;
153 s->max_size = qemu_chr_be_can_write(chr);
154 return s->max_size;
157 static void tcp_chr_process_IAC_bytes(Chardev *chr,
158 SocketChardev *s,
159 uint8_t *buf, int *size)
161 /* Handle any telnet or tn3270 client's basic IAC options.
162 * For telnet options, it satisfies char by char mode with no echo.
163 * For tn3270 options, it satisfies binary mode with EOR.
164 * All IAC options will be removed from the buf and the do_opt
165 * pointer will be used to track the state of the width of the
166 * IAC information.
168 * RFC854: "All TELNET commands consist of at least a two byte sequence.
169 * The commands dealing with option negotiation are three byte sequences,
170 * the third byte being the code for the option referenced."
171 * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
172 * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
173 * for tn3270.
174 * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
175 * session, and NOP and IP need to be done later.
178 int i;
179 int j = 0;
181 for (i = 0; i < *size; i++) {
182 if (s->do_telnetopt > 1) {
183 if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
184 /* Double IAC means send an IAC */
185 if (j != i) {
186 buf[j] = buf[i];
188 j++;
189 s->do_telnetopt = 1;
190 } else {
191 if ((unsigned char)buf[i] == IAC_BREAK
192 && s->do_telnetopt == 2) {
193 /* Handle IAC break commands by sending a serial break */
194 qemu_chr_be_event(chr, CHR_EVENT_BREAK);
195 s->do_telnetopt++;
196 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
197 || (unsigned char)buf[i] == IAC_SB
198 || (unsigned char)buf[i] == IAC_SE)
199 && s->do_telnetopt == 2) {
200 buf[j++] = IAC;
201 buf[j++] = buf[i];
202 s->do_telnetopt++;
203 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
204 || (unsigned char)buf[i] == IAC_NOP)
205 && s->do_telnetopt == 2) {
206 /* TODO: IP and NOP need to be implemented later. */
207 s->do_telnetopt++;
209 s->do_telnetopt++;
211 if (s->do_telnetopt >= 4) {
212 s->do_telnetopt = 1;
214 } else {
215 if ((unsigned char)buf[i] == IAC) {
216 s->do_telnetopt = 2;
217 } else {
218 if (j != i) {
219 buf[j] = buf[i];
221 j++;
225 *size = j;
228 static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
230 SocketChardev *s = SOCKET_CHARDEV(chr);
232 int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
234 assert(num <= TCP_MAX_FDS);
236 if (to_copy) {
237 int i;
239 memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
241 /* Close unused fds */
242 for (i = to_copy; i < s->read_msgfds_num; i++) {
243 close(s->read_msgfds[i]);
246 g_free(s->read_msgfds);
247 s->read_msgfds = 0;
248 s->read_msgfds_num = 0;
251 return to_copy;
254 static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
256 SocketChardev *s = SOCKET_CHARDEV(chr);
258 /* clear old pending fd array */
259 g_free(s->write_msgfds);
260 s->write_msgfds = NULL;
261 s->write_msgfds_num = 0;
263 if (!s->connected ||
264 !qio_channel_has_feature(s->ioc,
265 QIO_CHANNEL_FEATURE_FD_PASS)) {
266 return -1;
269 if (num) {
270 s->write_msgfds = g_new(int, num);
271 memcpy(s->write_msgfds, fds, num * sizeof(int));
274 s->write_msgfds_num = num;
276 return 0;
279 static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
281 SocketChardev *s = SOCKET_CHARDEV(chr);
282 struct iovec iov = { .iov_base = buf, .iov_len = len };
283 int ret;
284 size_t i;
285 int *msgfds = NULL;
286 size_t msgfds_num = 0;
288 if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
289 ret = qio_channel_readv_full(s->ioc, &iov, 1,
290 &msgfds, &msgfds_num,
291 NULL);
292 } else {
293 ret = qio_channel_readv_full(s->ioc, &iov, 1,
294 NULL, NULL,
295 NULL);
298 if (ret == QIO_CHANNEL_ERR_BLOCK) {
299 errno = EAGAIN;
300 ret = -1;
301 } else if (ret == -1) {
302 errno = EIO;
305 if (msgfds_num) {
306 /* close and clean read_msgfds */
307 for (i = 0; i < s->read_msgfds_num; i++) {
308 close(s->read_msgfds[i]);
311 if (s->read_msgfds_num) {
312 g_free(s->read_msgfds);
315 s->read_msgfds = msgfds;
316 s->read_msgfds_num = msgfds_num;
319 for (i = 0; i < s->read_msgfds_num; i++) {
320 int fd = s->read_msgfds[i];
321 if (fd < 0) {
322 continue;
325 /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
326 qemu_set_block(fd);
328 #ifndef MSG_CMSG_CLOEXEC
329 qemu_set_cloexec(fd);
330 #endif
333 return ret;
336 static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
338 SocketChardev *s = SOCKET_CHARDEV(chr);
339 return qio_channel_create_watch(s->ioc, cond);
342 static void tcp_chr_free_connection(Chardev *chr)
344 SocketChardev *s = SOCKET_CHARDEV(chr);
345 int i;
347 if (s->read_msgfds_num) {
348 for (i = 0; i < s->read_msgfds_num; i++) {
349 close(s->read_msgfds[i]);
351 g_free(s->read_msgfds);
352 s->read_msgfds = NULL;
353 s->read_msgfds_num = 0;
356 if (s->hup_source != NULL) {
357 g_source_destroy(s->hup_source);
358 g_source_unref(s->hup_source);
359 s->hup_source = NULL;
362 tcp_set_msgfds(chr, NULL, 0);
363 remove_fd_in_watch(chr);
364 object_unref(OBJECT(s->sioc));
365 s->sioc = NULL;
366 object_unref(OBJECT(s->ioc));
367 s->ioc = NULL;
368 g_free(chr->filename);
369 chr->filename = NULL;
370 s->connected = 0;
373 static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
374 bool is_listen, bool is_telnet)
376 switch (addr->type) {
377 case SOCKET_ADDRESS_TYPE_INET:
378 return g_strdup_printf("%s%s:%s:%s%s", prefix,
379 is_telnet ? "telnet" : "tcp",
380 addr->u.inet.host,
381 addr->u.inet.port,
382 is_listen ? ",server" : "");
383 break;
384 case SOCKET_ADDRESS_TYPE_UNIX:
385 return g_strdup_printf("%sunix:%s%s", prefix,
386 addr->u.q_unix.path,
387 is_listen ? ",server" : "");
388 break;
389 case SOCKET_ADDRESS_TYPE_FD:
390 return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.str,
391 is_listen ? ",server" : "");
392 break;
393 case SOCKET_ADDRESS_TYPE_VSOCK:
394 return g_strdup_printf("%svsock:%s:%s", prefix,
395 addr->u.vsock.cid,
396 addr->u.vsock.port);
397 default:
398 abort();
402 static void update_disconnected_filename(SocketChardev *s)
404 Chardev *chr = CHARDEV(s);
406 g_free(chr->filename);
407 chr->filename = SocketAddress_to_str("disconnected:", s->addr,
408 s->is_listen, s->is_telnet);
411 /* NB may be called even if tcp_chr_connect has not been
412 * reached, due to TLS or telnet initialization failure,
413 * so can *not* assume s->connected == true
415 static void tcp_chr_disconnect(Chardev *chr)
417 SocketChardev *s = SOCKET_CHARDEV(chr);
418 bool emit_close = s->connected;
420 tcp_chr_free_connection(chr);
422 if (s->listener) {
423 qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
424 chr, NULL);
426 update_disconnected_filename(s);
427 if (emit_close) {
428 qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
430 if (s->reconnect_time) {
431 qemu_chr_socket_restart_timer(chr);
435 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
437 Chardev *chr = CHARDEV(opaque);
438 SocketChardev *s = SOCKET_CHARDEV(opaque);
439 uint8_t buf[CHR_READ_BUF_LEN];
440 int len, size;
442 if (!s->connected || s->max_size <= 0) {
443 return TRUE;
445 len = sizeof(buf);
446 if (len > s->max_size) {
447 len = s->max_size;
449 size = tcp_chr_recv(chr, (void *)buf, len);
450 if (size == 0 || size == -1) {
451 /* connection closed */
452 tcp_chr_disconnect(chr);
453 } else if (size > 0) {
454 if (s->do_telnetopt) {
455 tcp_chr_process_IAC_bytes(chr, s, buf, &size);
457 if (size > 0) {
458 qemu_chr_be_write(chr, buf, size);
462 return TRUE;
465 static gboolean tcp_chr_hup(QIOChannel *channel,
466 GIOCondition cond,
467 void *opaque)
469 Chardev *chr = CHARDEV(opaque);
470 tcp_chr_disconnect(chr);
471 return G_SOURCE_REMOVE;
474 static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
476 SocketChardev *s = SOCKET_CHARDEV(chr);
477 int size;
479 if (!s->connected) {
480 return 0;
483 qio_channel_set_blocking(s->ioc, true, NULL);
484 size = tcp_chr_recv(chr, (void *) buf, len);
485 qio_channel_set_blocking(s->ioc, false, NULL);
486 if (size == 0) {
487 /* connection closed */
488 tcp_chr_disconnect(chr);
491 return size;
494 static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
495 struct sockaddr_storage *ps, socklen_t ps_len,
496 bool is_listen, bool is_telnet)
498 char shost[NI_MAXHOST], sserv[NI_MAXSERV];
499 char phost[NI_MAXHOST], pserv[NI_MAXSERV];
500 const char *left = "", *right = "";
502 switch (ss->ss_family) {
503 #ifndef _WIN32
504 case AF_UNIX:
505 return g_strdup_printf("unix:%s%s",
506 ((struct sockaddr_un *)(ss))->sun_path,
507 is_listen ? ",server" : "");
508 #endif
509 case AF_INET6:
510 left = "[";
511 right = "]";
512 /* fall through */
513 case AF_INET:
514 getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
515 sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
516 getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
517 pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
518 return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
519 is_telnet ? "telnet" : "tcp",
520 left, shost, right, sserv,
521 is_listen ? ",server" : "",
522 left, phost, right, pserv);
524 default:
525 return g_strdup_printf("unknown");
529 static void tcp_chr_connect(void *opaque)
531 Chardev *chr = CHARDEV(opaque);
532 SocketChardev *s = SOCKET_CHARDEV(opaque);
534 g_free(chr->filename);
535 chr->filename = sockaddr_to_str(
536 &s->sioc->localAddr, s->sioc->localAddrLen,
537 &s->sioc->remoteAddr, s->sioc->remoteAddrLen,
538 s->is_listen, s->is_telnet);
540 s->connected = 1;
541 if (s->ioc) {
542 chr->gsource = io_add_watch_poll(chr, s->ioc,
543 tcp_chr_read_poll,
544 tcp_chr_read,
545 chr, chr->gcontext);
548 s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
549 g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
550 chr, NULL);
551 g_source_attach(s->hup_source, chr->gcontext);
553 qemu_chr_be_event(chr, CHR_EVENT_OPENED);
556 static void tcp_chr_update_read_handler(Chardev *chr)
558 SocketChardev *s = SOCKET_CHARDEV(chr);
560 if (!s->connected) {
561 return;
564 remove_fd_in_watch(chr);
565 if (s->ioc) {
566 chr->gsource = io_add_watch_poll(chr, s->ioc,
567 tcp_chr_read_poll,
568 tcp_chr_read, chr,
569 chr->gcontext);
573 typedef struct {
574 Chardev *chr;
575 char buf[21];
576 size_t buflen;
577 } TCPChardevTelnetInit;
579 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
580 GIOCondition cond G_GNUC_UNUSED,
581 gpointer user_data)
583 TCPChardevTelnetInit *init = user_data;
584 ssize_t ret;
586 ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
587 if (ret < 0) {
588 if (ret == QIO_CHANNEL_ERR_BLOCK) {
589 ret = 0;
590 } else {
591 tcp_chr_disconnect(init->chr);
592 return FALSE;
595 init->buflen -= ret;
597 if (init->buflen == 0) {
598 tcp_chr_connect(init->chr);
599 return FALSE;
602 memmove(init->buf, init->buf + ret, init->buflen);
604 return TRUE;
607 static void tcp_chr_telnet_init(Chardev *chr)
609 SocketChardev *s = SOCKET_CHARDEV(chr);
610 TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
611 size_t n = 0;
613 #define IACSET(x, a, b, c) \
614 do { \
615 x[n++] = a; \
616 x[n++] = b; \
617 x[n++] = c; \
618 } while (0)
620 init->chr = chr;
621 if (!s->is_tn3270) {
622 init->buflen = 12;
623 /* Prep the telnet negotion to put telnet in binary,
624 * no echo, single char mode */
625 IACSET(init->buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */
626 IACSET(init->buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */
627 IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */
628 IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */
629 } else {
630 init->buflen = 21;
631 /* Prep the TN3270 negotion based on RFC1576 */
632 IACSET(init->buf, 0xff, 0xfd, 0x19); /* IAC DO EOR */
633 IACSET(init->buf, 0xff, 0xfb, 0x19); /* IAC WILL EOR */
634 IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO BINARY */
635 IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL BINARY */
636 IACSET(init->buf, 0xff, 0xfd, 0x18); /* IAC DO TERMINAL TYPE */
637 IACSET(init->buf, 0xff, 0xfa, 0x18); /* IAC SB TERMINAL TYPE */
638 IACSET(init->buf, 0x01, 0xff, 0xf0); /* SEND IAC SE */
641 #undef IACSET
643 qio_channel_add_watch(
644 s->ioc, G_IO_OUT,
645 tcp_chr_telnet_init_io,
646 init, NULL);
650 static void tcp_chr_tls_handshake(QIOTask *task,
651 gpointer user_data)
653 Chardev *chr = user_data;
654 SocketChardev *s = user_data;
656 if (qio_task_propagate_error(task, NULL)) {
657 tcp_chr_disconnect(chr);
658 } else {
659 /* tn3270 does not support TLS yet */
660 if (s->do_telnetopt && !s->is_tn3270) {
661 tcp_chr_telnet_init(chr);
662 } else {
663 tcp_chr_connect(chr);
669 static void tcp_chr_tls_init(Chardev *chr)
671 SocketChardev *s = SOCKET_CHARDEV(chr);
672 QIOChannelTLS *tioc;
673 Error *err = NULL;
674 gchar *name;
676 if (s->is_listen) {
677 tioc = qio_channel_tls_new_server(
678 s->ioc, s->tls_creds,
679 NULL, /* XXX Use an ACL */
680 &err);
681 } else {
682 tioc = qio_channel_tls_new_client(
683 s->ioc, s->tls_creds,
684 s->addr->u.inet.host,
685 &err);
687 if (tioc == NULL) {
688 error_free(err);
689 tcp_chr_disconnect(chr);
690 return;
692 name = g_strdup_printf("chardev-tls-%s-%s",
693 s->is_listen ? "server" : "client",
694 chr->label);
695 qio_channel_set_name(QIO_CHANNEL(tioc), name);
696 g_free(name);
697 object_unref(OBJECT(s->ioc));
698 s->ioc = QIO_CHANNEL(tioc);
700 qio_channel_tls_handshake(tioc,
701 tcp_chr_tls_handshake,
702 chr,
703 NULL);
707 static void tcp_chr_set_client_ioc_name(Chardev *chr,
708 QIOChannelSocket *sioc)
710 SocketChardev *s = SOCKET_CHARDEV(chr);
711 char *name;
712 name = g_strdup_printf("chardev-tcp-%s-%s",
713 s->is_listen ? "server" : "client",
714 chr->label);
715 qio_channel_set_name(QIO_CHANNEL(sioc), name);
716 g_free(name);
720 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
722 SocketChardev *s = SOCKET_CHARDEV(chr);
724 if (s->ioc != NULL) {
725 return -1;
728 s->ioc = QIO_CHANNEL(sioc);
729 object_ref(OBJECT(sioc));
730 s->sioc = sioc;
731 object_ref(OBJECT(sioc));
733 qio_channel_set_blocking(s->ioc, false, NULL);
735 if (s->do_nodelay) {
736 qio_channel_set_delay(s->ioc, false);
738 if (s->listener) {
739 qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
742 if (s->tls_creds) {
743 tcp_chr_tls_init(chr);
744 } else {
745 if (s->do_telnetopt) {
746 tcp_chr_telnet_init(chr);
747 } else {
748 tcp_chr_connect(chr);
752 return 0;
756 static int tcp_chr_add_client(Chardev *chr, int fd)
758 int ret;
759 QIOChannelSocket *sioc;
761 sioc = qio_channel_socket_new_fd(fd, NULL);
762 if (!sioc) {
763 return -1;
765 tcp_chr_set_client_ioc_name(chr, sioc);
766 ret = tcp_chr_new_client(chr, sioc);
767 object_unref(OBJECT(sioc));
768 return ret;
771 static void tcp_chr_accept(QIONetListener *listener,
772 QIOChannelSocket *cioc,
773 void *opaque)
775 Chardev *chr = CHARDEV(opaque);
777 tcp_chr_set_client_ioc_name(chr, cioc);
778 tcp_chr_new_client(chr, cioc);
781 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
783 SocketChardev *s = SOCKET_CHARDEV(chr);
784 QIOChannelSocket *sioc;
786 /* It can't wait on s->connected, since it is set asynchronously
787 * in TLS and telnet cases, only wait for an accepted socket */
788 while (!s->ioc) {
789 if (s->is_listen) {
790 info_report("QEMU waiting for connection on: %s",
791 chr->filename);
792 sioc = qio_net_listener_wait_client(s->listener);
793 tcp_chr_set_client_ioc_name(chr, sioc);
794 tcp_chr_new_client(chr, sioc);
795 object_unref(OBJECT(sioc));
796 } else {
797 sioc = qio_channel_socket_new();
798 tcp_chr_set_client_ioc_name(chr, sioc);
799 if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
800 object_unref(OBJECT(sioc));
801 return -1;
803 tcp_chr_new_client(chr, sioc);
804 object_unref(OBJECT(sioc));
808 return 0;
811 static void char_socket_finalize(Object *obj)
813 Chardev *chr = CHARDEV(obj);
814 SocketChardev *s = SOCKET_CHARDEV(obj);
816 tcp_chr_free_connection(chr);
817 tcp_chr_reconn_timer_cancel(s);
818 qapi_free_SocketAddress(s->addr);
819 if (s->listener) {
820 qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
821 object_unref(OBJECT(s->listener));
823 if (s->tls_creds) {
824 object_unref(OBJECT(s->tls_creds));
827 qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
830 static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
832 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
833 Chardev *chr = CHARDEV(opaque);
834 SocketChardev *s = SOCKET_CHARDEV(chr);
835 Error *err = NULL;
837 if (qio_task_propagate_error(task, &err)) {
838 check_report_connect_error(chr, err);
839 error_free(err);
840 goto cleanup;
843 s->connect_err_reported = false;
844 tcp_chr_new_client(chr, sioc);
846 cleanup:
847 object_unref(OBJECT(sioc));
850 static gboolean socket_reconnect_timeout(gpointer opaque)
852 Chardev *chr = CHARDEV(opaque);
853 SocketChardev *s = SOCKET_CHARDEV(opaque);
854 QIOChannelSocket *sioc;
856 g_source_unref(s->reconnect_timer);
857 s->reconnect_timer = NULL;
859 if (chr->be_open) {
860 return false;
863 sioc = qio_channel_socket_new();
864 tcp_chr_set_client_ioc_name(chr, sioc);
865 qio_channel_socket_connect_async(sioc, s->addr,
866 qemu_chr_socket_connected,
867 chr, NULL);
869 return false;
872 static void qmp_chardev_open_socket(Chardev *chr,
873 ChardevBackend *backend,
874 bool *be_opened,
875 Error **errp)
877 SocketChardev *s = SOCKET_CHARDEV(chr);
878 ChardevSocket *sock = backend->u.socket.data;
879 bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
880 bool is_listen = sock->has_server ? sock->server : true;
881 bool is_telnet = sock->has_telnet ? sock->telnet : false;
882 bool is_tn3270 = sock->has_tn3270 ? sock->tn3270 : false;
883 bool is_waitconnect = sock->has_wait ? sock->wait : false;
884 int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
885 QIOChannelSocket *sioc = NULL;
886 SocketAddress *addr;
888 s->is_listen = is_listen;
889 s->is_telnet = is_telnet;
890 s->is_tn3270 = is_tn3270;
891 s->do_nodelay = do_nodelay;
892 if (sock->tls_creds) {
893 Object *creds;
894 creds = object_resolve_path_component(
895 object_get_objects_root(), sock->tls_creds);
896 if (!creds) {
897 error_setg(errp, "No TLS credentials with id '%s'",
898 sock->tls_creds);
899 goto error;
901 s->tls_creds = (QCryptoTLSCreds *)
902 object_dynamic_cast(creds,
903 TYPE_QCRYPTO_TLS_CREDS);
904 if (!s->tls_creds) {
905 error_setg(errp, "Object with id '%s' is not TLS credentials",
906 sock->tls_creds);
907 goto error;
909 object_ref(OBJECT(s->tls_creds));
910 if (is_listen) {
911 if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
912 error_setg(errp, "%s",
913 "Expected TLS credentials for server endpoint");
914 goto error;
916 } else {
917 if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
918 error_setg(errp, "%s",
919 "Expected TLS credentials for client endpoint");
920 goto error;
925 s->addr = addr = socket_address_flatten(sock->addr);
927 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
928 /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
929 if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
930 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
933 /* be isn't opened until we get a connection */
934 *be_opened = false;
936 update_disconnected_filename(s);
938 if (is_listen) {
939 if (is_telnet || is_tn3270) {
940 s->do_telnetopt = 1;
942 } else if (reconnect > 0) {
943 s->reconnect_time = reconnect;
946 if (s->reconnect_time) {
947 sioc = qio_channel_socket_new();
948 tcp_chr_set_client_ioc_name(chr, sioc);
949 qio_channel_socket_connect_async(sioc, s->addr,
950 qemu_chr_socket_connected,
951 chr, NULL);
952 } else {
953 if (s->is_listen) {
954 char *name;
955 s->listener = qio_net_listener_new();
957 name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
958 qio_net_listener_set_name(s->listener, name);
959 g_free(name);
961 if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
962 object_unref(OBJECT(s->listener));
963 s->listener = NULL;
964 goto error;
967 qapi_free_SocketAddress(s->addr);
968 s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
969 update_disconnected_filename(s);
971 if (is_waitconnect &&
972 qemu_chr_wait_connected(chr, errp) < 0) {
973 return;
975 if (!s->ioc) {
976 qio_net_listener_set_client_func(s->listener, tcp_chr_accept,
977 chr, NULL);
979 } else if (qemu_chr_wait_connected(chr, errp) < 0) {
980 goto error;
984 return;
986 error:
987 if (sioc) {
988 object_unref(OBJECT(sioc));
992 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
993 Error **errp)
995 bool is_listen = qemu_opt_get_bool(opts, "server", false);
996 bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
997 bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
998 bool is_tn3270 = qemu_opt_get_bool(opts, "tn3270", false);
999 bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
1000 int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0);
1001 const char *path = qemu_opt_get(opts, "path");
1002 const char *host = qemu_opt_get(opts, "host");
1003 const char *port = qemu_opt_get(opts, "port");
1004 const char *tls_creds = qemu_opt_get(opts, "tls-creds");
1005 SocketAddressLegacy *addr;
1006 ChardevSocket *sock;
1008 backend->type = CHARDEV_BACKEND_KIND_SOCKET;
1009 if (!path) {
1010 if (!host) {
1011 error_setg(errp, "chardev: socket: no host given");
1012 return;
1014 if (!port) {
1015 error_setg(errp, "chardev: socket: no port given");
1016 return;
1018 } else {
1019 if (tls_creds) {
1020 error_setg(errp, "TLS can only be used over TCP socket");
1021 return;
1025 sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
1026 qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
1028 sock->has_nodelay = true;
1029 sock->nodelay = do_nodelay;
1030 sock->has_server = true;
1031 sock->server = is_listen;
1032 sock->has_telnet = true;
1033 sock->telnet = is_telnet;
1034 sock->has_tn3270 = true;
1035 sock->tn3270 = is_tn3270;
1036 sock->has_wait = true;
1037 sock->wait = is_waitconnect;
1038 sock->has_reconnect = true;
1039 sock->reconnect = reconnect;
1040 sock->tls_creds = g_strdup(tls_creds);
1042 addr = g_new0(SocketAddressLegacy, 1);
1043 if (path) {
1044 UnixSocketAddress *q_unix;
1045 addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
1046 q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
1047 q_unix->path = g_strdup(path);
1048 } else {
1049 addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
1050 addr->u.inet.data = g_new(InetSocketAddress, 1);
1051 *addr->u.inet.data = (InetSocketAddress) {
1052 .host = g_strdup(host),
1053 .port = g_strdup(port),
1054 .has_to = qemu_opt_get(opts, "to"),
1055 .to = qemu_opt_get_number(opts, "to", 0),
1056 .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1057 .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1058 .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1059 .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1062 sock->addr = addr;
1065 static void
1066 char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1067 void *opaque, Error **errp)
1069 SocketChardev *s = SOCKET_CHARDEV(obj);
1071 visit_type_SocketAddress(v, name, &s->addr, errp);
1074 static bool
1075 char_socket_get_connected(Object *obj, Error **errp)
1077 SocketChardev *s = SOCKET_CHARDEV(obj);
1079 return s->connected;
1082 static void char_socket_class_init(ObjectClass *oc, void *data)
1084 ChardevClass *cc = CHARDEV_CLASS(oc);
1086 cc->parse = qemu_chr_parse_socket;
1087 cc->open = qmp_chardev_open_socket;
1088 cc->chr_wait_connected = tcp_chr_wait_connected;
1089 cc->chr_write = tcp_chr_write;
1090 cc->chr_sync_read = tcp_chr_sync_read;
1091 cc->chr_disconnect = tcp_chr_disconnect;
1092 cc->get_msgfds = tcp_get_msgfds;
1093 cc->set_msgfds = tcp_set_msgfds;
1094 cc->chr_add_client = tcp_chr_add_client;
1095 cc->chr_add_watch = tcp_chr_add_watch;
1096 cc->chr_update_read_handler = tcp_chr_update_read_handler;
1098 object_class_property_add(oc, "addr", "SocketAddress",
1099 char_socket_get_addr, NULL,
1100 NULL, NULL, &error_abort);
1102 object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1103 NULL, &error_abort);
1106 static const TypeInfo char_socket_type_info = {
1107 .name = TYPE_CHARDEV_SOCKET,
1108 .parent = TYPE_CHARDEV,
1109 .instance_size = sizeof(SocketChardev),
1110 .instance_finalize = char_socket_finalize,
1111 .class_init = char_socket_class_init,
1114 static void register_types(void)
1116 type_register_static(&char_socket_type_info);
1119 type_init(register_types);