r3 - trunk

des at projects.linpro.no des at projects.linpro.no
Fri Feb 10 15:41:36 CET 2006


Author: des
Date: 2006-02-10 15:41:36 +0100 (Fri, 10 Feb 2006)
New Revision: 3

Added:
   trunk/Makefile.am
   trunk/autogen.sh
   trunk/configure.ac
   trunk/connection.c
   trunk/connection.h
   trunk/listener.c
   trunk/listener.h
   trunk/log.c
   trunk/request.c
   trunk/request.h
   trunk/varnish.c
   trunk/varnish.h
Log:
This is the skeleton code I wrote on my way back from Basel last fall.  The
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.

Added: trunk/Makefile.am
===================================================================
--- trunk/Makefile.am	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/Makefile.am	2006-02-10 14:41:36 UTC (rev 3)
@@ -0,0 +1,10 @@
+# $Id$
+
+bin_PROGRAMS = varnish
+
+varnish_SOURCES = \
+	connection.c \
+	listener.c \
+	log.c \
+	request.c \
+	varnish.c


Property changes on: trunk/Makefile.am
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/autogen.sh	2006-02-10 14:41:36 UTC (rev 3)
@@ -0,0 +1,9 @@
+#!/bin/sh
+#
+# $Id$
+#
+
+aclocal
+autoheader
+automake --add-missing --copy --force --foreign
+autoconf


Property changes on: trunk/autogen.sh
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Id

Added: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/configure.ac	2006-02-10 14:41:36 UTC (rev 3)
@@ -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 at 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


Property changes on: trunk/configure.ac
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/connection.c
===================================================================
--- trunk/connection.c	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/connection.c	2006-02-10 14:41:36 UTC (rev 3)
@@ -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);
+}


Property changes on: trunk/connection.c
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/connection.h
===================================================================
--- trunk/connection.h	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/connection.h	2006-02-10 14:41:36 UTC (rev 3)
@@ -0,0 +1,13 @@
+/*
+ * $Id$
+ */
+
+#ifndef CONNECTION_H_INCLUDED
+#define CONNECTION_H_INCLUDED
+
+struct connection {
+	int sd;
+	struct sockaddr_storage addr;
+};
+
+#endif


Property changes on: trunk/connection.h
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/listener.c
===================================================================
--- trunk/listener.c	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/listener.c	2006-02-10 14:41:36 UTC (rev 3)
@@ -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);
+		}
+	}
+}


Property changes on: trunk/listener.c
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/listener.h
===================================================================
--- trunk/listener.h	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/listener.h	2006-02-10 14:41:36 UTC (rev 3)
@@ -0,0 +1,13 @@
+/*
+ * $Id$
+ */
+
+#ifndef LISTENER_H_INCLUDED
+#define LISTENER_H_INCLUDED
+
+struct listener {
+	int sd;
+	struct sockaddr_storage addr;
+};
+
+#endif


Property changes on: trunk/listener.h
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/log.c
===================================================================
--- trunk/log.c	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/log.c	2006-02-10 14:41:36 UTC (rev 3)
@@ -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();
+}


Property changes on: trunk/log.c
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/request.c
===================================================================
--- trunk/request.c	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/request.c	2006-02-10 14:41:36 UTC (rev 3)
@@ -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);
+}


Property changes on: trunk/request.c
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/request.h
===================================================================
--- trunk/request.h	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/request.h	2006-02-10 14:41:36 UTC (rev 3)
@@ -0,0 +1,12 @@
+/*
+ * $Id$
+ */
+
+#ifndef REQUEST_H_INCLUDED
+#define REQUEST_H_INCLUDED
+
+struct request {
+	struct connection *conn;
+};
+
+#endif


Property changes on: trunk/request.h
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/varnish.c
===================================================================
--- trunk/varnish.c	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/varnish.c	2006-02-10 14:41:36 UTC (rev 3)
@@ -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);
+}


Property changes on: trunk/varnish.c
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/varnish.h
===================================================================
--- trunk/varnish.h	2006-02-10 12:48:04 UTC (rev 2)
+++ trunk/varnish.h	2006-02-10 14:41:36 UTC (rev 3)
@@ -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


Property changes on: trunk/varnish.h
___________________________________________________________________
Name: svn:keywords
   + Id




More information about the varnish-commit mailing list