Esempio n. 1
0
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);
}