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

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: client.c,v 1.81.2.1 1999/02/14 08:35:00 wessels Exp $
  3.  *
  4.  * DEBUG: section 0     WWW Client
  5.  * AUTHOR: Harvest Derived
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. #ifndef BUFSIZ
  36. #define BUFSIZ 8192
  37. #endif
  38. /* Local functions */
  39. static int client_comm_connect(int, char *, u_short, struct timeval *);
  40. static void usage(const char *progname);
  41. static int Now(struct timeval *);
  42. static SIGHDLR catch;
  43. static SIGHDLR pipe_handler;
  44. static void set_our_signal();
  45. static int put_fd;
  46. static char *put_file = NULL;
  47. static struct stat sb;
  48. int total_bytes = 0;
  49. static void
  50. usage(const char *progname)
  51. {
  52.     fprintf(stderr,
  53. "Usage: %s [-arsv] [-i IMS] [-h host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] urln"
  54. "Options:n"
  55. "    -P file      PUT request.n"
  56. "    -a           Do NOT include Accept: header.n"
  57. "    -r           Force cache to reload URL.n"
  58. "    -s           Silent.  Do not print data to stdout.n"
  59. "    -v           Verbose. Print outgoing message to stderr.n"
  60. "    -i IMS       If-Modified-Since time (in Epoch seconds).n"
  61. "    -h host      Retrieve URL from cache on hostname.  Default is localhost.n"
  62. "    -p port      Port number of cache.  Default is %d.n"
  63. "    -m method    Request method, default is GET.n"
  64. "    -t count     Trace count cache-hopsn"
  65. "    -g count     Ping mode, "count" iterations (0 to loop until interrupted).n"
  66. "    -I interval  Ping interval in seconds (default 1 second).n"
  67. "    -H 'string'  Extra headers to send. Use '\n' for new lines.n",
  68. progname, CACHE_HTTP_PORT);
  69.     exit(1);
  70. }
  71. static int interrupted = 0;
  72. int
  73. main(int argc, char *argv[])
  74. {
  75.     int conn, c, len, bytesWritten;
  76.     int port, to_stdout, reload;
  77.     int ping, pcount;
  78.     int keep_alive = 0;
  79.     int opt_noaccept = 0;
  80.     int opt_put = 0;
  81.     int opt_verbose = 0;
  82.     char url[BUFSIZ], msg[BUFSIZ], buf[BUFSIZ], hostname[BUFSIZ];
  83.     char extra_hdrs[BUFSIZ];
  84.     const char *method = "GET";
  85.     extern char *optarg;
  86.     time_t ims = 0;
  87.     int max_forwards = -1;
  88.     struct timeval tv1, tv2;
  89.     int i = 0, loops;
  90.     long ping_int;
  91.     long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0;
  92.     /* set the defaults */
  93.     strcpy(hostname, "localhost");
  94.     extra_hdrs[0] = '';
  95.     port = CACHE_HTTP_PORT;
  96.     to_stdout = 1;
  97.     reload = 0;
  98.     ping = 0;
  99.     pcount = 0;
  100.     ping_int = 1 * 1000;
  101.     if (argc < 2) {
  102. usage(argv[0]); /* need URL */
  103.     } else if (argc >= 2) {
  104. strcpy(url, argv[argc - 1]);
  105. if (url[0] == '-')
  106.     usage(argv[0]);
  107. while ((c = getopt(argc, argv, "ah:P:i:km:p:rsvt:g:p:I:H:?")) != -1)
  108.     switch (c) {
  109.     case 'a':
  110. opt_noaccept = 1;
  111. break;
  112.     case 'h': /* host:arg */
  113. if (optarg != NULL)
  114.     strcpy(hostname, optarg);
  115. break;
  116.     case 's': /* silent */
  117. to_stdout = 0;
  118. break;
  119.     case 'k': /* backward compat */
  120. keep_alive = 1;
  121. break;
  122.     case 'r': /* reload */
  123. reload = 1;
  124. break;
  125.     case 'p': /* port number */
  126. sscanf(optarg, "%d", &port);
  127. if (port < 1)
  128.     port = CACHE_HTTP_PORT; /* default */
  129. break;
  130.     case 'P':
  131. put_file = xstrdup(optarg);
  132. break;
  133.     case 'i': /* IMS */
  134. ims = (time_t) atoi(optarg);
  135. break;
  136.     case 'm':
  137. method = xstrdup(optarg);
  138. break;
  139.     case 't':
  140. method = xstrdup("TRACE");
  141. max_forwards = atoi(optarg);
  142. break;
  143.     case 'g':
  144. ping = 1;
  145. pcount = atoi(optarg);
  146. to_stdout = 0;
  147. break;
  148.     case 'I':
  149. if ((ping_int = atoi(optarg) * 1000) <= 0)
  150.     usage(argv[0]);
  151. break;
  152.     case 'H':
  153. if (strlen(optarg)) {
  154.     char *t;
  155.     strncpy(extra_hdrs, optarg, sizeof(extra_hdrs));
  156.     while ((t = strstr(extra_hdrs, "\n")))
  157. *t = 'r', *(t + 1) = 'n';
  158. }
  159. break;
  160.     case 'v':
  161. /* undocumented: may increase verb-level by giving more -v's */
  162. opt_verbose++;
  163. break;
  164.     case '?': /* usage */
  165.     default:
  166. usage(argv[0]);
  167. break;
  168.     }
  169.     }
  170.     /* Build the HTTP request */
  171.     if (strncmp(url, "mgr:", 4) == 0) {
  172. char *t = xstrdup(url + 4);
  173. snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t);
  174. xfree(t);
  175.     }
  176.     if (put_file) {
  177. opt_put = 1;
  178. /*method = xstrdup("PUT"); */
  179. put_fd = open(put_file, O_RDONLY);
  180. set_our_signal();
  181. if (put_fd < 0) {
  182.     fprintf(stderr, "%s: can't open file (%s)n", argv[0],
  183. xstrerror());
  184.     exit(-1);
  185. }
  186. fstat(put_fd, &sb);
  187.     }
  188.     snprintf(msg, BUFSIZ, "%s %s HTTP/1.0rn", method, url);
  189.     if (reload) {
  190. snprintf(buf, BUFSIZ, "Pragma: no-cachern");
  191. strcat(msg, buf);
  192.     }
  193.     if (put_fd > 0) {
  194. snprintf(buf, BUFSIZ, "Content-length: %drn", (int) sb.st_size);
  195. strcat(msg, buf);
  196.     }
  197.     if (opt_noaccept == 0) {
  198. snprintf(buf, BUFSIZ, "Accept: */*rn");
  199. strcat(msg, buf);
  200.     }
  201.     if (ims) {
  202. snprintf(buf, BUFSIZ, "If-Modified-Since: %srn", mkrfc1123(ims));
  203. strcat(msg, buf);
  204.     }
  205.     if (max_forwards > -1) {
  206. snprintf(buf, BUFSIZ, "Max-Forwards: %drn", max_forwards);
  207. strcat(msg, buf);
  208.     }
  209.     if (keep_alive) {
  210. if (port != 80)
  211.     snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alivern");
  212. else
  213.     snprintf(buf, BUFSIZ, "Connection: keep-alivern");
  214. strcat(msg, buf);
  215.     }
  216.     strcat(msg, extra_hdrs);
  217.     snprintf(buf, BUFSIZ, "rn");
  218.     strcat(msg, buf);
  219.     if (opt_verbose)
  220. fprintf(stderr, "headers: '%s'n", msg);
  221.     if (ping) {
  222. #if HAVE_SIGACTION
  223. struct sigaction sa, osa;
  224. if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) {
  225.     sa.sa_handler = catch;
  226.     sa.sa_flags = 0;
  227.     sigemptyset(&sa.sa_mask);
  228.     (void) sigaction(SIGINT, &sa, NULL);
  229. }
  230. #else
  231. void (*osig) ();
  232. if ((osig = signal(SIGINT, catch)) != SIG_DFL)
  233.     (void) signal(SIGINT, osig);
  234. #endif
  235.     }
  236.     loops = ping ? pcount : 1;
  237.     for (i = 0; loops == 0 || i < loops; i++) {
  238. /* Connect to the server */
  239. if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  240.     perror("client: socket");
  241.     exit(1);
  242. }
  243. if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) {
  244.     if (errno == 0) {
  245. fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.n", hostname, port);
  246.     } else {
  247. char tbuf[BUFSIZ];
  248. snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d",
  249.     hostname, port);
  250. perror(tbuf);
  251.     }
  252.     exit(1);
  253. }
  254. /* Send the HTTP request */
  255. bytesWritten = write(conn, msg, strlen(msg));
  256. if (bytesWritten < 0) {
  257.     perror("client: ERROR: write");
  258.     exit(1);
  259. } else if (bytesWritten != strlen(msg)) {
  260.     fprintf(stderr, "client: ERROR: Cannot send request?: %sn", msg);
  261.     exit(1);
  262. }
  263. if (put_file) {
  264.     int x;
  265.     lseek(put_fd, 0, SEEK_SET);
  266.     while ((x = read(put_fd, buf, sizeof(buf))) > 0) {
  267. x = write(conn, buf, x);
  268. total_bytes += x;
  269. if (x <= 0)
  270.     break;
  271.     }
  272.     if (x != 0)
  273. fprintf(stderr, "client: ERROR: Cannot send file.n");
  274. }
  275. /* Read the data */
  276. while ((len = read(conn, buf, sizeof(buf))) > 0) {
  277.     if (to_stdout)
  278. fwrite(buf, len, 1, stdout);
  279. }
  280. (void) close(conn); /* done with socket */
  281. if (interrupted)
  282.     break;
  283. if (ping) {
  284.     struct tm *tmp;
  285.     time_t t2s;
  286.     long elapsed_msec;
  287.     (void) Now(&tv2);
  288.     elapsed_msec = tvSubMsec(tv1, tv2);
  289.     t2s = tv2.tv_sec;
  290.     tmp = localtime(&t2s);
  291.     fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secsn",
  292. tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
  293. tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1,
  294. elapsed_msec / 1000, elapsed_msec % 1000);
  295.     if (i == 0 || elapsed_msec < ping_min)
  296. ping_min = elapsed_msec;
  297.     if (i == 0 || elapsed_msec > ping_max)
  298. ping_max = elapsed_msec;
  299.     ping_sum += elapsed_msec;
  300.     /* Delay until next "ping_int" boundary */
  301.     if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) {
  302. struct timeval tvs;
  303. long msec_left = ping_int - elapsed_msec;
  304. tvs.tv_sec = msec_left / 1000;
  305. tvs.tv_usec = (msec_left % 1000) * 1000;
  306. select(0, NULL, NULL, NULL, &tvs);
  307.     }
  308. }
  309.     }
  310.     if (ping && i) {
  311. ping_mean = ping_sum / i;
  312. fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = "
  313.     "%ld.%03ld/%ld.%03ld/%ld.%03ldn", i,
  314.     ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000,
  315.     ping_max / 1000, ping_max % 1000);
  316.     }
  317.     exit(0);
  318.     /*NOTREACHED */
  319.     return 0;
  320. }
  321. static int
  322. client_comm_connect(int sock, char *dest_host, u_short dest_port, struct timeval *tvp)
  323. {
  324.     static const struct hostent *hp = NULL;
  325.     static struct sockaddr_in to_addr;
  326.     /* Set up the destination socket address for message to send to. */
  327.     if (hp == NULL) {
  328. to_addr.sin_family = AF_INET;
  329. if ((hp = gethostbyname(dest_host)) == 0) {
  330.     return (-1);
  331. }
  332. xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
  333. to_addr.sin_port = htons(dest_port);
  334.     }
  335.     if (tvp)
  336. (void) Now(tvp);
  337.     return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in));
  338. }
  339. static int
  340. Now(struct timeval *tp)
  341. {
  342. #if GETTIMEOFDAY_NO_TZP
  343.     return gettimeofday(tp);
  344. #else
  345.     return gettimeofday(tp, NULL);
  346. #endif
  347. } /* ARGSUSED */
  348. static void
  349. catch(int sig)
  350. {
  351.     interrupted = 1;
  352.     fprintf(stderr, "Interrupted.n");
  353. }
  354. static void
  355. pipe_handler(int sig)
  356. {
  357.     fprintf(stderr, "SIGPIPE received.n");
  358. }
  359. static void
  360. set_our_signal()
  361. {
  362. #if HAVE_SIGACTION
  363.     struct sigaction sa;
  364.     sa.sa_handler = pipe_handler;
  365.     sa.sa_flags = SA_RESTART;
  366.     sigemptyset(&sa.sa_mask);
  367.     if (sigaction(SIGPIPE, &sa, NULL) < 0) {
  368. fprintf(stderr, "Cannot set PIPE signal.n");
  369. exit(-1);
  370.     }
  371. #else
  372.     signal(SIGPIPE, pipe_handler);
  373. #endif
  374. }