]> err.no Git - varnish/commitdiff
This is the skeleton code I wrote on my way back from Basel last fall. The
authordes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 10 Feb 2006 14:41:36 +0000 (14:41 +0000)
committerdes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 10 Feb 2006 14:41:36 +0000 (14:41 +0000)
code itself is probably not worth much, but I've put quite a lot of work into
two portions of it: the autoconf framework and the listener code.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3 d4fa192b-c00b-0410-8231-f00ffab90ce4

12 files changed:
Makefile.am [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
connection.c [new file with mode: 0644]
connection.h [new file with mode: 0644]
listener.c [new file with mode: 0644]
listener.h [new file with mode: 0644]
log.c [new file with mode: 0644]
request.c [new file with mode: 0644]
request.h [new file with mode: 0644]
varnish.c [new file with mode: 0644]
varnish.h [new file with mode: 0644]

diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..04d11a2
--- /dev/null
@@ -0,0 +1,10 @@
+# $Id$
+
+bin_PROGRAMS = varnish
+
+varnish_SOURCES = \
+       connection.c \
+       listener.c \
+       log.c \
+       request.c \
+       varnish.c
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..be61b2b
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# $Id$
+#
+
+aclocal
+autoheader
+automake --add-missing --copy --force --foreign
+autoconf
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..ca8869d
--- /dev/null
@@ -0,0 +1,64 @@
+# $Id$
+
+AC_PREREQ(2.59)
+AC_COPYRIGHT([Copyright (c) 2006 Linpro AS])
+AC_REVISION([$Id$])
+AC_INIT([Varnish], [0.1], [varnish-dev@projects.linpro.no])
+AC_CONFIG_SRCDIR([varnish.c])
+AC_CONFIG_HEADER([config.h])
+
+AC_CANONICAL_SYSTEM
+AC_LANG(C)
+
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+# Compiler flags (assume GCC).
+# This section *must* come before AC_PROG_CC / AC_PROG_CPP.
+CFLAGS="${CFLAGS:--O2}"
+AC_ARG_ENABLE(wall,
+       AS_HELP_STRING([--enable-wall],[use -Wall (default is NO)]),
+       CFLAGS="${CFLAGS} -Wall")
+AC_ARG_ENABLE(pedantic,
+       AS_HELP_STRING([--enable-pedantic],[enable pedantic warnings (default is NO)]),
+       CFLAGS="${CFLAGS} -pedantic")
+AC_ARG_ENABLE(werror,
+       AS_HELP_STRING([--enable-werror],[use -Werror (default is NO)]),
+       CFLAGS="${CFLAGS} -Werror")
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([sys/socket.h])
+AC_CHECK_HEADERS([netinet/in.h])
+AC_CHECK_HEADERS([stddef.h])
+AC_CHECK_HEADERS([stdlib.h])
+AC_CHECK_HEADERS([unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,[
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+])
+
+# Checks for library functions.
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([strerror])
+AC_FUNC_STRERROR_R
+AC_CHECK_FUNCS([socket])
+
+AC_CONFIG_FILES([
+    Makefile
+])
+AC_OUTPUT
diff --git a/connection.c b/connection.c
new file mode 100644 (file)
index 0000000..4e22640
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "varnish.h"
+#include "connection.h"
+
+void
+connection_destroy(struct connection *c)
+{
+       close(c->sd);
+       /* bzero(c, sizeof *c); */
+       free(c);
+}
diff --git a/connection.h b/connection.h
new file mode 100644 (file)
index 0000000..dfabe0b
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * $Id$
+ */
+
+#ifndef CONNECTION_H_INCLUDED
+#define CONNECTION_H_INCLUDED
+
+struct connection {
+       int sd;
+       struct sockaddr_storage addr;
+};
+
+#endif
diff --git a/listener.c b/listener.c
new file mode 100644 (file)
index 0000000..9c31900
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "varnish.h"
+#include "listener.h"
+#include "connection.h"
+
+/*
+ * Create a socket that listens on the specified port.  We use an IPv6 TCP
+ * socket and clear the IPV6_V6ONLY option to accept IPv4 connections on
+ * the same socket.
+ */
+struct listener *
+listener_create(int port)
+{
+       struct listener *l;
+       socklen_t addr_len;
+       int zero = 0;
+
+       l = calloc(1, sizeof *l);
+       if (l == NULL) {
+               log_syserr("calloc()");
+               return (NULL);
+       }
+       l->sd = -1;
+#if defined(AF_INET6) && defined(IPV6_V6ONLY)
+       if ((l->sd = socket(AF_INET6, SOCK_STREAM, 0)) > 0) {
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&l->addr;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               addr->sin6_len =
+#endif
+               addr_len = sizeof *addr;
+               addr->sin6_family = AF_INET6;
+               addr->sin6_port = htons(port);
+               if (setsockopt(l->sd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof zero) != 0) {
+                       log_syserr("setsockopt()");
+                       return (NULL);
+               }
+       } else if (errno != EPROTONOSUPPORT) {
+               log_syserr("socket()");
+               return (NULL);
+       } else
+#endif
+       if ((l->sd = socket(AF_INET, SOCK_STREAM, 0)) > 0) {
+               struct sockaddr_in *addr = (struct sockaddr_in *)&l->addr;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+               addr->sin_len =
+#endif
+               addr_len = sizeof *addr;
+               addr->sin_family = AF_INET;
+               addr->sin_port = htons(port);
+       } else {
+               log_syserr("socket()");
+               return (NULL);
+       }
+       if (bind(l->sd, (struct sockaddr *)&l->addr, addr_len) != 0) {
+               log_syserr("bind()");
+               return (NULL);
+       }
+       if (listen(l->sd, 16) != 0) {
+               log_syserr("listen()");
+               return (NULL);
+       }
+       return (l);
+}
+
+void
+listener_destroy(struct listener *l)
+{
+       close(l->sd);
+       /* bzero(l, sizeof *l); */
+       free(l);
+}
+
+struct connection *
+listener_accept(struct listener *l)
+{
+       struct connection *c;
+       socklen_t len;
+
+       c = calloc(1, sizeof *c);
+       for (;;) {
+               len = sizeof c->addr;
+               c->sd = accept(l->sd, (struct sockaddr *)&c->addr, &len);
+               if (c->sd != -1) {
+                       switch (c->addr.ss_family) {
+#if defined(AF_INET6)
+                       case AF_INET6: {
+                               struct sockaddr_in6 *addr =
+                                   (struct sockaddr_in6 *)&c->addr;
+                               uint16_t *ip = (uint16_t *)&addr->sin6_addr;
+
+                               log_info("%s(): [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%u",
+                                   __func__,
+                                   ntohs(ip[0]), ntohs(ip[1]),
+                                   ntohs(ip[2]), ntohs(ip[3]),
+                                   ntohs(ip[4]), ntohs(ip[5]),
+                                   ntohs(ip[6]), ntohs(ip[7]),
+                                   ntohs(addr->sin6_port));
+                               break;
+                       }
+#endif
+                       case AF_INET: {
+                               struct sockaddr_in *addr =
+                                   (struct sockaddr_in *)&c->addr;
+                               uint8_t *ip = (uint8_t *)&addr->sin_addr;
+
+                               log_info("%s(): %u.%u.%u.%u:%u",
+                                   __func__,
+                                   ip[0], ip[1], ip[2], ip[3],
+                                   ntohs(addr->sin_port));
+                               break;
+                       }
+                       default:
+                               LOG_UNREACHABLE();
+                       }
+                       return (c);
+               }
+               if (errno != EINTR) {
+                       log_syserr("accept()");
+                       free(c);
+                       return (NULL);
+               }
+       }
+}
diff --git a/listener.h b/listener.h
new file mode 100644 (file)
index 0000000..15d83ff
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * $Id$
+ */
+
+#ifndef LISTENER_H_INCLUDED
+#define LISTENER_H_INCLUDED
+
+struct listener {
+       int sd;
+       struct sockaddr_storage addr;
+};
+
+#endif
diff --git a/log.c b/log.c
new file mode 100644 (file)
index 0000000..de52de1
--- /dev/null
+++ b/log.c
@@ -0,0 +1,94 @@
+/*
+ * $Id$
+ */
+
+#include <sys/signal.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "varnish.h"
+
+static void
+emit(const char *fmt, va_list ap)
+{
+       vfprintf(stderr, fmt, ap);
+       fprintf(stderr, "\n");
+}
+
+static void
+sysemit(const char *fmt, va_list ap)
+{
+       char errstr[64];
+
+#if defined(HAVE_STRERROR_R)
+       strerror_r(errno, errstr, sizeof errstr);
+#else
+       snprintf(errstr, sizeof errstr, "%s", strerror(errno));
+#endif
+       vfprintf(stderr, fmt, ap);
+       fprintf(stderr, ": %s\n", errstr);
+}
+
+static void
+panic(void)
+{
+       signal(SIGABRT, SIG_DFL);
+       kill(getpid(), SIGABRT);
+}
+
+void
+log_info(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       emit(fmt, ap);
+       va_end(ap);
+}
+
+void
+log_err(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       emit(fmt, ap);
+       va_end(ap);
+}
+
+void
+log_syserr(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       sysemit(fmt, ap);
+       va_end(ap);
+}
+
+void
+log_panic(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       emit(fmt, ap);
+       va_end(ap);
+       panic();
+}
+
+void
+log_syspanic(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       sysemit(fmt, ap);
+       va_end(ap);
+       panic();
+}
diff --git a/request.c b/request.c
new file mode 100644 (file)
index 0000000..a8d17f6
--- /dev/null
+++ b/request.c
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ */
+
+#include <stdlib.h>
+
+#include "varnish.h"
+#include "request.h"
+
+request_t *
+request_wait(connection_t *c, unsigned int timeout)
+{
+       request_t *r;
+
+       r = calloc(1, sizeof *r);
+       if (r == NULL) {
+               log_syserr("calloc()");
+               return (NULL);
+       }
+
+       /* ... */
+
+       return (r);
+}
+
+void
+request_destroy(request_t *r)
+{
+       /* bzero(r, sizeof *r); */
+       free(r);
+}
diff --git a/request.h b/request.h
new file mode 100644 (file)
index 0000000..3fd94d8
--- /dev/null
+++ b/request.h
@@ -0,0 +1,12 @@
+/*
+ * $Id$
+ */
+
+#ifndef REQUEST_H_INCLUDED
+#define REQUEST_H_INCLUDED
+
+struct request {
+       struct connection *conn;
+};
+
+#endif
diff --git a/varnish.c b/varnish.c
new file mode 100644 (file)
index 0000000..3484e3e
--- /dev/null
+++ b/varnish.c
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "varnish.h"
+
+static void
+varnish(void)
+{
+       listener_t *l;
+       connection_t *c;
+       request_t *r;
+
+       l = listener_create(8080);
+       while ((c = listener_accept(l)) != NULL) {
+               r = request_wait(c, 0);
+               /* ... */
+               request_destroy(r);
+               connection_destroy(c);
+       }
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage: varnish\n");
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int o;
+
+       while ((o = getopt(argc, argv, "")) != -1)
+               switch (o) {
+               default:
+                       usage();
+               }
+
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 0)
+               usage();
+
+       varnish();
+
+       LOG_UNREACHABLE();
+       exit(1);
+}
diff --git a/varnish.h b/varnish.h
new file mode 100644 (file)
index 0000000..7d3d3c5
--- /dev/null
+++ b/varnish.h
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ */
+
+#ifndef VARNISH_H_INCLUDED
+#define VARNISH_H_INCLUDED
+
+#include "config.h"
+
+/* opaque structures */
+typedef struct listener listener_t;
+typedef struct connection connection_t;
+typedef struct request request_t;
+
+/* connection.c */
+void connection_destroy(connection_t *c);
+
+/* listener.c */
+listener_t *listener_create(int port);
+void listener_destroy(listener_t *l);
+connection_t *listener_accept(listener_t *l);
+
+/* log.c */
+void log_info(const char *fmt, ...);
+void log_err(const char *fmt, ...);
+void log_syserr(const char *fmt, ...);
+void log_panic(const char *fmt, ...);
+void log_syspanic(const char *fmt, ...);
+
+#define LOG_UNREACHABLE() \
+       log_panic("%s(%d): %s(): unreachable code reached", \
+           __FILE__, __LINE__, __func__)
+
+/* request.c */
+request_t *request_wait(connection_t *c, unsigned int timeout);
+void request_destroy(request_t *r);
+
+#endif