]> git.ozlabs.org Git - ccan/blob - ccan/io/test/run-21-io_close_taken_fd.c
io: io_close_taken_fd to steal fd from conn.
[ccan] / ccan / io / test / run-21-io_close_taken_fd.c
1 #include <ccan/io/io.h>
2 /* Include the C files directly. */
3 #include <ccan/io/poll.c>
4 #include <ccan/io/io.c>
5 #include <ccan/tap/tap.h>
6 #include <sys/wait.h>
7 #include <stdio.h>
8
9 #define PORT "65021"
10
11 static struct io_listener *l;
12
13 static struct io_plan *steal_fd(struct io_conn *conn, int *fd)
14 {
15         io_close_listener(l);
16         *fd = io_conn_fd(conn);
17         return io_close_taken_fd(conn);
18 }
19
20 static int make_listen_fd(const char *port, struct addrinfo **info)
21 {
22         int fd, on = 1;
23         struct addrinfo *addrinfo, hints;
24
25         memset(&hints, 0, sizeof(hints));
26         hints.ai_family = AF_UNSPEC;
27         hints.ai_socktype = SOCK_STREAM;
28         hints.ai_flags = AI_PASSIVE;
29         hints.ai_protocol = 0;
30
31         if (getaddrinfo(NULL, port, &hints, &addrinfo) != 0)
32                 return -1;
33
34         fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
35                     addrinfo->ai_protocol);
36         if (fd < 0)
37                 return -1;
38
39         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
40         if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
41                 close(fd);
42                 return -1;
43         }
44         if (listen(fd, 1) != 0) {
45                 close(fd);
46                 return -1;
47         }
48         *info = addrinfo;
49         return fd;
50 }
51
52 int main(void)
53 {
54         struct addrinfo *addrinfo = NULL;
55         int i, fd, in_fd, status;
56         char buf[strlen("hellothere")];
57
58         /* This is how many tests you plan to run */
59         plan_tests(15);
60         fd = make_listen_fd(PORT, &addrinfo);
61         l = io_new_listener(NULL, fd, steal_fd, &in_fd);
62         fflush(stdout);
63         if (!fork()) {
64                 io_close_listener(l);
65                 fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
66                             addrinfo->ai_protocol);
67                 if (fd < 0)
68                         exit(1);
69                 if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
70                         exit(2);
71                 signal(SIGPIPE, SIG_IGN);
72                 for (i = 0; i < strlen("hellothere"); i++) {
73                         if (write(fd, "hellothere" + i, 1) != 1)
74                                 break;
75                 }
76                 close(fd);
77                 freeaddrinfo(addrinfo);
78                 exit(0);
79         }
80         freeaddrinfo(addrinfo);
81         ok1(io_loop(NULL, NULL) == NULL);
82
83         for (i = 0; i < strlen("hellothere"); i++)
84                 ok1(read(in_fd, buf + i, 1) == 1);
85
86         ok1(memcmp(buf, "hellothere", sizeof(buf)) == 0);
87         ok1(wait(&status));
88         ok1(WIFEXITED(status));
89         ok1(WEXITSTATUS(status) == 0);
90
91         /* This exits depending on whether all tests passed */
92         return exit_status();
93 }