listener.c \
log.c \
request.c \
+ system-common.c \
+ system-@target_os@.c \
varnish.c
# Checks for header files.
AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_HEADER_TIME
AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([netinet/in.h])
AC_CHECK_HEADERS([stddef.h])
#include <unistd.h>
#include "varnish.h"
+#include "log.h"
#include "connection.h"
+struct connection {
+ int sd;
+ struct sockaddr_storage addr;
+};
+
+/*
+ * Accepts a connection from the provided listening descriptor. Does not
+ * loop to handle EINTR or other similar conditions.
+ */
+connection_t *
+connection_accept(int ld)
+{
+ connection_t *c;
+ socklen_t len;
+
+ if ((c = calloc(1, sizeof *c)) == NULL)
+ return (NULL);
+
+ len = sizeof c->addr;
+ if ((c->sd = accept(ld, (struct sockaddr *)&c->addr, &len)) == -1) {
+ free(c);
+ return (NULL);
+ }
+ 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);
+}
+
void
connection_destroy(struct connection *c)
{
#ifndef CONNECTION_H_INCLUDED
#define CONNECTION_H_INCLUDED
-struct connection {
- int sd;
- struct sockaddr_storage addr;
-};
+typedef struct connection connection_t;
+
+connection_t *connection_accept(int ld);
+void connection_destroy(connection_t *c);
#endif
#include <unistd.h>
#include "varnish.h"
-#include "listener.h"
#include "connection.h"
+#include "listener.h"
+#include "log.h"
+
+struct listener {
+ int sd;
+ struct sockaddr_storage addr;
+};
/*
* Create a socket that listens on the specified port. We use an IPv6 TCP
free(l);
}
-struct connection *
+connection_t *
listener_accept(struct listener *l)
{
- struct connection *c;
- socklen_t len;
+ connection_t *c;
- 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();
- }
+ if ((c = connection_accept(l->sd)) != NULL)
return (c);
- }
if (errno != EINTR) {
log_syserr("accept()");
free(c);
#ifndef LISTENER_H_INCLUDED
#define LISTENER_H_INCLUDED
-struct listener {
- int sd;
- struct sockaddr_storage addr;
-};
+#include "connection.h"
+
+typedef struct listener listener_t;
+
+listener_t *listener_create(int port);
+void listener_destroy(listener_t *l);
+connection_t *listener_accept(listener_t *l);
#endif
* $Id$
*/
+#include <sys/types.h>
#include <sys/signal.h>
+#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <time.h>
+#endif
#include <unistd.h>
#include "varnish.h"
+#include "log.h"
+#include "system.h"
+
+static void
+timestamp(void)
+{
+ struct timeval now;
+
+ if (gettimeofday(&now, NULL) == -1)
+ now.tv_sec = now.tv_usec = 0;
+ fprintf(stderr, "%lu.%06lu [%lu] ",
+ (unsigned long)now.tv_sec,
+ (unsigned long)now.tv_usec,
+ (unsigned long)sys.pid);
+}
static void
emit(const char *fmt, va_list ap)
{
+ timestamp();
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
}
#else
snprintf(errstr, sizeof errstr, "%s", strerror(errno));
#endif
+ timestamp();
vfprintf(stderr, fmt, ap);
fprintf(stderr, ": %s\n", errstr);
}
--- /dev/null
+/*
+ * $Id$
+ */
+
+#ifndef LOG_H_INCLUDED
+#define LOG_H_INCLUDED
+
+
+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__)
+
+#endif
#include <stdlib.h>
#include "varnish.h"
+#include "connection.h"
+#include "log.h"
#include "request.h"
+struct request {
+ connection_t *conn;
+};
+
request_t *
request_wait(connection_t *c, unsigned int timeout)
{
#ifndef REQUEST_H_INCLUDED
#define REQUEST_H_INCLUDED
-struct request {
- struct connection *conn;
-};
+typedef struct request request_t;
+
+request_t *request_wait(connection_t *c, unsigned int timeout);
+void request_destroy(request_t *r);
#endif
--- /dev/null
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+
+#include <unistd.h>
+
+#include "varnish.h"
+#include "system.h"
+
+system_t sys;
+
+/*
+ * gather system information at startup
+ */
+void
+system_init(void)
+{
+ sys.pid = getpid();
+ system_init_ncpu();
+}
+
+/*
+ * fork() wrapper, updates sys.pid
+ */
+pid_t
+system_fork(void)
+{
+ pid_t pid;
+
+ if ((pid = fork()) == 0)
+ sys.pid = getpid();
+ return (pid);
+}
--- /dev/null
+/*
+ * $Id$
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include "varnish.h"
+#include "log.h"
+#include "system.h"
+
+void
+system_init_ncpu(void)
+{
+ FILE *cpuinfo;
+ char line[256];
+ int n;
+
+ sys.ncpu = 0;
+ if ((cpuinfo = fopen("/proc/cpuinfo", "r")) == NULL)
+ return;
+ while (fgets(line, sizeof line, cpuinfo) != NULL) {
+ if (sscanf(line, "processor : %d", &n) == 1)
+ sys.ncpu++;
+ }
+ fclose(cpuinfo);
+ if (sys.ncpu == 0)
+ sys.ncpu = 1;
+ log_info("%d cpu(s)", sys.ncpu);
+}
--- /dev/null
+/*
+ * $Id$
+ */
+
+#ifndef SYSTEM_H_INCLUDED
+#define SYSTEM_H_INCLUDED
+
+typedef struct system system_t;
+
+struct system {
+ int ncpu;
+ pid_t pid;
+};
+
+extern system_t sys;
+
+void system_init_ncpu(void);
+void system_init(void);
+pid_t system_fork(void);
+
+#endif
* $Id$
*/
+#include <sys/wait.h>
+
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "varnish.h"
+#include "connection.h"
+#include "listener.h"
+#include "log.h"
+#include "request.h"
+#include "system.h"
static void
-varnish(void)
+varnish_child(listener_t *l)
{
- 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);
}
+ LOG_UNREACHABLE();
+}
+
+static void
+varnish(void)
+{
+ listener_t *l;
+ int i, status;
+ pid_t pid;
+
+ system_init();
+ log_info("starting Varnish");
+ l = listener_create(8080);
+ for (i = 0; i < sys.ncpu; ++i) {
+ switch ((pid = system_fork())) {
+ case -1:
+ log_panic("fork()");
+ break;
+ case 0:
+ varnish_child(l);
+ _exit(1);
+ break;
+ default:
+ log_info("forked child %lu", (unsigned long)pid);
+ break;
+ }
+ }
+ for (;;) {
+ if ((pid = wait(&status)) == -1) {
+ if (errno == ECHILD)
+ return;
+ } else {
+ log_info("child %lu exited", (unsigned long)pid);
+ }
+ }
}
static void
varnish();
- LOG_UNREACHABLE();
exit(1);
}
#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