xref: /haiku/src/tests/system/network/firefox_crash.cpp (revision bb83316a5811a550c4f850d07fa8e328e7ac0a94)
1 /*
2  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 //!	A test app trying to reproduce bug #2197.
7 
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <netinet/in.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/select.h>
15 #include <sys/socket.h>
16 
17 
18 static int
19 open_tcp_socket()
20 {
21 	int fd = socket(AF_INET, SOCK_STREAM, 0);
22 	if (fd < 0)
23 		return -1;
24 
25 	// make it non-blocking
26 	fcntl(fd, F_SETFL, O_NONBLOCK);
27 
28 	return fd;
29 }
30 
31 
32 static void
33 init_sockaddr(struct sockaddr_in& address, unsigned ipAddress, unsigned port)
34 {
35 	memset(&address, 0, sizeof(sockaddr_in));
36 	address.sin_family = AF_INET;
37 	address.sin_port = htons(port);
38 	address.sin_addr.s_addr = htonl(ipAddress);
39 }
40 
41 
42 static int
43 tcp_pair(int pair[])
44 {
45 	pair[0] = pair[1] = -1;
46 
47 	int listenSocket = open_tcp_socket();
48 	if (listenSocket < 0)
49 		return -1;
50 
51 	sockaddr_in listenAddress;
52 	sockaddr_in peerAddress;
53 	sockaddr_in address;
54 	socklen_t length;
55 	init_sockaddr(listenAddress, INADDR_LOOPBACK, 0);
56 
57 	if (bind(listenSocket, (sockaddr*)&listenAddress, sizeof(sockaddr_in)) != 0)
58 		goto error;
59 
60 	length = sizeof(sockaddr_in);
61 	if (getsockname(listenSocket, (sockaddr*)&listenAddress, &length) != 0)
62 		goto error;
63 
64 	if (listen(listenSocket, 5) != 0)
65 		goto error;
66 
67 	pair[0] = open_tcp_socket();
68 	if (pair[0] < 0)
69 		goto error;
70 
71 	init_sockaddr(address, INADDR_LOOPBACK, ntohs(listenAddress.sin_port));
72 
73 	if (connect(pair[0], (sockaddr*)&address, sizeof(sockaddr_in)) != 0
74 		&& errno != EINPROGRESS)
75 		goto error;
76 
77 	if (errno == EINPROGRESS) {
78 		struct timeval tv;
79 		tv.tv_sec = 100000;
80 		tv.tv_usec = 0;
81 		fd_set set;
82 		FD_ZERO(&set);
83 		FD_SET(pair[0], &set);
84 		if (select(pair[0] + 1, NULL, &set, NULL, &tv) < 0)
85 			fprintf(stderr, "write select() failed: %s\n", strerror(errno));
86 	}
87 
88 	length = sizeof(sockaddr_in);
89 	if (getsockname(pair[0], (sockaddr*)&address, &length) != 0)
90 		goto error;
91 
92 	while (true) {
93 		pair[1] = accept(listenSocket, (sockaddr*)&peerAddress, &length);
94 		if (pair[1] >= 0)
95 			break;
96 
97 		if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ETIMEDOUT)
98 			goto error;
99 
100 		struct timeval tv;
101 		tv.tv_sec = 100000;
102 		tv.tv_usec = 0;
103 		fd_set set;
104 		FD_ZERO(&set);
105 		FD_SET(listenSocket, &set);
106 		if (select(listenSocket + 1, &set, NULL, NULL, &tv) < 0)
107 			fprintf(stderr, "read select() failed: %s\n", strerror(errno));
108 	}
109 
110 	if (peerAddress.sin_port != address.sin_port)
111 		goto error;
112 
113 	close(listenSocket);
114     return 0;
115 
116 error:
117 	close(listenSocket);
118 	for (int i = 0; i < 2; i++) {
119 		if (pair[i] >= 0)
120 			close(pair[i]);
121 	}
122 
123     return -1;
124 }
125 
126 
127 int
128 main(int argc, char** argv)
129 {
130 	int pair[2];
131 	if (tcp_pair(pair) == 0) {
132 		close(pair[0]);
133 		close(pair[1]);
134 	} else
135 		fprintf(stderr, "pair failed: %s\n", strerror(errno));
136 	return 0;
137 }
138 
139