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

Wrap the management of the session workspace in functions, to prevent

pointer gymnastics getting out of hand.

In addition to the obvious alloc/return primitives there are also 
reserve/release primitives for when we don't know the length yet.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1498 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent f54ff6ba
...@@ -29,6 +29,7 @@ varnishd_SOURCES = \ ...@@ -29,6 +29,7 @@ varnishd_SOURCES = \
cache_vrt.c \ cache_vrt.c \
cache_vrt_acl.c \ cache_vrt_acl.c \
cache_vrt_re.c \ cache_vrt_re.c \
cache_ws.c \
hash_simple_list.c \ hash_simple_list.c \
hash_classic.c \ hash_classic.c \
mgt_child.c \ mgt_child.c \
......
...@@ -76,9 +76,30 @@ enum step { ...@@ -76,9 +76,30 @@ enum step {
#undef STEP #undef STEP
}; };
/*--------------------------------------------------------------------
* Workspace structure for quick memory allocation.
*/
struct ws {
char *s; /* (S)tart of buffer */
char *e; /* (E)nd of buffer */
char *f; /* (F)ree pointer */
char *r; /* (R)eserved length */
};
void WS_Init(struct ws *ws, void *space, unsigned len);
unsigned WS_Reserve(struct ws *ws, unsigned bytes);
void WS_Release(struct ws *ws, unsigned bytes);
void WS_ReleaseP(struct ws *ws, char *ptr);
void WS_Assert(struct ws *ws);
void WS_Reset(struct ws *ws);
char *WS_Alloc(struct ws *ws, unsigned bytes);
void WS_Return(struct ws *ws, char *b, char *e);
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* HTTP Request/Response/Header handling structure. * HTTP Request/Response/Header handling structure.
* RSN: struct worker and struct session will have one of these embedded.
*/ */
struct http_hdr { struct http_hdr {
...@@ -90,11 +111,9 @@ struct http { ...@@ -90,11 +111,9 @@ struct http {
unsigned magic; unsigned magic;
#define HTTP_MAGIC 0x6428b5c9 #define HTTP_MAGIC 0x6428b5c9
char *s; /* (S)tart of buffer */ struct ws ws[1];
char *t; /* start of (T)railing data */ char *rx_s, *rx_e; /* Received Request */
char *v; /* end of (V)alid bytes */ char *pl_s, *pl_e; /* Pipelined bytes */
char *f; /* first (F)ree byte */
char *e; /* (E)nd of buffer */
unsigned char conds; /* If-* headers present */ unsigned char conds; /* If-* headers present */
enum httpwhence { enum httpwhence {
......
...@@ -214,7 +214,7 @@ cnt_done(struct sess *sp) ...@@ -214,7 +214,7 @@ cnt_done(struct sess *sp)
sp->step = STP_RECV; sp->step = STP_RECV;
return (0); return (0);
} }
if (sp->http->t < sp->http->v) { if (sp->http->pl_s < sp->http->pl_e) {
VSL_stats->sess_readahead++; VSL_stats->sess_readahead++;
sp->step = STP_AGAIN; sp->step = STP_AGAIN;
return (0); return (0);
...@@ -426,13 +426,12 @@ cnt_lookup(struct sess *sp) ...@@ -426,13 +426,12 @@ cnt_lookup(struct sess *sp)
{ {
struct object *o; struct object *o;
assert(sp->http->f > sp->http->s);
assert(sp->http->f >= sp->http->t);
if (sp->obj == NULL) { if (sp->obj == NULL) {
sp->hash_b = sp->http->f; WS_Reserve(sp->http->ws, 0);
sp->hash_b = sp->http->ws->f;
sp->hash_e = sp->hash_b; sp->hash_e = sp->hash_b;
VCL_hash_method(sp); /* XXX: no-op for now */ VCL_hash_method(sp); /* XXX: no-op for now */
WS_ReleaseP(sp->http->ws, sp->hash_e);
/* XXX check error */ /* XXX check error */
} }
...@@ -449,12 +448,7 @@ cnt_lookup(struct sess *sp) ...@@ -449,12 +448,7 @@ cnt_lookup(struct sess *sp)
return (1); return (1);
} }
xxxassert (sp->hash_e == sp->http->f); WS_Return(sp->http->ws, sp->hash_b, sp->hash_e);
if (sp->hash_e == sp->http->f) {
/* Nobody alloc'ed after us, free again */
sp->http->f = sp->hash_b;
}
sp->hash_b = sp->hash_e = NULL; sp->hash_b = sp->hash_e = NULL;
sp->obj = o; sp->obj = o;
......
...@@ -251,8 +251,8 @@ HSH_Deref(struct object *o) ...@@ -251,8 +251,8 @@ HSH_Deref(struct object *o)
if (r != 0) if (r != 0)
return; return;
if (o->http.s != NULL) if (o->http.ws->s != NULL)
free(o->http.s); free(o->http.ws->s);
HSH_Freestore(o); HSH_Freestore(o);
free(o); free(o);
......
...@@ -164,16 +164,11 @@ http_StatusMessage(int status) ...@@ -164,16 +164,11 @@ http_StatusMessage(int status)
void void
http_Setup(struct http *hp, void *space, unsigned len) http_Setup(struct http *hp, void *space, unsigned len)
{ {
char *sp = space;
assert(len > 0); assert(len > 0);
memset(hp, 0, sizeof *hp); memset(hp, 0, sizeof *hp);
hp->magic = HTTP_MAGIC; hp->magic = HTTP_MAGIC;
hp->s = sp; WS_Init(hp->ws, space, len);
hp->t = sp;
hp->v = sp;
hp->f = sp;
hp->e = sp + len;
hp->nhd = HTTP_HDR_FIRST; hp->nhd = HTTP_HDR_FIRST;
} }
...@@ -329,20 +324,20 @@ int ...@@ -329,20 +324,20 @@ int
http_GetTail(struct http *hp, unsigned len, char **b, char **e) http_GetTail(struct http *hp, unsigned len, char **b, char **e)
{ {
if (hp->t >= hp->v) if (hp->pl_s >= hp->pl_e)
return (0); return (0);
if (len == 0) if (len == 0)
len = hp->v - hp->t; len = hp->pl_e - hp->pl_e;
if (hp->t + len > hp->v) if (hp->pl_s + len > hp->pl_e)
len = hp->v - hp->t; len = hp->pl_e - hp->pl_s;
if (len == 0) if (len == 0)
return (0); return (0);
*b = hp->t; *b = hp->pl_s;
*e = hp->t + len; *e = hp->pl_s + len;
hp->t += len; hp->pl_s += len;
assert(hp->t <= hp->v); assert(hp->pl_s <= hp->pl_e);
return (1); return (1);
} }
...@@ -357,15 +352,16 @@ http_Read(struct http *hp, int fd, void *p, unsigned len) ...@@ -357,15 +352,16 @@ http_Read(struct http *hp, int fd, void *p, unsigned len)
char *b = p; char *b = p;
u = 0; u = 0;
if (hp->t < hp->v) { if (hp->pl_s < hp->pl_e) {
u = hp->v - hp->t; u = hp->pl_e - hp->pl_s;
if (u > len) if (u > len)
u = len; u = len;
memcpy(b, hp->t, u); memcpy(b, hp->pl_s, u);
hp->t += u; hp->pl_s += u;
b += u; b += u;
len -= u; len -= u;
} }
hp->pl_s = hp->pl_e = NULL;
if (len > 0) { if (len > 0) {
i = read(fd, b, len); i = read(fd, b, len);
if (i < 0) if (i < 0)
...@@ -417,8 +413,8 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p) ...@@ -417,8 +413,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->v); /* http_header_complete() guarantees this */ assert(p < hp->rx_e); /* http_header_complete() guarantees this */
for (; p < hp->v; p = r) { for (; p < hp->rx_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);
...@@ -445,8 +441,6 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p) ...@@ -445,8 +441,6 @@ http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
WSLR(w, http2shmlog(hp, HTTP_T_LostHeader), fd, p, q); WSLR(w, http2shmlog(hp, HTTP_T_LostHeader), fd, p, q);
} }
} }
assert(hp->t <= hp->v);
assert(hp->t == r);
return (0); return (0);
} }
...@@ -458,12 +452,11 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -458,12 +452,11 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
char *p; char *p;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
AN(hp->t); /* Assert a NUL at rx_e */
assert(hp->s < hp->t); assert(hp->rx_s < hp->rx_e);
assert(hp->t <= hp->v);
hp->logtag = HTTP_Rx; hp->logtag = HTTP_Rx;
for (p = hp->s ; isspace(*p); p++) for (p = hp->rx_s ; isspace(*p); p++)
continue; continue;
/* First, the request type (GET/HEAD etc) */ /* First, the request type (GET/HEAD etc) */
...@@ -478,7 +471,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -478,7 +471,7 @@ 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->s, hp->v); WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
return (400); return (400);
} }
hp->hd[HTTP_HDR_URL].b = p; hp->hd[HTTP_HDR_URL].b = p;
...@@ -487,7 +480,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -487,7 +480,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd)
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(w, HTTP_T_URL, fd, hp, HTTP_HDR_URL);
if (*p == '\n') { if (*p == '\n') {
WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v); WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
return (400); return (400);
} }
*p++ = '\0'; *p++ = '\0';
...@@ -496,7 +489,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -496,7 +489,7 @@ 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->s, hp->v); WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
return (400); return (400);
} }
hp->hd[HTTP_HDR_PROTO].b = p; hp->hd[HTTP_HDR_PROTO].b = p;
...@@ -509,7 +502,7 @@ http_DissectRequest(struct worker *w, struct http *hp, int fd) ...@@ -509,7 +502,7 @@ 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->s, hp->v); WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
return (400); return (400);
} }
*p++ = '\0'; *p++ = '\0';
...@@ -525,16 +518,15 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd) ...@@ -525,16 +518,15 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
char *p, *q; char *p, *q;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
AN(hp->t); /* Assert a NUL at rx_e */
assert(hp->s < hp->t); assert(hp->rx_s < hp->rx_e);
assert(hp->t <= hp->v);
hp->logtag = HTTP_Rx; hp->logtag = HTTP_Rx;
for (p = hp->s ; isspace(*p); p++) for (p = hp->rx_s ; isspace(*p); p++)
continue; continue;
if (memcmp(p, "HTTP/1.", 7)) { if (memcmp(p, "HTTP/1.", 7)) {
WSLR(w, SLT_HttpGarbage, fd, hp->s, hp->v); WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
return (400); return (400);
} }
/* First, protocol */ /* First, protocol */
...@@ -572,7 +564,9 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd) ...@@ -572,7 +564,9 @@ http_DissectResponse(struct worker *w, struct http *hp, int fd)
return (http_dissect_hdrs(w, hp, fd, p)); return (http_dissect_hdrs(w, hp, fd, p));
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------
* Return nonzero if we have a complete HTTP request.
*/
static int static int
http_header_complete(struct http *hp) http_header_complete(struct http *hp)
...@@ -580,33 +574,33 @@ http_header_complete(struct http *hp) ...@@ -580,33 +574,33 @@ http_header_complete(struct http *hp)
char *p; char *p;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
assert(hp->v <= hp->e); assert(*hp->rx_e == '\0');
assert(*hp->v == '\0');
/* Skip any leading white space */ /* Skip any leading white space */
for (p = hp->s ; p < hp->v && isspace(*p); p++) for (p = hp->rx_s ; p < hp->rx_e && isspace(*p); p++)
continue; continue;
if (p >= hp->v) { if (p >= hp->rx_e) {
hp->v = hp->s; hp->rx_e = hp->rx_s;
return (0); return (0);
} }
while (1) { while (1) {
/* XXX: we could save location of all linebreaks for later */ /* XXX: we could save location of all linebreaks for later */
p = strchr(p, '\n'); p = strchr(p, '\n');
if (p == NULL) if (p == NULL)
return (0); return (0); /* XXX: Could cache p */
p++; p++;
if (*p == '\r') if (*p == '\r')
p++; p++;
if (*p != '\n') if (*p == '\n')
continue; break;
break;
} }
if (++p > hp->v) p++;
return (0); WS_ReleaseP(hp->ws, hp->rx_e);
hp->t = p; if (p != hp->rx_e) {
assert(hp->t > hp->s); hp->pl_s = p;
assert(hp->t <= hp->v); hp->pl_e = hp->rx_e;
hp->f = hp->v; hp->rx_e = p;
}
/* XXX: Check this stuff... */
return (1); return (1);
} }
...@@ -618,25 +612,26 @@ http_RecvPrep(struct http *hp) ...@@ -618,25 +612,26 @@ http_RecvPrep(struct http *hp)
unsigned l; unsigned l;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
assert(hp->v <= hp->e); WS_Assert(hp->ws);
assert(hp->t <= hp->v); WS_Reset(hp->ws);
if (hp->t > hp->s && hp->t < hp->v) { WS_Reserve(hp->ws, 0);
l = hp->v - hp->t; hp->rx_s = hp->ws->f;
memmove(hp->s, hp->t, l); hp->rx_e = hp->rx_s;
hp->v = hp->s + l; if (hp->pl_s != NULL) {
hp->t = hp->s; assert(hp->pl_s < hp->pl_e);
*hp->v = '\0'; l = hp->pl_e - hp->pl_s;
} else { memmove(hp->rx_s, hp->pl_s, l);
hp->v = hp->s; hp->rx_e = hp->rx_s + l;
hp->t = hp->s; hp->pl_s = hp->pl_e = NULL;
} }
*hp->rx_e = '\0';
} }
int int
http_RecvPrepAgain(struct http *hp) http_RecvPrepAgain(struct http *hp)
{ {
http_RecvPrep(hp); http_RecvPrep(hp);
if (hp->v == hp->s) if (hp->rx_s == hp->rx_e)
return (0); return (0);
return (http_header_complete(hp)); return (http_header_complete(hp));
} }
...@@ -649,38 +644,35 @@ http_RecvSome(int fd, struct http *hp) ...@@ -649,38 +644,35 @@ http_RecvSome(int fd, struct http *hp)
unsigned l; unsigned l;
int i; int i;
l = (hp->e - hp->s) / 2; l = (hp->ws->e - hp->rx_e) - 1;
if (l < hp->v - hp->s)
l = 0;
else
l -= hp->v - hp->s;
if (l <= 1) { if (l <= 1) {
VSL(SLT_HttpError, fd, "Received too much"); VSL(SLT_HttpError, fd, "Received too much");
VSLR(SLT_HttpGarbage, fd, hp->s, hp->v); VSLR(SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
hp->t = NULL; hp->rx_s = hp->rx_e = NULL;
WS_Release(hp->ws, 0);
return (1); return (1);
} }
errno = 0; errno = 0;
i = read(fd, hp->v, l - 1); i = read(fd, hp->rx_e, l - 1);
if (i > 0) { if (i > 0) {
hp->v += i; hp->rx_e += i;
*hp->v = '\0'; *hp->rx_e = '\0';
if (http_header_complete(hp)) if (http_header_complete(hp))
return(0); return(0);
return (-1); return (-1);
} }
if (hp->v != hp->s) { if (hp->rx_e != hp->rx_s) {
VSL(SLT_HttpError, fd, VSL(SLT_HttpError, fd,
"Received (only) %d bytes, errno %d", "Received (only) %d bytes, errno %d",
hp->v - hp->s, errno); hp->rx_e - hp->rx_s, errno);
VSLR(SLT_Debug, fd, hp->s, hp->v); VSLR(SLT_Debug, fd, hp->rx_s, hp->rx_e);
} else if (errno == 0) } else if (errno == 0)
VSL(SLT_HttpError, fd, "Received nothing"); VSL(SLT_HttpError, fd, "Received nothing");
else else
VSL(SLT_HttpError, fd, VSL(SLT_HttpError, fd, "Received errno %d", errno);
"Received errno %d", errno); hp->rx_s = hp->rx_e = NULL;
hp->t = NULL; WS_Release(hp->ws, 0);
return(2); return(2);
} }
...@@ -707,6 +699,7 @@ void ...@@ -707,6 +699,7 @@ void
http_CopyHttp(struct http *to, struct http *fm) http_CopyHttp(struct http *to, struct http *fm)
{ {
unsigned u, l; unsigned u, l;
char *p;
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC); CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
...@@ -717,10 +710,10 @@ http_CopyHttp(struct http *to, struct http *fm) ...@@ -717,10 +710,10 @@ http_CopyHttp(struct http *to, struct http *fm)
AN(fm->hd[u].e); AN(fm->hd[u].e);
l += (fm->hd[u].e - fm->hd[u].b) + 1; l += (fm->hd[u].e - fm->hd[u].b) + 1;
} }
to->s = malloc(l); p = malloc(l);
XXXAN(to->s); XXXAN(p);
to->e = to->s + l; WS_Init(to->ws, p, l);
to->f = to->s; WS_Reserve(to->ws, 0);
for (u = 0; u < fm->nhd; u++) { for (u = 0; u < fm->nhd; u++) {
if (fm->hd[u].b == NULL) if (fm->hd[u].b == NULL)
continue; continue;
...@@ -728,12 +721,13 @@ http_CopyHttp(struct http *to, struct http *fm) ...@@ -728,12 +721,13 @@ http_CopyHttp(struct http *to, struct http *fm)
assert(*fm->hd[u].e == '\0'); assert(*fm->hd[u].e == '\0');
l = fm->hd[u].e - fm->hd[u].b; l = fm->hd[u].e - fm->hd[u].b;
assert(l == strlen(fm->hd[u].b)); assert(l == strlen(fm->hd[u].b));
memcpy(to->f, fm->hd[u].b, l); memcpy(p, fm->hd[u].b, l);
to->hd[u].b = to->f; to->hd[u].b = p;
to->hd[u].e = to->f + l; to->hd[u].e = p + l;
*to->hd[u].e = '\0'; *to->hd[u].e = '\0';
to->f += l + 1; p += l + 1;
} }
/* XXX: Leave to->ws reserved for now */
to->nhd = fm->nhd; to->nhd = fm->nhd;
} }
...@@ -860,7 +854,7 @@ http_ClrHeader(struct http *to) ...@@ -860,7 +854,7 @@ http_ClrHeader(struct http *to)
{ {
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
to->f = to->v; /* XXX ??? to->f = to->v; Not sure this is valid */
to->nhd = HTTP_HDR_FIRST; to->nhd = HTTP_HDR_FIRST;
memset(to->hd, 0, sizeof to->hd); memset(to->hd, 0, sizeof to->hd);
} }
...@@ -882,46 +876,45 @@ http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr) ...@@ -882,46 +876,45 @@ http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void static void
http_PutProtocol(struct worker *w, int fd, struct http *to, const char *protocol) http_PutField(struct http *to, int field, const char *string)
{ {
char *e, *p;
int l; int l;
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
l = strlcpy(to->f, protocol, to->e - to->f); e = strchr(string, '\0');
xxxassert(to->f + l < to->e); l = (e - string);
to->hd[HTTP_HDR_PROTO].b = to->f; p = WS_Alloc(to->ws, l + 1);
to->hd[HTTP_HDR_PROTO].e = to->f + l; memcpy(p, string, l + 1);
to->f += l + 1; to->hd[field].b = p;
to->hd[field].e = p + l;
}
void
http_PutProtocol(struct worker *w, int fd, struct http *to, const char *protocol)
{
http_PutField(to, HTTP_HDR_PROTO, protocol);
WSLH(w, HTTP_T_Protocol, fd, to, HTTP_HDR_PROTO); WSLH(w, HTTP_T_Protocol, fd, to, HTTP_HDR_PROTO);
} }
void void
http_PutStatus(struct worker *w, int fd, struct http *to, int status) http_PutStatus(struct worker *w, int fd, struct http *to, int status)
{ {
int l; char stat[4];
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); assert(status >= 0 && status <= 999);
assert(status >= 100 && status <= 999); sprintf(stat, "%d", status);
l = snprintf(to->f, to->e - to->f, "%d", status); http_PutField(to, HTTP_HDR_STATUS, stat);
xxxassert(to->f + l < to->e);
to->hd[HTTP_HDR_STATUS].b = to->f;
to->hd[HTTP_HDR_STATUS].e = to->f + l;
to->f += l + 1;
WSLH(w, HTTP_T_Status, fd, to, HTTP_HDR_STATUS); WSLH(w, HTTP_T_Status, fd, to, HTTP_HDR_STATUS);
} }
void void
http_PutResponse(struct worker *w, int fd, struct http *to, const char *response) http_PutResponse(struct worker *w, int fd, struct http *to, const char *response)
{ {
int l;
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); http_PutField(to, HTTP_HDR_RESPONSE, response);
l = strlcpy(to->f, response, to->e - to->f);
xxxassert(to->f + l < to->e);
to->hd[HTTP_HDR_RESPONSE].b = to->f;
to->hd[HTTP_HDR_RESPONSE].e = to->f + l;
to->f += l + 1;
WSLH(w, HTTP_T_Response, fd, to, HTTP_HDR_RESPONSE); WSLH(w, HTTP_T_Response, fd, to, HTTP_HDR_RESPONSE);
} }
...@@ -932,18 +925,18 @@ http_PrintfHeader(struct worker *w, int fd, struct http *to, const char *fmt, .. ...@@ -932,18 +925,18 @@ http_PrintfHeader(struct worker *w, int fd, struct http *to, const char *fmt, ..
unsigned l, n; unsigned l, n;
CHECK_OBJ_NOTNULL(to, HTTP_MAGIC); CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
l = to->e - to->f; l = WS_Reserve(to->ws, 0);
va_start(ap, fmt); va_start(ap, fmt);
n = vsnprintf(to->f, l, fmt, ap); n = vsnprintf(to->ws->f, l, fmt, ap);
va_end(ap); va_end(ap);
if (n >= l || to->nhd >= HTTP_HDR_MAX) { if (n + 1 >= l || to->nhd >= HTTP_HDR_MAX) {
VSL_stats->losthdr++; VSL_stats->losthdr++;
WSL(w, http2shmlog(to, HTTP_T_LostHeader), fd, "%s", to->f); WSL(w, http2shmlog(to, HTTP_T_LostHeader), fd, "%s", to->ws->f);
WS_Release(to->ws, 0);
} else { } else {
assert(to->f < to->e); to->hd[to->nhd].b = to->ws->f;
to->hd[to->nhd].b = to->f; to->hd[to->nhd].e = to->ws->f + n;
to->hd[to->nhd].e = to->f + n; WS_Release(to->ws, n + 1);
to->f += n + 1;
WSLH(w, HTTP_T_Header, fd, to, to->nhd); WSLH(w, HTTP_T_Header, fd, to, to->nhd);
to->nhd++; to->nhd++;
} }
......
...@@ -57,7 +57,6 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl) ...@@ -57,7 +57,6 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl)
const char *msg; const char *msg;
char date[40]; char date[40];
time_t now; time_t now;
size_t len;
int fd; int fd;
assert(status >= 100 && status <= 999); assert(status >= 100 && status <= 999);
...@@ -122,10 +121,8 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl) ...@@ -122,10 +121,8 @@ SYN_ErrorPage(struct sess *sp, int status, const char *reason, int ttl)
vsb_delete(&vsb); vsb_delete(&vsb);
/* allocate space for header */ /* allocate space for header */
/* XXX what if the object already has a header? */
h->v = h->s = calloc(len = 1024, 1); WS_Init(h->ws, malloc(1024), 1024);
XXXAN(h->s);
h->e = h->s + len;
/* generate header */ /* generate header */
http_ClrHeader(h); http_ClrHeader(h);
......
...@@ -284,10 +284,8 @@ VRT_l_req_hash(struct sess *sp, const char *str) ...@@ -284,10 +284,8 @@ VRT_l_req_hash(struct sess *sp, const char *str)
if (str == NULL) if (str == NULL)
str = ""; str = "";
l = strlen(str); l = strlen(str);
xxxassert (sp->hash_e == sp->http->f); xxxassert (sp->hash_e + l + 1 <= sp->http->ws->e);
xxxassert (sp->hash_e + l + 1 <= sp->http->e);
memcpy(sp->hash_e, str, l); memcpy(sp->hash_e, str, l);
sp->hash_e[l] = '#'; sp->hash_e[l] = '#';
sp->hash_e += l + 1; sp->hash_e += l + 1;
sp->http->f += l + 1;
} }
/*-
* Copyright (c) 2006 Verdens Gang AS
* Copyright (c) 2006 Linpro AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*
*/
#include <sys/types.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "heritage.h"
#include "shmlog.h"
#include "vcl.h"
#include "cli_priv.h"
#include "cache.h"
void
WS_Assert(struct ws *ws)
{
assert(ws != NULL);
assert(ws->s != NULL);
assert(ws->e != NULL);
assert(ws->s < ws->e);
assert(ws->f >= ws->s);
assert(ws->f <= ws->e);
if (ws->r) {
assert(ws->r > ws->s);
assert(ws->r <= ws->e);
}
}
void
WS_Init(struct ws *ws, void *space, unsigned len)
{
assert(space != NULL);
memset(ws, 0, sizeof *ws);
ws->s = space;
ws->e = ws->s + len;
ws->f = ws->s;
WS_Assert(ws);
}
void
WS_Reset(struct ws *ws)
{
WS_Assert(ws);
assert(ws->r == NULL);
ws->f = ws->s;
}
char *
WS_Alloc(struct ws *ws, unsigned bytes)
{
char *r;
WS_Assert(ws);
assert(ws->r == NULL);
xxxassert(ws->f + bytes <= ws->e);
r = ws->f;
ws->f += bytes;
return (r);
}
unsigned
WS_Reserve(struct ws *ws, unsigned bytes)
{
WS_Assert(ws);
assert(ws->r == NULL);
if (bytes == 0)
bytes = ws->e - ws->f;
xxxassert(ws->f + bytes <= ws->e);
ws->r = ws->f + bytes;
return (ws->r - ws->f);
}
void
WS_Release(struct ws *ws, unsigned bytes)
{
WS_Assert(ws);
assert(ws->r != NULL);
assert(ws->f + bytes <= ws->r);
ws->f += bytes;
ws->r = NULL;
}
void
WS_ReleaseP(struct ws *ws, char *ptr)
{
WS_Assert(ws);
assert(ws->r != NULL);
assert(ptr >= ws->f);
assert(ptr <= ws->r);
ws->f = ptr;
ws->r = NULL;
}
void
WS_Return(struct ws *ws, char *s, char *e)
{
WS_Assert(ws);
if (e == ws->f)
ws->f = s;
}
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