[4.0] 47d66bb Introduce http->failed to mark struct http's suffering from trouble.
Poul-Henning Kamp
phk at FreeBSD.org
Tue Jun 24 11:31:54 CEST 2014
commit 47d66bb472669e4def4c180cd349e0552d3b4451
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Jun 3 11:55:18 2014 +0000
Introduce http->failed to mark struct http's suffering from trouble.
Usually, (probably always) this means failure to get workspace for
modifications of the http.
The intent is that this flag will have the same "latching" behaviour
as error handling in VSB's: Once set, it stays set and nobody
reads or writes the struct http any more.
Setting the flag causes a SLT_Error message.
Rewrite http_CollectHdr() to respect failed and optimize it
slightly while were here.
diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index a82ea69..979eedd 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -202,6 +202,7 @@ struct http {
uint16_t status;
uint8_t protover;
uint8_t conds; /* If-* headers present */
+ uint8_t failed; /* usually: ws-alloc failed */
};
/*--------------------------------------------------------------------
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 88ff577..49522cd 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -93,6 +93,15 @@ http_VSL_log(const struct http *hp)
}
/*--------------------------------------------------------------------*/
+
+static void
+http_fail(struct http *hp)
+{
+ VSLb(hp->vsl, SLT_Error, "out of workspace");
+ hp->failed = 1;
+}
+
+/*--------------------------------------------------------------------*/
/* List of canonical HTTP response code names from RFC2616 */
static struct http_msg {
@@ -146,12 +155,17 @@ HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
enum VSL_tag_e whence)
{
http_Teardown(hp);
+ hp->nhd = HTTP_HDR_FIRST;
hp->logtag = whence;
hp->ws = ws;
hp->vsl = vsl;
}
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * http_Teardown() is a safety feature, we use it to zap all http
+ * structs once we're done with them, to minimize the risk that
+ * old stale pointers exist to no longer valid stuff.
+ */
void
http_Teardown(struct http *hp)
@@ -162,7 +176,6 @@ http_Teardown(struct http *hp)
memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
- hp->nhd = HTTP_HDR_FIRST;
}
/*--------------------------------------------------------------------*/
@@ -181,6 +194,26 @@ http_IsHdr(const txt *hh, const char *hdr)
return (!strncasecmp(hdr, hh->b, l));
}
+/*--------------------------------------------------------------------*/
+
+static unsigned
+http_findhdr(const struct http *hp, unsigned l, const char *hdr)
+{
+ unsigned u;
+
+ for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
+ Tcheck(hp->hd[u]);
+ if (hp->hd[u].e < hp->hd[u].b + l + 1)
+ continue;
+ if (hp->hd[u].b[l] != ':')
+ continue;
+ if (strncasecmp(hdr, hp->hd[u].b, l))
+ continue;
+ return (u);
+ }
+ return (0);
+}
+
/*--------------------------------------------------------------------
* This function collapses multiple headerlines of the same name.
* The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
@@ -189,57 +222,60 @@ http_IsHdr(const txt *hh, const char *hdr)
void
http_CollectHdr(struct http *hp, const char *hdr)
{
- unsigned u, v, ml, f = 0, x;
+ unsigned u, l, ml, f, x, d;
char *b = NULL, *e = NULL;
- for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
- while (u < hp->nhd && http_IsHdr(&hp->hd[u], hdr)) {
- Tcheck(hp->hd[u]);
- if (f == 0) {
- /* Found first header, just record the fact */
- f = u;
- break;
- }
- if (b == NULL) {
- /* Found second header, start our collection */
- ml = WS_Reserve(hp->ws, 0);
- b = hp->ws->f;
- e = b + ml;
- x = Tlen(hp->hd[f]);
- if (b + x < e) {
- memcpy(b, hp->hd[f].b, x);
- b += x;
- } else
- b = e;
- }
+ if (hp->failed)
+ return;
+ l = hdr[0];
+ assert(l == strlen(hdr + 1));
+ assert(hdr[l] == ':');
+ f = http_findhdr(hp, l - 1, hdr + 1);
+ if (f == 0)
+ return;
- AN(b);
- AN(e);
-
- /* Append the Nth header we found */
- if (b < e)
- *b++ = ',';
- x = Tlen(hp->hd[u]) - *hdr;
- if (b + x < e) {
- memcpy(b, hp->hd[u].b + *hdr, x);
- b += x;
- } else
- b = e;
-
- /* Shift remaining headers up one slot */
- for (v = u; v < hp->nhd - 1; v++)
- hp->hd[v] = hp->hd[v + 1];
- hp->nhd--;
+ for (d = u = f + 1; u < hp->nhd; u++) {
+ Tcheck(hp->hd[u]);
+ if (!http_IsHdr(&hp->hd[u], hdr)) {
+ if (d != u)
+ hp->hd[d] = hp->hd[u];
+ d++;
+ continue;
+ }
+ if (b == NULL) {
+ /* Found second header, start our collection */
+ ml = WS_Reserve(hp->ws, 0);
+ b = hp->ws->f;
+ e = b + ml;
+ x = Tlen(hp->hd[f]);
+ if (b + x >= e) {
+ http_fail(hp);
+ WS_Release(hp->ws, 0);
+ return;
+ }
+ memcpy(b, hp->hd[f].b, x);
+ b += x;
}
+ AN(b);
+ AN(e);
+
+ /* Append the Nth header we found */
+ if (b < e)
+ *b++ = ',';
+ x = Tlen(hp->hd[u]) - l;
+ if (b + x >= e) {
+ http_fail(hp);
+ WS_Release(hp->ws, 0);
+ return;
+ }
+ memcpy(b, hp->hd[u].b + *hdr, x);
+ b += x;
}
if (b == NULL)
return;
+ hp->nhd = (uint16_t)d;
AN(e);
- if (b >= e) {
- WS_Release(hp->ws, 0);
- return;
- }
*b = '\0';
hp->hd[f].b = hp->ws->f;
hp->hd[f].e = b;
@@ -248,24 +284,6 @@ http_CollectHdr(struct http *hp, const char *hdr)
/*--------------------------------------------------------------------*/
-static unsigned
-http_findhdr(const struct http *hp, unsigned l, const char *hdr)
-{
- unsigned u;
-
- for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
- Tcheck(hp->hd[u]);
- if (hp->hd[u].e < hp->hd[u].b + l + 1)
- continue;
- if (hp->hd[u].b[l] != ':')
- continue;
- if (strncasecmp(hdr, hp->hd[u].b, l))
- continue;
- return (u);
- }
- return (0);
-}
-
int
http_GetHdr(const struct http *hp, const char *hdr, char **ptr)
{
More information about the varnish-commit
mailing list