1 #include "qemu/osdep.h"
2 #include <glib/gstdio.h>
3 
4 #include "qemu/config-file.h"
5 #include "qemu/module.h"
6 #include "qemu/option.h"
7 #include "qemu/sockets.h"
8 #include "chardev/char-fe.h"
9 #include "chardev/char-mux.h"
10 #include "sysemu/sysemu.h"
11 #include "qapi/error.h"
12 #include "qapi/qapi-commands-char.h"
13 #include "qapi/qmp/qdict.h"
14 #include "qom/qom-qobject.h"
15 #include "io/channel-socket.h"
16 #include "qapi/qobject-input-visitor.h"
17 #include "qapi/qapi-visit-sockets.h"
18 #include "socket-helpers.h"
19 
20 static bool quit;
21 
22 typedef struct FeHandler {
23     int read_count;
24     bool is_open;
25     int openclose_count;
26     bool openclose_mismatch;
27     int last_event;
28     char read_buf[128];
29 } FeHandler;
30 
main_loop(void)31 static void main_loop(void)
32 {
33     quit = false;
34     do {
35         main_loop_wait(false);
36     } while (!quit);
37 }
38 
fe_can_read(void * opaque)39 static int fe_can_read(void *opaque)
40 {
41     FeHandler *h = opaque;
42 
43     return sizeof(h->read_buf) - h->read_count;
44 }
45 
fe_read(void * opaque,const uint8_t * buf,int size)46 static void fe_read(void *opaque, const uint8_t *buf, int size)
47 {
48     FeHandler *h = opaque;
49 
50     g_assert_cmpint(size, <=, fe_can_read(opaque));
51 
52     memcpy(h->read_buf + h->read_count, buf, size);
53     h->read_count += size;
54     quit = true;
55 }
56 
fe_event(void * opaque,int event)57 static void fe_event(void *opaque, int event)
58 {
59     FeHandler *h = opaque;
60     bool new_open_state;
61 
62     h->last_event = event;
63     switch (event) {
64     case CHR_EVENT_BREAK:
65         break;
66     case CHR_EVENT_OPENED:
67     case CHR_EVENT_CLOSED:
68         h->openclose_count++;
69         new_open_state = (event == CHR_EVENT_OPENED);
70         if (h->is_open == new_open_state) {
71             h->openclose_mismatch = true;
72         }
73         h->is_open = new_open_state;
74         /* no break */
75     default:
76         quit = true;
77         break;
78     }
79 }
80 
81 #ifdef _WIN32
char_console_test_subprocess(void)82 static void char_console_test_subprocess(void)
83 {
84     QemuOpts *opts;
85     Chardev *chr;
86 
87     opts = qemu_opts_create(qemu_find_opts("chardev"), "console-label",
88                             1, &error_abort);
89     qemu_opt_set(opts, "backend", "console", &error_abort);
90 
91     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
92     g_assert_nonnull(chr);
93 
94     qemu_chr_write_all(chr, (const uint8_t *)"CONSOLE", 7);
95 
96     qemu_opts_del(opts);
97     object_unparent(OBJECT(chr));
98 }
99 
char_console_test(void)100 static void char_console_test(void)
101 {
102     g_test_trap_subprocess("/char/console/subprocess", 0, 0);
103     g_test_trap_assert_passed();
104     g_test_trap_assert_stdout("CONSOLE");
105 }
106 #endif
char_stdio_test_subprocess(void)107 static void char_stdio_test_subprocess(void)
108 {
109     Chardev *chr;
110     CharBackend be;
111     int ret;
112 
113     chr = qemu_chr_new("label", "stdio", NULL);
114     g_assert_nonnull(chr);
115 
116     qemu_chr_fe_init(&be, chr, &error_abort);
117     qemu_chr_fe_set_open(&be, true);
118     ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
119     g_assert_cmpint(ret, ==, 4);
120 
121     qemu_chr_fe_deinit(&be, true);
122 }
123 
char_stdio_test(void)124 static void char_stdio_test(void)
125 {
126     g_test_trap_subprocess("/char/stdio/subprocess", 0, 0);
127     g_test_trap_assert_passed();
128     g_test_trap_assert_stdout("buf");
129 }
130 
char_ringbuf_test(void)131 static void char_ringbuf_test(void)
132 {
133     QemuOpts *opts;
134     Chardev *chr;
135     CharBackend be;
136     char *data;
137     int ret;
138 
139     opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
140                             1, &error_abort);
141     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
142 
143     qemu_opt_set(opts, "size", "5", &error_abort);
144     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
145     g_assert_null(chr);
146     qemu_opts_del(opts);
147 
148     opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
149                             1, &error_abort);
150     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
151     qemu_opt_set(opts, "size", "2", &error_abort);
152     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
153     g_assert_nonnull(chr);
154     qemu_opts_del(opts);
155 
156     qemu_chr_fe_init(&be, chr, &error_abort);
157     ret = qemu_chr_fe_write(&be, (void *)"buff", 4);
158     g_assert_cmpint(ret, ==, 4);
159 
160     data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
161     g_assert_cmpstr(data, ==, "ff");
162     g_free(data);
163 
164     data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
165     g_assert_cmpstr(data, ==, "");
166     g_free(data);
167 
168     qemu_chr_fe_deinit(&be, true);
169 
170     /* check alias */
171     opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label",
172                             1, &error_abort);
173     qemu_opt_set(opts, "backend", "memory", &error_abort);
174     qemu_opt_set(opts, "size", "2", &error_abort);
175     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
176     g_assert_nonnull(chr);
177     object_unparent(OBJECT(chr));
178     qemu_opts_del(opts);
179 }
180 
char_mux_test(void)181 static void char_mux_test(void)
182 {
183     QemuOpts *opts;
184     Chardev *chr, *base;
185     char *data;
186     FeHandler h1 = { 0, false, 0, false, }, h2 = { 0, false, 0, false, };
187     CharBackend chr_be1, chr_be2;
188 
189     opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
190                             1, &error_abort);
191     qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
192     qemu_opt_set(opts, "size", "128", &error_abort);
193     qemu_opt_set(opts, "mux", "on", &error_abort);
194     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
195     g_assert_nonnull(chr);
196     qemu_opts_del(opts);
197 
198     qemu_chr_fe_init(&chr_be1, chr, &error_abort);
199     qemu_chr_fe_set_handlers(&chr_be1,
200                              fe_can_read,
201                              fe_read,
202                              fe_event,
203                              NULL,
204                              &h1,
205                              NULL, true);
206 
207     qemu_chr_fe_init(&chr_be2, chr, &error_abort);
208     qemu_chr_fe_set_handlers(&chr_be2,
209                              fe_can_read,
210                              fe_read,
211                              fe_event,
212                              NULL,
213                              &h2,
214                              NULL, true);
215     qemu_chr_fe_take_focus(&chr_be2);
216 
217     base = qemu_chr_find("mux-label-base");
218     g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0);
219 
220     qemu_chr_be_write(base, (void *)"hello", 6);
221     g_assert_cmpint(h1.read_count, ==, 0);
222     g_assert_cmpint(h2.read_count, ==, 6);
223     g_assert_cmpstr(h2.read_buf, ==, "hello");
224     h2.read_count = 0;
225 
226     g_assert_cmpint(h1.last_event, !=, 42); /* should be MUX_OUT or OPENED */
227     g_assert_cmpint(h2.last_event, !=, 42); /* should be MUX_IN or OPENED */
228     /* sending event on the base broadcast to all fe, historical reasons? */
229     qemu_chr_be_event(base, 42);
230     g_assert_cmpint(h1.last_event, ==, 42);
231     g_assert_cmpint(h2.last_event, ==, 42);
232     qemu_chr_be_event(chr, -1);
233     g_assert_cmpint(h1.last_event, ==, 42);
234     g_assert_cmpint(h2.last_event, ==, -1);
235 
236     /* switch focus */
237     qemu_chr_be_write(base, (void *)"\1b", 2);
238     g_assert_cmpint(h1.last_event, ==, 42);
239     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_BREAK);
240 
241     qemu_chr_be_write(base, (void *)"\1c", 2);
242     g_assert_cmpint(h1.last_event, ==, CHR_EVENT_MUX_IN);
243     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
244     qemu_chr_be_event(chr, -1);
245     g_assert_cmpint(h1.last_event, ==, -1);
246     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
247 
248     qemu_chr_be_write(base, (void *)"hello", 6);
249     g_assert_cmpint(h2.read_count, ==, 0);
250     g_assert_cmpint(h1.read_count, ==, 6);
251     g_assert_cmpstr(h1.read_buf, ==, "hello");
252     h1.read_count = 0;
253 
254     qemu_chr_be_write(base, (void *)"\1b", 2);
255     g_assert_cmpint(h1.last_event, ==, CHR_EVENT_BREAK);
256     g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT);
257 
258     /* open/close state and corresponding events */
259     g_assert_true(qemu_chr_fe_backend_open(&chr_be1));
260     g_assert_true(qemu_chr_fe_backend_open(&chr_be2));
261     g_assert_true(h1.is_open);
262     g_assert_false(h1.openclose_mismatch);
263     g_assert_true(h2.is_open);
264     g_assert_false(h2.openclose_mismatch);
265 
266     h1.openclose_count = h2.openclose_count = 0;
267 
268     qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
269                              NULL, NULL, false);
270     qemu_chr_fe_set_handlers(&chr_be2, NULL, NULL, NULL, NULL,
271                              NULL, NULL, false);
272     g_assert_cmpint(h1.openclose_count, ==, 0);
273     g_assert_cmpint(h2.openclose_count, ==, 0);
274 
275     h1.is_open = h2.is_open = false;
276     qemu_chr_fe_set_handlers(&chr_be1,
277                              NULL,
278                              NULL,
279                              fe_event,
280                              NULL,
281                              &h1,
282                              NULL, false);
283     qemu_chr_fe_set_handlers(&chr_be2,
284                              NULL,
285                              NULL,
286                              fe_event,
287                              NULL,
288                              &h2,
289                              NULL, false);
290     g_assert_cmpint(h1.openclose_count, ==, 1);
291     g_assert_false(h1.openclose_mismatch);
292     g_assert_cmpint(h2.openclose_count, ==, 1);
293     g_assert_false(h2.openclose_mismatch);
294 
295     qemu_chr_be_event(base, CHR_EVENT_CLOSED);
296     qemu_chr_be_event(base, CHR_EVENT_OPENED);
297     g_assert_cmpint(h1.openclose_count, ==, 3);
298     g_assert_false(h1.openclose_mismatch);
299     g_assert_cmpint(h2.openclose_count, ==, 3);
300     g_assert_false(h2.openclose_mismatch);
301 
302     qemu_chr_fe_set_handlers(&chr_be2,
303                              fe_can_read,
304                              fe_read,
305                              fe_event,
306                              NULL,
307                              &h2,
308                              NULL, false);
309     qemu_chr_fe_set_handlers(&chr_be1,
310                              fe_can_read,
311                              fe_read,
312                              fe_event,
313                              NULL,
314                              &h1,
315                              NULL, false);
316 
317     /* remove first handler */
318     qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL,
319                              NULL, NULL, true);
320     qemu_chr_be_write(base, (void *)"hello", 6);
321     g_assert_cmpint(h1.read_count, ==, 0);
322     g_assert_cmpint(h2.read_count, ==, 0);
323 
324     qemu_chr_be_write(base, (void *)"\1c", 2);
325     qemu_chr_be_write(base, (void *)"hello", 6);
326     g_assert_cmpint(h1.read_count, ==, 0);
327     g_assert_cmpint(h2.read_count, ==, 6);
328     g_assert_cmpstr(h2.read_buf, ==, "hello");
329     h2.read_count = 0;
330 
331     /* print help */
332     qemu_chr_be_write(base, (void *)"\1?", 2);
333     data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort);
334     g_assert_cmpint(strlen(data), !=, 0);
335     g_free(data);
336 
337     qemu_chr_fe_deinit(&chr_be1, false);
338     qemu_chr_fe_deinit(&chr_be2, true);
339 }
340 
341 
websock_server_read(void * opaque,const uint8_t * buf,int size)342 static void websock_server_read(void *opaque, const uint8_t *buf, int size)
343 {
344     g_assert_cmpint(size, ==, 5);
345     g_assert(memcmp(buf, "world", size) == 0);
346     quit = true;
347 }
348 
349 
websock_server_can_read(void * opaque)350 static int websock_server_can_read(void *opaque)
351 {
352     return 10;
353 }
354 
355 
websock_check_http_headers(char * buf,int size)356 static bool websock_check_http_headers(char *buf, int size)
357 {
358     int i;
359     const char *ans[] = { "HTTP/1.1 101 Switching Protocols\r\n",
360                           "Server: QEMU VNC\r\n",
361                           "Upgrade: websocket\r\n",
362                           "Connection: Upgrade\r\n",
363                           "Sec-WebSocket-Accept:",
364                           "Sec-WebSocket-Protocol: binary\r\n" };
365 
366     for (i = 0; i < 6; i++) {
367         if (g_strstr_len(buf, size, ans[i]) == NULL) {
368             return false;
369         }
370     }
371 
372     return true;
373 }
374 
375 
websock_client_read(void * opaque,const uint8_t * buf,int size)376 static void websock_client_read(void *opaque, const uint8_t *buf, int size)
377 {
378     const uint8_t ping[] = { 0x89, 0x85,                  /* Ping header */
379                              0x07, 0x77, 0x9e, 0xf9,      /* Masking key */
380                              0x6f, 0x12, 0xf2, 0x95, 0x68 /* "hello" */ };
381 
382     const uint8_t binary[] = { 0x82, 0x85,                  /* Binary header */
383                                0x74, 0x90, 0xb9, 0xdf,      /* Masking key */
384                                0x03, 0xff, 0xcb, 0xb3, 0x10 /* "world" */ };
385     Chardev *chr_client = opaque;
386 
387     if (websock_check_http_headers((char *) buf, size)) {
388         qemu_chr_fe_write(chr_client->be, ping, sizeof(ping));
389     } else if (buf[0] == 0x8a && buf[1] == 0x05) {
390         g_assert(strncmp((char *) buf + 2, "hello", 5) == 0);
391         qemu_chr_fe_write(chr_client->be, binary, sizeof(binary));
392     } else {
393         g_assert(buf[0] == 0x88 && buf[1] == 0x16);
394         g_assert(strncmp((char *) buf + 4, "peer requested close", 10) == 0);
395         quit = true;
396     }
397 }
398 
399 
websock_client_can_read(void * opaque)400 static int websock_client_can_read(void *opaque)
401 {
402     return 4096;
403 }
404 
405 
char_websock_test(void)406 static void char_websock_test(void)
407 {
408     QObject *addr;
409     QDict *qdict;
410     const char *port;
411     char *tmp;
412     char *handshake_port;
413     CharBackend be;
414     CharBackend client_be;
415     Chardev *chr_client;
416     Chardev *chr = qemu_chr_new("server",
417                                 "websocket:127.0.0.1:0,server,nowait", NULL);
418     const char handshake[] = "GET / HTTP/1.1\r\n"
419                              "Upgrade: websocket\r\n"
420                              "Connection: Upgrade\r\n"
421                              "Host: localhost:%s\r\n"
422                              "Origin: http://localhost:%s\r\n"
423                              "Sec-WebSocket-Key: o9JHNiS3/0/0zYE1wa3yIw==\r\n"
424                              "Sec-WebSocket-Version: 13\r\n"
425                              "Sec-WebSocket-Protocol: binary\r\n\r\n";
426     const uint8_t close[] = { 0x88, 0x82,             /* Close header */
427                               0xef, 0xaa, 0xc5, 0x97, /* Masking key */
428                               0xec, 0x42              /* Status code */ };
429 
430     addr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
431     qdict = qobject_to(QDict, addr);
432     port = qdict_get_str(qdict, "port");
433     tmp = g_strdup_printf("tcp:127.0.0.1:%s", port);
434     handshake_port = g_strdup_printf(handshake, port, port);
435     qobject_unref(qdict);
436 
437     qemu_chr_fe_init(&be, chr, &error_abort);
438     qemu_chr_fe_set_handlers(&be, websock_server_can_read, websock_server_read,
439                              NULL, NULL, chr, NULL, true);
440 
441     chr_client = qemu_chr_new("client", tmp, NULL);
442     qemu_chr_fe_init(&client_be, chr_client, &error_abort);
443     qemu_chr_fe_set_handlers(&client_be, websock_client_can_read,
444                              websock_client_read,
445                              NULL, NULL, chr_client, NULL, true);
446     g_free(tmp);
447 
448     qemu_chr_write_all(chr_client,
449                        (uint8_t *) handshake_port,
450                        strlen(handshake_port));
451     g_free(handshake_port);
452     main_loop();
453 
454     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
455     g_assert(object_property_get_bool(OBJECT(chr_client),
456                                       "connected", &error_abort));
457 
458     qemu_chr_write_all(chr_client, close, sizeof(close));
459     main_loop();
460 
461     object_unparent(OBJECT(chr_client));
462     object_unparent(OBJECT(chr));
463 }
464 
465 
466 #ifndef _WIN32
char_pipe_test(void)467 static void char_pipe_test(void)
468 {
469     gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
470     gchar *tmp, *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL);
471     Chardev *chr;
472     CharBackend be;
473     int ret, fd;
474     char buf[10];
475     FeHandler fe = { 0, };
476 
477     in = g_strdup_printf("%s.in", pipe);
478     if (mkfifo(in, 0600) < 0) {
479         abort();
480     }
481     out = g_strdup_printf("%s.out", pipe);
482     if (mkfifo(out, 0600) < 0) {
483         abort();
484     }
485 
486     tmp = g_strdup_printf("pipe:%s", pipe);
487     chr = qemu_chr_new("pipe", tmp, NULL);
488     g_assert_nonnull(chr);
489     g_free(tmp);
490 
491     qemu_chr_fe_init(&be, chr, &error_abort);
492 
493     ret = qemu_chr_fe_write(&be, (void *)"pipe-out", 9);
494     g_assert_cmpint(ret, ==, 9);
495 
496     fd = open(out, O_RDWR);
497     ret = read(fd, buf, sizeof(buf));
498     g_assert_cmpint(ret, ==, 9);
499     g_assert_cmpstr(buf, ==, "pipe-out");
500     close(fd);
501 
502     fd = open(in, O_WRONLY);
503     ret = write(fd, "pipe-in", 8);
504     g_assert_cmpint(ret, ==, 8);
505     close(fd);
506 
507     qemu_chr_fe_set_handlers(&be,
508                              fe_can_read,
509                              fe_read,
510                              fe_event,
511                              NULL,
512                              &fe,
513                              NULL, true);
514 
515     main_loop();
516 
517     g_assert_cmpint(fe.read_count, ==, 8);
518     g_assert_cmpstr(fe.read_buf, ==, "pipe-in");
519 
520     qemu_chr_fe_deinit(&be, true);
521 
522     g_assert(g_unlink(in) == 0);
523     g_assert(g_unlink(out) == 0);
524     g_assert(g_rmdir(tmp_path) == 0);
525     g_free(in);
526     g_free(out);
527     g_free(tmp_path);
528     g_free(pipe);
529 }
530 #endif
531 
532 typedef struct SocketIdleData {
533     GMainLoop *loop;
534     Chardev *chr;
535     bool conn_expected;
536     CharBackend *be;
537     CharBackend *client_be;
538 } SocketIdleData;
539 
540 
socket_read_hello(void * opaque,const uint8_t * buf,int size)541 static void socket_read_hello(void *opaque, const uint8_t *buf, int size)
542 {
543     g_assert_cmpint(size, ==, 5);
544     g_assert(strncmp((char *)buf, "hello", 5) == 0);
545 
546     quit = true;
547 }
548 
socket_can_read_hello(void * opaque)549 static int socket_can_read_hello(void *opaque)
550 {
551     return 10;
552 }
553 
make_udp_socket(int * port)554 static int make_udp_socket(int *port)
555 {
556     struct sockaddr_in addr = { 0, };
557     socklen_t alen = sizeof(addr);
558     int ret, sock = qemu_socket(PF_INET, SOCK_DGRAM, 0);
559 
560     g_assert_cmpint(sock, >, 0);
561     addr.sin_family = AF_INET ;
562     addr.sin_addr.s_addr = htonl(INADDR_ANY);
563     addr.sin_port = 0;
564     ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
565     g_assert_cmpint(ret, ==, 0);
566     ret = getsockname(sock, (struct sockaddr *)&addr, &alen);
567     g_assert_cmpint(ret, ==, 0);
568 
569     *port = ntohs(addr.sin_port);
570     return sock;
571 }
572 
char_udp_test_internal(Chardev * reuse_chr,int sock)573 static void char_udp_test_internal(Chardev *reuse_chr, int sock)
574 {
575     struct sockaddr_in other;
576     SocketIdleData d = { 0, };
577     Chardev *chr;
578     CharBackend *be;
579     socklen_t alen = sizeof(other);
580     int ret;
581     char buf[10];
582     char *tmp = NULL;
583 
584     if (reuse_chr) {
585         chr = reuse_chr;
586         be = chr->be;
587     } else {
588         int port;
589         sock = make_udp_socket(&port);
590         tmp = g_strdup_printf("udp:127.0.0.1:%d", port);
591         chr = qemu_chr_new("client", tmp, NULL);
592         g_assert_nonnull(chr);
593 
594         be = g_alloca(sizeof(CharBackend));
595         qemu_chr_fe_init(be, chr, &error_abort);
596     }
597 
598     d.chr = chr;
599     qemu_chr_fe_set_handlers(be, socket_can_read_hello, socket_read_hello,
600                              NULL, NULL, &d, NULL, true);
601     ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5);
602     g_assert_cmpint(ret, ==, 5);
603 
604     ret = recvfrom(sock, buf, sizeof(buf), 0,
605                    (struct sockaddr *)&other, &alen);
606     g_assert_cmpint(ret, ==, 5);
607     ret = sendto(sock, buf, 5, 0, (struct sockaddr *)&other, alen);
608     g_assert_cmpint(ret, ==, 5);
609 
610     main_loop();
611 
612     if (!reuse_chr) {
613         close(sock);
614         qemu_chr_fe_deinit(be, true);
615     }
616     g_free(tmp);
617 }
618 
char_udp_test(void)619 static void char_udp_test(void)
620 {
621     char_udp_test_internal(NULL, 0);
622 }
623 
624 
625 typedef struct {
626     int event;
627     bool got_pong;
628 } CharSocketTestData;
629 
630 
631 #define SOCKET_PING "Hello"
632 #define SOCKET_PONG "World"
633 
634 
635 static void
char_socket_event(void * opaque,int event)636 char_socket_event(void *opaque, int event)
637 {
638     CharSocketTestData *data = opaque;
639     data->event = event;
640 }
641 
642 
643 static void
char_socket_read(void * opaque,const uint8_t * buf,int size)644 char_socket_read(void *opaque, const uint8_t *buf, int size)
645 {
646     CharSocketTestData *data = opaque;
647     g_assert_cmpint(size, ==, sizeof(SOCKET_PONG));
648     g_assert(memcmp(buf, SOCKET_PONG, size) == 0);
649     data->got_pong = true;
650 }
651 
652 
653 static int
char_socket_can_read(void * opaque)654 char_socket_can_read(void *opaque)
655 {
656     return sizeof(SOCKET_PONG);
657 }
658 
659 
660 static char *
char_socket_addr_to_opt_str(SocketAddress * addr,bool fd_pass,const char * reconnect,bool is_listen)661 char_socket_addr_to_opt_str(SocketAddress *addr, bool fd_pass,
662                             const char *reconnect, bool is_listen)
663 {
664     if (fd_pass) {
665         QIOChannelSocket *ioc = qio_channel_socket_new();
666         int fd;
667         char *optstr;
668         g_assert(!reconnect);
669         if (is_listen) {
670             qio_channel_socket_listen_sync(ioc, addr, 1, &error_abort);
671         } else {
672             qio_channel_socket_connect_sync(ioc, addr, &error_abort);
673         }
674         fd = ioc->fd;
675         ioc->fd = -1;
676         optstr = g_strdup_printf("socket,id=cdev0,fd=%d%s",
677                                  fd, is_listen ? ",server,nowait" : "");
678         object_unref(OBJECT(ioc));
679         return optstr;
680     } else {
681         switch (addr->type) {
682         case SOCKET_ADDRESS_TYPE_INET:
683             return g_strdup_printf("socket,id=cdev0,host=%s,port=%s%s%s",
684                                    addr->u.inet.host,
685                                    addr->u.inet.port,
686                                    reconnect ? reconnect : "",
687                                    is_listen ? ",server,nowait" : "");
688 
689         case SOCKET_ADDRESS_TYPE_UNIX:
690             return g_strdup_printf("socket,id=cdev0,path=%s%s%s",
691                                    addr->u.q_unix.path,
692                                    reconnect ? reconnect : "",
693                                    is_listen ? ",server,nowait" : "");
694 
695         default:
696             g_assert_not_reached();
697         }
698     }
699 }
700 
701 
702 static void
char_socket_ping_pong(QIOChannel * ioc)703 char_socket_ping_pong(QIOChannel *ioc)
704 {
705     char greeting[sizeof(SOCKET_PING)];
706     const char *response = SOCKET_PONG;
707 
708     qio_channel_read_all(ioc, greeting, sizeof(greeting), &error_abort);
709 
710     g_assert(memcmp(greeting, SOCKET_PING, sizeof(greeting)) == 0);
711 
712     qio_channel_write_all(ioc, response, sizeof(SOCKET_PONG), &error_abort);
713 
714     object_unref(OBJECT(ioc));
715 }
716 
717 
718 static gpointer
char_socket_server_client_thread(gpointer data)719 char_socket_server_client_thread(gpointer data)
720 {
721     SocketAddress *addr = data;
722     QIOChannelSocket *ioc = qio_channel_socket_new();
723 
724     qio_channel_socket_connect_sync(ioc, addr, &error_abort);
725 
726     char_socket_ping_pong(QIO_CHANNEL(ioc));
727 
728     return NULL;
729 }
730 
731 
732 typedef struct {
733     SocketAddress *addr;
734     bool wait_connected;
735     bool fd_pass;
736 } CharSocketServerTestConfig;
737 
738 
char_socket_server_test(gconstpointer opaque)739 static void char_socket_server_test(gconstpointer opaque)
740 {
741     const CharSocketServerTestConfig *config = opaque;
742     Chardev *chr;
743     CharBackend be = {0};
744     CharSocketTestData data = {0};
745     QObject *qaddr;
746     SocketAddress *addr;
747     Visitor *v;
748     QemuThread thread;
749     int ret;
750     bool reconnected = false;
751     char *optstr;
752     QemuOpts *opts;
753 
754     g_setenv("QTEST_SILENT_ERRORS", "1", 1);
755     /*
756      * We rely on config->addr containing "nowait", otherwise
757      * qemu_chr_new() will block until a client connects. We
758      * can't spawn our client thread though, because until
759      * qemu_chr_new() returns we don't know what TCP port was
760      * allocated by the OS
761      */
762     optstr = char_socket_addr_to_opt_str(config->addr,
763                                          config->fd_pass,
764                                          NULL,
765                                          true);
766     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
767                                    optstr, true);
768     g_assert_nonnull(opts);
769     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
770     qemu_opts_del(opts);
771     g_assert_nonnull(chr);
772     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
773 
774     qaddr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
775     g_assert_nonnull(qaddr);
776 
777     v = qobject_input_visitor_new(qaddr);
778     visit_type_SocketAddress(v, "addr", &addr, &error_abort);
779     visit_free(v);
780     qobject_unref(qaddr);
781 
782     qemu_chr_fe_init(&be, chr, &error_abort);
783 
784  reconnect:
785     data.event = -1;
786     qemu_chr_fe_set_handlers(&be, NULL, NULL,
787                              char_socket_event, NULL,
788                              &data, NULL, true);
789     g_assert(data.event == -1);
790 
791     /*
792      * Kick off a thread to act as the "remote" client
793      * which just plays ping-pong with us
794      */
795     qemu_thread_create(&thread, "client",
796                        char_socket_server_client_thread,
797                        addr, QEMU_THREAD_JOINABLE);
798     g_assert(data.event == -1);
799 
800     if (config->wait_connected) {
801         /* Synchronously accept a connection */
802         qemu_chr_wait_connected(chr, &error_abort);
803     } else {
804         /*
805          * Asynchronously accept a connection when the evnt
806          * loop reports the listener socket as readable
807          */
808         while (data.event == -1) {
809             main_loop_wait(false);
810         }
811     }
812     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
813     g_assert(data.event == CHR_EVENT_OPENED);
814     data.event = -1;
815 
816     /* Send a greeting to the client */
817     ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING,
818                                 sizeof(SOCKET_PING));
819     g_assert_cmpint(ret, ==, sizeof(SOCKET_PING));
820     g_assert(data.event == -1);
821 
822     /* Setup a callback to receive the reply to our greeting */
823     qemu_chr_fe_set_handlers(&be, char_socket_can_read,
824                              char_socket_read,
825                              char_socket_event, NULL,
826                              &data, NULL, true);
827     g_assert(data.event == CHR_EVENT_OPENED);
828     data.event = -1;
829 
830     /* Wait for the client to go away */
831     while (data.event == -1) {
832         main_loop_wait(false);
833     }
834     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
835     g_assert(data.event == CHR_EVENT_CLOSED);
836     g_assert(data.got_pong);
837 
838     qemu_thread_join(&thread);
839 
840     if (!reconnected) {
841         reconnected = true;
842         goto reconnect;
843     }
844 
845     qapi_free_SocketAddress(addr);
846     object_unparent(OBJECT(chr));
847     g_free(optstr);
848     g_unsetenv("QTEST_SILENT_ERRORS");
849 }
850 
851 
852 static gpointer
char_socket_client_server_thread(gpointer data)853 char_socket_client_server_thread(gpointer data)
854 {
855     QIOChannelSocket *ioc = data;
856     QIOChannelSocket *cioc;
857 
858     cioc = qio_channel_socket_accept(ioc, &error_abort);
859     g_assert_nonnull(cioc);
860 
861     char_socket_ping_pong(QIO_CHANNEL(cioc));
862 
863     return NULL;
864 }
865 
866 
867 typedef struct {
868     SocketAddress *addr;
869     const char *reconnect;
870     bool wait_connected;
871     bool fd_pass;
872 } CharSocketClientTestConfig;
873 
874 
char_socket_client_test(gconstpointer opaque)875 static void char_socket_client_test(gconstpointer opaque)
876 {
877     const CharSocketClientTestConfig *config = opaque;
878     QIOChannelSocket *ioc;
879     char *optstr;
880     Chardev *chr;
881     CharBackend be = {0};
882     CharSocketTestData data = {0};
883     SocketAddress *addr;
884     QemuThread thread;
885     int ret;
886     bool reconnected = false;
887     QemuOpts *opts;
888 
889     /*
890      * Setup a listener socket and determine get its address
891      * so we know the TCP port for the client later
892      */
893     ioc = qio_channel_socket_new();
894     g_assert_nonnull(ioc);
895     qio_channel_socket_listen_sync(ioc, config->addr, 1, &error_abort);
896     addr = qio_channel_socket_get_local_address(ioc, &error_abort);
897     g_assert_nonnull(addr);
898 
899     /*
900      * Kick off a thread to act as the "remote" client
901      * which just plays ping-pong with us
902      */
903     qemu_thread_create(&thread, "client",
904                        char_socket_client_server_thread,
905                        ioc, QEMU_THREAD_JOINABLE);
906 
907     /*
908      * Populate the chardev address based on what the server
909      * is actually listening on
910      */
911     optstr = char_socket_addr_to_opt_str(addr,
912                                          config->fd_pass,
913                                          config->reconnect,
914                                          false);
915 
916     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
917                                    optstr, true);
918     g_assert_nonnull(opts);
919     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
920     qemu_opts_del(opts);
921     g_assert_nonnull(chr);
922 
923     if (config->reconnect) {
924         /*
925          * If reconnect is set, the connection will be
926          * established in a background thread and we won't
927          * see the "connected" status updated until we
928          * run the main event loop, or call qemu_chr_wait_connected
929          */
930         g_assert(!object_property_get_bool(OBJECT(chr), "connected",
931                                            &error_abort));
932     } else {
933         g_assert(object_property_get_bool(OBJECT(chr), "connected",
934                                           &error_abort));
935     }
936 
937     qemu_chr_fe_init(&be, chr, &error_abort);
938 
939  reconnect:
940     data.event = -1;
941     qemu_chr_fe_set_handlers(&be, NULL, NULL,
942                              char_socket_event, NULL,
943                              &data, NULL, true);
944     if (config->reconnect) {
945         g_assert(data.event == -1);
946     } else {
947         g_assert(data.event == CHR_EVENT_OPENED);
948     }
949 
950     if (config->wait_connected) {
951         /*
952          * Synchronously wait for the connection to complete
953          * This should be a no-op if reconnect is not set.
954          */
955         qemu_chr_wait_connected(chr, &error_abort);
956     } else {
957         /*
958          * Asynchronously wait for the connection to be reported
959          * as complete when the background thread reports its
960          * status.
961          * The loop will short-circuit if reconnect was set
962          */
963         while (data.event == -1) {
964             main_loop_wait(false);
965         }
966     }
967     g_assert(data.event == CHR_EVENT_OPENED);
968     data.event = -1;
969     g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort));
970 
971     /* Send a greeting to the server */
972     ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING,
973                                 sizeof(SOCKET_PING));
974     g_assert_cmpint(ret, ==, sizeof(SOCKET_PING));
975     g_assert(data.event == -1);
976 
977     /* Setup a callback to receive the reply to our greeting */
978     qemu_chr_fe_set_handlers(&be, char_socket_can_read,
979                              char_socket_read,
980                              char_socket_event, NULL,
981                              &data, NULL, true);
982     g_assert(data.event == CHR_EVENT_OPENED);
983     data.event = -1;
984 
985     /* Wait for the server to go away */
986     while (data.event == -1) {
987         main_loop_wait(false);
988     }
989     g_assert(data.event == CHR_EVENT_CLOSED);
990     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
991     g_assert(data.got_pong);
992     qemu_thread_join(&thread);
993 
994     if (config->reconnect && !reconnected) {
995         reconnected = true;
996         qemu_thread_create(&thread, "client",
997                            char_socket_client_server_thread,
998                            ioc, QEMU_THREAD_JOINABLE);
999         goto reconnect;
1000     }
1001 
1002     object_unref(OBJECT(ioc));
1003     object_unparent(OBJECT(chr));
1004     qapi_free_SocketAddress(addr);
1005     g_free(optstr);
1006 }
1007 
1008 static void
count_closed_event(void * opaque,int event)1009 count_closed_event(void *opaque, int event)
1010 {
1011     int *count = opaque;
1012     if (event == CHR_EVENT_CLOSED) {
1013         (*count)++;
1014     }
1015 }
1016 
1017 static void
char_socket_discard_read(void * opaque,const uint8_t * buf,int size)1018 char_socket_discard_read(void *opaque, const uint8_t *buf, int size)
1019 {
1020 }
1021 
char_socket_server_two_clients_test(gconstpointer opaque)1022 static void char_socket_server_two_clients_test(gconstpointer opaque)
1023 {
1024     SocketAddress *incoming_addr = (gpointer) opaque;
1025     Chardev *chr;
1026     CharBackend be = {0};
1027     QObject *qaddr;
1028     SocketAddress *addr;
1029     Visitor *v;
1030     char *optstr;
1031     QemuOpts *opts;
1032     QIOChannelSocket *ioc1, *ioc2;
1033     int closed = 0;
1034 
1035     g_setenv("QTEST_SILENT_ERRORS", "1", 1);
1036     /*
1037      * We rely on addr containing "nowait", otherwise
1038      * qemu_chr_new() will block until a client connects. We
1039      * can't spawn our client thread though, because until
1040      * qemu_chr_new() returns we don't know what TCP port was
1041      * allocated by the OS
1042      */
1043     optstr = char_socket_addr_to_opt_str(incoming_addr,
1044                                          false,
1045                                          NULL,
1046                                          true);
1047     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"),
1048                                    optstr, true);
1049     g_assert_nonnull(opts);
1050     chr = qemu_chr_new_from_opts(opts, NULL, &error_abort);
1051     qemu_opts_del(opts);
1052     g_assert_nonnull(chr);
1053     g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_abort));
1054 
1055     qaddr = object_property_get_qobject(OBJECT(chr), "addr", &error_abort);
1056     g_assert_nonnull(qaddr);
1057 
1058     v = qobject_input_visitor_new(qaddr);
1059     visit_type_SocketAddress(v, "addr", &addr, &error_abort);
1060     visit_free(v);
1061     qobject_unref(qaddr);
1062 
1063     qemu_chr_fe_init(&be, chr, &error_abort);
1064 
1065     qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read,
1066                              count_closed_event, NULL,
1067                              &closed, NULL, true);
1068 
1069     ioc1 = qio_channel_socket_new();
1070     qio_channel_socket_connect_sync(ioc1, addr, &error_abort);
1071     qemu_chr_wait_connected(chr, &error_abort);
1072 
1073     /* switch the chardev to another context */
1074     GMainContext *ctx = g_main_context_new();
1075     qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read,
1076                              count_closed_event, NULL,
1077                              &closed, ctx, true);
1078 
1079     /* Start a second connection while the first is still connected.
1080      * It will be placed in the listen() backlog, and connect() will
1081      * succeed immediately.
1082      */
1083     ioc2 = qio_channel_socket_new();
1084     qio_channel_socket_connect_sync(ioc2, addr, &error_abort);
1085 
1086     object_unref(OBJECT(ioc1));
1087     /* The two connections should now be processed serially.  */
1088     while (g_main_context_iteration(ctx, TRUE)) {
1089         if (closed == 1 && ioc2) {
1090             object_unref(OBJECT(ioc2));
1091             ioc2 = NULL;
1092         }
1093         if (closed == 2) {
1094             break;
1095         }
1096     }
1097 
1098     qapi_free_SocketAddress(addr);
1099     object_unparent(OBJECT(chr));
1100     g_main_context_unref(ctx);
1101     g_free(optstr);
1102     g_unsetenv("QTEST_SILENT_ERRORS");
1103 }
1104 
1105 
1106 #if defined(HAVE_CHARDEV_SERIAL) && !defined(WIN32)
char_serial_test(void)1107 static void char_serial_test(void)
1108 {
1109     QemuOpts *opts;
1110     Chardev *chr;
1111 
1112     opts = qemu_opts_create(qemu_find_opts("chardev"), "serial-id",
1113                             1, &error_abort);
1114     qemu_opt_set(opts, "backend", "serial", &error_abort);
1115     qemu_opt_set(opts, "path", "/dev/null", &error_abort);
1116 
1117     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
1118     g_assert_nonnull(chr);
1119     /* TODO: add more tests with a pty */
1120     object_unparent(OBJECT(chr));
1121 
1122     /* test tty alias */
1123     qemu_opt_set(opts, "backend", "tty", &error_abort);
1124     chr = qemu_chr_new_from_opts(opts, NULL, NULL);
1125     g_assert_nonnull(chr);
1126     object_unparent(OBJECT(chr));
1127 
1128     qemu_opts_del(opts);
1129 }
1130 #endif
1131 
1132 #ifndef _WIN32
char_file_fifo_test(void)1133 static void char_file_fifo_test(void)
1134 {
1135     Chardev *chr;
1136     CharBackend be;
1137     char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
1138     char *fifo = g_build_filename(tmp_path, "fifo", NULL);
1139     char *out = g_build_filename(tmp_path, "out", NULL);
1140     ChardevFile file = { .in = fifo,
1141                          .has_in = true,
1142                          .out = out };
1143     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
1144                                .u.file.data = &file };
1145     FeHandler fe = { 0, };
1146     int fd, ret;
1147 
1148     if (mkfifo(fifo, 0600) < 0) {
1149         abort();
1150     }
1151 
1152     fd = open(fifo, O_RDWR);
1153     ret = write(fd, "fifo-in", 8);
1154     g_assert_cmpint(ret, ==, 8);
1155 
1156     chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend,
1157                            NULL, &error_abort);
1158 
1159     qemu_chr_fe_init(&be, chr, &error_abort);
1160     qemu_chr_fe_set_handlers(&be,
1161                              fe_can_read,
1162                              fe_read,
1163                              fe_event,
1164                              NULL,
1165                              &fe, NULL, true);
1166 
1167     g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
1168     qmp_chardev_send_break("label-foo", NULL);
1169     g_assert_cmpint(fe.last_event, !=, CHR_EVENT_BREAK);
1170     qmp_chardev_send_break("label-file", NULL);
1171     g_assert_cmpint(fe.last_event, ==, CHR_EVENT_BREAK);
1172 
1173     main_loop();
1174 
1175     close(fd);
1176 
1177     g_assert_cmpint(fe.read_count, ==, 8);
1178     g_assert_cmpstr(fe.read_buf, ==, "fifo-in");
1179 
1180     qemu_chr_fe_deinit(&be, true);
1181 
1182     g_unlink(fifo);
1183     g_free(fifo);
1184     g_unlink(out);
1185     g_free(out);
1186     g_rmdir(tmp_path);
1187     g_free(tmp_path);
1188 }
1189 #endif
1190 
char_file_test_internal(Chardev * ext_chr,const char * filepath)1191 static void char_file_test_internal(Chardev *ext_chr, const char *filepath)
1192 {
1193     char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
1194     char *out;
1195     Chardev *chr;
1196     char *contents = NULL;
1197     ChardevFile file = {};
1198     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
1199                                .u.file.data = &file };
1200     gsize length;
1201     int ret;
1202 
1203     if (ext_chr) {
1204         chr = ext_chr;
1205         out = g_strdup(filepath);
1206         file.out = out;
1207     } else {
1208         out = g_build_filename(tmp_path, "out", NULL);
1209         file.out = out;
1210         chr = qemu_chardev_new(NULL, TYPE_CHARDEV_FILE, &backend,
1211                                NULL, &error_abort);
1212     }
1213     ret = qemu_chr_write_all(chr, (uint8_t *)"hello!", 6);
1214     g_assert_cmpint(ret, ==, 6);
1215 
1216     ret = g_file_get_contents(out, &contents, &length, NULL);
1217     g_assert(ret == TRUE);
1218     g_assert_cmpint(length, ==, 6);
1219     g_assert(strncmp(contents, "hello!", 6) == 0);
1220 
1221     if (!ext_chr) {
1222         object_unref(OBJECT(chr));
1223         g_unlink(out);
1224     }
1225     g_free(contents);
1226     g_rmdir(tmp_path);
1227     g_free(tmp_path);
1228     g_free(out);
1229 }
1230 
char_file_test(void)1231 static void char_file_test(void)
1232 {
1233     char_file_test_internal(NULL, NULL);
1234 }
1235 
char_null_test(void)1236 static void char_null_test(void)
1237 {
1238     Error *err = NULL;
1239     Chardev *chr;
1240     CharBackend be;
1241     int ret;
1242 
1243     chr = qemu_chr_find("label-null");
1244     g_assert_null(chr);
1245 
1246     chr = qemu_chr_new("label-null", "null", NULL);
1247     chr = qemu_chr_find("label-null");
1248     g_assert_nonnull(chr);
1249 
1250     g_assert(qemu_chr_has_feature(chr,
1251                  QEMU_CHAR_FEATURE_FD_PASS) == false);
1252     g_assert(qemu_chr_has_feature(chr,
1253                  QEMU_CHAR_FEATURE_RECONNECTABLE) == false);
1254 
1255     /* check max avail */
1256     qemu_chr_fe_init(&be, chr, &error_abort);
1257     qemu_chr_fe_init(&be, chr, &err);
1258     error_free_or_abort(&err);
1259 
1260     /* deinit & reinit */
1261     qemu_chr_fe_deinit(&be, false);
1262     qemu_chr_fe_init(&be, chr, &error_abort);
1263 
1264     qemu_chr_fe_set_open(&be, true);
1265 
1266     qemu_chr_fe_set_handlers(&be,
1267                              fe_can_read,
1268                              fe_read,
1269                              fe_event,
1270                              NULL,
1271                              NULL, NULL, true);
1272 
1273     ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
1274     g_assert_cmpint(ret, ==, 4);
1275 
1276     qemu_chr_fe_deinit(&be, true);
1277 }
1278 
char_invalid_test(void)1279 static void char_invalid_test(void)
1280 {
1281     Chardev *chr;
1282     g_setenv("QTEST_SILENT_ERRORS", "1", 1);
1283     chr = qemu_chr_new("label-invalid", "invalid", NULL);
1284     g_assert_null(chr);
1285     g_unsetenv("QTEST_SILENT_ERRORS");
1286 }
1287 
chardev_change(void * opaque)1288 static int chardev_change(void *opaque)
1289 {
1290     return 0;
1291 }
1292 
chardev_change_denied(void * opaque)1293 static int chardev_change_denied(void *opaque)
1294 {
1295     return -1;
1296 }
1297 
char_hotswap_test(void)1298 static void char_hotswap_test(void)
1299 {
1300     char *chr_args;
1301     Chardev *chr;
1302     CharBackend be;
1303 
1304     gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL);
1305     char *filename = g_build_filename(tmp_path, "file", NULL);
1306     ChardevFile file = { .out = filename };
1307     ChardevBackend backend = { .type = CHARDEV_BACKEND_KIND_FILE,
1308                                .u.file.data = &file };
1309     ChardevReturn *ret;
1310 
1311     int port;
1312     int sock = make_udp_socket(&port);
1313     g_assert_cmpint(sock, >, 0);
1314 
1315     chr_args = g_strdup_printf("udp:127.0.0.1:%d", port);
1316 
1317     chr = qemu_chr_new("chardev", chr_args, NULL);
1318     qemu_chr_fe_init(&be, chr, &error_abort);
1319 
1320     /* check that chardev operates correctly */
1321     char_udp_test_internal(chr, sock);
1322 
1323     /* set the handler that denies the hotswap */
1324     qemu_chr_fe_set_handlers(&be, NULL, NULL,
1325                              NULL, chardev_change_denied, NULL, NULL, true);
1326 
1327     /* now, change is denied and has to keep the old backend operating */
1328     ret = qmp_chardev_change("chardev", &backend, NULL);
1329     g_assert(!ret);
1330     g_assert(be.chr == chr);
1331 
1332     char_udp_test_internal(chr, sock);
1333 
1334     /* now allow the change */
1335     qemu_chr_fe_set_handlers(&be, NULL, NULL,
1336                              NULL, chardev_change, NULL, NULL, true);
1337 
1338     /* has to succeed now */
1339     ret = qmp_chardev_change("chardev", &backend, &error_abort);
1340     g_assert(be.chr != chr);
1341 
1342     close(sock);
1343     chr = be.chr;
1344 
1345     /* run the file chardev test */
1346     char_file_test_internal(chr, filename);
1347 
1348     object_unparent(OBJECT(chr));
1349 
1350     qapi_free_ChardevReturn(ret);
1351     g_unlink(filename);
1352     g_free(filename);
1353     g_rmdir(tmp_path);
1354     g_free(tmp_path);
1355     g_free(chr_args);
1356 }
1357 
1358 static SocketAddress tcpaddr = {
1359     .type = SOCKET_ADDRESS_TYPE_INET,
1360     .u.inet.host = (char *)"127.0.0.1",
1361     .u.inet.port = (char *)"0",
1362 };
1363 #ifndef WIN32
1364 static SocketAddress unixaddr = {
1365     .type = SOCKET_ADDRESS_TYPE_UNIX,
1366     .u.q_unix.path = (char *)"test-char.sock",
1367 };
1368 #endif
1369 
main(int argc,char ** argv)1370 int main(int argc, char **argv)
1371 {
1372     bool has_ipv4, has_ipv6;
1373 
1374     qemu_init_main_loop(&error_abort);
1375     socket_init();
1376 
1377     g_test_init(&argc, &argv, NULL);
1378 
1379     if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
1380         g_printerr("socket_check_protocol_support() failed\n");
1381         goto end;
1382     }
1383 
1384     module_call_init(MODULE_INIT_QOM);
1385     qemu_add_opts(&qemu_chardev_opts);
1386 
1387     g_test_add_func("/char/null", char_null_test);
1388     g_test_add_func("/char/invalid", char_invalid_test);
1389     g_test_add_func("/char/ringbuf", char_ringbuf_test);
1390     g_test_add_func("/char/mux", char_mux_test);
1391 #ifdef _WIN32
1392     g_test_add_func("/char/console/subprocess", char_console_test_subprocess);
1393     g_test_add_func("/char/console", char_console_test);
1394 #endif
1395     g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
1396     g_test_add_func("/char/stdio", char_stdio_test);
1397 #ifndef _WIN32
1398     g_test_add_func("/char/pipe", char_pipe_test);
1399 #endif
1400     g_test_add_func("/char/file", char_file_test);
1401 #ifndef _WIN32
1402     g_test_add_func("/char/file-fifo", char_file_fifo_test);
1403 #endif
1404 
1405 #define SOCKET_SERVER_TEST(name, addr)                                  \
1406     static CharSocketServerTestConfig server1 ## name =                 \
1407         { addr, false, false };                                         \
1408     static CharSocketServerTestConfig server2 ## name =                 \
1409         { addr, true, false };                                          \
1410     static CharSocketServerTestConfig server3 ## name =                 \
1411         { addr, false, true };                                          \
1412     static CharSocketServerTestConfig server4 ## name =                 \
1413         { addr, true, true };                                           \
1414     g_test_add_data_func("/char/socket/server/mainloop/" # name,        \
1415                          &server1 ##name, char_socket_server_test);     \
1416     g_test_add_data_func("/char/socket/server/wait-conn/" # name,       \
1417                          &server2 ##name, char_socket_server_test);     \
1418     g_test_add_data_func("/char/socket/server/mainloop-fdpass/" # name, \
1419                          &server3 ##name, char_socket_server_test);     \
1420     g_test_add_data_func("/char/socket/server/wait-conn-fdpass/" # name, \
1421                          &server4 ##name, char_socket_server_test)
1422 
1423 #define SOCKET_CLIENT_TEST(name, addr)                                  \
1424     static CharSocketClientTestConfig client1 ## name =                 \
1425         { addr, NULL, false, false };                                   \
1426     static CharSocketClientTestConfig client2 ## name =                 \
1427         { addr, NULL, true, false };                                    \
1428     static CharSocketClientTestConfig client3 ## name =                 \
1429         { addr, ",reconnect=1", false };                                \
1430     static CharSocketClientTestConfig client4 ## name =                 \
1431         { addr, ",reconnect=1", true };                                 \
1432     static CharSocketClientTestConfig client5 ## name =                 \
1433         { addr, NULL, false, true };                                    \
1434     static CharSocketClientTestConfig client6 ## name =                 \
1435         { addr, NULL, true, true };                                     \
1436     g_test_add_data_func("/char/socket/client/mainloop/" # name,        \
1437                          &client1 ##name, char_socket_client_test);     \
1438     g_test_add_data_func("/char/socket/client/wait-conn/" # name,       \
1439                          &client2 ##name, char_socket_client_test);     \
1440     g_test_add_data_func("/char/socket/client/mainloop-reconnect/" # name, \
1441                          &client3 ##name, char_socket_client_test);     \
1442     g_test_add_data_func("/char/socket/client/wait-conn-reconnect/" # name, \
1443                          &client4 ##name, char_socket_client_test);     \
1444     g_test_add_data_func("/char/socket/client/mainloop-fdpass/" # name, \
1445                          &client5 ##name, char_socket_client_test);     \
1446     g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \
1447                          &client6 ##name, char_socket_client_test)
1448 
1449     if (has_ipv4) {
1450         SOCKET_SERVER_TEST(tcp, &tcpaddr);
1451         SOCKET_CLIENT_TEST(tcp, &tcpaddr);
1452         g_test_add_data_func("/char/socket/server/two-clients/tcp", &tcpaddr,
1453                              char_socket_server_two_clients_test);
1454     }
1455 #ifndef WIN32
1456     SOCKET_SERVER_TEST(unix, &unixaddr);
1457     SOCKET_CLIENT_TEST(unix, &unixaddr);
1458     g_test_add_data_func("/char/socket/server/two-clients/unix", &unixaddr,
1459                          char_socket_server_two_clients_test);
1460 #endif
1461 
1462     g_test_add_func("/char/udp", char_udp_test);
1463 #if defined(HAVE_CHARDEV_SERIAL) && !defined(WIN32)
1464     g_test_add_func("/char/serial", char_serial_test);
1465 #endif
1466     g_test_add_func("/char/hotswap", char_hotswap_test);
1467     g_test_add_func("/char/websocket", char_websock_test);
1468 
1469 end:
1470     return g_test_run();
1471 }
1472