tcp-banger2.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:13k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. #include "config.h"
  2. /* $Id: tcp-banger2.c,v 1.22.2.2 1999/02/12 21:40:20 wessels Exp $ */
  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. /* Cannot increase FD_SETSIZE on Linux */
  11. #if defined(_SQUID_LINUX_)
  12. #undef CHANGE_FD_SETSIZE
  13. #define CHANGE_FD_SETSIZE 0
  14. #endif
  15. /* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
  16.  * to return EINVAL. */
  17. /* Marian Durkovic <marian@svf.stuba.sk> */
  18. /* Peter Wemm <peter@spinner.DIALix.COM> */
  19. #if defined(_SQUID_FREEBSD_)
  20. #include <osreldate.h>
  21. #if __FreeBSD_version < 220000
  22. #undef CHANGE_FD_SETSIZE
  23. #define CHANGE_FD_SETSIZE 0
  24. #endif
  25. #endif
  26. /* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
  27. #if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
  28. #define FD_SETSIZE SQUID_MAXFD
  29. #endif
  30. #if HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #if HAVE_STDLIB_H
  34. #include <stdlib.h>
  35. #endif
  36. #if HAVE_STDIO_H
  37. #include <stdio.h>
  38. #endif
  39. #if HAVE_FCNTL_H
  40. #include <fcntl.h>
  41. #endif
  42. #ifdef HAVE_STRING_H
  43. #include <string.h>
  44. #endif
  45. #ifdef HAVE_STRINGS_H
  46. #include <strings.h>
  47. #endif
  48. #if HAVE_SYS_TYPES_H
  49. #include <sys/types.h>
  50. #endif
  51. #if HAVE_SYS_SELECT_H
  52. #include <sys/select.h>
  53. #endif
  54. #if HAVE_SIGNAL_H
  55. #include <signal.h>
  56. #endif
  57. #if HAVE_TIME_H
  58. #include <time.h>
  59. #endif
  60. #if HAVE_SYS_TIME_H
  61. #include <sys/time.h>
  62. #endif
  63. #if HAVE_SYS_SOCKET_H
  64. #include <sys/socket.h>
  65. #endif
  66. #if HAVE_NETINET_IN_H
  67. #include <netinet/in.h>
  68. #endif
  69. #if HAVE_ARPA_INET_H
  70. #include <arpa/inet.h>
  71. #endif
  72. #if HAVE_ERRNO_H
  73. #include <errno.h>
  74. #endif
  75. #if HAVE_SYS_STAT_H
  76. #include <sys/stat.h>
  77. #endif
  78. #if HAVE_ASSERT_H
  79. #include <assert.h>
  80. #endif
  81. #if HAVE_CTYPE_H
  82. #include <ctype.h>
  83. #endif
  84. #define PROXY_PORT 3128
  85. #define PROXY_ADDR "127.0.0.1"
  86. #define READ_BUF_SZ 4096
  87. static int proxy_port = PROXY_PORT;
  88. static char *proxy_addr = PROXY_ADDR;
  89. static char *progname;
  90. static int reqpersec;
  91. static int nrequests;
  92. static int opt_ims = 0;
  93. static int opt_range = 0;
  94. static int opt_accel = 0;
  95. static int max_connections = 64;
  96. static time_t lifetime = 60;
  97. static time_t process_lifetime = 86400;
  98. static struct timeval now;
  99. static long total_bytes_written = 0;
  100. static long total_bytes_read = 0;
  101. static int opt_checksum = 0;
  102. FILE *trace_file = NULL;
  103. typedef void (CB) (int, void *);
  104. struct _f {
  105.     CB *cb;
  106.     CB *ccb;
  107.     void *data;
  108.     time_t start;
  109. };
  110. struct _request {
  111.     int fd;
  112.     char *url;
  113.     char method[16];
  114.     char requestbodyfile[256];
  115.     char buf[READ_BUF_SZ * 2 + 1];
  116.     int headfound;
  117.     int validsize;
  118.     int bodysize;
  119.     int content_length;
  120.     int status;
  121.     long validsum;
  122.     long sum;
  123. };
  124. struct _f FD[SQUID_MAXFD];
  125. int nfds = 0;
  126. int maxfd = 0;
  127. static void
  128. free_request(struct _request *r)
  129. {
  130.     if (r->url)
  131. free(r->url);
  132.     free(r);
  133. }
  134. char *
  135. mkrfc850(t)
  136.      time_t *t;
  137. {
  138.     static char buf[128];
  139.     struct tm *gmt = gmtime(t);
  140.     buf[0] = '';
  141.     (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt);
  142.     return buf;
  143. }
  144. void
  145. fd_close(int fd)
  146. {
  147.     close(fd);
  148.     if (FD[fd].ccb)
  149. FD[fd].ccb(fd, FD[fd].data);
  150.     FD[fd].ccb = NULL;
  151.     FD[fd].cb = NULL;
  152.     FD[fd].data = NULL;
  153.     nfds--;
  154.     if (fd == maxfd) {
  155. while (fd > 0 && FD[fd].cb == NULL)
  156.     fd--;
  157. maxfd = fd;
  158.     }
  159. }
  160. void
  161. fd_open(int fd, CB * cb, void *data, CB * ccb)
  162. {
  163.     assert(fd < SQUID_MAXFD);
  164.     FD[fd].cb = cb;
  165.     FD[fd].ccb = ccb;
  166.     FD[fd].data = data;
  167.     FD[fd].start = now.tv_sec;
  168.     if (fd > maxfd)
  169. maxfd = fd;
  170.     nfds++;
  171. }
  172. void
  173. sig_intr(int sig)
  174. {
  175.     fd_close(0);
  176.     nfds++;
  177.     printf("rWaiting for open connections to finish...n");
  178.     signal(sig, SIG_DFL);
  179. }
  180. void
  181. read_reply(int fd, void *data)
  182. {
  183.     struct _request *r = data;
  184.     static unsigned char buf[READ_BUF_SZ];
  185.     int len;
  186.     int used = 0;
  187.     if ((len = read(fd, buf, READ_BUF_SZ)) <= 0) {
  188. fd_close(fd);
  189. reqpersec++;
  190. nrequests++;
  191. return;
  192.     }
  193.     total_bytes_read += len;
  194.     if (r->headfound < 2) {
  195. char *p, *header = NULL;
  196. int oldlen = strlen(r->buf);
  197. int newlen = oldlen + len;
  198. assert(oldlen <= READ_BUF_SZ);
  199. memcpy(r->buf + oldlen, buf, len);
  200. r->buf[newlen + 1] = '';
  201. for (p = r->buf; r->headfound < 2 && used < newlen; p++, used++) {
  202.     switch (*p) {
  203.     case 'n':
  204. r->headfound++;
  205. if (!header)
  206.     break;
  207. /* Decode header */
  208. if (strncmp(header, "HTTP", 4) == 0)
  209.     r->status = atoi(header + 8);
  210. else if (strncasecmp(header, "Content-Length:", 15) == 0)
  211.     r->content_length = atoi(header + 15);
  212. else if (strncasecmp(header, "X-Request-URI:", 14) == 0) {
  213.     /* Check URI */
  214.     if (strncmp(r->url, header + 15, strcspn(header + 15, "rn"))) {
  215. char url[8192];
  216. strncpy(url, header + 15, strcspn(header + 15, "rn"));
  217. url[strcspn(header + 15, "rn")] = 'n';
  218. fprintf(stderr, "ERROR: Sent %s received %sn",
  219.     r->url, url);
  220.     }
  221. }
  222. header = NULL;
  223. break;
  224.     case 'r':
  225. break;
  226.     default:
  227. r->headfound = 0;
  228. if (!header)
  229.     header = p;
  230. break;
  231.     }
  232. }
  233. if (header) {
  234.     memmove(r->buf, header, newlen - (header - r->buf) + 1);
  235. }
  236. assert(used >= oldlen);
  237. used -= oldlen;
  238.     }
  239.     r->bodysize += len - used;
  240.     if (opt_checksum) {
  241. for (; used < len; used++) {
  242.     r->sum += buf[used];
  243. }
  244.     }
  245. }
  246. void
  247. reply_done(int fd, void *data)
  248. {
  249.     struct _request *r = data;
  250.     if (opt_range); /* skip size checks for now */
  251.     else if (r->bodysize != r->content_length && r->content_length >= 0)
  252. fprintf(stderr, "ERROR: %s got %d of %d bytesn",
  253.     r->url, r->bodysize, r->content_length);
  254.     else if (r->validsize >= 0) {
  255. if (r->validsize != r->bodysize)
  256.     fprintf(stderr, "WARNING: %s size mismatch wanted %d bytes got %dn",
  257. r->url, r->validsize, r->bodysize);
  258. else if (opt_checksum && r->validsum != r->sum)
  259.     fprintf(stderr, "WARNING: %s invalid checksum wanted 0x%lx got 0x%lxn",
  260. r->url, r->validsum, r->sum);
  261.     }
  262.     if (trace_file) {
  263. if (opt_checksum)
  264.     fprintf(trace_file, "%s %s %d %s %d 0x%lxn",
  265. r->method, r->url, r->status, r->requestbodyfile, r->bodysize, r->sum);
  266. else
  267.     fprintf(trace_file, "%s %s %d %s %dn",
  268. r->method, r->url, r->status, r->requestbodyfile, r->bodysize);
  269.     }
  270.     free_request(r);
  271. }
  272. struct _request *
  273. request(char *urlin)
  274. {
  275.     int s = -1, f = -1;
  276.     char buf[4096];
  277.     char msg[8192];
  278.     char *method, *url, *file, *size, *checksum;
  279.     char *host;
  280.     char urlbuf[8192];
  281.     int len, len2;
  282.     time_t w;
  283.     struct stat st;
  284.     struct sockaddr_in S;
  285.     struct _request *r;
  286.     if (*urlin == '')
  287. return NULL;
  288.     if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  289. perror("socket");
  290. return NULL;
  291.     }
  292.     memset(&S, '', sizeof(struct sockaddr_in));
  293.     S.sin_family = AF_INET;
  294.     S.sin_port = htons(proxy_port);
  295.     S.sin_addr.s_addr = inet_addr(proxy_addr);
  296.     if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) {
  297. close(s);
  298. perror("connect");
  299. return NULL;
  300.     }
  301.     strcpy(urlbuf, urlin);
  302.     method = strtok(urlbuf, " ");
  303.     url = strtok(NULL, " ");
  304.     file = strtok(NULL, " ");
  305.     size = strtok(NULL, " ");
  306.     checksum = strtok(NULL, " ");
  307.     if (!url) {
  308. url = method;
  309. method = "GET";
  310.     }
  311.     if (!file)
  312. file = "-";
  313.     if (!size)
  314. size = "-";
  315.     if (!checksum)
  316. checksum = "-";
  317.     r = calloc(1, sizeof *r);
  318.     assert(r != NULL);
  319.     r->url = strdup(url);
  320.     assert(r->url);
  321.     strcpy(r->method, method);
  322.     strcpy(r->requestbodyfile, file);
  323.     r->fd = s;
  324.     if (size && strcmp(size, "-") != 0)
  325. r->validsize = atoi(size);
  326.     else
  327. r->validsize = -1; /* Unknown */
  328.     if (checksum && strcmp(checksum, "-") != 0)
  329. r->validsum = strtoul(checksum, NULL, 0);
  330.     r->content_length = -1; /* Unknown */
  331.     if (opt_accel) {
  332. host = strchr(url, '/') + 2;
  333. url = strchr(host, '/');
  334.     } else {
  335. host = NULL;
  336.     }
  337.     sprintf(msg, "%s %s HTTP/1.0rn", method, url);
  338.     if (host) {
  339. url[0] = '';
  340. sprintf(buf, "Host: %srn", host);
  341. strcat(msg, buf);
  342. url[0] = '/';
  343.     }
  344.     strcat(msg, "Accept: */*rn");
  345.     if (opt_ims && (lrand48() & 0x03) == 0) {
  346. w = time(NULL) - (lrand48() & 0x3FFFF);
  347. sprintf(buf, "If-Modified-Since: %srn", mkrfc850(&w));
  348. strcat(msg, buf);
  349.     }
  350.     if (file && strcmp(file, "-") != 0) {
  351. f = open(file, O_RDONLY);
  352. if (f < 0) {
  353.     perror("open file");
  354.     exit(1);
  355. }
  356. fstat(f, &st);
  357. sprintf(buf, "Content-Length: %drn", (int) st.st_size);
  358. strcat(msg, buf);
  359.     }
  360.     if (opt_range && (lrand48() & 0x03) == 0) {
  361. int len;
  362. int count = 0;
  363. strcat(msg, "Range: bytes=");
  364. while (((len = (int) lrand48()) & 0x03) == 0 || !count) {
  365.     const int offset = (int) lrand48();
  366.     if (count)
  367. strcat(msg, ",");
  368.     switch (lrand48() & 0x03) {
  369.     case 0:
  370. sprintf(buf, "-%d", len);
  371. break;
  372.     case 1:
  373. sprintf(buf, "%d-", offset);
  374. break;
  375.     default:
  376. sprintf(buf, "%d-%d", offset, offset + len);
  377. break;
  378.     }
  379.     strcat(msg, buf);
  380.     count++;
  381. }
  382. strcat(msg, "rn");
  383.     }
  384.     strcat(msg, "rn");
  385.     len = strlen(msg);
  386.     if ((len2 = write(s, msg, len)) != len) {
  387. close(s);
  388. perror("write request");
  389. free_request(r);
  390. return NULL;
  391.     } else
  392. total_bytes_written += len2;
  393.     if (f >= 0) {
  394. while ((len = read(f, buf, sizeof(buf))) > 0) {
  395.     len2 = write(s, buf, len);
  396.     if (len2 < 0) {
  397. perror("write body");
  398. close(s);
  399. free_request(r);
  400.     }
  401. }
  402. if (len < 0) {
  403.     perror("read body");
  404.     exit(1);
  405. }
  406.     }
  407. /*
  408.  * if (fcntl(s, F_SETFL, O_NDELAY) < 0)
  409.  * perror("fcntl O_NDELAY");
  410.  */
  411.     return r;
  412. }
  413. void
  414. read_url(int fd, void *junk)
  415. {
  416.     struct _request *r;
  417.     static char buf[8192];
  418.     char *t;
  419.     buf[0] = '';
  420.     if (fgets(buf, 8191, stdin) == NULL) {
  421. printf("Done Reading URLSn");
  422. fd_close(0);
  423. nfds++;
  424. return;
  425.     }
  426.     if (buf[0] == '')
  427. return;
  428.     if ((t = strchr(buf, 'n')))
  429. *t = '';
  430.     r = request(buf);
  431.     if (!r) {
  432. max_connections = nfds - 1;
  433. printf("NOTE: max_connections set at %dn", max_connections);
  434.     } else {
  435. fd_open(r->fd, read_reply, r, reply_done);
  436.     }
  437. }
  438. void
  439. usage(void)
  440. {
  441.     fprintf(stderr, "usage: %s: -p port -h host -n maxn", progname);
  442.     fprintf(stderr, " -t <tracefile>  Save request tracen");
  443.     fprintf(stderr, " -c              Check checksum agains tracen");
  444.     fprintf(stderr, " -i              Send random If-Modified-Since timesn");
  445.     fprintf(stderr, " -l <seconds>    Connection lifetime timeout (default 60)n");
  446.     fprintf(stderr, " -a              Accelerator moden");
  447. }
  448. int
  449. main(argc, argv)
  450.      int argc;
  451.      char *argv[];
  452. {
  453.     int i;
  454.     int c;
  455.     int dt;
  456.     int j;
  457.     fd_set R, R2;
  458.     struct timeval start;
  459.     struct timeval last;
  460.     struct timeval to;
  461.     setbuf(stdout, NULL);
  462.     setbuf(stderr, NULL);
  463.     progname = strdup(argv[0]);
  464.     gettimeofday(&now, NULL);
  465.     start = last = now;
  466.     while ((c = getopt(argc, argv, "ap:h:n:icrl:L:t:")) != -1) {
  467. switch (c) {
  468. case 'a':
  469.     opt_accel = 1;
  470.     break;
  471. case 'p':
  472.     proxy_port = atoi(optarg);
  473.     break;
  474. case 'h':
  475.     proxy_addr = strdup(optarg);
  476.     break;
  477. case 'n':
  478.     max_connections = atoi(optarg);
  479.     break;
  480. case 'i':
  481.     opt_ims = 1;
  482.     break;
  483. case 'l':
  484.     lifetime = (time_t) atoi(optarg);
  485.     break;
  486. case 'L':
  487.     process_lifetime = (time_t) atoi(optarg);
  488.     break;
  489. case 'c':
  490.     opt_checksum = 1;
  491.     break;
  492. case 't':
  493.     trace_file = fopen(optarg, "a");
  494.     assert(trace_file);
  495.     setbuf(trace_file, NULL);
  496.     break;
  497. case 'r':
  498.     opt_range = 1;
  499.     break;
  500. default:
  501.     usage();
  502.     return 1;
  503. }
  504.     }
  505.     fd_open(0, read_url, NULL, NULL);
  506.     nfds--;
  507.     signal(SIGINT, sig_intr);
  508.     signal(SIGPIPE, SIG_IGN);
  509.     FD_ZERO(&R2);
  510.     while (nfds || FD[0].cb) {
  511. FD_ZERO(&R);
  512. to.tv_sec = 0;
  513. to.tv_usec = 100000;
  514. if (nfds < max_connections && FD[0].cb)
  515.     FD_SET(0, &R);
  516. for (i = 1; i <= maxfd; i++) {
  517.     if (FD[i].cb == NULL)
  518. continue;
  519.     if (now.tv_sec - FD[i].start > lifetime) {
  520. fprintf(stderr, "WARNING: fd %d lifetime timeoutn", i);
  521. fd_close(i);
  522. continue;
  523.     }
  524.     FD_SET(i, &R);
  525. }
  526. if (select(maxfd + 1, &R, NULL, NULL, &to) < 0) {
  527.     fprintf(stderr, "maxfd=%dn", maxfd);
  528.     if (errno != EINTR)
  529. perror("select");
  530.     continue;
  531. }
  532. gettimeofday(&now, NULL);
  533. for (i = 0; i <= maxfd; i++) {
  534.     if (!FD_ISSET(i, &R))
  535. continue;
  536.     FD[i].cb(i, FD[i].data);
  537.     if (nfds < max_connections && FD[0].cb) {
  538. j = 0;
  539. FD_SET(0, &R2);
  540. to.tv_sec = 0;
  541. to.tv_usec = 0;
  542. if (select(1, &R2, NULL, NULL, &to) == 1)
  543.     FD[0].cb(0, FD[0].data);
  544.     }
  545. }
  546. if (now.tv_sec > last.tv_sec) {
  547.     last = now;
  548.     dt = (int) (now.tv_sec - start.tv_sec);
  549.     printf("T+ %6d: %9d req (%+4d), %4d conn, %3d/sec avg, %dmb, %dkb/sec avgn",
  550. dt,
  551. nrequests,
  552. reqpersec,
  553. nfds,
  554. (int) (nrequests / dt),
  555. (int) total_bytes_read / 1024 / 1024,
  556. (int) total_bytes_read / 1024 / dt);
  557.     reqpersec = 0;
  558.     /*
  559.      * if (dt > process_lifetime)
  560.      *     exit(0);
  561.      */
  562. }
  563.     }
  564.     printf("Exiting normallyn");
  565.     return 0;
  566. }