From phk at projects.linpro.no Mon Apr 3 07:14:24 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 3 Apr 2006 09:14:24 +0200 (CEST) Subject: r93 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060403071424.53E451ED604@projects.linpro.no> Author: phk Date: 2006-04-03 09:14:24 +0200 (Mon, 03 Apr 2006) New Revision: 93 Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/include/shmlog_tags.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Add 5 dummy fields to the http headers, we will need them subsequently. Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-03-31 08:27:08 UTC (rev 92) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 07:14:24 UTC (rev 93) @@ -55,7 +55,7 @@ if (*p == '\r') p++; -#define HTTPH(a, b) sp->b = NULL; +#define HTTPH(a, b, c, d, e, f, g) sp->b = NULL; #include "http_headers.h" #undef HTTPH @@ -77,7 +77,7 @@ continue; \ } -#define HTTPH(a, b) W(a ":", b, p, q, sp) +#define HTTPH(a, b, c, d, e, f, g) W(a ":", b, p, q, sp) #include "http_headers.h" #undef HTTPH #undef W Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-03-31 08:27:08 UTC (rev 92) +++ trunk/varnish-cache/include/http_headers.h 2006-04-03 07:14:24 UTC (rev 93) @@ -2,24 +2,24 @@ * $Id$ */ -HTTPH("Accept-Charset", H_Accept_Charset) -HTTPH("Accept-Encoding", H_Accept_Encoding) -HTTPH("Accept-Language", H_Accept_Language) -HTTPH("Accept", H_Accept) -HTTPH("Authorization", H_Authorization) -HTTPH("Connection", H_Connection) -HTTPH("Expect", H_Expect) -HTTPH("From", H_From) -HTTPH("Host", H_Host) -HTTPH("If-Match", H_If_Match) -HTTPH("If-Modified-Since", H_If_Modified_Since) -HTTPH("If-None-Match", H_If_None_Match) -HTTPH("If-Range", H_If_Range) -HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since) -HTTPH("Keep-Alive", H_Keep_Alive) -HTTPH("Max-Forwards", H_Max_Forwards) -HTTPH("Proxy-Authorization", H_Proxy_Authorization) -HTTPH("Range", H_Range) -HTTPH("Referer", H_Referer) -HTTPH("TE", H_TE) -HTTPH("User-Agent", H_User_Agent) +HTTPH("Accept-Charset", H_Accept_Charset, 0, 0, 0, 0, 0) +HTTPH("Accept-Encoding", H_Accept_Encoding, 0, 0, 0, 0, 0) +HTTPH("Accept-Language", H_Accept_Language, 0, 0, 0, 0, 0) +HTTPH("Accept", H_Accept, 0, 0, 0, 0, 0) +HTTPH("Authorization", H_Authorization, 0, 0, 0, 0, 0) +HTTPH("Connection", H_Connection, 0, 0, 0, 0, 0) +HTTPH("Expect", H_Expect, 0, 0, 0, 0, 0) +HTTPH("From", H_From, 0, 0, 0, 0, 0) +HTTPH("Host", H_Host, 0, 0, 0, 0, 0) +HTTPH("If-Match", H_If_Match, 0, 0, 0, 0, 0) +HTTPH("If-Modified-Since", H_If_Modified_Since, 0, 0, 0, 0, 0) +HTTPH("If-None-Match", H_If_None_Match, 0, 0, 0, 0, 0) +HTTPH("If-Range", H_If_Range, 0, 0, 0, 0, 0) +HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 0, 0, 0, 0, 0) +HTTPH("Keep-Alive", H_Keep_Alive, 0, 0, 0, 0, 0) +HTTPH("Max-Forwards", H_Max_Forwards, 0, 0, 0, 0, 0) +HTTPH("Proxy-Authorization", H_Proxy_Authorization, 0, 0, 0, 0, 0) +HTTPH("Range", H_Range, 0, 0, 0, 0, 0) +HTTPH("Referer", H_Referer, 0, 0, 0, 0, 0) +HTTPH("TE", H_TE, 0, 0, 0, 0, 0) +HTTPH("User-Agent", H_User_Agent, 0, 0, 0, 0, 0) Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-03-31 08:27:08 UTC (rev 92) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-03 07:14:24 UTC (rev 93) @@ -14,6 +14,6 @@ SLTM(URL) SLTM(Protocol) SLTM(H_Unknown) -#define HTTPH(a, b) SLTM(b) +#define HTTPH(a, b, c, d, e, f, g) SLTM(b) #include "http_headers.h" #undef HTTPH Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-03-31 08:27:08 UTC (rev 92) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-03 07:14:24 UTC (rev 93) @@ -37,7 +37,7 @@ const char *req_b; const char *url_b; const char *proto_b; -#define HTTPH(a, b) const char *b; +#define HTTPH(a, b, c, d, e, f, g) const char *b; #include #undef HTTPH Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-03-31 08:27:08 UTC (rev 92) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-03 07:14:24 UTC (rev 93) @@ -418,32 +418,32 @@ fputs(" const char *req_b;\n", f); fputs(" const char *url_b;\n", f); fputs(" const char *proto_b;\n", f); - fputs("#define HTTPH(a, b) const char *b;\n", f); + fputs("#define HTTPH(a, b, c, d, e, f, g) const char *b;\n", f); fputs("/*\n", f); fputs(" * $Id$\n", f); fputs(" */\n", f); fputs("\n", f); - fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset)\n", f); - fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding)\n", f); - fputs("HTTPH(\"Accept-Language\", H_Accept_Language)\n", f); - fputs("HTTPH(\"Accept\", H_Accept)\n", f); - fputs("HTTPH(\"Authorization\", H_Authorization)\n", f); - fputs("HTTPH(\"Connection\", H_Connection)\n", f); - fputs("HTTPH(\"Expect\", H_Expect)\n", f); - fputs("HTTPH(\"From\", H_From)\n", f); - fputs("HTTPH(\"Host\", H_Host)\n", f); - fputs("HTTPH(\"If-Match\", H_If_Match)\n", f); - fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since)\n", f); - fputs("HTTPH(\"If-None-Match\", H_If_None_Match)\n", f); - fputs("HTTPH(\"If-Range\", H_If_Range)\n", f); - fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since)\n", f); - fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive)\n", f); - fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards)\n", f); - fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization)\n", f); - fputs("HTTPH(\"Range\", H_Range)\n", f); - fputs("HTTPH(\"Referer\", H_Referer)\n", f); - fputs("HTTPH(\"TE\", H_TE)\n", f); - fputs("HTTPH(\"User-Agent\", H_User_Agent)\n", f); + fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept\", H_Accept, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Authorization\", H_Authorization, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Connection\", H_Connection, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Expect\", H_Expect, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"From\", H_From, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Host\", H_Host, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Match\", H_If_Match, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Range\", H_If_Range, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Range\", H_Range, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Referer\", H_Referer, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"TE\", H_TE, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"User-Agent\", H_User_Agent, 0, 0, 0, 0, 0)\n", f); fputs("#undef HTTPH\n", f); fputs("\n", f); fputs(" enum {\n", f); From phk at projects.linpro.no Mon Apr 3 07:27:29 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 3 Apr 2006 09:27:29 +0200 (CEST) Subject: r94 - trunk/varnish-cache/bin/varnishd Message-ID: <20060403072729.170621ED61D@projects.linpro.no> Author: phk Date: 2006-04-03 09:27:28 +0200 (Mon, 03 Apr 2006) New Revision: 94 Modified: trunk/varnish-cache/bin/varnishd/cache_vcl.c Log: Call the init function when the VCL code is loaded. We may want to postpone this to use time later on. Modified: trunk/varnish-cache/bin/varnishd/cache_vcl.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-03 07:14:24 UTC (rev 93) +++ trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-03 07:27:28 UTC (rev 94) @@ -94,6 +94,7 @@ active_vcl = vcl; AZ(pthread_mutex_unlock(&sessmtx)); fprintf(stderr, "Loaded \"%s\" as \"%s\"\n", fn , name); + vcl->conf->init_func(); return (0); } From phk at projects.linpro.no Mon Apr 3 09:02:27 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 3 Apr 2006 11:02:27 +0200 (CEST) Subject: r95 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060403090227.B2BA21ED61F@projects.linpro.no> Author: phk Date: 2006-04-03 11:02:27 +0200 (Mon, 03 Apr 2006) New Revision: 95 Added: trunk/varnish-cache/bin/varnishd/cache_pipe.c Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_acceptor.c trunk/varnish-cache/bin/varnishd/cache_backend.c trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: A little step for humanity but a big step for varnish: Implement pipe-through mode and see the first web-pages actually pass through varnish. Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-03 09:02:27 UTC (rev 95) @@ -10,6 +10,7 @@ cache_httpd.c \ cache_main.c \ cache_pool.c \ + cache_pipe.c \ cache_shmlog.c \ cache_vcl.c \ cli_event.c \ Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-03 09:02:27 UTC (rev 95) @@ -4,9 +4,13 @@ /* cache_acceptor.c */ void *vca_main(void *arg); +void vca_retire_session(struct sess *sp); /* cache_backend.c */ void VBE_Init(void); +int VBE_GetFd(struct backend *bp, void **ptr); +void VBE_Pass(struct sess *sp); +void VBE_ClosedFd(void *ptr); /* cache_httpd.c */ void HttpdAnalyze(struct sess *sp); @@ -14,6 +18,9 @@ /* cache_main.c */ pthread_mutex_t sessmtx; +/* cache_pipe.c */ +void PipeSession(struct sess *sp); + /* cache_pool.c */ void CacheInitPool(void); void DealWithSession(struct sess *sp); Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-03 09:02:27 UTC (rev 95) @@ -137,3 +137,12 @@ return ("FOOBAR"); } + +void +vca_retire_session(struct sess *sp) +{ + + if (sp->fd >= 0) + close(sp->fd); + free(sp); +} Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-03 09:02:27 UTC (rev 95) @@ -12,6 +12,7 @@ #include #include #include +#include #include "libvarnish.h" #include "vcl_lang.h" @@ -86,7 +87,7 @@ /*--------------------------------------------------------------------*/ int -VBE_GetFd(struct backend *bp) +VBE_GetFd(struct backend *bp, void **ptr) { struct vbe *vp; struct vbe_conn *vc; @@ -113,20 +114,81 @@ TAILQ_REMOVE(&vp->fconn, vc, list); TAILQ_INSERT_TAIL(&vp->bconn, vc, list); AZ(pthread_mutex_unlock(&vbemtx)); - return (vc->fd); + } else { + vc = calloc(sizeof *vc, 1); + assert(vc != NULL); + vc->vbe = vp; + vc->fd = -1; + TAILQ_INSERT_TAIL(&vp->bconn, vc, list); + AZ(pthread_mutex_unlock(&vbemtx)); + connect_to_backend(vc, bp); } - vc = calloc(sizeof *vc, 1); - assert(vc != NULL); - vc->vbe = vp; - vc->fd = -1; - TAILQ_INSERT_TAIL(&vp->bconn, vc, list); + *ptr = vc; + return (vc->fd); +} + +void +VBE_ClosedFd(void *ptr) +{ + struct vbe_conn *vc; + + vc = ptr; + AZ(pthread_mutex_lock(&vbemtx)); + TAILQ_REMOVE(&vc->vbe->bconn, vc, list); AZ(pthread_mutex_unlock(&vbemtx)); - connect_to_backend(vc, bp); + free(vc); +} - /* XXX */ - return (-1); +/*--------------------------------------------------------------------*/ +void +VBE_Pass(struct sess *sp) +{ + int fd, i; + void *fd_token; + struct sbuf *sb; + + fd = VBE_GetFd(sp->backend, &fd_token); + assert(fd != -1); + + sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + assert(sb != NULL); + sbuf_cat(sb, sp->req); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->url); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->proto); + sbuf_cat(sb, "\r\n"); +#define HTTPH(a, b, c, d, e, f, g) \ + do { \ + if (c && sp->b != NULL) { \ + sbuf_cat(sb, a ": "); \ + sbuf_cat(sb, sp->b); \ + sbuf_cat(sb, "\r\n"); \ + } \ + } while (0); +#include "http_headers.h" +#undef HTTPH + sbuf_cat(sb, "\r\n"); + sbuf_finish(sb); + printf("REQ: <%s>\n", sbuf_data(sb)); + i = write(fd, sbuf_data(sb), sbuf_len(sb)); + assert(i == sbuf_len(sb)); + { + char buf[101]; + + for(;;) { + i = read(fd, buf, 100); + if (i > 0) { + buf[i] = '\0'; + printf("RESP: <%s>\n", buf); + } + } + + } } +/*--------------------------------------------------------------------*/ + void VBE_Init(void) { Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 09:02:27 UTC (rev 95) @@ -22,30 +22,30 @@ sp->handling = HND_Unclass; /* First, isolate and possibly identify request type */ - sp->req_b = sp->rcv; + sp->req = sp->rcv; for (p = sp->rcv; isalpha(*p); p++) ; - VSLR(SLT_Request, sp->fd, sp->req_b, p); + VSLR(SLT_Request, sp->fd, sp->req, p); *p++ = '\0'; /* Next find the URI */ while (isspace(*p)) p++; - sp->url_b = p; + sp->url = p; while (!isspace(*p)) p++; - VSLR(SLT_URL, sp->fd, sp->url_b, p); + VSLR(SLT_URL, sp->fd, sp->url, p); *p++ = '\0'; /* Finally, look for protocol, if any */ while (isspace(*p) && *p != '\n') p++; - sp->proto_b = p; + sp->proto = p; if (*p != '\n') { while (!isspace(*p)) p++; } - VSLR(SLT_Protocol, sp->fd, sp->proto_b, p); + VSLR(SLT_Protocol, sp->fd, sp->proto, p); *p++ = '\0'; while (isspace(*p) && *p != '\n') Added: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-03 09:02:27 UTC (rev 95) @@ -0,0 +1,97 @@ +/* + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libvarnish.h" +#include "vcl_lang.h" +#include "cache.h" + +struct edir { + int fd; + struct event ev; +}; + +static void +rdf(int fd, short event, void *arg) +{ + int i, j; + struct edir *ep; + char buf[BUFSIZ]; + + ep = arg; + i = read(fd, buf, sizeof buf); + if (i <= 0) { + shutdown(fd, SHUT_RD); + shutdown(ep->fd, SHUT_WR); + event_del(&ep->ev); + } else { + j = write(ep->fd, buf, i); + assert(i == j); + } +} + +void +PipeSession(struct sess *sp) +{ + int fd, i; + void *fd_token; + struct sbuf *sb; + struct event_base *eb; + struct edir e1, e2; + + fd = VBE_GetFd(sp->backend, &fd_token); + assert(fd != -1); + + sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + assert(sb != NULL); + sbuf_cat(sb, sp->req); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->url); + if (sp->proto != NULL) { + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->proto); + } + sbuf_cat(sb, "\r\n"); +#define HTTPH(a, b, c, d, e, f, g) \ + do { \ + if (sp->b != NULL) { \ + sbuf_cat(sb, a ": "); \ + sbuf_cat(sb, sp->b); \ + sbuf_cat(sb, "\r\n"); \ + } \ + } while (0); +#include "http_headers.h" +#undef HTTPH + sbuf_cat(sb, "\r\n"); + sbuf_finish(sb); + printf("REQ: <%s>\n", sbuf_data(sb)); + i = write(fd, sbuf_data(sb), sbuf_len(sb)); + assert(i == sbuf_len(sb)); + + e1.fd = fd; + e2.fd = sp->fd; + eb = event_init(); + event_set(&e1.ev, sp->fd, EV_READ | EV_PERSIST, rdf, &e1); + event_base_set(eb, &e1.ev); + event_set(&e2.ev, fd, EV_READ | EV_PERSIST, rdf, &e2); + event_base_set(eb, &e2.ev); + event_add(&e1.ev, NULL); + event_add(&e2.ev, NULL); + event_base_loop(eb, 0); + close (fd); + close (sp->fd); + /* XXX: Delete eb */ + VBE_ClosedFd(fd_token); + sp->fd = -1; +} Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-03 09:02:27 UTC (rev 95) @@ -39,10 +39,12 @@ printf("Handling: %d\n", sp->handling); + PipeSession(sp); + AZ(pthread_mutex_lock(&sessmtx)); RelVCL(sp->vcl); sp->vcl = NULL; - /* XXX send session to acceptor for reuse/disposal */ + vca_retire_session(sp); } } Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/include/http_headers.h 2006-04-03 09:02:27 UTC (rev 95) @@ -1,16 +1,26 @@ /* * $Id$ + * + * a Http header name + * b session field name + * c PassThrough handling (0=remove, 1=pass) + * d unused + * e unused + * f unused + * g unused + * + * a b c d e f g + *-------------------------------------------------------------------- */ - HTTPH("Accept-Charset", H_Accept_Charset, 0, 0, 0, 0, 0) HTTPH("Accept-Encoding", H_Accept_Encoding, 0, 0, 0, 0, 0) HTTPH("Accept-Language", H_Accept_Language, 0, 0, 0, 0, 0) HTTPH("Accept", H_Accept, 0, 0, 0, 0, 0) HTTPH("Authorization", H_Authorization, 0, 0, 0, 0, 0) -HTTPH("Connection", H_Connection, 0, 0, 0, 0, 0) +HTTPH("Connection", H_Connection, 1, 0, 0, 0, 0) HTTPH("Expect", H_Expect, 0, 0, 0, 0, 0) HTTPH("From", H_From, 0, 0, 0, 0, 0) -HTTPH("Host", H_Host, 0, 0, 0, 0, 0) +HTTPH("Host", H_Host, 1, 0, 0, 0, 0) HTTPH("If-Match", H_If_Match, 0, 0, 0, 0, 0) HTTPH("If-Modified-Since", H_If_Modified_Since, 0, 0, 0, 0, 0) HTTPH("If-None-Match", H_If_None_Match, 0, 0, 0, 0, 0) @@ -22,4 +32,4 @@ HTTPH("Range", H_Range, 0, 0, 0, 0, 0) HTTPH("Referer", H_Referer, 0, 0, 0, 0, 0) HTTPH("TE", H_TE, 0, 0, 0, 0, 0) -HTTPH("User-Agent", H_User_Agent, 0, 0, 0, 0, 0) +HTTPH("User-Agent", H_User_Agent, 1, 0, 0, 0, 0) Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-03 09:02:27 UTC (rev 95) @@ -34,9 +34,9 @@ unsigned rcv_len; /* HTTP request info, points into rcv */ - const char *req_b; - const char *url_b; - const char *proto_b; + const char *req; + const char *url; + const char *proto; #define HTTPH(a, b, c, d, e, f, g) const char *b; #include #undef HTTPH @@ -44,7 +44,8 @@ enum { HND_Unclass, HND_Handle, - HND_Pass + HND_Pass, + HND_Pipe } handling; char done; Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-03 07:27:28 UTC (rev 94) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-03 09:02:27 UTC (rev 95) @@ -415,23 +415,33 @@ fputs(" unsigned rcv_len;\n", f); fputs("\n", f); fputs(" /* HTTP request info, points into rcv */\n", f); - fputs(" const char *req_b;\n", f); - fputs(" const char *url_b;\n", f); - fputs(" const char *proto_b;\n", f); + fputs(" const char *req;\n", f); + fputs(" const char *url;\n", f); + fputs(" const char *proto;\n", f); fputs("#define HTTPH(a, b, c, d, e, f, g) const char *b;\n", f); fputs("/*\n", f); fputs(" * $Id$\n", f); + fputs(" *\n", f); + fputs(" * a Http header name\n", f); + fputs(" * b session field name\n", f); + fputs(" * c PassThrough handling (0=remove, 1=pass)\n", f); + fputs(" * d unused\n", f); + fputs(" * e unused\n", f); + fputs(" * f unused\n", f); + fputs(" * g unused\n", f); + fputs(" *\n", f); + fputs(" * a b c d e f g \n", f); + fputs(" *--------------------------------------------------------------------\n", f); fputs(" */\n", f); - fputs("\n", f); fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Accept\", H_Accept, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Authorization\", H_Authorization, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Connection\", H_Connection, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Connection\", H_Connection, 1, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Expect\", H_Expect, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"From\", H_From, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Host\", H_Host, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Host\", H_Host, 1, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"If-Match\", H_If_Match, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 0, 0, 0, 0, 0)\n", f); @@ -443,13 +453,14 @@ fputs("HTTPH(\"Range\", H_Range, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Referer\", H_Referer, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"TE\", H_TE, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"User-Agent\", H_User_Agent, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 0, 0, 0, 0)\n", f); fputs("#undef HTTPH\n", f); fputs("\n", f); fputs(" enum {\n", f); fputs(" HND_Unclass,\n", f); fputs(" HND_Handle,\n", f); - fputs(" HND_Pass\n", f); + fputs(" HND_Pass,\n", f); + fputs(" HND_Pipe\n", f); fputs(" } handling;\n", f); fputs("\n", f); fputs(" char done;\n", f); From phk at projects.linpro.no Mon Apr 3 11:03:28 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 3 Apr 2006 13:03:28 +0200 (CEST) Subject: r96 - trunk/varnish-cache/bin/varnishd Message-ID: <20060403110328.7D42E1ED604@projects.linpro.no> Author: phk Date: 2006-04-03 13:03:28 +0200 (Mon, 03 Apr 2006) New Revision: 96 Modified: trunk/varnish-cache/bin/varnishd/cache_main.c trunk/varnish-cache/bin/varnishd/cli_event.c trunk/varnish-cache/bin/varnishd/cli_event.h trunk/varnish-cache/bin/varnishd/mgt.h trunk/varnish-cache/bin/varnishd/mgt_child.c trunk/varnish-cache/bin/varnishd/varnishd.c Log: How I wish people would think more ahead when writing libraries like libevent. The entire "implicit event engine" api assumption stinks. Deal with it better. Modified: trunk/varnish-cache/bin/varnishd/cache_main.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_main.c 2006-04-03 09:02:27 UTC (rev 95) +++ trunk/varnish-cache/bin/varnishd/cache_main.c 2006-04-03 11:03:28 UTC (rev 96) @@ -113,7 +113,7 @@ assert(eb != NULL); CVCL_Load(heritage.vcl_file, "boot"); - cli = cli_setup(heritage.fds[2], heritage.fds[1], 0, cli_proto); + cli = cli_setup(eb, heritage.fds[2], heritage.fds[1], 0, cli_proto); evtimer_set(&ev_keepalive, timer_keepalive, NULL); event_base_set(eb, &ev_keepalive); Modified: trunk/varnish-cache/bin/varnishd/cli_event.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cli_event.c 2006-04-03 09:02:27 UTC (rev 95) +++ trunk/varnish-cache/bin/varnishd/cli_event.c 2006-04-03 11:03:28 UTC (rev 96) @@ -123,8 +123,25 @@ printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg); } +/* + * XXX: included in libevent in CVS + */ + +static int +bufferevent_base_set(struct event_base *base, struct bufferevent *bufev) +{ + int res; + + res = event_base_set(base, &bufev->ev_read); + if (res == -1) + return (res); + + res = event_base_set(base, &bufev->ev_write); + return (res); +} + struct cli * -cli_setup(int fdr, int fdw, int ver, struct cli_proto *cli_proto) +cli_setup(struct event_base *eb, int fdr, int fdw, int ver, struct cli_proto *cli_proto) { struct cli *cli; @@ -133,11 +150,13 @@ cli->bev0 = bufferevent_new(fdr, rdcb, wrcb, excb, cli); assert(cli->bev0 != NULL); + bufferevent_base_set(eb, cli->bev0); if (fdr == fdw) cli->bev1 = cli->bev0; else cli->bev1 = bufferevent_new(fdw, rdcb, wrcb, excb, cli); assert(cli->bev1 != NULL); + bufferevent_base_set(eb, cli->bev1); cli->sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); assert(cli->sb != NULL); Modified: trunk/varnish-cache/bin/varnishd/cli_event.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cli_event.h 2006-04-03 09:02:27 UTC (rev 95) +++ trunk/varnish-cache/bin/varnishd/cli_event.h 2006-04-03 11:03:28 UTC (rev 96) @@ -11,7 +11,7 @@ struct cli_proto *cli_proto; }; -struct cli *cli_setup(int fdr, int fdw, int ver, struct cli_proto *cli_proto); +struct cli *cli_setup(struct event_base *eb, int fdr, int fdw, int ver, struct cli_proto *cli_proto); void cli_suspend(struct cli *cli); void cli_resume(struct cli *cli); void cli_encode_string(struct evbuffer *buf, char *b); Modified: trunk/varnish-cache/bin/varnishd/mgt.h =================================================================== --- trunk/varnish-cache/bin/varnishd/mgt.h 2006-04-03 09:02:27 UTC (rev 95) +++ trunk/varnish-cache/bin/varnishd/mgt.h 2006-04-03 11:03:28 UTC (rev 96) @@ -2,7 +2,7 @@ * $Id$ */ -extern struct event_base *eb; +extern struct event_base *mgt_eb; void mgt_child_start(void); void mgt_child_stop(void); Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c =================================================================== --- trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-03 09:02:27 UTC (rev 95) +++ trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-03 11:03:28 UTC (rev 96) @@ -246,6 +246,7 @@ assert(child_cli1 != NULL); evtimer_set(&ev_child_pingpong, child_pingpong, NULL); + event_base_set(mgt_eb, &ev_child_pingpong); child_pingpong(0, 0, NULL); } Modified: trunk/varnish-cache/bin/varnishd/varnishd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-03 09:02:27 UTC (rev 95) +++ trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-03 11:03:28 UTC (rev 96) @@ -34,7 +34,7 @@ /*--------------------------------------------------------------------*/ struct heritage heritage; -struct event_base *eb; +struct event_base *mgt_eb; /*-------------------------------------------------------------------- * Generic passthrough for CLI functions @@ -242,15 +242,15 @@ struct cli *cli; int i; - eb = event_init(); - assert(eb != NULL); + mgt_eb = event_init(); + assert(mgt_eb != NULL); - cli = cli_setup(0, 1, 1, cli_proto); + cli = cli_setup(mgt_eb, 0, 1, 1, cli_proto); signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL); signal_add(&e_sigchld, NULL); - i = event_dispatch(); + i = event_base_loop(mgt_eb, 0); if (i != 0) printf("event_dispatch() = %d\n", i); From phk at projects.linpro.no Mon Apr 3 11:05:53 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 3 Apr 2006 13:05:53 +0200 (CEST) Subject: r97 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060403110553.889D91ED645@projects.linpro.no> Author: phk Date: 2006-04-03 13:05:53 +0200 (Mon, 03 Apr 2006) New Revision: 97 Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/bin/varnishd/cache_pipe.c trunk/varnish-cache/include/shmlog_tags.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Segregate http header fields into a separate structure, we will reuse them a few places by the looks of it. Add VCA_UNKNOWNHDR (=10) fields for unknown HTTP headers. If more headers arrive than that, they're lost (and logged as such). Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-03 11:03:28 UTC (rev 96) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-03 11:05:53 UTC (rev 97) @@ -152,17 +152,17 @@ sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); assert(sb != NULL); - sbuf_cat(sb, sp->req); + sbuf_cat(sb, sp->http.req); sbuf_cat(sb, " "); - sbuf_cat(sb, sp->url); + sbuf_cat(sb, sp->http.url); sbuf_cat(sb, " "); - sbuf_cat(sb, sp->proto); + sbuf_cat(sb, sp->http.proto); sbuf_cat(sb, "\r\n"); #define HTTPH(a, b, c, d, e, f, g) \ do { \ - if (c && sp->b != NULL) { \ + if (c && sp->http.b != NULL) { \ sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp->b); \ + sbuf_cat(sb, sp->http.b); \ sbuf_cat(sb, "\r\n"); \ } \ } while (0); Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 11:03:28 UTC (rev 96) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 11:05:53 UTC (rev 97) @@ -22,30 +22,30 @@ sp->handling = HND_Unclass; /* First, isolate and possibly identify request type */ - sp->req = sp->rcv; + sp->http.req = sp->rcv; for (p = sp->rcv; isalpha(*p); p++) ; - VSLR(SLT_Request, sp->fd, sp->req, p); + VSLR(SLT_Request, sp->fd, sp->http.req, p); *p++ = '\0'; /* Next find the URI */ while (isspace(*p)) p++; - sp->url = p; + sp->http.url = p; while (!isspace(*p)) p++; - VSLR(SLT_URL, sp->fd, sp->url, p); + VSLR(SLT_URL, sp->fd, sp->http.url, p); *p++ = '\0'; /* Finally, look for protocol, if any */ while (isspace(*p) && *p != '\n') p++; - sp->proto = p; + sp->http.proto = p; if (*p != '\n') { while (!isspace(*p)) p++; } - VSLR(SLT_Protocol, sp->fd, sp->proto, p); + VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); *p++ = '\0'; while (isspace(*p) && *p != '\n') @@ -55,9 +55,7 @@ if (*p == '\r') p++; -#define HTTPH(a, b, c, d, e, f, g) sp->b = NULL; -#include "http_headers.h" -#undef HTTPH + memset(&sp->http, 0, sizeof sp->http); for (; p < sp->rcv + sp->rcv_len; p = r) { q = strchr(p, '\n'); @@ -72,7 +70,7 @@ if (!strncasecmp(p, a, strlen(a))) { \ for (p += strlen(a); p < q && isspace(*p); p++) \ continue; \ - sp->b = p; \ + sp->http.b = p; \ VSLR(SLT_##b, sp->fd, p, q); \ continue; \ } @@ -81,7 +79,11 @@ #include "http_headers.h" #undef HTTPH #undef W - VSLR(SLT_H_Unknown, sp->fd, p, q); + if (sp->http.nuhdr < VCA_UNKNOWNHDR) { + sp->http.uhdr[sp->http.nuhdr++] = p; + VSLR(SLT_HD_Unknown, sp->fd, p, q); + } else { + VSLR(SLT_HD_Lost, sp->fd, p, q); + } } - } Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-03 11:03:28 UTC (rev 96) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-03 11:05:53 UTC (rev 97) @@ -55,19 +55,19 @@ sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); assert(sb != NULL); - sbuf_cat(sb, sp->req); + sbuf_cat(sb, sp->http.req); sbuf_cat(sb, " "); - sbuf_cat(sb, sp->url); - if (sp->proto != NULL) { + sbuf_cat(sb, sp->http.url); + if (sp->http.proto != NULL) { sbuf_cat(sb, " "); - sbuf_cat(sb, sp->proto); + sbuf_cat(sb, sp->http.proto); } sbuf_cat(sb, "\r\n"); #define HTTPH(a, b, c, d, e, f, g) \ do { \ - if (sp->b != NULL) { \ + if (sp->http.b != NULL) { \ sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp->b); \ + sbuf_cat(sb, sp->http.b); \ sbuf_cat(sb, "\r\n"); \ } \ } while (0); Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-03 11:03:28 UTC (rev 96) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-03 11:05:53 UTC (rev 97) @@ -13,7 +13,8 @@ SLTM(Request) SLTM(URL) SLTM(Protocol) -SLTM(H_Unknown) +SLTM(HD_Unknown) +SLTM(HD_Lost) #define HTTPH(a, b, c, d, e, f, g) SLTM(b) #include "http_headers.h" #undef HTTPH Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-03 11:03:28 UTC (rev 96) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-03 11:05:53 UTC (rev 97) @@ -22,7 +22,19 @@ #define VCA_RXBUFSIZE 1024 #define VCA_ADDRBUFSIZE 32 +#define VCA_UNKNOWNHDR 10 +struct httphdr { + const char *req; + const char *url; + const char *proto; +#define HTTPH(a, b, c, d, e, f, g) const char *b; +#include +#undef HTTPH + const char *uhdr[VCA_UNKNOWNHDR]; + unsigned nuhdr; +}; + struct sess { int fd; @@ -34,12 +46,7 @@ unsigned rcv_len; /* HTTP request info, points into rcv */ - const char *req; - const char *url; - const char *proto; -#define HTTPH(a, b, c, d, e, f, g) const char *b; -#include -#undef HTTPH + struct httphdr http; enum { HND_Unclass, Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-03 11:03:28 UTC (rev 96) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-03 11:05:53 UTC (rev 97) @@ -403,18 +403,9 @@ fputs("\n", f); fputs("#define VCA_RXBUFSIZE 1024\n", f); fputs("#define VCA_ADDRBUFSIZE 32\n", f); + fputs("#define VCA_UNKNOWNHDR 10\n", f); fputs("\n", f); - fputs("struct sess {\n", f); - fputs(" int fd;\n", f); - fputs("\n", f); - fputs(" /* formatted ascii client address */\n", f); - fputs(" char addr[VCA_ADDRBUFSIZE];\n", f); - fputs("\n", f); - fputs(" /* Receive buffer for HTTP header */\n", f); - fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f); - fputs(" unsigned rcv_len;\n", f); - fputs("\n", f); - fputs(" /* HTTP request info, points into rcv */\n", f); + fputs("struct httphdr {\n", f); fputs(" const char *req;\n", f); fputs(" const char *url;\n", f); fputs(" const char *proto;\n", f); @@ -455,7 +446,23 @@ fputs("HTTPH(\"TE\", H_TE, 0, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 0, 0, 0, 0)\n", f); fputs("#undef HTTPH\n", f); + fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); + fputs(" unsigned nuhdr;\n", f); + fputs("};\n", f); fputs("\n", f); + fputs("struct sess {\n", f); + fputs(" int fd;\n", f); + fputs("\n", f); + fputs(" /* formatted ascii client address */\n", f); + fputs(" char addr[VCA_ADDRBUFSIZE];\n", f); + fputs("\n", f); + fputs(" /* Receive buffer for HTTP header */\n", f); + fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f); + fputs(" unsigned rcv_len;\n", f); + fputs("\n", f); + fputs(" /* HTTP request info, points into rcv */\n", f); + fputs(" struct httphdr http;\n", f); + fputs("\n", f); fputs(" enum {\n", f); fputs(" HND_Unclass,\n", f); fputs(" HND_Handle,\n", f); From des at projects.linpro.no Mon Apr 3 11:59:08 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Mon, 3 Apr 2006 13:59:08 +0200 (CEST) Subject: r98 - in trunk/varnish-cache/contrib/libevent: . WIN32-Code WIN32-Prj test Message-ID: <20060403115908.733E01ED648@projects.linpro.no> Author: des Date: 2006-04-03 13:59:08 +0200 (Mon, 03 Apr 2006) New Revision: 98 Added: trunk/varnish-cache/contrib/libevent/event_rpcgen.py trunk/varnish-cache/contrib/libevent/event_tagging.c trunk/varnish-cache/contrib/libevent/http.c trunk/varnish-cache/contrib/libevent/http.h trunk/varnish-cache/contrib/libevent/strlcpy.c trunk/varnish-cache/contrib/libevent/test/regress.h trunk/varnish-cache/contrib/libevent/test/regress.rpc trunk/varnish-cache/contrib/libevent/test/regress_http.c Modified: trunk/varnish-cache/contrib/libevent/Makefile.am trunk/varnish-cache/contrib/libevent/README trunk/varnish-cache/contrib/libevent/WIN32-Code/win32.c trunk/varnish-cache/contrib/libevent/WIN32-Prj/libevent.dsp trunk/varnish-cache/contrib/libevent/buffer.c trunk/varnish-cache/contrib/libevent/configure.in trunk/varnish-cache/contrib/libevent/devpoll.c trunk/varnish-cache/contrib/libevent/epoll.c trunk/varnish-cache/contrib/libevent/evbuffer.c trunk/varnish-cache/contrib/libevent/event.3 trunk/varnish-cache/contrib/libevent/event.c trunk/varnish-cache/contrib/libevent/event.h trunk/varnish-cache/contrib/libevent/kqueue.c trunk/varnish-cache/contrib/libevent/log.h trunk/varnish-cache/contrib/libevent/poll.c trunk/varnish-cache/contrib/libevent/rtsig.c trunk/varnish-cache/contrib/libevent/select.c trunk/varnish-cache/contrib/libevent/signal.c trunk/varnish-cache/contrib/libevent/test/Makefile.am trunk/varnish-cache/contrib/libevent/test/regress.c trunk/varnish-cache/contrib/libevent/test/test-weof.c trunk/varnish-cache/contrib/libevent/test/test.sh Log: Update from libevent CVS trunk. Modified: trunk/varnish-cache/contrib/libevent/Makefile.am =================================================================== --- trunk/varnish-cache/contrib/libevent/Makefile.am 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/Makefile.am 2006-04-03 11:59:08 UTC (rev 98) @@ -2,9 +2,11 @@ SUBDIRS = . sample test +bin_SCRIPTS = event_rpcgen.py + EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h event.3 \ kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \ - devpoll.c \ + devpoll.c event_rpcgen.py \ sample/Makefile.am sample/Makefile.in sample/event-test.c \ sample/signal-test.c sample/time-test.c \ test/Makefile.am test/Makefile.in test/bench.c test/regress.c \ @@ -21,9 +23,10 @@ lib_LTLIBRARIES = libevent.la -libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c +libevent_la_SOURCES = event.c buffer.c evbuffer.c log.c event_tagging.c \ + http.c http.h libevent_la_LIBADD = @LTLIBOBJS@ -libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:2:0 +libevent_la_LDFLAGS = -release @VERSION@ -version-info 1:3:0 include_HEADERS = event.h Modified: trunk/varnish-cache/contrib/libevent/README =================================================================== --- trunk/varnish-cache/contrib/libevent/README 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/README 2006-04-03 11:59:08 UTC (rev 98) @@ -12,6 +12,10 @@ Before, reporting any problems, please run the regression tests. +To enable the low-level tracing build the library as: + +CFLAGS=-DUSE_DEBUG ./configure [...] + Acknowledgements: ----------------- @@ -24,5 +28,8 @@ Mike Davis William Ahern Alexander von Gernler + Artur Grabowski + Stas Bekman + Tassilo von Parseval If I have forgotten your name, please contact me. Modified: trunk/varnish-cache/contrib/libevent/WIN32-Code/win32.c =================================================================== --- trunk/varnish-cache/contrib/libevent/WIN32-Code/win32.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/WIN32-Code/win32.c 2006-04-03 11:59:08 UTC (rev 98) @@ -81,6 +81,7 @@ int win32_del (void *, struct event *); int win32_recalc (struct event_base *base, void *, int); int win32_dispatch (struct event_base *base, void *, struct timeval *); +void win32_dealloc (void *); struct eventop win32ops = { "win32", @@ -88,7 +89,8 @@ win32_insert, win32_del, win32_recalc, - win32_dispatch + win32_dispatch, + win32_dealloc }; #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET))) @@ -135,6 +137,8 @@ if (set->fd_count == op->fd_setsz) { if (realloc_fd_sets(op, op->fd_setsz*2)) return (-1); + /* set pointer will have changed and needs reiniting! */ + set = read ? op->readset_in : op->writeset_in; } set->fd_array[set->fd_count] = s; return (set->fd_count++); @@ -363,7 +367,28 @@ return (0); } +void +win32_dealloc(void *arg) +{ + struct win32op *win32op = arg; + if (win32op->readset_in) + free(win32op->readset_in); + if (win32op->writeset_in) + free(win32op->writeset_in); + if (win32op->readset_out) + free(win32op->readset_out); + if (win32op->writeset_out) + free(win32op->writeset_out); + if (win32op->exset_out) + free(win32op->exset_out); + if (win32op->events) + free(win32op->events); + + memset(win32op, 0, sizeof(win32op)); + free(win32op); +} + static int signal_handler(int sig) { Modified: trunk/varnish-cache/contrib/libevent/WIN32-Prj/libevent.dsp =================================================================== --- trunk/varnish-cache/contrib/libevent/WIN32-Prj/libevent.dsp 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/WIN32-Prj/libevent.dsp 2006-04-03 11:59:08 UTC (rev 98) @@ -85,7 +85,7 @@ # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File -SOURCE=..\err.c +SOURCE=..\log.c # End Source File # Begin Source File Modified: trunk/varnish-cache/contrib/libevent/buffer.c =================================================================== --- trunk/varnish-cache/contrib/libevent/buffer.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/buffer.c 2006-04-03 11:59:08 UTC (rev 98) @@ -117,45 +117,55 @@ } res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off); - if (res == 0) + if (res == 0) { + /* We drain the input buffer on success */ evbuffer_drain(inbuf, inbuf->off); + } return (res); } int -evbuffer_add_printf(struct evbuffer *buf, char *fmt, ...) +evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) { - int res = -1; - char *msg; -#ifndef HAVE_VASPRINTF - static char buffer[4096]; -#endif - va_list ap; + char *buffer; + size_t space; + size_t oldoff = buf->off; + int sz; - va_start(ap, fmt); + for (;;) { + buffer = buf->buffer + buf->off; + space = buf->totallen - buf->misalign - buf->off; -#ifdef HAVE_VASPRINTF - if (vasprintf(&msg, fmt, ap) == -1) - goto end; +#ifdef WIN32 + sz = vsnprintf(buffer, space - 1, fmt, ap); + buffer[space - 1] = '\0'; #else -# ifdef WIN32 - _vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap); - buffer[sizeof(buffer)-1] = '\0'; -# else /* ! WIN32 */ - vsnprintf(buffer, sizeof(buffer), fmt, ap); -# endif - msg = buffer; + sz = vsnprintf(buffer, space, fmt, ap); #endif - - res = strlen(msg); - if (evbuffer_add(buf, msg, res) == -1) - res = -1; -#ifdef HAVE_VASPRINTF - free(msg); + if (sz == -1) + return (-1); + if (sz < space) { + buf->off += sz; + if (buf->cb != NULL) + (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); + return (sz); + } + if (evbuffer_expand(buf, sz + 1) == -1) + return (-1); -end: -#endif + } + /* NOTREACHED */ +} + +int +evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) +{ + int res = -1; + va_list ap; + + va_start(ap, fmt); + res = evbuffer_add_vprintf(buf, fmt, ap); va_end(ap); return (res); @@ -184,16 +194,16 @@ char * evbuffer_readline(struct evbuffer *buffer) { - char *data = EVBUFFER_DATA(buffer); + u_char *data = EVBUFFER_DATA(buffer); size_t len = EVBUFFER_LENGTH(buffer); char *line; - int i; + u_int i; for (i = 0; i < len; i++) { if (data[i] == '\r' || data[i] == '\n') break; } - + if (i == len) return (NULL); @@ -332,8 +342,21 @@ #endif #ifdef FIONREAD - if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) + if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) { n = EVBUFFER_MAX_READ; + } else if (n > EVBUFFER_MAX_READ && n > howmuch) { + /* + * It's possible that a lot of data is available for + * reading. We do not want to exhaust resources + * before the reader has a chance to do something + * about it. If the reader does not tell us how much + * data we should read, we artifically limit it. + */ + if (n > buf->totallen << 2) + n = buf->totallen << 2; + if (n < EVBUFFER_MAX_READ) + n = EVBUFFER_MAX_READ; + } #endif if (howmuch < 0 || howmuch > n) howmuch = n; @@ -397,7 +420,7 @@ } u_char * -evbuffer_find(struct evbuffer *buffer, u_char *what, size_t len) +evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len) { size_t remain = buffer->off; u_char *search = buffer->buffer; Modified: trunk/varnish-cache/contrib/libevent/configure.in =================================================================== --- trunk/varnish-cache/contrib/libevent/configure.in 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/configure.in 2006-04-03 11:59:08 UTC (rev 98) @@ -2,7 +2,7 @@ dnl Dug Song AC_INIT(event.c) -AM_INIT_AUTOMAKE(libevent,1.1a) +AM_INIT_AUTOMAKE(libevent,1.2) AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE @@ -117,7 +117,8 @@ AC_HEADER_TIME dnl Checks for library functions. -AC_CHECK_FUNCS(gettimeofday vasprintf fcntl) +AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime) +AC_REPLACE_FUNCS(strlcpy) AC_MSG_CHECKING(for F_SETFD in fcntl.h) AC_EGREP_CPP(yes, Modified: trunk/varnish-cache/contrib/libevent/devpoll.c =================================================================== --- trunk/varnish-cache/contrib/libevent/devpoll.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/devpoll.c 2006-04-03 11:59:08 UTC (rev 98) @@ -76,6 +76,7 @@ int devpoll_del (void *, struct event *); int devpoll_recalc (struct event_base *, void *, int); int devpoll_dispatch (struct event_base *, void *, struct timeval *); +void devpoll_dealloc (void *); struct eventop devpollops = { "devpoll", @@ -83,7 +84,8 @@ devpoll_add, devpoll_del, devpoll_recalc, - devpoll_dispatch + devpoll_dispatch, + devpoll_dealloc }; #define NEVENT 32000 @@ -401,3 +403,21 @@ return (0); } + +void +devpoll_dealloc(void *arg) +{ + struct devpollop *devpollop = arg; + + if (devpollop->fds) + free(devpollop->fds); + if (devpollop->events) + free(devpollop->events); + if (devpollop->changes) + free(devpollop->changes); + if (devpollop->dpfd >= 0) + close(devpollop->dpfd); + + memset(devpollop, 0, sizeof(struct devpollop)); + free(devpollop); +} Modified: trunk/varnish-cache/contrib/libevent/epoll.c =================================================================== --- trunk/varnish-cache/contrib/libevent/epoll.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/epoll.c 2006-04-03 11:59:08 UTC (rev 98) @@ -76,6 +76,7 @@ int epoll_del (void *, struct event *); int epoll_recalc (struct event_base *, void *, int); int epoll_dispatch (struct event_base *, void *, struct timeval *); +void epoll_dealloc (void *); struct eventop epollops = { "epoll", @@ -83,7 +84,8 @@ epoll_add, epoll_del, epoll_recalc, - epoll_dispatch + epoll_dispatch, + epoll_dealloc }; #ifdef HAVE_SETFD @@ -109,8 +111,14 @@ return (NULL); if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && - rl.rlim_cur != RLIM_INFINITY) - nfiles = rl.rlim_cur; + rl.rlim_cur != RLIM_INFINITY) { + /* + * Solaris is somewhat retarded - it's important to drop + * backwards compatibility when making changes. So, don't + * dare to put rl.rlim_cur here. + */ + nfiles = rl.rlim_cur - 1; + } /* Initalize the kernel queue */ @@ -343,3 +351,19 @@ return (0); } + +void +epoll_dealloc(void *arg) +{ + struct epollop *epollop = arg; + + if (epollop->fds) + free(epollop->fds); + if (epollop->events) + free(epollop->events); + if (epollop->epfd >= 0) + close(epollop->epfd); + + memset(epollop, 0, sizeof(struct epollop)); + free(epollop); +} Modified: trunk/varnish-cache/contrib/libevent/evbuffer.c =================================================================== --- trunk/varnish-cache/contrib/libevent/evbuffer.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/evbuffer.c 2006-04-03 11:59:08 UTC (rev 98) @@ -74,7 +74,7 @@ void *arg) { struct bufferevent *bufev = arg; /* - * If we are below the watermak then reschedule reading if it's + * If we are below the watermark then reschedule reading if it's * still enabled. */ if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) { @@ -92,13 +92,21 @@ int res = 0; short what = EVBUFFER_READ; size_t len; + int howmuch = -1; if (event == EV_TIMEOUT) { what |= EVBUFFER_TIMEOUT; goto error; } - res = evbuffer_read(bufev->input, fd, -1); + /* + * If we have a high watermark configured then we don't want to + * read more data than would make us reach the watermark. + */ + if (bufev->wm_read.high != 0) + howmuch = bufev->wm_read.high; + + res = evbuffer_read(bufev->input, fd, howmuch); if (res == -1) { if (errno == EAGAIN || errno == EINTR) goto reschedule; @@ -226,7 +234,12 @@ bufev->cbarg = cbarg; - bufev->enabled = EV_READ | EV_WRITE; + /* + * Set to EV_WRITE so that using bufferevent_write is going to + * trigger a callback. Reading needs to be explicitly enabled + * because otherwise no data will be available. + */ + bufev->enabled = EV_WRITE; return (bufev); } @@ -372,3 +385,16 @@ bufferevent_read_pressure_cb(bufev->input, 0, EVBUFFER_LENGTH(bufev->input), bufev); } + +int +bufferevent_base_set(struct event_base *base, struct bufferevent *bufev) +{ + int res; + + res = event_base_set(base, &bufev->ev_read); + if (res == -1) + return (res); + + res = event_base_set(base, &bufev->ev_write); + return (res); +} Modified: trunk/varnish-cache/contrib/libevent/event.3 =================================================================== --- trunk/varnish-cache/contrib/libevent/event.3 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/event.3 2006-04-03 11:59:08 UTC (rev 98) @@ -34,9 +34,11 @@ .Nm event_dispatch , .Nm event_loop , .Nm event_loopexit , +.Nm event_set , +.Nm event_base_dispatch , .Nm event_base_loop , .Nm event_base_loopexit , -.Nm event_set , +.Nm event_base_set , .Nm event_add , .Nm event_del , .Nm event_once , @@ -46,12 +48,12 @@ .Nm event_priority_set , .Nm evtimer_set , .Nm evtimer_add , -.Nm evtimer_del +.Nm evtimer_del , .Nm evtimer_pending , .Nm evtimer_initialized , .Nm signal_set , .Nm signal_add , -.Nm signal_del +.Nm signal_del , .Nm signal_pending , .Nm signal_initialized , .Nm bufferevent_new , @@ -62,16 +64,20 @@ .Nm bufferevent_enable , .Nm bufferevent_disable , .Nm bufferevent_settimeout , +.Nm bufferevent_base_set , .Nm evbuffer_new , .Nm evbuffer_free , .Nm evbuffer_add , .Nm evbuffer_add_buffer , .Nm evbuffer_add_printf , +.Nm evbuffer_add_vprintf , .Nm evbuffer_drain , .Nm evbuffer_write , .Nm evbuffer_read , .Nm evbuffer_find , -.Nm evbuffer_readline +.Nm evbuffer_readline , +.Nm evhttp_start , +.Nm evhttp_free .Nd execute a function when a specific event occurs .Sh SYNOPSIS .Fd #include @@ -84,13 +90,17 @@ .Fn "event_loop" "int flags" .Ft int .Fn "event_loopexit" "struct timeval *tv" -.Ft int -.Fn "event_base_loop" "struct event_base *" "int flags" -.Ft int -.Fn "event_base_loopexit" "struct event_base *" "struct timeval *tv" .Ft void .Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" .Ft int +.Fn "event_base_dispatch" "struct event_base *base" +.Ft int +.Fn "event_base_loop" "struct event_base *base" "int flags" +.Ft int +.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv" +.Ft int +.Fn "event_base_set" "struct event_base *base" "struct event *" +.Ft int .Fn "event_add" "struct event *ev" "struct timeval *tv" .Ft int .Fn "event_del" "struct event *ev" @@ -140,6 +150,8 @@ .Fn "bufferevent_disable" "struct bufferevent *bufev" "short event" .Ft void .Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write" +.Ft int +.Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev" .Ft "struct evbuffer *" .Fn "evbuffer_new" "void" .Ft void @@ -150,6 +162,8 @@ .Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src" .Ft int .Fn "evbuffer_add_printf" "struct evbuffer *buf" "char *fmt" "..." +.Ft int +.Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap" .Ft void .Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size" .Ft int @@ -160,6 +174,10 @@ .Fn "evbuffer_find" "struct evbuffer *buf" "u_char *data" "size_t size" .Ft "char *" .Fn "evbuffer_readline" "struct evbuffer *buf" +.Ft "struct evhttp *" +.Fn "evhttp_start" "const char *address" "u_short port" +.Ft "void" +.Fn "evhttp_free" "struct evhttp* http" .Ft int .Fa (*event_sigcb)(void) ; .Ft int @@ -193,24 +211,26 @@ to indicate that a signal has been received. The application sets .Va event_sigcb -to a callback function. After the signal handler sets +to a callback function. +After the signal handler sets .Va event_gotsig , .Nm event_dispatch -will execute the callback function to process received signals. The -callback returns 1 when no events are registered any more. It can -return -1 to indicate an error to the +will execute the callback function to process received signals. +The callback returns 1 when no events are registered any more. +It can return -1 to indicate an error to the .Nm event library, causing .Fn event_dispatch to terminate with .Va errno set to -.Er EINTR. +.Er EINTR . .Pp The .Nm event_loop function provides an interface for single pass execution of pending -events. The flags +events. +The flags .Va EVLOOP_ONCE and .Va EVLOOP_NONBLOCK @@ -243,14 +263,14 @@ argument given in the .Fa arg argument. -The +The .Fa fd indicates the file descriptor that should be monitored for events. The events can be either .Va EV_READ , .Va EV_WRITE , -or both. -Indicating that an application can read or write from the file descriptor +or both, +indicating that an application can read or write from the file descriptor respectively without blocking. .Pp The function @@ -278,18 +298,18 @@ .Fn event_del and does not need to be reinitialized unless the function called and/or the argument to it are to be changed. -However, when an +However, when an .Fa ev -structure has been added to libevent using +structure has been added to libevent using .Fn event_add -the structure must persist until the event occurs (assuming -.Fa EV_PERSIST -is not set) or is removed -using -.Fn event_del . +the structure must persist until the event occurs (assuming +.Fa EV_PERSIST +is not set) or is removed +using +.Fn event_del . You may not reuse the same -.Fa ev -structure for multiple monitored descriptors; each descriptor +.Fa ev +structure for multiple monitored descriptors; each descriptor needs its own .Fa ev . .Pp @@ -297,13 +317,15 @@ .Fn event_add schedules the execution of the .Fa ev -event when the event specified in +event when the event specified in .Fn event_set occurs or in at least the time specified in the .Fa tv . If .Fa tv -is NULL, no timeout occurs and the function will only be called +is +.Dv NULL , +no timeout occurs and the function will only be called if a matching event occurs on the file descriptor. The event in the .Fa ev @@ -335,7 +357,7 @@ structure. This function supports .Fa EV_TIMEOUT , -.Fa EV_READ +.Fa EV_READ , and .Fa EV_WRITE . .Pp @@ -346,10 +368,10 @@ is pending to run. If .Va EV_TIMEOUT -was specified and +was specified and .Fa tv is not -.Va NULL , +.Dv NULL , the expiration time of the event will be returned in .Fa tv . .Pp @@ -365,10 +387,9 @@ and .Fn evtimer_pending are abbreviations for common situations where only a timeout is required. -The file descriptor passed will be -1, and the event type will be +The file descriptor passed will be \-1, and the event type will be .Va EV_TIMEOUT . .Pp -.Pp The functions .Fn signal_set , .Fn signal_add , @@ -385,23 +406,23 @@ .Va EV_PERSIST . .Pp It is possible to disable support for -.Va epoll , kqueue , devpoll, poll +.Va epoll , kqueue , devpoll , poll or .Va select by setting the environment variable -.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL, EVENT_NOPOLL +.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL or -.Va EVENT_NOSELECT . +.Va EVENT_NOSELECT , +respectively. By setting the environment variable .Va EVENT_SHOW_METHOD , .Nm libevent displays the kernel notification method that it uses. -.Pp .Sh EVENT PRIORITIES By default .Nm libevent schedules all active events with the same priority. -However, sometime it is desirable to process some events with a higher +However, sometimes it is desirable to process some events with a higher priority than others. For that reason, .Nm libevent @@ -421,7 +442,6 @@ .Nm libevent assigns the middle priority to all events unless their priority is explicitly set. -.Pp .Sh THREAD SAFE EVENTS .Nm Libevent has experimental support for thread-safe events. @@ -429,24 +449,27 @@ .Fn event_init , an event base is returned. This event base can be used in conjunction with calls to -.Fn event_base_set +.Fn event_base_set , .Fn event_base_dispatch , .Fn event_base_loop , +.Fn event_base_loopexit , and -.Fn event_base_loopexit . -.Fn event_base_set +.Fn bufferevent_base_set . +.Fn event_base_set should be called after preparing an event with -.Fn event_set , +.Fn event_set , as -.Fn event_set +.Fn event_set assigns the provided event to the most recently created event base. -.Pp +.Fn bufferevent_base_set +should be called after preparing a bufferevent with +.Fn bufferevent_new . .Sh BUFFERED EVENTS .Nm libevent provides an abstraction on top of the regular event callbacks. This abstraction is called a .Va "buffered event" . -A buffered event provides input and output buffer that get filled +A buffered event provides input and output buffers that get filled and drained automatically. The user of a buffered event no longer deals directly with the IO, but instead is reading from input and writing to output buffers. @@ -454,21 +477,33 @@ A new bufferevent is created by .Fn bufferevent_new . The parameter -.Fa "fd" +.Fa fd specifies the file descriptor from which data is read and written to. -This file descriptor is not allowed to be a +This file descriptor is not allowed to be a .Xr pipe 2 . The next three parameters are callbacks. -The read and write callback have the following form +The read and write callback have the following form: .Ft void -.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" +.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" . +The error callback has the following form: +.Ft void +.Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" . The argument is specified by the fourth parameter .Fa "cbarg" . +A +.Fa bufferevent struct +pointer is returned on success, NULL on error. .Pp -By default the buffered event is read enabled and will try to read -from the file descriptor. -The write callback is executed whenever the output buffer is drained -below the write low watermark which is +Once initialized, the bufferevent structure can be used repeatedly with +bufferevent_enable() and bufferevent_disable(). The flags parameter can +be a combination of +.Va EV_READ +and +.Va EV_WRITE . +When read enabled the bufferevent will try to read from the file +descriptor and call the read callback. The write callback is executed +whenever the output buffer is drained below the write low watermark, +which is .Va 0 by default. .Pp @@ -482,18 +517,43 @@ function is used to read data from the input buffer. Both functions return the amount of data written or read. .Pp +If multiple bases are in use, bufferevent_base_set() must be called before +enabling the bufferevent for the first time. +.Sh NON-BLOCKING HTTP SUPPORT +.Nm libevent +provides a very thin HTTP layer that can be used both to host an HTTP +server and also to make HTTP requests. +An HTTP server can be created by calling +.Fn evhttp_start . +When the HTTP server is no longer used, it can be freed via +.Fn evhttp_free . +.Pp +To be notified of HTTP requests, a user needs to register callbacks with the +HTTP server. +This can be done by calling +.Fn evhttp_set_cb . +The second argument is the URI for which a callback is being registered. +The corresponding callback will receive an +.Va struct evhttp_request +object that contains all information about the request. +.Pp +This section does not document all the possible function calls, please +check +.Va event.h +for the public interfaces. .Sh RETURN VALUES Upon successful completion .Fn event_add and .Fn event_del return 0. -Otherwise, -1 is returned and the global variable errno is +Otherwise, \-1 is returned and the global variable errno is set to indicate the error. .Sh SEE ALSO -.Xr timeout 9 , +.Xr kqueue 2 , +.Xr poll 2 , .Xr select 2 , -.Xr kqueue 2 +.Xr timeout 9 .Sh HISTORY The .Nm event @@ -508,7 +568,6 @@ The .Nm event library was written by Niels Provos. -.Pp .Sh BUGS This documentation is neither complete nor authoritative. If you are in doubt about the usage of this API then Modified: trunk/varnish-cache/contrib/libevent/event.c =================================================================== --- trunk/varnish-cache/contrib/libevent/event.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/event.c 2006-04-03 11:59:08 UTC (rev 98) @@ -24,7 +24,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #ifdef WIN32 #define WIN32_LEAN_AND_MEAN @@ -46,6 +48,7 @@ #include #endif #include +#include #include #include @@ -107,8 +110,8 @@ struct event_base *current_base = NULL; /* Handle signals - This is a deprecated interface */ -int (*event_sigcb)(void); /* Signal callback when gotsig is set */ -volatile int event_gotsig; /* Set in signal handler */ +int (*event_sigcb)(void); /* Signal callback when gotsig is set */ +volatile sig_atomic_t event_gotsig; /* Set in signal handler */ /* Prototypes */ static void event_queue_insert(struct event_base *, struct event *, int); @@ -135,6 +138,23 @@ return (0); } +static int +gettime(struct timeval *tp) +{ +#ifdef HAVE_CLOCK_GETTIME + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + return (-1); + tp->tv_sec = ts.tv_sec; + tp->tv_usec = ts.tv_nsec / 1000; +#else + gettimeofday(tp, NULL); +#endif + + return (0); +} + RB_PROTOTYPE(event_tree, event, ev_timeout_node, compare); RB_GENERATE(event_tree, event, ev_timeout_node, compare); @@ -150,7 +170,7 @@ event_sigcb = NULL; event_gotsig = 0; - gettimeofday(¤t_base->event_tv, NULL); + gettime(¤t_base->event_tv); RB_INIT(¤t_base->timetree); TAILQ_INIT(¤t_base->eventqueue); @@ -176,6 +196,33 @@ return (current_base); } +void +event_base_free(struct event_base *base) +{ + int i; + + if (base == NULL && current_base) + base = current_base; + if (base == current_base) + current_base = NULL; + + assert(base); + assert(TAILQ_EMPTY(&base->eventqueue)); + for (i=0; i < base->nactivequeues; ++i) + assert(TAILQ_EMPTY(base->activequeues[i])); + + assert(RB_EMPTY(&base->timetree)); + + for (i = 0; i < base->nactivequeues; ++i) + free(base->activequeues[i]); + free(base->activequeues); + + if (base->evsel->dealloc != NULL) + base->evsel->dealloc(base->evbase); + + free(base); +} + int event_priority_init(int npriorities) { @@ -313,12 +360,12 @@ struct timeval tv; int res, done; - /* Calculate the initial events that we are waiting for */ - if (evsel->recalc(base, evbase, 0) == -1) - return (-1); - done = 0; while (!done) { + /* Calculate the initial events that we are waiting for */ + if (evsel->recalc(base, evbase, 0) == -1) + return (-1); + /* Terminate the loop if we have been asked to */ if (base->event_gotterm) { base->event_gotterm = 0; @@ -338,7 +385,7 @@ } /* Check if time is running backwards */ - gettimeofday(&tv, NULL); + gettime(&tv); if (timercmp(&tv, &base->event_tv, <)) { struct timeval off; event_debug(("%s: time is running backwards, corrected", @@ -372,9 +419,6 @@ done = 1; } else if (flags & EVLOOP_NONBLOCK) done = 1; - - if (evsel->recalc(base, evbase, 0) == -1) - return (-1); } event_debug(("%s: asked to terminate loop.", __func__)); @@ -499,6 +543,7 @@ int event_pending(struct event *ev, short event, struct timeval *tv) { + struct timeval now, res; int flags = 0; if (ev->ev_flags & EVLIST_INSERTED) @@ -513,8 +558,13 @@ event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL); /* See if there is a timeout that we should report */ - if (tv != NULL && (flags & event & EV_TIMEOUT)) - *tv = ev->ev_timeout; + if (tv != NULL && (flags & event & EV_TIMEOUT)) { + gettime(&now); + timersub(&ev->ev_timeout, &now, &res); + /* correctly remap to real time */ + gettimeofday(&now, NULL); + timeradd(&now, &res, tv); + } return (flags & event); } @@ -558,7 +608,7 @@ event_queue_remove(base, ev, EVLIST_ACTIVE); } - gettimeofday(&now, NULL); + gettime(&now); timeradd(&now, tv, &ev->ev_timeout); event_debug(( @@ -654,7 +704,7 @@ return (0); } - if (gettimeofday(&now, NULL) == -1) + if (gettime(&now) == -1) return (-1); if (timercmp(&ev->ev_timeout, &now, <=)) { @@ -690,7 +740,7 @@ struct timeval now; struct event *ev, *next; - gettimeofday(&now, NULL); + gettime(&now); for (ev = RB_MIN(event_tree, &base->timetree); ev; ev = next) { if (timercmp(&ev->ev_timeout, &now, >)) Modified: trunk/varnish-cache/contrib/libevent/event.h =================================================================== --- trunk/varnish-cache/contrib/libevent/event.h 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/event.h 2006-04-03 11:59:08 UTC (rev 98) @@ -31,6 +31,8 @@ extern "C" { #endif +#include + #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include @@ -101,11 +103,25 @@ #define EVENT_SIGNAL(ev) (int)ev->ev_fd #define EVENT_FD(ev) (int)ev->ev_fd +/* + * Key-Value pairs. Can be used for HTTP headers but also for + * query argument parsing. + */ +struct evkeyval { + TAILQ_ENTRY(evkeyval) next; + + char *key; + char *value; +}; + #ifdef _EVENT_DEFINED_TQENTRY #undef TAILQ_ENTRY +struct event_list; +struct evkeyvalq; #undef _EVENT_DEFINED_TQENTRY #else TAILQ_HEAD (event_list, event); +TAILQ_HEAD (evkeyvalq, evkeyval); #endif /* _EVENT_DEFINED_TQENTRY */ #ifdef _EVENT_DEFINED_RBENTRY #undef RB_ENTRY @@ -119,6 +135,7 @@ int (*del)(void *, struct event *); int (*recalc)(struct event_base *, void *, int); int (*dispatch)(struct event_base *, void *, struct timeval *); + void (*dealloc)(void *); }; #define TIMEOUT_DEFAULT {5, 0} @@ -126,6 +143,7 @@ void *event_init(void); int event_dispatch(void); int event_base_dispatch(struct event_base *); +void event_base_free(struct event_base *); #define _EVENT_LOG_DEBUG 0 #define _EVENT_LOG_MSG 1 @@ -263,13 +281,115 @@ int evbuffer_remove(struct evbuffer *, void *, size_t); char *evbuffer_readline(struct evbuffer *); int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *); -int evbuffer_add_printf(struct evbuffer *, char *fmt, ...); +int evbuffer_add_printf(struct evbuffer *, const char *fmt, ...); +int evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap); void evbuffer_drain(struct evbuffer *, size_t); int evbuffer_write(struct evbuffer *, int); int evbuffer_read(struct evbuffer *, int, int); -u_char *evbuffer_find(struct evbuffer *, u_char *, size_t); +u_char *evbuffer_find(struct evbuffer *, const u_char *, size_t); void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *); +/* + * Marshaling tagged data - We assume that all tags are inserted in their + * numeric order - so that unknown tags will always be higher than the + * known ones - and we can just ignore the end of an event buffer. + */ + +void evtag_init(void); + +void evtag_marshal(struct evbuffer *evbuf, u_int8_t tag, const void *data, + u_int16_t len); + +void encode_int(struct evbuffer *evbuf, u_int32_t number); + +void evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag, + u_int32_t integer); + +void evtag_marshal_string(struct evbuffer *buf, u_int8_t tag, + const char *string); + +void evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag, + struct timeval *tv); + +void evtag_test(void); + +int evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag, + struct evbuffer *dst); +int evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag); +int evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength); +int evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength); +int evtag_consume(struct evbuffer *evbuf); + +int evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag, + u_int32_t *pinteger); + +int evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data, + size_t len); + +int evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag, + char **pstring); + +int evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag, + struct timeval *ptv); + +/* + * Basic support for HTTP serving. + * + * As libevent is a library for dealing with event notification and most + * interesting applications are networked today, I have often found the + * need to write HTTP code. The following prototypes and definitions provide + * an application with a minimal interface for making HTTP requests and for + * creating a very simple HTTP server. + */ + +/* Response codes */ +#define HTTP_OK 200 +#define HTTP_MOVEPERM 301 +#define HTTP_MOVETEMP 302 +#define HTTP_NOTFOUND 404 + +struct evhttp; +struct evhttp_request; + +/* Start an HTTP server on the specified address and port */ +struct evhttp *evhttp_start(const char *address, u_short port); + +/* + * Free the previously create HTTP server. Works only if no requests are + * currently being served. + */ +void evhttp_free(struct evhttp* http); + +/* Set a callback for a specified URI */ +void evhttp_set_cb(struct evhttp *, const char *, + void (*)(struct evhttp_request *, void *), void *); + +/* Set a callback for all requests that are not caught by specific callbacks */ +void evhttp_set_gencb(struct evhttp *, + void (*)(struct evhttp_request *, void *), void *); + +void evhttp_send_error(struct evhttp_request *, int, const char *); +void evhttp_send_reply(struct evhttp_request *, int, const char *, + struct evbuffer *); + +/* Interfaces for making requests */ +enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD }; + +struct evhttp_request *evhttp_request_new( + void (*cb)(struct evhttp_request *, void *), void *arg); +void evhttp_request_free(struct evhttp_request *req); +const char *evhttp_request_uri(struct evhttp_request *req); + +/* Interfaces for dealing with HTTP headers */ + +const char *evhttp_find_header(struct evkeyvalq *, const char *); +int evhttp_remove_header(struct evkeyvalq *, const char *); +int evhttp_add_header(struct evkeyvalq *, const char *, const char *); +void evhttp_clear_headers(struct evkeyvalq *); + +/* Miscellaneous utility functions */ +void evhttp_parse_query(const char *uri, struct evkeyvalq *); +char *evhttp_htmlescape(const char *html); #ifdef __cplusplus } #endif Added: trunk/varnish-cache/contrib/libevent/event_rpcgen.py =================================================================== --- trunk/varnish-cache/contrib/libevent/event_rpcgen.py 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/event_rpcgen.py 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,1378 @@ +#!/usr/bin/env python +# +# Copyright (c) 2005 Niels Provos +# All rights reserved. +# +# Generates marshalling code based on libevent. + +import sys +import re + +# +_NAME = "event_rpcgen.py" +_VERSION = "0.1" +_STRUCT_RE = '[a-z][a-z_0-9]*' + +# Globals +line_count = 0 + +leading = re.compile(r'^\s+') +trailing = re.compile(r'\s+$') +white = re.compile(r'^\s+') +cppcomment = re.compile(r'\/\/.*$') +cppdirect = [] + +# Holds everything that makes a struct +class Struct: + def __init__(self, name): + self._name = name + self._entries = [] + self._tags = {} + print >>sys.stderr, ' Created struct: %s' % name + + def AddEntry(self, entry): + if self._tags.has_key(entry.Tag()): + print >>sys.stderr, ( 'Entry "%s" duplicates tag number ' + '%d from "%s" around line %d' ) % ( + entry.Name(), entry.Tag(), + self._tags[entry.Tag()], line_count) + sys.exit(1) + self._entries.append(entry) + self._tags[entry.Tag()] = entry.Name() + print >>sys.stderr, ' Added entry: %s' % entry.Name() + + def Name(self): + return self._name + + def EntryTagName(self, entry): + """Creates the name inside an enumeration for distinguishing data + types.""" + name = "%s_%s" % (self._name, entry.Name()) + return name.upper() + + def PrintIdented(self, file, ident, code): + """Takes an array, add indentation to each entry and prints it.""" + for entry in code: + print >>file, '%s%s' % (ident, entry) + + def PrintTags(self, file): + """Prints the tag definitions for a structure.""" + print >>file, '/* Tag definition for %s */' % self._name + print >>file, 'enum %s_ {' % self._name.lower() + for entry in self._entries: + print >>file, ' %s=%d,' % (self.EntryTagName(entry), + entry.Tag()) + print >>file, ' %s_MAX_TAGS' % (self._name.upper()) + print >>file, '} %s_tags;\n' % (self._name.lower()) + + def PrintForwardDeclaration(self, file): + print >>file, 'struct %s;' % self._name + + def PrintDeclaration(self, file): + print >>file, '/* Structure declaration for %s */' % self._name + print >>file, 'struct %s {' % self._name + for entry in self._entries: + dcl = entry.Declaration() + dcl.extend( + entry.AssignDeclaration('(*%s_assign)' % entry.Name())) + dcl.extend( + entry.GetDeclaration('(*%s_get)' % entry.Name())) + if entry.Array(): + dcl.extend( + entry.AddDeclaration('(*%s_add)' % entry.Name())) + self.PrintIdented(file, ' ', dcl) + print >>file, '' + for entry in self._entries: + print >>file, ' u_int8_t %s_set;' % entry.Name() + print >>file, '};\n' + + print >>file, ( + 'struct %s *%s_new();\n' % (self._name, self._name) + + 'void %s_free(struct %s *);\n' % (self._name, self._name) + + 'void %s_clear(struct %s *);\n' % (self._name, self._name) + + 'void %s_marshal(struct evbuffer *, const struct %s *);\n' % ( + self._name, self._name) + + 'int %s_unmarshal(struct %s *, struct evbuffer *);\n' % ( + self._name, self._name) + + 'int %s_complete(struct %s *);' % (self._name, self._name) + ) + print >>file, ('void evtag_marshal_%s(struct evbuffer *, u_int8_t, ' + 'const struct %s *);') % ( self._name, self._name) + print >>file, ('int evtag_unmarshal_%s(struct evbuffer *, u_int8_t, ' + 'struct %s *);') % ( self._name, self._name) + + # Write a setting function of every variable + for entry in self._entries: + self.PrintIdented(file, '', entry.AssignDeclaration( + entry.AssignFuncName())) + self.PrintIdented(file, '', entry.GetDeclaration( + entry.GetFuncName())) + if entry.Array(): + self.PrintIdented(file, '', entry.AddDeclaration( + entry.AddFuncName())) + + print >>file, '/* --- %s done --- */\n' % self._name + + def PrintCode(self, file): + print >>file, ('/*\n' + ' * Implementation of %s\n' + ' */\n') % self._name + + # Creation + print >>file, ( 'struct %s *\n' % self._name + + '%s_new()\n' % self._name + + '{\n' + ' struct %s *tmp;\n' % self._name + + ' if ((tmp = malloc(sizeof(struct %s))) == NULL) {\n' + ' event_warn("%%s: malloc", __func__);\n' + ' return (NULL);\n' % self._name + + ' }' + ) + for entry in self._entries: + self.PrintIdented(file, ' ', entry.CodeNew('tmp')) + print >>file, ' tmp->%s_set = 0;\n' % entry.Name() + + print >>file, (' return (tmp);\n' + '}\n') + + # Adding + for entry in self._entries: + if entry.Array(): + self.PrintIdented(file, '', entry.CodeAdd()) + print >>file, '' + + # Assigning + for entry in self._entries: + self.PrintIdented(file, '', entry.CodeAssign()) + print >>file, '' + + # Getting + for entry in self._entries: + self.PrintIdented(file, '', entry.CodeGet()) + print >>file, '' + + # Clearing + print >>file, ( 'void\n' + '%s_clear(struct %s *tmp)\n' % ( + self._name, self._name)+ + '{' + ) + for entry in self._entries: + self.PrintIdented(file, ' ', entry.CodeClear('tmp')) + + print >>file, '}\n' + + # Freeing + print >>file, ( 'void\n' + '%s_free(struct %s *tmp)\n' % ( + self._name, self._name)+ + '{' + ) + for entry in self._entries: + self.PrintIdented(file, ' ', entry.CodeFree('tmp')) + + print >>file, (' free(tmp);\n' + '}\n') + + # Marshaling + print >>file, ('void\n' + '%s_marshal(struct evbuffer *evbuf, ' + 'const struct %s *tmp)' % (self._name, self._name) + + '{') + for entry in self._entries: + indent = ' ' + # Optional entries do not have to be set + if entry.Optional(): + indent += ' ' + print >>file, ' if (tmp->%s_set) {' % entry.Name() + self.PrintIdented( + file, indent, + entry.CodeMarshal('evbuf', self.EntryTagName(entry), 'tmp')) + if entry.Optional(): + print >>file, ' }' + + print >>file, '}\n' + + # Unmarshaling + print >>file, ('int\n' + '%s_unmarshal(struct %s *tmp, ' + ' struct evbuffer *evbuf)\n' % ( + self._name, self._name) + + '{\n' + ' u_int8_t tag;\n' + ' while (EVBUFFER_LENGTH(evbuf) > 0) {\n' + ' if (evtag_peek(evbuf, &tag) == -1)\n' + ' return (-1);\n' + ' switch (tag) {\n' + ) + for entry in self._entries: + print >>file, ' case %s:\n' % self.EntryTagName(entry) + if not entry.Array(): + print >>file, ( + ' if (tmp->%s_set)\n' + ' return (-1);' + ) % (entry.Name()) + + self.PrintIdented( + file, ' ', + entry.CodeUnmarshal('evbuf', + self.EntryTagName(entry), 'tmp')) + + print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() + + ' break;\n' ) + print >>file, ( ' default:\n' + ' return -1;\n' + ' }\n' + ' }\n' ) + # Check if it was decoded completely + print >>file, ( ' if (%s_complete(tmp) == -1)\n' % self._name + + ' return (-1);') + + # Successfully decoded + print >>file, ( ' return (0);\n' + '}\n') + + # Checking if a structure has all the required data + print >>file, ( + 'int\n' + '%s_complete(struct %s *msg)\n' % (self._name, self._name) + + '{' ) + for entry in self._entries: + self.PrintIdented( + file, ' ', + entry.CodeComplete('msg')) + print >>file, ( + ' return (0);\n' + '}\n' ) + + # Complete message unmarshaling + print >>file, ( + 'int\n' + 'evtag_unmarshal_%s(struct evbuffer *evbuf, u_int8_t need_tag, ' + ' struct %s *msg)' + ) % (self._name, self._name) + print >>file, ( + '{\n' + ' u_int8_t tag;\n' + ' int res = -1;\n' + '\n' + ' struct evbuffer *tmp = evbuffer_new();\n' + '\n' + ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1' + ' || tag != need_tag)\n' + ' goto error;\n' + '\n' + ' if (%s_unmarshal(msg, tmp) == -1)\n' + ' goto error;\n' + '\n' + ' res = 0;\n' + '\n' + ' error:\n' + ' evbuffer_free(tmp);\n' + ' return (res);\n' + '}\n' ) % self._name + + # Complete message marshaling + print >>file, ( + 'void\n' + 'evtag_marshal_%s(struct evbuffer *evbuf, u_int8_t tag, ' + 'const struct %s *msg)\n' % (self._name, self._name) + + '{\n' + ' struct evbuffer *_buf = evbuffer_new();\n' + ' assert(_buf != NULL);\n' + ' evbuffer_drain(_buf, -1);\n' + ' %s_marshal(_buf, msg);\n' % self._name + + ' evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), ' + 'EVBUFFER_LENGTH(_buf));\n' + ' evbuffer_free(_buf);\n' + '}\n' ) + +class Entry: + def __init__(self, type, name, tag): + self._type = type + self._name = name + self._tag = int(tag) + self._ctype = type + self._optional = 0 + self._can_be_array = 0 + self._array = 0 + self._line_count = -1 + self._struct = None + + def SetStruct(self, struct): + self._struct = struct + + def LineCount(self): + assert self._line_count != -1 + return self._line_count + + def SetLineCount(self, number): + self._line_count = number + + def Array(self): + return self._array + + def Optional(self): + return self._optional + + def Tag(self): + return self._tag + + def Name(self): + return self._name + + def Type(self): + return self._type + + def MakeArray(self, yes=1): + self._array = yes + + def MakeOptional(self): + self._optional = 1 + + def GetFuncName(self): + return '%s_%s_get' % (self._struct.Name(), self._name) + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeGet(self): + code = [ 'int', + '%s_%s_get(struct %s *msg, %s *value)' % ( + self._struct.Name(), self._name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1)' % self._name, + ' return (-1);', + ' *value = msg->%s_data;' % self._name, + ' return (0);', + '}' ] + return code + + def AssignFuncName(self): + return '%s_%s_assign' % (self._struct.Name(), self._name) + + def AddFuncName(self): + return '%s_%s_add' % (self._struct.Name(), self._name) + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeAssign(self): + code = [ 'int', + '%s_%s_assign(struct %s *msg, const %s value)' % ( + self._struct.Name(), self._name, + self._struct.Name(), self._ctype), + '{', + ' msg->%s_set = 1;' % self._name, + ' msg->%s_data = value;' % self._name, + ' return (0);', + '}' ] + return code + + def CodeClear(self, structname): + code = [ '%s->%s_set = 0;' % (structname, self.Name()) ] + + return code + + def CodeComplete(self, structname): + if self.Optional(): + return [] + + code = [ 'if (!%s->%s_set)' % (structname, self.Name()), + ' return (-1);' ] + + return code + + def CodeFree(self, name): + return [] + + def CodeNew(self, name): + code = [ '%s->%s_assign = %s_%s_assign;' % ( + name, self._name, self._struct.Name(), self._name ), + '%s->%s_get = %s_%s_get;' % ( + name, self._name, self._struct.Name(), self._name ), + ] + if self.Array(): + code.append( + '%s->%s_add = %s_%s_add;' % ( + name, self._name, self._struct.Name(), self._name ) ) + return code + + def Verify(self): + if self.Array() and not self._can_be_array: + print >>sys.stderr, ( + 'Entry "%s" cannot be created as an array ' + 'around line %d' ) % (self._name, self.LineCount()) + sys.exit(1) + if not self._struct: + print >>sys.stderr, ( + 'Entry "%s" does not know which struct it belongs to ' + 'around line %d' ) % (self._name, self.LineCount()) + sys.exit(1) + if self._optional and self._array: + print >>sys.stderr, ( 'Entry "%s" has illegal combination of ' + 'optional and array around line %d' ) % ( + self._name, self.LineCount() ) + sys.exit(1) + +class EntryBytes(Entry): + def __init__(self, type, name, tag, length): + # Init base class + Entry.__init__(self, type, name, tag) + + self._length = length + self._ctype = 'u_int8_t' + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s **);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def Declaration(self): + dcl = ['u_int8_t %s_data[%s];' % (self._name, self._length)] + + return dcl + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, %s **value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1)' % name, + ' return (-1);', + ' *value = msg->%s_data;' % name, + ' return (0);', + '}' ] + return code + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, const %s *value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' msg->%s_set = 1;' % name, + ' memcpy(msg->%s_data, value, %s);' % ( + name, self._length), + ' return (0);', + '}' ] + return code + + def CodeUnmarshal(self, buf, tag_name, var_name): + code = [ 'if (evtag_unmarshal_fixed(%s, %s, ' % (buf, tag_name) + + '%s->%s_data, ' % (var_name, self._name) + + 'sizeof(%s->%s_data)) == -1) {' % ( + var_name, self._name), + ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( + self._name ), + ' return (-1);', + '}' + ] + return code + + def CodeMarshal(self, buf, tag_name, var_name): + code = ['evtag_marshal(%s, %s, %s->%s_data, sizeof(%s->%s_data));' % ( + buf, tag_name, var_name, self._name, var_name, self._name )] + return code + + def CodeClear(self, structname): + code = [ '%s->%s_set = 0;' % (structname, self.Name()), + 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( + structname, self._name, structname, self._name)] + + return code + + def CodeNew(self, name): + code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( + name, self._name, name, self._name)] + code.extend(Entry.CodeNew(self, name)) + return code + + def Verify(self): + if not self._length: + print >>sys.stderr, 'Entry "%s" needs a length around line %d' % ( + self._name, self.LineCount() ) + sys.exit(1) + + Entry.Verify(self) + +class EntryInt(Entry): + def __init__(self, type, name, tag): + # Init base class + Entry.__init__(self, type, name, tag) + + self._ctype = 'u_int32_t' + + def CodeUnmarshal(self, buf, tag_name, var_name): + code = ['if (evtag_unmarshal_int(%s, %s, &%s->%s_data) == -1) {' % ( + buf, tag_name, var_name, self._name), + ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( + self._name ), + ' return (-1);', + '}' ] + return code + + def CodeMarshal(self, buf, tag_name, var_name): + code = ['evtag_marshal_int(%s, %s, %s->%s_data);' % ( + buf, tag_name, var_name, self._name)] + return code + + def Declaration(self): + dcl = ['u_int32_t %s_data;' % self._name] + + return dcl + +class EntryString(Entry): + def __init__(self, type, name, tag): + # Init base class + Entry.__init__(self, type, name, tag) + + self._ctype = 'char *' + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, const %s value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_data != NULL)' % name, + ' free(msg->%s_data);' % name, + ' if ((msg->%s_data = strdup(value)) == NULL)' % name, + ' return (-1);', + ' msg->%s_set = 1;' % name, + ' return (0);', + '}' ] + return code + + def CodeUnmarshal(self, buf, tag_name, var_name): + code = ['if (evtag_unmarshal_string(%s, %s, &%s->%s_data) == -1) {' % ( + buf, tag_name, var_name, self._name), + ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( + self._name ), + ' return (-1);', + '}' + ] + return code + + def CodeMarshal(self, buf, tag_name, var_name): + code = ['evtag_marshal_string(%s, %s, %s->%s_data);' % ( + buf, tag_name, var_name, self._name)] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' free (%s->%s_data);' % (structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeNew(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name)] + code.extend(Entry.CodeNew(self, name)) + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL)' % (name, self._name), + ' free (%s->%s_data); ' % (name, self._name)] + + return code + + def Declaration(self): + dcl = ['char *%s_data;' % self._name] + + return dcl + +class EntryStruct(Entry): + def __init__(self, type, name, tag, refname): + # Init base class + Entry.__init__(self, type, name, tag) + + self._can_be_array = 1 + self._refname = refname + self._ctype = 'struct %s' % refname + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s **);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, %s **value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1) {' % name, + ' msg->%s_data = %s_new();' % (name, self._refname), + ' if (msg->%s_data == NULL)' % name, + ' return (-1);', + ' msg->%s_set = 1;' % name, + ' }', + ' *value = msg->%s_data;' % name, + ' return (0);', + '}' ] + return code + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, const %s *value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' struct evbuffer *tmp = NULL;', + ' if (msg->%s_set) {' % name, + ' %s_clear(msg->%s_data);' % (self._refname, name), + ' msg->%s_set = 0;' % name, + ' } else {', + ' msg->%s_data = %s_new();' % (name, self._refname), + ' if (msg->%s_data == NULL) {' % name, + ' event_warn("%%s: %s_new()", __func__);' % ( + self._refname), + ' goto error;', + ' }', + ' }', + ' if ((tmp = evbuffer_new()) == NULL) {', + ' event_warn("%s: evbuffer_new()", __func__);', + ' goto error;', + ' }', + ' %s_marshal(tmp, value); ' % self._refname, + ' if (%s_unmarshal(msg->%s_data, tmp) == -1) {' % ( + self._refname, name ), + ' event_warnx("%%s: %s_unmarshal", __func__);' % ( + self._refname), + ' goto error;', + ' }', + ' msg->%s_set = 1;' % name, + ' evbuffer_free(tmp);', + ' return (0);', + ' error:', + ' if (tmp != NULL)', + ' evbuffer_free(tmp);', + ' if (msg->%s_data != NULL) {' % name, + ' %s_free(msg->%s_data);' % (self._refname, name), + ' msg->%s_data = NULL;' % name, + ' }', + ' return (-1);', + '}' ] + return code + + def CodeComplete(self, structname): + if self.Optional(): + code = [ 'if (%s->%s_set && %s_complete(%s->%s_data) == -1)' % ( + structname, self.Name(), + self._refname, structname, self.Name()), + ' return (-1);' ] + else: + code = [ 'if (%s_complete(%s->%s_data) == -1)' % ( + self._refname, structname, self.Name()), + ' return (-1);' ] + + return code + + def CodeUnmarshal(self, buf, tag_name, var_name): + code = ['%s->%s_data = %s_new();' % ( + var_name, self._name, self._refname), + 'if (%s->%s_data == NULL)' % (var_name, self._name), + ' return (-1);', + 'if (evtag_unmarshal_%s(%s, %s, %s->%s_data) == -1) {' % ( + self._refname, buf, tag_name, var_name, self._name), + ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( + self._name ), + ' return (-1);', + '}' + ] + return code + + def CodeMarshal(self, buf, tag_name, var_name): + code = ['evtag_marshal_%s(%s, %s, %s->%s_data);' % ( + self._refname, buf, tag_name, var_name, self._name)] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' %s_free(%s->%s_data);' % ( + self._refname, structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeNew(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name)] + code.extend(Entry.CodeNew(self, name)) + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL)' % (name, self._name), + ' %s_free(%s->%s_data); ' % ( + self._refname, name, self._name)] + + return code + + def Declaration(self): + dcl = ['struct %s *%s_data;' % (self._refname, self._name)] + + return dcl + +class EntryVarBytes(Entry): + def __init__(self, type, name, tag): + # Init base class + Entry.__init__(self, type, name, tag) + + self._ctype = 'u_int8_t *' + + def GetDeclaration(self, funcname): + code = [ 'int %s(struct %s *, %s *, u_int32_t *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, const %s, u_int32_t);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, ' + 'const %s value, u_int32_t len)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_data != NULL)' % name, + ' free (msg->%s_data);' % name, + ' msg->%s_data = malloc(len);' % name, + ' if (msg->%s_data == NULL)' % name, + ' return (-1);', + ' msg->%s_set = 1;' % name, + ' msg->%s_length = len;' % name, + ' memcpy(msg->%s_data, value, len);' % name, + ' return (0);', + '}' ] + return code + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, %s *value, u_int32_t *plen)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1)' % name, + ' return (-1);', + ' *value = msg->%s_data;' % name, + ' *plen = msg->%s_length;' % name, + ' return (0);', + '}' ] + return code + + def CodeUnmarshal(self, buf, tag_name, var_name): + code = ['if (evtag_payload_length(%s, &%s->%s_length) == -1)' % ( + buf, var_name, self._name), + ' return (-1);', + # We do not want DoS opportunities + 'if (%s->%s_length > EVBUFFER_LENGTH(%s))' % ( + var_name, self._name, buf), + ' return (-1);', + 'if ((%s->%s_data = malloc(%s->%s_length)) == NULL)' % ( + var_name, self._name, var_name, self._name), + ' return (-1);', + 'if (evtag_unmarshal_fixed(%s, %s, %s->%s_data, ' + '%s->%s_length) == -1) {' % ( + buf, tag_name, var_name, self._name, var_name, self._name), + ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( + self._name ), + ' return (-1);', + '}' + ] + return code + + def CodeMarshal(self, buf, tag_name, var_name): + code = ['evtag_marshal(%s, %s, %s->%s_data, %s->%s_length);' % ( + buf, tag_name, var_name, self._name, var_name, self._name)] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' free (%s->%s_data);' % (structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_length = 0;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeNew(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name), + '%s->%s_length = 0;' % (name, self._name) ] + code.extend(Entry.CodeNew(self, name)) + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL)' % (name, self._name), + ' free (%s->%s_data); ' % (name, self._name)] + + return code + + def Declaration(self): + dcl = ['u_int8_t *%s_data;' % self._name, + 'u_int32_t %s_length;' % self._name] + + return dcl + +class EntryArray(Entry): + def __init__(self, entry): + # Init base class + Entry.__init__(self, entry._type, entry._name, entry._tag) + + self._entry = entry + self._refname = entry._refname + self._ctype = 'struct %s' % self._refname + + def GetDeclaration(self, funcname): + """Allows direct access to elements of the array.""" + code = [ 'int %s(struct %s *, int, %s **);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AssignDeclaration(self, funcname): + code = [ 'int %s(struct %s *, int, const %s *);' % ( + funcname, self._struct.Name(), self._ctype ) ] + return code + + def AddDeclaration(self, funcname): + code = [ '%s *%s(struct %s *);' % ( + self._ctype, funcname, self._struct.Name() ) ] + return code + + def CodeGet(self): + name = self._name + code = [ 'int', + '%s_%s_get(struct %s *msg, int offset, %s **value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' if (msg->%s_set != 1)' % name, + ' return (-1);', + ' if (offset >= msg->%s_length)' % name, + ' return (-1);', + ' *value = msg->%s_data[offset];' % name, + ' return (0);', + '}' ] + return code + + def CodeAssign(self): + name = self._name + code = [ 'int', + '%s_%s_assign(struct %s *msg, int off, const %s *value)' % ( + self._struct.Name(), name, + self._struct.Name(), self._ctype), + '{', + ' struct evbuffer *tmp = NULL;', + ' if (msg->%s_set != 1)' % name, + ' return (-1);', + ' if (off >= msg->%s_length)' % name, + ' return (-1);', + '', + ' %s_clear(msg->%s_data[off]);' % (self._refname, name), + ' if ((tmp = evbuffer_new()) == NULL) {', + ' event_warn("%s: evbuffer_new()", __func__);', + ' goto error;', + ' }', + ' %s_marshal(tmp, value); ' % self._refname, + ' if (%s_unmarshal(msg->%s_data[off], tmp) == -1) {' % ( + self._refname, name ), + ' event_warnx("%%s: %s_unmarshal", __func__);' % ( + self._refname), + ' goto error;', + ' }', + ' evbuffer_free(tmp);', + ' return (0);', + ' error:', + ' if (tmp != NULL)', + ' evbuffer_free(tmp);', + ' %s_clear(msg->%s_data[off]);' % (self._refname, name), + ' return (-1);', + '}' ] + return code + + def CodeAdd(self): + name = self._name + code = [ + '%s *' % self._ctype, + '%s_%s_add(struct %s *msg)' % ( + self._struct.Name(), name, self._struct.Name()), + '{', + ' msg->%s_length++;' % name, + ' msg->%s_data = (struct %s**)realloc(msg->%s_data, ' + ' msg->%s_length * sizeof(struct %s*));' % ( + name, self._refname, name, name, self._refname ), + ' if (msg->%s_data == NULL)' % name, + ' return (NULL);', + ' msg->%s_data[msg->%s_length - 1] = %s_new();' % ( + name, name, self._refname), + ' if (msg->%s_data[msg->%s_length - 1] == NULL) {' % (name, name), + ' msg->%s_length--; ' % name, + ' return (NULL);', + ' }', + ' msg->%s_set = 1;' % name, + ' return (msg->%s_data[msg->%s_length - 1]);' % (name, name), + '}' + ] + return code + + def CodeComplete(self, structname): + code = [] + if self.Optional(): + code.append( 'if (%s->%s_set)' % (structname, self.Name())) + + code.extend(['{', + ' int i;', + ' for (i = 0; i < %s->%s_length; ++i) {' % ( + structname, self.Name()), + ' if (%s_complete(%s->%s_data[i]) == -1)' % ( + self._refname, structname, self.Name()), + ' return (-1);', + ' }', + '}' + ]) + + return code + + def CodeUnmarshal(self, buf, tag_name, var_name): + code = ['if (%s_%s_add(%s) == NULL)' % ( + self._struct.Name(), self._name, var_name), + ' return (-1);', + 'if (evtag_unmarshal_%s(%s, %s, ' + '%s->%s_data[%s->%s_length - 1]) == -1) {' % ( + self._refname, buf, tag_name, var_name, self._name, + var_name, self._name), + ' %s->%s_length--; ' % (var_name, self._name), + ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( + self._name ), + ' return (-1);', + '}' + ] + return code + + def CodeMarshal(self, buf, tag_name, var_name): + code = ['{', + ' int i;', + ' for (i = 0; i < %s->%s_length; ++i) {' % ( + var_name, self._name), + ' evtag_marshal_%s(%s, %s, %s->%s_data[i]);' % ( + self._refname, buf, tag_name, var_name, self._name), + ' }', + '}' + ] + return code + + def CodeClear(self, structname): + code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), + ' int i;', + ' for (i = 0; i < %s->%s_length; ++i) {' % ( + structname, self.Name()), + ' %s_free(%s->%s_data[i]);' % ( + self._refname, structname, self.Name()), + ' }', + ' free(%s->%s_data);' % (structname, self.Name()), + ' %s->%s_data = NULL;' % (structname, self.Name()), + ' %s->%s_set = 0;' % (structname, self.Name()), + ' %s->%s_length = 0;' % (structname, self.Name()), + '}' + ] + + return code + + def CodeNew(self, name): + code = ['%s->%s_data = NULL;' % (name, self._name), + '%s->%s_length = 0;' % (name, self._name)] + code.extend(Entry.CodeNew(self, name)) + return code + + def CodeFree(self, name): + code = ['if (%s->%s_data != NULL) {' % (name, self._name), + ' int i;', + ' for (i = 0; i < %s->%s_length; ++i) {' % ( + name, self._name), + ' %s_free(%s->%s_data[i]); ' % ( + self._refname, name, self._name), + ' %s->%s_data[i] = NULL;' % (name, self._name), + ' }', + ' free(%s->%s_data);' % (name, self._name), + ' %s->%s_data = NULL;' % (name, self._name), + ' %s->%s_length = 0;' % (name, self._name), + '}' + ] + + return code + + def Declaration(self): + dcl = ['struct %s **%s_data;' % (self._refname, self._name), + 'int %s_length;' % self._name] + + return dcl + +def NormalizeLine(line): + global leading + global trailing + global white + global cppcomment + + line = cppcomment.sub('', line) + line = leading.sub('', line) + line = trailing.sub('', line) + line = white.sub(' ', line) + + return line + +def ProcessOneEntry(newstruct, entry): + optional = 0 + array = 0 + type = '' + name = '' + tag = '' + tag_set = None + separator = '' + fixed_length = '' + + tokens = entry.split(' ') + while tokens: + token = tokens[0] + tokens = tokens[1:] + + if not type: + if not optional and token == 'optional': + optional = 1 + continue + + if not array and token == 'array': + array = 1 + continue + + if not type: + type = token + continue + + if not name: + res = re.match(r'^([^\[\]]+)(\[.*\])?$', token) + if not res: + print >>sys.stderr, 'Cannot parse name: \"%s\" around %d' % ( + entry, line_count) + sys.exit(1) + name = res.group(1) + fixed_length = res.group(2) + if fixed_length: + fixed_length = fixed_length[1:-1] + continue + + if not separator: + separator = token + if separator != '=': + print >>sys.stderr, 'Expected "=" after name \"%s\" got %s' % ( + name, token) + sys.exit(1) + continue + + if not tag_set: + tag_set = 1 + if not re.match(r'^[0-9]+$', token): + print >>sys.stderr, 'Expected tag number: \"%s\"' % entry + sys.exit(1) + tag = int(token) + continue + + print >>sys.stderr, 'Cannot parse \"%s\"' % entry + sys.exit(1) + + if not tag_set: + print >>sys.stderr, 'Need tag number: \"%s\"' % entry + sys.exit(1) + + # Create the right entry + if type == 'bytes': + if fixed_length: + newentry = EntryBytes(type, name, tag, fixed_length) + else: + newentry = EntryVarBytes(type, name, tag) + elif type == 'int' and not fixed_length: + newentry = EntryInt(type, name, tag) + elif type == 'string' and not fixed_length: + newentry = EntryString(type, name, tag) + else: + res = re.match(r'^struct\[(%s)\]$' % _STRUCT_RE, type, re.IGNORECASE) + if res: + # References another struct defined in our file + newentry = EntryStruct(type, name, tag, res.group(1)) + else: + print >>sys.stderr, 'Bad type: "%s" in "%s"' % (type, entry) + sys.exit(1) + + structs = [] + + if optional: + newentry.MakeOptional() + if array: + newentry.MakeArray() + + newentry.SetStruct(newstruct) + newentry.SetLineCount(line_count) + newentry.Verify() + + if array: + # We need to encapsulate this entry into a struct + newname = newentry.Name()+ '_array' + + # Now borgify the new entry. + newentry = EntryArray(newentry) + newentry.SetStruct(newstruct) + newentry.SetLineCount(line_count) + newentry.MakeArray() + + newstruct.AddEntry(newentry) + + return structs + +def ProcessStruct(data): + tokens = data.split(' ') + + # First three tokens are: 'struct' 'name' '{' + newstruct = Struct(tokens[1]) + + inside = ' '.join(tokens[3:-1]) + + tokens = inside.split(';') + + structs = [] + + for entry in tokens: + entry = NormalizeLine(entry) + if not entry: + continue + + # It's possible that new structs get defined in here + structs.extend(ProcessOneEntry(newstruct, entry)) + + structs.append(newstruct) + return structs + +def GetNextStruct(file): + global line_count + global cppdirect + + got_struct = 0 + + processed_lines = [] + + have_c_comment = 0 + data = '' + for line in file: + line_count += 1 + line = line[:-1] + + if not have_c_comment and re.search(r'/\*', line): + if re.search(r'/\*.*\*/', line): + line = re.sub(r'/\*.*\*/', '', line) + else: + line = re.sub(r'/\*.*$', '', line) + have_c_comment = 1 + + if have_c_comment: + if not re.search(r'\*/', line): + continue + have_c_comment = 0 + line = re.sub(r'^.*\*/', '', line) + + line = NormalizeLine(line) + + if not line: + continue + + if not got_struct: + if re.match(r'#include ["<].*[>"]', line): + cppdirect.append(line) + continue + + if re.match(r'^#(if( |def)|endif)', line): + cppdirect.append(line) + continue + + if not re.match(r'^struct %s {$' % _STRUCT_RE, + line, re.IGNORECASE): + print >>sys.stderr, 'Missing struct on line %d: %s' % ( + line_count, line) + sys.exit(1) + else: + got_struct = 1 + data += line + continue + + # We are inside the struct + tokens = line.split('}') + if len(tokens) == 1: + data += ' ' + line + continue + + if len(tokens[1]): + print >>sys.stderr, 'Trailing garbage after struct on line %d' % ( + line_count ) + sys.exit(1) + + # We found the end of the struct + data += ' %s}' % tokens[0] + break + + # Remove any comments, that might be in there + data = re.sub(r'/\*.*\*/', '', data) + + return data + + +def Parse(file): + """Parses the input file and returns C code and corresponding header + file.""" + + entities = [] + + while 1: + # Just gets the whole struct nicely formatted + data = GetNextStruct(file) + + if not data: + break + + entities.extend(ProcessStruct(data)) + + return entities + +def GuardName(name): + name = '_'.join(name.split('.')) + name = '_'.join(name.split('/')) + guard = '_'+name.upper()+'_' + + return guard + +def HeaderPreamble(name): + guard = GuardName(name) + pre = ( + '/*\n' + ' * Automatically generated from %s\n' + ' */\n\n' + '#ifndef %s\n' + '#define %s\n\n' ) % ( + name, guard, guard) + pre += ( + '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n' + '#define EVTAG_ASSIGN(msg, member, args...) ' + '(*(msg)->member##_assign)(msg, ## args)\n' + '#define EVTAG_GET(msg, member, args...) ' + '(*(msg)->member##_get)(msg, ## args)\n' + '#define EVTAG_ADD(msg, member) (*(msg)->member##_add)(msg)\n' + '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n' + ) + + return pre + + +def HeaderPostamble(name): + guard = GuardName(name) + return '#endif /* %s */' % guard + +def BodyPreamble(name): + global _NAME + global _VERSION + + header_file = '.'.join(name.split('.')[:-1]) + '.gen.h' + + pre = ( '/*\n' + ' * Automatically generated from %s\n' + ' * by %s/%s. DO NOT EDIT THIS FILE.\n' + ' */\n\n' ) % (name, _NAME, _VERSION) + pre += ( '#include \n' + '#include \n' + '#include \n' + '#include \n' + '#include \n' + '#include \n\n' ) + + for include in cppdirect: + pre += '%s\n' % include + + pre += '\n#include "%s"\n\n' % header_file + + pre += 'void event_err(int eval, const char *fmt, ...);\n' + pre += 'void event_warn(const char *fmt, ...);\n' + pre += 'void event_errx(int eval, const char *fmt, ...);\n' + pre += 'void event_warnx(const char *fmt, ...);\n\n' + + return pre + +def main(argv): + filename = argv[1] + + if filename.split('.')[-1] != 'rpc': + ext = filename.split('.')[-1] + print >>sys.stderr, 'Unrecognized file extension: %s' % ext + sys.exit(1) + + print >>sys.stderr, 'Reading \"%s\"' % filename + + fp = open(filename, 'r') + entities = Parse(fp) + fp.close() + + header_file = '.'.join(filename.split('.')[:-1]) + '.gen.h' + impl_file = '.'.join(filename.split('.')[:-1]) + '.gen.c' + + print >>sys.stderr, '... creating "%s"' % header_file + header_fp = open(header_file, 'w') + print >>header_fp, HeaderPreamble(filename) + + # Create forward declarations: allows other structs to reference + # each other + for entry in entities: + entry.PrintForwardDeclaration(header_fp) + print >>header_fp, '' + + for entry in entities: + entry.PrintTags(header_fp) + entry.PrintDeclaration(header_fp) + print >>header_fp, HeaderPostamble(filename) + header_fp.close() + + print >>sys.stderr, '... creating "%s"' % impl_file + impl_fp = open(impl_file, 'w') + print >>impl_fp, BodyPreamble(filename) + for entry in entities: + entry.PrintCode(impl_fp) + impl_fp.close() + +if __name__ == '__main__': + main(sys.argv) Property changes on: trunk/varnish-cache/contrib/libevent/event_rpcgen.py ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + text/script Added: trunk/varnish-cache/contrib/libevent/event_tagging.c =================================================================== --- trunk/varnish-cache/contrib/libevent/event_tagging.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/event_tagging.c 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2003, 2004 Niels Provos + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "event.h" + +int decode_int(u_int32_t *pnumber, struct evbuffer *evbuf); + +static struct evbuffer *_buf; + +void +evtag_init() +{ + if ((_buf = evbuffer_new()) == NULL) + err(1, "%s: malloc", __func__); +} + +/* + * We encode integer's by nibbles; the first nibble contains the number + * of significant nibbles - 1; this allows us to encode up to 64-bit + * integers. This function is byte-order independent. + */ + +void +encode_int(struct evbuffer *evbuf, u_int32_t number) +{ + int off = 1, nibbles = 0; + u_int8_t data[5]; + + memset(data, 0, sizeof(data)); + while (number) { + if (off & 0x1) + data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); + else + data[off/2] = (data[off/2] & 0x0f) | + ((number & 0x0f) << 4); + number >>= 4; + off++; + } + + if (off > 2) + nibbles = off - 2; + + /* Off - 1 is the number of encoded nibbles */ + data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4); + + evbuffer_add(evbuf, data, (off + 1) / 2); +} + +/* + * Marshal a data type, the general format is as follows: + * + * tag number: one byte; length: var bytes; payload: var bytes + */ + +void +evtag_marshal(struct evbuffer *evbuf, u_int8_t tag, + const void *data, u_int16_t len) +{ + evbuffer_add(evbuf, &tag, sizeof(tag)); + encode_int(evbuf, len); + evbuffer_add(evbuf, (void *)data, len); +} + +/* Marshaling for integers */ +void +evtag_marshal_int(struct evbuffer *evbuf, u_int8_t tag, u_int32_t integer) +{ + evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + encode_int(_buf, integer); + + evbuffer_add(evbuf, &tag, sizeof(tag)); + encode_int(evbuf, EVBUFFER_LENGTH(_buf)); + evbuffer_add_buffer(evbuf, _buf); +} + +void +evtag_marshal_string(struct evbuffer *buf, u_int8_t tag, const char *string) +{ + evtag_marshal(buf, tag, string, strlen(string)); +} + +void +evtag_marshal_timeval(struct evbuffer *evbuf, u_int8_t tag, struct timeval *tv) +{ + evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + + encode_int(_buf, tv->tv_sec); + encode_int(_buf, tv->tv_usec); + + evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), + EVBUFFER_LENGTH(_buf)); +} + +static int __inline +decode_int_internal(u_int32_t *pnumber, struct evbuffer *evbuf, int dodrain) +{ + u_int32_t number = 0; + u_int8_t *data = EVBUFFER_DATA(evbuf); + int len = EVBUFFER_LENGTH(evbuf); + int nibbles = 0, off; + + if (!len) + return (-1); + + nibbles = ((data[0] & 0xf0) >> 4) + 1; + if (nibbles > 8 || (nibbles >> 1) > len - 1) + return (-1); + + off = nibbles; + while (off > 0) { + number <<= 4; + if (off & 0x1) + number |= data[off >> 1] & 0x0f; + else + number |= (data[off >> 1] & 0xf0) >> 4; + off--; + } + + len = (nibbles >> 1) + 1; + if (dodrain) + evbuffer_drain(evbuf, len); + + *pnumber = number; + + return (len); +} + +int +decode_int(u_int32_t *pnumber, struct evbuffer *evbuf) +{ + return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0); +} + +int +evtag_peek(struct evbuffer *evbuf, u_int8_t *ptag) +{ + if (EVBUFFER_LENGTH(evbuf) < 2) + return (-1); + *ptag = EVBUFFER_DATA(evbuf)[0]; + + return (0); +} + +int +evtag_peek_length(struct evbuffer *evbuf, u_int32_t *plength) +{ + struct evbuffer tmp; + int res; + + if (EVBUFFER_LENGTH(evbuf) < 2) + return (-1); + + tmp = *evbuf; + tmp.buffer += 1; + tmp.off -= 1; + + res = decode_int_internal(plength, &tmp, 0); + if (res == -1) + return (-1); + + *plength += res + 1; + + return (0); +} + +int +evtag_payload_length(struct evbuffer *evbuf, u_int32_t *plength) +{ + struct evbuffer tmp; + int res; + + if (EVBUFFER_LENGTH(evbuf) < 2) + return (-1); + + tmp = *evbuf; + tmp.buffer += 1; + tmp.off -= 1; + + res = decode_int_internal(plength, &tmp, 0); + if (res == -1) + return (-1); + + return (0); +} + +int +evtag_consume(struct evbuffer *evbuf) +{ + u_int32_t len; + evbuffer_drain(evbuf, 1); + if (decode_int(&len, evbuf) == -1) + return (-1); + evbuffer_drain(evbuf, len); + + return (0); +} + +/* Reads the data type from an event buffer */ + +int +evtag_unmarshal(struct evbuffer *src, u_int8_t *ptag, struct evbuffer *dst) +{ + u_int8_t tag; + u_int16_t len; + u_int32_t integer; + + if (evbuffer_remove(src, &tag, sizeof(tag)) != sizeof(tag)) + return (-1); + if (decode_int(&integer, src) == -1) + return (-1); + len = integer; + + if (EVBUFFER_LENGTH(src) < len) + return (-1); + + if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1) + return (-1); + + evbuffer_drain(src, len); + + *ptag = tag; + return (len); +} + +/* Marshaling for integers */ + +int +evtag_unmarshal_int(struct evbuffer *evbuf, u_int8_t need_tag, + u_int32_t *pinteger) +{ + u_int8_t tag; + u_int16_t len; + u_int32_t integer; + + if (evbuffer_remove(evbuf, &tag, sizeof(tag)) != sizeof(tag) || + tag != need_tag) + return (-1); + if (decode_int(&integer, evbuf) == -1) + return (-1); + len = integer; + + if (EVBUFFER_LENGTH(evbuf) < len) + return (-1); + + evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1) + return (-1); + + evbuffer_drain(evbuf, len); + + return (decode_int(pinteger, _buf)); +} + +/* Unmarshal a fixed length tag */ + +int +evtag_unmarshal_fixed(struct evbuffer *src, u_int8_t need_tag, void *data, + size_t len) +{ + u_int8_t tag; + + /* Initialize this event buffer so that we can read into it */ + evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + + /* Now unmarshal a tag and check that it matches the tag we want */ + if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag) + return (-1); + + if (EVBUFFER_LENGTH(_buf) != len) + return (-1); + + memcpy(data, EVBUFFER_DATA(_buf), len); + return (0); +} + +int +evtag_unmarshal_string(struct evbuffer *evbuf, u_int8_t need_tag, + char **pstring) +{ + u_int8_t tag; + + evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + + if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) + return (-1); + + *pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1); + if (*pstring == NULL) + err(1, "%s: calloc", __func__); + evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf)); + + return (0); +} + +int +evtag_unmarshal_timeval(struct evbuffer *evbuf, u_int8_t need_tag, + struct timeval *ptv) +{ + u_int8_t tag; + u_int32_t integer; + + evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf)); + if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag) + return (-1); + + if (decode_int(&integer, _buf) == -1) + return (-1); + ptv->tv_sec = integer; + if (decode_int(&integer, _buf) == -1) + return (-1); + ptv->tv_usec = integer; + + return (0); +} Added: trunk/varnish-cache/contrib/libevent/http.c =================================================================== --- trunk/varnish-cache/contrib/libevent/http.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/http.c 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,1492 @@ +/* + * Copyright (c) 2002-2006 Niels Provos + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_IOCCOM_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif +#include +#include +#include + +#undef timeout_pending +#undef timeout_initialized + +#include "event.h" +#include "log.h" +#include "http.h" + +extern int debug; + +static int make_socket_ai(int (*f)(int, const struct sockaddr *, socklen_t), + struct addrinfo *); +static int make_socket(int (*)(int, const struct sockaddr *, socklen_t), + const char *, short); +static void name_from_addr(struct sockaddr *, socklen_t, char **, char **); + +void evhttp_write(int, short, void *); + +static const char * +html_replace(char ch) +{ + static char buf[2]; + + switch (ch) { + case '<': + return "<"; + case '>': + return ">"; + case '"': + return """; + case '\'': + return "'"; + case '&': + return "&"; + default: + break; + } + + /* Echo the character back */ + buf[0] = ch; + buf[1] = '\0'; + + return buf; +} + +/* + * Replaces <, >, ", ' and & with <, >, ", + * ' and & correspondingly. + * + * The returned string needs to be freed by the caller. + */ + +char * +evhttp_htmlescape(const char *html) +{ + int i, new_size = 0; + char *escaped_html, *p; + + for (i = 0; i < strlen(html); ++i) + new_size += strlen(html_replace(html[i])); + + p = escaped_html = malloc(new_size + 1); + if (escaped_html == NULL) + event_err(1, "%s: malloc(%d)", __func__, new_size + 1); + for (i = 0; i < strlen(html); ++i) { + const char *replaced = html_replace(html[i]); + /* this is length checked */ + strcpy(p, replaced); + p += strlen(replaced); + } + + *p = '\0'; + + return (escaped_html); +} + +const char * +evhttp_method(enum evhttp_cmd_type type) +{ + const char *method; + + switch (type) { + case EVHTTP_REQ_GET: + method = "GET"; + break; + case EVHTTP_REQ_POST: + method = "POST"; + break; + case EVHTTP_REQ_HEAD: + method = "HEAD"; + break; + default: + method = NULL; + break; + } + + return (method); +} + +void +evhttp_form_response(struct evbuffer *buf, struct evhttp_request *req) +{ + /* Clean out the buffer */ + evbuffer_drain(buf, buf->off); + + /* Create the header fields */ + evhttp_make_header(buf, req); + + /* Append the response buffer */ + evbuffer_add(buf, + EVBUFFER_DATA(req->buffer), EVBUFFER_LENGTH(req->buffer)); +} + +void +evhttp_write_buffer(struct evhttp_request *req, struct evbuffer *buffer, + void (*cb)(struct evhttp_request *, void *), void *arg) +{ + struct timeval tv; + + event_debug(("%s: preparing to write buffer\n", __func__)); + + if (req->buffer != buffer) { + if (req->buffer != NULL) + evbuffer_free(req->buffer); + req->buffer = buffer; + } + + /* Set call back */ + + req->cb = cb; + req->cb_arg = arg; + + event_set(&req->ev, req->fd, EV_WRITE, evhttp_write, req); + timerclear(&tv); + tv.tv_sec = HTTP_WRITE_TIMEOUT; + event_add(&req->ev, &tv); +} + +/* + * Create the headers need for an HTTP reply + */ +static void +evhttp_make_header_request(struct evbuffer *buf, struct evhttp_request *req) +{ + static char line[1024]; + const char *method; + + evhttp_remove_header(req->output_headers, "Accept-Encoding"); + evhttp_remove_header(req->output_headers, "Proxy-Connection"); + evhttp_remove_header(req->output_headers, "Connection"); + evhttp_add_header(req->output_headers, "Connection", "close"); + req->minor = 0; + + /* Generate request line */ + method = evhttp_method(req->type); + snprintf(line, sizeof(line), "%s %s HTTP/%d.%d\r\n", + method, req->uri, req->major, req->minor); + evbuffer_add(buf, line, strlen(line)); + + /* Add the content length on a post request if missing */ + if (req->type == EVHTTP_REQ_POST && + evhttp_find_header(req->output_headers, "Content-Length") == NULL){ + char size[12]; + snprintf(size, sizeof(size), "%d", + EVBUFFER_LENGTH(req->buffer)); + evhttp_add_header(req->output_headers, "Content-Length", size); + } +} + +/* + * Create the headers needed for an HTTP reply + */ +static void +evhttp_make_header_response(struct evbuffer *buf, struct evhttp_request *req) +{ + static char line[1024]; + snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n", + req->major, req->minor, req->response_code, + req->response_code_line); + evbuffer_add(buf, line, strlen(line)); + + /* Potentially add headers */ + if (evhttp_find_header(req->output_headers, "Content-Type") == NULL) { + evhttp_add_header(req->output_headers, + "Content-Type", "text/html; charset=ISO-8859-1"); + } +} + +void +evhttp_make_header(struct evbuffer *buf, struct evhttp_request *req) +{ + static char line[1024]; + struct evkeyval *header; + + /* + * Depending if this is a HTTP request or response, we might need to + * add some new headers or remove existing headers. + */ + if (req->kind == EVHTTP_REQUEST) { + evhttp_make_header_request(buf, req); + } else { + evhttp_make_header_response(buf, req); + } + + TAILQ_FOREACH(header, req->output_headers, next) { + snprintf(line, sizeof(line), "%s: %s\r\n", + header->key, header->value); + evbuffer_add(buf, line, strlen(line)); + } + evbuffer_add(buf, "\r\n", 2); + + if (req->kind == EVHTTP_REQUEST) { + int len = EVBUFFER_LENGTH(req->buffer); + + /* Add the POST data */ + if (len > 0) + evbuffer_add(buf, EVBUFFER_DATA(req->buffer), len); + } +} + +/* Separated host, port and file from URI */ + +int +evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile) +{ + static char host[1024]; + static char file[1024]; + char *p, *p2; + int len; + u_short port; + + len = strlen(HTTP_PREFIX); + if (strncasecmp(url, HTTP_PREFIX, len)) + return (-1); + + url += len; + + /* We might overrun */ + if (strlcpy(host, url, sizeof (host)) >= sizeof(host)) + return (-1); + + p = strchr(host, '/'); + if (p != NULL) { + *p = '\0'; + p2 = p + 1; + } else + p2 = NULL; + + if (pfile != NULL) { + /* Generate request file */ + if (p2 == NULL) + p2 = ""; + snprintf(file, sizeof(file), "/%s", p2); + } + + p = strchr(host, ':'); + if (p != NULL) { + *p = '\0'; + port = atoi(p + 1); + + if (port == 0) + return (-1); + } else + port = HTTP_DEFAULTPORT; + + if (phost != NULL) + *phost = host; + if (pport != NULL) + *pport = port; + if (pfile != NULL) + *pfile = file; + + return (0); +} + +void +evhttp_fail(struct evhttp_request *req) +{ + evhttp_request_free(req); +} + +void +evhttp_write(int fd, short what, void *arg) +{ + struct evhttp_request *req = arg; + struct timeval tv; + int n; + + if (what == EV_TIMEOUT) { + evhttp_fail(req); + return; + } + + n = evbuffer_write(req->buffer, fd); + if (n == -1) { + event_warn("%s: evbuffer_write", __func__); + evhttp_fail(req); + return; + } + + if (n == 0) { + event_warnx("%s: write nothing\n", __func__); + evhttp_fail(req); + return; + } + + if (EVBUFFER_LENGTH(req->buffer) != 0) { + timerclear(&tv); + tv.tv_sec = HTTP_WRITE_TIMEOUT; + event_add(&req->ev, &tv); + return; + } + + /* Activate our call back */ + (*req->cb)(req, req->cb_arg); +} + +/* + * Reads data into a buffer structure until no more data + * can be read on the file descriptor or we have read all + * the data that we wanted to read. + * Execute callback when done. + */ + +void +evhttp_read(int fd, short what, void *arg) +{ + struct evhttp_request *req = arg; + struct timeval tv; + int n; + + if (what == EV_TIMEOUT) { + evhttp_fail(req); + return; + } + + n = evbuffer_read(req->buffer, fd, req->ntoread); + event_debug(("%s: got %d on %d\n", __func__, n, req->fd)); + + if (n == -1) { + event_warn("%s: evbuffer_read", __func__); + evhttp_fail(req); + } + + /* Adjust the amount of data that we have left to read */ + if (req->ntoread > 0) + req->ntoread -= n; + + if (n == 0 || req->ntoread == 0) { + (*req->cb)(req, req->cb_arg); + return; + } + + timerclear(&tv); + tv.tv_sec = HTTP_READ_TIMEOUT; + event_add(&req->ev, &tv); +} + +void +evhttp_write_requestcb(struct evhttp_request *req, void *arg) +{ + /* Restore the original callbacks */ + req->cb = req->save_cb; + req->cb_arg = req->save_cbarg; + + /* This is after writing the request to the server */ + + /* We are done writing our header and are now expecting the response */ + req->kind = EVHTTP_RESPONSE; + + evhttp_start_read(req); +} + +/* + * Clean up a connection object + */ + +void +evhttp_connection_free(struct evhttp_connection *evcon) +{ + event_del(&evcon->ev); + + if (evcon->fd != -1) + close(evcon->fd); + + if (evcon->address != NULL) + free(evcon->address); + + free(evcon); +} + +/* + * Call back for asynchronous connection attempt. + */ + +void +evhttp_connectioncb(int fd, short what, void *arg) +{ + struct evhttp_connection *evcon = arg; + int error; + socklen_t errsz = sizeof(error); + + if (what == EV_TIMEOUT) { + event_warnx("%s: connection timeout for \"%s:%d\" on %d\n", + __func__, evcon->address, evcon->port, evcon->fd); + goto cleanup; + } + + /* Check if the connection completed */ + if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, &error, + &errsz) == -1) { + event_warn("%s: getsockopt for \"%s:%d\" on %d", + __func__, evcon->address, evcon->port, evcon->fd); + goto cleanup; + } + + if (error) { + event_warnx("%s: connect failed for \"%s:%d\" on %d: %s\n", + __func__, evcon->address, evcon->port, evcon->fd, + strerror(error)); + goto cleanup; + } + + /* We are connected to the server now */ + event_debug(("%s: connected to \"%s:%d\" on %d\n", + __func__, evcon->address, evcon->port, evcon->fd)); + + /* We are turning the connection object over to the user */ + (*evcon->cb)(evcon, evcon->cb_arg); + return; + + cleanup: + /* Signal error to the user */ + (*evcon->cb)(NULL, evcon->cb_arg); + + evhttp_connection_free(evcon); + return; +} + +/* + * Check if we got a valid response code. + */ + +int +evhttp_valid_response_code(int code) +{ + if (code == 0) + return (0); + + return (1); +} + +/* Parses the status line of a web server */ + +int +evhttp_parse_response_line(struct evhttp_request *req, char *line) +{ + char *protocol; + char *number; + char *readable; + + protocol = strsep(&line, " "); + if (line == NULL) + return (-1); + number = strsep(&line, " "); + if (line == NULL) + return (-1); + readable = line; + + if (strcmp(protocol, "HTTP/1.0") == 0) { + req->major = 1; + req->minor = 0; + } else if (strcmp(protocol, "HTTP/1.1") == 0) { + req->major = 1; + req->minor = 1; + } else { + event_warnx("%s: bad protocol \"%s\" on %d\n", + __func__, protocol, req->fd); + return (-1); + } + + req->response_code = atoi(number); + if (!evhttp_valid_response_code(req->response_code)) { + event_warnx("%s: bad response code \"%s\" on %d\n", + __func__, number, req->fd); + return (-1); + } + + if ((req->response_code_line = strdup(readable)) == NULL) + event_err(1, "%s: strdup", __func__); + + return (0); +} + +/* Parse the first line of a HTTP request */ + +int +evhttp_parse_request_line(struct evhttp_request *req, char *line) +{ + char *method; + char *uri; + char *version; + + /* Parse the request line */ + method = strsep(&line, " "); + if (line == NULL) + return (-1); + uri = strsep(&line, " "); + if (line == NULL) + return (-1); + version = strsep(&line, " "); + if (line != NULL) + return (-1); + + /* First line */ + if (strcmp(method, "GET") == 0) { + req->type = EVHTTP_REQ_GET; + } else if (strcmp(method, "POST") == 0) { + req->type = EVHTTP_REQ_POST; + } else if (strcmp(method, "HEAD") == 0) { + req->type = EVHTTP_REQ_HEAD; + } else { + event_warnx("%s: bad method %s on fd %d\n", + __func__, method, req->fd); + return (-1); + } + + if (strcmp(version, "HTTP/1.0") == 0) { + req->major = 1; + req->minor = 0; + } else if (strcmp(version, "HTTP/1.1") == 0) { + req->major = 1; + req->minor = 1; + } else { + event_warnx("%s: bad version %s on %d\n", + __func__, version, req->fd); + return (-1); + } + + if ((req->uri = strdup(uri)) == NULL) { + event_warn("%s: strdup", __func__); + return (-1); + } + + return (0); +} + +const char * +evhttp_find_header(struct evkeyvalq *headers, const char *key) +{ + struct evkeyval *header; + + TAILQ_FOREACH(header, headers, next) { + if (strcasecmp(header->key, key) == 0) + return (header->value); + } + + return (NULL); +} + +void +evhttp_clear_headers(struct evkeyvalq *headers) +{ + struct evkeyval *header; + + for (header = TAILQ_FIRST(headers); + header != NULL; + header = TAILQ_FIRST(headers)) { + TAILQ_REMOVE(headers, header, next); + free(header->key); + free(header->value); + free(header); + } +} + +/* + * Returns 0, if the header was successfully removed. + * Returns -1, if the header could not be found. + */ + +int +evhttp_remove_header(struct evkeyvalq *headers, const char *key) +{ + struct evkeyval *header; + + TAILQ_FOREACH(header, headers, next) { + if (strcasecmp(header->key, key) == 0) + break; + } + + if (header == NULL) + return (-1); + + /* Free and remove the header that we found */ + TAILQ_REMOVE(headers, header, next); + free(header->key); + free(header->value); + free(header); + + return (0); +} + +int +evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value) +{ + struct evkeyval *header; + + header = calloc(1, sizeof(struct evkeyval)); + if (header == NULL) { + event_warn("%s: calloc", __func__); + return (-1); + } + if ((header->key = strdup(key)) == NULL) { + free(header); + event_warn("%s: strdup", __func__); + return (-1); + } + if ((header->value = strdup(value)) == NULL) { + free(header->key); + free(header); + event_warn("%s: strdup", __func__); + return (-1); + } + + TAILQ_INSERT_TAIL(headers, header, next); + + return (0); +} + +/* + * Parses header lines from a request or a response into the specified + * request object given an event buffer. + * + * Returns + * -1 on error + * 0 when we need to read more headers + * 1 when all headers have been read. + */ + +int +evhttp_parse_lines(struct evhttp_request *req, struct evbuffer* buffer) +{ + u_char *endp; + int done = 0; + + struct evkeyvalq* headers = req->input_headers; + while ((endp = evbuffer_find(buffer, "\r\n", 2)) != NULL) { + char *skey, *svalue; + + if (strncmp(EVBUFFER_DATA(buffer), "\r\n", 2) == 0) { + evbuffer_drain(buffer, 2); + /* Last header - Done */ + done = 1; + break; + } + + *endp = '\0'; + endp += 2; + + event_debug(("%s: Got: %s\n", __func__, EVBUFFER_DATA(buffer))); + + /* Processing of header lines */ + if (req->got_firstline == 0) { + switch (req->kind) { + case EVHTTP_REQUEST: + if (evhttp_parse_request_line(req, EVBUFFER_DATA(buffer)) == -1) + return (-1); + break; + case EVHTTP_RESPONSE: + if (evhttp_parse_response_line(req, EVBUFFER_DATA(buffer)) == -1) + return (-1); + break; + default: + return (-1); + } + req->got_firstline = 1; + } else { + /* Regular header */ + svalue = EVBUFFER_DATA(buffer); + skey = strsep(&svalue, ":"); + if (svalue == NULL) + return (-1); + + svalue += strspn(svalue, " "); + + if (evhttp_add_header(headers, skey, svalue) == -1) + return (-1); + } + + /* Move the uncompleted headers forward */ + evbuffer_drain(buffer, endp - EVBUFFER_DATA(buffer)); + } + + return (done); +} + +void +evhttp_get_body(struct evhttp_request *req) +{ + struct timeval tv; + const char *content_length; + const char *connection; + struct evkeyvalq *headers = req->input_headers; + + /* If this is a request without a body, then we are done */ + if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) { + (*req->cb)(req, req->cb_arg); + return; + } + + content_length = evhttp_find_header(headers, "Content-Length"); + connection = evhttp_find_header(headers, "Connection"); + + if (content_length == NULL && connection == NULL) + req->ntoread = -1; + else if (content_length == NULL && + strcasecmp(connection, "Close") != 0) { + /* Bad combination, we don't know when it will end */ + event_warnx("%s: we got no content length, but the server" + " wants to keep the connection open: %s.\n", + __func__, connection); + evhttp_fail(req); + return; + } else if (content_length == NULL) + req->ntoread = -1; + else + req->ntoread = atoi(content_length); + + event_debug(("%s: bytes to read: %d (in buffer %d)\n", + __func__, req->ntoread, EVBUFFER_LENGTH(req->buffer))); + + if (req->ntoread > 0) + req->ntoread -= EVBUFFER_LENGTH(req->buffer); + + if (req->ntoread == 0) { + (*req->cb)(req, req->cb_arg); + return; + } + + event_set(&req->ev, req->fd, EV_READ, evhttp_read, req); + timerclear(&tv); + tv.tv_sec = HTTP_READ_TIMEOUT; + event_add(&req->ev, &tv); +} + +void +evhttp_read_header(int fd, short what, void *arg) +{ + struct timeval tv; + struct evhttp_request *req = arg; + int n, res; + + if (what == EV_TIMEOUT) { + event_warnx("%s: timeout on %d\n", __func__, fd); + evhttp_request_free(req); + return; + } + + n = evbuffer_read(req->buffer, fd, -1); + if (n == 0) { + event_warnx("%s: no more data on %d\n", __func__, fd); + evhttp_request_free(req); + return; + } + if (n == -1) { + event_warnx("%s: bad read on %d\n", __func__, fd); + evhttp_request_free(req); + return; + } + + res = evhttp_parse_lines(req, req->buffer); + if (res == -1) { + /* Error while reading, terminate */ + event_warnx("%s: bad header lines on %d\n", __func__, fd); + evhttp_request_free(req); + return; + } else if (res == 0) { + /* Need more header lines */ + timerclear(&tv); + tv.tv_sec = HTTP_READ_TIMEOUT; + event_add(&req->ev, &tv); + return; + } + + /* Done reading headers, do the real work */ + switch (req->kind) { + case EVHTTP_REQUEST: + event_debug(("%s: checking for post data on %d\n", + __func__, req->fd)); + evhttp_get_body(req); + break; + + case EVHTTP_RESPONSE: + event_debug(("%s: starting to read body for \"%s\" on %d\n", + __func__, req->remote_host, req->fd)); + evhttp_get_body(req); + break; + + default: + event_warnx("%s: bad header on %d\n", __func__, fd); + evhttp_fail(req); + break; + } +} + +/* + * Creates a TCP connection to the specified port and executes a callback + * when finished. Failure or sucess is indicate by the passed connection + * object. + * + * Although this interface accepts a hostname, it is intended to take + * only numeric hostnames so that non-blocking DNS resolution can + * happen elsewhere. + */ + +struct evhttp_connection * +evhttp_connect(const char *address, unsigned short port, + void (*cb)(struct evhttp_connection *, void *), void *cb_arg) +{ + struct evhttp_connection *evcon = NULL; + struct timeval tv; + + event_debug(("Attempting connection to %s:%d\n", address, port)); + + if ((evcon = calloc(1, sizeof(struct evhttp_connection))) == NULL) { + event_warn("%s: calloc failed", __func__); + goto error; + } + + evcon->fd = -1; + evcon->port = port; + if ((evcon->address = strdup(address)) == NULL) { + event_warn("%s: strdup failed", __func__); + goto error; + } + + /* Let the user name when something interesting happened */ + evcon->cb = cb; + evcon->cb_arg = cb_arg; + + /* Do async connection to HTTP server */ + if ((evcon->fd = make_socket(connect, address, port)) == -1) { + event_warn("%s: failed to connect to \"%s:%d\"", + __func__, address, port); + goto error; + } + + /* Set up a callback for successful connection setup */ + event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon); + timerclear(&tv); + tv.tv_sec = HTTP_CONNECT_TIMEOUT; + event_add(&evcon->ev, &tv); + + return (evcon); + + error: + if (evcon != NULL) + evhttp_connection_free(evcon); + return (NULL); +} + +/* + * Starts an HTTP request on the provided evhttp_connection object. + * + * In theory we might use this to queue requests on the connection + * object. + */ + +int +evhttp_make_request(struct evhttp_connection *evcon, + struct evhttp_request *req, + enum evhttp_cmd_type type, const char *uri) +{ + struct evbuffer *evbuf = evbuffer_new(); + + if (evbuf == NULL) + return (-1); + + /* We are making a request */ + req->fd = evcon->fd; + req->kind = EVHTTP_REQUEST; + req->type = type; + if (req->uri != NULL) + free(req->uri); + if ((req->uri = strdup(uri)) == NULL) + goto error; + + /* Set the protocol version if it is not supplied */ + if (!req->major && !req->minor) { + req->major = 1; + req->minor = 1; + } + + /* Create the header from the store arguments */ + evhttp_make_header(evbuf, req); + + /* Schedule the write */ + req->save_cb = req->cb; + req->save_cbarg = req->cb_arg; + + /* evbuf is being freed when the request finishes */ + evhttp_write_buffer(req, evbuf, evhttp_write_requestcb, NULL); + return (0); + + error: + evbuffer_free(evbuf); + return (-1); +} + +/* + * Reads data from file descriptor into request structure + * Request structure needs to be set up correctly. + */ + +void +evhttp_start_read(struct evhttp_request *req) +{ + struct timeval tv; + + /* Set up an event to read the headers */ + event_set(&req->ev, req->fd, EV_READ, evhttp_read_header, req); + + timerclear(&tv); + tv.tv_sec = HTTP_READ_TIMEOUT; + event_add(&req->ev, &tv); +} + +void +evhttp_send_done(struct evhttp_request *req, void *arg) +{ + evhttp_request_free(req); +} + +/* + * Returns an error page. + */ + +void +evhttp_send_error(struct evhttp_request *req, int error, const char *reason) +{ + char *fmt = "\n" + "%d %s\n" + "\n" + "

Method Not Implemented

\n" + "Invalid method in request

\n" + "\n"; + + struct evbuffer *buf = evbuffer_new(); + + evhttp_response_code(req, error, reason); + + evbuffer_add_printf(buf, fmt, error, reason); + + evhttp_send_page(req, buf); + + evbuffer_free(buf); +} + +/* Requires that headers and response code are already set up */ + +static __inline void +evhttp_send(struct evhttp_request *req, struct evbuffer *databuf) +{ + struct evbuffer *buf = req->buffer; + + evbuffer_drain(buf, -1); + + /* Adds headers to the response */ + evhttp_make_header(buf, req); + + evbuffer_add_buffer(buf, databuf); + + evhttp_write_buffer(req, buf, evhttp_send_done, NULL); +} + +void +evhttp_send_reply(struct evhttp_request *req, int code, const char *reason, + struct evbuffer *databuf) +{ + evhttp_response_code(req, code, reason); + + evhttp_send(req, databuf); +} + +void +evhttp_response_code(struct evhttp_request *req, int code, const char *reason) +{ + req->kind = EVHTTP_RESPONSE; + req->response_code = code; + if (req->response_code_line != NULL) + free(req->response_code_line); + req->response_code_line = strdup(reason); +} + +void +evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf) +{ + if (req->kind != EVHTTP_RESPONSE) + evhttp_response_code(req, 200, "OK"); + + evhttp_clear_headers(req->output_headers); + evhttp_add_header(req->output_headers, "Content-Type", "text/html"); + evhttp_add_header(req->output_headers, "Connection", "close"); + + evhttp_send(req, databuf); +} + +/* + * Helper function to parse out arguments in a query. + * The arguments are separated by key and value. + */ + +void +evhttp_parse_query(const char *uri, struct evkeyvalq *headers) +{ + char *line; + char *argument; + char *p; + + TAILQ_INIT(headers); + + /* No arguments - we are done */ + if (strchr(uri, '?') == NULL) + return; + + if ((line = strdup(uri)) == NULL) + event_err(1, "%s: strdup", __func__); + + + argument = line; + + /* We already know that there has to be a ? */ + strsep(&argument, "?"); + + p = argument; + while (p != NULL && *p != '\0') { + char *key, *value; + argument = strsep(&p, "&"); + + value = argument; + key = strsep(&value, "="); + if (value == NULL) + goto error; + + event_warnx("Got: %s -> %s\n", key, value); + evhttp_add_header(headers, key, value); + } + + error: + free(line); +} + +void +evhttp_handle_request(struct evhttp_request *req, void *arg) +{ + struct evhttp *http = arg; + struct evhttp_cb *cb; + + /* Test for different URLs */ + TAILQ_FOREACH(cb, &http->callbacks, next) { + int res; + char *p = strchr(req->uri, '?'); + if (p == NULL) + res = strcmp(cb->what, req->uri) == 0; + else + res = strncmp(cb->what, req->uri, + (size_t)(p - req->uri)) == 0; + if (res) { + (*cb->cb)(req, cb->cbarg); + return; + } + } + + /* Generic call back */ + if (http->gencb) { + (*http->gencb)(req, http->gencbarg); + return; + } else { + /* We need to send a 404 here */ + char *fmt = "" + "404 Not Found" + "" + "

Not Found

" + "

The requested URL %s was not found on this server.

" + "\n"; + + char *escaped_html = evhttp_htmlescape(req->uri); + struct evbuffer *buf = evbuffer_new(); + + evhttp_response_code(req, HTTP_NOTFOUND, "Not Found"); + + evbuffer_add_printf(buf, fmt, escaped_html); + + free(escaped_html); + + evhttp_send_page(req, buf); + + evbuffer_free(buf); + } +} + +static void +accept_socket(int fd, short what, void *arg) +{ + struct evhttp *http = arg; + struct sockaddr_storage ss; + socklen_t addrlen = sizeof(ss); + int nfd; + + if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) { + event_warn("%s: bad accept", __func__); + return; + } + + evhttp_get_request(nfd, (struct sockaddr *)&ss, addrlen, + evhttp_handle_request, http); +} + +static int +bind_socket(struct evhttp *http, const char *address, u_short port) +{ + struct event *ev = &http->bind_ev; + int fd; + + if ((fd = make_socket(bind, address, port)) == -1) + return (-1); + + if (listen(fd, 10) == -1) { + event_warn("%s: listen", __func__); + return (-1); + } + + /* Schedule the socket for accepting */ + event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http); + event_add(ev, NULL); + + event_debug(("Bound to port %d - Awaiting connections ... ", port)); + + return (0); +} + +/* + * Start a web server on the specified address and port. + */ + +struct evhttp * +evhttp_start(const char *address, u_short port) +{ + struct evhttp *http; + + if ((http = calloc(1, sizeof(struct evhttp))) == NULL) { + event_warn("%s: calloc", __func__); + return (NULL); + } + + TAILQ_INIT(&http->callbacks); + + if (bind_socket(http, address, port) == -1) { + free(http); + return (NULL); + } + + return (http); +} + +void +evhttp_free(struct evhttp* http) +{ + struct evhttp_cb *http_cb; + int fd = http->bind_ev.ev_fd; + + /* Remove the accepting part */ + event_del(&http->bind_ev); + close(fd); + + while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) { + TAILQ_REMOVE(&http->callbacks, http_cb, next); + free(http_cb->what); + free(http_cb); + } + + free(http); +} + +void +evhttp_set_cb(struct evhttp *http, const char *uri, + void (*cb)(struct evhttp_request *, void *), void *cbarg) +{ + struct evhttp_cb *http_cb; + + if ((http_cb = calloc(1, sizeof(struct evhttp_cb))) == NULL) + event_err(1, "%s: calloc", __func__); + + http_cb->what = strdup(uri); + http_cb->cb = cb; + http_cb->cbarg = cbarg; + + TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next); +} + +void +evhttp_set_gencb(struct evhttp *http, + void (*cb)(struct evhttp_request *, void *), void *cbarg) +{ + http->gencb = cb; + http->gencbarg = cbarg; +} + +/* + * Request related functions + */ + +struct evhttp_request * +evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg) +{ + struct evhttp_request *req = NULL; + + /* Allocate request structure */ + if ((req = calloc(1, sizeof(struct evhttp_request))) == NULL) { + event_warn("%s: calloc", __func__); + goto error; + } + + req->fd = -1; + req->kind = EVHTTP_RESPONSE; + req->input_headers = calloc(1, sizeof(struct evkeyvalq)); + if (req->input_headers == NULL) { + event_warn("%s: calloc", __func__); + goto error; + } + TAILQ_INIT(req->input_headers); + + req->output_headers = calloc(1, sizeof(struct evkeyvalq)); + if (req->output_headers == NULL) { + event_warn("%s: calloc", __func__); + goto error; + } + TAILQ_INIT(req->output_headers); + + req->buffer = evbuffer_new(); + + req->cb = cb; + req->cb_arg = arg; + + return (req); + + error: + if (req != NULL) + evhttp_request_free(req); + return (NULL); +} + +void +evhttp_request_free(struct evhttp_request *req) +{ + if (req->fd != -1) + close(req->fd); + if (req->remote_host != NULL) + free(req->remote_host); + if (req->uri != NULL) + free(req->uri); + if (req->response_code_line != NULL) + free(req->response_code_line); + + if (event_initialized(&req->ev)) + event_del(&req->ev); + + evhttp_clear_headers(req->input_headers); + free(req->input_headers); + + evhttp_clear_headers(req->output_headers); + free(req->output_headers); + + if (req->buffer != NULL) + evbuffer_free(req->buffer); + free(req); +} + +/* + * Allows for inspection of the request URI + */ + +const char * +evhttp_request_uri(struct evhttp_request *req) { + if (req->uri == NULL) + event_debug(("%s: request %p has no uri\n", req)); + return (req->uri); +} + +/* + * Takes a file descriptor to read a request from. + * The callback is executed once the whole request has been read. + */ + +void +evhttp_get_request(int fd, struct sockaddr *sa, socklen_t salen, + void (*cb)(struct evhttp_request *, void *), void *arg) +{ + struct evhttp_request *req; + char *hostname, *portname; + + name_from_addr(sa, salen, &hostname, &portname); + event_debug(("%s: new request from %s:%s on %d\n", + __func__, hostname, portname, fd)); + + if ((req = evhttp_request_new(cb, arg)) == NULL) + return; + + req->fd = fd; + req->kind = EVHTTP_REQUEST; + + if ((req->remote_host = strdup(hostname)) == NULL) + event_err(1, "%s: strdup", __func__); + req->remote_port = atoi(portname); + + evhttp_start_read(req); +} + + +/* + * Network helper functions that we do not want to export to the rest of + * the world. + */ + +static struct addrinfo * +addr_from_name(char *address) +{ + struct addrinfo ai, *aitop; + + memset(&ai, 0, sizeof (ai)); + ai.ai_family = AF_INET; + ai.ai_socktype = SOCK_RAW; + ai.ai_flags = 0; + if (getaddrinfo(address, NULL, &ai, &aitop) != 0) { + event_warn("getaddrinfo"); + return (NULL); + } + + return (aitop); +} + +static void +name_from_addr(struct sockaddr *sa, socklen_t salen, + char **phost, char **pport) +{ + static char ntop[NI_MAXHOST]; + static char strport[NI_MAXSERV]; + + if (getnameinfo(sa, salen, + ntop, sizeof(ntop), strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV) != 0) + event_err(1, "getnameinfo failed"); + + *phost = ntop; + *pport = strport; +} + +/* Either connect or bind */ + +static int +make_socket_ai(int (*f)(int, const struct sockaddr *, socklen_t), + struct addrinfo *ai) +{ + struct linger linger; + int fd, on = 1; + int serrno; + + /* Create listen socket */ + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + event_warn("socket"); + return (-1); + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { + event_warn("fcntl(O_NONBLOCK)"); + goto out; + } + + if (fcntl(fd, F_SETFD, 1) == -1) { + event_warn("fcntl(F_SETFD)"); + goto out; + } + + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)); + linger.l_onoff = 1; + linger.l_linger = 5; + setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); + + if ((f)(fd, ai->ai_addr, ai->ai_addrlen) == -1) { + if (errno != EINPROGRESS) { + goto out; + } + } + + return (fd); + + out: + serrno = errno; + close(fd); + errno = serrno; + return (-1); +} + +static int +make_socket(int (*f)(int, const struct sockaddr *, socklen_t), + const char *address, short port) +{ + struct addrinfo ai, *aitop; + char strport[NI_MAXSERV]; + int fd; + + memset(&ai, 0, sizeof (ai)); + ai.ai_family = AF_INET; + ai.ai_socktype = SOCK_STREAM; + ai.ai_flags = f != connect ? AI_PASSIVE : 0; + snprintf(strport, sizeof (strport), "%d", port); + if (getaddrinfo(address, strport, &ai, &aitop) != 0) { + event_warn("getaddrinfo"); + return (-1); + } + + fd = make_socket_ai(f, aitop); + + freeaddrinfo(aitop); + + return (fd); +} Added: trunk/varnish-cache/contrib/libevent/http.h =================================================================== --- trunk/varnish-cache/contrib/libevent/http.h 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/http.h 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,125 @@ +/* + * Copyright 2001 Niels Provos + * All rights reserved. + * + * This header file contains definitions for dealing with HTTP requests + * that are internal to libevent. As user of the library, you should not + * need to know about these. + */ + +#ifndef _HTTP_H_ +#define _HTTP_H_ + +#define HTTP_CONNECT_TIMEOUT 45 +#define HTTP_WRITE_TIMEOUT 50 +#define HTTP_READ_TIMEOUT 50 + +#define HTTP_PREFIX "http://" +#define HTTP_DEFAULTPORT 80 + +struct evbuffer; +struct addrinfo; + +/* A stupid connection object - maybe make this a bufferevent later */ + +struct evhttp_connection { + int fd; + struct event ev; + + char *address; + u_short port; + + void (*cb)(struct evhttp_connection *, void *); + void *cb_arg; +}; + +enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE }; + +struct evhttp_request { + struct evkeyvalq *input_headers; + struct evkeyvalq *output_headers; + + char *remote_host; + u_short remote_port; + + enum evhttp_request_kind kind; + enum evhttp_cmd_type type; + + char *uri; /* uri after HTTP request was parsed */ + + char major; /* HTTP Major number */ + char minor; /* HTTP Minor number */ + + int got_firstline; + int response_code; /* HTTP Response code */ + char *response_code_line; /* Readable response */ + + int fd; + + struct event ev; + + struct evbuffer *buffer; + int ntoread; + + /* Callback */ + void (*cb)(struct evhttp_request *, void *); + void *cb_arg; + + void (*save_cb)(struct evhttp_request *, void *); + void *save_cbarg; +}; + +struct evhttp_cb { + TAILQ_ENTRY(evhttp_cb) next; + + char *what; + + void (*cb)(struct evhttp_request *req, void *); + void *cbarg; +}; + +struct evhttp { + struct event bind_ev; + + TAILQ_HEAD(httpcbq, evhttp_cb) callbacks; + + void (*gencb)(struct evhttp_request *req, void *); + void *gencbarg; +}; + +void evhttp_get_request(int, struct sockaddr *, socklen_t, + void (*)(struct evhttp_request *, void *), void *); + +/* + * Starts a connection to the specified address and invokes the callback + * if everything is fine. + */ +struct evhttp_connection *evhttp_connect( + const char *address, unsigned short port, + void (*cb)(struct evhttp_connection *, void *), void *cb_arg); + +/* Frees an http connection */ +void evhttp_connection_free(struct evhttp_connection *evcon); + +int evhttp_make_request(struct evhttp_connection *evcon, + struct evhttp_request *req, + enum evhttp_cmd_type type, const char *uri); + +int evhttp_hostportfile(char *, char **, u_short *, char **); + +int evhttp_parse_lines(struct evhttp_request *, struct evbuffer*); + +void evhttp_start_read(struct evhttp_request *); +void evhttp_read_header(int, short, void *); +void evhttp_make_header(struct evbuffer *, struct evhttp_request *); + +void evhttp_form_response(struct evbuffer *, struct evhttp_request *); +void evhttp_write_buffer(struct evhttp_request *, struct evbuffer *, + void (*)(struct evhttp_request *, void *), void *); + +/* response sending HTML the data in the buffer */ +void evhttp_response_code(struct evhttp_request *, int, const char *); +void evhttp_send_page(struct evhttp_request *, struct evbuffer *); +void evhttp_fail(struct evhttp_request *); + +#endif /* _HTTP_H */ Modified: trunk/varnish-cache/contrib/libevent/kqueue.c =================================================================== --- trunk/varnish-cache/contrib/libevent/kqueue.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/kqueue.c 2006-04-03 11:59:08 UTC (rev 98) @@ -75,6 +75,7 @@ int kq_recalc (struct event_base *, void *, int); int kq_dispatch (struct event_base *, void *, struct timeval *); int kq_insert (struct kqop *, struct kevent *); +void kq_dealloc (void *); const struct eventop kqops = { "kqueue", @@ -82,7 +83,8 @@ kq_add, kq_del, kq_recalc, - kq_dispatch + kq_dispatch, + kq_dealloc }; void * @@ -266,10 +268,8 @@ if (!which) continue; - if (!(ev->ev_events & EV_PERSIST)) { - ev->ev_flags &= ~EVLIST_X_KQINKERNEL; + if (!(ev->ev_events & EV_PERSIST)) event_del(ev); - } event_active(ev, which, ev->ev_events & EV_SIGNAL ? events[i].data : 1); @@ -396,3 +396,18 @@ return (0); } + +void +kq_dealloc(void *arg) +{ + struct kqop *kqop = arg; + + if (kqop->changes) + free(kqop->changes); + if (kqop->events) + free(kqop->events); + if (kqop->kq) + close(kqop->kq); + memset(kqop, 0, sizeof(struct kqop)); + free(kqop); +} Modified: trunk/varnish-cache/contrib/libevent/log.h =================================================================== --- trunk/varnish-cache/contrib/libevent/log.h 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/log.h 2006-04-03 11:59:08 UTC (rev 98) @@ -33,11 +33,11 @@ void event_warnx(const char *fmt, ...); void event_msgx(const char *fmt, ...); void _event_debugx(const char *fmt, ...); -#undef USE_DEBUG + #ifdef USE_DEBUG #define event_debug(x) _event_debugx x #else -#define event_debug(x) +#define event_debug(x) do {;} while (0) #endif #endif Modified: trunk/varnish-cache/contrib/libevent/poll.c =================================================================== --- trunk/varnish-cache/contrib/libevent/poll.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/poll.c 2006-04-03 11:59:08 UTC (rev 98) @@ -74,14 +74,16 @@ int poll_del (void *, struct event *); int poll_recalc (struct event_base *, void *, int); int poll_dispatch (struct event_base *, void *, struct timeval *); +void poll_dealloc (void *); -struct eventop pollops = { +const struct eventop pollops = { "poll", poll_init, poll_add, poll_del, poll_recalc, - poll_dispatch + poll_dispatch, + poll_dealloc }; void * @@ -89,11 +91,11 @@ { struct pollop *pollop; - /* Disable kqueue when this environment variable is set */ + /* Disable poll when this environment variable is set */ if (getenv("EVENT_NOPOLL")) return (NULL); - if (!(pollop = calloc(1, sizeof(struct pollop)))) + if (!(pollop = calloc(1, sizeof(struct pollop)))) return (NULL); evsignal_init(&pollop->evsigmask); @@ -182,7 +184,7 @@ return (0); for (i = 0; i < nfds; i++) { - int what = pop->event_set[i].revents; + int what = pop->event_set[i].revents; struct event *r_ev = NULL, *w_ev = NULL; if (!what) continue; @@ -355,3 +357,21 @@ poll_check_ok(pop); return (0); } + +void +poll_dealloc(void *arg) +{ + struct pollop *pop = arg; + + if (pop->event_set) + free(pop->event_set); + if (pop->event_r_back) + free(pop->event_r_back); + if (pop->event_w_back) + free(pop->event_w_back); + if (pop->idxplus1_by_fd) + free(pop->idxplus1_by_fd); + + memset(pop, 0, sizeof(struct pollop)); + free(pop); +} Modified: trunk/varnish-cache/contrib/libevent/rtsig.c =================================================================== --- trunk/varnish-cache/contrib/libevent/rtsig.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/rtsig.c 2006-04-03 11:59:08 UTC (rev 98) @@ -1,3 +1,152 @@ +/* + * Copyright (c) 2006 Mathew Mills + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ +/* + * Meta-level comments: You know that a kernel interface is wrong if + * supporting it requires three times more code than any of the other + * kernel interfaces supported in libevent. Niels - 2006-02-22 + */ +/** + + "RTSIG" is a shorthand for using O_ASYNC to make descriptors send + signals when readable/writable and to use POSIX real-time signals + witch are queued unlike normal signals. At first blush this may + seem like a alternative to epoll, but a number of problems arise + when attempting to build an eventloop entirely out of rtsig. + Still, we can use rtsig in combination with poll() to + provide an eventloop that allows for many thousands of sockets + without huge overheads implicit with using select() or poll() + alone. epoll and kqueue are far superior to rtsig and should be + used where available, but rtsig has been in standard Linux kernels + for a long time and have a huge installation base. epoll requires + special patches for 2.4 kernels and 2.6 kernels are not yet nearly + so ubiquitous. + + rtsig problems: + - O_ASYNC mechanisms work only on sockets - not pipes or tty's + + - O_ASYNC signals are edge-triggered, POLLIN on packet arriving + or socket close; POLLOUT when a socket transitions from + non-writable to writable. Being edge-triggered means the + event-handler callbacks must transition the level ( reading + completely the socket buffer contents ) or it will be unable to + reliably receive notification again. + + - rtsig implementations must be intimately involved in how a + process dispatches signals. + + - delivering signals per-event can be expensive, CPU-wise, but + sigtimedwait() blocks on signals only and means non-sockets + cannot be serviced. + + Theory of operation: + This libevent module uses rtsig to allow us to manage a set of + poll-event descriptors. We can drop uninteresting fd's from the + pollset if the fd will send a signal when it becomes interesting + again. + + poll() offers us level-triggering and, when we have verified the + level of a socket, we can trust the edge-trigger nature of the + ASYNC signal. + + As an eventloop we must poll for external events but leverage + kernel functionality to sleep between events ( until the loop's + next scheduled timed event ). + + If we are polling on any non-sockets then we simply have no choice + about blocking on the poll() call. If we blocked on the + sigtimedwait() call as rtsig papers recommend we will not wake on + non-socket state transitions. As part of libevent, this module + must support non-socket polling. + + Many applications, however, do not need to poll on non-sockets and + so this module should be able to optimize this case by using + sigtimedwait(). For this reason this module can actually trigger + events in each of three different ways: + - poll() returning ready events from descriptors in the pollset + + - real-time signals dequeued via sigtimedwait() + + - real-time signals that call an installed signal handler which in + turn writes the contents of siginfo to one end of a socketpair + DGRAM socket. The other end of the socket is always in the + pollset so poll will be guaranteed to return even if the signal is + received before entering poll(). + + non-socket descriptors force us to block on the poll() for the + duration of a dispatch. In this case we unblock (w/ sigprocmask) + the managed signals just before polling. Each managed signal is + handled by signal_handler() which send()'s the contents of siginfo + over the socketpair. Otherwise, we call poll() with a timeout of + 0ms so it checks the levels of the fd's in the pollset and returns + immediately. Any fd that is a socket and has no active state is + removed from the pollset for the next pass -- we will rely on + getting a signal for events on these fd's. + + The receiving end of the siginfo socketpair is in the pollset + (permanently) so if we are polling on non-sockets, the delivery of + signals immediately following sigprocmask( SIG_UNBLOCK...) will + result in a readable op->signal_recv_fd which ensures the poll() + will return immediately. If the poll() call is blocking and a + signal arrives ( possibly a real-time signal from a socket not in + the pollset ) its handler will write the data to the socketpair + and interrupt the poll(). + + After every poll call we attempt a non-blocking recv from the + signal_recv_fd and continue to recv and dispatch the events until + recv indicates the socket buffer is empty. + + One might raise concerns about receiving event activations from + both poll() and from the rtsig data in the signal_recv_fd. + Fortunately, libevent is already structured for event coalescing, + so this issue is mitigated ( though we do some work twice for the + same event making us less efficient ). I suspect that the cost of + turning off the O_ASYNC flag on fd's in the pollset is more + expensive than handling some events twice. Looking at the + kernel's source code for setting O_ASYNC, it looks like it takes a + global kernel lock... + + After a poll and recv-loop for the signal_recv_fd, we finally do a + sigtimedwait(). sigtimedwait will only block if we haven't + blocked in poll() and we have not enqueued events from either the + poll or the recv-loop. Because sigtimedwait blocks all signals + that are not in the set of signals to be dequeued, we need to + dequeue almost all signals and make sure we dispatch them + correctly. We dequeue any signal that is not blocked as well as + all libevent-managed signals. If we get a signal that is not + managed by libevent we lookup the sigaction for the specific + signal and call that function ourselves. + + Finally, I should mention that getting a SIGIO signal indicates + that the rtsig buffer has overflowed and we have lost events. + This forces us to add _every_ descriptor to the pollset to recover. + +*/ + + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -20,152 +169,465 @@ #include #include #include -#ifndef HAVE_WORKING_RTSIG -#include -#endif +#include #include +#include -#define EVLIST_X_NORT 0x1000 /* Skip RT signals (internal) */ - #include "event.h" +#include "event-internal.h" #include "log.h" extern struct event_list signalqueue; +#include +#ifndef __NR_gettid +#define gettid() getpid() +#else + +#if ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3))) +_syscall0(pid_t,gettid) +#endif + +#endif + +#define EVLIST_NONSOCK 0x1000 /* event is for a non-socket file-descriptor */ +#define EVLIST_DONTDEL 0x2000 /* event should always be in the pollset */ +#define MAXBUFFERSIZE (1024 * 1024 * 2) /* max socketbuffer for signal-spair */ +#define INIT_MAX 16 /* init/min # of fd positions in our pollset */ + +static int signal_send_fd[_NSIG]; /* the globalend of the signal socketpair */ +static int trouble[_NSIG]; /* 1 when signal-handler cant send to signal_send_fd */ + +struct rtdata; +TAILQ_HEAD(rtdata_list, rtdata); + struct rtsigop { - sigset_t sigs; - struct pollfd *poll; - struct event **toev; - int cur, max, total; -#ifndef HAVE_WORKING_RTSIG - int pollmode; -#endif + sigset_t sigs; /* signal mask for all _managed_ signals */ + struct pollfd *poll; /* poll structures */ + struct rtdata **ptodat; /* map poll_position to rtdata */ + int cur; /* cur # fd's in a poll set */ + int max; /* max # fd's in a poll set, start at 16 and grow as needed */ + int total; /* count of fd's we are watching now */ + int signo; /* the signo we use for ASYNC fd notifications */ + int nonsock; /* number of non-socket fd's we are watching */ + int highestfd; /* highest fd accomodated by fdtodat */ + struct rtdata_list **fdtodat; /* map fd to rtdata ( and thus to event ) */ + int signal_recv_fd; /* recv side of the signal_send_fd */ + int signal_send_fd; /* recv side of the signal_send_fd */ + struct event sigfdev; /* our own event structure for the signal fd */ }; -#define INIT_MAX 16 +struct rtdata { + /* rtdata holds rtsig-private state on each event */ + TAILQ_ENTRY (rtdata) next; + struct event *ev; + int poll_position; +}; +void *rtsig_init(void); +int rtsig_add(void *, struct event *); +int rtsig_del(void *, struct event *); +int rtsig_recalc(struct event_base *, void *, int); +int rtsig_dispatch(struct event_base *, void *, struct timeval *); + +struct eventop rtsigops = { + "rtsig", + rtsig_init, + rtsig_add, + rtsig_del, + rtsig_recalc, + rtsig_dispatch +}; + +static void +signal_handler(int sig, siginfo_t *info, void *ctx) +{ + /* + * the signal handler for all libevent-managed signals only + * used if we need to do a blocking poll() call due to + * non-socket fd's in the pollset. + */ + + siginfo_t *i = info; + siginfo_t i_local; + + if (trouble[sig - 1]) { + i_local.si_signo = SIGIO; + i_local.si_errno = 0; + i_local.si_code = 0; + i = &i_local; + trouble[sig - 1] = 0; + } + + if (send(signal_send_fd[sig - 1], i, sizeof(*i), + MSG_DONTWAIT|MSG_NOSIGNAL) == -1) + trouble[sig - 1] = 1; +} + +static void +donothing(int fd, short event, void *arg) +{ + /* + * callback for our signal_recv_fd event structure + * we don't want to act on these events, we just want to wake the poll() + */ +}; + +static void +signotset(sigset_t *set) +{ + int i, l; + l = sizeof(*set) / 4; + for (i = 0; i < l; i++) { + ((unsigned *)set)[i] = ~((unsigned *)set)[i]; + } +} + +/* The next three functions manage our private data about each event struct */ + static int -poll_add(struct rtsigop *op, struct event *ev) +grow_fdset(struct rtsigop *op, int newhigh) { - struct pollfd *pfd; + /* + * grow the fd -> rtdata array because we have encountered a + * new fd too high to fit in the existing array + */ - if (op->poll == NULL) return 0; + struct rtdata_list **p; + struct rtdata_list *datset; + int i,x; + int newcnt = (newhigh + 1) << 1; - if (op->cur == op->max) { - void *p; + if (newhigh <= op->highestfd) + return (0); - p = realloc(op->poll, sizeof(*op->poll) * (op->max << 1)); - if (!p) { - errno = ENOMEM; - return -1; - } - op->poll = p; - p = realloc(op->toev, sizeof(*op->toev) * (op->max << 1)); - if (!p) { - op->poll = realloc(op->poll, sizeof(*op->poll) * op->max); - errno = ENOMEM; - return -1; - } - op->toev = p; - op->max <<= 1; - } + p = op->fdtodat; + p = realloc(op->fdtodat, sizeof(struct rtdata_list *) * newcnt); + if (p == NULL) + return (-1); + op->fdtodat = p; - pfd = &op->poll[op->cur]; - pfd->fd = ev->ev_fd; - pfd->events = 0; - if (ev->ev_events & EV_READ) pfd->events |= POLLIN; - if (ev->ev_events & EV_WRITE) pfd->events |= POLLOUT; - pfd->revents = 0; + datset = calloc(newcnt - (op->highestfd + 1), + sizeof(struct rtdata_list)); + if (datset == NULL) + return (-1); - op->toev[op->cur] = ev; - op->cur++; + for (i = op->highestfd + 1, x = 0; i < newcnt; i++, x++) { + op->fdtodat[i] = &(datset[x]); + TAILQ_INIT(op->fdtodat[i]); + } - return 0; + op->highestfd = newcnt - 1; + return (0); } +static struct rtdata * +ev2dat(struct rtsigop *op, struct event *ev, int create) +{ + /* + * given an event struct, find the dat structure that + * corresponds to it if create is non-zero and the rtdata + * structure does not exist, create it return NULL if not + * found + */ + + int found = 0; + int fd = ev->ev_fd; + struct rtdata *ret = NULL; + + if (op->highestfd < fd && create) + if (grow_fdset(op, fd) == -1) + return (NULL); + + TAILQ_FOREACH(ret, op->fdtodat[fd], next) { + if (ret->ev == ev) { + found = 1; + break; + } + } + + if (!found) { + if (!create) + return (NULL); + + ret = calloc(1, sizeof(struct rtdata)); + if (ret == NULL) + return (NULL); + ret->ev = ev; + ret->poll_position = -1; + TAILQ_INSERT_TAIL(op->fdtodat[fd], ret, next); + } + + return (ret); +} + static void +dat_del(struct rtsigop *op, struct rtdata *dat) +{ + /* + * delete our private notes about a given event struct + * called from rtsig_del() only + */ + int fd; + if (dat == NULL) + return; + fd = dat->ev->ev_fd; + + TAILQ_REMOVE(op->fdtodat[fd], dat, next); + memset(dat, 0, sizeof(*dat)); + free(dat); +} + + +static void +set_sigaction(int sig) +{ + /* + * set the standard handler for any libevent-managed signal, + * including the rtsig used for O_ASYNC notifications + */ + struct sigaction act; + + act.sa_flags = SA_RESTART | SA_SIGINFO; + sigfillset(&(act.sa_mask)); + act.sa_sigaction = &signal_handler; + sigaction(sig, &act, NULL); +} + +static int +find_rt_signal() +{ + /* find an unused rtsignal */ + struct sigaction act; + int sig = SIGRTMIN; + + while (sig <= SIGRTMAX) { + if (sigaction(sig, NULL, &act) != 0) { + if (errno == EINTR) + continue; + } else { + if (act.sa_flags & SA_SIGINFO) { + if (act.sa_sigaction == NULL) + return (sig); + } else { + if (act.sa_handler == SIG_DFL) + return (sig); + } + } + sig++; + } + return (0); +} + +/* + * the next three functions manage our pollset and the memory management for + * fd -> rtdata -> event -> poll_position maps + */ + +static int +poll_add(struct rtsigop *op, struct event *ev, struct rtdata *dat) +{ + struct pollfd *pfd; + int newmax = op->max << 1; + int pp; + + if (op->poll == NULL) + return (0); + + if (dat == NULL) + dat = ev2dat(op, ev, 0); + + if (dat == NULL) + return (0); + + pp = dat->poll_position; + + if (pp != -1) { + pfd = &op->poll[pp]; + if (ev->ev_events & EV_READ) + pfd->events |= POLLIN; + + if (ev->ev_events & EV_WRITE) + pfd->events |= POLLOUT; + + return (0); + } + + if (op->cur == op->max) { + void *p = realloc(op->poll, sizeof(*op->poll) * newmax); + if (p == NULL) { + errno = ENOMEM; + return (-1); + } + op->poll = p; + + p = realloc(op->ptodat, sizeof(*op->ptodat) * newmax); + if (p == NULL) { + /* shrink the pollset back down */ + op->poll = realloc(op->poll, + sizeof(*op->poll) * op->max); + errno = ENOMEM; + return (-1); + } + op->ptodat = p; + op->max = newmax; + } + + pfd = &op->poll[op->cur]; + pfd->fd = ev->ev_fd; + pfd->revents = 0; + pfd->events = 0; + + if (ev->ev_events & EV_READ) + pfd->events |= POLLIN; + + if (ev->ev_events & EV_WRITE) + pfd->events |= POLLOUT; + + op->ptodat[op->cur] = dat; + dat->poll_position = op->cur; + op->cur++; + + return (0); +} + +static void poll_free(struct rtsigop *op, int n) { - if (op->poll == NULL) return; + if (op->poll == NULL) + return; - op->cur--; - if (n < op->cur) { - memcpy(&op->poll[n], &op->poll[op->cur], sizeof(*op->poll)); - op->toev[n] = op->toev[op->cur]; - } - if (op->max > INIT_MAX && op->cur < op->max >> 1) { - op->max >>= 1; - op->poll = realloc(op->poll, sizeof(*op->poll) * op->max); - op->toev = realloc(op->toev, sizeof(*op->toev) * op->max); - } + op->cur--; + + if (n < op->cur) { + memcpy(&op->poll[n], &op->poll[op->cur], sizeof(*op->poll)); + op->ptodat[n] = op->ptodat[op->cur]; + op->ptodat[n]->poll_position = n; + } + + + /* less then half the max in use causes us to shrink */ + if (op->max > INIT_MAX && op->cur < op->max >> 1) { + op->max >>= 1; + op->poll = realloc(op->poll, sizeof(*op->poll) * op->max); + op->ptodat = realloc(op->ptodat, sizeof(*op->ptodat) * op->max); + } } static void -poll_remove(struct rtsigop *op, struct event *ev) +poll_remove(struct rtsigop *op, struct event *ev, struct rtdata *dat) { - int i; + int pp; + if (dat == NULL) + dat = ev2dat(op, ev, 0); - for (i = 0; i < op->cur; i++) { - if (op->toev[i] == ev) { - poll_free(op, i); - break; - } - } + if (dat == NULL) return; + + pp = dat->poll_position; + if (pp != -1) { + poll_free(op, pp); + dat->poll_position = -1; + } } static void activate(struct event *ev, int flags) { - if (!(ev->ev_events & EV_PERSIST)) event_del(ev); - event_active(ev, flags, 1); + /* activate an event, possibly removing one-shot events */ + if (!(ev->ev_events & EV_PERSIST)) + event_del(ev); + event_active(ev, flags, 1); } -void *rtsig_init(void); -int rtsig_add(void *, struct event *); -int rtsig_del(void *, struct event *); -int rtsig_recalc(struct event_base *, void *, int); -int rtsig_dispatch(struct event_base *, void *, struct timeval *); +#define FD_CLOSEONEXEC(x) do { \ + if (fcntl(x, F_SETFD, 1) == -1) \ + event_warn("fcntl(%d, F_SETFD)", x); \ +} while (0) -struct eventop rtsigops = { - "rtsig", - rtsig_init, - rtsig_add, - rtsig_del, - rtsig_recalc, - rtsig_dispatch -}; - void * rtsig_init(void) { struct rtsigop *op; + int sockets[2]; + int optarg; + struct rtdata *dat; + int flags; if (getenv("EVENT_NORTSIG")) - return (NULL); + goto err; - op = malloc(sizeof(*op)); - if (op == NULL) return (NULL); + op = calloc(1, sizeof(*op)); + if (op == NULL) + goto err; - memset(op, 0, sizeof(*op)); - op->max = INIT_MAX; op->poll = malloc(sizeof(*op->poll) * op->max); - if (op->poll == NULL) { - free(op); - return (NULL); - } - op->toev = malloc(sizeof(*op->toev) * op->max); - if (op->toev == NULL) { - free(op->poll); - free(op); - return (NULL); - } + if (op->poll == NULL) + goto err_free_op; + op->signo = find_rt_signal(); + if (op->signo == 0) + goto err_free_poll; + + op->nonsock = 0; + + if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sockets) != 0) + goto err_free_poll; + + FD_CLOSEONEXEC(sockets[0]); + FD_CLOSEONEXEC(sockets[1]); + + signal_send_fd[op->signo - 1] = sockets[0]; + trouble[op->signo - 1] = 0; + op->signal_send_fd = sockets[0]; + op->signal_recv_fd = sockets[1]; + flags = fcntl(op->signal_recv_fd, F_GETFL); + fcntl(op->signal_recv_fd, F_SETFL, flags | O_NONBLOCK); + + optarg = MAXBUFFERSIZE; + setsockopt(signal_send_fd[op->signo - 1], + SOL_SOCKET, SO_SNDBUF, + &optarg, sizeof(optarg)); + + optarg = MAXBUFFERSIZE; + setsockopt(op->signal_recv_fd, + SOL_SOCKET, SO_RCVBUF, + &optarg, sizeof(optarg)); + + op->highestfd = -1; + op->fdtodat = NULL; + if (grow_fdset(op, 1) == -1) + goto err_close_pair; + + op->ptodat = malloc(sizeof(*op->ptodat) * op->max); + if (op->ptodat == NULL) + goto err_close_pair; + sigemptyset(&op->sigs); sigaddset(&op->sigs, SIGIO); - sigaddset(&op->sigs, SIGRTMIN); + sigaddset(&op->sigs, op->signo); sigprocmask(SIG_BLOCK, &op->sigs, NULL); + set_sigaction(SIGIO); + set_sigaction(op->signo); + event_set(&(op->sigfdev), op->signal_recv_fd, EV_READ|EV_PERSIST, + donothing, NULL); + op->sigfdev.ev_flags |= EVLIST_DONTDEL; + dat = ev2dat(op, &(op->sigfdev), 1); + poll_add(op, &(op->sigfdev), dat); + return (op); + + err_close_pair: + close(op->signal_recv_fd); + close(signal_send_fd[op->signo - 1]); + + err_free_poll: + free(op->poll); + + err_free_op: + free(op); + err: + return (NULL); } int @@ -173,79 +635,102 @@ { struct rtsigop *op = (struct rtsigop *) arg; int flags, i; -#ifndef HAVE_WORKING_RTSIG - struct stat st; -#endif + struct stat statbuf; + struct rtdata *dat; if (ev->ev_events & EV_SIGNAL) { + int signo = EVENT_SIGNAL(ev); + sigaddset(&op->sigs, EVENT_SIGNAL(ev)); - return sigprocmask(SIG_BLOCK, &op->sigs, NULL); + if (sigprocmask(SIG_BLOCK, &op->sigs, NULL) == -1) + return (-1); + + set_sigaction(signo); + + signal_send_fd[signo - 1] = op->signal_send_fd; + trouble[signo - 1] = 0; + + return (0); } - if (!(ev->ev_events & (EV_READ | EV_WRITE))) return 0; + if (!(ev->ev_events & (EV_READ|EV_WRITE))) + return (0); -#ifndef HAVE_WORKING_RTSIG - if (fstat(ev->ev_fd, &st) == -1) return -1; - if (S_ISFIFO(st.st_mode)) { - ev->ev_flags |= EVLIST_X_NORT; - op->pollmode++; - } -#endif + if (-1 == fstat(ev->ev_fd, &statbuf)) + return (-1); + if (!S_ISSOCK(statbuf.st_mode)) + ev->ev_flags |= EVLIST_NONSOCK; + flags = fcntl(ev->ev_fd, F_GETFL); if (flags == -1) return (-1); if (!(flags & O_ASYNC)) { - if (fcntl(ev->ev_fd, F_SETSIG, SIGRTMIN) == -1 - || fcntl(ev->ev_fd, F_SETOWN, (int) getpid()) == -1) + if (fcntl(ev->ev_fd, F_SETSIG, op->signo) == -1 || + fcntl(ev->ev_fd, F_SETOWN, (int) gettid()) == -1) return (-1); - - if (fcntl(ev->ev_fd, F_SETFL, flags | O_ASYNC)) + + /* + * the overhead of always handling writeable edges + * isn't going to be that bad... + */ + if (fcntl(ev->ev_fd, F_SETFL, flags | O_ASYNC|O_RDWR)) return (-1); } #ifdef O_ONESIGFD + /* + * F_SETAUXFL and O_ONESIGFD are defined in a non-standard + * linux kernel patch to coalesce events for fds + */ fcntl(ev->ev_fd, F_SETAUXFL, O_ONESIGFD); #endif + dat = ev2dat(op, ev, 1); + if (dat == NULL) + return (-1); + op->total++; - if (poll_add(op, ev) == -1) - goto err; + if (ev->ev_flags & EVLIST_NONSOCK) + op->nonsock++; + if (poll_add(op, ev, dat) == -1) { + /* must check the level of new fd's */ + i = errno; + fcntl(ev->ev_fd, F_SETFL, flags); + errno = i; + return (-1); + } + return (0); - - err: - i = errno; - fcntl(ev->ev_fd, F_SETFL, flags); - errno = i; - return (-1); } int rtsig_del(void *arg, struct event *ev) { + struct rtdata *dat; struct rtsigop *op = (struct rtsigop *) arg; if (ev->ev_events & EV_SIGNAL) { sigset_t sigs; sigdelset(&op->sigs, EVENT_SIGNAL(ev)); - + sigemptyset(&sigs); sigaddset(&sigs, EVENT_SIGNAL(ev)); return (sigprocmask(SIG_UNBLOCK, &sigs, NULL)); } - if (!(ev->ev_events & (EV_READ | EV_WRITE))) + if (!(ev->ev_events & (EV_READ|EV_WRITE))) return (0); -#ifndef HAVE_WORKING_RTSIG - if (ev->ev_flags & EVLIST_X_NORT) - op->pollmode--; -#endif - poll_remove(op, ev); + dat = ev2dat(op, ev, 0); + poll_remove(op, ev, dat); + dat_del(op, dat); op->total--; + if (ev->ev_flags & EVLIST_NONSOCK) + op->nonsock--; return (0); } @@ -253,183 +738,248 @@ int rtsig_recalc(struct event_base *base, void *arg, int max) { - return (0); + return (0); } -int -rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv) +/* + * the following do_X functions implement the different stages of a single + * eventloop pass: poll(), recv(sigsock), sigtimedwait() + * + * do_siginfo_dispatch() is a common factor to both do_sigwait() and + * do_signals_from_socket(). + */ + +static inline int +do_poll(struct rtsigop *op, struct timespec *ts) { - struct rtsigop *op = (struct rtsigop *) arg; - struct timespec ts; - int res, i; + int res = 0; + int i = 0; + + if (op->cur > 1) { + /* non-empty poll set (modulo the signalfd) */ + if (op->nonsock) { + int timeout = ts->tv_nsec / 1000000 + ts->tv_sec * 1000; + + sigprocmask(SIG_UNBLOCK, &(op->sigs), NULL); - if (op->poll == NULL) - goto retry_poll; -#ifndef HAVE_WORKING_RTSIG - if (op->pollmode) - goto poll_all; -#endif + res = poll(op->poll, op->cur, timeout); + + sigprocmask(SIG_BLOCK, &(op->sigs), NULL); + + ts->tv_sec = 0; + ts->tv_nsec = 0; + } else { + res = poll(op->poll, op->cur, 0); + } - if (op->cur) { - ts.tv_sec = ts.tv_nsec = 0; - } else { - ts.tv_sec = tv->tv_sec; - ts.tv_nsec = tv->tv_usec * 1000; - } - - for (;;) { - siginfo_t info; - struct event *ev; - int signum; - - signum = sigtimedwait(&op->sigs, &info, &ts); - - if (signum == -1) { - if (errno == EAGAIN) - break; + if (res < 0) { return (errno == EINTR ? 0 : -1); + } else if (res) { + ts->tv_sec = 0; + ts->tv_nsec = 0; } - ts.tv_sec = ts.tv_nsec = 0; + i = 0; + while (i < op->cur) { + struct rtdata *dat = op->ptodat[i]; + struct event *ev = dat->ev; - if (signum == SIGIO) { -#ifndef HAVE_WORKING_RTSIG - poll_all: -#endif - free(op->poll); - free(op->toev); - retry_poll: - op->cur = 0; - op->max = op->total; - op->poll = malloc(sizeof(*op->poll) * op->total); - if (op->poll == NULL) - return (-1); - op->toev = malloc(sizeof(*op->toev) * op->total); - if (op->toev == NULL) { - free(op->poll); - op->poll = NULL; - return (-1); + if (op->poll[i].revents) { + int flags = 0; + + if (op->poll[i].revents & (POLLIN | POLLERR)) + flags |= EV_READ; + + if (op->poll[i].revents & POLLOUT) + flags |= EV_WRITE; + + if (!(ev->ev_events & EV_PERSIST)) { + poll_remove(op, ev, op->ptodat[i]); + event_del(ev); + } else { + i++; + } + + event_active(ev, flags, 1); + } else { + if (ev->ev_flags & (EVLIST_NONSOCK|EVLIST_DONTDEL)) { + i++; + } else { + poll_remove(op, ev, op->ptodat[i]); + } } + } + } + return (res); +} - TAILQ_FOREACH(ev, &base->eventqueue, ev_next) - if (!(ev->ev_flags & EVLIST_X_NORT)) - poll_add(op, ev); +static inline int +do_siginfo_dispatch(struct event_base *base, struct rtsigop *op, + siginfo_t *info) +{ + int signum; + struct rtdata *dat, *next_dat; + struct event *ev, *next_ev; - break; - } + if (info == NULL) + return (-1); - if (signum == SIGRTMIN) { - int flags, i, sigok = 0; + signum = info->si_signo; + if (signum == op->signo) { + int flags, sigok = 0; + flags = 0; - if (info.si_band <= 0) { /* SI_SIGIO */ - flags = EV_READ | EV_WRITE; - } else { - flags = 0; - if (info.si_band & POLLIN) flags |= EV_READ; - if (info.si_band & POLLOUT) flags |= EV_WRITE; - if (!flags) continue; - } + if (info->si_band & (POLLIN|POLLERR)) + flags |= EV_READ; + if (info->si_band & POLLOUT) + flags |= EV_WRITE; - for (i = 0; flags && i < op->cur; i++) { - ev = op->toev[i]; + if (!flags) + return (0); - if (ev->ev_fd == info.si_fd) { - flags &= ~ev->ev_events; - sigok = 1; - } + if (info->si_fd > op->highestfd) + return (-1); + + dat = TAILQ_FIRST(op->fdtodat[info->si_fd]); + while (dat != TAILQ_END(op->fdtodat[info->si_fd])) { + next_dat = TAILQ_NEXT(dat, next); + if (flags & dat->ev->ev_events) { + ev = dat->ev; + poll_add(op, ev, dat); + activate(ev, flags & ev->ev_events); + sigok = 1; } - - for (ev = TAILQ_FIRST(&base->eventqueue); - flags && ev != TAILQ_END(&base->eventqueue); - ev = TAILQ_NEXT(ev, ev_next)) { - if (ev->ev_fd == info.si_fd) { - if (flags & ev->ev_events) { - i = poll_add(op, ev); - if (i == -1) return -1; - flags &= ~ev->ev_events; - } - sigok = 1; + dat = next_dat; + } + } else if (signum == SIGIO) { + TAILQ_FOREACH(ev, &base->eventqueue, ev_next) { + if (ev->ev_events & (EV_READ|EV_WRITE)) + poll_add(op, ev, NULL); + } + return (1); /* 1 means the caller should poll() again */ + + } else if (sigismember(&op->sigs, signum)) { + /* managed signals are queued */ + ev = TAILQ_FIRST(&signalqueue); + while (ev != TAILQ_END(&signalqueue)) { + next_ev = TAILQ_NEXT(ev, ev_signal_next); + if (EVENT_SIGNAL(ev) == signum) + activate(ev, EV_SIGNAL); + ev = next_ev; + } + } else { + /* dispatch unmanaged signals immediately */ + struct sigaction sa; + if (sigaction(signum, NULL, &sa) == 0) { + if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction) { + (*sa.sa_sigaction)(signum, info, NULL); + } else if (sa.sa_handler) { + if ((int)sa.sa_handler != 1) + (*sa.sa_handler)(signum); + } else { + if (signum != SIGCHLD) { + /* non-blocked SIG_DFL */ + kill(gettid(), signum); } } - - if (!sigok) { - flags = fcntl(info.si_fd, F_GETFL); - if (flags == -1) return -1; - fcntl(info.si_fd, F_SETFL, flags & ~O_ASYNC); - } - } else { - TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { - if (EVENT_SIGNAL(ev) == signum) - activate(ev, EV_SIGNAL); - } } } - if (!op->cur) - return (0); + return (0); +} - res = poll(op->poll, op->cur, tv->tv_sec * 1000 + - (tv->tv_usec + 999) / 1000); - if (res < 0) - return (-1); +/* + * return 1 if we should poll again + * return 0 if we are all set + * return -1 on error + */ +static inline int +do_sigwait(struct event_base *base, struct rtsigop *op, struct timespec *ts, + sigset_t *sigs) +{ + for (;;) { + siginfo_t info; + int signum; - i = 0; -#ifdef HAVE_WORKING_RTSIG - while (i < res) { -#else - while (i < op->cur) { -#endif - if (op->poll[i].revents) { - int flags = 0; - struct event *ev = op->toev[i]; + signum = sigtimedwait(sigs, &info, ts); - if (op->poll[i].revents & POLLIN) - flags |= EV_READ; - if (op->poll[i].revents & POLLOUT) - flags |= EV_WRITE; + ts->tv_sec = 0; + ts->tv_nsec = 0; - if (!(ev->ev_events & EV_PERSIST)) { - event_del(ev); - res--; - } else { - i++; - } - event_active(ev, flags, 1); - } else { -#ifndef HAVE_WORKING_RTSIG - if (op->toev[i]->ev_flags & EVLIST_X_NORT) { - i++; - res++; - continue; - } -#endif - for (;;) { - op->cur--; - if (i == op->cur) - break; - if (op->poll[op->cur].revents) { - memcpy(&op->poll[i], &op->poll[op->cur], sizeof(*op->poll)); - op->toev[i] = op->toev[op->cur]; - break; - } - } + if (signum == -1) { + if (errno == EAGAIN || errno == EINTR) + return (0); + return (-1); + } else if (1 == do_siginfo_dispatch(base, op, &info)) { + return (1); } } -#ifdef HAVE_WORKING_RTSIG - op->cur = res; -#endif - if (!op->cur) { - op->max = INIT_MAX; - free(op->poll); - free(op->toev); - /* We just freed it, we shouldn't have a problem getting it back. */ - op->poll = malloc(sizeof(*op->poll) * op->max); - op->toev = malloc(sizeof(*op->toev) * op->max); + /* NOTREACHED */ +} - if (op->poll == NULL || op->toev == NULL) - event_err(1, "%s: malloc"); +static inline int +do_signals_from_socket(struct event_base *base, struct rtsigop *op, + struct timespec *ts) +{ + int fd = op->signal_recv_fd; + siginfo_t info; + int res; + + for (;;) { + res = recv(fd, &info, sizeof(info), MSG_NOSIGNAL); + if (res == -1) { + if (errno == EAGAIN) + return (0); + if (errno == EINTR) + continue; + return (-1); + } else { + ts->tv_sec = 0; + ts->tv_nsec = 0; + if (1 == do_siginfo_dispatch(base, op, &info)) + return (1); + } } + /* NOTREACHED */ +} +int +rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv) +{ + struct rtsigop *op = (struct rtsigop *) arg; + struct timespec ts; + int res; + sigset_t sigs; + + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * 1000; + + poll_for_level: + res = do_poll(op, &ts); /* ts can be modified in do_XXX() */ + + res = do_signals_from_socket(base, op, &ts); + if (res == 1) + goto poll_for_level; + else if (res == -1) + return (-1); + + /* + * the mask = managed_signals | unblocked-signals + * MM - if this is not blocking do we need to cast the net this wide? + */ + sigemptyset(&sigs); + sigprocmask(SIG_BLOCK, &sigs, &sigs); + signotset(&sigs); + sigorset(&sigs, &sigs, &op->sigs); + + res = do_sigwait(base, op, &ts, &sigs); + + if (res == 1) + goto poll_for_level; + else if (res == -1) + return (-1); + return (0); } + Modified: trunk/varnish-cache/contrib/libevent/select.c =================================================================== --- trunk/varnish-cache/contrib/libevent/select.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/select.c 2006-04-03 11:59:08 UTC (rev 98) @@ -76,6 +76,7 @@ int select_del (void *, struct event *); int select_recalc (struct event_base *, void *, int); int select_dispatch (struct event_base *, void *, struct timeval *); +void select_dealloc (void *); const struct eventop selectops = { "select", @@ -83,7 +84,8 @@ select_add, select_del, select_recalc, - select_dispatch + select_dispatch, + select_dealloc }; static int select_resize(struct selectop *sop, int fdsz); @@ -93,7 +95,7 @@ { struct selectop *sop; - /* Disable kqueue when this environment variable is set */ + /* Disable select when this environment variable is set */ if (getenv("EVENT_NOSELECT")) return (NULL); @@ -131,7 +133,7 @@ } #else -#define check_selectop(sop) +#define check_selectop(sop) do {;} while (0) #endif /* @@ -350,3 +352,25 @@ check_selectop(sop); return (0); } + +void +select_dealloc(void *arg) +{ + struct selectop *sop = arg; + + if (sop->event_readset_in) + free(sop->event_readset_in); + if (sop->event_writeset_in) + free(sop->event_writeset_in); + if (sop->event_readset_out) + free(sop->event_readset_out); + if (sop->event_writeset_out) + free(sop->event_writeset_out); + if (sop->event_r_by_fd) + free(sop->event_r_by_fd); + if (sop->event_w_by_fd) + free(sop->event_w_by_fd); + + memset(sop, 0, sizeof(struct selectop)); + free(sop); +} Modified: trunk/varnish-cache/contrib/libevent/signal.c =================================================================== --- trunk/varnish-cache/contrib/libevent/signal.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/signal.c 2006-04-03 11:59:08 UTC (rev 98) @@ -26,7 +26,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include #ifdef HAVE_SYS_TIME_H @@ -52,7 +54,7 @@ extern struct event_list signalqueue; -static short evsigcaught[NSIG]; +static sig_atomic_t evsigcaught[NSIG]; static int needrecalc; volatile sig_atomic_t evsignal_caught = 0; @@ -61,11 +63,12 @@ static int ev_signal_added; /* Callback for when the signal handler write a byte to our signaling socket */ -static void evsignal_cb(int fd, short what, void *arg) +static void +evsignal_cb(int fd, short what, void *arg) { static char signals[100]; struct event *ev = arg; - int n; + ssize_t n; n = read(fd, signals, sizeof(signals)); if (n == -1) @@ -98,6 +101,8 @@ FD_CLOSEONEXEC(ev_signal_pair[0]); FD_CLOSEONEXEC(ev_signal_pair[1]); + fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK); + event_set(&ev_signal, ev_signal_pair[1], EV_READ, evsignal_cb, &ev_signal); ev_signal.ev_flags |= EVLIST_INTERNAL; @@ -107,12 +112,12 @@ evsignal_add(sigset_t *evsigmask, struct event *ev) { int evsignal; - + if (ev->ev_events & (EV_READ|EV_WRITE)) event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); evsignal = EVENT_SIGNAL(ev); sigaddset(evsigmask, evsignal); - + return (0); } @@ -135,11 +140,14 @@ static void evsignal_handler(int sig) { + int save_errno = errno; + evsigcaught[sig]++; evsignal_caught = 1; /* Wake up our notification mechanism */ write(ev_signal_pair[0], "a", 1); + errno = save_errno; } int @@ -147,7 +155,7 @@ { struct sigaction sa; struct event *ev; - + if (!ev_signal_added) { ev_signal_added = 1; event_add(&ev_signal, NULL); @@ -159,13 +167,13 @@ if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1) return (-1); - + /* Reinstall our signal handler. */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = evsignal_handler; sa.sa_mask = *evsigmask; sa.sa_flags |= SA_RESTART; - + TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { if (sigaction(EVENT_SIGNAL(ev), &sa, NULL) == -1) return (-1); @@ -187,7 +195,7 @@ evsignal_process(void) { struct event *ev; - short ncalls; + sig_atomic_t ncalls; TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { ncalls = evsigcaught[EVENT_SIGNAL(ev)]; Added: trunk/varnish-cache/contrib/libevent/strlcpy.c =================================================================== --- trunk/varnish-cache/contrib/libevent/strlcpy.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/strlcpy.c 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,74 @@ +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 + * THE AUTHOR 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + register char *d = dst; + register const char *s = src; + register size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} Modified: trunk/varnish-cache/contrib/libevent/test/Makefile.am =================================================================== --- trunk/varnish-cache/contrib/libevent/test/Makefile.am 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/Makefile.am 2006-04-03 11:59:08 UTC (rev 98) @@ -4,20 +4,28 @@ CPPFPLAGS = -I.. CFLAGS = -I../compat @CFLAGS@ +EXTRA_DIST = regress.rpc + noinst_PROGRAMS = test-init test-eof test-weof test-time regress bench -test_init_sources = test-init.c -test_eof_sources = test-eof.c -test_weof_sources = test-weof.c -test_time_sources = test-time.c -regress_sources = regress.c -bench_sources = bench.c +BUILT_SOURCES = regress.gen.c regress.gen.h +test_init_SOURCES = test-init.c +test_eof_SOURCES = test-eof.c +test_weof_SOURCES = test-weof.c +test_time_SOURCES = test-time.c +regress_SOURCES = regress.c regress.h regress_http.c \ + regress.gen.c regress.gen.h +bench_SOURCES = bench.c +regress.gen.c regress.gen.h: regress.rpc + ../event_rpcgen.py regress.rpc + DISTCLEANFILES = *~ +CLEANFILES = regress.gen.h regress.gen.c test: test-init test-eof test-weof test-time regress verify: test @./test.sh -bench test-init test-eof test-weof test-time regress: ../libevent.la +bench test-init test-eof test-weof test-time: ../libevent.la Modified: trunk/varnish-cache/contrib/libevent/test/regress.c =================================================================== --- trunk/varnish-cache/contrib/libevent/test/regress.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/regress.c 2006-04-03 11:59:08 UTC (rev 98) @@ -39,21 +39,28 @@ #ifdef HAVE_SYS_TIME_H #include #endif +#include #ifndef WIN32 #include #include #include #endif +#include #include #include #include #include #include -#include +#include "event.h" +#include "log.h" +#include "http.h" -static int pair[2]; -static int test_ok; +#include "regress.h" +#include "regress.gen.h" + +int pair[2]; +int test_ok; static int called; static char wbuf[4096]; static char rbuf[4096]; @@ -276,7 +283,7 @@ } void -test1(void) +test_simpleread(void) { struct event ev; @@ -295,7 +302,7 @@ } void -test2(void) +test_simplewrite(void) { struct event ev; @@ -311,7 +318,7 @@ } void -test3(void) +test_multiple(void) { struct event ev, ev2; int i; @@ -340,7 +347,7 @@ } void -test4(void) +test_persistent(void) { struct event ev, ev2; int i; @@ -369,7 +376,7 @@ } void -test5(void) +test_combined(void) { struct both r1, r2, w1, w2; @@ -404,7 +411,7 @@ } void -test6(void) +test_simpletimeout(void) { struct timeval tv; struct event ev; @@ -424,7 +431,7 @@ #ifndef WIN32 void -test7(void) +test_simplesignal(void) { struct event ev; struct itimerval itv; @@ -447,7 +454,7 @@ #endif void -test8(void) +test_loopexit(void) { struct timeval tv, tv_start, tv_end; struct event ev; @@ -477,6 +484,21 @@ } void +test_evbuffer(void) { + setup_test("Evbuffer: "); + + struct evbuffer *evb = evbuffer_new(); + + evbuffer_add_printf(evb, "%s/%d", "hello", 1); + + if (EVBUFFER_LENGTH(evb) == 7 && + strcmp(EVBUFFER_DATA(evb), "hello/1") == 0) + test_ok = 1; + + cleanup_test(); +} + +void readcb(struct bufferevent *bev, void *arg) { if (EVBUFFER_LENGTH(bev->input) == 8333) { @@ -499,7 +521,7 @@ } void -test9(void) +test_bufferevent(void) { struct bufferevent *bev1, *bev2; char buffer[8333]; @@ -637,7 +659,211 @@ cleanup_test(); } +int decode_int(u_int32_t *pnumber, struct evbuffer *evbuf); +void +read_once_cb(int fd, short event, void *arg) +{ + char buf[256]; + int len; + + len = read(fd, buf, sizeof(buf)); + + if (called) { + test_ok = 0; + } else if (len) { + /* Assumes global pair[0] can be used for writing */ + write(pair[0], TEST1, strlen(TEST1)+1); + test_ok = 1; + } + + called++; +} + +void +test_want_only_once(void) +{ + struct event ev; + struct timeval tv; + + /* Very simple read test */ + setup_test("Want read only once: "); + + write(pair[0], TEST1, strlen(TEST1)+1); + + /* Setup the loop termination */ + timerclear(&tv); + tv.tv_sec = 1; + event_loopexit(&tv); + + event_set(&ev, pair[1], EV_READ, read_once_cb, &ev); + if (event_add(&ev, NULL) == -1) + exit(1); + event_dispatch(); + + cleanup_test(); +} + +#define TEST_MAX_INT 6 + +void +evtag_int_test(void) +{ + struct evbuffer *tmp = evbuffer_new(); + u_int32_t integers[TEST_MAX_INT] = { + 0xaf0, 0x1000, 0x1, 0xdeadbeef, 0x00, 0xbef000 + }; + u_int32_t integer; + int i; + + for (i = 0; i < TEST_MAX_INT; i++) { + int oldlen, newlen; + oldlen = EVBUFFER_LENGTH(tmp); + encode_int(tmp, integers[i]); + newlen = EVBUFFER_LENGTH(tmp); + fprintf(stdout, "\t\tencoded 0x%08x with %d bytes\n", + integers[i], newlen - oldlen); + } + + for (i = 0; i < TEST_MAX_INT; i++) { + if (decode_int(&integer, tmp) == -1) { + fprintf(stderr, "decode %d failed", i); + exit(1); + } + if (integer != integers[i]) { + fprintf(stderr, "got %x, wanted %x", + integer, integers[i]); + exit(1); + } + } + + if (EVBUFFER_LENGTH(tmp) != 0) { + fprintf(stderr, "trailing data"); + exit(1); + } + evbuffer_free(tmp); + + fprintf(stdout, "\t%s: OK\n", __func__); +} + +void +evtag_fuzz() +{ + u_char buffer[4096]; + struct evbuffer *tmp = evbuffer_new(); + struct timeval tv; + int i, j; + + int not_failed = 0; + for (j = 0; j < 100; j++) { + for (i = 0; i < sizeof(buffer); i++) + buffer[i] = rand(); + evbuffer_drain(tmp, -1); + evbuffer_add(tmp, buffer, sizeof(buffer)); + + if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) + not_failed++; + } + + /* The majority of decodes should fail */ + if (not_failed >= 10) { + fprintf(stderr, "evtag_unmarshal should have failed"); + exit(1); + } + + /* Now insert some corruption into the tag length field */ + evbuffer_drain(tmp, -1); + timerclear(&tv); + tv.tv_sec = 1; + evtag_marshal_timeval(tmp, 0, &tv); + evbuffer_add(tmp, buffer, sizeof(buffer)); + + EVBUFFER_DATA(tmp)[1] = 0xff; + if (evtag_unmarshal_timeval(tmp, 0, &tv) != -1) { + fprintf(stderr, "evtag_unmarshal_timeval should have failed"); + exit(1); + } + + evbuffer_free(tmp); + + fprintf(stdout, "\t%s: OK\n", __func__); +} + +void +evtag_test(void) +{ + fprintf(stdout, "Testing Tagging:\n"); + + evtag_init(); + evtag_int_test(); + evtag_fuzz(); + + fprintf(stdout, "OK\n"); +} + +void +rpc_test(void) +{ + struct msg *msg, *msg2; + struct kill *kill; + struct run *run; + struct evbuffer *tmp = evbuffer_new(); + int i; + + fprintf(stdout, "Testing RPC: "); + + msg = msg_new(); + EVTAG_ASSIGN(msg, from_name, "niels"); + EVTAG_ASSIGN(msg, to_name, "phoenix"); + + if (EVTAG_GET(msg, kill, &kill) == -1) { + fprintf(stderr, "Failed to set kill message.\n"); + exit(1); + } + + EVTAG_ASSIGN(kill, weapon, "feather"); + EVTAG_ASSIGN(kill, action, "tickle"); + + for (i = 0; i < 3; ++i) { + run = EVTAG_ADD(msg, run); + if (run == NULL) { + fprintf(stderr, "Failed to add run message.\n"); + exit(1); + } + EVTAG_ASSIGN(run, how, "very fast"); + } + + if (msg_complete(msg) == -1) { + fprintf(stderr, "Failed to make complete message.\n"); + exit(1); + } + + evtag_marshal_msg(tmp, 0, msg); + + msg2 = msg_new(); + if (evtag_unmarshal_msg(tmp, 0, msg2) == -1) { + fprintf(stderr, "Failed to unmarshal message.\n"); + exit(1); + } + + if (!EVTAG_HAS(msg2, from_name) || + !EVTAG_HAS(msg2, to_name) || + !EVTAG_HAS(msg2, kill)) { + fprintf(stderr, "Missing data structures.\n"); + exit(1); + } + + if (EVTAG_LEN(msg2, run) != 3) { + fprintf(stderr, "Wrong number of run messages.\n"); + exit(1); + } + + msg_free(msg); + msg_free(msg2); + + fprintf(stdout, "OK\n"); +} + int main (int argc, char **argv) { @@ -656,23 +882,27 @@ /* Initalize the event library */ event_base = event_init(); - test1(); + http_suite(); + + test_simpleread(); - test2(); + test_simplewrite(); - test3(); + test_multiple(); - test4(); + test_persistent(); - test5(); + test_combined(); - test6(); + test_simpletimeout(); #ifndef WIN32 - test7(); + test_simplesignal(); #endif - test8(); + test_loopexit(); - test9(); + test_evbuffer(); + + test_bufferevent(); test_priorities(1); test_priorities(2); @@ -680,6 +910,12 @@ test_multiple_events_for_same_fd(); + test_want_only_once(); + + evtag_test(); + + rpc_test(); + return (0); } Added: trunk/varnish-cache/contrib/libevent/test/regress.h =================================================================== --- trunk/varnish-cache/contrib/libevent/test/regress.h 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/regress.h 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2000-2004 Niels Provos + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ +#ifndef _REGRESS_H_ +#define _REGRESS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void http_suite(void); +void http_basic_test(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _REGRESS_H_ */ Added: trunk/varnish-cache/contrib/libevent/test/regress.rpc =================================================================== --- trunk/varnish-cache/contrib/libevent/test/regress.rpc 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/regress.rpc 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,17 @@ +/* tests data packing and unpacking */ + +struct msg { + string from_name = 1; + string to_name = 2; + optional struct[kill] kill = 3; + array struct[run] run = 4; +} + +struct kill { + string weapon = 1; + string action = 2; +} + +struct run { + string how = 1; +} Added: trunk/varnish-cache/contrib/libevent/test/regress_http.c =================================================================== --- trunk/varnish-cache/contrib/libevent/test/regress_http.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/regress_http.c 2006-04-03 11:59:08 UTC (rev 98) @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2003-2006 Niels Provos + * All rights reserved. + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ + +#ifdef WIN32 +#include +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include +#ifndef WIN32 +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "event.h" +#include "log.h" +#include "http.h" + +extern int pair[]; +extern int test_ok; + +static struct evhttp *http; + +void http_basic_cb(struct evhttp_request *req, void *arg); +void http_post_cb(struct evhttp_request *req, void *arg); + +struct evhttp * +http_setup(short *pport) +{ + int i; + struct evhttp *myhttp; + short port = -1; + + /* Try a few different ports */ + for (i = 0; i < 50; ++i) { + myhttp = evhttp_start("127.0.0.1", 8080 + i); + if (myhttp != NULL) { + port = 8080 + i; + break; + } + } + + if (port == -1) + event_errx(1, "Could not start web server"); + + /* Register a callback for certain types of requests */ + evhttp_set_cb(myhttp, "/test", http_basic_cb, NULL); + evhttp_set_cb(myhttp, "/postit", http_post_cb, NULL); + + *pport = port; + return (myhttp); +} + +int +http_connect(const char *address, u_short port) +{ + /* Stupid code for connecting */ + struct addrinfo ai, *aitop; + char strport[NI_MAXSERV]; + int fd; + + memset(&ai, 0, sizeof (ai)); + ai.ai_family = AF_INET; + ai.ai_socktype = SOCK_STREAM; + snprintf(strport, sizeof (strport), "%d", port); + if (getaddrinfo(address, strport, &ai, &aitop) != 0) { + event_warn("getaddrinfo"); + return (-1); + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + event_err(1, "socket failed"); + + if (connect(fd, aitop->ai_addr, aitop->ai_addrlen) == -1) + event_err(1, "connect failed"); + + freeaddrinfo(aitop); + + return (fd); +} + +void +http_readcb(struct bufferevent *bev, void *arg) +{ + const char *what = "This is funny"; + + event_debug(("%s: %s\n", __func__, EVBUFFER_DATA(bev->input))); + + if (evbuffer_find(bev->input, what, strlen(what)) != NULL) { + struct evhttp_request *req = evhttp_request_new(NULL, NULL); + req->kind = EVHTTP_RESPONSE; + int done = evhttp_parse_lines(req, bev->input); + + if (done == 1 && + evhttp_find_header(req->input_headers, + "Content-Type") != NULL) + test_ok++; + evhttp_request_free(req); + bufferevent_disable(bev, EV_READ); + event_loopexit(NULL); + } +} + +void +http_writecb(struct bufferevent *bev, void *arg) +{ + if (EVBUFFER_LENGTH(bev->output) == 0) { + /* enable reading of the reply */ + bufferevent_enable(bev, EV_READ); + test_ok++; + } +} + +void +http_errorcb(struct bufferevent *bev, short what, void *arg) +{ + test_ok = -2; + event_loopexit(NULL); +} + +void +http_basic_cb(struct evhttp_request *req, void *arg) +{ + event_debug((stderr, "%s: called\n", __func__)); + + struct evbuffer *evb = evbuffer_new(); + evbuffer_add_printf(evb, "This is funny"); + + evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + + evbuffer_free(evb); +} + +void +http_basic_test(void) +{ + struct bufferevent *bev; + int fd; + char *http_request; + short port = -1; + + test_ok = 0; + fprintf(stdout, "Testing Basic HTTP Server: "); + + http = http_setup(&port); + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = bufferevent_new(fd, http_readcb, http_writecb, + http_errorcb, NULL); + + http_request = + "GET /test HTTP/1.1\r\n" + "Host: somehost \r\n" + "\r\n"; + + bufferevent_write(bev, http_request, strlen(http_request)); + + event_dispatch(); + + bufferevent_free(bev); + close(fd); + + evhttp_free(http); + + if (test_ok != 2) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + fprintf(stdout, "OK\n"); +} + +void http_connectcb(struct evhttp_connection *evcon, void *arg); + +void +http_connection_test(void) +{ + short port = -1; + struct evhttp_connection *evcon = NULL; + + test_ok = 0; + fprintf(stdout, "Testing Basic HTTP Connection: "); + + http = http_setup(&port); + + evcon = evhttp_connect("127.0.0.1", port, http_connectcb, NULL); + if (evcon == NULL) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + event_dispatch(); + + evhttp_connection_free(evcon); + evhttp_free(http); + + if (test_ok != 1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + fprintf(stdout, "OK\n"); +} + +void http_request_done(struct evhttp_request *, void *); + +void +http_connectcb(struct evhttp_connection *evcon, void *arg) +{ + struct evhttp_request *req = NULL; + + if (evcon == NULL) { + fprintf(stdout, "FAILED\n"); + exit (1); + } + + /* + * At this point, we want to schedule a request to the HTTP + * server using our make request method. + */ + + req = evhttp_request_new(http_request_done, NULL); + + /* Add the information that we care about */ + evhttp_add_header(req->output_headers, "Host", "somehost"); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } +} + +void +http_request_done(struct evhttp_request *req, void *arg) +{ + const char *what = "This is funny"; + + if (req->response_code != HTTP_OK) { + + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (EVBUFFER_LENGTH(req->buffer) != strlen(what)) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (memcmp(EVBUFFER_DATA(req->buffer), what, strlen(what)) != 0) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + event_loopexit(NULL); +} + +/* + * HTTP POST test. + */ + +void http_connect_forpostcb(struct evhttp_connection *evcon, void *arg); + +void +http_post_test(void) +{ + short port = -1; + struct evhttp_connection *evcon = NULL; + + test_ok = 0; + fprintf(stdout, "Testing HTTP POST Request: "); + + http = http_setup(&port); + + evcon = evhttp_connect("127.0.0.1", port, http_connect_forpostcb, NULL); + if (evcon == NULL) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + event_dispatch(); + + evhttp_connection_free(evcon); + evhttp_free(http); + + if (test_ok != 1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + fprintf(stdout, "OK\n"); +} + +void http_postrequest_done(struct evhttp_request *, void *); + +#define POST_DATA "Okay. Not really printf" + +void +http_connect_forpostcb(struct evhttp_connection *evcon, void *arg) +{ + struct evhttp_request *req = NULL; + + if (evcon == NULL) { + fprintf(stdout, "FAILED\n"); + exit (1); + } + + /* + * At this point, we want to schedule an HTTP POST request + * server using our make request method. + */ + + req = evhttp_request_new(http_postrequest_done, NULL); + + /* Add the information that we care about */ + evhttp_add_header(req->output_headers, "Host", "somehost"); + evbuffer_add_printf(req->buffer, POST_DATA); + + if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) { + fprintf(stdout, "FAILED\n"); + exit(1); + } +} + +void +http_post_cb(struct evhttp_request *req, void *arg) +{ + event_debug((stderr, "%s: called\n", __func__)); + + /* Yes, we are expecting a post request */ + if (req->type != EVHTTP_REQ_POST) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + if (EVBUFFER_LENGTH(req->buffer) != strlen(POST_DATA)) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + if (strcmp(EVBUFFER_DATA(req->buffer), POST_DATA)) { + fprintf(stdout, "FAILED\n"); + exit(1); + } + + struct evbuffer *evb = evbuffer_new(); + evbuffer_add_printf(evb, "This is funny"); + + evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb); + + evbuffer_free(evb); +} + +void +http_postrequest_done(struct evhttp_request *req, void *arg) +{ + const char *what = "This is funny"; + + if (req->response_code != HTTP_OK) { + + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (evhttp_find_header(req->input_headers, "Content-Type") == NULL) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (EVBUFFER_LENGTH(req->buffer) != strlen(what)) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + if (memcmp(EVBUFFER_DATA(req->buffer), what, strlen(what)) != 0) { + fprintf(stderr, "FAILED\n"); + exit(1); + } + + test_ok = 1; + event_loopexit(NULL); +} + + +void +http_suite(void) +{ + http_basic_test(); + http_connection_test(); + http_post_test(); +} Modified: trunk/varnish-cache/contrib/libevent/test/test-weof.c =================================================================== --- trunk/varnish-cache/contrib/libevent/test/test-weof.c 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/test-weof.c 2006-04-03 11:59:08 UTC (rev 98) @@ -47,7 +47,7 @@ { struct event ev; - if (signal(SIGPIPE, SIG_IGN) == SIG_IGN) + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) return (1); if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) Modified: trunk/varnish-cache/contrib/libevent/test/test.sh =================================================================== --- trunk/varnish-cache/contrib/libevent/test/test.sh 2006-04-03 11:05:53 UTC (rev 97) +++ trunk/varnish-cache/contrib/libevent/test/test.sh 2006-04-03 11:59:08 UTC (rev 98) @@ -1,17 +1,19 @@ #!/bin/sh setup () { - export EVENT_NOKQUEUE=yes - export EVENT_NODEVPOLL=yes - export EVENT_NOPOLL=yes - export EVENT_NOSELECT=yes - export EVENT_NOEPOLL=yes - export EVENT_NORTSIG=yes + EVENT_NOKQUEUE=yes; export EVENT_NOKQUEUE + EVENT_NODEVPOLL=yes; export EVENT_NODEVPOLL + EVENT_NOPOLL=yes; export EVENT_NOPOLL + EVENT_NOSELECT=yes; export EVENT_NOSELECT + EVENT_NOEPOLL=yes; export EVENT_NOEPOLL + EVENT_NORTSIG=yes; export EVENT_NORTSIG } test () { - if ! ./test-init 2>/dev/null ; + if ./test-init 2>/dev/null ; then + true + else echo Skipping test return fi @@ -51,31 +53,37 @@ # Need to do this by hand? setup unset EVENT_NOKQUEUE +export EVENT_NOKQUEUE echo "KQUEUE" test setup unset EVENT_NODEVPOLL +export EVENT_NODEVPOLL echo "DEVPOLL" test setup unset EVENT_NOPOLL +export EVENT_NOPOLL echo "POLL" test setup unset EVENT_NOSELECT +export EVENT_NOSELECT echo "SELECT" test setup unset EVENT_NORTSIG +export EVENT_NORTSIG echo "RTSIG" test setup unset EVENT_NOEPOLL +export EVENT_NOEPOLL echo "EPOLL" test From des at projects.linpro.no Mon Apr 3 12:05:44 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Mon, 3 Apr 2006 14:05:44 +0200 (CEST) Subject: r99 - in trunk/varnish-cache/contrib/libevent: sample test Message-ID: <20060403120544.448ED1ED646@projects.linpro.no> Author: des Date: 2006-04-03 14:05:44 +0200 (Mon, 03 Apr 2006) New Revision: 99 Removed: trunk/varnish-cache/contrib/libevent/sample/Makefile.in trunk/varnish-cache/contrib/libevent/test/Makefile.in Log: Remove generated files which were committed by mistake. Deleted: trunk/varnish-cache/contrib/libevent/sample/Makefile.in =================================================================== --- trunk/varnish-cache/contrib/libevent/sample/Makefile.in 2006-04-03 11:59:08 UTC (rev 98) +++ trunk/varnish-cache/contrib/libevent/sample/Makefile.in 2006-04-03 12:05:44 UTC (rev 99) @@ -1,430 +0,0 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - - at SET_MAKE@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -noinst_PROGRAMS = event-test$(EXEEXT) time-test$(EXEEXT) \ - signal-test$(EXEEXT) -subdir = sample -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -PROGRAMS = $(noinst_PROGRAMS) -event_test_SOURCES = event-test.c -event_test_OBJECTS = event-test.$(OBJEXT) -event_test_LDADD = $(LDADD) -event_test_DEPENDENCIES = ../libevent.la -signal_test_SOURCES = signal-test.c -signal_test_OBJECTS = signal-test.$(OBJEXT) -signal_test_LDADD = $(LDADD) -signal_test_DEPENDENCIES = ../libevent.la -time_test_SOURCES = time-test.c -time_test_OBJECTS = time-test.$(OBJEXT) -time_test_LDADD = $(LDADD) -time_test_DEPENDENCIES = ../libevent.la -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -depcomp = -am__depfiles_maybe = -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = event-test.c signal-test.c time-test.c -DIST_SOURCES = event-test.c signal-test.c time-test.c -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = -I../compat -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBTOOL_DEPS = @LIBTOOL_DEPS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ -MAKEINFO = @MAKEINFO@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -AUTOMAKE_OPTIONS = foreign no-dependencies -LDADD = ../libevent.la -CPPFPLAGS = -I.. -event_test_sources = event-test.c -time_test_sources = time-test.c -signal_test_sources = signal-test.c -DISTCLEANFILES = *~ -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sample/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign sample/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; for p in $$list; do \ - f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f $$p $$f"; \ - rm -f $$p $$f ; \ - done -event-test$(EXEEXT): $(event_test_OBJECTS) $(event_test_DEPENDENCIES) - @rm -f event-test$(EXEEXT) - $(LINK) $(event_test_LDFLAGS) $(event_test_OBJECTS) $(event_test_LDADD) $(LIBS) -signal-test$(EXEEXT): $(signal_test_OBJECTS) $(signal_test_DEPENDENCIES) - @rm -f signal-test$(EXEEXT) - $(LINK) $(signal_test_LDFLAGS) $(signal_test_OBJECTS) $(signal_test_LDADD) $(LIBS) -time-test$(EXEEXT): $(time_test_OBJECTS) $(time_test_DEPENDENCIES) - @rm -f time-test$(EXEEXT) - $(LINK) $(time_test_LDFLAGS) $(time_test_OBJECTS) $(time_test_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -.c.o: - $(COMPILE) -c $< - -.c.obj: - $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: - $(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-info-am - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstPROGRAMS ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-exec \ - install-exec-am install-info install-info-am install-man \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ - uninstall-info-am - - -verify: -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: Deleted: trunk/varnish-cache/contrib/libevent/test/Makefile.in =================================================================== --- trunk/varnish-cache/contrib/libevent/test/Makefile.in 2006-04-03 11:59:08 UTC (rev 98) +++ trunk/varnish-cache/contrib/libevent/test/Makefile.in 2006-04-03 12:05:44 UTC (rev 99) @@ -1,462 +0,0 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - - at SET_MAKE@ - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -noinst_PROGRAMS = test-init$(EXEEXT) test-eof$(EXEEXT) \ - test-weof$(EXEEXT) test-time$(EXEEXT) regress$(EXEEXT) \ - bench$(EXEEXT) -subdir = test -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -PROGRAMS = $(noinst_PROGRAMS) -bench_SOURCES = bench.c -bench_OBJECTS = bench.$(OBJEXT) -bench_LDADD = $(LDADD) -bench_DEPENDENCIES = ../libevent.la -regress_SOURCES = regress.c -regress_OBJECTS = regress.$(OBJEXT) -regress_LDADD = $(LDADD) -regress_DEPENDENCIES = ../libevent.la -test_eof_SOURCES = test-eof.c -test_eof_OBJECTS = test-eof.$(OBJEXT) -test_eof_LDADD = $(LDADD) -test_eof_DEPENDENCIES = ../libevent.la -test_init_SOURCES = test-init.c -test_init_OBJECTS = test-init.$(OBJEXT) -test_init_LDADD = $(LDADD) -test_init_DEPENDENCIES = ../libevent.la -test_time_SOURCES = test-time.c -test_time_OBJECTS = test-time.$(OBJEXT) -test_time_LDADD = $(LDADD) -test_time_DEPENDENCIES = ../libevent.la -test_weof_SOURCES = test-weof.c -test_weof_OBJECTS = test-weof.$(OBJEXT) -test_weof_LDADD = $(LDADD) -test_weof_DEPENDENCIES = ../libevent.la -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -depcomp = -am__depfiles_maybe = -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = bench.c regress.c test-eof.c test-init.c test-time.c \ - test-weof.c -DIST_SOURCES = bench.c regress.c test-eof.c test-init.c test-time.c \ - test-weof.c -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = -I../compat @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIBTOOL_DEPS = @LIBTOOL_DEPS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ -MAKEINFO = @MAKEINFO@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -AUTOMAKE_OPTIONS = foreign no-dependencies -LDADD = ../libevent.la -CPPFPLAGS = -I.. -test_init_sources = test-init.c -test_eof_sources = test-eof.c -test_weof_sources = test-weof.c -test_time_sources = test-time.c -regress_sources = regress.c -bench_sources = bench.c -DISTCLEANFILES = *~ -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign test/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -clean-noinstPROGRAMS: - @list='$(noinst_PROGRAMS)'; for p in $$list; do \ - f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f $$p $$f"; \ - rm -f $$p $$f ; \ - done -bench$(EXEEXT): $(bench_OBJECTS) $(bench_DEPENDENCIES) - @rm -f bench$(EXEEXT) - $(LINK) $(bench_LDFLAGS) $(bench_OBJECTS) $(bench_LDADD) $(LIBS) -regress$(EXEEXT): $(regress_OBJECTS) $(regress_DEPENDENCIES) - @rm -f regress$(EXEEXT) - $(LINK) $(regress_LDFLAGS) $(regress_OBJECTS) $(regress_LDADD) $(LIBS) -test-eof$(EXEEXT): $(test_eof_OBJECTS) $(test_eof_DEPENDENCIES) - @rm -f test-eof$(EXEEXT) - $(LINK) $(test_eof_LDFLAGS) $(test_eof_OBJECTS) $(test_eof_LDADD) $(LIBS) -test-init$(EXEEXT): $(test_init_OBJECTS) $(test_init_DEPENDENCIES) - @rm -f test-init$(EXEEXT) - $(LINK) $(test_init_LDFLAGS) $(test_init_OBJECTS) $(test_init_LDADD) $(LIBS) -test-time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES) - @rm -f test-time$(EXEEXT) - $(LINK) $(test_time_LDFLAGS) $(test_time_OBJECTS) $(test_time_LDADD) $(LIBS) -test-weof$(EXEEXT): $(test_weof_OBJECTS) $(test_weof_DEPENDENCIES) - @rm -f test-weof$(EXEEXT) - $(LINK) $(test_weof_LDFLAGS) $(test_weof_OBJECTS) $(test_weof_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -.c.o: - $(COMPILE) -c $< - -.c.obj: - $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: - $(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-info-am - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstPROGRAMS ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-exec \ - install-exec-am install-info install-info-am install-man \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ - uninstall-info-am - - -test: test-init test-eof test-weof test-time regress - -verify: test - @./test.sh - -bench test-init test-eof test-weof test-time regress: ../libevent.la -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: From des at projects.linpro.no Mon Apr 3 14:04:16 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Mon, 3 Apr 2006 16:04:16 +0200 (CEST) Subject: r100 - trunk/varnish-cache/contrib/libevent/WIN32-Code Message-ID: <20060403140416.51C741ED64B@projects.linpro.no> Author: des Date: 2006-04-03 16:04:16 +0200 (Mon, 03 Apr 2006) New Revision: 100 Removed: trunk/varnish-cache/contrib/libevent/WIN32-Code/provos at badschwartau.provos.org.12766 Log: GC Deleted: trunk/varnish-cache/contrib/libevent/WIN32-Code/provos at badschwartau.provos.org.12766 =================================================================== --- trunk/varnish-cache/contrib/libevent/WIN32-Code/provos at badschwartau.provos.org.12766 2006-04-03 12:05:44 UTC (rev 99) +++ trunk/varnish-cache/contrib/libevent/WIN32-Code/provos at badschwartau.provos.org.12766 2006-04-03 14:04:16 UTC (rev 100) @@ -1 +0,0 @@ -link provos at badschwartau.provos.org.12766 \ No newline at end of file From des at projects.linpro.no Mon Apr 3 14:20:41 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Mon, 3 Apr 2006 16:20:41 +0200 (CEST) Subject: r101 - in trunk/varnish-cache: . contrib Message-ID: <20060403142041.93BE01ED649@projects.linpro.no> Author: des Date: 2006-04-03 16:20:41 +0200 (Mon, 03 Apr 2006) New Revision: 101 Added: trunk/varnish-cache/contrib/Makefile.am Modified: trunk/varnish-cache/Makefile.am trunk/varnish-cache/autogen.sh trunk/varnish-cache/configure.ac Log: Hook up libevent to the build. Note that this should be made conditional at some later date. Modified: trunk/varnish-cache/Makefile.am =================================================================== --- trunk/varnish-cache/Makefile.am 2006-04-03 14:04:16 UTC (rev 100) +++ trunk/varnish-cache/Makefile.am 2006-04-03 14:20:41 UTC (rev 101) @@ -1,3 +1,3 @@ # $Id$ -SUBDIRS = include lib bin +SUBDIRS = contrib include lib bin Modified: trunk/varnish-cache/autogen.sh =================================================================== --- trunk/varnish-cache/autogen.sh 2006-04-03 14:04:16 UTC (rev 100) +++ trunk/varnish-cache/autogen.sh 2006-04-03 14:20:41 UTC (rev 101) @@ -8,8 +8,13 @@ export PATH fi -aclocal -libtoolize --copy --force -autoheader -automake --add-missing --copy --force --foreign -autoconf +base=$(cd $(dirname $0) && pwd) +for dir in $base $base/contrib/libevent ; do + echo $dir + cd $dir + aclocal + libtoolize --copy --force + autoheader + automake --add-missing --copy --force --foreign + autoconf +done Modified: trunk/varnish-cache/configure.ac =================================================================== --- trunk/varnish-cache/configure.ac 2006-04-03 14:04:16 UTC (rev 100) +++ trunk/varnish-cache/configure.ac 2006-04-03 14:20:41 UTC (rev 101) @@ -63,14 +63,16 @@ AC_CONFIG_FILES([ Makefile + bin/Makefile + bin/varnishd/Makefile + bin/varnishlog/Makefile + contrib/Makefile include/Makefile lib/Makefile lib/libsbuf/Makefile lib/libvarnish/Makefile lib/libvarnishapi/Makefile lib/libvcl/Makefile - bin/Makefile - bin/varnishd/Makefile - bin/varnishlog/Makefile ]) +AC_CONFIG_SUBDIRS(contrib/libevent) AC_OUTPUT Added: trunk/varnish-cache/contrib/Makefile.am =================================================================== --- trunk/varnish-cache/contrib/Makefile.am 2006-04-03 14:04:16 UTC (rev 100) +++ trunk/varnish-cache/contrib/Makefile.am 2006-04-03 14:20:41 UTC (rev 101) @@ -0,0 +1,3 @@ +# $Id$ + +SUBDIRS = libevent From phk at projects.linpro.no Mon Apr 3 14:41:51 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 3 Apr 2006 16:41:51 +0200 (CEST) Subject: r102 - trunk/varnish-cache/bin/varnishd Message-ID: <20060403144151.5F8721ED648@projects.linpro.no> Author: phk Date: 2006-04-03 16:41:51 +0200 (Mon, 03 Apr 2006) New Revision: 102 Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c Log: Move memset further up. Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 14:20:41 UTC (rev 101) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-03 14:41:51 UTC (rev 102) @@ -21,6 +21,8 @@ sp->handling = HND_Unclass; + memset(&sp->http, 0, sizeof sp->http); + /* First, isolate and possibly identify request type */ sp->http.req = sp->rcv; for (p = sp->rcv; isalpha(*p); p++) @@ -55,8 +57,6 @@ if (*p == '\r') p++; - memset(&sp->http, 0, sizeof sp->http); - for (; p < sp->rcv + sp->rcv_len; p = r) { q = strchr(p, '\n'); r = q + 1; From des at projects.linpro.no Tue Apr 4 07:24:07 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Tue, 4 Apr 2006 09:24:07 +0200 (CEST) Subject: r103 - in trunk/varnish-cache: bin/varnishd include lib/libvarnish lib/libvcl Message-ID: <20060404072407.8C1F61ED610@projects.linpro.no> Author: des Date: 2006-04-04 09:24:07 +0200 (Tue, 04 Apr 2006) New Revision: 103 Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c trunk/varnish-cache/include/cli_priv.h trunk/varnish-cache/include/libvarnish.h trunk/varnish-cache/lib/libvarnish/argv.c trunk/varnish-cache/lib/libvarnish/cli.c trunk/varnish-cache/lib/libvcl/vcl_compile.c Log: Portability tweaks: use our own sbuf.h and queue.h; get rid of __DECONST; get rid of digittoint() (which is pointless since ISO C guarantees that digits are consecutive in the execution character set); get rid of __unused. Also fix a buglet in argv.c's BackSlash() (parsing of octal numbers), and constify the array passed around by ParseArgv() and FreeArgv(). Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-03 14:41:51 UTC (rev 102) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-04 07:24:07 UTC (rev 103) @@ -69,7 +69,7 @@ } static void -accept_f(int fd, short event, void *arg __unused) +accept_f(int fd, short event, void *arg) { socklen_t l; struct sessmem *sm; @@ -77,6 +77,7 @@ struct sess *sp; char port[10]; + (void)arg; sm = calloc(sizeof *sm, 1); assert(sm != NULL); /* * XXX: this is probably one we should handle Modified: trunk/varnish-cache/include/cli_priv.h =================================================================== --- trunk/varnish-cache/include/cli_priv.h 2006-04-03 14:41:51 UTC (rev 102) +++ trunk/varnish-cache/include/cli_priv.h 2006-04-04 07:24:07 UTC (rev 103) @@ -11,7 +11,7 @@ struct cli; /* NB: struct cli is opaque at this level. */ -typedef void cli_func_t(struct cli*, char **av, void *priv); +typedef void cli_func_t(struct cli*, const char **av, void *priv); struct cli_proto { /* These must match the CLI_* macros in cli.h */ Modified: trunk/varnish-cache/include/libvarnish.h =================================================================== --- trunk/varnish-cache/include/libvarnish.h 2006-04-03 14:41:51 UTC (rev 102) +++ trunk/varnish-cache/include/libvarnish.h 2006-04-04 07:24:07 UTC (rev 103) @@ -3,10 +3,9 @@ */ /* from libvarnish/argv.c */ -void FreeArgv(char **argv); -char **ParseArgv(const char *s, int comment); +void FreeArgv(const char **argv); +const char **ParseArgv(const char *s, int comment); /* Assert zero return value */ #define AZ(foo) do { assert((foo) == 0); } while (0) - Modified: trunk/varnish-cache/lib/libvarnish/argv.c =================================================================== --- trunk/varnish-cache/lib/libvarnish/argv.c 2006-04-03 14:41:51 UTC (rev 102) +++ trunk/varnish-cache/lib/libvarnish/argv.c 2006-04-04 07:24:07 UTC (rev 103) @@ -1,12 +1,12 @@ /* * $Id$ * - * char **ParseArgv(const char *s, int comment) + * const char **ParseArgv(const char *s, int comment) * Parse a command like line into an argv[] * Index zero contains NULL or an error message * "double quotes" and backslash substitution is handled. * - * void FreeArgv(char **argv) + * void FreeArgv(const char **argv) * Free the result of ParseArgv() * */ @@ -48,15 +48,15 @@ i = '\\'; r = 2; break; - case '0': case '1': case '2': case 3: - case '4': case '5': case '6': case 7: + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': for (r = 1; r < 4; r++) { if (!isdigit(s[r])) break; - if (digittoint(s[r]) > 7) + if (s[r] - '0' > 7) break; i <<= 3; - i |= digittoint(s[r]); + i |= s[r] - '0'; } break; case 'x': @@ -96,10 +96,10 @@ return (p); } -char ** +const char ** ParseArgv(const char *s, int comment) { - char **argv; + const char **argv; const char *p; int nargv, largv; int i, quote; @@ -131,8 +131,7 @@ if (*s == '\\') { i = BackSlash(s, NULL); if (i == 0) { - argv[0] = __DECONST(void *, - "Illegal backslash sequence"); + argv[0] = "Illegal backslash sequence"; return (argv); } s += i; @@ -147,8 +146,7 @@ if (*s == '"') break; if (*s == '\0') { - argv[0] = __DECONST(void *, - "Missing '\"'"); + argv[0] = "Missing '\"'"; return (argv); } s++; @@ -166,12 +164,12 @@ } void -FreeArgv(char **argv) +FreeArgv(const char **argv) { int i; for (i = 1; argv[i] != NULL; i++) - free(argv[i]); + free((void *)(uintptr_t)argv[i]); free(argv); } Modified: trunk/varnish-cache/lib/libvarnish/cli.c =================================================================== --- trunk/varnish-cache/lib/libvarnish/cli.c 2006-04-03 14:41:51 UTC (rev 102) +++ trunk/varnish-cache/lib/libvarnish/cli.c 2006-04-04 07:24:07 UTC (rev 103) @@ -19,7 +19,7 @@ */ void -cli_func_help(struct cli *cli, char **av, void *priv) +cli_func_help(struct cli *cli, const char **av, void *priv) { struct cli_proto *cp; @@ -41,7 +41,7 @@ void cli_dispatch(struct cli *cli, struct cli_proto *clp, const char *line) { - char **av; + const char **av; unsigned u; struct cli_proto *cp; Modified: trunk/varnish-cache/lib/libvcl/vcl_compile.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-04-03 14:41:51 UTC (rev 102) +++ trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-04-04 07:24:07 UTC (rev 103) @@ -33,22 +33,22 @@ * and all the rest... */ +#include +#include +#include + #include -#include #include -#include +#include #include -#include +#include +#include #include #include -#include -#include -#include +#include +#include +#include -#include -#include -#include - #include "vcl_priv.h" #include "libvcl.h" @@ -316,15 +316,15 @@ case 'b': *q++ = '\b'; r += 2; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': - u = digittoint(r[1]); + u = r[1] - '0'; r += 2; - if (isdigit(r[0]) && digittoint(r[0]) < 8) { + if (isdigit(r[0]) && (r[0] - '0') < 8) { u <<= 3; - u |= digittoint(r[0]); + u |= r[0] - '0'; r++; - if (isdigit(r[0]) && digittoint(r[0]) < 8) { + if (isdigit(r[0]) && (r[0] - '0') < 8) { u <<= 3; - u |= digittoint(r[0]); + u |= r[0] - '0'; r++; } } @@ -471,7 +471,7 @@ Expect(tl, CNUM); for (p = tl->t->b; p < tl->t->e; p++) { d *= 10; - d += digittoint(*p); + d += *p - '0'; } NextToken(tl); return (d); @@ -490,7 +490,7 @@ Expect(tl, CNUM); for (p = tl->t->b; p < tl->t->e; p++) { d *= 10; - d += digittoint(*p); + d += *p - '0'; } NextToken(tl); if (tl->t->tok != '.') @@ -499,7 +499,7 @@ if (tl->t->tok != CNUM) return (d); for (p = tl->t->b; p < tl->t->e; p++) { - d += digittoint(*p) * e; + d += (*p - '0') * e; e *= 0.1; } NextToken(tl); @@ -645,9 +645,10 @@ } static void -Cond_String(struct var *vp __unused, struct tokenlist *tl) +Cond_String(struct var *vp, struct tokenlist *tl) { + (void)vp; switch (tl->t->tok) { case '~': I(tl); sbuf_printf(tl->fc, "string_match(%s, ", vp->cname); From phk at projects.linpro.no Tue Apr 4 07:24:22 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:24:22 +0200 (CEST) Subject: r104 - trunk/varnish-cache/include Message-ID: <20060404072422.EFD731ED622@projects.linpro.no> Author: phk Date: 2006-04-04 09:24:22 +0200 (Tue, 04 Apr 2006) New Revision: 104 Modified: trunk/varnish-cache/include/shmlog_tags.h Log: Add a Debug shmemlog tag. Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-04 07:24:07 UTC (rev 103) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-04 07:24:22 UTC (rev 104) @@ -6,6 +6,7 @@ * */ +SLTM(Debug) SLTM(CLI) SLTM(SessionOpen) SLTM(SessionClose) From phk at projects.linpro.no Tue Apr 4 07:24:54 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:24:54 +0200 (CEST) Subject: r105 - trunk/varnish-cache/contrib/libevent Message-ID: <20060404072454.ACF0E1ED651@projects.linpro.no> Author: phk Date: 2006-04-04 09:24:54 +0200 (Tue, 04 Apr 2006) New Revision: 105 Modified: trunk/varnish-cache/contrib/libevent/event.h Log: Add a missing prototype until libevent people catch up. Modified: trunk/varnish-cache/contrib/libevent/event.h =================================================================== --- trunk/varnish-cache/contrib/libevent/event.h 2006-04-04 07:24:22 UTC (rev 104) +++ trunk/varnish-cache/contrib/libevent/event.h 2006-04-04 07:24:54 UTC (rev 105) @@ -260,6 +260,7 @@ struct bufferevent *bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); int bufferevent_priority_set(struct bufferevent *bufev, int pri); +int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); void bufferevent_free(struct bufferevent *bufev); int bufferevent_write(struct bufferevent *bufev, void *data, size_t size); int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); From phk at projects.linpro.no Tue Apr 4 07:26:27 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:26:27 +0200 (CEST) Subject: r106 - trunk/varnish-cache/bin/varnishd Message-ID: <20060404072627.0F6041ED657@projects.linpro.no> Author: phk Date: 2006-04-04 09:26:26 +0200 (Tue, 04 Apr 2006) New Revision: 106 Modified: trunk/varnish-cache/bin/varnishd/cli_event.c Log: Use bufferevent_base_set() from libevent Modified: trunk/varnish-cache/bin/varnishd/cli_event.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cli_event.c 2006-04-04 07:24:54 UTC (rev 105) +++ trunk/varnish-cache/bin/varnishd/cli_event.c 2006-04-04 07:26:26 UTC (rev 106) @@ -123,23 +123,6 @@ printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg); } -/* - * XXX: included in libevent in CVS - */ - -static int -bufferevent_base_set(struct event_base *base, struct bufferevent *bufev) -{ - int res; - - res = event_base_set(base, &bufev->ev_read); - if (res == -1) - return (res); - - res = event_base_set(base, &bufev->ev_write); - return (res); -} - struct cli * cli_setup(struct event_base *eb, int fdr, int fdw, int ver, struct cli_proto *cli_proto) { From phk at projects.linpro.no Tue Apr 4 07:27:06 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:27:06 +0200 (CEST) Subject: r107 - trunk/varnish-cache/include Message-ID: <20060404072706.D0B5A1ED658@projects.linpro.no> Author: phk Date: 2006-04-04 09:27:06 +0200 (Tue, 04 Apr 2006) New Revision: 107 Modified: trunk/varnish-cache/include/vcl_lang.h Log: Add a session callback pointer to struct sess. Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-04 07:26:26 UTC (rev 106) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-04 07:27:06 UTC (rev 107) @@ -8,6 +8,9 @@ /* XXX: This include is bad. The VCL compiler shouldn't know about it. */ #include +struct sess; +typedef void sesscb_f(struct sess *sp); + struct vcl_ref { unsigned line; unsigned pos; @@ -59,6 +62,8 @@ TAILQ_ENTRY(sess) list; + sesscb_f *sesscb; + struct backend *backend; struct VCL_conf *vcl; From phk at projects.linpro.no Tue Apr 4 07:29:45 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:29:45 +0200 (CEST) Subject: r108 - trunk/varnish-cache/bin/varnishd Message-ID: <20060404072945.453AF1ED657@projects.linpro.no> Author: phk Date: 2006-04-04 09:29:45 +0200 (Tue, 04 Apr 2006) New Revision: 108 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_acceptor.c trunk/varnish-cache/bin/varnishd/cache_httpd.c Log: Make the "receive a HTTP protocol header" code generic Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 07:27:06 UTC (rev 107) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 07:29:45 UTC (rev 108) @@ -2,6 +2,8 @@ * $Id$ */ +struct event_base; + /* cache_acceptor.c */ void *vca_main(void *arg); void vca_retire_session(struct sess *sp); @@ -14,10 +16,14 @@ /* cache_httpd.c */ void HttpdAnalyze(struct sess *sp); +void HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func); /* cache_main.c */ pthread_mutex_t sessmtx; +/* cache_pass.c */ +void PassSession(struct sess *sp); + /* cache_pipe.c */ void PipeSession(struct sess *sp); @@ -30,6 +36,7 @@ #ifdef SHMLOGHEAD_MAGIC 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, "%s(%d)", __func__, __LINE__) #endif /* cache_vcl.c */ Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-04 07:27:06 UTC (rev 107) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-04 07:29:45 UTC (rev 108) @@ -32,43 +32,6 @@ }; static void -http_read_f(int fd, short event, void *arg) -{ - struct sess *sp = arg; - const char *p; - int i; - - assert(VCA_RXBUFSIZE - sp->rcv_len > 0); - i = read(fd, sp->rcv + sp->rcv_len, VCA_RXBUFSIZE - sp->rcv_len); - if (i <= 0) { - VSL(SLT_SessionClose, sp->fd, "remote %d", sp->rcv_len); - event_del(sp->rd_e); - close(sp->fd); - free(sp->mem); - return; - } - - sp->rcv_len += i; - sp->rcv[sp->rcv_len] = '\0'; - - p = sp->rcv; - while (1) { - /* XXX: we could save location of all linebreaks for later */ - p = strchr(p, '\n'); - if (p == NULL) - return; - p++; - if (*p == '\r') - p++; - if (*p != '\n') - continue; - break; - } - event_del(sp->rd_e); - DealWithSession(sp); -} - -static void accept_f(int fd, short event, void *arg) { socklen_t l; @@ -100,10 +63,7 @@ strlcat(sp->addr, ":", VCA_ADDRBUFSIZE); strlcat(sp->addr, port, VCA_ADDRBUFSIZE); VSL(SLT_SessionOpen, sp->fd, "%s", sp->addr); - event_set(sp->rd_e, sp->fd, EV_READ | EV_PERSIST, - http_read_f, sp); - event_base_set(evb, sp->rd_e); - event_add(sp->rd_e, NULL); /* XXX: timeout */ + HttpdGetHead(sp, evb, DealWithSession); } void * Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 07:27:06 UTC (rev 107) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 07:29:45 UTC (rev 108) @@ -5,15 +5,21 @@ */ #include +#include +#include +#include #include #include #include +#include #include "libvarnish.h" #include "shmlog.h" #include "vcl_lang.h" #include "cache.h" +/*--------------------------------------------------------------------*/ + void HttpdAnalyze(struct sess *sp) { @@ -87,3 +93,55 @@ } } } + +/*--------------------------------------------------------------------*/ + +static void +http_read_f(int fd, short event, void *arg) +{ + struct sess *sp = arg; + const char *p; + int i; + + assert(VCA_RXBUFSIZE - sp->rcv_len > 0); + i = read(fd, sp->rcv + sp->rcv_len, VCA_RXBUFSIZE - sp->rcv_len); + if (i <= 0) { + VSL(SLT_SessionClose, sp->fd, "remote %d", sp->rcv_len); + event_del(sp->rd_e); + close(sp->fd); + free(sp->mem); + return; + } + + sp->rcv_len += i; + sp->rcv[sp->rcv_len] = '\0'; + + p = sp->rcv; + while (1) { + /* XXX: we could save location of all linebreaks for later */ + p = strchr(p, '\n'); + if (p == NULL) + return; + p++; + if (*p == '\r') + p++; + if (*p != '\n') + continue; + break; + } + event_del(sp->rd_e); + sp->sesscb(sp); +} + +/*--------------------------------------------------------------------*/ + +void +HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func) +{ + + sp->sesscb = func; + assert(sp->rd_e != NULL); + event_set(sp->rd_e, sp->fd, EV_READ | EV_PERSIST, http_read_f, sp); + event_base_set(eb, sp->rd_e); + event_add(sp->rd_e, NULL); /* XXX: timeout */ +} From phk at projects.linpro.no Tue Apr 4 07:30:32 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:30:32 +0200 (CEST) Subject: r109 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060404073032.CD6021ED659@projects.linpro.no> Author: phk Date: 2006-04-04 09:30:32 +0200 (Tue, 04 Apr 2006) New Revision: 109 Added: trunk/varnish-cache/bin/varnishd/cache_pass.c Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache_backend.c trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Get "Pass" mode moving Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-04 07:29:45 UTC (rev 108) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-04 07:30:32 UTC (rev 109) @@ -10,6 +10,7 @@ cache_httpd.c \ cache_main.c \ cache_pool.c \ + cache_pass.c \ cache_pipe.c \ cache_shmlog.c \ cache_vcl.c \ Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-04 07:29:45 UTC (rev 108) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-04 07:30:32 UTC (rev 109) @@ -139,54 +139,7 @@ free(vc); } -/*--------------------------------------------------------------------*/ -void -VBE_Pass(struct sess *sp) -{ - int fd, i; - void *fd_token; - struct sbuf *sb; - fd = VBE_GetFd(sp->backend, &fd_token); - assert(fd != -1); - - sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); - assert(sb != NULL); - sbuf_cat(sb, sp->http.req); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.url); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.proto); - sbuf_cat(sb, "\r\n"); -#define HTTPH(a, b, c, d, e, f, g) \ - do { \ - if (c && sp->http.b != NULL) { \ - sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp->http.b); \ - sbuf_cat(sb, "\r\n"); \ - } \ - } while (0); -#include "http_headers.h" -#undef HTTPH - sbuf_cat(sb, "\r\n"); - sbuf_finish(sb); - printf("REQ: <%s>\n", sbuf_data(sb)); - i = write(fd, sbuf_data(sb), sbuf_len(sb)); - assert(i == sbuf_len(sb)); - { - char buf[101]; - - for(;;) { - i = read(fd, buf, 100); - if (i > 0) { - buf[i] = '\0'; - printf("RESP: <%s>\n", buf); - } - } - - } -} - /*--------------------------------------------------------------------*/ void Added: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 07:29:45 UTC (rev 108) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 07:30:32 UTC (rev 109) @@ -0,0 +1,76 @@ +/* + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libvarnish.h" +#include "shmlog.h" +#include "vcl_lang.h" +#include "cache.h" + +static void +PassReturn(struct sess *sp) +{ + + HERE(); + HttpdAnalyze(sp); +} + +/*--------------------------------------------------------------------*/ +void +PassSession(struct sess *sp) +{ + int fd, i; + void *fd_token; + struct sbuf *sb; + struct event_base *eb; + struct sess sp2; + struct event ev; + + fd = VBE_GetFd(sp->backend, &fd_token); + assert(fd != -1); + + sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + assert(sb != NULL); + sbuf_cat(sb, sp->http.req); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->http.url); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->http.proto); + sbuf_cat(sb, "\r\n"); +#define HTTPH(a, b, c, d, e, f, g) \ + do { \ + if (c && sp->http.b != NULL) { \ + sbuf_cat(sb, a ": "); \ + sbuf_cat(sb, sp->http.b); \ + sbuf_cat(sb, "\r\n"); \ + } \ + } while (0); +#include "http_headers.h" +#undef HTTPH + sbuf_cat(sb, "\r\n"); + sbuf_finish(sb); + printf("REQ: <%s>\n", sbuf_data(sb)); + i = write(fd, sbuf_data(sb), sbuf_len(sb)); + assert(i == sbuf_len(sb)); + + memset(&sp2, 0, sizeof sp2); + memset(&ev, 0, sizeof ev); + sp2.rd_e = &ev; + sp2.fd = fd; + eb = event_init(); + HttpdGetHead(&sp2, eb, PassReturn); + event_base_loop(eb, 0); +} Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 07:29:45 UTC (rev 108) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 07:30:32 UTC (rev 109) @@ -39,7 +39,11 @@ printf("Handling: %d\n", sp->handling); - PipeSession(sp); + if (0) { + PipeSession(sp); + } else { + PassSession(sp); + } AZ(pthread_mutex_lock(&sessmtx)); RelVCL(sp->vcl); Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-04 07:29:45 UTC (rev 108) +++ trunk/varnish-cache/include/http_headers.h 2006-04-04 07:30:32 UTC (rev 109) @@ -12,24 +12,24 @@ * a b c d e f g *-------------------------------------------------------------------- */ -HTTPH("Accept-Charset", H_Accept_Charset, 0, 0, 0, 0, 0) -HTTPH("Accept-Encoding", H_Accept_Encoding, 0, 0, 0, 0, 0) -HTTPH("Accept-Language", H_Accept_Language, 0, 0, 0, 0, 0) -HTTPH("Accept", H_Accept, 0, 0, 0, 0, 0) -HTTPH("Authorization", H_Authorization, 0, 0, 0, 0, 0) -HTTPH("Connection", H_Connection, 1, 0, 0, 0, 0) -HTTPH("Expect", H_Expect, 0, 0, 0, 0, 0) -HTTPH("From", H_From, 0, 0, 0, 0, 0) +HTTPH("Accept-Charset", H_Accept_Charset, 1, 0, 0, 0, 0) +HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 0, 0, 0, 0) +HTTPH("Accept-Language", H_Accept_Language, 1, 0, 0, 0, 0) +HTTPH("Accept", H_Accept, 1, 0, 0, 0, 0) +HTTPH("Authorization", H_Authorization, 1, 0, 0, 0, 0) +HTTPH("Connection", H_Connection, 0, 0, 0, 0, 0) +HTTPH("Expect", H_Expect, 1, 0, 0, 0, 0) +HTTPH("From", H_From, 1, 0, 0, 0, 0) HTTPH("Host", H_Host, 1, 0, 0, 0, 0) -HTTPH("If-Match", H_If_Match, 0, 0, 0, 0, 0) -HTTPH("If-Modified-Since", H_If_Modified_Since, 0, 0, 0, 0, 0) -HTTPH("If-None-Match", H_If_None_Match, 0, 0, 0, 0, 0) -HTTPH("If-Range", H_If_Range, 0, 0, 0, 0, 0) -HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 0, 0, 0, 0, 0) +HTTPH("If-Match", H_If_Match, 1, 0, 0, 0, 0) +HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 0, 0, 0, 0) +HTTPH("If-None-Match", H_If_None_Match, 1, 0, 0, 0, 0) +HTTPH("If-Range", H_If_Range, 1, 0, 0, 0, 0) +HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 0, 0, 0, 0) HTTPH("Keep-Alive", H_Keep_Alive, 0, 0, 0, 0, 0) -HTTPH("Max-Forwards", H_Max_Forwards, 0, 0, 0, 0, 0) -HTTPH("Proxy-Authorization", H_Proxy_Authorization, 0, 0, 0, 0, 0) -HTTPH("Range", H_Range, 0, 0, 0, 0, 0) -HTTPH("Referer", H_Referer, 0, 0, 0, 0, 0) -HTTPH("TE", H_TE, 0, 0, 0, 0, 0) +HTTPH("Max-Forwards", H_Max_Forwards, 1, 0, 0, 0, 0) +HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 0, 0, 0, 0) +HTTPH("Range", H_Range, 1, 0, 0, 0, 0) +HTTPH("Referer", H_Referer, 1, 0, 0, 0, 0) +HTTPH("TE", H_TE, 1, 0, 0, 0, 0) HTTPH("User-Agent", H_User_Agent, 1, 0, 0, 0, 0) Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-04 07:29:45 UTC (rev 108) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-04 07:30:32 UTC (rev 109) @@ -389,6 +389,9 @@ fputs("/* XXX: This include is bad. The VCL compiler shouldn't know about it. */\n", f); fputs("#include \n", f); fputs("\n", f); + fputs("struct sess;\n", f); + fputs("typedef void sesscb_f(struct sess *sp);\n", f); + fputs("\n", f); fputs("struct vcl_ref {\n", f); fputs(" unsigned line;\n", f); fputs(" unsigned pos;\n", f); @@ -424,26 +427,26 @@ fputs(" * a b c d e f g \n", f); fputs(" *--------------------------------------------------------------------\n", f); fputs(" */\n", f); - fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept\", H_Accept, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Authorization\", H_Authorization, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Connection\", H_Connection, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Expect\", H_Expect, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"From\", H_From, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept\", H_Accept, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Authorization\", H_Authorization, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Connection\", H_Connection, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Expect\", H_Expect, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"From\", H_From, 1, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Host\", H_Host, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Match\", H_If_Match, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Range\", H_If_Range, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Match\", H_If_Match, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Range\", H_If_Range, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since, 1, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Range\", H_Range, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Referer\", H_Referer, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"TE\", H_TE, 0, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Range\", H_Range, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Referer\", H_Referer, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"TE\", H_TE, 1, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 0, 0, 0, 0)\n", f); fputs("#undef HTTPH\n", f); fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); @@ -474,6 +477,8 @@ fputs("\n", f); fputs(" TAILQ_ENTRY(sess) list;\n", f); fputs("\n", f); + fputs(" sesscb_f *sesscb;\n", f); + fputs("\n", f); fputs(" struct backend *backend;\n", f); fputs(" struct VCL_conf *vcl;\n", f); fputs("\n", f); From phk at projects.linpro.no Tue Apr 4 07:46:30 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 09:46:30 +0200 (CEST) Subject: r110 - in trunk/varnish-cache: include lib/libvarnish Message-ID: <20060404074630.6771C1ED659@projects.linpro.no> Author: phk Date: 2006-04-04 09:46:30 +0200 (Tue, 04 Apr 2006) New Revision: 110 Modified: trunk/varnish-cache/include/cli_priv.h trunk/varnish-cache/include/libvarnish.h trunk/varnish-cache/lib/libvarnish/argv.c trunk/varnish-cache/lib/libvarnish/cli.c Log: Reverse constification of Argv functions. After cascading through all the CLI functions we hit the fact that the evbuffer functions in libevent are not properly constified. It's better to deconst the error messages and just "let it be known" that argv[0] is const (or NULL). Modified: trunk/varnish-cache/include/cli_priv.h =================================================================== --- trunk/varnish-cache/include/cli_priv.h 2006-04-04 07:30:32 UTC (rev 109) +++ trunk/varnish-cache/include/cli_priv.h 2006-04-04 07:46:30 UTC (rev 110) @@ -11,7 +11,7 @@ struct cli; /* NB: struct cli is opaque at this level. */ -typedef void cli_func_t(struct cli*, const char **av, void *priv); +typedef void cli_func_t(struct cli*, char **av, void *priv); struct cli_proto { /* These must match the CLI_* macros in cli.h */ Modified: trunk/varnish-cache/include/libvarnish.h =================================================================== --- trunk/varnish-cache/include/libvarnish.h 2006-04-04 07:30:32 UTC (rev 109) +++ trunk/varnish-cache/include/libvarnish.h 2006-04-04 07:46:30 UTC (rev 110) @@ -3,8 +3,8 @@ */ /* from libvarnish/argv.c */ -void FreeArgv(const char **argv); -const char **ParseArgv(const char *s, int comment); +void FreeArgv(char **argv); +char **ParseArgv(const char *s, int comment); /* Assert zero return value */ Modified: trunk/varnish-cache/lib/libvarnish/argv.c =================================================================== --- trunk/varnish-cache/lib/libvarnish/argv.c 2006-04-04 07:30:32 UTC (rev 109) +++ trunk/varnish-cache/lib/libvarnish/argv.c 2006-04-04 07:46:30 UTC (rev 110) @@ -96,10 +96,10 @@ return (p); } -const char ** +char ** ParseArgv(const char *s, int comment) { - const char **argv; + char **argv; const char *p; int nargv, largv; int i, quote; @@ -131,7 +131,7 @@ if (*s == '\\') { i = BackSlash(s, NULL); if (i == 0) { - argv[0] = "Illegal backslash sequence"; + argv[0] = (void*)(uintptr_t)"Illegal backslash sequence"; return (argv); } s += i; @@ -146,7 +146,7 @@ if (*s == '"') break; if (*s == '\0') { - argv[0] = "Missing '\"'"; + argv[0] = (void*)(uintptr_t)"Missing '\"'"; return (argv); } s++; @@ -164,12 +164,12 @@ } void -FreeArgv(const char **argv) +FreeArgv(char **argv) { int i; for (i = 1; argv[i] != NULL; i++) - free((void *)(uintptr_t)argv[i]); + free(argv[i]); free(argv); } Modified: trunk/varnish-cache/lib/libvarnish/cli.c =================================================================== --- trunk/varnish-cache/lib/libvarnish/cli.c 2006-04-04 07:30:32 UTC (rev 109) +++ trunk/varnish-cache/lib/libvarnish/cli.c 2006-04-04 07:46:30 UTC (rev 110) @@ -19,7 +19,7 @@ */ void -cli_func_help(struct cli *cli, const char **av, void *priv) +cli_func_help(struct cli *cli, char **av, void *priv) { struct cli_proto *cp; @@ -41,7 +41,7 @@ void cli_dispatch(struct cli *cli, struct cli_proto *clp, const char *line) { - const char **av; + char **av; unsigned u; struct cli_proto *cp; From phk at projects.linpro.no Tue Apr 4 08:20:24 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 10:20:24 +0200 (CEST) Subject: r111 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060404082024.40B561ED65A@projects.linpro.no> Author: phk Date: 2006-04-04 10:20:24 +0200 (Tue, 04 Apr 2006) New Revision: 111 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pipe.c trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/include/shmlog_tags.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Add HTTP response headers and processing. Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 08:20:24 UTC (rev 111) @@ -15,7 +15,7 @@ void VBE_ClosedFd(void *ptr); /* cache_httpd.c */ -void HttpdAnalyze(struct sess *sp); +void HttpdAnalyze(struct sess *sp, int rr); void HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func); /* cache_main.c */ Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 08:20:24 UTC (rev 111) @@ -21,7 +21,7 @@ /*--------------------------------------------------------------------*/ void -HttpdAnalyze(struct sess *sp) +HttpdAnalyze(struct sess *sp, int rr) { char *p, *q, *r; @@ -29,37 +29,68 @@ memset(&sp->http, 0, sizeof sp->http); - /* First, isolate and possibly identify request type */ - sp->http.req = sp->rcv; - for (p = sp->rcv; isalpha(*p); p++) - ; - VSLR(SLT_Request, sp->fd, sp->http.req, p); - *p++ = '\0'; + if (rr == 1) { + /* First, isolate and possibly identify request type */ + sp->http.req = sp->rcv; + for (p = sp->rcv; isalpha(*p); p++) + ; + VSLR(SLT_Request, sp->fd, sp->http.req, p); + *p++ = '\0'; - /* Next find the URI */ - while (isspace(*p)) - p++; - sp->http.url = p; - while (!isspace(*p)) - p++; - VSLR(SLT_URL, sp->fd, sp->http.url, p); - *p++ = '\0'; + /* Next find the URI */ + while (isspace(*p)) + p++; + sp->http.url = p; + while (!isspace(*p)) + p++; + VSLR(SLT_URL, sp->fd, sp->http.url, p); + *p++ = '\0'; - /* Finally, look for protocol, if any */ - while (isspace(*p) && *p != '\n') + /* Finally, look for protocol, if any */ + while (isspace(*p) && *p != '\n') + p++; + sp->http.proto = p; + if (*p != '\n') { + while (!isspace(*p)) + p++; + } + VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); + *p++ = '\0'; + + while (isspace(*p) && *p != '\n') + p++; p++; - sp->http.proto = p; - if (*p != '\n') { + } else { + /* First, protocol */ + sp->http.proto = sp->rcv; + p = sp->rcv; while (!isspace(*p)) p++; - } - VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); - *p++ = '\0'; + *p++ = '\0'; + VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); - while (isspace(*p) && *p != '\n') + /* Next find the status */ + while (isspace(*p)) + p++; + sp->http.status = p; + while (!isspace(*p)) + p++; + VSLR(SLT_Status, sp->fd, sp->http.status, p); + *p++ = '\0'; + + /* Next find the response */ + while (isspace(*p)) + p++; + sp->http.response = p; + while (*p != '\n') + p++; + for (q = p; q > sp->http.response && isspace(q[-1]); q--) + continue; + *q = '\0'; + VSLR(SLT_Response, sp->fd, sp->http.response, q); p++; + } - p++; if (*p == '\r') p++; @@ -81,7 +112,10 @@ continue; \ } -#define HTTPH(a, b, c, d, e, f, g) W(a ":", b, p, q, sp) +#define HTTPH(a, b, c, d, e, f, g) \ + if (c & rr) { \ + W(a ":", b, p, q, sp); \ + } #include "http_headers.h" #undef HTTPH #undef W Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 08:20:24 UTC (rev 111) @@ -25,7 +25,7 @@ { HERE(); - HttpdAnalyze(sp); + HttpdAnalyze(sp, 2); } /*--------------------------------------------------------------------*/ @@ -52,7 +52,7 @@ sbuf_cat(sb, "\r\n"); #define HTTPH(a, b, c, d, e, f, g) \ do { \ - if (c && sp->http.b != NULL) { \ + if (d && sp->http.b != NULL) { \ sbuf_cat(sb, a ": "); \ sbuf_cat(sb, sp->http.b); \ sbuf_cat(sb, "\r\n"); \ @@ -62,7 +62,6 @@ #undef HTTPH sbuf_cat(sb, "\r\n"); sbuf_finish(sb); - printf("REQ: <%s>\n", sbuf_data(sb)); i = write(fd, sbuf_data(sb), sbuf_len(sb)); assert(i == sbuf_len(sb)); Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-04 08:20:24 UTC (rev 111) @@ -75,7 +75,6 @@ #undef HTTPH sbuf_cat(sb, "\r\n"); sbuf_finish(sb); - printf("REQ: <%s>\n", sbuf_data(sb)); i = write(fd, sbuf_data(sb), sbuf_len(sb)); assert(i == sbuf_len(sb)); Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 08:20:24 UTC (rev 111) @@ -31,7 +31,7 @@ sp->vcl = GetVCL(); AZ(pthread_mutex_unlock(&sessmtx)); - HttpdAnalyze(sp); + HttpdAnalyze(sp, 1); sp->backend = sp->vcl->default_backend; /* Call the VCL program */ Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/include/http_headers.h 2006-04-04 08:20:24 UTC (rev 111) @@ -3,8 +3,8 @@ * * a Http header name * b session field name - * c PassThrough handling (0=remove, 1=pass) - * d unused + * c Request(1)/Response(2) bitfield + * d Pass header * e unused * f unused * g unused @@ -12,24 +12,35 @@ * a b c d e f g *-------------------------------------------------------------------- */ -HTTPH("Accept-Charset", H_Accept_Charset, 1, 0, 0, 0, 0) -HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 0, 0, 0, 0) -HTTPH("Accept-Language", H_Accept_Language, 1, 0, 0, 0, 0) -HTTPH("Accept", H_Accept, 1, 0, 0, 0, 0) -HTTPH("Authorization", H_Authorization, 1, 0, 0, 0, 0) -HTTPH("Connection", H_Connection, 0, 0, 0, 0, 0) -HTTPH("Expect", H_Expect, 1, 0, 0, 0, 0) -HTTPH("From", H_From, 1, 0, 0, 0, 0) -HTTPH("Host", H_Host, 1, 0, 0, 0, 0) -HTTPH("If-Match", H_If_Match, 1, 0, 0, 0, 0) -HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 0, 0, 0, 0) -HTTPH("If-None-Match", H_If_None_Match, 1, 0, 0, 0, 0) -HTTPH("If-Range", H_If_Range, 1, 0, 0, 0, 0) -HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 0, 0, 0, 0) -HTTPH("Keep-Alive", H_Keep_Alive, 0, 0, 0, 0, 0) -HTTPH("Max-Forwards", H_Max_Forwards, 1, 0, 0, 0, 0) -HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 0, 0, 0, 0) -HTTPH("Range", H_Range, 1, 0, 0, 0, 0) -HTTPH("Referer", H_Referer, 1, 0, 0, 0, 0) -HTTPH("TE", H_TE, 1, 0, 0, 0, 0) -HTTPH("User-Agent", H_User_Agent, 1, 0, 0, 0, 0) +HTTPH("Connection", H_Connection, 3, 0, 0, 0, 0) +HTTPH("Keep-Alive", H_Keep_Alive, 3, 0, 0, 0, 0) + +HTTPH("Accept-Charset", H_Accept_Charset, 1, 1, 0, 0, 0) +HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 1, 0, 0, 0) +HTTPH("Accept-Language", H_Accept_Language, 1, 1, 0, 0, 0) +HTTPH("Accept", H_Accept, 1, 1, 0, 0, 0) +HTTPH("Authorization", H_Authorization, 1, 1, 0, 0, 0) +HTTPH("Expect", H_Expect, 1, 1, 0, 0, 0) +HTTPH("From", H_From, 1, 1, 0, 0, 0) +HTTPH("Host", H_Host, 1, 1, 0, 0, 0) +HTTPH("If-Match", H_If_Match, 1, 1, 0, 0, 0) +HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 1, 0, 0, 0) +HTTPH("If-None-Match", H_If_None_Match, 1, 1, 0, 0, 0) +HTTPH("If-Range", H_If_Range, 1, 1, 0, 0, 0) +HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 1, 0, 0, 0) +HTTPH("Max-Forwards", H_Max_Forwards, 1, 1, 0, 0, 0) +HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 1, 0, 0, 0) +HTTPH("Range", H_Range, 1, 1, 0, 0, 0) +HTTPH("Referer", H_Referer, 1, 1, 0, 0, 0) +HTTPH("TE", H_TE, 1, 1, 0, 0, 0) +HTTPH("User-Agent", H_User_Agent, 1, 1, 0, 0, 0) + +HTTPH("Server", H_Server, 2, 0, 0, 0, 0) +HTTPH("Content-Type", H_Content_Type, 2, 0, 0, 0, 0) +HTTPH("Date", H_Date, 2, 0, 0, 0, 0) +HTTPH("Last-Modified", H_Last_Modified, 2, 0, 0, 0, 0) +HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 0, 0, 0, 0) +HTTPH("Content-Length", H_Content_Length, 2, 0, 0, 0, 0) +HTTPH("Cache-Control", H_Cache_Control, 2, 0, 0, 0, 0) +HTTPH("Vary", H_Vary, 2, 0, 0, 0, 0) +HTTPH("Expires", H_Expires, 2, 0, 0, 0, 0) Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-04 08:20:24 UTC (rev 111) @@ -12,6 +12,8 @@ SLTM(SessionClose) SLTM(ClientAddr) SLTM(Request) +SLTM(Response) +SLTM(Status) SLTM(URL) SLTM(Protocol) SLTM(HD_Unknown) Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-04 08:20:24 UTC (rev 111) @@ -31,6 +31,8 @@ const char *req; const char *url; const char *proto; + const char *status; + const char *response; #define HTTPH(a, b, c, d, e, f, g) const char *b; #include #undef HTTPH Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-04 07:46:30 UTC (rev 110) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-04 08:20:24 UTC (rev 111) @@ -412,14 +412,16 @@ fputs(" const char *req;\n", f); fputs(" const char *url;\n", f); fputs(" const char *proto;\n", f); + fputs(" const char *status;\n", f); + fputs(" const char *response;\n", f); fputs("#define HTTPH(a, b, c, d, e, f, g) const char *b;\n", f); fputs("/*\n", f); fputs(" * $Id$\n", f); fputs(" *\n", f); fputs(" * a Http header name\n", f); fputs(" * b session field name\n", f); - fputs(" * c PassThrough handling (0=remove, 1=pass)\n", f); - fputs(" * d unused\n", f); + fputs(" * c Request(1)/Response(2) bitfield\n", f); + fputs(" * d Pass header\n", f); fputs(" * e unused\n", f); fputs(" * f unused\n", f); fputs(" * g unused\n", f); @@ -427,27 +429,38 @@ fputs(" * a b c d e f g \n", f); fputs(" *--------------------------------------------------------------------\n", f); fputs(" */\n", f); - fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept\", H_Accept, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Authorization\", H_Authorization, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Connection\", H_Connection, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Expect\", H_Expect, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"From\", H_From, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Host\", H_Host, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Match\", H_If_Match, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Range\", H_If_Range, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive, 0, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Range\", H_Range, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Referer\", H_Referer, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"TE\", H_TE, 1, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Connection\", H_Connection, 3, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive, 3, 0, 0, 0, 0)\n", f); + fputs("\n", f); + fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept\", H_Accept, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Authorization\", H_Authorization, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Expect\", H_Expect, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"From\", H_From, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Host\", H_Host, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Match\", H_If_Match, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Range\", H_If_Range, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Range\", H_Range, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Referer\", H_Referer, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"TE\", H_TE, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 1, 0, 0, 0)\n", f); + fputs("\n", f); + fputs("HTTPH(\"Server\", H_Server, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Content-Type\", H_Content_Type, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Date\", H_Date, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Last-Modified\", H_Last_Modified, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Ranges\", H_Accept_Ranges, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Content-Length\", H_Content_Length, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Cache-Control\", H_Cache_Control, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Vary\", H_Vary, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Expires\", H_Expires, 2, 0, 0, 0, 0)\n", f); fputs("#undef HTTPH\n", f); fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); fputs(" unsigned nuhdr;\n", f); From phk at projects.linpro.no Tue Apr 4 09:05:45 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 4 Apr 2006 11:05:45 +0200 (CEST) Subject: r112 - in trunk/varnish-cache: bin/varnishd bin/varnishlog include lib/libvcl Message-ID: <20060404090545.9BC8D1ED65A@projects.linpro.no> Author: phk Date: 2006-04-04 11:05:45 +0200 (Tue, 04 Apr 2006) New Revision: 112 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishlog/varnishlog.c trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Get pass-through working for the first request. Now we can start to play with multi-request sessions and all that. Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 09:05:45 UTC (rev 112) @@ -36,7 +36,7 @@ #ifdef SHMLOGHEAD_MAGIC 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, "%s(%d)", __func__, __LINE__) +#define HERE() VSL(SLT_Debug, 0, "HERE: %s(%d)", __func__, __LINE__) #endif /* cache_vcl.c */ Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 09:05:45 UTC (rev 112) @@ -163,6 +163,8 @@ continue; break; } + sp->hdr_end = p - sp->rcv; + VSL(SLT_Debug, 0, "HTTP %u %u", sp->rcv_len, sp->hdr_end); event_del(sp->rd_e); sp->sesscb(sp); } Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 09:05:45 UTC (rev 112) @@ -4,9 +4,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -24,7 +26,6 @@ PassReturn(struct sess *sp) { - HERE(); HttpdAnalyze(sp, 2); } @@ -32,12 +33,14 @@ void PassSession(struct sess *sp) { - int fd, i; + int fd, i, j; void *fd_token; struct sbuf *sb; struct event_base *eb; struct sess sp2; struct event ev; + char buf[BUFSIZ]; + off_t cl; fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); @@ -72,4 +75,56 @@ eb = event_init(); HttpdGetHead(&sp2, eb, PassReturn); event_base_loop(eb, 0); + sbuf_clear(sb); + sbuf_cat(sb, sp2.http.proto); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp2.http.status); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp2.http.response); + sbuf_cat(sb, "\r\n"); +#define HTTPH(a, b, c, d, e, f, g) \ + do { \ + if (d && sp2.http.b != NULL) { \ + sbuf_cat(sb, a ": "); \ + sbuf_cat(sb, sp2.http.b); \ + sbuf_cat(sb, "\r\n"); \ + } \ + } while (0); +#include "http_headers.h" +#undef HTTPH + sbuf_cat(sb, "\r\n"); + sbuf_finish(sb); + i = write(sp->fd, sbuf_data(sb), sbuf_len(sb)); + assert(i == sbuf_len(sb)); + if (sp2.http.H_Content_Length != NULL) { + cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); + VSL(SLT_Debug, 0, "CL %ju %u %u", cl, sp->rcv_len, sp->hdr_end); + i = fcntl(sp2.fd, F_GETFL); + i &= ~O_NONBLOCK; + i = fcntl(sp2.fd, F_SETFL, i); + assert(i != -1); + i = sp2.rcv_len - sp2.hdr_end; + if (i > 0) { + VSL(SLT_Debug, 0, "Wr1 %d", i); + j = write(sp->fd, sp2.rcv + sp2.hdr_end, i); + assert(j == i); + cl -= 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) { + VSL(SLT_Debug, 0, "Rd %d", i); + cl -= i; + j = write(sp->fd, buf, i); + assert(j == i); + } else if (i == 0) { + VSL(SLT_Debug, 0, "EOF %d", i); + break; + } + } + } } Modified: trunk/varnish-cache/bin/varnishlog/varnishlog.c =================================================================== --- trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-04 09:05:45 UTC (rev 112) @@ -78,8 +78,10 @@ while (1) { if (*p == SLT_WRAPMARKER) break; - while (*p == SLT_ENDMARKER) + while (*p == SLT_ENDMARKER) { + fflush(stdout); sleep(1); + } printf("%02x %02d %02x%02x %-12s <", p[0], p[1], p[2], p[3], tagnames[p[0]]); @@ -90,251 +92,3 @@ } } } - - -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include "mgt.h" -#include "heritage.h" -#include "cli_event.h" - -/*--------------------------------------------------------------------*/ - -struct heritage heritage; -struct event_base *eb; - -/*-------------------------------------------------------------------- - * Generic passthrough for CLI functions - */ - -void -cli_passthrough_cb(unsigned u, const char *r, void *priv) -{ - struct cli *cli = priv; - - cli_out(cli, "%s\n", r); - cli_result(cli, u); - cli_resume(cli); -} - -static void -cli_func_passthrough(struct cli *cli, char **av __unused, void *priv) -{ - - cli_suspend(cli); - mgt_child_request(cli_passthrough_cb, cli, &av[2], av[1]); -} - -/*--------------------------------------------------------------------*/ - -static void -cli_func_server_start(struct cli *cli, char **av __unused, void *priv __unused) -{ - - mgt_child_start(); -} - -/*--------------------------------------------------------------------*/ - -static void -cli_func_server_stop(struct cli *cli, char **av __unused, void *priv __unused) -{ - - mgt_child_stop(); -} - -/*--------------------------------------------------------------------*/ - -static void -cli_func_verbose(struct cli *cli, char **av __unused, void *priv) -{ - - cli->verbose = !cli->verbose; -} - - -static void -cli_func_ping(struct cli *cli, char **av, void *priv __unused) -{ - time_t t; - - if (av[2] != NULL) { - cli_out(cli, "Got your %s\n", av[2]); - } - time(&t); - cli_out(cli, "PONG %ld\n", t); -} - -/*--------------------------------------------------------------------*/ - -static struct cli_proto cli_proto[] = { - /* URL manipulation */ - { CLI_URL_QUERY, cli_func_passthrough, NULL }, - { CLI_URL_PURGE, cli_func_passthrough, NULL }, - { CLI_URL_STATUS, cli_func_passthrough, NULL }, - { CLI_CONFIG_LOAD }, - { CLI_CONFIG_INLINE }, - { CLI_CONFIG_UNLOAD }, - { CLI_CONFIG_LIST }, - { CLI_CONFIG_USE }, - { CLI_SERVER_FREEZE, cli_func_passthrough, NULL }, - { CLI_SERVER_THAW, cli_func_passthrough, NULL }, - { CLI_SERVER_SUSPEND, cli_func_passthrough, NULL }, - { CLI_SERVER_RESUME, cli_func_passthrough, NULL }, - { CLI_SERVER_STOP, cli_func_server_stop, NULL }, - { CLI_SERVER_START, cli_func_server_start, NULL }, - { CLI_SERVER_RESTART }, - { CLI_PING, cli_func_ping, NULL }, - { CLI_STATS }, - { CLI_ZERO }, - { CLI_HELP, cli_func_help, cli_proto }, - { CLI_VERBOSE, cli_func_verbose, NULL }, - { CLI_EXIT }, - { CLI_QUIT }, - { CLI_BYE }, - { NULL } -}; - -static void -testme(void) -{ - struct event e_sigchld; - struct cli *cli; - int i; - - eb = event_init(); - assert(eb != NULL); - - cli = cli_setup(0, 1, 1, cli_proto); - - signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL); - signal_add(&e_sigchld, NULL); - - i = event_dispatch(); - if (i != 0) - printf("event_dispatch() = %d\n", i); - -} - -/*--------------------------------------------------------------------*/ - -static void -usage(void) -{ - fprintf(stderr, "usage: varnishd [options]\n"); - fprintf(stderr, " %-20s # %s\n", "-d", "debug"); - fprintf(stderr, " %-20s # %s\n", "-p number", "TCP listen port"); -#if 0 - -c clusterid at cluster_controller - -f config_file - -m memory_limit - -s kind[,storage-options] - -l logfile,logsize - -b backend ip... - -u uid - -a CLI_port -#endif - exit(1); -} - -/*--------------------------------------------------------------------*/ - -#include "shmlog.h" - -static void -init_vsl(const char *fn, unsigned size) -{ - struct shmloghead slh; - int i; - - heritage.vsl_fd = open(fn, O_RDWR | O_CREAT, 0600); - if (heritage.vsl_fd < 0) { - fprintf(stderr, "Could not open %s: %s\n", - fn, strerror(errno)); - exit (1); - } - i = read(heritage.vsl_fd, &slh, sizeof slh); - if (i == sizeof slh && slh.magic == SHMLOGHEAD_MAGIC) { - /* XXX more checks */ - heritage.vsl_size = slh.size + slh.start; - return; - } - slh.magic = SHMLOGHEAD_MAGIC; - slh.size = size; - slh.ptr = 0; - slh.start = sizeof slh; - AZ(lseek(heritage.vsl_fd, 0, SEEK_SET)); - i = write(heritage.vsl_fd, &slh, sizeof slh); - assert(i == sizeof slh); - AZ(ftruncate(heritage.vsl_fd, sizeof slh + size)); - heritage.vsl_size = slh.size + slh.start; -} - -/*--------------------------------------------------------------------*/ - -/* for development purposes */ -#include - -int -main(int argc, char *argv[]) -{ - int o; - const char *portnumber = "8080"; - unsigned dflag = 1; /* XXX: debug=on for now */ - - register_printf_render_std((const unsigned char *)"HVQ"); - - while ((o = getopt(argc, argv, "dp:")) != -1) - switch (o) { - case 'd': - dflag++; - break; - case 'p': - portnumber = optarg; - break; - default: - usage(); - } - - argc -= optind; - argv += optind; - - if (argc != 0) - usage(); - - /* - * XXX: Lacking the suspend/resume facility (due to the socket API - * missing an unlisten(2) facility) we may want to push this into - * the child to limit the amount of time where the socket(s) exists - * but do not answer. That, on the other hand, would eliminate the - * possibility of doing a "no-glitch" restart of the child process. - */ - open_tcp(portnumber); - - init_vsl(SHMLOG_FILENAME, 1024*1024); - - testme(); - - - exit(0); -} -#endif Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/include/http_headers.h 2006-04-04 09:05:45 UTC (rev 112) @@ -14,6 +14,7 @@ */ HTTPH("Connection", H_Connection, 3, 0, 0, 0, 0) HTTPH("Keep-Alive", H_Keep_Alive, 3, 0, 0, 0, 0) +HTTPH("Cache-Control", H_Cache_Control, 3, 1, 0, 0, 0) HTTPH("Accept-Charset", H_Accept_Charset, 1, 1, 0, 0, 0) HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 1, 0, 0, 0) @@ -34,13 +35,14 @@ HTTPH("Referer", H_Referer, 1, 1, 0, 0, 0) HTTPH("TE", H_TE, 1, 1, 0, 0, 0) HTTPH("User-Agent", H_User_Agent, 1, 1, 0, 0, 0) +HTTPH("Pragma", H_Pragma, 1, 1, 0, 0, 0) -HTTPH("Server", H_Server, 2, 0, 0, 0, 0) -HTTPH("Content-Type", H_Content_Type, 2, 0, 0, 0, 0) -HTTPH("Date", H_Date, 2, 0, 0, 0, 0) -HTTPH("Last-Modified", H_Last_Modified, 2, 0, 0, 0, 0) -HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 0, 0, 0, 0) -HTTPH("Content-Length", H_Content_Length, 2, 0, 0, 0, 0) -HTTPH("Cache-Control", H_Cache_Control, 2, 0, 0, 0, 0) -HTTPH("Vary", H_Vary, 2, 0, 0, 0, 0) -HTTPH("Expires", H_Expires, 2, 0, 0, 0, 0) +HTTPH("Server", H_Server, 2, 1, 0, 0, 0) +HTTPH("Content-Type", H_Content_Type, 2, 1, 0, 0, 0) +HTTPH("Date", H_Date, 2, 1, 0, 0, 0) +HTTPH("Last-Modified", H_Last_Modified, 2, 1, 0, 0, 0) +HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 1, 0, 0, 0) +HTTPH("Content-Length", H_Content_Length, 2, 1, 0, 0, 0) +HTTPH("Vary", H_Vary, 2, 1, 0, 0, 0) +HTTPH("Expires", H_Expires, 2, 1, 0, 0, 0) +HTTPH("Location", H_Location, 2, 1, 0, 0, 0) Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-04 09:05:45 UTC (rev 112) @@ -49,6 +49,7 @@ /* Receive buffer for HTTP header */ char rcv[VCA_RXBUFSIZE + 1]; unsigned rcv_len; + unsigned hdr_end; /* HTTP request info, points into rcv */ struct httphdr http; Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-04 08:20:24 UTC (rev 111) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-04 09:05:45 UTC (rev 112) @@ -431,6 +431,7 @@ fputs(" */\n", f); fputs("HTTPH(\"Connection\", H_Connection, 3, 0, 0, 0, 0)\n", f); fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive, 3, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Cache-Control\", H_Cache_Control, 3, 1, 0, 0, 0)\n", f); fputs("\n", f); fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 1, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 1, 1, 0, 0, 0)\n", f); @@ -451,16 +452,17 @@ fputs("HTTPH(\"Referer\", H_Referer, 1, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"TE\", H_TE, 1, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Pragma\", H_Pragma, 1, 1, 0, 0, 0)\n", f); fputs("\n", f); - fputs("HTTPH(\"Server\", H_Server, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Content-Type\", H_Content_Type, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Date\", H_Date, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Last-Modified\", H_Last_Modified, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Ranges\", H_Accept_Ranges, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Content-Length\", H_Content_Length, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Cache-Control\", H_Cache_Control, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Vary\", H_Vary, 2, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Expires\", H_Expires, 2, 0, 0, 0, 0)\n", f); + fputs("HTTPH(\"Server\", H_Server, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Content-Type\", H_Content_Type, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Date\", H_Date, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Last-Modified\", H_Last_Modified, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Accept-Ranges\", H_Accept_Ranges, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Content-Length\", H_Content_Length, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Vary\", H_Vary, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Expires\", H_Expires, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Location\", H_Location, 2, 1, 0, 0, 0)\n", f); fputs("#undef HTTPH\n", f); fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); fputs(" unsigned nuhdr;\n", f); @@ -475,6 +477,7 @@ fputs(" /* Receive buffer for HTTP header */\n", f); fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f); fputs(" unsigned rcv_len;\n", f); + fputs(" unsigned hdr_end;\n", f); fputs("\n", f); fputs(" /* HTTP request info, points into rcv */\n", f); fputs(" struct httphdr http;\n", f); From des at linpro.no Tue Apr 4 09:34:23 2006 From: des at linpro.no (Dag-Erling =?iso-8859-1?Q?Sm=F8rgrav?=) Date: Tue, 04 Apr 2006 11:34:23 +0200 Subject: r110 - in trunk/varnish-cache: include lib/libvarnish References: <20060404074630.6771C1ED659@projects.linpro.no> Message-ID: phk at projects.linpro.no writes: > Log: > Reverse constification of Argv functions. After cascading through all > the CLI functions we hit the fact that the evbuffer functions in libevent > are not properly constified. > > It's better to deconst the error messages and just "let it be known" that > argv[0] is const (or NULL). OK. We should probably have a compat.h which defines __DECONST (preferably with a better name) so we don't have to spell it out everywhere, and a libcompat (statically linked) which defines strlcat() etc. The alternative is to strdup() the error message, which removes the need for special-casing argv[0]. DES -- Dag-Erling Sm?rgrav Senior Software Developer Linpro AS - www.linpro.no From des at projects.linpro.no Tue Apr 4 10:07:40 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Tue, 4 Apr 2006 12:07:40 +0200 (CEST) Subject: r113 - in trunk/varnish-cache: . include lib lib/libcompat Message-ID: <20060404100740.21B141ED63F@projects.linpro.no> Author: des Date: 2006-04-04 12:07:40 +0200 (Tue, 04 Apr 2006) New Revision: 113 Added: trunk/varnish-cache/include/compat.h trunk/varnish-cache/lib/libcompat/ trunk/varnish-cache/lib/libcompat/Makefile.am trunk/varnish-cache/lib/libcompat/strlcat.c trunk/varnish-cache/lib/libcompat/strlcpy.c Modified: trunk/varnish-cache/configure.ac trunk/varnish-cache/include/Makefile.am trunk/varnish-cache/lib/Makefile.am Log: Add a libcompat with strlcat() and strlcpy() from OpenBSD. Modified: trunk/varnish-cache/configure.ac =================================================================== --- trunk/varnish-cache/configure.ac 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/configure.ac 2006-04-04 10:07:40 UTC (rev 113) @@ -60,6 +60,10 @@ AC_CHECK_FUNCS([strerror]) AC_FUNC_STRERROR_R AC_CHECK_FUNCS([socket]) +AC_CHECK_FUNCS([strlcat]) +AM_CONDITIONAL(HAVE_STRLCAT, test x$ac_strlcat = xtrue) +AC_CHECK_FUNCS([strlcpy]) +AM_CONDITIONAL(HAVE_STRLCPY, test x$ac_strlcpy = xtrue) AC_CONFIG_FILES([ Makefile @@ -69,6 +73,7 @@ contrib/Makefile include/Makefile lib/Makefile + lib/libcompat/Makefile lib/libsbuf/Makefile lib/libvarnish/Makefile lib/libvarnishapi/Makefile Modified: trunk/varnish-cache/include/Makefile.am =================================================================== --- trunk/varnish-cache/include/Makefile.am 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/include/Makefile.am 2006-04-04 10:07:40 UTC (rev 113) @@ -1,6 +1,7 @@ # $Id$ include_HEADERS = \ + compat.h \ hash.h \ libvarnish.h \ queue.h \ Added: trunk/varnish-cache/include/compat.h =================================================================== --- trunk/varnish-cache/include/compat.h 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/include/compat.h 2006-04-04 10:07:40 UTC (rev 113) @@ -0,0 +1,16 @@ +/* + * $Id$ + */ + +#ifndef COMPAT_H_INCLUDED +#define COMPAT_H_INCLUDED + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t size); +#endif + +#ifndef HAVE_STRLCAT +size_t strlcat(char *dst, const char *src, size_t size); +#endif + +#endif Property changes on: trunk/varnish-cache/include/compat.h ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/lib/Makefile.am =================================================================== --- trunk/varnish-cache/lib/Makefile.am 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/lib/Makefile.am 2006-04-04 10:07:40 UTC (rev 113) @@ -1,6 +1,7 @@ # $Id$ SUBDIRS = \ + libcompat \ libsbuf \ libvarnish \ libvarnishapi \ Added: trunk/varnish-cache/lib/libcompat/Makefile.am =================================================================== --- trunk/varnish-cache/lib/libcompat/Makefile.am 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/lib/libcompat/Makefile.am 2006-04-04 10:07:40 UTC (rev 113) @@ -0,0 +1,15 @@ +# $Id$ + +INCLUDES = -I$(top_srcdir)/include + +lib_LIBRARIES = libcompat.a + +libcompat_a_SOURCES = + +if !HAVE_STRLCAT +libcompat_a_SOURCES += strlcat.c +endif + +if !HAVE_STRLCPY +libcompat_a_SOURCES += strlcpy.c +endif Property changes on: trunk/varnish-cache/lib/libcompat/Makefile.am ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/varnish-cache/lib/libcompat/strlcat.c =================================================================== --- trunk/varnish-cache/lib/libcompat/strlcat.c 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/lib/libcompat/strlcat.c 2006-04-04 10:07:40 UTC (rev 113) @@ -0,0 +1,59 @@ +/* $Id$ */ +/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "config.h" +#include "compat.h" + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} Property changes on: trunk/varnish-cache/lib/libcompat/strlcat.c ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/varnish-cache/lib/libcompat/strlcpy.c =================================================================== --- trunk/varnish-cache/lib/libcompat/strlcpy.c 2006-04-04 09:05:45 UTC (rev 112) +++ trunk/varnish-cache/lib/libcompat/strlcpy.c 2006-04-04 10:07:40 UTC (rev 113) @@ -0,0 +1,55 @@ +/* $Id$ */ +/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "config.h" +#include "compat.h" + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} Property changes on: trunk/varnish-cache/lib/libcompat/strlcpy.c ___________________________________________________________________ Name: svn:keywords + Id From des at projects.linpro.no Tue Apr 4 10:08:36 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Tue, 4 Apr 2006 12:08:36 +0200 (CEST) Subject: r114 - trunk/varnish-cache/lib/libsbuf Message-ID: <20060404100836.808BF1ED650@projects.linpro.no> Author: des Date: 2006-04-04 12:08:36 +0200 (Tue, 04 Apr 2006) New Revision: 114 Modified: trunk/varnish-cache/lib/libsbuf/Makefile.am Log: Make libsbuf static. Modified: trunk/varnish-cache/lib/libsbuf/Makefile.am =================================================================== --- trunk/varnish-cache/lib/libsbuf/Makefile.am 2006-04-04 10:07:40 UTC (rev 113) +++ trunk/varnish-cache/lib/libsbuf/Makefile.am 2006-04-04 10:08:36 UTC (rev 114) @@ -2,10 +2,7 @@ INCLUDES = -I$(top_srcdir)/include -lib_LTLIBRARIES = libsbuf.la +lib_LIBRARIES = libsbuf.a -libsbuf_la_SOURCES = \ +libsbuf_a_SOURCES = \ sbuf.c - -man_MANS = \ - sbuf.3 From des at projects.linpro.no Tue Apr 4 10:08:49 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Tue, 4 Apr 2006 12:08:49 +0200 (CEST) Subject: r115 - trunk/varnish-cache/bin/varnishd Message-ID: <20060404100849.5E0311ED65D@projects.linpro.no> Author: des Date: 2006-04-04 12:08:49 +0200 (Tue, 04 Apr 2006) New Revision: 115 Modified: trunk/varnish-cache/bin/varnishd/Makefile.am Log: Link in libcompat, and libsbuf is now static. Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-04 10:08:36 UTC (rev 114) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-04 10:08:49 UTC (rev 115) @@ -22,8 +22,9 @@ varnishd_LDFLAGS = -export-dynamic varnishd_LDADD = \ + $(top_builddir)/lib/libcompat/libcompat.a \ + $(top_builddir)/lib/libsbuf/libsbuf.a \ $(top_builddir)/lib/libvarnish/libvarnish.la \ - $(top_builddir)/lib/libsbuf/libsbuf.la \ $(top_builddir)/lib/libvcl/libvcl.la \ $(top_builddir)/contrib/libevent/libevent.la \ -lpthread From des at projects.linpro.no Tue Apr 4 10:09:37 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Tue, 4 Apr 2006 12:09:37 +0200 (CEST) Subject: r116 - trunk/varnish-cache/bin/varnishd Message-ID: <20060404100937.CD8E21ED660@projects.linpro.no> Author: des Date: 2006-04-04 12:09:37 +0200 (Tue, 04 Apr 2006) New Revision: 116 Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c trunk/varnish-cache/bin/varnishd/cache_backend.c trunk/varnish-cache/bin/varnishd/cache_main.c trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/bin/varnishd/mgt_child.c Log: More portability changes: include config.h and compat.h, get rid of __unused. Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-04 10:08:49 UTC (rev 115) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-04 10:09:37 UTC (rev 116) @@ -16,6 +16,8 @@ #include #include +#include "config.h" +#include "compat.h" #include "libvarnish.h" #include "vcl_lang.h" #include "heritage.h" Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-04 10:08:49 UTC (rev 115) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-04 10:09:37 UTC (rev 116) @@ -2,17 +2,18 @@ * $Id$ */ -#include -#include -#include -#include -#include -#include -#include #include #include + +#include #include +#include +#include #include +#include +#include +#include +#include #include "libvarnish.h" #include "vcl_lang.h" Modified: trunk/varnish-cache/bin/varnishd/cache_main.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_main.c 2006-04-04 10:08:49 UTC (rev 115) +++ trunk/varnish-cache/bin/varnishd/cache_main.c 2006-04-04 10:09:37 UTC (rev 116) @@ -53,9 +53,10 @@ /*--------------------------------------------------------------------*/ static void -cli_func_url_query(struct cli *cli, char **av, void *priv __unused) +cli_func_url_query(struct cli *cli, char **av, void *priv) { + (void)priv; cli_out(cli, "url <%s>", av[2]); cli_result(cli, CLIS_UNIMPL); } @@ -63,10 +64,11 @@ /*--------------------------------------------------------------------*/ static void -cli_func_ping(struct cli *cli, char **av, void *priv __unused) +cli_func_ping(struct cli *cli, char **av, void *priv) { time_t t; + (void)priv; VSL(SLT_CLI, 0, av[1]); arm_keepalive(); if (av[2] != NULL) { Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 10:08:49 UTC (rev 115) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 10:09:37 UTC (rev 116) @@ -5,6 +5,7 @@ #include #include #include +#include #include "libvarnish.h" #include "vcl_lang.h" @@ -15,10 +16,11 @@ static pthread_cond_t shdcnd; static void * -CacheWorker(void *priv __unused) +CacheWorker(void *priv) { struct sess *sp; + (void)priv; AZ(pthread_mutex_lock(&sessmtx)); while (1) { while (1) { Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c =================================================================== --- trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-04 10:08:49 UTC (rev 115) +++ trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-04 10:09:37 UTC (rev 116) @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include From des at projects.linpro.no Tue Apr 4 10:35:49 2006 From: des at projects.linpro.no (des at projects.linpro.no) Date: Tue, 4 Apr 2006 12:35:49 +0200 (CEST) Subject: r117 - in trunk/varnish-cache: . lib/libcompat Message-ID: <20060404103549.2CFC71ED664@projects.linpro.no> Author: des Date: 2006-04-04 12:35:49 +0200 (Tue, 04 Apr 2006) New Revision: 117 Modified: trunk/varnish-cache/configure.ac trunk/varnish-cache/lib/libcompat/Makefile.am trunk/varnish-cache/lib/libcompat/strlcat.c trunk/varnish-cache/lib/libcompat/strlcpy.c Log: I can't get AM_CONDITIONAL to work properly, so use a bigger hammer. Modified: trunk/varnish-cache/configure.ac =================================================================== --- trunk/varnish-cache/configure.ac 2006-04-04 10:09:37 UTC (rev 116) +++ trunk/varnish-cache/configure.ac 2006-04-04 10:35:49 UTC (rev 117) @@ -61,9 +61,7 @@ AC_FUNC_STRERROR_R AC_CHECK_FUNCS([socket]) AC_CHECK_FUNCS([strlcat]) -AM_CONDITIONAL(HAVE_STRLCAT, test x$ac_strlcat = xtrue) AC_CHECK_FUNCS([strlcpy]) -AM_CONDITIONAL(HAVE_STRLCPY, test x$ac_strlcpy = xtrue) AC_CONFIG_FILES([ Makefile Modified: trunk/varnish-cache/lib/libcompat/Makefile.am =================================================================== --- trunk/varnish-cache/lib/libcompat/Makefile.am 2006-04-04 10:09:37 UTC (rev 116) +++ trunk/varnish-cache/lib/libcompat/Makefile.am 2006-04-04 10:35:49 UTC (rev 117) @@ -4,12 +4,6 @@ lib_LIBRARIES = libcompat.a -libcompat_a_SOURCES = - -if !HAVE_STRLCAT -libcompat_a_SOURCES += strlcat.c -endif - -if !HAVE_STRLCPY -libcompat_a_SOURCES += strlcpy.c -endif +libcompat_a_SOURCES = \ + strlcat.c \ + strlcpy.c Modified: trunk/varnish-cache/lib/libcompat/strlcat.c =================================================================== --- trunk/varnish-cache/lib/libcompat/strlcat.c 2006-04-04 10:09:37 UTC (rev 116) +++ trunk/varnish-cache/lib/libcompat/strlcat.c 2006-04-04 10:35:49 UTC (rev 117) @@ -23,6 +23,7 @@ #include "config.h" #include "compat.h" +#ifndef HAVE_STRLCAT /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters @@ -57,3 +58,4 @@ return(dlen + (s - src)); /* count does not include NUL */ } +#endif Modified: trunk/varnish-cache/lib/libcompat/strlcpy.c =================================================================== --- trunk/varnish-cache/lib/libcompat/strlcpy.c 2006-04-04 10:09:37 UTC (rev 116) +++ trunk/varnish-cache/lib/libcompat/strlcpy.c 2006-04-04 10:35:49 UTC (rev 117) @@ -23,6 +23,7 @@ #include "config.h" #include "compat.h" +#ifndef HAVE_STRLCPY /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). @@ -53,3 +54,4 @@ return(s - src - 1); /* count does not include NUL */ } +#endif From phk at phk.freebsd.dk Tue Apr 4 10:38:50 2006 From: phk at phk.freebsd.dk (Poul-Henning Kamp) Date: Tue, 04 Apr 2006 12:38:50 +0200 Subject: r110 - in trunk/varnish-cache: include lib/libvarnish In-Reply-To: Your message of "Tue, 04 Apr 2006 11:34:23 +0200." Message-ID: <62552.1144147130@critter.freebsd.dk> In message , Dag-Erling =?iso-8859-1?Q?Sm=F8rgra v?= writes: >phk at projects.linpro.no writes: >OK. We should probably have a compat.h which defines __DECONST >(preferably with a better name) so we don't have to spell it out >everywhere, and a libcompat (statically linked) which defines >strlcat() etc. I'm sure I've used much stuff that will call for changes or a libcompat, but lets see how bad it is as we get there. I have thought about sticking a compat wrapper around libevent, but I'll wait for Provos to answer before I decide that. > >The alternative is to strdup() the error message, which removes the >need for special-casing argv[0]. yeah, but then we'd have to handle strdup() errors :-( -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk at FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. From phk at projects.linpro.no Wed Apr 5 09:40:22 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Wed, 5 Apr 2006 11:40:22 +0200 (CEST) Subject: r118 - in trunk/varnish-cache: . bin/varnishd Message-ID: <20060405094022.F3DB91ED61F@projects.linpro.no> Author: phk Date: 2006-04-05 11:40:22 +0200 (Wed, 05 Apr 2006) New Revision: 118 Modified: trunk/varnish-cache/autogen.sh trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pipe.c trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Account for the last byte of the header. Modified: trunk/varnish-cache/autogen.sh =================================================================== --- trunk/varnish-cache/autogen.sh 2006-04-04 10:35:49 UTC (rev 117) +++ trunk/varnish-cache/autogen.sh 2006-04-05 09:40:22 UTC (rev 118) @@ -3,6 +3,8 @@ # $Id$ # +set -ex + if [ -d /usr/local/gnu-autotools/bin ] ; then PATH=${PATH}:/usr/local/gnu-autotools/bin export PATH @@ -10,6 +12,7 @@ base=$(cd $(dirname $0) && pwd) for dir in $base $base/contrib/libevent ; do + ( echo $dir cd $dir aclocal @@ -17,4 +20,14 @@ autoheader automake --add-missing --copy --force --foreign autoconf + ) done + +sh configure \ + --enable-pedantic \ + --enable-wall \ + --enable-werror \ + --enable-dependency-tracking + +# This is a safety-measure during development +( cd lib/libvcl && ./*.tcl ) Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-04 10:35:49 UTC (rev 117) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-05 09:40:22 UTC (rev 118) @@ -4,6 +4,16 @@ struct event_base; +#ifdef EV_TIMEOUT +struct worker { + struct event_base *eb; + struct event e1, e2; + struct sbuf *sb; +}; +#else +struct worker; +#endif + /* cache_acceptor.c */ void *vca_main(void *arg); void vca_retire_session(struct sess *sp); @@ -22,10 +32,10 @@ pthread_mutex_t sessmtx; /* cache_pass.c */ -void PassSession(struct sess *sp); +void PassSession(struct worker *w, struct sess *sp); /* cache_pipe.c */ -void PipeSession(struct sess *sp); +void PipeSession(struct worker *w, struct sess *sp); /* cache_pool.c */ void CacheInitPool(void); Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-04 10:35:49 UTC (rev 117) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-05 09:40:22 UTC (rev 118) @@ -163,7 +163,7 @@ continue; break; } - sp->hdr_end = p - sp->rcv; + sp->hdr_end = ++p - sp->rcv; VSL(SLT_Debug, 0, "HTTP %u %u", sp->rcv_len, sp->hdr_end); event_del(sp->rd_e); sp->sesscb(sp); Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-04 10:35:49 UTC (rev 117) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-05 09:40:22 UTC (rev 118) @@ -31,71 +31,66 @@ /*--------------------------------------------------------------------*/ void -PassSession(struct sess *sp) +PassSession(struct worker *w, struct sess *sp) { int fd, i, j; void *fd_token; - struct sbuf *sb; - struct event_base *eb; struct sess sp2; - struct event ev; char buf[BUFSIZ]; off_t cl; fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); - assert(sb != NULL); - sbuf_cat(sb, sp->http.req); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.url); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.proto); - sbuf_cat(sb, "\r\n"); + sbuf_clear(w->sb); + assert(w->sb != NULL); + sbuf_cat(w->sb, sp->http.req); + sbuf_cat(w->sb, " "); + sbuf_cat(w->sb, sp->http.url); + sbuf_cat(w->sb, " "); + sbuf_cat(w->sb, sp->http.proto); + sbuf_cat(w->sb, "\r\n"); #define HTTPH(a, b, c, d, e, f, g) \ do { \ if (d && sp->http.b != NULL) { \ - sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp->http.b); \ - sbuf_cat(sb, "\r\n"); \ + sbuf_cat(w->sb, a ": "); \ + sbuf_cat(w->sb, sp->http.b); \ + sbuf_cat(w->sb, "\r\n"); \ } \ } while (0); #include "http_headers.h" #undef HTTPH - sbuf_cat(sb, "\r\n"); - sbuf_finish(sb); - i = write(fd, sbuf_data(sb), sbuf_len(sb)); - assert(i == sbuf_len(sb)); + sbuf_cat(w->sb, "\r\n"); + sbuf_finish(w->sb); + i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); memset(&sp2, 0, sizeof sp2); - memset(&ev, 0, sizeof ev); - sp2.rd_e = &ev; + sp2.rd_e = &w->e1; sp2.fd = fd; - eb = event_init(); - HttpdGetHead(&sp2, eb, PassReturn); - event_base_loop(eb, 0); - sbuf_clear(sb); - sbuf_cat(sb, sp2.http.proto); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp2.http.status); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp2.http.response); - sbuf_cat(sb, "\r\n"); + HttpdGetHead(&sp2, w->eb, PassReturn); + event_base_loop(w->eb, 0); + sbuf_clear(w->sb); + sbuf_cat(w->sb, sp2.http.proto); + sbuf_cat(w->sb, " "); + sbuf_cat(w->sb, sp2.http.status); + sbuf_cat(w->sb, " "); + sbuf_cat(w->sb, sp2.http.response); + sbuf_cat(w->sb, "\r\n"); #define HTTPH(a, b, c, d, e, f, g) \ do { \ if (d && sp2.http.b != NULL) { \ - sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp2.http.b); \ - sbuf_cat(sb, "\r\n"); \ + sbuf_cat(w->sb, a ": "); \ + sbuf_cat(w->sb, sp2.http.b); \ + sbuf_cat(w->sb, "\r\n"); \ } \ } while (0); #include "http_headers.h" #undef HTTPH - sbuf_cat(sb, "\r\n"); - sbuf_finish(sb); - i = write(sp->fd, sbuf_data(sb), sbuf_len(sb)); - assert(i == sbuf_len(sb)); + sbuf_cat(w->sb, "\r\n"); + sbuf_finish(w->sb); + i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); if (sp2.http.H_Content_Length != NULL) { cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); VSL(SLT_Debug, 0, "CL %ju %u %u", cl, sp->rcv_len, sp->hdr_end); Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-04 10:35:49 UTC (rev 117) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-05 09:40:22 UTC (rev 118) @@ -42,55 +42,51 @@ } void -PipeSession(struct sess *sp) +PipeSession(struct worker *w, struct sess *sp) { int fd, i; void *fd_token; - struct sbuf *sb; - struct event_base *eb; struct edir e1, e2; fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); - assert(sb != NULL); - sbuf_cat(sb, sp->http.req); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.url); + sbuf_clear(w->sb); + assert(w->sb != NULL); + sbuf_cat(w->sb, sp->http.req); + sbuf_cat(w->sb, " "); + sbuf_cat(w->sb, sp->http.url); if (sp->http.proto != NULL) { - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.proto); + sbuf_cat(w->sb, " "); + sbuf_cat(w->sb, sp->http.proto); } - sbuf_cat(sb, "\r\n"); + sbuf_cat(w->sb, "\r\n"); #define HTTPH(a, b, c, d, e, f, g) \ do { \ if (sp->http.b != NULL) { \ - sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp->http.b); \ - sbuf_cat(sb, "\r\n"); \ + sbuf_cat(w->sb, a ": "); \ + sbuf_cat(w->sb, sp->http.b); \ + sbuf_cat(w->sb, "\r\n"); \ } \ } while (0); #include "http_headers.h" #undef HTTPH - sbuf_cat(sb, "\r\n"); - sbuf_finish(sb); - i = write(fd, sbuf_data(sb), sbuf_len(sb)); - assert(i == sbuf_len(sb)); + sbuf_cat(w->sb, "\r\n"); + sbuf_finish(w->sb); + i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); e1.fd = fd; e2.fd = sp->fd; - eb = event_init(); event_set(&e1.ev, sp->fd, EV_READ | EV_PERSIST, rdf, &e1); - event_base_set(eb, &e1.ev); + event_base_set(w->eb, &e1.ev); event_set(&e2.ev, fd, EV_READ | EV_PERSIST, rdf, &e2); - event_base_set(eb, &e2.ev); + event_base_set(w->eb, &e2.ev); event_add(&e1.ev, NULL); event_add(&e2.ev, NULL); - event_base_loop(eb, 0); + event_base_loop(w->eb, 0); close (fd); close (sp->fd); - /* XXX: Delete eb */ VBE_ClosedFd(fd_token); sp->fd = -1; } Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-04 10:35:49 UTC (rev 117) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-05 09:40:22 UTC (rev 118) @@ -3,9 +3,13 @@ */ #include +#include #include #include #include +#include +#include +#include #include "libvarnish.h" #include "vcl_lang.h" @@ -19,7 +23,14 @@ CacheWorker(void *priv) { struct sess *sp; + struct worker w; + memset(&w, 0, sizeof w); + w.eb = event_init(); + assert(w.eb != NULL); + w.sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); + assert(w.sb != NULL); + (void)priv; AZ(pthread_mutex_lock(&sessmtx)); while (1) { @@ -42,9 +53,9 @@ printf("Handling: %d\n", sp->handling); if (0) { - PipeSession(sp); + PipeSession(&w, sp); } else { - PassSession(sp); + PassSession(&w, sp); } AZ(pthread_mutex_lock(&sessmtx)); From phk at phk.freebsd.dk Wed Apr 5 09:42:59 2006 From: phk at phk.freebsd.dk (Poul-Henning Kamp) Date: Wed, 05 Apr 2006 11:42:59 +0200 Subject: r118 - in trunk/varnish-cache: . bin/varnishd In-Reply-To: Your message of "Wed, 05 Apr 2006 11:40:22 +0200." <20060405094022.F3DB91ED61F@projects.linpro.no> Message-ID: <89118.1144230179@critter.freebsd.dk> Ok, this was the commit that got away from me, it should only have applied to trunk/varnish-cache/bin/varnishd/cache_httpd.c. The commit message for the remaining files are: trunk/varnish-cache/autogen.sh Automate a fair bit more for developer convenience. the rest: Give worker threads a little cache of handy objects in order to avoid creating/destroying them for every request: An event_base, a sbuf and two events. In message <20060405094022.F3DB91ED61F at projects.linpro.no>, phk at projects.linpro .no writes: >Author: phk >Date: 2006-04-05 11:40:22 +0200 (Wed, 05 Apr 2006) >New Revision: 118 > >Modified: > trunk/varnish-cache/autogen.sh > trunk/varnish-cache/bin/varnishd/cache.h > trunk/varnish-cache/bin/varnishd/cache_httpd.c > trunk/varnish-cache/bin/varnishd/cache_pass.c > trunk/varnish-cache/bin/varnishd/cache_pipe.c > trunk/varnish-cache/bin/varnishd/cache_pool.c >Log: >Account for the last byte of the header. > -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk at FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. From des at linpro.no Wed Apr 5 09:44:48 2006 From: des at linpro.no (Dag-Erling =?iso-8859-1?Q?Sm=F8rgrav?=) Date: Wed, 05 Apr 2006 11:44:48 +0200 Subject: r118 - in trunk/varnish-cache: . bin/varnishd References: <20060405094022.F3DB91ED61F@projects.linpro.no> Message-ID: phk at projects.linpro.no writes: > Modified: trunk/varnish-cache/autogen.sh > =================================================================== > --- trunk/varnish-cache/autogen.sh 2006-04-04 10:35:49 UTC (rev 117) > +++ trunk/varnish-cache/autogen.sh 2006-04-05 09:40:22 UTC (rev 118) > @@ -3,6 +3,8 @@ > # $Id$ > # > > +set -ex > + > if [ -d /usr/local/gnu-autotools/bin ] ; then > PATH=${PATH}:/usr/local/gnu-autotools/bin > export PATH > @@ -10,6 +12,7 @@ > > base=$(cd $(dirname $0) && pwd) > for dir in $base $base/contrib/libevent ; do > + ( > echo $dir > cd $dir > aclocal > @@ -17,4 +20,14 @@ > autoheader > automake --add-missing --copy --force --foreign > autoconf > + ) > done > + > +sh configure \ > + --enable-pedantic \ > + --enable-wall \ > + --enable-werror \ > + --enable-dependency-tracking > + > +# This is a safety-measure during development > +( cd lib/libvcl && ./*.tcl ) This is wrong. In any case, you don't need to run configure from autogen; if you have an old Makefile lying around, simply running 'make' after editing any of the autoconf / automake files will regenerate everything and re-run configure with the same arguments that were used the first time around. DES -- Dag-Erling Sm?rgrav Senior Software Developer Linpro AS - www.linpro.no From phk at phk.freebsd.dk Wed Apr 5 10:13:17 2006 From: phk at phk.freebsd.dk (Poul-Henning Kamp) Date: Wed, 05 Apr 2006 12:13:17 +0200 Subject: r118 - in trunk/varnish-cache: . bin/varnishd In-Reply-To: Your message of "Wed, 05 Apr 2006 11:44:48 +0200." Message-ID: <89305.1144231997@critter.freebsd.dk> In message , Dag-Erling =?iso-8859-1?Q?Sm=F8rgra v?= writes: >phk at projects.linpro.no writes: >> Modified: trunk/varnish-cache/autogen.sh > >This is wrong. In any case, you don't need to run configure from >autogen; if you have an old Makefile lying around, simply running >'make' after editing any of the autoconf / automake files will >regenerate everything and re-run configure with the same arguments >that were used the first time around. I didn't mean for this file to be committed in the first place, and I'll revert it shortly. -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk at FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. From phk at projects.linpro.no Wed Apr 5 10:33:37 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Wed, 5 Apr 2006 12:33:37 +0200 (CEST) Subject: r119 - trunk/varnish-cache Message-ID: <20060405103337.455191ED640@projects.linpro.no> Author: phk Date: 2006-04-05 12:33:37 +0200 (Wed, 05 Apr 2006) New Revision: 119 Modified: trunk/varnish-cache/autogen.sh Log: Eliminate leaked developer hacks. Modified: trunk/varnish-cache/autogen.sh =================================================================== --- trunk/varnish-cache/autogen.sh 2006-04-05 09:40:22 UTC (rev 118) +++ trunk/varnish-cache/autogen.sh 2006-04-05 10:33:37 UTC (rev 119) @@ -22,12 +22,3 @@ autoconf ) done - -sh configure \ - --enable-pedantic \ - --enable-wall \ - --enable-werror \ - --enable-dependency-tracking - -# This is a safety-measure during development -( cd lib/libvcl && ./*.tcl ) From phk at projects.linpro.no Thu Apr 6 07:50:05 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 09:50:05 +0200 (CEST) Subject: r120 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406075005.23AA41ED668@projects.linpro.no> Author: phk Date: 2006-04-06 09:50:05 +0200 (Thu, 06 Apr 2006) New Revision: 120 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_httpd.c Log: Add a function to (re)build a HTTP request or response into an sbuf. Enable Id keyword Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-05 10:33:37 UTC (rev 119) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-06 07:50:05 UTC (rev 120) @@ -3,6 +3,7 @@ */ struct event_base; +struct sbuf; #ifdef EV_TIMEOUT struct worker { @@ -27,6 +28,7 @@ /* cache_httpd.c */ void HttpdAnalyze(struct sess *sp, int rr); void HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func); +void HttpdBuildSbuf(int resp, int filter, struct sbuf *sb, struct sess *sp); /* cache_main.c */ pthread_mutex_t sessmtx; Property changes on: trunk/varnish-cache/bin/varnishd/cache.h ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-05 10:33:37 UTC (rev 119) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 07:50:05 UTC (rev 120) @@ -12,6 +12,7 @@ #include #include #include +#include #include "libvarnish.h" #include "shmlog.h" @@ -181,3 +182,40 @@ event_base_set(eb, sp->rd_e); event_add(sp->rd_e, NULL); /* XXX: timeout */ } + +/*--------------------------------------------------------------------*/ + +void +HttpdBuildSbuf(int resp, int filter, struct sbuf *sb, struct sess *sp) +{ + + sbuf_clear(sb); + assert(sb != NULL); + if (resp) { + sbuf_cat(sb, sp->http.proto); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->http.status); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->http.response); + } else { + sbuf_cat(sb, sp->http.req); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->http.url); + sbuf_cat(sb, " "); + sbuf_cat(sb, sp->http.proto); + } + sbuf_cat(sb, "\r\n"); +#define HTTPH(a, b, c, d, e, f, g) \ + do { \ + if ((!filter || d) && sp->http.b != NULL) { \ + sbuf_cat(sb, a ": "); \ + sbuf_cat(sb, sp->http.b); \ + sbuf_cat(sb, "\r\n"); \ + } \ + } while (0); +#include "http_headers.h" +#undef HTTPH + sbuf_cat(sb, "\r\n"); + sbuf_finish(sb); + +} Property changes on: trunk/varnish-cache/bin/varnishd/cache_httpd.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 07:50:58 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 09:50:58 +0200 (CEST) Subject: r121 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406075058.6797B1ED640@projects.linpro.no> Author: phk Date: 2006-04-06 09:50:58 +0200 (Thu, 06 Apr 2006) New Revision: 121 Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pipe.c Log: Use HttpdBuildSbuf() Enable Id keyword Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 07:50:05 UTC (rev 120) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 07:50:58 UTC (rev 121) @@ -42,65 +42,32 @@ fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - sbuf_clear(w->sb); - assert(w->sb != NULL); - sbuf_cat(w->sb, sp->http.req); - sbuf_cat(w->sb, " "); - sbuf_cat(w->sb, sp->http.url); - sbuf_cat(w->sb, " "); - sbuf_cat(w->sb, sp->http.proto); - sbuf_cat(w->sb, "\r\n"); -#define HTTPH(a, b, c, d, e, f, g) \ - do { \ - if (d && sp->http.b != NULL) { \ - sbuf_cat(w->sb, a ": "); \ - sbuf_cat(w->sb, sp->http.b); \ - sbuf_cat(w->sb, "\r\n"); \ - } \ - } while (0); -#include "http_headers.h" -#undef HTTPH - sbuf_cat(w->sb, "\r\n"); - sbuf_finish(w->sb); + HttpdBuildSbuf(0, 1, w->sb, sp); + i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); + /* XXX: copy any contents */ + + memset(&sp2, 0, sizeof sp2); sp2.rd_e = &w->e1; sp2.fd = fd; HttpdGetHead(&sp2, w->eb, PassReturn); event_base_loop(w->eb, 0); - sbuf_clear(w->sb); - sbuf_cat(w->sb, sp2.http.proto); - sbuf_cat(w->sb, " "); - sbuf_cat(w->sb, sp2.http.status); - sbuf_cat(w->sb, " "); - sbuf_cat(w->sb, sp2.http.response); - sbuf_cat(w->sb, "\r\n"); -#define HTTPH(a, b, c, d, e, f, g) \ - do { \ - if (d && sp2.http.b != NULL) { \ - sbuf_cat(w->sb, a ": "); \ - sbuf_cat(w->sb, sp2.http.b); \ - sbuf_cat(w->sb, "\r\n"); \ - } \ - } while (0); -#include "http_headers.h" -#undef HTTPH - sbuf_cat(w->sb, "\r\n"); - sbuf_finish(w->sb); + + HttpdBuildSbuf(1, 1, w->sb, &sp2); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); + if (sp2.http.H_Content_Length != NULL) { cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); - VSL(SLT_Debug, 0, "CL %ju %u %u", cl, sp->rcv_len, sp->hdr_end); i = fcntl(sp2.fd, F_GETFL); i &= ~O_NONBLOCK; i = fcntl(sp2.fd, F_SETFL, i); assert(i != -1); i = sp2.rcv_len - sp2.hdr_end; if (i > 0) { - VSL(SLT_Debug, 0, "Wr1 %d", i); j = write(sp->fd, sp2.rcv + sp2.hdr_end, i); assert(j == i); cl -= i; @@ -112,14 +79,15 @@ i = recv(sp2.fd, buf, j, 0); assert(i >= 0); if (i > 0) { - VSL(SLT_Debug, 0, "Rd %d", i); cl -= i; j = write(sp->fd, buf, i); assert(j == i); } else if (i == 0) { - VSL(SLT_Debug, 0, "EOF %d", i); break; } } } + + /* XXX: move remaining input in sp->rcv */ + /* XXX: return session to acceptor */ } Property changes on: trunk/varnish-cache/bin/varnishd/cache_pass.c ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-06 07:50:05 UTC (rev 120) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-06 07:50:58 UTC (rev 121) @@ -44,37 +44,21 @@ void PipeSession(struct worker *w, struct sess *sp) { - int fd, i; + int fd, i, j; void *fd_token; struct edir e1, e2; fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - sbuf_clear(w->sb); - assert(w->sb != NULL); - sbuf_cat(w->sb, sp->http.req); - sbuf_cat(w->sb, " "); - sbuf_cat(w->sb, sp->http.url); - if (sp->http.proto != NULL) { - sbuf_cat(w->sb, " "); - sbuf_cat(w->sb, sp->http.proto); - } - sbuf_cat(w->sb, "\r\n"); -#define HTTPH(a, b, c, d, e, f, g) \ - do { \ - if (sp->http.b != NULL) { \ - sbuf_cat(w->sb, a ": "); \ - sbuf_cat(w->sb, sp->http.b); \ - sbuf_cat(w->sb, "\r\n"); \ - } \ - } while (0); -#include "http_headers.h" -#undef HTTPH - sbuf_cat(w->sb, "\r\n"); - sbuf_finish(w->sb); + HttpdBuildSbuf(0, 0, w->sb, sp); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); + i = sp->rcv_len - sp->hdr_end; + if (i > 0) { + j = write(sp->fd, sp->rcv + sp->hdr_end, i); + assert(j == i); + } e1.fd = fd; e2.fd = sp->fd; Property changes on: trunk/varnish-cache/bin/varnishd/cache_pipe.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 08:15:46 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 10:15:46 +0200 (CEST) Subject: r122 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406081546.41AC11ED668@projects.linpro.no> Author: phk Date: 2006-04-06 10:15:46 +0200 (Thu, 06 Apr 2006) New Revision: 122 Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c Log: It's cheaper to pipe than to pass, so if the client indicates "Connection: close", pipe instead of passing. Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 07:50:58 UTC (rev 121) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 08:15:46 UTC (rev 122) @@ -26,7 +26,7 @@ PassReturn(struct sess *sp) { - HttpdAnalyze(sp, 2); + /* do nothing */ } /*--------------------------------------------------------------------*/ @@ -39,22 +39,30 @@ char buf[BUFSIZ]; off_t cl; + if (sp->http.H_Connection != NULL && + !strcmp(sp->http.H_Connection, "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); HttpdBuildSbuf(0, 1, w->sb, sp); - i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); /* XXX: copy any contents */ - memset(&sp2, 0, sizeof sp2); sp2.rd_e = &w->e1; sp2.fd = fd; HttpdGetHead(&sp2, w->eb, PassReturn); event_base_loop(w->eb, 0); + HttpdAnalyze(&sp2, 2); HttpdBuildSbuf(1, 1, w->sb, &sp2); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); From phk at projects.linpro.no Thu Apr 6 08:16:26 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 10:16:26 +0200 (CEST) Subject: r123 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406081626.852DF1ED66F@projects.linpro.no> Author: phk Date: 2006-04-06 10:16:26 +0200 (Thu, 06 Apr 2006) New Revision: 123 Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c Log: Don't attempt to restart child process (yet). Add Id Keyword handling Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c =================================================================== --- trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-06 08:15:46 UTC (rev 122) +++ trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-06 08:16:26 UTC (rev 123) @@ -290,6 +290,9 @@ printf("pid = %d status = 0x%x\n", p, status); assert(p == child_pid); + printf("Child died :-(\n"); + exit (0); + bufferevent_free(child_std); /* XXX: is this enough ? */ child_std = NULL; Property changes on: trunk/varnish-cache/bin/varnishd/mgt_child.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 08:18:11 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 10:18:11 +0200 (CEST) Subject: r124 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406081811.8E76C1ED668@projects.linpro.no> Author: phk Date: 2006-04-06 10:18:11 +0200 (Thu, 06 Apr 2006) New Revision: 124 Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Respect VCL choice of handling Do Id keyword Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-06 08:16:26 UTC (rev 123) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-06 08:18:11 UTC (rev 124) @@ -51,11 +51,15 @@ sp->vcl->main_func(sp); printf("Handling: %d\n", sp->handling); - - if (0) { + switch(sp->handling) { + case HND_Unclass: + case HND_Handle: + case HND_Pipe: PipeSession(&w, sp); - } else { + break; + case HND_Pass: PassSession(&w, sp); + break; } AZ(pthread_mutex_lock(&sessmtx)); Property changes on: trunk/varnish-cache/bin/varnishd/cache_pool.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 08:18:53 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 10:18:53 +0200 (CEST) Subject: r125 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406081853.D0C401ED670@projects.linpro.no> Author: phk Date: 2006-04-06 10:18:53 +0200 (Thu, 06 Apr 2006) New Revision: 125 Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c Log: Add an assert, remove debugging. Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 08:18:11 UTC (rev 124) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 08:18:53 UTC (rev 125) @@ -97,6 +97,7 @@ for (; p < sp->rcv + sp->rcv_len; p = r) { q = strchr(p, '\n'); + assert(q != NULL); r = q + 1; if (q > p && q[-1] == '\r') q--; @@ -165,7 +166,6 @@ break; } sp->hdr_end = ++p - sp->rcv; - VSL(SLT_Debug, 0, "HTTP %u %u", sp->rcv_len, sp->hdr_end); event_del(sp->rd_e); sp->sesscb(sp); } From phk at projects.linpro.no Thu Apr 6 09:08:13 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:08:13 +0200 (CEST) Subject: r126 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406090813.448801ED670@projects.linpro.no> Author: phk Date: 2006-04-06 11:08:13 +0200 (Thu, 06 Apr 2006) New Revision: 126 Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c Log: Don't log the terminating NUL on response proto field. Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 08:18:53 UTC (rev 125) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 09:08:13 UTC (rev 126) @@ -67,8 +67,8 @@ p = sp->rcv; while (!isspace(*p)) p++; + VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); *p++ = '\0'; - VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); /* Next find the status */ while (isspace(*p)) @@ -166,6 +166,7 @@ break; } sp->hdr_end = ++p - sp->rcv; + event_del(sp->rd_e); sp->sesscb(sp); } @@ -217,5 +218,4 @@ #undef HTTPH sbuf_cat(sb, "\r\n"); sbuf_finish(sb); - } From phk at projects.linpro.no Thu Apr 6 09:09:09 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:09:09 +0200 (CEST) Subject: r127 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406090909.AC6201ED672@projects.linpro.no> Author: phk Date: 2006-04-06 11:09:09 +0200 (Thu, 06 Apr 2006) New Revision: 127 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_acceptor.c Log: Add a vca_recycle_session() function which sticks a session back into the acceptors event engine. Do Id keyword Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-06 09:08:13 UTC (rev 126) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-06 09:09:09 UTC (rev 127) @@ -18,6 +18,7 @@ /* cache_acceptor.c */ void *vca_main(void *arg); void vca_retire_session(struct sess *sp); +void vca_recycle_session(struct sess *sp); /* cache_backend.c */ void VBE_Init(void); Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-06 09:08:13 UTC (rev 126) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-06 09:09:09 UTC (rev 127) @@ -1,5 +1,9 @@ /* * $Id$ + * + * XXX: We need to pass sessions back into the event engine when they are + * reused. Not sure what the most efficient way is for that. For now + * write the session pointer to a pipe which the event engine monitors. */ #include @@ -25,6 +29,8 @@ #include "cache.h" static struct event_base *evb; +static struct event pipe_e; +static int pipes[2]; static struct event accept_e[2 * HERITAGE_NSOCKS]; @@ -34,6 +40,17 @@ }; static void +pipe_f(int fd, short event, void *arg) +{ + struct sess *sp; + int i; + + i = read(fd, &sp, sizeof sp); + assert(i == sizeof sp); + HttpdGetHead(sp, evb, DealWithSession); +} + +static void accept_f(int fd, short event, void *arg) { socklen_t l; @@ -74,8 +91,13 @@ unsigned u; struct event *ep; + AZ(pipe(pipes)); evb = event_init(); + event_set(&pipe_e, pipes[0], EV_READ | EV_PERSIST, pipe_f, NULL); + event_base_set(evb, &pipe_e); + event_add(&pipe_e, NULL); + ep = accept_e; for (u = 0; u < HERITAGE_NSOCKS; u++) { if (heritage.sock_local[u] >= 0) { @@ -102,9 +124,17 @@ } void +vca_recycle_session(struct sess *sp) +{ + VSL(SLT_SessionReuse, sp->fd, "%s", sp->addr); + write(pipes[1], &sp, sizeof sp); +} + +void vca_retire_session(struct sess *sp) { + VSL(SLT_SessionClose, sp->fd, "%s", sp->addr); if (sp->fd >= 0) close(sp->fd); free(sp); Property changes on: trunk/varnish-cache/bin/varnishd/cache_acceptor.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 09:09:58 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:09:58 +0200 (CEST) Subject: r128 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406090958.DC3C41ED670@projects.linpro.no> Author: phk Date: 2006-04-06 11:09:58 +0200 (Thu, 06 Apr 2006) New Revision: 128 Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c Log: Prune the bits we used from the input buffer before we recycle the session. Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 09:09:09 UTC (rev 127) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 09:09:58 UTC (rev 128) @@ -94,8 +94,16 @@ break; } } + assert(cl == 0); } - /* XXX: move remaining input in sp->rcv */ - /* XXX: return session to acceptor */ + if (sp->rcv_len > sp->hdr_end) { + memmove(sp->rcv, sp->rcv + sp->hdr_end, + sp->rcv_len - sp->hdr_end); + sp->rcv_len -= sp->hdr_end; + sp->rcv[sp->rcv_len] = '\0'; + } else { + sp->rcv_len = 0; + sp->rcv[sp->rcv_len] = '\0'; + } } From phk at projects.linpro.no Thu Apr 6 09:10:25 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:10:25 +0200 (CEST) Subject: r129 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406091025.1014C1ED670@projects.linpro.no> Author: phk Date: 2006-04-06 11:10:24 +0200 (Thu, 06 Apr 2006) New Revision: 129 Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Recycle sessions instead of retiring them. Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-06 09:09:58 UTC (rev 128) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-06 09:10:24 UTC (rev 129) @@ -65,7 +65,7 @@ AZ(pthread_mutex_lock(&sessmtx)); RelVCL(sp->vcl); sp->vcl = NULL; - vca_retire_session(sp); + vca_recycle_session(sp); } } From phk at projects.linpro.no Thu Apr 6 09:11:28 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:11:28 +0200 (CEST) Subject: r130 - trunk/varnish-cache/include Message-ID: <20060406091128.A638D1ED676@projects.linpro.no> Author: phk Date: 2006-04-06 11:11:28 +0200 (Thu, 06 Apr 2006) New Revision: 130 Modified: trunk/varnish-cache/include/shmlog_tags.h Log: Log tag for session reuse. Do Id Keyword Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-06 09:10:24 UTC (rev 129) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-06 09:11:28 UTC (rev 130) @@ -9,6 +9,7 @@ SLTM(Debug) SLTM(CLI) SLTM(SessionOpen) +SLTM(SessionReuse) SLTM(SessionClose) SLTM(ClientAddr) SLTM(Request) Property changes on: trunk/varnish-cache/include/shmlog_tags.h ___________________________________________________________________ Name: svn:keywords + Id From phk at phk.freebsd.dk Thu Apr 6 09:15:45 2006 From: phk at phk.freebsd.dk (Poul-Henning Kamp) Date: Thu, 06 Apr 2006 11:15:45 +0200 Subject: r130 - trunk/varnish-cache/include In-Reply-To: Your message of "Thu, 06 Apr 2006 11:11:28 +0200." <20060406091128.A638D1ED676@projects.linpro.no> Message-ID: <11995.1144314945@critter.freebsd.dk> I am now able to handle multiple requests from the client on the same TCP connection. I'm leaking memory and backend sessions doing so, but at least I can now point my firefox at a website through varnish and get something back :-) -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk at FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence. From phk at projects.linpro.no Thu Apr 6 09:30:46 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:30:46 +0200 (CEST) Subject: r131 - trunk/varnish-cache/include Message-ID: <20060406093046.667541ED678@projects.linpro.no> Author: phk Date: 2006-04-06 11:30:46 +0200 (Thu, 06 Apr 2006) New Revision: 131 Modified: trunk/varnish-cache/include/shmlog_tags.h Log: Add shmlog tags for pipe and pass handling Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-06 09:11:28 UTC (rev 130) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-06 09:30:46 UTC (rev 131) @@ -12,6 +12,8 @@ SLTM(SessionReuse) SLTM(SessionClose) SLTM(ClientAddr) +SLTM(HandlingPass) +SLTM(HandlingPipe) SLTM(Request) SLTM(Response) SLTM(Status) From phk at projects.linpro.no Thu Apr 6 09:33:19 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:33:19 +0200 (CEST) Subject: r132 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060406093319.D11101ED679@projects.linpro.no> Author: phk Date: 2006-04-06 11:33:19 +0200 (Thu, 06 Apr 2006) New Revision: 132 Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pipe.c trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Rename hdr_end to a more sensible rcv_ptr which points to the first unaccounted for character in the buffer. Do Id Keyword Modified: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 09:30:46 UTC (rev 131) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-06 09:33:19 UTC (rev 132) @@ -165,7 +165,7 @@ continue; break; } - sp->hdr_end = ++p - sp->rcv; + sp->rcv_ptr = ++p - sp->rcv; event_del(sp->rd_e); sp->sesscb(sp); Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 09:30:46 UTC (rev 131) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 09:33:19 UTC (rev 132) @@ -45,11 +45,13 @@ * If client wants only this one request, piping is safer * and cheaper */ + VSL(SLT_HandlingPass, sp->fd, "pipe"); PipeSession(w, sp); return; } fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); + VSL(SLT_HandlingPass, sp->fd, "%d", fd); HttpdBuildSbuf(0, 1, w->sb, sp); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); @@ -60,6 +62,10 @@ 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 + */ HttpdGetHead(&sp2, w->eb, PassReturn); event_base_loop(w->eb, 0); HttpdAnalyze(&sp2, 2); @@ -74,11 +80,12 @@ i &= ~O_NONBLOCK; i = fcntl(sp2.fd, F_SETFL, i); assert(i != -1); - i = sp2.rcv_len - sp2.hdr_end; + i = sp2.rcv_len - sp2.rcv_ptr; if (i > 0) { - j = write(sp->fd, sp2.rcv + sp2.hdr_end, i); + 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; @@ -97,13 +104,10 @@ assert(cl == 0); } - if (sp->rcv_len > sp->hdr_end) { - memmove(sp->rcv, sp->rcv + sp->hdr_end, - sp->rcv_len - sp->hdr_end); - sp->rcv_len -= sp->hdr_end; - sp->rcv[sp->rcv_len] = '\0'; - } else { - sp->rcv_len = 0; - sp->rcv[sp->rcv_len] = '\0'; - } + /* 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; } Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-06 09:30:46 UTC (rev 131) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-06 09:33:19 UTC (rev 132) @@ -14,6 +14,7 @@ #include #include "libvarnish.h" +#include "shmlog.h" #include "vcl_lang.h" #include "cache.h" @@ -50,13 +51,14 @@ fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); + VSL(SLT_HandlingPipe, sp->fd, "%d", fd); HttpdBuildSbuf(0, 0, w->sb, sp); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); - i = sp->rcv_len - sp->hdr_end; + i = sp->rcv_len - sp->rcv_ptr; if (i > 0) { - j = write(sp->fd, sp->rcv + sp->hdr_end, i); + j = write(sp->fd, sp->rcv + sp->rcv_ptr, i); assert(j == i); } Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-06 09:30:46 UTC (rev 131) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-06 09:33:19 UTC (rev 132) @@ -49,7 +49,7 @@ /* Receive buffer for HTTP header */ char rcv[VCA_RXBUFSIZE + 1]; unsigned rcv_len; - unsigned hdr_end; + unsigned rcv_ptr; /* HTTP request info, points into rcv */ struct httphdr http; Property changes on: trunk/varnish-cache/include/vcl_lang.h ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-06 09:30:46 UTC (rev 131) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-06 09:33:19 UTC (rev 132) @@ -477,7 +477,7 @@ fputs(" /* Receive buffer for HTTP header */\n", f); fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f); fputs(" unsigned rcv_len;\n", f); - fputs(" unsigned hdr_end;\n", f); + fputs(" unsigned rcv_ptr;\n", f); fputs("\n", f); fputs(" /* HTTP request info, points into rcv */\n", f); fputs(" struct httphdr http;\n", f); Property changes on: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 09:38:00 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:38:00 +0200 (CEST) Subject: r133 - trunk/varnish-cache/bin/varnishlog Message-ID: <20060406093800.BBC991ED678@projects.linpro.no> Author: phk Date: 2006-04-06 11:38:00 +0200 (Thu, 06 Apr 2006) New Revision: 133 Modified: trunk/varnish-cache/bin/varnishlog/Makefile.am trunk/varnish-cache/bin/varnishlog/varnishlog.c Log: Output the fd in decimal instead of hex. Do Id Keyword Modified: trunk/varnish-cache/bin/varnishlog/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishlog/Makefile.am 2006-04-06 09:33:19 UTC (rev 132) +++ trunk/varnish-cache/bin/varnishlog/Makefile.am 2006-04-06 09:38:00 UTC (rev 133) @@ -1,4 +1,4 @@ -# $Id: Makefile.am 62 2006-03-23 15:31:20Z phk $ +# $Id$ INCLUDES = -I$(top_srcdir)/include Property changes on: trunk/varnish-cache/bin/varnishlog/Makefile.am ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/bin/varnishlog/varnishlog.c =================================================================== --- trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-06 09:33:19 UTC (rev 132) +++ trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-06 09:38:00 UTC (rev 133) @@ -39,6 +39,7 @@ { int fd; int i; + unsigned u; struct shmloghead slh; unsigned char *p; @@ -82,9 +83,9 @@ fflush(stdout); sleep(1); } - printf("%02x %02d %02x%02x %-12s <", - p[0], p[1], p[2], p[3], - tagnames[p[0]]); + u = (p[2] << 8) | p[3]; + printf("%02x %02d %4d %-12s <", + p[0], p[1], u, tagnames[p[0]]); if (p[1] > 0) fwrite(p + 4, p[1], 1, stdout); printf(">\n"); Property changes on: trunk/varnish-cache/bin/varnishlog/varnishlog.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 09:59:30 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 11:59:30 +0200 (CEST) Subject: r134 - in trunk/varnish-cache: include lib/libvcl Message-ID: <20060406095930.DADDC1ED67B@projects.linpro.no> Author: phk Date: 2006-04-06 11:59:30 +0200 (Thu, 06 Apr 2006) New Revision: 134 Modified: trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Pass Content-Encoding header Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-06 09:38:00 UTC (rev 133) +++ trunk/varnish-cache/include/http_headers.h 2006-04-06 09:59:30 UTC (rev 134) @@ -46,3 +46,5 @@ HTTPH("Vary", H_Vary, 2, 1, 0, 0, 0) HTTPH("Expires", H_Expires, 2, 1, 0, 0, 0) HTTPH("Location", H_Location, 2, 1, 0, 0, 0) +HTTPH("Content-Encoding", H_Content_Encoding, 2, 1, 0, 0, 0) + Property changes on: trunk/varnish-cache/include/http_headers.h ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-06 09:38:00 UTC (rev 133) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-06 09:59:30 UTC (rev 134) @@ -463,6 +463,8 @@ fputs("HTTPH(\"Vary\", H_Vary, 2, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"Expires\", H_Expires, 2, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"Location\", H_Location, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"Content-Encoding\", H_Content_Encoding, 2, 1, 0, 0, 0)\n", f); + fputs("\n", f); fputs("#undef HTTPH\n", f); fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); fputs(" unsigned nuhdr;\n", f); From phk at projects.linpro.no Thu Apr 6 10:00:45 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 12:00:45 +0200 (CEST) Subject: r135 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406100045.D711A1ED66D@projects.linpro.no> Author: phk Date: 2006-04-06 12:00:45 +0200 (Thu, 06 Apr 2006) New Revision: 135 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_backend.c Log: Add VBE_RecycleFd() function to recycle backend connections Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-06 09:59:30 UTC (rev 134) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-06 10:00:45 UTC (rev 135) @@ -25,7 +25,9 @@ int VBE_GetFd(struct backend *bp, void **ptr); void VBE_Pass(struct sess *sp); void VBE_ClosedFd(void *ptr); +void VBE_RecycleFd(void *ptr); + /* cache_httpd.c */ void HttpdAnalyze(struct sess *sp, int rr); void HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func); Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-06 09:59:30 UTC (rev 134) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-06 10:00:45 UTC (rev 135) @@ -128,6 +128,8 @@ return (vc->fd); } +/*--------------------------------------------------------------------*/ + void VBE_ClosedFd(void *ptr) { @@ -140,7 +142,20 @@ free(vc); } +/*--------------------------------------------------------------------*/ +void +VBE_RecycleFd(void *ptr) +{ + struct vbe_conn *vc; + + vc = ptr; + AZ(pthread_mutex_lock(&vbemtx)); + TAILQ_REMOVE(&vc->vbe->bconn, vc, list); + TAILQ_INSERT_HEAD(&vc->vbe->fconn, vc, list); + AZ(pthread_mutex_unlock(&vbemtx)); +} + /*--------------------------------------------------------------------*/ void Property changes on: trunk/varnish-cache/bin/varnishd/cache_backend.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Thu Apr 6 10:01:09 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Thu, 6 Apr 2006 12:01:09 +0200 (CEST) Subject: r136 - trunk/varnish-cache/bin/varnishd Message-ID: <20060406100109.87B8E1ED66C@projects.linpro.no> Author: phk Date: 2006-04-06 12:01:09 +0200 (Thu, 06 Apr 2006) New Revision: 136 Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c Log: Close or recycle backend connections as appropriate Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 10:00:45 UTC (rev 135) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-06 10:01:09 UTC (rev 136) @@ -104,6 +104,14 @@ assert(cl == 0); } + if (sp2.http.H_Connection != NULL && + !strcmp(sp2.http.H_Connection, "close")) { + close(fd); + VBE_ClosedFd(fd_token); + } 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, From phk at projects.linpro.no Tue Apr 11 08:28:20 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 11 Apr 2006 10:28:20 +0200 (CEST) Subject: r137 - trunk/varnish-cache/bin/varnishd Message-ID: <20060411082820.C90831ED66D@projects.linpro.no> Author: phk Date: 2006-04-11 10:28:20 +0200 (Tue, 11 Apr 2006) New Revision: 137 Added: trunk/varnish-cache/bin/varnishd/hash_simple_list.c Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_main.c trunk/varnish-cache/bin/varnishd/cache_shmlog.c trunk/varnish-cache/bin/varnishd/cache_vcl.c trunk/varnish-cache/bin/varnishd/cli_event.c trunk/varnish-cache/bin/varnishd/cli_event.h trunk/varnish-cache/bin/varnishd/heritage.h trunk/varnish-cache/bin/varnishd/mgt.h trunk/varnish-cache/bin/varnishd/tcp.c Log: Beginnings of the object lookup stuff: A simple list based implementation to get things moving. Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-06 10:01:09 UTC (rev 136) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-11 08:28:20 UTC (rev 137) @@ -15,6 +15,7 @@ cache_shmlog.c \ cache_vcl.c \ cli_event.c \ + hash_simple_list.c \ mgt_child.c \ tcp.c \ varnishd.c Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-06 10:01:09 UTC (rev 136) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-11 08:28:20 UTC (rev 137) @@ -15,6 +15,28 @@ struct worker; #endif +/* Hashing -----------------------------------------------------------*/ +struct object { /* XXX: this goes elsewhere in due time */ + unsigned char hash[16]; + unsigned refcnt; +}; + +typedef void hash_init_f(void); +typedef struct object *hash_lookup_f(unsigned char *key, struct object *nobj); +typedef void hash_purge_f(struct object *obj); + +struct hash_slinger { + const char *name; + hash_init_f *init; + hash_lookup_f *lookup; + hash_purge_f *purge; +}; + +extern struct hash_slinger hsl_slinger; + +/* Prototypes etc ----------------------------------------------------*/ + + /* cache_acceptor.c */ void *vca_main(void *arg); void vca_retire_session(struct sess *sp); Property changes on: trunk/varnish-cache/bin/varnishd/cache_main.c ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/bin/varnishd/cache_shmlog.c ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/bin/varnishd/cache_vcl.c ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/bin/varnishd/cli_event.c ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/bin/varnishd/cli_event.h ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/varnish-cache/bin/varnishd/hash_simple_list.c =================================================================== --- trunk/varnish-cache/bin/varnishd/hash_simple_list.c 2006-04-06 10:01:09 UTC (rev 136) +++ trunk/varnish-cache/bin/varnishd/hash_simple_list.c 2006-04-11 08:28:20 UTC (rev 137) @@ -0,0 +1,89 @@ +/* + * $Id$ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct hsl_entry { + TAILQ_ENTRY(hsl_entry) list; + struct object *obj; +}; + +static TAILQ_HEAD(, hsl_entry) hsl_head = TAILQ_HEAD_INITIALIZER(hsl_head); +static pthread_mutex_t hsl_mutex; + +static void +hsl_init(void) +{ + + AZ(pthread_mutex_init(&hsl_mutex, NULL)); +} + +static struct object * +hsl_lookup(unsigned char *key, struct object *nobj) +{ + struct hsl_entry *he, *he2; + int i; + + AZ(pthread_mutex_lock(&hsl_mutex)); + TAILQ_FOREACH(he, &hsl_head, list) { + i = memcmp(key, he->obj->hash, sizeof he->obj->hash); + if (i == 0) { + he->obj->refcnt++; + nobj = he->obj; + AZ(pthread_mutex_unlock(&hsl_mutex)); + return (nobj); + } + if (i < 0) + continue; + if (nobj == NULL) { + AZ(pthread_mutex_unlock(&hsl_mutex)); + return (NULL); + } + break; + } + he2 = calloc(sizeof *he2, 1); + assert(he2 != NULL); + he2->obj = nobj; + nobj->refcnt++; + if (he != NULL) + TAILQ_INSERT_BEFORE(he, he2, list); + else + TAILQ_INSERT_TAIL(&hsl_head, he2, list); + AZ(pthread_mutex_unlock(&hsl_mutex)); + return (nobj); +} + +static void +hsl_purge(struct object *obj) +{ + struct hsl_entry *he; + + assert(obj->refcnt > 0); + AZ(pthread_mutex_lock(&hsl_mutex)); + TAILQ_FOREACH(he, &hsl_head, list) { + if (he->obj == obj) { + TAILQ_REMOVE(&hsl_head, he, list); + AZ(pthread_mutex_unlock(&hsl_mutex)); + free(he); + return; + } + } + assert(he != NULL); +} + +struct hash_slinger hsl_slinger = { + "simple_list", + hsl_init, + hsl_lookup, + hsl_purge +}; Property changes on: trunk/varnish-cache/bin/varnishd/heritage.h ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/bin/varnishd/mgt.h ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/bin/varnishd/tcp.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Wed Apr 12 08:56:48 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Wed, 12 Apr 2006 10:56:48 +0200 (CEST) Subject: r138 - trunk/varnish-cache/include Message-ID: <20060412085648.DF2831ED502@projects.linpro.no> Author: phk Date: 2006-04-12 10:56:48 +0200 (Wed, 12 Apr 2006) New Revision: 138 Modified: trunk/varnish-cache/include/http_headers.h Log: Add ETag: header Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-11 08:28:20 UTC (rev 137) +++ trunk/varnish-cache/include/http_headers.h 2006-04-12 08:56:48 UTC (rev 138) @@ -47,4 +47,5 @@ HTTPH("Expires", H_Expires, 2, 1, 0, 0, 0) HTTPH("Location", H_Location, 2, 1, 0, 0, 0) HTTPH("Content-Encoding", H_Content_Encoding, 2, 1, 0, 0, 0) +HTTPH("ETag:", H_ETag, 2, 1, 0, 0, 0) From phk at projects.linpro.no Wed Apr 12 08:58:54 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Wed, 12 Apr 2006 10:58:54 +0200 (CEST) Subject: r139 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060412085854.4EF951ED687@projects.linpro.no> Author: phk Date: 2006-04-12 10:58:54 +0200 (Wed, 12 Apr 2006) New Revision: 139 Modified: trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/bin/varnishd/cache_vcl.c trunk/varnish-cache/bin/varnishd/varnishd.c trunk/varnish-cache/include/cli.h trunk/varnish-cache/include/cli_priv.h trunk/varnish-cache/include/libvcl.h trunk/varnish-cache/include/shmlog.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_compile.c trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c trunk/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl trunk/varnish-cache/lib/libvcl/vcl_priv.h trunk/varnish-cache/lib/libvcl/vcl_token_defs.h Log: Implement the three function VCL model in the compiler. Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-12 08:58:54 UTC (rev 139) @@ -16,10 +16,6 @@ #endif /* Hashing -----------------------------------------------------------*/ -struct object { /* XXX: this goes elsewhere in due time */ - unsigned char hash[16]; - unsigned refcnt; -}; typedef void hash_init_f(void); typedef struct object *hash_lookup_f(unsigned char *key, struct object *nobj); Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-12 08:58:54 UTC (rev 139) @@ -48,7 +48,7 @@ sp->backend = sp->vcl->default_backend; /* Call the VCL program */ - sp->vcl->main_func(sp); + sp->vcl->recv_func(sp); printf("Handling: %d\n", sp->handling); switch(sp->handling) { Modified: trunk/varnish-cache/bin/varnishd/cache_vcl.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-12 08:58:54 UTC (rev 139) @@ -196,3 +196,7 @@ sess->handling = HND_Pass; sess->done++; } + +void VCL_insert(VCL_FARGS) { } +void VCL_fetch(VCL_FARGS) { } +void VCL_error(VCL_FARGS, unsigned err, const char *str) { } Modified: trunk/varnish-cache/bin/varnishd/varnishd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-12 08:58:54 UTC (rev 139) @@ -71,21 +71,27 @@ "backend default {\n" " set backend.host = \"%s\";\n" "}\n" - "sub main {\n" - " pass;\n" -#if 0 + "sub vcl_recv {\n" " if (req.request != \"GET\" && req.request != \"HEAD\") {\n" " pass;\n" " }\n" - " lookup;\n" + "}\n" + "\n" + "sub vcl_lookup {\n" " if (!obj.valid) {\n" " fetch;\n" - " if (obj.cacheable) {\n" - " insert;\n" - " }\n" " }\n" -#endif + " if (!obj.cacheable) {\n" + " pass;\n" + " }\n" "}\n" + "\n" + "sub vcl_fetch {\n" + " if (!obj.valid) {\n" + " error;\n" + " }\n" + " insert;\n" + "}\n" "", bflag); assert(buf != NULL); sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); Property changes on: trunk/varnish-cache/include/cli.h ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/include/cli_priv.h ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/include/libvcl.h ___________________________________________________________________ Name: svn:keywords + Id Property changes on: trunk/varnish-cache/include/shmlog.h ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-12 08:58:54 UTC (rev 139) @@ -40,6 +40,13 @@ unsigned nuhdr; }; +struct object { + unsigned char hash[16]; + unsigned refcnt; + unsigned valid; + unsigned cacheable; +}; + struct sess { int fd; @@ -68,6 +75,7 @@ sesscb_f *sesscb; struct backend *backend; + struct object *obj; struct VCL_conf *vcl; /* Various internal stuff */ @@ -93,14 +101,15 @@ #define VCL_PASS_ARGS sess void VCL_count(unsigned); -void VCL_no_cache(); -void VCL_no_new_cache(); +void VCL_no_cache(VCL_FARGS); +void VCL_no_new_cache(VCL_FARGS); int ip_match(unsigned, struct vcl_acl *); int string_match(const char *, const char *); int VCL_rewrite(const char *, const char *); -int VCL_error(unsigned, const char *); +void VCL_error(VCL_FARGS, unsigned, const char *); void VCL_pass(VCL_FARGS); -int VCL_fetch(void); +void VCL_fetch(VCL_FARGS); +void VCL_insert(VCL_FARGS); int VCL_switch_config(const char *); typedef void vcl_init_f(void); @@ -110,7 +119,9 @@ unsigned magic; #define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */ vcl_init_f *init_func; - vcl_func_f *main_func; + vcl_func_f *recv_func; + vcl_func_f *lookup_func; + vcl_func_f *fetch_func; struct backend *default_backend; struct vcl_ref *ref; unsigned nref; Modified: trunk/varnish-cache/lib/libvcl/vcl_compile.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-04-12 08:58:54 UTC (rev 139) @@ -121,6 +121,9 @@ static struct var vars[] = { + { "req.request", STRING, 0, "sess->http.req" }, + { "obj.valid", BOOL, 0, "sess->obj->valid" }, + { "obj.cacheable", BOOL, 0, "sess->obj->cacheable" }, #if 0 { "req.ttlfactor", FLOAT, 0, "req->ttlfactor" }, { "req.url.host", STRING, 0, "req->url.host" }, @@ -659,6 +662,15 @@ tl->t->e - tl->t->b, tl->t->b); NextToken(tl); break; + case T_NEQ: + I(tl); sbuf_printf(tl->fc, "strcmp(%s, ", vp->cname); + NextToken(tl); + ExpectErr(tl, CSTR); + sbuf_printf(tl->fc, "%*.*s)\n", + tl->t->e - tl->t->b, + tl->t->e - tl->t->b, tl->t->b); + NextToken(tl); + break; default: sbuf_printf(tl->sb, "Illegal condition "); ErrToken(tl, tl->t); @@ -874,29 +886,41 @@ switch (at->tok) { case T_NO_NEW_CACHE: I(tl); - sbuf_printf(tl->fc, "VCL_no_new_cache();\n"); + sbuf_printf(tl->fc, "VCL_no_new_cache(VCL_PASS_ARGS);\n"); return; case T_NO_CACHE: I(tl); - sbuf_printf(tl->fc, "VCL_no_cache();\n"); + sbuf_printf(tl->fc, "VCL_no_cache(VCL_PASS_ARGS);\n"); return; case T_FINISH: - I(tl); - sbuf_printf(tl->fc, "return;\n"); + I(tl); sbuf_printf(tl->fc, "sess->done = 1;\n"); + I(tl); sbuf_printf(tl->fc, "return;\n"); return; case T_PASS: I(tl); sbuf_printf(tl->fc, "VCL_pass(VCL_PASS_ARGS);\n"); - sbuf_printf(tl->fc, "return;\n"); + I(tl); sbuf_printf(tl->fc, "sess->done = 1;\n"); + I(tl); sbuf_printf(tl->fc, "return;\n"); return; case T_FETCH: I(tl); - sbuf_printf(tl->fc, "VCL_fetch();\n"); + sbuf_printf(tl->fc, "VCL_fetch(VCL_PASS_ARGS);\n"); + I(tl); sbuf_printf(tl->fc, "sess->done = 1;\n"); + I(tl); sbuf_printf(tl->fc, "return;\n"); return; + case T_INSERT: + I(tl); + sbuf_printf(tl->fc, "VCL_insert(VCL_PASS_ARGS);\n"); + I(tl); sbuf_printf(tl->fc, "sess->done = 1;\n"); + I(tl); sbuf_printf(tl->fc, "return;\n"); + return; case T_ERROR: - a = UintVal(tl); + if (tl->t->tok == CNUM) + a = UintVal(tl); + else + a = 0; I(tl); - sbuf_printf(tl->fc, "VCL_error(%u, ", a); + sbuf_printf(tl->fc, "VCL_error(VCL_PASS_ARGS, %u, ", a); if (tl->t->tok == CSTR) { sbuf_printf(tl->fc, "%*.*s);\n", tl->t->e - tl->t->b, @@ -904,6 +928,8 @@ NextToken(tl); } else sbuf_printf(tl->fc, "(const char *)0);\n"); + I(tl); sbuf_printf(tl->fc, "sess->done = 1;\n"); + I(tl); sbuf_printf(tl->fc, "return;\n"); return; case T_SWITCH_CONFIG: ExpectErr(tl, ID); @@ -1537,9 +1563,10 @@ "\t.magic = VCL_CONF_MAGIC,\n"); sbuf_printf(tl->fc, "\t.init_func = VCL_Init,\n"); + sbuf_printf(tl->fc, "\t.recv_func = VCL_function_vcl_recv,\n"); + sbuf_printf(tl->fc, "\t.lookup_func = VCL_function_vcl_lookup,\n"); + sbuf_printf(tl->fc, "\t.fetch_func = VCL_function_vcl_fetch,\n"); sbuf_printf(tl->fc, - "\t.main_func = VCL_function_main,\n"); - sbuf_printf(tl->fc, "\t.default_backend = &VCL_backend_default,\n"); sbuf_printf(tl->fc, "\t.ref = VCL_ref,\n"); Property changes on: trunk/varnish-cache/lib/libvcl/vcl_compile.c ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-12 08:58:54 UTC (rev 139) @@ -218,6 +218,12 @@ } return (0); case 'i': + if (p[0] == 'i' && p[1] == 'n' && p[2] == 's' && + p[3] == 'e' && p[4] == 'r' && p[5] == 't' + && !isvar(p[6])) { + *q = p + 6; + return (T_INSERT); + } if (p[0] == 'i' && p[1] == 'f' && !isvar(p[2])) { *q = p + 2; return (T_IF); @@ -360,6 +366,7 @@ vcl_tnames[T_IF] = "if"; vcl_tnames[T_INC] = "++"; vcl_tnames[T_INCR] = "+="; + vcl_tnames[T_INSERT] = "insert"; vcl_tnames[T_LEQ] = "<="; vcl_tnames[T_MUL] = "*="; vcl_tnames[T_NEQ] = "!="; @@ -464,12 +471,20 @@ fputs("HTTPH(\"Expires\", H_Expires, 2, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"Location\", H_Location, 2, 1, 0, 0, 0)\n", f); fputs("HTTPH(\"Content-Encoding\", H_Content_Encoding, 2, 1, 0, 0, 0)\n", f); + fputs("HTTPH(\"ETag:\", H_ETag, 2, 1, 0, 0, 0)\n", f); fputs("\n", f); fputs("#undef HTTPH\n", f); fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); fputs(" unsigned nuhdr;\n", f); fputs("};\n", f); fputs("\n", f); + fputs("struct object { \n", f); + fputs(" unsigned char hash[16];\n", f); + fputs(" unsigned refcnt;\n", f); + fputs(" unsigned valid;\n", f); + fputs(" unsigned cacheable;\n", f); + fputs("};\n", f); + fputs("\n", f); fputs("struct sess {\n", f); fputs(" int fd;\n", f); fputs("\n", f); @@ -498,6 +513,7 @@ fputs(" sesscb_f *sesscb;\n", f); fputs("\n", f); fputs(" struct backend *backend;\n", f); + fputs(" struct object *obj;\n", f); fputs(" struct VCL_conf *vcl;\n", f); fputs("\n", f); fputs(" /* Various internal stuff */\n", f); @@ -523,14 +539,15 @@ fputs("#define VCL_PASS_ARGS sess\n", f); fputs("\n", f); fputs("void VCL_count(unsigned);\n", f); - fputs("void VCL_no_cache();\n", f); - fputs("void VCL_no_new_cache();\n", f); + fputs("void VCL_no_cache(VCL_FARGS);\n", f); + fputs("void VCL_no_new_cache(VCL_FARGS);\n", f); fputs("int ip_match(unsigned, struct vcl_acl *);\n", f); fputs("int string_match(const char *, const char *);\n", f); fputs("int VCL_rewrite(const char *, const char *);\n", f); - fputs("int VCL_error(unsigned, const char *);\n", f); + fputs("void VCL_error(VCL_FARGS, unsigned, const char *);\n", f); fputs("void VCL_pass(VCL_FARGS);\n", f); - fputs("int VCL_fetch(void);\n", f); + fputs("void VCL_fetch(VCL_FARGS);\n", f); + fputs("void VCL_insert(VCL_FARGS);\n", f); fputs("int VCL_switch_config(const char *);\n", f); fputs("\n", f); fputs("typedef void vcl_init_f(void);\n", f); @@ -540,7 +557,9 @@ fputs(" unsigned magic;\n", f); fputs("#define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */\n", f); fputs(" vcl_init_f *init_func;\n", f); - fputs(" vcl_func_f *main_func;\n", f); + fputs(" vcl_func_f *recv_func;\n", f); + fputs(" vcl_func_f *lookup_func;\n", f); + fputs(" vcl_func_f *fetch_func;\n", f); fputs(" struct backend *default_backend;\n", f); fputs(" struct vcl_ref *ref;\n", f); fputs(" unsigned nref;\n", f); Modified: trunk/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/lib/libvcl/vcl_gen_fixed_token.tcl 2006-04-12 08:58:54 UTC (rev 139) @@ -15,6 +15,7 @@ error pass fetch + insert call no_cache no_new_cache Property changes on: trunk/varnish-cache/lib/libvcl/vcl_priv.h ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/lib/libvcl/vcl_token_defs.h =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_token_defs.h 2006-04-12 08:56:48 UTC (rev 138) +++ trunk/varnish-cache/lib/libvcl/vcl_token_defs.h 2006-04-12 08:58:54 UTC (rev 139) @@ -16,29 +16,30 @@ #define T_ERROR 137 #define T_PASS 138 #define T_FETCH 139 -#define T_CALL 140 -#define T_NO_CACHE 141 -#define T_NO_NEW_CACHE 142 -#define T_SET 143 -#define T_REWRITE 144 -#define T_FINISH 145 -#define T_SWITCH_CONFIG 146 -#define T_INC 147 -#define T_DEC 148 -#define T_CAND 149 -#define T_COR 150 -#define T_LEQ 151 -#define T_EQ 152 -#define T_NEQ 153 -#define T_GEQ 154 -#define T_SHR 155 -#define T_SHL 156 -#define T_INCR 157 -#define T_DECR 158 -#define T_MUL 159 -#define T_DIV 160 -#define ID 161 -#define VAR 162 -#define CNUM 163 -#define CSTR 164 -#define EOI 165 +#define T_INSERT 140 +#define T_CALL 141 +#define T_NO_CACHE 142 +#define T_NO_NEW_CACHE 143 +#define T_SET 144 +#define T_REWRITE 145 +#define T_FINISH 146 +#define T_SWITCH_CONFIG 147 +#define T_INC 148 +#define T_DEC 149 +#define T_CAND 150 +#define T_COR 151 +#define T_LEQ 152 +#define T_EQ 153 +#define T_NEQ 154 +#define T_GEQ 155 +#define T_SHR 156 +#define T_SHL 157 +#define T_INCR 158 +#define T_DECR 159 +#define T_MUL 160 +#define T_DIV 161 +#define ID 162 +#define VAR 163 +#define CNUM 164 +#define CSTR 165 +#define EOI 166 Property changes on: trunk/varnish-cache/lib/libvcl/vcl_token_defs.h ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Tue Apr 18 07:34:24 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 18 Apr 2006 09:34:24 +0200 (CEST) Subject: r140 - trunk/varnish-cache/bin/varnishd Message-ID: <20060418073424.CD8141ED61F@projects.linpro.no> Author: phk Date: 2006-04-18 09:34:24 +0200 (Tue, 18 Apr 2006) New Revision: 140 Added: trunk/varnish-cache/bin/varnishd/storage_malloc.c Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/hash_simple_list.c Log: Add trivial malloc backed storage backend. Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-12 08:58:54 UTC (rev 139) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-18 07:34:24 UTC (rev 140) @@ -17,6 +17,7 @@ cli_event.c \ hash_simple_list.c \ mgt_child.c \ + storage_malloc.c \ tcp.c \ varnishd.c Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-12 08:58:54 UTC (rev 139) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-18 07:34:24 UTC (rev 140) @@ -30,6 +30,28 @@ extern struct hash_slinger hsl_slinger; +/* Storage -----------------------------------------------------------*/ + +struct storage { + TAILQ_ENTRY(storage) list; + void *ptr; + unsigned len; + void *priv; +}; + +typedef void storage_init_f(void); +typedef struct storage *storage_alloc_f(unsigned size); +typedef void storage_free_f(struct storage *); + +struct stevedore { + const char *name; + storage_init_f *init; + storage_alloc_f *alloc; + storage_free_f *free; +}; + +extern struct stevedore sma_stevedore; + /* Prototypes etc ----------------------------------------------------*/ Property changes on: trunk/varnish-cache/bin/varnishd/hash_simple_list.c ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/varnish-cache/bin/varnishd/storage_malloc.c =================================================================== --- trunk/varnish-cache/bin/varnishd/storage_malloc.c 2006-04-12 08:58:54 UTC (rev 139) +++ trunk/varnish-cache/bin/varnishd/storage_malloc.c 2006-04-18 07:34:24 UTC (rev 140) @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * Storage method based on malloc(3) + */ + +#include +#include +#include +#include + +#include "vcl_lang.h" +#include "cache.h" + +struct sma { + struct storage s; +}; + +static void +sma_init(void) +{ +} + +static struct storage * +sma_alloc(unsigned size) +{ + struct sma *sma; + + sma = calloc(sizeof *sma, 1); + assert(sma != NULL); + sma->s.priv = sma; + sma->s.ptr = malloc(size); + assert(sma->s.ptr != NULL); + sma->s.len = size; + return (&sma->s); +} + +static void +sma_free(struct storage *s) +{ + struct sma *sma; + + sma = s->priv; + free(sma->s.ptr); + free(sma); +} + +struct stevedore sma_stevedore = { + "Malloc", + sma_init, + sma_alloc, + sma_free +}; Property changes on: trunk/varnish-cache/bin/varnishd/storage_malloc.c ___________________________________________________________________ Name: svn:keywords + Id From phk at projects.linpro.no Tue Apr 18 08:23:44 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 18 Apr 2006 10:23:44 +0200 (CEST) Subject: r141 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060418082344.6E5FA1ED691@projects.linpro.no> Author: phk Date: 2006-04-18 10:23:44 +0200 (Tue, 18 Apr 2006) New Revision: 141 Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_main.c trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/bin/varnishd/cache_vcl.c trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Add busyflag and strorage link to objects. Initialize default hasher and stevedore. Give each workerthread an object pointer to be kept populated with a template object for when lookups miss and need to insert one. Add libmd to get MD5, (choice of hash-algorithm to be revisited later) Implement lookup, begin on fetch. Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-18 08:23:44 UTC (rev 141) @@ -29,4 +29,5 @@ $(top_builddir)/lib/libvarnish/libvarnish.la \ $(top_builddir)/lib/libvcl/libvcl.la \ $(top_builddir)/contrib/libevent/libevent.la \ - -lpthread + -lpthread \ + -lmd Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-18 08:23:44 UTC (rev 141) @@ -10,6 +10,7 @@ struct event_base *eb; struct event e1, e2; struct sbuf *sb; + struct object *nobj; }; #else struct worker; @@ -30,6 +31,8 @@ extern struct hash_slinger hsl_slinger; +extern struct hash_slinger *hash; + /* Storage -----------------------------------------------------------*/ struct storage { @@ -52,6 +55,8 @@ extern struct stevedore sma_stevedore; +extern struct stevedore *stevedore; + /* Prototypes etc ----------------------------------------------------*/ Modified: trunk/varnish-cache/bin/varnishd/cache_main.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_main.c 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/bin/varnishd/cache_main.c 2006-04-18 08:23:44 UTC (rev 141) @@ -25,6 +25,9 @@ static struct event ev_keepalive; static pthread_t vca_thread; +struct hash_slinger *hash; +struct stevedore *stevedore; + pthread_mutex_t sessmtx; /*--------------------------------------------------------------------*/ @@ -114,6 +117,12 @@ eb = event_init(); assert(eb != NULL); + hash = &hsl_slinger; + hash->init(); + + stevedore = &sma_stevedore; + stevedore->init(); + CVCL_Load(heritage.vcl_file, "boot"); cli = cli_setup(eb, heritage.fds[2], heritage.fds[1], 0, cli_proto); Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-18 08:23:44 UTC (rev 141) @@ -3,6 +3,7 @@ */ #include +#include #include #include #include @@ -10,8 +11,10 @@ #include #include #include +#include #include "libvarnish.h" +#include "shmlog.h" #include "vcl_lang.h" #include "cache.h" @@ -19,11 +22,55 @@ static pthread_cond_t shdcnd; +static int +LookupSession(struct worker *w, struct sess *sp) +{ + struct object *o; + unsigned char key[16]; + MD5_CTX ctx; + + if (w->nobj == NULL) { + w->nobj = calloc(sizeof *w->nobj, 1); + assert(w->nobj != NULL); + w->nobj->busy = 1; + TAILQ_INIT(&w->nobj->store); + } + + MD5Init(&ctx); + MD5Update(&ctx, sp->http.url, strlen(sp->http.url)); + MD5Final(key, &ctx); + o = hash->lookup(key, w->nobj); + if (o == w->nobj) + w->nobj = NULL; + /* + * XXX: if obj is busy, park session on it + */ + + sp->obj = o; + sp->handling = HND_Unclass; + sp->vcl->lookup_func(sp); + if (sp->handling == HND_Unclass) { + if (o->valid && o->cacheable) + sp->handling = HND_Deliver; + else + sp->handling = HND_Pass; + } + return (0); +} + +static int +FetchSession(struct worker *w, struct sess *sp) +{ + + assert(w == NULL); +} + static void * CacheWorker(void *priv) { struct sess *sp; struct worker w; + int done; memset(&w, 0, sizeof w); w.eb = event_init(); @@ -47,19 +94,36 @@ HttpdAnalyze(sp, 1); sp->backend = sp->vcl->default_backend; - /* Call the VCL program */ + + /* + * Call the VCL recv function. + * Default action is to lookup + */ + sp->handling = HND_Lookup; + sp->vcl->recv_func(sp); - printf("Handling: %d\n", sp->handling); - switch(sp->handling) { - case HND_Unclass: - case HND_Handle: - case HND_Pipe: - PipeSession(&w, sp); - break; - case HND_Pass: - PassSession(&w, sp); - break; + for (done = 0; !done; ) { + printf("Handling: %d\n", sp->handling); + switch(sp->handling) { + case HND_Lookup: + done = LookupSession(&w, sp); + break; + case HND_Fetch: + done = FetchSession(&w, sp); + break; + case HND_Pipe: + PipeSession(&w, sp); + done = 1; + break; + case HND_Pass: + PassSession(&w, sp); + done = 1; + break; + case HND_Unclass: + case HND_Deliver: + assert(sp->handling == HND_Unclass); + } } AZ(pthread_mutex_lock(&sessmtx)); Modified: trunk/varnish-cache/bin/varnishd/cache_vcl.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-18 08:23:44 UTC (rev 141) @@ -198,5 +198,11 @@ } void VCL_insert(VCL_FARGS) { } -void VCL_fetch(VCL_FARGS) { } -void VCL_error(VCL_FARGS, unsigned err, const char *str) { } + +void VCL_fetch(VCL_FARGS) { + sess->handling = HND_Fetch; + sess->done++; +} + +void VCL_error(VCL_FARGS, unsigned err, const char *str) { +} Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-18 08:23:44 UTC (rev 141) @@ -45,6 +45,10 @@ unsigned refcnt; unsigned valid; unsigned cacheable; + + unsigned busy; + + TAILQ_HEAD(, storage) store; }; struct sess { @@ -63,9 +67,11 @@ enum { HND_Unclass, - HND_Handle, + HND_Deliver, HND_Pass, - HND_Pipe + HND_Pipe, + HND_Lookup, + HND_Fetch } handling; char done; Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-18 07:34:24 UTC (rev 140) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-18 08:23:44 UTC (rev 141) @@ -483,6 +483,10 @@ fputs(" unsigned refcnt;\n", f); fputs(" unsigned valid;\n", f); fputs(" unsigned cacheable;\n", f); + fputs("\n", f); + fputs(" unsigned busy;\n", f); + fputs("\n", f); + fputs(" TAILQ_HEAD(, storage) store;\n", f); fputs("};\n", f); fputs("\n", f); fputs("struct sess {\n", f); @@ -501,9 +505,11 @@ fputs("\n", f); fputs(" enum {\n", f); fputs(" HND_Unclass,\n", f); - fputs(" HND_Handle,\n", f); + fputs(" HND_Deliver,\n", f); fputs(" HND_Pass,\n", f); - fputs(" HND_Pipe\n", f); + fputs(" HND_Pipe,\n", f); + fputs(" HND_Lookup,\n", f); + fputs(" HND_Fetch\n", f); fputs(" } handling;\n", f); fputs("\n", f); fputs(" char done;\n", f); From phk at projects.linpro.no Wed Apr 19 06:34:11 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Wed, 19 Apr 2006 08:34:11 +0200 (CEST) Subject: r142 - in trunk/varnish-cache: bin/varnishd bin/varnishlog include lib/libvcl Message-ID: <20060419063411.2035E1ED61F@projects.linpro.no> Author: phk Date: 2006-04-19 08:34:10 +0200 (Wed, 19 Apr 2006) New Revision: 142 Added: trunk/varnish-cache/bin/varnishd/cache_fetch.c Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/bin/varnishd/hash_simple_list.c trunk/varnish-cache/bin/varnishlog/varnishlog.c trunk/varnish-cache/include/shmlog_tags.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Implement enough of FetchSession and DeliverSession that we can actually deliver a cached object. Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-19 06:34:10 UTC (rev 142) @@ -7,6 +7,7 @@ varnishd_SOURCES = \ cache_acceptor.c \ cache_backend.c \ + cache_fetch.c \ cache_httpd.c \ cache_main.c \ cache_pool.c \ Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-19 06:34:10 UTC (rev 142) @@ -20,12 +20,14 @@ typedef void hash_init_f(void); typedef struct object *hash_lookup_f(unsigned char *key, struct object *nobj); +typedef void hash_deref_f(struct object *obj); typedef void hash_purge_f(struct object *obj); struct hash_slinger { const char *name; hash_init_f *init; hash_lookup_f *lookup; + hash_deref_f *deref; hash_purge_f *purge; }; @@ -37,7 +39,7 @@ struct storage { TAILQ_ENTRY(storage) list; - void *ptr; + unsigned char *ptr; unsigned len; void *priv; }; @@ -72,6 +74,8 @@ void VBE_ClosedFd(void *ptr); void VBE_RecycleFd(void *ptr); +/* cache_fetch.c */ +int FetchSession(struct worker *w, struct sess *sp); /* cache_httpd.c */ void HttpdAnalyze(struct sess *sp, int rr); Added: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-19 06:34:10 UTC (rev 142) @@ -0,0 +1,125 @@ +/* + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libvarnish.h" +#include "shmlog.h" +#include "vcl_lang.h" +#include "cache.h" + +static void +FetchReturn(struct sess *sp) +{ + + /* do nothing */ +} + +/*--------------------------------------------------------------------*/ +int +FetchSession(struct worker *w, struct sess *sp) +{ + int fd, i; + void *fd_token; + struct sess sp2; + off_t cl; + struct storage *st; + unsigned char *p; + + fd = VBE_GetFd(sp->backend, &fd_token); + assert(fd != -1); + VSL(SLT_HandlingFetch, sp->fd, "%d", fd); + + HttpdBuildSbuf(0, 1, w->sb, sp); + i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); + + /* 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 + */ + HttpdGetHead(&sp2, w->eb, FetchReturn); + event_base_loop(w->eb, 0); + HttpdAnalyze(&sp2, 2); + + /* XXX: fill in object from headers */ + sp->obj->valid = 1; + sp->obj->cacheable = 1; + + /* XXX: unbusy, and kick other sessions into action */ + sp->obj->busy = 0; + + assert (sp2.http.H_Content_Length != NULL); /* XXX */ + + cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); + + sp->handling = HND_Unclass; + sp->vcl->fetch_func(sp); + + st = stevedore->alloc(cl); + TAILQ_INSERT_TAIL(&sp->obj->store, st, list); + st->len = cl; + sp->obj->len = cl; + p = st->ptr; + + i = fcntl(sp2.fd, F_GETFL); /* XXX ? */ + i &= ~O_NONBLOCK; + i = fcntl(sp2.fd, F_SETFL, i); + + i = sp2.rcv_len - sp2.rcv_ptr; + if (i > 0) { + memcpy(p, sp2.rcv + sp2.rcv_ptr, i); + p += i; + cl -= i; + } + if (cl != 0) { + i = read(sp2.fd, p, cl); + VSL(SLT_Debug, 0, "R i %d cl %jd", i, cl); + assert(i == cl); + } + + HttpdBuildSbuf(1, 1, w->sb, &sp2); + i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); + + i = write(sp->fd, st->ptr, st->len); + VSL(SLT_Debug, 0, "W i %d st->len %u", i, st->len); + assert(i == st->len); + + hash->deref(sp->obj); + + if (sp2.http.H_Connection != NULL && + !strcmp(sp2.http.H_Connection, "close")) { + close(fd); + VBE_ClosedFd(fd_token); + } 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; + return (1); +} Property changes on: trunk/varnish-cache/bin/varnishd/cache_fetch.c ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-19 06:34:10 UTC (rev 142) @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -40,8 +41,12 @@ MD5Update(&ctx, sp->http.url, strlen(sp->http.url)); MD5Final(key, &ctx); o = hash->lookup(key, w->nobj); - if (o == w->nobj) + if (o == w->nobj) { + VSL(SLT_Debug, 0, "Lookup new %p %s", o, sp->http.url); w->nobj = NULL; + } else { + VSL(SLT_Debug, 0, "Lookup found %p %s", o, sp->http.url); + } /* * XXX: if obj is busy, park session on it */ @@ -59,10 +64,26 @@ } static int -FetchSession(struct worker *w, struct sess *sp) +DeliverSession(struct worker *w, struct sess *sp) { + char buf[BUFSIZ]; + int i, j; + struct storage *st; - assert(w == NULL); + sprintf(buf, + "HTTP/1.1 200 OK\r\n" + "Server: Varnish\r\n" + "Content-Length: %u\r\n" + "\r\n", sp->obj->len); + + j = strlen(buf); + i = write(sp->fd, buf, j); + assert(i == j); + TAILQ_FOREACH(st, &sp->obj->store, list) { + i = write(sp->fd, st->ptr, st->len); + assert(i == st->len); + } + return (1); } static void * @@ -112,6 +133,9 @@ case HND_Fetch: done = FetchSession(&w, sp); break; + case HND_Deliver: + done = DeliverSession(&w, sp); + break; case HND_Pipe: PipeSession(&w, sp); done = 1; @@ -121,15 +145,22 @@ done = 1; break; case HND_Unclass: - case HND_Deliver: assert(sp->handling == HND_Unclass); } } + if (sp->http.H_Connection != NULL && + !strcmp(sp->http.H_Connection, "close")) { + close(sp->fd); + sp->fd = -1; + } AZ(pthread_mutex_lock(&sessmtx)); RelVCL(sp->vcl); sp->vcl = NULL; - vca_recycle_session(sp); + if (sp->fd < 0) + vca_retire_session(sp); + else + vca_recycle_session(sp); } } Modified: trunk/varnish-cache/bin/varnishd/hash_simple_list.c =================================================================== --- trunk/varnish-cache/bin/varnishd/hash_simple_list.c 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/bin/varnishd/hash_simple_list.c 2006-04-19 06:34:10 UTC (rev 142) @@ -55,6 +55,7 @@ assert(he2 != NULL); he2->obj = nobj; nobj->refcnt++; + memcpy(nobj->hash, key, sizeof nobj->hash); if (he != NULL) TAILQ_INSERT_BEFORE(he, he2, list); else @@ -64,6 +65,15 @@ } static void +hsl_deref(struct object *obj) +{ + + AZ(pthread_mutex_lock(&hsl_mutex)); + obj->refcnt--; + AZ(pthread_mutex_unlock(&hsl_mutex)); +} + +static void hsl_purge(struct object *obj) { struct hsl_entry *he; @@ -85,5 +95,6 @@ "simple_list", hsl_init, hsl_lookup, + hsl_deref, hsl_purge }; Modified: trunk/varnish-cache/bin/varnishlog/varnishlog.c =================================================================== --- trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-19 06:34:10 UTC (rev 142) @@ -40,6 +40,7 @@ int fd; int i; unsigned u; + unsigned startup; struct shmloghead slh; unsigned char *p; @@ -74,6 +75,7 @@ for (i = 0; stagnames[i].tag != SLT_ENDMARKER; i++) tagnames[stagnames[i].tag] = stagnames[i].name; + startup = 1; while (1) { p = logstart; while (1) { @@ -82,13 +84,16 @@ while (*p == SLT_ENDMARKER) { fflush(stdout); sleep(1); + startup = 0; } u = (p[2] << 8) | p[3]; - printf("%02x %02d %4d %-12s <", - p[0], p[1], u, tagnames[p[0]]); - if (p[1] > 0) - fwrite(p + 4, p[1], 1, stdout); - printf(">\n"); + if (!startup) { + printf("%02x %02d %4d %-12s <", + p[0], p[1], u, tagnames[p[0]]); + if (p[1] > 0) + fwrite(p + 4, p[1], 1, stdout); + printf(">\n"); + } p += p[1] + 4; } } Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-19 06:34:10 UTC (rev 142) @@ -12,6 +12,7 @@ SLTM(SessionReuse) SLTM(SessionClose) SLTM(ClientAddr) +SLTM(HandlingFetch) SLTM(HandlingPass) SLTM(HandlingPipe) SLTM(Request) Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-19 06:34:10 UTC (rev 142) @@ -47,6 +47,7 @@ unsigned cacheable; unsigned busy; + unsigned len; TAILQ_HEAD(, storage) store; }; Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-18 08:23:44 UTC (rev 141) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-19 06:34:10 UTC (rev 142) @@ -485,6 +485,7 @@ fputs(" unsigned cacheable;\n", f); fputs("\n", f); fputs(" unsigned busy;\n", f); + fputs(" unsigned len;\n", f); fputs("\n", f); fputs(" TAILQ_HEAD(, storage) store;\n", f); fputs("};\n", f); From phk at projects.linpro.no Wed Apr 19 06:38:57 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Wed, 19 Apr 2006 08:38:57 +0200 (CEST) Subject: r143 - trunk/varnish-cache/bin/varnishd Message-ID: <20060419063857.A48331ED698@projects.linpro.no> Author: phk Date: 2006-04-19 08:38:57 +0200 (Wed, 19 Apr 2006) New Revision: 143 Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c Log: Loop until we have read it all Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-19 06:34:10 UTC (rev 142) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-19 06:38:57 UTC (rev 143) @@ -91,10 +91,13 @@ p += i; cl -= i; } - if (cl != 0) { + + while (cl != 0) { i = read(sp2.fd, p, cl); + assert(i > 0); VSL(SLT_Debug, 0, "R i %d cl %jd", i, cl); - assert(i == cl); + p += i; + cl -= i; } HttpdBuildSbuf(1, 1, w->sb, &sp2); From phk at projects.linpro.no Mon Apr 24 19:09:32 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 24 Apr 2006 21:09:32 +0200 (CEST) Subject: r144 - trunk/varnish-cache/include Message-ID: <20060424190932.33CF11ED61F@projects.linpro.no> Author: phk Date: 2006-04-24 21:09:32 +0200 (Mon, 24 Apr 2006) New Revision: 144 Modified: trunk/varnish-cache/include/http_headers.h Log: Sort and annotate Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-19 06:38:57 UTC (rev 143) +++ trunk/varnish-cache/include/http_headers.h 2006-04-24 19:09:32 UTC (rev 144) @@ -12,40 +12,53 @@ * a b c d e f g *-------------------------------------------------------------------- */ -HTTPH("Connection", H_Connection, 3, 0, 0, 0, 0) -HTTPH("Keep-Alive", H_Keep_Alive, 3, 0, 0, 0, 0) -HTTPH("Cache-Control", H_Cache_Control, 3, 1, 0, 0, 0) -HTTPH("Accept-Charset", H_Accept_Charset, 1, 1, 0, 0, 0) -HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 1, 0, 0, 0) -HTTPH("Accept-Language", H_Accept_Language, 1, 1, 0, 0, 0) -HTTPH("Accept", H_Accept, 1, 1, 0, 0, 0) -HTTPH("Authorization", H_Authorization, 1, 1, 0, 0, 0) -HTTPH("Expect", H_Expect, 1, 1, 0, 0, 0) -HTTPH("From", H_From, 1, 1, 0, 0, 0) -HTTPH("Host", H_Host, 1, 1, 0, 0, 0) -HTTPH("If-Match", H_If_Match, 1, 1, 0, 0, 0) -HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 1, 0, 0, 0) -HTTPH("If-None-Match", H_If_None_Match, 1, 1, 0, 0, 0) -HTTPH("If-Range", H_If_Range, 1, 1, 0, 0, 0) -HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 1, 0, 0, 0) -HTTPH("Max-Forwards", H_Max_Forwards, 1, 1, 0, 0, 0) -HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 1, 0, 0, 0) -HTTPH("Range", H_Range, 1, 1, 0, 0, 0) -HTTPH("Referer", H_Referer, 1, 1, 0, 0, 0) -HTTPH("TE", H_TE, 1, 1, 0, 0, 0) -HTTPH("User-Agent", H_User_Agent, 1, 1, 0, 0, 0) -HTTPH("Pragma", H_Pragma, 1, 1, 0, 0, 0) +HTTPH("Keep-Alive", H_Keep_Alive, 3, 0, 0, 0, 0) /* RFC2068 */ -HTTPH("Server", H_Server, 2, 1, 0, 0, 0) -HTTPH("Content-Type", H_Content_Type, 2, 1, 0, 0, 0) -HTTPH("Date", H_Date, 2, 1, 0, 0, 0) -HTTPH("Last-Modified", H_Last_Modified, 2, 1, 0, 0, 0) -HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 1, 0, 0, 0) -HTTPH("Content-Length", H_Content_Length, 2, 1, 0, 0, 0) -HTTPH("Vary", H_Vary, 2, 1, 0, 0, 0) -HTTPH("Expires", H_Expires, 2, 1, 0, 0, 0) -HTTPH("Location", H_Location, 2, 1, 0, 0, 0) -HTTPH("Content-Encoding", H_Content_Encoding, 2, 1, 0, 0, 0) -HTTPH("ETag:", H_ETag, 2, 1, 0, 0, 0) - +HTTPH("Accept", H_Accept, 1, 1, 0, 0, 0) /* RFC2616 14.1 */ +HTTPH("Accept-Charset", H_Accept_Charset, 1, 1, 0, 0, 0) /* RFC2616 14.2 */ +HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 1, 0, 0, 0) /* RFC2616 14.3 */ +HTTPH("Accept-Language", H_Accept_Language, 1, 1, 0, 0, 0) /* RFC2616 14.4 */ +HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 1, 0, 0, 0) /* RFC2616 14.5 */ +HTTPH("Age", H_Age, 2, 1, 0, 0, 0) /* RFC2616 14.6 */ +HTTPH("Allow", H_Allow, 2, 1, 0, 0, 0) /* RFC2616 14.7 */ +HTTPH("Authorization", H_Authorization, 1, 1, 0, 0, 0) /* RFC2616 14.8 */ +HTTPH("Cache-Control", H_Cache_Control, 3, 1, 0, 0, 0) /* RFC2616 14.9 */ +HTTPH("Connection", H_Connection, 3, 0, 0, 0, 0) /* RFC2616 14.10 */ +HTTPH("Content-Encoding", H_Content_Encoding, 2, 1, 0, 0, 0) /* RFC2616 14.11 */ +HTTPH("Content-Langugae", H_Content_Language, 2, 1, 0, 0, 0) /* RFC2616 14.12 */ +HTTPH("Content-Length", H_Content_Length, 2, 1, 0, 0, 0) /* RFC2616 14.13 */ +HTTPH("Content-Location", H_Content_Location, 2, 1, 0, 0, 0) /* RFC2616 14.14 */ +HTTPH("Content-MD5", H_Content_MD5, 2, 1, 0, 0, 0) /* RFC2616 14.15 */ +HTTPH("Content-Range", H_Content_Range, 2, 1, 0, 0, 0) /* RFC2616 14.16 */ +HTTPH("Content-Type", H_Content_Type, 2, 1, 0, 0, 0) /* RFC2616 14.17 */ +HTTPH("Date", H_Date, 2, 1, 0, 0, 0) /* RFC2616 14.18 */ +HTTPH("ETag", H_ETag, 2, 1, 0, 0, 0) /* RFC2616 14.19 */ +HTTPH("Expect", H_Expect, 1, 1, 0, 0, 0) /* RFC2616 14.20 */ +HTTPH("Expires", H_Expires, 2, 1, 0, 0, 0) /* RFC2616 14.21 */ +HTTPH("From", H_From, 1, 1, 0, 0, 0) /* RFC2616 14.22 */ +HTTPH("Host", H_Host, 1, 1, 0, 0, 0) /* RFC2616 14.23 */ +HTTPH("If-Match", H_If_Match, 1, 1, 0, 0, 0) /* RFC2616 14.24 */ +HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 1, 0, 0, 0) /* RFC2616 14.25 */ +HTTPH("If-None-Match", H_If_None_Match, 1, 1, 0, 0, 0) /* RFC2616 14.26 */ +HTTPH("If-Range", H_If_Range, 1, 1, 0, 0, 0) /* RFC2616 14.27 */ +HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 1, 0, 0, 0) /* RFC2616 14.28 */ +HTTPH("Last-Modified", H_Last_Modified, 2, 1, 0, 0, 0) /* RFC2616 14.29 */ +HTTPH("Location", H_Location, 2, 1, 0, 0, 0) /* RFC2616 14.30 */ +HTTPH("Max-Forwards", H_Max_Forwards, 1, 1, 0, 0, 0) /* RFC2616 14.31 */ +HTTPH("Pragma", H_Pragma, 1, 1, 0, 0, 0) /* RFC2616 14.32 */ +HTTPH("Proxy-Authenticate", H_Proxy_Authenticate, 2, 1, 0, 0, 0) /* RFC2616 14.33 */ +HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 1, 0, 0, 0) /* RFC2616 14.34 */ +HTTPH("Range", H_Range, 1, 1, 0, 0, 0) /* RFC2616 14.35 */ +HTTPH("Referer", H_Referer, 1, 1, 0, 0, 0) /* RFC2616 14.36 */ +HTTPH("Retry-After", H_Retry_After, 2, 1, 0, 0, 0) /* RFC2616 14.37 */ +HTTPH("Server", H_Server, 2, 1, 0, 0, 0) /* RFC2616 14.38 */ +HTTPH("TE", H_TE, 1, 1, 0, 0, 0) /* RFC2616 14.39 */ +HTTPH("Trailer", H_Trailer, 1, 1, 0, 0, 0) /* RFC2616 14.40 */ +HTTPH("Transfer-Encoding", H_Transfer_Encoding, 2, 1, 0, 0, 0) /* RFC2616 14.41 */ +HTTPH("Upgrade", H_Upgrade, 2, 1, 0, 0, 0) /* RFC2616 14.42 */ +HTTPH("User-Agent", H_User_Agent, 1, 1, 0, 0, 0) /* RFC2616 14.43 */ +HTTPH("Vary", H_Vary, 2, 1, 0, 0, 0) /* RFC2616 14.44 */ +HTTPH("Via", H_Via, 2, 1, 0, 0, 0) /* RFC2616 14.45 */ +HTTPH("Warning", H_Warning, 2, 1, 0, 0, 0) /* RFC2616 14.46 */ +HTTPH("WWW-Authenticate", H_WWW_Authenticate, 2, 1, 0, 0, 0) /* RFC2616 14.47 */ From phk at projects.linpro.no Mon Apr 24 19:10:09 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Mon, 24 Apr 2006 21:10:09 +0200 (CEST) Subject: r145 - trunk/varnish-cache/bin/varnishd Message-ID: <20060424191009.B915D1ED693@projects.linpro.no> Author: phk Date: 2006-04-24 21:10:09 +0200 (Mon, 24 Apr 2006) New Revision: 145 Modified: trunk/varnish-cache/bin/varnishd/varnishd.c Log: Add an indecisive comment Modified: trunk/varnish-cache/bin/varnishd/varnishd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-24 19:09:32 UTC (rev 144) +++ trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-24 19:10:09 UTC (rev 145) @@ -66,6 +66,14 @@ char *buf, *vf; struct sbuf *sb; + /* + * XXX: should do a "HEAD /" on the -b argument to see that + * XXX: it even works. On the other hand, we should do that + * XXX: for all backends in the cache process whenever we + * XXX: change config, but for a complex VCL, it might not be + * XXX: a bug for a backend to not reply at that time, so then + * XXX: again: we should check it here in the "trivial" case. + */ buf = NULL; asprintf(&buf, "backend default {\n" From phk at projects.linpro.no Tue Apr 25 06:16:22 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 08:16:22 +0200 (CEST) Subject: r146 - in trunk/varnish-cache: bin/varnishd include lib/libvcl Message-ID: <20060425061622.D2F8B1ED693@projects.linpro.no> Author: phk Date: 2006-04-25 08:16:22 +0200 (Tue, 25 Apr 2006) New Revision: 146 Added: trunk/varnish-cache/bin/varnishd/cache_http.c Removed: trunk/varnish-cache/bin/varnishd/cache_httpd.c Modified: trunk/varnish-cache/bin/varnishd/Makefile.am trunk/varnish-cache/bin/varnishd/cache.h trunk/varnish-cache/bin/varnishd/cache_acceptor.c trunk/varnish-cache/bin/varnishd/cache_fetch.c trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pipe.c trunk/varnish-cache/bin/varnishd/cache_pool.c trunk/varnish-cache/bin/varnishd/cache_vcl.c trunk/varnish-cache/bin/varnishd/varnishd.c trunk/varnish-cache/include/http_headers.h trunk/varnish-cache/include/shmlog_tags.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_compile.c trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Redo http header storage and processing Modified: trunk/varnish-cache/bin/varnishd/Makefile.am =================================================================== --- trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/Makefile.am 2006-04-25 06:16:22 UTC (rev 146) @@ -8,7 +8,7 @@ cache_acceptor.c \ cache_backend.c \ cache_fetch.c \ - cache_httpd.c \ + cache_http.c \ cache_main.c \ cache_pool.c \ cache_pass.c \ Modified: trunk/varnish-cache/bin/varnishd/cache.h =================================================================== --- trunk/varnish-cache/bin/varnishd/cache.h 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache.h 2006-04-25 06:16:22 UTC (rev 146) @@ -77,10 +77,17 @@ /* cache_fetch.c */ int FetchSession(struct worker *w, struct sess *sp); -/* cache_httpd.c */ -void HttpdAnalyze(struct sess *sp, int rr); -void HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func); -void HttpdBuildSbuf(int resp, int filter, struct sbuf *sb, struct sess *sp); +/* cache_http.c */ +typedef void http_callback_f(void *, int good); +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_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); +void http_Dissect(struct http *sp, int fd, int rr); +void http_BuildSbuf(int resp, struct sbuf *sb, struct http *hp); /* cache_main.c */ pthread_mutex_t sessmtx; @@ -93,7 +100,7 @@ /* cache_pool.c */ void CacheInitPool(void); -void DealWithSession(struct sess *sp); +void DealWithSession(void *arg, int good); /* cache_shmlog.c */ void VSL_Init(void); Modified: trunk/varnish-cache/bin/varnishd/cache_acceptor.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_acceptor.c 2006-04-25 06:16:22 UTC (rev 146) @@ -47,7 +47,7 @@ i = read(fd, &sp, sizeof sp); assert(i == sizeof sp); - HttpdGetHead(sp, evb, DealWithSession); + http_RecvHead(sp->http, sp->fd, evb, DealWithSession, sp); } static void @@ -82,7 +82,8 @@ strlcat(sp->addr, ":", VCA_ADDRBUFSIZE); strlcat(sp->addr, port, VCA_ADDRBUFSIZE); VSL(SLT_SessionOpen, sp->fd, "%s", sp->addr); - HttpdGetHead(sp, evb, DealWithSession); + sp->http = http_New(); + http_RecvHead(sp->http, sp->fd, evb, DealWithSession, sp); } void * @@ -134,8 +135,11 @@ vca_retire_session(struct sess *sp) { - VSL(SLT_SessionClose, sp->fd, "%s", sp->addr); - if (sp->fd >= 0) + if (sp->http != NULL) + http_Delete(sp->http); + if (sp->fd >= 0) { + VSL(SLT_SessionClose, sp->fd, "%s", sp->addr); close(sp->fd); + } free(sp); } Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 06:16:22 UTC (rev 146) @@ -22,13 +22,6 @@ #include "vcl_lang.h" #include "cache.h" -static void -FetchReturn(struct sess *sp) -{ - - /* do nothing */ -} - /*--------------------------------------------------------------------*/ int FetchSession(struct worker *w, struct sess *sp) @@ -39,12 +32,14 @@ off_t cl; struct storage *st; unsigned char *p; + char *b, *e; + struct http *hp; fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - VSL(SLT_HandlingFetch, sp->fd, "%d", fd); - HttpdBuildSbuf(0, 1, w->sb, sp); + hp = http_New(); + http_BuildSbuf(0, w->sb, sp->http); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -57,9 +52,9 @@ * XXX: It might be cheaper to avoid the event_engine and simply * XXX: read(2) the header */ - HttpdGetHead(&sp2, w->eb, FetchReturn); + http_RecvHead(hp, sp2.fd, w->eb, NULL, NULL); event_base_loop(w->eb, 0); - HttpdAnalyze(&sp2, 2); + http_Dissect(hp, sp2.fd, 2); /* XXX: fill in object from headers */ sp->obj->valid = 1; @@ -68,9 +63,10 @@ /* XXX: unbusy, and kick other sessions into action */ sp->obj->busy = 0; - assert (sp2.http.H_Content_Length != NULL); /* XXX */ + assert(http_GetHdr(hp, "Content-Length", &b)); - cl = strtoumax(sp2.http.H_Content_Length, NULL, 0); + cl = strtoumax(b, NULL, 0); + VSL(SLT_Debug, 0, "cl %jd (%s)", cl, b); sp->handling = HND_Unclass; sp->vcl->fetch_func(sp); @@ -85,44 +81,37 @@ i &= ~O_NONBLOCK; i = fcntl(sp2.fd, F_SETFL, i); - i = sp2.rcv_len - sp2.rcv_ptr; - if (i > 0) { - memcpy(p, sp2.rcv + sp2.rcv_ptr, i); + if (http_GetTail(hp, cl, &b, &e)) { + i = e - b; + VSL(SLT_Debug, 0, "T i %d cl %jd", i, cl); + memcpy(p, b, i); p += i; cl -= i; } while (cl != 0) { i = read(sp2.fd, p, cl); - assert(i > 0); VSL(SLT_Debug, 0, "R i %d cl %jd", i, cl); + assert(i > 0); p += i; cl -= i; } - HttpdBuildSbuf(1, 1, w->sb, &sp2); + http_BuildSbuf(1, w->sb, hp); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); i = write(sp->fd, st->ptr, st->len); - VSL(SLT_Debug, 0, "W i %d st->len %u", i, st->len); assert(i == st->len); hash->deref(sp->obj); - if (sp2.http.H_Connection != NULL && - !strcmp(sp2.http.H_Connection, "close")) { + if (http_GetHdr(sp->http, "Connection", &b) && + !strcasecmp(b, "close")) { close(fd); VBE_ClosedFd(fd_token); } 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; return (1); } Copied: trunk/varnish-cache/bin/varnishd/cache_http.c (from rev 139, trunk/varnish-cache/bin/varnishd/cache_httpd.c) =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-12 08:58:54 UTC (rev 139) +++ trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 06:16:22 UTC (rev 146) @@ -0,0 +1,343 @@ +/* + * $Id$ + * + * HTTP request storage and manipulation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libvarnish.h" +#include "shmlog.h" +#include "vcl_lang.h" +#include "cache.h" + +static unsigned http_bufsize = 4096; +static unsigned http_nhdr = 128; + +/*--------------------------------------------------------------------*/ + +struct http { + struct event ev; + http_callback_f *callback; + void *arg; + + char *s; /* start of buffer */ + char *v; /* valid bytes */ + char *t; /* start of trailing data */ + + + char *req; + char *url; + char *proto; + char *status; + char *response; + + char **hdr; + unsigned nhdr; +}; + +/*--------------------------------------------------------------------*/ + +struct http * +http_New(void) +{ + struct http *hp; + + hp = calloc(sizeof *hp, 1); + assert(hp != NULL); + + hp->s = malloc(http_bufsize); + assert(hp->s != NULL); + + hp->v = hp->s; + + hp->hdr = malloc(sizeof *hp->hdr * http_nhdr); + assert(hp->hdr != NULL); + + return (hp); +} + +void +http_Delete(struct http *hp) +{ + + free(hp->hdr); + free(hp->s); + free(hp); +} + +/*--------------------------------------------------------------------*/ + +int +http_GetHdr(struct http *hp, const char *hdr, char **ptr) +{ + unsigned u, l; + char *p; + + l = strlen(hdr); + for (u = 0; u < hp->nhdr; u++) { + if (strncasecmp(hdr, hp->hdr[u], l)) + continue; + p = hp->hdr[u]; + if (p[l] != ':') + continue; + p += l + 1; + while (isspace(*p)) + p++; + *ptr = p; + return (1); + } + return (0); +} + +int +http_GetURL(struct http *hp, char **b) +{ + if (hp->url == NULL) + return (0); + *b = hp->url; + return (1); +} + +int +http_GetTail(struct http *hp, unsigned len, char **b, char **e) +{ + + if (hp->t >= hp->v) + return (0); + + if (len == 0) + len = hp->v - hp->t; + + if (hp->t + len > hp->v) + len = hp->v - hp->t; + if (len == 0) + return (0); + *b = hp->t; + *e = hp->t + len; + hp->t += len; + return (1); +} + +/*--------------------------------------------------------------------*/ + +void +http_Dissect(struct http *hp, int fd, int rr) +{ + char *p, *q, *r; + + if (rr == 1) { + /* First, isolate and possibly identify request type */ + hp->req = hp->s; + for (p = hp->s; isalpha(*p); p++) + ; + VSLR(SLT_Request, fd, hp->req, p); + *p++ = '\0'; + + /* Next find the URI */ + while (isspace(*p)) + p++; + hp->url = p; + while (!isspace(*p)) + p++; + VSLR(SLT_URL, fd, hp->url, p); + *p++ = '\0'; + + /* Finally, look for protocol, if any */ + while (isspace(*p) && *p != '\n') + p++; + hp->proto = p; + if (*p != '\n') { + while (!isspace(*p)) + p++; + } + VSLR(SLT_Protocol, fd, hp->proto, p); + *p++ = '\0'; + + while (isspace(*p) && *p != '\n') + p++; + p++; + } else { + /* First, protocol */ + hp->proto = hp->s; + p = hp->s; + while (!isspace(*p)) + p++; + VSLR(SLT_Protocol, fd, hp->proto, p); + *p++ = '\0'; + + /* Next find the status */ + while (isspace(*p)) + p++; + hp->status = p; + while (!isspace(*p)) + p++; + VSLR(SLT_Status, fd, hp->status, p); + *p++ = '\0'; + + /* Next find the response */ + while (isspace(*p)) + p++; + hp->response = p; + while (*p != '\n') + p++; + for (q = p; q > hp->response && isspace(q[-1]); q--) + continue; + *q = '\0'; + VSLR(SLT_Response, fd, hp->response, q); + p++; + } + + if (*p == '\r') + p++; + + for (; p < hp->v; p = r) { + q = strchr(p, '\n'); + assert(q != NULL); + r = q + 1; + if (q > p && q[-1] == '\r') + q--; + *q = '\0'; + if (p == q) + break; + + if (hp->nhdr < http_nhdr) { + hp->hdr[hp->nhdr++] = p; + VSLR(SLT_Header, fd, p, q); + } else { + VSLR(SLT_LostHeader, fd, p, q); + } + } + if (*++p == '\r') + p++; + hp->t = ++p; +} + +/*--------------------------------------------------------------------*/ + +static void +http_read_f(int fd, short event, void *arg) +{ + struct http *hp = arg; + char *p; + int i; + + assert(hp->v < hp->s + http_bufsize); + i = read(fd, hp->v, (hp->s + http_bufsize) - hp->v); + if (i <= 0) { + if (hp->v != hp->s) + VSL(SLT_SessionClose, fd, + "remote had %d bytes", hp->v - hp->s); + else + VSL(SLT_SessionClose, fd, "remote"); + hp->t = NULL; + event_del(&hp->ev); + if (hp->callback != NULL) + hp->callback(hp->arg, 0); + return; + } + + hp->v += i; + *hp->v = '\0'; + + p = hp->s; + while (1) { + /* XXX: we could save location of all linebreaks for later */ + p = strchr(p, '\n'); + if (p == NULL) + return; + p++; + if (*p == '\r') + p++; + if (*p != '\n') + continue; + break; + } + hp->t = ++p; + + event_del(&hp->ev); + if (hp->callback != NULL) + hp->callback(hp->arg, 1); +} + +/*--------------------------------------------------------------------*/ + +void +http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg) +{ + + assert(hp != NULL); + hp->callback = func; + hp->arg = arg; + hp->t = hp->s; + event_set(&hp->ev, fd, EV_READ | EV_PERSIST, http_read_f, hp); + event_base_set(eb, &hp->ev); + event_add(&hp->ev, NULL); /* XXX: timeout */ +} + +/*--------------------------------------------------------------------*/ + +static int +http_supress(const char *hdr, int flag) +{ + +#define HTTPH_0(a,d) +#define HTTPH_1(a,d) \ + if ((flag & d) && !strncasecmp(hdr, a, strlen(a))) { \ + return (1); \ + } +#define HTTPH_2(a,d) HTTPH_1(a,d) +#define HTTPH_3(a,d) HTTPH_1(a,d) + +#define HTTPH(a,b,c,d,e,f,g) HTTPH_ ## d(a ":",d) +#include "http_headers.h" +#undef HTTPH +#undef HTTPH_0 +#undef HTTPH_1 +#undef HTTPH_2 +#undef HTTPH_3 + + return (0); +} + +/*--------------------------------------------------------------------*/ + +void +http_BuildSbuf(int resp, struct sbuf *sb, struct http *hp) +{ + unsigned u; + + sbuf_clear(sb); + assert(sb != NULL); + if (resp) { + sbuf_cat(sb, hp->proto); + sbuf_cat(sb, " "); + sbuf_cat(sb, hp->status); + sbuf_cat(sb, " "); + sbuf_cat(sb, hp->response); + } else { + sbuf_cat(sb, hp->req); + sbuf_cat(sb, " "); + sbuf_cat(sb, hp->url); + sbuf_cat(sb, " "); + sbuf_cat(sb, hp->proto); + } + sbuf_cat(sb, "\r\n"); + + for (u = 0; u < hp->nhdr; u++) { + if (http_supress(hp->hdr[u], resp)) + continue; + sbuf_cat(sb, hp->hdr[u]); + sbuf_cat(sb, "\r\n"); + } + sbuf_cat(sb, "\r\n"); + sbuf_finish(sb); +} Deleted: trunk/varnish-cache/bin/varnishd/cache_httpd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_httpd.c 2006-04-25 06:16:22 UTC (rev 146) @@ -1,221 +0,0 @@ -/* - * $Id$ - * - * Stuff relating to HTTP server side - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libvarnish.h" -#include "shmlog.h" -#include "vcl_lang.h" -#include "cache.h" - -/*--------------------------------------------------------------------*/ - -void -HttpdAnalyze(struct sess *sp, int rr) -{ - char *p, *q, *r; - - sp->handling = HND_Unclass; - - memset(&sp->http, 0, sizeof sp->http); - - if (rr == 1) { - /* First, isolate and possibly identify request type */ - sp->http.req = sp->rcv; - for (p = sp->rcv; isalpha(*p); p++) - ; - VSLR(SLT_Request, sp->fd, sp->http.req, p); - *p++ = '\0'; - - /* Next find the URI */ - while (isspace(*p)) - p++; - sp->http.url = p; - while (!isspace(*p)) - p++; - VSLR(SLT_URL, sp->fd, sp->http.url, p); - *p++ = '\0'; - - /* Finally, look for protocol, if any */ - while (isspace(*p) && *p != '\n') - p++; - sp->http.proto = p; - if (*p != '\n') { - while (!isspace(*p)) - p++; - } - VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); - *p++ = '\0'; - - while (isspace(*p) && *p != '\n') - p++; - p++; - } else { - /* First, protocol */ - sp->http.proto = sp->rcv; - p = sp->rcv; - while (!isspace(*p)) - p++; - VSLR(SLT_Protocol, sp->fd, sp->http.proto, p); - *p++ = '\0'; - - /* Next find the status */ - while (isspace(*p)) - p++; - sp->http.status = p; - while (!isspace(*p)) - p++; - VSLR(SLT_Status, sp->fd, sp->http.status, p); - *p++ = '\0'; - - /* Next find the response */ - while (isspace(*p)) - p++; - sp->http.response = p; - while (*p != '\n') - p++; - for (q = p; q > sp->http.response && isspace(q[-1]); q--) - continue; - *q = '\0'; - VSLR(SLT_Response, sp->fd, sp->http.response, q); - p++; - } - - if (*p == '\r') - p++; - - for (; p < sp->rcv + sp->rcv_len; p = r) { - q = strchr(p, '\n'); - assert(q != NULL); - r = q + 1; - if (q > p && q[-1] == '\r') - q--; - *q = '\0'; - if (p == q) - break; - -#define W(a, b, p, q, sp) \ - if (!strncasecmp(p, a, strlen(a))) { \ - for (p += strlen(a); p < q && isspace(*p); p++) \ - continue; \ - sp->http.b = p; \ - VSLR(SLT_##b, sp->fd, p, q); \ - continue; \ - } - -#define HTTPH(a, b, c, d, e, f, g) \ - if (c & rr) { \ - W(a ":", b, p, q, sp); \ - } -#include "http_headers.h" -#undef HTTPH -#undef W - if (sp->http.nuhdr < VCA_UNKNOWNHDR) { - sp->http.uhdr[sp->http.nuhdr++] = p; - VSLR(SLT_HD_Unknown, sp->fd, p, q); - } else { - VSLR(SLT_HD_Lost, sp->fd, p, q); - } - } -} - -/*--------------------------------------------------------------------*/ - -static void -http_read_f(int fd, short event, void *arg) -{ - struct sess *sp = arg; - const char *p; - int i; - - assert(VCA_RXBUFSIZE - sp->rcv_len > 0); - i = read(fd, sp->rcv + sp->rcv_len, VCA_RXBUFSIZE - sp->rcv_len); - if (i <= 0) { - VSL(SLT_SessionClose, sp->fd, "remote %d", sp->rcv_len); - event_del(sp->rd_e); - close(sp->fd); - free(sp->mem); - return; - } - - sp->rcv_len += i; - sp->rcv[sp->rcv_len] = '\0'; - - p = sp->rcv; - while (1) { - /* XXX: we could save location of all linebreaks for later */ - p = strchr(p, '\n'); - if (p == NULL) - return; - p++; - if (*p == '\r') - p++; - if (*p != '\n') - continue; - break; - } - sp->rcv_ptr = ++p - sp->rcv; - - event_del(sp->rd_e); - sp->sesscb(sp); -} - -/*--------------------------------------------------------------------*/ - -void -HttpdGetHead(struct sess *sp, struct event_base *eb, sesscb_f *func) -{ - - sp->sesscb = func; - assert(sp->rd_e != NULL); - event_set(sp->rd_e, sp->fd, EV_READ | EV_PERSIST, http_read_f, sp); - event_base_set(eb, sp->rd_e); - event_add(sp->rd_e, NULL); /* XXX: timeout */ -} - -/*--------------------------------------------------------------------*/ - -void -HttpdBuildSbuf(int resp, int filter, struct sbuf *sb, struct sess *sp) -{ - - sbuf_clear(sb); - assert(sb != NULL); - if (resp) { - sbuf_cat(sb, sp->http.proto); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.status); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.response); - } else { - sbuf_cat(sb, sp->http.req); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.url); - sbuf_cat(sb, " "); - sbuf_cat(sb, sp->http.proto); - } - sbuf_cat(sb, "\r\n"); -#define HTTPH(a, b, c, d, e, f, g) \ - do { \ - if ((!filter || d) && sp->http.b != NULL) { \ - sbuf_cat(sb, a ": "); \ - sbuf_cat(sb, sp->http.b); \ - sbuf_cat(sb, "\r\n"); \ - } \ - } while (0); -#include "http_headers.h" -#undef HTTPH - sbuf_cat(sb, "\r\n"); - sbuf_finish(sb); -} Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-25 06:16:22 UTC (rev 146) @@ -22,13 +22,6 @@ #include "vcl_lang.h" #include "cache.h" -static void -PassReturn(struct sess *sp) -{ - - /* do nothing */ -} - /*--------------------------------------------------------------------*/ void PassSession(struct worker *w, struct sess *sp) @@ -38,22 +31,20 @@ struct sess sp2; char buf[BUFSIZ]; off_t cl; + char *b; - if (sp->http.H_Connection != NULL && - !strcmp(sp->http.H_Connection, "close")) { + if (http_GetHdr(sp->http, "Connection", &b) && !strcmp(b, "close")) { /* * If client wants only this one request, piping is safer * and cheaper */ - VSL(SLT_HandlingPass, sp->fd, "pipe"); PipeSession(w, sp); return; } fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - VSL(SLT_HandlingPass, sp->fd, "%d", fd); - HttpdBuildSbuf(0, 1, w->sb, sp); + http_BuildSbuf(0, w->sb, sp->http); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -66,14 +57,19 @@ * XXX: It might be cheaper to avoid the event_engine and simply * XXX: read(2) the header */ - HttpdGetHead(&sp2, w->eb, PassReturn); + http_RecvHead(sp2.http, sp2.fd, w->eb, NULL, NULL); event_base_loop(w->eb, 0); - HttpdAnalyze(&sp2, 2); + http_Dissect(sp2.http, sp2.fd, 2); - HttpdBuildSbuf(1, 1, w->sb, &sp2); + http_BuildSbuf(1, w->sb, sp2.http); 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); @@ -118,4 +114,5 @@ sp->rcv_len - sp->rcv_ptr); sp->rcv_len -= sp->rcv_ptr; sp->rcv_ptr = 0; +#endif } Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-25 06:16:22 UTC (rev 146) @@ -51,16 +51,19 @@ fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - VSL(SLT_HandlingPipe, sp->fd, "%d", fd); - HttpdBuildSbuf(0, 0, w->sb, sp); + http_BuildSbuf(0, w->sb, sp->http); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); + assert(__LINE__ == 0); + j = 0; +#if 0 i = sp->rcv_len - sp->rcv_ptr; if (i > 0) { j = write(sp->fd, sp->rcv + sp->rcv_ptr, i); assert(j == i); } +#endif e1.fd = fd; e2.fd = sp->fd; Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-25 06:16:22 UTC (rev 146) @@ -29,6 +29,7 @@ struct object *o; unsigned char key[16]; MD5_CTX ctx; + char *b; if (w->nobj == NULL) { w->nobj = calloc(sizeof *w->nobj, 1); @@ -37,15 +38,16 @@ TAILQ_INIT(&w->nobj->store); } + assert(http_GetURL(sp->http, &b)); MD5Init(&ctx); - MD5Update(&ctx, sp->http.url, strlen(sp->http.url)); + MD5Update(&ctx, b, strlen(b)); MD5Final(key, &ctx); o = hash->lookup(key, w->nobj); if (o == w->nobj) { - VSL(SLT_Debug, 0, "Lookup new %p %s", o, sp->http.url); + VSL(SLT_Debug, 0, "Lookup new %p %s", o, b); w->nobj = NULL; } else { - VSL(SLT_Debug, 0, "Lookup found %p %s", o, sp->http.url); + VSL(SLT_Debug, 0, "Lookup found %p %s", o, b); } /* * XXX: if obj is busy, park session on it @@ -92,6 +94,7 @@ struct sess *sp; struct worker w; int done; + char *b; memset(&w, 0, sizeof w); w.eb = event_init(); @@ -112,7 +115,7 @@ sp->vcl = GetVCL(); AZ(pthread_mutex_unlock(&sessmtx)); - HttpdAnalyze(sp, 1); + http_Dissect(sp->http, sp->fd, 1); sp->backend = sp->vcl->default_backend; @@ -125,31 +128,38 @@ sp->vcl->recv_func(sp); for (done = 0; !done; ) { - printf("Handling: %d\n", sp->handling); switch(sp->handling) { case HND_Lookup: + VSL(SLT_Handling, sp->fd, "Lookup"); done = LookupSession(&w, sp); break; case HND_Fetch: + VSL(SLT_Handling, sp->fd, "Fetch"); done = FetchSession(&w, sp); break; case HND_Deliver: + VSL(SLT_Handling, sp->fd, "Deliver"); done = DeliverSession(&w, sp); break; case HND_Pipe: + VSL(SLT_Handling, sp->fd, "Pipe"); PipeSession(&w, sp); done = 1; break; case HND_Pass: + VSL(SLT_Handling, sp->fd, "Pass"); PassSession(&w, sp); done = 1; break; case HND_Unclass: + VSL(SLT_Handling, sp->fd, "Unclass"); assert(sp->handling == HND_Unclass); + assert(sp->handling != HND_Unclass); } } - if (sp->http.H_Connection != NULL && - !strcmp(sp->http.H_Connection, "close")) { + if (http_GetHdr(sp->http, "Connection", &b) && + !strcmp(b, "close")) { + VSL(SLT_SessionClose, sp->fd, "hdr"); close(sp->fd); sp->fd = -1; } @@ -165,8 +175,14 @@ } void -DealWithSession(struct sess *sp) +DealWithSession(void *arg, int good) { + struct sess *sp = arg; + + if (!good) { + vca_retire_session(sp); + return; + } AZ(pthread_mutex_lock(&sessmtx)); TAILQ_INSERT_TAIL(&shd, sp, list); AZ(pthread_mutex_unlock(&sessmtx)); Modified: trunk/varnish-cache/bin/varnishd/cache_vcl.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/cache_vcl.c 2006-04-25 06:16:22 UTC (rev 146) @@ -12,6 +12,7 @@ #include "cli.h" #include "cli_priv.h" +#include "shmlog.h" #include "vcl_lang.h" #include "libvarnish.h" #include "cache.h" @@ -206,3 +207,11 @@ void VCL_error(VCL_FARGS, unsigned err, const char *str) { } + +void +VCL_count(unsigned u) +{ + + VSL(SLT_VCL, 0, "%u", u); +} + Modified: trunk/varnish-cache/bin/varnishd/varnishd.c =================================================================== --- trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/bin/varnishd/varnishd.c 2006-04-25 06:16:22 UTC (rev 146) @@ -329,11 +329,6 @@ #include #include -void -VCL_count(unsigned u) -{ -} - int main(int argc, char *argv[]) { Modified: trunk/varnish-cache/include/http_headers.h =================================================================== --- trunk/varnish-cache/include/http_headers.h 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/include/http_headers.h 2006-04-25 06:16:22 UTC (rev 146) @@ -4,7 +4,7 @@ * a Http header name * b session field name * c Request(1)/Response(2) bitfield - * d Pass header + * d Supress header to backend (1) / Supress header to client (2) * e unused * f unused * g unused @@ -13,52 +13,52 @@ *-------------------------------------------------------------------- */ -HTTPH("Keep-Alive", H_Keep_Alive, 3, 0, 0, 0, 0) /* RFC2068 */ +HTTPH("Keep-Alive", H_Keep_Alive, 3, 3, 0, 0, 0) /* RFC2068 */ -HTTPH("Accept", H_Accept, 1, 1, 0, 0, 0) /* RFC2616 14.1 */ -HTTPH("Accept-Charset", H_Accept_Charset, 1, 1, 0, 0, 0) /* RFC2616 14.2 */ -HTTPH("Accept-Encoding", H_Accept_Encoding, 1, 1, 0, 0, 0) /* RFC2616 14.3 */ -HTTPH("Accept-Language", H_Accept_Language, 1, 1, 0, 0, 0) /* RFC2616 14.4 */ -HTTPH("Accept-Ranges", H_Accept_Ranges, 2, 1, 0, 0, 0) /* RFC2616 14.5 */ -HTTPH("Age", H_Age, 2, 1, 0, 0, 0) /* RFC2616 14.6 */ -HTTPH("Allow", H_Allow, 2, 1, 0, 0, 0) /* RFC2616 14.7 */ -HTTPH("Authorization", H_Authorization, 1, 1, 0, 0, 0) /* RFC2616 14.8 */ -HTTPH("Cache-Control", H_Cache_Control, 3, 1, 0, 0, 0) /* RFC2616 14.9 */ -HTTPH("Connection", H_Connection, 3, 0, 0, 0, 0) /* RFC2616 14.10 */ -HTTPH("Content-Encoding", H_Content_Encoding, 2, 1, 0, 0, 0) /* RFC2616 14.11 */ -HTTPH("Content-Langugae", H_Content_Language, 2, 1, 0, 0, 0) /* RFC2616 14.12 */ -HTTPH("Content-Length", H_Content_Length, 2, 1, 0, 0, 0) /* RFC2616 14.13 */ -HTTPH("Content-Location", H_Content_Location, 2, 1, 0, 0, 0) /* RFC2616 14.14 */ -HTTPH("Content-MD5", H_Content_MD5, 2, 1, 0, 0, 0) /* RFC2616 14.15 */ -HTTPH("Content-Range", H_Content_Range, 2, 1, 0, 0, 0) /* RFC2616 14.16 */ -HTTPH("Content-Type", H_Content_Type, 2, 1, 0, 0, 0) /* RFC2616 14.17 */ -HTTPH("Date", H_Date, 2, 1, 0, 0, 0) /* RFC2616 14.18 */ -HTTPH("ETag", H_ETag, 2, 1, 0, 0, 0) /* RFC2616 14.19 */ -HTTPH("Expect", H_Expect, 1, 1, 0, 0, 0) /* RFC2616 14.20 */ -HTTPH("Expires", H_Expires, 2, 1, 0, 0, 0) /* RFC2616 14.21 */ -HTTPH("From", H_From, 1, 1, 0, 0, 0) /* RFC2616 14.22 */ -HTTPH("Host", H_Host, 1, 1, 0, 0, 0) /* RFC2616 14.23 */ -HTTPH("If-Match", H_If_Match, 1, 1, 0, 0, 0) /* RFC2616 14.24 */ -HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 1, 0, 0, 0) /* RFC2616 14.25 */ -HTTPH("If-None-Match", H_If_None_Match, 1, 1, 0, 0, 0) /* RFC2616 14.26 */ -HTTPH("If-Range", H_If_Range, 1, 1, 0, 0, 0) /* RFC2616 14.27 */ -HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 1, 0, 0, 0) /* RFC2616 14.28 */ -HTTPH("Last-Modified", H_Last_Modified, 2, 1, 0, 0, 0) /* RFC2616 14.29 */ -HTTPH("Location", H_Location, 2, 1, 0, 0, 0) /* RFC2616 14.30 */ -HTTPH("Max-Forwards", H_Max_Forwards, 1, 1, 0, 0, 0) /* RFC2616 14.31 */ -HTTPH("Pragma", H_Pragma, 1, 1, 0, 0, 0) /* RFC2616 14.32 */ -HTTPH("Proxy-Authenticate", H_Proxy_Authenticate, 2, 1, 0, 0, 0) /* RFC2616 14.33 */ -HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 1, 0, 0, 0) /* RFC2616 14.34 */ -HTTPH("Range", H_Range, 1, 1, 0, 0, 0) /* RFC2616 14.35 */ -HTTPH("Referer", H_Referer, 1, 1, 0, 0, 0) /* RFC2616 14.36 */ -HTTPH("Retry-After", H_Retry_After, 2, 1, 0, 0, 0) /* RFC2616 14.37 */ -HTTPH("Server", H_Server, 2, 1, 0, 0, 0) /* RFC2616 14.38 */ -HTTPH("TE", H_TE, 1, 1, 0, 0, 0) /* RFC2616 14.39 */ -HTTPH("Trailer", H_Trailer, 1, 1, 0, 0, 0) /* RFC2616 14.40 */ -HTTPH("Transfer-Encoding", H_Transfer_Encoding, 2, 1, 0, 0, 0) /* RFC2616 14.41 */ -HTTPH("Upgrade", H_Upgrade, 2, 1, 0, 0, 0) /* RFC2616 14.42 */ -HTTPH("User-Agent", H_User_Agent, 1, 1, 0, 0, 0) /* RFC2616 14.43 */ -HTTPH("Vary", H_Vary, 2, 1, 0, 0, 0) /* RFC2616 14.44 */ -HTTPH("Via", H_Via, 2, 1, 0, 0, 0) /* RFC2616 14.45 */ -HTTPH("Warning", H_Warning, 2, 1, 0, 0, 0) /* RFC2616 14.46 */ -HTTPH("WWW-Authenticate", H_WWW_Authenticate, 2, 1, 0, 0, 0) /* RFC2616 14.47 */ +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, 0, 0, 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, 0, 0, 0, 0) /* RFC2616 14.9 */ +HTTPH("Connection", H_Connection, 3, 3, 0, 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, 0, 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, 0, 0, 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 */ +HTTPH("Expect", H_Expect, 1, 0, 0, 0, 0) /* RFC2616 14.20 */ +HTTPH("Expires", H_Expires, 2, 0, 0, 0, 0) /* RFC2616 14.21 */ +HTTPH("From", H_From, 1, 0, 0, 0, 0) /* RFC2616 14.22 */ +HTTPH("Host", H_Host, 1, 0, 0, 0, 0) /* RFC2616 14.23 */ +HTTPH("If-Match", H_If_Match, 1, 0, 0, 0, 0) /* RFC2616 14.24 */ +HTTPH("If-Modified-Since", H_If_Modified_Since, 1, 0, 0, 0, 0) /* RFC2616 14.25 */ +HTTPH("If-None-Match", H_If_None_Match, 1, 0, 0, 0, 0) /* RFC2616 14.26 */ +HTTPH("If-Range", H_If_Range, 1, 0, 0, 0, 0) /* RFC2616 14.27 */ +HTTPH("If-Unmodified-Since", H_If_Unmodifed_Since, 1, 0, 0, 0, 0) /* RFC2616 14.28 */ +HTTPH("Last-Modified", H_Last_Modified, 2, 0, 0, 0, 0) /* RFC2616 14.29 */ +HTTPH("Location", H_Location, 2, 0, 0, 0, 0) /* RFC2616 14.30 */ +HTTPH("Max-Forwards", H_Max_Forwards, 1, 0, 0, 0, 0) /* RFC2616 14.31 */ +HTTPH("Pragma", H_Pragma, 1, 0, 0, 0, 0) /* RFC2616 14.32 */ +HTTPH("Proxy-Authenticate", H_Proxy_Authenticate, 2, 0, 0, 0, 0) /* RFC2616 14.33 */ +HTTPH("Proxy-Authorization", H_Proxy_Authorization, 1, 0, 0, 0, 0) /* RFC2616 14.34 */ +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, 0, 0, 0, 0) /* RFC2616 14.39 */ +HTTPH("Trailer", H_Trailer, 1, 0, 0, 0, 0) /* RFC2616 14.40 */ +HTTPH("Transfer-Encoding", H_Transfer_Encoding, 2, 0, 0, 0, 0) /* RFC2616 14.41 */ +HTTPH("Upgrade", H_Upgrade, 2, 0, 0, 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 */ +HTTPH("Warning", H_Warning, 2, 0, 0, 0, 0) /* RFC2616 14.46 */ +HTTPH("WWW-Authenticate", H_WWW_Authenticate, 2, 0, 0, 0, 0) /* RFC2616 14.47 */ Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-25 06:16:22 UTC (rev 146) @@ -12,16 +12,12 @@ SLTM(SessionReuse) SLTM(SessionClose) SLTM(ClientAddr) -SLTM(HandlingFetch) -SLTM(HandlingPass) -SLTM(HandlingPipe) +SLTM(Handling) SLTM(Request) SLTM(Response) SLTM(Status) SLTM(URL) SLTM(Protocol) -SLTM(HD_Unknown) -SLTM(HD_Lost) -#define HTTPH(a, b, c, d, e, f, g) SLTM(b) -#include "http_headers.h" -#undef HTTPH +SLTM(Header) +SLTM(LostHeader) +SLTM(VCL) Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-25 06:16:22 UTC (rev 146) @@ -23,23 +23,8 @@ unsigned mask; }; -#define VCA_RXBUFSIZE 1024 #define VCA_ADDRBUFSIZE 32 -#define VCA_UNKNOWNHDR 10 -struct httphdr { - const char *req; - const char *url; - const char *proto; - const char *status; - const char *response; -#define HTTPH(a, b, c, d, e, f, g) const char *b; -#include -#undef HTTPH - const char *uhdr[VCA_UNKNOWNHDR]; - unsigned nuhdr; -}; - struct object { unsigned char hash[16]; unsigned refcnt; @@ -58,14 +43,9 @@ /* formatted ascii client address */ char addr[VCA_ADDRBUFSIZE]; - /* Receive buffer for HTTP header */ - char rcv[VCA_RXBUFSIZE + 1]; - unsigned rcv_len; - unsigned rcv_ptr; + /* HTTP request */ + struct http *http; - /* HTTP request info, points into rcv */ - struct httphdr http; - enum { HND_Unclass, HND_Deliver, Modified: trunk/varnish-cache/lib/libvcl/vcl_compile.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/lib/libvcl/vcl_compile.c 2006-04-25 06:16:22 UTC (rev 146) @@ -121,7 +121,7 @@ static struct var vars[] = { - { "req.request", STRING, 0, "sess->http.req" }, + { "req.request", STRING, 0, "\"GET\"" }, { "obj.valid", BOOL, 0, "sess->obj->valid" }, { "obj.cacheable", BOOL, 0, "sess->obj->cacheable" }, #if 0 Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-24 19:10:09 UTC (rev 145) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-25 06:16:22 UTC (rev 146) @@ -411,73 +411,8 @@ fputs(" unsigned mask;\n", f); fputs("};\n", f); fputs("\n", f); - fputs("#define VCA_RXBUFSIZE 1024\n", f); fputs("#define VCA_ADDRBUFSIZE 32\n", f); - fputs("#define VCA_UNKNOWNHDR 10\n", f); fputs("\n", f); - fputs("struct httphdr {\n", f); - fputs(" const char *req;\n", f); - fputs(" const char *url;\n", f); - fputs(" const char *proto;\n", f); - fputs(" const char *status;\n", f); - fputs(" const char *response;\n", f); - fputs("#define HTTPH(a, b, c, d, e, f, g) const char *b;\n", f); - fputs("/*\n", f); - fputs(" * $Id$\n", f); - fputs(" *\n", f); - fputs(" * a Http header name\n", f); - fputs(" * b session field name\n", f); - fputs(" * c Request(1)/Response(2) bitfield\n", f); - fputs(" * d Pass header\n", f); - fputs(" * e unused\n", f); - fputs(" * f unused\n", f); - fputs(" * g unused\n", f); - fputs(" *\n", f); - fputs(" * a b c d e f g \n", f); - fputs(" *--------------------------------------------------------------------\n", f); - fputs(" */\n", f); - fputs("HTTPH(\"Connection\", H_Connection, 3, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Keep-Alive\", H_Keep_Alive, 3, 0, 0, 0, 0)\n", f); - fputs("HTTPH(\"Cache-Control\", H_Cache_Control, 3, 1, 0, 0, 0)\n", f); - fputs("\n", f); - fputs("HTTPH(\"Accept-Charset\", H_Accept_Charset, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Encoding\", H_Accept_Encoding, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Language\", H_Accept_Language, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept\", H_Accept, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Authorization\", H_Authorization, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Expect\", H_Expect, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"From\", H_From, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Host\", H_Host, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Match\", H_If_Match, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Modified-Since\", H_If_Modified_Since, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-None-Match\", H_If_None_Match, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Range\", H_If_Range, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"If-Unmodified-Since\", H_If_Unmodifed_Since, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Max-Forwards\", H_Max_Forwards, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Proxy-Authorization\", H_Proxy_Authorization, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Range\", H_Range, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Referer\", H_Referer, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"TE\", H_TE, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"User-Agent\", H_User_Agent, 1, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Pragma\", H_Pragma, 1, 1, 0, 0, 0)\n", f); - fputs("\n", f); - fputs("HTTPH(\"Server\", H_Server, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Content-Type\", H_Content_Type, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Date\", H_Date, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Last-Modified\", H_Last_Modified, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Accept-Ranges\", H_Accept_Ranges, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Content-Length\", H_Content_Length, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Vary\", H_Vary, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Expires\", H_Expires, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Location\", H_Location, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"Content-Encoding\", H_Content_Encoding, 2, 1, 0, 0, 0)\n", f); - fputs("HTTPH(\"ETag:\", H_ETag, 2, 1, 0, 0, 0)\n", f); - fputs("\n", f); - fputs("#undef HTTPH\n", f); - fputs(" const char *uhdr[VCA_UNKNOWNHDR];\n", f); - fputs(" unsigned nuhdr;\n", f); - fputs("};\n", f); - fputs("\n", f); fputs("struct object { \n", f); fputs(" unsigned char hash[16];\n", f); fputs(" unsigned refcnt;\n", f); @@ -496,14 +431,9 @@ fputs(" /* formatted ascii client address */\n", f); fputs(" char addr[VCA_ADDRBUFSIZE];\n", f); fputs("\n", f); - fputs(" /* Receive buffer for HTTP header */\n", f); - fputs(" char rcv[VCA_RXBUFSIZE + 1];\n", f); - fputs(" unsigned rcv_len;\n", f); - fputs(" unsigned rcv_ptr;\n", f); + fputs(" /* HTTP request */\n", f); + fputs(" struct http *http;\n", f); fputs("\n", f); - fputs(" /* HTTP request info, points into rcv */\n", f); - fputs(" struct httphdr http;\n", f); - fputs("\n", f); fputs(" enum {\n", f); fputs(" HND_Unclass,\n", f); fputs(" HND_Deliver,\n", f); From phk at projects.linpro.no Tue Apr 25 06:48:56 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 08:48:56 +0200 (CEST) Subject: r147 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425064856.EC8EF1ED6AC@projects.linpro.no> Author: phk Date: 2006-04-25 08:48:56 +0200 (Tue, 25 Apr 2006) New Revision: 147 Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Move shmlog entry, remove debugging Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 06:16:22 UTC (rev 146) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 06:48:56 UTC (rev 147) @@ -37,6 +37,7 @@ fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); + VSL(SLT_Handling, sp->fd, "Fetch fd %d", fd); hp = http_New(); http_BuildSbuf(0, w->sb, sp->http); @@ -66,7 +67,6 @@ assert(http_GetHdr(hp, "Content-Length", &b)); cl = strtoumax(b, NULL, 0); - VSL(SLT_Debug, 0, "cl %jd (%s)", cl, b); sp->handling = HND_Unclass; sp->vcl->fetch_func(sp); @@ -83,7 +83,6 @@ if (http_GetTail(hp, cl, &b, &e)) { i = e - b; - VSL(SLT_Debug, 0, "T i %d cl %jd", i, cl); memcpy(p, b, i); p += i; cl -= i; @@ -91,7 +90,6 @@ while (cl != 0) { i = read(sp2.fd, p, cl); - VSL(SLT_Debug, 0, "R i %d cl %jd", i, cl); assert(i > 0); p += i; cl -= i; Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-25 06:16:22 UTC (rev 146) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-25 06:48:56 UTC (rev 147) @@ -134,7 +134,6 @@ done = LookupSession(&w, sp); break; case HND_Fetch: - VSL(SLT_Handling, sp->fd, "Fetch"); done = FetchSession(&w, sp); break; case HND_Deliver: From phk at projects.linpro.no Tue Apr 25 06:52:27 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 08:52:27 +0200 (CEST) Subject: r148 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425065227.0B1111ED6AF@projects.linpro.no> Author: phk Date: 2006-04-25 08:52:26 +0200 (Tue, 25 Apr 2006) New Revision: 148 Modified: trunk/varnish-cache/bin/varnishd/cache_http.c Log: Add an end pointer so allocation size can be changed on the fly Modified: trunk/varnish-cache/bin/varnishd/cache_http.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 06:48:56 UTC (rev 147) +++ trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 06:52:26 UTC (rev 148) @@ -30,6 +30,7 @@ void *arg; char *s; /* start of buffer */ + char *e; /* end of buffer */ char *v; /* valid bytes */ char *t; /* start of trailing data */ @@ -57,7 +58,9 @@ hp->s = malloc(http_bufsize); assert(hp->s != NULL); + hp->e = hp->s + http_bufsize; hp->v = hp->s; + hp->t = hp->s; hp->hdr = malloc(sizeof *hp->hdr * http_nhdr); assert(hp->hdr != NULL); @@ -230,8 +233,8 @@ char *p; int i; - assert(hp->v < hp->s + http_bufsize); - i = read(fd, hp->v, (hp->s + http_bufsize) - hp->v); + assert(hp->v < hp->e); + i = read(fd, hp->v, hp->e - hp->v); if (i <= 0) { if (hp->v != hp->s) VSL(SLT_SessionClose, fd, @@ -263,6 +266,11 @@ } hp->t = ++p; +#if 0 +printf("Head:\n%#H\n", hp->s, hp->t - hp->s); +printf("Tail:\n%#H\n", hp->t, hp->v - hp->t); +#endif + event_del(&hp->ev); if (hp->callback != NULL) hp->callback(hp->arg, 1); @@ -275,8 +283,11 @@ { assert(hp != NULL); + VSL(SLT_Debug, fd, "%s s %p t %p v %p", __func__, hp->s, hp->t, hp->v); + assert(hp->t == hp->s || hp->t == hp->v); /* XXX pipelining */ hp->callback = func; hp->arg = arg; + hp->v = hp->s; hp->t = hp->s; event_set(&hp->ev, fd, EV_READ | EV_PERSIST, http_read_f, hp); event_base_set(eb, &hp->ev); From phk at projects.linpro.no Tue Apr 25 07:04:43 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 09:04:43 +0200 (CEST) Subject: r149 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425070443.2C4061ED699@projects.linpro.no> Author: phk Date: 2006-04-25 09:04:43 +0200 (Tue, 25 Apr 2006) New Revision: 149 Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c trunk/varnish-cache/bin/varnishd/cache_fetch.c Log: Track backend connections in shmem log Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-25 06:52:26 UTC (rev 148) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-25 07:04:43 UTC (rev 149) @@ -16,7 +16,9 @@ #include #include "libvarnish.h" +#include "shmlog.h" #include "vcl_lang.h" +#include "cache.h" /* * The internal backend structure for managing connection pools per @@ -82,6 +84,7 @@ } while ((res0 = res0->ai_next) != NULL); freeaddrinfo(res); vc->fd = s; + VSL(SLT_BackendOpen, vc->fd, ""); return; } @@ -136,6 +139,8 @@ struct vbe_conn *vc; vc = ptr; + VSL(SLT_BackendClose, vc->fd, ""); + close(vc->fd); AZ(pthread_mutex_lock(&vbemtx)); TAILQ_REMOVE(&vc->vbe->bconn, vc, list); AZ(pthread_mutex_unlock(&vbemtx)); @@ -150,6 +155,7 @@ struct vbe_conn *vc; vc = ptr; + VSL(SLT_BackendReuse, vc->fd, ""); AZ(pthread_mutex_lock(&vbemtx)); TAILQ_REMOVE(&vc->vbe->bconn, vc, list); TAILQ_INSERT_HEAD(&vc->vbe->fconn, vc, list); Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 06:52:26 UTC (rev 148) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 07:04:43 UTC (rev 149) @@ -106,7 +106,6 @@ if (http_GetHdr(sp->http, "Connection", &b) && !strcasecmp(b, "close")) { - close(fd); VBE_ClosedFd(fd_token); } else { VBE_RecycleFd(fd_token); From phk at projects.linpro.no Tue Apr 25 07:10:36 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 09:10:36 +0200 (CEST) Subject: r150 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425071036.B60B81ED6A3@projects.linpro.no> Author: phk Date: 2006-04-25 09:10:36 +0200 (Tue, 25 Apr 2006) New Revision: 150 Modified: trunk/varnish-cache/bin/varnishd/cache_http.c Log: reset header count before we dissect Modified: trunk/varnish-cache/bin/varnishd/cache_http.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 07:04:43 UTC (rev 149) +++ trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 07:10:36 UTC (rev 150) @@ -202,6 +202,7 @@ if (*p == '\r') p++; + hp->nhdr = 0; for (; p < hp->v; p = r) { q = strchr(p, '\n'); assert(q != NULL); @@ -346,6 +347,8 @@ for (u = 0; u < hp->nhdr; u++) { if (http_supress(hp->hdr[u], resp)) continue; + if (0) + VSL(SLT_Debug, 0, "Build %s", hp->hdr[u]); sbuf_cat(sb, hp->hdr[u]); sbuf_cat(sb, "\r\n"); } From phk at projects.linpro.no Tue Apr 25 08:14:29 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 10:14:29 +0200 (CEST) Subject: r151 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425081429.2316D1ED6BB@projects.linpro.no> Author: phk Date: 2006-04-25 10:14:29 +0200 (Tue, 25 Apr 2006) New Revision: 151 Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c trunk/varnish-cache/bin/varnishd/cache_pool.c Log: Implement a rudimentary chunked Transfer-Encoding Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 07:10:36 UTC (rev 150) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 08:14:29 UTC (rev 151) @@ -22,55 +22,18 @@ #include "vcl_lang.h" #include "cache.h" -/*--------------------------------------------------------------------*/ -int -FetchSession(struct worker *w, struct sess *sp) +static int +fetch_straight(struct worker *w, struct sess *sp, struct http *hp, char *b) { - int fd, i; - void *fd_token; + int i; + char *e; struct sess sp2; + unsigned char *p; off_t cl; struct storage *st; - unsigned char *p; - char *b, *e; - struct http *hp; - fd = VBE_GetFd(sp->backend, &fd_token); - assert(fd != -1); - VSL(SLT_Handling, sp->fd, "Fetch fd %d", fd); - - hp = http_New(); - http_BuildSbuf(0, w->sb, sp->http); - i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); - assert(i == sbuf_len(w->sb)); - - /* 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(hp, sp2.fd, w->eb, NULL, NULL); - event_base_loop(w->eb, 0); - http_Dissect(hp, sp2.fd, 2); - - /* XXX: fill in object from headers */ - sp->obj->valid = 1; - sp->obj->cacheable = 1; - - /* XXX: unbusy, and kick other sessions into action */ - sp->obj->busy = 0; - - assert(http_GetHdr(hp, "Content-Length", &b)); - cl = strtoumax(b, NULL, 0); - sp->handling = HND_Unclass; - sp->vcl->fetch_func(sp); - st = stevedore->alloc(cl); TAILQ_INSERT_TAIL(&sp->obj->store, st, list); st->len = cl; @@ -106,9 +69,154 @@ if (http_GetHdr(sp->http, "Connection", &b) && !strcasecmp(b, "close")) { + return (1); + } else { + return (0); + } +} + +static int +fetch_chunked(struct worker *w, struct sess *sp, struct http *hp) +{ + int i; + char *b, *q, *e; + struct sess sp2; + unsigned char *p; + struct storage *st; + unsigned u; + char buf[20]; + char *bp, *be; + + i = fcntl(sp2.fd, F_GETFL); /* XXX ? */ + i &= ~O_NONBLOCK; + i = fcntl(sp2.fd, F_SETFL, i); + + be = buf + sizeof buf; + while (1) { + bp = buf; + if (http_GetTail(hp, be - bp, &b, &e)) { +if (0) +printf("Tail: (H)\n%#H\n", b, e - b); + memcpy(bp, b, e - b); + bp += e - b; + } else { + i = read(sp2.fd, bp, be - bp); + assert(i >= 0); + bp += i; + } + u = strtoul(buf, &q, 16); +if (0) +printf("Buf: u %u q %p buf %p\n%#H\n", u, q, buf, buf, bp - buf); + if (q == NULL || (*q != '\n' && *q != '\r')) + continue; + if (*q == '\r') + q++; + assert(*q == '\n'); + q++; + if (u == 0) + break; + st = stevedore->alloc(u); + TAILQ_INSERT_TAIL(&sp->obj->store, st, list); + st->len = u; + sp->obj->len += u; + p = st->ptr; + memcpy(p, q, bp - q); + p += bp - q; + u -= bp - q; + if (http_GetTail(hp, u, &b, &e)) { +if (0) +printf("Tail: (B)\n%#H\n", b, e - b); + memcpy(p, b, e - b); + p += e - b; + u -= e - b; + } + if (u > 0) { + i = read(sp2.fd, p, u); +if (0) +printf("u = %u i = %d\n", u, i); + assert(i == u); + } +if (0) +printf("Store:\n%#H\n", st->ptr, st->len); + } + + http_BuildSbuf(1, w->sb, hp); + i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); + + TAILQ_FOREACH(st, &sp->obj->store, list) { + i = write(sp->fd, st->ptr, st->len); + assert(i == st->len); + } + + hash->deref(sp->obj); + + if (http_GetHdr(sp->http, "Connection", &b) && + !strcasecmp(b, "close")) { + return (1); + } else { + return (0); + } +} + +/*--------------------------------------------------------------------*/ +int +FetchSession(struct worker *w, struct sess *sp) +{ + int fd, i, cls; + void *fd_token; + struct sess sp2; + struct http *hp; + char *b; + + fd = VBE_GetFd(sp->backend, &fd_token); + assert(fd != -1); + VSL(SLT_Handling, sp->fd, "Fetch fd %d", fd); + + hp = http_New(); + http_BuildSbuf(0, w->sb, sp->http); + i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); + assert(i == sbuf_len(w->sb)); + + /* 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(hp, sp2.fd, w->eb, NULL, NULL); + event_base_loop(w->eb, 0); + http_Dissect(hp, sp2.fd, 2); + + /* XXX: fill in object from headers */ + sp->obj->valid = 1; + sp->obj->cacheable = 1; + + sp->handling = HND_Insert; + sp->vcl->fetch_func(sp); + + assert(sp->handling == HND_Insert); + + if (http_GetHdr(hp, "Content-Length", &b)) { + cls = fetch_straight(w, sp, hp, b); + } else if (http_GetHdr(hp, "Transfer-Encoding", &b) && + !strcasecmp(b, "chunked")) { + cls = fetch_chunked(w, sp, hp); + } else { + assert(0 == 1); + cls = 0; + } + + if (cls) VBE_ClosedFd(fd_token); - } else { + else VBE_RecycleFd(fd_token); - } + + /* XXX: unbusy, and kick other sessions into action */ + sp->obj->busy = 0; + return (1); } Modified: trunk/varnish-cache/bin/varnishd/cache_pool.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-25 07:10:36 UTC (rev 150) +++ trunk/varnish-cache/bin/varnishd/cache_pool.c 2006-04-25 08:14:29 UTC (rev 151) @@ -150,7 +150,7 @@ PassSession(&w, sp); done = 1; break; - case HND_Unclass: + default: VSL(SLT_Handling, sp->fd, "Unclass"); assert(sp->handling == HND_Unclass); assert(sp->handling != HND_Unclass); From phk at projects.linpro.no Tue Apr 25 08:17:17 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 10:17:17 +0200 (CEST) Subject: r152 - in trunk/varnish-cache: include lib/libvcl Message-ID: <20060425081717.25CBA1ED6BE@projects.linpro.no> Author: phk Date: 2006-04-25 10:17:17 +0200 (Tue, 25 Apr 2006) New Revision: 152 Modified: trunk/varnish-cache/include/shmlog_tags.h trunk/varnish-cache/include/vcl_lang.h trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c Log: Add new shmlog tags and handling states Modified: trunk/varnish-cache/include/shmlog_tags.h =================================================================== --- trunk/varnish-cache/include/shmlog_tags.h 2006-04-25 08:14:29 UTC (rev 151) +++ trunk/varnish-cache/include/shmlog_tags.h 2006-04-25 08:17:17 UTC (rev 152) @@ -11,6 +11,9 @@ SLTM(SessionOpen) SLTM(SessionReuse) SLTM(SessionClose) +SLTM(BackendOpen) +SLTM(BackendReuse) +SLTM(BackendClose) SLTM(ClientAddr) SLTM(Handling) SLTM(Request) Modified: trunk/varnish-cache/include/vcl_lang.h =================================================================== --- trunk/varnish-cache/include/vcl_lang.h 2006-04-25 08:14:29 UTC (rev 151) +++ trunk/varnish-cache/include/vcl_lang.h 2006-04-25 08:17:17 UTC (rev 152) @@ -52,7 +52,8 @@ HND_Pass, HND_Pipe, HND_Lookup, - HND_Fetch + HND_Fetch, + HND_Insert } handling; char done; Modified: trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c =================================================================== --- trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-25 08:14:29 UTC (rev 151) +++ trunk/varnish-cache/lib/libvcl/vcl_fixed_token.c 2006-04-25 08:17:17 UTC (rev 152) @@ -440,7 +440,8 @@ fputs(" HND_Pass,\n", f); fputs(" HND_Pipe,\n", f); fputs(" HND_Lookup,\n", f); - fputs(" HND_Fetch\n", f); + fputs(" HND_Fetch,\n", f); + fputs(" HND_Insert\n", f); fputs(" } handling;\n", f); fputs("\n", f); fputs(" char done;\n", f); From phk at projects.linpro.no Tue Apr 25 08:17:43 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 10:17:43 +0200 (CEST) Subject: r153 - trunk/varnish-cache/bin/varnishlog Message-ID: <20060425081743.92ABF1ED6C1@projects.linpro.no> Author: phk Date: 2006-04-25 10:17:43 +0200 (Tue, 25 Apr 2006) New Revision: 153 Modified: trunk/varnish-cache/bin/varnishlog/varnishlog.c Log: Make width colum wider and decimal Modified: trunk/varnish-cache/bin/varnishlog/varnishlog.c =================================================================== --- trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-25 08:17:17 UTC (rev 152) +++ trunk/varnish-cache/bin/varnishlog/varnishlog.c 2006-04-25 08:17:43 UTC (rev 153) @@ -88,7 +88,7 @@ } u = (p[2] << 8) | p[3]; if (!startup) { - printf("%02x %02d %4d %-12s <", + printf("%02x %3d %4d %-12s <", p[0], p[1], u, tagnames[p[0]]); if (p[1] > 0) fwrite(p + 4, p[1], 1, stdout); From phk at projects.linpro.no Tue Apr 25 09:30:53 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 11:30:53 +0200 (CEST) Subject: r154 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425093053.029301ED6BE@projects.linpro.no> Author: phk Date: 2006-04-25 11:30:53 +0200 (Tue, 25 Apr 2006) New Revision: 154 Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c Log: Keep alive often enough Modified: trunk/varnish-cache/bin/varnishd/mgt_child.c =================================================================== --- trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-25 08:17:43 UTC (rev 153) +++ trunk/varnish-cache/bin/varnishd/mgt_child.c 2006-04-25 09:30:53 UTC (rev 154) @@ -188,7 +188,7 @@ time(&t); mgt_child_request(child_pingpong_ccb, NULL, NULL, "ping %ld", t); if (1) { - tv.tv_sec = 30; + tv.tv_sec = 10; tv.tv_usec = 0; evtimer_del(&ev_child_pingpong); evtimer_add(&ev_child_pingpong, &tv); From phk at projects.linpro.no Tue Apr 25 09:31:28 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 11:31:28 +0200 (CEST) Subject: r155 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425093128.E4FB51ED6C7@projects.linpro.no> Author: phk Date: 2006-04-25 11:31:28 +0200 (Tue, 25 Apr 2006) New Revision: 155 Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c trunk/varnish-cache/bin/varnishd/cache_pipe.c Log: Fix argument to http_BuildSbuf Modified: trunk/varnish-cache/bin/varnishd/cache_pass.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-25 09:30:53 UTC (rev 154) +++ trunk/varnish-cache/bin/varnishd/cache_pass.c 2006-04-25 09:31:28 UTC (rev 155) @@ -44,7 +44,7 @@ fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - http_BuildSbuf(0, w->sb, sp->http); + http_BuildSbuf(1, w->sb, sp->http); i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -61,7 +61,7 @@ event_base_loop(w->eb, 0); http_Dissect(sp2.http, sp2.fd, 2); - http_BuildSbuf(1, w->sb, sp2.http); + http_BuildSbuf(2, w->sb, sp2.http); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); Modified: trunk/varnish-cache/bin/varnishd/cache_pipe.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-25 09:30:53 UTC (rev 154) +++ trunk/varnish-cache/bin/varnishd/cache_pipe.c 2006-04-25 09:31:28 UTC (rev 155) @@ -52,7 +52,7 @@ fd = VBE_GetFd(sp->backend, &fd_token); assert(fd != -1); - http_BuildSbuf(0, w->sb, sp->http); + http_BuildSbuf(0, w->sb, sp->http); /* XXX: 0 ?? */ i = write(fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); assert(__LINE__ == 0); From phk at projects.linpro.no Tue Apr 25 09:32:14 2006 From: phk at projects.linpro.no (phk at projects.linpro.no) Date: Tue, 25 Apr 2006 11:32:14 +0200 (CEST) Subject: r156 - trunk/varnish-cache/bin/varnishd Message-ID: <20060425093214.D5E3F1ED6C5@projects.linpro.no> Author: phk Date: 2006-04-25 11:32:14 +0200 (Tue, 25 Apr 2006) New Revision: 156 Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c trunk/varnish-cache/bin/varnishd/cache_fetch.c trunk/varnish-cache/bin/varnishd/cache_http.c Log: test backend connections at allocation time. General bush-wacking in the fetch code. Modified: trunk/varnish-cache/bin/varnishd/cache_backend.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-25 09:31:28 UTC (rev 155) +++ trunk/varnish-cache/bin/varnishd/cache_backend.c 2006-04-25 09:32:14 UTC (rev 156) @@ -14,6 +14,7 @@ #include #include #include +#include #include "libvarnish.h" #include "shmlog.h" @@ -91,11 +92,41 @@ /*--------------------------------------------------------------------*/ int +tst_fd(int fd) +{ + fd_set r,w,e; + int i; + struct timeval tv; + char c; + + FD_ZERO(&r); + FD_ZERO(&w); + FD_ZERO(&e); + FD_SET(fd, &r); + FD_SET(fd, &w); + FD_SET(fd, &e); + tv.tv_sec = 0; + tv.tv_usec = 0; + i = select(fd + 1, &r, &w, &e, &tv); + printf("tst_fd fd %d i %d flag %d/%d/%d\n", + fd, i, FD_ISSET(fd, &r), FD_ISSET(fd, &w), FD_ISSET(fd, &e)); + if (FD_ISSET(fd, &r)) { + i = read(fd, &c, 1); + if (i == 0) + return (1); + } + return (0); +} + +/*--------------------------------------------------------------------*/ + +int VBE_GetFd(struct backend *bp, void **ptr) { struct vbe *vp; struct vbe_conn *vc; +again: AZ(pthread_mutex_lock(&vbemtx)); vp = bp->vbe; if (vp == NULL) { @@ -118,6 +149,10 @@ TAILQ_REMOVE(&vp->fconn, vc, list); TAILQ_INSERT_TAIL(&vp->bconn, vc, list); AZ(pthread_mutex_unlock(&vbemtx)); + if (tst_fd(vc->fd)) { + VBE_ClosedFd(vc); + goto again; + } } else { vc = calloc(sizeof *vc, 1); assert(vc != NULL); Modified: trunk/varnish-cache/bin/varnishd/cache_fetch.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 09:31:28 UTC (rev 155) +++ trunk/varnish-cache/bin/varnishd/cache_fetch.c 2006-04-25 09:32:14 UTC (rev 156) @@ -23,11 +23,10 @@ #include "cache.h" static int -fetch_straight(struct worker *w, struct sess *sp, struct http *hp, char *b) +fetch_straight(struct worker *w, struct sess *sp, int fd, struct http *hp, char *b) { int i; char *e; - struct sess sp2; unsigned char *p; off_t cl; struct storage *st; @@ -40,25 +39,27 @@ sp->obj->len = cl; p = st->ptr; - i = fcntl(sp2.fd, F_GETFL); /* XXX ? */ + i = fcntl(fd, F_GETFL); /* XXX ? */ i &= ~O_NONBLOCK; - i = fcntl(sp2.fd, F_SETFL, i); + i = fcntl(fd, F_SETFL, i); if (http_GetTail(hp, cl, &b, &e)) { i = e - b; + VSL(SLT_Debug, 0, "Fetch_Tail %jd %d", cl, i); memcpy(p, b, i); p += i; cl -= i; } while (cl != 0) { - i = read(sp2.fd, p, cl); + i = read(fd, p, cl); + VSL(SLT_Debug, 0, "Fetch_Read %jd %d", cl, i); assert(i > 0); p += i; cl -= i; } - http_BuildSbuf(1, w->sb, hp); + http_BuildSbuf(2, w->sb, hp); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -76,20 +77,19 @@ } static int -fetch_chunked(struct worker *w, struct sess *sp, struct http *hp) +fetch_chunked(struct worker *w, struct sess *sp, int fd, struct http *hp) { int i; char *b, *q, *e; - struct sess sp2; unsigned char *p; struct storage *st; unsigned u; char buf[20]; char *bp, *be; - i = fcntl(sp2.fd, F_GETFL); /* XXX ? */ + i = fcntl(fd, F_GETFL); /* XXX ? */ i &= ~O_NONBLOCK; - i = fcntl(sp2.fd, F_SETFL, i); + i = fcntl(fd, F_SETFL, i); be = buf + sizeof buf; while (1) { @@ -100,7 +100,7 @@ memcpy(bp, b, e - b); bp += e - b; } else { - i = read(sp2.fd, bp, be - bp); + i = read(fd, bp, be - bp); assert(i >= 0); bp += i; } @@ -131,7 +131,7 @@ u -= e - b; } if (u > 0) { - i = read(sp2.fd, p, u); + i = read(fd, p, u); if (0) printf("u = %u i = %d\n", u, i); assert(i == u); @@ -140,7 +140,7 @@ printf("Store:\n%#H\n", st->ptr, st->len); } - http_BuildSbuf(1, w->sb, hp); + http_BuildSbuf(2, w->sb, hp); i = write(sp->fd, sbuf_data(w->sb), sbuf_len(w->sb)); assert(i == sbuf_len(w->sb)); @@ -165,7 +165,6 @@ { int fd, i, cls; void *fd_token; - struct sess sp2; struct http *hp; char *b; @@ -174,22 +173,21 @@ VSL(SLT_Handling, sp->fd, "Fetch fd %d", fd); hp = http_New(); - http_BuildSbuf(0, w->sb, sp->http); +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)); /* 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(hp, sp2.fd, w->eb, NULL, NULL); + http_RecvHead(hp, fd, w->eb, NULL, NULL); event_base_loop(w->eb, 0); - http_Dissect(hp, sp2.fd, 2); + http_Dissect(hp, fd, 2); /* XXX: fill in object from headers */ sp->obj->valid = 1; @@ -201,12 +199,12 @@ assert(sp->handling == HND_Insert); if (http_GetHdr(hp, "Content-Length", &b)) { - cls = fetch_straight(w, sp, hp, b); + cls = fetch_straight(w, sp, fd, hp, b); } else if (http_GetHdr(hp, "Transfer-Encoding", &b) && !strcasecmp(b, "chunked")) { - cls = fetch_chunked(w, sp, hp); + cls = fetch_chunked(w, sp, fd, hp); } else { - assert(0 == 1); + VSL(SLT_Debug, fd, "No transfer"); cls = 0; } Modified: trunk/varnish-cache/bin/varnishd/cache_http.c =================================================================== --- trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 09:31:28 UTC (rev 155) +++ trunk/varnish-cache/bin/varnishd/cache_http.c 2006-04-25 09:32:14 UTC (rev 156) @@ -137,6 +137,7 @@ { char *p, *q, *r; + assert(hp->t != NULL); if (rr == 1) { /* First, isolate and possibly identify request type */ hp->req = hp->s; @@ -227,6 +228,8 @@ /*--------------------------------------------------------------------*/ +#include + static void http_read_f(int fd, short event, void *arg) { @@ -235,13 +238,14 @@ int i; assert(hp->v < hp->e); + errno = 0; i = read(fd, hp->v, hp->e - hp->v); if (i <= 0) { if (hp->v != hp->s) VSL(SLT_SessionClose, fd, - "remote had %d bytes", hp->v - hp->s); + "remote had %d bytes errno %d", hp->v - hp->s, errno); else - VSL(SLT_SessionClose, fd, "remote"); + VSL(SLT_SessionClose, fd, "remote errno %d", errno); hp->t = NULL; event_del(&hp->ev); if (hp->callback != NULL) @@ -329,25 +333,27 @@ sbuf_clear(sb); assert(sb != NULL); - if (resp) { + if (resp == 2) { sbuf_cat(sb, hp->proto); sbuf_cat(sb, " "); sbuf_cat(sb, hp->status); sbuf_cat(sb, " "); sbuf_cat(sb, hp->response); - } else { + } else if (resp == 1) { sbuf_cat(sb, hp->req); sbuf_cat(sb, " "); sbuf_cat(sb, hp->url); sbuf_cat(sb, " "); sbuf_cat(sb, hp->proto); + } else { + assert(resp == 1 || resp == 2); } sbuf_cat(sb, "\r\n"); for (u = 0; u < hp->nhdr; u++) { if (http_supress(hp->hdr[u], resp)) continue; - if (0) + if (1) VSL(SLT_Debug, 0, "Build %s", hp->hdr[u]); sbuf_cat(sb, hp->hdr[u]); sbuf_cat(sb, "\r\n");