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); }
static void cmd_http_sendhex(CMD_ARGS) { struct http *hp; char buf[3], *q; uint8_t *p; int i, j, l; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AZ(av[2]); l = strlen(av[1]) / 2; p = malloc(l); AN(p); q = av[1]; for (i = 0; i < l; i++) { while (vct_issp(*q)) q++; if (*q == '\0') break; memcpy(buf, q, 2); q += 2; buf[2] = '\0'; if (!vct_ishex(buf[0]) || !vct_ishex(buf[1])) vtc_log(hp->vl, 0, "Illegal Hex char \"%c%c\"", buf[0], buf[1]); p[i] = (uint8_t)strtoul(buf, NULL, 16); } vtc_hexdump(hp->vl, 4, "sendhex", (void*)p, i); j = write(hp->fd, p, i); assert(j == i); free(p); }
static int fetch_chunked(struct sess *sp, struct http_conn *htc) { int i; char buf[20]; /* XXX: 20 is arbitrary */ unsigned u; ssize_t cl; sp->wrk->vfp->begin(sp, 0); assert(sp->wrk->body_status == BS_CHUNKED); do { /* Skip leading whitespace */ do { i = HTC_Read(htc, buf, 1); CERR(); } while (vct_islws(buf[0])); /* Collect hex digits, skipping leading zeros */ for (u = 1; u < sizeof buf; u++) { do { i = HTC_Read(htc, buf + u, 1); CERR(); } while (u == 1 && buf[0] == '0' && buf[u] == '0'); if (!vct_ishex(buf[u])) break; } if (u >= sizeof buf) { WSP(sp, SLT_FetchError, "chunked header too long"); return (-1); } /* Skip trailing white space */ while(vct_islws(buf[u]) && buf[u] != '\n') { i = HTC_Read(htc, buf + u, 1); CERR(); } if (buf[u] != '\n') { WSP(sp, SLT_FetchError, "chunked header char syntax"); return (-1); } buf[u] = '\0'; cl = fetch_number(buf, 16); if (cl < 0) { WSP(sp, SLT_FetchError, "chunked header nbr syntax"); return (-1); } else if (cl > 0) { i = sp->wrk->vfp->bytes(sp, htc, cl); CERR(); } i = HTC_Read(htc, buf, 1); CERR(); if (buf[0] == '\r') { i = HTC_Read(htc, buf, 1); CERR(); } if (buf[0] != '\n') { WSP(sp, SLT_FetchError, "chunked tail syntax"); return (-1); } } while (cl > 0); return (0); }
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); }