Exemplo n.º 1
0
enum htc_status_e
HTC_RxStuff(struct http_conn *htc, htc_complete_f *func,
    double *t1, double *t2, double ti, double tn, int maxbytes)
{
	double tmo;
	double now;
	enum htc_status_e hs;
	ssize_t z;

	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	AN(htc->rfd);
	assert(*htc->rfd > 0);
	AN(htc->ws->r);
	AN(htc->rxbuf_b);
	assert(htc->rxbuf_b <= htc->rxbuf_e);
	assert(htc->rxbuf_e <= htc->ws->r);

	AZ(isnan(tn));
	if (t1 != NULL)
		assert(isnan(*t1));

	if (htc->rxbuf_e == htc->ws->r) {
		/* Can't work with a zero size buffer */
		WS_ReleaseP(htc->ws, htc->rxbuf_b);
		return (HTC_S_OVERFLOW);
	}
	z = (htc->ws->r - htc->rxbuf_b);
	if (z < maxbytes)
		maxbytes = z;	/* Cap maxbytes at available WS */

	while (1) {
		now = VTIM_real();
		AZ(htc->pipeline_b);
		AZ(htc->pipeline_e);
		assert(htc->rxbuf_e <= htc->ws->r);

		hs = func(htc);
		if (hs == HTC_S_OVERFLOW || hs == HTC_S_JUNK) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			return (hs);
		}
		if (hs == HTC_S_COMPLETE) {
			WS_ReleaseP(htc->ws, htc->rxbuf_e);
			/* Got it, run with it */
			if (t1 != NULL && isnan(*t1))
				*t1 = now;
			if (t2 != NULL)
				*t2 = now;
			return (HTC_S_COMPLETE);
		}
		if (hs == HTC_S_MORE) {
			/* Working on it */
			if (t1 != NULL && isnan(*t1))
				*t1 = now;
		} else if (hs == HTC_S_EMPTY)
			htc->rxbuf_e = htc->rxbuf_b;
		else
			WRONG("htc_status_e");

		tmo = tn - now;
		if (!isnan(ti) && ti < tn && hs == HTC_S_EMPTY)
			tmo = ti - now;
		z = maxbytes - (htc->rxbuf_e - htc->rxbuf_b);
		if (z <= 0) {
			/* maxbytes reached but not HTC_S_COMPLETE. Return
			 * overflow. */
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			return (HTC_S_OVERFLOW);
		}
		if (tmo <= 0.0)
			tmo = 1e-3;
		z = VTCP_read(*htc->rfd, htc->rxbuf_e, z, tmo);
		if (z == 0 || z == -1) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			return (HTC_S_EOF);
		} else if (z > 0)
			htc->rxbuf_e += z;
		else if (z == -2) {
			if (hs == HTC_S_EMPTY && ti <= now) {
				WS_ReleaseP(htc->ws, htc->rxbuf_b);
				return (HTC_S_IDLE);
			}
			if (tn <= now) {
				WS_ReleaseP(htc->ws, htc->rxbuf_b);
				return (HTC_S_TIMEOUT);
			}
		}
	}
}
Exemplo n.º 2
0
enum htc_status_e
HTC_RxStuff(struct http_conn *htc, htc_complete_f *func,
    double *t1, double *t2, double ti, double tn, int maxbytes)
{
	double tmo;
	double now;
	enum htc_status_e hs;
	int i;

	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	AN(htc->ws->r);
	AN(htc->rxbuf_b);
	assert(htc->rxbuf_b <= htc->rxbuf_e);

	AZ(isnan(tn));
	if (t1 != NULL)
		assert(isnan(*t1));

	if (htc->rxbuf_e == htc->ws->r) {
		/* Can't work with a zero size buffer */
		WS_ReleaseP(htc->ws, htc->rxbuf_b);
		return (HTC_S_OVERFLOW);
	}
	if ((htc->ws->r - htc->rxbuf_b) - 1L < maxbytes)
		maxbytes = (htc->ws->r - htc->rxbuf_b) - 1L; /* Space for NUL */

	while (1) {
		now = VTIM_real();
		AZ(htc->pipeline_b);
		AZ(htc->pipeline_e);
		assert(htc->rxbuf_e < htc->ws->r);
		*htc->rxbuf_e = '\0';
		hs = func(htc);
		if (hs == HTC_S_OVERFLOW || hs == HTC_S_JUNK) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			return (hs);
		}
		if (hs == HTC_S_COMPLETE) {
			WS_ReleaseP(htc->ws, htc->rxbuf_e);
			/* Got it, run with it */
			if (t1 != NULL && isnan(*t1))
				*t1 = now;
			if (t2 != NULL)
				*t2 = now;
			return (HTC_S_COMPLETE);
		}
		if (hs == HTC_S_MORE) {
			/* Working on it */
			if (t1 != NULL && isnan(*t1))
				*t1 = now;
		} else if (hs == HTC_S_EMPTY)
			htc->rxbuf_e = htc->rxbuf_b;
		else
			WRONG("htc_status_e");

		tmo = tn - now;
		if (!isnan(ti) && ti < tn)
			tmo = ti - now;
		i = maxbytes - (htc->rxbuf_e - htc->rxbuf_b);
		assert(i >= 0);
		if (i == 0) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			return (HTC_S_OVERFLOW);
		}
		if (tmo <= 0.0)
			tmo = 1e-3;
		i = VTCP_read(htc->fd, htc->rxbuf_e, i, tmo);
		if (i == 0 || i == -1) {
			WS_ReleaseP(htc->ws, htc->rxbuf_b);
			return (HTC_S_EOF);
		} else if (i > 0)
			htc->rxbuf_e += i;
		else if (i == -2) {
			if (hs == HTC_S_EMPTY && ti <= now) {
				WS_ReleaseP(htc->ws, htc->rxbuf_b);
				return (HTC_S_IDLE);
			}
			if (tn <= now) {
				WS_ReleaseP(htc->ws, htc->rxbuf_b);
				return (HTC_S_TIMEOUT);
			}
		}
	}
}