From 4f10cd7a93a1267e3989a059f318f714fd0a17d3 Mon Sep 17 00:00:00 2001 From: des Date: Sun, 9 Mar 2008 15:17:49 +0000 Subject: [PATCH] Include complete headers with each replayed request. Ignore SIGPIPE, otherwise varnishreplay will stop as soon as varnishd starts overflowing. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2576 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- .../bin/varnishreplay/varnishreplay.c | 188 +++++++++++------- 1 file changed, 112 insertions(+), 76 deletions(-) diff --git a/varnish-cache/bin/varnishreplay/varnishreplay.c b/varnish-cache/bin/varnishreplay/varnishreplay.c index 18086af8..4319a88b 100644 --- a/varnish-cache/bin/varnishreplay/varnishreplay.c +++ b/varnish-cache/bin/varnishreplay/varnishreplay.c @@ -30,6 +30,9 @@ #include "config.h" +#include +#include + #include #include #include @@ -173,7 +176,7 @@ thread_get(int fd, void *(*thread_main)(void *)) while (fd >= newnthreads) newnthreads += newnthreads + 1; newthreads = realloc(newthreads, newnthreads * sizeof *newthreads); - assert(newthreads != NULL); + XXXAN(newthreads != NULL); memset(newthreads + nthreads, 0, (newnthreads - nthreads) * sizeof *newthreads); threads = newthreads; @@ -189,7 +192,7 @@ thread_get(int fd, void *(*thread_main)(void *)) mailbox_destroy(&threads[fd]->mbox); freez(threads[fd]); } - thread_log(1, 0, "thread %p started", + thread_log(0, 0, "thread %p started", (void *)threads[fd]->thread_id); } return (threads[fd]); @@ -210,7 +213,7 @@ thread_close(int fd) return; mailbox_close(&threads[fd]->mbox); pthread_join(threads[fd]->thread_id, NULL); - thread_log(1, 0, "thread %p stopped", + thread_log(0, 0, "thread %p stopped", (void *)threads[fd]->thread_id); mailbox_destroy(&threads[fd]->mbox); freez(threads[fd]); @@ -237,6 +240,7 @@ isprefix(const char *str, const char *prefix, const char *end, const char **next return (1); } +#if 0 static int isequal(const char *str, const char *reference, const char *end) { @@ -248,6 +252,7 @@ isequal(const char *str, const char *reference, const char *end) return (0); return (1); } +#endif /* * Returns a copy of the entire string with leading and trailing spaces @@ -404,6 +409,7 @@ receive_response(int sock) line_len = read_line(&line, sock); if (line_len < 0) return (-1); + thread_log(2, 0, "< %.*s", line_len, line); end = line + line_len; if (line_len == 0) { freez(line); @@ -474,6 +480,8 @@ receive_response(int sock) static void * replay_thread(void *arg) { + struct iovec iov[6]; + char space[1] = " ", crlf[2] = "\r\n"; struct thread *thr = arg; struct message *msg; enum shmlogtag tag; @@ -481,14 +489,20 @@ replay_thread(void *arg) char *ptr; const char *end, *next; - char *df_H = NULL; /* %H, Protocol version */ - char *df_Host = NULL; /* %{Host}i */ - char *df_Uq = NULL; /* %U%q, URL path and query string */ - char *df_m = NULL; /* %m, Request method*/ - char *df_c = NULL; /* Connection info (keep-alive, close) */ + char *df_method = NULL; /* Request method*/ + char *df_proto = NULL; /* Protocol version */ + char *df_url = NULL; /* URL and query string */ + char *df_conn = NULL; /* Connection info (keep-alive, close) */ + char **df_hdr = NULL; /* Headers */ + size_t df_hdrsz = 0; /* Size of df_hdr */ + int df_nhdr = 0; /* Number of headers */ int bogus = 0; /* bogus request */ + int i; + + int sock = -1, reopen = 1; - int sock, reopen = 1; + df_hdrsz = 16; + df_hdr = malloc(df_hdrsz * sizeof *df_hdr); while ((msg = mailbox_get(&thr->mbox)) != NULL) { tag = msg->tag; @@ -500,115 +514,134 @@ replay_thread(void *arg) switch (tag) { case SLT_RxRequest: - if (df_m != NULL) + if (df_method != NULL) bogus = 1; else - df_m = trimline(ptr, end); + df_method = trimline(ptr, end); break; case SLT_RxURL: - if (df_Uq != NULL) + if (df_url != NULL) bogus = 1; else - df_Uq = trimline(ptr, end); + df_url = trimline(ptr, end); break; case SLT_RxProtocol: - if (df_H != NULL) + if (df_proto != NULL) bogus = 1; else - df_H = trimline(ptr, end); + df_proto = trimline(ptr, end); break; case SLT_RxHeader: - if (isprefix(ptr, "host:", end, &next)) - df_Host = trimline(next, end); + while (df_hdrsz <= df_nhdr) { + df_hdrsz *= 2; + df_hdr = realloc(df_hdr, df_hdrsz * sizeof *df_hdr); + XXXAN(df_hdr); + } + df_hdr[df_nhdr++] = trimline(ptr, end); if (isprefix(ptr, "connection:", end, &next)) - df_c = trimline(next, end); + df_conn = trimline(next, end); break; default: break; } + freez(msg->ptr); + freez(msg); + if (tag != SLT_ReqEnd) continue; - if (!df_m || !df_Uq || !df_H) + if (!df_method || !df_url || !df_proto) { + bogus = 1; + } else if (strcmp(df_method, "GET") != 0 && strcmp(df_method, "HEAD") != 0) { + bogus = 1; + } else if (strcmp(df_proto, "HTTP/1.0") == 0) { + reopen = !(df_conn && strcasecmp(df_conn, "keep-alive") == 0); + } else if (strcmp(df_proto, "HTTP/1.1") == 0) { + reopen = (df_conn && strcasecmp(df_conn, "close") == 0); + } else { bogus = 1; + } if (bogus) { thread_log(1, 0, "bogus"); } else { - /* If the method is supported (GET or HEAD), send the request out - * on the socket. If the socket needs reopening, reopen it first. - * When the request is sent, call the function for receiving - * the answer. - */ - if (!(strcmp(df_m, "GET") && strcmp(df_m, "HEAD"))) { - if (reopen) - sock = VSS_connect(addr_info); - reopen = 0; - - thread_log(1, 0, "%s %s %s", df_m, df_Uq, df_H); - - write(sock, df_m, strlen(df_m)); - write(sock, " ", 1); - write(sock, df_Uq, strlen(df_Uq)); - write(sock, " ", 1); - write(sock, df_H, strlen(df_H)); - write(sock, " ", 1); - write(sock, "\r\n", 2); - - if (strncmp(df_H, "HTTP/1.0", 8)) - reopen = 1; - - write(sock, "Host: ", 6); - if (df_Host) { - thread_log(1, 0, "Host: %s", df_Host); - write(sock, df_Host, strlen(df_Host)); - } - write(sock, "\r\n", 2); - if (df_c) { - thread_log(1, 0, "Connection: %s", df_c); - write(sock, "Connection: ", 12); - write(sock, df_c, strlen(df_c)); - write(sock, "\r\n", 2); - if (isequal(df_c, "keep-alive", df_c + strlen(df_c))) - reopen = 0; + if (sock == -1) { + thread_log(1, 0, "open"); + sock = VSS_connect(addr_info); + assert(sock != -1); + } + + thread_log(1, 0, "%s %s %s", df_method, df_url, df_proto); + + iov[0].iov_base = df_method; + iov[0].iov_len = strlen(df_method); + iov[2].iov_base = df_url; + iov[2].iov_len = strlen(df_url); + iov[4].iov_base = df_proto; + iov[4].iov_len = strlen(df_proto); + iov[1].iov_base = iov[3].iov_base = space; + iov[1].iov_len = iov[3].iov_len = 1; + iov[5].iov_base = crlf; + iov[5].iov_len = 2; + if (writev(sock, iov, 6) == -1) { + thread_log(0, errno, "writev()"); + goto close; + } + + for (i = 0; i < df_nhdr; ++i) { + thread_log(2, 0, "%d %s", i, df_hdr[i]); + iov[0].iov_base = df_hdr[i]; + iov[0].iov_len = strlen(df_hdr[i]); + iov[1].iov_base = crlf; + iov[1].iov_len = 2; + if (writev(sock, iov, 2) == -1) { + thread_log(0, errno, "writev()"); + goto close; } - write(sock, "\r\n", 2); - if (!reopen) - reopen = receive_response(sock); - if (reopen) - close(sock); + } + if (write(sock, crlf, 2) == -1) { + thread_log(0, errno, "writev()"); + goto close; + } + if (receive_response(sock) || reopen) { +close: + thread_log(1, 0, "close"); + close(sock); + sock = -1; } } /* clean up */ - freez(msg->ptr); - freez(msg); - freez(df_H); - freez(df_Host); - freez(df_Uq); - freez(df_m); - freez(df_c); + freez(df_method); + freez(df_url); + freez(df_proto); + freez(df_conn); + while (df_nhdr) { + --df_nhdr; + freez(df_hdr[df_nhdr]); + } bogus = 0; } /* leftovers */ - freez(msg->ptr); - freez(msg); - freez(df_H); - freez(df_Host); - freez(df_Uq); - freez(df_m); - freez(df_c); + freez(df_method); + freez(df_url); + freez(df_proto); + freez(df_conn); + while (df_nhdr) { + --df_nhdr; + freez(df_hdr[df_nhdr]); + } + freez(df_hdr); return (0); } - static int gen_traffic(void *priv, enum shmlogtag tag, unsigned fd, unsigned len, unsigned spec, const char *ptr) @@ -616,6 +649,7 @@ gen_traffic(void *priv, enum shmlogtag tag, unsigned fd, struct thread *thr; const char *end; struct message *msg; + int i; (void)priv; @@ -624,7 +658,7 @@ gen_traffic(void *priv, enum shmlogtag tag, unsigned fd, if (fd == 0 || !(spec & VSL_S_CLIENT)) return (0); - thread_log(2, 0, "%d %s", fd, VSL_tags[tag]); + thread_log(3, 0, "%d %s", fd, VSL_tags[tag]); thr = thread_get(fd, replay_thread); msg = malloc(sizeof (struct message)); msg->tag = tag; @@ -680,6 +714,8 @@ main(int argc, char *argv[]) addr_info = init_connection(address); + signal(SIGPIPE, SIG_IGN); + while (VSL_Dispatch(vd, gen_traffic, NULL) == 0) /* nothing */ ; thread_close(0); -- 2.39.5