]>
Commit | Line | Data |
---|---|---|
47130615 | 1 | |
eb5f55b3 | 2 | #include "config.h" |
3 | ||
4 | /* | |
5 | * On some systems, FD_SETSIZE is set to something lower than the | |
6 | * actual number of files which can be opened. IRIX is one case, | |
7 | * NetBSD is another. So here we increase FD_SETSIZE to our | |
8 | * configure-discovered maximum *before* any system includes. | |
9 | */ | |
10 | #define CHANGE_FD_SETSIZE 1 | |
11 | ||
12 | /* Cannot increase FD_SETSIZE on Linux */ | |
13 | #if defined(_SQUID_LINUX_) | |
14 | #undef CHANGE_FD_SETSIZE | |
15 | #define CHANGE_FD_SETSIZE 0 | |
16 | #endif | |
17 | ||
18 | /* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2) | |
19 | * to return EINVAL. */ | |
20 | /* Marian Durkovic <marian@svf.stuba.sk> */ | |
21 | /* Peter Wemm <peter@spinner.DIALix.COM> */ | |
22 | #if defined(_SQUID_FREEBSD_) | |
23 | #include <osreldate.h> | |
24 | #if __FreeBSD_version < 220000 | |
25 | #undef CHANGE_FD_SETSIZE | |
26 | #define CHANGE_FD_SETSIZE 0 | |
27 | #endif | |
28 | #endif | |
29 | ||
30 | /* Increase FD_SETSIZE if SQUID_MAXFD is bigger */ | |
31 | #if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE | |
32 | #define FD_SETSIZE SQUID_MAXFD | |
33 | #endif | |
34 | ||
35 | #if HAVE_UNISTD_H | |
36 | #include <unistd.h> | |
37 | #endif | |
38 | #if HAVE_STDLIB_H | |
39 | #include <stdlib.h> | |
40 | #endif | |
41 | #if HAVE_STDIO_H | |
42 | #include <stdio.h> | |
43 | #endif | |
44 | #if HAVE_FCNTL_H | |
45 | #include <fcntl.h> | |
46 | #endif | |
47 | #ifdef HAVE_STRING_H | |
48 | #include <string.h> | |
49 | #endif | |
50 | #ifdef HAVE_STRINGS_H | |
51 | #include <strings.h> | |
52 | #endif | |
53 | #ifdef HAVE_BSTRING_H | |
54 | #include <bstring.h> | |
55 | #endif | |
56 | #if HAVE_SYS_TYPES_H | |
57 | #include <sys/types.h> | |
58 | #endif | |
59 | #if HAVE_SYS_SELECT_H | |
60 | #include <sys/select.h> | |
61 | #endif | |
62 | #if HAVE_SIGNAL_H | |
63 | #include <signal.h> | |
64 | #endif | |
65 | #if HAVE_TIME_H | |
66 | #include <time.h> | |
67 | #endif | |
68 | #if HAVE_SYS_TIME_H | |
69 | #include <sys/time.h> | |
70 | #endif | |
71 | #if HAVE_SYS_SOCKET_H | |
72 | #include <sys/socket.h> | |
73 | #endif | |
74 | #if HAVE_NETINET_IN_H | |
75 | #include <netinet/in.h> | |
76 | #endif | |
77 | #if HAVE_ARPA_INET_H | |
78 | #include <arpa/inet.h> | |
79 | #endif | |
80 | #if HAVE_ERRNO_H | |
81 | #include <errno.h> | |
82 | #endif | |
83 | #if HAVE_CTYPE_H | |
84 | #include <ctype.h> | |
85 | #endif | |
86 | #if HAVE_ASSERT_H | |
87 | #include <assert.h> | |
88 | #endif | |
14ff08f1 | 89 | #if HAVE_SYS_STAT_H |
90 | #include <sys/stat.h> | |
91 | #endif | |
eb5f55b3 | 92 | |
93 | #define PROXY_PORT 3128 | |
94 | #define PROXY_ADDR "127.0.0.1" | |
95 | #define MAX_FDS 1024 | |
96 | #define READ_BUF_SZ 4096 | |
97 | #define min(x,y) ((x)<(y)? (x) : (y)) | |
98 | ||
99 | static int proxy_port = PROXY_PORT; | |
100 | static char *proxy_addr = PROXY_ADDR; | |
101 | static char *progname; | |
102 | static int noutstanding = 0; | |
103 | static int done_reading_urls = 0; | |
104 | static int opt_ims = 0; | |
14ff08f1 | 105 | static int opt_checksum = 0; |
106 | static int opt_reopen = 1; | |
107 | static int max_outstanding = 10; | |
eb5f55b3 | 108 | static time_t lifetime = 60; |
109 | static const char *const crlf = "\r\n"; | |
14ff08f1 | 110 | static int trace_fd = -1; |
111 | static int total_bytes_read = 0; | |
eb5f55b3 | 112 | |
113 | #define REPLY_HDR_SZ 8192 | |
114 | ||
115 | struct _r { | |
14ff08f1 | 116 | char url[1024]; |
eb5f55b3 | 117 | int content_length; |
118 | int hdr_length; | |
119 | int hdr_offset; | |
120 | int bytes_read; | |
121 | char reply_hdrs[REPLY_HDR_SZ]; | |
122 | struct _r *next; | |
14ff08f1 | 123 | long sum; |
124 | long validsize; | |
125 | long validsum; | |
eb5f55b3 | 126 | }; |
127 | ||
128 | static struct _r *Requests; | |
129 | ||
130 | char * | |
131 | mkrfc850(t) | |
132 | time_t *t; | |
133 | { | |
134 | static char buf[128]; | |
135 | struct tm *gmt = gmtime(t); | |
136 | buf[0] = '\0'; | |
137 | (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt); | |
138 | return buf; | |
139 | } | |
140 | ||
141 | ||
142 | char * | |
143 | mime_headers_end(const char *mime) | |
144 | { | |
145 | const char *p1, *p2; | |
146 | const char *end = NULL; | |
147 | ||
148 | p1 = strstr(mime, "\n\r\n"); | |
149 | p2 = strstr(mime, "\n\n"); | |
150 | ||
151 | if (p1 && p2) | |
152 | end = p1 < p2 ? p1 : p2; | |
153 | else | |
154 | end = p1 ? p1 : p2; | |
155 | if (end) | |
156 | end += (end == p1 ? 3 : 2); | |
157 | ||
158 | return (char *) end; | |
159 | } | |
160 | ||
161 | void | |
162 | sig_intr(int sig) | |
163 | { | |
14ff08f1 | 164 | fprintf(stderr, "\rWaiting for open connections to finish...\n"); |
eb5f55b3 | 165 | signal(sig, SIG_DFL); |
14ff08f1 | 166 | done_reading_urls = 1; |
eb5f55b3 | 167 | } |
168 | ||
169 | int | |
14ff08f1 | 170 | |
eb5f55b3 | 171 | open_http_socket(void) |
172 | { | |
173 | int s; | |
174 | struct sockaddr_in S; | |
175 | if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { | |
176 | perror("socket"); | |
177 | return -1; | |
178 | } | |
179 | memset(&S, '\0', sizeof(struct sockaddr_in)); | |
180 | S.sin_family = AF_INET; | |
181 | S.sin_port = htons(proxy_port); | |
182 | S.sin_addr.s_addr = inet_addr(proxy_addr); | |
183 | if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) { | |
184 | close(s); | |
185 | perror("connect"); | |
186 | return -1; | |
187 | } | |
188 | return s; | |
189 | } | |
190 | ||
191 | int | |
14ff08f1 | 192 | send_request(int fd, const char *data) |
eb5f55b3 | 193 | { |
14ff08f1 | 194 | char msg[4096],buf[4096]; |
eb5f55b3 | 195 | int len; |
196 | time_t w; | |
197 | struct _r *r; | |
198 | struct _r **R; | |
14ff08f1 | 199 | char *method, *url, *file, *size, *checksum; |
200 | char *tmp = strdup(data); | |
201 | struct stat st; | |
202 | int file_fd = -1; | |
203 | method=strtok(tmp, " "); | |
204 | url=strtok(NULL, " "); | |
205 | file=strtok(NULL, " "); | |
206 | size=strtok(NULL, " "); | |
207 | checksum=strtok(NULL, " "); | |
208 | if (!url) { | |
209 | url=method; | |
210 | method="GET"; | |
211 | } | |
212 | if (file && strcmp(file,"-")==0) | |
213 | file=NULL; | |
214 | if (size && strcmp(size,"-")==0) | |
215 | size=NULL; | |
216 | if (checksum && strcmp(checksum,"-")==0) | |
217 | checksum=NULL; | |
218 | msg[0] = '\0'; | |
219 | sprintf(buf, "%s %s HTTP/1.0\r\n", method, url); | |
220 | strcat(msg,buf); | |
221 | strcat(msg, "Accept: */*\r\n"); | |
222 | strcat(msg, "Proxy-Connection: Keep-Alive\r\n"); | |
eb5f55b3 | 223 | if (opt_ims && (lrand48() & 0x03) == 0) { |
224 | w = time(NULL) - (lrand48() & 0x3FFFF); | |
14ff08f1 | 225 | sprintf(buf, "If-Modified-Since: %s\r\n", mkrfc850(&w)); |
226 | strcat(msg, buf); | |
eb5f55b3 | 227 | } |
14ff08f1 | 228 | if (file) { |
229 | if ( (file_fd = open(file,O_RDONLY)) < 0) { | |
230 | perror("open"); | |
231 | return -1; | |
232 | } | |
233 | if ( fstat(file_fd, &st) ) { | |
234 | perror("fstat"); | |
235 | close(file_fd); | |
236 | return -1; | |
237 | } | |
238 | sprintf(buf, "Content-length: %d\r\n", st.st_size); | |
239 | strcat(msg, buf); | |
240 | } | |
241 | strcat(msg, "\r\n"); | |
242 | len = strlen(msg); | |
243 | if (write(fd, msg, len) < 0) { | |
eb5f55b3 | 244 | close(fd); |
14ff08f1 | 245 | perror("request write"); |
246 | close(file_fd); | |
eb5f55b3 | 247 | return -1; |
248 | } | |
14ff08f1 | 249 | if (file) { |
250 | while((len=read(file_fd, buf, sizeof buf)) > 0) { | |
251 | if (write(fd, buf, len) < 0) { | |
252 | close(fd); | |
253 | perror("body write"); | |
254 | close(file_fd); | |
255 | return -1; | |
256 | } | |
257 | } | |
258 | if (len < 0) { | |
259 | perror("file read"); | |
260 | close(file_fd); | |
261 | return -1; | |
262 | } | |
263 | close(file_fd); | |
264 | } | |
eb5f55b3 | 265 | r = calloc(1, sizeof(struct _r)); |
14ff08f1 | 266 | strcpy(r->url, url); |
267 | if (size) | |
268 | r->validsize = atoi(size); | |
269 | else | |
270 | r->validsize = -1; | |
271 | if (checksum) | |
272 | r->validsum = atoi(checksum); | |
eb5f55b3 | 273 | for (R = &Requests; *R; R = &(*R)->next); |
274 | *R = r; | |
14ff08f1 | 275 | /* fprintf(stderr, "REQUESTED %s\n", url); */ |
eb5f55b3 | 276 | noutstanding++; |
277 | return 0; | |
278 | } | |
279 | ||
280 | static int | |
281 | get_header_int_value(const char *hdr, const char *buf, const char *end) | |
282 | { | |
283 | const char *t; | |
284 | for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) { | |
285 | if (strncasecmp(t, hdr, strlen(hdr)) == 0) { | |
286 | t += strlen(hdr); | |
287 | while (isspace(*t)) | |
288 | t++; | |
289 | return atoi(t); | |
290 | } | |
291 | } | |
14ff08f1 | 292 | return -1; |
eb5f55b3 | 293 | } |
294 | ||
14ff08f1 | 295 | static const char * |
296 | get_header_string_value(const char *hdr, const char *buf, const char *end) | |
297 | { | |
298 | const char *t; | |
299 | static char result[8192]; | |
300 | for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) { | |
301 | if (strncasecmp(t, hdr, strlen(hdr)) == 0) { | |
302 | t += strlen(hdr); | |
303 | while (isspace(*t)) | |
304 | t++; | |
305 | strcpy(result,""); | |
306 | strncat(result,t,strcspn(t, crlf)); | |
307 | return result; | |
308 | } | |
309 | } | |
310 | return NULL; | |
311 | } | |
312 | ||
313 | void | |
314 | request_done(struct _r *r) | |
315 | { | |
316 | #if 0 | |
317 | fprintf(stderr, "DONE: %s, (%d+%d)\n", | |
318 | r->url, | |
319 | r->hdr_length, | |
320 | r->content_length); | |
321 | #endif | |
322 | if (r->content_length != r->bytes_read) | |
323 | fprintf(stderr, "ERROR! Short reply, expected %d bytes got %d\n", | |
324 | r->content_length, r->bytes_read); | |
325 | else if (r->validsize >= 0) { | |
326 | if (r->validsize != r->bytes_read) | |
327 | fprintf(stderr, "WARNING: %s Object size mismatch, expected %d got %d\n", | |
328 | r->url, r->validsize, r->bytes_read); | |
329 | else if (opt_checksum && r->sum != r->validsum) | |
330 | fprintf(stderr, "WARNING: %s Checksum error. Expected %d got %d\n", | |
331 | r->url, r->validsum, r->sum); | |
332 | } | |
333 | } | |
eb5f55b3 | 334 | int |
14ff08f1 | 335 | handle_read(char *inbuf, int len) |
eb5f55b3 | 336 | { |
337 | struct _r *r = Requests; | |
338 | const char *end; | |
14ff08f1 | 339 | const char *url; |
340 | static char buf[READ_BUF_SZ]; | |
341 | int hlen,blen; | |
342 | if (len < 0 ) { | |
eb5f55b3 | 343 | perror("read"); |
344 | Requests = r->next; | |
14ff08f1 | 345 | request_done(r); |
e3fc4f10 | 346 | free(r); |
347 | noutstanding--; | |
14ff08f1 | 348 | if (trace_fd >= 0) |
349 | write(trace_fd,"\n[CLOSED]\n",10); | |
eb5f55b3 | 350 | return -1; |
351 | } | |
14ff08f1 | 352 | total_bytes_read += len; |
353 | xmemcpy(buf,inbuf,len); | |
eb5f55b3 | 354 | if (len == 0) { |
14ff08f1 | 355 | fprintf(stderr, "WARNING: %s, server closed socket after %d+%d bytes\n", r->url, r->hdr_offset, r->bytes_read); |
356 | /* XXX, If no data was received and it isn't the first request on this | |
357 | * connection then the request should be restarted rather than aborted | |
358 | * but this is a simple test program an not a full blown HTTP client. | |
359 | */ | |
360 | request_done(r); | |
eb5f55b3 | 361 | Requests = r->next; |
362 | free(r); | |
363 | noutstanding--; | |
364 | return -1; | |
365 | } | |
14ff08f1 | 366 | if (trace_fd > 0) |
367 | write(trace_fd, buf, len); | |
368 | while (len > 0) { | |
369 | /* Build headers */ | |
370 | if (r->hdr_length == 0) { | |
371 | hlen = min(len, REPLY_HDR_SZ - r->hdr_offset - 1); | |
372 | xmemcpy(r->reply_hdrs + r->hdr_offset, buf, hlen); | |
373 | r->hdr_offset += hlen; | |
374 | r->reply_hdrs[r->hdr_offset] = '\0'; | |
375 | len -= hlen; | |
376 | /* Save any remaining read data */ | |
377 | xmemmove(buf, buf + hlen, len); | |
378 | } | |
379 | /* Process headers */ | |
380 | if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) { | |
381 | #if 0 | |
382 | fprintf(stderr, "FOUND EOH FOR %s\n", r->url); */ | |
383 | #endif | |
384 | r->hdr_length = end - r->reply_hdrs; | |
385 | #if 0 | |
386 | fprintf(stderr, "HDR_LENGTH = %d\n", r->hdr_length); | |
387 | #endif | |
388 | /* "unread" any body contents received */ | |
389 | blen = r->hdr_offset - r->hdr_length; | |
390 | assert(blen >= 0); | |
391 | if (blen > 0) { | |
392 | xmemmove(buf + blen, buf, len); | |
393 | xmemcpy(buf, r->reply_hdrs + r->hdr_length, blen); | |
394 | len += blen; | |
395 | } | |
396 | r->reply_hdrs[r->hdr_length]='\0'; /* Null terminate headers */ | |
397 | /* Parse headers */ | |
398 | r->content_length = get_header_int_value("content-length:", r->reply_hdrs, end); | |
399 | /* fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length); */ | |
400 | url = get_header_string_value("X-Request-URI:", r->reply_hdrs, end); | |
401 | if (url != NULL && strcmp(r->url, url) != 0) | |
402 | fprintf(stderr, "WARNING: %s got reply %s\n", r->url, url); | |
403 | #if XREQUESTURI || 0 | |
404 | fprintf(stderr, "LOCATION = %s\n", get_header_string_value("X-Request-URI:", r->reply_hdrs, end)); | |
405 | #endif | |
406 | } | |
407 | if ( !(len==0 || r->hdr_length > 0) ) { | |
408 | fprintf(stderr, "ERROR!!!\n"); | |
409 | assert((len==0 || r->hdr_length > 0)); | |
eb5f55b3 | 410 | } |
14ff08f1 | 411 | /* Process body */ |
412 | if (r->hdr_length != 0) { | |
413 | int i; | |
414 | int bytes_left, bytes_used; | |
415 | if (r->content_length >= 0) { | |
416 | bytes_left = r->content_length - r->bytes_read; | |
417 | assert(bytes_left >= 0); | |
418 | bytes_used = len < bytes_left ? len : bytes_left; | |
419 | } else { | |
420 | bytes_left = len + 1; /* Unknown end... */ | |
421 | bytes_used = len; | |
422 | } | |
423 | if (opt_checksum) { | |
424 | for(i=0; i<bytes_used; i++) | |
425 | r->sum += (int)buf[i] & 0xFF; | |
426 | } | |
427 | r->bytes_read += bytes_used; | |
428 | len -= bytes_used; | |
429 | if (bytes_left == bytes_used) { | |
430 | request_done(r); | |
431 | Requests = r->next; | |
432 | free(r); | |
433 | noutstanding--; | |
434 | r = Requests; | |
5a91f458 | 435 | } else if (r->content_length > -1) { |
14ff08f1 | 436 | assert(r->bytes_read < r->content_length); |
437 | } | |
dbfed404 | 438 | xmemmove(buf, buf + bytes_used, len); |
eb5f55b3 | 439 | } |
440 | } | |
441 | return 0; | |
442 | } | |
443 | ||
444 | int | |
445 | read_reply(int fd) | |
446 | { | |
447 | static char buf[READ_BUF_SZ]; | |
448 | int len; | |
449 | int x; | |
450 | len = read(fd, buf, READ_BUF_SZ); | |
451 | x = handle_read(buf, len); | |
14ff08f1 | 452 | if (x < 0) { |
453 | perror("read reply"); | |
eb5f55b3 | 454 | close(fd); |
14ff08f1 | 455 | } |
eb5f55b3 | 456 | return x; |
457 | } | |
458 | ||
459 | void | |
460 | main_loop(void) | |
461 | { | |
462 | static int pconn_fd = -1; | |
463 | static char buf[8192]; | |
464 | struct timeval to; | |
14ff08f1 | 465 | struct timeval now,last,start; |
eb5f55b3 | 466 | fd_set R; |
467 | struct _r *r; | |
468 | struct _r *nextr; | |
469 | int x; | |
e3fc4f10 | 470 | int timeouts; |
14ff08f1 | 471 | int nrequests = 0, rrequests = 0, reqpersec = 0; |
472 | ||
473 | gettimeofday(&start, NULL); | |
474 | last = start; | |
475 | ||
476 | pconn_fd = open_http_socket(); | |
477 | if (pconn_fd < 0) { | |
478 | perror("socket"); | |
479 | exit(1); | |
480 | } | |
eb5f55b3 | 481 | while (!done_reading_urls || noutstanding) { |
14ff08f1 | 482 | if (!opt_reopen && pconn_fd < 0) { |
483 | fprintf(stderr,"TERMINATED: Connection closed\n"); | |
484 | break; | |
e3fc4f10 | 485 | } |
14ff08f1 | 486 | if (pconn_fd<0) { |
eb5f55b3 | 487 | pconn_fd = open_http_socket(); |
488 | if (pconn_fd < 0) { | |
489 | perror("socket"); | |
490 | exit(1); | |
491 | } | |
492 | nextr = Requests; | |
493 | Requests = NULL; | |
14ff08f1 | 494 | noutstanding=0; |
eb5f55b3 | 495 | while ((r = nextr) != NULL) { |
496 | nextr = r->next; | |
14ff08f1 | 497 | if (send_request(pconn_fd, r->url) != 0) { |
498 | close(pconn_fd); | |
499 | pconn_fd=-1; | |
500 | nextr = r; | |
501 | for (r = Requests; r!=NULL && r->next; r=r->next); | |
502 | if (r != NULL) | |
503 | r->next = nextr; | |
504 | else | |
505 | Requests = nextr; | |
506 | break; | |
507 | } | |
eb5f55b3 | 508 | free(r); |
eb5f55b3 | 509 | } |
e3fc4f10 | 510 | timeouts = 0; |
14ff08f1 | 511 | if (pconn_fd <0) |
512 | continue; | |
eb5f55b3 | 513 | } |
14ff08f1 | 514 | if (timeouts == 200) { |
515 | close(pconn_fd); | |
516 | pconn_fd = -1; | |
517 | r = Requests; | |
518 | Requests = Requests->next; | |
519 | fprintf(stderr, "ABORT %s\n", Requests->url); | |
520 | free(r); | |
521 | noutstanding--; | |
522 | } | |
523 | if (pconn_fd>=0 && noutstanding < max_outstanding && !done_reading_urls) { | |
eb5f55b3 | 524 | char *t; |
525 | if (fgets(buf, 8191, stdin) == NULL) { | |
14ff08f1 | 526 | fprintf(stderr, "Done Reading URLS\n"); |
eb5f55b3 | 527 | done_reading_urls = 1; |
14ff08f1 | 528 | continue; |
eb5f55b3 | 529 | } |
14ff08f1 | 530 | rrequests++; |
eb5f55b3 | 531 | if ((t = strchr(buf, '\n'))) |
532 | *t = '\0'; | |
14ff08f1 | 533 | if (send_request(pconn_fd, buf) != 0) { |
534 | close(pconn_fd); | |
535 | pconn_fd=-1; | |
536 | continue; | |
537 | } | |
538 | nrequests++; | |
539 | reqpersec++; | |
e3fc4f10 | 540 | timeouts = 0; |
eb5f55b3 | 541 | } |
542 | FD_ZERO(&R); | |
543 | to.tv_sec = 1; | |
544 | to.tv_usec = 0; | |
545 | FD_SET(pconn_fd, &R); | |
546 | x = select(pconn_fd + 1, &R, NULL, NULL, &to); | |
547 | if (x < 0) { | |
548 | if (errno != EINTR) | |
549 | perror("select"); | |
550 | continue; | |
551 | } else if (x == 0) { | |
552 | assert(Requests != NULL); | |
e3fc4f10 | 553 | fprintf(stderr, "TIMEOUT %s; %d, %d\n", Requests->url, |
554 | ++timeouts, noutstanding); | |
eb5f55b3 | 555 | continue; |
556 | } | |
557 | if (FD_ISSET(pconn_fd, &R)) { | |
e3fc4f10 | 558 | timeouts = 0; |
eb5f55b3 | 559 | if (read_reply(pconn_fd) != 0) |
560 | pconn_fd = -1; | |
561 | } | |
14ff08f1 | 562 | gettimeofday(&now, NULL); |
563 | if (now.tv_sec > last.tv_sec) { | |
564 | int dt; | |
565 | int nreq; | |
566 | last = now; | |
567 | dt = (int) (now.tv_sec - start.tv_sec); | |
568 | nreq=0; | |
569 | for (r=Requests; r ; r=r->next) nreq++; | |
570 | printf("T+ %6d: %9d req (%+4d), %4d pend, %3d/sec avg, %dmb, %dkb/sec avg\n", | |
571 | dt, | |
572 | nrequests, | |
573 | reqpersec, | |
574 | nreq, | |
575 | (int) (nrequests / dt), | |
576 | (int)total_bytes_read / 1024 / 1024, | |
577 | (int)total_bytes_read / 1024 / dt); | |
578 | reqpersec = 0; | |
579 | } | |
eb5f55b3 | 580 | } |
581 | } | |
582 | ||
583 | void | |
584 | usage(void) | |
585 | { | |
14ff08f1 | 586 | fprintf(stderr, "usage: %s: -p port -h host -n max -t tracefile -i -c -l lifetime\n", progname); |
eb5f55b3 | 587 | } |
588 | ||
589 | int | |
590 | main(argc, argv) | |
591 | int argc; | |
592 | char *argv[]; | |
593 | { | |
594 | int c; | |
595 | setbuf(stdout, NULL); | |
596 | setbuf(stderr, NULL); | |
597 | progname = strdup(argv[0]); | |
14ff08f1 | 598 | while ((c = getopt(argc, argv, "p:h:n:t:icl:r")) != -1) { |
eb5f55b3 | 599 | switch (c) { |
600 | case 'p': | |
601 | proxy_port = atoi(optarg); | |
602 | break; | |
603 | case 'h': | |
604 | proxy_addr = strdup(optarg); | |
605 | break; | |
606 | case 'n': | |
14ff08f1 | 607 | max_outstanding = atoi(optarg); |
eb5f55b3 | 608 | break; |
609 | case 'i': | |
610 | opt_ims = 1; | |
611 | break; | |
14ff08f1 | 612 | case 'c': |
613 | opt_checksum = 1; | |
614 | break; | |
eb5f55b3 | 615 | case 'l': |
616 | lifetime = (time_t) atoi(optarg); | |
617 | break; | |
14ff08f1 | 618 | case 't': |
619 | trace_fd = open(optarg,O_WRONLY|O_CREAT|O_TRUNC,0666); | |
620 | break; | |
621 | case 'r': | |
622 | opt_reopen = !opt_reopen; | |
623 | break; | |
eb5f55b3 | 624 | default: |
625 | usage(); | |
626 | return 1; | |
627 | } | |
628 | } | |
629 | signal(SIGINT, sig_intr); | |
5616e319 | 630 | signal(SIGPIPE, SIG_IGN); |
eb5f55b3 | 631 | main_loop(); |
632 | return 0; | |
633 | } |