#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 */
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);
}
#include <assert.h>
#include <stdio.h>
+#include <inttypes.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
+#include <fcntl.h>
#include <pthread.h>
#include <sys/queue.h>
#include <sys/types.h>
PassReturn(struct sess *sp)
{
- HERE();
HttpdAnalyze(sp, 2);
}
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);
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;
+ }
+ }
+ }
}
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]]);
}
}
}
-
-
-#if 0
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <sys/wait.h>
-
-#include <event.h>
-#include <sbuf.h>
-
-#include <cli.h>
-#include <cli_priv.h>
-#include <libvarnish.h>
-
-#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@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 <printf.h>
-
-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
*/
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("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)
/* 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;
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(\"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);
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);