示例#1
0
void
clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, squid_off_t size)
{
    const char *key;
    ClientInfo *c;
    if (!Config.onoff.client_db)
	return;
    key = xinet_ntoa(addr);
    c = (ClientInfo *) hash_lookup(client_table, key);
    if (c == NULL)
	c = clientdbAdd(addr);
    if (c == NULL)
	debug_trap("clientdbUpdate: Failed to add entry");
    if (p == PROTO_HTTP) {
	c->Http.n_requests++;
	c->Http.result_hist[ltype]++;
	kb_incr(&c->Http.kbytes_out, size);
	if (isTcpHit(ltype))
	    kb_incr(&c->Http.hit_kbytes_out, size);
    } else if (p == PROTO_ICP) {
	c->Icp.n_requests++;
	c->Icp.result_hist[ltype]++;
	kb_incr(&c->Icp.kbytes_out, size);
	if (LOG_UDP_HIT == ltype)
	    kb_incr(&c->Icp.hit_kbytes_out, size);
    }
    c->last_seen = squid_curtime;
}
示例#2
0
/* free fetch state structures
 * must be called only when fetch cbdata is valid */
static void
peerDigestFetchFinish(DigestFetchState * fetch, int err)
{
    assert(fetch->entry && fetch->request);

    if (fetch->old_entry) {
	debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n");
	storeUnregister(fetch->old_entry, fetch);
	storeReleaseRequest(fetch->old_entry);
	storeUnlockObject(fetch->old_entry);
	fetch->old_entry = NULL;
    }
    /* update global stats */
    kb_incr(&Counter.cd.kbytes_sent, (size_t) fetch->sent.bytes);
    kb_incr(&Counter.cd.kbytes_recv, (size_t) fetch->recv.bytes);
    Counter.cd.msgs_sent += fetch->sent.msg;
    Counter.cd.msgs_recv += fetch->recv.msg;

    /* unlock everything */
    storeUnregister(fetch->entry, fetch);
    storeUnlockObject(fetch->entry);
    requestUnlink(fetch->request);
    fetch->entry = NULL;
    fetch->request = NULL;
    assert(fetch->pd == NULL);
    cbdataUnlock(fetch);
    cbdataFree(fetch);
}
static void
whoisReadReply(int fd, void *data)
{
    WhoisState *p = data;
    StoreEntry *entry = p->entry;
    char *buf = memAllocate(MEM_4K_BUF);
    MemObject *mem = entry->mem_obj;
    int len;
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, 4095);
    buf[len] = '\0';
    debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len);
    debug(75, 5) ("{%s}\n", buf);
    if (len > 0) {
	if (0 == mem->inmem_hi) {
	    http_reply *reply = mem->reply;
	    http_version_t version;
	    storeBuffer(entry);
	    httpBuildVersion(&version, 1, 0);
	    httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2);
	    httpReplySwapOut(reply, entry);
	}
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.http.kbytes_in, len);
	storeAppend(entry, buf, len);
	storeBufferFlush(entry);
	commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
    } else if (len < 0) {
	debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
	} else {
	    ErrorState *err;
	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, p->fwd->request);
	    err->xerrno = errno;
	    fwdFail(p->fwd, err);
	    comm_close(fd);
	}
    } else {
	storeTimestampsSet(entry);
	storeBufferFlush(entry);
	if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
	    storeSetPublicKey(entry);
	fwdComplete(p->fwd);
	debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry));
	comm_close(fd);
    }
    memFree(buf, MEM_4K_BUF);
}
示例#4
0
/* Read from client side and queue it for writing to the server */
static void
sslReadClient(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    assert(fd == sslState->client.fd);
    debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %d\n",
	fd, SQUID_TCP_SO_RCVBUF - sslState->client.len,
	sslState->client.len);
    Counter.syscalls.sock.reads++;
    len = read(fd,
	sslState->client.buf + sslState->client.len,
	SQUID_TCP_SO_RCVBUF - sslState->client.len);
    debug(26, 3) ("sslReadClient: FD %d, read   %d bytes\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
	kb_incr(&Counter.client_http.kbytes_in, len);
	sslState->client.len += len;
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ECONNRESET == errno ? 3 : 1) ("sslReadClient: FD %d: read failure: %s\n",
	    fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    } else if (len == 0) {
	comm_close(fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
示例#5
0
/* This will be called when data is ready to be read from fd.  Read until
 * error or connection closed. */
static void
gopherReadReply(int fd, void *data)
{
    GopherStateData *gopherState = data;
    StoreEntry *entry = gopherState->entry;
    char *buf = NULL;
    int len;
    int clen;
    int bin;
    size_t read_sz;
#if DELAY_POOLS
    delay_id delay_id;
#endif
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    buf = memAllocate(MEM_4K_BUF);
    read_sz = 4096 - 1;		/* leave room for termination */
#if DELAY_POOLS
    delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
#endif
    /* leave one space for \0 in gopherToHTML */
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, read_sz);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
#if DELAY_POOLS
	delayBytesIn(delay_id, len);
#endif
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.other.kbytes_in, len);
    }
    debug(10, 5) ("gopherReadReply: FD %d read len=%d\n", fd, len);
    if (len > 0) {
	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
	IOStats.Gopher.reads++;
	for (clen = len - 1, bin = 0; clen; bin++)
	    clen >>= 1;
	IOStats.Gopher.read_hist[bin]++;
    }
示例#6
0
static void
whoisReadReply(int fd, void *data)
{
    WhoisState *p = data;
    StoreEntry *entry = p->entry;
    char *buf = memAllocate(MEM_4K_BUF);
    MemObject *mem = entry->mem_obj;
    int len;
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, 4095);
    buf[len] = '\0';
    debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len);
    debug(75, 5) ("{%s}\n", buf);
    if (len > 0) {
	if (0 == mem->inmem_hi)
	    mem->reply->sline.status = HTTP_OK;
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.http.kbytes_in, len);
	storeAppend(entry, buf, len);
	commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
    } else if (len < 0) {
	debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
	} else if (mem->inmem_hi == 0) {
	    ErrorState *err;
	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
	    err->xerrno = errno;
	    fwdFail(p->fwd, err);
	    comm_close(fd);
	} else {
	    comm_close(fd);
	}
    } else {
	fwdComplete(p->fwd);
	debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry));
	comm_close(fd);
    }
    memFree(buf, MEM_4K_BUF);
}
示例#7
0
/*
 * copied from httpReadReply()
 *
 * by the time this is called, the ICAP headers have already
 * been read.
 */
void
icapReadReply(int fd, void *data)
{
    IcapStateData *icap = data;
    StoreEntry *entry = icap->respmod.entry;
    const request_t *request = icap->request;
    int len;
    debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data);
    if (icap->flags.no_content && !icap->flags.http_server_eof) {	//AI

	return;
    }
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    statCounter.syscalls.sock.reads++;
    len = memBufRead(fd, &icap->chunk_buf);
    debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.icap.all.kbytes_in, len);
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	if (icap->chunk_buf.size < icap->chunk_buf.capacity) {
	    *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0';
	    debug(81, 9) ("{%s}\n", icap->chunk_buf.buf);
	}
    }
    if (len <= 0) {
	debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd);
	    commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
	} else if (entry->mem_obj->inmem_hi == 0) {
	    ErrorState *err;
	    debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd);
	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	    err->request = requestLink((request_t *) request);
	    err->xerrno = errno;
	    errorAppendEntry(entry, err);
	    comm_close(fd);
	} else {
	    debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n",
		fd);
	    comm_close(fd);
	}
	return;
    }
    if (icapReadReply2(icap) < 0)
	comm_close(fd);
}
示例#8
0
/* destroys digest if peer disappeared
 * must be called only when fetch and pd cbdata are valid */
static void
peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err)
{
    PeerDigest *pd = fetch->pd;
    const char *host = strBuf(pd->host);

    pd->times.received = squid_curtime;
    pd->times.req_delay = fetch->resp_time;
    kb_incr(&pd->stats.sent.kbytes, (size_t) fetch->sent.bytes);
    kb_incr(&pd->stats.recv.kbytes, (size_t) fetch->recv.bytes);
    pd->stats.sent.msgs += fetch->sent.msg;
    pd->stats.recv.msgs += fetch->recv.msg;

    if (err) {
	debug(72, 1) ("%sdisabling (%s) digest from %s\n",
	    pcb_valid ? "temporary " : "",
	    pd->req_result, host);

	if (pd->cd) {
	    cacheDigestDestroy(pd->cd);
	    pd->cd = NULL;
	}
	pd->flags.usable = 0;

	if (!pcb_valid)
	    peerDigestNotePeerGone(pd);
    } else {
	assert(pcb_valid);

	pd->flags.usable = 1;

	/* XXX: ugly condition, but how? */
	if (fetch->entry->store_status == STORE_OK)
	    debug(72, 2) ("re-used old digest from %s\n", host);
	else
	    debug(72, 2) ("received valid digest from %s\n", host);
    }
    fetch->pd = NULL;
    cbdataUnlock(pd);
}
/* This will be called when data is ready to be read from fd.  Read until
 * error or connection closed. */
static void
waisReadReply(int fd, void *data)
{
    WaisStateData *waisState = data;
    LOCAL_ARRAY(char, buf, 4096);
    StoreEntry *entry = waisState->entry;
    int len;
    int clen;
    int bin;
    size_t read_sz;
#if DELAY_POOLS
    delay_id delay_id;
#endif
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    read_sz = 4096;
#if DELAY_POOLS
    delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
#endif
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, read_sz);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
#if DELAY_POOLS
	delayBytesIn(delay_id, len);
#endif
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.other.kbytes_in, len);
    }
    debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, len);
    if (len > 0) {
	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
	IOStats.Wais.reads++;
	for (clen = len - 1, bin = 0; clen; bin++)
	    clen >>= 1;
	IOStats.Wais.read_hist[bin]++;
    }
示例#10
0
static void
icpCount(void *buf, int which, size_t len, int delay)
{
    icp_common_t *icp = buf;
    if (len < sizeof(*icp))
	return;
    if (SENT == which) {
	statCounter.icp.pkts_sent++;
	kb_incr(&statCounter.icp.kbytes_sent, len);
	if (ICP_QUERY == icp->opcode) {
	    statCounter.icp.queries_sent++;
	    kb_incr(&statCounter.icp.q_kbytes_sent, len);
	} else {
	    statCounter.icp.replies_sent++;
	    kb_incr(&statCounter.icp.r_kbytes_sent, len);
	    /* this is the sent-reply service time */
	    statHistCount(&statCounter.icp.reply_svc_time, delay);
	}
	if (ICP_HIT == icp->opcode)
	    statCounter.icp.hits_sent++;
    } else if (RECV == which) {
	statCounter.icp.pkts_recv++;
	kb_incr(&statCounter.icp.kbytes_recv, len);
	if (ICP_QUERY == icp->opcode) {
	    statCounter.icp.queries_recv++;
	    kb_incr(&statCounter.icp.q_kbytes_recv, len);
	} else {
	    statCounter.icp.replies_recv++;
	    kb_incr(&statCounter.icp.r_kbytes_recv, len);
	    /* statCounter.icp.query_svc_time set in clientUpdateCounters */
	}
	if (ICP_HIT == icp->opcode)
	    statCounter.icp.hits_recv++;
    }
}
示例#11
0
/* Read from server side and queue it for writing to the client */
static void
sslReadServer(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    size_t read_sz = SQUID_TCP_SO_RCVBUF - sslState->server.len;
    assert(fd == sslState->server.fd);
    debug(26, 3) ("sslReadServer: FD %d, reading %d bytes at offset %d\n",
	fd, read_sz, sslState->server.len);
    errno = 0;
#if DELAY_POOLS
    read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
#endif
    Counter.syscalls.sock.reads++;
    len = read(fd, sslState->server.buf + sslState->server.len, read_sz);
    debug(26, 3) ("sslReadServer: FD %d, read   %d bytes\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
#if DELAY_POOLS
	delayBytesIn(sslState->delay_id, len);
#endif
	kb_incr(&Counter.server.all.kbytes_in, len);
	kb_incr(&Counter.server.other.kbytes_in, len);
	sslState->server.len += len;
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ignoreErrno(errno) ? 3 : 1)
	    ("sslReadServer: FD %d: read failure: %s\n", fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    } else if (len == 0) {
	comm_close(sslState->server.fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
示例#12
0
/* Writes data from the client buffer to the server side */
static void
sslWriteServer(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    assert(fd == sslState->server.fd);
    debug(26, 3) ("sslWriteServer: FD %d, %d bytes to write\n",
	fd, sslState->client.len);
    Counter.syscalls.sock.writes++;
    len = write(fd,
	sslState->client.buf,
	sslState->client.len);
    debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_WRITE);
	kb_incr(&Counter.server.all.kbytes_out, len);
	kb_incr(&Counter.server.other.kbytes_out, len);
	assert(len <= sslState->client.len);
	sslState->client.len -= len;
	if (sslState->client.len > 0) {
	    /* we didn't write the whole thing */
	    xmemmove(sslState->client.buf,
		sslState->client.buf + len,
		sslState->client.len);
	}
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ignoreErrno(errno) ? 3 : 1)
	    ("sslWriteServer: FD %d: write failure: %s.\n", fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
示例#13
0
static int
peerDigestSetCBlock(PeerDigest * pd, const char *buf)
{
    StoreDigestCBlock cblock;
    int freed_size = 0;
    const char *host = strBuf(pd->host);

    xmemcpy(&cblock, buf, sizeof(cblock));
    /* network -> host conversions */
    cblock.ver.current = ntohs(cblock.ver.current);
    cblock.ver.required = ntohs(cblock.ver.required);
    cblock.capacity = ntohl(cblock.capacity);
    cblock.count = ntohl(cblock.count);
    cblock.del_count = ntohl(cblock.del_count);
    cblock.mask_size = ntohl(cblock.mask_size);
    debug(72, 2) ("got digest cblock from %s; ver: %d (req: %d)\n",
	host, (int) cblock.ver.current, (int) cblock.ver.required);
    debug(72, 2) ("\t size: %d bytes, e-cnt: %d, e-util: %d%%\n",
	cblock.mask_size, cblock.count,
	xpercentInt(cblock.count, cblock.capacity));
    /* check version requirements (both ways) */
    if (cblock.ver.required > CacheDigestVer.current) {
	debug(72, 1) ("%s digest requires version %d; have: %d\n",
	    host, cblock.ver.required, CacheDigestVer.current);
	return 0;
    }
    if (cblock.ver.current < CacheDigestVer.required) {
	debug(72, 1) ("%s digest is version %d; we require: %d\n",
	    host, cblock.ver.current, CacheDigestVer.required);
	return 0;
    }
    /* check consistency */
    if (cblock.ver.required > cblock.ver.current ||
	cblock.mask_size <= 0 || cblock.capacity <= 0 ||
	cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) {
	debug(72, 0) ("%s digest cblock is corrupted.\n", host);
	return 0;
    }
    /* check consistency further */
    if (cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) {
	debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n",
	    host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry));
	return 0;
    }
    /* there are some things we cannot do yet */
    if (cblock.hash_func_count != CacheDigestHashFuncCount) {
	debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n",
	    host, cblock.hash_func_count, CacheDigestHashFuncCount);
	return 0;
    }
    /*
     * no cblock bugs below this point
     */
    /* check size changes */
    if (pd->cd && cblock.mask_size != pd->cd->mask_size) {
	debug(72, 2) ("%s digest changed size: %d -> %d\n",
	    host, cblock.mask_size, pd->cd->mask_size);
	freed_size = pd->cd->mask_size;
	cacheDigestDestroy(pd->cd);
	pd->cd = NULL;
    }
    if (!pd->cd) {
	debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n",
	    host, cblock.mask_size, (int) (cblock.mask_size - freed_size));
	pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry);
	if (cblock.mask_size >= freed_size)
	    kb_incr(&Counter.cd.memory, cblock.mask_size - freed_size);
    }
    assert(pd->cd);
    /* these assignments leave us in an inconsistent state until we finish reading the digest */
    pd->cd->count = cblock.count;
    pd->cd->del_count = cblock.del_count;
    return 1;
}
示例#14
0
static void
icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag,
    void *data)
{
    IcapStateData *icap = data;
    ErrorState *err;

    icap->flags.write_pending = 0;
    debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n",
	fd, size, errflag);
    if (size > 0) {
	fd_bytes(fd, size, FD_WRITE);
	kb_incr(&statCounter.icap.all.kbytes_out, size);
    }
    if (errflag == COMM_ERR_CLOSING)
	return;
    if (errflag) {
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->xerrno = errno;
	if (cbdataValid(icap))
	    err->request = requestLink(icap->request);
	storeEntryReset(icap->respmod.entry);
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    }
    if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) {
        debug(81, 3) ("icapSendRespModDone: Entry Aborded\n");	
	comm_close(fd);
	return;
    }
    if (icap->flags.send_zero_chunk) {
	debug(81,
	    3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n");
	icap->flags.send_zero_chunk = 0;
	icapSendRespMod(icap, NULL, 0, 1);
	return;
    }
    if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) {
	/* Schedule reading the ICAP response */
	debug(81,
	    3)
	    ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n",
	    fd);
	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
#if 1
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
#else
	if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
	    /*
	     * Set the read timeout only after all data has been sent
	     * or we are waiting for a preview response
	     * If the ICAP server does not return any data till all data
	     * has been sent, we are likely to hit the timeout for large
	     * HTTP bodies
	     */
	    commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	}
#endif
    }
}