io: change io_idle() to io_wait()
[ccan] / ccan / io / test / run-09-connect.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 #ifndef PORT
10 #define PORT "65009"
11 #endif
12
13 static struct io_listener *l;
14
15 struct data {
16         int state;
17         char buf[10];
18 };
19
20 static struct io_plan closer(struct io_conn *conn, struct data *d)
21 {
22         d->state++;
23         return io_close();
24 }
25
26 static struct io_plan connected(struct io_conn *conn, struct data *d2)
27 {
28         ok1(d2->state == 0);
29         d2->state++;
30         return io_read(d2->buf, sizeof(d2->buf), closer, d2);
31 }
32
33 static void init_conn(int fd, struct data *d)
34 {
35         ok1(d->state == 0);
36         d->state++;
37         io_new_conn(fd, io_write(d->buf, sizeof(d->buf), closer, d));
38         io_close_listener(l);
39 }
40
41 static int make_listen_fd(const char *port, struct addrinfo **info)
42 {
43         int fd, on = 1;
44         struct addrinfo *addrinfo, hints;
45
46         memset(&hints, 0, sizeof(hints));
47         hints.ai_family = AF_UNSPEC;
48         hints.ai_socktype = SOCK_STREAM;
49         hints.ai_flags = AI_PASSIVE;
50         hints.ai_protocol = 0;
51
52         if (getaddrinfo(NULL, port, &hints, &addrinfo) != 0)
53                 return -1;
54
55         fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
56                     addrinfo->ai_protocol);
57         if (fd < 0)
58                 return -1;
59
60         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
61         if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
62                 close(fd);
63                 return -1;
64         }
65         if (listen(fd, 1) != 0) {
66                 close(fd);
67                 return -1;
68         }
69         *info = addrinfo;
70         return fd;
71 }
72
73 int main(void)
74 {
75         struct data *d = malloc(sizeof(*d)), *d2 = malloc(sizeof(*d2));
76         struct addrinfo *addrinfo;
77         int fd;
78
79         /* This is how many tests you plan to run */
80         plan_tests(8);
81         d->state = 0;
82         memset(d->buf, 'a', sizeof(d->buf));
83         fd = make_listen_fd(PORT, &addrinfo);
84         ok1(fd >= 0);
85         l = io_new_listener(fd, init_conn, d);
86         ok1(l);
87
88         fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
89                     addrinfo->ai_protocol);
90         d2->state = 0;
91         ok1(io_new_conn(fd, io_connect(fd, addrinfo, connected, d2)));
92
93         ok1(io_loop() == NULL);
94         ok1(d->state == 2);
95         ok1(d2->state == 2);
96
97         freeaddrinfo(addrinfo);
98         free(d);
99         free(d2);
100
101         /* This exits depending on whether all tests passed */
102         return exit_status();
103 }