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);
}
Exemple #2
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);
}