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); }
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)); }
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); }
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); }
/* * 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); }
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); }
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); }