]> git.ipfire.org Git - thirdparty/squid.git/blame - src/client.cc
Add counter for cachemgr output
[thirdparty/squid.git] / src / client.cc
CommitLineData
ea3a2a69 1
da2d50d1 2
30a4f2a8 3/*
da2d50d1 4 * $Id: client.cc,v 1.42 1997/11/21 01:59:15 wessels Exp $
30a4f2a8 5 *
6 * DEBUG: section 0 WWW Client
7 * AUTHOR: Harvest Derived
8 *
42c04c16 9 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 10 * --------------------------------------------------------
11 *
12 * Squid is the result of efforts by numerous individuals from the
13 * Internet community. Development is led by Duane Wessels of the
14 * National Laboratory for Applied Network Research and funded by
15 * the National Science Foundation.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 *
31 */
32
33/*
34 * Copyright (c) 1994, 1995. All rights reserved.
35 *
36 * The Harvest software was developed by the Internet Research Task
37 * Force Research Group on Resource Discovery (IRTF-RD):
38 *
39 * Mic Bowman of Transarc Corporation.
40 * Peter Danzig of the University of Southern California.
41 * Darren R. Hardy of the University of Colorado at Boulder.
42 * Udi Manber of the University of Arizona.
43 * Michael F. Schwartz of the University of Colorado at Boulder.
44 * Duane Wessels of the University of Colorado at Boulder.
45 *
46 * This copyright notice applies to software in the Harvest
47 * ``src/'' directory only. Users should consult the individual
48 * copyright notices in the ``components/'' subdirectories for
49 * copyright information about other software bundled with the
50 * Harvest source code distribution.
51 *
52 * TERMS OF USE
53 *
54 * The Harvest software may be used and re-distributed without
55 * charge, provided that the software origin and research team are
56 * cited in any use of the system. Most commonly this is
57 * accomplished by including a link to the Harvest Home Page
58 * (http://harvest.cs.colorado.edu/) from the query page of any
59 * Broker you deploy, as well as in the query result pages. These
60 * links are generated automatically by the standard Broker
61 * software distribution.
62 *
63 * The Harvest software is provided ``as is'', without express or
64 * implied warranty, and with no support nor obligation to assist
65 * in its use, correction, modification or enhancement. We assume
66 * no liability with respect to the infringement of copyrights,
67 * trade secrets, or any patents, and are not responsible for
68 * consequential damages. Proper use of the Harvest software is
69 * entirely the responsibility of the user.
70 *
71 * DERIVATIVE WORKS
72 *
73 * Users may make derivative works from the Harvest software, subject
74 * to the following constraints:
75 *
76 * - You must include the above copyright notice and these
77 * accompanying paragraphs in all forms of derivative works,
78 * and any documentation and other materials related to such
79 * distribution and use acknowledge that the software was
80 * developed at the above institutions.
81 *
82 * - You must notify IRTF-RD regarding your distribution of
83 * the derivative work.
84 *
85 * - You must clearly notify users that your are distributing
86 * a modified version and not the original Harvest software.
87 *
88 * - Any derivative product is also subject to these copyright
89 * and use restrictions.
90 *
91 * Note that the Harvest software is NOT in the public domain. We
92 * retain copyright, as specified above.
93 *
94 * HISTORY OF FREE SOFTWARE STATUS
95 *
96 * Originally we required sites to license the software in cases
97 * where they were going to build commercial products/services
98 * around Harvest. In June 1995 we changed this policy. We now
99 * allow people to use the core Harvest software (the code found in
100 * the Harvest ``src/'' directory) for free. We made this change
101 * in the interest of encouraging the widest possible deployment of
102 * the technology. The Harvest software is really a reference
103 * implementation of a set of protocols and formats, some of which
104 * we intend to standardize. We encourage commercial
105 * re-implementations of code complying to this set of standards.
106 */
090089c4 107
44a47c6e 108#include "squid.h"
090089c4 109
110#ifndef BUFSIZ
111#define BUFSIZ 8192
112#endif
113
114/* Local functions */
899bab3f 115static int client_comm_connect(int, char *, u_short, struct timeval *);
f5b8bbc4 116static void usage(const char *progname);
899bab3f 117static int Now(struct timeval *);
118static SIGHDLR catch;
090089c4 119
b8d8561b 120static void
0ee4272b 121usage(const char *progname)
090089c4 122{
0ee4272b 123 fprintf(stderr,
899bab3f 124 "Usage: %s [-ars] [-i IMS] [-h host] [-p port] [-m method] [-t count] [-I ping-interval] url\n"
fe4e214f 125 "Options:\n"
899bab3f 126 " -a Do NOT include Accept: header.\n"
127 " -r Force cache to reload URL.\n"
128 " -s Silent. Do not print data to stdout.\n"
129 " -i IMS If-Modified-Since time (in Epoch seconds).\n"
130 " -h host Retrieve URL from cache on hostname. Default is localhost.\n"
131 " -p port Port number of cache. Default is %d.\n"
132 " -m method Request method, default is GET.\n"
133 " -t count Trace count cache-hops\n"
134 " -g count Ping mode, \"count\" iterations (0 to loop until interrupted).\n"
135 " -I interval Ping interval in seconds (default 1 second).\n",
fe4e214f 136 progname, CACHE_HTTP_PORT);
090089c4 137 exit(1);
138}
139
899bab3f 140static int interrupted = 0;
b8d8561b 141int
142main(int argc, char *argv[])
090089c4 143{
144 int conn, c, len, bytesWritten;
145 int port, to_stdout, reload;
899bab3f 146 int ping, pcount;
599eadbe 147 int keep_alive = 0;
88738790 148 int opt_noaccept = 0;
090089c4 149 char url[BUFSIZ], msg[BUFSIZ], buf[BUFSIZ], hostname[BUFSIZ];
0ee4272b 150 const char *method = "GET";
090089c4 151 extern char *optarg;
234967c9 152 time_t ims = 0;
b3b64e58 153 int max_forwards = -1;
899bab3f 154 struct timeval tv1, tv2;
155 int i = 0, loops;
156 long ping_int;
157 long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0;
090089c4 158
159 /* set the defaults */
160 strcpy(hostname, "localhost");
161 port = CACHE_HTTP_PORT;
162 to_stdout = 1;
163 reload = 0;
899bab3f 164 ping = 0;
165 pcount = 0;
166 ping_int = 1 * 1000;
090089c4 167
168 if (argc < 2) {
169 usage(argv[0]); /* need URL */
170 } else if (argc >= 2) {
171 strcpy(url, argv[argc - 1]);
172 if (url[0] == '-')
173 usage(argv[0]);
899bab3f 174 while ((c = getopt(argc, argv, "ah:i:km:p:rst:g:I:?")) != -1)
090089c4 175 switch (c) {
88738790 176 case 'a':
177 opt_noaccept = 1;
178 break;
090089c4 179 case 'h': /* host:arg */
090089c4 180 if (optarg != NULL)
181 strcpy(hostname, optarg);
182 break;
183 case 's': /* silent */
090089c4 184 to_stdout = 0;
185 break;
599eadbe 186 case 'k': /* backward compat */
187 keep_alive = 1;
188 break;
090089c4 189 case 'r': /* reload */
190 reload = 1;
191 break;
192 case 'p': /* port number */
193 sscanf(optarg, "%d", &port);
194 if (port < 1)
195 port = CACHE_HTTP_PORT; /* default */
196 break;
234967c9 197 case 'i': /* IMS */
198 ims = (time_t) atoi(optarg);
199 break;
200 case 'm':
201 method = xstrdup(optarg);
202 break;
b3b64e58 203 case 't':
204 method = xstrdup("TRACE");
205 max_forwards = atoi(optarg);
206 break;
899bab3f 207 case 'g':
208 ping = 1;
209 pcount = atoi(optarg);
210 to_stdout = 0;
211 break;
212 case 'I':
213 if ((ping_int = atoi(optarg) * 1000) <= 0)
214 usage(argv[0]);
215 break;
090089c4 216 case '?': /* usage */
217 default:
218 usage(argv[0]);
219 break;
220 }
221 }
090089c4 222 /* Build the HTTP request */
042461c3 223 snprintf(msg, BUFSIZ, "%s %s HTTP/1.0\r\n", method, url);
090089c4 224 if (reload) {
042461c3 225 snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n");
234967c9 226 strcat(msg, buf);
227 }
88738790 228 if (opt_noaccept == 0) {
042461c3 229 snprintf(buf, BUFSIZ, "Accept: */*\r\n");
88738790 230 strcat(msg, buf);
231 }
234967c9 232 if (ims) {
042461c3 233 snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims));
234967c9 234 strcat(msg, buf);
090089c4 235 }
b3b64e58 236 if (max_forwards > -1) {
042461c3 237 snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards);
b3b64e58 238 strcat(msg, buf);
239 }
599eadbe 240 if (keep_alive) {
042461c3 241 snprintf(buf, BUFSIZ, "Proxy-Connection: Keep-Alive\r\n");
599eadbe 242 strcat(msg, buf);
243 }
042461c3 244 snprintf(buf, BUFSIZ, "\r\n");
234967c9 245 strcat(msg, buf);
090089c4 246
899bab3f 247 if (ping) {
248#if HAVE_SIGACTION
249 struct sigaction sa, osa;
250 if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) {
251 sa.sa_handler = catch;
252 sa.sa_flags = 0;
253 sigemptyset(&sa.sa_mask);
254 (void) sigaction(SIGINT, &sa, NULL);
255 }
256#else
257 void (*osig) ();
258 if ((osig = signal(SIGINT, catch)) != SIG_DFL)
259 (void) signal(SIGINT, osig);
260#endif
261 }
262 loops = ping ? pcount : 1;
263 for (i = 0; loops == 0 || i < loops; i++) {
264 /* Connect to the server */
265 if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
266 perror("client: socket");
267 exit(1);
268 }
269 if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) {
270 if (errno == 0) {
271 fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port);
272 } else {
273 char tbuf[BUFSIZ];
2bbd722b 274 snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d",
899bab3f 275 hostname, port);
276 perror(tbuf);
277 }
278 exit(1);
279 }
280 /* Send the HTTP request */
281 bytesWritten = write(conn, msg, strlen(msg));
282 if (bytesWritten < 0) {
283 perror("client: ERROR: write");
284 exit(1);
285 } else if (bytesWritten != strlen(msg)) {
286 fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg);
287 exit(1);
288 }
289 /* Read the data */
290 while ((len = read(conn, buf, sizeof(buf))) > 0) {
291 if (to_stdout)
292 fwrite(buf, len, 1, stdout);
293 }
294 (void) close(conn); /* done with socket */
295
296 if (interrupted)
297 break;
298
299 if (ping) {
300 struct tm *tmp;
301 time_t t2s;
302 long elapsed_msec;
303
304 (void) Now(&tv2);
305 elapsed_msec = tvSubMsec(tv1, tv2);
306 t2s = tv2.tv_sec;
307 tmp = localtime(&t2s);
308 fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs\n",
309 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
310 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1,
311 elapsed_msec / 1000, elapsed_msec % 1000);
312 if (i == 0 || elapsed_msec < ping_min)
313 ping_min = elapsed_msec;
314 if (i == 0 || elapsed_msec > ping_max)
315 ping_max = elapsed_msec;
316 ping_sum += elapsed_msec;
317 /* Delay until next "ping_int" boundary */
318 if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) {
319 struct timeval tvs;
320 long msec_left = ping_int - elapsed_msec;
321
322 tvs.tv_sec = msec_left / 1000;
323 tvs.tv_usec = (msec_left % 1000) * 1000;
324 select(0, NULL, NULL, NULL, &tvs);
325 }
326 }
090089c4 327 }
899bab3f 328
329 if (ping && i) {
330 ping_mean = ping_sum / i;
331 fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = "
332 "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i,
333 ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000,
334 ping_max / 1000, ping_max % 1000);
090089c4 335 }
090089c4 336 exit(0);
337 /*NOTREACHED */
983061ed 338 return 0;
090089c4 339}
340
b8d8561b 341static int
899bab3f 342client_comm_connect(int sock, char *dest_host, u_short dest_port, struct timeval *tvp)
090089c4 343{
899bab3f 344 static const struct hostent *hp = NULL;
090089c4 345 static struct sockaddr_in to_addr;
346
347 /* Set up the destination socket address for message to send to. */
899bab3f 348 if (hp == NULL) {
349 to_addr.sin_family = AF_INET;
090089c4 350
899bab3f 351 if ((hp = gethostbyname(dest_host)) == 0) {
352 return (-1);
353 }
354 xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length);
355 to_addr.sin_port = htons(dest_port);
090089c4 356 }
899bab3f 357 if (tvp)
358 (void) Now(tvp);
090089c4 359 return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in));
360}
899bab3f 361
362static int
363Now(struct timeval *tp)
364{
365#if GETTIMEOFDAY_NO_TZP
366 return gettimeofday(tp);
367#else
368 return gettimeofday(tp, NULL);
369#endif
370} /* ARGSUSED */
371
372static void
373catch(int sig)
374{
375 interrupted = 1;
376 fprintf(stderr, "Interrupted.\n");
377}