unsigned WRW_WriteH(struct worker *w, const txt *hh, const char *suf) { unsigned u; CHECK_OBJ_NOTNULL(w, WORKER_MAGIC); AN(w->wrw.wfd); AN(w); AN(hh); AN(hh->b); AN(hh->e); u = WRW_Write(w, hh->b, hh->e - hh->b); if (suf != NULL) u += WRW_Write(w, suf, -1); return (u); }
unsigned WRW_WriteH(struct sess *sp, const txt *hh, const char *suf) { unsigned u; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); AN(sp->wrkvar.wfd); AN(sp->wrk); AN(hh); AN(hh->b); AN(hh->e); u = WRW_Write(sp, hh->b, hh->e - hh->b); if (suf != NULL) u += WRW_Write(sp, suf, -1); return (u); }
unsigned HTTP1_Write(const struct worker *w, const struct http *hp, int resp) { unsigned u, l; if (resp) { l = WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " "); hp->hd[HTTP_HDR_STATUS].b = WS_Alloc(hp->ws, 4); AN(hp->hd[HTTP_HDR_STATUS].b); assert(hp->status >= 100 && hp->status <= 999); sprintf(hp->hd[HTTP_HDR_STATUS].b, "%3d", hp->status); hp->hd[HTTP_HDR_STATUS].e = hp->hd[HTTP_HDR_STATUS].b + 3; l += WRW_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " "); l += WRW_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], "\r\n"); } else { AN(hp->hd[HTTP_HDR_URL].b); l = WRW_WriteH(w, &hp->hd[HTTP_HDR_METHOD], " "); l += WRW_WriteH(w, &hp->hd[HTTP_HDR_URL], " "); l += WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n"); } for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { if (hp->hd[u].b == NULL) continue; AN(hp->hd[u].b); AN(hp->hd[u].e); l += WRW_WriteH(w, &hp->hd[u], "\r\n"); } l += WRW_Write(w, "\r\n", -1); return (l); }
int FetchReqBody(const struct sess *sp) { unsigned long content_length; char buf[8192]; char *ptr, *endp; int rdcnt; if (http_GetHdr(sp->req->http, H_Content_Length, &ptr)) { content_length = strtoul(ptr, &endp, 10); /* XXX should check result of conversion */ while (content_length) { if (content_length > sizeof buf) rdcnt = sizeof buf; else rdcnt = content_length; rdcnt = HTC_Read(sp->wrk, sp->req->htc, buf, rdcnt); if (rdcnt <= 0) return (1); content_length -= rdcnt; if (!sp->req->sendbody) continue; (void)WRW_Write(sp->wrk, buf, rdcnt); /* XXX: stats ? */ if (WRW_Flush(sp->wrk)) return (2); } } if (http_GetHdr(sp->req->http, H_Transfer_Encoding, NULL)) { /* XXX: Handle chunked encoding. */ WSP(sp, SLT_Debug, "Transfer-Encoding in request"); return (1); } return (0); }
void VGZ_WrwFlush(const struct worker *wrk, struct vgz *vg) { CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC); if (vg->m_len == 0) return; (void)WRW_Write(wrk, vg->m_buf, vg->m_len); (void)WRW_Flush(wrk); vg->m_len = 0; }
vbf_iter_req_body(struct req *req, void *priv, void *ptr, size_t l) { struct worker *wrk; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CAST_OBJ_NOTNULL(wrk, priv, WORKER_MAGIC); if (l > 0) { (void)WRW_Write(wrk, ptr, l); if (WRW_Flush(wrk)) return (-1); } return (0); }
void WRW_EndChunk(struct worker *w) { struct wrw *wrw; CHECK_OBJ_NOTNULL(w, WORKER_MAGIC); wrw = &w->wrw; assert(wrw->ciov < wrw->siov); (void)WRW_Flush(w); wrw->ciov = wrw->siov; wrw->niov = 0; wrw->cliov = 0; (void)WRW_Write(w, "0\r\n\r\n", -1); }
v1d_bytes(struct req *req, enum vdp_action act, const void *ptr, ssize_t len) { ssize_t wl = 0; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); assert(req->vdp_nxt == -1); /* always at the bottom of the pile */ if (len > 0) wl = WRW_Write(req->wrk, ptr, len); if (wl > 0) req->acct_req.bodybytes += wl; if (act > VDP_NULL && WRW_Flush(req->wrk)) return (-1); if (len != wl) return (-1); return (0); }
unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int *hf) { unsigned u, l; assert(hf == HTTP1_Req || hf == HTTP1_Resp); AN(hp->hd[hf[0]].b); AN(hp->hd[hf[1]].b); AN(hp->hd[hf[2]].b); l = WRW_WriteH(w, &hp->hd[hf[0]], " "); l += WRW_WriteH(w, &hp->hd[hf[1]], " "); l += WRW_WriteH(w, &hp->hd[hf[2]], "\r\n"); for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) l += WRW_WriteH(w, &hp->hd[u], "\r\n"); l += WRW_Write(w, "\r\n", -1); return (l); }
unsigned http_Write(struct worker *w, const struct http *hp, int resp) { unsigned u, l; int fd = *(w->wrw.wfd); if (resp) { l = WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " "); WSLH(w, fd, hp, HTTP_HDR_PROTO); hp->hd[HTTP_HDR_STATUS].b = WS_Alloc(w->ws, 4); AN(hp->hd[HTTP_HDR_STATUS].b); sprintf(hp->hd[HTTP_HDR_STATUS].b, "%3d", hp->status); hp->hd[HTTP_HDR_STATUS].e = hp->hd[HTTP_HDR_STATUS].b + 3; l += WRW_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " "); WSLH(w, fd, hp, HTTP_HDR_STATUS); l += WRW_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], "\r\n"); WSLH(w, fd, hp, HTTP_HDR_RESPONSE); } else { AN(hp->hd[HTTP_HDR_URL].b); l = WRW_WriteH(w, &hp->hd[HTTP_HDR_REQ], " "); WSLH(w, fd, hp, HTTP_HDR_REQ); l += WRW_WriteH(w, &hp->hd[HTTP_HDR_URL], " "); WSLH(w, fd, hp, HTTP_HDR_URL); l += WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n"); WSLH(w, fd, hp, HTTP_HDR_PROTO); } for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { if (hp->hd[u].b == NULL) continue; AN(hp->hd[u].b); AN(hp->hd[u].e); l += WRW_WriteH(w, &hp->hd[u], "\r\n"); WSLH(w, fd, hp, u); } l += WRW_Write(w, "\r\n", -1); return (l); }
int VGZ_WrwGunzip(struct worker *wrk, struct vgz *vg, const void *ibuf, ssize_t ibufl) { int i; size_t dl; const void *dp; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(vg, VGZ_MAGIC); AN(vg->m_buf); VGZ_Ibuf(vg, ibuf, ibufl); if (ibufl == 0) return (VGZ_OK); do { if (vg->m_len == vg->m_sz) i = VGZ_STUCK; else { i = VGZ_Gunzip(vg, &dp, &dl); vg->m_len += dl; } if (i < VGZ_OK) { /* XXX: VSL ? */ return (-1); } if (vg->m_len == vg->m_sz || i == VGZ_STUCK) { wrk->acct_tmp.bodybytes += vg->m_len; (void)WRW_Write(wrk, vg->m_buf, vg->m_len); (void)WRW_Flush(wrk); vg->m_len = 0; VGZ_Obuf(vg, vg->m_buf, vg->m_sz); } } while (!VGZ_IbufEmpty(vg)); if (i == VGZ_STUCK) i = VGZ_OK; return (i); }
void PipeSession(struct sess *sp) { struct vbc *vc; struct worker *w; struct pollfd fds[2]; int i; CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); w = sp->wrk; sp->vbc = VDI_GetFd(NULL, sp); if (sp->vbc == NULL) return; vc = sp->vbc; (void)VTCP_blocking(vc->fd); WRW_Reserve(w, &vc->fd); sp->wrk->acct_tmp.hdrbytes += http_Write(w, sp->vsl_id, sp->wrk->bereq, 0); if (sp->htc->pipeline.b != NULL) sp->wrk->acct_tmp.bodybytes += WRW_Write(w, sp->htc->pipeline.b, Tlen(sp->htc->pipeline)); i = WRW_FlushRelease(w); if (i) { SES_Close(sp, "pipe"); VDI_CloseFd(sp); return; } sp->t_resp = VTIM_real(); memset(fds, 0, sizeof fds); // XXX: not yet (void)VTCP_linger(vc->fd, 0); fds[0].fd = vc->fd; fds[0].events = POLLIN | POLLERR; // XXX: not yet (void)VTCP_linger(sp->fd, 0); fds[1].fd = sp->fd; fds[1].events = POLLIN | POLLERR; while (fds[0].fd > -1 || fds[1].fd > -1) { fds[0].revents = 0; fds[1].revents = 0; i = poll(fds, 2, params->pipe_timeout * 1000); if (i < 1) break; if (fds[0].revents && rdf(vc->fd, sp->fd)) { if (fds[1].fd == -1) break; (void)shutdown(vc->fd, SHUT_RD); (void)shutdown(sp->fd, SHUT_WR); fds[0].events = 0; fds[0].fd = -1; } if (fds[1].revents && rdf(sp->fd, vc->fd)) { if (fds[0].fd == -1) break; (void)shutdown(sp->fd, SHUT_RD); (void)shutdown(vc->fd, SHUT_WR); fds[1].events = 0; fds[1].fd = -1; } } SES_Close(sp, "pipe"); VDI_CloseFd(sp); }
void PipeRequest(struct req *req) { struct vbc *vc; struct worker *wrk; struct pollfd fds[2]; struct busyobj *bo; int i; CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC); wrk = req->wrk; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); bo = req->busyobj; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); vc = VDI_GetFd(NULL, bo); if (vc == NULL) return; bo->vbc = vc; /* For panic dumping */ (void)VTCP_blocking(vc->fd); WRW_Reserve(wrk, &vc->fd, bo->vsl, req->t_req); req->acct_req.hdrbytes += HTTP1_Write(wrk, bo->bereq, 0); if (req->htc->pipeline.b != NULL) req->acct_req.bodybytes += WRW_Write(wrk, req->htc->pipeline.b, Tlen(req->htc->pipeline)); i = WRW_FlushRelease(wrk); if (i) { SES_Close(req->sp, SC_TX_PIPE); VDI_CloseFd(&vc); return; } req->t_resp = VTIM_real(); memset(fds, 0, sizeof fds); // XXX: not yet (void)VTCP_linger(vc->fd, 0); fds[0].fd = vc->fd; fds[0].events = POLLIN | POLLERR; // XXX: not yet (void)VTCP_linger(req->sp->fd, 0); fds[1].fd = req->sp->fd; fds[1].events = POLLIN | POLLERR; while (fds[0].fd > -1 || fds[1].fd > -1) { fds[0].revents = 0; fds[1].revents = 0; i = poll(fds, 2, cache_param->pipe_timeout * 1000); if (i < 1) break; if (fds[0].revents && rdf(vc->fd, req->sp->fd)) { if (fds[1].fd == -1) break; (void)shutdown(vc->fd, SHUT_RD); (void)shutdown(req->sp->fd, SHUT_WR); fds[0].events = 0; fds[0].fd = -1; } if (fds[1].revents && rdf(req->sp->fd, vc->fd)) { if (fds[0].fd == -1) break; (void)shutdown(req->sp->fd, SHUT_RD); (void)shutdown(vc->fd, SHUT_WR); fds[1].events = 0; fds[1].fd = -1; } } SES_Close(req->sp, SC_TX_PIPE); VDI_CloseFd(&vc); bo->vbc = NULL; }