From 596a73b53ef47e56a6943ddeac7297d7da6cee79 Mon Sep 17 00:00:00 2001 From: Michael Barker Date: Sun, 23 Jan 2022 15:47:17 +0000 Subject: [PATCH] Support Static Linking (#1261) * [C] Add aeron_symbol_table and use it to resovle internal symbols. Encapsulate dlsym lookups. Separate object and function pointers and correctly deal generic versions of each. Remove multiple instances of warning ignores for -Wpendantic. * [C] Fix windows compilation error. * [C] Add unit test. Break early on object resolution. * [C] Switch to specifying length on symbol tables instead of using a NULL terminator. * [C] Use struct to hold function pointer to avoid ignoring -Wpendantic. * [C] Move function definition out of header. Add missing prototype. * [C] Use length when scanning function symbol tables. * [C] Use strncmp to perform a bounded comparison. Add additional bounded length check function. Use typedef for generic function pointer. * [C] Newline at end of file. --- aeron-client/src/main/c/CMakeLists.txt | 2 + aeron-client/src/main/c/aeron_agent.c | 79 ++++----- aeron-client/src/main/c/aeron_common.h | 2 + aeron-client/src/main/c/util/aeron_dlopen.c | 19 ++ aeron-client/src/main/c/util/aeron_dlopen.h | 4 +- aeron-client/src/main/c/util/aeron_strutil.c | 1 + aeron-client/src/main/c/util/aeron_strutil.h | 37 ++++ .../src/main/c/util/aeron_symbol_table.c | 162 ++++++++++++++++++ .../src/main/c/util/aeron_symbol_table.h | 49 ++++++ aeron-client/src/test/c/CMakeLists.txt | 1 + .../src/test/c/util/aeron_strutil_test.cpp | 32 ++++ .../test/c/util/aeron_symbol_table_test.cpp | 82 +++++++++ aeron-driver/src/main/c/CMakeLists.txt | 4 +- .../src/main/c/aeron_congestion_control.c | 44 +++-- aeron-driver/src/main/c/aeron_driver.c | 96 ++++------- .../src/main/c/aeron_driver_name_resolver.h | 5 + aeron-driver/src/main/c/aeron_flow_control.c | 47 +++-- aeron-driver/src/main/c/aeron_name_resolver.c | 75 ++++---- .../src/main/c/aeron_termination_validator.c | 52 +++--- .../src/main/c/agent/aeron_driver_agent.c | 5 +- .../aeron_udp_channel_transport_bindings.c | 126 ++++++-------- .../aeron_udp_channel_transport_bindings.h | 24 +-- 22 files changed, 641 insertions(+), 307 deletions(-) create mode 100644 aeron-client/src/main/c/util/aeron_symbol_table.c create mode 100644 aeron-client/src/main/c/util/aeron_symbol_table.h create mode 100644 aeron-client/src/test/c/util/aeron_symbol_table_test.cpp diff --git a/aeron-client/src/main/c/CMakeLists.txt b/aeron-client/src/main/c/CMakeLists.txt index 247480110a..cd715b3510 100644 --- a/aeron-client/src/main/c/CMakeLists.txt +++ b/aeron-client/src/main/c/CMakeLists.txt @@ -81,6 +81,7 @@ set(SOURCE util/aeron_parse_util.c util/aeron_properties_util.c util/aeron_strutil.c + util/aeron_symbol_table.c uri/aeron_uri.c aeron_agent.c aeron_alloc.c @@ -152,6 +153,7 @@ set(HEADERS util/aeron_platform.h util/aeron_properties_util.h util/aeron_strutil.h + util/aeron_symbol_table.h uri/aeron_uri.h aeron_agent.h aeron_alloc.h diff --git a/aeron-client/src/main/c/aeron_agent.c b/aeron-client/src/main/c/aeron_agent.c index 0241bdb974..de4c889c17 100644 --- a/aeron-client/src/main/c/aeron_agent.c +++ b/aeron-client/src/main/c/aeron_agent.c @@ -28,6 +28,7 @@ #include "util/aeron_error.h" #include "util/aeron_dlopen.h" #include "util/aeron_parse_util.h" +#include "util/aeron_symbol_table.h" #include "aeron_agent.h" #include "aeron_alloc.h" @@ -282,6 +283,19 @@ aeron_idle_strategy_t aeron_idle_strategy_backoff = aeron_idle_strategy_backoff_state_init_args }; +static const aeron_symbol_table_obj_t aeron_idle_strategy_table[] = + { + { "sleeping", "aeron_idle_strategy_sleeping", &aeron_idle_strategy_sleeping }, + { "sleep-ns", "aeron_idle_strategy_sleeping", &aeron_idle_strategy_sleeping }, + { "yield", "aeron_idle_strategy_yielding", &aeron_idle_strategy_yielding }, + { "spin", "aeron_idle_strategy_busy_spinning", &aeron_idle_strategy_busy_spinning }, + { "noop", "aeron_idle_strategy_noop", &aeron_idle_strategy_noop }, + { "backoff", "aeron_idle_strategy_backoff", &aeron_idle_strategy_backoff }, + }; + +static const size_t aeron_idle_strategy_table_length = + sizeof(aeron_idle_strategy_table) / sizeof (aeron_symbol_table_obj_t); + aeron_idle_strategy_func_t aeron_idle_strategy_load( const char *idle_strategy_name, void **idle_strategy_state, @@ -292,74 +306,43 @@ aeron_idle_strategy_func_t aeron_idle_strategy_load( if (NULL == idle_strategy_name || NULL == idle_strategy_state) { - AERON_SET_ERR(EINVAL, "%s", "invalid idle strategy name or state"); + AERON_SET_ERR(EINVAL, "%s", "invalid idle object name or state"); return NULL; } - *idle_strategy_state = NULL; + aeron_idle_strategy_t *idle_strategy = aeron_symbol_table_obj_load( + aeron_idle_strategy_table, aeron_idle_strategy_table_length, idle_strategy_name, "idle strategy"); - if (strncmp(idle_strategy_name, "sleep-ns", strlen("sleep-ns")) == 0 || - strncmp(idle_strategy_name, "sleeping", strlen("sleeping")) == 0) - { - return aeron_idle_strategy_load("aeron_idle_strategy_sleeping", idle_strategy_state, env_var, init_args); - } - else if (strncmp(idle_strategy_name, "yield", strlen("yield")) == 0) + if (NULL == idle_strategy) { - return aeron_idle_strategy_load("aeron_idle_strategy_yielding", idle_strategy_state, env_var, init_args); - } - else if (strncmp(idle_strategy_name, "spin", strlen("spin")) == 0) - { - return aeron_idle_strategy_load("aeron_idle_strategy_busy_spinning", idle_strategy_state, env_var, init_args); - } - else if (strncmp(idle_strategy_name, "noop", strlen("noop")) == 0) - { - return aeron_idle_strategy_load("aeron_idle_strategy_noop", idle_strategy_state, env_var, init_args); - } - else if (strncmp(idle_strategy_name, "backoff", strlen("backoff")) == 0) - { - return aeron_idle_strategy_load("aeron_idle_strategy_backoff", idle_strategy_state, env_var, init_args); + AERON_APPEND_ERR("%s", ""); + return NULL; } - else - { - char idle_func_name[AERON_MAX_PATH] = { 0 }; - aeron_idle_strategy_t *idle_strategy = NULL; - snprintf(idle_func_name, sizeof(idle_func_name) - 1, "%s", idle_strategy_name); - if ((idle_strategy = (aeron_idle_strategy_t *)aeron_dlsym(RTLD_DEFAULT, idle_func_name)) == NULL) - { - AERON_SET_ERR(EINVAL, "could not find idle strategy %s: dlsym - %s", idle_func_name, aeron_dlerror()); - return NULL; - } - idle_func = idle_strategy->idle; - aeron_idle_strategy_init_func_t idle_init_func = idle_strategy->init; - - void *idle_state = NULL; - if (idle_init_func(&idle_state, env_var, init_args) < 0) - { - return NULL; - } + *idle_strategy_state = NULL; + idle_func = idle_strategy->idle; + aeron_idle_strategy_init_func_t idle_init_func = idle_strategy->init; - *idle_strategy_state = idle_state; + void *idle_state = NULL; + if (idle_init_func(&idle_state, env_var, init_args) < 0) + { + return NULL; } + *idle_strategy_state = idle_state; + return idle_func; } aeron_agent_on_start_func_t aeron_agent_on_start_load(const char *name) { aeron_agent_on_start_func_t func = NULL; -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - if ((func = (aeron_agent_on_start_func_t)aeron_dlsym(RTLD_DEFAULT, name)) == NULL) + + if ((*(void **)(&func) = aeron_dlsym(RTLD_DEFAULT, name)) == NULL) { AERON_SET_ERR(EINVAL, "could not find agent on_start func %s: dlsym - %s", name, aeron_dlerror()); return NULL; } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif return func; } diff --git a/aeron-client/src/main/c/aeron_common.h b/aeron-client/src/main/c/aeron_common.h index 9c21de3f34..fad3274ca7 100644 --- a/aeron-client/src/main/c/aeron_common.h +++ b/aeron-client/src/main/c/aeron_common.h @@ -33,4 +33,6 @@ uint8_t aeron_semantic_version_minor(int32_t version); uint8_t aeron_semantic_version_patch(int32_t version); +typedef void (*aeron_fptr_t)(void); + #endif //AERON_COMMON_H diff --git a/aeron-client/src/main/c/util/aeron_dlopen.c b/aeron-client/src/main/c/util/aeron_dlopen.c index 15f6da99c7..469095eb72 100644 --- a/aeron-client/src/main/c/util/aeron_dlopen.c +++ b/aeron-client/src/main/c/util/aeron_dlopen.c @@ -45,6 +45,19 @@ const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_lengt return buffer; } +const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length) +{ +#if defined(AERON_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + void *addr = (void *)func; +#if defined(AERON_COMPILER_GCC) +#pragma GCC diagnostic pop +#endif + return aeron_dlinfo(addr, buffer, max_buffer_length); +} + #elif defined(AERON_COMPILER_MSVC) #include "concurrent/aeron_counters_manager.h" @@ -158,6 +171,12 @@ char *aeron_dlerror() return messageBuffer; } +const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length) +{ + buffer[0] = '\0'; + return buffer; +} + const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_length) { buffer[0] = '\0'; diff --git a/aeron-client/src/main/c/util/aeron_dlopen.h b/aeron-client/src/main/c/util/aeron_dlopen.h index c9ceb4419a..2657636b00 100644 --- a/aeron-client/src/main/c/util/aeron_dlopen.h +++ b/aeron-client/src/main/c/util/aeron_dlopen.h @@ -28,7 +28,8 @@ #define aeron_dlopen(x) dlopen(x, RTLD_LAZY | RTLD_GLOBAL) #define aeron_dlerror dlerror -const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_length); +const char *aeron_dlinfo(const void *, char *buffer, size_t max_buffer_length); +const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length); #elif defined(AERON_COMPILER_MSVC) @@ -39,6 +40,7 @@ void *aeron_dlsym(void *module, const char *name); void *aeron_dlopen(const char *filename); char *aeron_dlerror(); const char *aeron_dlinfo(const void *addr, char *buffer, size_t max_buffer_length); +const char *aeron_dlinfo_func(void (*func)(void), char *buffer, size_t max_buffer_length); #else #error Unsupported platform! diff --git a/aeron-client/src/main/c/util/aeron_strutil.c b/aeron-client/src/main/c/util/aeron_strutil.c index 0af361c069..e52e1a34f3 100644 --- a/aeron-client/src/main/c/util/aeron_strutil.c +++ b/aeron-client/src/main/c/util/aeron_strutil.c @@ -263,3 +263,4 @@ int getopt(int argc, char *const argv[], const char *opt_string) #endif extern uint64_t aeron_fnv_64a_buf(uint8_t *buf, size_t len); +extern bool aeron_str_length(const char *str, size_t length_bound, size_t *length); diff --git a/aeron-client/src/main/c/util/aeron_strutil.h b/aeron-client/src/main/c/util/aeron_strutil.h index d47b30b58b..b2d502ebe9 100644 --- a/aeron-client/src/main/c/util/aeron_strutil.h +++ b/aeron-client/src/main/c/util/aeron_strutil.h @@ -19,6 +19,7 @@ #include #include +#include void aeron_format_date(char *str, size_t count, int64_t timestamp); @@ -78,4 +79,40 @@ AERON_EXPORT extern int optind; int getopt(int argc, char *const argv[], const char *opt_string); #endif +/** + * Checks that the string length is strictly less than the specified bound. + * + * @param str String to be compared. + * @param length_bound Limit to the length of the string being checked. + * @param length Out parameter for the actual length of the string (if non-null and less than length_bound). + * NULL values for this parameter are permitted. If str is NULL this value is unmodified. If + * the function returns false, the value is also unmodified. + * @return true if less than the specified bound, NULL is always true. + */ +inline bool aeron_str_length(const char *str, size_t length_bound, size_t *length) +{ + if (NULL == str) + { + return true; + } + + size_t i = 0; + bool result = false; + for (; i < length_bound; i++) + { + if ('\0' == str[i]) + { + result = true; + break; + } + } + + if (result && NULL != length) + { + *length = i; + } + + return result; +} + #endif //AERON_STRUTIL_H diff --git a/aeron-client/src/main/c/util/aeron_symbol_table.c b/aeron-client/src/main/c/util/aeron_symbol_table.c new file mode 100644 index 0000000000..e8ff6d1bd8 --- /dev/null +++ b/aeron-client/src/main/c/util/aeron_symbol_table.c @@ -0,0 +1,162 @@ +/* + * Copyright 2014-2021 Real Logic Limited. + * + * 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 + * + * https://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. + */ + +#if defined(__linux__) +#define _BSD_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include + +#include "util/aeron_dlopen.h" +#include "util/aeron_error.h" +#include "util/aeron_strutil.h" +#include "aeron_symbol_table.h" + + +static void* aeron_symbol_table_obj_scan(const aeron_symbol_table_obj_t *table, size_t table_size, const char *symbol) +{ + void* result = NULL; + + for (size_t i = 0; i < table_size; i++) + { + const char *alias = table[(int)i].alias; + const char *name = table[(int)i].name; + + if (NULL == alias || NULL == name) + { + break; + } + + if (0 == strncmp(alias, symbol, AERON_SYMBOL_TABLE_NAME_MAX_LENGTH + 1) || + 0 == strncmp(name, symbol, AERON_SYMBOL_TABLE_NAME_MAX_LENGTH + 1)) + { + result = table[i].object; + break; + } + } + + return result; +} + +void* aeron_symbol_table_obj_load( + const aeron_symbol_table_obj_t *table, size_t table_length, const char *name, const char *component_name) +{ + if (NULL == name) + { + AERON_SET_ERR(EINVAL, "%s", "name must not be null"); + return NULL; + } + + if (NULL == component_name) + { + AERON_SET_ERR(EINVAL, "%s", "component_name must not be null"); + return NULL; + } + + if (!aeron_str_length(name, AERON_SYMBOL_TABLE_NAME_MAX_LENGTH + 1, NULL)) + { + AERON_SET_ERR(EINVAL, "name must not exceed %d characters", AERON_SYMBOL_TABLE_NAME_MAX_LENGTH); + return NULL; + } + + void *obj = aeron_symbol_table_obj_scan(table, table_length, name); + if (NULL == obj) + { + char copied_name[AERON_MAX_PATH] = { 0 }; + + snprintf(copied_name, sizeof(copied_name) - 1, "%s", name); + obj = aeron_dlsym(RTLD_DEFAULT, copied_name); + } + + if (NULL == obj) + { + AERON_SET_ERR(EINVAL, "could not find %s object %s: dlsym - %s", component_name, name, aeron_dlerror()); + return NULL; + } + + return obj; +} + + +static aeron_fptr_t aeron_symbol_table_func_scan( + const aeron_symbol_table_func_t *table, size_t table_length, const char *symbol) +{ + aeron_fptr_t result = NULL; + + for (size_t i = 0; i < table_length; i++) + { + const char *alias = table[(int)i].alias; + const char *name = table[(int)i].name; + + if (NULL == alias || NULL == name) + { + break; + } + + if (0 == strncmp(alias, symbol, AERON_SYMBOL_TABLE_NAME_MAX_LENGTH + 1) || + 0 == strncmp(name, symbol, AERON_SYMBOL_TABLE_NAME_MAX_LENGTH + 1)) + { + result = table[i].function; + break; + } + } + + return result; +} + +aeron_fptr_t aeron_symbol_table_func_load( + const aeron_symbol_table_func_t *table, + size_t table_length, + const char *name, + const char *component_name) +{ + if (NULL == name) + { + AERON_SET_ERR(EINVAL, "%s", "name must not be null"); + return NULL; + } + + if (NULL == component_name) + { + AERON_SET_ERR(EINVAL, "%s", "component_name must not be null"); + return NULL; + } + + if (!aeron_str_length(name, AERON_SYMBOL_TABLE_NAME_MAX_LENGTH + 1, NULL)) + { + AERON_SET_ERR(EINVAL, "name must not exceed %d characters", AERON_SYMBOL_TABLE_NAME_MAX_LENGTH); + return NULL; + } + + aeron_fptr_t func = aeron_symbol_table_func_scan(table, table_length, name); + + if (NULL == func) + { + *(void **)(&func) = aeron_dlsym(RTLD_DEFAULT, name); + } + + if (NULL == func) + { + AERON_SET_ERR(EINVAL, "could not find %s %s: dlsym - %s", component_name, name, aeron_dlerror()); + } + + return func; +} diff --git a/aeron-client/src/main/c/util/aeron_symbol_table.h b/aeron-client/src/main/c/util/aeron_symbol_table.h new file mode 100644 index 0000000000..b15c2deefe --- /dev/null +++ b/aeron-client/src/main/c/util/aeron_symbol_table.h @@ -0,0 +1,49 @@ +/* + * Copyright 2014-2021 Real Logic Limited. + * + * 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 + * + * https://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. + */ + +#ifndef AERON_SYMBOL_TABLE_H +#define AERON_SYMBOL_TABLE_H + +#include "aeron_common.h" + +#define AERON_SYMBOL_TABLE_NAME_MAX_LENGTH (1023) + +struct aeron_symbol_table_obj_stct +{ + const char *alias; + const char *name; + void *object; +}; +typedef struct aeron_symbol_table_obj_stct aeron_symbol_table_obj_t; + +void* aeron_symbol_table_obj_load( + const aeron_symbol_table_obj_t *table, size_t table_length, const char *name, const char *component_name); + +struct aeron_symbol_table_func_stct +{ + const char *alias; + const char *name; + aeron_fptr_t function; +}; +typedef struct aeron_symbol_table_func_stct aeron_symbol_table_func_t; + +aeron_fptr_t aeron_symbol_table_func_load( + const aeron_symbol_table_func_t *table, + size_t table_length, + const char *name, + const char *component_name); + +#endif // AERON_SYMBOL_TABLE_H diff --git a/aeron-client/src/test/c/CMakeLists.txt b/aeron-client/src/test/c/CMakeLists.txt index 31bbabbdf4..4b131e4157 100644 --- a/aeron-client/src/test/c/CMakeLists.txt +++ b/aeron-client/src/test/c/CMakeLists.txt @@ -63,3 +63,4 @@ aeron_c_client_test(math_test util/aeron_math_test.cpp) aeron_c_client_test(strutil_test util/aeron_strutil_test.cpp) aeron_c_client_test(error_test util/aeron_error_test.cpp) aeron_c_client_test(netutil_test util/aeron_netutil_test.cpp) +aeron_c_client_test(symbol_table_test util/aeron_symbol_table_test.cpp) diff --git a/aeron-client/src/test/c/util/aeron_strutil_test.cpp b/aeron-client/src/test/c/util/aeron_strutil_test.cpp index a80ffc7418..a5e256b8ed 100644 --- a/aeron-client/src/test/c/util/aeron_strutil_test.cpp +++ b/aeron-client/src/test/c/util/aeron_strutil_test.cpp @@ -136,3 +136,35 @@ TEST_F(StrUtilTest, shouldHandleNull) EXPECT_EQ(num_tokens, -EINVAL); } + +TEST_F(StrUtilTest, checkStringLength) +{ + size_t length_initial_value = 1; + const char str1[] = {'h', 'e', 'l', 'l', 'o', '\0'}; + EXPECT_FALSE(aeron_str_length(str1, 5, nullptr)); + EXPECT_TRUE(aeron_str_length(str1, 6, nullptr)); + + size_t length = length_initial_value; + EXPECT_FALSE(aeron_str_length(str1, 5, &length)); + EXPECT_EQ(length_initial_value, length); + + length = length_initial_value; + EXPECT_TRUE(aeron_str_length(str1, 6, &length)); + EXPECT_EQ(5U, length); +} + +TEST_F(StrUtilTest, checkStringLengthEmptyAndNull) +{ + size_t length_initial_value = 1; + const char* str1 = ""; + EXPECT_TRUE(aeron_str_length(str1, 5, nullptr)); + EXPECT_TRUE(aeron_str_length(nullptr, 5, nullptr)); + + size_t length = length_initial_value; + EXPECT_TRUE(aeron_str_length(str1, 5, &length)); + EXPECT_EQ(0U, length); + + length = length_initial_value; + EXPECT_TRUE(aeron_str_length(nullptr, 5, &length)); + EXPECT_EQ(length_initial_value, length); +} diff --git a/aeron-client/src/test/c/util/aeron_symbol_table_test.cpp b/aeron-client/src/test/c/util/aeron_symbol_table_test.cpp new file mode 100644 index 0000000000..b63f4aa2fb --- /dev/null +++ b/aeron-client/src/test/c/util/aeron_symbol_table_test.cpp @@ -0,0 +1,82 @@ +/* + * Copyright 2014-2021 Real Logic Limited. + * + * 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 + * + * https://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. + */ + +#include + +extern "C" +{ +#include "util/aeron_symbol_table.h" +} +#undef max + +class SymbolTableTest : public testing::Test +{ +public: + SymbolTableTest() = default; +}; + +void foo_function() +{ + +} + +void bar_function() +{ + +} + +const char *foo_object = "hello world"; +const char *bar_object = "hello fairyland"; + +aeron_symbol_table_func_t test_function_table[] + { + { "foo", "foo_function", foo_function }, + { "bar", "bar_function", bar_function }, + }; +static const size_t test_func_table_length = sizeof(test_function_table) / sizeof(aeron_symbol_table_func_t); + +aeron_symbol_table_obj_t test_obj_table[] + { + { "foo", "foo_object", (void *)foo_object }, + { "bar", "bar_object", (void *)bar_object }, + }; + +static const size_t test_obj_table_length = sizeof(test_obj_table) / sizeof(aeron_symbol_table_obj_t); + +TEST_F(SymbolTableTest, shouldFindObjects) +{ + EXPECT_EQ(foo_object, aeron_symbol_table_obj_load(test_obj_table, test_obj_table_length, "foo", "object table")); + EXPECT_EQ(foo_object, aeron_symbol_table_obj_load( + test_obj_table, test_obj_table_length, "foo_object", "object table")); + EXPECT_EQ(bar_object, aeron_symbol_table_obj_load(test_obj_table, test_obj_table_length, "bar", "object table")); + EXPECT_EQ(bar_object, aeron_symbol_table_obj_load( + test_obj_table, test_obj_table_length, "bar_object", "object table")); + EXPECT_EQ(nullptr, aeron_symbol_table_obj_load(test_obj_table, test_obj_table_length, "baz", "object table")); +} + +TEST_F(SymbolTableTest, shouldFindFunctionPointers) +{ + EXPECT_EQ(foo_function, aeron_symbol_table_func_load( + test_function_table, test_func_table_length, "foo", "function table")); + EXPECT_EQ(foo_function, aeron_symbol_table_func_load( + test_function_table, test_func_table_length, "foo_function", "function table")); + EXPECT_EQ(bar_function, aeron_symbol_table_func_load( + test_function_table, test_func_table_length, "bar", "function table")); + EXPECT_EQ(bar_function, aeron_symbol_table_func_load( + test_function_table, test_func_table_length, "bar_function", "function table")); + EXPECT_EQ(nullptr, aeron_symbol_table_func_load( + test_function_table, test_func_table_length, "baz", "function table")); +} diff --git a/aeron-driver/src/main/c/CMakeLists.txt b/aeron-driver/src/main/c/CMakeLists.txt index b2ec7f0b22..993c4f4a30 100644 --- a/aeron-driver/src/main/c/CMakeLists.txt +++ b/aeron-driver/src/main/c/CMakeLists.txt @@ -155,6 +155,7 @@ SET(C_CLIENT_SOURCE ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_parse_util.c ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_properties_util.c ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_strutil.c + ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_symbol_table.c ${AERON_C_CLIENT_SOURCE_PATH}/uri/aeron_uri.c ${AERON_C_CLIENT_SOURCE_PATH}/aeron_agent.c ${AERON_C_CLIENT_SOURCE_PATH}/aeron_alloc.c @@ -224,6 +225,7 @@ set(C_CLIENT_HEADERS ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_platform.h ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_properties_util.h ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_strutil.h + ${AERON_C_CLIENT_SOURCE_PATH}/util/aeron_symbol_table.h ${AERON_C_CLIENT_SOURCE_PATH}/aeron_agent.h ${AERON_C_CLIENT_SOURCE_PATH}/aeron_alloc.h ${AERON_C_CLIENT_SOURCE_PATH}/aeron_client.h @@ -366,7 +368,7 @@ target_link_libraries( target_link_libraries( aeronmd - aeron_driver + aeron_driver_static ${CMAKE_DL_LIBS} ${AERON_LIB_BSD_LIBS} ${AERON_LIB_UUID_LIBS} diff --git a/aeron-driver/src/main/c/aeron_congestion_control.c b/aeron-driver/src/main/c/aeron_congestion_control.c index d72d848fdf..50e6090e8a 100644 --- a/aeron-driver/src/main/c/aeron_congestion_control.c +++ b/aeron-driver/src/main/c/aeron_congestion_control.c @@ -23,7 +23,7 @@ #include #include "util/aeron_parse_util.h" #include "util/aeron_error.h" -#include "util/aeron_dlopen.h" +#include "util/aeron_symbol_table.h" #include "aeron_congestion_control.h" #include "aeron_alloc.h" #include "aeron_driver_context.h" @@ -38,27 +38,33 @@ #define AERON_CUBICCONGESTIONCONTROL_B (0.2) #define AERON_CUBICCONGESTIONCONTROL_RTT_TIMEOUT_MULTIPLE (4) -aeron_congestion_control_strategy_supplier_func_t aeron_congestion_control_strategy_supplier_load( - const char *strategy_name) -{ - aeron_congestion_control_strategy_supplier_func_t func = NULL; - -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - if ((func = (aeron_congestion_control_strategy_supplier_func_t)aeron_dlsym(RTLD_DEFAULT, strategy_name)) == NULL) +static const aeron_symbol_table_func_t aeron_congestion_control_table[] = { - AERON_SET_ERR( - EINVAL, "could not find congestion control strategy %s: dlsym - %s", strategy_name, aeron_dlerror()); + { + "default", + "aeron_congestion_control_default_strategy_supplier", + (aeron_fptr_t)aeron_congestion_control_default_strategy_supplier + }, + { + "static", + "aeron_static_window_congestion_control_strategy_supplier", + (aeron_fptr_t)aeron_static_window_congestion_control_strategy_supplier + }, + { + "cubic", + "aeron_cubic_congestion_control_strategy_supplier", + (aeron_fptr_t)aeron_cubic_congestion_control_strategy_supplier + }, + }; - return NULL; - } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif +static const size_t aeron_congestion_control_table_length = + sizeof(aeron_congestion_control_table) / sizeof(aeron_symbol_table_func_t); - return func; +aeron_congestion_control_strategy_supplier_func_t aeron_congestion_control_strategy_supplier_load( + const char *strategy_name) +{ + return (aeron_congestion_control_strategy_supplier_func_t)aeron_symbol_table_func_load( + aeron_congestion_control_table, aeron_congestion_control_table_length, strategy_name, "congestion control"); } struct aeron_static_window_congestion_control_strategy_state_stct diff --git a/aeron-driver/src/main/c/aeron_driver.c b/aeron-driver/src/main/c/aeron_driver.c index db7728fa3e..d1e27faee0 100644 --- a/aeron-driver/src/main/c/aeron_driver.c +++ b/aeron-driver/src/main/c/aeron_driver.c @@ -542,83 +542,63 @@ void aeron_driver_context_print_configuration(aeron_driver_context_t *context) fprintf(fpout, "\n loss_report_length=%" PRIu64, (uint64_t)context->loss_report_length); fprintf(fpout, "\n send_to_sm_poll_ratio=%" PRIu64, (uint64_t)context->send_to_sm_poll_ratio); -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - - fprintf(fpout, "\n epoch_clock=%p%s", - (void *)context->epoch_clock, - aeron_dlinfo((const void *)context->epoch_clock, buffer, sizeof(buffer))); - fprintf(fpout, "\n nano_clock=%p%s", - (void *)context->nano_clock, - aeron_dlinfo((const void *)context->nano_clock, buffer, sizeof(buffer))); + fprintf(fpout, "\n epoch_clock=%s", + aeron_dlinfo_func((aeron_fptr_t)context->epoch_clock, buffer, sizeof(buffer))); + fprintf(fpout, "\n nano_clock=%s", + aeron_dlinfo_func((aeron_fptr_t)context->nano_clock, buffer, sizeof(buffer))); /* cachedEpochClock */ /* cachedNanoClock */ fprintf(fpout, "\n threading_mode=%d", context->threading_mode); - fprintf(fpout, "\n agent_on_start_func=%p%s", - (void *)context->agent_on_start_func, - aeron_dlinfo((const void *)context->agent_on_start_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n agent_on_start_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->agent_on_start_func, buffer, sizeof(buffer))); fprintf(fpout, "\n agent_on_start_state=%p", context->agent_on_start_state); - fprintf(fpout, "\n conductor_idle_strategy_func=%p%s", - (void *)context->conductor_idle_strategy_func, - aeron_dlinfo((const void *)context->conductor_idle_strategy_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n conductor_idle_strategy_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->conductor_idle_strategy_func, buffer, sizeof(buffer))); fprintf(fpout, "\n conductor_idle_strategy_init_args=%p%s", (void *)context->conductor_idle_strategy_init_args, context->conductor_idle_strategy_init_args ? context->conductor_idle_strategy_init_args : ""); - fprintf(fpout, "\n sender_idle_strategy_func=%p%s", - (void *)context->sender_idle_strategy_func, - aeron_dlinfo((const void *)context->sender_idle_strategy_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n sender_idle_strategy_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->sender_idle_strategy_func, buffer, sizeof(buffer))); fprintf(fpout, "\n sender_idle_strategy_init_args=%p%s", (void *)context->sender_idle_strategy_init_args, context->sender_idle_strategy_init_args ? context->sender_idle_strategy_init_args : ""); - fprintf(fpout, "\n receiver_idle_strategy_func=%p%s", - (void *)context->receiver_idle_strategy_func, - aeron_dlinfo((const void *)context->receiver_idle_strategy_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n receiver_idle_strategy_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->receiver_idle_strategy_func, buffer, sizeof(buffer))); fprintf(fpout, "\n receiver_idle_strategy_init_args=%p%s", (void *)context->receiver_idle_strategy_init_args, context->receiver_idle_strategy_init_args ? context->receiver_idle_strategy_init_args : ""); - fprintf(fpout, "\n shared_network_idle_strategy_func=%p%s", - (void *)context->shared_network_idle_strategy_func, - aeron_dlinfo((const void *)context->shared_network_idle_strategy_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n shared_network_idle_strategy_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->shared_network_idle_strategy_func, buffer, sizeof(buffer))); fprintf(fpout, "\n shared_network_idle_strategy_init_args=%p%s", (void *)context->shared_network_idle_strategy_init_args, context->shared_network_idle_strategy_init_args ? context->shared_network_idle_strategy_init_args : ""); - fprintf(fpout, "\n shared_idle_strategy_func=%p%s", - (void *)context->shared_idle_strategy_func, - aeron_dlinfo((const void *)context->shared_idle_strategy_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n shared_idle_strategy_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->shared_idle_strategy_func, buffer, sizeof(buffer))); fprintf(fpout, "\n shared_idle_strategy_init_args=%p%s", (void *)context->shared_idle_strategy_init_args, context->shared_idle_strategy_init_args ? context->shared_idle_strategy_init_args : ""); - fprintf(fpout, "\n unicast_flow_control_supplier_func=%p%s", - (void *)context->unicast_flow_control_supplier_func, - aeron_dlinfo((const void *)context->unicast_flow_control_supplier_func, buffer, sizeof(buffer))); - fprintf(fpout, "\n multicast_flow_control_supplier_func=%p%s", - (void *)context->multicast_flow_control_supplier_func, - aeron_dlinfo((const void *)context->multicast_flow_control_supplier_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n unicast_flow_control_supplier_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->unicast_flow_control_supplier_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n multicast_flow_control_supplier_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->multicast_flow_control_supplier_func, buffer, sizeof(buffer))); fprintf(fpout, "\n receiver_group_tag.is_present=%d", context->receiver_group_tag.is_present); fprintf(fpout, "\n receiver_group_tag.value=%" PRId64, context->receiver_group_tag.value); fprintf(fpout, "\n flow_control.group_tag=%" PRId64, context->flow_control.group_tag); fprintf(fpout, "\n flow_control.group_min_size=%" PRId32, context->flow_control.group_min_size); fprintf(fpout, "\n flow_control_receiver_timeout_ns=%" PRIu64, context->flow_control.receiver_timeout_ns); - fprintf(fpout, "\n congestion_control_supplier_func=%p%s", - (void *)context->congestion_control_supplier_func, - aeron_dlinfo((const void *)context->congestion_control_supplier_func, buffer, sizeof(buffer))); - fprintf(fpout, "\n usable_fs_space_func=%p%s", - (void *)context->usable_fs_space_func, - aeron_dlinfo((const void *)context->usable_fs_space_func, buffer, sizeof(buffer))); - fprintf(fpout, "\n termination_validator_func=%p%s", - (void *)context->termination_validator_func, - aeron_dlinfo((const void *)context->termination_validator_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n congestion_control_supplier_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->congestion_control_supplier_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n usable_fs_space_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->usable_fs_space_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n termination_validator_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->termination_validator_func, buffer, sizeof(buffer))); fprintf(fpout, "\n termination_validator_state=%p", context->termination_validator_state); - fprintf(fpout, "\n termination_hook_func=%p%s", - (void *)context->termination_hook_func, - aeron_dlinfo((const void *)context->termination_hook_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n termination_hook_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->termination_hook_func, buffer, sizeof(buffer))); fprintf(fpout, "\n termination_hook_state=%p", context->termination_hook_state); - fprintf(fpout, "\n name_resolver_supplier_func=%p%s", - (void *)context->name_resolver_supplier_func, - aeron_dlinfo((const void *)context->name_resolver_supplier_func, buffer, sizeof(buffer))); + fprintf(fpout, "\n name_resolver_supplier_func=%s", + aeron_dlinfo_func((aeron_fptr_t)context->name_resolver_supplier_func, buffer, sizeof(buffer))); fprintf(fpout, "\n name_resolver_init_args=%s", (void *)context->name_resolver_init_args ? context->name_resolver_init_args : ""); fprintf(fpout, "\n resolver_name=%s", @@ -647,7 +627,7 @@ void aeron_driver_context_print_configuration(aeron_driver_context_t *context) fpout, "\n conductor_udp_channel_transport_bindings.%s=%s,%p%s", conductor_bindings->meta_info.type, conductor_bindings->meta_info.name, - conductor_bindings->meta_info.source_symbol, + bindings->meta_info.source_symbol, aeron_dlinfo(conductor_bindings->meta_info.source_symbol, buffer, sizeof(buffer))); } @@ -657,11 +637,10 @@ void aeron_driver_context_print_configuration(aeron_driver_context_t *context) while (NULL != interceptor_bindings) { fprintf( - fpout, "\n udp_channel_outgoing_interceptor_bindings.%s=%s,%p%s", + fpout, "\n udp_channel_outgoing_interceptor_bindings.%s=%s,%s", interceptor_bindings->meta_info.type, interceptor_bindings->meta_info.name, - interceptor_bindings->meta_info.source_symbol, - aeron_dlinfo(interceptor_bindings->meta_info.source_symbol, buffer, sizeof(buffer))); + aeron_dlinfo_func(interceptor_bindings->meta_info.source_symbol, buffer, sizeof(buffer))); interceptor_bindings = interceptor_bindings->meta_info.next_interceptor_bindings; } @@ -670,19 +649,14 @@ void aeron_driver_context_print_configuration(aeron_driver_context_t *context) while (NULL != interceptor_bindings) { fprintf( - fpout, "\n udp_channel_incoming_interceptor_bindings.%s=%s,%p%s", + fpout, "\n udp_channel_incoming_interceptor_bindings.%s=%s,%s", interceptor_bindings->meta_info.type, interceptor_bindings->meta_info.name, - interceptor_bindings->meta_info.source_symbol, - aeron_dlinfo(interceptor_bindings->meta_info.source_symbol, buffer, sizeof(buffer))); + aeron_dlinfo_func(interceptor_bindings->meta_info.source_symbol, buffer, sizeof(buffer))); interceptor_bindings = interceptor_bindings->meta_info.next_interceptor_bindings; } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif - fprintf(fpout, "\n}\n"); } diff --git a/aeron-driver/src/main/c/aeron_driver_name_resolver.h b/aeron-driver/src/main/c/aeron_driver_name_resolver.h index 98aeaad0b4..2e2ecb5dd4 100644 --- a/aeron-driver/src/main/c/aeron_driver_name_resolver.h +++ b/aeron-driver/src/main/c/aeron_driver_name_resolver.h @@ -24,6 +24,8 @@ #define AERON_COUNTER_NAME_RESOLVER_CACHE_ENTRIES_COUNTER_TYPE_ID (16) #include "protocol/aeron_udp_protocol.h" +#include "aeronmd.h" +#include "aeron_name_resolver_cache.h" int aeron_driver_name_resolver_set_resolution_header( aeron_resolution_header_t *resolution_header, @@ -41,4 +43,7 @@ int aeron_driver_name_resolver_set_resolution_header_from_sockaddr( const char *name, size_t name_length); +int aeron_driver_name_resolver_supplier( + aeron_name_resolver_t *resolver, const char *args, aeron_driver_context_t *context); + #endif //AERON_NAME_RESOLVER_DRIVER_H diff --git a/aeron-driver/src/main/c/aeron_flow_control.c b/aeron-driver/src/main/c/aeron_flow_control.c index 42e40c7412..e863b31a4c 100644 --- a/aeron-driver/src/main/c/aeron_flow_control.c +++ b/aeron-driver/src/main/c/aeron_flow_control.c @@ -23,29 +23,42 @@ #include #include "media/aeron_udp_channel.h" #include "util/aeron_error.h" -#include "util/aeron_dlopen.h" #include "util/aeron_parse_util.h" +#include "util/aeron_symbol_table.h" #include "aeron_alloc.h" #include "aeron_flow_control.h" -aeron_flow_control_strategy_supplier_func_t aeron_flow_control_strategy_supplier_load(const char *strategy_name) -{ - aeron_flow_control_strategy_supplier_func_t func = NULL; - -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - if ((func = (aeron_flow_control_strategy_supplier_func_t)aeron_dlsym(RTLD_DEFAULT, strategy_name)) == NULL) +aeron_symbol_table_func_t aeron_flow_control_strategy_table[] = { - AERON_SET_ERR(EINVAL, "could not find flow control strategy %s: dlsym - %s", strategy_name, aeron_dlerror()); - return NULL; - } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif + { + AERON_UNICAST_MAX_FLOW_CONTROL_STRATEGY_NAME, + "aeron_unicast_flow_control_strategy_supplier", + (aeron_fptr_t)aeron_unicast_flow_control_strategy_supplier + }, + { + AERON_MULTICAST_MAX_FLOW_CONTROL_STRATEGY_NAME, + "aeron_max_multicast_flow_control_strategy_supplier", + (aeron_fptr_t)aeron_max_multicast_flow_control_strategy_supplier + }, + { + AERON_MULTICAST_MIN_FLOW_CONTROL_STRATEGY_NAME, + "aeron_min_flow_control_strategy_supplier", + (aeron_fptr_t)aeron_min_flow_control_strategy_supplier + }, + { + AERON_MULTICAST_TAGGED_FLOW_CONTROL_STRATEGY_NAME, + "aeron_tagged_flow_control_strategy_supplier", + (aeron_fptr_t)aeron_tagged_flow_control_strategy_supplier + } + }; - return func; +static const size_t aeron_flow_control_strategy_table_length = + sizeof(aeron_flow_control_strategy_table) / sizeof(aeron_symbol_table_func_t); + +aeron_flow_control_strategy_supplier_func_t aeron_flow_control_strategy_supplier_load(const char *strategy_name) +{ + return (aeron_flow_control_strategy_supplier_func_t)aeron_symbol_table_func_load( + aeron_flow_control_strategy_table, aeron_flow_control_strategy_table_length, strategy_name, "flow control"); } bool aeron_flow_control_strategy_has_required_receivers_default(aeron_flow_control_strategy_t *strategy) diff --git a/aeron-driver/src/main/c/aeron_name_resolver.c b/aeron-driver/src/main/c/aeron_name_resolver.c index bc6928bbea..26c3447127 100644 --- a/aeron-driver/src/main/c/aeron_name_resolver.c +++ b/aeron-driver/src/main/c/aeron_name_resolver.c @@ -27,7 +27,32 @@ #include "util/aeron_netutil.h" #include "util/aeron_dlopen.h" #include "util/aeron_strutil.h" +#include "util/aeron_symbol_table.h" #include "aeron_name_resolver.h" +#include "aeron_driver_name_resolver.h" +#include "aeron_csv_table_name_resolver.h" + +static const aeron_symbol_table_func_t aeron_name_resolver_table[] = + { + { + "default", + "aeron_default_name_resolver_supplier", + (aeron_fptr_t)aeron_default_name_resolver_supplier + }, + { + "driver", + "aeron_driver_name_resolver_supplier", + (aeron_fptr_t)aeron_driver_name_resolver_supplier + }, + { + "csv_table", + "aeron_csv_table_name_resolver_supplier", + (aeron_fptr_t)aeron_csv_table_name_resolver_supplier + } + }; + +static const size_t aeron_name_resolver_table_length = + sizeof(aeron_name_resolver_table) / sizeof(aeron_symbol_table_func_t); static void aeron_name_resolver_load_function_info( aeron_name_resolver_t *resolver, @@ -179,43 +204,8 @@ int aeron_name_resolver_resolve_host_and_port( aeron_name_resolver_supplier_func_t aeron_name_resolver_supplier_load(const char *name) { - aeron_name_resolver_supplier_func_t supplier_func; - - if (NULL == name) - { - AERON_SET_ERR(EINVAL, "%s", "invalid name_resolver supplier function name"); - return NULL; - } - - if (0 == strncmp(name, AERON_NAME_RESOLVER_SUPPLIER_DEFAULT, sizeof(AERON_NAME_RESOLVER_SUPPLIER_DEFAULT))) - { - supplier_func = aeron_default_name_resolver_supplier; - } - else if (0 == strncmp(name, AERON_NAME_RESOLVER_CSV_TABLE, sizeof(AERON_NAME_RESOLVER_CSV_TABLE))) - { - supplier_func = aeron_name_resolver_supplier_load("aeron_csv_table_name_resolver_supplier"); - } - else if (0 == strncmp(name, AERON_NAME_RESOLVER_DRIVER, sizeof(AERON_NAME_RESOLVER_DRIVER))) - { - supplier_func = aeron_name_resolver_supplier_load("aeron_driver_name_resolver_supplier"); - } - else - { -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - if ((supplier_func = (aeron_name_resolver_supplier_func_t)aeron_dlsym(RTLD_DEFAULT, name)) == NULL) - { - AERON_SET_ERR( - EINVAL, "could not find name resolver %s: dlsym - %s", name, aeron_dlerror()); - } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif - } - - return supplier_func; + return (aeron_name_resolver_supplier_func_t)aeron_symbol_table_func_load( + aeron_name_resolver_table, aeron_name_resolver_table_length, name, "name resolver"); } static void aeron_name_resolver_load_function_info( @@ -225,13 +215,6 @@ static void aeron_name_resolver_load_function_info( char *resolve_name_buffer, size_t resolve_name_buffer_len) { -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - aeron_dlinfo((const void *)resolver->lookup_func, lookup_name_buffer, lookup_name_buffer_len); - aeron_dlinfo((const void *)resolver->resolve_func, resolve_name_buffer, resolve_name_buffer_len); -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif + aeron_dlinfo_func((aeron_fptr_t)resolver->lookup_func, lookup_name_buffer, lookup_name_buffer_len); + aeron_dlinfo_func((aeron_fptr_t)resolver->resolve_func, resolve_name_buffer, resolve_name_buffer_len); } diff --git a/aeron-driver/src/main/c/aeron_termination_validator.c b/aeron-driver/src/main/c/aeron_termination_validator.c index 4a19493e87..8689617d16 100644 --- a/aeron-driver/src/main/c/aeron_termination_validator.c +++ b/aeron-driver/src/main/c/aeron_termination_validator.c @@ -22,9 +22,26 @@ #include #include #include "util/aeron_error.h" -#include "util/aeron_dlopen.h" +#include "util/aeron_symbol_table.h" #include "aeron_termination_validator.h" +static const aeron_symbol_table_func_t aeron_termination_validator_table[] = + { + { + "allow", + "aeron_driver_termination_validator_default_allow", + (aeron_fptr_t)aeron_driver_termination_validator_default_allow + }, + { + "deny", + "aeron_driver_termination_validator_default_deny", + (aeron_fptr_t)aeron_driver_termination_validator_default_deny + } + }; + +static const size_t aeron_termination_validator_table_length = + sizeof(aeron_termination_validator_table) / sizeof(aeron_symbol_table_func_t); + bool aeron_driver_termination_validator_default_allow(void *state, uint8_t *token_buffer, int32_t token_length) { return true; @@ -37,32 +54,9 @@ bool aeron_driver_termination_validator_default_deny(void *state, uint8_t *token aeron_driver_termination_validator_func_t aeron_driver_termination_validator_load(const char *validator_name) { - aeron_driver_termination_validator_func_t func = NULL; - - if (strncmp(validator_name, "allow", sizeof("allow")) == 0) - { - return aeron_driver_termination_validator_load("aeron_driver_termination_validator_default_allow"); - } - else if (strncmp(validator_name, "deny", sizeof("deny")) == 0) - { - return aeron_driver_termination_validator_load("aeron_driver_termination_validator_default_deny"); - } - else - { -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - if ((func = (aeron_driver_termination_validator_func_t)aeron_dlsym(RTLD_DEFAULT, validator_name)) == NULL) - { - AERON_SET_ERR( - EINVAL, "could not find termination validator %s: dlsym - %s", validator_name, aeron_dlerror()); - return NULL; - } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif - } - - return func; + return (aeron_driver_termination_validator_func_t)aeron_symbol_table_func_load( + aeron_termination_validator_table, + aeron_termination_validator_table_length, + validator_name, + "terminate validator"); } diff --git a/aeron-driver/src/main/c/agent/aeron_driver_agent.c b/aeron-driver/src/main/c/agent/aeron_driver_agent.c index 63daad21de..21c66a45be 100644 --- a/aeron-driver/src/main/c/agent/aeron_driver_agent.c +++ b/aeron-driver/src/main/c/agent/aeron_driver_agent.c @@ -31,7 +31,6 @@ #include "agent/aeron_driver_agent.h" #include "aeron_driver_context.h" -#include "util/aeron_dlopen.h" #include "aeron_alloc.h" #include "util/aeron_arrayutil.h" #include "aeron_windows.h" @@ -1011,7 +1010,7 @@ int aeron_driver_agent_init_logging_events_interceptors(aeron_driver_context_t * incoming_bindings->meta_info.name = "logging"; incoming_bindings->meta_info.type = "interceptor"; - incoming_bindings->meta_info.source_symbol = "aeron_driver_agent_context_init"; + incoming_bindings->meta_info.source_symbol = (aeron_fptr_t)aeron_driver_agent_context_init; incoming_bindings->meta_info.next_interceptor_bindings = NULL; if (NULL == context->udp_channel_incoming_interceptor_bindings) @@ -1056,7 +1055,7 @@ int aeron_driver_agent_init_logging_events_interceptors(aeron_driver_context_t * outgoing_bindings->meta_info.name = "logging"; outgoing_bindings->meta_info.type = "interceptor"; - outgoing_bindings->meta_info.source_symbol = "aeron_driver_agent_context_init"; + outgoing_bindings->meta_info.source_symbol = (aeron_fptr_t)aeron_driver_agent_context_init; outgoing_bindings->meta_info.next_interceptor_bindings = context->udp_channel_outgoing_interceptor_bindings; context->udp_channel_outgoing_interceptor_bindings = outgoing_bindings; diff --git a/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.c b/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.c index b19c639688..6322f1fb89 100644 --- a/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.c +++ b/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.c @@ -27,6 +27,8 @@ #include "util/aeron_error.h" #include "util/aeron_dlopen.h" #include "util/aeron_strutil.h" +#include "util/aeron_symbol_table.h" +#include "aeron_udp_channel_transport_loss.h" #include "aeron_udp_channel_transport_bindings.h" #include "aeron_udp_channel_transport.h" #include "aeron_udp_transport_poller.h" @@ -52,9 +54,37 @@ aeron_udp_channel_transport_bindings_t aeron_udp_channel_transport_bindings_defa } }; +static const aeron_symbol_table_obj_t aeron_udp_channel_transport_bindings_table[] = + { + { + "default", + "aeron_udp_channel_transport_bindings_default", + (void *)&aeron_udp_channel_transport_bindings_default + }, + }; + +static const size_t aeron_udp_channel_transport_bindings_table_length = + sizeof(aeron_udp_channel_transport_bindings_table) / sizeof (aeron_symbol_table_obj_t); + +static const aeron_symbol_table_func_t aeron_udp_channel_interceptor_table[] = + { + { + "loss", + "aeron_udp_channel_interceptor_loss_load", + (aeron_fptr_t)aeron_udp_channel_interceptor_loss_load + } + }; + +static const size_t aeron_udp_channel_interceptor_table_length = + sizeof(aeron_udp_channel_transport_bindings_table) / sizeof(aeron_symbol_table_func_t); + aeron_udp_channel_transport_bindings_t *aeron_udp_channel_transport_bindings_load_media(const char *bindings_name) { - aeron_udp_channel_transport_bindings_t *bindings = NULL; + aeron_udp_channel_transport_bindings_t *bindings = aeron_symbol_table_obj_load( + aeron_udp_channel_transport_bindings_table, + aeron_udp_channel_transport_bindings_table_length, + bindings_name, + "udp channel bindings"); if (NULL == bindings_name) { @@ -62,20 +92,7 @@ aeron_udp_channel_transport_bindings_t *aeron_udp_channel_transport_bindings_loa return NULL; } - if (strncmp(bindings_name, "default", sizeof("default")) == 0) - { - return aeron_udp_channel_transport_bindings_load_media("aeron_udp_channel_transport_bindings_default"); - } - else - { - if ((bindings = (aeron_udp_channel_transport_bindings_t *)aeron_dlsym(RTLD_DEFAULT, bindings_name)) == NULL) - { - AERON_SET_ERR( - EINVAL, "could not find UDP channel transport bindings %s: dlsym - %s", bindings_name, aeron_dlerror()); - return NULL; - } - bindings->meta_info.source_symbol = bindings; - } + bindings->meta_info.source_symbol = bindings; return bindings; } @@ -83,38 +100,11 @@ aeron_udp_channel_transport_bindings_t *aeron_udp_channel_transport_bindings_loa static aeron_udp_channel_interceptor_bindings_load_func_t *aeron_udp_channel_interceptor_bindings_load_interceptor( const char *interceptor_name) { - aeron_udp_channel_interceptor_bindings_load_func_t *load_interceptor = NULL; - - if (NULL == interceptor_name) - { - return NULL; - } - - if (strncmp(interceptor_name, "loss", sizeof("loss")) == 0) - { - return aeron_udp_channel_interceptor_bindings_load_interceptor("aeron_udp_channel_interceptor_loss_load"); - } - else - { -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - if ((load_interceptor = (aeron_udp_channel_interceptor_bindings_load_func_t *)aeron_dlsym( - RTLD_DEFAULT, interceptor_name)) == NULL) - { - AERON_SET_ERR(EINVAL, - "could not find interceptor bindings %s: dlsym - %s", - interceptor_name, - aeron_dlerror()); - return NULL; - } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif - } - - return load_interceptor; + return (aeron_udp_channel_interceptor_bindings_load_func_t *)aeron_symbol_table_func_load( + aeron_udp_channel_interceptor_table, + aeron_udp_channel_interceptor_table_length, + interceptor_name, + "interceptor bindings"); } #define AERON_MAX_INTERCEPTORS_LEN (4094) @@ -177,14 +167,7 @@ aeron_udp_channel_interceptor_bindings_t *aeron_udp_channel_interceptor_bindings return NULL; } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - current_bindings->meta_info.source_symbol = (const void *)interceptor_load_func; -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif + current_bindings->meta_info.source_symbol = (aeron_fptr_t)interceptor_load_func; } return current_bindings; @@ -258,14 +241,7 @@ int aeron_udp_channel_data_paths_init( return -1; } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif outgoing_transport_interceptor->interceptor_state = media_bindings; -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif /* last interceptor calls sendmmsg_func/sendmsg_func from transport bindings */ outgoing_transport_interceptor->outgoing_mmsg_func = aeron_udp_channel_outgoing_interceptor_mmsg_to_transport; @@ -328,16 +304,18 @@ int aeron_udp_channel_data_paths_init( return -1; } -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - incoming_transport_interceptor->interceptor_state = (void *)recv_func; -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif + aeron_udp_channel_transport_recv_func_holder_t *recv_function_holder = NULL; + if (aeron_alloc( + (void **)&recv_function_holder, sizeof(aeron_udp_channel_transport_recv_func_holder_t)) < 0) + { + AERON_APPEND_ERR("%s", "Function holder for last incoming interceptor for UDP transport bindings"); + return -1; + } + recv_function_holder->func = recv_func; + + incoming_transport_interceptor->interceptor_state = recv_function_holder; incoming_transport_interceptor->incoming_func = aeron_udp_channel_incoming_interceptor_to_endpoint; - incoming_transport_interceptor->close_func = NULL; + incoming_transport_interceptor->close_func = aeron_udp_channel_transport_recv_func_holder_close; incoming_transport_interceptor->next_interceptor = NULL; last_incoming_interceptor->next_interceptor = incoming_transport_interceptor; data_paths->recv_func = aeron_udp_channel_incoming_interceptor_recv_func; @@ -383,6 +361,12 @@ int aeron_udp_channel_data_paths_delete(aeron_udp_channel_data_paths_t *data_pat return 0; } +int aeron_udp_channel_transport_recv_func_holder_close(void *holder) +{ + aeron_free(holder); + return 0; +} + extern int aeron_udp_channel_outgoing_interceptor_sendmmsg( aeron_udp_channel_data_paths_t *data_paths, aeron_udp_channel_transport_t *transport, diff --git a/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.h b/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.h index 8348802863..beeba16532 100644 --- a/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.h +++ b/aeron-driver/src/main/c/media/aeron_udp_channel_transport_bindings.h @@ -227,7 +227,7 @@ struct aeron_udp_channel_interceptor_bindings_stct const char *name; const char *type; const aeron_udp_channel_interceptor_bindings_t *next_interceptor_bindings; - const void *source_symbol; + void (*source_symbol)(void); } meta_info; }; @@ -264,6 +264,14 @@ struct aeron_udp_channel_data_paths_stct aeron_udp_transport_recv_func_t recv_func; }; +struct aeron_udp_channel_transport_recv_func_holder_stct +{ + aeron_udp_transport_recv_func_t func; +}; +typedef struct aeron_udp_channel_transport_recv_func_holder_stct aeron_udp_channel_transport_recv_func_holder_t; + +int aeron_udp_channel_transport_recv_func_holder_close(void *holder); + inline int aeron_udp_channel_outgoing_interceptor_sendmmsg( aeron_udp_channel_data_paths_t *data_paths, aeron_udp_channel_transport_t *transport, @@ -352,16 +360,10 @@ inline void aeron_udp_channel_incoming_interceptor_to_endpoint( struct sockaddr_storage *addr, struct timespec *media_timestamp) { -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#endif - aeron_udp_transport_recv_func_t recv_func = (aeron_udp_transport_recv_func_t)interceptor_state; -#if defined(AERON_COMPILER_GCC) -#pragma GCC diagnostic pop -#endif - - recv_func( + aeron_udp_channel_transport_recv_func_holder_t *recv_function_holder = + (aeron_udp_channel_transport_recv_func_holder_t *)interceptor_state; + + recv_function_holder->func( NULL, transport, receiver_clientd,