From: phk Date: Mon, 1 May 2006 10:55:27 +0000 (+0000) Subject: Add INCOMPL() macro to mark missing code. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d77f84f47039445165d8d36f2e53a2b26714013;p=varnish Add INCOMPL() macro to mark missing code. Add http_HdrIs() to check if we have a given header and if we do if it has a given value. Use it. Ignore SIGPIPE since SO_NOSIGPIPE doesn't work reliably, (but set it on accepted TCP connections anyway). Update passing to match fetching, including a chunked encoding method. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@159 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index 2b2d306f..a34925a7 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -83,6 +83,7 @@ struct http; struct http *http_New(void); void http_Delete(struct http *hp); int http_GetHdr(struct http *hp, const char *hdr, char **ptr); +int http_HdrIs(struct http *hp, const char *hdr, const char *val); int http_GetTail(struct http *hp, unsigned len, char **b, char **e); int http_GetURL(struct http *hp, char **b); void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg); @@ -108,6 +109,10 @@ void VSL_Init(void); void VSLR(enum shmlogtag tag, unsigned id, const char *b, const char *e); void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...); #define HERE() VSL(SLT_Debug, 0, "HERE: %s(%d)", __func__, __LINE__) +#define INCOMPL() do { \ + VSL(SLT_Debug, 0, "INCOMPLETE AT: %s(%d)", __func__, __LINE__); \ + assert(__LINE__ == 0); \ + } while (0) #endif /* cache_vcl.c */ diff --git a/varnish-cache/bin/varnishd/cache_acceptor.c b/varnish-cache/bin/varnishd/cache_acceptor.c index b05b95e6..fb6fae04 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.c +++ b/varnish-cache/bin/varnishd/cache_acceptor.c @@ -58,6 +58,7 @@ accept_f(int fd, short event, void *arg) struct sockaddr addr; struct sess *sp; char port[10]; + int i; (void)arg; sm = calloc(sizeof *sm, 1); @@ -76,6 +77,8 @@ accept_f(int fd, short event, void *arg) free(sp); return; } + i = 1; + AZ(setsockopt(sp->fd, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i)); AZ(getnameinfo(&addr, l, sp->addr, VCA_ADDRBUFSIZE, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV)); diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index 33370305..35c477d2 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -165,9 +165,7 @@ FetchSession(struct worker *w, struct sess *sp) VSL(SLT_Handling, sp->fd, "Fetch fd %d", fd); hp = http_New(); -HERE(); http_BuildSbuf(1, w->sb, sp->http); -HERE(); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -190,12 +188,11 @@ HERE(); assert(sp->handling == HND_Insert); - if (http_GetHdr(hp, "Content-Length", &b)) { + if (http_GetHdr(hp, "Content-Length", &b)) cls = fetch_straight(w, sp, fd, hp, b); - } else if (http_GetHdr(hp, "Transfer-Encoding", &b) && - !strcasecmp(b, "chunked")) { + else if (http_HdrIs(hp, "Transfer-Encoding", "chunked")) cls = fetch_chunked(w, sp, fd, hp); - } else { + else { VSL(SLT_Debug, fd, "No transfer"); cls = 0; } diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index 718980ce..ba451487 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -101,6 +101,19 @@ http_GetHdr(struct http *hp, const char *hdr, char **ptr) return (0); } +int +http_HdrIs(struct http *hp, const char *hdr, const char *val) +{ + char *p; + + if (!http_GetHdr(hp, hdr, &p)) + return (0); + assert(p != NULL); + if (!strcasecmp(p, val)) + return (1); + return (0); +} + int http_GetURL(struct http *hp, char **b) { @@ -346,6 +359,7 @@ http_BuildSbuf(int resp, struct sbuf *sb, struct http *hp) sbuf_cat(sb, " "); sbuf_cat(sb, hp->proto); } else { + printf("resp = %d\n", resp); assert(resp == 1 || resp == 2); } sbuf_cat(sb, "\r\n"); diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c index 224cbf9c..c5e3e56e 100644 --- a/varnish-cache/bin/varnishd/cache_main.c +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,9 @@ child_main(void) struct cli *cli; int i; + /* XXX: SO_NOSIGPIPE does not work reliably :-( */ + signal(SIGPIPE, SIG_IGN); + setbuf(stdout, NULL); setbuf(stderr, NULL); printf("Child starts\n"); diff --git a/varnish-cache/bin/varnishd/cache_pass.c b/varnish-cache/bin/varnishd/cache_pass.c index 6dce02b2..72e02bf2 100644 --- a/varnish-cache/bin/varnishd/cache_pass.c +++ b/varnish-cache/bin/varnishd/cache_pass.c @@ -22,25 +22,146 @@ #include "vcl_lang.h" #include "cache.h" + +/*--------------------------------------------------------------------*/ + +static int +pass_straight(struct worker *w, struct sess *sp, int fd, struct http *hp, char *bi) +{ + int i, j; + char *b, *e; + off_t cl; + unsigned c; + char buf[BUFSIZ]; + + if (bi != NULL) + cl = strtoumax(bi, NULL, 0); + else + cl = (1<<30); /* XXX */ + + i = fcntl(fd, F_GETFL); /* XXX ? */ + i &= ~O_NONBLOCK; + i = fcntl(fd, F_SETFL, i); + + while (cl != 0) { + c = cl; + if (c > sizeof buf) + c = sizeof buf; + if (http_GetTail(hp, c, &b, &e)) { + i = e - b; + j = write(sp->fd, b, i); + assert(i == j); + cl -= i; + continue; + } + i = read(fd, buf, c); + if (i == 0 && bi == NULL) + return (1); + assert(i > 0); + j = write(sp->fd, buf, i); + assert(i == j); + cl -= i; + } + return (0); +} + + +/*--------------------------------------------------------------------*/ + +static int +pass_chunked(struct worker *w, struct sess *sp, int fd, struct http *hp) +{ + int i, j; + char *b, *q, *e; + char *p; + unsigned u; + char buf[BUFSIZ]; + char *bp, *be; + + i = fcntl(fd, F_GETFL); /* XXX ? */ + i &= ~O_NONBLOCK; + i = fcntl(fd, F_SETFL, i); + + bp = buf; + be = buf + sizeof buf; + p = buf; + while (1) { + if (http_GetTail(hp, be - bp, &b, &e)) { + memcpy(bp, b, e - b); + bp += e - b; + } else { + /* XXX: must be safe from backend */ + i = read(fd, bp, be - bp); + assert(i > 0); + bp += i; + } + /* buffer valid from p to bp */ + + u = strtoul(p, &q, 16); + if (q == NULL || (*q != '\n' && *q != '\r')) { + INCOMPL(); + /* XXX: move bp to buf start, get more */ + } + if (*q == '\r') + q++; + assert(*q == '\n'); + q++; + if (u == 0) + break; + + j = q - p; + i = write(sp->fd, q, j); + assert(i == j); + + p = q; + + while (u > 0) { + j = u; + if (bp == p) { + bp = p = buf; + break; + } + if (bp - p < j) + j = bp - p; + i = write(sp->fd, p, j); + assert(i == j); + p += j; + u -= i; + } + while (u > 0) { + if (http_GetTail(hp, u, &b, &e)) { + j = e - b; + i = write(sp->fd, q, j); + assert(i == j); + u -= j; + } else + break; + } + while (u > 0) { + j = u; + if (j > sizeof buf) + j = sizeof buf; + i = read(fd, buf, j); + assert(i > 0); + j = write(sp->fd, buf, i); + assert(j == i); + u -= i; + } + } + return (0); +} + + /*--------------------------------------------------------------------*/ void PassSession(struct worker *w, struct sess *sp) { - int fd, i, j; + int fd, i; void *fd_token; - struct sess sp2; - char buf[BUFSIZ]; - off_t cl; + struct http *hp; char *b; + int cls; - if (http_GetHdr(sp->http, "Connection", &b) && !strcmp(b, "close")) { - /* - * If client wants only this one request, piping is safer - * and cheaper - */ - PipeSession(w, sp); - return; - } fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); @@ -50,69 +171,35 @@ PassSession(struct worker *w, struct sess *sp) /* XXX: copy any contents */ - memset(&sp2, 0, sizeof sp2); - sp2.rd_e = &w->e1; - sp2.fd = fd; /* * XXX: It might be cheaper to avoid the event_engine and simply * XXX: read(2) the header */ - http_RecvHead(sp2.http, sp2.fd, w->eb, NULL, NULL); + hp = http_New(); + http_RecvHead(hp, fd, w->eb, NULL, NULL); event_base_loop(w->eb, 0); - http_Dissect(sp2.http, sp2.fd, 2); + http_Dissect(hp, fd, 2); - http_BuildSbuf(2, w->sb, sp2.http); + http_BuildSbuf(2, w->sb, hp); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); - assert(__LINE__ == 0); - cl = j = 0; - *buf = 0; - -#if 0 - if (sp2.http.H_Content_Length != NULL) { - cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); - i = fcntl(sp2.fd, F_GETFL); - i &= ~O_NONBLOCK; - i = fcntl(sp2.fd, F_SETFL, i); - assert(i != -1); - i = sp2.rcv_len - sp2.rcv_ptr; - if (i > 0) { - j = write(sp->fd, sp2.rcv + sp2.rcv_ptr, i); - assert(j == i); - cl -= i; - sp2.rcv_ptr += i; - } - while (cl > 0) { - j = sizeof buf; - if (j > cl) - j = cl; - i = recv(sp2.fd, buf, j, 0); - assert(i >= 0); - if (i > 0) { - cl -= i; - j = write(sp->fd, buf, i); - assert(j == i); - } else if (i == 0) { - break; - } - } - assert(cl == 0); + if (http_GetHdr(hp, "Content-Length", &b)) + cls = pass_straight(w, sp, fd, hp, b); + else if (http_HdrIs(hp, "Connection", "close")) + cls = pass_straight(w, sp, fd, hp, NULL); + else if (http_HdrIs(hp, "Transfer-Encoding", "chunked")) + cls = pass_chunked(w, sp, fd, hp); + else { + INCOMPL(); + cls = 1; } - if (sp2.http.H_Connection != NULL && - !strcmp(sp2.http.H_Connection, "close")) { - close(fd); + if (http_GetHdr(hp, "Connection", &b) && !strcasecmp(b, "close")) + cls = 1; + + if (cls) VBE_ClosedFd(fd_token); - } else { + else VBE_RecycleFd(fd_token); - } - - /* XXX: this really belongs in the acceptor */ - if (sp->rcv_len > sp->rcv_ptr) - memmove(sp->rcv, sp->rcv + sp->rcv_ptr, - sp->rcv_len - sp->rcv_ptr); - sp->rcv_len -= sp->rcv_ptr; - sp->rcv_ptr = 0; -#endif } diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c index 0cfe5df7..57425cba 100644 --- a/varnish-cache/bin/varnishd/cache_pool.c +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -126,6 +126,7 @@ CacheWorker(void *priv) sp->handling = HND_Lookup; sp->vcl->recv_func(sp); + sp->handling = HND_Pass; for (done = 0; !done; ) { switch(sp->handling) {