#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
#include "vtc.h"
+#include "vqueue.h"
+#include "miniobj.h"
+#include "vss.h"
+#include "libvarnish.h"
+
+struct server {
+ unsigned magic;
+#define SERVER_MAGIC 0x55286619
+ char *name;
+ VTAILQ_ENTRY(server) list;
+
+ unsigned repeat;
+ char *spec;
+
+ int depth;
+ int sock;
+ const char *listen;
+ struct vss_addr **vss_addr;
+ char *addr;
+ char *port;
+
+ pthread_t tp;
+};
+
+static VTAILQ_HEAD(, server) servers =
+ VTAILQ_HEAD_INITIALIZER(servers);
+
+/**********************************************************************
+ * Server thread
+ */
+
+static void *
+server_thread(void *priv)
+{
+ struct server *s;
+
+ CAST_OBJ_NOTNULL(s, priv, SERVER_MAGIC);
+
+ printf("### Server %s started\n", s->name);
+ sleep(3);
+ printf("### Server %s ending\n", s->name);
+
+ return (NULL);
+}
+
+/**********************************************************************
+ * Allocate and initialize a server
+ */
+
+static struct server *
+server_new(char *name)
+{
+ struct server *s;
+
+ ALLOC_OBJ(s, SERVER_MAGIC);
+ s->name = name;
+ s->listen = ":9080";
+ s->depth = 1;
+ s->sock = -1;
+ VTAILQ_INSERT_TAIL(&servers, s, list);
+ return (s);
+}
+
+/**********************************************************************
+ * Start the server thread
+ */
+
+static void
+server_start(struct server *s)
+{
+ int naddr;
+
+ CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
+ printf("Starting server %s\n", s->name);
+ if (s->sock < 0) {
+ AZ(VSS_parse(s->listen, &s->addr, &s->port));
+ naddr = VSS_resolve(s->addr, s->port, &s->vss_addr);
+ if (naddr != 1) {
+ fprintf(stderr,
+ "Server %s listen address not unique\n"
+ " \"%s\" resolves to (%d) sockets\n",
+ s->name, s->listen, naddr);
+ exit (1);
+ }
+ s->sock = VSS_listen(s->vss_addr[0], s->depth);
+ assert(s->sock >= 0);
+ }
+ printf("\tsocket fd is %d\n", s->sock);
+ AZ(pthread_create(&s->tp, NULL, server_thread, s));
+}
+
+/**********************************************************************
+ * Wait for server thread to stop
+ */
+
+static void
+server_wait(struct server *s)
+{
+ void *res;
+
+ CHECK_OBJ_NOTNULL(s, SERVER_MAGIC);
+ printf("Waiting for server %s\n", s->name);
+ AZ(pthread_join(s->tp, &res));
+ if (res != NULL) {
+ fprintf(stderr, "Server %s returned \"%s\"\n",
+ s->name, (char *)res);
+ exit (1);
+ }
+ s->tp = NULL;
+}
+
+/**********************************************************************
+ * Server command dispatch
+ */
+
void
cmd_server(char **av, void *priv)
{
+ struct server *s;
+
+ (void)priv;
+ assert(!strcmp(av[0], "server"));
+ av++;
+
+ VTAILQ_FOREACH(s, &servers, list)
+ if (!strcmp(s->name, av[0]))
+ break;
+ if (s == NULL)
+ s = server_new(av[0]);
+ av++;
- cmd_dump(av, priv);
+ for (; *av != NULL; av++) {
+ if (!strcmp(*av, "-repeat")) {
+ s->repeat = atoi(av[1]);
+ av++;
+ continue;
+ }
+ if (!strcmp(*av, "-start")) {
+ server_start(s);
+ continue;
+ }
+ if (!strcmp(*av, "-wait")) {
+ server_wait(s);
+ continue;
+ }
+ if (**av == '{') {
+ s->spec = *av;
+ continue;
+ }
+ fprintf(stderr, "Unknown server argument: %s\n", *av);
+ exit (1);
+ }
}