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 {
uint16_t status;
uint8_t protover;
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);
/* cache_http1_proto.c */
enum htc_status_e {
enum http1_status_e {
HTTP1_ALL_WHITESPACE = -3,
HTTP1_OVERFLOW = -2,
HTTP1_ERROR_EOF = -1,
......@@ -968,13 +969,12 @@ enum htc_status_e {
void HTTP1_Init(struct http_conn *htc, struct ws *ws, int fd, struct vsl_log *,
unsigned maxbytes, unsigned maxhdr);
enum htc_status_e HTTP1_Reinit(struct http_conn *htc);
enum htc_status_e HTTP1_Rx(struct http_conn *htc);
enum http1_status_e HTTP1_Reinit(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);
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_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*);
#define HTTPH(a, b, c) extern char b[];
......
......@@ -238,7 +238,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
{
struct vbc *vc;
struct http *hp;
enum htc_status_e hs;
enum http1_status_e hs;
int retry = -1;
int i, j, first;
struct http_conn *htc;
......@@ -371,6 +371,6 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
return (-1);
}
bo->doclose = HTTP1_DoConnection(hp);
bo->doclose = hp->doclose;
return (0);
}
......@@ -92,7 +92,7 @@ http1_wait(struct sess *sp, struct worker *wrk, struct req *req)
struct pollfd pfd[1];
double now, when;
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(wrk, WORKER_MAGIC);
......@@ -380,7 +380,7 @@ http1_dissect(struct worker *wrk, struct req *req)
AZ(req->err_code);
req->ws_req = WS_Snapshot(req->ws);
req->doclose = HTTP1_DoConnection(req->http);
req->doclose = req->http->doclose;
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,
* the ws somewhere, because WS_Reset only fiddles pointers.
*/
enum htc_status_e
enum http1_status_e
HTTP1_Reinit(struct http_conn *htc)
{
unsigned l;
......@@ -112,7 +112,7 @@ HTTP1_Reinit(struct http_conn *htc)
* 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)
{
char *p;
......@@ -159,7 +159,7 @@ HTTP1_Complete(struct http_conn *htc)
* Receive more HTTP protocol bytes
*/
enum htc_status_e
enum http1_status_e
HTTP1_Rx(struct http_conn *htc)
{
int i;
......@@ -228,7 +228,7 @@ HTTP1_Read(struct http_conn *htc, void *d, size_t len)
*/
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;
txt t = htc->rxbuf;
......@@ -304,7 +304,7 @@ htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
*/
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;
......@@ -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[2]].e = '\0';
return (htc_dissect_hdrs(hp, p, htc));
return (http1_dissect_hdrs(hp, p, htc));
}
/*--------------------------------------------------------------------*/
static uint16_t
htc_request_check_host_hdr(const struct http *hp)
http1_request_check_host_hdr(const struct http *hp)
{
int u;
int seen_host = 0;
for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
if (hp->hd[u].b == NULL)
continue;
......@@ -399,7 +400,7 @@ htc_request_check_host_hdr(const struct http *hp)
/*--------------------------------------------------------------------*/
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"))
hp->protover = 10;
......@@ -409,6 +410,47 @@ htc_proto_ver(struct http *hp)
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
......@@ -425,14 +467,14 @@ HTTP1_DissectRequest(struct req *req)
hp = req->http;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
retval = htc_splitline(hp, htc, HTTP1_Req);
retval = http1_splitline(hp, htc, HTTP1_Req);
if (retval != 0) {
VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
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) {
return (retval);
}
......@@ -449,6 +491,8 @@ HTTP1_DissectRequest(struct req *req)
}
}
hp->doclose = http1_DoConnection(hp);
return (retval);
}
......@@ -464,11 +508,11 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
if (htc_splitline(hp, htc, HTTP1_Resp))
if (http1_splitline(hp, htc, HTTP1_Resp))
retval = 503;
if (retval == 0) {
htc_proto_ver(hp);
http1_proto_ver(hp);
if (hp->protover != 10 && hp->protover != 11)
retval = 503;
}
......@@ -501,46 +545,8 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
!Tlen(hp->hd[HTTP_HDR_REASON]))
http_SetH(hp, HTTP_HDR_REASON, http_Status2Reason(hp->status));
return (retval);
}
/*--------------------------------------------------------------------
*/
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;;
hp->doclose = http1_DoConnection(hp);
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);
}
......
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