From 083a70393faf163a12bba8092e60fe904f80b421 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Mon, 20 Apr 2026 10:40:38 +0300 Subject: [PATCH] Minor hashtable refactor --- src/auth.c | 29 --------------- src/conf.c | 6 ++-- src/hash.c | 92 ++++++++++++++++++++++++++++++------------------ src/resolve.c | 11 ------ src/structures.h | 32 ++++++++++------- 5 files changed, 80 insertions(+), 90 deletions(-) diff --git a/src/auth.c b/src/auth.c index 487fc48..ed120d5 100644 --- a/src/auth.c +++ b/src/auth.c @@ -7,7 +7,6 @@ */ #include "proxy.h" -#include "libs/blake2.h" static FILTER_ACTION (*ext_ssl_parent)(struct clientparam * param) = NULL; @@ -776,34 +775,6 @@ int checkACL(struct clientparam * param){ return 3; } -struct authcache { - unsigned char username[64]; -#ifndef NOIPv6 - uint8_t sincr_addr[16]; - uint8_t sinsl_addr[16]; -#else - uint8_t sincr_addr[4]; - uint8_t sinsl_addr[4]; -#endif - uint16_t sincr_family; - uint16_t sinsl_family; -}; - -void param2hash(const void *index, uint8_t *hash, const unsigned char *rnd){ - blake2b_state S; - const struct clientparam *param = (struct clientparam *)index; - - blake2b_init_key(&S, HASH_SIZE, rnd, sizeof(unsigned)*4); - if((conf.authcachetype & 1) && !(conf.authcachetype & 8))blake2b_update(&S, SAADDR(¶m->sincr), SAADDRLEN(¶m->sincr)); - if((conf.authcachetype & 2) && param->username)blake2b_update(&S, param->username, strlen((const char *)param->username)); - if((conf.authcachetype & 4) && param->password)blake2b_update(&S, param->password, strlen((const char *)param->password)); - if((conf.authcachetype & 16))blake2b_update(&S, ¶m->srv->acl, sizeof(param->srv->acl)); - blake2b_final(&S, hash, HASH_SIZE); -} - -struct hashtable auth_table = {0, sizeof(struct authcache), {0,0,0,0}, NULL, NULL, 0, param2hash}; - - int cacheauth(struct clientparam * param){ struct authcache ac; uint32_t ttl; diff --git a/src/conf.c b/src/conf.c index 4c04360..a0606c7 100644 --- a/src/conf.c +++ b/src/conf.c @@ -197,7 +197,7 @@ static int h_proxy(int argc, unsigned char ** argv){ childdef.service = S_PROXY; childdef.helpmessage = " -n - no NTLM support\n"; #ifdef NOIPV6 - if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){ + if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize)){ fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, proxy may run very slow\n", linenum); } #endif @@ -230,7 +230,7 @@ static int h_proxy(int argc, unsigned char ** argv){ childdef.service = S_SOCKS; childdef.helpmessage = " -n - no NTLM support\n"; #ifdef NOIPV6 - if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){ + if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize)){ fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, socks may run very slow\n", linenum); } #endif @@ -276,7 +276,7 @@ static int h_proxy(int argc, unsigned char ** argv){ childdef.service = S_DNSPR; childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n"; #ifndef NOIPV6 - if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize) || resolvfunc == fakeresolver){ + if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize) || resolvfunc == fakeresolver){ fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum); } #endif diff --git a/src/hash.c b/src/hash.c index 934918b..af40c1d 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1,6 +1,14 @@ #include "proxy.h" #include "libs/blake2.h" + +struct hashentry { + uint8_t hash[HASH_SIZE]; + time_t expires; + uint32_t inext; + char value[4]; +}; + static uint32_t hashindex(struct hashtable *ht, const uint8_t* hash){ return (*(unsigned *)hash ) % (ht->tablesize); } @@ -16,16 +24,16 @@ void destroyhashtable(struct hashtable *ht){ myfree(ht->hashvalues); ht->hashvalues = NULL; } - ht->hashsize = 0; + ht->poolsize = 0; ht->tablesize = 0; pthread_mutex_unlock(&hash_mutex); } #define hvalue(ht,I) ((struct hashentry *)(ht->hashvalues + (I-1)*(sizeof(struct hashentry) + ht->recsize - 4))) -int inithashtable(struct hashtable *ht, unsigned nhashsize){ +int inithashtable(struct hashtable *ht, unsigned npoolsize){ unsigned i; - unsigned tablesize, hashsize; + unsigned tablesize, poolsize; clock_t c; #ifdef _WIN32 @@ -40,7 +48,7 @@ int inithashtable(struct hashtable *ht, unsigned nhashsize){ #endif c = clock(); - hashsize = tablesize = (nhashsize >> 2); + poolsize = tablesize = (npoolsize >> 2); if(tablesize < 2) return 1; pthread_mutex_lock(&hash_mutex); if(ht->ihashtable){ @@ -51,29 +59,25 @@ int inithashtable(struct hashtable *ht, unsigned nhashsize){ myfree(ht->hashvalues); ht->hashvalues = NULL; } - ht->hashsize = 0; + ht->poolsize = 0; ht->tablesize = 0; if(!(ht->ihashtable = myalloc(tablesize * sizeof(uint32_t)))){ pthread_mutex_unlock(&hash_mutex); return 2; } - if(!(ht->hashvalues = myalloc(hashsize * (sizeof(struct hashentry) + (ht->recsize-4))))){ + if(!(ht->hashvalues = myalloc(poolsize * (sizeof(struct hashentry) + (ht->recsize-4))))){ myfree(ht->ihashtable); ht->ihashtable = NULL; pthread_mutex_unlock(&hash_mutex); return 3; } - ht->hashsize = hashsize; + ht->poolsize = poolsize; ht->tablesize = tablesize; - ht->growlimit = nhashsize; - ht->rnd[0] = myrand(&tb, sizeof(tb)); - ht->rnd[1] = myrand(ht->ihashtable, sizeof(ht->ihashtable)); - ht->rnd[2] = myrand(&c, sizeof(c)); - ht->rnd[3] = myrand(ht->hashvalues,sizeof(ht->hashvalues)); + ht->growlimit = npoolsize; memset(ht->ihashtable, 0, ht->tablesize * sizeof(uint32_t)); - memset(ht->hashvalues, 0, ht->hashsize * (sizeof(struct hashentry) + ht->recsize - 4)); + memset(ht->hashvalues, 0, ht->poolsize * (sizeof(struct hashentry) + ht->recsize - 4)); - for(i = 1; i < ht->hashsize; i++) { + for(i = 1; i < ht->poolsize; i++) { hvalue(ht,i)->inext = i+1; } ht->ihashempty = 1; @@ -85,7 +89,7 @@ static void hashcompact(struct hashtable *ht){ int i; uint32_t he, *hep; - if((conf.time - ht->compacted) < 300 || !ht->tablesize || !ht->hashsize || ht->ihashempty) return; + if((conf.time - ht->compacted) < 300 || !ht->tablesize || !ht->poolsize || ht->ihashempty) return; for(i = 0; i < ht->tablesize; i++){ for(hep = ht->ihashtable + i; (he = *hep) != 0; ){ if(hvalue(ht,he)->expires < conf.time ) { @@ -102,24 +106,24 @@ static void hashcompact(struct hashtable *ht){ } static void hashgrow(struct hashtable *ht){ - unsigned newsize = (ht->hashsize + (ht->hashsize >> 1)); + unsigned newsize = (ht->poolsize + (ht->poolsize >> 1)); unsigned i; void * newvalues; - if(!ht->tablesize || !ht->hashsize) return; - if(ht->hashsize / ht->tablesize < 4) hashcompact(ht); + if(!ht->tablesize || !ht->poolsize) return; + if(ht->poolsize / ht->tablesize < 4) hashcompact(ht); if(ht->ihashempty) return; - if(ht->hashsize >= ht->growlimit) return; + if(ht->poolsize >= ht->growlimit) return; if(newsize > ht->growlimit) newsize = ht->growlimit; newvalues = myrealloc(ht->hashvalues, newsize * (sizeof(struct hashentry) + ht->recsize - 4)); if(!newvalues) return; - memset(ht->hashvalues + (ht->hashsize * (sizeof(struct hashentry) + ht->recsize - 4)), 0, (newsize - ht->hashsize) * (sizeof(struct hashentry) + ht->recsize - 4)); - for(i = ht->hashsize + 1; i < newsize; i++) { + memset(ht->hashvalues + (ht->poolsize * (sizeof(struct hashentry) + ht->recsize - 4)), 0, (newsize - ht->poolsize) * (sizeof(struct hashentry) + ht->recsize - 4)); + for(i = ht->poolsize + 1; i < newsize; i++) { hvalue(ht,i)->inext = i+1; } hvalue(ht,newsize)->inext = ht->ihashempty; - ht->ihashempty = ht->hashsize + 1; - ht->hashsize = newsize; + ht->ihashempty = ht->poolsize + 1; + ht->poolsize = newsize; } @@ -128,21 +132,20 @@ void hashadd(struct hashtable *ht, const void* name, const void* value, time_t e uint32_t hen, he; uint32_t *hep; int overwrite = 0; - uint8_t hash[HASH_SIZE]; + uint8_t hash[ht->hash_size]; uint32_t index; uint32_t last = 0; - pthread_mutex_lock(&hash_mutex); if(!ht||!value||!name||!ht->ihashtable) { - pthread_mutex_unlock(&hash_mutex); return; } - ht->index2hash(name, hash, (unsigned char *)ht->rnd); + ht->index2hash(name, hash); + pthread_mutex_lock(&hash_mutex); index = hashindex(ht, hash); for(hep = ht->ihashtable + index; (he = *hep)!=0; ){ - if(hvalue(ht,he)->expires < conf.time || !memcmp(hash, hvalue(ht,he)->hash, HASH_SIZE)) { + if(hvalue(ht,he)->expires < conf.time || !memcmp(hash, hvalue(ht,he)->hash, ht->hash_size)) { (*hep) = hvalue(ht,he)->inext; hvalue(ht,he)->expires = 0; hvalue(ht,he)->inext = ht->ihashempty; @@ -168,7 +171,7 @@ void hashadd(struct hashtable *ht, const void* name, const void* value, time_t e hen = last; } if(hen){ - memcpy(hvalue(ht,hen)->hash, hash, HASH_SIZE); + memcpy(hvalue(ht,hen)->hash, hash, ht->hash_size); memcpy(hvalue(ht,hen)->value, value, ht->recsize); hvalue(ht,hen)->expires = expires; } @@ -177,17 +180,16 @@ void hashadd(struct hashtable *ht, const void* name, const void* value, time_t e } int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *ttl){ - uint8_t hash[HASH_SIZE]; + uint8_t hash[ht->hash_size]; uint32_t *hep; uint32_t he; uint32_t index; - pthread_mutex_lock(&hash_mutex); if(!ht || !ht->ihashtable || !name) { - pthread_mutex_unlock(&hash_mutex); return 0; } - ht->index2hash(name, hash, (unsigned char *)ht->rnd); + ht->index2hash(name, hash); + pthread_mutex_lock(&hash_mutex); index = hashindex(ht, hash); for(hep = ht->ihashtable + index; (he = *hep)!=0; ){ if(hvalue(ht, he)->expires < conf.time) { @@ -196,7 +198,7 @@ int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *tt hvalue(ht,he)->inext = ht->ihashempty; ht->ihashempty = he; } - else if(!memcmp(hash, hvalue(ht,he)->hash, HASH_SIZE)){ + else if(!memcmp(hash, hvalue(ht,he)->hash, ht->hash_size)){ if(ttl) *ttl = (uint32_t)(hvalue(ht,he)->expires - conf.time); memcpy(value, hvalue(ht,he)->value, ht->recsize); pthread_mutex_unlock(&hash_mutex); @@ -207,3 +209,25 @@ int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *tt pthread_mutex_unlock(&hash_mutex); return 0; } + +void char_index2hash(const void *index, uint8_t *hash){ + const char* name = index; + + blake2b(hash, HASH_SIZE, index, strlen((const char*)index), NULL, 0); +} + +void param2hash(const void *index, uint8_t *hash){ + blake2b_state S; + const struct clientparam *param = (struct clientparam *)index; + + blake2b_init(&S, HASH_SIZE); + if((conf.authcachetype & 1) && !(conf.authcachetype & 8))blake2b_update(&S, SAADDR(¶m->sincr), SAADDRLEN(¶m->sincr)); + if((conf.authcachetype & 2) && param->username)blake2b_update(&S, param->username, strlen((const char *)param->username)); + if((conf.authcachetype & 4) && param->password)blake2b_update(&S, param->password, strlen((const char *)param->password)); + if((conf.authcachetype & 16))blake2b_update(&S, ¶m->srv->acl, sizeof(param->srv->acl)); + blake2b_final(&S, hash, HASH_SIZE); +} + +struct hashtable dns_table = {0, 0, 0, 4, HASH_SIZE, char_index2hash}; +struct hashtable dns6_table = {0, 0, 0, 16, HASH_SIZE, char_index2hash}; +struct hashtable auth_table = {0, 0, 0, sizeof(struct authcache), HASH_SIZE, param2hash}; diff --git a/src/resolve.c b/src/resolve.c index 05cec1f..fc34e04 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -1,15 +1,4 @@ #include "proxy.h" -#include "libs/blake2.h" - - -void char_index2hash(const void *index, uint8_t *hash, const unsigned char *rnd){ - const char* name = index; - - blake2b(hash, HASH_SIZE, index, strlen((const char*)index), rnd, 4*sizeof(unsigned) ); -} - -struct hashtable dns_table = {0, 4, {0,0,0,0}, NULL, NULL, 0, char_index2hash}; -struct hashtable dns6_table = {0, 16, {0,0,0,0}, NULL, NULL, 0, char_index2hash}; struct nserver nservers[MAXNSERVERS] = {{{0},0}, {{0},0}, {{0},0}, {{0},0}, {{0},0}}; struct nserver authnserver; diff --git a/src/structures.h b/src/structures.h index b2f5a41..05911af 100644 --- a/src/structures.h +++ b/src/structures.h @@ -756,30 +756,36 @@ struct child { #define HASH_SIZE (16) -struct hashentry { - uint8_t hash[HASH_SIZE]; - time_t expires; - uint32_t inext; - char value[4]; -}; - struct hashtable { - unsigned hashsize; + unsigned poolsize; + unsigned tablesize; + unsigned growlimit; unsigned recsize; - unsigned rnd[4]; + unsigned hash_size; + void (*index2hash)(const void *index, unsigned char *hash); uint32_t * ihashtable; uint8_t * hashvalues; - uint32_t ihashempty; - void (*index2hash)(const void *index, unsigned char *hash, const unsigned char *rnd); - unsigned growlimit; - int tablesize; time_t compacted; + uint32_t ihashempty; }; extern struct hashtable dns_table; extern struct hashtable dns6_table; extern struct hashtable auth_table; +struct authcache { + unsigned char username[64]; +#ifndef NOIPv6 + uint8_t sincr_addr[16]; + uint8_t sinsl_addr[16]; +#else + uint8_t sincr_addr[4]; + uint8_t sinsl_addr[4]; +#endif + uint16_t sincr_family; + uint16_t sinsl_family; +}; + struct pluginlink { struct symbol symbols; struct extparam *conf;