From 1360696c2d6ed7083a71979c8382c9d34df12cf0 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Tue, 30 Jul 2024 14:36:22 +0000 Subject: More stuff Signed-off-by: Laurent Bercot --- src/cache/cache.c | 2 +- src/cache/deps-exe/shibari-cache | 1 - src/cache/dns.c | 38 ------------------ src/cache/log.c | 27 ++++++++++++- src/cache/query.c | 81 +++++++++++++++++++++++++++++++++++++- src/cache/shibari-cache-internal.h | 51 ++++++++++-------------- src/cache/shibari-cache.c | 65 +++++++++++++++--------------- src/cache/tcpconnection.c | 11 ++++++ src/cache/udpqueue.c | 70 +++++++++----------------------- src/include/shibari/dcache.h | 3 +- src/libdcache/dcache_search.c | 13 +++++- 11 files changed, 202 insertions(+), 160 deletions(-) delete mode 100644 src/cache/dns.c diff --git a/src/cache/cache.c b/src/cache/cache.c index e8796f7..1169350 100644 --- a/src/cache/cache.c +++ b/src/cache/cache.c @@ -45,7 +45,7 @@ int cache_search (s6dns_domain_t const *name, uint16_t qtype, dcache_key_t *data char key[name->len + 1] ; uint16_pack_big(key, qtype) ; memcpy(key + 2, name->s, name->len - 1) ; - node = dcache_search(&cache, key, name->len + 1) ; + node = dcache_search_g(&cache, key, name->len + 1) ; if (!node) return 0 ; data->s = node->key.s + node->key.len ; data->len = node->datalen ; diff --git a/src/cache/deps-exe/shibari-cache b/src/cache/deps-exe/shibari-cache index 44d74a0..e363f19 100644 --- a/src/cache/deps-exe/shibari-cache +++ b/src/cache/deps-exe/shibari-cache @@ -1,7 +1,6 @@ cache.o clientaccess.o conf.o -dns.o log.o query.o tcpconnection.o diff --git a/src/cache/dns.c b/src/cache/dns.c deleted file mode 100644 index ce5b611..0000000 --- a/src/cache/dns.c +++ /dev/null @@ -1,38 +0,0 @@ -/* ISC license. */ - -#include - -#include - -#include "shibari-cache-internal.h" - -int dns_newquery (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len) -{ - dcache_key_t data ; - s6dns_message_header_t hdr ; - s6dns_message_counts_t counts ; - s6dns_domain_t name ; - unsigned int pos ; - unsigned int rcode ; - uint16_t qtype ; - char key[257] ; - - if (!s6dns_message_parse_init(&hdr, &counts, buf, len, &pos)) return 1 ; - if (hdr.opcode) { rcode = 4 ; goto err ; } - if (!hdr.rd) { rcode = 1 ; goto err ; } - if (!s6dns_message_parse_question(&counts, &name, &qtype, buf, len, &pos) - || !s6dns_domain_encode(&name)) - { - rcode = errno == ENOTSUP ? 4 : 1 ; - goto answer ; - } - - if (cache_search(&name, qtype, &data)) goto got ; - return 1 ; - - answer: - return 1 ; - err: - got : - return 1 ; -} diff --git a/src/cache/log.c b/src/cache/log.c index bc67384..0e20f91 100644 --- a/src/cache/log.c +++ b/src/cache/log.c @@ -6,7 +6,9 @@ #include "shibari-cache-internal.h" -void log_tcptimeout (uint16_t i) + + +void log_udp4bad (char const *ip, uint16_t port) { if (g->verbosity >= 3) { @@ -20,11 +22,34 @@ void log_newtcp4 (char const *ip, uint16_t port) } } +void log_tcpbad (uint16_t i) +{ + if (g->verbosity >= 3) + { + } +} + +void log_tcptimeout (uint16_t i) +{ + if (g->verbosity >= 3) + { + } +} + #ifdef SKALIBS_IPV6_ENABLED + +void log_udp6bad (char const *ip, uint16_t port) +{ + if (g->verbosity >= 3) + { + } +} + void log_newtcp6 (char const *ip, uint16_t port) { if (g->verbosity >= 3) { } } + #endif diff --git a/src/cache/query.c b/src/cache/query.c index 8f5e423..7fb27c4 100644 --- a/src/cache/query.c +++ b/src/cache/query.c @@ -2,8 +2,9 @@ #include -#include +#include +#include #include "shibari-cache-internal.h" static uint16_t query_delete (query *q) @@ -12,6 +13,7 @@ static uint16_t query_delete (query *q) QUERY(newi)->next = q->next ; QUERY(q->next)->prev = q->prev ; q->xindex = UINT16_MAX ; + q->qname.len = 0 ; return newi ; } @@ -38,7 +40,82 @@ uint16_t query_succeed (uint16_t id) return query_delete(q) ; } -int query_new (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len) +int query_end (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len) { + return source < 2 ? + udpqueue_add(g->udpqueues[source] + i, source, ip, port, buf, len) : + tcpconnection_add(g->tcpconnections + i, buf, len) ; +} + +int query_error (uint8_t source, uint16_t i, char const *ip, uint16_t port, s6dns_domain_t *name, uint16_t qtype, uint16_t id, unsigned int rcode) +{ + s6dns_message_header_t hdr = S6DNS_MESSAGE_HEADER_ZERO ; + unsigned int pos = 12 ; + char pkt[name->len + 16] ; + hdr.id = id ; + hdr.qr = 1 ; + hdr.ra = 1 ; + hdr.rcode = rcode ; + hdr.counts.qd = 1 ; + s6dns_message_header_pack(pkt, &hdr) ; + memcpy(pkt + pos, name->s, name->len) ; pos += name->len ; + uint16_pack_big(pkt + pos, qtype) ; pos += 2 ; + uint16_pack_big(pkt + pos, SHIBARI_C_IN) ; pos += 2 ; + return query_end(source, i, ip, port, pkt, pos) ; +} + +static void query_init (query *q, uint8_t source, uint16_t i, char const *ip, uint16_t port, s6dns_domain_t const *name, uint16_t qtype) +{ + q->source = source ; + q->i = i ; + if (source < 2) + { + memcpy(q->ip, ip, source ? 16 : 4) ; + q->port = port ; + } + q->port = port ; + if (!stralloc_catb(&q->qname, name->s, name->len)) dienomem() ; + q->qtype = qtype ; + q->prefixlen = 0 ; +} + +static query *query_new (uint8_t source, uint16_t i, char const *ip, uint16_t port, s6dns_domain_t const *name, uint16_t qtype) +{ + uint16_t n = genset_new(&g->queries) ; + query *sentinel = QUERY(g->qsentinel) ; + query *q = QUERY(n) ; + query_init(q, source, i, ip, port, name, type) ; + q->prev = g->qsentinel ; + q->next = sentinel->next ; + QUERY(sentinel->next)->prev = n ; + sentinel->next = n ; + return q ; +} + +int query_start (uint8_t source, uint16_t i, char const *ip, uint16_t port, char const *buf, uint16_t len) +{ + dcache_key_t data ; + s6dns_message_header_t hdr ; + s6dns_message_counts_t counts ; + s6dns_domain_t name ; + unsigned int pos ; + unsigned int rcode ; + uint16_t qtype ; + + if (!s6dns_message_parse_init(&hdr, &counts, buf, len, &pos) + || !s6dns_message_parse_question(&counts, &name, &qtype, buf, len, &pos) + || !s6dns_domain_encode(&name)) return 0 ; + if (hdr.opcode) return query_error(source, i, ip, port, &name, qtype, hdr.id, 4) ; + if (!hdr.rd) return query_error(source, i, ip, port, &name, qtype, hdr.id, 9) ; + + if (cache_search(&name, qtype, &data)) + return query_end(source, i, ip, port, data.s, data.len) ; + + { + uint16_t j = genset_new(&g->queries) ; + query *q = QUERY(j) ; + } + return 1 ; } + diff --git a/src/cache/shibari-cache-internal.h b/src/cache/shibari-cache-internal.h index c8819fd..950bfdc 100644 --- a/src/cache/shibari-cache-internal.h +++ b/src/cache/shibari-cache-internal.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,8 @@ #include +#define dienomem() strerr_diefu1sys(111, "concatenate data") ; + /* cache */ @@ -47,17 +50,15 @@ extern int conf_get_uint64 (char const *, uint64_t *) ; extern char const *conf_get_string (char const *) ; - /* dns */ - -extern int dns_newquery (uint8_t, uint16_t, char const *, uint16_t, char const *, uint16_t) ; - - /* log */ +extern void log_udp4bad (char const *, uint16_t) ; extern void log_newtcp4 (char const *, uint16_t) ; +extern void log_tcpbad (uint16_t) ; +extern void log_tcptimeout (uint16_t) ; #ifdef SKALIBS_IPV6_ENABLED +extern void log_udp6bad (char const *, uint16_t) ; extern void log_newtcp6 (char const *, uint16_t) ; -extern void log_tcptimeout (uint16_t) ; #endif @@ -67,15 +68,17 @@ typedef struct query_s query, *query_ref ; struct query_s { s6dns_engine_t dt ; + stralloc qname ; uint16_t prev ; uint16_t next ; uint16_t xindex ; uint16_t i ; uint16_t port ; + uint16_t qtype ; uint8_t source ; char ip[SKALIBS_IP_SIZE] ; } ; -#define QUERY_ZERO { .dt = S6DNS_ENGINE_ZERO, .prev = 0, .next = 0, .xindex = UINT16_MAX, .i = 0, .port = 0, .source = 0, .ip = { 0 } } +#define QUERY_ZERO { .dt = S6DNS_ENGINE_ZERO, .qname = STRALLOC_ZERO, .prev = 0, .next = 0, .xindex = UINT16_MAX, .i = 0, .port = 0, qtype = 0, name = 0, .source = 0, .ip = { 0 } } #define nq (genset_n(&g->queries) - 1) #define QUERY(i) genset_p(query, &g->queries, (i)) #define qstart (QUERY(g->qsentinel)->next) @@ -83,8 +86,9 @@ struct query_s extern uint16_t query_abort (uint16_t) ; extern uint16_t query_fail (uint16_t) ; extern uint16_t query_succeed (uint16_t) ; -extern int query_new (uint8_t, uint16_t, char const *, uint16_t, char const *, uint16_t) ; +extern int query_start (uint8_t, uint16_t, char const *, uint16_t, char const *, uint16_t) ; +extern int query_end (uint8_t, uint16_t, char const *, uint16_t, char const *, uint16_t) ; /* tcpconnection */ @@ -114,32 +118,20 @@ extern void tcpconnection_new (int) ; /* udpqueue */ -typedef struct udp4msg_s udp4msg, *udp4msg_ref ; -struct udp4msg_s -{ - char ip[4] ; - uint16_t port ; - uint16_t len ; -} ; -#define UDP4MSG_ZERO { .ip = { 0 }, .port = 0, .len = 0 } - -#ifdef SKALIBS_IPV6_ENABLED -typedef struct udp6msg_s udp6msg, *udp6msg_ref ; -struct udp6msg_s +typedef struct udpaux_s udpaux, *udpaux_ref ; +struct udpaux_s { - char ip[16] ; uint16_t port ; uint16_t len ; } ; -#define UDP6MSG_ZERO { .ip = { 0 }, .port = 0, .len = 0 } -#endif +#define UDPAUX_ZERO { .port = 0, .len = 0 } typedef struct udpqueue_s udpqueue, *udpqueue_ref ; struct udpqueue_s { int fd ; stralloc storage ; - genalloc messages ; /* udp[46]msg */ + genalloc messages ; /* udpaux */ tain deadline ; uint16_t xindex ; } ; @@ -147,13 +139,8 @@ struct udpqueue_s extern void udpqueue_drop (udpqueue *) ; -extern int udpqueue_add4 (udpqueue *, char const *, uint16_t, char const *, uint16_t) ; -extern int udpqueue_flush4 (udpqueue *) ; - -#ifdef SKALIBS_IPV6_ENABLED -extern int udpqueue_add6 (udpqueue *, char const *, uint16_t, char const *, uint16_t) ; -extern int udpqueue_flush6 (udpqueue *) ; -#endif +extern int udpqueue_add (udpqueue *, uint8_t, char const *, uint16_t, char const *, uint16_t) ; +extern int udpqueue_flush (udpqueue *, uint8_t) ; /* main */ @@ -166,6 +153,7 @@ struct global_s uint16_t verbosity ; tain rtto ; tain wtto ; + udpqueue *udpqueues[2] ; genset tcpconnections ; /* tcpconnection */ genset queries ; /* query */ uint16_t tcpsentinel ; @@ -177,6 +165,7 @@ struct global_s .verbosity = 1, \ .rtto = TAIN_INFINITE, \ .wtto = TAIN_INFINITE, \ + .udpqueues = { 0, 0 }, \ .tcpconnections = GENSET_ZERO, \ .queries = GENSET_ZERO, \ .tcpsentinel = 0, \ diff --git a/src/cache/shibari-cache.c b/src/cache/shibari-cache.c index ea705bd..d9391f2 100644 --- a/src/cache/shibari-cache.c +++ b/src/cache/shibari-cache.c @@ -197,6 +197,8 @@ int main (int argc, char const *const *argv) memset(udpq4, 0, n4 * sizeof(udpqueue)) ; memset(udpq6, 0, n6 * sizeof(udpqueue)) ; + g->udpqueues[0] = udpq4 ; + g->udpqueues[1] = udpq6 ; memset(tcpconnection_storage, 0, (maxtcp + 1) * sizeof(tcpconnection)) ; memset(query_storage, 0, (maxqueries + 1) * sizeof(query)) ; GENSET_init(&g->tcpconnections, tcpconnection, tcpconnection_storage, tcpconnection_freelist, maxtcp + 1) ; @@ -391,10 +393,11 @@ int main (int argc, char const *const *argv) else { - for (uint16_t i = 0 ; i < j ; i++) if (x[i].revents & IOPAUSE_EXCEPT) x[i].revents |= x[i].events ; - if (x[0].revents & IOPAUSE_READ) { handle_signals() ; continue ; } + + /* write udp */ + for (uint16_t i = 0 ; i < n4 ; i++) if (udpq4[i].xindex < UINT16_MAX) { if (x[udpq4[i].xindex].revents & IOPAUSE_WRITE) @@ -423,6 +426,9 @@ int main (int argc, char const *const *argv) } #endif + + /* write tcp */ + for (uint16_t i = tcpstart ; i != g->tcpsentinel ; i = TCPCONNECTION(i)->next) { tcpconnection *p = TCPCONNECTION(i) ; @@ -430,6 +436,9 @@ int main (int argc, char const *const *argv) if (tcpconnection_flush(p) == -1) i = tcpconnection_delete(p) ; } + + /* process in-flight queries */ + for (uint16_t i = qstart ; i != g->qsentinel ; i = QUERY(i)->next) { if (QUERY(i)->xindex == UINT16_MAX) continue ; @@ -438,6 +447,9 @@ int main (int argc, char const *const *argv) else if (r > 0) i = query_succeed(i) ; } + + /* read udp */ + for (uint16_t i = 0 ; i < n4 ; i++) { if (udpq4[i].xindex < UINT16_MAX && x[udpq4[i].xindex].revents & IOPAUSE_READ) @@ -456,18 +468,11 @@ int main (int argc, char const *const *argv) strerr_diefu2sys(111, "read from UDP socket bound to ", fmt) ; } if (!len) break ; - if (len < 12 || len > 512) continue ; - if (!clientaccess_ip4(ip)) continue ; - if (!dns_newquery(0, i, ip, port, buf, len)) + if (len < 12 || len > 512 + || !clientaccess_ip4(ip) + || !query_start(0, i, ip, port, buf, len)) { - if (g->verbosity) - { - char fmtip[IP4_FMT] ; - char fmtport[UINT16_FMT] ; - fmtip[ip4_fmt(fmtip, ip)] = 0 ; - fmtport[uint16_fmt(fmtport, port)] = 0 ; - strerr_warnwu4sys("process new UDP query from ip ", fmtip, " port ", fmtport) ; - } + if (g->verbosity >= 3) log_udpbad(ip, port) ; } } } @@ -492,24 +497,20 @@ int main (int argc, char const *const *argv) strerr_diefu2sys(111, "read from UDP socket bound to ", fmt) ; } if (!len) break ; - if (len < 12 || len > 512) continue ; - if (!clientaccess_ip6(ip)) continue ; - if (!dns_newquery(1, i, ip, port, buf, len)) + if (len < 12 || len > 512 + || !clientaccess_ip6(ip) + || !query_start(1, i, ip, port, buf, len)) { - if (g->verbosity) - { - char fmtip[IP4_FMT] ; - char fmtport[UINT16_FMT] ; - fmtip[ip4_fmt(fmtip, ip)] = 0 ; - fmtport[uint16_fmt(fmtport, port)] = 0 ; - strerr_warnwu4sys("process new UDP query from ip ", fmtip, " port ", fmtport) ; - } + if (g->verbosity >= 3) log_udpbad(ip, port) ; } } } } #endif + + /* read tcp */ + for (uint16_t i = tcpstart ; i != g->tcpsentinel ; i = TCPCONNECTION(i)->next) { tcpconnection *p = TCPCONNECTION(i) ; @@ -521,21 +522,21 @@ int main (int argc, char const *const *argv) int l = sanitize_read(mininetstring_read(bufalloc_fd(&p->out), &p->in, &p->instate)) ; if (l == -1) { i = tcpconnection_delete(p) ; break ; } if (!l) break ; - if (p->in.len < 12 || p->in.len > 65536) { i = tcpconnection_delete(p) ; break ; } - if (!dns_newquery(2, i, 0, 0, p->in.s, p->in.len)) + if (p->in.len < 12 || p->in.len > 65536 + || !query_start(2, i, 0, 0, p->in.s, p->in.len)) { - if (g->verbosity) - { - char fmt[UINT16_FMT] ; - fmt[uint16_fmt(fmt, i)] = 0 ; - strerr_warnwu2sys("process TCP query on connection ", fmt) ; - } + if (g->verbosity >= 3) log_tcpbad(i) ; + i = tcpconnection_delete(p) ; + break ; } p->in.len = 0 ; } } } + + /* new tcp */ + for (uint16_t i = 0 ; i < n4 ; i++) if (tcp4xindex[i] < UINT16_MAX) { if (x[tcp4xindex[i]].revents & IOPAUSE_READ) diff --git a/src/cache/tcpconnection.c b/src/cache/tcpconnection.c index 71a4299..40c3035 100644 --- a/src/cache/tcpconnection.c +++ b/src/cache/tcpconnection.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,16 @@ uint16_t tcpconnection_delete (tcpconnection *p) return newi ; } +int tcpconnection_add (tcpconnection *p, char const *s, uint16_t len) +{ + char pack[2] ; + if (!stralloc_readyplus(&p->out.x, 2 + len)) return 0 ; + uint16_pack_big(pack, len) ; + bufalloc_put(&p->out, pack, 2) ; + bufalloc_put(&p->out, s, len) ; + return 0 ; +} + int tcpconnection_flush (tcpconnection *p) { return bufalloc_flush(&p->out) ? 1 : diff --git a/src/cache/udpqueue.c b/src/cache/udpqueue.c index 8750d18..901292e 100644 --- a/src/cache/udpqueue.c +++ b/src/cache/udpqueue.c @@ -18,65 +18,35 @@ void udpqueue_drop (udpqueue *q) tain_add_g(&q->deadline, &tain_infinite_relative) ; } -int udpqueue_add4 (udpqueue *q, char const *ip, uint16_t port, char const *s, uint16_t len) +int udpqueue_add (udpqueue *q, uint8_t source, char const *ip, uint16_t port, char const *s, uint16_t len) { - udp4msg msg = { .port = port, .len = len } ; - if (!stralloc_readyplus(&q->storage, len)) return 0 ; - memcpy(msg.ip, ip, 4) ; - if (!genalloc_append(udp4msg, &q->messages, &msg)) return 0 ; + size_t iplen = source ? 16 : 4 ; + udpaux msg = { .port = port, .len = len } ; + if (!stralloc_readyplus(&q->storage, iplen + len)) return 0 ; + if (!genalloc_append(udpaux, &q->messages, &msg)) return 0 ; if (!q->storage.len) tain_add_g(&q->deadline, &g->wtto) ; + stralloc_catb(&q->storage, ip, iplen) ; stralloc_catb(&q->storage, s, len) ; return 1 ; } -int udpqueue_flush4 (udpqueue *q) +int udpqueue_flush (udpqueue *q, uint8_t is6) { - size_t n = genalloc_len(udp4msg, &q->messages) ; + size_t n = genalloc_len(udpaux, &q->messages) ; size_t shead = 0, head = 0 ; ssize_t r = 1 ; while (head < n) { - udp4msg const *msg = genalloc_s(udp4msg, &q->messages) + head ; - ssize_t r = socket_send4(q->fd, q->storage.s + shead, msg->len, msg->ip, msg->port) ; - if (r <= 0) goto adjust ; - shead += msg->len ; - } - udpqueue_drop(q) ; - return 1 ; - - adjust: - memmove(q->storage.s, q->storage.s + shead, q->storage.len - shead) ; - q->storage.len -= shead ; - memmove(genalloc_s(udp4msg, &q->messages), genalloc_s(udp4msg, &q->messages) + head, (n - head) * sizeof(udp4msg)) ; - genalloc_setlen(udp4msg, &q->messages, n - head) ; - if (shead) tain_add_g(&q->deadline, &g->wtto) ; - return sanitize_read(r) ; -} - -#ifdef SKALIBS_IPv6_ENABLED - -int udpqueue_add6 (udpqueue *q, char const *ip, uint16_t port, char const *s, uint16_t len) -{ - udp6msg msg = { .port = port, .len = len } ; - if (!stralloc_readyplus(&q->storage, len)) return 0 ; - memcpy(msg.ip, ip, 16) ; - if (!genalloc_append(udp6msg, &q->messages, &msg)) return 0 ; - if (!q->storage.len) tain_add_g(&q->deadline, &g->wtto) ; - stralloc_catb(&q->storage, s, len) ; - return 1 ; -} - -int udpqueue_flush6 (udpqueue *q) -{ - size_t n = genalloc_len(udp6msg, &q->messages) ; - size_t shead = 0, head = 0 ; - ssize_t r = 1 ; - while (head < n) - { - udp6msg const *msg = genalloc_s(udp4msg, &q->messages) + head ; - r = socket_send6(q->fd, q->storage.s + shead, msg->len, msg->ip, msg->port) ; + udpaux const *msg = genalloc_s(udpaux, &q->messages) + head ; + ssize_t r ; +#if SKALIBS_IPV6_ENABLED + if (is6) + r = socket_send6(q->fd, q->storage.s + shead + 16, msg->len, q->storage.s + shead, msg->port) ; + else +#endif + r = socket_send4(q->fd, q->storage.s + shead + 4, msg->len, q->storage.s + shead, msg->port) ; if (r <= 0) goto adjust ; - shead += msg->len ; + shead += (is6 ? 16 : 4) + msg->len ; } udpqueue_drop(q) ; return 1 ; @@ -84,10 +54,8 @@ int udpqueue_flush6 (udpqueue *q) adjust: memmove(q->storage.s, q->storage.s + shead, q->storage.len - shead) ; q->storage.len -= shead ; - memmove(genalloc_s(udp6msg, &q->messages), genalloc_s(udp6msg, &q->messages) + head, (n - head) * sizeof(udp6msg)) ; - genalloc_setlen(udp6msg, &q->messages, n - head) ; + memmove(genalloc_s(udpaux, &q->messages), genalloc_s(udpaux, &q->messages) + head, (n - head) * sizeof(udpaux)) ; + genalloc_setlen(udpaux, &q->messages, n - head) ; if (shead) tain_add_g(&q->deadline, &g->wtto) ; return sanitize_read(r) ; } - -#endif diff --git a/src/include/shibari/dcache.h b/src/include/shibari/dcache.h index 50fc44d..1ec9fb6 100644 --- a/src/include/shibari/dcache.h +++ b/src/include/shibari/dcache.h @@ -42,7 +42,8 @@ struct dcache_s #define DCACHE_ZERO { .storage = GENSETDYN_ZERO, .by_key = AVLTREE_ZERO, .by_entry = AVLTREE_ZERO, .by_expire = AVLTREE_ZERO, .max = 0, .size = 0, .motion = 0 } extern void dcache_init (dcache_t *, uint64_t) ; -extern dcache_node_t *dcache_search (dcache_t *, char const *, uint16_t) ; +extern dcache_node_t *dcache_search (dcache_t *, char const *, uint16_t, tain const *) ; +#define dcache_search_g(d, key, keylen) dcache_search(d, key, (keylen), &STAMP) extern int dcache_add (dcache_t *, char const *, uint16_t, char const *, uint16_t, tain const *, tain const *) ; #define dcache_add_g(d, key, keylen, data, datalen, expire) dcache_add(d, key, keylen, data, datalen, (expire), &STAMP) extern void dcache_clean_expired (dcache_t *, tain const *) ; diff --git a/src/libdcache/dcache_search.c b/src/libdcache/dcache_search.c index 0239b88..3d79dd6 100644 --- a/src/libdcache/dcache_search.c +++ b/src/libdcache/dcache_search.c @@ -7,9 +7,18 @@ #include #include "dcache-internal.h" -dcache_node_t *dcache_search (dcache_t *z, char const *key, uint16_t keylen) +dcache_node_t *dcache_search (dcache_t *z, char const *key, uint16_t keylen, tain const *stamp) { uint32_t i ; dcache_key_t k = { .s = (char *)key, .len = keylen } ; - return avltree_search(&z->by_key, &k, &i) ? DNODE(z, i) : 0 ; + if (avltree_search(&z->by_key, &k, &i)) + { + if (tain_less(&DNODE(z, i)->expire, stamp)) + { + dcache_clean_expired(z, stamp) ; + if (!avltree_search(&z->by_key, &k, &i)) return 0 ; + } + return DNODE(z, i) ; + } + else return 0 ; } -- cgit v1.2.3