]> git.ozlabs.org Git - ccan/blob - ccan/io/test/run-46-exclusive.c
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / io / test / run-46-exclusive.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 "65046"
10
11 struct data {
12         struct io_listener *l;
13         int num_clients;
14         char *pattern;
15         char buf[30];
16         size_t buflen;
17 };
18
19 static struct io_plan *read_more(struct io_conn *conn, struct data *d);
20
21 static struct io_plan *read_done(struct io_conn *conn, struct data *d)
22 {
23         tal_resize(&d->pattern, tal_count(d->pattern) + strlen(d->buf));
24         strcat(d->pattern, d->buf);
25         return read_more(conn, d);
26 }
27
28 static struct io_plan *read_more(struct io_conn *conn, struct data *d)
29 {
30         memset(d->buf, 0, sizeof(d->buf));
31         return io_read_partial(conn, d->buf, sizeof(d->buf), &d->buflen,
32                                read_done, d);
33 }
34
35
36 static struct io_plan *init_conn(struct io_conn *conn, struct data *d)
37 {
38         d->num_clients++;
39         if (d->num_clients == 2) {
40                 /* Free listener so when conns close we exit io_loop */
41                 io_close_listener(d->l);
42                 /* Set priority to second connection. */
43                 ok1(io_conn_exclusive(conn, true) == true);
44         }
45         return read_more(conn, d);
46 }
47
48
49 static int make_listen_fd(const char *port, struct addrinfo **info)
50 {
51         int fd, on = 1;
52         struct addrinfo *addrinfo, hints;
53
54         memset(&hints, 0, sizeof(hints));
55         hints.ai_family = AF_UNSPEC;
56         hints.ai_socktype = SOCK_STREAM;
57         hints.ai_flags = AI_PASSIVE;
58         hints.ai_protocol = 0;
59
60         if (getaddrinfo(NULL, port, &hints, &addrinfo) != 0)
61                 return -1;
62
63         fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
64                     addrinfo->ai_protocol);
65         if (fd < 0)
66                 return -1;
67
68         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
69         if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
70                 close(fd);
71                 return -1;
72         }
73         if (listen(fd, 1) != 0) {
74                 close(fd);
75                 return -1;
76         }
77         *info = addrinfo;
78         return fd;
79 }
80
81 int main(void)
82 {
83         struct addrinfo *addrinfo = NULL;
84         int fd, status;
85         struct data d;
86
87         d.num_clients = 0;
88
89         /* This is how many tests you plan to run */
90         plan_tests(8);
91         fd = make_listen_fd(PORT, &addrinfo);
92         ok1(fd >= 0);
93         d.l = io_new_listener(NULL, fd, init_conn, &d);
94         ok1(d.l);
95         fflush(stdout);
96
97         if (!fork()) {
98                 int fd1, fd2;
99
100                 io_close_listener(d.l);
101                 fd1 = socket(addrinfo->ai_family, addrinfo->ai_socktype,
102                             addrinfo->ai_protocol);
103                 if (fd1 < 0)
104                         exit(1);
105                 if (connect(fd1, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
106                         exit(2);
107                 if (write(fd1, "1hellothere", strlen("1hellothere")) != strlen("1hellothere"))
108                         exit(3);
109                 fd2 = socket(addrinfo->ai_family, addrinfo->ai_socktype,
110                             addrinfo->ai_protocol);
111                 if (fd2 < 0)
112                         exit(1);
113                 if (connect(fd2, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0)
114                         exit(2);
115                 signal(SIGPIPE, SIG_IGN);
116
117                 sleep(1);
118                 if (write(fd1, "1helloagain", strlen("1helloagain")) != strlen("1helloagain"))
119                         exit(4);
120                 sleep(1);
121                 if (write(fd2, "2hellonew", strlen("2hellonew")) != strlen("2hellonew"))
122                         exit(5);
123                 close(fd1);
124                 close(fd2);
125                 freeaddrinfo(addrinfo);
126                 exit(0);
127         }
128         freeaddrinfo(addrinfo);
129
130         d.pattern = tal_arrz(NULL, char, 1);
131         ok1(io_loop(NULL, NULL) == NULL);
132         if (!ok1(strcmp(d.pattern, "1hellothere2hellonew1helloagain") == 0))
133                 printf("d.patterns = %s\n", d.pattern);
134         tal_free(d.pattern);
135
136         ok1(wait(&status));
137         ok1(WIFEXITED(status));
138         ok1(WEXITSTATUS(status) == 0);
139
140         /* This exits depending on whether all tests passed */
141         return exit_status();
142 }