mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-25 10:13:44 +00:00
Refine LRU cache by clearing old objects
This commit is contained in:
@@ -56,6 +56,12 @@ remove_from_block_list(char *addr)
|
||||
return cache_remove(block_list, addr, addr_len);
|
||||
}
|
||||
|
||||
void
|
||||
clear_block_list()
|
||||
{
|
||||
cache_clear(block_list, 3600); // Clear items older than 1 hour
|
||||
}
|
||||
|
||||
int
|
||||
check_block_list(char *addr, int err_level)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
int init_acl(const char *path);
|
||||
void free_acl(void);
|
||||
void clear_block_list(void);
|
||||
|
||||
int acl_match_host(const char *ip);
|
||||
int acl_add_ip(const char *ip);
|
||||
|
||||
+43
-1
@@ -94,7 +94,7 @@ cache_delete(struct cache *cache, int keep_data)
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->data);
|
||||
} else {
|
||||
ss_free(tmp->data);
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
@@ -106,6 +106,45 @@ cache_delete(struct cache *cache, int keep_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Clear old cache object
|
||||
*
|
||||
* @param cache
|
||||
* The cache object to clear
|
||||
*
|
||||
* @param age
|
||||
* Clear only objects older than the age (sec)
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_clear(struct cache *cache, ev_tstamp age)
|
||||
{
|
||||
struct cache_entry *entry, *tmp;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ev_tstamp now = ev_time();
|
||||
|
||||
HASH_ITER(hh, cache->entries, entry, tmp){
|
||||
if (now - entry->ts > age) {
|
||||
HASH_DEL(cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Removes a cache entry
|
||||
*
|
||||
* @param cache
|
||||
@@ -179,6 +218,7 @@ cache_lookup(struct cache *cache, char *key, size_t key_len, void *result)
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
if (tmp) {
|
||||
HASH_DELETE(hh, cache->entries, tmp);
|
||||
tmp->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);
|
||||
*dirty_hack = tmp->data;
|
||||
} else {
|
||||
@@ -200,6 +240,7 @@ cache_key_exist(struct cache *cache, char *key, size_t key_len)
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
if (tmp) {
|
||||
HASH_DELETE(hh, cache->entries, tmp);
|
||||
tmp->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);
|
||||
return 1;
|
||||
} else {
|
||||
@@ -242,6 +283,7 @@ cache_insert(struct cache *cache, char *key, size_t key_len, void *data)
|
||||
entry->key = ss_malloc(key_len);
|
||||
memcpy(entry->key, key, key_len);
|
||||
entry->data = data;
|
||||
entry->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry);
|
||||
|
||||
if (HASH_COUNT(cache->entries) >= cache->max_entries) {
|
||||
|
||||
+9
-6
@@ -29,6 +29,7 @@
|
||||
#define _CACHE_
|
||||
|
||||
#include "uthash.h"
|
||||
#include "ev.h"
|
||||
|
||||
/**
|
||||
* A cache entry
|
||||
@@ -36,6 +37,7 @@
|
||||
struct cache_entry {
|
||||
char *key; /**<The key */
|
||||
void *data; /**<Payload */
|
||||
ev_tstamp ts; /**<Timestamp */
|
||||
UT_hash_handle hh; /**<Hash Handle for uthash */
|
||||
};
|
||||
|
||||
@@ -48,12 +50,13 @@ struct cache {
|
||||
void (*free_cb) (void *element); /**<Callback function to free cache entries */
|
||||
};
|
||||
|
||||
extern int cache_create(struct cache **dst, const size_t capacity,
|
||||
int cache_create(struct cache **dst, const size_t capacity,
|
||||
void (*free_cb)(void *element));
|
||||
extern int cache_delete(struct cache *cache, int keep_data);
|
||||
extern int cache_lookup(struct cache *cache, char *key, size_t key_len, void *result);
|
||||
extern int cache_insert(struct cache *cache, char *key, size_t key_len, void *data);
|
||||
extern int cache_remove(struct cache *cache, char *key, size_t key_len);
|
||||
extern int cache_key_exist(struct cache *cache, char *key, size_t key_len);
|
||||
int cache_delete(struct cache *cache, int keep_data);
|
||||
int cache_clear(struct cache *cache, ev_tstamp age);
|
||||
int cache_lookup(struct cache *cache, char *key, size_t key_len, void *result);
|
||||
int cache_insert(struct cache *cache, char *key, size_t key_len, void *data);
|
||||
int cache_remove(struct cache *cache, char *key, size_t key_len);
|
||||
int cache_key_exist(struct cache *cache, char *key, size_t key_len);
|
||||
|
||||
#endif
|
||||
|
||||
+3
-3
@@ -1392,7 +1392,7 @@ enc_key_init(int method, const char *pass)
|
||||
if (sodium_init() == -1) {
|
||||
FATAL("Failed to initialize sodium");
|
||||
}
|
||||
|
||||
|
||||
if (method == SALSA20 || method == CHACHA20 || method == CHACHA20IETF) {
|
||||
// Fake cipher
|
||||
cipher = (cipher_kt_t *)&cipher_info;
|
||||
@@ -1469,8 +1469,8 @@ enc_init(const char *pass, const char *method)
|
||||
break;
|
||||
}
|
||||
if (m >= CIPHER_NUM) {
|
||||
LOGE("Invalid cipher name: %s, use table instead", method);
|
||||
m = TABLE;
|
||||
LOGE("Invalid cipher name: %s, use rc4-md5 instead", method);
|
||||
m = RC4_MD5;
|
||||
}
|
||||
}
|
||||
if (m == TABLE) {
|
||||
|
||||
+1
-1
@@ -1316,7 +1316,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (method == NULL) {
|
||||
method = "table";
|
||||
method = "rc4-md5";
|
||||
}
|
||||
|
||||
if (timeout == NULL) {
|
||||
|
||||
@@ -910,6 +910,10 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (method == NULL) {
|
||||
method = "rc4-md5";
|
||||
}
|
||||
|
||||
if (timeout == NULL) {
|
||||
timeout = "60";
|
||||
}
|
||||
|
||||
+13
-1
@@ -91,6 +91,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents);
|
||||
static void remote_recv_cb(EV_P_ ev_io *w, int revents);
|
||||
static void remote_send_cb(EV_P_ ev_io *w, int revents);
|
||||
static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents);
|
||||
static void block_list_clear_cb(EV_P_ ev_timer *watcher, int revents);
|
||||
|
||||
static remote_t *new_remote(int fd);
|
||||
static server_t *new_server(int fd, listen_ctx_t *listener);
|
||||
@@ -127,6 +128,7 @@ static char *manager_address = NULL;
|
||||
uint64_t tx = 0;
|
||||
uint64_t rx = 0;
|
||||
ev_timer stat_update_watcher;
|
||||
ev_timer block_list_watcher;
|
||||
|
||||
static struct cork_dllist connections;
|
||||
|
||||
@@ -974,6 +976,12 @@ server_send_cb(EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
block_list_clear_cb(EV_P_ ev_timer *watcher, int revents)
|
||||
{
|
||||
clear_block_list();
|
||||
}
|
||||
|
||||
static void
|
||||
server_timeout_cb(EV_P_ ev_timer *watcher, int revents)
|
||||
{
|
||||
@@ -1653,7 +1661,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (method == NULL) {
|
||||
method = "table";
|
||||
method = "rc4-md5";
|
||||
}
|
||||
|
||||
if (timeout == NULL) {
|
||||
@@ -1793,6 +1801,9 @@ main(int argc, char **argv)
|
||||
ev_timer_start(EV_DEFAULT, &stat_update_watcher);
|
||||
}
|
||||
|
||||
ev_timer_init(&block_list_watcher, block_list_clear_cb, UPDATE_INTERVAL, UPDATE_INTERVAL);
|
||||
ev_timer_start(EV_DEFAULT, &block_list_watcher);
|
||||
|
||||
// setuid
|
||||
if (user != NULL) {
|
||||
run_as(user);
|
||||
@@ -1811,6 +1822,7 @@ main(int argc, char **argv)
|
||||
if (manager_address != NULL) {
|
||||
ev_timer_stop(EV_DEFAULT, &stat_update_watcher);
|
||||
}
|
||||
ev_timer_stop(EV_DEFAULT, &block_list_watcher);
|
||||
|
||||
// Clean up
|
||||
for (int i = 0; i <= server_num; i++) {
|
||||
|
||||
@@ -909,6 +909,10 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (method == NULL) {
|
||||
method = "rc4-md5";
|
||||
}
|
||||
|
||||
if (timeout == NULL) {
|
||||
timeout = "60";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user