static void *
varnish_thread(void *priv)
{
	struct varnish *v;
	char buf[BUFSIZ];
	struct pollfd *fds, fd;
	int i;

	CAST_OBJ_NOTNULL(v, priv, VARNISH_MAGIC);
	(void)VTCP_nonblocking(v->fds[0]);
	while (1) {
		fds = &fd;
		memset(fds, 0, sizeof *fds);
		fds->fd = v->fds[0];
		fds->events = POLLIN;
		i = poll(fds, 1, 1000);
		if (i == 0)
			continue;
		if (fds->revents & (POLLERR|POLLHUP))
			break;
		i = read(v->fds[0], buf, sizeof buf - 1);
		if (i <= 0)
			break;
		buf[i] = '\0';
		vtc_dump(v->vl, 3, "debug", buf, -2);
	}
	return (NULL);
}
示例#2
0
int
VTCP_connect(const struct suckaddr *name, int msec)
{
	int s, i;
	struct pollfd fds[1];
	const struct sockaddr *sa;
	socklen_t sl;
	int val;

	if (name == NULL)
		return (-1);
	/* Attempt the connect */
	AN(VSA_Sane(name));
	sa = VSA_Get_Sockaddr(name, &sl);
	AN(sa);
	AN(sl);

	s = socket(sa->sa_family, SOCK_STREAM, 0);
	if (s < 0)
		return (s);

	/* Set the socket non-blocking */
	if (msec != 0)
		(void)VTCP_nonblocking(s);

	val = 1;
	AZ(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val));

	i = connect(s, sa, sl);
	if (i == 0)
		return (s);
	if (errno != EINPROGRESS) {
		AZ(close(s));
		return (-1);
	}

	if (msec < 0) {
		/*
		 * Caller is responsible for waiting and
		 * calling VTCP_connected
		 */
		return (s);
	}

	assert(msec > 0);
	/* Exercise our patience, polling for write */
	fds[0].fd = s;
	fds[0].events = POLLWRNORM;
	fds[0].revents = 0;
	i = poll(fds, 1, msec);

	if (i == 0) {
		/* Timeout, close and give up */
		AZ(close(s));
		errno = ETIMEDOUT;
		return (-1);
	}

	return (VTCP_connected(s));
}
示例#3
0
void *
vtc_record(struct vtclog *vl, int fd, struct vsb *vsb)
{
	char buf[65536];
	struct pollfd fds[1];
	int i;

	(void)VTCP_nonblocking(fd);
	while (1) {
		memset(fds, 0, sizeof fds);
		fds->fd = fd;
		fds->events = POLLIN;
		i = poll(fds, 1, 10000);
		if (i == 0)
			continue;
		if (fds->revents & POLLIN) {
			i = read(fd, buf, sizeof buf - 1);
			if (i > 0) {
				if (vsb != NULL)
					VSB_bcat(vsb, buf, i);
				buf[i] = '\0';
				vtc_dump(vl, 3, "debug", buf, -2);
			}
		}
		if (fds->revents & (POLLERR|POLLHUP)) {
			vtc_log(vl, 4, "STDOUT poll 0x%x", fds->revents);
			break;
		}
	}
	return (NULL);
}
示例#4
0
int
VTCP_connect(int s, const struct suckaddr *name, int msec)
{
	int i, k;
	socklen_t l;
	struct pollfd fds[1];
	const struct sockaddr *sa;
	socklen_t sl;

	assert(s >= 0);

	/* Set the socket non-blocking */
	if (msec > 0)
		(void)VTCP_nonblocking(s);

	/* Attempt the connect */
	AN(VSA_Sane(name));
	sa = VSA_Get_Sockaddr(name, &sl);
	i = connect(s, sa, sl);
	if (i == 0 || errno != EINPROGRESS)
		return (i);

	assert(msec > 0);
	/* Exercise our patience, polling for write */
	fds[0].fd = s;
	fds[0].events = POLLWRNORM;
	fds[0].revents = 0;
	i = poll(fds, 1, msec);

	if (i == 0) {
		/* Timeout, close and give up */
		errno = ETIMEDOUT;
		return (-1);
	}

	/* Find out if we got a connection */
	l = sizeof k;
	AZ(getsockopt(s, SOL_SOCKET, SO_ERROR, &k, &l));

	/* An error means no connection established */
	errno = k;
	if (k)
		return (-1);

	(void)VTCP_blocking(s);
	return (0);
}
示例#5
0
/*
 * Connect to the socket specified by the address info in va.
 * Return the socket.
 */
int
VSS_connect(const struct vss_addr *va, int nonblock)
{
	int sd, i;

	sd = socket(va->va_family, va->va_socktype, va->va_protocol);
	if (sd < 0) {
		if (errno != EPROTONOSUPPORT)
			perror("socket()");
		return (-1);
	}
	if (nonblock)
		(void)VTCP_nonblocking(sd);
	i = connect(sd, (const void *)&va->va_addr, va->va_addrlen);
	if (i == 0 || (nonblock && errno == EINPROGRESS))
		return (sd);
	perror("connect()");
	(void)close(sd);
	return (-1);
}
示例#6
0
void
SES_Wait(struct sess *sp, const struct transport *xp)
{
	struct pool *pp;
	struct waited *wp;

	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
	CHECK_OBJ_NOTNULL(xp, TRANSPORT_MAGIC);
	pp = sp->pool;
	CHECK_OBJ_NOTNULL(pp, POOL_MAGIC);
	assert(sp->fd > 0);
	/*
	 * XXX: waiter_epoll prevents us from zeroing the struct because
	 * XXX: it keeps state across calls.
	 */
	if (VTCP_nonblocking(sp->fd)) {
		SES_Delete(sp, SC_REM_CLOSE, NAN);
		return;
	}

	/*
	 * put struct waited on the workspace
	 */
	if (WS_Reserve(sp->ws, sizeof(struct waited))
	    < sizeof(struct waited)) {
		SES_Delete(sp, SC_OVERLOAD, NAN);
		return;
	}
	wp = (void*)sp->ws->f;
	INIT_OBJ(wp, WAITED_MAGIC);
	wp->fd = sp->fd;
	wp->priv1 = sp;
	wp->priv2 = (uintptr_t)xp;
	wp->idle = sp->t_idle;
	wp->func = ses_handle;
	wp->tmo = &cache_param->timeout_idle;
	if (Wait_Enter(pp->waiter, wp))
		SES_Delete(sp, SC_PIPE_OVERFLOW, NAN);
}
示例#7
0
void
SES_Wait(struct sess *sp)
{
	struct sesspool *pp;

	CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
	pp = sp->sesspool;
	CHECK_OBJ_NOTNULL(pp, SESSPOOL_MAGIC);
	/*
	 * XXX: waiter_epoll prevents us from zeroing the struct because
	 * XXX: it keeps state across calls.
	 */
	if (VTCP_nonblocking(sp->fd)) {
		SES_Delete(sp, SC_REM_CLOSE, NAN);
		return;
	}
	sp->waited.magic = WAITED_MAGIC;
	sp->waited.fd = sp->fd;
	sp->waited.ptr = sp;
	sp->waited.idle = sp->t_idle;
	if (Wait_Enter(pp->http1_waiter, &sp->waited))
		SES_Delete(sp, SC_PIPE_OVERFLOW, NAN);
}