#include "cache.h" #include "third/uthash.h" #include #include #include #include #include #include #include pthread_rwlock_t cacheLock; struct cache *not_http_dst_cache = NULL; static int check_interval; _Noreturn static void* check_cache(void*) { while (true) { pthread_rwlock_wrlock(&cacheLock); const time_t now = time(NULL); struct cache *cur, *tmp; HASH_ITER(hh, not_http_dst_cache, cur, tmp) { if (difftime(now, cur->last_time) > check_interval * 2) { HASH_DEL(not_http_dst_cache, cur); free(cur); } } pthread_rwlock_unlock(&cacheLock); sleep(check_interval); } } void init_not_http_cache(const int interval) { check_interval = interval; if (pthread_rwlock_init(&cacheLock, NULL) != 0) { syslog(LOG_ERR, "Failed to init cache lock"); exit(EXIT_FAILURE); } syslog(LOG_INFO, "Cache lock initialized"); pthread_t cleanup_thread; const __auto_type ret = pthread_create(&cleanup_thread, NULL, check_cache, NULL); if (ret) { syslog(LOG_ERR, "Failed to create cleanup thread: %d", ret); exit(EXIT_FAILURE); } syslog(LOG_INFO, "Cleanup thread created"); pthread_detach(cleanup_thread); } bool cache_contains(struct addr_port target) { pthread_rwlock_rdlock(&cacheLock); struct cache *s; HASH_FIND(hh, not_http_dst_cache, &target, sizeof(struct addr_port), s); pthread_rwlock_unlock(&cacheLock); if (s != NULL) { bool ret; pthread_rwlock_wrlock(&cacheLock); if (difftime(time(NULL), s->last_time) > check_interval * 2) { HASH_DEL(not_http_dst_cache, s); free(s); ret = false; } else { s->last_time = time(NULL); ret = true; } pthread_rwlock_unlock(&cacheLock); return ret; } return false; } void cache_add(struct addr_port addr_port) { pthread_rwlock_wrlock(&cacheLock); struct cache *s; HASH_FIND(hh, not_http_dst_cache, &addr_port, sizeof(struct addr_port), s); if (s == NULL) { s = malloc(sizeof(struct cache)); memcpy(&s->target.addr, &addr_port, sizeof(struct addr_port)); HASH_ADD(hh, not_http_dst_cache, target.addr, sizeof(struct addr_port), s); } s->last_time = time(NULL); pthread_rwlock_unlock(&cacheLock); }