socket: Remove fo_ioctl(FIONBIO) for sockets.
[dragonfly.git] / test / socket / accept4 / block / accept4_block.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/time.h>
4 #include <sys/un.h>
5 #include <sys/wait.h>
6
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9
10 #include <err.h>
11 #include <errno.h>
12 #include <signal.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #define WRITE_WAIT_TIME 8       /* unit: sec */
19 #define READ_WAIT_MIN   6       /* unit: sec */
20
21 static void
22 usage(const char *cmd)
23 {
24         fprintf(stderr, "%s -p port\n", cmd);
25         exit(1);
26 }
27
28 static void
29 connect_client(int port, int ctrl_s)
30 {
31         struct sockaddr_in in;
32         int s, dummy;
33
34         s = socket(AF_INET, SOCK_STREAM, 0);
35         if (s < 0)
36                 err(1, "client socket failed");
37
38         memset(&in, 0, sizeof(in));
39         in.sin_family = AF_INET;
40         in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
41         in.sin_port = htons(port);
42         if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
43                 err(1, "connect failed");
44
45         /* Make sure server side compltes the 3-way handshake */
46         sleep(1);
47
48         /* connect is done */
49         write(ctrl_s, &dummy, sizeof(dummy));
50
51         sleep(WRITE_WAIT_TIME);
52         write(s, &dummy, sizeof(dummy));
53
54         pause();
55         exit(0);
56 }
57
58 int
59 main(int argc, char *argv[])
60 {
61         struct sockaddr_in in;
62         int serv_s, s, ctrl_s[2];
63         int opt, port, dummy, n, status, panic, ex;
64         struct timespec stime, etime;
65         pid_t pid;
66
67         ex = 1;
68         panic = 0;
69
70         port = 0;
71         while ((opt = getopt(argc, argv, "p:")) != -1) {
72                 char *endptr;
73
74                 switch (opt) {
75                 case 'p':
76                         port = strtol(optarg, &endptr, 0);
77                         if (*endptr != '\0')
78                                 errx(1, "invalid -p");
79                         break;
80
81                 default:
82                         usage(argv[0]);
83                 }
84         }
85         if (port <= 0)
86                 usage(argv[0]);
87
88         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ctrl_s) < 0)
89                 err(1, "socketpair failed");
90
91         serv_s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
92         if (serv_s < 0)
93                 err(1, "socket failed");
94
95         memset(&in, 0, sizeof(in));
96         in.sin_family = AF_INET;
97         in.sin_port = htons(port);
98         if (bind(serv_s, (const struct sockaddr *)&in, sizeof(in)) < 0)
99                 err(1, "bind failed");
100
101         if (listen(serv_s, 0) < 0)
102                 err(1, "listen failed");
103
104         pid = fork();
105         if (pid < 0) {
106                 err(1, "fork failed");
107         } else if (pid == 0) {
108                 close(ctrl_s[0]);
109                 connect_client(port, ctrl_s[1]);
110                 abort();
111         }
112
113         /* Wait for the connect */
114         read(ctrl_s[0], &dummy, sizeof(dummy));
115
116         s = accept4(serv_s, NULL, NULL, 0);
117         if (s < 0) {
118                 warn("accept4 failed");
119                 goto done;
120         }
121         panic = 1;
122
123         clock_gettime(CLOCK_MONOTONIC, &stime);
124         n = read(s, &dummy, sizeof(dummy));
125         if (n < 0) {
126                 warn("read failed");
127                 goto done;
128         } else if (n != sizeof(dummy)) {
129                 warnx("read size mismatch");
130                 goto done;
131         }
132         clock_gettime(CLOCK_MONOTONIC, &etime);
133
134         if (etime.tv_sec - stime.tv_sec < READ_WAIT_MIN) {
135                 warnx("invalid wait time %ld", etime.tv_sec - stime.tv_sec);
136                 goto done;
137         }
138
139         ex = 0;
140         panic = 0;
141         fprintf(stderr, "passed\n");
142 done:
143         kill(pid, SIGKILL);
144         waitpid(pid, &status, 0);
145         if (panic)
146                 abort();
147         exit(ex);
148 }