diff options
Diffstat (limited to 'hicn-light/src/hicn/core/listener_table.c')
-rw-r--r-- | hicn-light/src/hicn/core/listener_table.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c new file mode 100644 index 000000000..4a0f74a13 --- /dev/null +++ b/hicn-light/src/hicn/core/listener_table.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file listener_table.c + * \brief Implementation of hICN listener table + */ + +#include <hicn/util/log.h> +#include <hicn/util/sstrncpy.h> + +#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 + +typedef struct { + char name[SYMBOLIC_NAME_LEN]; +} name_key_t; + +listener_table_t *_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->name_keys = slab_create(name_key_t, SLAB_INIT_SIZE); + table->id_by_key = kh_init_lt_key(); + table->listener_keys = slab_create(listener_key_t, SLAB_INIT_SIZE); + + /* + * We start by allocating a reasonably-sized pool, as this will eventually + * be resized if needed. + */ + pool_init(table->listeners, init_size, 0); + + return table; +} + +void listener_table_free(listener_table_t *table) { + unsigned listener_id; + kh_foreach_value(table->id_by_key, listener_id, { + listener_t *listener = listener_table_get_by_id(table, listener_id); + const char *name = listener_get_name(listener); + INFO("Removing listener %s [%d]", name, listener->fd); + listener_finalize(listener); + }); + + kh_destroy_lt_name(table->id_by_name); + slab_free(table->name_keys); + kh_destroy_lt_key(table->id_by_key); + slab_free(table->listener_keys); + + pool_free(table->listeners); + free(table); +} + +listener_t *listener_table_allocate(const listener_table_t *table, + const listener_key_t *key, + const char *name) { + listener_t *listener = NULL; + pool_get(table->listeners, listener); + if (!listener) return NULL; + + off_t id = listener - table->listeners; + int rc; + + // Add in name hash table + name_key_t *name_copy = slab_get(name_key_t, table->name_keys); + strcpy_s(name_copy->name, sizeof(name_key_t), name); + + khiter_t k = kh_put_lt_name(table->id_by_name, name_copy->name, &rc); + assert(rc == KH_ADDED || rc == KH_RESET); + kh_value(table->id_by_name, k) = (unsigned int)id; + + // Add in key hash table + listener_key_t *key_copy = slab_get(listener_key_t, table->listener_keys); + memcpy(key_copy, key, sizeof(listener_key_t)); + + k = kh_put_lt_key(table->id_by_key, key_copy, &rc); + assert(rc == KH_ADDED || rc == KH_RESET); + kh_value(table->id_by_key, k) = (unsigned int)id; + + assert(kh_size(table->id_by_name) == kh_size(table->id_by_key)); + return listener; +} + +void listener_table_deallocate(const listener_table_t *table, + listener_t *listener) { + const char *name = listener_get_name(listener); + listener_key_t *key = listener_get_key(listener); + + // Remove from name hash table + khiter_t k = kh_get_lt_name(table->id_by_name, name); + assert(k != kh_end(table->id_by_name)); + kh_del_lt_name(table->id_by_name, k); + slab_put(table->name_keys, kh_key(table->id_by_name, k)); + + // Remove from key hash table + k = kh_get_lt_key(table->id_by_key, key); + assert(k != kh_end(table->id_by_key)); + kh_del_lt_key(table->id_by_key, k); + slab_put(table->listener_keys, kh_key(table->id_by_key, k)); + + assert(kh_size(table->id_by_name) == kh_size(table->id_by_key)); + pool_put(table->listeners, listener); +} + +listener_t *listener_table_get_by_address(listener_table_t *table, + face_type_t type, + const address_t *address) { + listener_key_t key = listener_key_factory(*address, type); + khiter_t k = kh_get_lt_key(table->id_by_key, &key); + if (k == kh_end(table->id_by_key)) return NULL; + return listener_table_at(table, kh_val(table->id_by_key, k)); +} + +listener_t *listener_table_get_by_key(listener_table_t *table, + const listener_key_t *key) { + khiter_t k = kh_get_lt_key(table->id_by_key, key); + if (k == kh_end(table->id_by_key)) return NULL; + return listener_table_at(table, kh_val(table->id_by_key, k)); +} + +void listener_table_remove_by_id(listener_table_t *table, off_t id) { + listener_t *listener = listener_table_at(table, id); + INFO("Removing listener %d (%s)", id, listener_get_name(listener)); + + listener_table_deallocate(table, listener); +} + +off_t listener_table_get_id_by_name(const listener_table_t *table, + const char *name) { + khiter_t k = kh_get_lt_name(table->id_by_name, name); + if (k == kh_end(table->id_by_name)) return LISTENER_ID_UNDEFINED; + return kh_val(table->id_by_name, k); +} + +listener_t *listener_table_get_by_name(listener_table_t *table, + const char *name) { + unsigned listener_id = + (unsigned int)listener_table_get_id_by_name(table, name); + if (!listener_id_is_valid(listener_id)) return NULL; + return listener_table_at(table, listener_id); +} + +listener_t *_listener_table_get_by_id(listener_table_t *table, off_t id) { + return listener_table_get_by_id(table, id); +} + +void listener_table_print_by_key(const listener_table_t *table) { + const listener_key_t *k; + unsigned v; + + char addr_str[NI_MAXHOST]; + int port; + listener_t *listener; + const char *name; + + INFO("*** Listener table ***"); + kh_foreach(table->id_by_key, k, v, { + address_to_string(&k->address, addr_str, &port); + listener = listener_table_get_by_id(table, v); + name = listener_get_name(listener); + INFO("%s:%d - %s\t\t\t\t(%u, %s)", addr_str, port, face_type_str(k->type), + v, name); + }) +} + +void listener_table_print_by_name(const listener_table_t *table) { + const char *k; + unsigned v; + + char addr_str[NI_MAXHOST]; + int port; + listener_t *listener; + const listener_key_t *key; + + INFO("*** Listener table ***"); + kh_foreach(table->id_by_name, k, v, { + listener = listener_table_get_by_id(table, v); + key = listener_get_key(listener); + address_to_string(&key->address, addr_str, &port); + + INFO("%s:%d - %s\t\t\t\t(%u, %s)", addr_str, port, face_type_str(key->type), + v, k); + }) +} |