qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

main.c (6697B)


      1 /*
      2  * Copyright 6WIND S.A., 2014
      3  *
      4  * This work is licensed under the terms of the GNU GPL, version 2 or
      5  * (at your option) any later version.  See the COPYING file in the
      6  * top-level directory.
      7  */
      8 
      9 #include "qemu/osdep.h"
     10 
     11 #include "ivshmem-client.h"
     12 
     13 #define IVSHMEM_CLIENT_DEFAULT_VERBOSE        0
     14 #define IVSHMEM_CLIENT_DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
     15 
     16 typedef struct IvshmemClientArgs {
     17     bool verbose;
     18     const char *unix_sock_path;
     19 } IvshmemClientArgs;
     20 
     21 /* show ivshmem_client_usage and exit with given error code */
     22 static void
     23 ivshmem_client_usage(const char *name, int code)
     24 {
     25     fprintf(stderr, "%s [opts]\n", name);
     26     fprintf(stderr, "  -h: show this help\n");
     27     fprintf(stderr, "  -v: verbose mode\n");
     28     fprintf(stderr, "  -S <unix_sock_path>: path to the unix socket\n"
     29                     "     to connect to.\n"
     30                     "     default=%s\n", IVSHMEM_CLIENT_DEFAULT_UNIX_SOCK_PATH);
     31     exit(code);
     32 }
     33 
     34 /* parse the program arguments, exit on error */
     35 static void
     36 ivshmem_client_parse_args(IvshmemClientArgs *args, int argc, char *argv[])
     37 {
     38     int c;
     39 
     40     while ((c = getopt(argc, argv,
     41                        "h"  /* help */
     42                        "v"  /* verbose */
     43                        "S:" /* unix_sock_path */
     44                       )) != -1) {
     45 
     46         switch (c) {
     47         case 'h': /* help */
     48             ivshmem_client_usage(argv[0], 0);
     49             break;
     50 
     51         case 'v': /* verbose */
     52             args->verbose = 1;
     53             break;
     54 
     55         case 'S': /* unix_sock_path */
     56             args->unix_sock_path = optarg;
     57             break;
     58 
     59         default:
     60             ivshmem_client_usage(argv[0], 1);
     61             break;
     62         }
     63     }
     64 }
     65 
     66 /* show command line help */
     67 static void
     68 ivshmem_client_cmdline_help(void)
     69 {
     70     printf("dump: dump peers (including us)\n"
     71            "int <peer> <vector>: notify one vector on a peer\n"
     72            "int <peer> all: notify all vectors of a peer\n"
     73            "int all: notify all vectors of all peers (excepting us)\n");
     74 }
     75 
     76 /* read stdin and handle commands */
     77 static int
     78 ivshmem_client_handle_stdin_command(IvshmemClient *client)
     79 {
     80     IvshmemClientPeer *peer;
     81     char buf[128];
     82     char *s, *token;
     83     int ret;
     84     int peer_id, vector;
     85 
     86     memset(buf, 0, sizeof(buf));
     87     ret = read(0, buf, sizeof(buf) - 1);
     88     if (ret < 0) {
     89         return -1;
     90     }
     91 
     92     s = buf;
     93     while ((token = strsep(&s, "\n\r;")) != NULL) {
     94         if (!strcmp(token, "")) {
     95             continue;
     96         }
     97         if (!strcmp(token, "?")) {
     98             ivshmem_client_cmdline_help();
     99         }
    100         if (!strcmp(token, "help")) {
    101             ivshmem_client_cmdline_help();
    102         } else if (!strcmp(token, "dump")) {
    103             ivshmem_client_dump(client);
    104         } else if (!strcmp(token, "int all")) {
    105             ivshmem_client_notify_broadcast(client);
    106         } else if (sscanf(token, "int %d %d", &peer_id, &vector) == 2) {
    107             peer = ivshmem_client_search_peer(client, peer_id);
    108             if (peer == NULL) {
    109                 printf("cannot find peer_id = %d\n", peer_id);
    110                 continue;
    111             }
    112             ivshmem_client_notify(client, peer, vector);
    113         } else if (sscanf(token, "int %d all", &peer_id) == 1) {
    114             peer = ivshmem_client_search_peer(client, peer_id);
    115             if (peer == NULL) {
    116                 printf("cannot find peer_id = %d\n", peer_id);
    117                 continue;
    118             }
    119             ivshmem_client_notify_all_vects(client, peer);
    120         } else {
    121             printf("invalid command, type help\n");
    122         }
    123     }
    124 
    125     printf("cmd> ");
    126     fflush(stdout);
    127     return 0;
    128 }
    129 
    130 /* listen on stdin (command line), on unix socket (notifications of new
    131  * and dead peers), and on eventfd (IRQ request) */
    132 static int
    133 ivshmem_client_poll_events(IvshmemClient *client)
    134 {
    135     fd_set fds;
    136     int ret, maxfd;
    137 
    138     while (1) {
    139 
    140         FD_ZERO(&fds);
    141         FD_SET(0, &fds); /* add stdin in fd_set */
    142         maxfd = 1;
    143 
    144         ivshmem_client_get_fds(client, &fds, &maxfd);
    145 
    146         ret = select(maxfd, &fds, NULL, NULL, NULL);
    147         if (ret < 0) {
    148             if (errno == EINTR) {
    149                 continue;
    150             }
    151 
    152             fprintf(stderr, "select error: %s\n", strerror(errno));
    153             break;
    154         }
    155         if (ret == 0) {
    156             continue;
    157         }
    158 
    159         if (FD_ISSET(0, &fds) &&
    160             ivshmem_client_handle_stdin_command(client) < 0 && errno != EINTR) {
    161             fprintf(stderr, "ivshmem_client_handle_stdin_command() failed\n");
    162             break;
    163         }
    164 
    165         if (ivshmem_client_handle_fds(client, &fds, maxfd) < 0) {
    166             fprintf(stderr, "ivshmem_client_handle_fds() failed\n");
    167             break;
    168         }
    169     }
    170 
    171     return ret;
    172 }
    173 
    174 /* callback when we receive a notification (just display it) */
    175 static void
    176 ivshmem_client_notification_cb(const IvshmemClient *client,
    177                                const IvshmemClientPeer *peer,
    178                                unsigned vect, void *arg)
    179 {
    180     (void)client;
    181     (void)arg;
    182     printf("receive notification from peer_id=%" PRId64 " vector=%u\n",
    183            peer->id, vect);
    184 }
    185 
    186 int
    187 main(int argc, char *argv[])
    188 {
    189     struct sigaction sa;
    190     IvshmemClient client;
    191     IvshmemClientArgs args = {
    192         .verbose = IVSHMEM_CLIENT_DEFAULT_VERBOSE,
    193         .unix_sock_path = IVSHMEM_CLIENT_DEFAULT_UNIX_SOCK_PATH,
    194     };
    195 
    196     /* parse arguments, will exit on error */
    197     ivshmem_client_parse_args(&args, argc, argv);
    198 
    199     /* Ignore SIGPIPE, see this link for more info:
    200      * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
    201     sa.sa_handler = SIG_IGN;
    202     sa.sa_flags = 0;
    203     if (sigemptyset(&sa.sa_mask) == -1 ||
    204         sigaction(SIGPIPE, &sa, 0) == -1) {
    205         perror("failed to ignore SIGPIPE; sigaction");
    206         return 1;
    207     }
    208 
    209     ivshmem_client_cmdline_help();
    210     printf("cmd> ");
    211     fflush(stdout);
    212 
    213     if (ivshmem_client_init(&client, args.unix_sock_path,
    214                             ivshmem_client_notification_cb, NULL,
    215                             args.verbose) < 0) {
    216         fprintf(stderr, "cannot init client\n");
    217         return 1;
    218     }
    219 
    220     while (1) {
    221         if (ivshmem_client_connect(&client) < 0) {
    222             fprintf(stderr, "cannot connect to server, retry in 1 second\n");
    223             sleep(1);
    224             continue;
    225         }
    226 
    227         fprintf(stdout, "listen on server socket %d\n", client.sock_fd);
    228 
    229         if (ivshmem_client_poll_events(&client) == 0) {
    230             continue;
    231         }
    232 
    233         /* disconnected from server, reset all peers */
    234         fprintf(stdout, "disconnected from server\n");
    235 
    236         ivshmem_client_close(&client);
    237     }
    238 
    239     return 0;
    240 }