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

Complete the split of HTTP-editing and HTTP-transmission functions.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2055 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent f6b82905
...@@ -110,8 +110,6 @@ struct http { ...@@ -110,8 +110,6 @@ struct http {
#define HTTP_MAGIC 0x6428b5c9 #define HTTP_MAGIC 0x6428b5c9
struct ws *ws; struct ws *ws;
txt rx; /* Received Request */
txt pl; /* Pipelined bytes */
unsigned char conds; /* If-* headers present */ unsigned char conds; /* If-* headers present */
enum httpwhence logtag; enum httpwhence logtag;
...@@ -126,7 +124,7 @@ struct http_conn { ...@@ -126,7 +124,7 @@ struct http_conn {
unsigned magic; unsigned magic;
#define HTTP_CONN_MAGIC 0x3e19edd1 #define HTTP_CONN_MAGIC 0x3e19edd1
struct http *http; int fd;
struct ws *ws; struct ws *ws;
txt rxbuf; txt rxbuf;
txt pipeline; txt pipeline;
...@@ -289,6 +287,8 @@ struct sess { ...@@ -289,6 +287,8 @@ struct sess {
struct http *http; struct http *http;
struct ws ws[1]; struct ws ws[1];
struct http_conn htc[1];
/* Timestamps, all on TIM_real() timescale */ /* Timestamps, all on TIM_real() timescale */
double t_open; double t_open;
double t_req; double t_req;
...@@ -470,18 +470,17 @@ int http_GetStatus(const struct http *hp); ...@@ -470,18 +470,17 @@ int http_GetStatus(const struct http *hp);
const char *http_GetReq(const struct http *hp); const char *http_GetReq(const struct http *hp);
const char *http_GetProto(const struct http *hp); const char *http_GetProto(const struct http *hp);
int http_HdrIs(const struct http *hp, const char *hdr, const char *val); int http_HdrIs(const struct http *hp, const char *hdr, const char *val);
int http_GetTail(struct http *hp, unsigned len, char **b, char **e); int http_DissectRequest(struct sess *sp);
int http_Read(struct http *hp, int fd, void *b, unsigned len); int http_DissectResponse(struct worker *w, struct http_conn *htc, struct http *sp);
void http_RecvPrep(struct http *hp);
int http_RecvPrepAgain(struct http *hp);
int http_RecvSome(int fd, struct http *hp);
int http_RecvHead(struct http *hp, int fd);
int http_DissectRequest(struct worker *w, struct http *sp, int fd);
int http_DissectResponse(struct worker *w, struct http *sp, int fd);
const char *http_DoConnection(struct http *hp); const char *http_DoConnection(struct http *hp);
void http_CopyHome(struct worker *w, int fd, struct http *hp); void http_CopyHome(struct worker *w, int fd, struct http *hp);
void http_Unset(struct http *hp, const char *hdr); void http_Unset(struct http *hp, const char *hdr);
/* cache_httpconn.c */
void HTC_Init(struct http_conn *htc, struct ws *ws, int fd);
int HTC_Reinit(struct http_conn *htc);
int HTC_Rx(struct http_conn *htc);
int HTC_Read(struct http_conn *htc, void *d, unsigned len);
#define HTTPH(a, b, c, d, e, f, g) extern char b[]; #define HTTPH(a, b, c, d, e, f, g) extern char b[];
#include "http_headers.h" #include "http_headers.h"
......
...@@ -194,7 +194,7 @@ vca_acct(void *arg) ...@@ -194,7 +194,7 @@ vca_acct(void *arg)
sp->id = i; sp->id = i;
sp->t_open = TIM_real(); sp->t_open = TIM_real();
http_RecvPrep(sp->http); HTC_Init(sp->htc, sp->ws, sp->fd);
sp->step = STP_FIRST; sp->step = STP_FIRST;
WRK_QueueSession(sp); WRK_QueueSession(sp);
} }
...@@ -224,13 +224,13 @@ vca_pollsession(struct sess *sp) ...@@ -224,13 +224,13 @@ vca_pollsession(struct sess *sp)
{ {
int i; int i;
i = http_RecvSome(sp->fd, sp->http); i = HTC_Rx(sp->htc);
if (i < 1) /* XXX: fix retval */
return (i); if (i == 0)
return (-1);
if (i == 1) if (i == 1)
vca_close_session(sp, "overflow"); return (0);
else if (i == 2) vca_close_session(sp, "err/poll");
vca_close_session(sp, "no request");
return (1); return (1);
} }
......
...@@ -88,20 +88,15 @@ cnt_again(struct sess *sp) ...@@ -88,20 +88,15 @@ cnt_again(struct sess *sp)
assert(sp->xid == 0); assert(sp->xid == 0);
do do
i = http_RecvSome(sp->fd, sp->http); i = HTC_Rx(sp->htc);
while (i == -1); while (i == 0);
if (i == 0) { if (i == 1) {
sp->step = STP_RECV; sp->step = STP_RECV;
return (0); } else {
}
if (i == 1)
vca_close_session(sp, "overflow"); vca_close_session(sp, "overflow");
else if (i == 2) sp->step = STP_DONE;
vca_close_session(sp, "no request"); }
else
INCOMPL();
sp->step = STP_DONE;
return (0); return (0);
} }
...@@ -185,6 +180,7 @@ static int ...@@ -185,6 +180,7 @@ static int
cnt_done(struct sess *sp) cnt_done(struct sess *sp)
{ {
double dh, dp, da; double dh, dp, da;
int i;
AZ(sp->obj); AZ(sp->obj);
AZ(sp->bereq); AZ(sp->bereq);
...@@ -224,12 +220,13 @@ cnt_done(struct sess *sp) ...@@ -224,12 +220,13 @@ cnt_done(struct sess *sp)
return (1); return (1);
} }
if (http_RecvPrepAgain(sp->http)) { i = HTC_Reinit(sp->htc);
if (i == 1) {
VSL_stats->sess_pipeline++; VSL_stats->sess_pipeline++;
sp->step = STP_RECV; sp->step = STP_RECV;
return (0); return (0);
} }
if (sp->http->pl.b < sp->http->pl.e) { if (Tlen(sp->htc->rxbuf)) {
VSL_stats->sess_readahead++; VSL_stats->sess_readahead++;
sp->step = STP_AGAIN; sp->step = STP_AGAIN;
return (0); return (0);
...@@ -388,13 +385,13 @@ cnt_first(struct sess *sp) ...@@ -388,13 +385,13 @@ cnt_first(struct sess *sp)
sp->wrk->acct.sess++; sp->wrk->acct.sess++;
SES_RefSrcAddr(sp); SES_RefSrcAddr(sp);
do do
i = http_RecvSome(sp->fd, sp->http); i = HTC_Rx(sp->htc);
while (i == -1); while (i == 0);
if (i == 0) { if (i == 1) {
sp->step = STP_RECV; sp->step = STP_RECV;
return (0); return (0);
} }
if (i == 1) if (i == -1)
vca_close_session(sp, "blast"); vca_close_session(sp, "blast");
else if (i == 2) else if (i == 2)
vca_close_session(sp, "silent"); vca_close_session(sp, "silent");
...@@ -756,7 +753,7 @@ cnt_recv(struct sess *sp) ...@@ -756,7 +753,7 @@ cnt_recv(struct sess *sp)
sp->vcl = sp->wrk->vcl; sp->vcl = sp->wrk->vcl;
sp->wrk->vcl = NULL; sp->wrk->vcl = NULL;
done = http_DissectRequest(sp->wrk, sp->http, sp->fd); done = http_DissectRequest(sp);
if (done != 0) { if (done != 0) {
RES_Error(sp, done, NULL); /* XXX: STP_ERROR ? */ RES_Error(sp, done, NULL); /* XXX: STP_ERROR ? */
sp->step = STP_DONE; sp->step = STP_DONE;
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
static int static int
fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b) fetch_straight(struct sess *sp, struct http_conn *htc, const char *b)
{ {
int i; int i;
unsigned char *p; unsigned char *p;
...@@ -70,12 +70,12 @@ fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b) ...@@ -70,12 +70,12 @@ fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b)
sp->obj->len = cl; sp->obj->len = cl;
p = st->ptr; p = st->ptr;
i = fcntl(fd, F_GETFL); /* XXX ? */ i = fcntl(htc->fd, F_GETFL); /* XXX ? */
i &= ~O_NONBLOCK; i &= ~O_NONBLOCK;
i = fcntl(fd, F_SETFL, i); i = fcntl(htc->fd, F_SETFL, i);
while (cl > 0) { while (cl > 0) {
i = http_Read(hp, fd, p, cl); i = HTC_Read(htc, p, cl);
if (i <= 0) if (i <= 0)
return (-1); return (-1);
p += i; p += i;
...@@ -88,7 +88,7 @@ fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b) ...@@ -88,7 +88,7 @@ fetch_straight(struct sess *sp, int fd, struct http *hp, const char *b)
/* XXX: Cleanup. It must be possible somehow :-( */ /* XXX: Cleanup. It must be possible somehow :-( */
static int static int
fetch_chunked(struct sess *sp, int fd, struct http *hp) fetch_chunked(struct sess *sp, struct http_conn *htc)
{ {
int i; int i;
char *q; char *q;
...@@ -132,7 +132,7 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp) ...@@ -132,7 +132,7 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp)
* deal more complex than reading a single character * deal more complex than reading a single character
* at a time. * at a time.
*/ */
i = http_Read(hp, fd, bp, 1); i = HTC_Read(htc, bp, 1);
if (i <= 0) if (i <= 0)
return (-1); return (-1);
bp += i; bp += i;
...@@ -179,7 +179,7 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp) ...@@ -179,7 +179,7 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp)
/* Pick up the rest of this chunk */ /* Pick up the rest of this chunk */
while (v > 0) { while (v > 0) {
i = http_Read(hp, fd, st->ptr + st->len, v); i = HTC_Read(htc, st->ptr + st->len, v);
if (i <= 0) if (i <= 0)
return (-1); return (-1);
st->len += i; st->len += i;
...@@ -211,16 +211,16 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp) ...@@ -211,16 +211,16 @@ fetch_chunked(struct sess *sp, int fd, struct http *hp)
#include <errno.h> #include <errno.h>
static int static int
fetch_eof(struct sess *sp, int fd, struct http *hp) fetch_eof(struct sess *sp, struct http_conn *htc)
{ {
int i; int i;
unsigned char *p; unsigned char *p;
struct storage *st; struct storage *st;
unsigned v; unsigned v;
i = fcntl(fd, F_GETFL); /* XXX ? */ i = fcntl(htc->fd, F_GETFL); /* XXX ? */
i &= ~O_NONBLOCK; i &= ~O_NONBLOCK;
i = fcntl(fd, F_SETFL, i); i = fcntl(htc->fd, F_SETFL, i);
p = NULL; p = NULL;
v = 0; v = 0;
...@@ -234,7 +234,7 @@ fetch_eof(struct sess *sp, int fd, struct http *hp) ...@@ -234,7 +234,7 @@ fetch_eof(struct sess *sp, int fd, struct http *hp)
} }
AN(p); AN(p);
AN(st); AN(st);
i = http_Read(hp, fd, p, v); i = HTC_Read(htc, p, v);
if (i < 0) if (i < 0)
return (-1); return (-1);
if (i == 0) if (i == 0)
...@@ -268,6 +268,8 @@ Fetch(struct sess *sp) ...@@ -268,6 +268,8 @@ Fetch(struct sess *sp)
struct bereq *bereq; struct bereq *bereq;
int mklen, is_head; int mklen, is_head;
unsigned len; unsigned len;
struct http_conn htc[1];
int i;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
...@@ -300,12 +302,12 @@ Fetch(struct sess *sp) ...@@ -300,12 +302,12 @@ Fetch(struct sess *sp)
CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC); CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC); HTC_Init(htc, bereq->ws, vc->fd);
if (http_RecvHead(hp, vc->fd)) { do
/* XXX: cleanup */ i = HTC_Rx(htc);
return (1); while (i == 0);
}
if (http_DissectResponse(sp->wrk, hp, vc->fd)) { if (http_DissectResponse(sp->wrk, htc, hp)) {
/* XXX: cleanup */ /* XXX: cleanup */
return (1); return (1);
} }
...@@ -326,8 +328,8 @@ Fetch(struct sess *sp) ...@@ -326,8 +328,8 @@ Fetch(struct sess *sp)
CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC); CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
/* Filter into object */ /* Filter into object */
hp2 = &sp->obj->http; hp2 = &sp->obj->http;
len = Tlen(hp->rx); len = Tlen(htc->rxbuf);
len += 256; /* margin for content-length etc */ len += 256; /* XXX: margin for content-length etc */
CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC); CHECK_OBJ_NOTNULL(sp->backend, BACKEND_MAGIC);
b = malloc(len); b = malloc(len);
...@@ -349,10 +351,10 @@ Fetch(struct sess *sp) ...@@ -349,10 +351,10 @@ Fetch(struct sess *sp)
if (is_head) { if (is_head) {
/* nothing */ /* nothing */
} else if (http_GetHdr(hp, H_Content_Length, &b)) { } else if (http_GetHdr(hp, H_Content_Length, &b)) {
cls = fetch_straight(sp, vc->fd, hp, b); cls = fetch_straight(sp, htc, b);
mklen = 1; mklen = 1;
} else if (http_HdrIs(hp, H_Transfer_Encoding, "chunked")) { } else if (http_HdrIs(hp, H_Transfer_Encoding, "chunked")) {
cls = fetch_chunked(sp, vc->fd, hp); cls = fetch_chunked(sp, htc);
mklen = 1; mklen = 1;
} else if (http_GetHdr(hp, H_Transfer_Encoding, &b)) { } else if (http_GetHdr(hp, H_Transfer_Encoding, &b)) {
/* XXX: AUGH! */ /* XXX: AUGH! */
...@@ -362,7 +364,7 @@ Fetch(struct sess *sp) ...@@ -362,7 +364,7 @@ Fetch(struct sess *sp)
} else if (strcmp(http_GetProto(hp), "HTTP/1.1")) { } else if (strcmp(http_GetProto(hp), "HTTP/1.1")) {
switch (http_GetStatus(hp)) { switch (http_GetStatus(hp)) {
case 200: case 200:
cls = fetch_eof(sp, vc->fd, hp); cls = fetch_eof(sp, htc);
mklen = 1; mklen = 1;
break; break;
default: default:
......
...@@ -347,7 +347,7 @@ http_GetReq(const struct http *hp) ...@@ -347,7 +347,7 @@ http_GetReq(const struct http *hp)
*/ */
static int static int
http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p) http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p, txt t)
{ {
char *q, *r; char *q, *r;
...@@ -357,8 +357,8 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p) ...@@ -357,8 +357,8 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
hp->nhd = HTTP_HDR_FIRST; hp->nhd = HTTP_HDR_FIRST;
hp->conds = 0; hp->conds = 0;
r = NULL; /* For FlexeLint */ r = NULL; /* For FlexeLint */
assert(p < hp->rx.e); /* http_header_complete() guarantees this */ assert(p < t.e); /* http_header_complete() guarantees this */
for (; p < hp->rx.e; p = r) { for (; p < t.e; p = r) {
/* XXX: handle continuation lines */ /* XXX: handle continuation lines */
q = strchr(p, '\n'); q = strchr(p, '\n');
assert(q != NULL); assert(q != NULL);
...@@ -391,16 +391,23 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p) ...@@ -391,16 +391,23 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
int int
http_DissectRequest(struct worker *w, struct http *hp, int fd) http_DissectRequest(struct sess *sp)
{ {
char *p; char *p;
struct http_conn *htc;
struct http *hp;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
htc = sp->htc;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
hp = sp->http;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
/* Assert a NUL at rx.e */ /* Assert a NUL at rx.e */
Tcheck(hp->rx); Tcheck(htc->rxbuf);
hp->logtag = HTTP_Rx; hp->logtag = HTTP_Rx;
for (p = hp->rx.b ; isspace(*p); p++) for (p = htc->rxbuf.b ; isspace(*p); p++)
continue; continue;
/* First, the request type (GET/HEAD etc) */ /* First, the request type (GET/HEAD etc) */
...@@ -408,23 +415,23 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -408,23 +415,23 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
for (; isalpha(*p); p++) for (; isalpha(*p); p++)
; ;
hp->hd[HTTP_HDR_REQ].e = p; hp->hd[HTTP_HDR_REQ].e = p;
WSLH(w, HTTP_T_Request, fd, hp, HTTP_HDR_REQ); WSLH(sp->wrk, HTTP_T_Request, sp->fd, hp, HTTP_HDR_REQ);
*p++ = '\0'; *p++ = '\0';
/* Next find the URI */ /* Next find the URI */
while (isspace(*p) && *p != '\n') while (isspace(*p) && *p != '\n')
p++; p++;
if (*p == '\n') { if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx); WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400); return (400);
} }
hp->hd[HTTP_HDR_URL].b = p; hp->hd[HTTP_HDR_URL].b = p;
while (!isspace(*p)) while (!isspace(*p))
p++; p++;
hp->hd[HTTP_HDR_URL].e = p; hp->hd[HTTP_HDR_URL].e = p;
WSLH(w, HTTP_T_URL, fd, hp, HTTP_HDR_URL); WSLH(sp->wrk, HTTP_T_URL, sp->fd, hp, HTTP_HDR_URL);
if (*p == '\n') { if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx); WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400); return (400);
} }
*p++ = '\0'; *p++ = '\0';
...@@ -433,44 +440,45 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -433,44 +440,45 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
while (isspace(*p) && *p != '\n') while (isspace(*p) && *p != '\n')
p++; p++;
if (*p == '\n') { if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx); WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400); return (400);
} }
hp->hd[HTTP_HDR_PROTO].b = p; hp->hd[HTTP_HDR_PROTO].b = p;
while (!isspace(*p)) while (!isspace(*p))
p++; p++;
hp->hd[HTTP_HDR_PROTO].e = p; hp->hd[HTTP_HDR_PROTO].e = p;
WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO); WSLH(sp->wrk, HTTP_T_Protocol, sp->fd, hp, HTTP_HDR_PROTO);
if (*p != '\n') if (*p != '\n')
*p++ = '\0'; *p++ = '\0';
while (isspace(*p) && *p != '\n') while (isspace(*p) && *p != '\n')
p++; p++;
if (*p != '\n') { if (*p != '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->rx); WSLR(sp->wrk, SLT_HttpGarbage, sp->fd, htc->rxbuf);
return (400); return (400);
} }
*p++ = '\0'; *p++ = '\0';
return (http_dissect_hdrs(w, hp, fd, p)); return (http_dissect_hdrs(sp->wrk, hp, sp->fd, p, htc->rxbuf));
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
int int
http_DissectResponse(struct worker *w, struct http *hp, int fd) http_DissectResponse(struct worker *w, struct http_conn *htc, struct http *hp)
{ {
char *p, *q; char *p, *q;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
/* Assert a NUL at rx.e */ /* Assert a NUL at rx.e (?) */
Tcheck(hp->rx); Tcheck(htc->rxbuf);
hp->logtag = HTTP_Rx; hp->logtag = HTTP_Rx;
for (p = hp->rx.b ; isspace(*p); p++) for (p = htc->rxbuf.b ; isspace(*p); p++)
continue; continue;
if (memcmp(p, "HTTP/1.", 7)) { if (memcmp(p, "HTTP/1.", 7)) {
WSLR(w, SLT_HttpGarbage, fd, hp->rx); WSLR(w, SLT_HttpGarbage, htc->fd, htc->rxbuf);
return (400); return (400);
} }
/* First, protocol */ /* First, protocol */
...@@ -478,7 +486,7 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd) ...@@ -478,7 +486,7 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
while (!isspace(*p)) while (!isspace(*p))
p++; p++;
hp->hd[HTTP_HDR_PROTO].e = p; hp->hd[HTTP_HDR_PROTO].e = p;
WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO); WSLH(w, HTTP_T_Protocol, htc->fd, hp, HTTP_HDR_PROTO);
*p++ = '\0'; *p++ = '\0';
/* Next find the status */ /* Next find the status */
...@@ -488,7 +496,7 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd) ...@@ -488,7 +496,7 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
while (!isspace(*p)) while (!isspace(*p))
p++; p++;
hp->hd[HTTP_HDR_STATUS].e = p; hp->hd[HTTP_HDR_STATUS].e = p;
WSLH(w, HTTP_T_Status, fd, hp, HTTP_HDR_STATUS); WSLH(w, HTTP_T_Status, htc->fd, hp, HTTP_HDR_STATUS);
*p++ = '\0'; *p++ = '\0';
/* Next find the response */ /* Next find the response */
...@@ -502,11 +510,12 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd) ...@@ -502,11 +510,12 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
continue; continue;
*q = '\0'; *q = '\0';
hp->hd[HTTP_HDR_RESPONSE].e = q; hp->hd[HTTP_HDR_RESPONSE].e = q;
WSLH(w, HTTP_T_Response, fd, hp, HTTP_HDR_RESPONSE); WSLH(w, HTTP_T_Response, htc->fd, hp, HTTP_HDR_RESPONSE);
p++; p++;
return (http_dissect_hdrs(w, hp, fd, p)); return (http_dissect_hdrs(w, hp, htc->fd, p, htc->rxbuf));
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void void
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
* HTTP protocol requests * HTTP protocol requests
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
...@@ -39,8 +41,7 @@ ...@@ -39,8 +41,7 @@
#include "cache.h" #include "cache.h"
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Check if we have a complete HTTP request or response yet between the * Check if we have a complete HTTP request or response yet
* two pointers given.
* *
* Return values: * Return values:
* -1 No, and you can nuke the (white-space) content. * -1 No, and you can nuke the (white-space) content.
...@@ -49,19 +50,19 @@ ...@@ -49,19 +50,19 @@
*/ */
static int static int
http_header_complete(const char *b, const char *e) htc_header_complete(txt *t)
{ {
const char *p; const char *p;
AN(b); Tcheck(*t);
AN(e); assert(*t->e == '\0');
assert(b <= e);
assert(*e == '\0');
/* Skip any leading white space */ /* Skip any leading white space */
for (p = b ; isspace(*p); p++) for (p = t->b ; isspace(*p); p++)
continue; continue;
if (*p == '\0') if (*p == '\0') {
return (-1); t->e = t->b;
return (0);
}
while (1) { while (1) {
p = strchr(p, '\n'); p = strchr(p, '\n');
if (p == NULL) if (p == NULL)
...@@ -73,169 +74,109 @@ http_header_complete(const char *b, const char *e) ...@@ -73,169 +74,109 @@ http_header_complete(const char *b, const char *e)
break; break;
} }
p++; p++;
return (p - b); return (p - t->b);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void void
http_RecvPrep(struct http *hp) HTC_Init(struct http_conn *htc, struct ws *ws, int fd)
{ {
unsigned l;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); htc->magic = HTTP_CONN_MAGIC;
WS_Assert(hp->ws); htc->ws = ws;
WS_Reset(hp->ws); htc->fd = fd;
WS_Reserve(hp->ws, 0); WS_Reset(htc->ws);
hp->rx.b = hp->ws->f; WS_Reserve(htc->ws, (htc->ws->e - htc->ws->s) / 2);
hp->rx.e = hp->rx.b; htc->rxbuf.b = ws->f;
if (hp->pl.b != NULL) { htc->rxbuf.e = ws->f;
l = Tlen(hp->pl); htc->pipeline.b = NULL;
memmove(hp->rx.b, hp->pl.b, l); htc->pipeline.e = NULL;
hp->rx.e = hp->rx.b + l;
hp->pl.b = hp->pl.e = NULL;
}
*hp->rx.e = '\0';
} }
/*--------------------------------------------------------------------
* 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.
*/
int int
http_RecvPrepAgain(struct http *hp) HTC_Reinit(struct http_conn *htc)
{ {
unsigned l;
int i; int i;
http_RecvPrep(hp); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
if (hp->rx.b == hp->rx.e) WS_Reset(htc->ws);
return (0); WS_Reserve(htc->ws, (htc->ws->e - htc->ws->s) / 2);
i = http_header_complete(hp->rx.b, hp->rx.e); htc->rxbuf.b = htc->ws->f;
if (i == -1) htc->rxbuf.e = htc->ws->f;
hp->rx.e = hp->rx.b; if (htc->pipeline.b != NULL) {
if (i <= 0) l = Tlen(htc->pipeline);
return (0); memmove(htc->rxbuf.b, htc->pipeline.b, l);
WS_ReleaseP(hp->ws, hp->rx.e); htc->rxbuf.e += l;
if (hp->rx.e != hp->rx.b + i) { htc->pipeline.b = NULL;
hp->pl.b = hp->rx.b + i; htc->pipeline.e = NULL;
hp->pl.e = hp->rx.e;
hp->rx.e = hp->pl.b;
} }
*htc->rxbuf.e = '\0';
i = htc_header_complete(&htc->rxbuf);
return (i); return (i);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
int int
http_RecvSome(int fd, struct http *hp) HTC_Rx(struct http_conn *htc)
{ {
unsigned l;
int i; int i;
l = pdiff(hp->rx.e, hp->ws->e) - 1; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
l /= 2; /* Don't fill all of workspace with read-ahead */ i = (htc->ws->r - htc->rxbuf.e) - 1; /* space for NUL */
if (l <= 1) { assert(i > 0);
VSL(SLT_HttpError, fd, "Received too much"); i = read(htc->fd, htc->rxbuf.e, i);
VSLR(SLT_HttpGarbage, fd, hp->rx); if (i < 0) {
hp->rx.b = hp->rx.e = NULL; WS_ReleaseP(htc->ws, htc->rxbuf.b);
WS_Release(hp->ws, 0); return (-1);
return (1);
} }
errno = 0; htc->rxbuf.e += i;
i = read(fd, hp->rx.e, l - 1); *htc->rxbuf.e = '\0';
if (i > 0) { i = htc_header_complete(&htc->rxbuf);
hp->rx.e += i; if (i == 0)
*hp->rx.e = '\0';
i = http_header_complete(hp->rx.b, hp->rx.e);
if (i == -1)
hp->rx.e = hp->rx.b;
if (i == 0)
return (-1);
WS_ReleaseP(hp->ws, hp->rx.e);
if (hp->rx.e != hp->rx.b + i) {
hp->pl.b = hp->rx.b + i;
hp->pl.e = hp->rx.e;
hp->rx.e = hp->pl.b;
}
return (0); return (0);
WS_ReleaseP(htc->ws, htc->rxbuf.e);
if (htc->rxbuf.b + i < htc->rxbuf.e) {
htc->pipeline.b = htc->rxbuf.b + i;
htc->pipeline.e = htc->rxbuf.e;
htc->rxbuf.e = htc->pipeline.b;
} }
if (hp->rx.e != hp->rx.b) {
VSL(SLT_HttpError, fd,
"Received (only) %d bytes, errno %d",
hp->rx.e - hp->rx.b, errno);
VSLR(SLT_Debug, fd, hp->rx);
} else if (errno == 0)
VSL(SLT_HttpError, fd, "Received nothing");
else
VSL(SLT_HttpError, fd, "Received errno %d", errno);
hp->rx.b = hp->rx.e = NULL;
WS_Release(hp->ws, 0);
return(2);
}
/*--------------------------------------------------------------------*/
int
http_RecvHead(struct http *hp, int fd)
{
int i;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
http_RecvPrep(hp);
do
i = http_RecvSome(fd, hp);
while (i == -1);
return (i);
}
/*--------------------------------------------------------------------*/
int
http_GetTail(struct http *hp, unsigned len, char **b, char **e)
{
if (hp->pl.b >= hp->pl.e)
return (0);
if (len == 0)
len = Tlen(hp->pl);
if (hp->pl.b + len > hp->pl.e)
len = Tlen(hp->pl);
if (len == 0)
return (0);
*b = hp->pl.b;
*e = hp->pl.b + len;
hp->pl.b += len;
Tcheck(hp->pl);
return (1); return (1);
} }
/*--------------------------------------------------------------------*/
/* Read from fd, but soak up any tail first */
int int
http_Read(struct http *hp, int fd, void *p, unsigned len) HTC_Read(struct http_conn *htc, void *d, unsigned len)
{ {
unsigned l;
unsigned char *p;
int i; int i;
unsigned u;
char *b = p; l = 0;
p = d;
u = 0; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
if (hp->pl.b < hp->pl.e) { if (htc->pipeline.b) {
u = Tlen(hp->pl); l = Tlen(htc->pipeline);
if (u > len) if (l > len)
u = len; l = len;
memcpy(b, hp->pl.b, u); memcpy(p, htc->pipeline.b, l);
hp->pl.b += u; p += l;
b += u; len -= l;
len -= u; htc->pipeline.b += l;
} if (htc->pipeline.b == htc->pipeline.e)
if (hp->pl.e == hp->pl.b) htc->pipeline.b = htc->pipeline.e = NULL;
hp->pl.b = hp->pl.e = NULL;
if (len > 0) {
i = read(fd, b, len);
if (i < 0) /* XXX i == 0 ?? */
return (i);
u += i;
} }
return (u); if (len == 0)
return (l);
i = read(htc->fd, p, len);
if (i < 0)
return (i);
return (i + l);
} }
...@@ -70,7 +70,6 @@ void ...@@ -70,7 +70,6 @@ void
PipeSession(struct sess *sp) PipeSession(struct sess *sp)
{ {
struct vbe_conn *vc; struct vbe_conn *vc;
char *b, *e;
struct worker *w; struct worker *w;
struct bereq *bereq; struct bereq *bereq;
struct pollfd fds[2]; struct pollfd fds[2];
...@@ -89,8 +88,8 @@ PipeSession(struct sess *sp) ...@@ -89,8 +88,8 @@ PipeSession(struct sess *sp)
WRK_Reset(w, &vc->fd); WRK_Reset(w, &vc->fd);
http_Write(w, bereq->http, 0); http_Write(w, bereq->http, 0);
if (http_GetTail(sp->http, 0, &b, &e) && b != e) if (sp->htc->pipeline.b != NULL)
WRK_Write(w, b, e - b); WRK_Write(w, sp->htc->pipeline.b, Tlen(sp->htc->pipeline));
if (WRK_Flush(w)) { if (WRK_Flush(w)) {
vca_close_session(sp, "pipe"); vca_close_session(sp, "pipe");
......
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