Ejemplo n.º 1
0
static void
idnsSendTcpQueryDone(int fd, char *bufnotused, size_t size, int errflag, void *data)
{
	idns_query *q = data;
	if (size > 0)
		fd_bytes(fd, size, FD_WRITE);
	if (errflag == COMM_ERR_CLOSING)
		return;
	if (errflag)
	{
		idnsTcpCleanup(q);
		return;
	}
	commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0);
}
Ejemplo n.º 2
0
/*
 * Aborts with fatal message if write() returns something other
 * than its length argument.
 */
static void
logfileWriteWrapper(Logfile * lf, const void *buf, size_t len)
{
    l_stdio_t *ll = (l_stdio_t *) lf->data;
    size_t s;
    s = FD_WRITE_METHOD(ll->fd, (char const *) buf, len);
    fd_bytes(ll->fd, s, FD_WRITE);

    if (s == len)
	return;

    if (!lf->flags.fatal)
	return;

    fatalf("logfileWrite (stdio): %s: %s\n", lf->path, xstrerror());
}
Ejemplo n.º 3
0
static void
logfile_mod_udp_write(Logfile * lf, const char *buf, size_t len)
{
    l_udp_t *ll = (l_udp_t *) lf->data;
    ssize_t s;
    s = write(ll->fd, (char const *) buf, len);
    fd_bytes(ll->fd, s, FD_WRITE);
#if 0
    if (s < 0) {
        debug(1, 1) ("logfile (udp): got errno %d (%s)\n", errno, xstrerror());
    }
    if (s != len) {
        debug(1, 1) ("logfile (udp): len %d, wrote %d\n", len, s);
    }
#endif

    /* We don't worry about network errors for now */
}
Ejemplo n.º 4
0
/* Read from FD */
static void
diskHandleRead(int fd, void *data)
{
    dread_ctrl *ctrl_dat = data;
    fde *F = &fd_table[fd];
    int len;
    int rc = DISK_OK;
    /*
     * FD < 0 indicates premature close; we just have to free
     * the state data.
     */
    if (fd < 0) {
	memFree(ctrl_dat, MEM_DREAD_CTRL);
	return;
    }
    if (F->disk.offset != ctrl_dat->file_offset) {
	debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n",
	    fd, (int) ctrl_dat->file_offset);
	lseek(fd, ctrl_dat->file_offset, SEEK_SET);	/* XXX ignore return? */
	statCounter.syscalls.disk.seeks++;
	F->disk.offset = ctrl_dat->file_offset;
    }
    errno = 0;
    len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len);
    if (len > 0)
	F->disk.offset += len;
    statCounter.syscalls.disk.reads++;
    fd_bytes(fd, len, FD_READ);
    if (len < 0) {
	if (ignoreErrno(errno)) {
	    commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);
	    return;
	}
	debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror());
	len = 0;
	rc = DISK_ERROR;
    } else if (len == 0) {
	rc = DISK_EOF;
    }
    if (cbdataValid(ctrl_dat->client_data))
	ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data);
    cbdataUnlock(ctrl_dat->client_data);
    memFree(ctrl_dat, MEM_DREAD_CTRL);
}
Ejemplo n.º 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]++;
    }
Ejemplo n.º 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);
}
Ejemplo n.º 7
0
/* 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]++;
    }
Ejemplo n.º 8
0
static void
idnsSendQuery(idns_query * q)
{
	int x;
	int ns;
	if (DnsSocket < 0)
	{
		debug(78, 1) ("idnsSendQuery: Can't send query, no DNS socket!\n");
		return;
	}
	/* XXX Select nameserver */
	assert(nns > 0);
	assert(q->lru.next == NULL);
	assert(q->lru.prev == NULL);
	idnsTcpCleanup(q);
try_again:
	ns = q->nsends % nns;
	x = comm_udp_sendto(DnsSocket,
						&nameservers[ns].S,
						sizeof(nameservers[ns].S),
						q->buf,
						q->sz);
	q->nsends++;
	q->queue_t = q->sent_t = current_time;
	if (x < 0)
	{
		debug(50, 1) ("idnsSendQuery: FD %d: sendto: %s\n",
					  DnsSocket, xstrerror());
		if (q->nsends % nns != 0)
			goto try_again;
	}
	else
	{
		fd_bytes(DnsSocket, x, FD_WRITE);
		commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0);
	}
	nameservers[ns].nqueries++;
	dlinkAdd(q, &q->lru, &lru_list);
	idnsTickleQueue();
}
Ejemplo n.º 9
0
/* Writes data from the server buffer to the client side */
static void
sslWriteClient(int fd, void *data)
{
    SslStateData *sslState = data;
    int len;
    assert(fd == sslState->client.fd);
    debug(26, 3) ("sslWriteClient: FD %d, %d bytes to write\n",
	fd, sslState->server.len);
    Counter.syscalls.sock.writes++;
    len = write(fd,
	sslState->server.buf,
	sslState->server.len);
    debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_WRITE);
	kb_incr(&Counter.client_http.kbytes_out, len);
	assert(len <= sslState->server.len);
	sslState->server.len -= len;
	/* increment total object size */
	if (sslState->size_ptr)
	    *sslState->size_ptr += len;
	if (sslState->server.len > 0) {
	    /* we didn't write the whole thing */
	    xmemmove(sslState->server.buf,
		sslState->server.buf + len,
		sslState->server.len);
	}
    }
    cbdataLock(sslState);
    if (len < 0) {
	debug(50, ignoreErrno(errno) ? 3 : 1)
	    ("sslWriteClient: FD %d: write failure: %s.\n", fd, xstrerror());
	if (!ignoreErrno(errno))
	    comm_close(fd);
    }
    if (cbdataValid(sslState))
	sslSetSelect(sslState);
    cbdataUnlock(sslState);
}
Ejemplo n.º 10
0
static void
identReadReply(int fd, void *data)
{
	IdentStateData *state = data;
	LOCAL_ARRAY(char, buf, BUFSIZ);
	char *ident = NULL;
	char *t = NULL;
	int len = -1;
	buf[0] = '\0';
	statCounter.syscalls.sock.reads++;
	len = FD_READ_METHOD(fd, buf, BUFSIZ - 1);
	fd_bytes(fd, len, FD_READ);
	if (len <= 0)
	{
		comm_close(fd);
		return;
	}
	/*
	 * XXX This isn't really very tolerant. It should read until EOL
	 * or EOF and then decode the answer... If the reply is fragmented
	 * then this will fail
	 */
	buf[len] = '\0';
	if ((t = strchr(buf, '\r')))
		*t = '\0';
	if ((t = strchr(buf, '\n')))
		*t = '\0';
	debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
	if (strstr(buf, "USERID"))
	{
		if ((ident = strrchr(buf, ':')))
		{
			while (xisspace(*++ident));
			identCallback(state, ident);
		}
	}
	comm_close(fd);
}
Ejemplo n.º 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);
}
Ejemplo n.º 12
0
static void
idnsReadTcp(int fd, void *data)
{
	ssize_t n;
	idns_query *q = data;
	int ns = (q->nsends - 1) % nns;
	if (!q->tcp_buffer)
		q->tcp_buffer = memAllocBuf(1024, &q->tcp_buffer_size);
	statCounter.syscalls.sock.reads++;
	n = FD_READ_METHOD(q->tcp_socket, q->tcp_buffer + q->tcp_buffer_offset, q->tcp_buffer_size - q->tcp_buffer_offset);
	if (n < 0 && ignoreErrno(errno))
	{
		commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0);
		return;
	}
	if (n <= 0)
	{
		debug(78, 1) ("idnsReadTcp: Short response from nameserver %d for %s.\n", ns + 1, q->name);
		idnsTcpCleanup(q);
		return;
	}
	fd_bytes(fd, n, FD_READ);
	q->tcp_buffer_offset += n;
	if (q->tcp_buffer_offset > 2)
	{
		unsigned short response_size = ntohs(*(short *) q->tcp_buffer);
		if (q->tcp_buffer_offset >= response_size + 2)
		{
			nameservers[ns].nreplies++;
			idnsGrokReply(q->tcp_buffer + 2, response_size);
			return;
		}
		if (q->tcp_buffer_size < response_size + 2)
			q->tcp_buffer = memReallocBuf(q->tcp_buffer, response_size + 2, &q->tcp_buffer_size);
	}
	commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0);
}
Ejemplo n.º 13
0
/* write handler */
static void
diskHandleWrite(int fd, void *notused)
{
    int len = 0;
    fde *F = &fd_table[fd];
    struct _fde_disk *fdd = &F->disk;
    dwrite_q *q = fdd->write_q;
    int status = DISK_OK;
    int do_callback;
    int do_close;
    if (NULL == q)
	return;
    debug(6, 3) ("diskHandleWrite: FD %d\n", fd);
    F->flags.write_daemon = 0;
    assert(fdd->write_q != NULL);
    assert(fdd->write_q->len > fdd->write_q->buf_offset);
    debug(6, 3) ("diskHandleWrite: FD %d writing %d bytes\n",
	fd, (int) (fdd->write_q->len - fdd->write_q->buf_offset));
    errno = 0;
    if (fdd->write_q->file_offset != -1)
	lseek(fd, fdd->write_q->file_offset, SEEK_SET);
    len = FD_WRITE_METHOD(fd,
	fdd->write_q->buf + fdd->write_q->buf_offset,
	fdd->write_q->len - fdd->write_q->buf_offset);
    debug(6, 3) ("diskHandleWrite: FD %d len = %d\n", fd, len);
    statCounter.syscalls.disk.writes++;
    fd_bytes(fd, len, FD_WRITE);
    if (len < 0) {
	if (!ignoreErrno(errno)) {
	    status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
	    debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n",
		fd, xstrerror());
	    /*
	     * If there is no write callback, then this file is
	     * most likely something important like a log file, or
	     * an interprocess pipe.  Its not a swapfile.  We feel
	     * that a write failure on a log file is rather important,
	     * and Squid doesn't otherwise deal with this condition.
	     * So to get the administrators attention, we exit with
	     * a fatal message.
	     */
	    if (fdd->wrt_handle == NULL)
		fatal("Write failure -- check your disk space and cache.log");
	    /*
	     * If there is a write failure, then we notify the
	     * upper layer via the callback, at the end of this
	     * function.  Meanwhile, flush all pending buffers
	     * here.  Let the upper layer decide how to handle the
	     * failure.  This will prevent experiencing multiple,
	     * repeated write failures for the same FD because of
	     * the queued data.
	     */
	    do {
		fdd->write_q = q->next;
		if (q->free_func)
		    (q->free_func) (q->buf);
		if (q) {
		    memFree(q, MEM_DWRITE_Q);
		    q = NULL;
		}
	    } while ((q = fdd->write_q));
	}
	len = 0;
    }
    if (q != NULL) {
	/* q might become NULL from write failure above */
	q->buf_offset += len;
	if (q->buf_offset > q->len)
	    debug(50, 1) ("diskHandleWrite: q->buf_offset > q->len (%p,%d, %d, %d FD %d)\n",
		q, (int) q->buf_offset, (int) q->len, len, fd);
	assert(q->buf_offset <= q->len);
	if (q->buf_offset == q->len) {
	    /* complete write */
	    fdd->write_q = q->next;
	    if (q->free_func)
		(q->free_func) (q->buf);
	    if (q) {
		memFree(q, MEM_DWRITE_Q);
		q = NULL;
	    }
	}
    }
    if (fdd->write_q == NULL) {
	/* no more data */
	fdd->write_q_tail = NULL;
    } else {
	/* another block is queued */
	diskCombineWrites(fdd);
	cbdataLock(fdd->wrt_handle_data);
	commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
	F->flags.write_daemon = 1;
    }
    do_close = F->flags.close_request;
    if (fdd->wrt_handle) {
	if (fdd->wrt_handle_data == NULL)
	    do_callback = 1;
	else if (cbdataValid(fdd->wrt_handle_data))
	    do_callback = 1;
	else
	    do_callback = 0;
	if (fdd->wrt_handle_data != NULL)
	    cbdataUnlock(fdd->wrt_handle_data);
	if (do_callback) {
	    fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data);
	    /*
	     * NOTE, this callback can close the FD, so we must
	     * not touch 'F', 'fdd', etc. after this.
	     */
	    return;
	}
    }
    if (do_close)
	file_close(fd);
}
Ejemplo n.º 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
    }
}
Ejemplo n.º 15
0
static void
idnsRead(int fd, void *data)
{
	int *N = &incoming_sockets_accepted;
	ssize_t len;
	struct sockaddr_in from;
	socklen_t from_len;
	int max = INCOMING_DNS_MAX;
	static char rbuf[SQUID_UDP_SO_RCVBUF];
	int ns;
	while (max--)
	{
		from_len = sizeof(from);
		memset(&from, '\0', from_len);
		statCounter.syscalls.sock.recvfroms++;
		len = recvfrom(fd, rbuf, sizeof(rbuf), 0, (struct sockaddr *) &from, &from_len);
		if (len == 0)
			break;
		if (len < 0)
		{
			if (ignoreErrno(errno))
				break;
#ifdef _SQUID_LINUX_
			/* Some Linux systems seem to set the FD for reading and then
			 * return ECONNREFUSED when sendto() fails and generates an ICMP
			 * port unreachable message. */
			/* or maybe an EHOSTUNREACH "No route to host" message */
			if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
#endif
				debug(50, 1) ("idnsRead: FD %d recvfrom: %s\n",
							  fd, xstrerror());
			break;
		}
		fd_bytes(DnsSocket, len, FD_READ);
		assert(N);
		(*N)++;
		debug(78, 3) ("idnsRead: FD %d: received %d bytes from %s.\n",
					  fd,
					  (int) len,
					  inet_ntoa(from.sin_addr));
		ns = idnsFromKnownNameserver(&from);
		if (ns >= 0)
		{
			nameservers[ns].nreplies++;
		}
		else if (Config.onoff.ignore_unknown_nameservers)
		{
			static time_t last_warning = 0;
			if (squid_curtime - last_warning > 60)
			{
				debug(78, 1) ("WARNING: Reply from unknown nameserver [%s]\n",
							  inet_ntoa(from.sin_addr));
				last_warning = squid_curtime;
			}
			continue;
		}
		idnsGrokReply(rbuf, len);
	}
	if (lru_list.head)
		commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0);
}