]> err.no Git - varnish/commitdiff
HTTP header munging part (N of M)
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 21 Jul 2006 09:32:09 +0000 (09:32 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 21 Jul 2006 09:32:09 +0000 (09:32 +0000)
NB: Only pass mode (lightly) tested right now.

Give up on the three element array per header and use a two element struct
instead, it reduces obfuscation and removes risk of pointer fandango.

Introduce #defined filtercontrol in http_headers.h, use them in a new
field.  Only Pass is there for now.

Use the http-workspace for building headers instead of sbuf.

Move uiovec handling to cache_pool.c where it more naturally belongs
and so we can use it on both backends and sessions.

Add http header munging functiosn for copying, printf'ing, filtering and
writing headers.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@533 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_center.c
varnish-cache/bin/varnishd/cache_hash.c
varnish-cache/bin/varnishd/cache_http.c
varnish-cache/bin/varnishd/cache_pass.c
varnish-cache/bin/varnishd/cache_pool.c
varnish-cache/bin/varnishd/cache_response.c
varnish-cache/bin/varnishd/cache_vrt.c
varnish-cache/include/http_headers.h

index a1bc5fa3dfa2661afa24a002826784f061912400..f743a654a5df203edc29d14f0bca80456c62dfbc 100644 (file)
 #include "common.h"
 #include "miniobj.h"
 
-#define MAX_IOVS               10
-
 #define MAX_HTTP_HDRS          32
 
+#define MAX_IOVS               (MAX_HTTP_HDRS * 2)
+
 #define HTTP_HDR_REQ           0
 #define HTTP_HDR_URL           1
 #define HTTP_HDR_PROTO         2
 #define HTTP_HDR_RESPONSE      4
 #define HTTP_HDR_FIRST         5
 
-#define HTTP_START             0
-#define HTTP_DATA              1
-#define HTTP_END               2
-
 struct event_base;
 struct cli;
 struct sbuf;
@@ -52,6 +48,11 @@ enum step {
 
 typedef void http_callback_f(void *, int bad);
 
+struct http_hdr {
+       char                    *b;
+       char                    *e;
+};
+
 struct http {
        unsigned                magic;
 #define HTTP_MAGIC             0x6428b5c9
@@ -67,8 +68,9 @@ struct http {
 
        unsigned                conds;          /* If-* headers present */
 
-       char                    *hd[MAX_HTTP_HDRS][HTTP_END + 1];
+       struct http_hdr         hd[MAX_HTTP_HDRS];
        unsigned                nhd;
+       unsigned char           hdf[MAX_HTTP_HDRS];
 };
 
 /*--------------------------------------------------------------------*/
@@ -85,6 +87,8 @@ struct worker {
        pthread_cond_t          cv;
        TAILQ_ENTRY(worker)     list;
 
+       int                     *wfd;
+       unsigned                werr;   /* valid after WRK_Flush() */
        struct iovec            iov[MAX_IOVS];
        unsigned                niov;
        size_t                  liov;
@@ -296,6 +300,13 @@ void HSH_Init(void);
 
 /* cache_http.c */
 void HTTP_Init(void);
+void http_Write(struct worker *w, struct http *hp, int resp);
+void http_CopyReq(int fd, struct http *to, struct http *fm);
+void http_CopyResp(int fd, struct http *to, struct http *fm);
+void http_FilterHeader(int fd, struct http *to, struct http *fm, unsigned how);
+void http_CopyHeader(int fd, struct http *to, struct http *fm, unsigned n);
+void http_PrintfHeader(int fd, struct http *to, const char *fmt, ...);
+int http_IsHdr(struct http_hdr *hh, char *hdr);
 void http_Setup(struct http *ht, void *space, unsigned len);
 int http_GetHdr(struct http *hp, const char *hdr, char **ptr);
 int http_GetHdrField(struct http *hp, const char *hdr, const char *field, char **ptr);
@@ -318,7 +329,7 @@ void http_BuildSbuf(int fd, enum http_build mode, struct sbuf *sb, struct http *
 #undef HTTPH
 
 /* cache_pass.c */
-void PassSession(struct worker *w, struct sess *sp);
+void PassSession(struct sess *sp);
 void PassBody(struct worker *w, struct sess *sp);
 
 /* cache_pipe.c */
@@ -327,6 +338,10 @@ void PipeSession(struct worker *w, struct sess *sp);
 /* cache_pool.c */
 void WRK_Init(void);
 void WRK_QueueSession(struct sess *sp);
+void WRK_Reset(struct worker *w, int *fd);
+int WRK_Flush(struct worker *w);
+void WRK_Write(struct worker *w, const void *ptr, size_t len);
+void WRK_WriteH(struct worker *w, struct http_hdr *hh, const char *suf);
 
 /* cache_session.c [SES] */
 void SES_Init(void);
@@ -352,8 +367,6 @@ void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...);
 
 /* cache_response.c */
 void RES_Error(struct sess *sp, int error, const char *msg);
-void RES_Flush(struct sess *sp);
-void RES_Write(struct sess *sp, const void *ptr, size_t len);
 void RES_WriteObj(struct sess *sp);
 
 /* cache_vcl.c */
index 374801ad5514365475c5b3c619c8dd5c6165f4a3..9ef843884ea7cb20f95f90c829d6f916a0c78175 100644 (file)
@@ -90,8 +90,7 @@ cnt_done(struct sess *sp)
        } else if (http_GetHdr(sp->http, H_Connection, &b) &&
            !strcmp(b, "close")) {
                vca_close_session(sp, "Connection header");
-       } else if (strcmp(sp->http->hd[HTTP_HDR_PROTO][HTTP_START],
-           "HTTP/1.1")) {
+       } else if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) {
                vca_close_session(sp, "not HTTP/1.1");
        }
        VCL_Rel(sp->vcl);
@@ -263,7 +262,7 @@ cnt_hit(struct sess *sp)
        if (sp->handling == VCL_RET_PASS) {
                HSH_Deref(sp->obj);
                sp->obj = NULL;
-               PassSession(sp->wrk, sp);
+               PassSession(sp);
                sp->step = STP_PASSBODY;
                return (0);
        }
@@ -398,7 +397,7 @@ cnt_miss(struct sess *sp)
                HSH_Unbusy(sp->obj);
                HSH_Deref(sp->obj);
                sp->obj = 0;
-               PassSession(sp->wrk, sp);
+               PassSession(sp);
                sp->step = STP_PASSBODY;
                return (0);
        }
@@ -431,7 +430,7 @@ static int
 cnt_pass(struct sess *sp)
 {
 
-       PassSession(sp->wrk, sp);
+       PassSession(sp);
        sp->step = STP_PASSBODY;
        return (0);
 }
index fb11aa7edc16a56f9df413e10935a6ae37374e3c..f18b87b3d668ea7c5b5242bf5fdbaabf5796233b 100644 (file)
@@ -77,7 +77,7 @@ HSH_Lookup(struct sess *sp)
        } else
                CHECK_OBJ_NOTNULL(w->nobj, OBJECT_MAGIC);
 
-       url = h->hd[HTTP_HDR_URL][HTTP_START];
+       url = h->hd[HTTP_HDR_URL].b;
        if (!http_GetHdr(h, H_Host, &host))
                host = url;
        if (sp->obj != NULL) {
index 731dccc544334c472acb9e94d6433f5f4f2fca13..c6d7b929c2bb568dba1c0058f3fa3777a91469d6 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <stdio.h>
+#include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
@@ -19,8 +20,8 @@
 #include "http_headers.h"
 #undef HTTPH
 
-#define VSLH(a, b, c, d) \
-       VSLR((a), (b), (c)->hd[d][HTTP_START], (c)->hd[d][HTTP_END]);
+#define VSLH(ax, bx, cx, dx) \
+       VSLR((ax), (bx), (cx)->hd[(dx)].b, (cx)->hd[(dx)].e);
 
 /*--------------------------------------------------------------------*/
 
@@ -37,6 +38,25 @@ http_Setup(struct http *hp, void *space, unsigned len)
        hp->v = sp;
        hp->f = sp;
        hp->e = sp + len;
+       hp->nhd = HTTP_HDR_FIRST;
+}
+
+/*--------------------------------------------------------------------*/
+
+
+int
+http_IsHdr(struct http_hdr *hh, char *hdr)
+{
+       unsigned l;
+
+       assert(hh->b != NULL);
+       assert(hh->e != NULL);
+       assert(hdr != NULL);
+       l = hdr[0];
+       assert(l == strlen(hdr + 1));
+       assert(hdr[l] == ':');
+       hdr++;
+       return (!strncasecmp(hdr, hh->b, l));
 }
 
 /*--------------------------------------------------------------------*/
@@ -52,27 +72,26 @@ http_GetHdr(struct http *hp, const char *hdr, char **ptr)
        assert(hdr[l] == ':');
        hdr++;
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-               assert(hp->hd[u][HTTP_START] != NULL);
-               assert(hp->hd[u][HTTP_END] != NULL);
-               if (hp->hd[u][HTTP_END] < hp->hd[u][HTTP_START] + l)
+               assert(hp->hd[u].b != NULL);
+               assert(hp->hd[u].e != NULL);
+               if (hp->hd[u].e < hp->hd[u].b + l)
                        continue;
-               if (hp->hd[u][HTTP_START][l-1] != ':')
+               if (hp->hd[u].b[l-1] != ':')
                        continue;
-               if (strncasecmp(hdr, hp->hd[u][HTTP_START], l))
+               if (strncasecmp(hdr, hp->hd[u].b, l))
                        continue;
-               if (hp->hd[u][HTTP_DATA] == NULL) {
-                       p = hp->hd[u][HTTP_START] + l;
-                       while (isspace(*p))
-                               p++;
-                       hp->hd[u][HTTP_DATA] = p;
-               }
-               *ptr = hp->hd[u][HTTP_DATA];
+               p = hp->hd[u].b + l;
+               while (isspace(*p))
+                       p++;
+               *ptr = p;
                return (1);
        }
        *ptr = NULL;
        return (0);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_GetHdrField(struct http *hp, const char *hdr, const char *field, char **ptr)
 {
@@ -106,6 +125,8 @@ http_GetHdrField(struct http *hp, const char *hdr, const char *field, char **ptr
        return (0);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_HdrIs(struct http *hp, const char *hdr, const char *val)
 {
@@ -119,6 +140,8 @@ http_HdrIs(struct http *hp, const char *hdr, const char *val)
        return (0);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_GetTail(struct http *hp, unsigned len, char **b, char **e)
 {
@@ -140,6 +163,7 @@ http_GetTail(struct http *hp, unsigned len, char **b, char **e)
        return (1);
 }
 
+/*--------------------------------------------------------------------*/
 /* Read from fd, but soak up any tail first */
 
 int
@@ -168,12 +192,14 @@ http_Read(struct http *hp, int fd, void *p, unsigned len)
        return (u);
 }
 
+/*--------------------------------------------------------------------*/
+
 int
 http_GetStatus(struct http *hp)
 {
 
-       assert(hp->hd[HTTP_HDR_STATUS][HTTP_START] != NULL);
-       return (strtoul(hp->hd[HTTP_HDR_STATUS][HTTP_START],
+       assert(hp->hd[HTTP_HDR_STATUS].b != NULL);
+       return (strtoul(hp->hd[HTTP_HDR_STATUS].b,
            NULL /* XXX */, 10));
 }
 
@@ -211,8 +237,8 @@ http_dissect_hdrs(struct http *hp, int fd, char *p)
                        hp->conds = 1;
 
                if (hp->nhd < MAX_HTTP_HDRS) {
-                       hp->hd[hp->nhd][HTTP_START] = p;
-                       hp->hd[hp->nhd][HTTP_END] = q;
+                       hp->hd[hp->nhd].b = p;
+                       hp->hd[hp->nhd].e = q;
                        VSLH(SLT_RxHeader, fd, hp, hp->nhd);
                        hp->nhd++;
                } else {
@@ -239,10 +265,10 @@ http_DissectRequest(struct http *hp, int fd)
                continue;
 
        /* First, the request type (GET/HEAD etc) */
-       hp->hd[HTTP_HDR_REQ][HTTP_START] = p;
+       hp->hd[HTTP_HDR_REQ].b = p;
        for (; isalpha(*p); p++)
                ;
-       hp->hd[HTTP_HDR_REQ][HTTP_END] = p;
+       hp->hd[HTTP_HDR_REQ].e = p;
        VSLH(SLT_Request, fd, hp, HTTP_HDR_REQ);
        *p++ = '\0';
 
@@ -253,10 +279,10 @@ http_DissectRequest(struct http *hp, int fd)
                VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
                return (400);
        }
-       hp->hd[HTTP_HDR_URL][HTTP_START] = p;
+       hp->hd[HTTP_HDR_URL].b = p;
        while (!isspace(*p))
                p++;
-       hp->hd[HTTP_HDR_URL][HTTP_END] = p;
+       hp->hd[HTTP_HDR_URL].e = p;
        VSLH(SLT_URL, fd, hp, HTTP_HDR_URL);
        if (*p == '\n') {
                VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
@@ -271,10 +297,10 @@ http_DissectRequest(struct http *hp, int fd)
                VSLR(SLT_HttpGarbage, fd, hp->s, hp->v);
                return (400);
        }
-       hp->hd[HTTP_HDR_PROTO][HTTP_START] = p;
+       hp->hd[HTTP_HDR_PROTO].b = p;
        while (!isspace(*p))
                p++;
-       hp->hd[HTTP_HDR_PROTO][HTTP_END] = p;
+       hp->hd[HTTP_HDR_PROTO].e = p;
        VSLH(SLT_Protocol, fd, hp, HTTP_HDR_PROTO);
        if (*p != '\n')
                *p++ = '\0';
@@ -303,34 +329,34 @@ http_DissectResponse(struct http *hp, int fd)
                continue;
 
        /* First, protocol */
-       hp->hd[HTTP_HDR_PROTO][HTTP_START] = p;
+       hp->hd[HTTP_HDR_PROTO].b = p;
        while (!isspace(*p))
                p++;
-       hp->hd[HTTP_HDR_PROTO][HTTP_END] = p;
+       hp->hd[HTTP_HDR_PROTO].e = p;
        VSLH(SLT_Protocol, fd, hp, HTTP_HDR_PROTO);
        *p++ = '\0';
 
        /* Next find the status */
        while (isspace(*p))
                p++;
-       hp->hd[HTTP_HDR_STATUS][HTTP_START] = p;
+       hp->hd[HTTP_HDR_STATUS].b = p;
        while (!isspace(*p))
                p++;
-       hp->hd[HTTP_HDR_STATUS][HTTP_END] = p;
+       hp->hd[HTTP_HDR_STATUS].e = p;
        VSLH(SLT_Status, fd, hp, HTTP_HDR_STATUS);
        *p++ = '\0';
 
        /* Next find the response */
        while (isspace(*p))
                p++;
-       hp->hd[HTTP_HDR_RESPONSE][HTTP_START] = p;
+       hp->hd[HTTP_HDR_RESPONSE].b = p;
        while (*p != '\n')
                p++;
-       for (q = p; q > hp->hd[HTTP_HDR_RESPONSE][HTTP_START] &&
+       for (q = p; q > hp->hd[HTTP_HDR_RESPONSE].b &&
            isspace(q[-1]); q--)
                continue;
        *q = '\0';
-       hp->hd[HTTP_HDR_RESPONSE][HTTP_END] = q;
+       hp->hd[HTTP_HDR_RESPONSE].e = q;
        VSLH(SLT_Response, fd, hp, HTTP_HDR_RESPONSE);
        p++;
 
@@ -375,8 +401,6 @@ http_header_complete(struct http *hp)
 
 /*--------------------------------------------------------------------*/
 
-#include <errno.h>
-
 static void
 http_read_f(int fd, short event, void *arg)
 {
@@ -484,6 +508,130 @@ http_supress(const char *hdr, int flag)
 
 /*--------------------------------------------------------------------*/
 
+static void
+http_copyh(int fd, struct http *to, struct http *fm, unsigned n, enum shmlogtag tag)
+{
+
+       assert(n < MAX_HTTP_HDRS);
+       assert(fm->hd[n].b != NULL);
+       to->hd[n].b = fm->hd[n].b;
+       to->hd[n].e = fm->hd[n].e;
+       VSLH(tag, fd, to, n);
+}
+
+void
+http_CopyReq(int fd, struct http *to, struct http *fm)
+{
+
+       CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
+       CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+       http_copyh(fd, to, fm, HTTP_HDR_REQ, SLT_Request);
+       http_copyh(fd, to, fm, HTTP_HDR_URL, SLT_URL);
+       http_copyh(fd, to, fm, HTTP_HDR_PROTO, SLT_Protocol);
+}
+
+
+void
+http_CopyResp(int fd, struct http *to, struct http *fm)
+{
+
+       CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
+       CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+       http_copyh(fd, to, fm, HTTP_HDR_PROTO, SLT_Protocol);
+       http_copyh(fd, to, fm, HTTP_HDR_STATUS, SLT_Status);
+       http_copyh(fd, to, fm, HTTP_HDR_RESPONSE, SLT_Response);
+}
+
+void
+http_CopyHeader(int fd, struct http *to, struct http *fm, unsigned n)
+{
+
+       CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
+       CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
+       assert(n < MAX_HTTP_HDRS);
+       assert(fm->hd[n].b != NULL);
+       if (to->nhd < MAX_HTTP_HDRS) {
+               to->hd[to->nhd].b = fm->hd[n].b;
+               to->hd[to->nhd].e = fm->hd[n].e;
+               VSLH(SLT_TxHeader, fd, to, to->nhd);
+               to->nhd++;
+       } else  {
+               VSL_stats->losthdr++;
+               VSLH(SLT_LostHeader, fd, fm, n);
+       }
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_FilterHeader(int fd, struct http *to, struct http *fm, unsigned how)
+{
+       unsigned u;
+
+       to->nhd = HTTP_HDR_FIRST;
+       for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
+#define HTTPH(a, b, c, d, e, f, g) \
+               if (((e) & how) && http_IsHdr(&fm->hd[u], (b))) \
+                       continue;
+#include "http_headers.h"
+#undef HTTPH
+               http_CopyHeader(fd, to, fm, u);
+       }
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_PrintfHeader(int fd, struct http *to, const char *fmt, ...)
+{
+       va_list ap;
+       unsigned l, n;
+
+       va_start(ap, fmt);
+       l = to->e - to->f;
+       n = vsnprintf(to->f, l, fmt, ap);
+       if (n + 1 > l || to->nhd >= MAX_HTTP_HDRS) {
+               VSL_stats->losthdr++;
+               VSL(SLT_LostHeader, fd, "%s", to->f);
+       } else {
+               assert(to->f < to->e);
+               to->hd[to->nhd].b = to->f;
+               to->hd[to->nhd].e = to->f + n;
+               to->f += n + 1;
+               VSLH(SLT_TxHeader, fd, to, to->nhd);
+               to->nhd++;
+       }
+       va_end(ap);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+http_Write(struct worker *w, struct http *hp, int resp)
+{
+       unsigned u;
+
+       if (resp) {
+               assert(hp->hd[HTTP_HDR_STATUS].b != NULL);
+               WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
+               WRK_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
+               WRK_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], " ");
+       } else {
+               assert(hp->hd[HTTP_HDR_URL].b != NULL);
+               WRK_WriteH(w, &hp->hd[HTTP_HDR_REQ], " ");
+               WRK_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
+               WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
+       }
+       for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
+               assert(hp->hd[u].b != NULL);
+               assert(hp->hd[u].e != NULL);
+               WRK_WriteH(w, &hp->hd[u], "\r\n");
+       }
+       WRK_Write(w, "\r\n", -1);
+}
+
+/*--------------------------------------------------------------------*/
+
 void
 http_BuildSbuf(int fd, enum http_build mode, struct sbuf *sb, struct http *hp)
 {
@@ -503,31 +651,29 @@ http_BuildSbuf(int fd, enum http_build mode, struct sbuf *sb, struct http *hp)
                assert(__LINE__ == 0);
        }
        if (rr == 0) {
-               sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO][HTTP_START]);
+               sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO].b);
                sbuf_cat(sb, " ");
-               sbuf_cat(sb, hp->hd[HTTP_HDR_STATUS][HTTP_START]);
+               sbuf_cat(sb, hp->hd[HTTP_HDR_STATUS].b);
                sbuf_cat(sb, " ");
-               sbuf_cat(sb, hp->hd[HTTP_HDR_RESPONSE][HTTP_START]);
+               sbuf_cat(sb, hp->hd[HTTP_HDR_RESPONSE].b);
        } else {
                if (rr == 2) {
                        sbuf_cat(sb, "GET ");
                } else {
-                       sbuf_cat(sb, hp->hd[HTTP_HDR_REQ][HTTP_START]);
+                       sbuf_cat(sb, hp->hd[HTTP_HDR_REQ].b);
                        sbuf_cat(sb, " ");
                }
-               sbuf_cat(sb, hp->hd[HTTP_HDR_URL][HTTP_START]);
+               sbuf_cat(sb, hp->hd[HTTP_HDR_URL].b);
                sbuf_cat(sb, " ");
-               sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO][HTTP_START]);
+               sbuf_cat(sb, hp->hd[HTTP_HDR_PROTO].b);
        }
 
        sbuf_cat(sb, "\r\n");
 
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
-               if (http_supress(hp->hd[u][HTTP_START], sup))
+               if (http_supress(hp->hd[u].b, sup))
                        continue;
-               if (1)
-                       VSL(SLT_TxHeader, fd, "%s", hp->hd[u][HTTP_START]);
-               sbuf_cat(sb, hp->hd[u][HTTP_START]);
+               sbuf_cat(sb, hp->hd[u].b);
                sbuf_cat(sb, "\r\n");
        }
        if (mode != Build_Reply) {
index 14c33e9b2a8b284158c5a4b47f660fdb7d1fcb06..fbb4635093c499aa5e9cebcbbcded06e654228ed 100644 (file)
@@ -46,8 +46,9 @@ pass_straight(struct sess *sp, int fd, struct http *hp, char *bi)
                if (i == 0 && bi == NULL)
                        return (1);
                assert(i > 0);
-               RES_Write(sp, buf, i);
-               RES_Flush(sp);
+               WRK_Write(sp->wrk, buf, i);
+               if (WRK_Flush(sp->wrk))
+                       vca_close_session(sp, "remote closed");
                cl -= i;
        }
        return (0);
@@ -92,7 +93,7 @@ pass_chunked(struct sess *sp, int fd, struct http *hp)
                if (u == 0)
                        break;
 
-               RES_Write(sp, p, q - p);
+               WRK_Write(sp->wrk, p, q - p);
 
                p = q;
 
@@ -104,28 +105,30 @@ pass_chunked(struct sess *sp, int fd, struct http *hp)
                        }
                        if (bp - p < j)
                                j = bp - p;
-                       RES_Write(sp, p, j);
+                       WRK_Write(sp->wrk, p, j);
                        p += j;
                        u -= j;
                }
                while (u > 0) {
                        if (http_GetTail(hp, u, &b, &e)) {
                                j = e - b;
-                               RES_Write(sp, q, j);
+                               WRK_Write(sp->wrk, q, j);
                                u -= j;
                        } else
                                break;
                }
-               RES_Flush(sp);
+               if (WRK_Flush(sp->wrk))
+                       vca_close_session(sp, "remote closed");
                while (u > 0) {
                        j = u;
                        if (j > sizeof buf)
                                j = sizeof buf;
                        i = read(fd, buf, j);
                        assert(i > 0);
-                       RES_Write(sp, buf, i);
+                       WRK_Write(sp->wrk, buf, i);
                        u -= i;
-                       RES_Flush(sp);
+                       if (WRK_Flush(sp->wrk))
+                               vca_close_session(sp, "remote closed");
                }
        }
        return (0);
@@ -138,32 +141,34 @@ void
 PassBody(struct worker *w, struct sess *sp)
 {
        struct vbe_conn *vc;
-       struct http *hp;
        char *b;
        int cls;
 
-       hp = sp->bkd_http;
-       assert(hp != NULL);
        vc = sp->vbc;
        assert(vc != NULL);
 
-       http_BuildSbuf(sp->fd, Build_Reply, w->sb, hp);
-       sbuf_cat(w->sb, "\r\n");
-       sbuf_finish(w->sb);
-       RES_Write(sp, sbuf_data(w->sb), sbuf_len(w->sb));
-
-       if (http_GetHdr(hp, H_Content_Length, &b))
-               cls = pass_straight(sp, vc->fd, hp, b);
-       else if (http_HdrIs(hp, H_Connection, "close"))
-               cls = pass_straight(sp, vc->fd, hp, NULL);
-       else if (http_HdrIs(hp, H_Transfer_Encoding, "chunked"))
-               cls = pass_chunked(sp, vc->fd, hp);
+       sp->http->f = sp->http->v;
+       sp->http->nhd = HTTP_HDR_FIRST;
+       http_CopyResp(sp->fd, sp->http, vc->http);
+       http_FilterHeader(sp->fd, sp->http, vc->http, HTTPH_A_PASS);
+       http_PrintfHeader(sp->fd, sp->http, "X-Varnish: %u", sp->xid);
+       WRK_Reset(w, &sp->fd);
+       http_Write(w, sp->http, 1);
+
+       if (http_GetHdr(vc->http, H_Content_Length, &b))
+               cls = pass_straight(sp, vc->fd, vc->http, b);
+       else if (http_HdrIs(vc->http, H_Connection, "close"))
+               cls = pass_straight(sp, vc->fd, vc->http, NULL);
+       else if (http_HdrIs(vc->http, H_Transfer_Encoding, "chunked"))
+               cls = pass_chunked(sp, vc->fd, vc->http);
        else {
-               cls = pass_straight(sp, vc->fd, hp, NULL);
+               cls = pass_straight(sp, vc->fd, vc->http, NULL);
        }
-       RES_Flush(sp);
 
-       if (http_GetHdr(hp, H_Connection, &b) && !strcasecmp(b, "close"))
+       if (WRK_Flush(w))
+               vca_close_session(sp, "remote closed");
+
+       if (http_GetHdr(vc->http, H_Connection, &b) && !strcasecmp(b, "close"))
                cls = 1;
 
        if (cls)
@@ -172,21 +177,31 @@ PassBody(struct worker *w, struct sess *sp)
                VBE_RecycleFd(vc);
 }
 
+
 /*--------------------------------------------------------------------*/
+
 void
-PassSession(struct worker *w, struct sess *sp)
+PassSession(struct sess *sp)
 {
        int i;
        struct vbe_conn *vc;
        struct http *hp;
+       struct worker *w;
 
+       CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+       CHECK_OBJ_NOTNULL(sp->wrk, WORKER_MAGIC);
+       w = sp->wrk;
        vc = VBE_GetFd(sp->backend, sp->xid);
        assert(vc != NULL);
        VSL(SLT_Backend, sp->fd, "%d %s", vc->fd, sp->backend->vcl_name);
 
-       http_BuildSbuf(vc->fd, Build_Pass, w->sb, sp->http);
-       i = write(vc->fd, sbuf_data(w->sb), sbuf_len(w->sb));
-       assert(i == sbuf_len(w->sb));
+       http_CopyReq(vc->fd, vc->http, sp->http);
+       http_FilterHeader(vc->fd, vc->http, sp->http, HTTPH_R_PASS);
+       http_PrintfHeader(vc->fd, vc->http, "X-Varnish: %u", sp->xid);
+       WRK_Reset(w, &vc->fd);
+       http_Write(w, vc->http, 0);
+       i = WRK_Flush(w);
+       assert(i == 0);
 
        /* XXX: copy any contents */
 
index 4bed37bc8a1850d78c76d28ab347bb67e0e9c477..31b730e0c19389de8742229b109cfe7a7b72d4d8 100644 (file)
@@ -24,6 +24,73 @@ static unsigned              wrk_overflow;
 static TAILQ_HEAD(, worker) wrk_head = TAILQ_HEAD_INITIALIZER(wrk_head);
 static TAILQ_HEAD(, workreq) wrk_reqhead = TAILQ_HEAD_INITIALIZER(wrk_reqhead);
 
+/*--------------------------------------------------------------------
+ * Write data to fd
+ * We try to use writev() if possible in order to minimize number of
+ * syscalls made and packets sent.  It also just might allow the worker
+ * thread to complete the request without holding stuff locked.
+ */
+
+void
+WRK_Reset(struct worker *w, int *fd)
+{
+
+       CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+       w->werr = 0;
+       w->liov = 0;
+       w->niov = 0;
+       w->wfd = fd;
+}
+
+int
+WRK_Flush(struct worker *w)
+{
+       int i;
+
+       CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+       if (*w->wfd < 0 || w->niov == 0 || w->werr)
+               return (w->werr);
+VSL(SLT_Debug, 0, "%s %d", __func__, *w->wfd);
+       i = writev(*w->wfd, w->iov, w->niov);
+       if (i != w->liov)
+               w->werr++;
+       else {
+               w->liov = 0;
+               w->niov = 0;
+       }
+       return (w->werr);
+}
+
+void
+WRK_WriteH(struct worker *w, struct http_hdr *hh, const char *suf)
+{
+       
+       CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+       assert(w != NULL);
+       assert(hh != NULL);
+       assert(hh->b != NULL);
+       assert(hh->e != NULL);
+       WRK_Write(w, hh->b, hh->e - hh->b);
+       if (suf != NULL)
+               WRK_Write(w, suf, -1);
+}
+
+void
+WRK_Write(struct worker *w, const void *ptr, size_t len)
+{
+
+       CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
+       if (len == 0 || *w->wfd < 0)
+               return;
+       if (len == -1)
+               len = strlen(ptr);
+       if (w->niov == MAX_IOVS)
+               WRK_Flush(w);
+       w->iov[w->niov].iov_base = (void*)(uintptr_t)ptr;
+       w->iov[w->niov++].iov_len = len;
+       w->liov += len;
+}
+
 /*--------------------------------------------------------------------*/
 
 static void
index 38bd09ac1f4450b29c69061157de11a0e32f6d7d..594a75d7888d355014cc88236ef136a91ec653e2 100644 (file)
@@ -65,50 +65,12 @@ RES_Error(struct sess *sp, int error, const char *msg)
                "  </BODY>\r\n"
                "</HTML>\r\n");
        sbuf_finish(sb);
-       RES_Write(sp, sbuf_data(sb), sbuf_len(sb));
-       RES_Flush(sp);
+       WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
+       WRK_Flush(sp->wrk);
        vca_close_session(sp, msg);
 }
 
 
-/*--------------------------------------------------------------------
- * Write data to client
- * We try to use writev() if possible in order to minimize number of
- * syscalls made and packets sent.  It also just might allow the worker
- * thread to complete the request without holding stuff locked.
- */
-
-void
-RES_Flush(struct sess *sp)
-{
-       int i;
-
-       if (sp->fd < 0 || sp->wrk->niov == 0)
-               return;
-       i = writev(sp->fd, sp->wrk->iov, sp->wrk->niov);
-       if (i != sp->wrk->liov)
-               vca_close_session(sp, "remote closed");
-       sp->wrk->liov = 0;
-       sp->wrk->niov = 0;
-}
-
-void
-RES_Write(struct sess *sp, const void *ptr, size_t len)
-{
-
-       if (sp->fd < 0 || len == 0)
-               return;
-       if (len == -1)
-               len = strlen(ptr);
-       if (sp->wrk->niov == MAX_IOVS)
-               RES_Flush(sp);
-       if (sp->fd < 0)
-               return;
-       sp->wrk->iov[sp->wrk->niov].iov_base = (void*)(uintptr_t)ptr;
-       sp->wrk->iov[sp->wrk->niov++].iov_len = len;
-       sp->wrk->liov += len;
-}
-
 /*--------------------------------------------------------------------*/
 
 static void
@@ -121,18 +83,18 @@ res_do_304(struct sess *sp, char *p)
 
        VSL(SLT_Status, sp->fd, "%u", 304);
        VSL(SLT_Length, sp->fd, "%u", 0);
-       RES_Write(sp, "HTTP/1.1 304 Not Modified\r\n", -1);
-       RES_Write(sp, "Via: 1.1 varnish\r\n", -1);
-       RES_Write(sp, "Last-Modified: ", -1);
-       RES_Write(sp, p, -1);
-       RES_Write(sp, "\r\n", -1);
-       if (strcmp(sp->http->hd[HTTP_HDR_PROTO][HTTP_START], "HTTP/1.1")) 
-               RES_Write(sp, "Connection: close\r\n", -1);
+       WRK_Write(sp->wrk, "HTTP/1.1 304 Not Modified\r\n", -1);
+       WRK_Write(sp->wrk, "Via: 1.1 varnish\r\n", -1);
+       WRK_Write(sp->wrk, "Last-Modified: ", -1);
+       WRK_Write(sp->wrk, p, -1);
+       WRK_Write(sp->wrk, "\r\n", -1);
+       if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) 
+               WRK_Write(sp->wrk, "Connection: close\r\n", -1);
        sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid);
        sbuf_printf(sb, "\r\n");
        sbuf_finish(sb);
-       RES_Write(sp, sbuf_data(sb), sbuf_len(sb));
-       RES_Flush(sp);
+       WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
+       WRK_Flush(sp->wrk);
 }
 
 /*--------------------------------------------------------------------*/
@@ -180,26 +142,26 @@ RES_WriteObj(struct sess *sp)
        VSL(SLT_Status, sp->fd, "%u", sp->obj->response);
        VSL(SLT_Length, sp->fd, "%u", sp->obj->len);
 
-       RES_Write(sp, sp->obj->header, strlen(sp->obj->header));
+       WRK_Write(sp->wrk, sp->obj->header, strlen(sp->obj->header));
 
        sbuf_clear(sb);
        sbuf_printf(sb, "Age: %u\r\n",
                sp->obj->age + sp->t_req - sp->obj->entered);
        sbuf_printf(sb, "Via: 1.1 varnish\r\n");
        sbuf_printf(sb, "X-Varnish: xid %u\r\n", sp->obj->xid);
-       if (strcmp(sp->http->hd[HTTP_HDR_PROTO][HTTP_START], "HTTP/1.1")) 
+       if (strcmp(sp->http->hd[HTTP_HDR_PROTO].b, "HTTP/1.1")) 
                sbuf_printf(sb, "Connection: close\r\n");
        sbuf_printf(sb, "\r\n");
        sbuf_finish(sb);
-       RES_Write(sp, sbuf_data(sb), sbuf_len(sb));
+       WRK_Write(sp->wrk, sbuf_data(sb), sbuf_len(sb));
        bytes += sbuf_len(sb);
        /* XXX: conditional request handling */
-       if (!strcmp(sp->http->hd[HTTP_HDR_REQ][HTTP_START], "GET")) {
+       if (!strcmp(sp->http->hd[HTTP_HDR_REQ].b, "GET")) {
                TAILQ_FOREACH(st, &sp->obj->store, list) {
                        assert(st->stevedore != NULL);
                        u += st->len;
                        if (st->stevedore->send == NULL) {
-                               RES_Write(sp, st->ptr, st->len);
+                               WRK_Write(sp->wrk, st->ptr, st->len);
                                continue;
                        }
                        st->stevedore->send(st, sp,
@@ -210,5 +172,5 @@ RES_WriteObj(struct sess *sp)
                assert(u == sp->obj->len);
        }
        SES_ChargeBytes(sp, bytes + u);
-       RES_Flush(sp);
+       WRK_Flush(sp->wrk);
 }
index 9aa02eb13c11477805bd89faa18fe92036b34382..d913c58932c9afae1455ab239e2376fed09612df 100644 (file)
@@ -60,7 +60,7 @@ VRT_GetReq(struct sess *sp)
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
        assert(sp != NULL);
        assert(sp->http != NULL);
-       return (sp->http->hd[HTTP_HDR_REQ][HTTP_START]);
+       return (sp->http->hd[HTTP_HDR_REQ].b);
 }
 
 /*--------------------------------------------------------------------*/
index 10e0415daf9186fb20ad5bb123d297172f6cf954..2c9ad8c1968a61620eb4707561973e96076f3072 100644 (file)
@@ -5,7 +5,7 @@
  * b   session field name
  * c   Request(1)/Response(2) bitfield
  * d   Supress header to backend (1) / Supress header to client (2)
- * e   unused
+ * e   Supress header in pass from client to backend
  * f   unused
  * g   unused
  *
  *--------------------------------------------------------------------
  */
 
-HTTPH("Keep-Alive",            H_Keep_Alive,           3, 3, 0, 0, 0)  /* RFC2068 */
+#ifndef HTTPH_R_PASS
+#define HTTPH_R_PASS   (1 << 0)
+#define HTTPH_A_PASS   (1 << 1)
+#endif
+
+HTTPH("Keep-Alive",            H_Keep_Alive,           3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2068 */
 
 HTTPH("Accept",                        H_Accept,               1, 0, 0, 0, 0)  /* RFC2616 14.1 */
 HTTPH("Accept-Charset",                H_Accept_Charset,       1, 0, 0, 0, 0)  /* RFC2616 14.2 */
 HTTPH("Accept-Encoding",       H_Accept_Encoding,      1, 0, 0, 0, 0)  /* RFC2616 14.3 */
 HTTPH("Accept-Language",       H_Accept_Language,      1, 0, 0, 0, 0)  /* RFC2616 14.4 */
-HTTPH("Accept-Ranges",         H_Accept_Ranges,        2, 3, 0, 0, 0)  /* RFC2616 14.5 */
+HTTPH("Accept-Ranges",         H_Accept_Ranges,        2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.5 */
 HTTPH("Age",                   H_Age,                  2, 0, 0, 0, 0)  /* RFC2616 14.6 */
 HTTPH("Allow",                 H_Allow,                2, 0, 0, 0, 0)  /* RFC2616 14.7 */
 HTTPH("Authorization",         H_Authorization,        1, 0, 0, 0, 0)  /* RFC2616 14.8 */
-HTTPH("Cache-Control",         H_Cache_Control,        3, 3, 0, 0, 0)  /* RFC2616 14.9 */
-HTTPH("Connection",            H_Connection,           3, 3, 0, 0, 0)  /* RFC2616 14.10 */
+HTTPH("Cache-Control",         H_Cache_Control,        3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.9 */
+HTTPH("Connection",            H_Connection,           3, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.10 */
 HTTPH("Content-Encoding",      H_Content_Encoding,     2, 0, 0, 0, 0)  /* RFC2616 14.11 */
 HTTPH("Content-Langugae",      H_Content_Language,     2, 0, 0, 0, 0)  /* RFC2616 14.12 */
 HTTPH("Content-Length",                H_Content_Length,       2, 2, 0, 0, 0)  /* RFC2616 14.13 */
 HTTPH("Content-Location",      H_Content_Location,     2, 0, 0, 0, 0)  /* RFC2616 14.14 */
 HTTPH("Content-MD5",           H_Content_MD5,          2, 0, 0, 0, 0)  /* RFC2616 14.15 */
-HTTPH("Content-Range",         H_Content_Range,        2, 3, 0, 0, 0)  /* RFC2616 14.16 */
+HTTPH("Content-Range",         H_Content_Range,        2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.16 */
 HTTPH("Content-Type",          H_Content_Type,         2, 0, 0, 0, 0)  /* RFC2616 14.17 */
 HTTPH("Date",                  H_Date,                 2, 0, 0, 0, 0)  /* RFC2616 14.18 */
 HTTPH("ETag",                  H_ETag,                 2, 0, 0, 0, 0)  /* RFC2616 14.19 */
@@ -55,10 +60,10 @@ HTTPH("Range",                      H_Range,                1, 0, 0, 0, 0)  /* RFC2616 14.35 */
 HTTPH("Referer",               H_Referer,              1, 0, 0, 0, 0)  /* RFC2616 14.36 */
 HTTPH("Retry-After",           H_Retry_After,          2, 0, 0, 0, 0)  /* RFC2616 14.37 */
 HTTPH("Server",                        H_Server,               2, 0, 0, 0, 0)  /* RFC2616 14.38 */
-HTTPH("TE",                    H_TE,                   1, 3, 0, 0, 0)  /* RFC2616 14.39 */
-HTTPH("Trailer",               H_Trailer,              1, 3, 0, 0, 0)  /* RFC2616 14.40 */
-HTTPH("Transfer-Encoding",     H_Transfer_Encoding,    2, 3, 0, 0, 0)  /* RFC2616 14.41 */
-HTTPH("Upgrade",               H_Upgrade,              2, 3, 0, 0, 0)  /* RFC2616 14.42 */
+HTTPH("TE",                    H_TE,                   1, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.39 */
+HTTPH("Trailer",               H_Trailer,              1, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.40 */
+HTTPH("Transfer-Encoding",     H_Transfer_Encoding,    2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.41 */
+HTTPH("Upgrade",               H_Upgrade,              2, 3, HTTPH_R_PASS|HTTPH_A_PASS, 0, 0)  /* RFC2616 14.42 */
 HTTPH("User-Agent",            H_User_Agent,           1, 0, 0, 0, 0)  /* RFC2616 14.43 */
 HTTPH("Vary",                  H_Vary,                 2, 0, 0, 0, 0)  /* RFC2616 14.44 */
 HTTPH("Via",                   H_Via,                  2, 0, 0, 0, 0)  /* RFC2616 14.45 */