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 31 static void main_loop(void) 32 { 33 quit = false; 34 do { 35 main_loop_wait(false); 36 } while (!quit); 37 } 38 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 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 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 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 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 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 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 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 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 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 371 static int websock_server_can_read(void *opaque) 372 { 373 return 10; 374 } 375 376 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 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 421 static int websock_client_can_read(void *opaque) 422 { 423 return 4096; 424 } 425 426 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 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 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 570 static int socket_can_read_hello(void *opaque) 571 { 572 return 10; 573 } 574 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 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 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 659 char_socket_event(void *opaque, QEMUChrEvent event) 660 { 661 CharSocketTestData *data = opaque; 662 data->event = event; 663 } 664 665 static void 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 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 698 char_socket_can_read(void *opaque) 699 { 700 return sizeof(SOCKET_PONG); 701 } 702 703 704 static char * 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 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 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 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 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 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 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 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 1120 char_socket_discard_read(void *opaque, const uint8_t *buf, int size) 1121 { 1122 } 1123 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) 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) 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 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 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 1350 static void char_file_test(void) 1351 { 1352 char_file_test_internal(NULL, NULL); 1353 } 1354 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 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 1407 static int chardev_change(void *opaque) 1408 { 1409 return 0; 1410 } 1411 1412 static int chardev_change_denied(void *opaque) 1413 { 1414 return -1; 1415 } 1416 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 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