reentrant save cert_cache
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
#define CACHE_LIMIT 30
|
#define CACHE_SIZE 30
|
||||||
|
|
||||||
typedef struct private_cert_cache_t private_cert_cache_t;
|
typedef struct private_cert_cache_t private_cert_cache_t;
|
||||||
typedef struct relation_t relation_t;
|
typedef struct relation_t relation_t;
|
||||||
@@ -39,6 +39,16 @@ struct private_cert_cache_t {
|
|||||||
* list of trusted subject-issuer relations, as relation_t
|
* list of trusted subject-issuer relations, as relation_t
|
||||||
*/
|
*/
|
||||||
linked_list_t *relations;
|
linked_list_t *relations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do we have an active enumerator
|
||||||
|
*/
|
||||||
|
bool enumerating;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* have we increased the cache without a check_cache?
|
||||||
|
*/
|
||||||
|
bool check_required;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,13 +73,45 @@ static void relation_destroy(relation_t *this)
|
|||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check the cache for oversize
|
||||||
|
*/
|
||||||
|
static void check_cache(private_cert_cache_t *this)
|
||||||
|
{
|
||||||
|
if (this->enumerating)
|
||||||
|
{
|
||||||
|
this->check_required = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (this->relations->get_count(this->relations) > CACHE_SIZE)
|
||||||
|
{
|
||||||
|
relation_t *oldest = NULL, *current;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
|
enumerator = this->relations->create_enumerator(this->relations);
|
||||||
|
while (enumerator->enumerate(enumerator, ¤t))
|
||||||
|
{
|
||||||
|
if (oldest == NULL || oldest->last_use <= current->last_use)
|
||||||
|
{
|
||||||
|
oldest = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->relations->remove(this->relations, oldest, NULL);
|
||||||
|
relation_destroy(oldest);
|
||||||
|
}
|
||||||
|
this->check_required = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of cert_cache_t.issued_by.
|
* Implementation of cert_cache_t.issued_by.
|
||||||
*/
|
*/
|
||||||
static bool issued_by(private_cert_cache_t *this,
|
static bool issued_by(private_cert_cache_t *this,
|
||||||
certificate_t *subject, certificate_t *issuer)
|
certificate_t *subject, certificate_t *issuer)
|
||||||
{
|
{
|
||||||
relation_t *found = NULL, *current, *oldest = NULL;
|
relation_t *found = NULL, *current;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
/* lookup cache */
|
/* lookup cache */
|
||||||
@@ -82,10 +124,6 @@ static bool issued_by(private_cert_cache_t *this,
|
|||||||
found = current;
|
found = current;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (oldest == NULL || oldest->last_use <= current->last_use)
|
|
||||||
{
|
|
||||||
oldest = current;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
if (found)
|
if (found)
|
||||||
@@ -102,12 +140,8 @@ static bool issued_by(private_cert_cache_t *this,
|
|||||||
found->subject = subject->get_ref(subject);
|
found->subject = subject->get_ref(subject);
|
||||||
found->issuer = issuer->get_ref(issuer);
|
found->issuer = issuer->get_ref(issuer);
|
||||||
found->last_use = time(NULL);
|
found->last_use = time(NULL);
|
||||||
if (this->relations->get_count(this->relations) > CACHE_LIMIT && oldest)
|
|
||||||
{
|
|
||||||
this->relations->remove(this->relations, oldest, NULL);
|
|
||||||
relation_destroy(oldest);
|
|
||||||
}
|
|
||||||
this->relations->insert_last(this->relations, found);
|
this->relations->insert_last(this->relations, found);
|
||||||
|
check_cache(this);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +155,8 @@ typedef struct {
|
|||||||
key_type_t key;
|
key_type_t key;
|
||||||
/** ID to get a cert from */
|
/** ID to get a cert from */
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
|
/** reverse pointer to cache */
|
||||||
|
private_cert_cache_t *this;
|
||||||
} cert_data_t;
|
} cert_data_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,6 +202,19 @@ static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clean up enumeration data
|
||||||
|
*/
|
||||||
|
static void certs_destroy(cert_data_t *data)
|
||||||
|
{
|
||||||
|
data->this->enumerating--;
|
||||||
|
if (data->this->check_required)
|
||||||
|
{
|
||||||
|
check_cache(data->this);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* implementation of credential_set_t.create_cert_enumerator
|
* implementation of credential_set_t.create_cert_enumerator
|
||||||
*/
|
*/
|
||||||
@@ -183,10 +232,12 @@ static enumerator_t *create_enumerator(private_cert_cache_t *this,
|
|||||||
data->cert = cert;
|
data->cert = cert;
|
||||||
data->key = key;
|
data->key = key;
|
||||||
data->id = id;
|
data->id = id;
|
||||||
|
data->this = this;
|
||||||
|
this->enumerating++;
|
||||||
|
|
||||||
return enumerator_create_filter(
|
return enumerator_create_filter(
|
||||||
this->relations->create_enumerator(this->relations),
|
this->relations->create_enumerator(this->relations),
|
||||||
(void*)certs_filter, data, (void*)free);
|
(void*)certs_filter, data, (void*)certs_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,6 +286,8 @@ cert_cache_t *cert_cache_create()
|
|||||||
this->public.destroy = (void(*)(cert_cache_t*))destroy;
|
this->public.destroy = (void(*)(cert_cache_t*))destroy;
|
||||||
|
|
||||||
this->relations = linked_list_create();
|
this->relations = linked_list_create();
|
||||||
|
this->enumerating = FALSE;
|
||||||
|
this->check_required = FALSE;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user