From e574454b3e9dea655dcda64ce8cc35034c1b67e6 Mon Sep 17 00:00:00 2001 From: des Date: Thu, 10 Aug 2006 13:03:09 +0000 Subject: [PATCH] Rewrite pass_chunked(). git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@785 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache_pass.c | 76 +++++++++++++------------ 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache_pass.c b/varnish-cache/bin/varnishd/cache_pass.c index 283bed14..f977272e 100644 --- a/varnish-cache/bin/varnishd/cache_pass.c +++ b/varnish-cache/bin/varnishd/cache_pass.c @@ -61,8 +61,7 @@ static int pass_chunked(struct sess *sp, int fd, struct http *hp) { int i, j; - char *b, *q, *e; - char *p; + char *p, *q; unsigned u; char buf[PASS_BUFSIZ]; char *bp, *be; @@ -76,62 +75,64 @@ pass_chunked(struct sess *sp, int fd, struct http *hp) p = buf; while (1) { i = http_Read(hp, fd, bp, be - bp); - i = read(fd, bp, be - bp); - assert(i > 0); + assert(i >= 0); + if (i == 0 && p == bp) + break; bp += i; /* buffer valid from p to bp */ + assert(bp >= p); + /* chunk starts with f("%x\r\n", len) */ u = strtoul(p, &q, 16); - if (q == NULL || (*q != '\n' && *q != '\r')) { - INCOMPL(); - /* XXX: move bp to buf start, get more */ - } - if (*q == '\r') + while (q && q < bp && *q == ' ') + /* shouldn't happen - but sometimes it does */ q++; + if (q == NULL || q > bp - 2 /* want \r\n in same buffer */) { + /* short - move to start of buffer and extend */ + memmove(buf, p, bp - p); + bp -= p - buf; + p = buf; + continue; + } + assert(*q == '\r'); + q++; assert(*q == '\n'); q++; - if (u == 0) + + /* we just received the final zero-length chunk */ + if (u == 0) { + sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, p, q - p); break; + } - sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, p, q - p); + /* include chunk header */ + u += q - p; - p = q; + /* include trailing \r\n with chunk */ + u += 2; - while (u > 0) { + for (;;) { j = u; - if (bp == p) { - bp = p = buf; - break; - } if (bp - p < j) j = bp - p; sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, p, j); + WRK_Flush(sp->wrk); p += j; u -= j; - } - while (u > 0) { - if (http_GetTail(hp, u, &b, &e)) { - j = e - b; - sp->wrk->acct.bodybytes += - WRK_Write(sp->wrk, q, j); - u -= j; - } else + assert(u >= 0); + if (u == 0) break; - } - if (WRK_Flush(sp->wrk)) - vca_close_session(sp, "remote closed"); - while (u > 0) { + p = bp = buf; j = u; - if (j > sizeof buf) - j = sizeof buf; - i = read(fd, buf, j); + if (j > be - bp) + j = be - bp; + i = http_Read(hp, fd, bp, j); assert(i > 0); - sp->wrk->acct.bodybytes += WRK_Write(sp->wrk, buf, i); - u -= i; - if (WRK_Flush(sp->wrk)) - vca_close_session(sp, "remote closed"); + bp += i; } } + if (WRK_Flush(sp->wrk)) + vca_close_session(sp, "remote closed"); return (0); } @@ -155,6 +156,9 @@ PassBody(struct sess *sp) 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); + /* XXX */ + if (http_HdrIs(vc->http, H_Transfer_Encoding, "chunked")) + http_PrintfHeader(sp->fd, sp->http, "Transfer-Encoding: chunked"); WRK_Reset(sp->wrk, &sp->fd); sp->wrk->acct.hdrbytes += http_Write(sp->wrk, sp->http, 1); -- 2.39.5