qemu-char: delete send_all/recv_all helper methods
[qemu/ar7.git] / contrib / ivshmem-server / main.c
blob9b0d6e2319c028f01367195ecd3248cfaa6a7d25
1 /*
2 * Copyright 6WIND S.A., 2014
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 */
9 #include "qemu-common.h"
11 #include "ivshmem-server.h"
13 #define IVSHMEM_SERVER_DEFAULT_VERBOSE 0
14 #define IVSHMEM_SERVER_DEFAULT_FOREGROUND 0
15 #define IVSHMEM_SERVER_DEFAULT_PID_FILE "/var/run/ivshmem-server.pid"
16 #define IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
17 #define IVSHMEM_SERVER_DEFAULT_SHM_PATH "ivshmem"
18 #define IVSHMEM_SERVER_DEFAULT_SHM_SIZE (4*1024*1024)
19 #define IVSHMEM_SERVER_DEFAULT_N_VECTORS 1
21 /* used to quit on signal SIGTERM */
22 static int ivshmem_server_quit;
24 /* arguments given by the user */
25 typedef struct IvshmemServerArgs {
26 bool verbose;
27 bool foreground;
28 const char *pid_file;
29 const char *unix_socket_path;
30 const char *shm_path;
31 uint64_t shm_size;
32 unsigned n_vectors;
33 } IvshmemServerArgs;
35 /* show ivshmem_server_usage and exit with given error code */
36 static void
37 ivshmem_server_usage(const char *name, int code)
39 fprintf(stderr, "%s [opts]\n", name);
40 fprintf(stderr, " -h: show this help\n");
41 fprintf(stderr, " -v: verbose mode\n");
42 fprintf(stderr, " -F: foreground mode (default is to daemonize)\n");
43 fprintf(stderr, " -p <pid_file>: path to the PID file (used in daemon\n"
44 " mode only).\n"
45 " Default=%s\n", IVSHMEM_SERVER_DEFAULT_SHM_PATH);
46 fprintf(stderr, " -S <unix_socket_path>: path to the unix socket\n"
47 " to listen to.\n"
48 " Default=%s\n", IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH);
49 fprintf(stderr, " -m <shm_path>: path to the shared memory.\n"
50 " The path corresponds to a POSIX shm name or a\n"
51 " hugetlbfs mount point.\n"
52 " default=%s\n", IVSHMEM_SERVER_DEFAULT_SHM_PATH);
53 fprintf(stderr, " -l <size>: size of shared memory in bytes. The suffix\n"
54 " K, M and G can be used (ex: 1K means 1024).\n"
55 " default=%u\n", IVSHMEM_SERVER_DEFAULT_SHM_SIZE);
56 fprintf(stderr, " -n <n_vects>: number of vectors.\n"
57 " default=%u\n", IVSHMEM_SERVER_DEFAULT_N_VECTORS);
59 exit(code);
62 /* parse the program arguments, exit on error */
63 static void
64 ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
66 int c;
67 unsigned long long v;
68 Error *err = NULL;
70 while ((c = getopt(argc, argv,
71 "h" /* help */
72 "v" /* verbose */
73 "F" /* foreground */
74 "p:" /* pid_file */
75 "S:" /* unix_socket_path */
76 "m:" /* shm_path */
77 "l:" /* shm_size */
78 "n:" /* n_vectors */
79 )) != -1) {
81 switch (c) {
82 case 'h': /* help */
83 ivshmem_server_usage(argv[0], 0);
84 break;
86 case 'v': /* verbose */
87 args->verbose = 1;
88 break;
90 case 'F': /* foreground */
91 args->foreground = 1;
92 break;
94 case 'p': /* pid_file */
95 args->pid_file = optarg;
96 break;
98 case 'S': /* unix_socket_path */
99 args->unix_socket_path = optarg;
100 break;
102 case 'm': /* shm_path */
103 args->shm_path = optarg;
104 break;
106 case 'l': /* shm_size */
107 parse_option_size("shm_size", optarg, &args->shm_size, &err);
108 if (err) {
109 error_report_err(err);
110 ivshmem_server_usage(argv[0], 1);
112 break;
114 case 'n': /* n_vectors */
115 if (parse_uint_full(optarg, &v, 0) < 0) {
116 fprintf(stderr, "cannot parse n_vectors\n");
117 ivshmem_server_usage(argv[0], 1);
119 args->n_vectors = v;
120 break;
122 default:
123 ivshmem_server_usage(argv[0], 1);
124 break;
128 if (args->n_vectors > IVSHMEM_SERVER_MAX_VECTORS) {
129 fprintf(stderr, "too many requested vectors (max is %d)\n",
130 IVSHMEM_SERVER_MAX_VECTORS);
131 ivshmem_server_usage(argv[0], 1);
134 if (args->verbose == 1 && args->foreground == 0) {
135 fprintf(stderr, "cannot use verbose in daemon mode\n");
136 ivshmem_server_usage(argv[0], 1);
140 /* wait for events on listening server unix socket and connected client
141 * sockets */
142 static int
143 ivshmem_server_poll_events(IvshmemServer *server)
145 fd_set fds;
146 int ret = 0, maxfd;
148 while (!ivshmem_server_quit) {
150 FD_ZERO(&fds);
151 maxfd = 0;
152 ivshmem_server_get_fds(server, &fds, &maxfd);
154 ret = select(maxfd, &fds, NULL, NULL, NULL);
156 if (ret < 0) {
157 if (errno == EINTR) {
158 continue;
161 fprintf(stderr, "select error: %s\n", strerror(errno));
162 break;
164 if (ret == 0) {
165 continue;
168 if (ivshmem_server_handle_fds(server, &fds, maxfd) < 0) {
169 fprintf(stderr, "ivshmem_server_handle_fds() failed\n");
170 break;
174 return ret;
177 static void
178 ivshmem_server_quit_cb(int signum)
180 ivshmem_server_quit = 1;
184 main(int argc, char *argv[])
186 IvshmemServer server;
187 struct sigaction sa, sa_quit;
188 IvshmemServerArgs args = {
189 .verbose = IVSHMEM_SERVER_DEFAULT_VERBOSE,
190 .foreground = IVSHMEM_SERVER_DEFAULT_FOREGROUND,
191 .pid_file = IVSHMEM_SERVER_DEFAULT_PID_FILE,
192 .unix_socket_path = IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH,
193 .shm_path = IVSHMEM_SERVER_DEFAULT_SHM_PATH,
194 .shm_size = IVSHMEM_SERVER_DEFAULT_SHM_SIZE,
195 .n_vectors = IVSHMEM_SERVER_DEFAULT_N_VECTORS,
197 int ret = 1;
199 /* parse arguments, will exit on error */
200 ivshmem_server_parse_args(&args, argc, argv);
202 /* Ignore SIGPIPE, see this link for more info:
203 * http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
204 sa.sa_handler = SIG_IGN;
205 sa.sa_flags = 0;
206 if (sigemptyset(&sa.sa_mask) == -1 ||
207 sigaction(SIGPIPE, &sa, 0) == -1) {
208 perror("failed to ignore SIGPIPE; sigaction");
209 goto err;
212 sa_quit.sa_handler = ivshmem_server_quit_cb;
213 sa_quit.sa_flags = 0;
214 if (sigemptyset(&sa_quit.sa_mask) == -1 ||
215 sigaction(SIGTERM, &sa_quit, 0) == -1) {
216 perror("failed to add SIGTERM handler; sigaction");
217 goto err;
220 /* init the ivshms structure */
221 if (ivshmem_server_init(&server, args.unix_socket_path, args.shm_path,
222 args.shm_size, args.n_vectors, args.verbose) < 0) {
223 fprintf(stderr, "cannot init server\n");
224 goto err;
227 /* start the ivshmem server (open shm & unix socket) */
228 if (ivshmem_server_start(&server) < 0) {
229 fprintf(stderr, "cannot bind\n");
230 goto err;
233 /* daemonize if asked to */
234 if (!args.foreground) {
235 FILE *fp;
237 if (qemu_daemon(1, 1) < 0) {
238 fprintf(stderr, "cannot daemonize: %s\n", strerror(errno));
239 goto err_close;
242 /* write pid file */
243 fp = fopen(args.pid_file, "w");
244 if (fp == NULL) {
245 fprintf(stderr, "cannot write pid file: %s\n", strerror(errno));
246 goto err_close;
249 fprintf(fp, "%d\n", (int) getpid());
250 fclose(fp);
253 ivshmem_server_poll_events(&server);
254 fprintf(stdout, "server disconnected\n");
255 ret = 0;
257 err_close:
258 ivshmem_server_close(&server);
259 err:
260 return ret;