linked_list_t *sets;
/**
+ * thread local set of credentials, linked_list_t with credential_set_t's
+ */
+ pthread_key_t local_sets;
+
+ /**
* trust relationship and certificate cache
*/
cert_cache_t *cache;
/**
- * mutex to gain exclusive access
+ * read-write lock to sets list
*/
- mutex_t *mutex;
+ pthread_rwlock_t lock;
};
/** data to pass to create_private_enumerator */
identification_t *other;
} shared_data_t;
+/** enumerator over local and global sets */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over global sets */
+ enumerator_t *global;
+ /** enumerator over local sets */
+ enumerator_t *local;
+} sets_enumerator_t;
+
+/**
+ * destroy a sets_enumerator_t
+ */
+static void sets_enumerator_destroy(sets_enumerator_t *this)
+{
+ DESTROY_IF(this->global);
+ DESTROY_IF(this->local);
+ free(this);
+}
+
+/**
+ * sets_enumerator_t.enumerate
+ */
+static bool sets_enumerator_enumerate(sets_enumerator_t *this,
+ credential_set_t **set)
+{
+ if (this->global)
+ {
+ if (this->global->enumerate(this->global, set))
+ {
+ return TRUE;
+ }
+ /* end of global sets, look for local */
+ this->global->destroy(this->global);
+ this->global = NULL;
+ }
+ if (this->local)
+ {
+ return this->local->enumerate(this->local, set);
+ }
+ return FALSE;
+}
+
+/**
+ * create an enumerator over both, global and local sets
+ */
+static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
+{
+ linked_list_t *local;
+ sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t);
+
+ enumerator->public.enumerate = (void*)sets_enumerator_enumerate;
+ enumerator->public.destroy = (void*)sets_enumerator_destroy;
+ enumerator->global = this->sets->create_enumerator(this->sets);
+ enumerator->local = NULL;
+ local = pthread_getspecific(this->local_sets);
+ if (local)
+ {
+ enumerator->local = local->create_enumerator(local);
+ }
+ return &enumerator->public;
+}
+
/**
* cleanup function for cert data
*/
static void destroy_cert_data(cert_data_t *data)
{
- data->this->mutex->unlock(data->this->mutex);
+ pthread_rwlock_unlock(&data->this->lock);
free(data);
}
data->id = id;
data->trusted = trusted;
- this->mutex->lock(this->mutex);
- return enumerator_create_nested(this->sets->create_enumerator(this->sets),
+ pthread_rwlock_rdlock(&this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_cert, data,
(void*)destroy_cert_data);
}
certificate_t *current, *found = NULL;
enumerator_t *enumerator;
- this->mutex->lock(this->mutex);
enumerator = create_cert_enumerator(this, cert, key, id, trusted);
if (enumerator->enumerate(enumerator, ¤t))
{
found = current->get_ref(current);
}
enumerator->destroy(enumerator);
- this->mutex->unlock(this->mutex);
return found;
}
*/
static void destroy_cdp_data(cdp_data_t *data)
{
- data->this->mutex->unlock(data->this->mutex);
+ pthread_rwlock_unlock(&data->this->lock);
free(data);
}
data->type = type;
data->id = id;
- this->mutex->lock(this->mutex);
- return enumerator_create_nested(this->sets->create_enumerator(this->sets),
+ pthread_rwlock_rdlock(&this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_cdp, data,
(void*)destroy_cdp_data);
}
*/
static void destroy_private_data(private_data_t *data)
{
- data->this->mutex->unlock(data->this->mutex);
+ pthread_rwlock_unlock(&data->this->lock);
free(data);
}
data->this = this;
data->type = key;
data->keyid = keyid;
- this->mutex->lock(this->mutex);
- return enumerator_create_nested(this->sets->create_enumerator(this->sets),
- (void*)create_private, data, (void*)destroy_private_data);
+ pthread_rwlock_rdlock(&this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_private, data,
+ (void*)destroy_private_data);
}
/**
*/
static void destroy_shared_data(shared_data_t *data)
{
- data->this->mutex->unlock(data->this->mutex);
+ pthread_rwlock_unlock(&data->this->lock);
free(data);
}
data->me = me;
data->other = other;
- this->mutex->lock(this->mutex);
- return enumerator_create_nested(this->sets->create_enumerator(this->sets),
+ pthread_rwlock_rdlock(&this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
(void*)create_shared, data,
(void*)destroy_shared_data);
}
}
/**
- * forward declaration
+ * add a credential set to the thread local list
+ */
+static void add_local_set(private_credential_manager_t *this,
+ credential_set_t *set)
+{
+ linked_list_t *sets;
+
+ sets = pthread_getspecific(this->local_sets);
+ if (!sets)
+ { /* first invocation */
+ sets = linked_list_create();
+ pthread_setspecific(this->local_sets, sets);
+ }
+ sets->insert_last(sets, set);
+}
+
+/**
+ * remove a credential set from the thread local list
*/
+static void remove_local_set(private_credential_manager_t *this,
+ credential_set_t *set)
+{
+ linked_list_t *sets;
+
+ sets = pthread_getspecific(this->local_sets);
+ sets->remove(sets, set, NULL);
+}
+/**
+ * forward declaration
+ */
static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
key_type_t type, identification_t *id, bool crl, bool ocsp);
+
/**
* Do an OCSP request
*/
bool verified = FALSE;
wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
- this->sets->insert_last(this->sets, wrapper);
+ add_local_set(this, &wrapper->set);
subject = &response->certificate;
responder = subject->get_issuer(subject);
}
enumerator->destroy(enumerator);
- this->sets->remove(this->sets, wrapper, NULL);
+ remove_local_set(this, &wrapper->set);
wrapper->destroy(wrapper);
return verified;
}
this->inner->destroy(this->inner);
if (this->wrapper)
{
- this->this->sets->remove(this->this->sets, this->wrapper, NULL);
+ remove_local_set(this->this, &this->wrapper->set);
this->wrapper->destroy(this->wrapper);
}
- this->this->mutex->unlock(this->this->mutex);
+ pthread_rwlock_unlock(&this->this->lock);
free(this);
}
enumerator->this = this;
enumerator->current = NULL;
enumerator->wrapper = NULL;
- this->mutex->lock(this->mutex);
if (auth)
{
enumerator->wrapper = auth_info_wrapper_create(auth);
- this->sets->insert_last(this->sets, enumerator->wrapper);
+ add_local_set(this, &enumerator->wrapper->set);
}
+ pthread_rwlock_rdlock(&this->lock);
return &enumerator->public;
}
}
}
- this->mutex->lock(this->mutex);
/* try to build a trustchain for each certificate found */
enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
while (enumerator->enumerate(enumerator, &cert))
}
enumerator->destroy(enumerator);
}
- this->mutex->unlock(this->mutex);
return private;
}
static void flush_cache(private_credential_manager_t *this,
certificate_type_t type)
{
- this->mutex->lock(this->mutex);
this->cache->flush(this->cache, type);
- this->mutex->unlock(this->mutex);
}
/**
static void add_set(private_credential_manager_t *this,
credential_set_t *set)
{
- this->mutex->lock(this->mutex);
+ pthread_rwlock_wrlock(&this->lock);
this->sets->insert_last(this->sets, set);
- this->mutex->unlock(this->mutex);
+ pthread_rwlock_unlock(&this->lock);
}
+
/**
* Implementation of credential_manager_t.remove_set.
*/
static void remove_set(private_credential_manager_t *this, credential_set_t *set)
{
- this->mutex->lock(this->mutex);
+ pthread_rwlock_wrlock(&this->lock);
this->sets->remove(this->sets, set, NULL);
- this->mutex->unlock(this->mutex);
+ pthread_rwlock_unlock(&this->lock);
}
/**
{
this->sets->remove(this->sets, this->cache, NULL);
this->sets->destroy(this->sets);
+ pthread_key_delete(this->local_sets);
this->cache->destroy(this->cache);
- this->mutex->destroy(this->mutex);
+ pthread_rwlock_destroy(&this->lock);
free(this);
}
this->public.destroy = (void(*)(credential_manager_t*))destroy;
this->sets = linked_list_create();
+ pthread_key_create(&this->local_sets, (void*)this->sets->destroy);
this->cache = cert_cache_create();
this->sets->insert_first(this->sets, this->cache);
- this->mutex = mutex_create(MUTEX_RECURSIVE);
+ pthread_rwlock_init(&this->lock, NULL);
return &this->public;
}
#include <daemon.h>
#include <utils/linked_list.h>
+#include <utils/mutex.h>
#define CACHE_SIZE 30
* have we increased the cache without a check_cache?
*/
bool check_required;
+
+ /**
+ * mutex to lock relations list
+ */
+ mutex_t *mutex;
};
/**
enumerator_t *enumerator;
/* lookup cache */
+ this->mutex->lock(this->mutex);
enumerator = this->relations->create_enumerator(this->relations);
while (enumerator->enumerate(enumerator, ¤t))
{
}
}
enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
if (found)
{
return TRUE;
found->subject = subject->get_ref(subject);
found->issuer = issuer->get_ref(issuer);
found->last_use = time(NULL);
+ this->mutex->lock(this->mutex);
this->relations->insert_last(this->relations, found);
check_cache(this);
+ this->mutex->unlock(this->mutex);
return TRUE;
}
{
check_cache(data->this);
}
+ data->this->mutex->unlock(data->this->mutex);
free(data);
}
data->key = key;
data->id = id;
data->this = this;
- this->enumerating++;
+ this->mutex->lock(this->mutex);
+ this->enumerating++;
return enumerator_create_filter(
this->relations->create_enumerator(this->relations),
(void*)certs_filter, data, (void*)certs_destroy);
enumerator_t *enumerator;
relation_t *relation;
+ this->mutex->lock(this->mutex);
enumerator = this->relations->create_enumerator(this->relations);
while (enumerator->enumerate(enumerator, &relation))
{
}
}
enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
}
/**
static void destroy(private_cert_cache_t *this)
{
this->relations->destroy_function(this->relations, (void*)relation_destroy);
+ this->mutex->destroy(this->mutex);
free(this);
}
this->relations = linked_list_create();
this->enumerating = FALSE;
this->check_required = FALSE;
+ this->mutex = mutex_create(MUTEX_RECURSIVE);
return &this->public;
}