xref: /openbsd-src/regress/lib/libpthread/setsockopt/1/setsockopt1.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: setsockopt1.c,v 1.1 2009/12/26 01:34:18 fgsch Exp $	*/
2 /*
3  * Federico G. Schwindt <fgsch@openbsd.org>, 2009. Public Domain.
4  */
5 
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <err.h>
10 #include <fcntl.h>
11 #include <netdb.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include "test.h"
16 
17 static void
18 alarm_handler(int sig)
19 {
20 	_exit(NOTOK);
21 }
22 
23 int
24 check_timeout(int s, int sec, struct timeval *to)
25 {
26 	struct timeval t1, t2;
27 	struct timeval e, d;
28 	char buf[BUFSIZ];
29 
30 	ASSERT(signal(SIGALRM, alarm_handler) != SIG_ERR);
31 	CHECKe(alarm(sec));
32 	CHECKe(gettimeofday(&t1, NULL));
33 	ASSERT(read(s, &buf, sizeof(buf)) == -1);
34 	CHECKe(gettimeofday(&t2, NULL));
35 	ASSERT(errno == EAGAIN);
36 	timersub(&t2, &t1, &e);
37 	timersub(&e, to, &d);
38 	return ((d.tv_sec > 1 || (d.tv_usec / 1000) > 100) ? 1 : 0);
39 }
40 
41 static void *
42 sock_connect(void *arg)
43 {
44 	struct sockaddr_in sin;
45 	struct timeval to;
46 	int s, s2, s3;
47 
48 	CHECKe(s = socket(AF_INET, SOCK_STREAM, 0));
49 	CHECKe(s2 = dup(s));
50 	CHECKe(s3 = fcntl(s, F_DUPFD, s));
51 	bzero(&sin, sizeof(sin));
52 	sin.sin_family = AF_INET;
53 	sin.sin_len = sizeof(sin);
54 	sin.sin_port = htons(6543);
55 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
56 	CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin)));
57 	to.tv_sec = 2;
58 	to.tv_usec = 0.5 * 1e6;
59 	CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)));
60 	CHECKr(check_timeout(s, 3, &to));
61 	CHECKr(check_timeout(s2, 3, &to));
62 	CHECKr(check_timeout(s3, 3, &to));
63 	to.tv_sec = 1;
64 	to.tv_usec = 0.5 * 1e6;
65 	CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)));
66 	CHECKr(check_timeout(s, 2, &to));
67 	CHECKr(check_timeout(s2, 2, &to));
68 	CHECKr(check_timeout(s3, 2, &to));
69 	return (NULL);
70 }
71 
72 static void *
73 sock_accept(void *arg)
74 {
75 	pthread_t connect_thread;
76 	struct sockaddr_in sin;
77 	int s;
78 
79 	CHECKe(s = socket(AF_INET, SOCK_STREAM, 0));
80 	bzero(&sin, sizeof(sin));
81 	sin.sin_family = AF_INET;
82 	sin.sin_len = sizeof(sin);
83 	sin.sin_port = htons(6543);
84 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
85 	CHECKe(bind(s, (struct sockaddr *)&sin, sizeof(sin)));
86 	CHECKe(listen(s, 2));
87 
88 	CHECKr(pthread_create(&connect_thread, NULL, sock_connect, NULL));
89 	CHECKr(pthread_join(connect_thread, NULL));
90 	return (NULL);
91 }
92 
93 int
94 main(int argc, char **argv)
95 {
96 	pthread_t accept_thread;
97 
98 	CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL));
99 	CHECKr(pthread_join(accept_thread, NULL));
100 	SUCCEED;
101 }
102