]> git.ipfire.org Git - thirdparty/squid.git/blame - test-suite/tcp-banger3.c
Currently the fs related subsystem is broken in trunk, because of
[thirdparty/squid.git] / test-suite / tcp-banger3.c
CommitLineData
2742510a 1#include "config.h"
2
3/*
4 * On some systems, FD_SETSIZE is set to something lower than the
5 * actual number of files which can be opened. IRIX is one case,
6 * NetBSD is another. So here we increase FD_SETSIZE to our
7 * configure-discovered maximum *before* any system includes.
8 */
9#define CHANGE_FD_SETSIZE 1
10
11/* Cannot increase FD_SETSIZE on Linux */
12#if defined(_SQUID_LINUX_)
13#undef CHANGE_FD_SETSIZE
14#define CHANGE_FD_SETSIZE 0
15#endif
16
17/* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
18 * to return EINVAL. */
19/* Marian Durkovic <marian@svf.stuba.sk> */
20/* Peter Wemm <peter@spinner.DIALix.COM> */
21#if defined(_SQUID_FREEBSD_)
22#include <osreldate.h>
23#if __FreeBSD_version < 220000
24#undef CHANGE_FD_SETSIZE
25#define CHANGE_FD_SETSIZE 0
26#endif
27#endif
28
29/* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
30#if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
31#define FD_SETSIZE SQUID_MAXFD
32#endif
33
34#if HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37#if HAVE_STDLIB_H
38#include <stdlib.h>
39#endif
40#if HAVE_STDIO_H
41#include <stdio.h>
42#endif
43#if HAVE_FCNTL_H
44#include <fcntl.h>
45#endif
46#ifdef HAVE_STRING_H
47#include <string.h>
48#endif
49#ifdef HAVE_STRINGS_H
50#include <strings.h>
51#endif
52#if HAVE_SYS_TYPES_H
53#include <sys/types.h>
54#endif
55#if HAVE_SYS_SELECT_H
56#include <sys/select.h>
57#endif
58#if HAVE_SIGNAL_H
59#include <signal.h>
60#endif
61#if HAVE_TIME_H
62#include <time.h>
63#endif
64#if HAVE_SYS_TIME_H
65#include <sys/time.h>
66#endif
67#if HAVE_SYS_SOCKET_H
68#include <sys/socket.h>
69#endif
70#if HAVE_NETINET_IN_H
71#include <netinet/in.h>
72#endif
73#if HAVE_ARPA_INET_H
74#include <arpa/inet.h>
75#endif
76#if HAVE_ERRNO_H
77#include <errno.h>
78#endif
79#if HAVE_SYS_STAT_H
80#include <sys/stat.h>
81#endif
82#if HAVE_ASSERT_H
83#include <assert.h>
84#endif
85#include <netdb.h>
86#include <sys/wait.h>
87
88#define READ_BUF_SZ 4096
89#define URL_BUF_SZ 4096
90
91struct _thing {
92 int rfd;
93 int wfd;
94 int state;
95 pid_t pid;
96 char url[URL_BUF_SZ];
97 struct _thing *next;
98};
99typedef struct _thing thing;
100
101static thing *things = NULL;
102static fd_set R1;
103static int maxfd = 0;
104static struct timeval now;
105#if DEBUG
106static int debug = 1;
107#else
108static int debug = 0;
109#endif
110
2327c45c 111int
112tvSubMsec(struct timeval t1, struct timeval t2)
113{
114 return (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000;
115}
116
2742510a 117static int
118get_url(const char *url)
119{
120 char host[URL_BUF_SZ];
121 char path[URL_BUF_SZ];
122 char request[URL_BUF_SZ];
123 char reply[READ_BUF_SZ];
124 char *t;
125 int x;
126 int s;
127 int nr = 0;
128 struct hostent *h;
129 struct sockaddr_in S;
130 unsigned short port = 80;
131 assert(!strncmp(url, "http://", 7));
132 strncpy(host, url + 7, URL_BUF_SZ);
133 if ((t = strchr(host, '/')))
26ac0430 134 *t = '\0';
2742510a 135 if ((t = strchr(host, ':'))) {
26ac0430
AJ
136 *t = '\0';
137 port = (unsigned short) atoi(t + 1);
2742510a 138 }
b6a2f15e 139#if 0
2742510a 140 if ((int) port != 80)
26ac0430 141 return 0;
b6a2f15e 142#endif
2742510a 143 t = strchr(url + 7, '/');
144 strncpy(path, (t ? t : "/"), URL_BUF_SZ);
145 memset(&S, '\0', sizeof(S));
146 h = gethostbyname(host);
147 if (!h)
26ac0430 148 return 0;
2742510a 149 memcpy(&S.sin_addr.s_addr, h->h_addr_list[0], sizeof(S.sin_addr.s_addr));
150 S.sin_port = htons(port);
151 S.sin_family = AF_INET;
152 if (debug)
26ac0430 153 fprintf(stderr, "%s (%s) %d %s\n", host, inet_ntoa(S.sin_addr), (int) port, path);
2742510a 154 s = socket(PF_INET, SOCK_STREAM, 0);
2327c45c 155 if (s < 0) {
26ac0430
AJ
156 perror("socket");
157 return -errno;
2327c45c 158 }
2742510a 159 x = connect(s, (struct sockaddr *) &S, sizeof(S));
160 if (x < 0) {
26ac0430
AJ
161 perror(host);
162 return -errno;
2742510a 163 }
164 snprintf(request, URL_BUF_SZ,
26ac0430
AJ
165 "GET %s HTTP/1.1\r\n"
166 "Accept: */*\r\n"
167 "Host: %s\r\n"
168 "Connection: close\r\n"
169 "\r\n",
170 path,
171 host);
2742510a 172 x = write(s, request, strlen(request));
173 if (x < 0) {
26ac0430
AJ
174 perror("write");
175 return -errno;
2742510a 176 }
177 do {
26ac0430
AJ
178 x = read(s, reply, READ_BUF_SZ);
179 if (x > 0)
180 nr += x;
2742510a 181 } while (x > 0);
182 close(s);
183 return nr;
184}
185
186static void
187child_main_loop(void)
188{
189 char buf[URL_BUF_SZ];
190 char *t;
191 int n;
2327c45c 192 struct timeval t1;
193 struct timeval t2;
2742510a 194 if (debug)
26ac0430 195 fprintf(stderr, "Child PID %d entering child_main_loop\n", (int) getpid());
2742510a 196 setbuf(stdin, NULL);
197 setbuf(stdout, NULL);
198 setbuf(stderr, NULL);
199 while (fgets(buf, URL_BUF_SZ, stdin)) {
26ac0430
AJ
200 t = strchr(buf, '\n');
201 if (t == NULL)
202 continue;
203 *t = '\0';
204 if (strncmp(buf, "http://", 7))
205 continue;
206 gettimeofday(&t1, NULL);
207 n = get_url(buf);
208 gettimeofday(&t2, NULL);
209 printf("%d %d\n", n, tvSubMsec(t1, t2));
2742510a 210 }
211}
212
213static thing *
214create_a_thing(char *argv[])
215{
216 int p2c[2];
217 int c2p[2];
218 int prfd, pwfd, crfd, cwfd;
219 pid_t pid;
220 thing *t;
221 if (pipe(p2c) < 0)
26ac0430 222 abort();
2742510a 223 if (pipe(c2p) < 0)
26ac0430 224 abort();
2742510a 225 prfd = p2c[0];
226 cwfd = p2c[1];
227 crfd = c2p[0];
228 pwfd = c2p[1];
229 if ((pid = fork()) < 0)
26ac0430 230 abort();
2742510a 231 if (pid > 0) { /* parent */
26ac0430
AJ
232 /* close shared socket with child */
233 close(crfd);
234 close(cwfd);
235 t = calloc(1, sizeof(*t));
236 t->wfd = pwfd;
237 t->rfd = prfd;
238 if (pwfd > maxfd)
239 maxfd = pwfd;
240 if (prfd > maxfd)
241 maxfd = prfd;
242 t->pid = pid;
243 return t;
2742510a 244 }
245 /* child */
246 close(prfd);
247 close(pwfd);
248 dup2(crfd, 0);
249 dup2(cwfd, 1);
250 close(crfd);
251 close(cwfd);
252 child_main_loop();
253 exit(0);
254}
255
256static void
257create_children(char *argv[])
258{
259 thing *t;
260 thing **T = &things;
261 int i;
262 for (i = 0; i < 20; i++) {
26ac0430
AJ
263 t = create_a_thing(argv);
264 assert(t);
265 if (debug)
266 fprintf(stderr, "Thing #%d on FD %d/%d\n",
267 i, t->rfd, t->wfd);
268 *T = t;
269 T = &t->next;
2742510a 270 }
271}
272
273char *
274parent_read_url(void)
275{
276 static char buf[URL_BUF_SZ];
277 while (fgets(buf, URL_BUF_SZ, stdin)) {
26ac0430
AJ
278 if (strncmp(buf, "http://", 7))
279 continue;
280 return buf;
2742510a 281 }
282 return NULL;
283}
284
285static thing *
286get_idle_thing(void)
287{
288 thing *t;
289 thing *n = things;
290 while ((t = n)) {
26ac0430
AJ
291 n = t->next;
292 if (t->state == 0)
293 break;
2742510a 294 }
295 return t;
296}
297
298static void
299dispatch(thing * t, char *url)
300{
301 int x;
302 char *s;
303 assert(t->state == 0);
304 x = write(t->wfd, url, strlen(url));
305 if (x < 0)
26ac0430 306 perror("write");
2742510a 307 if (debug)
26ac0430 308 fprintf(stderr, "dispatched URL to thing PID %d, %d bytes\n", (int) t->pid, x);
2742510a 309 strncpy(t->url, url, URL_BUF_SZ);
310 if ((s = strchr(t->url, '\n')))
26ac0430 311 *s = '\0';
2742510a 312 t->state = 1;
313 FD_SET(t->rfd, &R1);
314}
315
316static void
317read_reply(thing * t)
318{
319 char buf[128];
320 int i;
321 int x;
2327c45c 322 int j;
2742510a 323 x = read(t->rfd, buf, 128);
324 if (x < 0) {
26ac0430 325 perror("read");
2327c45c 326 } else if (2 == sscanf(buf, "%d %d", &i, &j)) {
26ac0430
AJ
327 gettimeofday(&now, NULL);
328 printf("%d.%06d %9d %9d %s\n", (int) now.tv_sec, (int) now.tv_usec, i, j, t->url);
2742510a 329 }
330 t->state = 0;
331 FD_CLR(t->rfd, &R1);
332}
333
334static void
335parent_main_loop(void)
336{
337 thing *t;
338 char *url;
339 fd_set R2;
340 int x;
cae16863 341 struct timeval to;
2742510a 342 FD_ZERO(&R1);
343 for (;;) {
26ac0430
AJ
344 while ((t = get_idle_thing()) && (url = parent_read_url()))
345 dispatch(t, url);
346 R2 = R1;
347 to.tv_sec = 60;
348 to.tv_usec = 0;
349 x = select(maxfd + 1, &R2, NULL, NULL, &to);
350 if (x < 0) {
351 perror("select");
352 continue;
353 } else if (x == 0) {
354 return;
355 }
356 for (t = things; t; t = t->next) {
357 if (t->state != 1)
358 continue;
359 if (!FD_ISSET(t->rfd, &R2))
360 continue;
361 read_reply(t);
362 }
2742510a 363 }
364}
365
366static void
367sig_child(int sig)
368{
369 int status;
370 pid_t pid;
371 do {
26ac0430 372 pid = waitpid(-1, &status, WNOHANG);
2742510a 373 } while (pid > 0 || (pid < 0 && errno == EINTR));
374 signal(sig, sig_child);
375}
376
377
378int
379main(int argc, char *argv[])
380{
8d1ef8ff 381 int i;
2742510a 382 signal(SIGCHLD, sig_child);
383 create_children(argv);
384 parent_main_loop();
468ae12b 385 for (i = 3; i <= maxfd; i++)
26ac0430 386 close(i);
8d1ef8ff 387 sleep(1);
2742510a 388}