net: remove noerr dependency.
[ccan] / ccan / net / test / run.c
1 #include <ccan/net/net.h>
2 #include <ccan/net/net.c>
3 #include <ccan/tap/tap.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <stdio.h>
7 #include <err.h>
8
9 static unsigned int server(int protocol, int type)
10 {
11         int sock;
12         union {
13                 struct sockaddr addr;
14                 struct sockaddr_in ipv4;
15                 struct sockaddr_in6 ipv6;
16         } addr;
17         socklen_t addlen = sizeof(addr);
18
19         sock = socket(protocol, type, 0);
20
21         /* Bind to free port. */
22         listen(sock, 0);
23
24         /* Figure out what port it gave us. */
25         getsockname(sock, &addr.addr, &addlen);
26         fflush(stdout);
27
28         if (fork() == 0) {
29                 int ret, fd;
30
31                 alarm(3);
32                 fd = accept(sock, NULL, 0);
33                 if (fd < 0)
34                         err(1, "Accepting from socket %i", sock);
35
36                 ret = write(fd, "Yay!", strlen("Yay!"));
37                 if (ret != strlen("Yay!"))
38                         err(1, "Write returned %i", ret);
39                 exit(0);
40         }
41         close(sock);
42         return ntohs(protocol == AF_INET
43                      ? addr.ipv4.sin_port : addr.ipv6.sin6_port);
44 }
45
46 int main(void)
47 {
48         struct addrinfo *addr, *addr2;
49         int fd, status;
50         struct sockaddr saddr;
51         socklen_t slen = sizeof(saddr);
52         char buf[20];
53         unsigned int port;
54
55         plan_tests(16);
56         port = server(AF_INET, SOCK_STREAM);
57         sprintf(buf, "%u", port);
58
59         addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM);
60         addr2 = net_client_lookup("ip6-localhost", buf,
61                                   AF_UNSPEC, SOCK_STREAM);
62         ok1(addr);
63         ok1(addr2);
64         /* Join them as if they were from one lookup. */
65         addr->ai_next = addr2;
66
67         fd = net_connect(addr);
68         ok1(fd >= 0);
69
70         ok1(getsockname(fd, &saddr, &slen) == 0);
71         ok1(saddr.sa_family == AF_INET);
72         status = read(fd, buf, sizeof(buf));
73         ok(status == strlen("Yay!"),
74            "Read returned %i (%s)", status, strerror(errno));
75         ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
76         close(fd);
77         addr->ai_next = NULL;
78         freeaddrinfo(addr);
79         freeaddrinfo(addr2);
80
81         port = server(AF_INET6, SOCK_STREAM);
82         sprintf(buf, "%u", port);
83
84         addr = net_client_lookup("localhost", buf, AF_UNSPEC, SOCK_STREAM);
85         addr2 = net_client_lookup("ip6-localhost", buf,
86                                   AF_UNSPEC, SOCK_STREAM);
87         ok1(addr);
88         ok1(addr2);
89         /* Join them as if they were from one lookup. */
90         addr->ai_next = addr2;
91
92         fd = net_connect(addr);
93         ok1(fd >= 0);
94
95         ok1(getsockname(fd, &saddr, &slen) == 0);
96         ok1(saddr.sa_family == AF_INET6);
97         status = read(fd, buf, sizeof(buf));
98         ok(status == strlen("Yay!"),
99            "Read returned %i (%s)", status, strerror(errno));
100         ok1(strncmp(buf, "Yay!", strlen("Yay!")) == 0);
101         close(fd);
102         addr->ai_next = NULL;
103         freeaddrinfo(addr);
104         freeaddrinfo(addr2);
105
106         wait(&status);
107         ok1(WIFEXITED(status));
108         ok1(WEXITSTATUS(status) == 0);
109
110         /* This exits depending on whether all tests passed */
111         return exit_status();
112 }