From 7356408ca1554468c9d7b9840aaaee28b4341c8d Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Wed, 9 Sep 2020 11:59:36 +0200 Subject: [HICN-563] listener and connection tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I88b85a61908d97bda1afb08d31c3bf10b4d9c5c5 Signed-off-by: Jordan Augé --- hicn-light/src/hicn/base/bitmap.h | 5 +- hicn-light/src/hicn/base/test/test-bitmap.cc | 4 +- hicn-light/src/hicn/core/connection_table.c | 25 ++- hicn-light/src/hicn/core/connection_table.h | 234 +++++++++++++++++++++------ hicn-light/src/hicn/core/content_store.c | 4 +- hicn-light/src/hicn/core/content_store.h | 23 ++- hicn-light/src/hicn/core/forwarder.c | 4 +- hicn-light/src/hicn/core/listener_table.c | 37 +++-- hicn-light/src/hicn/core/listener_table.h | 189 +++++++++++++++++++--- 9 files changed, 421 insertions(+), 104 deletions(-) (limited to 'hicn-light/src/hicn') diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h index bebbf8860..8fd9fcd70 100644 --- a/hicn-light/src/hicn/base/bitmap.h +++ b/hicn-light/src/hicn/base/bitmap.h @@ -25,6 +25,9 @@ #include #include "common.h" +#include "vector.h" + +typedef uint_fast32_t bitmap_t; #define BITMAP_WIDTH(bitmap) (sizeof((bitmap)[0]) * 8) @@ -56,7 +59,7 @@ * @param[in] bitmap The bitmap to access. * @param[in] i The bit position. */ -#define bitmap_get(bitmap, i) ((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap)))) +#define bitmap_get(bitmap, i) (((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap)))) >> ((i) % BITMAP_WIDTH(bitmap))) /* * @brief Returns whether the i-th bit is set (equal to 1) in a bitmap. diff --git a/hicn-light/src/hicn/base/test/test-bitmap.cc b/hicn-light/src/hicn/base/test/test-bitmap.cc index e7ff7044a..d6ab94f3e 100644 --- a/hicn-light/src/hicn/base/test/test-bitmap.cc +++ b/hicn-light/src/hicn/base/test/test-bitmap.cc @@ -34,7 +34,7 @@ class BitmapTest : public ::testing::Test { } virtual ~BitmapTest() { - + // You can do clean-up work that doesn't throw exceptions here. } @@ -68,7 +68,7 @@ TEST_F(BitmapTest, BitmapUnSet) { EXPECT_FALSE(bitmap_is_set(bitmap, 20)); EXPECT_TRUE(bitmap_is_unset(bitmap, 20)); EXPECT_TRUE(bitmap_is_set(bitmap, 19)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 19)); + EXPECT_FALSE(bitmap_is_unset(bitmap, 19)); } diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c index fd8013b73..0b7df0384 100644 --- a/hicn-light/src/hicn/core/connection_table.c +++ b/hicn-light/src/hicn/core/connection_table.c @@ -18,22 +18,35 @@ * \brief Implementation of hICN connection table */ -#include -#include +#include -/* This is only used for first allocation, as the table is resizeable */ +#include "connection.h" +#include "connection_table.h" + +/* This is only used as a hint for first allocation, as the table is resizeable */ #define DEFAULT_CONNECTION_TABLE_SIZE 64 connection_table_t * -connection_table_create(size_t elt_size, size_t max_elts) +_connection_table_create(size_t init_size, size_t max_size) { + if (init_size == 0) + init_size = DEFAULT_CONNECTION_TABLE_SIZE; + connection_table_t * table = malloc(sizeof(connection_table_t)); if (!table) return NULL; + table->max_size = max_size; + + /* Initialize indices */ table->id_by_pair = kh_init_ct_pair(); table->id_by_name = kh_init_ct_name(); - pool_init(table->connections, DEFAULT_CONNECTION_TABLE_SIZE); + + /* + * We start by allocating a reasonably-sized pool, as this will eventually + * be resized if needed. + */ + pool_init(table->connections, init_size); return table; } @@ -57,7 +70,7 @@ connection_table_get_by_pair(const connection_table_t * table, return table->connections + kh_val(table->id_by_pair, k); } -unsigned +off_t connection_table_get_id_by_name(const connection_table_t * table, const char * name) { diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h index c0406ced8..8a9342f45 100644 --- a/hicn-light/src/hicn/core/connection_table.h +++ b/hicn-light/src/hicn/core/connection_table.h @@ -16,84 +16,172 @@ /** * \file connection_table.h * \brief hICN connection_table + * + * The connection table is composed of : + * - a pool of connections allowing access through their id in constant time; + * - a set of indices in the form of hash table for efficient index lookups: + * . by name + * . by address pair + * + * For efficient index retrieval, the header will be prepended and the + * resulting pointer will directly point to the connection pool. */ -/* Iterate on connection table : to remove all connections associated to a - * listener based on listen address */ +#ifndef HICNLIGHT_CONNECTION_TABLE_H +#define HICNLIGHT_CONNECTION_TABLE_H -#ifndef HICN_CONNECTION_TABLE_H -#define HICN_CONNECTION_TABLE_H - -//#include #include #include #include #include #include -#include +#define _ct_var(x) _ct_var_##x +/* Hash functions for indices. */ #define address_pair_hash(pair) (hash32(pair, sizeof(address_pair_t))) #define address_pair_hash_eq(a, b) (address_pair_hash(b) - address_pair_hash(a)) +/* Hash table types for indices. */ KHASH_INIT(ct_pair, const address_pair_t *, unsigned, 0, address_pair_hash, address_pair_hash_eq); - KHASH_INIT(ct_name, const char *, unsigned, 0, str_hash, str_hash_eq); -/* - * The connection table is composed of : - * - a connection pool allowing connection access by id in constant time - * - a hash table allowing to perform lookups based on address pairs, to get a connection id. - * - * For fast lookup by ID, the connection table will point to the beginning of - * the pool / vector, holding all connections. - * The header will be prepended - */ - typedef struct { + size_t max_size; + kh_ct_pair_t * id_by_pair; kh_ct_name_t * id_by_name; connection_t * connections; // pool } connection_table_t; -#define connection_table_allocate(table, conn, pair, name) \ +/** + * @brief Allocate a connection from the connection table. + * + * @param[in] table The connection table from which to allocate a connection. + * @param[out] connection The pointer that will hold the allocated connection. + * @param[in] pair The address pair associated to the connection (to update index). + * @param[in] name The name associated to the connection (to update index). + * + * NOTE: + * - This function updates all indices from the connection table if the + * allocation is successful. + * - You should always check that the returned connection is not NULL, which + * would signal that the pool is exhausted and could not be extended. + */ +#define connection_table_allocate(TABLE, CONN, PAIR, NAME) \ do { \ - pool_get(table->connections, conn); \ - off_t connection_id = conn - table->connections; \ - int res; \ - khiter_t k = kh_put_ct_pair(table->id_by_pair, pair, &res); \ - kh_value(table->id_by_pair, k) = connection_id; \ - if (name) { \ - k = kh_put_ct_name(table->id_by_name, name, &res); \ - kh_value(table->id_by_name, k) = connection_id; \ + pool_get((TABLE)->connections, CONN); \ + if (CONN) { \ + off_t _ct_var(id) = (CONN) - (TABLE)->connections; \ + int _ct_var(res); \ + khiter_t _ct_var(k); \ + _ct_var(k) = kh_put_ct_pair((TABLE)->id_by_pair, PAIR, &_ct_var(res)); \ + kh_value((TABLE)->id_by_pair, _ct_var(k)) = _ct_var(id); \ + if (NAME) { \ + _ct_var(k) = kh_put_ct_name((TABLE)->id_by_name, (NAME), &_ct_var(res));\ + kh_value((TABLE)->id_by_name, _ct_var(k)) = _ct_var(id); \ + } \ } \ } while(0) -#define connection_table_deallocate(table, conn) \ +/** + * @brief Deallocate a connection and return it to the connection table pool. + * + * @param[in] table The connection table to which the connection is returned. + * @param[in] conn The connection that is returned to the pool. + * + * NOTE: + * - Upon returning a connection to the pool, all indices pointing to that + * connection are also cleared. + */ +#define connection_table_deallocate(TABLE, CONN) \ do { \ - const address_pair_t * pair = connection_get_pair(connection); \ - khiter_t k = kh_get_ct_pair(table->id_by_pair, pair); \ - if (k != kh_end(table->id_by_pair)) \ - kh_del_ct_pair(table->id_by_pair, k); \ + const address_pair_t * _ct_var(pair) = connection_get_pair(CONN); \ + khiter_t _ct_var(k); \ + _ct_var(k) = kh_get_ct_pair((TABLE)->id_by_pair, _ct_var(pair)); \ + if (_ct_var(k) != kh_end((TABLE)->id_by_pair)) \ + kh_del_ct_pair((TABLE)->id_by_pair, _ct_var(k)); \ \ - const char * name = connection_get_name(connection); \ - if (name) { \ - k = kh_get_ct_name(table->id_by_name, name); \ - if (k != kh_end(table->id_by_name)) \ - kh_del_ct_name(table->id_by_name, k); \ + const char * _ct_var(name) = connection_get_name(CONN); \ + if (_ct_var(name)) { \ + _ct_var(k) = kh_get_ct_name((TABLE)->id_by_name, _ct_var(name)); \ + if (_ct_var(k) != kh_end((TABLE)->id_by_name)) \ + kh_del_ct_name((TABLE)->id_by_name, _ct_var(k)); \ } \ \ - pool_put(table->connections, conn); \ + pool_put((TABLE)->connections, CONN); \ } while(0) \ -#define connection_table_len(table) (pool_elts(table->connections)) +/** + * @brief Returns the length of the connection table, the number of active + * connections. + * + * @param[in] table The connection table for which we retrieve the length. + * + * @return size_t The length of the connection table. + * + * NOTE: + * - The length of the connection table, that is the number of currently active + * connections. + */ +#define connection_table_len(table) (pool_len(table->connections)) +/** + * @brief Validate an index in the connection table. + * + * @param[in] table The connection table in which to validate an index. + * @param[in] id The index of the connection to validate. + * + * @return bool A flag indicating whether the connection index is valid or not. + */ #define connection_table_validate_id(table, id) \ pool_validate_id((table)->connections, (id)) +/** + * @brief Return the connection corresponding to the specified index in the + * connection table. + * + * @param[in] table The connection table for which to retrieve the connection. + * @param[in] id The index for which to retrieve the connection. + * + * @return connection_t * The connection correponding to the specified index in + * the connection table. + * + * @see connection_table_get_by_id + * + * NOTE: + * - In this function, the index is not validated. + */ #define connection_table_at(table, id) ((table)->connections + id) +/** + * @brief Return the connection corresponding to the specified and validated + * index in the connection table. + * + * @param[in] table The connection table for which to retrieve the connection. + * @param[in] id The index for which to retrieve the connection. + * + * @return connection_t * The connection correponding to the specified index in + * the connection table. + * + * @see connection_table_get_by_id + * + * NOTE: + * - In this function, the index is validated. + */ +#define connection_table_get_by_id(table, id) \ + connection_table_validate_id(table, id) \ + ? connection_table_at(table, id) : NULL + +/** + * @brief Returns the index of a given connection in the connection table. + * + * @param[in] table The connection table from which to retrieve the index. + * @param[in] conn The connection for which to retrieve the index. + * + * @return off_t The index of the specified connection in the connection table. + */ #define connection_table_get_connection_id(table, conn) \ (conn - table->connections) @@ -101,26 +189,74 @@ do { pool_foreach(table->connections, (conn), BODY) #define connection_table_enumerate(table, i, conn, BODY) \ - pool_foreach(table->connections, (i), (conn), BODY) + pool_enumerate(table->connections, (i), (conn), BODY) -connection_table_t * connection_table_create(); -void connection_table_free(connection_table_t * table); +/** + * @brief Create a new connection table (extended parameters). + * + * @param[in] init_size Initially allocated size (hint, 0 = use default value). + * @param[in] max_size Maximum size (0 = unlimited). + * + * @return connection_table_t* The newly created connection table. + */ +connection_table_t * _connection_table_create(size_t init_size, size_t max_size); -#define connection_table_get_by_id(table, id) \ - connection_table_validate_id((table), (id)) \ - ? connection_table_at((table), (id)) : NULL; +/** + * @brief Create a new connection table (minimal parameters). + * + * @return connection_table_t* The newly created connection table. + */ +#define connection_table_create() _connection_table_create(0, 0) +/** + * @brief Free a connection table + * + * @param[in] table Connection table to free + */ +void connection_table_free(connection_table_t * table); + +/** + * @brief Retrieve a connection from the connection table by address pair. + * + * @param[in] table The connection table in which to search. + * @param[in] pair The address pair to search for. + * + * @return connection_t * The connection matching the specified address pair, or + * NULL if not found. + */ connection_t * connection_table_get_by_pair(const connection_table_t * table, const address_pair_t * pair); -unsigned connection_table_get_id_by_name(const connection_table_t * table, +/** + * @brief Return a connection index from the connection table by name. + * + * @param[in] table The connection table in which to search. + * @param[in] name The name to search for. + * + * @return off_t The index of the connection matching the name, or + * CONNECTION_ID_UNDEFINED if not found. + */ +off_t connection_table_get_id_by_name(const connection_table_t * table, const char * name); +/** + * @brief Return a connection from the connection table by name. + * + * @param[in] table The connection table in which to search. + * @param[in] name The name to search for. + * + * @return connection_t * The connection matching the name, or NULL if not + * found. + */ connection_t * connection_table_get_by_name(const connection_table_t * table, const char * name); +/** + * @brief Remove a connection from the connection table by its index. + * + * @param[in] table The connection table from which to delete the connection. + * @param[in] id The index of the connection to remove. + */ void connection_table_remove_by_id(connection_table_t * table, off_t id); -//unsigned connection_table_add(connection_table_t * table, Connection * connection); - -#endif /* HICN_CONNECTION_TABLE_H */ +#endif /* HICNLIGHT_CONNECTION_TABLE_H */ diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c index 7ed2bd838..77d40ace5 100644 --- a/hicn-light/src/hicn/core/content_store.c +++ b/hicn-light/src/hicn/core/content_store.c @@ -46,7 +46,7 @@ do { content_store_t * -content_store_create(content_store_type_t type, size_t max_elts) +_content_store_create(content_store_type_t type, size_t init_size, size_t max_size) { content_store_t * cs = malloc(sizeof(content_store_t)); if (!cs) @@ -56,7 +56,7 @@ content_store_create(content_store_type_t type, size_t max_elts) cs->type = type; // XXX TODO an entry = data + metadata specific to each policy - pool_init(cs->entries, max_elts); + pool_init(cs->entries, init_size); // data // options diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h index 1a339f494..5cddeaa87 100644 --- a/hicn-light/src/hicn/core/content_store.h +++ b/hicn-light/src/hicn/core/content_store.h @@ -45,6 +45,7 @@ KHASH_INIT(cs_name, const Name *, unsigned, 0, name_hash, name_hash_eq); typedef struct { content_store_type_t type; + size_t max_size; // XXX TODO api to dynamically set max size content_store_entry_t * entries; // pool @@ -60,7 +61,25 @@ typedef struct { content_store_stats_t stats; } content_store_t; -content_store_t * content_store_create(content_store_type_t type, size_t max_elts); +/** + * @brief Create a new content store (extended parameters) + * + * @param[in] type Content store type + * @param[in] init_size Initially allocated size (hint, 0 = use default value) + * @param[in] max_size Maximum size (0 = unlimited) + * + * @return content_store_t* - The newly created content store + */ +content_store_t * _content_store_create(content_store_type_t type, size_t init_size, size_t max_size); + +/** + * @brief Create a new content store + * + * @param[in] type Content store type + * + * @return content_store_t* - The newly created content store + */ +#define content_store_create( TYPE) _content_store_create((TYPE), 0, 0) void content_store_free(content_store_t * cs); @@ -74,7 +93,7 @@ void content_store_remove_entry(content_store_t * cs, content_store_entry_t * en bool content_store_remove(content_store_t * cs, msgbuf_t * msgbuf); -#define content_store_size(content_store) (pool_elts(cs->entries)) +#define content_store_size(content_store) (pool_len(cs->entries)) void content_store_purge_entry(content_store_t * cs, content_store_entry_t * entry); diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c index 94baade94..9c3df906d 100644 --- a/hicn-light/src/hicn/core/forwarder.c +++ b/hicn-light/src/hicn/core/forwarder.c @@ -224,8 +224,8 @@ forwarder_create() size_t objectStoreSize = configuration_content_store_get_size(forwarder_get_configuration(forwarder)); - forwarder->content_store = content_store_create(CONTENT_STORE_TYPE_LRU, - objectStoreSize); + forwarder->content_store = _content_store_create(CONTENT_STORE_TYPE_LRU, + objectStoreSize, 0); if (!forwarder->content_store) goto ERR_CONTENT_STORE; diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c index e3cbb310d..f69ad7535 100644 --- a/hicn-light/src/hicn/core/listener_table.c +++ b/hicn-light/src/hicn/core/listener_table.c @@ -18,22 +18,35 @@ * \brief Implementation of hICN listener table */ -#include -#include +#include -/* This is only used for first allocation, as the table is resizeable */ +#include "listener_table.h" +#include "listener.h" + +/* This is only used as a hint for first allocation, as the table is resizeable */ #define DEFAULT_LISTENER_TABLE_SIZE 64 listener_table_t * -listener_table_create(size_t elt_size, size_t max_elts) +_listener_table_create(size_t init_size, size_t max_size) { + if (init_size == 0) + init_size = DEFAULT_LISTENER_TABLE_SIZE; + listener_table_t * table = malloc(sizeof(listener_table_t)); if (!table) return NULL; + table->max_size = max_size; + + /* Initialize indices */ table->id_by_name = kh_init_lt_name(); table->id_by_key = kh_init_lt_key(); - pool_init(table->listeners, DEFAULT_LISTENER_TABLE_SIZE); + + /* + * We start by allocating a reasonably-sized pool, as this will eventually + * be resized if needed. + */ + pool_init(table->listeners, init_size); return table; } @@ -91,17 +104,3 @@ listener_table_get_by_name(listener_table_t * table, const char * name) return NULL; return listener_table_at(table, kh_val(table->id_by_name, k)); } - -#if 0 -unsigned -listener_table_add(listener_table_t * table, listener_t * listener) -{ - // XXX missing hash and key storage - listener_t * lst; - pool_get(table->listeners, lst); - lst = listener; - unsigned listener_id = lst - table, - Listener_SetId(listener, listener_id); - return listener_id; -} -#endif diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h index 66959def4..70cd8bbbf 100644 --- a/hicn-light/src/hicn/core/listener_table.h +++ b/hicn-light/src/hicn/core/listener_table.h @@ -16,10 +16,19 @@ /** * \file listener_table.h * \brief hICN listener table + * + * The listener table is composed of: + * - a pool of listeners allowing access through their index in constant time; + * - a set of indices in the form of hash table for efficient index lookups: + * . by name + * . by key (listener_type, address) + * + * For efficient index retrieval, the header will be prepended and the + * resulting pointer will directly point to the listener pool. */ -#ifndef HICN_LISTENER_TABLE_H -#define HICN_LISTENER_TABLE_H +#ifndef HICNLIGHT_LISTENER_TABLE_H +#define HICNLIGHT_LISTENER_TABLE_H #include #include @@ -30,34 +39,65 @@ #define _lt_var(x) _lt_var_##x +/* Hash functions for indices */ #define key_hash(key) (hash(key, sizeof(listener_key_t))) #define key_hash_eq(a, b) (key_hash(b) - key_hash(a)) +/* Hash table types for indices */ KHASH_INIT(lt_name, const char *, unsigned, 0, str_hash, str_hash_eq); KHASH_INIT(lt_key, listener_key_t *, unsigned, 0, key_hash, key_hash_eq); typedef struct { - kh_lt_key_t * id_by_key; - kh_lt_name_t * id_by_name; - listener_t * listeners; // pool + size_t max_size; + + kh_lt_key_t * id_by_key; + kh_lt_name_t * id_by_name; + + listener_t * listeners; // pool } listener_table_t; +/** + * @brief Allocate a listener from the listener table. + * + * @param[in] table The listener table from which to allocate a listener. + * @param[out] listener The pointer that will hold the allocated listener. + * @param[in] pair The address pair associated to the listener (to update index) + * @param[in] name The name associated to the listener (to update index) + * + * NOTE: + * - This function updates all indices from the listener table if the + * allocation is successful. + * - You should always check that the returned listener is not NULL, which + * would signal that the pool is exhausted and could not be extended. + */ #define listener_table_allocate(TABLE, LISTENER, KEY, NAME) \ do { \ pool_get(table->listeners, (LISTENER)); \ - off_t _lt_var(id) = (LISTENER) - (TABLE)->listeners; \ - int _lt_var(res); \ - khiter_t _lt_var(k); \ - _lt_var(k) = kh_put_lt_name((TABLE)->id_by_name, (NAME), &_lt_var(res)); \ - kh_value((TABLE)->id_by_name, _lt_var(k)) = _lt_var(id); \ - \ - listener->type = (KEY)->type; \ - listener->address = (KEY)->address; \ - listener_key_t * _lt_var(key) = listener_get_key(LISTENER); \ - _lt_var(k) = kh_put_lt_key((TABLE)->id_by_key, _lt_var(key), &_lt_var(res));\ - kh_value((TABLE)->id_by_key, _lt_var(k)) = _lt_var(id); \ + if (LISTENER) { \ + off_t _lt_var(id) = (LISTENER) - (TABLE)->listeners; \ + int _lt_var(res); \ + khiter_t _lt_var(k); \ + _lt_var(k) = kh_put_lt_name((TABLE)->id_by_name, (NAME), &_lt_var(res));\ + kh_value((TABLE)->id_by_name, _lt_var(k)) = _lt_var(id); \ + \ + listener->type = (KEY)->type; \ + listener->address = (KEY)->address; \ + listener_key_t * _lt_var(key) = listener_get_key(LISTENER); \ + _lt_var(k) = kh_put_lt_key((TABLE)->id_by_key, _lt_var(key), &_lt_var(res));\ + kh_value((TABLE)->id_by_key, _lt_var(k)) = _lt_var(id); \ + } \ } while(0) +/** + * @brief Deallocate a listener and return it to the listener table pool. + * + * @param[in] table The listener table to which the listener is returned. + * @param[in] conn The listener that is returned to the pool. + * + * NOTE: + * - Upon returning a listener to the pool, all indices pointing to that + * listener are also cleared. + */ #define listener_table_deallocate(TABLE, LISTENER) \ do { \ const address_key_t * _lt_var(key) = listener_get_key(LISTENER); \ @@ -74,33 +114,140 @@ do { pool_put((TABLE)->listeners, LISTENER); \ } while(0) \ +/** + * @brief Returns the length of the connection table, the number of active + * connections. + * + * @param[in] table The connection table for which we retrieve the length. + * + * @return size_t The length of the connection table. + * + * NOTE: + * - The length of the connection table, that is the number of currently active + * connections. + */ +#define listener_table_len(table) (pool_len(table->listeners)) -#define listener_table_len(table) (pool_elts(table->listeners)) - -#define listener_table_validate_id(table, id) pool_validate_id(table->listeners, id) +/** + * @brief Validate an index in the listener table. + * + * @param[in] table The listener table in which to validate an index. + * @param[in] id The index of the listener to validate. + * + * @return bool A flag indicating whether the listener index is valid or not. + */ +#define listener_table_validate_id(table, id) \ + pool_validate_id(table->listeners, id) +/** + * @brief Return the connection corresponding to the specified index in the + * connection table. + * + * @param[in] table The connection table for which to retrieve the connection. + * @param[in] id The index for which to retrieve the connection. + * + * @return connection_t * The connection correponding to the specified index in + * the connection table. + * + * @see listener_table_get_by_id + * + * NOTE: + * - In this function, the index is not validated. + */ #define listener_table_at(table, id) ((table)->listeners + id) +/** + * @brief Return the listener corresponding to the specified and validated + * index in the listener table. + * + * @param[in] table The listener table for which to retrieve the listener. + * @param[in] id The index for which to retrieve the listener. + * + * @return listener_t * The listener correponding to the specified index in + * the listener table. + * + * @see listener_table_get_by_id + * + * NOTE: + * - In this function, the index is validated. + */ #define listener_table_get_by_id(table, id) \ listener_table_validate_id(table, id) \ ? listener_table_at(table, id) : NULL +/** + * @brief Returns the index of a given listener in the listener table. + * + * @param[in] table The listener table from which to retrieve the index. + * @param[in] conn The listener for which to retrieve the index. + * + * @return off_t The index of the specified listener in the listener table. + */ #define listener_table_get_listener_id(table, listener) (listener - table->listeners) #define listener_table_foreach(table, listener, BODY) \ pool_foreach(table->listeners, listener, do { BODY } while(0) ) -listener_table_t * listener_table_create(); +#define listener_table_enumerate(table, i, conn, BODY) \ + pool_enumerate(table->listeners, (i), (conn), BODY) + +/** + * @brief Create a new listener table (extended parameters) + * + * @param[in] init_size Initially allocated size (hint, 0 = use default value) + * @param[in] max_size Maximum size (0 = unlimited) + * + * @return listener_table_t* - The newly created listener table + */ +listener_table_t * _listener_table_create(size_t init_size, size_t max_size); + +/** + * @brief Create a new listener table (minimal parameters) + * + * @return listener_table_t* - The newly created listener table + */ +#define listener_table_create() _listener_table_create(0, 0) + +/** + * @brief Free a listener table + * + * @param[in] table Listener table to free + */ void listener_table_free(listener_table_t * table); +/** + * @brief Retrieve a listener from the listener table by address. + * + * @param[in] table The listener table in which to search. + * @param[in] type The face type characterizing the listener to search for. + * @param[in] address The address to search for. + * + * @return listener_t * The listener matching the specified address, or + * NULL if not found. + */ listener_t * listener_table_get_by_address(listener_table_t * table, face_type_t type, const address_t * address); +/** + * @brief Return a listener from the listener table by name. + * + * @param[in] table The listener table in which to search. + * @param[in] name The name to search for. + * + * @return listener_t * The listener matching the name, or NULL if not + * found. + */ listener_t * listener_table_get_by_name(listener_table_t * table, const char *name); +/** + * @brief Remove a listener from the listener table by its index. + * + * @param[in] table The listener table from which to delete the listener. + * @param[in] id The index of the listener to remove. + */ void listener_table_remove_by_id(listener_table_t * table, off_t id); unsigned listener_table_add(listener_table_t * table, listener_t * listener); -#endif /* HICN_LISTENER_TABLE_H */ +#endif /* HICNLIGHT_LISTENER_TABLE_H */ -- cgit 1.2.3-korg