Commit cb879824 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Make Connection: handling an entirely internal http1 issue.

parent 40ec4a6b
...@@ -198,6 +198,7 @@ struct http { ...@@ -198,6 +198,7 @@ struct http {
uint16_t status; uint16_t status;
uint8_t protover; uint8_t protover;
uint8_t conds; /* If-* headers present */ uint8_t conds; /* If-* headers present */
enum sess_close doclose;
}; };
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
...@@ -958,7 +959,7 @@ void http_Merge(const struct http *fm, struct http *to, int not_ce); ...@@ -958,7 +959,7 @@ void http_Merge(const struct http *fm, struct http *to, int not_ce);
/* cache_http1_proto.c */ /* cache_http1_proto.c */
enum htc_status_e { enum http1_status_e {
HTTP1_ALL_WHITESPACE = -3, HTTP1_ALL_WHITESPACE = -3,
HTTP1_OVERFLOW = -2, HTTP1_OVERFLOW = -2,
HTTP1_ERROR_EOF = -1, HTTP1_ERROR_EOF = -1,
...@@ -968,13 +969,12 @@ enum htc_status_e { ...@@ -968,13 +969,12 @@ enum htc_status_e {
void HTTP1_Init(struct http_conn *htc, struct ws *ws, int fd, struct vsl_log *, void HTTP1_Init(struct http_conn *htc, struct ws *ws, int fd, struct vsl_log *,
unsigned maxbytes, unsigned maxhdr); unsigned maxbytes, unsigned maxhdr);
enum htc_status_e HTTP1_Reinit(struct http_conn *htc); enum http1_status_e HTTP1_Reinit(struct http_conn *htc);
enum htc_status_e HTTP1_Rx(struct http_conn *htc); enum http1_status_e HTTP1_Rx(struct http_conn *htc);
ssize_t HTTP1_Read(struct http_conn *htc, void *d, size_t len); ssize_t HTTP1_Read(struct http_conn *htc, void *d, size_t len);
enum htc_status_e HTTP1_Complete(struct http_conn *htc); enum http1_status_e HTTP1_Complete(struct http_conn *htc);
uint16_t HTTP1_DissectRequest(struct req *); uint16_t HTTP1_DissectRequest(struct req *);
uint16_t HTTP1_DissectResponse(struct http *sp, const struct http_conn *htc); uint16_t HTTP1_DissectResponse(struct http *sp, const struct http_conn *htc);
enum sess_close HTTP1_DoConnection(struct http *);
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*);
#define HTTPH(a, b, c) extern char b[]; #define HTTPH(a, b, c) extern char b[];
......
...@@ -238,7 +238,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req) ...@@ -238,7 +238,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
{ {
struct vbc *vc; struct vbc *vc;
struct http *hp; struct http *hp;
enum htc_status_e hs; enum http1_status_e hs;
int retry = -1; int retry = -1;
int i, j, first; int i, j, first;
struct http_conn *htc; struct http_conn *htc;
...@@ -371,6 +371,6 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req) ...@@ -371,6 +371,6 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
return (-1); return (-1);
} }
bo->doclose = HTTP1_DoConnection(hp); bo->doclose = hp->doclose;
return (0); return (0);
} }
...@@ -92,7 +92,7 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req) ...@@ -92,7 +92,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 htc_status_e hs; enum http1_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);
...@@ -380,7 +380,7 @@ http1_dissect(struct worker *wrk, struct req *req) ...@@ -380,7 +380,7 @@ http1_dissect(struct worker *wrk, struct req *req)
AZ(req->err_code); AZ(req->err_code);
req->ws_req = WS_Snapshot(req->ws); req->ws_req = WS_Snapshot(req->ws);
req->doclose = HTTP1_DoConnection(req->http); req->doclose = req->http->doclose;
http_Unset(req->http, H_Expect); http_Unset(req->http, H_Expect);
......
...@@ -88,7 +88,7 @@ HTTP1_Init(struct http_conn *htc, struct ws *ws, int fd, struct vsl_log *vsl, ...@@ -88,7 +88,7 @@ HTTP1_Init(struct http_conn *htc, struct ws *ws, int fd, struct vsl_log *vsl,
* the ws somewhere, because WS_Reset only fiddles pointers. * the ws somewhere, because WS_Reset only fiddles pointers.
*/ */
enum htc_status_e enum http1_status_e
HTTP1_Reinit(struct http_conn *htc) HTTP1_Reinit(struct http_conn *htc)
{ {
unsigned l; unsigned l;
...@@ -112,7 +112,7 @@ HTTP1_Reinit(struct http_conn *htc) ...@@ -112,7 +112,7 @@ HTTP1_Reinit(struct http_conn *htc)
* Check if we have a complete HTTP request or response yet * Check if we have a complete HTTP request or response yet
*/ */
enum htc_status_e enum http1_status_e
HTTP1_Complete(struct http_conn *htc) HTTP1_Complete(struct http_conn *htc)
{ {
char *p; char *p;
...@@ -159,7 +159,7 @@ HTTP1_Complete(struct http_conn *htc) ...@@ -159,7 +159,7 @@ HTTP1_Complete(struct http_conn *htc)
* Receive more HTTP protocol bytes * Receive more HTTP protocol bytes
*/ */
enum htc_status_e enum http1_status_e
HTTP1_Rx(struct http_conn *htc) HTTP1_Rx(struct http_conn *htc)
{ {
int i; int i;
...@@ -228,7 +228,7 @@ HTTP1_Read(struct http_conn *htc, void *d, size_t len) ...@@ -228,7 +228,7 @@ HTTP1_Read(struct http_conn *htc, void *d, size_t len)
*/ */
static uint16_t static uint16_t
htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc) http1_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
{ {
char *q, *r; char *q, *r;
txt t = htc->rxbuf; txt t = htc->rxbuf;
...@@ -304,7 +304,7 @@ htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc) ...@@ -304,7 +304,7 @@ htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
*/ */
static uint16_t static uint16_t
htc_splitline(struct http *hp, const struct http_conn *htc, const int *hf) http1_splitline(struct http *hp, const struct http_conn *htc, const int *hf)
{ {
char *p; char *p;
...@@ -369,16 +369,17 @@ htc_splitline(struct http *hp, const struct http_conn *htc, const int *hf) ...@@ -369,16 +369,17 @@ htc_splitline(struct http *hp, const struct http_conn *htc, const int *hf)
*hp->hd[hf[1]].e = '\0'; *hp->hd[hf[1]].e = '\0';
*hp->hd[hf[2]].e = '\0'; *hp->hd[hf[2]].e = '\0';
return (htc_dissect_hdrs(hp, p, htc)); return (http1_dissect_hdrs(hp, p, htc));
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static uint16_t static uint16_t
htc_request_check_host_hdr(const struct http *hp) http1_request_check_host_hdr(const struct http *hp)
{ {
int u; int u;
int seen_host = 0; int seen_host = 0;
for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) { for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
if (hp->hd[u].b == NULL) if (hp->hd[u].b == NULL)
continue; continue;
...@@ -399,7 +400,7 @@ htc_request_check_host_hdr(const struct http *hp) ...@@ -399,7 +400,7 @@ htc_request_check_host_hdr(const struct http *hp)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static void static void
htc_proto_ver(struct http *hp) http1_proto_ver(struct http *hp)
{ {
if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0")) if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0"))
hp->protover = 10; hp->protover = 10;
...@@ -409,6 +410,47 @@ htc_proto_ver(struct http *hp) ...@@ -409,6 +410,47 @@ htc_proto_ver(struct http *hp)
hp->protover = 9; hp->protover = 9;
} }
/*--------------------------------------------------------------------
*/
static enum sess_close
http1_DoConnection(struct http *hp)
{
char *p, *q;
enum sess_close retval;
unsigned u;
if (hp->protover < 11)
retval = SC_REQ_HTTP10;
else
retval = SC_NULL;;
http_CollectHdr(hp, H_Connection);
if (!http_GetHdr(hp, H_Connection, &p))
return (retval);
AN(p);
for (; *p; p++) {
if (vct_issp(*p))
continue;
if (*p == ',')
continue;
for (q = p + 1; *q; q++)
if (*q == ',' || vct_issp(*q))
break;
u = pdiff(p, q);
if (u == 5 && !strncasecmp(p, "close", u))
retval = SC_REQ_CLOSE;
if (u == 10 && !strncasecmp(p, "keep-alive", u))
retval = SC_NULL;
http_MarkHeader(hp, p, u, HDF_FILTER);
if (!*q)
break;
p = q;
}
return (retval);
}
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
uint16_t uint16_t
...@@ -425,14 +467,14 @@ HTTP1_DissectRequest(struct req *req) ...@@ -425,14 +467,14 @@ HTTP1_DissectRequest(struct req *req)
hp = req->http; hp = req->http;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
retval = htc_splitline(hp, htc, HTTP1_Req); retval = http1_splitline(hp, htc, HTTP1_Req);
if (retval != 0) { if (retval != 0) {
VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf); VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
return (retval); return (retval);
} }
htc_proto_ver(hp); http1_proto_ver(hp);
retval = htc_request_check_host_hdr(hp); retval = http1_request_check_host_hdr(hp);
if (retval != 0) { if (retval != 0) {
return (retval); return (retval);
} }
...@@ -449,6 +491,8 @@ HTTP1_DissectRequest(struct req *req) ...@@ -449,6 +491,8 @@ HTTP1_DissectRequest(struct req *req)
} }
} }
hp->doclose = http1_DoConnection(hp);
return (retval); return (retval);
} }
...@@ -464,11 +508,11 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc) ...@@ -464,11 +508,11 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
if (htc_splitline(hp, htc, HTTP1_Resp)) if (http1_splitline(hp, htc, HTTP1_Resp))
retval = 503; retval = 503;
if (retval == 0) { if (retval == 0) {
htc_proto_ver(hp); http1_proto_ver(hp);
if (hp->protover != 10 && hp->protover != 11) if (hp->protover != 10 && hp->protover != 11)
retval = 503; retval = 503;
} }
...@@ -501,46 +545,8 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc) ...@@ -501,46 +545,8 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
!Tlen(hp->hd[HTTP_HDR_REASON])) !Tlen(hp->hd[HTTP_HDR_REASON]))
http_SetH(hp, HTTP_HDR_REASON, http_Status2Reason(hp->status)); http_SetH(hp, HTTP_HDR_REASON, http_Status2Reason(hp->status));
return (retval); hp->doclose = http1_DoConnection(hp);
}
/*--------------------------------------------------------------------
*/
enum sess_close
HTTP1_DoConnection(struct http *hp)
{
char *p, *q;
enum sess_close retval;
unsigned u;
if (hp->protover < 11)
retval = SC_REQ_HTTP10;
else
retval = SC_NULL;;
http_CollectHdr(hp, H_Connection);
if (!http_GetHdr(hp, H_Connection, &p))
return (retval);
AN(p);
for (; *p; p++) {
if (vct_issp(*p))
continue;
if (*p == ',')
continue;
for (q = p + 1; *q; q++)
if (*q == ',' || vct_issp(*q))
break;
u = pdiff(p, q);
if (u == 5 && !strncasecmp(p, "close", u))
retval = SC_REQ_CLOSE;
if (u == 10 && !strncasecmp(p, "keep-alive", u))
retval = SC_NULL;
http_MarkHeader(hp, p, u, HDF_FILTER);
if (!*q)
break;
p = q;
}
return (retval); return (retval);
} }
......
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