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