Hide things not appropriate behind is_backend
[fio.git] / server.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <limits.h>
5 #include <string.h>
6 #include <getopt.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/poll.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <sys/time.h>
14 #include <sys/mman.h>
15 #include <signal.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <netdb.h>
19
20 #include "fio.h"
21
22 static int net_port = 8765;
23
24 static int accept_loop(int listen_sk)
25 {
26         struct sockaddr addr;
27         unsigned int len = sizeof(addr);
28         int sk, do_exit = 0;
29
30 again:
31         sk = accept(listen_sk, &addr, &len);
32         if (sk < 0) {
33                 log_err("fio: accept failed\n");
34                 return -1;
35         }
36
37         /* read forever */
38         while (!do_exit) {
39                 char buf[131072];
40                 int ret;
41
42                 ret = recv(sk, buf, 4096, 0);
43                 if (ret > 0) {
44                         if (!strncmp("FIO_QUIT", buf, 8)) {
45                                 do_exit = 1;
46                                 break;
47                         }
48                         parse_jobs_ini(buf, 1, 0);
49                         exec_run();
50                         reset_fio_state();
51                         break;
52                 } else if (!ret)
53                         break;
54                 if (errno == EAGAIN || errno == EINTR)
55                         continue;
56                 break;
57         }
58
59         close(sk);
60
61         if (!do_exit)
62                 goto again;
63
64         return 0;
65 }
66
67 int fio_server(void)
68 {
69         struct sockaddr_in saddr_in;
70         struct sockaddr addr;
71         unsigned int len;
72         int sk, opt;
73
74         sk = socket(AF_INET, SOCK_STREAM, 0);
75         if (sk < 0) {
76                 log_err("fio: socket\n");
77                 return -1;
78         }
79
80         opt = 1;
81         if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
82                 log_err("fio: setsockopt\n");
83                 return -1;
84         }
85 #ifdef SO_REUSEPORT
86         if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
87                 td_verror(td, errno, "setsockopt");
88                 return 1;
89         }
90 #endif
91
92         saddr_in.sin_family = AF_INET;
93         saddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
94         saddr_in.sin_port = htons(net_port);
95
96         if (bind(sk, (struct sockaddr *) &saddr_in, sizeof(saddr_in)) < 0) {
97                 perror("bind");
98                 log_err("fio: bind\n");
99                 return -1;
100         }
101
102         if (listen(sk, 1) < 0) {
103                 log_err("fio: listen\n");
104                 return -1;
105         }
106
107         len = sizeof(addr);
108         if (getsockname(sk, &addr, &len) < 0) {
109                 log_err("fio: getsockname");
110                 return -1;
111         }
112
113         return accept_loop(sk);
114 }