]>
git.ipfire.org Git - thirdparty/squid.git/blob - test-suite/tcp-banger2.c
4d1a8a1d0e361288f91ab73c099411112bc2e213
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
12 * On some systems, FD_SETSIZE is set to something lower than the
13 * actual number of files which can be opened. IRIX is one case,
14 * NetBSD is another. So here we increase FD_SETSIZE to our
15 * configure-discovered maximum *before* any system includes.
17 #define CHANGE_FD_SETSIZE 1
19 /* Cannot increase FD_SETSIZE on Linux */
21 #undef CHANGE_FD_SETSIZE
22 #define CHANGE_FD_SETSIZE 0
25 /* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
26 * to return EINVAL. */
27 /* Marian Durkovic <marian@svf.stuba.sk> */
28 /* Peter Wemm <peter@spinner.DIALix.COM> */
30 #include <osreldate.h>
31 #if __FreeBSD_version < 220000
32 #undef CHANGE_FD_SETSIZE
33 #define CHANGE_FD_SETSIZE 0
37 /* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
38 #if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
39 #define FD_SETSIZE SQUID_MAXFD
61 #include <sys/socket.h>
64 #include <netinet/in.h>
67 #include <arpa/inet.h>
82 #define PROXY_PORT 3128
83 #define PROXY_ADDR "127.0.0.1"
84 #define READ_BUF_SZ 4096
86 static int proxy_port
= PROXY_PORT
;
87 static char *proxy_addr
= PROXY_ADDR
;
88 static char *progname
;
91 static int opt_ims
= 0;
92 static int opt_range
= 0;
93 static int opt_accel
= 0;
94 static int max_connections
= 64;
95 static time_t lifetime
= 60;
96 static time_t process_lifetime
= 86400;
97 static struct timeval now
;
98 static long long total_bytes_written
= 0;
99 static long long total_bytes_read
= 0;
100 static int opt_checksum
= 0;
101 static char *custom_header
= NULL
;
102 FILE *trace_file
= NULL
;
104 typedef void (CB
) (int, void *);
116 char requestbodyfile
[256];
117 char buf
[READ_BUF_SZ
* 2 + 1];
128 struct _f FD
[SQUID_MAXFD
];
133 free_request(struct _request
*r
)
140 #define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
145 static char buf
[128];
146 struct tm
*gmt
= gmtime(t
);
148 (void) strftime(buf
, 127, RFC1123_STRFTIME
, gmt
);
157 FD
[fd
].ccb(fd
, FD
[fd
].data
);
163 while (fd
> 0 && FD
[fd
].cb
== NULL
)
170 fd_open(int fd
, CB
* cb
, void *data
, CB
* ccb
)
172 assert(fd
< SQUID_MAXFD
);
176 FD
[fd
].start
= now
.tv_sec
;
187 printf("\rWaiting for open connections to finish...\n");
188 signal(sig
, SIG_DFL
);
192 read_reply(int fd
, void *data
)
194 struct _request
*r
= data
;
195 static unsigned char buf
[READ_BUF_SZ
];
198 if ((len
= read(fd
, buf
, READ_BUF_SZ
)) <= 0) {
204 total_bytes_read
+= len
;
205 if (r
->headfound
< 2) {
206 char *p
, *header
= NULL
;
207 int oldlen
= strlen(r
->buf
);
208 int newlen
= oldlen
+ len
;
209 assert(oldlen
<= READ_BUF_SZ
);
210 memcpy(r
->buf
+ oldlen
, buf
, len
);
211 r
->buf
[newlen
+ 1] = '\0';
212 for (p
= r
->buf
; r
->headfound
< 2 && used
< newlen
; p
++, used
++) {
219 if (strncmp(header
, "HTTP", 4) == 0)
220 r
->status
= atoi(header
+ 8);
221 else if (strncasecmp(header
, "Content-Length:", 15) == 0)
222 r
->content_length
= atoi(header
+ 15);
223 else if (strncasecmp(header
, "X-Request-URI:", 14) == 0) {
225 if (strncmp(r
->url
, header
+ 15, strcspn(header
+ 15, "\r\n"))) {
227 strncpy(url
, header
+ 15, strcspn(header
+ 15, "\r\n"));
228 url
[strcspn(header
+ 15, "\r\n")] = '\n';
229 fprintf(stderr
, "ERROR: Sent %s received %s\n",
245 memmove(r
->buf
, header
, newlen
- (header
- r
->buf
) + 1);
247 assert(used
>= oldlen
);
250 r
->bodysize
+= len
- used
;
252 for (; used
< len
; used
++) {
259 reply_done(int fd
, void *data
)
261 struct _request
*r
= data
;
262 if (opt_range
); /* skip size checks for now */
263 else if (strcmp(r
->method
, "HEAD") == 0);
264 else if (r
->bodysize
!= r
->content_length
&& r
->content_length
>= 0)
265 fprintf(stderr
, "ERROR: %s got %d of %d bytes\n",
266 r
->url
, r
->bodysize
, r
->content_length
);
267 else if (r
->validsize
>= 0) {
268 if (r
->validsize
!= r
->bodysize
)
269 fprintf(stderr
, "WARNING: %s size mismatch wanted %d bytes got %d\n",
270 r
->url
, r
->validsize
, r
->bodysize
);
271 else if (opt_checksum
&& r
->validsum
!= r
->sum
)
272 fprintf(stderr
, "WARNING: %s invalid checksum wanted 0x%lx got 0x%lx\n",
273 r
->url
, r
->validsum
, r
->sum
);
275 if (r
->validstatus
&& r
->status
!= r
->validstatus
) {
276 fprintf(stderr
, "WARNING: %s status mismatch wanted %d got %d\n",
277 r
->url
, r
->validstatus
, r
->status
);
281 fprintf(trace_file
, "%s %s %d %s %d 0x%lx\n",
282 r
->method
, r
->url
, r
->status
, r
->requestbodyfile
, r
->bodysize
, r
->sum
);
284 fprintf(trace_file
, "%s %s %d %s %d\n",
285 r
->method
, r
->url
, r
->status
, r
->requestbodyfile
, r
->bodysize
);
291 request(char *urlin
) {
295 char *method
, *url
, *file
, *size
, *checksum
, *status
;
301 struct sockaddr_in S
;
305 if ((s
= socket(PF_INET
, SOCK_STREAM
, 0)) < 0) {
309 memset(&S
, '\0', sizeof(struct sockaddr_in
));
310 S
.sin_family
= AF_INET
;
311 S
.sin_port
= htons(proxy_port
);
312 S
.sin_addr
.s_addr
= inet_addr(proxy_addr
);
313 if (connect(s
, (struct sockaddr
*) &S
, sizeof(S
)) < 0) {
318 strcpy(urlbuf
, urlin
);
319 method
= strtok(urlbuf
, " ");
320 url
= strtok(NULL
, " ");
321 status
= strtok(NULL
, " ");
322 file
= strtok(NULL
, " ");
323 size
= strtok(NULL
, " ");
324 checksum
= strtok(NULL
, " ");
335 r
= calloc(1, sizeof *r
);
337 r
->url
= xstrdup(url
);
339 strcpy(r
->method
, method
);
340 strcpy(r
->requestbodyfile
, file
);
342 if (size
&& strcmp(size
, "-") != 0)
343 r
->validsize
= atoi(size
);
345 r
->validsize
= -1; /* Unknown */
346 if (checksum
&& strcmp(checksum
, "-") != 0)
347 r
->validsum
= strtoul(checksum
, NULL
, 0);
349 r
->validstatus
= atoi(status
);
350 r
->content_length
= -1; /* Unknown */
352 host
= strchr(url
, '/') + 2;
353 url
= strchr(host
, '/');
357 snprintf(msg
, sizeof(msg
)-1, "%s %s HTTP/1.0\r\n", method
, url
);
360 snprintf(buf
, sizeof(buf
)-1, "Host: %s\r\n", host
);
364 strcat(msg
, "Accept: */*\r\n");
365 if (opt_ims
&& (lrand48() & 0x03) == 0) {
366 w
= time(NULL
) - (lrand48() & 0x3FFFF);
367 snprintf(buf
, sizeof(buf
)-1, "If-Modified-Since: %s\r\n", mkrfc850(&w
));
370 if (file
&& strcmp(file
, "-") != 0) {
371 f
= open(file
, O_RDONLY
);
377 snprintf(buf
, sizeof(buf
)-1, "Content-Length: %d\r\n", (int) st
.st_size
);
380 if (opt_range
&& (lrand48() & 0x03) == 0) {
383 strcat(msg
, "Range: bytes=");
384 while (((len
= (int) lrand48()) & 0x03) == 0 || !count
) {
385 const int offset
= (int) lrand48();
388 switch (lrand48() & 0x03) {
390 snprintf(buf
, sizeof(buf
)-1, "-%d", len
);
393 snprintf(buf
, sizeof(buf
)-1, "%d-", offset
);
396 snprintf(buf
, sizeof(buf
)-1, "%d-%d", offset
, offset
+ len
);
404 strcat(msg
, custom_header
);
407 if ((len2
= write(s
, msg
, len
)) != len
) {
409 perror("write request");
413 total_bytes_written
+= len2
;
415 while ((len
= read(f
, buf
, sizeof(buf
))) > 0) {
416 len2
= write(s
, buf
, len
);
418 perror("write body");
429 * if (fcntl(s, F_SETFL, O_NDELAY) < 0)
430 * perror("fcntl O_NDELAY");
436 read_url(int fd
, void *junk
)
439 static char buf
[8192];
442 if (fgets(buf
, 8191, stdin
) == NULL
) {
443 printf("Done Reading URLS\n");
450 if ((t
= strchr(buf
, '\n')))
454 max_connections
= nfds
- 1;
455 printf("NOTE: max_connections set at %d\n", max_connections
);
457 fd_open(r
->fd
, read_reply
, r
, reply_done
);
464 fprintf(stderr
, "usage: %s: -p port -h host -n max\n", progname
);
465 fprintf(stderr
, " -t <tracefile> Save request trace\n");
466 fprintf(stderr
, " -c Check checksum agains trace\n");
467 fprintf(stderr
, " -i Send random If-Modified-Since times\n");
468 fprintf(stderr
, " -l <seconds> Connection lifetime timeout (default 60)\n");
469 fprintf(stderr
, " -a Accelerator mode\n");
470 fprintf(stderr
, " -H <string> Custom header\n");
483 struct timeval start
;
486 setbuf(stdout
, NULL
);
487 setbuf(stderr
, NULL
);
488 progname
= xstrdup(argv
[0]);
489 gettimeofday(&now
, NULL
);
491 custom_header
= xstrdup("");
492 while ((c
= getopt(argc
, argv
, "ap:h:H:n:icrl:L:t:")) != -1) {
498 proxy_port
= atoi(optarg
);
501 proxy_addr
= xstrdup(optarg
);
504 max_connections
= atoi(optarg
);
510 lifetime
= (time_t) atoi(optarg
);
513 process_lifetime
= (time_t) atoi(optarg
);
519 trace_file
= fopen(optarg
, "a");
521 setbuf(trace_file
, NULL
);
527 custom_header
= realloc(custom_header
, strlen(custom_header
) + strlen(optarg
) + 2 + 1);
528 strcat(custom_header
, optarg
);
529 strcat(custom_header
, "\r\n");
536 fd_open(0, read_url
, NULL
, NULL
);
538 signal(SIGINT
, sig_intr
);
539 signal(SIGPIPE
, SIG_IGN
);
541 while (nfds
|| FD
[0].cb
) {
545 if (nfds
< max_connections
&& FD
[0].cb
)
547 for (i
= 1; i
<= maxfd
; i
++) {
548 if (FD
[i
].cb
== NULL
)
550 if (now
.tv_sec
- FD
[i
].start
> lifetime
) {
551 fprintf(stderr
, "WARNING: fd %d lifetime timeout\n", i
);
557 if (select(maxfd
+ 1, &R
, NULL
, NULL
, &to
) < 0) {
558 fprintf(stderr
, "maxfd=%d\n", maxfd
);
563 gettimeofday(&now
, NULL
);
564 for (i
= 0; i
<= maxfd
; i
++) {
565 if (!FD_ISSET(i
, &R
))
567 FD
[i
].cb(i
, FD
[i
].data
);
568 if (nfds
< max_connections
&& FD
[0].cb
) {
573 if (select(1, &R2
, NULL
, NULL
, &to
) == 1)
574 FD
[0].cb(0, FD
[0].data
);
577 if (now
.tv_sec
> last
.tv_sec
) {
579 dt
= (int) (now
.tv_sec
- start
.tv_sec
);
580 printf("T+ %6d: %9d req (%+4d), %4d conn, %3d/sec avg, %dmb, %dkb/sec avg\n",
585 (int) (nrequests
/ dt
),
586 (int) (total_bytes_read
/ 1024 / 1024),
587 (int) (total_bytes_read
/ 1024 / dt
));
590 * if (dt > process_lifetime)
595 printf("Exiting normally\n");