diff options
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r-- | src/libstrongswan/utils/enumerator.c | 62 | ||||
-rw-r--r-- | src/libstrongswan/utils/hashtable.c | 433 | ||||
-rw-r--r-- | src/libstrongswan/utils/hashtable.h | 116 | ||||
-rw-r--r-- | src/libstrongswan/utils/host.c | 6 | ||||
-rw-r--r-- | src/libstrongswan/utils/identification.c | 3 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 16 | ||||
-rw-r--r-- | src/libstrongswan/utils/lexparser.c | 28 | ||||
-rw-r--r-- | src/libstrongswan/utils/lexparser.h | 8 | ||||
-rw-r--r-- | src/libstrongswan/utils/mutex.c | 52 | ||||
-rw-r--r-- | src/libstrongswan/utils/mutex.h | 12 |
10 files changed, 675 insertions, 61 deletions
diff --git a/src/libstrongswan/utils/enumerator.c b/src/libstrongswan/utils/enumerator.c index 4ebc2e097..e7653a9b2 100644 --- a/src/libstrongswan/utils/enumerator.c +++ b/src/libstrongswan/utils/enumerator.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -12,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: enumerator.c 4142 2008-07-02 08:09:07Z martin $ + * $Id: enumerator.c 4744 2008-12-03 10:03:59Z tobias $ */ #include "enumerator.h" @@ -215,27 +216,48 @@ static bool enumerate_token_enum(token_enum_t *this, char **token) } } - /* find separators */ - sep = this->sep; - while (*sep) + switch (*this->pos) { - tmp = strchr(this->pos, *sep); - if (tmp && (pos == NULL || tmp < pos)) + case '"': + case '\'': { - pos = tmp; + /* read quoted token */ + tmp = strchr(this->pos + 1, *this->pos); + if (tmp) + { + *token = this->pos + 1; + *tmp = '\0'; + this->pos = tmp + 1; + return TRUE; + } + /* unterminated string, FALL-THROUGH */ + } + default: + { + /* find nearest separator */ + sep = this->sep; + while (*sep) + { + tmp = strchr(this->pos, *sep); + if (tmp && (pos == NULL || tmp < pos)) + { + pos = tmp; + } + sep++; + } + *token = this->pos; + if (pos) + { + *pos = '\0'; + this->pos = pos + 1; + } + else + { + last = TRUE; + pos = this->pos = strchr(this->pos, '\0'); + } + break; } - sep++; - } - *token = this->pos; - if (pos) - { - *pos = '\0'; - this->pos = pos + 1; - } - else - { - last = TRUE; - pos = this->pos = strchr(this->pos, '\0'); } /* trim trailing characters/separators */ @@ -268,7 +290,7 @@ static bool enumerate_token_enum(token_enum_t *this, char **token) } } - if (!last || pos > *token) + if (!last || pos >= *token) { return TRUE; } diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c new file mode 100644 index 000000000..892d08b6c --- /dev/null +++ b/src/libstrongswan/utils/hashtable.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id: hashtable.c 4812 2008-12-17 09:56:05Z tobias $ + */ + +#include <utils/linked_list.h> + +#include "hashtable.h" + +/** The maximum capacity of the hash table (MUST be a power of 2) */ +#define MAX_CAPACITY (1 << 30) + +typedef struct pair_t pair_t; + +/** + * This pair holds a pointer to the key and value it represents. + */ +struct pair_t { + /** + * Key of a hash table item. + */ + void *key; + + /** + * Value of a hash table item. + */ + void *value; + + /** + * Cached hash (used in case of a resize). + */ + u_int hash; +}; + +/** + * Creates an empty pair object. + */ +pair_t *pair_create(void *key, void *value, u_int hash) +{ + pair_t *this = malloc_thing(pair_t); + + this->key = key; + this->value = value; + this->hash = hash; + + return this; +} + +typedef struct private_hashtable_t private_hashtable_t; + +/** + * Private data of a hashtable_t object. + * + */ +struct private_hashtable_t { + /** + * Public part of hash table. + */ + hashtable_t public; + + /** + * The number of items in the hash table. + */ + u_int count; + + /** + * The current capacity of the hash table (always a power of 2). + */ + u_int capacity; + + /** + * The current mask to calculate the row index (capacity - 1). + */ + u_int mask; + + /** + * The load factor. + */ + float load_factor; + + /** + * The actual table. + */ + linked_list_t **table; + + /** + * The hashing function. + */ + hashtable_hash_t hash; + + /** + * The equality function. + */ + hashtable_equals_t equals; +}; + +typedef struct private_enumerator_t private_enumerator_t; + +/** + * hash table enumerator implementation + */ +struct private_enumerator_t { + + /** + * implements enumerator interface + */ + enumerator_t enumerator; + + /** + * associated hash table + */ + private_hashtable_t *table; + + /** + * current row index + */ + u_int row; + + /** + * enumerator for the current row + */ + enumerator_t *current; +}; + +/** + * Compare a pair in a list with the given key. + */ +static inline bool pair_equals(pair_t *pair, private_hashtable_t *this, void *key) +{ + return this->equals(key, pair->key); +} + +/** + * This function returns the next-highest power of two for the given number. + * The algorithm works by setting all bits on the right-hand side of the most + * significant 1 to 1 and then increments the whole number so it rolls over + * to the nearest power of two. Note: returns 0 for n == 0 + */ +static u_int get_nearest_powerof2(u_int n) +{ + u_int i; + --n; + for (i = 1; i < sizeof(u_int) * 8; i <<= 1) + { + n |= n >> i; + } + return ++n; +} + +/** + * Init hash table parameters + */ +static void init_hashtable(private_hashtable_t *this, u_int capacity) +{ + capacity = max(1, min(capacity, MAX_CAPACITY)); + this->capacity = get_nearest_powerof2(capacity); + this->mask = this->capacity - 1; + this->load_factor = 0.75; + + this->table = calloc(this->capacity, sizeof(linked_list_t*)); +} + +/** + * Double the size of the hash table and rehash all the elements. + */ +static void rehash(private_hashtable_t *this) +{ + u_int row; + u_int old_capacity = this->capacity; + linked_list_t **old_table = this->table; + + if (old_capacity >= MAX_CAPACITY) + { + return; + } + + init_hashtable(this, old_capacity << 1); + + for (row = 0; row < old_capacity; ++row) + { + linked_list_t *list; + if ((list = old_table[row]) != NULL) + { + pair_t *pair; + enumerator_t *enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &pair)) + { + linked_list_t *new_list; + u_int new_row = pair->hash & this->mask; + list->remove_at(list, enumerator); + if ((new_list = this->table[new_row]) == NULL) + { + new_list = this->table[new_row] = linked_list_create(); + } + new_list->insert_last(new_list, pair); + } + enumerator->destroy(enumerator); + list->destroy(list); + } + } + free(old_table); +} + +/** + * Implementation of hashtable_t.put + */ +static void *put(private_hashtable_t *this, void *key, void *value) +{ + linked_list_t *list; + void *old_value = NULL; + u_int hash = this->hash(key); + u_int row = hash & this->mask; + + if ((list = this->table[row]) != NULL) + { + pair_t *pair; + enumerator_t *enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &pair)) + { + if (pair_equals(pair, this, key)) + { + old_value = pair->value; + pair->value = value; + break; + } + } + enumerator->destroy(enumerator); + } + else + { + list = this->table[row] = linked_list_create(); + } + + if (!old_value) + { + list->insert_last(list, pair_create(key, value, hash)); + this->count++; + } + + if (this->count >= this->capacity * this->load_factor) + { + rehash(this); + } + + return old_value; +} + +/** + * Implementation of hashtable_t.get + */ +static void *get(private_hashtable_t *this, void *key) +{ + void *value = NULL; + linked_list_t *list; + u_int row = this->hash(key) & this->mask; + + if ((list = this->table[row]) != NULL) + { + pair_t *pair; + if (list->find_first(list, (linked_list_match_t)pair_equals, + (void**)&pair, this, key) == SUCCESS) + { + value = pair->value; + } + } + + return value; +} + +/** + * Implementation of hashtable_t.remove + */ +static void *remove(private_hashtable_t *this, void *key) +{ + void *value = NULL; + linked_list_t *list; + u_int row = this->hash(key) & this->mask; + + if ((list = this->table[row]) != NULL) + { + pair_t *pair; + enumerator_t *enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &pair)) + { + if (pair_equals(pair, this, key)) + { + list->remove_at(list, enumerator); + value = pair->value; + this->count--; + free(pair); + break; + } + } + enumerator->destroy(enumerator); + } + + return value; +} + +/** + * Implementation of hashtable_t.get_count + */ +static u_int get_count(private_hashtable_t *this) +{ + return this->count; +} + +/** + * Implementation of private_enumerator_t.enumerator.enumerate. + */ +static bool enumerate(private_enumerator_t *this, void **key, void **value) +{ + while (this->row < this->table->capacity) + { + if (this->current) + { + pair_t *pair; + + if (this->current->enumerate(this->current, &pair)) + { + if (key) + { + *key = pair->key; + } + if (value) + { + *value = pair->value; + } + return TRUE; + } + this->current->destroy(this->current); + this->current = NULL; + } + else + { + linked_list_t *list; + + if ((list = this->table->table[this->row]) != NULL) + { + this->current = list->create_enumerator(list); + continue; + } + } + this->row++; + } + return FALSE; +} + +/** + * Implementation of private_enumerator_t.enumerator.destroy. + */ +static void enumerator_destroy(private_enumerator_t *this) +{ + if (this->current) + { + this->current->destroy(this->current); + } + free(this); +} + +/** + * Implementation of hashtable_t.create_enumerator. + */ +static enumerator_t* create_enumerator(private_hashtable_t *this) +{ + private_enumerator_t *enumerator = malloc_thing(private_enumerator_t); + + enumerator->enumerator.enumerate = (void*)enumerate; + enumerator->enumerator.destroy = (void*)enumerator_destroy; + enumerator->table = this; + enumerator->row = 0; + enumerator->current = NULL; + + return &enumerator->enumerator; +} + +/** + * Implementation of hashtable_t.destroy + */ +static void destroy(private_hashtable_t *this) +{ + u_int row; + for (row = 0; row < this->capacity; ++row) + { + linked_list_t *list; + if ((list = this->table[row]) != NULL) + { + list->destroy_function(list, free); + } + } + free(this->table); + free(this); +} + +/* + * Described in header. + */ +hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals, + u_int capacity) +{ + private_hashtable_t *this = malloc_thing(private_hashtable_t); + + this->public.put = (void*(*)(hashtable_t*,void*,void*))put; + this->public.get = (void*(*)(hashtable_t*,void*))get; + this->public.remove = (void*(*)(hashtable_t*,void*))remove; + this->public.get_count = (u_int(*)(hashtable_t*))get_count; + this->public.create_enumerator = (enumerator_t*(*)(hashtable_t*))create_enumerator; + this->public.destroy = (void(*)(hashtable_t*))destroy; + + this->count = 0; + this->capacity = 0; + this->mask = 0; + this->load_factor = 0; + this->table = NULL; + this->hash = hash; + this->equals = equals; + + init_hashtable(this, capacity); + + return &this->public; +} diff --git a/src/libstrongswan/utils/hashtable.h b/src/libstrongswan/utils/hashtable.h new file mode 100644 index 000000000..3d3005e73 --- /dev/null +++ b/src/libstrongswan/utils/hashtable.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id: hashtable.h 4762 2008-12-05 10:01:52Z martin $ + */ + +/** + * @defgroup hashtable hashtable + * @{ @ingroup utils + */ + +#ifndef HASHTABLE_H_ +#define HASHTABLE_H_ + +#include <utils/enumerator.h> + +typedef struct hashtable_t hashtable_t; + +/** + * Prototype for a function that computes the hash code from the given key. + * + * @param key key to hash + * @return hash code + */ +typedef u_int (*hashtable_hash_t)(void *key); + +/** + * Prototype for a function that compares the two keys for equality. + * + * @param key first key (the one we are looking for) + * @param other_key second key + * @return TRUE if the keys are equal + */ +typedef bool (*hashtable_equals_t)(void *key, void *other_key); + +/** + * Class implementing a hash table. + * + * General purpose hash table. This hash table is not synchronized. + */ +struct hashtable_t { + + /** + * Create an enumerator over the hash table key/value pairs. + * + * @return enumerator over (void *key, void *value) + */ + enumerator_t *(*create_enumerator) (hashtable_t *this); + + /** + * Adds the given value with the given key to the hash table, if there + * exists no entry with that key. NULL is returned in this case. + * Otherwise the existing value is replaced and the function returns the + * old value. + * + * @param key the key to store + * @param value the value to store + * @return NULL if no item was replaced, the old value otherwise + */ + void *(*put) (hashtable_t *this, void *key, void *value); + + /** + * Returns the value with the given key, if the hash table contains such an + * entry, otherwise NULL is returned. + * + * @param key the key of the requested value + * @return the value, NULL if not found + */ + void *(*get) (hashtable_t *this, void *key); + + /** + * Removes the value with the given key from the hash table and returns the + * removed value (or NULL if no such value existed). + * + * @param key the key of the value to remove + * @return the removed value, NULL if not found + */ + void *(*remove) (hashtable_t *this, void *key); + + /** + * Gets the number of items in the hash table. + * + * @return number of items + */ + u_int (*get_count) (hashtable_t *this); + + /** + * Destroys a hash table object. + */ + void (*destroy) (hashtable_t *this); + +}; + +/** + * Creates an empty hash table object. + * + * @param hash hash function + * @param equals equals function + * @param capacity initial capacity + * @return hashtable_t object. + */ +hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals, + u_int capacity); + +#endif /* HASHTABLE_H_ @} */ diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index 4702222e8..719c5a529 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -15,7 +15,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: host.c 4639 2008-11-12 15:09:24Z martin $ + * $Id: host.c 4856 2009-02-05 22:13:48Z andreas $ */ #define _GNU_SOURCE @@ -453,6 +453,10 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port) { return host_create_any(af ? af : AF_INET); } + if (streq(string, "%any6")) + { + return host_create_any(af ? af : AF_INET6); + } else if (strchr(string, ':')) { /* gethostbyname does not like IPv6 addresses - fallback */ diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index db442e9ab..529e62509 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: identification.c 4344 2008-09-17 02:17:01Z andreas $ + * $Id: identification.c 4856 2009-02-05 22:13:48Z andreas $ */ #define _GNU_SOURCE @@ -1046,6 +1046,7 @@ identification_t *identification_create_from_string(char *string) else if (strchr(string, '@') == NULL) { if (streq(string, "%any") + || streq(string, "%any6") || streq(string, "0.0.0.0") || streq(string, "*") || streq(string, "::") diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 73409158d..4c56c9596 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -12,9 +12,11 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: leak_detective.c 4609 2008-11-10 16:44:27Z martin $ + * $Id: leak_detective.c 4796 2008-12-12 09:10:52Z martin $ */ +#define _GNU_SOURCE +#include <sched.h> #include <stddef.h> #include <string.h> #include <stdio.h> @@ -160,6 +162,7 @@ char *whitelist[] = { /* pthread stuff */ "pthread_create", "pthread_setspecific", + "__pthread_setspecific", /* glibc functions */ "mktime", "__gmtime_r", @@ -199,6 +202,7 @@ char *whitelist[] = { "RSA_new_method", "DH_new_method", "ENGINE_load_builtin_engines", + "OPENSSL_config", }; /** @@ -471,6 +475,16 @@ leak_detective_t *leak_detective_create() if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) { + cpu_set_t mask; + + CPU_ZERO(&mask); + CPU_SET(0, &mask); + + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) != 0) + { + fprintf(stderr, "setting CPU affinity failed: %m"); + } + lib->leak_detective = TRUE; install_hooks(); } diff --git a/src/libstrongswan/utils/lexparser.c b/src/libstrongswan/utils/lexparser.c index 8b7b3b547..5725df1ea 100644 --- a/src/libstrongswan/utils/lexparser.c +++ b/src/libstrongswan/utils/lexparser.c @@ -11,16 +11,11 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: lexparser.c 3872 2008-04-25 07:04:59Z andreas $ + * $Id: lexparser.c 4877 2009-02-18 09:45:54Z martin $ */ -/* memrchr is a GNU extension */ -#define _GNU_SOURCE -#include <string.h> - #include "lexparser.h" - /** * eat whitespace */ @@ -30,7 +25,7 @@ bool eat_whitespace(chunk_t *src) { src->ptr++; src->len--; } - return src->len > 0 && *src->ptr != '#'; + return src->len > 0 && *src->ptr != '#'; } /** @@ -51,11 +46,11 @@ bool extract_token(chunk_t *token, const char termination, chunk_t *src) if (termination == ' ') { u_char *eot_tab = memchr(src->ptr, '\t', src->len); - + /* check if a tab instead of a space terminates the token */ eot = ( eot_tab == NULL || (eot && eot < eot_tab) ) ? eot : eot_tab; } - + /* initialize empty token */ *token = chunk_empty; @@ -76,16 +71,17 @@ bool extract_token(chunk_t *token, const char termination, chunk_t *src) } /** - * extracts a token ending with the last occurrence of a given termination symbol + * extracts a token ending with the first occurrence of a given null-terminated string */ -bool extract_last_token(chunk_t *token, const char termination, chunk_t *src) +bool extract_token_str(chunk_t *token, const char *termination, chunk_t *src) { - u_char *eot = memrchr(src->ptr, termination, src->len); + u_char *eot = memstr(src->ptr, termination, src->len); + size_t l = strlen(termination); /* initialize empty token */ *token = chunk_empty; - if (eot == NULL) /* termination symbol not found */ + if (eot == NULL) /* termination string not found */ { return FALSE; } @@ -94,9 +90,9 @@ bool extract_last_token(chunk_t *token, const char termination, chunk_t *src) token->ptr = src->ptr; token->len = (u_int)(eot - src->ptr); - /* advance src pointer after termination symbol */ - src->ptr = eot + 1; - src->len -= (token->len + 1); + /* advance src pointer after termination string */ + src->ptr = eot + l; + src->len -= (token->len + l); return TRUE; } diff --git a/src/libstrongswan/utils/lexparser.h b/src/libstrongswan/utils/lexparser.h index 7d54ca22e..c47f65718 100644 --- a/src/libstrongswan/utils/lexparser.h +++ b/src/libstrongswan/utils/lexparser.h @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: lexparser.h 3876 2008-04-26 09:24:14Z andreas $ + * $Id: lexparser.h 4877 2009-02-18 09:45:54Z martin $ */ /** @@ -37,14 +37,14 @@ bool eat_whitespace(chunk_t *src); bool match(const char *pattern, const chunk_t *ch); /** - * Extracts a token ending with the first occurence a given termination symbol + * Extracts a token ending with the first occurrence of a given termination symbol */ bool extract_token(chunk_t *token, const char termination, chunk_t *src); /** - * Extracts a token ending with the last occurence a given termination symbol + * Extracts a token ending with the first occurrence of a given null-terminated string */ -bool extract_last_token(chunk_t *token, const char termination, chunk_t *src); +bool extract_token_str(chunk_t *token, const char *termination, chunk_t *src); /** * Fetches a new text line terminated by \n or \r\n diff --git a/src/libstrongswan/utils/mutex.c b/src/libstrongswan/utils/mutex.c index ddb0d2df6..ba4b72b0c 100644 --- a/src/libstrongswan/utils/mutex.c +++ b/src/libstrongswan/utils/mutex.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -12,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: mutex.c 4591 2008-11-05 16:12:54Z martin $ + * $Id: mutex.c 4803 2008-12-15 09:13:43Z martin $ */ #define _GNU_SOURCE @@ -76,7 +77,7 @@ static void profiler_cleanup(lock_profile_t *profile) */ static void profiler_init(lock_profile_t *profile) { - profile->backtrace = backtrace_create(3); + profile->backtrace = backtrace_create(2); timerclear(&profile->waited); } @@ -332,28 +333,17 @@ static void wait(private_condvar_t *this, private_mutex_t *mutex) } /** - * Implementation of condvar_t.timed_wait. + * Implementation of condvar_t.timed_wait_abs. */ -static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, - u_int timeout) +static bool timed_wait_abs(private_condvar_t *this, private_mutex_t *mutex, + timeval_t time) { struct timespec ts; - struct timeval tv; - u_int s, ms; bool timed_out; - gettimeofday(&tv, NULL); - - s = timeout / 1000; - ms = timeout % 1000; + ts.tv_sec = time.tv_sec; + ts.tv_nsec = time.tv_usec * 1000; - ts.tv_sec = tv.tv_sec + s; - ts.tv_nsec = tv.tv_usec * 1000 + ms * 1000000; - if (ts.tv_nsec > 1000000000 /* 1s */) - { - ts.tv_nsec -= 1000000000; - ts.tv_sec++; - } if (mutex->recursive) { private_r_mutex_t* recursive = (private_r_mutex_t*)mutex; @@ -372,6 +362,31 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, } /** + * Implementation of condvar_t.timed_wait. + */ +static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, + u_int timeout) +{ + timeval_t tv; + u_int s, ms; + + gettimeofday(&tv, NULL); + + s = timeout / 1000; + ms = timeout % 1000; + + tv.tv_sec += s; + tv.tv_usec += ms * 1000; + + if (tv.tv_usec > 1000000 /* 1s */) + { + tv.tv_usec -= 1000000; + tv.tv_sec++; + } + return timed_wait_abs(this, mutex, tv); +} + +/** * Implementation of condvar_t.signal. */ static void signal(private_condvar_t *this) @@ -410,6 +425,7 @@ condvar_t *condvar_create(condvar_type_t type) this->public.wait = (void(*)(condvar_t*, mutex_t *mutex))wait; this->public.timed_wait = (bool(*)(condvar_t*, mutex_t *mutex, u_int timeout))timed_wait; + this->public.timed_wait_abs = (bool(*)(condvar_t*, mutex_t *mutex, timeval_t time))timed_wait_abs; this->public.signal = (void(*)(condvar_t*))signal; this->public.broadcast = (void(*)(condvar_t*))broadcast; this->public.destroy = (void(*)(condvar_t*))condvar_destroy; diff --git a/src/libstrongswan/utils/mutex.h b/src/libstrongswan/utils/mutex.h index a0a198024..4cdd96a99 100644 --- a/src/libstrongswan/utils/mutex.h +++ b/src/libstrongswan/utils/mutex.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -11,6 +12,8 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: mutex.h 4697 2008-11-25 19:30:02Z tobias $ */ /** @@ -99,6 +102,15 @@ struct condvar_t { bool (*timed_wait)(condvar_t *this, mutex_t *mutex, u_int timeout); /** + * Wait on a condvar until it gets signalized, or times out. + * + * @param mutex mutex to release while waiting + * @param time absolute time until timeout + * @return TRUE if timed out, FALSE otherwise + */ + bool (*timed_wait_abs)(condvar_t *this, mutex_t *mutex, timeval_t timeout); + + /** * Wake up a single thread in a condvar. */ void (*signal)(condvar_t *this); |