Commit 6f396932 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Move the primitives for buffered reads on sockets into cache_session.c

(for lack of any better place) since they will become involved in
protocol switching.
parent cba62530
...@@ -853,19 +853,7 @@ enum sess_close http_DoConnection(struct http *hp); ...@@ -853,19 +853,7 @@ enum sess_close http_DoConnection(struct http *hp);
/* cache_http1_proto.c */ /* cache_http1_proto.c */
enum http1_status_e { enum htc_status_e HTTP1_Complete(struct http_conn *htc);
HTTP1_ALL_WHITESPACE = -3,
HTTP1_OVERFLOW = -2,
HTTP1_ERROR_EOF = -1,
HTTP1_NEED_MORE = 0,
HTTP1_COMPLETE = 1
};
void HTTP1_RxInit(struct http_conn *htc, struct ws *ws,
unsigned maxbytes, unsigned maxhdr);
enum http1_status_e HTTP1_Reinit(struct http_conn *htc);
enum http1_status_e HTTP1_Rx(struct http_conn *htc);
enum http1_status_e HTTP1_Complete(struct http_conn *htc);
uint16_t HTTP1_DissectRequest(struct http_conn *htc, struct http *hp); uint16_t HTTP1_DissectRequest(struct http_conn *htc, struct http *hp);
uint16_t HTTP1_DissectResponse(struct http *sp, struct http_conn *htc); uint16_t HTTP1_DissectResponse(struct http *sp, struct http_conn *htc);
unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*); unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*);
...@@ -995,6 +983,19 @@ struct req *SES_GetReq(const struct worker *, struct sess *); ...@@ -995,6 +983,19 @@ struct req *SES_GetReq(const struct worker *, struct sess *);
void SES_ReleaseReq(struct req *); void SES_ReleaseReq(struct req *);
task_func_t SES_Proto_Sess; task_func_t SES_Proto_Sess;
enum htc_status_e {
HTC_S_EMPTY = -3,
HTC_S_OVERFLOW = -2,
HTC_S_EOF = -1,
HTC_S_OK = 0,
HTC_S_COMPLETE = 1
};
void SES_RxInit(struct http_conn *htc, struct ws *ws,
unsigned maxbytes, unsigned maxhdr);
void SES_RxReInit(struct http_conn *htc);
enum htc_status_e SES_Rx(struct http_conn *htc);
#define SESS_ATTR(UP, low, typ, len) \ #define SESS_ATTR(UP, low, typ, len) \
int SES_Get_##low(const struct sess *sp, typ *dst); \ int SES_Get_##low(const struct sess *sp, typ *dst); \
void SES_Reserve_##low(struct sess *sp, typ *dst); void SES_Reserve_##low(struct sess *sp, typ *dst);
......
...@@ -153,6 +153,84 @@ SES_Get_String_Attr(const struct sess *sp, enum sess_attr a) ...@@ -153,6 +153,84 @@ SES_Get_String_Attr(const struct sess *sp, enum sess_attr a)
return (q); return (q);
} }
/*--------------------------------------------------------------------*/
void
SES_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes,
unsigned maxhdr)
{
htc->magic = HTTP_CONN_MAGIC;
htc->ws = ws;
htc->maxbytes = maxbytes;
htc->maxhdr = maxhdr;
(void)WS_Reserve(htc->ws, htc->maxbytes);
htc->rxbuf_b = ws->f;
htc->rxbuf_e = ws->f;
*htc->rxbuf_e = '\0';
htc->pipeline_b = NULL;
htc->pipeline_e = NULL;
}
/*--------------------------------------------------------------------
* Start over, and recycle any pipelined input.
* The WS_Reset is safe, even though the pipelined input is stored in
* the ws somewhere, because WS_Reset only fiddles pointers.
*/
void
SES_RxReInit(struct http_conn *htc)
{
ssize_t l;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
(void)WS_Reserve(htc->ws, htc->maxbytes);
htc->rxbuf_b = htc->ws->f;
htc->rxbuf_e = htc->ws->f;
if (htc->pipeline_b != NULL) {
l = htc->pipeline_e - htc->pipeline_b;
assert(l > 0);
memmove(htc->rxbuf_b, htc->pipeline_b, l);
htc->rxbuf_e += l;
htc->pipeline_b = NULL;
htc->pipeline_e = NULL;
}
*htc->rxbuf_e = '\0';
}
/*--------------------------------------------------------------------
* Receive more HTTP protocol bytes
*/
enum htc_status_e
SES_Rx(struct http_conn *htc)
{
int i;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
AN(htc->ws->r);
AZ(htc->pipeline_b);
AZ(htc->pipeline_e);
i = (htc->ws->r - htc->rxbuf_e) - 1; /* space for NUL */
if (i <= 0) {
WS_ReleaseP(htc->ws, htc->rxbuf_b);
return (HTC_S_OVERFLOW);
}
i = read(htc->fd, htc->rxbuf_e, i);
if (i <= 0) {
/*
* We wouldn't come here if we had a complete HTTP header
* so consequently an EOF can not be OK
*/
WS_ReleaseP(htc->ws, htc->rxbuf_b);
return (HTC_S_EOF);
}
htc->rxbuf_e += i;
*htc->rxbuf_e = '\0';
return (HTC_S_OK);
}
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Get a new session, preferably by recycling an already ready one * Get a new session, preferably by recycling an already ready one
* *
......
...@@ -76,7 +76,7 @@ int ...@@ -76,7 +76,7 @@ int
V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host) V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host)
{ {
struct http *hp; struct http *hp;
enum http1_status_e hs; enum htc_status_e hs;
int retry = 1; int retry = 1;
int j, first; int j, first;
ssize_t i; ssize_t i;
...@@ -144,7 +144,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host) ...@@ -144,7 +144,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host)
/* Receive response */ /* Receive response */
HTTP1_RxInit(htc, bo->ws, cache_param->http_resp_size, SES_RxInit(htc, bo->ws, cache_param->http_resp_size,
cache_param->http_resp_hdr_len); cache_param->http_resp_hdr_len);
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
...@@ -153,8 +153,10 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host) ...@@ -153,8 +153,10 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host)
first = 1; first = 1;
do { do {
hs = HTTP1_Rx(htc); hs = SES_Rx(htc);
if (hs == HTTP1_OVERFLOW) { if (hs == HTC_S_OK)
hs = HTTP1_Complete(htc);
if (hs == HTC_S_OVERFLOW) {
bo->acct.beresp_hdrbytes += bo->acct.beresp_hdrbytes +=
htc->rxbuf_e - htc->rxbuf_b; htc->rxbuf_e - htc->rxbuf_b;
VSLb(bo->vsl, SLT_FetchError, VSLb(bo->vsl, SLT_FetchError,
...@@ -163,7 +165,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host) ...@@ -163,7 +165,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host)
bo->doclose = SC_RX_OVERFLOW; bo->doclose = SC_RX_OVERFLOW;
return (-1); return (-1);
} }
if (hs == HTTP1_ERROR_EOF) { if (hs == HTC_S_EOF) {
bo->acct.beresp_hdrbytes += bo->acct.beresp_hdrbytes +=
htc->rxbuf_e - htc->rxbuf_b; htc->rxbuf_e - htc->rxbuf_b;
VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF", VSLb(bo->vsl, SLT_FetchError, "http %sread error: EOF",
...@@ -177,7 +179,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host) ...@@ -177,7 +179,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, const char *def_host)
VTCP_set_read_timeout(htc->fd, VTCP_set_read_timeout(htc->fd,
htc->between_bytes_timeout); htc->between_bytes_timeout);
} }
} while (hs != HTTP1_COMPLETE); } while (hs != HTC_S_COMPLETE);
bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b; bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b;
hp = bo->beresp; hp = bo->beresp;
......
...@@ -56,7 +56,7 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req) ...@@ -56,7 +56,7 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
struct pollfd pfd[1]; struct pollfd pfd[1];
double now, when; double now, when;
enum sess_close why = SC_NULL; enum sess_close why = SC_NULL;
enum http1_status_e hs; enum htc_status_e hs;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
...@@ -80,10 +80,12 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req) ...@@ -80,10 +80,12 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
assert(j >= 0); assert(j >= 0);
now = VTIM_real(); now = VTIM_real();
if (j != 0) if (j != 0)
hs = HTTP1_Rx(req->htc); hs = SES_Rx(req->htc);
else else
hs = HTC_S_OK; // XXX HTC_S_TIMEOUT ?
if (hs == HTC_S_OK)
hs = HTTP1_Complete(req->htc); hs = HTTP1_Complete(req->htc);
if (hs == HTTP1_COMPLETE) { if (hs == HTC_S_COMPLETE) {
/* Got it, run with it */ /* Got it, run with it */
if (isnan(req->t_first)) if (isnan(req->t_first))
req->t_first = now; req->t_first = now;
...@@ -92,13 +94,13 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req) ...@@ -92,13 +94,13 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
req->acct.req_hdrbytes += req->acct.req_hdrbytes +=
req->htc->rxbuf_e - req->htc->rxbuf_b; req->htc->rxbuf_e - req->htc->rxbuf_b;
return (REQ_FSM_MORE); return (REQ_FSM_MORE);
} else if (hs == HTTP1_ERROR_EOF) { } else if (hs == HTC_S_EOF) {
why = SC_REM_CLOSE; why = SC_REM_CLOSE;
break; break;
} else if (hs == HTTP1_OVERFLOW) { } else if (hs == HTC_S_OVERFLOW) {
why = SC_RX_OVERFLOW; why = SC_RX_OVERFLOW;
break; break;
} else if (hs == HTTP1_ALL_WHITESPACE) { } else if (hs == HTC_S_EMPTY) {
/* Nothing but whitespace */ /* Nothing but whitespace */
when = sp->t_idle + cache_param->timeout_idle; when = sp->t_idle + cache_param->timeout_idle;
if (when < now) { if (when < now) {
...@@ -208,7 +210,8 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req) ...@@ -208,7 +210,8 @@ http1_cleanup(struct sess *sp, struct worker *wrk, struct req *req)
WS_Reset(req->ws, NULL); WS_Reset(req->ws, NULL);
WS_Reset(wrk->aws, NULL); WS_Reset(wrk->aws, NULL);
if (HTTP1_Reinit(req->htc) == HTTP1_COMPLETE) { SES_RxReInit(req->htc);
if (HTTP1_Complete(req->htc) == HTC_S_COMPLETE) {
AZ(req->vsl->wid); AZ(req->vsl->wid);
req->t_first = req->t_req = sp->t_idle; req->t_first = req->t_req = sp->t_idle;
wrk->stats->sess_pipeline++; wrk->stats->sess_pipeline++;
...@@ -372,7 +375,7 @@ HTTP1_Session(struct worker *wrk, struct req *req) ...@@ -372,7 +375,7 @@ HTTP1_Session(struct worker *wrk, struct req *req)
if (sp->sess_step == S_STP_H1NEWREQ) { if (sp->sess_step == S_STP_H1NEWREQ) {
req->htc->fd = sp->fd; req->htc->fd = sp->fd;
HTTP1_RxInit(req->htc, req->ws, SES_RxInit(req->htc, req->ws,
cache_param->http_req_size, cache_param->http_req_hdr_len); cache_param->http_req_size, cache_param->http_req_hdr_len);
} }
......
...@@ -57,58 +57,11 @@ const int HTTP1_Resp[3] = { ...@@ -57,58 +57,11 @@ const int HTTP1_Resp[3] = {
HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_REASON HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_REASON
}; };
/*--------------------------------------------------------------------*/
void
HTTP1_RxInit(struct http_conn *htc, struct ws *ws, unsigned maxbytes,
unsigned maxhdr)
{
htc->magic = HTTP_CONN_MAGIC;
htc->ws = ws;
htc->maxbytes = maxbytes;
htc->maxhdr = maxhdr;
(void)WS_Reserve(htc->ws, htc->maxbytes);
htc->rxbuf_b = ws->f;
htc->rxbuf_e = ws->f;
*htc->rxbuf_e = '\0';
htc->pipeline_b = NULL;
htc->pipeline_e = NULL;
}
/*--------------------------------------------------------------------
* Start over, and recycle any pipelined input.
* The WS_Reset is safe, even though the pipelined input is stored in
* the ws somewhere, because WS_Reset only fiddles pointers.
*/
enum http1_status_e
HTTP1_Reinit(struct http_conn *htc)
{
ssize_t l;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
(void)WS_Reserve(htc->ws, htc->maxbytes);
htc->rxbuf_b = htc->ws->f;
htc->rxbuf_e = htc->ws->f;
if (htc->pipeline_b != NULL) {
l = htc->pipeline_e - htc->pipeline_b;
assert(l > 0);
memmove(htc->rxbuf_b, htc->pipeline_b, l);
htc->rxbuf_e += l;
htc->pipeline_b = NULL;
htc->pipeline_e = NULL;
}
*htc->rxbuf_e = '\0';
return (HTTP1_Complete(htc));
}
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Check if we have a complete HTTP request or response yet * Check if we have a complete HTTP request or response yet
*/ */
enum http1_status_e enum htc_status_e
HTTP1_Complete(struct http_conn *htc) HTTP1_Complete(struct http_conn *htc)
{ {
char *p; char *p;
...@@ -127,12 +80,12 @@ HTTP1_Complete(struct http_conn *htc) ...@@ -127,12 +80,12 @@ HTTP1_Complete(struct http_conn *htc)
/* All white space */ /* All white space */
htc->rxbuf_e = htc->rxbuf_b; htc->rxbuf_e = htc->rxbuf_b;
*htc->rxbuf_e = '\0'; *htc->rxbuf_e = '\0';
return (HTTP1_ALL_WHITESPACE); return (HTC_S_EMPTY);
} }
while (1) { while (1) {
p = strchr(p, '\n'); p = strchr(p, '\n');
if (p == NULL) if (p == NULL)
return (HTTP1_NEED_MORE); return (HTC_S_OK);
p++; p++;
if (*p == '\r') if (*p == '\r')
p++; p++;
...@@ -146,39 +99,7 @@ HTTP1_Complete(struct http_conn *htc) ...@@ -146,39 +99,7 @@ HTTP1_Complete(struct http_conn *htc)
htc->pipeline_e = htc->rxbuf_e; htc->pipeline_e = htc->rxbuf_e;
htc->rxbuf_e = p; htc->rxbuf_e = p;
} }
return (HTTP1_COMPLETE); return (HTC_S_COMPLETE);
}
/*--------------------------------------------------------------------
* Receive more HTTP protocol bytes
*/
enum http1_status_e
HTTP1_Rx(struct http_conn *htc)
{
int i;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
AN(htc->ws->r);
AZ(htc->pipeline_b);
AZ(htc->pipeline_e);
i = (htc->ws->r - htc->rxbuf_e) - 1; /* space for NUL */
if (i <= 0) {
WS_ReleaseP(htc->ws, htc->rxbuf_b);
return (HTTP1_OVERFLOW);
}
i = read(htc->fd, htc->rxbuf_e, i);
if (i <= 0) {
/*
* We wouldn't come here if we had a complete HTTP header
* so consequently an EOF can not be OK
*/
WS_ReleaseP(htc->ws, htc->rxbuf_b);
return (HTTP1_ERROR_EOF);
}
htc->rxbuf_e += i;
*htc->rxbuf_e = '\0';
return (HTTP1_Complete(htc));
} }
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
......
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