예제 #1
0
static void
child_main_loop(void)
{
    char buf[URL_BUF_SZ];
    char *t;
    int n;
    struct timeval t1;
    struct timeval t2;
    if (debug)
	fprintf(stderr, "Child PID %d entering child_main_loop\n", (int) getpid());
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
    while (fgets(buf, URL_BUF_SZ, stdin)) {
	t = strchr(buf, '\n');
	if (t == NULL)
	    continue;
	*t = '\0';
	if (strncmp(buf, "http://", 7))
	    continue;
	gettimeofday(&t1, NULL);
	n = get_url(buf);
	gettimeofday(&t2, NULL);
	printf("%d %d\n", n, tvSubMsec(t1, t2));
    }
}
예제 #2
0
static void
peerCountHandleIcpReply(peer * p, peer_t type, protocol_t proto, void *hdrnotused, void *data)
{
    ps_state *psstate = data;
    StoreEntry *fake = psstate->entry;
    MemObject *mem = fake->mem_obj;
    int rtt = tvSubMsec(mem->start_ping, current_time);
    assert(proto == PROTO_ICP);
    assert(fake);
    assert(mem);
    psstate->ping.n_recv++;
    p->stats.rtt = intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, RTT_AV_FACTOR);
}
예제 #3
0
static void
helperStatefulHandleRead(int fd, void *data)
{
    int len;
    char *t = NULL;
    helper_stateful_server *srv = data;
    helper_stateful_request *r;
    statefulhelper *hlp = srv->parent;
    assert(fd == srv->rfd);
    assert(cbdataValid(data));
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, srv->buf + srv->offset, srv->buf_sz - srv->offset);
    fd_bytes(fd, len, FD_READ);
    debug(84, 5) ("helperStatefulHandleRead: %d bytes from %s #%d.\n",
	len, hlp->id_name, srv->index + 1);
    if (len <= 0) {
	if (len < 0)
	    debug(84, 1) ("helperStatefulHandleRead: FD %d read: %s\n", fd, xstrerror());
	comm_close(fd);
	return;
    }
    srv->offset += len;
    srv->buf[srv->offset] = '\0';
    r = srv->request;
    if (r == NULL) {
	/* someone spoke without being spoken to */
	debug(84, 1) ("helperStatefulHandleRead: unexpected read from %s #%d, %d bytes\n",
	    hlp->id_name, srv->index + 1, len);
	srv->offset = 0;
    } else if ((t = strchr(srv->buf, '\n'))) {
	/* end of reply found */
	debug(84, 3) ("helperStatefulHandleRead: end of reply found\n");
	*t = '\0';
	srv->flags.busy = 0;
	srv->offset = 0;
	srv->request = NULL;
	hlp->stats.replies++;
	hlp->stats.avg_svc_time =
	    intAverage(hlp->stats.avg_svc_time,
	    tvSubMsec(srv->dispatch_time, current_time),
	    hlp->stats.replies, REDIRECT_AV_FACTOR);
	if (cbdataValid(r->data)) {
	    r->callback(r->data, srv, srv->buf);
	} else {
	    debug(84, 1) ("StatefulHandleRead: no callback data registered\n");
	}
	helperStatefulRequestFree(r);
    } else {
	commSetSelect(srv->rfd, COMM_SELECT_READ, helperStatefulHandleRead, srv, 0);
    }
}
예제 #4
0
void
helperStatefulStats(StoreEntry * sentry, statefulhelper * hlp)
{
    helper_stateful_server *srv;
    dlink_node *link;
    double tt;
    storeAppendPrintf(sentry, "number running: %d of %d\n",
	hlp->n_running, hlp->n_to_start);
    storeAppendPrintf(sentry, "requests sent: %d\n",
	hlp->stats.requests);
    storeAppendPrintf(sentry, "replies received: %d\n",
	hlp->stats.replies);
    storeAppendPrintf(sentry, "queue length: %d\n",
	hlp->stats.queue_size);
    storeAppendPrintf(sentry, "avg service time: %d msec\n",
	hlp->stats.avg_svc_time);
    storeAppendPrintf(sentry, "\n");
    storeAppendPrintf(sentry, "%7s\t%7s\t%7s\t%11s\t%s\t%7s\t%7s\t%7s\n",
	"#",
	"FD",
	"PID",
	"# Requests",
	"Flags",
	"Time",
	"Offset",
	"Request");
    for (link = hlp->servers.head; link; link = link->next) {
	srv = link->data;
	tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time);
	storeAppendPrintf(sentry, "%7d\t%7d\t%7d\t%11d\t%c%c%c%c%c\t%7.3f\t%7d\t%s\n",
	    srv->index + 1,
	    srv->rfd,
	    srv->pid,
	    srv->stats.uses,
	    srv->flags.alive ? 'A' : ' ',
	    srv->flags.busy ? 'B' : ' ',
	    srv->flags.closing ? 'C' : ' ',
	    srv->flags.reserved ? 'R' : ' ',
	    srv->flags.shutdown ? 'S' : ' ',
	    tt < 0.0 ? 0.0 : tt,
	    (int) srv->offset,
	    srv->request ? log_quote(srv->request->buf) : "(none)");
    }
    storeAppendPrintf(sentry, "\nFlags key:\n\n");
    storeAppendPrintf(sentry, "   A = ALIVE\n");
    storeAppendPrintf(sentry, "   B = BUSY\n");
    storeAppendPrintf(sentry, "   C = CLOSING\n");
    storeAppendPrintf(sentry, "   R = RESERVED or DEFERRED\n");
    storeAppendPrintf(sentry, "   S = SHUTDOWN\n");
    storeAppendPrintf(sentry, "   P = PLACEHOLDER\n");
}
예제 #5
0
static void
neighborUpdateRtt(peer * p, MemObject * mem)
{
    int rtt;
    if (!mem)
	return;
    if (!mem->start_ping.tv_sec)
	return;
    rtt = tvSubMsec(mem->start_ping, current_time);
    if (rtt < 1 || rtt > 10000)
	return;
    p->stats.rtt = intAverage(p->stats.rtt, rtt,
	p->stats.pings_acked, RTT_AV_FACTOR);
}
예제 #6
0
static void
netdbSaveState(void *foo)
{
    Logfile *lf;
    netdbEntry *n;
    net_db_name *x;
    struct timeval start = current_time;
    int count = 0;
    if (strcmp(Config.netdbFilename, "none") == 0)
        return;
    /*
     * This was nicer when we were using stdio, but thanks to
     * Solaris bugs, its a bad idea.  fopen can fail if more than
     * 256 FDs are open.
     */
    /*
     * unlink() is here because there is currently no way to make
     * logfileOpen() use O_TRUNC.
     */
    unlink(Config.netdbFilename);
    lf = logfileOpen(Config.netdbFilename, 4096, 0);
    if (NULL == lf) {
        debug(50, 1) ("netdbSaveState: %s: %s\n", Config.netdbFilename, xstrerror());
        return;
    }
    hash_first(addr_table);
    while ((n = (netdbEntry *) hash_next(addr_table))) {
        if (n->pings_recv == 0)
            continue;
        logfilePrintf(lf, "%s %d %d %10.5f %10.5f %d %d",
                      n->network,
                      n->pings_sent,
                      n->pings_recv,
                      n->hops,
                      n->rtt,
                      (int) n->next_ping_time,
                      (int) n->last_use_time);
        for (x = n->hosts; x; x = x->next)
            logfilePrintf(lf, " %s", hashKeyStr(&x->hash));
        logfilePrintf(lf, "\n");
        count++;
#undef RBUF_SZ
    }
    logfileClose(lf);
    getCurrentTime();
    debug(38, 1) ("NETDB state saved; %d entries, %d msec\n",
                  count, tvSubMsec(start, current_time));
    eventAddIsh("netdbSaveState", netdbSaveState, NULL, 3600.0, 1);
}
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_verbose = 0;
    const char *hostname, *localhost;
    char url[BUFSIZ], msg[BUFSIZ], buf[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;
    char *proxy_user = NULL;
    char *proxy_password = NULL;
    char *www_user = NULL;
    char *www_password = NULL;

    /* set the defaults */
    hostname = "localhost";
    localhost = NULL;
    extra_hdrs[0] = '\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) {
	strncpy(url, argv[argc - 1], BUFSIZ);
	url[BUFSIZ - 1] = '\0';
	if (url[0] == '-')
	    usage(argv[0]);
	while ((c = getopt(argc, argv, "ah:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1)
	    switch (c) {
	    case 'a':
		opt_noaccept = 1;
		break;
	    case 'h':		/* remote host */
		if (optarg != NULL)
		    hostname = optarg;
		break;
	    case 'l':		/* local host */
		if (optarg != NULL)
		    localhost = 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 'T':
		io_timeout = atoi(optarg);
		break;
	    case 'u':
		proxy_user = optarg;
		break;
	    case 'w':
		proxy_password = optarg;
		break;
	    case 'U':
		www_user = optarg;
		break;
	    case 'W':
		www_password = optarg;
		break;
	    case 'v':
		/* undocumented: may increase verb-level by giving more -v's */
		opt_verbose++;
		break;
	    case '?':		/* usage */
	    default:
		usage(argv[0]);
		break;
	    }
    }
#ifdef _SQUID_MSWIN_
    {
	WSADATA wsaData;
	WSAStartup(2, &wsaData);
    }
#endif
    /* 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) {
	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);
	}
#ifdef _SQUID_WIN32_
	setmode(put_fd, O_BINARY);
#endif
	fstat(put_fd, &sb);
    }
    snprintf(msg, BUFSIZ, "%s %s HTTP/1.0\r\n", method, url);
    if (reload) {
	snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n");
	strcat(msg, buf);
    }
    if (put_fd > 0) {
	snprintf(buf, BUFSIZ, "Content-length: %d\r\n", (int) sb.st_size);
	strcat(msg, buf);
    }
    if (opt_noaccept == 0) {
	snprintf(buf, BUFSIZ, "Accept: */*\r\n");
	strcat(msg, buf);
    }
    if (ims) {
	snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims));
	strcat(msg, buf);
    }
    if (max_forwards > -1) {
	snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards);
	strcat(msg, buf);
    }
    if (proxy_user) {
	char *user = proxy_user;
	char *password = proxy_password;
#if HAVE_GETPASS
	if (!password)
	    password = getpass("Proxy password: "******"ERROR: Proxy password missing\n");
	    exit(1);
	}
	snprintf(buf, BUFSIZ, "%s:%s", user, password);
	snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\r\n", base64_encode(buf));
	strcat(msg, buf);
    }
    if (www_user) {
	char *user = www_user;
	char *password = www_password;
#if HAVE_GETPASS
	if (!password)
	    password = getpass("WWW password: "******"ERROR: WWW password missing\n");
	    exit(1);
	}
	snprintf(buf, BUFSIZ, "%s:%s", user, password);
	snprintf(buf, BUFSIZ, "Authorization: Basic %s\r\n", base64_encode(buf));
	strcat(msg, buf);
    }
    if (keep_alive) {
	if (port != 80)
	    snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n");
	else
	    snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n");
	strcat(msg, buf);
    }
    strcat(msg, extra_hdrs);
    snprintf(buf, BUFSIZ, "\r\n");
    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 = catchSignal;
	    sa.sa_flags = 0;
	    sigemptyset(&sa.sa_mask);
	    (void) sigaction(SIGINT, &sa, NULL);
	}
#else
	void (*osig) ();
	if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL)
	    (void) signal(SIGINT, osig);
#endif
    }
    loops = ping ? pcount : 1;
    for (i = 0; loops == 0 || i < loops; i++) {
	squid_off_t fsize = 0;
	/* Connect to the server */
	if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
	    perror("client: socket");
	    exit(1);
	}
	if (localhost && client_comm_bind(conn, localhost) < 0) {
	    perror("client: bind");
	    exit(1);
	}
	if (client_comm_connect(conn, hostname, port, (ping || opt_verbose) ? &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 = mywrite(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?: %s\n", msg);
	    exit(1);
	}
	if (put_file) {
	    int x;
	    lseek(put_fd, 0, SEEK_SET);
#ifdef _SQUID_MSWIN_
	    while ((x = read(put_fd, buf, sizeof(buf))) > 0) {
#else
	    while ((x = myread(put_fd, buf, sizeof(buf))) > 0) {
#endif
		x = mywrite(conn, buf, x);
		total_bytes += x;
		if (x <= 0)
		    break;
	    }
	    if (x != 0)
		fprintf(stderr, "client: ERROR: Cannot send file.\n");
	}
	/* Read the data */

#ifdef _SQUID_MSWIN_
	setmode(1, O_BINARY);
#endif
	while ((len = myread(conn, buf, sizeof(buf))) > 0) {
	    fsize += len;
	    if (to_stdout)
		fwrite(buf, len, 1, stdout);
	}
#ifdef _SQUID_MSWIN_
	setmode(1, O_TEXT);
#endif
	(void) close(conn);	/* done with socket */

	if (interrupted)
	    break;

	if (ping || opt_verbose) {
	    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 secs, %f KB/s (%" PRINTF_OFF_T "KB)\n",
		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,
		elapsed_msec ? (double) fsize / elapsed_msec * 1000 / 1024 : -1.0,
		(fsize + 1023) / 1024);
	    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 (ping && (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.%03ld\n", 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_bind(int sock, const char *local_host)
{
    static const struct hostent *hp = NULL;
    static struct sockaddr_in from_addr;

    /* Set up the source socket address from which to send. */
    if (hp == NULL) {
	from_addr.sin_family = AF_INET;

	if ((hp = gethostbyname(local_host)) == 0) {
	    return (-1);
	}
	xmemcpy(&from_addr.sin_addr, hp->h_addr, hp->h_length);
	from_addr.sin_port = 0;
    }
    return bind(sock, (struct sockaddr *) &from_addr, sizeof(struct sockaddr_in));
}

static int
client_comm_connect(int sock, const 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
catchSignal(int sig)
{
    interrupted = 1;
    fprintf(stderr, "Interrupted.\n");
}
예제 #8
0
static void
netdbReloadState(void)
{
    char *buf;
    char *t;
    char *s;
    int fd;
    int l;
    struct stat sb;
    netdbEntry *n;
    netdbEntry N;
    struct in_addr addr;
    int count = 0;
    struct timeval start = current_time;

    if (strcmp(Config.netdbFilename, "none") == 0)
        return;

    /*
     * This was nicer when we were using stdio, but thanks to
     * Solaris bugs, its a bad idea.  fopen can fail if more than
     * 256 FDs are open.
     */
    fd = file_open(Config.netdbFilename, O_RDONLY | O_BINARY);
    if (fd < 0)
        return;
    if (fstat(fd, &sb) < 0) {
        file_close(fd);
        return;
    }
    t = buf = xcalloc(1, (size_t) sb.st_size + 1);
    l = FD_READ_METHOD(fd, buf, (int) sb.st_size);
    file_close(fd);
    if (l <= 0)
        return;
    while ((s = strchr(t, '\n'))) {
        char *q;
        assert(s - buf < l);
        *s = '\0';
        memset(&N, '\0', sizeof(netdbEntry));
        q = strtok(t, w_space);
        t = s + 1;
        if (NULL == q)
            continue;
        if (!safe_inet_addr(q, &addr))
            continue;
        if (netdbLookupAddr(addr) != NULL)	/* no dups! */
            continue;
        if ((q = strtok(NULL, w_space)) == NULL)
            continue;
        N.pings_sent = atoi(q);
        if ((q = strtok(NULL, w_space)) == NULL)
            continue;
        N.pings_recv = atoi(q);
        if (N.pings_recv == 0)
            continue;
        /* give this measurement low weight */
        N.pings_sent = 1;
        N.pings_recv = 1;
        if ((q = strtok(NULL, w_space)) == NULL)
            continue;
        N.hops = atof(q);
        if ((q = strtok(NULL, w_space)) == NULL)
            continue;
        N.rtt = atof(q);
        if ((q = strtok(NULL, w_space)) == NULL)
            continue;
        N.next_ping_time = (time_t) atoi(q);
        if ((q = strtok(NULL, w_space)) == NULL)
            continue;
        N.last_use_time = (time_t) atoi(q);
        n = memAllocate(MEM_NETDBENTRY);
        xmemcpy(n, &N, sizeof(netdbEntry));
        netdbHashInsert(n, addr);
        while ((q = strtok(NULL, w_space)) != NULL) {
            if (netdbLookupHost(q) != NULL)	/* no dups! */
                continue;
            netdbHostInsert(n, q);
        }
        count++;
    }
    xfree(buf);
    getCurrentTime();
    debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n",
                  count, tvSubMsec(start, current_time));
}