Commit 3cc4a726 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Introduce an enum to make the states of HTTP reception more readable.

parent ae3e5a3a
......@@ -871,12 +871,20 @@ void http_Unset(struct http *hp, const char *hdr);
void http_CollectHdr(struct http *hp, const char *hdr);
/* cache_httpconn.c */
enum htc_status_e {
HTC_ALL_WHITESPACE = -3,
HTC_OVERFLOW = -2,
HTC_ERROR_EOF = -1,
HTC_NEED_MORE = 0,
HTC_COMPLETE = 1
};
void HTC_Init(struct http_conn *htc, struct ws *ws, int fd, struct vsl_log *,
unsigned maxbytes, unsigned maxhdr);
int HTC_Reinit(struct http_conn *htc);
int HTC_Rx(struct http_conn *htc);
enum htc_status_e HTC_Rx(struct http_conn *htc);
ssize_t HTC_Read(struct http_conn *htc, void *d, size_t len);
int HTC_Complete(struct http_conn *htc);
enum htc_status_e HTC_Complete(struct http_conn *htc);
#define HTTPH(a, b, c) extern char b[];
#include "tbl/http_headers.h"
......
......@@ -106,10 +106,11 @@ DOT }
static int
cnt_wait(struct sess *sp, struct worker *wrk, struct req *req)
{
int i, j, tmo;
int j, tmo;
struct pollfd pfd[1];
double now, when;
enum sess_close why = SC_NULL;
enum htc_status_e hs;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
......@@ -135,20 +136,20 @@ cnt_wait(struct sess *sp, struct worker *wrk, struct req *req)
assert(j >= 0);
now = VTIM_real();
if (j != 0)
i = HTC_Rx(req->htc);
hs = HTC_Rx(req->htc);
else
i = HTC_Complete(req->htc);
if (i == 1) {
hs = HTC_Complete(req->htc);
if (hs == HTC_COMPLETE) {
/* Got it, run with it */
req->t_req = now;
return (0);
} else if (i == -1) {
} else if (hs == HTC_ERROR_EOF) {
why = SC_REM_CLOSE;
break;
} else if (i == -2) {
} else if (hs == HTC_OVERFLOW) {
why = SC_RX_OVERFLOW;
break;
} else if (i == -3) {
} else if (hs == HTC_ALL_WHITESPACE) {
/* Nothing but whitespace */
when = sp->t_idle + cache_param->timeout_idle;
if (when < now) {
......
......@@ -437,8 +437,9 @@ FetchHdr(struct req *req, int need_host_hdr, int sendbody)
struct worker *wrk;
struct busyobj *bo;
struct http *hp;
enum htc_status_e hs;
int retry = -1;
int i;
int i, first;
struct http_conn *htc;
wrk = req->wrk;
......@@ -499,31 +500,31 @@ FetchHdr(struct req *req, int need_host_hdr, int sendbody)
VTCP_set_read_timeout(vc->fd, vc->first_byte_timeout);
i = HTC_Rx(htc);
if (i < 0) {
VSLb(req->vsl, SLT_FetchError,
"http first read error: %d %d (%s)",
i, errno, strerror(errno));
VDI_CloseFd(&bo->vbc);
/* XXX: other cleanup ? */
/* Retryable if we never received anything */
return (i == -1 ? retry : -1);
}
VTCP_set_read_timeout(vc->fd, vc->between_bytes_timeout);
while (i == 0) {
i = HTC_Rx(htc);
if (i < 0) {
first = 1;
do {
hs = HTC_Rx(htc);
if (hs == HTC_OVERFLOW) {
VSLb(req->vsl, SLT_FetchError,
"http first read error: %d %d (%s)",
i, errno, strerror(errno));
"http %sread error: overflow",
first ? "first " : "");
VDI_CloseFd(&bo->vbc);
/* XXX: other cleanup ? */
return (-1);
}
}
if (hs == HTC_ERROR_EOF) {
VSLb(req->vsl, SLT_FetchError,
"http %sread error: EOF",
first ? "first " : "");
VDI_CloseFd(&bo->vbc);
/* XXX: other cleanup ? */
return (retry);
}
if (first) {
first = 0;
VTCP_set_read_timeout(vc->fd,
vc->between_bytes_timeout);
}
} while (hs != HTC_COMPLETE);
hp = bo->beresp;
......
......@@ -46,44 +46,6 @@
#include "vct.h"
/*--------------------------------------------------------------------
* Check if we have a complete HTTP request or response yet
*
* Return values:
* -3 All whitespace so far
* 0 No, keep trying
* >0 Yes, it is this many bytes long.
*/
static int
htc_header_complete(txt *t)
{
const char *p;
Tcheck(*t);
assert(*t->e == '\0');
/* Skip any leading white space */
for (p = t->b ; vct_islws(*p); p++)
continue;
if (p == t->e) {
/* All white space */
t->e = t->b;
*t->e = '\0';
return (-3);
}
while (1) {
p = strchr(p, '\n');
if (p == NULL)
return (0);
p++;
if (*p == '\r')
p++;
if (*p == '\n')
break;
}
p++;
return (p - t->b);
}
/*--------------------------------------------------------------------*/
......@@ -139,15 +101,45 @@ HTC_Reinit(struct http_conn *htc)
* Return 1 if we have a complete HTTP procol header
*/
int
/*--------------------------------------------------------------------
* Check if we have a complete HTTP request or response yet
*
*/
enum htc_status_e
HTC_Complete(struct http_conn *htc)
{
int i;
const char *p;
txt *t;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
i = htc_header_complete(&htc->rxbuf);
if (i <= 0)
return (i);
t = &htc->rxbuf;
Tcheck(*t);
assert(*t->e == '\0');
/* Skip any leading white space */
for (p = t->b ; vct_islws(*p); p++)
continue;
if (p == t->e) {
/* All white space */
t->e = t->b;
*t->e = '\0';
return (HTC_ALL_WHITESPACE);
}
while (1) {
p = strchr(p, '\n');
if (p == NULL)
return (HTC_NEED_MORE);
p++;
if (*p == '\r')
p++;
if (*p == '\n')
break;
}
p++;
i = p - t->b;
WS_ReleaseP(htc->ws, htc->rxbuf.e);
AZ(htc->pipeline.b);
AZ(htc->pipeline.e);
......@@ -156,20 +148,14 @@ HTC_Complete(struct http_conn *htc)
htc->pipeline.e = htc->rxbuf.e;
htc->rxbuf.e = htc->pipeline.b;
}
return (1);
return (HTC_COMPLETE);
}
/*--------------------------------------------------------------------
* Receive more HTTP protocol bytes
* Returns:
* -3 all whitespace so far
* -2 overflow
* -1 error/EOF
* 0 more needed
* 1 got complete HTTP header
*/
int
enum htc_status_e
HTC_Rx(struct http_conn *htc)
{
int i;
......@@ -179,7 +165,7 @@ HTC_Rx(struct http_conn *htc)
i = (htc->ws->r - htc->rxbuf.e) - 1; /* space for NUL */
if (i <= 0) {
WS_ReleaseP(htc->ws, htc->rxbuf.b);
return (-2);
return (HTC_OVERFLOW);
}
i = read(htc->fd, htc->rxbuf.e, i);
if (i <= 0) {
......@@ -188,7 +174,7 @@ HTC_Rx(struct http_conn *htc)
* so consequently an EOF can not be OK
*/
WS_ReleaseP(htc->ws, htc->rxbuf.b);
return (-1);
return (HTC_ERROR_EOF);
}
htc->rxbuf.e += i;
*htc->rxbuf.e = '\0';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment