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

代理服务器

开发平台:

Unix_Linux

  1. #include "config.h"
  2. /*
  3.  * On some systems, FD_SETSIZE is set to something lower than the
  4.  * actual number of files which can be opened.  IRIX is one case,
  5.  * NetBSD is another.  So here we increase FD_SETSIZE to our
  6.  * configure-discovered maximum *before* any system includes.
  7.  */
  8. #define CHANGE_FD_SETSIZE 1
  9. /* Cannot increase FD_SETSIZE on Linux */
  10. #if defined(_SQUID_LINUX_)
  11. #undef CHANGE_FD_SETSIZE
  12. #define CHANGE_FD_SETSIZE 0
  13. #endif
  14. /* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
  15.  * to return EINVAL. */
  16. /* Marian Durkovic <marian@svf.stuba.sk> */
  17. /* Peter Wemm <peter@spinner.DIALix.COM> */
  18. #if defined(_SQUID_FREEBSD_)
  19. #include <osreldate.h>
  20. #if __FreeBSD_version < 220000
  21. #undef CHANGE_FD_SETSIZE
  22. #define CHANGE_FD_SETSIZE 0
  23. #endif
  24. #endif
  25. /* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
  26. #if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
  27. #define FD_SETSIZE SQUID_MAXFD
  28. #endif
  29. #if HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #if HAVE_STDLIB_H
  33. #include <stdlib.h>
  34. #endif
  35. #if HAVE_STDIO_H
  36. #include <stdio.h>
  37. #endif
  38. #if HAVE_FCNTL_H
  39. #include <fcntl.h>
  40. #endif
  41. #ifdef HAVE_STRING_H
  42. #include <string.h>
  43. #endif
  44. #ifdef HAVE_STRINGS_H
  45. #include <strings.h>
  46. #endif
  47. #if HAVE_SYS_TYPES_H
  48. #include <sys/types.h>
  49. #endif
  50. #if HAVE_SYS_SELECT_H
  51. #include <sys/select.h>
  52. #endif
  53. #if HAVE_SIGNAL_H
  54. #include <signal.h>
  55. #endif
  56. #if HAVE_TIME_H
  57. #include <time.h>
  58. #endif
  59. #if HAVE_SYS_TIME_H
  60. #include <sys/time.h>
  61. #endif
  62. #if HAVE_SYS_SOCKET_H
  63. #include <sys/socket.h>
  64. #endif
  65. #if HAVE_NETINET_IN_H
  66. #include <netinet/in.h>
  67. #endif
  68. #if HAVE_ARPA_INET_H
  69. #include <arpa/inet.h>
  70. #endif
  71. #if HAVE_ERRNO_H
  72. #include <errno.h>
  73. #endif
  74. #if HAVE_SYS_STAT_H
  75. #include <sys/stat.h>
  76. #endif
  77. #if HAVE_ASSERT_H
  78. #include <assert.h>
  79. #endif
  80. #include <netdb.h>
  81. #include <sys/wait.h>
  82. #define READ_BUF_SZ 4096
  83. #define URL_BUF_SZ 4096
  84. struct _thing {
  85.     int rfd;
  86.     int wfd;
  87.     int state;
  88.     pid_t pid;
  89.     char url[URL_BUF_SZ];
  90.     struct _thing *next;
  91. };
  92. typedef struct _thing thing;
  93. static thing *things = NULL;
  94. static fd_set R1;
  95. static int maxfd = 0;
  96. static struct timeval now;
  97. #if DEBUG
  98. static int debug = 1;
  99. #else
  100. static int debug = 0;
  101. #endif
  102. int
  103. tvSubMsec(struct timeval t1, struct timeval t2)
  104. {
  105.     return (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000;
  106. }
  107. static int
  108. get_url(const char *url)
  109. {
  110.     char host[URL_BUF_SZ];
  111.     char path[URL_BUF_SZ];
  112.     char request[URL_BUF_SZ];
  113.     char reply[READ_BUF_SZ];
  114.     char *t;
  115.     int x;
  116.     int s;
  117.     int nr = 0;
  118.     struct hostent *h;
  119.     struct sockaddr_in S;
  120.     unsigned short port = 80;
  121.     assert(!strncmp(url, "http://", 7));
  122.     strncpy(host, url + 7, URL_BUF_SZ);
  123.     if ((t = strchr(host, '/')))
  124. *t = '';
  125.     if ((t = strchr(host, ':'))) {
  126. *t = '';
  127. port = (unsigned short) atoi(t + 1);
  128.     }
  129. #if 0
  130.     if ((int) port != 80)
  131. return 0;
  132. #endif
  133.     t = strchr(url + 7, '/');
  134.     strncpy(path, (t ? t : "/"), URL_BUF_SZ);
  135.     memset(&S, '', sizeof(S));
  136.     h = gethostbyname(host);
  137.     if (!h)
  138. return 0;
  139.     memcpy(&S.sin_addr.s_addr, h->h_addr_list[0], sizeof(S.sin_addr.s_addr));
  140.     S.sin_port = htons(port);
  141.     S.sin_family = AF_INET;
  142.     if (debug)
  143. fprintf(stderr, "%s (%s) %d %sn", host, inet_ntoa(S.sin_addr), (int) port, path);
  144.     s = socket(PF_INET, SOCK_STREAM, 0);
  145.     if (s < 0) {
  146. perror("socket");
  147. return -errno;
  148.     }
  149.     x = connect(s, (struct sockaddr *) &S, sizeof(S));
  150.     if (x < 0) {
  151. perror(host);
  152. return -errno;
  153.     }
  154.     snprintf(request, URL_BUF_SZ,
  155. "GET %s HTTP/1.1rn"
  156. "Accept: */*rn"
  157. "Host: %srn"
  158. "Connection: closern"
  159. "rn",
  160. path,
  161. host);
  162.     x = write(s, request, strlen(request));
  163.     if (x < 0) {
  164. perror("write");
  165. return -errno;
  166.     }
  167.     do {
  168. x = read(s, reply, READ_BUF_SZ);
  169. if (x > 0)
  170.     nr += x;
  171.     } while (x > 0);
  172.     close(s);
  173.     return nr;
  174. }
  175. static void
  176. child_main_loop(void)
  177. {
  178.     char buf[URL_BUF_SZ];
  179.     char *t;
  180.     int n;
  181.     struct timeval t1;
  182.     struct timeval t2;
  183.     if (debug)
  184. fprintf(stderr, "Child PID %d entering child_main_loopn", (int) getpid());
  185.     setbuf(stdin, NULL);
  186.     setbuf(stdout, NULL);
  187.     setbuf(stderr, NULL);
  188.     while (fgets(buf, URL_BUF_SZ, stdin)) {
  189. t = strchr(buf, 'n');
  190. if (t == NULL)
  191.     continue;
  192. *t = '';
  193. if (strncmp(buf, "http://", 7))
  194.     continue;
  195. gettimeofday(&t1, NULL);
  196. n = get_url(buf);
  197. gettimeofday(&t2, NULL);
  198. printf("%d %dn", n, tvSubMsec(t1, t2));
  199.     }
  200. }
  201. static thing *
  202. create_a_thing(char *argv[])
  203. {
  204.     int p2c[2];
  205.     int c2p[2];
  206.     int prfd, pwfd, crfd, cwfd;
  207.     pid_t pid;
  208.     thing *t;
  209.     if (pipe(p2c) < 0)
  210. abort();
  211.     if (pipe(c2p) < 0)
  212. abort();
  213.     prfd = p2c[0];
  214.     cwfd = p2c[1];
  215.     crfd = c2p[0];
  216.     pwfd = c2p[1];
  217.     if ((pid = fork()) < 0)
  218. abort();
  219.     if (pid > 0) { /* parent */
  220. /* close shared socket with child */
  221. close(crfd);
  222. close(cwfd);
  223. t = calloc(1, sizeof(*t));
  224. t->wfd = pwfd;
  225. t->rfd = prfd;
  226. if (pwfd > maxfd)
  227.     maxfd = pwfd;
  228. if (prfd > maxfd)
  229.     maxfd = prfd;
  230. t->pid = pid;
  231. return t;
  232.     }
  233.     /* child */
  234.     close(prfd);
  235.     close(pwfd);
  236.     dup2(crfd, 0);
  237.     dup2(cwfd, 1);
  238.     close(crfd);
  239.     close(cwfd);
  240.     child_main_loop();
  241.     exit(0);
  242. }
  243. static void
  244. create_children(char *argv[])
  245. {
  246.     thing *t;
  247.     thing **T = &things;
  248.     int i;
  249.     for (i = 0; i < 20; i++) {
  250. t = create_a_thing(argv);
  251. assert(t);
  252. if (debug)
  253.     fprintf(stderr, "Thing #%d on FD %d/%dn",
  254. i, t->rfd, t->wfd);
  255. *T = t;
  256. T = &t->next;
  257.     }
  258. }
  259. char *
  260. parent_read_url(void)
  261. {
  262.     static char buf[URL_BUF_SZ];
  263.     while (fgets(buf, URL_BUF_SZ, stdin)) {
  264. if (strncmp(buf, "http://", 7))
  265.     continue;
  266. return buf;
  267.     }
  268.     return NULL;
  269. }
  270. static thing *
  271. get_idle_thing(void)
  272. {
  273.     thing *t;
  274.     thing *n = things;
  275.     while ((t = n)) {
  276. n = t->next;
  277. if (t->state == 0)
  278.     break;
  279.     }
  280.     return t;
  281. }
  282. static void
  283. dispatch(thing * t, char *url)
  284. {
  285.     int x;
  286.     char *s;
  287.     assert(t->state == 0);
  288.     x = write(t->wfd, url, strlen(url));
  289.     if (x < 0)
  290. perror("write");
  291.     if (debug)
  292. fprintf(stderr, "dispatched URL to thing PID %d, %d bytesn", (int) t->pid, x);
  293.     strncpy(t->url, url, URL_BUF_SZ);
  294.     if ((s = strchr(t->url, 'n')))
  295. *s = '';
  296.     t->state = 1;
  297.     FD_SET(t->rfd, &R1);
  298. }
  299. static void
  300. read_reply(thing * t)
  301. {
  302.     char buf[128];
  303.     int i;
  304.     int x;
  305.     int j;
  306.     x = read(t->rfd, buf, 128);
  307.     if (x < 0) {
  308. perror("read");
  309.     } else if (2 == sscanf(buf, "%d %d", &i, &j)) {
  310. gettimeofday(&now, NULL);
  311. printf("%d.%06d %9d %9d %sn", (int) now.tv_sec, (int) now.tv_usec, i, j, t->url);
  312.     }
  313.     t->state = 0;
  314.     FD_CLR(t->rfd, &R1);
  315. }
  316. static void
  317. parent_main_loop(void)
  318. {
  319.     thing *t;
  320.     char *url;
  321.     fd_set R2;
  322.     int x;
  323.     struct timeval to;
  324.     FD_ZERO(&R1);
  325.     for (;;) {
  326. while ((t = get_idle_thing()) && (url = parent_read_url()))
  327.     dispatch(t, url);
  328. R2 = R1;
  329. to.tv_sec = 60;
  330. to.tv_usec = 0;
  331. x = select(maxfd + 1, &R2, NULL, NULL, &to);
  332. if (x < 0) {
  333.     perror("select");
  334.     continue;
  335. } else if (x == 0) {
  336.     return;
  337. }
  338. for (t = things; t; t = t->next) {
  339.     if (t->state != 1)
  340. continue;
  341.     if (!FD_ISSET(t->rfd, &R2))
  342. continue;
  343.     read_reply(t);
  344. }
  345.     }
  346. }
  347. static void
  348. sig_child(int sig)
  349. {
  350.     int status;
  351.     pid_t pid;
  352.     do {
  353. pid = waitpid(-1, &status, WNOHANG);
  354.     } while (pid > 0 || (pid < 0 && errno == EINTR));
  355.     signal(sig, sig_child);
  356. }
  357. int
  358. main(int argc, char *argv[])
  359. {
  360.     int i;
  361.     signal(SIGCHLD, sig_child);
  362.     create_children(argv);
  363.     parent_main_loop();
  364.     for (i=3;i<=maxfd; i++)
  365. close(i);
  366.     sleep(1);
  367. }