]>
git.ipfire.org Git - thirdparty/squid.git/blob - test-suite/pconn-banger.c
2 * Copyright (C) 1996-2014 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.
10 #include "compat/getaddrinfo.h"
34 #include <sys/socket.h>
37 #include <netinet/in.h>
40 #include <arpa/inet.h>
55 #define PROXY_PORT "3128"
56 #define PROXY_ADDR "127.0.0.1"
58 #define READ_BUF_SZ 4096
59 #define min(x,y) ((x)<(y)? (x) : (y))
61 static int proxy_port
= PROXY_PORT
;
62 static char *proxy_addr
= PROXY_ADDR
;
63 static char *progname
;
64 static int noutstanding
= 0;
65 static int done_reading_urls
= 0;
66 static int opt_ims
= 0;
67 static int opt_checksum
= 0;
68 static int opt_reopen
= 1;
69 static int max_outstanding
= 10;
70 static time_t lifetime
= 60;
71 static const char *const crlf
= "\r\n";
72 static int trace_fd
= -1;
73 static int total_bytes_read
= 0;
75 #define REPLY_HDR_SZ 8192
83 char reply_hdrs
[REPLY_HDR_SZ
];
90 static struct _r
*Requests
;
97 struct tm
*gmt
= gmtime(t
);
99 (void) strftime(buf
, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt
);
104 mime_headers_end(const char *mime
)
107 const char *end
= NULL
;
109 p1
= strstr(mime
, "\n\r\n");
110 p2
= strstr(mime
, "\n\n");
113 end
= p1
< p2
? p1
: p2
;
117 end
+= (end
== p1
? 3 : 2);
125 fprintf(stderr
, "\rWaiting for open connections to finish...\n");
126 signal(sig
, SIG_DFL
);
127 done_reading_urls
= 1;
131 open_http_socket(void)
134 struct addrinfo
*AI
= NULL
;
135 struct addrinfo hints
;
137 memset(&hints
, '\0', sizeof(struct addrinfo
));
138 hints
.ai_flags
= AI_NUMERICHOST
|AI_NUMERICSERV
;
139 hints
.ai_family
= AF_UNSPEC
;
140 hints
.ai_socktype
= SOCK_STREAM
;
142 getaddrinfo(proxy_addr
, proxy_port
, &hints
, AI
);
144 if ((s
= socket(AI
->ai_family
, AI
->ai_socktype
, AI
->ai_protocol
)) < 0) {
147 } else if (connect(s
, AI
->ai_addr
, AI
->ai_addrlen
) < 0) {
158 send_request(int fd
, const char *data
)
160 char msg
[4096], buf
[4096];
165 char *method
, *url
, *file
, *size
, *checksum
;
166 char *tmp
= xstrdup(data
);
169 method
= strtok(tmp
, " ");
170 url
= strtok(NULL
, " ");
171 file
= strtok(NULL
, " ");
172 size
= strtok(NULL
, " ");
173 checksum
= strtok(NULL
, " ");
178 if (file
&& strcmp(file
, "-") == 0)
180 if (size
&& strcmp(size
, "-") == 0)
182 if (checksum
&& strcmp(checksum
, "-") == 0)
185 snprintf(buf
, sizeof(buf
)-1, "%s %s HTTP/1.0\r\n", method
, url
);
187 strcat(msg
, "Accept: */*\r\n");
188 strcat(msg
, "Proxy-Connection: Keep-Alive\r\n");
189 if (opt_ims
&& (lrand48() & 0x03) == 0) {
190 w
= time(NULL
) - (lrand48() & 0x3FFFF);
191 snprintf(buf
, sizeof(buf
)-1, "If-Modified-Since: %s\r\n", mkrfc850(&w
));
195 if ((file_fd
= open(file
, O_RDONLY
)) < 0) {
199 if (fstat(file_fd
, &st
)) {
204 snprintf(buf
, sizeof(buf
)-1, "Content-length: %d\r\n", st
.st_size
);
209 if (write(fd
, msg
, len
) < 0) {
211 perror("request write");
216 while ((len
= read(file_fd
, buf
, sizeof buf
)) > 0) {
217 if (write(fd
, buf
, len
) < 0) {
219 perror("body write");
231 r
= calloc(1, sizeof(struct _r
));
234 r
->validsize
= atoi(size
);
238 r
->validsum
= atoi(checksum
);
239 for (R
= &Requests
; *R
; R
= &(*R
)->next
);
241 /* fprintf(stderr, "REQUESTED %s\n", url); */
247 get_header_int_value(const char *hdr
, const char *buf
, const char *end
)
250 for (t
= buf
; t
< end
; t
+= strcspn(t
, crlf
), t
+= strspn(t
, crlf
)) {
251 if (strncasecmp(t
, hdr
, strlen(hdr
)) == 0) {
262 get_header_string_value(const char *hdr
, const char *buf
, const char *end
)
265 static char result
[8192];
266 for (t
= buf
; t
< end
; t
+= strcspn(t
, crlf
), t
+= strspn(t
, crlf
)) {
267 if (strncasecmp(t
, hdr
, strlen(hdr
)) == 0) {
272 strncat(result
, t
, strcspn(t
, crlf
));
280 request_done(struct _r
*r
)
283 fprintf(stderr
, "DONE: %s, (%d+%d)\n",
288 if (r
->content_length
!= r
->bytes_read
)
289 fprintf(stderr
, "ERROR! Short reply, expected %d bytes got %d\n",
290 r
->content_length
, r
->bytes_read
);
291 else if (r
->validsize
>= 0) {
292 if (r
->validsize
!= r
->bytes_read
)
293 fprintf(stderr
, "WARNING: %s Object size mismatch, expected %d got %d\n",
294 r
->url
, r
->validsize
, r
->bytes_read
);
295 else if (opt_checksum
&& r
->sum
!= r
->validsum
)
296 fprintf(stderr
, "WARNING: %s Checksum error. Expected %d got %d\n",
297 r
->url
, r
->validsum
, r
->sum
);
301 handle_read(char *inbuf
, int len
)
303 struct _r
*r
= Requests
;
306 static char buf
[READ_BUF_SZ
];
315 write(trace_fd
, "\n[CLOSED]\n", 10);
318 total_bytes_read
+= len
;
319 memcpy(buf
, inbuf
, len
);
321 fprintf(stderr
, "WARNING: %s, server closed socket after %d+%d bytes\n", r
->url
, r
->hdr_offset
, r
->bytes_read
);
322 /* XXX, If no data was received and it isn't the first request on this
323 * connection then the request should be restarted rather than aborted
324 * but this is a simple test program an not a full blown HTTP client.
333 write(trace_fd
, buf
, len
);
336 if (r
->hdr_length
== 0) {
337 hlen
= min(len
, REPLY_HDR_SZ
- r
->hdr_offset
- 1);
338 memcpy(r
->reply_hdrs
+ r
->hdr_offset
, buf
, hlen
);
339 r
->hdr_offset
+= hlen
;
340 r
->reply_hdrs
[r
->hdr_offset
] = '\0';
342 /* Save any remaining read data */
343 memmove(buf
, buf
+ hlen
, len
);
345 /* Process headers */
346 if (r
->hdr_length
== 0 && (end
= mime_headers_end(r
->reply_hdrs
)) != NULL
) {
348 fprintf(stderr
, "FOUND EOH FOR %s\n", r
->url
);
351 r
->hdr_length
= end
- r
->reply_hdrs
;
353 fprintf(stderr
, "HDR_LENGTH = %d\n", r
->hdr_length
);
355 /* "unread" any body contents received */
356 blen
= r
->hdr_offset
- r
->hdr_length
;
359 memmove(buf
+ blen
, buf
, len
);
360 memcpy(buf
, r
->reply_hdrs
+ r
->hdr_length
, blen
);
363 r
->reply_hdrs
[r
->hdr_length
] = '\0'; /* Null terminate headers */
365 r
->content_length
= get_header_int_value("content-length:", r
->reply_hdrs
, end
);
366 /* fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length); */
367 url
= get_header_string_value("X-Request-URI:", r
->reply_hdrs
, end
);
368 if (url
!= NULL
&& strcmp(r
->url
, url
) != 0)
369 fprintf(stderr
, "WARNING: %s got reply %s\n", r
->url
, url
);
371 fprintf(stderr
, "LOCATION = %s\n", get_header_string_value("X-Request-URI:", r
->reply_hdrs
, end
));
374 if (!(len
== 0 || r
->hdr_length
> 0)) {
375 fprintf(stderr
, "ERROR!!!\n");
376 assert((len
== 0 || r
->hdr_length
> 0));
379 if (r
->hdr_length
!= 0) {
381 int bytes_left
, bytes_used
;
382 if (r
->content_length
>= 0) {
383 bytes_left
= r
->content_length
- r
->bytes_read
;
384 assert(bytes_left
>= 0);
385 bytes_used
= len
< bytes_left
? len
: bytes_left
;
387 bytes_left
= len
+ 1; /* Unknown end... */
391 for (i
= 0; i
< bytes_used
; i
++)
392 r
->sum
+= (int) buf
[i
] & 0xFF;
394 r
->bytes_read
+= bytes_used
;
396 if (bytes_left
== bytes_used
) {
402 } else if (r
->content_length
> -1) {
403 assert(r
->bytes_read
< r
->content_length
);
405 memmove(buf
, buf
+ bytes_used
, len
);
414 static char buf
[READ_BUF_SZ
];
417 len
= read(fd
, buf
, READ_BUF_SZ
);
418 x
= handle_read(buf
, len
);
420 perror("read reply");
429 static int pconn_fd
= -1;
430 static char buf
[8192];
432 struct timeval now
, last
, start
;
438 int nrequests
= 0, rrequests
= 0, reqpersec
= 0;
440 gettimeofday(&start
, NULL
);
443 pconn_fd
= open_http_socket();
448 while (!done_reading_urls
|| noutstanding
) {
449 if (!opt_reopen
&& pconn_fd
< 0) {
450 fprintf(stderr
, "TERMINATED: Connection closed\n");
454 pconn_fd
= open_http_socket();
462 while ((r
= nextr
) != NULL
) {
464 if (send_request(pconn_fd
, r
->url
) != 0) {
468 for (r
= Requests
; r
!= NULL
&& r
->next
; r
= r
->next
);
481 if (timeouts
== 200) {
485 Requests
= Requests
->next
;
486 fprintf(stderr
, "ABORT %s\n", Requests
->url
);
490 if (pconn_fd
>= 0 && noutstanding
< max_outstanding
&& !done_reading_urls
) {
492 if (fgets(buf
, 8191, stdin
) == NULL
) {
493 fprintf(stderr
, "Done Reading URLS\n");
494 done_reading_urls
= 1;
498 if ((t
= strchr(buf
, '\n')))
500 if (send_request(pconn_fd
, buf
) != 0) {
512 FD_SET(pconn_fd
, &R
);
513 x
= select(pconn_fd
+ 1, &R
, NULL
, NULL
, &to
);
519 assert(Requests
!= NULL
);
520 fprintf(stderr
, "TIMEOUT %s; %d, %d\n", Requests
->url
,
521 ++timeouts
, noutstanding
);
524 if (FD_ISSET(pconn_fd
, &R
)) {
526 if (read_reply(pconn_fd
) != 0)
529 gettimeofday(&now
, NULL
);
530 if (now
.tv_sec
> last
.tv_sec
) {
534 dt
= (int) (now
.tv_sec
- start
.tv_sec
);
536 for (r
= Requests
; r
; r
= r
->next
)
538 printf("T+ %6d: %9d req (%+4d), %4d pend, %3d/sec avg, %dmb, %dkb/sec avg\n",
543 (int) (nrequests
/ dt
),
544 (int) total_bytes_read
/ 1024 / 1024,
545 (int) total_bytes_read
/ 1024 / dt
);
554 fprintf(stderr
, "usage: %s: -p port -h host -n max -t tracefile -i -c -l lifetime\n", progname
);
563 setbuf(stdout
, NULL
);
564 setbuf(stderr
, NULL
);
565 progname
= xstrdup(argv
[0]);
566 while ((c
= getopt(argc
, argv
, "p:h:n:t:icl:r")) != -1) {
569 proxy_port
= atoi(optarg
);
572 proxy_addr
= xstrdup(optarg
);
575 max_outstanding
= atoi(optarg
);
584 lifetime
= (time_t) atoi(optarg
);
587 trace_fd
= open(optarg
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0666);
590 opt_reopen
= !opt_reopen
;
597 signal(SIGINT
, sig_intr
);
598 signal(SIGPIPE
, SIG_IGN
);