xref: /openbmc/qemu/chardev/char-socket.c (revision 9dea2df8)
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 "io/channel-tls.h"
29 #include "io/channel-websock.h"
30 #include "io/net-listener.h"
31 #include "qemu/error-report.h"
32 #include "qemu/option.h"
33 #include "qapi/error.h"
34 #include "qapi/clone-visitor.h"
35 #include "qapi/qapi-visit-sockets.h"
36 
37 #include "chardev/char-io.h"
38 
39 /***********************************************************/
40 /* TCP Net console */
41 
42 #define TCP_MAX_FDS 16
43 
44 typedef struct {
45     char buf[21];
46     size_t buflen;
47 } TCPChardevTelnetInit;
48 
49 typedef enum {
50     TCP_CHARDEV_STATE_DISCONNECTED,
51     TCP_CHARDEV_STATE_CONNECTING,
52     TCP_CHARDEV_STATE_CONNECTED,
53 } TCPChardevState;
54 
55 typedef struct {
56     Chardev parent;
57     QIOChannel *ioc; /* Client I/O channel */
58     QIOChannelSocket *sioc; /* Client master channel */
59     QIONetListener *listener;
60     GSource *hup_source;
61     QCryptoTLSCreds *tls_creds;
62     TCPChardevState state;
63     int max_size;
64     int do_telnetopt;
65     int do_nodelay;
66     int *read_msgfds;
67     size_t read_msgfds_num;
68     int *write_msgfds;
69     size_t write_msgfds_num;
70 
71     SocketAddress *addr;
72     bool is_listen;
73     bool is_telnet;
74     bool is_tn3270;
75     GSource *telnet_source;
76     TCPChardevTelnetInit *telnet_init;
77 
78     bool is_websock;
79 
80     GSource *reconnect_timer;
81     int64_t reconnect_time;
82     bool connect_err_reported;
83 
84     QIOTask *connect_task;
85 } SocketChardev;
86 
87 #define SOCKET_CHARDEV(obj)                                     \
88     OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
89 
90 static gboolean socket_reconnect_timeout(gpointer opaque);
91 static void tcp_chr_telnet_init(Chardev *chr);
92 
93 static void tcp_chr_change_state(SocketChardev *s, TCPChardevState state)
94 {
95     switch (state) {
96     case TCP_CHARDEV_STATE_DISCONNECTED:
97         break;
98     case TCP_CHARDEV_STATE_CONNECTING:
99         assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED);
100         break;
101     case TCP_CHARDEV_STATE_CONNECTED:
102         assert(s->state == TCP_CHARDEV_STATE_CONNECTING);
103         break;
104     }
105     s->state = state;
106 }
107 
108 static void tcp_chr_reconn_timer_cancel(SocketChardev *s)
109 {
110     if (s->reconnect_timer) {
111         g_source_destroy(s->reconnect_timer);
112         g_source_unref(s->reconnect_timer);
113         s->reconnect_timer = NULL;
114     }
115 }
116 
117 static void qemu_chr_socket_restart_timer(Chardev *chr)
118 {
119     SocketChardev *s = SOCKET_CHARDEV(chr);
120     char *name;
121 
122     assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED);
123     assert(!s->reconnect_timer);
124     name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
125     s->reconnect_timer = qemu_chr_timeout_add_ms(chr,
126                                                  s->reconnect_time * 1000,
127                                                  socket_reconnect_timeout,
128                                                  chr);
129     g_source_set_name(s->reconnect_timer, name);
130     g_free(name);
131 }
132 
133 static void check_report_connect_error(Chardev *chr,
134                                        Error *err)
135 {
136     SocketChardev *s = SOCKET_CHARDEV(chr);
137 
138     if (!s->connect_err_reported) {
139         error_report("Unable to connect character device %s: %s",
140                      chr->label, error_get_pretty(err));
141         s->connect_err_reported = true;
142     }
143     qemu_chr_socket_restart_timer(chr);
144 }
145 
146 static void tcp_chr_accept(QIONetListener *listener,
147                            QIOChannelSocket *cioc,
148                            void *opaque);
149 
150 static int tcp_chr_read_poll(void *opaque);
151 static void tcp_chr_disconnect(Chardev *chr);
152 
153 /* Called with chr_write_lock held.  */
154 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
155 {
156     SocketChardev *s = SOCKET_CHARDEV(chr);
157 
158     if (s->state == TCP_CHARDEV_STATE_CONNECTED) {
159         int ret =  io_channel_send_full(s->ioc, buf, len,
160                                         s->write_msgfds,
161                                         s->write_msgfds_num);
162 
163         /* free the written msgfds in any cases
164          * other than ret < 0 && errno == EAGAIN
165          */
166         if (!(ret < 0 && EAGAIN == errno)
167             && s->write_msgfds_num) {
168             g_free(s->write_msgfds);
169             s->write_msgfds = 0;
170             s->write_msgfds_num = 0;
171         }
172 
173         if (ret < 0 && errno != EAGAIN) {
174             if (tcp_chr_read_poll(chr) <= 0) {
175                 tcp_chr_disconnect(chr);
176                 return len;
177             } /* else let the read handler finish it properly */
178         }
179 
180         return ret;
181     } else {
182         /* XXX: indicate an error ? */
183         return len;
184     }
185 }
186 
187 static int tcp_chr_read_poll(void *opaque)
188 {
189     Chardev *chr = CHARDEV(opaque);
190     SocketChardev *s = SOCKET_CHARDEV(opaque);
191     if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
192         return 0;
193     }
194     s->max_size = qemu_chr_be_can_write(chr);
195     return s->max_size;
196 }
197 
198 static void tcp_chr_process_IAC_bytes(Chardev *chr,
199                                       SocketChardev *s,
200                                       uint8_t *buf, int *size)
201 {
202     /* Handle any telnet or tn3270 client's basic IAC options.
203      * For telnet options, it satisfies char by char mode with no echo.
204      * For tn3270 options, it satisfies binary mode with EOR.
205      * All IAC options will be removed from the buf and the do_opt
206      * pointer will be used to track the state of the width of the
207      * IAC information.
208      *
209      * RFC854: "All TELNET commands consist of at least a two byte sequence.
210      * The commands dealing with option negotiation are three byte sequences,
211      * the third byte being the code for the option referenced."
212      * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes.
213      * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary
214      * for tn3270.
215      * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270
216      * session, and NOP and IP need to be done later.
217      */
218 
219     int i;
220     int j = 0;
221 
222     for (i = 0; i < *size; i++) {
223         if (s->do_telnetopt > 1) {
224             if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
225                 /* Double IAC means send an IAC */
226                 if (j != i) {
227                     buf[j] = buf[i];
228                 }
229                 j++;
230                 s->do_telnetopt = 1;
231             } else {
232                 if ((unsigned char)buf[i] == IAC_BREAK
233                     && s->do_telnetopt == 2) {
234                     /* Handle IAC break commands by sending a serial break */
235                     qemu_chr_be_event(chr, CHR_EVENT_BREAK);
236                     s->do_telnetopt++;
237                 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR
238                            || (unsigned char)buf[i] == IAC_SB
239                            || (unsigned char)buf[i] == IAC_SE)
240                            && s->do_telnetopt == 2) {
241                     buf[j++] = IAC;
242                     buf[j++] = buf[i];
243                     s->do_telnetopt++;
244                 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP
245                            || (unsigned char)buf[i] == IAC_NOP)
246                            && s->do_telnetopt == 2) {
247                     /* TODO: IP and NOP need to be implemented later. */
248                     s->do_telnetopt++;
249                 }
250                 s->do_telnetopt++;
251             }
252             if (s->do_telnetopt >= 4) {
253                 s->do_telnetopt = 1;
254             }
255         } else {
256             if ((unsigned char)buf[i] == IAC) {
257                 s->do_telnetopt = 2;
258             } else {
259                 if (j != i) {
260                     buf[j] = buf[i];
261                 }
262                 j++;
263             }
264         }
265     }
266     *size = j;
267 }
268 
269 static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
270 {
271     SocketChardev *s = SOCKET_CHARDEV(chr);
272 
273     int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
274 
275     assert(num <= TCP_MAX_FDS);
276 
277     if (to_copy) {
278         int i;
279 
280         memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
281 
282         /* Close unused fds */
283         for (i = to_copy; i < s->read_msgfds_num; i++) {
284             close(s->read_msgfds[i]);
285         }
286 
287         g_free(s->read_msgfds);
288         s->read_msgfds = 0;
289         s->read_msgfds_num = 0;
290     }
291 
292     return to_copy;
293 }
294 
295 static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
296 {
297     SocketChardev *s = SOCKET_CHARDEV(chr);
298 
299     /* clear old pending fd array */
300     g_free(s->write_msgfds);
301     s->write_msgfds = NULL;
302     s->write_msgfds_num = 0;
303 
304     if ((s->state != TCP_CHARDEV_STATE_CONNECTED) ||
305         !qio_channel_has_feature(s->ioc,
306                                  QIO_CHANNEL_FEATURE_FD_PASS)) {
307         return -1;
308     }
309 
310     if (num) {
311         s->write_msgfds = g_new(int, num);
312         memcpy(s->write_msgfds, fds, num * sizeof(int));
313     }
314 
315     s->write_msgfds_num = num;
316 
317     return 0;
318 }
319 
320 static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
321 {
322     SocketChardev *s = SOCKET_CHARDEV(chr);
323     struct iovec iov = { .iov_base = buf, .iov_len = len };
324     int ret;
325     size_t i;
326     int *msgfds = NULL;
327     size_t msgfds_num = 0;
328 
329     if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
330         ret = qio_channel_readv_full(s->ioc, &iov, 1,
331                                      &msgfds, &msgfds_num,
332                                      NULL);
333     } else {
334         ret = qio_channel_readv_full(s->ioc, &iov, 1,
335                                      NULL, NULL,
336                                      NULL);
337     }
338 
339     if (ret == QIO_CHANNEL_ERR_BLOCK) {
340         errno = EAGAIN;
341         ret = -1;
342     } else if (ret == -1) {
343         errno = EIO;
344     }
345 
346     if (msgfds_num) {
347         /* close and clean read_msgfds */
348         for (i = 0; i < s->read_msgfds_num; i++) {
349             close(s->read_msgfds[i]);
350         }
351 
352         if (s->read_msgfds_num) {
353             g_free(s->read_msgfds);
354         }
355 
356         s->read_msgfds = msgfds;
357         s->read_msgfds_num = msgfds_num;
358     }
359 
360     for (i = 0; i < s->read_msgfds_num; i++) {
361         int fd = s->read_msgfds[i];
362         if (fd < 0) {
363             continue;
364         }
365 
366         /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
367         qemu_set_block(fd);
368 
369 #ifndef MSG_CMSG_CLOEXEC
370         qemu_set_cloexec(fd);
371 #endif
372     }
373 
374     return ret;
375 }
376 
377 static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
378 {
379     SocketChardev *s = SOCKET_CHARDEV(chr);
380     return qio_channel_create_watch(s->ioc, cond);
381 }
382 
383 static void remove_hup_source(SocketChardev *s)
384 {
385     if (s->hup_source != NULL) {
386         g_source_destroy(s->hup_source);
387         g_source_unref(s->hup_source);
388         s->hup_source = NULL;
389     }
390 }
391 
392 static void tcp_chr_free_connection(Chardev *chr)
393 {
394     SocketChardev *s = SOCKET_CHARDEV(chr);
395     int i;
396 
397     if (s->read_msgfds_num) {
398         for (i = 0; i < s->read_msgfds_num; i++) {
399             close(s->read_msgfds[i]);
400         }
401         g_free(s->read_msgfds);
402         s->read_msgfds = NULL;
403         s->read_msgfds_num = 0;
404     }
405 
406     remove_hup_source(s);
407 
408     tcp_set_msgfds(chr, NULL, 0);
409     remove_fd_in_watch(chr);
410     object_unref(OBJECT(s->sioc));
411     s->sioc = NULL;
412     object_unref(OBJECT(s->ioc));
413     s->ioc = NULL;
414     g_free(chr->filename);
415     chr->filename = NULL;
416     tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
417 }
418 
419 static const char *qemu_chr_socket_protocol(SocketChardev *s)
420 {
421     if (s->is_telnet) {
422         return "telnet";
423     }
424     return s->is_websock ? "websocket" : "tcp";
425 }
426 
427 static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix)
428 {
429     switch (s->addr->type) {
430     case SOCKET_ADDRESS_TYPE_INET:
431         return g_strdup_printf("%s%s:%s:%s%s", prefix,
432                                qemu_chr_socket_protocol(s),
433                                s->addr->u.inet.host,
434                                s->addr->u.inet.port,
435                                s->is_listen ? ",server" : "");
436         break;
437     case SOCKET_ADDRESS_TYPE_UNIX:
438         return g_strdup_printf("%sunix:%s%s", prefix,
439                                s->addr->u.q_unix.path,
440                                s->is_listen ? ",server" : "");
441         break;
442     case SOCKET_ADDRESS_TYPE_FD:
443         return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str,
444                                s->is_listen ? ",server" : "");
445         break;
446     case SOCKET_ADDRESS_TYPE_VSOCK:
447         return g_strdup_printf("%svsock:%s:%s", prefix,
448                                s->addr->u.vsock.cid,
449                                s->addr->u.vsock.port);
450     default:
451         abort();
452     }
453 }
454 
455 static void update_disconnected_filename(SocketChardev *s)
456 {
457     Chardev *chr = CHARDEV(s);
458 
459     g_free(chr->filename);
460     if (s->addr) {
461         chr->filename = qemu_chr_socket_address(s, "disconnected:");
462     } else {
463         chr->filename = g_strdup("disconnected:socket");
464     }
465 }
466 
467 /* NB may be called even if tcp_chr_connect has not been
468  * reached, due to TLS or telnet initialization failure,
469  * so can *not* assume s->state == TCP_CHARDEV_STATE_CONNECTED
470  */
471 static void tcp_chr_disconnect(Chardev *chr)
472 {
473     SocketChardev *s = SOCKET_CHARDEV(chr);
474     bool emit_close = s->state == TCP_CHARDEV_STATE_CONNECTED;
475 
476     tcp_chr_free_connection(chr);
477 
478     if (s->listener) {
479         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
480                                               chr, NULL, chr->gcontext);
481     }
482     update_disconnected_filename(s);
483     if (emit_close) {
484         qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
485     }
486     if (s->reconnect_time) {
487         qemu_chr_socket_restart_timer(chr);
488     }
489 }
490 
491 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
492 {
493     Chardev *chr = CHARDEV(opaque);
494     SocketChardev *s = SOCKET_CHARDEV(opaque);
495     uint8_t buf[CHR_READ_BUF_LEN];
496     int len, size;
497 
498     if ((s->state != TCP_CHARDEV_STATE_CONNECTED) ||
499         s->max_size <= 0) {
500         return TRUE;
501     }
502     len = sizeof(buf);
503     if (len > s->max_size) {
504         len = s->max_size;
505     }
506     size = tcp_chr_recv(chr, (void *)buf, len);
507     if (size == 0 || (size == -1 && errno != EAGAIN)) {
508         /* connection closed */
509         tcp_chr_disconnect(chr);
510     } else if (size > 0) {
511         if (s->do_telnetopt) {
512             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
513         }
514         if (size > 0) {
515             qemu_chr_be_write(chr, buf, size);
516         }
517     }
518 
519     return TRUE;
520 }
521 
522 static gboolean tcp_chr_hup(QIOChannel *channel,
523                                GIOCondition cond,
524                                void *opaque)
525 {
526     Chardev *chr = CHARDEV(opaque);
527     tcp_chr_disconnect(chr);
528     return G_SOURCE_REMOVE;
529 }
530 
531 static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
532 {
533     SocketChardev *s = SOCKET_CHARDEV(chr);
534     int size;
535 
536     if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
537         return 0;
538     }
539 
540     qio_channel_set_blocking(s->ioc, true, NULL);
541     size = tcp_chr_recv(chr, (void *) buf, len);
542     qio_channel_set_blocking(s->ioc, false, NULL);
543     if (size == 0) {
544         /* connection closed */
545         tcp_chr_disconnect(chr);
546     }
547 
548     return size;
549 }
550 
551 static char *qemu_chr_compute_filename(SocketChardev *s)
552 {
553     struct sockaddr_storage *ss = &s->sioc->localAddr;
554     struct sockaddr_storage *ps = &s->sioc->remoteAddr;
555     socklen_t ss_len = s->sioc->localAddrLen;
556     socklen_t ps_len = s->sioc->remoteAddrLen;
557     char shost[NI_MAXHOST], sserv[NI_MAXSERV];
558     char phost[NI_MAXHOST], pserv[NI_MAXSERV];
559     const char *left = "", *right = "";
560 
561     switch (ss->ss_family) {
562 #ifndef _WIN32
563     case AF_UNIX:
564         return g_strdup_printf("unix:%s%s",
565                                ((struct sockaddr_un *)(ss))->sun_path,
566                                s->is_listen ? ",server" : "");
567 #endif
568     case AF_INET6:
569         left  = "[";
570         right = "]";
571         /* fall through */
572     case AF_INET:
573         getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
574                     sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
575         getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
576                     pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
577         return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
578                                qemu_chr_socket_protocol(s),
579                                left, shost, right, sserv,
580                                s->is_listen ? ",server" : "",
581                                left, phost, right, pserv);
582 
583     default:
584         return g_strdup_printf("unknown");
585     }
586 }
587 
588 static void update_ioc_handlers(SocketChardev *s)
589 {
590     Chardev *chr = CHARDEV(s);
591 
592     if (s->state != TCP_CHARDEV_STATE_CONNECTED) {
593         return;
594     }
595 
596     remove_fd_in_watch(chr);
597     chr->gsource = io_add_watch_poll(chr, s->ioc,
598                                      tcp_chr_read_poll,
599                                      tcp_chr_read, chr,
600                                      chr->gcontext);
601 
602     remove_hup_source(s);
603     s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP);
604     g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup,
605                           chr, NULL);
606     g_source_attach(s->hup_source, chr->gcontext);
607 }
608 
609 static void tcp_chr_connect(void *opaque)
610 {
611     Chardev *chr = CHARDEV(opaque);
612     SocketChardev *s = SOCKET_CHARDEV(opaque);
613 
614     g_free(chr->filename);
615     chr->filename = qemu_chr_compute_filename(s);
616 
617     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTED);
618     update_ioc_handlers(s);
619     qemu_chr_be_event(chr, CHR_EVENT_OPENED);
620 }
621 
622 static void tcp_chr_telnet_destroy(SocketChardev *s)
623 {
624     if (s->telnet_source) {
625         g_source_destroy(s->telnet_source);
626         g_source_unref(s->telnet_source);
627         s->telnet_source = NULL;
628     }
629 }
630 
631 static void tcp_chr_update_read_handler(Chardev *chr)
632 {
633     SocketChardev *s = SOCKET_CHARDEV(chr);
634 
635     if (s->listener) {
636         /*
637          * It's possible that chardev context is changed in
638          * qemu_chr_be_update_read_handlers().  Reset it for QIO net
639          * listener if there is.
640          */
641         qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept,
642                                               chr, NULL, chr->gcontext);
643     }
644 
645     if (s->telnet_source) {
646         tcp_chr_telnet_init(CHARDEV(s));
647     }
648 
649     update_ioc_handlers(s);
650 }
651 
652 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
653                                        GIOCondition cond G_GNUC_UNUSED,
654                                        gpointer user_data)
655 {
656     SocketChardev *s = user_data;
657     Chardev *chr = CHARDEV(s);
658     TCPChardevTelnetInit *init = s->telnet_init;
659     ssize_t ret;
660 
661     assert(init);
662 
663     ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
664     if (ret < 0) {
665         if (ret == QIO_CHANNEL_ERR_BLOCK) {
666             ret = 0;
667         } else {
668             tcp_chr_disconnect(chr);
669             goto end;
670         }
671     }
672     init->buflen -= ret;
673 
674     if (init->buflen == 0) {
675         tcp_chr_connect(chr);
676         goto end;
677     }
678 
679     memmove(init->buf, init->buf + ret, init->buflen);
680 
681     return G_SOURCE_CONTINUE;
682 
683 end:
684     g_free(s->telnet_init);
685     s->telnet_init = NULL;
686     g_source_unref(s->telnet_source);
687     s->telnet_source = NULL;
688     return G_SOURCE_REMOVE;
689 }
690 
691 static void tcp_chr_telnet_init(Chardev *chr)
692 {
693     SocketChardev *s = SOCKET_CHARDEV(chr);
694     TCPChardevTelnetInit *init;
695     size_t n = 0;
696 
697     /* Destroy existing task */
698     tcp_chr_telnet_destroy(s);
699 
700     if (s->telnet_init) {
701         /* We are possibly during a handshake already */
702         goto cont;
703     }
704 
705     s->telnet_init = g_new0(TCPChardevTelnetInit, 1);
706     init = s->telnet_init;
707 
708 #define IACSET(x, a, b, c)                      \
709     do {                                        \
710         x[n++] = a;                             \
711         x[n++] = b;                             \
712         x[n++] = c;                             \
713     } while (0)
714 
715     if (!s->is_tn3270) {
716         init->buflen = 12;
717         /* Prep the telnet negotion to put telnet in binary,
718          * no echo, single char mode */
719         IACSET(init->buf, 0xff, 0xfb, 0x01);  /* IAC WILL ECHO */
720         IACSET(init->buf, 0xff, 0xfb, 0x03);  /* IAC WILL Suppress go ahead */
721         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL Binary */
722         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO Binary */
723     } else {
724         init->buflen = 21;
725         /* Prep the TN3270 negotion based on RFC1576 */
726         IACSET(init->buf, 0xff, 0xfd, 0x19);  /* IAC DO EOR */
727         IACSET(init->buf, 0xff, 0xfb, 0x19);  /* IAC WILL EOR */
728         IACSET(init->buf, 0xff, 0xfd, 0x00);  /* IAC DO BINARY */
729         IACSET(init->buf, 0xff, 0xfb, 0x00);  /* IAC WILL BINARY */
730         IACSET(init->buf, 0xff, 0xfd, 0x18);  /* IAC DO TERMINAL TYPE */
731         IACSET(init->buf, 0xff, 0xfa, 0x18);  /* IAC SB TERMINAL TYPE */
732         IACSET(init->buf, 0x01, 0xff, 0xf0);  /* SEND IAC SE */
733     }
734 
735 #undef IACSET
736 
737 cont:
738     s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT,
739                                                     tcp_chr_telnet_init_io,
740                                                     s, NULL,
741                                                     chr->gcontext);
742 }
743 
744 
745 static void tcp_chr_websock_handshake(QIOTask *task, gpointer user_data)
746 {
747     Chardev *chr = user_data;
748     SocketChardev *s = user_data;
749 
750     if (qio_task_propagate_error(task, NULL)) {
751         tcp_chr_disconnect(chr);
752     } else {
753         if (s->do_telnetopt) {
754             tcp_chr_telnet_init(chr);
755         } else {
756             tcp_chr_connect(chr);
757         }
758     }
759 }
760 
761 
762 static void tcp_chr_websock_init(Chardev *chr)
763 {
764     SocketChardev *s = SOCKET_CHARDEV(chr);
765     QIOChannelWebsock *wioc = NULL;
766     gchar *name;
767 
768     wioc = qio_channel_websock_new_server(s->ioc);
769 
770     name = g_strdup_printf("chardev-websocket-server-%s", chr->label);
771     qio_channel_set_name(QIO_CHANNEL(wioc), name);
772     g_free(name);
773     object_unref(OBJECT(s->ioc));
774     s->ioc = QIO_CHANNEL(wioc);
775 
776     qio_channel_websock_handshake(wioc, tcp_chr_websock_handshake, chr, NULL);
777 }
778 
779 
780 static void tcp_chr_tls_handshake(QIOTask *task,
781                                   gpointer user_data)
782 {
783     Chardev *chr = user_data;
784     SocketChardev *s = user_data;
785 
786     if (qio_task_propagate_error(task, NULL)) {
787         tcp_chr_disconnect(chr);
788     } else {
789         if (s->is_websock) {
790             tcp_chr_websock_init(chr);
791         } else if (s->do_telnetopt) {
792             tcp_chr_telnet_init(chr);
793         } else {
794             tcp_chr_connect(chr);
795         }
796     }
797 }
798 
799 
800 static void tcp_chr_tls_init(Chardev *chr)
801 {
802     SocketChardev *s = SOCKET_CHARDEV(chr);
803     QIOChannelTLS *tioc;
804     Error *err = NULL;
805     gchar *name;
806 
807     if (s->is_listen) {
808         tioc = qio_channel_tls_new_server(
809             s->ioc, s->tls_creds,
810             NULL, /* XXX Use an ACL */
811             &err);
812     } else {
813         tioc = qio_channel_tls_new_client(
814             s->ioc, s->tls_creds,
815             s->addr->u.inet.host,
816             &err);
817     }
818     if (tioc == NULL) {
819         error_free(err);
820         tcp_chr_disconnect(chr);
821         return;
822     }
823     name = g_strdup_printf("chardev-tls-%s-%s",
824                            s->is_listen ? "server" : "client",
825                            chr->label);
826     qio_channel_set_name(QIO_CHANNEL(tioc), name);
827     g_free(name);
828     object_unref(OBJECT(s->ioc));
829     s->ioc = QIO_CHANNEL(tioc);
830 
831     qio_channel_tls_handshake(tioc,
832                               tcp_chr_tls_handshake,
833                               chr,
834                               NULL,
835                               chr->gcontext);
836 }
837 
838 
839 static void tcp_chr_set_client_ioc_name(Chardev *chr,
840                                         QIOChannelSocket *sioc)
841 {
842     SocketChardev *s = SOCKET_CHARDEV(chr);
843     char *name;
844     name = g_strdup_printf("chardev-tcp-%s-%s",
845                            s->is_listen ? "server" : "client",
846                            chr->label);
847     qio_channel_set_name(QIO_CHANNEL(sioc), name);
848     g_free(name);
849 
850 }
851 
852 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
853 {
854     SocketChardev *s = SOCKET_CHARDEV(chr);
855 
856     if (s->state != TCP_CHARDEV_STATE_CONNECTING) {
857         return -1;
858     }
859 
860     s->ioc = QIO_CHANNEL(sioc);
861     object_ref(OBJECT(sioc));
862     s->sioc = sioc;
863     object_ref(OBJECT(sioc));
864 
865     qio_channel_set_blocking(s->ioc, false, NULL);
866 
867     if (s->do_nodelay) {
868         qio_channel_set_delay(s->ioc, false);
869     }
870     if (s->listener) {
871         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
872                                               NULL, chr->gcontext);
873     }
874 
875     if (s->tls_creds) {
876         tcp_chr_tls_init(chr);
877     } else if (s->is_websock) {
878         tcp_chr_websock_init(chr);
879     } else if (s->do_telnetopt) {
880         tcp_chr_telnet_init(chr);
881     } else {
882         tcp_chr_connect(chr);
883     }
884 
885     return 0;
886 }
887 
888 
889 static int tcp_chr_add_client(Chardev *chr, int fd)
890 {
891     int ret;
892     QIOChannelSocket *sioc;
893     SocketChardev *s = SOCKET_CHARDEV(chr);
894 
895     if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) {
896         return -1;
897     }
898 
899     sioc = qio_channel_socket_new_fd(fd, NULL);
900     if (!sioc) {
901         return -1;
902     }
903     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
904     tcp_chr_set_client_ioc_name(chr, sioc);
905     ret = tcp_chr_new_client(chr, sioc);
906     object_unref(OBJECT(sioc));
907     return ret;
908 }
909 
910 static void tcp_chr_accept(QIONetListener *listener,
911                            QIOChannelSocket *cioc,
912                            void *opaque)
913 {
914     Chardev *chr = CHARDEV(opaque);
915     SocketChardev *s = SOCKET_CHARDEV(chr);
916 
917     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
918     tcp_chr_set_client_ioc_name(chr, cioc);
919     tcp_chr_new_client(chr, cioc);
920 }
921 
922 
923 static int tcp_chr_connect_client_sync(Chardev *chr, Error **errp)
924 {
925     SocketChardev *s = SOCKET_CHARDEV(chr);
926     QIOChannelSocket *sioc = qio_channel_socket_new();
927     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
928     tcp_chr_set_client_ioc_name(chr, sioc);
929     if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
930         tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
931         object_unref(OBJECT(sioc));
932         return -1;
933     }
934     tcp_chr_new_client(chr, sioc);
935     object_unref(OBJECT(sioc));
936     return 0;
937 }
938 
939 
940 static void tcp_chr_accept_server_sync(Chardev *chr)
941 {
942     SocketChardev *s = SOCKET_CHARDEV(chr);
943     QIOChannelSocket *sioc;
944     info_report("QEMU waiting for connection on: %s",
945                 chr->filename);
946     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
947     sioc = qio_net_listener_wait_client(s->listener);
948     tcp_chr_set_client_ioc_name(chr, sioc);
949     tcp_chr_new_client(chr, sioc);
950     object_unref(OBJECT(sioc));
951 }
952 
953 
954 static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
955 {
956     SocketChardev *s = SOCKET_CHARDEV(chr);
957     const char *opts[] = { "telnet", "tn3270", "websock", "tls-creds" };
958     bool optset[] = { s->is_telnet, s->is_tn3270, s->is_websock, s->tls_creds };
959     size_t i;
960 
961     QEMU_BUILD_BUG_ON(G_N_ELEMENTS(opts) != G_N_ELEMENTS(optset));
962     for (i = 0; i < G_N_ELEMENTS(opts); i++) {
963         if (optset[i]) {
964             error_setg(errp,
965                        "'%s' option is incompatible with waiting for "
966                        "connection completion", opts[i]);
967             return -1;
968         }
969     }
970 
971     tcp_chr_reconn_timer_cancel(s);
972 
973     /*
974      * We expect states to be as follows:
975      *
976      *  - server
977      *    - wait   -> CONNECTED
978      *    - nowait -> DISCONNECTED
979      *  - client
980      *    - reconnect == 0 -> CONNECTED
981      *    - reconnect != 0 -> CONNECTING
982      *
983      */
984     if (s->state == TCP_CHARDEV_STATE_CONNECTING) {
985         if (!s->connect_task) {
986             error_setg(errp,
987                        "Unexpected 'connecting' state without connect task "
988                        "while waiting for connection completion");
989             return -1;
990         }
991         /*
992          * tcp_chr_wait_connected should only ever be run from the
993          * main loop thread associated with chr->gcontext, otherwise
994          * qio_task_wait_thread has a dangerous race condition with
995          * free'ing of the s->connect_task object.
996          *
997          * Acquiring the main context doesn't 100% prove we're in
998          * the main loop thread, but it does at least guarantee
999          * that the main loop won't be executed by another thread
1000          * avoiding the race condition with the task idle callback.
1001          */
1002         g_main_context_acquire(chr->gcontext);
1003         qio_task_wait_thread(s->connect_task);
1004         g_main_context_release(chr->gcontext);
1005 
1006         /*
1007          * The completion callback (qemu_chr_socket_connected) for
1008          * s->connect_task should have set this to NULL by the time
1009          * qio_task_wait_thread has returned.
1010          */
1011         assert(!s->connect_task);
1012 
1013         /*
1014          * NB we are *not* guaranteed to have "s->state == ..CONNECTED"
1015          * at this point as this first connect may be failed, so
1016          * allow the next loop to run regardless.
1017          */
1018     }
1019 
1020     while (s->state != TCP_CHARDEV_STATE_CONNECTED) {
1021         if (s->is_listen) {
1022             tcp_chr_accept_server_sync(chr);
1023         } else {
1024             Error *err = NULL;
1025             if (tcp_chr_connect_client_sync(chr, &err) < 0) {
1026                 if (s->reconnect_time) {
1027                     error_free(err);
1028                     g_usleep(s->reconnect_time * 1000ULL * 1000ULL);
1029                 } else {
1030                     error_propagate(errp, err);
1031                     return -1;
1032                 }
1033             }
1034         }
1035     }
1036 
1037     return 0;
1038 }
1039 
1040 static void char_socket_finalize(Object *obj)
1041 {
1042     Chardev *chr = CHARDEV(obj);
1043     SocketChardev *s = SOCKET_CHARDEV(obj);
1044 
1045     tcp_chr_free_connection(chr);
1046     tcp_chr_reconn_timer_cancel(s);
1047     qapi_free_SocketAddress(s->addr);
1048     tcp_chr_telnet_destroy(s);
1049     g_free(s->telnet_init);
1050     if (s->listener) {
1051         qio_net_listener_set_client_func_full(s->listener, NULL, NULL,
1052                                               NULL, chr->gcontext);
1053         object_unref(OBJECT(s->listener));
1054     }
1055     if (s->tls_creds) {
1056         object_unref(OBJECT(s->tls_creds));
1057     }
1058 
1059     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
1060 }
1061 
1062 static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
1063 {
1064     QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
1065     Chardev *chr = CHARDEV(opaque);
1066     SocketChardev *s = SOCKET_CHARDEV(chr);
1067     Error *err = NULL;
1068 
1069     s->connect_task = NULL;
1070 
1071     if (qio_task_propagate_error(task, &err)) {
1072         tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED);
1073         check_report_connect_error(chr, err);
1074         error_free(err);
1075         goto cleanup;
1076     }
1077 
1078     s->connect_err_reported = false;
1079     tcp_chr_new_client(chr, sioc);
1080 
1081 cleanup:
1082     object_unref(OBJECT(sioc));
1083 }
1084 
1085 
1086 static void tcp_chr_connect_client_task(QIOTask *task,
1087                                         gpointer opaque)
1088 {
1089     QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
1090     SocketAddress *addr = opaque;
1091     Error *err = NULL;
1092 
1093     qio_channel_socket_connect_sync(ioc, addr, &err);
1094 
1095     qio_task_set_error(task, err);
1096 }
1097 
1098 
1099 static void tcp_chr_connect_client_async(Chardev *chr)
1100 {
1101     SocketChardev *s = SOCKET_CHARDEV(chr);
1102     QIOChannelSocket *sioc;
1103 
1104     tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING);
1105     sioc = qio_channel_socket_new();
1106     tcp_chr_set_client_ioc_name(chr, sioc);
1107     /*
1108      * Normally code would use the qio_channel_socket_connect_async
1109      * method which uses a QIOTask + qio_task_set_error internally
1110      * to avoid blocking. The tcp_chr_wait_connected method, however,
1111      * needs a way to synchronize with completion of the background
1112      * connect task which can't be done with the QIOChannelSocket
1113      * async APIs. Thus we must use QIOTask directly to implement
1114      * the non-blocking concept locally.
1115      */
1116     s->connect_task = qio_task_new(OBJECT(sioc),
1117                                    qemu_chr_socket_connected,
1118                                    chr, NULL);
1119     qio_task_run_in_thread(s->connect_task,
1120                            tcp_chr_connect_client_task,
1121                            s->addr,
1122                            NULL,
1123                            chr->gcontext);
1124 }
1125 
1126 static gboolean socket_reconnect_timeout(gpointer opaque)
1127 {
1128     Chardev *chr = CHARDEV(opaque);
1129     SocketChardev *s = SOCKET_CHARDEV(opaque);
1130 
1131     g_source_unref(s->reconnect_timer);
1132     s->reconnect_timer = NULL;
1133 
1134     if (chr->be_open) {
1135         return false;
1136     }
1137 
1138     tcp_chr_connect_client_async(chr);
1139 
1140     return false;
1141 }
1142 
1143 
1144 static int qmp_chardev_open_socket_server(Chardev *chr,
1145                                           bool is_telnet,
1146                                           bool is_waitconnect,
1147                                           Error **errp)
1148 {
1149     SocketChardev *s = SOCKET_CHARDEV(chr);
1150     char *name;
1151     if (is_telnet) {
1152         s->do_telnetopt = 1;
1153     }
1154     s->listener = qio_net_listener_new();
1155 
1156     name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
1157     qio_net_listener_set_name(s->listener, name);
1158     g_free(name);
1159 
1160     if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) {
1161         object_unref(OBJECT(s->listener));
1162         s->listener = NULL;
1163         return -1;
1164     }
1165 
1166     qapi_free_SocketAddress(s->addr);
1167     s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
1168     update_disconnected_filename(s);
1169 
1170     if (is_waitconnect) {
1171         tcp_chr_accept_server_sync(chr);
1172     } else {
1173         qio_net_listener_set_client_func_full(s->listener,
1174                                               tcp_chr_accept,
1175                                               chr, NULL,
1176                                               chr->gcontext);
1177     }
1178 
1179     return 0;
1180 }
1181 
1182 
1183 static int qmp_chardev_open_socket_client(Chardev *chr,
1184                                           int64_t reconnect,
1185                                           Error **errp)
1186 {
1187     SocketChardev *s = SOCKET_CHARDEV(chr);
1188 
1189     if (reconnect > 0) {
1190         s->reconnect_time = reconnect;
1191         tcp_chr_connect_client_async(chr);
1192         return 0;
1193     } else {
1194         return tcp_chr_connect_client_sync(chr, errp);
1195     }
1196 }
1197 
1198 
1199 static bool qmp_chardev_validate_socket(ChardevSocket *sock,
1200                                         SocketAddress *addr,
1201                                         Error **errp)
1202 {
1203     /* Validate any options which have a dependency on address type */
1204     switch (addr->type) {
1205     case SOCKET_ADDRESS_TYPE_FD:
1206         if (sock->has_reconnect) {
1207             error_setg(errp,
1208                        "'reconnect' option is incompatible with "
1209                        "'fd' address type");
1210             return false;
1211         }
1212         if (sock->has_tls_creds &&
1213             !(sock->has_server && sock->server)) {
1214             error_setg(errp,
1215                        "'tls_creds' option is incompatible with "
1216                        "'fd' address type as client");
1217             return false;
1218         }
1219         break;
1220 
1221     case SOCKET_ADDRESS_TYPE_UNIX:
1222         if (sock->has_tls_creds) {
1223             error_setg(errp,
1224                        "'tls_creds' option is incompatible with "
1225                        "'unix' address type");
1226             return false;
1227         }
1228         break;
1229 
1230     case SOCKET_ADDRESS_TYPE_INET:
1231         break;
1232 
1233     case SOCKET_ADDRESS_TYPE_VSOCK:
1234         if (sock->has_tls_creds) {
1235             error_setg(errp,
1236                        "'tls_creds' option is incompatible with "
1237                        "'vsock' address type");
1238             return false;
1239         }
1240 
1241     default:
1242         break;
1243     }
1244 
1245     /* Validate any options which have a dependancy on client vs server */
1246     if (!sock->has_server || sock->server) {
1247         if (sock->has_reconnect) {
1248             error_setg(errp,
1249                        "'reconnect' option is incompatible with "
1250                        "socket in server listen mode");
1251             return false;
1252         }
1253     } else {
1254         if (sock->has_websocket && sock->websocket) {
1255             error_setg(errp, "%s", "Websocket client is not implemented");
1256             return false;
1257         }
1258         if (sock->has_wait) {
1259             error_setg(errp, "%s",
1260                        "'wait' option is incompatible with "
1261                        "socket in client connect mode");
1262             return false;
1263         }
1264     }
1265 
1266     return true;
1267 }
1268 
1269 
1270 static void qmp_chardev_open_socket(Chardev *chr,
1271                                     ChardevBackend *backend,
1272                                     bool *be_opened,
1273                                     Error **errp)
1274 {
1275     SocketChardev *s = SOCKET_CHARDEV(chr);
1276     ChardevSocket *sock = backend->u.socket.data;
1277     bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
1278     bool is_listen      = sock->has_server  ? sock->server  : true;
1279     bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
1280     bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
1281     bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
1282     bool is_websock     = sock->has_websocket ? sock->websocket : false;
1283     int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
1284     SocketAddress *addr;
1285 
1286     s->is_listen = is_listen;
1287     s->is_telnet = is_telnet;
1288     s->is_tn3270 = is_tn3270;
1289     s->is_websock = is_websock;
1290     s->do_nodelay = do_nodelay;
1291     if (sock->tls_creds) {
1292         Object *creds;
1293         creds = object_resolve_path_component(
1294             object_get_objects_root(), sock->tls_creds);
1295         if (!creds) {
1296             error_setg(errp, "No TLS credentials with id '%s'",
1297                        sock->tls_creds);
1298             return;
1299         }
1300         s->tls_creds = (QCryptoTLSCreds *)
1301             object_dynamic_cast(creds,
1302                                 TYPE_QCRYPTO_TLS_CREDS);
1303         if (!s->tls_creds) {
1304             error_setg(errp, "Object with id '%s' is not TLS credentials",
1305                        sock->tls_creds);
1306             return;
1307         }
1308         object_ref(OBJECT(s->tls_creds));
1309         if (is_listen) {
1310             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
1311                 error_setg(errp, "%s",
1312                            "Expected TLS credentials for server endpoint");
1313                 return;
1314             }
1315         } else {
1316             if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
1317                 error_setg(errp, "%s",
1318                            "Expected TLS credentials for client endpoint");
1319                 return;
1320             }
1321         }
1322     }
1323 
1324     s->addr = addr = socket_address_flatten(sock->addr);
1325 
1326     if (!qmp_chardev_validate_socket(sock, addr, errp)) {
1327         return;
1328     }
1329 
1330     qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
1331     /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
1332     if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
1333         qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
1334     }
1335 
1336     /* be isn't opened until we get a connection */
1337     *be_opened = false;
1338 
1339     update_disconnected_filename(s);
1340 
1341     if (s->is_listen) {
1342         if (qmp_chardev_open_socket_server(chr, is_telnet || is_tn3270,
1343                                            is_waitconnect, errp) < 0) {
1344             return;
1345         }
1346     } else {
1347         if (qmp_chardev_open_socket_client(chr, reconnect, errp) < 0) {
1348             return;
1349         }
1350     }
1351 }
1352 
1353 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
1354                                   Error **errp)
1355 {
1356     const char *path = qemu_opt_get(opts, "path");
1357     const char *host = qemu_opt_get(opts, "host");
1358     const char *port = qemu_opt_get(opts, "port");
1359     const char *fd = qemu_opt_get(opts, "fd");
1360     SocketAddressLegacy *addr;
1361     ChardevSocket *sock;
1362 
1363     if ((!!path + !!fd + !!host) != 1) {
1364         error_setg(errp,
1365                    "Exactly one of 'path', 'fd' or 'host' required");
1366         return;
1367     }
1368 
1369     if (host && !port) {
1370         error_setg(errp, "chardev: socket: no port given");
1371         return;
1372     }
1373 
1374     backend->type = CHARDEV_BACKEND_KIND_SOCKET;
1375     sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
1376     qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
1377 
1378     sock->has_nodelay = qemu_opt_get(opts, "delay");
1379     sock->nodelay = !qemu_opt_get_bool(opts, "delay", true);
1380     /*
1381      * We have different default to QMP for 'server', hence
1382      * we can't just check for existence of 'server'
1383      */
1384     sock->has_server = true;
1385     sock->server = qemu_opt_get_bool(opts, "server", false);
1386     sock->has_telnet = qemu_opt_get(opts, "telnet");
1387     sock->telnet = qemu_opt_get_bool(opts, "telnet", false);
1388     sock->has_tn3270 = qemu_opt_get(opts, "tn3270");
1389     sock->tn3270 = qemu_opt_get_bool(opts, "tn3270", false);
1390     sock->has_websocket = qemu_opt_get(opts, "websocket");
1391     sock->websocket = qemu_opt_get_bool(opts, "websocket", false);
1392     /*
1393      * We have different default to QMP for 'wait' when 'server'
1394      * is set, hence we can't just check for existence of 'wait'
1395      */
1396     sock->has_wait = qemu_opt_find(opts, "wait") || sock->server;
1397     sock->wait = qemu_opt_get_bool(opts, "wait", true);
1398     sock->has_reconnect = qemu_opt_find(opts, "reconnect");
1399     sock->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
1400     sock->has_tls_creds = qemu_opt_get(opts, "tls-creds");
1401     sock->tls_creds = g_strdup(qemu_opt_get(opts, "tls-creds"));
1402 
1403     addr = g_new0(SocketAddressLegacy, 1);
1404     if (path) {
1405         UnixSocketAddress *q_unix;
1406         addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
1407         q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
1408         q_unix->path = g_strdup(path);
1409     } else if (host) {
1410         addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
1411         addr->u.inet.data = g_new(InetSocketAddress, 1);
1412         *addr->u.inet.data = (InetSocketAddress) {
1413             .host = g_strdup(host),
1414             .port = g_strdup(port),
1415             .has_to = qemu_opt_get(opts, "to"),
1416             .to = qemu_opt_get_number(opts, "to", 0),
1417             .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1418             .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1419             .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1420             .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1421         };
1422     } else if (fd) {
1423         addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
1424         addr->u.fd.data = g_new(String, 1);
1425         addr->u.fd.data->str = g_strdup(fd);
1426     } else {
1427         g_assert_not_reached();
1428     }
1429     sock->addr = addr;
1430 }
1431 
1432 static void
1433 char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1434                      void *opaque, Error **errp)
1435 {
1436     SocketChardev *s = SOCKET_CHARDEV(obj);
1437 
1438     visit_type_SocketAddress(v, name, &s->addr, errp);
1439 }
1440 
1441 static bool
1442 char_socket_get_connected(Object *obj, Error **errp)
1443 {
1444     SocketChardev *s = SOCKET_CHARDEV(obj);
1445 
1446     return s->state == TCP_CHARDEV_STATE_CONNECTED;
1447 }
1448 
1449 static void char_socket_class_init(ObjectClass *oc, void *data)
1450 {
1451     ChardevClass *cc = CHARDEV_CLASS(oc);
1452 
1453     cc->parse = qemu_chr_parse_socket;
1454     cc->open = qmp_chardev_open_socket;
1455     cc->chr_wait_connected = tcp_chr_wait_connected;
1456     cc->chr_write = tcp_chr_write;
1457     cc->chr_sync_read = tcp_chr_sync_read;
1458     cc->chr_disconnect = tcp_chr_disconnect;
1459     cc->get_msgfds = tcp_get_msgfds;
1460     cc->set_msgfds = tcp_set_msgfds;
1461     cc->chr_add_client = tcp_chr_add_client;
1462     cc->chr_add_watch = tcp_chr_add_watch;
1463     cc->chr_update_read_handler = tcp_chr_update_read_handler;
1464 
1465     object_class_property_add(oc, "addr", "SocketAddress",
1466                               char_socket_get_addr, NULL,
1467                               NULL, NULL, &error_abort);
1468 
1469     object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1470                                    NULL, &error_abort);
1471 }
1472 
1473 static const TypeInfo char_socket_type_info = {
1474     .name = TYPE_CHARDEV_SOCKET,
1475     .parent = TYPE_CHARDEV,
1476     .instance_size = sizeof(SocketChardev),
1477     .instance_finalize = char_socket_finalize,
1478     .class_init = char_socket_class_init,
1479 };
1480 
1481 static void register_types(void)
1482 {
1483     type_register_static(&char_socket_type_info);
1484 }
1485 
1486 type_init(register_types);
1487