-/* $OpenBSD: rebound.c,v 1.106 2018/12/20 07:23:22 anton Exp $ */
+/* $OpenBSD: rebound.c,v 1.107 2018/12/27 18:00:15 tedu Exp $ */
/*
* Copyright (c) 2015 Ted Unangst <tedu@openbsd.org>
*
* after the response is set, the request must not free it.
*/
struct dnscache {
- TAILQ_ENTRY(dnscache) fifo;
+ RB_ENTRY(dnscache) expnode;
RB_ENTRY(dnscache) cachenode;
struct dnspacket *req;
size_t reqlen;
struct timespec basetime;
int permanent;
};
-static TAILQ_HEAD(, dnscache) cachefifo;
+static RB_HEAD(cacheexp, dnscache) cacheexp;
+RB_PROTOTYPE_STATIC(cacheexp, dnscache, expnode, expirycmp)
static RB_HEAD(cachetree, dnscache) cachetree;
RB_PROTOTYPE_STATIC(cachetree, dnscache, cachenode, cachecmp)
exit(1);
}
+static int
+expirycmp(struct dnscache *c1, struct dnscache *c2)
+{
+ if (timespeccmp(&c1->ts, &c2->ts, <))
+ return -1;
+ if (timespeccmp(&c1->ts, &c2->ts, >))
+ return 1;
+ return c1 < c2 ? -1 : 1;
+}
+RB_GENERATE_STATIC(cacheexp, dnscache, expnode, expirycmp)
+
static int
cachecmp(struct dnscache *c1, struct dnscache *c2)
{
{
cachecount -= 1;
RB_REMOVE(cachetree, &cachetree, ent);
- TAILQ_REMOVE(&cachefifo, ent, fifo);
+ RB_REMOVE(cacheexp, &cacheexp, ent);
free(ent->req);
free(ent->resp);
free(ent);
}
memcpy(ent->resp, buf, r);
ent->resplen = r;
+ if (RB_INSERT(cacheexp, &cacheexp, ent)) {
+ free(ent->resp);
+ ent->resp = NULL;
+ RB_REMOVE(cachetree, &cachetree, ent);
+ return;
+ }
cachecount += 1;
- TAILQ_INSERT_TAIL(&cachefifo, ent, fifo);
}
}
ent->resplen = resplen;
ent->permanent = 1;
+ /* not added to the cacheexp tree */
RB_INSERT(cachetree, &cachetree, ent);
return 0;
cachemax = 10000; /* something big, but not huge */
TAILQ_INIT(&reqfifo);
- TAILQ_INIT(&cachefifo);
+ RB_INIT(&cacheexp);
RB_INIT(&cachetree);
https_init();
while (conncount > connmax)
freerequest(TAILQ_FIRST(&reqfifo));
while (cachecount > cachemax)
- freecacheent(TAILQ_FIRST(&cachefifo));
+ freecacheent(RB_MIN(cacheexp, &cacheexp));
/* burn old cache entries */
- while ((ent = TAILQ_FIRST(&cachefifo))) {
+ while ((ent = RB_MIN(cacheexp, &cacheexp))) {
if (timespeccmp(&ent->ts, &now, <=))
freecacheent(ent);
else