cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-char.c (48212B)


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