client.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:11k
- /*
- * $Id: client.c,v 1.81.2.1 1999/02/14 08:35:00 wessels Exp $
- *
- * DEBUG: section 0 WWW Client
- * AUTHOR: Harvest Derived
- *
- * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from the
- * Internet community. Development is led by Duane Wessels of the
- * National Laboratory for Applied Network Research and funded by the
- * National Science Foundation. Squid is Copyrighted (C) 1998 by
- * Duane Wessels and the University of California San Diego. Please
- * see the COPYRIGHT file for full details. Squid incorporates
- * software developed and/or copyrighted by other sources. Please see
- * the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- */
- #include "squid.h"
- #ifndef BUFSIZ
- #define BUFSIZ 8192
- #endif
- /* Local functions */
- static int client_comm_connect(int, char *, u_short, struct timeval *);
- static void usage(const char *progname);
- static int Now(struct timeval *);
- static SIGHDLR catch;
- static SIGHDLR pipe_handler;
- static void set_our_signal();
- static int put_fd;
- static char *put_file = NULL;
- static struct stat sb;
- int total_bytes = 0;
- static void
- usage(const char *progname)
- {
- fprintf(stderr,
- "Usage: %s [-arsv] [-i IMS] [-h host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] urln"
- "Options:n"
- " -P file PUT request.n"
- " -a Do NOT include Accept: header.n"
- " -r Force cache to reload URL.n"
- " -s Silent. Do not print data to stdout.n"
- " -v Verbose. Print outgoing message to stderr.n"
- " -i IMS If-Modified-Since time (in Epoch seconds).n"
- " -h host Retrieve URL from cache on hostname. Default is localhost.n"
- " -p port Port number of cache. Default is %d.n"
- " -m method Request method, default is GET.n"
- " -t count Trace count cache-hopsn"
- " -g count Ping mode, "count" iterations (0 to loop until interrupted).n"
- " -I interval Ping interval in seconds (default 1 second).n"
- " -H 'string' Extra headers to send. Use '\n' for new lines.n",
- progname, CACHE_HTTP_PORT);
- exit(1);
- }
- static int interrupted = 0;
- int
- main(int argc, char *argv[])
- {
- int conn, c, len, bytesWritten;
- int port, to_stdout, reload;
- int ping, pcount;
- int keep_alive = 0;
- int opt_noaccept = 0;
- int opt_put = 0;
- int opt_verbose = 0;
- char url[BUFSIZ], msg[BUFSIZ], buf[BUFSIZ], hostname[BUFSIZ];
- char extra_hdrs[BUFSIZ];
- const char *method = "GET";
- extern char *optarg;
- time_t ims = 0;
- int max_forwards = -1;
- struct timeval tv1, tv2;
- int i = 0, loops;
- long ping_int;
- long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0;
- /* set the defaults */
- strcpy(hostname, "localhost");
- extra_hdrs[0] = ' ';
- port = CACHE_HTTP_PORT;
- to_stdout = 1;
- reload = 0;
- ping = 0;
- pcount = 0;
- ping_int = 1 * 1000;
- if (argc < 2) {
- usage(argv[0]); /* need URL */
- } else if (argc >= 2) {
- strcpy(url, argv[argc - 1]);
- if (url[0] == '-')
- usage(argv[0]);
- while ((c = getopt(argc, argv, "ah:P:i:km:p:rsvt:g:p:I:H:?")) != -1)
- switch (c) {
- case 'a':
- opt_noaccept = 1;
- break;
- case 'h': /* host:arg */
- if (optarg != NULL)
- strcpy(hostname, optarg);
- break;
- case 's': /* silent */
- to_stdout = 0;
- break;
- case 'k': /* backward compat */
- keep_alive = 1;
- break;
- case 'r': /* reload */
- reload = 1;
- break;
- case 'p': /* port number */
- sscanf(optarg, "%d", &port);
- if (port < 1)
- port = CACHE_HTTP_PORT; /* default */
- break;
- case 'P':
- put_file = xstrdup(optarg);
- break;
- case 'i': /* IMS */
- ims = (time_t) atoi(optarg);
- break;
- case 'm':
- method = xstrdup(optarg);
- break;
- case 't':
- method = xstrdup("TRACE");
- max_forwards = atoi(optarg);
- break;
- case 'g':
- ping = 1;
- pcount = atoi(optarg);
- to_stdout = 0;
- break;
- case 'I':
- if ((ping_int = atoi(optarg) * 1000) <= 0)
- usage(argv[0]);
- break;
- case 'H':
- if (strlen(optarg)) {
- char *t;
- strncpy(extra_hdrs, optarg, sizeof(extra_hdrs));
- while ((t = strstr(extra_hdrs, "\n")))
- *t = 'r', *(t + 1) = 'n';
- }
- break;
- case 'v':
- /* undocumented: may increase verb-level by giving more -v's */
- opt_verbose++;
- break;
- case '?': /* usage */
- default:
- usage(argv[0]);
- break;
- }
- }
- /* Build the HTTP request */
- if (strncmp(url, "mgr:", 4) == 0) {
- char *t = xstrdup(url + 4);
- snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t);
- xfree(t);
- }
- if (put_file) {
- opt_put = 1;
- /*method = xstrdup("PUT"); */
- put_fd = open(put_file, O_RDONLY);
- set_our_signal();
- if (put_fd < 0) {
- fprintf(stderr, "%s: can't open file (%s)n", argv[0],
- xstrerror());
- exit(-1);
- }
- fstat(put_fd, &sb);
- }
- snprintf(msg, BUFSIZ, "%s %s HTTP/1.0rn", method, url);
- if (reload) {
- snprintf(buf, BUFSIZ, "Pragma: no-cachern");
- strcat(msg, buf);
- }
- if (put_fd > 0) {
- snprintf(buf, BUFSIZ, "Content-length: %drn", (int) sb.st_size);
- strcat(msg, buf);
- }
- if (opt_noaccept == 0) {
- snprintf(buf, BUFSIZ, "Accept: */*rn");
- strcat(msg, buf);
- }
- if (ims) {
- snprintf(buf, BUFSIZ, "If-Modified-Since: %srn", mkrfc1123(ims));
- strcat(msg, buf);
- }
- if (max_forwards > -1) {
- snprintf(buf, BUFSIZ, "Max-Forwards: %drn", max_forwards);
- strcat(msg, buf);
- }
- if (keep_alive) {
- if (port != 80)
- snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alivern");
- else
- snprintf(buf, BUFSIZ, "Connection: keep-alivern");
- strcat(msg, buf);
- }
- strcat(msg, extra_hdrs);
- snprintf(buf, BUFSIZ, "rn");
- strcat(msg, buf);
- if (opt_verbose)
- fprintf(stderr, "headers: '%s'n", msg);
- if (ping) {
- #if HAVE_SIGACTION
- struct sigaction sa, osa;
- if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) {
- sa.sa_handler = catch;
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- (void) sigaction(SIGINT, &sa, NULL);
- }
- #else
- void (*osig) ();
- if ((osig = signal(SIGINT, catch)) != SIG_DFL)
- (void) signal(SIGINT, osig);
- #endif
- }
- loops = ping ? pcount : 1;
- for (i = 0; loops == 0 || i < loops; i++) {
- /* Connect to the server */
- if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
- perror("client: socket");
- exit(1);
- }
- if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) {
- if (errno == 0) {
- fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.n", hostname, port);
- } else {
- char tbuf[BUFSIZ];
- snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d",
- hostname, port);
- perror(tbuf);
- }
- exit(1);
- }
- /* Send the HTTP request */
- bytesWritten = write(conn, msg, strlen(msg));
- if (bytesWritten < 0) {
- perror("client: ERROR: write");
- exit(1);
- } else if (bytesWritten != strlen(msg)) {
- fprintf(stderr, "client: ERROR: Cannot send request?: %sn", msg);
- exit(1);
- }
- if (put_file) {
- int x;
- lseek(put_fd, 0, SEEK_SET);
- while ((x = read(put_fd, buf, sizeof(buf))) > 0) {
- x = write(conn, buf, x);
- total_bytes += x;
- if (x <= 0)
- break;
- }
- if (x != 0)
- fprintf(stderr, "client: ERROR: Cannot send file.n");
- }
- /* Read the data */
- while ((len = read(conn, buf, sizeof(buf))) > 0) {
- if (to_stdout)
- fwrite(buf, len, 1, stdout);
- }
- (void) close(conn); /* done with socket */
- if (interrupted)
- break;
- if (ping) {
- struct tm *tmp;
- time_t t2s;
- long elapsed_msec;
- (void) Now(&tv2);
- elapsed_msec = tvSubMsec(tv1, tv2);
- t2s = tv2.tv_sec;
- tmp = localtime(&t2s);
- fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secsn",
- tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
- tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1,
- elapsed_msec / 1000, elapsed_msec % 1000);
- if (i == 0 || elapsed_msec < ping_min)
- ping_min = elapsed_msec;
- if (i == 0 || elapsed_msec > ping_max)
- ping_max = elapsed_msec;
- ping_sum += elapsed_msec;
- /* Delay until next "ping_int" boundary */
- if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) {
- struct timeval tvs;
- long msec_left = ping_int - elapsed_msec;
- tvs.tv_sec = msec_left / 1000;
- tvs.tv_usec = (msec_left % 1000) * 1000;
- select(0, NULL, NULL, NULL, &tvs);
- }
- }
- }
- if (ping && i) {
- ping_mean = ping_sum / i;
- fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = "
- "%ld.%03ld/%ld.%03ld/%ld.%03ldn", i,
- ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000,
- ping_max / 1000, ping_max % 1000);
- }
- exit(0);
- /*NOTREACHED */
- return 0;
- }
- static int
- client_comm_connect(int sock, char *dest_host, u_short dest_port, struct timeval *tvp)
- {
- static const struct hostent *hp = NULL;
- static struct sockaddr_in to_addr;
- /* Set up the destination socket address for message to send to. */
- if (hp == NULL) {
- to_addr.sin_family = AF_INET;
- if ((hp = gethostbyname(dest_host)) == 0) {
- return (-1);
- }
- xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
- to_addr.sin_port = htons(dest_port);
- }
- if (tvp)
- (void) Now(tvp);
- return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in));
- }
- static int
- Now(struct timeval *tp)
- {
- #if GETTIMEOFDAY_NO_TZP
- return gettimeofday(tp);
- #else
- return gettimeofday(tp, NULL);
- #endif
- } /* ARGSUSED */
- static void
- catch(int sig)
- {
- interrupted = 1;
- fprintf(stderr, "Interrupted.n");
- }
- static void
- pipe_handler(int sig)
- {
- fprintf(stderr, "SIGPIPE received.n");
- }
- static void
- set_our_signal()
- {
- #if HAVE_SIGACTION
- struct sigaction sa;
- sa.sa_handler = pipe_handler;
- sa.sa_flags = SA_RESTART;
- sigemptyset(&sa.sa_mask);
- if (sigaction(SIGPIPE, &sa, NULL) < 0) {
- fprintf(stderr, "Cannot set PIPE signal.n");
- exit(-1);
- }
- #else
- signal(SIGPIPE, pipe_handler);
- #endif
- }