diff --git a/CMakeLists.txt b/CMakeLists.txt index 9662dcf..18c7807 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ add_dependencies(adc utils) add_dependencies(network utils) add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} ) +add_executable(test ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} ) add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c) add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c) @@ -83,15 +84,12 @@ if (SQLITE_SUPPORT) target_link_libraries(mod_auth_sqlite sqlite3 utils) target_link_libraries(uhub-passwd sqlite3 utils) set_target_properties(mod_auth_sqlite PROPERTIES PREFIX "") - - if (UNIX) - target_link_libraries(uhub pthread) - endif() endif() if(WIN32) target_link_libraries(uhub ws2_32) + target_link_libraries(test ws2_32) target_link_libraries(mod_logging ws2_32) target_link_libraries(mod_welcome ws2_32) endif() @@ -107,6 +105,7 @@ set_target_properties( PROPERTIES PREFIX "") target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils) +target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(mod_example utils) target_link_libraries(mod_welcome utils) target_link_libraries(mod_auth_simple utils) @@ -114,18 +113,20 @@ target_link_libraries(mod_chat_history utils) target_link_libraries(mod_chat_only utils) target_link_libraries(mod_logging utils) target_link_libraries(mod_topic utils) - +target_link_libraries(utils network) target_link_libraries(mod_welcome network) target_link_libraries(mod_logging network) if(UNIX) add_library(adcclient STATIC ${adcclient_SOURCES}) add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c) - target_link_libraries(uhub-admin adcclient adc network utils) + target_link_libraries(uhub-admin adcclient adc network utils pthread) + target_link_libraries(uhub pthread) + target_link_libraries(test pthread) if (ADC_STRESS) add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES}) - target_link_libraries(adcrush adcclient adc network utils) + target_link_libraries(adcrush adcclient adc network utils pthread) endif() endif() @@ -160,6 +161,7 @@ endif() if(SSL_SUPPORT) target_link_libraries(uhub ${SSL_LIBS}) + target_link_libraries(test ${SSL_LIBS}) if(UNIX) target_link_libraries(uhub-admin ${SSL_LIBS}) endif() diff --git a/autotest/exotic b/autotest/exotic new file mode 100755 index 0000000..d0338ef --- /dev/null +++ b/autotest/exotic @@ -0,0 +1,371 @@ +#!/usr/bin/perl -w +# exotic 0.4 +# Copyright (c) 2007-2012, Jan Vidar Krey + +use strict; + +my $program = $0; +my $file; +my $line; +my @tests; +my $found; +my $test; +my @files; + +if ($#ARGV == -1) +{ + die "Usage: $program files\n"; +} + +my $version = "0.4"; + +foreach my $arg (@ARGV) +{ + push(@files, $arg); +} + + +print "/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */\n"; +print "/* exotic/$version (Mon Nov 7 11:15:31 CET 2011) */\n\n"; + +print "#define __EXOTIC__STANDALONE__\n"; +standalone_include_exotic_h(); + +if ($#ARGV >= 0) +{ + foreach $file (@ARGV) + { + $found = 0; + open( FILE, "$file") || next; + my @data = ; + my $comment = 0; + + foreach $line (@data) { + chomp($line); + + if ($comment == 1) + { + if ($line =~ /^(.*\*\/)(.*)/) + { + $line = $2; + $comment = 0; + } + else + { + next; # ignore comment data + } + } + + if ($line =~ /^(.*)\/\*(.*)\*\/(.*)$/) + { + $line = $1 . " " . $3; # exclude comment stuff in between "/*" and "*/". + } + + if ($line =~ /^(.*)(\/\/.*)$/) { + $line = $1; # exclude stuff after "//" (FIXME: does not work if they are inside a string) + } + + if ($line =~ /\/\*/) { + $comment = 1; + next; + } + + if ($line =~ /^\s*EXO_TEST\(\s*(\w+)\s*,/) + { + $found++; + push(@tests, $1); + } + } + + if ($found > 0) { + print "#include \"" . $file . "\"\n"; + } + + close(FILE); + } + print "\n"; +} + +# Write a main() that will start the test run +print "int main(int argc, char** argv)\n{\n"; +print "\tstruct exotic_handle handle;\n\n"; +print "\tif (exotic_initialize(&handle, argc, argv) == -1)\n\t\treturn -1;\n\n"; + +if ($#tests > 0) +{ + print "\t/* Register the tests to be run */\n"; + foreach $test (@tests) + { + print "\texotic_add_test(&handle, &exotic_test_" . $test . ", \"" . $test . "\");\n"; + } +} +else +{ + print "\t/* No tests are found! */\n"; +} + +print "\n"; +print "\treturn exotic_run(&handle);\n"; +print "}\n\n"; + + +standalone_include_exotic_c(); + +sub standalone_include_exotic_h { +print ' +/* + * Exotic (EXtatic.Org Test InfrastuCture) + * Copyright (c) 2007, Jan Vidar Krey + */ + +#ifndef EXO_TEST +#define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block +#endif + +#ifndef HAVE_EXOTIC_AUTOTEST_H +#define HAVE_EXOTIC_AUTOTEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(*exo_test_t)(); + +enum exo_toggle { cfg_default, cfg_off, cfg_on }; + +struct exotic_handle +{ + enum exo_toggle config_show_summary; + enum exo_toggle config_show_pass; + enum exo_toggle config_show_fail; + unsigned int fail; + unsigned int pass; + struct exo_test_data* first; + struct exo_test_data* current; +}; + +extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); +extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); +extern int exotic_run(struct exotic_handle* handle); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_EXOTIC_AUTOTEST_H */ + +'; } +sub standalone_include_exotic_c { +print ' +/* + * Exotic - C/C++ source code testing + * Copyright (c) 2007, Jan Vidar Krey + */ + +#include +#include +#include +#include + +static void exotic_version(); + +#ifndef __EXOTIC__STANDALONE__ +#include "autotest.h" +static void exotic_version() +{ + printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} +#endif + +struct exo_test_data +{ + exo_test_t test; + char* name; + struct exo_test_data* next; +}; + + +static void exotic_summary(struct exotic_handle* handle) +{ + int total = handle->pass + handle->fail; + int pass_rate = total ? (100*handle->pass / total) : 0; + int fail_rate = total ? (100*handle->fail / total) : 0; + + printf("\n"); + printf("--------------------------------------------\n"); + printf("Results:\n"); + printf(" * Total tests run: %8d\n", total); + printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); + printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); + printf("--------------------------------------------\n"); +} + + +static void exotic_help(const char* program) +{ + printf("Usage: %s [OPTIONS]\n\n", program); + printf("Options:\n"); + printf(" --help -h Show this message\n"); + printf(" --version -v Show version\n"); + printf(" --summary -s show only summary)\n"); + printf(" --fail -f show only test failures\n"); + printf(" --pass -p show only test passes\n"); + printf("\nExamples:\n"); + printf(" %s -s -f\n\n", program); +} + + +int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) +{ + int n; + if (!handle || !argv) return -1; + + memset(handle, 0, sizeof(struct exotic_handle)); + + for (n = 1; n < argc; n++) + { + if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) + { + exotic_help(argv[0]); + exit(0); + } + + if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) + { + exotic_version(); + exit(0); + } + + if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) + { + handle->config_show_summary = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) + { + handle->config_show_fail = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) + { + handle->config_show_pass = cfg_on; + continue; + } + + fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); + exotic_help(argv[0]); + exit(0); + } + + if (handle->config_show_summary == cfg_on) + { + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + + } + else if (handle->config_show_pass == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else if (handle->config_show_fail == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; + } + return 0; +} + + +void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) +{ + if (!handle) + { + fprintf(stderr, "exotic_add_test: failed, no handle!\n"); + exit(-1); + } + + struct exo_test_data* test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); + if (!test) + { + fprintf(stderr, "exotic_add_test: out of memory!\n"); + exit(-1); + } + + /* Create the test */ + memset(test, 0, sizeof(struct exo_test_data)); + test->test = func; + test->name = strdup(name); + + /* Register the test in the handle */ + if (!handle->first) + { + handle->first = test; + handle->current = test; + } + else + { + handle->current->next = test; + handle->current = test; + } +} + + +int exotic_run(struct exotic_handle* handle) +{ + struct exo_test_data* tmp = NULL; + + if (!handle) + { + fprintf(stderr, "Error: exotic is not initialized\n"); + return -1; + } + + handle->current = handle->first; + while (handle->current) + { + tmp = handle->current; + + if (handle->current->test()) { + if (handle->config_show_pass == cfg_on) printf("* PASS test \'%s\'\n", tmp->name); + handle->pass++; + } else { + if (handle->config_show_fail == cfg_on) printf("* FAIL test \'%s\'\n", tmp->name); + handle->fail++; + } + + handle->current = handle->current->next; + + free(tmp->name); + free(tmp); + } + + if (!handle->first) + { + printf("(No tests added)\n"); + } + + if (handle->config_show_summary == cfg_on) + exotic_summary(handle); + + return (handle->fail) ? handle->fail : 0; +} + + +static void exotic_version() { + printf("exotic 0.4-standalone\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} +'; } + diff --git a/autotest/test.c b/autotest/test.c new file mode 100644 index 0000000..cb3142d --- /dev/null +++ b/autotest/test.c @@ -0,0 +1,1002 @@ +/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */ +/* exotic/0.4 (Mon Nov 7 11:15:31 CET 2011) */ + +#define __EXOTIC__STANDALONE__ + +/* + * Exotic (EXtatic.Org Test InfrastuCture) + * Copyright (c) 2007, Jan Vidar Krey + */ + +#ifndef EXO_TEST +#define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block +#endif + +#ifndef HAVE_EXOTIC_AUTOTEST_H +#define HAVE_EXOTIC_AUTOTEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int(*exo_test_t)(); + +enum exo_toggle { cfg_default, cfg_off, cfg_on }; + +struct exotic_handle +{ + enum exo_toggle config_show_summary; + enum exo_toggle config_show_pass; + enum exo_toggle config_show_fail; + unsigned int fail; + unsigned int pass; + struct exo_test_data* first; + struct exo_test_data* current; +}; + +extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); +extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); +extern int exotic_run(struct exotic_handle* handle); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_EXOTIC_AUTOTEST_H */ + +#include "test_commands.tcc" +#include "test_credentials.tcc" +#include "test_eventqueue.tcc" +#include "test_hub.tcc" +#include "test_inf.tcc" +#include "test_ipfilter.tcc" +#include "test_list.tcc" +#include "test_memory.tcc" +#include "test_message.tcc" +#include "test_misc.tcc" +#include "test_sid.tcc" +#include "test_tiger.tcc" +#include "test_timer.tcc" +#include "test_tokenizer.tcc" +#include "test_usermanager.tcc" + +int main(int argc, char** argv) +{ + struct exotic_handle handle; + + if (exotic_initialize(&handle, argc, argv) == -1) + return -1; + + /* Register the tests to be run */ + exotic_add_test(&handle, &exotic_test_setup, "setup"); + exotic_add_test(&handle, &exotic_test_command_setup_user, "command_setup_user"); + exotic_add_test(&handle, &exotic_test_command_create, "command_create"); + exotic_add_test(&handle, &exotic_test_command_access_1, "command_access_1"); + exotic_add_test(&handle, &exotic_test_command_access_2, "command_access_2"); + exotic_add_test(&handle, &exotic_test_command_access_3, "command_access_3"); + exotic_add_test(&handle, &exotic_test_command_syntax_1, "command_syntax_1"); + exotic_add_test(&handle, &exotic_test_command_syntax_2, "command_syntax_2"); + exotic_add_test(&handle, &exotic_test_command_missing_args_1, "command_missing_args_1"); + exotic_add_test(&handle, &exotic_test_command_missing_args_2, "command_missing_args_2"); + exotic_add_test(&handle, &exotic_test_command_missing_args_3, "command_missing_args_3"); + exotic_add_test(&handle, &exotic_test_command_number_1, "command_number_1"); + exotic_add_test(&handle, &exotic_test_command_number_2, "command_number_2"); + exotic_add_test(&handle, &exotic_test_command_number_3, "command_number_3"); + exotic_add_test(&handle, &exotic_test_command_user_1, "command_user_1"); + exotic_add_test(&handle, &exotic_test_command_user_2, "command_user_2"); + exotic_add_test(&handle, &exotic_test_command_user_3, "command_user_3"); + exotic_add_test(&handle, &exotic_test_command_user_4, "command_user_4"); + exotic_add_test(&handle, &exotic_test_command_user_5, "command_user_5"); + exotic_add_test(&handle, &exotic_test_command_command_1, "command_command_1"); + exotic_add_test(&handle, &exotic_test_command_command_2, "command_command_2"); + exotic_add_test(&handle, &exotic_test_command_command_3, "command_command_3"); + exotic_add_test(&handle, &exotic_test_command_command_4, "command_command_4"); + exotic_add_test(&handle, &exotic_test_command_command_5, "command_command_5"); + exotic_add_test(&handle, &exotic_test_command_command_6, "command_command_6"); + exotic_add_test(&handle, &exotic_test_command_command_7, "command_command_7"); + exotic_add_test(&handle, &exotic_test_command_command_8, "command_command_8"); + exotic_add_test(&handle, &exotic_test_command_cred_1, "command_cred_1"); + exotic_add_test(&handle, &exotic_test_command_cred_2, "command_cred_2"); + exotic_add_test(&handle, &exotic_test_command_cred_3, "command_cred_3"); + exotic_add_test(&handle, &exotic_test_command_cred_4, "command_cred_4"); + exotic_add_test(&handle, &exotic_test_command_cred_5, "command_cred_5"); + exotic_add_test(&handle, &exotic_test_command_cred_6, "command_cred_6"); + exotic_add_test(&handle, &exotic_test_command_cred_7, "command_cred_7"); + exotic_add_test(&handle, &exotic_test_command_cred_8, "command_cred_8"); + exotic_add_test(&handle, &exotic_test_command_parse_3, "command_parse_3"); + exotic_add_test(&handle, &exotic_test_command_parse_4, "command_parse_4"); + exotic_add_test(&handle, &exotic_test_command_argument_integer_1, "command_argument_integer_1"); + exotic_add_test(&handle, &exotic_test_command_argument_integer_2, "command_argument_integer_2"); + exotic_add_test(&handle, &exotic_test_command_argument_integer_3, "command_argument_integer_3"); + exotic_add_test(&handle, &exotic_test_command_argument_user_1, "command_argument_user_1"); + exotic_add_test(&handle, &exotic_test_command_argument_cid_1, "command_argument_cid_1"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_1, "command_argument_cred_1"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_2, "command_argument_cred_2"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_3, "command_argument_cred_3"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_4, "command_argument_cred_4"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_5, "command_argument_cred_5"); + exotic_add_test(&handle, &exotic_test_command_argument_cred_6, "command_argument_cred_6"); + exotic_add_test(&handle, &exotic_test_command_user_destroy, "command_user_destroy"); + exotic_add_test(&handle, &exotic_test_command_destroy, "command_destroy"); + exotic_add_test(&handle, &exotic_test_cleanup, "cleanup"); + exotic_add_test(&handle, &exotic_test_cred_to_string_1, "cred_to_string_1"); + exotic_add_test(&handle, &exotic_test_cred_to_string_2, "cred_to_string_2"); + exotic_add_test(&handle, &exotic_test_cred_to_string_3, "cred_to_string_3"); + exotic_add_test(&handle, &exotic_test_cred_to_string_4, "cred_to_string_4"); + exotic_add_test(&handle, &exotic_test_cred_to_string_5, "cred_to_string_5"); + exotic_add_test(&handle, &exotic_test_cred_to_string_6, "cred_to_string_6"); + exotic_add_test(&handle, &exotic_test_cred_to_string_7, "cred_to_string_7"); + exotic_add_test(&handle, &exotic_test_cred_to_string_8, "cred_to_string_8"); + exotic_add_test(&handle, &exotic_test_cred_from_string_1, "cred_from_string_1"); + exotic_add_test(&handle, &exotic_test_cred_from_string_2, "cred_from_string_2"); + exotic_add_test(&handle, &exotic_test_cred_from_string_3, "cred_from_string_3"); + exotic_add_test(&handle, &exotic_test_cred_from_string_4, "cred_from_string_4"); + exotic_add_test(&handle, &exotic_test_cred_from_string_5, "cred_from_string_5"); + exotic_add_test(&handle, &exotic_test_cred_from_string_6, "cred_from_string_6"); + exotic_add_test(&handle, &exotic_test_cred_from_string_7, "cred_from_string_7"); + exotic_add_test(&handle, &exotic_test_cred_from_string_8, "cred_from_string_8"); + exotic_add_test(&handle, &exotic_test_cred_from_string_9, "cred_from_string_9"); + exotic_add_test(&handle, &exotic_test_cred_from_string_10, "cred_from_string_10"); + exotic_add_test(&handle, &exotic_test_eventqueue_init_1, "eventqueue_init_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_init_2, "eventqueue_init_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_post_1, "eventqueue_post_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_process_1, "eventqueue_process_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_1, "eventqueue_size_1"); + exotic_add_test(&handle, &exotic_test_eventqueue_post_2, "eventqueue_post_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_2, "eventqueue_size_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_post_3, "eventqueue_post_3"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_3, "eventqueue_size_3"); + exotic_add_test(&handle, &exotic_test_eventqueue_process_2, "eventqueue_process_2"); + exotic_add_test(&handle, &exotic_test_eventqueue_size_4, "eventqueue_size_4"); + exotic_add_test(&handle, &exotic_test_eventqueue_shutdown_1, "eventqueue_shutdown_1"); + exotic_add_test(&handle, &exotic_test_hub_net_startup, "hub_net_startup"); + exotic_add_test(&handle, &exotic_test_hub_config_initialize, "hub_config_initialize"); + exotic_add_test(&handle, &exotic_test_hub_acl_initialize, "hub_acl_initialize"); + exotic_add_test(&handle, &exotic_test_hub_service_initialize, "hub_service_initialize"); + exotic_add_test(&handle, &exotic_test_hub_variables_startup, "hub_variables_startup"); + exotic_add_test(&handle, &exotic_test_hub_variables_shutdown, "hub_variables_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_acl_shutdown, "hub_acl_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_config_shutdown, "hub_config_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_service_shutdown, "hub_service_shutdown"); + exotic_add_test(&handle, &exotic_test_hub_net_shutdown, "hub_net_shutdown"); + exotic_add_test(&handle, &exotic_test_inf_create_setup, "inf_create_setup"); + exotic_add_test(&handle, &exotic_test_inf_ok_1, "inf_ok_1"); + exotic_add_test(&handle, &exotic_test_inf_cid_1, "inf_cid_1"); + exotic_add_test(&handle, &exotic_test_inf_cid_2, "inf_cid_2"); + exotic_add_test(&handle, &exotic_test_inf_cid_3, "inf_cid_3"); + exotic_add_test(&handle, &exotic_test_inf_cid_4, "inf_cid_4"); + exotic_add_test(&handle, &exotic_test_inf_cid_5, "inf_cid_5"); + exotic_add_test(&handle, &exotic_test_inf_cid_6, "inf_cid_6"); + exotic_add_test(&handle, &exotic_test_inf_cid_7, "inf_cid_7"); + exotic_add_test(&handle, &exotic_test_inf_cid_8, "inf_cid_8"); + exotic_add_test(&handle, &exotic_test_inf_cid_9, "inf_cid_9"); + exotic_add_test(&handle, &exotic_test_inf_pid_1, "inf_pid_1"); + exotic_add_test(&handle, &exotic_test_inf_pid_2, "inf_pid_2"); + exotic_add_test(&handle, &exotic_test_inf_pid_3, "inf_pid_3"); + exotic_add_test(&handle, &exotic_test_inf_pid_4, "inf_pid_4"); + exotic_add_test(&handle, &exotic_test_inf_pid_5, "inf_pid_5"); + exotic_add_test(&handle, &exotic_test_inf_pid_6, "inf_pid_6"); + exotic_add_test(&handle, &exotic_test_inf_pid_7, "inf_pid_7"); + exotic_add_test(&handle, &exotic_test_inf_pid_8, "inf_pid_8"); + exotic_add_test(&handle, &exotic_test_inf_pid_9, "inf_pid_9"); + exotic_add_test(&handle, &exotic_test_inf_nick_01, "inf_nick_01"); + exotic_add_test(&handle, &exotic_test_inf_nick_02, "inf_nick_02"); + exotic_add_test(&handle, &exotic_test_inf_nick_03, "inf_nick_03"); + exotic_add_test(&handle, &exotic_test_inf_nick_04, "inf_nick_04"); + exotic_add_test(&handle, &exotic_test_inf_nick_05, "inf_nick_05"); + exotic_add_test(&handle, &exotic_test_inf_nick_06, "inf_nick_06"); + exotic_add_test(&handle, &exotic_test_inf_nick_07, "inf_nick_07"); + exotic_add_test(&handle, &exotic_test_inf_nick_08, "inf_nick_08"); + exotic_add_test(&handle, &exotic_test_inf_nick_09, "inf_nick_09"); + exotic_add_test(&handle, &exotic_test_inf_nick_10, "inf_nick_10"); + exotic_add_test(&handle, &exotic_test_inf_limits_1, "inf_limits_1"); + exotic_add_test(&handle, &exotic_test_inf_limits_2, "inf_limits_2"); + exotic_add_test(&handle, &exotic_test_inf_limits_3, "inf_limits_3"); + exotic_add_test(&handle, &exotic_test_inf_limits_4, "inf_limits_4"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_setup, "inf_limit_hubs_setup"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_1, "inf_limit_hubs_1"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_2, "inf_limit_hubs_2"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_3, "inf_limit_hubs_3"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_4, "inf_limit_hubs_4"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_5, "inf_limit_hubs_5"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_6, "inf_limit_hubs_6"); + exotic_add_test(&handle, &exotic_test_inf_limit_hubs_7, "inf_limit_hubs_7"); + exotic_add_test(&handle, &exotic_test_inf_destroy_setup, "inf_destroy_setup"); + exotic_add_test(&handle, &exotic_test_prepare_network, "prepare_network"); + exotic_add_test(&handle, &exotic_test_check_ipv6, "check_ipv6"); + exotic_add_test(&handle, &exotic_test_create_addresses_1, "create_addresses_1"); + exotic_add_test(&handle, &exotic_test_create_addresses_2, "create_addresses_2"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_1, "ip_is_valid_ipv4_1"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_2, "ip_is_valid_ipv4_2"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_3, "ip_is_valid_ipv4_3"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_4, "ip_is_valid_ipv4_4"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_5, "ip_is_valid_ipv4_5"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_6, "ip_is_valid_ipv4_6"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_7, "ip_is_valid_ipv4_7"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_8, "ip_is_valid_ipv4_8"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv4_9, "ip_is_valid_ipv4_9"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_1, "ip_is_valid_ipv6_1"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_2, "ip_is_valid_ipv6_2"); + exotic_add_test(&handle, &exotic_test_ip_is_valid_ipv6_3, "ip_is_valid_ipv6_3"); + exotic_add_test(&handle, &exotic_test_ip4_compare_1, "ip4_compare_1"); + exotic_add_test(&handle, &exotic_test_ip4_compare_2, "ip4_compare_2"); + exotic_add_test(&handle, &exotic_test_ip4_compare_3, "ip4_compare_3"); + exotic_add_test(&handle, &exotic_test_ip4_compare_4, "ip4_compare_4"); + exotic_add_test(&handle, &exotic_test_ip4_compare_5, "ip4_compare_5"); + exotic_add_test(&handle, &exotic_test_ip4_compare_6, "ip4_compare_6"); + exotic_add_test(&handle, &exotic_test_ip6_compare_1, "ip6_compare_1"); + exotic_add_test(&handle, &exotic_test_ip6_compare_2, "ip6_compare_2"); + exotic_add_test(&handle, &exotic_test_ip6_compare_3, "ip6_compare_3"); + exotic_add_test(&handle, &exotic_test_ip6_compare_4, "ip6_compare_4"); + exotic_add_test(&handle, &exotic_test_ip6_compare_5, "ip6_compare_5"); + exotic_add_test(&handle, &exotic_test_ip6_compare_6, "ip6_compare_6"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_0, "ipv4_lmask_create_0"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_1, "ipv4_lmask_create_1"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_2, "ipv4_lmask_create_2"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_3, "ipv4_lmask_create_3"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_4, "ipv4_lmask_create_4"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_5, "ipv4_lmask_create_5"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_6, "ipv4_lmask_create_6"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_7, "ipv4_lmask_create_7"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_8, "ipv4_lmask_create_8"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_9, "ipv4_lmask_create_9"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_10, "ipv4_lmask_create_10"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_11, "ipv4_lmask_create_11"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_12, "ipv4_lmask_create_12"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_13, "ipv4_lmask_create_13"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_14, "ipv4_lmask_create_14"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_15, "ipv4_lmask_create_15"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_16, "ipv4_lmask_create_16"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_17, "ipv4_lmask_create_17"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_18, "ipv4_lmask_create_18"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_19, "ipv4_lmask_create_19"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_20, "ipv4_lmask_create_20"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_21, "ipv4_lmask_create_21"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_22, "ipv4_lmask_create_22"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_23, "ipv4_lmask_create_23"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_24, "ipv4_lmask_create_24"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_25, "ipv4_lmask_create_25"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_26, "ipv4_lmask_create_26"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_27, "ipv4_lmask_create_27"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_28, "ipv4_lmask_create_28"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_29, "ipv4_lmask_create_29"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_30, "ipv4_lmask_create_30"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_31, "ipv4_lmask_create_31"); + exotic_add_test(&handle, &exotic_test_ipv4_lmask_create_32, "ipv4_lmask_create_32"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_0, "ipv4_rmask_create_0"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_1, "ipv4_rmask_create_1"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_2, "ipv4_rmask_create_2"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_3, "ipv4_rmask_create_3"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_4, "ipv4_rmask_create_4"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_5, "ipv4_rmask_create_5"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_6, "ipv4_rmask_create_6"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_7, "ipv4_rmask_create_7"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_8, "ipv4_rmask_create_8"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_9, "ipv4_rmask_create_9"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_10, "ipv4_rmask_create_10"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_11, "ipv4_rmask_create_11"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_12, "ipv4_rmask_create_12"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_13, "ipv4_rmask_create_13"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_14, "ipv4_rmask_create_14"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_15, "ipv4_rmask_create_15"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_16, "ipv4_rmask_create_16"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_17, "ipv4_rmask_create_17"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_18, "ipv4_rmask_create_18"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_19, "ipv4_rmask_create_19"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_20, "ipv4_rmask_create_20"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_21, "ipv4_rmask_create_21"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_22, "ipv4_rmask_create_22"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_23, "ipv4_rmask_create_23"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_24, "ipv4_rmask_create_24"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_25, "ipv4_rmask_create_25"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_26, "ipv4_rmask_create_26"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_27, "ipv4_rmask_create_27"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_28, "ipv4_rmask_create_28"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_29, "ipv4_rmask_create_29"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_30, "ipv4_rmask_create_30"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_31, "ipv4_rmask_create_31"); + exotic_add_test(&handle, &exotic_test_ipv4_rmask_create_32, "ipv4_rmask_create_32"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_0, "ip6_lmask_create_0"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_1, "ip6_lmask_create_1"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_2, "ip6_lmask_create_2"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_3, "ip6_lmask_create_3"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_4, "ip6_lmask_create_4"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_5, "ip6_lmask_create_5"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_6, "ip6_lmask_create_6"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_7, "ip6_lmask_create_7"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_8, "ip6_lmask_create_8"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_9, "ip6_lmask_create_9"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_10, "ip6_lmask_create_10"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_11, "ip6_lmask_create_11"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_12, "ip6_lmask_create_12"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_13, "ip6_lmask_create_13"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_14, "ip6_lmask_create_14"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_15, "ip6_lmask_create_15"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_16, "ip6_lmask_create_16"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_17, "ip6_lmask_create_17"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_18, "ip6_lmask_create_18"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_19, "ip6_lmask_create_19"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_20, "ip6_lmask_create_20"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_21, "ip6_lmask_create_21"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_22, "ip6_lmask_create_22"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_23, "ip6_lmask_create_23"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_24, "ip6_lmask_create_24"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_25, "ip6_lmask_create_25"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_26, "ip6_lmask_create_26"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_27, "ip6_lmask_create_27"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_28, "ip6_lmask_create_28"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_29, "ip6_lmask_create_29"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_30, "ip6_lmask_create_30"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_31, "ip6_lmask_create_31"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_32, "ip6_lmask_create_32"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_33, "ip6_lmask_create_33"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_34, "ip6_lmask_create_34"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_35, "ip6_lmask_create_35"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_36, "ip6_lmask_create_36"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_37, "ip6_lmask_create_37"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_38, "ip6_lmask_create_38"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_39, "ip6_lmask_create_39"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_40, "ip6_lmask_create_40"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_41, "ip6_lmask_create_41"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_42, "ip6_lmask_create_42"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_43, "ip6_lmask_create_43"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_44, "ip6_lmask_create_44"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_45, "ip6_lmask_create_45"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_46, "ip6_lmask_create_46"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_47, "ip6_lmask_create_47"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_48, "ip6_lmask_create_48"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_49, "ip6_lmask_create_49"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_50, "ip6_lmask_create_50"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_51, "ip6_lmask_create_51"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_52, "ip6_lmask_create_52"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_53, "ip6_lmask_create_53"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_54, "ip6_lmask_create_54"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_55, "ip6_lmask_create_55"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_56, "ip6_lmask_create_56"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_57, "ip6_lmask_create_57"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_58, "ip6_lmask_create_58"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_59, "ip6_lmask_create_59"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_60, "ip6_lmask_create_60"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_61, "ip6_lmask_create_61"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_62, "ip6_lmask_create_62"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_63, "ip6_lmask_create_63"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_64, "ip6_lmask_create_64"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_65, "ip6_lmask_create_65"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_66, "ip6_lmask_create_66"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_67, "ip6_lmask_create_67"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_68, "ip6_lmask_create_68"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_69, "ip6_lmask_create_69"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_70, "ip6_lmask_create_70"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_71, "ip6_lmask_create_71"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_72, "ip6_lmask_create_72"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_73, "ip6_lmask_create_73"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_74, "ip6_lmask_create_74"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_75, "ip6_lmask_create_75"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_76, "ip6_lmask_create_76"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_77, "ip6_lmask_create_77"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_78, "ip6_lmask_create_78"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_79, "ip6_lmask_create_79"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_80, "ip6_lmask_create_80"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_81, "ip6_lmask_create_81"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_82, "ip6_lmask_create_82"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_83, "ip6_lmask_create_83"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_84, "ip6_lmask_create_84"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_85, "ip6_lmask_create_85"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_86, "ip6_lmask_create_86"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_87, "ip6_lmask_create_87"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_88, "ip6_lmask_create_88"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_89, "ip6_lmask_create_89"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_90, "ip6_lmask_create_90"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_91, "ip6_lmask_create_91"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_92, "ip6_lmask_create_92"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_93, "ip6_lmask_create_93"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_94, "ip6_lmask_create_94"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_95, "ip6_lmask_create_95"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_96, "ip6_lmask_create_96"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_97, "ip6_lmask_create_97"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_98, "ip6_lmask_create_98"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_99, "ip6_lmask_create_99"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_100, "ip6_lmask_create_100"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_101, "ip6_lmask_create_101"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_102, "ip6_lmask_create_102"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_103, "ip6_lmask_create_103"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_104, "ip6_lmask_create_104"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_105, "ip6_lmask_create_105"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_106, "ip6_lmask_create_106"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_107, "ip6_lmask_create_107"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_108, "ip6_lmask_create_108"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_109, "ip6_lmask_create_109"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_110, "ip6_lmask_create_110"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_111, "ip6_lmask_create_111"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_112, "ip6_lmask_create_112"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_113, "ip6_lmask_create_113"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_114, "ip6_lmask_create_114"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_115, "ip6_lmask_create_115"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_116, "ip6_lmask_create_116"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_117, "ip6_lmask_create_117"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_118, "ip6_lmask_create_118"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_119, "ip6_lmask_create_119"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_120, "ip6_lmask_create_120"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_121, "ip6_lmask_create_121"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_122, "ip6_lmask_create_122"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_123, "ip6_lmask_create_123"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_124, "ip6_lmask_create_124"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_125, "ip6_lmask_create_125"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_126, "ip6_lmask_create_126"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_127, "ip6_lmask_create_127"); + exotic_add_test(&handle, &exotic_test_ip6_lmask_create_128, "ip6_lmask_create_128"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_0, "ip6_rmask_create_0"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_1, "ip6_rmask_create_1"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_2, "ip6_rmask_create_2"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_3, "ip6_rmask_create_3"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_4, "ip6_rmask_create_4"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_5, "ip6_rmask_create_5"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_6, "ip6_rmask_create_6"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_7, "ip6_rmask_create_7"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_8, "ip6_rmask_create_8"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_9, "ip6_rmask_create_9"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_10, "ip6_rmask_create_10"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_11, "ip6_rmask_create_11"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_12, "ip6_rmask_create_12"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_13, "ip6_rmask_create_13"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_14, "ip6_rmask_create_14"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_15, "ip6_rmask_create_15"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_16, "ip6_rmask_create_16"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_17, "ip6_rmask_create_17"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_18, "ip6_rmask_create_18"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_19, "ip6_rmask_create_19"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_20, "ip6_rmask_create_20"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_21, "ip6_rmask_create_21"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_22, "ip6_rmask_create_22"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_23, "ip6_rmask_create_23"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_24, "ip6_rmask_create_24"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_25, "ip6_rmask_create_25"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_26, "ip6_rmask_create_26"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_27, "ip6_rmask_create_27"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_28, "ip6_rmask_create_28"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_29, "ip6_rmask_create_29"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_30, "ip6_rmask_create_30"); + exotic_add_test(&handle, &exotic_test_ip6_rmask_create_31, "ip6_rmask_create_31"); + exotic_add_test(&handle, &exotic_test_check_ban_setup_1, "check_ban_setup_1"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_1, "check_ban_ipv4_1"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_2, "check_ban_ipv4_2"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_3, "check_ban_ipv4_3"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_4, "check_ban_ipv4_4"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv4_5, "check_ban_ipv4_5"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_1, "check_ban_ipv6_1"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_2, "check_ban_ipv6_2"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_3, "check_ban_ipv6_3"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_4, "check_ban_ipv6_4"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_5, "check_ban_ipv6_5"); + exotic_add_test(&handle, &exotic_test_check_ban_ipv6_6, "check_ban_ipv6_6"); + exotic_add_test(&handle, &exotic_test_check_ban_afmix_1, "check_ban_afmix_1"); + exotic_add_test(&handle, &exotic_test_check_ban_afmix_2, "check_ban_afmix_2"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_1, "ip4_bitwise_AND_1"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_2, "ip4_bitwise_AND_2"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_3, "ip4_bitwise_AND_3"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_4, "ip4_bitwise_AND_4"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_AND_5, "ip4_bitwise_AND_5"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_1, "ip4_bitwise_OR_1"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_2, "ip4_bitwise_OR_2"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_3, "ip4_bitwise_OR_3"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_4, "ip4_bitwise_OR_4"); + exotic_add_test(&handle, &exotic_test_ip4_bitwise_OR_5, "ip4_bitwise_OR_5"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_1, "ip6_bitwise_AND_1"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_2, "ip6_bitwise_AND_2"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_AND_3, "ip6_bitwise_AND_3"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_1, "ip6_bitwise_OR_1"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_2, "ip6_bitwise_OR_2"); + exotic_add_test(&handle, &exotic_test_ip6_bitwise_OR_3, "ip6_bitwise_OR_3"); + exotic_add_test(&handle, &exotic_test_ip_range_1, "ip_range_1"); + exotic_add_test(&handle, &exotic_test_ip_range_2, "ip_range_2"); + exotic_add_test(&handle, &exotic_test_ip_range_3, "ip_range_3"); + exotic_add_test(&handle, &exotic_test_ip_range_4, "ip_range_4"); + exotic_add_test(&handle, &exotic_test_shutdown_network, "shutdown_network"); + exotic_add_test(&handle, &exotic_test_list_create_destroy, "list_create_destroy"); + exotic_add_test(&handle, &exotic_test_list_create, "list_create"); + exotic_add_test(&handle, &exotic_test_list_append_1, "list_append_1"); + exotic_add_test(&handle, &exotic_test_list_remove_1, "list_remove_1"); + exotic_add_test(&handle, &exotic_test_list_append_2, "list_append_2"); + exotic_add_test(&handle, &exotic_test_list_remove_2, "list_remove_2"); + exotic_add_test(&handle, &exotic_test_list_remove_3, "list_remove_3"); + exotic_add_test(&handle, &exotic_test_list_remove_4, "list_remove_4"); + exotic_add_test(&handle, &exotic_test_list_append_3, "list_append_3"); + exotic_add_test(&handle, &exotic_test_list_append_4, "list_append_4"); + exotic_add_test(&handle, &exotic_test_list_remove_5, "list_remove_5"); + exotic_add_test(&handle, &exotic_test_list_get_index_1, "list_get_index_1"); + exotic_add_test(&handle, &exotic_test_list_get_index_2, "list_get_index_2"); + exotic_add_test(&handle, &exotic_test_list_get_index_3, "list_get_index_3"); + exotic_add_test(&handle, &exotic_test_list_get_index_4, "list_get_index_4"); + exotic_add_test(&handle, &exotic_test_list_get_first_1, "list_get_first_1"); + exotic_add_test(&handle, &exotic_test_list_get_first_next_1, "list_get_first_next_1"); + exotic_add_test(&handle, &exotic_test_list_get_first_next_2, "list_get_first_next_2"); + exotic_add_test(&handle, &exotic_test_list_get_last_1, "list_get_last_1"); + exotic_add_test(&handle, &exotic_test_list_get_last_prev_1, "list_get_last_prev_1"); + exotic_add_test(&handle, &exotic_test_list_get_last_prev_2, "list_get_last_prev_2"); + exotic_add_test(&handle, &exotic_test_list_get_last_prev_next_1, "list_get_last_prev_next_1"); + exotic_add_test(&handle, &exotic_test_list_clear, "list_clear"); + exotic_add_test(&handle, &exotic_test_list_destroy_1, "list_destroy_1"); + exotic_add_test(&handle, &exotic_test_list_destroy_2, "list_destroy_2"); + exotic_add_test(&handle, &exotic_test_test_message_refc_1, "test_message_refc_1"); + exotic_add_test(&handle, &exotic_test_test_message_refc_2, "test_message_refc_2"); + exotic_add_test(&handle, &exotic_test_test_message_refc_3, "test_message_refc_3"); + exotic_add_test(&handle, &exotic_test_test_message_refc_4, "test_message_refc_4"); + exotic_add_test(&handle, &exotic_test_test_message_refc_5, "test_message_refc_5"); + exotic_add_test(&handle, &exotic_test_test_message_refc_6, "test_message_refc_6"); + exotic_add_test(&handle, &exotic_test_test_message_refc_7, "test_message_refc_7"); + exotic_add_test(&handle, &exotic_test_adc_message_first, "adc_message_first"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_1, "adc_message_parse_1"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_2, "adc_message_parse_2"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_3, "adc_message_parse_3"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_4, "adc_message_parse_4"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_5, "adc_message_parse_5"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_6, "adc_message_parse_6"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_7, "adc_message_parse_7"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_8, "adc_message_parse_8"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_9, "adc_message_parse_9"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_10, "adc_message_parse_10"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_11, "adc_message_parse_11"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_12, "adc_message_parse_12"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_13, "adc_message_parse_13"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_14, "adc_message_parse_14"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_15, "adc_message_parse_15"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_16, "adc_message_parse_16"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_17, "adc_message_parse_17"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_18, "adc_message_parse_18"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_19, "adc_message_parse_19"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_20, "adc_message_parse_20"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_21, "adc_message_parse_21"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_22, "adc_message_parse_22"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_23, "adc_message_parse_23"); + exotic_add_test(&handle, &exotic_test_adc_message_parse_24, "adc_message_parse_24"); + exotic_add_test(&handle, &exotic_test_adc_message_add_arg_1, "adc_message_add_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_add_arg_2, "adc_message_add_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_1, "adc_message_remove_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_2, "adc_message_remove_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_3, "adc_message_remove_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_remove_arg_4, "adc_message_remove_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_1, "adc_message_replace_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_2, "adc_message_replace_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_replace_arg_3, "adc_message_replace_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_1, "adc_message_get_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_2, "adc_message_get_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_3, "adc_message_get_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_get_arg_4, "adc_message_get_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_1, "adc_message_get_named_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_2, "adc_message_get_named_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_3, "adc_message_get_named_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_get_named_arg_4, "adc_message_get_named_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_1, "adc_message_has_named_arg_1"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_2, "adc_message_has_named_arg_2"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_3, "adc_message_has_named_arg_3"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_4, "adc_message_has_named_arg_4"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_5, "adc_message_has_named_arg_5"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_6, "adc_message_has_named_arg_6"); + exotic_add_test(&handle, &exotic_test_adc_message_has_named_arg_7, "adc_message_has_named_arg_7"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_1, "adc_message_terminate_1"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_2, "adc_message_terminate_2"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_3, "adc_message_terminate_3"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_4, "adc_message_terminate_4"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_5, "adc_message_terminate_5"); + exotic_add_test(&handle, &exotic_test_adc_message_terminate_6, "adc_message_terminate_6"); + exotic_add_test(&handle, &exotic_test_adc_message_escape_1, "adc_message_escape_1"); + exotic_add_test(&handle, &exotic_test_adc_message_escape_2, "adc_message_escape_2"); + exotic_add_test(&handle, &exotic_test_adc_message_escape_3, "adc_message_escape_3"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_1, "adc_message_copy_1"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_2, "adc_message_copy_2"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_3, "adc_message_copy_3"); + exotic_add_test(&handle, &exotic_test_adc_message_copy_4, "adc_message_copy_4"); + exotic_add_test(&handle, &exotic_test_adc_message_update_1, "adc_message_update_1"); + exotic_add_test(&handle, &exotic_test_adc_message_update_2, "adc_message_update_2"); + exotic_add_test(&handle, &exotic_test_adc_message_update_3, "adc_message_update_3"); + exotic_add_test(&handle, &exotic_test_adc_message_update_4, "adc_message_update_4"); + exotic_add_test(&handle, &exotic_test_adc_message_update_4_cleanup, "adc_message_update_4_cleanup"); + exotic_add_test(&handle, &exotic_test_adc_message_empty_1, "adc_message_empty_1"); + exotic_add_test(&handle, &exotic_test_adc_message_empty_2, "adc_message_empty_2"); + exotic_add_test(&handle, &exotic_test_adc_message_empty_3, "adc_message_empty_3"); + exotic_add_test(&handle, &exotic_test_adc_message_last, "adc_message_last"); + exotic_add_test(&handle, &exotic_test_is_num_0, "is_num_0"); + exotic_add_test(&handle, &exotic_test_is_num_1, "is_num_1"); + exotic_add_test(&handle, &exotic_test_is_num_2, "is_num_2"); + exotic_add_test(&handle, &exotic_test_is_num_3, "is_num_3"); + exotic_add_test(&handle, &exotic_test_is_num_4, "is_num_4"); + exotic_add_test(&handle, &exotic_test_is_num_5, "is_num_5"); + exotic_add_test(&handle, &exotic_test_is_num_6, "is_num_6"); + exotic_add_test(&handle, &exotic_test_is_num_7, "is_num_7"); + exotic_add_test(&handle, &exotic_test_is_num_8, "is_num_8"); + exotic_add_test(&handle, &exotic_test_is_num_9, "is_num_9"); + exotic_add_test(&handle, &exotic_test_is_num_10, "is_num_10"); + exotic_add_test(&handle, &exotic_test_is_num_11, "is_num_11"); + exotic_add_test(&handle, &exotic_test_is_space_1, "is_space_1"); + exotic_add_test(&handle, &exotic_test_is_space_2, "is_space_2"); + exotic_add_test(&handle, &exotic_test_is_white_space_1, "is_white_space_1"); + exotic_add_test(&handle, &exotic_test_is_white_space_2, "is_white_space_2"); + exotic_add_test(&handle, &exotic_test_is_white_space_3, "is_white_space_3"); + exotic_add_test(&handle, &exotic_test_is_white_space_4, "is_white_space_4"); + exotic_add_test(&handle, &exotic_test_itoa_1, "itoa_1"); + exotic_add_test(&handle, &exotic_test_itoa_2, "itoa_2"); + exotic_add_test(&handle, &exotic_test_itoa_3, "itoa_3"); + exotic_add_test(&handle, &exotic_test_itoa_4, "itoa_4"); + exotic_add_test(&handle, &exotic_test_itoa_5, "itoa_5"); + exotic_add_test(&handle, &exotic_test_itoa_6, "itoa_6"); + exotic_add_test(&handle, &exotic_test_itoa_7, "itoa_7"); + exotic_add_test(&handle, &exotic_test_itoa_8, "itoa_8"); + exotic_add_test(&handle, &exotic_test_base32_valid_1, "base32_valid_1"); + exotic_add_test(&handle, &exotic_test_base32_valid_2, "base32_valid_2"); + exotic_add_test(&handle, &exotic_test_base32_valid_3, "base32_valid_3"); + exotic_add_test(&handle, &exotic_test_base32_valid_4, "base32_valid_4"); + exotic_add_test(&handle, &exotic_test_base32_valid_5, "base32_valid_5"); + exotic_add_test(&handle, &exotic_test_base32_valid_6, "base32_valid_6"); + exotic_add_test(&handle, &exotic_test_base32_valid_7, "base32_valid_7"); + exotic_add_test(&handle, &exotic_test_base32_valid_8, "base32_valid_8"); + exotic_add_test(&handle, &exotic_test_base32_valid_9, "base32_valid_9"); + exotic_add_test(&handle, &exotic_test_base32_valid_10, "base32_valid_10"); + exotic_add_test(&handle, &exotic_test_base32_valid_11, "base32_valid_11"); + exotic_add_test(&handle, &exotic_test_base32_valid_12, "base32_valid_12"); + exotic_add_test(&handle, &exotic_test_base32_valid_13, "base32_valid_13"); + exotic_add_test(&handle, &exotic_test_base32_valid_14, "base32_valid_14"); + exotic_add_test(&handle, &exotic_test_base32_valid_15, "base32_valid_15"); + exotic_add_test(&handle, &exotic_test_base32_valid_16, "base32_valid_16"); + exotic_add_test(&handle, &exotic_test_base32_valid_17, "base32_valid_17"); + exotic_add_test(&handle, &exotic_test_base32_valid_18, "base32_valid_18"); + exotic_add_test(&handle, &exotic_test_base32_valid_19, "base32_valid_19"); + exotic_add_test(&handle, &exotic_test_base32_valid_20, "base32_valid_20"); + exotic_add_test(&handle, &exotic_test_base32_valid_21, "base32_valid_21"); + exotic_add_test(&handle, &exotic_test_base32_valid_22, "base32_valid_22"); + exotic_add_test(&handle, &exotic_test_base32_valid_23, "base32_valid_23"); + exotic_add_test(&handle, &exotic_test_base32_valid_24, "base32_valid_24"); + exotic_add_test(&handle, &exotic_test_base32_valid_25, "base32_valid_25"); + exotic_add_test(&handle, &exotic_test_base32_valid_26, "base32_valid_26"); + exotic_add_test(&handle, &exotic_test_base32_valid_27, "base32_valid_27"); + exotic_add_test(&handle, &exotic_test_base32_valid_28, "base32_valid_28"); + exotic_add_test(&handle, &exotic_test_base32_valid_29, "base32_valid_29"); + exotic_add_test(&handle, &exotic_test_base32_valid_30, "base32_valid_30"); + exotic_add_test(&handle, &exotic_test_base32_valid_31, "base32_valid_31"); + exotic_add_test(&handle, &exotic_test_base32_valid_32, "base32_valid_32"); + exotic_add_test(&handle, &exotic_test_base32_invalid_1, "base32_invalid_1"); + exotic_add_test(&handle, &exotic_test_base32_invalid_2, "base32_invalid_2"); + exotic_add_test(&handle, &exotic_test_base32_invalid_3, "base32_invalid_3"); + exotic_add_test(&handle, &exotic_test_base32_invalid_4, "base32_invalid_4"); + exotic_add_test(&handle, &exotic_test_base32_invalid_5, "base32_invalid_5"); + exotic_add_test(&handle, &exotic_test_base32_invalid_6, "base32_invalid_6"); + exotic_add_test(&handle, &exotic_test_base32_invalid_7, "base32_invalid_7"); + exotic_add_test(&handle, &exotic_test_base32_invalid_8, "base32_invalid_8"); + exotic_add_test(&handle, &exotic_test_base32_invalid_9, "base32_invalid_9"); + exotic_add_test(&handle, &exotic_test_base32_invalid_10, "base32_invalid_10"); + exotic_add_test(&handle, &exotic_test_base32_invalid_11, "base32_invalid_11"); + exotic_add_test(&handle, &exotic_test_base32_invalid_12, "base32_invalid_12"); + exotic_add_test(&handle, &exotic_test_base32_invalid_13, "base32_invalid_13"); + exotic_add_test(&handle, &exotic_test_base32_invalid_14, "base32_invalid_14"); + exotic_add_test(&handle, &exotic_test_base32_invalid_15, "base32_invalid_15"); + exotic_add_test(&handle, &exotic_test_base32_invalid_16, "base32_invalid_16"); + exotic_add_test(&handle, &exotic_test_base32_invalid_17, "base32_invalid_17"); + exotic_add_test(&handle, &exotic_test_base32_invalid_18, "base32_invalid_18"); + exotic_add_test(&handle, &exotic_test_base32_invalid_19, "base32_invalid_19"); + exotic_add_test(&handle, &exotic_test_base32_invalid_20, "base32_invalid_20"); + exotic_add_test(&handle, &exotic_test_base32_invalid_21, "base32_invalid_21"); + exotic_add_test(&handle, &exotic_test_base32_invalid_22, "base32_invalid_22"); + exotic_add_test(&handle, &exotic_test_base32_invalid_23, "base32_invalid_23"); + exotic_add_test(&handle, &exotic_test_base32_invalid_24, "base32_invalid_24"); + exotic_add_test(&handle, &exotic_test_base32_invalid_25, "base32_invalid_25"); + exotic_add_test(&handle, &exotic_test_base32_invalid_26, "base32_invalid_26"); + exotic_add_test(&handle, &exotic_test_base32_invalid_27, "base32_invalid_27"); + exotic_add_test(&handle, &exotic_test_base32_invalid_28, "base32_invalid_28"); + exotic_add_test(&handle, &exotic_test_base32_invalid_29, "base32_invalid_29"); + exotic_add_test(&handle, &exotic_test_base32_invalid_30, "base32_invalid_30"); + exotic_add_test(&handle, &exotic_test_base32_invalid_31, "base32_invalid_31"); + exotic_add_test(&handle, &exotic_test_utf8_valid_1, "utf8_valid_1"); + exotic_add_test(&handle, &exotic_test_utf8_valid_2, "utf8_valid_2"); + exotic_add_test(&handle, &exotic_test_utf8_valid_3, "utf8_valid_3"); + exotic_add_test(&handle, &exotic_test_utf8_valid_4, "utf8_valid_4"); + exotic_add_test(&handle, &exotic_test_utf8_valid_5, "utf8_valid_5"); + exotic_add_test(&handle, &exotic_test_utf8_valid_6, "utf8_valid_6"); + exotic_add_test(&handle, &exotic_test_utf8_valid_7, "utf8_valid_7"); + exotic_add_test(&handle, &exotic_test_utf8_valid_8, "utf8_valid_8"); + exotic_add_test(&handle, &exotic_test_utf8_valid_9, "utf8_valid_9"); + exotic_add_test(&handle, &exotic_test_utf8_valid_10, "utf8_valid_10"); + exotic_add_test(&handle, &exotic_test_utf8_valid_11, "utf8_valid_11"); + exotic_add_test(&handle, &exotic_test_utf8_valid_12, "utf8_valid_12"); + exotic_add_test(&handle, &exotic_test_sid_create_pool, "sid_create_pool"); + exotic_add_test(&handle, &exotic_test_sid_check_0a, "sid_check_0a"); + exotic_add_test(&handle, &exotic_test_sid_check_0b, "sid_check_0b"); + exotic_add_test(&handle, &exotic_test_sid_alloc_1, "sid_alloc_1"); + exotic_add_test(&handle, &exotic_test_sid_check_1a, "sid_check_1a"); + exotic_add_test(&handle, &exotic_test_sid_check_1b, "sid_check_1b"); + exotic_add_test(&handle, &exotic_test_sid_alloc_2, "sid_alloc_2"); + exotic_add_test(&handle, &exotic_test_sid_check_2, "sid_check_2"); + exotic_add_test(&handle, &exotic_test_sid_alloc_3, "sid_alloc_3"); + exotic_add_test(&handle, &exotic_test_sid_check_3, "sid_check_3"); + exotic_add_test(&handle, &exotic_test_sid_alloc_4, "sid_alloc_4"); + exotic_add_test(&handle, &exotic_test_sid_check_4, "sid_check_4"); + exotic_add_test(&handle, &exotic_test_sid_alloc_5, "sid_alloc_5"); + exotic_add_test(&handle, &exotic_test_sid_check_6, "sid_check_6"); + exotic_add_test(&handle, &exotic_test_sid_list_all_1, "sid_list_all_1"); + exotic_add_test(&handle, &exotic_test_sid_remove_1, "sid_remove_1"); + exotic_add_test(&handle, &exotic_test_sid_remove_2, "sid_remove_2"); + exotic_add_test(&handle, &exotic_test_sid_remove_3, "sid_remove_3"); + exotic_add_test(&handle, &exotic_test_sid_remove_4, "sid_remove_4"); + exotic_add_test(&handle, &exotic_test_sid_destroy_pool, "sid_destroy_pool"); + exotic_add_test(&handle, &exotic_test_hash_tiger_1, "hash_tiger_1"); + exotic_add_test(&handle, &exotic_test_hash_tiger_2, "hash_tiger_2"); + exotic_add_test(&handle, &exotic_test_hash_tiger_3, "hash_tiger_3"); + exotic_add_test(&handle, &exotic_test_hash_tiger_4, "hash_tiger_4"); + exotic_add_test(&handle, &exotic_test_hash_tiger_5, "hash_tiger_5"); + exotic_add_test(&handle, &exotic_test_hash_tiger_6, "hash_tiger_6"); + exotic_add_test(&handle, &exotic_test_hash_tiger_7, "hash_tiger_7"); + exotic_add_test(&handle, &exotic_test_timer_setup, "timer_setup"); + exotic_add_test(&handle, &exotic_test_timer_check_timeout_0, "timer_check_timeout_0"); + exotic_add_test(&handle, &exotic_test_timer_add_event_1, "timer_add_event_1"); + exotic_add_test(&handle, &exotic_test_timer_check_timeout_1, "timer_check_timeout_1"); + exotic_add_test(&handle, &exotic_test_timer_remove_event_1, "timer_remove_event_1"); + exotic_add_test(&handle, &exotic_test_timer_check_timeout_2, "timer_check_timeout_2"); + exotic_add_test(&handle, &exotic_test_timer_remove_event_1_no_crash, "timer_remove_event_1_no_crash"); + exotic_add_test(&handle, &exotic_test_timer_add_5_events_1, "timer_add_5_events_1"); + exotic_add_test(&handle, &exotic_test_timer_check_5_events_1, "timer_check_5_events_1"); + exotic_add_test(&handle, &exotic_test_timer_process_5_events_1, "timer_process_5_events_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_0, "tokenizer_basic_0"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1, "tokenizer_basic_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1a, "tokenizer_basic_1a"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1b, "tokenizer_basic_1b"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1c, "tokenizer_basic_1c"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1d, "tokenizer_basic_1d"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_1e, "tokenizer_basic_1e"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_2, "tokenizer_basic_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_2a, "tokenizer_basic_2a"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3, "tokenizer_basic_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3a, "tokenizer_basic_3a"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3b, "tokenizer_basic_3b"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3c, "tokenizer_basic_3c"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_3d, "tokenizer_basic_3d"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_0, "tokenizer_basic_compare_0"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_1, "tokenizer_basic_compare_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_2, "tokenizer_basic_compare_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_3, "tokenizer_basic_compare_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_4, "tokenizer_basic_compare_4"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_5, "tokenizer_basic_compare_5"); + exotic_add_test(&handle, &exotic_test_tokenizer_basic_compare_6, "tokenizer_basic_compare_6"); + exotic_add_test(&handle, &exotic_test_tokenizer_comment_1, "tokenizer_comment_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_comment_2, "tokenizer_comment_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_comment_3, "tokenizer_comment_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_1, "tokenizer_escape_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_2, "tokenizer_escape_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_3, "tokenizer_escape_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_4, "tokenizer_escape_4"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_5, "tokenizer_escape_5"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_6, "tokenizer_escape_6"); + exotic_add_test(&handle, &exotic_test_tokenizer_escape_7, "tokenizer_escape_7"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_1, "tokenizer_settings_1"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_2, "tokenizer_settings_2"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_3, "tokenizer_settings_3"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_4, "tokenizer_settings_4"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_5, "tokenizer_settings_5"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_6, "tokenizer_settings_6"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_7, "tokenizer_settings_7"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_8, "tokenizer_settings_8"); + exotic_add_test(&handle, &exotic_test_tokenizer_settings_9, "tokenizer_settings_9"); + exotic_add_test(&handle, &exotic_test_um_init_1, "um_init_1"); + exotic_add_test(&handle, &exotic_test_um_shutdown_1, "um_shutdown_1"); + exotic_add_test(&handle, &exotic_test_um_shutdown_2, "um_shutdown_2"); + exotic_add_test(&handle, &exotic_test_um_init_2, "um_init_2"); + exotic_add_test(&handle, &exotic_test_um_add_1, "um_add_1"); + exotic_add_test(&handle, &exotic_test_um_size_1, "um_size_1"); + exotic_add_test(&handle, &exotic_test_um_remove_1, "um_remove_1"); + exotic_add_test(&handle, &exotic_test_um_size_2, "um_size_2"); + exotic_add_test(&handle, &exotic_test_um_add_2, "um_add_2"); + exotic_add_test(&handle, &exotic_test_um_size_3, "um_size_3"); + exotic_add_test(&handle, &exotic_test_um_remove_2, "um_remove_2"); + exotic_add_test(&handle, &exotic_test_um_shutdown_4, "um_shutdown_4"); + + return exotic_run(&handle); +} + + +/* + * Exotic - C/C++ source code testing + * Copyright (c) 2007, Jan Vidar Krey + */ + +#include +#include +#include +#include + +static void exotic_version(); + +#ifndef __EXOTIC__STANDALONE__ +#include "autotest.h" +static void exotic_version() +{ + printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} +#endif + +struct exo_test_data +{ + exo_test_t test; + char* name; + struct exo_test_data* next; +}; + + +static void exotic_summary(struct exotic_handle* handle) +{ + int total = handle->pass + handle->fail; + int pass_rate = total ? (100*handle->pass / total) : 0; + int fail_rate = total ? (100*handle->fail / total) : 0; + + printf("\n"); + printf("--------------------------------------------\n"); + printf("Results:\n"); + printf(" * Total tests run: %8d\n", total); + printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); + printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); + printf("--------------------------------------------\n"); +} + + +static void exotic_help(const char* program) +{ + printf("Usage: %s [OPTIONS]\n\n", program); + printf("Options:\n"); + printf(" --help -h Show this message\n"); + printf(" --version -v Show version\n"); + printf(" --summary -s show only summary)\n"); + printf(" --fail -f show only test failures\n"); + printf(" --pass -p show only test passes\n"); + printf("\nExamples:\n"); + printf(" %s -s -f\n\n", program); +} + + +int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) +{ + int n; + if (!handle || !argv) return -1; + + memset(handle, 0, sizeof(struct exotic_handle)); + + for (n = 1; n < argc; n++) + { + if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) + { + exotic_help(argv[0]); + exit(0); + } + + if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) + { + exotic_version(); + exit(0); + } + + if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) + { + handle->config_show_summary = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) + { + handle->config_show_fail = cfg_on; + continue; + } + + if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) + { + handle->config_show_pass = cfg_on; + continue; + } + + fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); + exotic_help(argv[0]); + exit(0); + } + + if (handle->config_show_summary == cfg_on) + { + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + + } + else if (handle->config_show_pass == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else if (handle->config_show_fail == cfg_on) + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; + } + else + { + if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; + if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; + if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; + } + return 0; +} + + +void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) +{ + if (!handle) + { + fprintf(stderr, "exotic_add_test: failed, no handle!\n"); + exit(-1); + } + + struct exo_test_data* test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); + if (!test) + { + fprintf(stderr, "exotic_add_test: out of memory!\n"); + exit(-1); + } + + /* Create the test */ + memset(test, 0, sizeof(struct exo_test_data)); + test->test = func; + test->name = strdup(name); + + /* Register the test in the handle */ + if (!handle->first) + { + handle->first = test; + handle->current = test; + } + else + { + handle->current->next = test; + handle->current = test; + } +} + + +int exotic_run(struct exotic_handle* handle) +{ + struct exo_test_data* tmp = NULL; + + if (!handle) + { + fprintf(stderr, "Error: exotic is not initialized\n"); + return -1; + } + + handle->current = handle->first; + while (handle->current) + { + tmp = handle->current; + + if (handle->current->test()) { + if (handle->config_show_pass == cfg_on) printf("* PASS test '%s'\n", tmp->name); + handle->pass++; + } else { + if (handle->config_show_fail == cfg_on) printf("* FAIL test '%s'\n", tmp->name); + handle->fail++; + } + + handle->current = handle->current->next; + + free(tmp->name); + free(tmp); + } + + if (!handle->first) + { + printf("(No tests added)\n"); + } + + if (handle->config_show_summary == cfg_on) + exotic_summary(handle); + + return (handle->fail) ? handle->fail : 0; +} + + +static void exotic_version() { + printf("exotic 0.4-standalone\n\n"); + printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); + printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); +} diff --git a/autotest/update.sh b/autotest/update.sh new file mode 100755 index 0000000..5b2dba6 --- /dev/null +++ b/autotest/update.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +./exotic *.tcc > test.c + diff --git a/src/network/backend.c b/src/network/backend.c index e347b3e..678ab9d 100644 --- a/src/network/backend.c +++ b/src/network/backend.c @@ -146,6 +146,9 @@ int net_backend_process() return 0; } + // Process pending DNS results + net_dns_process(); + g_backend->handler.backend_process(g_backend->data, res); net_cleanup_process(g_backend->cleaner); diff --git a/src/network/dnsresolver.c b/src/network/dnsresolver.c new file mode 100644 index 0000000..1d5c597 --- /dev/null +++ b/src/network/dnsresolver.c @@ -0,0 +1,364 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "uhub.h" + +// #define DEBUG_LOOKUP_TIME 1 +#define MAX_CONCURRENT_JOBS 25 + +static struct net_dns_job* find_and_remove_job(struct net_dns_job* job); +static struct net_dns_result* find_and_remove_result(struct net_dns_job* job); + +struct net_dns_job +{ + net_dns_job_cb callback; + void* ptr; + + char* host; + int af; + +#ifdef DEBUG_LOOKUP_TIME + struct timeval time_start; + struct timeval time_finish; +#endif + + uhub_thread_t* thread_handle; +}; + +struct net_dns_result +{ + struct linked_list* addr_list; + struct net_dns_job* job; +}; + +static void free_job(struct net_dns_job* job) +{ + if (job) + { + hub_free(job->host); + hub_free(job); + } +} + +// NOTE: Any job manipulating the members of this +// struct must lock the mutex! +struct net_dns_subsystem +{ + struct linked_list* jobs; // currently running jobs + struct linked_list* results; // queue of results that are awaiting being delivered to callback. + uhub_mutex_t mutex; +}; + +static struct net_dns_subsystem* g_dns = NULL; + +void net_dns_initialize() +{ + LOG_TRACE("net_dns_initialize()"); + g_dns = (struct net_dns_subsystem*) hub_malloc_zero(sizeof(struct net_dns_subsystem)); + g_dns->jobs = list_create(); + g_dns->results = list_create(); + uhub_mutex_init(&g_dns->mutex); +} + +void net_dns_destroy() +{ + struct net_dns_job* job; + uhub_mutex_lock(&g_dns->mutex); + LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs)); + job = (struct net_dns_job*) list_get_first(g_dns->jobs); + uhub_mutex_unlock(&g_dns->mutex); + + while (job) + { + net_dns_job_cancel(job); + + uhub_mutex_lock(&g_dns->mutex); + job = (struct net_dns_job*) list_get_first(g_dns->jobs); + uhub_mutex_unlock(&g_dns->mutex); + } +} + +static void dummy_free(void* ptr) +{ +} + + +void net_dns_process() +{ + struct net_dns_result* result; + uhub_mutex_lock(&g_dns->mutex); + LOG_DUMP("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results)); + + for (result = (struct net_dns_result*) list_get_first(g_dns->results); result; result = (struct net_dns_result*) list_get_next(g_dns->results)) + { + struct net_dns_job* job = result->job; +#ifdef DEBUG_LOOKUP_TIME + struct timeval time_result; + timersub(&result->job->time_finish, &result->job->time_start, &time_result); + LOG_TRACE("DNS lookup took %d ms", (time_result.tv_sec * 1000) + (time_result.tv_usec / 1000)); +#endif + + // wait for the work thread to finish + uhub_thread_join(job->thread_handle); + + // callback - should we delete the data immediately? + if (job->callback(job, result)) + { + net_dns_result_free(result); + } + else + { + /* Caller wants to keep the result data, and + * thus needs to call net_dns_result_free() to release it later. + * We only clean up the job data here and keep the results intact. + */ + result->job = NULL; + free_job(job); + } + } + + list_clear(g_dns->results, &dummy_free); + uhub_mutex_unlock(&g_dns->mutex); +} + +static void* job_thread_resolve_name(void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) ptr; + struct addrinfo hints, *result, *it; + struct net_dns_result* dns_results; + int ret; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = job->af; + hints.ai_protocol = IPPROTO_TCP; + + ret = getaddrinfo(job->host, NULL, &hints, &result); + if (ret != 0) + { + LOG_WARN("getaddrinfo() failed: %s", gai_strerror(ret)); + return NULL; + } + + dns_results = (struct net_dns_result*) hub_malloc(sizeof(struct net_dns_result)); + dns_results->addr_list = list_create(); + dns_results->job = job; + + for (it = result; it; it = it->ai_next) + { + struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap)); + ipaddr->af = it->ai_family; + + if (it->ai_family == AF_INET) + { + struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr; + memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr)); + } + else if (it->ai_family == AF_INET6) + { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr; + memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr)); + } + else + { + LOG_WARN("getaddrinfo() returned result with unknown address family: %d", it->ai_family); + hub_free(ipaddr); + continue; + } + + LOG_WARN("getaddrinfo() - Address (%d): %s", ret++, ip_convert_to_string(ipaddr)); + list_append(dns_results->addr_list, ipaddr); + } + freeaddrinfo(result); + +#ifdef DEBUG_LOOKUP_TIME + gettimeofday(&job->time_finish, NULL); +#endif + + uhub_mutex_lock(&g_dns->mutex); + list_remove(g_dns->jobs, job); + list_append(g_dns->results, dns_results); + uhub_mutex_unlock(&g_dns->mutex); + + return dns_results; +} + + +extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job)); + job->host = strdup(host); + job->af = af; + job->callback = callback; + job->ptr = ptr; + +#ifdef DEBUG_LOOKUP_TIME + gettimeofday(&job->time_start, NULL); +#endif + + // FIXME - scheduling - what about a max number of threads? + uhub_mutex_lock(&g_dns->mutex); + job->thread_handle = uhub_thread_create(job_thread_resolve_name, job); + if (!job->thread_handle) + { + LOG_WARN("Unable to create thread"); + free_job(job); + job = NULL; + } + else + { + list_append(g_dns->jobs, job); + } + uhub_mutex_unlock(&g_dns->mutex); + return job; +} + + + +extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job)); +// job->host = strdup(addr); + job->af = ipaddr->af; + job->callback = callback; + job->ptr = ptr; + + +// if (pthread_create(&job->thread_handle, NULL, start_job, job)) +// { +// free_job(job); +// return NULL; +// } + return job; +} + +// NOTE: mutex must be locked first! +static struct net_dns_job* find_and_remove_job(struct net_dns_job* job) +{ + struct net_dns_job* it; + for (it = (struct net_dns_job*) list_get_first(g_dns->jobs); it; it = (struct net_dns_job*) list_get_next(g_dns->jobs)) + { + if (it == job) + { + list_remove(g_dns->jobs, it); + return job; + } + } + return NULL; +} + +// NOTE: mutex must be locked first! +static struct net_dns_result* find_and_remove_result(struct net_dns_job* job) +{ + struct net_dns_result* it; + for (it = (struct net_dns_result*) list_get_first(g_dns->results); it; it = (struct net_dns_result*) list_get_next(g_dns->results)) + { + if (it->job == job) + { + list_remove(g_dns->results, it); + return it; + } + } + return NULL; +} + + +extern int net_dns_job_cancel(struct net_dns_job* job) +{ + int retval = 0; + struct net_dns_result* res; + + LOG_TRACE("net_dns_job_cancel(): job=%p, name=%s", job, job->host); + + /* + * This function looks up the job in the jobs queue (which contains only active jobs) + * If that is found then the thread is cancelled, and the object is deleted. + * If the job was not found, that is either because it was an invalid job, or because + * it was already finished. At which point it was not deleted. + * If the job is already finished, but the result has not been delivered, then this + * deletes the result and the job. + */ + uhub_mutex_lock(&g_dns->mutex); + if (find_and_remove_job(job)) + { + // job still active - cancel it, then close it. + uhub_thread_cancel(job->thread_handle); + uhub_thread_join(job->thread_handle); + free_job(job); + retval = 1; + } + else if ((res = find_and_remove_result(job))) + { + // job already finished - close it. + uhub_thread_join(job->thread_handle); + net_dns_result_free(res); + } + uhub_mutex_unlock(&g_dns->mutex); + return retval; +} + +extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job) +{ + struct net_dns_result* res = NULL; + + // Wait for job to finish (if not already) + // This should make sure the job is removed from jobs and a result is + // present in results. + uhub_thread_join(job->thread_handle); + + // Remove the result in order to prevent the callback from being called. + uhub_mutex_lock(&g_dns->mutex); + res = find_and_remove_result(job); + uhub_assert(res != NULL); + res->job = NULL; + free_job(job); + uhub_mutex_unlock(&g_dns->mutex); + return res; +} + +void* net_dns_job_get_ptr(const struct net_dns_job* job) +{ + return job->ptr; +} + +extern size_t net_dns_result_size(const struct net_dns_result* res) +{ + return list_size(res->addr_list); +} + +extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res) +{ + struct ip_addr_encap* ipaddr = list_get_first(res->addr_list); + LOG_TRACE("net_dns_result_first() - Address: %s", ip_convert_to_string(ipaddr)); + return ipaddr; +} + +extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res) +{ + struct ip_addr_encap* ipaddr = list_get_next(res->addr_list); + LOG_TRACE("net_dns_result_next() - Address: %s", ip_convert_to_string(ipaddr)); + return ipaddr; +} + +extern void net_dns_result_free(struct net_dns_result* res) +{ + list_clear(res->addr_list, &hub_free); + list_destroy(res->addr_list); + free_job(res->job); + hub_free(res); +} diff --git a/src/network/dnsresolver.h b/src/network/dnsresolver.h new file mode 100644 index 0000000..6937422 --- /dev/null +++ b/src/network/dnsresolver.h @@ -0,0 +1,119 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef HAVE_UHUB_NETWORK_DNS_RESOLVER_H +#define HAVE_UHUB_NETWORK_DNS_RESOLVER_H + +struct net_dns_job; +struct net_dns_result; + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +/// Initialize the DNS subsystem +void net_dns_initialize(); + +/// Shutdown and destroy the DNS subsystem. This will cancel any pending DNS jobs. +void net_dns_destroy(); + +/// Process finished DNS lookups. +void net_dns_process(); + + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +/** + * Callback to be called when the DNS job has finished. + * If the name or address could not be resolved to an IP address (host not found, or found but has no address) + * then 'result' contains an empty list (@see net_dns_result_size()). + * If resolving caused an error then result is NULL. + * + * After this callback is called the job is considered done, and is freed. + * + * @param If 1 is returned then result is deleted immediately after the callback, + * otherwise the callback becomes owner of the result data which must be freed with net_dns_result_free(). + */ +typedef int (*net_dns_job_cb)(struct net_dns_job*, const struct net_dns_result* result); + +/** + * Resolve a hostname. + * + * @param host the hostname to be resolved. + * @param af the indicated address family. Should be AF_INET, AF_INET6 (or AF_UNSPEC - which means both AF_INET and AF_INET6. + * @param callback the callback to be called when the hostname has been resolved. + * @param ptr A user-defined pointer value. + * + * @return A resolve job handle if the job has successfully started or NULL if unable to start resolving. + */ +extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr); + +/** + * Perform a reverse DNS lookup for a given IP address. + * + * @see net_dns_gethostbyname() + * @return A resolve job handle if the job has successfully started or NULL if unable to start resolving. + */ +extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr); + +/** + * Cancel a DNS lookup job. + * + * It is only allowed to call this once after a job has been started (@see net_dns_gethostbyname(), @see net_dns_gethostbyaddr()) + * but before it has finished and delivered a to the callback address (@see net_dns_job_cb). + * + * @returns 1 if cancelled, or 0 if not cancelled (because the job was not found!) + */ +extern int net_dns_job_cancel(struct net_dns_job* job); + +/** + * Wait in a synchronous manner for a running DNS job to finished and + * return the result here. + * The job must be started with net_dns_gethostbyaddr/net_dns_gethostbyname + * and not finished or cancelled. + * + * If this function is invoked then the callback function will not be called and + * can therefore be NULL. + * + * + * struct net_dns_job* job = net_dns_gethostbyname("www.example.com", AF_INET, NULL, NULL); + * struct net_dns_result* net_dns_job_sync_wait(job); + * + */ +extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job); + +/** + * Returns the user specified pointer assigned to the resolving job +*/ +extern void* net_dns_job_get_ptr(const struct net_dns_job* job); + +/// Returns the number of results provided. This is 0 if the host could not be found (or has no matching IP address). +extern size_t net_dns_result_size(const struct net_dns_result*); + +/// Returns the first result (if net_dns_result_size > 0), or NULL if not first result exists. +extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*); + +/// Returns the next result or NULL if no next result exists. +extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*); + +/// When finished with the results +extern void net_dns_result_free(struct net_dns_result*); + +#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */ diff --git a/src/network/network.c b/src/network/network.c index f9b983f..327fe89 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -60,6 +60,9 @@ int net_initialize() #endif return -1; } + + net_dns_initialize(); + net_stats_initialize(); net_initialized = 1; return 0; @@ -94,8 +97,10 @@ int net_destroy() { LOG_TRACE("Shutting down network monitor"); + net_dns_destroy(); + net_backend_shutdown(); - + #ifdef SSL_SUPPORT net_ssl_library_shutdown(); #endif /* SSL_SUPPORT */ @@ -490,7 +495,6 @@ int net_socket_create(int af, int type, int protocol) } } #endif - return sd; } diff --git a/src/system.h b/src/system.h index e608489..98b1d85 100644 --- a/src/system.h +++ b/src/system.h @@ -34,6 +34,7 @@ #ifndef WINSOCK #define WINSOCK #endif +#define WINTHREAD_SUPPORT 1 #endif #if defined(__CYGWIN__) || defined(__MINGW32__) @@ -113,11 +114,13 @@ #define uhub_assert assert #ifdef __linux__ +#define POSIX_THREAD_SUPPORT #define USE_EPOLL #include #endif #ifdef BSD_LIKE +#define POSIX_THREAD_SUPPORT /* #define USE_KQUEUE #include @@ -279,6 +282,10 @@ typedef unsigned __int64 uint64_t; #define NEED_GETOPT #endif +#ifdef POSIX_THREAD_SUPPORT +#include +#endif + #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER) #define PLUGIN_API __declspec(dllexport) #else diff --git a/src/tools/adcclient.c b/src/tools/adcclient.c index a320da9..b7458e8 100644 --- a/src/tools/adcclient.c +++ b/src/tools/adcclient.c @@ -30,6 +30,7 @@ enum ADC_client_state { ps_none, /* Not connected */ + ps_dns, /* looking up name */ ps_conn, /* Connecting... */ ps_conn_ssl, /* SSL handshake */ ps_protocol, /* Have sent HSUP */ @@ -46,6 +47,13 @@ enum ADC_client_flags cflag_pipe = 4, }; +struct ADC_client_address +{ + enum Protocol { ADC, ADCS } protocol; + char* hostname; + uint16_t port; +}; + struct ADC_client { sid_t sid; @@ -59,8 +67,9 @@ struct ADC_client size_t timeout; struct net_connection* con; struct net_timer* timer; - struct sockaddr_in addr; - char* hub_address; + struct sockaddr_storage addr; + struct net_dns_job* dns_job; + struct ADC_client_address address; char* nick; char* desc; int flags; @@ -100,6 +109,7 @@ static void ADC_client_debug(struct ADC_client* client, const char* format, ...) static const char* ADC_client_state_string[] = { "ps_none", + "ps_dns", "ps_conn", "ps_conn_ssl", "ps_protocol", @@ -154,6 +164,9 @@ static void event_callback(struct net_connection* con, int events, void *arg) switch (client->state) { + case ps_dns: + break; + case ps_conn: if (events == NET_EVENT_TIMEOUT) { @@ -162,7 +175,7 @@ static void event_callback(struct net_connection* con, int events, void *arg) } if (events & NET_EVENT_WRITE) - ADC_client_connect(client, 0); + ADC_client_connect_internal(client); break; #ifdef SSL_SUPPORT @@ -493,7 +506,7 @@ void ADC_client_send(struct ADC_client* client, struct adc_message* msg) void ADC_client_send_info(struct ADC_client* client) { ADC_TRACE; - client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 64); + client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick); @@ -502,7 +515,17 @@ void ADC_client_send_info(struct ADC_client* client) adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc); } - adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION); + adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT " " VERSION); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SLOTS, 0); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_SIZE, 0); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_FILES, 0); + + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_NORMAL, 1); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_REGISTER, 0); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_OPERATOR, 0); + + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_DOWNLOAD_SPEED, 5 * 1024 * 1024); + adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024); adc_cid_pid(client); ADC_client_send(client, client->info); @@ -541,20 +564,31 @@ void ADC_client_destroy(struct ADC_client* client) adc_msg_free(client->info); hub_free(client->nick); hub_free(client->desc); - hub_free(client->hub_address); + hub_free(client->address.hostname); } int ADC_client_connect(struct ADC_client* client, const char* address) { ADC_TRACE; - if (!client->hub_address) + if (client->state == ps_none) { + // Parse address and start name resolving! if (!ADC_client_parse_address(client, address)) return 0; - + return 1; + } + else if (client->state == ps_dns) + { + // Done name resolving! client->callback(client, ADC_CLIENT_CONNECTING, 0); + ADC_client_set_state(client, ps_conn); } + return ADC_client_connect_internal(client); +} + +int ADC_client_connect_internal(struct ADC_client* client) +{ int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in)); if (ret == 0 || (ret == -1 && net_error() == EISCONN)) { @@ -632,19 +666,53 @@ void ADC_client_disconnect(struct ADC_client* client) } } +int ADC_client_dns_callback(struct net_dns_job* job, const struct net_dns_result* result) +{ + struct ADC_client* client = (struct ADC_client*) net_dns_job_get_ptr(job); + struct ip_addr_encap* ipaddr; + LOG_WARN("ADC_client_dns_callback(): result=%p (%d)", result, net_dns_result_size(result)); + + memset(&client->addr, 0, sizeof(client->addr)); + + ipaddr = net_dns_result_first(result); + switch (ipaddr->af) + { + case AF_INET: + { + struct sockaddr_in* addr4 = (struct sockaddr_in*) &client->addr; + addr4->sin_family = AF_INET; + addr4->sin_port = htons(client->address.port); + memcpy(&addr4->sin_addr, &ipaddr->internal_ip_data.in, sizeof(struct in_addr)); + break; + } + + case AF_INET6: + { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*) &client->addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(client->address.port); + memcpy(&addr6->sin6_addr, &ipaddr->internal_ip_data.in6, sizeof(struct in6_addr)); + break; + } + + default: + LOG_WARN("Unknown ipaddr!"); + } + + ADC_client_connect_internal(client); + return 1; +} + static int ADC_client_parse_address(struct ADC_client* client, const char* arg) { ADC_TRACE; + const char* hub_address = arg; char* split; int ssl = 0; - struct hostent* dns; - struct in_addr* addr; if (!arg) return 0; - client->hub_address = hub_strdup(arg); - /* Minimum length of a valid address */ if (strlen(arg) < 9) return 0; @@ -653,39 +721,33 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg) if (!strncmp(arg, "adc://", 6)) { client->flags &= ~cflag_ssl; + client->address.protocol = ADC; } else if (!strncmp(arg, "adcs://", 7)) { client->flags |= cflag_ssl; ssl = 1; + client->address.protocol = ADCS; } else return 0; /* Split hostname and port (if possible) */ - split = strrchr(client->hub_address + 6 + ssl, ':'); + hub_address = arg + 6 + ssl; + split = strrchr(hub_address, ':'); if (split == 0 || strlen(split) < 2 || strlen(split) > 6) return 0; /* Ensure port number is valid */ - int port = strtol(split+1, NULL, 10); - if (port <= 0 || port > 65535) + client->address.port = strtol(split+1, NULL, 10); + if (client->address.port <= 0 || client->address.port > 65535) return 0; - split[0] = 0; + client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]); - /* Resolve IP address (FIXME: blocking call) */ - dns = gethostbyname(client->hub_address + 6 + ssl); - if (dns) - { - addr = (struct in_addr*) dns->h_addr_list[0]; - } - - // Initialize the sockaddr struct. - memset(&client->addr, 0, sizeof(client->addr)); - client->addr.sin_family = AF_INET; - client->addr.sin_port = htons(port); - memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr)); + client->callback(client, ADC_CLIENT_NAME_LOOKUP, 0); + ADC_client_set_state(client, ps_dns); + client->dns_job = net_dns_gethostbyname(client->address.hostname, AF_UNSPEC, ADC_client_dns_callback, client); return 1; } diff --git a/src/tools/adcclient.h b/src/tools/adcclient.h index 17a07a6..47c067f 100644 --- a/src/tools/adcclient.h +++ b/src/tools/adcclient.h @@ -28,6 +28,7 @@ struct ADC_client; enum ADC_client_callback_type { + ADC_CLIENT_NAME_LOOKUP = 1000, ADC_CLIENT_CONNECTING = 1001, ADC_CLIENT_CONNECTED = 1002, ADC_CLIENT_DISCONNECTED = 1003, diff --git a/src/tools/admin.c b/src/tools/admin.c index 2c2ff05..0464dcb 100644 --- a/src/tools/admin.c +++ b/src/tools/admin.c @@ -91,6 +91,10 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type, { switch (type) { + case ADC_CLIENT_NAME_LOOKUP: + status("Looking up hostname..."); + break; + case ADC_CLIENT_CONNECTING: status("Connecting..."); break; @@ -107,6 +111,9 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type, status("SSL handshake."); break; + case ADC_CLIENT_SSL_OK: + break; + case ADC_CLIENT_LOGGING_IN: status("Logging in..."); break; diff --git a/src/uhub.h b/src/uhub.h index cb90b4c..4ba9672 100644 --- a/src/uhub.h +++ b/src/uhub.h @@ -68,12 +68,14 @@ extern "C" { #include "util/memory.h" #include "util/misc.h" #include "util/tiger.h" +#include "util/threads.h" #include "adc/sid.h" #include "adc/message.h" #include "network/network.h" #include "network/connection.h" +#include "network/dnsresolver.h" #include "network/ipcalc.h" #include "network/timeout.h" diff --git a/src/util/threads.c b/src/util/threads.c new file mode 100644 index 0000000..814037f --- /dev/null +++ b/src/util/threads.c @@ -0,0 +1,141 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "uhub.h" + +#ifdef POSIX_THREAD_SUPPORT +void uhub_mutex_init(uhub_mutex_t* mutex) +{ + pthread_mutex_init(mutex, NULL); +} + +void uhub_mutex_destroy(uhub_mutex_t* mutex) +{ + pthread_mutex_destroy(mutex); +} + +void uhub_mutex_lock(uhub_mutex_t* mutex) +{ + pthread_mutex_lock(mutex); +} + +void uhub_mutex_unlock(uhub_mutex_t* mutex) +{ + pthread_mutex_unlock(mutex); +} + +int uhub_mutex_trylock(uhub_mutex_t* mutex) +{ + int ret = pthread_mutex_trylock(mutex); + return (ret == 0); +} + +uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) +{ + uhub_thread_t* thread = (uhub_thread_t*) hub_malloc_zero(sizeof(uhub_thread_t)); + int ret = pthread_create(thread, NULL, start, arg); + if (ret == 0) + return thread; + hub_free(thread); + return NULL; +} + +void uhub_thread_cancel(uhub_thread_t* thread) +{ + pthread_cancel(thread); +} + +void* uhub_thread_join(uhub_thread_t* thread) +{ + void* ret = NULL; + pthread_join(thread, &ret); + hub_free(thread); + return ret; +} + + +#endif /* POSIX_THREAD_SUPPORT */ + +#ifdef WINTHREAD_SUPPORT + +struct winthread_data +{ + uhub_thread_t* handle; + uhub_thread_start start; + void* arg; +}; + +static DWORD WINAPI uhub_winthread_start(void* ptr) +{ + struct winthread_data* data = (struct winthread_data*) ptr; + DWORD ret = (DWORD) data->start(data->arg); + return ret; +} + +void uhub_mutex_init(uhub_mutex_t* mutex) +{ + InitializeCriticalSection(mutex); +} + +void uhub_mutex_destroy(uhub_mutex_t* mutex) +{ + DeleteCriticalSection(mutex); +} + +void uhub_mutex_lock(uhub_mutex_t* mutex) +{ + EnterCriticalSection(mutex); +} + +void uhub_mutex_unlock(uhub_mutex_t* mutex) +{ + LeaveCriticalSection(mutex); +} + +int uhub_mutex_trylock(uhub_mutex_t* mutex) +{ + return TryEnterCriticalSection(mutex); +} + +uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) +{ + struct winthread_data* thread = (struct winthread_data*) hub_malloc_zero(sizeof(struct winthread_data)); + thread->start = start; + thread->arg = arg; + thread->handle = CreateThread(NULL, 0, uhub_winthread_start, thread, 0, 0); + return thread; +} + +void uhub_thread_cancel(uhub_thread_t* thread) +{ + TerminateThread(thread->handle, 0); +} + +void* uhub_thread_join(uhub_thread_t* thread) +{ + void* ret = NULL; + DWORD exitCode; + WaitForSingleObject(thread->handle, INFINITE); + GetExitCodeThread(thread->handle, &exitCode); + ret = &exitCode; + CloseHandle(thread->handle); + hub_free(thread); + return ret; +} +#endif /* WINTHREAD_SUPPORT */ diff --git a/src/util/threads.h b/src/util/threads.h new file mode 100644 index 0000000..afc4359 --- /dev/null +++ b/src/util/threads.h @@ -0,0 +1,49 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2012, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef HAVE_UHUB_UTIL_THREADS_H +#define HAVE_UHUB_UTIL_THREADS_H + +typedef void*(*uhub_thread_start)(void*) ; + +#ifdef POSIX_THREAD_SUPPORT +typedef pthread_t uhub_thread_t; +typedef pthread_mutex_t uhub_mutex_t; +#endif + +#ifdef WINTHREAD_SUPPORT +struct winthread_data; +typedef struct winthread_data uhub_thread_t; +typedef CRITICAL_SECTION uhub_mutex_t; +#endif + +// Mutexes +extern void uhub_mutex_init(uhub_mutex_t* mutex); +extern void uhub_mutex_destroy(uhub_mutex_t* mutex); +extern void uhub_mutex_lock(uhub_mutex_t* mutex); +extern void uhub_mutex_unlock(uhub_mutex_t* mutex); +extern int uhub_mutex_trylock(uhub_mutex_t* mutex); + +// Threads +uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg); +void uhub_thread_cancel(uhub_thread_t* thread); +void* uhub_thread_join(uhub_thread_t* thread); + +#endif /* HAVE_UHUB_UTIL_THREADS_H */ +