]>
git.ipfire.org Git - thirdparty/squid.git/blob - test-suite/pconn-banger.c
2 * Copyright (C) 1996-2020 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.
33 #include <sys/socket.h>
36 #include <netinet/in.h>
39 #include <arpa/inet.h>
54 #define PROXY_PORT "3128"
55 #define PROXY_ADDR "127.0.0.1"
57 #define READ_BUF_SZ 4096
58 #define min(x,y) ((x)<(y)? (x) : (y))
60 static int proxy_port
= PROXY_PORT
;
61 static char *proxy_addr
= PROXY_ADDR
;
62 static char *progname
;
63 static int noutstanding
= 0;
64 static int done_reading_urls
= 0;
65 static int opt_ims
= 0;
66 static int opt_checksum
= 0;
67 static int opt_reopen
= 1;
68 static int max_outstanding
= 10;
69 static time_t lifetime
= 60;
70 static const char *const crlf
= "\r\n";
71 static int trace_fd
= -1;
72 static int total_bytes_read
= 0;
74 #define REPLY_HDR_SZ 8192
82 char reply_hdrs
[REPLY_HDR_SZ
];
89 static struct _r
*Requests
;
96 struct tm
*gmt
= gmtime(t
);
98 (void) strftime(buf
, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt
);
103 mime_headers_end(const char *mime
)
106 const char *end
= NULL
;
108 p1
= strstr(mime
, "\n\r\n");
109 p2
= strstr(mime
, "\n\n");
112 end
= p1
< p2
? p1
: p2
;
116 end
+= (end
== p1
? 3 : 2);
124 fprintf(stderr
, "\rWaiting for open connections to finish...\n");
125 signal(sig
, SIG_DFL
);
126 done_reading_urls
= 1;
130 open_http_socket(void)
133 struct addrinfo
*AI
= NULL
;
134 struct addrinfo hints
;
136 memset(&hints
, '\0', sizeof(struct addrinfo
));
137 hints
.ai_flags
= AI_NUMERICHOST
|AI_NUMERICSERV
;
138 hints
.ai_family
= AF_UNSPEC
;
139 hints
.ai_socktype
= SOCK_STREAM
;
141 getaddrinfo(proxy_addr
, proxy_port
, &hints
, AI
);
143 if ((s
= socket(AI
->ai_family
, AI
->ai_socktype
, AI
->ai_protocol
)) < 0) {
146 } else if (connect(s
, AI
->ai_addr
, AI
->ai_addrlen
) < 0) {
157 send_request(int fd
, const char *data
)
159 char msg
[4096], buf
[4096];
164 char *method
, *url
, *file
, *size
, *checksum
;
165 char *tmp
= xstrdup(data
);
168 method
= strtok(tmp
, " ");
169 url
= strtok(NULL
, " ");
170 file
= strtok(NULL
, " ");
171 size
= strtok(NULL
, " ");
172 checksum
= strtok(NULL
, " ");
177 if (file
&& strcmp(file
, "-") == 0)
179 if (size
&& strcmp(size
, "-") == 0)
181 if (checksum
&& strcmp(checksum
, "-") == 0)
184 snprintf(buf
, sizeof(buf
)-1, "%s %s HTTP/1.0\r\n", method
, url
);
186 strcat(msg
, "Accept: */*\r\n");
187 strcat(msg
, "Proxy-Connection: Keep-Alive\r\n");
188 if (opt_ims
&& (lrand48() & 0x03) == 0) {
189 w
= time(NULL
) - (lrand48() & 0x3FFFF);
190 snprintf(buf
, sizeof(buf
)-1, "If-Modified-Since: %s\r\n", mkrfc850(&w
));
194 if ((file_fd
= open(file
, O_RDONLY
)) < 0) {
198 if (fstat(file_fd
, &st
)) {
203 snprintf(buf
, sizeof(buf
)-1, "Content-length: %d\r\n", st
.st_size
);
208 if (write(fd
, msg
, len
) < 0) {
210 perror("request write");
215 while ((len
= read(file_fd
, buf
, sizeof buf
)) > 0) {
216 if (write(fd
, buf
, len
) < 0) {
218 perror("body write");
230 r
= calloc(1, sizeof(struct _r
));
233 r
->validsize
= atoi(size
);
237 r
->validsum
= atoi(checksum
);
238 for (R
= &Requests
; *R
; R
= &(*R
)->next
);
240 /* fprintf(stderr, "REQUESTED %s\n", url); */
246 get_header_int_value(const char *hdr
, const char *buf
, const char *end
)
249 for (t
= buf
; t
< end
; t
+= strcspn(t
, crlf
), t
+= strspn(t
, crlf
)) {
250 if (strncasecmp(t
, hdr
, strlen(hdr
)) == 0) {
261 get_header_string_value(const char *hdr
, const char *buf
, const char *end
)
264 static char result
[8192];
265 for (t
= buf
; t
< end
; t
+= strcspn(t
, crlf
), t
+= strspn(t
, crlf
)) {
266 if (strncasecmp(t
, hdr
, strlen(hdr
)) == 0) {
271 strncat(result
, t
, strcspn(t
, crlf
));
279 request_done(struct _r
*r
)
282 fprintf(stderr
, "DONE: %s, (%d+%d)\n",
287 if (r
->content_length
!= r
->bytes_read
)
288 fprintf(stderr
, "ERROR! Short reply, expected %d bytes got %d\n",
289 r
->content_length
, r
->bytes_read
);
290 else if (r
->validsize
>= 0) {
291 if (r
->validsize
!= r
->bytes_read
)
292 fprintf(stderr
, "WARNING: %s Object size mismatch, expected %d got %d\n",
293 r
->url
, r
->validsize
, r
->bytes_read
);
294 else if (opt_checksum
&& r
->sum
!= r
->validsum
)
295 fprintf(stderr
, "WARNING: %s Checksum error. Expected %d got %d\n",
296 r
->url
, r
->validsum
, r
->sum
);
300 handle_read(char *inbuf
, int len
)
302 struct _r
*r
= Requests
;
305 static char buf
[READ_BUF_SZ
];
314 write(trace_fd
, "\n[CLOSED]\n", 10);
317 total_bytes_read
+= len
;
318 memcpy(buf
, inbuf
, len
);
320 fprintf(stderr
, "WARNING: %s, server closed socket after %d+%d bytes\n", r
->url
, r
->hdr_offset
, r
->bytes_read
);
321 /* XXX, If no data was received and it isn't the first request on this
322 * connection then the request should be restarted rather than aborted
323 * but this is a simple test program an not a full blown HTTP client.
332 write(trace_fd
, buf
, len
);
335 if (r
->hdr_length
== 0) {
336 hlen
= min(len
, REPLY_HDR_SZ
- r
->hdr_offset
- 1);
337 memcpy(r
->reply_hdrs
+ r
->hdr_offset
, buf
, hlen
);
338 r
->hdr_offset
+= hlen
;
339 r
->reply_hdrs
[r
->hdr_offset
] = '\0';
341 /* Save any remaining read data */
342 memmove(buf
, buf
+ hlen
, len
);
344 /* Process headers */
345 if (r
->hdr_length
== 0 && (end
= mime_headers_end(r
->reply_hdrs
)) != NULL
) {
347 fprintf(stderr
, "FOUND EOH FOR %s\n", r
->url
);
350 r
->hdr_length
= end
- r
->reply_hdrs
;
352 fprintf(stderr
, "HDR_LENGTH = %d\n", r
->hdr_length
);
354 /* "unread" any body contents received */
355 blen
= r
->hdr_offset
- r
->hdr_length
;
358 memmove(buf
+ blen
, buf
, len
);
359 memcpy(buf
, r
->reply_hdrs
+ r
->hdr_length
, blen
);
362 r
->reply_hdrs
[r
->hdr_length
] = '\0'; /* Null terminate headers */
364 r
->content_length
= get_header_int_value("content-length:", r
->reply_hdrs
, end
);
365 /* fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length); */
366 url
= get_header_string_value("X-Request-URI:", r
->reply_hdrs
, end
);
367 if (url
!= NULL
&& strcmp(r
->url
, url
) != 0)
368 fprintf(stderr
, "WARNING: %s got reply %s\n", r
->url
, url
);
370 fprintf(stderr
, "LOCATION = %s\n", get_header_string_value("X-Request-URI:", r
->reply_hdrs
, end
));
373 if (!(len
== 0 || r
->hdr_length
> 0)) {
374 fprintf(stderr
, "ERROR!!!\n");
375 assert((len
== 0 || r
->hdr_length
> 0));
378 if (r
->hdr_length
!= 0) {
380 int bytes_left
, bytes_used
;
381 if (r
->content_length
>= 0) {
382 bytes_left
= r
->content_length
- r
->bytes_read
;
383 assert(bytes_left
>= 0);
384 bytes_used
= len
< bytes_left
? len
: bytes_left
;
386 bytes_left
= len
+ 1; /* Unknown end... */
390 for (i
= 0; i
< bytes_used
; i
++)
391 r
->sum
+= (int) buf
[i
] & 0xFF;
393 r
->bytes_read
+= bytes_used
;
395 if (bytes_left
== bytes_used
) {
401 } else if (r
->content_length
> -1) {
402 assert(r
->bytes_read
< r
->content_length
);
404 memmove(buf
, buf
+ bytes_used
, len
);
413 static char buf
[READ_BUF_SZ
];
416 len
= read(fd
, buf
, READ_BUF_SZ
);
417 x
= handle_read(buf
, len
);
419 perror("read reply");
428 static int pconn_fd
= -1;
429 static char buf
[8192];
431 struct timeval now
, last
, start
;
437 int nrequests
= 0, rrequests
= 0, reqpersec
= 0;
439 gettimeofday(&start
, NULL
);
442 pconn_fd
= open_http_socket();
447 while (!done_reading_urls
|| noutstanding
) {
448 if (!opt_reopen
&& pconn_fd
< 0) {
449 fprintf(stderr
, "TERMINATED: Connection closed\n");
453 pconn_fd
= open_http_socket();
461 while ((r
= nextr
) != NULL
) {
463 if (send_request(pconn_fd
, r
->url
) != 0) {
467 for (r
= Requests
; r
!= NULL
&& r
->next
; r
= r
->next
);
480 if (timeouts
== 200) {
484 Requests
= Requests
->next
;
485 fprintf(stderr
, "ABORT %s\n", Requests
->url
);
489 if (pconn_fd
>= 0 && noutstanding
< max_outstanding
&& !done_reading_urls
) {
491 if (fgets(buf
, 8191, stdin
) == NULL
) {
492 fprintf(stderr
, "Done Reading URLS\n");
493 done_reading_urls
= 1;
497 if ((t
= strchr(buf
, '\n')))
499 if (send_request(pconn_fd
, buf
) != 0) {
511 FD_SET(pconn_fd
, &R
);
512 x
= select(pconn_fd
+ 1, &R
, NULL
, NULL
, &to
);
518 assert(Requests
!= NULL
);
519 fprintf(stderr
, "TIMEOUT %s; %d, %d\n", Requests
->url
,
520 ++timeouts
, noutstanding
);
523 if (FD_ISSET(pconn_fd
, &R
)) {
525 if (read_reply(pconn_fd
) != 0)
528 gettimeofday(&now
, NULL
);
529 if (now
.tv_sec
> last
.tv_sec
) {
533 dt
= (int) (now
.tv_sec
- start
.tv_sec
);
535 for (r
= Requests
; r
; r
= r
->next
)
537 printf("T+ %6d: %9d req (%+4d), %4d pend, %3d/sec avg, %dmb, %dkb/sec avg\n",
542 (int) (nrequests
/ dt
),
543 (int) total_bytes_read
/ 1024 / 1024,
544 (int) total_bytes_read
/ 1024 / dt
);
553 fprintf(stderr
, "usage: %s: -p port -h host -n max -t tracefile -i -c -l lifetime\n", progname
);
562 setbuf(stdout
, NULL
);
563 setbuf(stderr
, NULL
);
564 progname
= xstrdup(argv
[0]);
565 while ((c
= getopt(argc
, argv
, "p:h:n:t:icl:r")) != -1) {
568 proxy_port
= atoi(optarg
);
571 proxy_addr
= xstrdup(optarg
);
574 max_outstanding
= atoi(optarg
);
583 lifetime
= (time_t) atoi(optarg
);
586 trace_fd
= open(optarg
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0666);
589 opt_reopen
= !opt_reopen
;
596 signal(SIGINT
, sig_intr
);
597 signal(SIGPIPE
, SIG_IGN
);