static int vbf_fetch_chunked(struct busyobj *bo, struct http_conn *htc) { int i; char buf[20]; /* XXX: 20 is arbitrary */ unsigned u; ssize_t cl; assert(htc->body_status == BS_CHUNKED); do { /* Skip leading whitespace */ do { if (HTTP1_Read(htc, buf, 1) <= 0) return (VFP_Error(bo, "chunked read err")); } while (vct_islws(buf[0])); if (!vct_ishex(buf[0])) return (VFP_Error(bo, "chunked header non-hex")); /* Collect hex digits, skipping leading zeros */ for (u = 1; u < sizeof buf; u++) { do { if (HTTP1_Read(htc, buf + u, 1) <= 0) return (VFP_Error(bo, "chunked read err")); } while (u == 1 && buf[0] == '0' && buf[u] == '0'); if (!vct_ishex(buf[u])) break; } if (u >= sizeof buf) return (VFP_Error(bo,"chunked header too long")); /* Skip trailing white space */ while(vct_islws(buf[u]) && buf[u] != '\n') if (HTTP1_Read(htc, buf + u, 1) <= 0) return (VFP_Error(bo, "chunked read err")); if (buf[u] != '\n') return (VFP_Error(bo,"chunked header no NL")); buf[u] = '\0'; cl = vbf_fetch_number(buf, 16); if (cl < 0) return (VFP_Error(bo,"chunked header number syntax")); if (cl > 0 && bo->vfp->bytes(bo, htc, cl) <= 0) return (VFP_Error(bo, "chunked read err")); i = HTTP1_Read(htc, buf, 1); if (i <= 0) return (VFP_Error(bo, "chunked read err")); if (buf[0] == '\r' && HTTP1_Read( htc, buf, 1) <= 0) return (VFP_Error(bo, "chunked read err")); if (buf[0] != '\n') return (VFP_Error(bo,"chunked tail no NL")); } while (cl > 0); return (0); }
v1f_pull_straight(struct busyobj *bo, void *p, ssize_t *lp, intptr_t *priv) { ssize_t l, lr; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); if (p == vfp_init) return (VFP_OK); if (p == vfp_fini) return (VFP_ERROR); AN(p); AN(lp); AN(priv); l = *lp; *lp = 0; if (!*priv) // XXX: Optimize Content-Len: 0 out earlier return (VFP_END); if (*priv < l) l = *priv; lr = HTTP1_Read(&bo->htc, p, l); if (lr <= 0) return (VFP_Error(bo, "straight insufficient bytes")); *lp = lr; *priv -= lr; if (*priv == 0) return (VFP_END); return (VFP_OK); }
vfp_nop_bytes(struct busyobj *bo, struct http_conn *htc, ssize_t bytes) { ssize_t l, wl; struct storage *st; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); while (bytes > 0) { st = VFP_GetStorage(bo, 0); if (st == NULL) return(-1); l = st->space - st->len; if (l > bytes) l = bytes; wl = HTTP1_Read(htc, st->ptr + st->len, l); if (wl <= 0) return (wl); st->len += wl; VBO_extend(bo, wl); bytes -= wl; } return (1); }
v1f_pull_eof(struct busyobj *bo, void *p, ssize_t *lp, intptr_t *priv) { ssize_t l, lr; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); if (p == vfp_init) return (VFP_OK); if (p == vfp_fini) return (VFP_ERROR); AN(p); AN(lp); AN(priv); l = *lp; *lp = 0; lr = HTTP1_Read(&bo->htc, p, l); if (lr < 0) return (VFP_Error(bo,"eof socket fail")); if (lr == 0) return (VFP_END); *lp = lr; return (VFP_OK); }
v1f_pull_chunked(struct busyobj *bo, void *p, ssize_t *lp, intptr_t *priv) { int i; char buf[20]; /* XXX: 20 is arbitrary */ unsigned u; ssize_t cl, l, lr; CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); if (p == vfp_init) return (VFP_OK); if (p == vfp_fini) return (VFP_ERROR); AN(p); AN(lp); AN(priv); l = *lp; *lp = 0; if (*priv == -1) { /* Skip leading whitespace */ do { if (HTTP1_Read(&bo->htc, buf, 1) <= 0) return (VFP_Error(bo, "chunked read err")); } while (vct_islws(buf[0])); if (!vct_ishex(buf[0])) return (VFP_Error(bo, "chunked header non-hex")); /* Collect hex digits, skipping leading zeros */ for (u = 1; u < sizeof buf; u++) { do { if (HTTP1_Read(&bo->htc, buf + u, 1) <= 0) return (VFP_Error(bo, "chunked read err")); } while (u == 1 && buf[0] == '0' && buf[u] == '0'); if (!vct_ishex(buf[u])) break; } if (u >= sizeof buf) return (VFP_Error(bo,"chunked header too long")); /* Skip trailing white space */ while(vct_islws(buf[u]) && buf[u] != '\n') if (HTTP1_Read(&bo->htc, buf + u, 1) <= 0) return (VFP_Error(bo, "chunked read err")); if (buf[u] != '\n') return (VFP_Error(bo,"chunked header no NL")); buf[u] = '\0'; cl = vbf_fetch_number(buf, 16); if (cl < 0) return (VFP_Error(bo,"chunked header number syntax")); *priv = cl; } if (*priv > 0) { if (*priv < l) l = *priv; lr = HTTP1_Read(&bo->htc, p, l); if (lr <= 0) return (VFP_Error(bo, "straight insufficient bytes")); *lp = lr; *priv -= lr; if (*priv == 0) *priv = -1; return (VFP_OK); } AZ(*priv); i = HTTP1_Read(&bo->htc, buf, 1); if (i <= 0) return (VFP_Error(bo, "chunked read err")); if (buf[0] == '\r' && HTTP1_Read(&bo->htc, buf, 1) <= 0) return (VFP_Error(bo, "chunked read err")); if (buf[0] != '\n') return (VFP_Error(bo,"chunked tail no NL")); return (VFP_END); }