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