#include <assert.h>
#include <pthread.h>
+#include <sys/uio.h>
#include <sys/time.h>
#include "queue.h"
#include "vcl_returns.h"
#include "common.h"
+#define MAX_IOVS 10
+
struct event_base;
struct cli;
struct sbuf;
unsigned nbr;
pthread_cond_t cv;
TAILQ_ENTRY(worker) list;
+
+ struct iovec iov[MAX_IOVS];
+ unsigned niov;
+ size_t liov;
};
struct workreq {
TAILQ_HEAD(,object) objects;
};
+/* -------------------------------------------------------------------*/
+
+struct client {
+ TAILQ_ENTRY(client) list;
+ unsigned nsess;
+ char addr[TCP_ADDRBUFFSIZE];
+ uint64_t bytes;
+};
+
struct sess {
int fd;
unsigned xid;
+ struct worker *wrk;
+
/* formatted ascii client address */
char addr[TCP_ADDRBUFFSIZE];
+ struct client *client;
/* HTTP request */
struct http *http;
void WRK_Init(void);
void WRK_QueueSession(struct sess *sp);
+/* cache_session.c [SES] */
+void SES_Init(void);
+struct sess *SES_New(struct sockaddr *addr, unsigned len);
+void SES_Delete(const struct sess *sp);
+
+
/* cache_shmlog.c */
void VSL_Init(void);
static pthread_t vca_thread;
-#define SESS_IOVS 10
-
static struct event accept_e[2 * HERITAGE_NSOCKS];
static TAILQ_HEAD(,sess) sesshead = TAILQ_HEAD_INITIALIZER(sesshead);
-struct sessmem {
- struct sess sess;
- struct iovec iov[SESS_IOVS];
- int niov;
- size_t liov;
- struct http http;
- char *http_hdr;
-};
-
-/*--------------------------------------------------------------------*/
-
-static struct sess *
-vca_new_sess(void)
-{
- struct sessmem *sm;
-
- sm = calloc(
- sizeof *sm +
- heritage.mem_http_headers * sizeof sm->http_hdr +
- heritage.mem_http_headerspace +
- heritage.mem_workspace,
- 1);
- if (sm == NULL)
- return (NULL);
- VSL_stats->n_sess++;
- sm->sess.mem = sm;
- sm->sess.http = &sm->http;
- http_Init(&sm->http, (void *)(sm + 1));
- return (&sm->sess);
-}
-
-static void
-vca_delete_sess(const struct sess *sp)
-{
-
- VSL_stats->n_sess--;
- free(sp->mem);
-}
-
/*--------------------------------------------------------------------
* Write data to client
{
int i;
- if (sp->fd < 0 || sp->mem->niov == 0)
+ if (sp->fd < 0 || sp->wrk->niov == 0)
return;
- i = writev(sp->fd, sp->mem->iov, sp->mem->niov);
- if (i != sp->mem->liov)
+ i = writev(sp->fd, sp->wrk->iov, sp->wrk->niov);
+ if (i != sp->wrk->liov)
vca_close_session(sp, "remote closed");
- sp->mem->liov = 0;
- sp->mem->niov = 0;
+ sp->wrk->liov = 0;
+ sp->wrk->niov = 0;
}
void
if (sp->fd < 0 || len == 0)
return;
- if (sp->mem->niov == SESS_IOVS)
+ if (sp->wrk->niov == MAX_IOVS)
vca_flush(sp);
if (sp->fd < 0)
return;
- sp->mem->iov[sp->mem->niov].iov_base = ptr;
- sp->mem->iov[sp->mem->niov++].iov_len = len;
- sp->mem->liov += len;
+ sp->wrk->iov[sp->wrk->niov].iov_base = ptr;
+ sp->wrk->iov[sp->wrk->niov++].iov_len = len;
+ sp->wrk->liov += len;
}
void
continue;
}
st->stevedore->send(st, sp,
- sp->mem->iov, sp->mem->niov, sp->mem->liov);
- sp->mem->niov = 0;
- sp->mem->liov = 0;
+ sp->wrk->iov, sp->wrk->niov, sp->wrk->liov);
+ sp->wrk->niov = 0;
+ sp->wrk->liov = 0;
}
assert(u == sp->obj->len);
}
(void)arg;
VSL_stats->client_conn++;
- sp = vca_new_sess();
- assert(sp != NULL); /* XXX handle */
-
l = sizeof addr;
- sp->fd = accept(fd, addr, &l);
- if (sp->fd < 0) {
- vca_delete_sess(sp);
+ i = accept(fd, addr, &l);
+ if (i < 0) {
return;
}
+ sp = SES_New(addr, l);
+ assert(sp != NULL); /* XXX handle */
+
+ sp->fd = i;
+
#ifdef SO_NOSIGPIPE /* XXX Linux */
i = 1;
AZ(setsockopt(sp->fd, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof i));
VSL(SLT_SessionReuse, sp->fd, "%s", sp->addr);
assert(sizeof sp == write(pipes[1], &sp, sizeof sp));
} else {
- vca_delete_sess(sp);
+ SES_Delete(sp);
}
}
--- /dev/null
+/*
+ * $Id$
+ *
+ * Session and Client management.
+ *
+ * The client structures are kept around only as a convenience feature to
+ * make it possible to track down offenders and misconfigured caches.
+ * As such it is pure overhead and we do not want to spend too much time
+ * on maintaining it.
+ *
+ * We identify clients by their address only and disregard the port number,
+ * because the desired level of granularity is "whois is abuse@ or tech-c@
+ * in the RIPE database.
+ */
+
+#include <stdlib.h>
+#include <sys/uio.h>
+
+#include "heritage.h"
+#include "cache.h"
+#include "shmlog.h"
+
+#define CLIENT_HASH 256
+
+/*--------------------------------------------------------------------*/
+
+struct sessmem {
+ struct sess sess;
+ struct http http;
+ char *http_hdr;
+};
+
+/*--------------------------------------------------------------------*/
+
+TAILQ_HEAD(clienthead ,client);
+
+static struct clienthead client_hash[CLIENT_HASH];
+
+/*--------------------------------------------------------------------*/
+
+struct sess *
+SES_New(struct sockaddr *addr, unsigned len)
+{
+ struct sessmem *sm;
+
+ (void)addr; /* XXX */
+ (void)len; /* XXX */
+ sm = calloc(
+ sizeof *sm +
+ heritage.mem_http_headers * sizeof sm->http_hdr +
+ heritage.mem_http_headerspace +
+ heritage.mem_workspace,
+ 1);
+ if (sm == NULL)
+ return (NULL);
+ VSL_stats->n_sess++;
+ sm->sess.mem = sm;
+ sm->sess.http = &sm->http;
+ http_Init(&sm->http, (void *)(sm + 1));
+ return (&sm->sess);
+}
+
+void
+SES_Delete(const struct sess *sp)
+{
+
+ VSL_stats->n_sess--;
+ free(sp->mem);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+SES_Init()
+{
+ int i;
+
+ for (i = 0; i < CLIENT_HASH; i++)
+ TAILQ_INIT(&client_hash[i]);
+}