metadata-set: Add implementation for a collection of metadata objects
This commit is contained in:
@@ -33,7 +33,7 @@ credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
|
||||
credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
|
||||
database/database_factory.c fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
|
||||
ipsec/ipsec_types.c \
|
||||
metadata/metadata_factory.c metadata/metadata_int.c \
|
||||
metadata/metadata_factory.c metadata/metadata_int.c metadata/metadata_set.c \
|
||||
networking/host.c networking/host_resolver.c networking/packet.c \
|
||||
networking/tun_device.c networking/streams/stream_manager.c \
|
||||
networking/streams/stream.c networking/streams/stream_service.c \
|
||||
|
||||
@@ -31,7 +31,7 @@ credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
|
||||
credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
|
||||
database/database_factory.c fetcher/fetcher.c fetcher/fetcher_manager.c eap/eap.c \
|
||||
ipsec/ipsec_types.c \
|
||||
metadata/metadata_factory.c metadata/metadata_int.c \
|
||||
metadata/metadata_factory.c metadata/metadata_int.c metadata/metadata_set.c \
|
||||
networking/host.c networking/host_resolver.c networking/packet.c \
|
||||
networking/tun_device.c networking/streams/stream_manager.c \
|
||||
networking/streams/stream.c networking/streams/stream_service.c \
|
||||
@@ -101,6 +101,7 @@ credentials/auth_cfg.h credentials/credential_set.h credentials/cert_validator.h
|
||||
database/database.h database/database_factory.h fetcher/fetcher.h \
|
||||
fetcher/fetcher_manager.h eap/eap.h pen/pen.h ipsec/ipsec_types.h \
|
||||
metadata/metadata.h metadata/metadata_factory.h metadata/metadata_int.h \
|
||||
metadata/metadata_set.h \
|
||||
networking/host.h networking/host_resolver.h networking/packet.h \
|
||||
networking/tun_device.h networking/streams/stream.h \
|
||||
networking/streams/stream_unix.h networking/streams/stream_service_unix.h \
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Tobias Brunner, codelabs GmbH
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "metadata_set.h"
|
||||
|
||||
#include <collections/array.h>
|
||||
|
||||
/**
|
||||
* Set of metadata objects, indexed via string.
|
||||
*/
|
||||
struct metadata_set_t {
|
||||
/** Stored metadata objects (entry_t) */
|
||||
array_t *entries;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stored data for each metadata object.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Key of the entry */
|
||||
const char *key;
|
||||
/** Stored metadata object */
|
||||
metadata_t *data;
|
||||
} entry_t;
|
||||
|
||||
/**
|
||||
* Destroy the given entry.
|
||||
*/
|
||||
static void destroy_entry(entry_t *entry)
|
||||
{
|
||||
entry->data->destroy(entry->data);
|
||||
free((char*)entry->key);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort entries by key
|
||||
*/
|
||||
static int entry_sort(const void *a, const void *b, void *user)
|
||||
{
|
||||
const entry_t *ea = a, *eb = b;
|
||||
return strcmp(ea->key, eb->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an entry by key
|
||||
*/
|
||||
static int entry_find(const void *a, const void *b)
|
||||
{
|
||||
return entry_sort(a, b, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
metadata_set_t *metadata_set_create()
|
||||
{
|
||||
metadata_set_t *set;
|
||||
|
||||
INIT(set);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
void metadata_set_put(metadata_set_t *set, const char *key, metadata_t *data)
|
||||
{
|
||||
entry_t *entry = NULL, lookup = {
|
||||
.key = key,
|
||||
};
|
||||
int idx;
|
||||
|
||||
if (!set)
|
||||
{
|
||||
DESTROY_IF(data);
|
||||
return;
|
||||
}
|
||||
|
||||
idx = array_bsearch(set->entries, &lookup, entry_find, &entry);
|
||||
if (idx != -1)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
entry->data->destroy(entry->data);
|
||||
entry->data = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
array_remove(set->entries, idx, NULL);
|
||||
destroy_entry(entry);
|
||||
}
|
||||
}
|
||||
else if (data)
|
||||
{
|
||||
INIT(entry,
|
||||
.key = strdup(key),
|
||||
.data = data,
|
||||
);
|
||||
array_insert_create(&set->entries, ARRAY_TAIL, entry);
|
||||
array_sort(set->entries, entry_sort, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
metadata_t *metadata_set_get(metadata_set_t *set, const char *key)
|
||||
{
|
||||
entry_t *entry = NULL, lookup = {
|
||||
.key = key,
|
||||
};
|
||||
|
||||
if (set && array_bsearch(set->entries, &lookup, entry_find, &entry) != -1)
|
||||
{
|
||||
return entry->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
metadata_set_t *metadata_set_clone(metadata_set_t *set)
|
||||
{
|
||||
metadata_set_t *clone;
|
||||
entry_t *entry, *entry_clone;
|
||||
int i;
|
||||
|
||||
if (!set)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(clone,
|
||||
.entries = array_create(0, array_count(set->entries)),
|
||||
);
|
||||
for (i = 0; i < array_count(set->entries); i++)
|
||||
{
|
||||
array_get(set->entries, i, &entry);
|
||||
INIT(entry_clone,
|
||||
.key = strdup(entry->key),
|
||||
.data = entry->data->clone(entry->data),
|
||||
);
|
||||
array_insert(clone->entries, i, entry_clone);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
void metadata_set_destroy(metadata_set_t *set)
|
||||
{
|
||||
if (set)
|
||||
{
|
||||
array_destroy_function(set->entries, (void*)destroy_entry, NULL);
|
||||
free(set);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Tobias Brunner, codelabs GmbH
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup metadata_set metadata_set
|
||||
* @{ @ingroup metadata
|
||||
*/
|
||||
|
||||
#ifndef METADATA_SET_H_
|
||||
#define METADATA_SET_H_
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
/**
|
||||
* Set of metadata objects, indexed via string.
|
||||
*/
|
||||
typedef struct metadata_set_t metadata_set_t;
|
||||
|
||||
/**
|
||||
* Create a metadata_set_t instance.
|
||||
*/
|
||||
metadata_set_t *metadata_set_create();
|
||||
|
||||
/**
|
||||
* Add a metadata object with the given key to the set, replacing any previous
|
||||
* object with the same key.
|
||||
*
|
||||
* @param set set to add metadata to
|
||||
* @param key key under which to store metadata (cloned)
|
||||
* @param data metadata object (adopted), NULL to remove/destroy
|
||||
* existing object
|
||||
*/
|
||||
void metadata_set_put(metadata_set_t *set, const char *key, metadata_t *data);
|
||||
|
||||
/**
|
||||
* Retrieve the metadata object with the given key.
|
||||
*
|
||||
* @param set set to query
|
||||
* @param key key of the metadata object
|
||||
* @return metadata object, NULL if not found
|
||||
*/
|
||||
metadata_t *metadata_set_get(metadata_set_t *set, const char *key);
|
||||
|
||||
/**
|
||||
* Clone a complete metadata set.
|
||||
*
|
||||
* @param set set to clone
|
||||
* @return cloned set
|
||||
*/
|
||||
metadata_set_t *metadata_set_clone(metadata_set_t *set);
|
||||
|
||||
/**
|
||||
* Destroy a metadata set, destroying all contained metadata objects.
|
||||
*
|
||||
* @param set set to destroy
|
||||
*/
|
||||
void metadata_set_destroy(metadata_set_t *set);
|
||||
|
||||
#endif /** METADATA_SET_H_ @}*/
|
||||
@@ -66,7 +66,8 @@ libstrongswan_tests_SOURCES = tests.h tests.c \
|
||||
suites/test_ed25519.c \
|
||||
suites/test_ed448.c \
|
||||
suites/test_signature_params.c \
|
||||
suites/test_metadata.c
|
||||
suites/test_metadata.c \
|
||||
suites/test_metadata_set.c
|
||||
|
||||
libstrongswan_tests_CFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Tobias Brunner, codelabs GmbH
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "test_suite.h"
|
||||
|
||||
#include <metadata/metadata_set.h>
|
||||
|
||||
START_TEST(test_destroy_null)
|
||||
{
|
||||
metadata_set_t *set = NULL;
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_destroy_empty)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_put_null)
|
||||
{
|
||||
metadata_set_t *set = NULL;
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "key", metadata);
|
||||
metadata_set_put(set, "other", NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_put)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "key", metadata);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_get_null)
|
||||
{
|
||||
metadata_set_t *set = NULL;
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = metadata_set_get(set, "key");
|
||||
ck_assert(!metadata);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/**
|
||||
* Assert that the given int metadata value is found with the given key.
|
||||
*/
|
||||
static void assert_int_value(metadata_set_t *set, const char *key, int expected)
|
||||
{
|
||||
metadata_t *metadata;
|
||||
int value;
|
||||
|
||||
metadata = metadata_set_get(set, key);
|
||||
ck_assert(metadata);
|
||||
metadata->get(metadata, &value);
|
||||
ck_assert_int_eq(expected, value);
|
||||
}
|
||||
|
||||
START_TEST(test_get)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "key", metadata);
|
||||
assert_int_value(set, "key", 42);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_get_missing)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = metadata_set_get(set, "key");
|
||||
ck_assert(!metadata);
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "other", metadata);
|
||||
metadata = metadata_set_get(set, "key");
|
||||
ck_assert(!metadata);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_get_multi)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "key", metadata);
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 0);
|
||||
metadata_set_put(set, "other", metadata);
|
||||
assert_int_value(set, "key", 42);
|
||||
assert_int_value(set, "other", 0);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_put_replace)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "whatever", metadata);
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 0);
|
||||
metadata_set_put(set, "other", metadata);
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 666);
|
||||
metadata_set_put(set, "other", metadata);
|
||||
assert_int_value(set, "whatever", 42);
|
||||
assert_int_value(set, "other", 666);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_put_remove)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "key", metadata);
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 0);
|
||||
metadata_set_put(set, "other", metadata);
|
||||
metadata_set_put(set, "other", NULL);
|
||||
assert_int_value(set, "key", 42);
|
||||
metadata = metadata_set_get(set, "other");
|
||||
ck_assert(!metadata);
|
||||
metadata_set_put(set, "key", NULL);
|
||||
metadata = metadata_set_get(set, "key");
|
||||
ck_assert(!metadata);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_put_remove_missing)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create();
|
||||
metadata_t *metadata;
|
||||
|
||||
metadata_set_put(set, "key", NULL);
|
||||
metadata = lib->metadata->create(lib->metadata, "int", 42);
|
||||
metadata_set_put(set, "key", metadata);
|
||||
assert_int_value(set, "key", 42);
|
||||
metadata_set_put(set, "key", NULL);
|
||||
metadata = metadata_set_get(set, "key");
|
||||
ck_assert(!metadata);
|
||||
metadata_set_put(set, "key", NULL);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_clone_null)
|
||||
{
|
||||
metadata_set_t *set = NULL, *clone;
|
||||
|
||||
clone = metadata_set_clone(set);
|
||||
ck_assert(!clone);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_clone_empty)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create(), *clone;
|
||||
|
||||
clone = metadata_set_clone(set);
|
||||
ck_assert(clone != set);
|
||||
|
||||
metadata_set_destroy(clone);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_clone)
|
||||
{
|
||||
metadata_set_t *set = metadata_set_create(), *clone;
|
||||
metadata_t *metadata;
|
||||
struct {
|
||||
const char *key;
|
||||
int value;
|
||||
} expected[] = {
|
||||
{ "key", 42, },
|
||||
{ "other", 666, },
|
||||
{ "abc", 4500, },
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < countof(expected); i++)
|
||||
{
|
||||
metadata = lib->metadata->create(lib->metadata, "int", expected[i].value);
|
||||
metadata_set_put(set, expected[i].key, metadata);
|
||||
}
|
||||
|
||||
clone = metadata_set_clone(set);
|
||||
ck_assert(clone != set);
|
||||
|
||||
for (i = 0; i < countof(expected); i++)
|
||||
{
|
||||
assert_int_value(set, expected[i].key, expected[i].value);
|
||||
assert_int_value(clone, expected[i].key, expected[i].value);
|
||||
}
|
||||
|
||||
metadata_set_put(set, expected[0].key, NULL);
|
||||
assert_int_value(clone, expected[0].key, expected[0].value);
|
||||
|
||||
metadata_set_destroy(clone);
|
||||
metadata_set_destroy(set);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *metadata_set_suite_create()
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("metadata_set");
|
||||
|
||||
tc = tcase_create("create/destroy");
|
||||
tcase_add_test(tc, test_destroy_null);
|
||||
tcase_add_test(tc, test_destroy_empty);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("put/get");
|
||||
tcase_add_test(tc, test_put_null);
|
||||
tcase_add_test(tc, test_put);
|
||||
tcase_add_test(tc, test_get_null);
|
||||
tcase_add_test(tc, test_get);
|
||||
tcase_add_test(tc, test_get_missing);
|
||||
tcase_add_test(tc, test_get_multi);
|
||||
tcase_add_test(tc, test_put_replace);
|
||||
tcase_add_test(tc, test_put_remove);
|
||||
tcase_add_test(tc, test_put_remove_missing);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("clone");
|
||||
tcase_add_test(tc, test_clone_null);
|
||||
tcase_add_test(tc, test_clone_empty);
|
||||
tcase_add_test(tc, test_clone);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -62,3 +62,4 @@ TEST_SUITE_DEPEND(ed25519_suite_create, PRIVKEY_GEN, KEY_ED25519)
|
||||
TEST_SUITE_DEPEND(ed448_suite_create, PRIVKEY_GEN, KEY_ED448)
|
||||
TEST_SUITE(signature_params_suite_create)
|
||||
TEST_SUITE(metadata_suite_create)
|
||||
TEST_SUITE(metadata_set_suite_create)
|
||||
|
||||
Reference in New Issue
Block a user