diff --git a/AUTHORS b/AUTHORS index edb51af..b438741 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,7 +4,7 @@ Authors of uhub Jan Vidar Krey, Design and implementation E_zombie, Centos/RedHat customization scripts and heavy load testing FleetCommand, Hub topic plugin code -MiMic, Implemented user commands +MiMic, Implemented user commands, and plugins Boris Pek (tehnick), Debian/Ubuntu packaging Tillmann Karras (Tilka), Misc. bug fixes Yoran Heling (Yorhel), TLS/SSL handshake detection bugfixes diff --git a/CMakeLists.txt b/CMakeLists.txt index 40e996e..c1fb764 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ ## ## Makefile for uhub -## Copyright (C) 2007-2012, Jan Vidar Krey +## Copyright (C) 2007-2013, Jan Vidar Krey # -cmake_minimum_required (VERSION 2.8.3) +cmake_minimum_required (VERSION 2.8.2) project (uhub NONE) enable_language(C) @@ -13,15 +13,25 @@ set (UHUB_VERSION_MINOR 4) set (UHUB_VERSION_PATCH 1) set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src") +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/Modules) option(RELEASE "Release build, debug build if disabled" ON) +option(LOWLEVEL_DEBUG, "Enable low level debug messages." OFF) option(LINK_SUPPORT "Allow hub linking" OFF) option(SSL_SUPPORT "Enable SSL support" ON) option(USE_OPENSSL "Use OpenSSL's SSL support" ON ) -option(SQLITE_SUPPORT "Enable SQLite support" ON) +option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF) option(ADC_STRESS "Enable the stress tester client" OFF) find_package(Git) +find_package(Sqlite3) + +include(TestBigEndian) + +TEST_BIG_ENDIAN(BIGENDIAN) +if (BIGENDIAN) + add_definitions(-DARCH_BIGENDIAN) +endif() if (SSL_SUPPORT) if (USE_OPENSSL) @@ -34,11 +44,19 @@ if (SSL_SUPPORT) endif() endif() +if (SYSTEMD_SUPPORT) + INCLUDE(FindPkgConfig) + pkg_search_module(SD_DAEMON REQUIRED libsystemd-daemon) + pkg_search_module(SD_JOURNAL REQUIRED libsystemd-journal) +endif() + if (MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() include_directories("${PROJECT_SOURCE_DIR}") +include_directories(${SQLITE3_INCLUDE_DIRS}) +link_directories(${SQLITE3_LIBRARY_DIRS}) file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c) list (REMOVE_ITEM uhub_SOURCES @@ -68,25 +86,18 @@ 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_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c) add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c) add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c) add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${PROJECT_SOURCE_DIR}/adc/sid.c) add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c ) add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c ) +add_library(mod_chat_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c ) add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c) add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c) add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c) - -if (SQLITE_SUPPORT) - add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c) - add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c) - - target_link_libraries(mod_auth_sqlite sqlite3 utils) - target_link_libraries(uhub-passwd sqlite3 utils) - set_target_properties(mod_auth_sqlite PROPERTIES PREFIX "") -endif() - +add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c) if(WIN32) target_link_libraries(uhub ws2_32) @@ -100,18 +111,23 @@ set_target_properties( mod_welcome mod_logging mod_auth_simple + mod_auth_sqlite mod_chat_history + mod_chat_history_sqlite mod_chat_only mod_no_guest_downloads mod_topic PROPERTIES PREFIX "") target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils) +target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} 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) +target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils) target_link_libraries(mod_chat_history utils) +target_link_libraries(mod_chat_history_sqlite ${SQLITE3_LIBRARIES} utils) target_link_libraries(mod_no_guest_downloads utils) target_link_libraries(mod_chat_only utils) target_link_libraries(mod_logging utils) @@ -120,6 +136,7 @@ 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) @@ -175,24 +192,37 @@ if(SSL_SUPPORT) endif() endif() +if (SYSTEMD_SUPPORT) + target_link_libraries(uhub ${SD_DAEMON_LIBRARIES}) + target_link_libraries(uhub ${SD_JOURNAL_LIBRARIES}) + target_link_libraries(test ${SD_DAEMON_LIBRARIES}) + target_link_libraries(test ${SD_JOURNAL_LIBRARIES}) + target_link_libraries(uhub-passwd ${SD_JOURNAL_LIBRARIES}) + target_link_libraries(uhub-admin ${SD_JOURNAL_LIBRARIES}) + include_directories(${SD_DAEMON_INCLUDE_DIRS}) + include_directories(${SD_JOURNAL_INCLUDE_DIRS}) + add_definitions(-DSYSTEMD) +endif() + configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h") mark_as_advanced(FORCE CMAKE_BUILD_TYPE) if (RELEASE) set(CMAKE_BUILD_TYPE Release) + add_definitions(-DNDEBUG) else() set(CMAKE_BUILD_TYPE Debug) - # add_definitions(-DDEBUG) + add_definitions(-DDEBUG) +endif() + +if (LOWLEVEL_DEBUG) + add_definitions(-DLOWLEVEL_DEBUG) endif() if (UNIX) - install( TARGETS uhub RUNTIME DESTINATION bin ) - install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL ) + install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin ) + install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL ) install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL ) - - if (SQLITE_SUPPORT) - install( TARGETS uhub-passwd RUNTIME DESTINATION bin ) - endif() endif() diff --git a/autotest/test.c b/autotest/test.c index aac3809..315690e 100644 --- a/autotest/test.c +++ b/autotest/test.c @@ -516,6 +516,15 @@ int main(int argc, char** argv) 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_remove_first_1_1, "list_remove_first_1_1"); + exotic_add_test(&handle, &exotic_test_list_remove_first_1_2, "list_remove_first_1_2"); + exotic_add_test(&handle, &exotic_test_list_remove_first_1_3, "list_remove_first_1_3"); + exotic_add_test(&handle, &exotic_test_list_remove_first_1_4, "list_remove_first_1_4"); + exotic_add_test(&handle, &exotic_test_list_remove_first_1_5, "list_remove_first_1_5"); + exotic_add_test(&handle, &exotic_test_list_append_list_1, "list_append_list_1"); + exotic_add_test(&handle, &exotic_test_list_append_list_2, "list_append_list_2"); + exotic_add_test(&handle, &exotic_test_list_append_list_3, "list_append_list_3"); + exotic_add_test(&handle, &exotic_test_list_clear_list_last, "list_clear_list_last"); 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"); @@ -951,7 +960,6 @@ int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) { struct exo_test_data* test; - if (!handle) { fprintf(stderr, "exotic_add_test: failed, no handle!\n"); diff --git a/autotest/test_list.tcc b/autotest/test_list.tcc index 707d18a..fd1b6f9 100644 --- a/autotest/test_list.tcc +++ b/autotest/test_list.tcc @@ -1,10 +1,16 @@ #include static struct linked_list* list = NULL; +static struct linked_list* list2 = NULL; static char A[2] = { 'A', 0 }; static char B[2] = { 'B', 0 }; static char C[2] = { 'C', 0 }; +static char A2[2] = { 'a', 0 }; +static char B2[2] = { 'b', 0 }; +static char C2[2] = { 'c', 0 }; + + static void null_free(void* ptr) { @@ -124,6 +130,82 @@ EXO_TEST(list_clear, { return list->size == 0 && list->first == 0 && list->last == 0 && list->iterator == 0; }); +static int g_remove_flag = 0; +static void null_free_inc_flag(void* ptr) +{ + (void) ptr; + g_remove_flag++; +} + +EXO_TEST(list_remove_first_1_1, +{ + list_append(list, A); + list_append(list, B); + list_append(list, C); + return list->size == 3; +}); + +EXO_TEST(list_remove_first_1_2, +{ + g_remove_flag = 0; + list_remove_first(list, null_free_inc_flag); + return list->size == 2 && g_remove_flag == 1; +}); + +EXO_TEST(list_remove_first_1_3, +{ + list_remove_first(list, NULL); + return list->size == 1; +}); + +EXO_TEST(list_remove_first_1_4, +{ + list_remove_first(list, NULL); + return list->size == 0; +}); + + +EXO_TEST(list_remove_first_1_5, +{ + list_remove_first(list, NULL); + return list->size == 0; +}); + + +EXO_TEST(list_append_list_1, +{ + list_append(list, A); + list_append(list, B); + list_append(list, C); + list2 = list_create(); + list_append(list2, A2); + list_append(list2, B2); + list_append(list2, C2); + return list->size == 3 && list2->size == 3; +}); + +EXO_TEST(list_append_list_2, +{ + list_append_list(list, list2); + return list->size == 6 && list2->size == 0; +}); + +EXO_TEST(list_append_list_3, +{ + list_destroy(list2); + return list_get_index(list, 0) == A && + list_get_index(list, 1) == B && + list_get_index(list, 2) == C && + list_get_index(list, 3) == A2 && + list_get_index(list, 4) == B2 && + list_get_index(list, 5) == C2; +}); + +EXO_TEST(list_clear_list_last, +{ + list_clear(list, &null_free); +}); + EXO_TEST(list_destroy_1, { list_destroy(list); diff --git a/cmake/Modules/FindSqlite3.cmake b/cmake/Modules/FindSqlite3.cmake new file mode 100644 index 0000000..9e08d6b --- /dev/null +++ b/cmake/Modules/FindSqlite3.cmake @@ -0,0 +1,77 @@ +# - Try to find sqlite3 +# Find sqlite3 headers, libraries and the answer to all questions. +# +# SQLITE3_FOUND True if sqlite3 got found +# SQLITE3_INCLUDEDIR Location of sqlite3 headers +# SQLITE3_LIBRARIES List of libaries to use sqlite3 +# SQLITE3_DEFINITIONS Definitions to compile sqlite3 +# +# Copyright (c) 2007 Juha Tuomala +# Copyright (c) 2007 Daniel Gollub +# Copyright (c) 2007 Alban Browaeys +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + +INCLUDE( FindPkgConfig ) +# Take care about sqlite3.pc settings +IF ( Sqlite3_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "REQUIRED" ) +ELSE ( Sqlite3_FIND_REQUIRED ) + SET( _pkgconfig_REQUIRED "" ) +ENDIF ( Sqlite3_FIND_REQUIRED ) + +IF ( SQLITE3_MIN_VERSION ) + PKG_SEARCH_MODULE( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3>=${SQLITE3_MIN_VERSION} ) +ELSE ( SQLITE3_MIN_VERSION ) + pkg_search_module( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3 ) +ENDIF ( SQLITE3_MIN_VERSION ) + + +# Look for sqlite3 include dir and libraries w/o pkgconfig +IF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND ) + FIND_PATH( _sqlite3_include_DIR sqlite3.h + PATHS + /opt/local/include/ + /sw/include/ + /usr/local/include/ + /usr/include/ + ) + FIND_LIBRARY( _sqlite3_link_DIR sqlite3 + PATHS + /opt/local/lib + /sw/lib + /usr/lib + /usr/local/lib + /usr/lib64 + /usr/local/lib64 + /opt/lib64 + ) + IF ( _sqlite3_include_DIR AND _sqlite3_link_DIR ) + SET ( _sqlite3_FOUND TRUE ) + ENDIF ( _sqlite3_include_DIR AND _sqlite3_link_DIR ) + + + IF ( _sqlite3_FOUND ) + SET ( SQLITE3_INCLUDE_DIRS ${_sqlite3_include_DIR} ) + SET ( SQLITE3_LIBRARIES ${_sqlite3_link_DIR} ) + ENDIF ( _sqlite3_FOUND ) + + # Report results + IF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) + SET( SQLITE3_FOUND 1 ) + MESSAGE( STATUS "Found sqlite3: ${SQLITE3_LIBRARIES} ${SQLITE3_INCLUDE_DIRS}" ) + ELSE ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) + IF ( Sqlite3_FIND_REQUIRED ) + MESSAGE( SEND_ERROR "Could NOT find sqlite3" ) + ELSE ( Sqlite3_FIND_REQUIRED ) + MESSAGE( STATUS "Could NOT find sqlite3" ) + ENDIF ( Sqlite3_FIND_REQUIRED ) + ENDIF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND ) + +ENDIF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND ) + +# Hide advanced variables from CMake GUIs +MARK_AS_ADVANCED( SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS ) diff --git a/src/adc/adcconst.h b/src/adc/adcconst.h index c4c5c8d..c723895 100644 --- a/src/adc/adcconst.h +++ b/src/adc/adcconst.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/adc/message.c b/src/adc/message.c index cfabb3f..3ca2095 100644 --- a/src/adc/message.c +++ b/src/adc/message.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -168,24 +168,24 @@ int adc_msg_get_arg_offset(struct adc_message* msg) { if (!msg || !msg->cache) return -1; - + switch (msg->cache[0]) { /* These *SHOULD* never be seen on a hub */ case 'U': case 'C': return 4; /* Actually: 4 + strlen(cid). */ - + case 'I': case 'H': return 4; - + case 'B': return 9; - + case 'F': return (10 + (list_size(msg->feature_cast_include)*5) + (list_size(msg->feature_cast_exclude)*5)); - + case 'D': case 'E': return 14; @@ -200,10 +200,10 @@ int adc_msg_is_empty(struct adc_message* msg) if (offset == -1) return -1; - + if ((msg->length - 1) == (size_t) offset) return 1; - + return 0; } @@ -283,23 +283,19 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd) if (cmd->feature_cast_include) { copy->feature_cast_include = list_create(); - tmp = list_get_first(cmd->feature_cast_include); - while (tmp) + LIST_FOREACH(char*, tmp, cmd->feature_cast_include, { list_append(copy->feature_cast_include, hub_strdup(tmp)); - tmp = list_get_next(cmd->feature_cast_include); - } + }); } if (cmd->feature_cast_exclude) { copy->feature_cast_exclude = list_create(); - tmp = list_get_first(cmd->feature_cast_exclude); - while (tmp) + LIST_FOREACH(char*, tmp, cmd->feature_cast_exclude, { list_append(copy->feature_cast_exclude, hub_strdup(tmp)); - tmp = list_get_next(cmd->feature_cast_exclude); - } + }); } ADC_MSG_ASSERT(copy); @@ -311,17 +307,17 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd) struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length) { struct adc_message* command = adc_msg_parse(line, length); - + if (!command) return 0; - + if (command->source && (!u || command->source != u->id.sid)) { LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0)); adc_msg_free(command); return 0; } - + return command; } @@ -335,7 +331,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length) int ok = 1; int need_terminate = 0; struct linked_list* feature_cast_list; - + if (command == NULL) return NULL; /* OOM */ @@ -599,14 +595,14 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2] int found = 0; int arg_offset = adc_msg_get_arg_offset(cmd); size_t temp_len = 0; - + adc_msg_unterminate(cmd); - + start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3); while (start) { endInfo = &cmd->cache[cmd->length]; - + if (&start[0] < &endInfo[0]) { end = memchr(&start[1], ' ', &endInfo[0]-&start[1]); @@ -615,13 +611,13 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2] { end = NULL; } - + if (end) { - + temp_len = &end[0] - &start[0]; // strlen(start); endlen = strlen(end); - + memmove(start, end, endlen); start[endlen] = '\0'; found++; @@ -636,9 +632,9 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2] } start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3); } - + adc_msg_terminate(cmd); - + return found; } @@ -687,7 +683,7 @@ char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2]) length = &end[0] - &start[0]; argument = hub_strndup(start, length); - + if (length > 0 && argument[length-1] == '\n') { argument[length-1] = 0; diff --git a/src/adc/message.h b/src/adc/message.h index 31b4e7f..02ec4fb 100644 --- a/src/adc/message.h +++ b/src/adc/message.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -229,7 +229,7 @@ void adc_msg_unterminate(struct adc_message* cmd); /** * @return the offset for the first command argument in msg->cache. * or -1 if the command is not understood. - * NOTE: for 'U' and 'C' commands (normally not seen by hubs), + * NOTE: for 'U' and 'C' commands (normally not seen by hubs), * this returns 4. Should be 4 + lengthOf(cid). */ int adc_msg_get_arg_offset(struct adc_message* msg); diff --git a/src/adc/sid.c b/src/adc/sid.c index f334516..4e4fdbd 100644 --- a/src/adc/sid.c +++ b/src/adc/sid.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -47,7 +47,7 @@ sid_t string_to_sid(const char* sid) sid_t nsid = 0; sid_t n, x; sid_t factors[] = { 32768, 1024, 32, 1}; - + if (!sid || strlen(sid) != 4) return 0; for (n = 0; n < 4; n++) { diff --git a/src/adc/sid.h b/src/adc/sid.h index 0def755..ff55a89 100644 --- a/src/adc/sid.h +++ b/src/adc/sid.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/auth.c b/src/core/auth.c index 6c83730..88affbe 100644 --- a/src/core/auth.c +++ b/src/core/auth.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -26,20 +26,20 @@ static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count) { char* data; - + if (!strncmp(line, cmd, strlen(cmd))) { data = &line[strlen(cmd)]; data[0] = '\0'; data++; - + data = strip_white_space(data); if (!*data) { LOG_FATAL("ACL parse error on line %d", line_count); return -1; } - + list_append(list, hub_strdup(data)); LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd); return 1; @@ -190,18 +190,18 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle) { int ret; memset(handle, 0, sizeof(struct acl_handle)); - + handle->users = list_create(); handle->users_denied = list_create(); handle->users_banned = list_create(); handle->cids = list_create(); handle->networks = list_create(); handle->nat_override = list_create(); - + if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override) { LOG_FATAL("acl_initialize: Out of memory"); - + list_destroy(handle->users); list_destroy(handle->users_denied); list_destroy(handle->users_banned); @@ -210,11 +210,11 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle) list_destroy(handle->nat_override); return -1; } - + if (config) { if (!*config->file_acl) return 0; - + ret = file_read_lines(config->file_acl, handle, &acl_parse_line); if (ret == -1) return -1; @@ -249,26 +249,26 @@ int acl_shutdown(struct acl_handle* handle) list_clear(handle->users, &acl_free_access_info); list_destroy(handle->users); } - + if (handle->users_denied) { list_clear(handle->users_denied, &hub_free); list_destroy(handle->users_denied); } - + if (handle->users_banned) { list_clear(handle->users_banned, &hub_free); list_destroy(handle->users_banned); } - - + + if (handle->cids) { list_clear(handle->cids, &hub_free); list_destroy(handle->cids); } - + if (handle->networks) { list_clear(handle->networks, &acl_free_ip_info); @@ -330,13 +330,11 @@ struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name) } #define STR_LIST_CONTAINS(LIST, STR) \ - str = (char*) list_get_first(LIST); \ - while (str) \ + LIST_FOREACH(char*, str, LIST, \ { \ if (strcasecmp(str, STR) == 0) \ return 1; \ - str = (char*) list_get_next(LIST); \ - } \ + }); \ return 0 int acl_is_cid_banned(struct acl_handle* handle, const char* data) @@ -400,34 +398,28 @@ int acl_user_unban_cid(struct acl_handle* handle, const char* cid) int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address) { struct ip_addr_encap raw; - struct ip_range* info = (struct ip_range*) list_get_first(handle->networks); + struct ip_range* info; + ip_convert_to_binary(ip_address, &raw); - - while (info) + LIST_FOREACH(struct ip_range*, info, handle->networks, { if (ip_in_range(&raw, info)) - { return 1; - } - info = (struct ip_range*) list_get_next(handle->networks); - } + }); return 0; } int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address) { struct ip_addr_encap raw; - struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override); + struct ip_range* info; + ip_convert_to_binary(ip_address, &raw); - - while (info) + LIST_FOREACH(struct ip_range*, info, handle->nat_override, { if (ip_in_range(&raw, info)) - { return 1; - } - info = (struct ip_range*) list_get_next(handle->nat_override); - } + }); return 0; } @@ -476,10 +468,10 @@ int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN); password_len = strlen(access->password); - + memcpy(&buf[0], access->password, password_len); memcpy(&buf[password_len], raw_challenge, TIGERSIZE); - + tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res); base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc); password_calc[MAX_CID_LEN] = 0; diff --git a/src/core/auth.h b/src/core/auth.h index 11fc978..e2aee23 100644 --- a/src/core/auth.h +++ b/src/core/auth.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/command_parser.c b/src/core/command_parser.c index c940f93..01b8b15 100644 --- a/src/core/command_parser.c +++ b/src/core/command_parser.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -26,7 +26,7 @@ static void hub_command_args_free(struct hub_command* cmd) if (!cmd->args) return; - for (data = (struct hub_command_arg_data*) list_get_first(cmd->args); data; data = (struct hub_command_arg_data*) list_get_next(cmd->args)) + LIST_FOREACH(struct hub_command_arg_data*, data, cmd->args, { switch (data->type) { @@ -39,7 +39,7 @@ static void hub_command_args_free(struct hub_command* cmd) default: break; } - } + }); list_clear(cmd->args, hub_free); list_destroy(cmd->args); @@ -77,8 +77,7 @@ static enum command_parse_status command_extract_arguments(struct hub_info* hub, if (greedy) { size = 1; - for (tmp = (char*) list_get_first(tokens); tmp; tmp = (char*) list_get_next(tokens)) - size += (strlen(tmp) + 1); + LIST_FOREACH(char*, tmp, tokens, { size += (strlen(tmp) + 1); }); token = hub_malloc_zero(size); while ((tmp = list_get_first(tokens))) diff --git a/src/core/command_parser.h b/src/core/command_parser.h index 34547e8..13dc64c 100644 --- a/src/core/command_parser.h +++ b/src/core/command_parser.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/commands.c b/src/core/commands.c index 7844381..58f84cb 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -98,14 +98,14 @@ struct command_handle* command_handler_lookup(struct command_base* cbase, const struct command_handle* handler = NULL; size_t prefix_len = strlen(prefix); - for (handler = (struct command_handle*) list_get_first(cbase->handlers); handler; handler = (struct command_handle*) list_get_next(cbase->handlers)) + LIST_FOREACH(struct command_handle*, handler, cbase->handlers, { if (prefix_len != handler->length) continue; if (!memcmp(prefix, handler->prefix, handler->length)) return handler; - } + }); return NULL; } @@ -292,7 +292,7 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc { cbuf_append(buf, "Available commands:\n"); - for (command = (struct command_handle*) list_get_first(cbase->handlers); command; command = (struct command_handle*) list_get_next(cbase->handlers)) + LIST_FOREACH(struct command_handle*, command, cbase->handlers, { if (command_is_available(command, user->credentials)) { @@ -301,7 +301,7 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc cbuf_append(buf, " "); cbuf_append_format(buf, " - %s\n", command->description); } - } + }); } else { @@ -432,12 +432,10 @@ static int command_whoip(struct command_base* cbase, struct hub_user* user, stru buf = cbuf_create(128 + ((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret)); cbuf_append_format(buf, "*** %s: Found %d match%s:\n", cmd->prefix, ret, ((ret != 1) ? "es" : "")); - u = (struct hub_user*) list_get_first(users); - while (u) + LIST_FOREACH(struct hub_user*, u, users, { cbuf_append_format(buf, "%s (%s)\n", u->id.nick, user_get_address(u)); - u = (struct hub_user*) list_get_next(users); - } + }); cbuf_append(buf, "\n"); send_message(cbase, user, buf); @@ -462,8 +460,7 @@ static int command_broadcast(struct command_base* cbase, struct hub_user* user, memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid)); memcpy(pm_flag + 2, from_sid, sizeof(from_sid)); - target = (struct hub_user*) list_get_first(cbase->hub->users->list); - while (target) + LIST_FOREACH(struct hub_user*, target, cbase->hub->users->list, { if (target != user) { @@ -480,8 +477,7 @@ static int command_broadcast(struct command_base* cbase, struct hub_user* user, route_to_user(cbase->hub, target, command); adc_msg_free(command); } - target = (struct hub_user*) list_get_next(cbase->hub->users->list); - } + }); cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : "")); send_message(cbase, user, buf); @@ -513,8 +509,7 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct command_status(cbase, user, cmd, buf); buf = cbuf_create(MAX_HELP_LINE); - log = (struct hub_logout_info*) list_get_first(messages); - while (log) + LIST_FOREACH(struct hub_logout_info*, log, messages, { const char* address = ip_convert_to_string(&log->addr); int show = 0; @@ -538,8 +533,7 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct send_message(cbase, user, buf); buf = cbuf_create(MAX_HELP_LINE); } - log = (struct hub_logout_info*) list_get_next(messages); - } + }); if (search_len) { diff --git a/src/core/commands.h b/src/core/commands.h index fab6ff0..76788d6 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/config.c b/src/core/config.c index 21ad102..56633f7 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -76,7 +76,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data) struct hub_config* config = (struct hub_config*) ptr_data; strip_off_ini_line_comments(line, line_count); - + if (!*line) return 0; LOG_DUMP("config_parse_line(): '%s'", line); diff --git a/src/core/config.h b/src/core/config.h index 889941b..cbac319 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/config.pl b/src/core/config.pl deleted file mode 100755 index cf88449..0000000 --- a/src/core/config.pl +++ /dev/null @@ -1,289 +0,0 @@ -#!/usr/bin/perl -w - -use strict; -use XML::DOM; - -sub write_c_header(@); -sub write_sql_dump(@); -sub get_data($); - -my $dump_to_sql = 0; - -# initialize parser and read the file -my $input = "./config.xml"; -my $parser = new XML::DOM::Parser; -my $tree = $parser->parsefile($input) || die "Unable to parse XML file."; - -# Get data -my $nodes = $tree->getElementsByTagName("option"); -my @options = (); -for (my $i = 0; $i < $nodes->getLength; $i++) -{ - my @data = get_data($nodes->item($i)); - push @options, \@data; -} - -write_c_header(@options); -write_sql_dump(@options) if ($dump_to_sql); - -my $config_defaults = "void config_defaults(struct hub_config* config)\n{\n"; -my $config_apply = "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n"; -my $config_free = "void free_config(struct hub_config* config)\n{\n"; -my $config_dump = "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n"; - -foreach my $option (@options) -{ - my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check, $ifdef) = @$option; - my $string = ($type =~ /(string|file|message)/); - my $min = undef; - my $max = undef; - my $regexp = undef; - - if (defined $check) - { - $min = $check->getAttribute("min"); - $max = $check->getAttribute("max"); - $regexp = $check->getAttribute("regexp"); - - $max = undef if ($max eq ""); - $min = undef if ($min eq ""); - $regexp = undef if ($regexp eq ""); - } - - $config_defaults .= "#ifdef $ifdef\n" if ($ifdef ne ""); - $config_defaults .= "\tconfig->$name = "; - $config_defaults .= "hub_strdup(\"" if ($string); - $config_defaults .= $default; - $config_defaults .= "\")" if ($string); - $config_defaults .= ";\n"; - $config_defaults .= "#endif /* $ifdef */\n" if ($ifdef ne ""); - - $config_apply .= "#ifdef $ifdef\n" if ($ifdef ne ""); - $config_apply .= "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n"; - - if ($type eq "int") - { - $config_apply .= "\t\tmin = $min;\n" if (defined $min); - $config_apply .= "\t\tmax = $max;\n" if (defined $max); - $config_apply .= "\t\tif (!apply_integer(key, data, &config->$name, "; - if (defined $min) { $config_apply .= "&min"; } else { $config_apply .= "0"; } - $config_apply .= ", "; - if (defined $max) { $config_apply .= "&max"; } else { $config_apply .= "0"; } - $config_apply .= "))\n"; - } - elsif ($type eq "boolean") - { - $config_apply .= "\t\tif (!apply_boolean(key, data, &config->$name))\n"; - } - elsif ($string) - { - $config_apply .="\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n"; - } - - $config_apply .= "\t\t{\n" . - "\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" . - "\t\t\treturn -1;\n" . - "\t\t}\n" . - "\t\treturn 0;\n" . - "\t}\n"; - $config_apply .= "#endif /* $ifdef */\n" if ($ifdef ne ""); - $config_apply .= "\n"; - - if ($string) - { - $config_free .= "#ifdef $ifdef\n" if ($ifdef ne ""); - $config_free .= "\thub_free(config->" . $name . ");\n"; - $config_free .= "#endif /* $ifdef */\n" if ($ifdef ne ""); - $config_free .= "\n"; - } - - my $out = "%s"; - my $val = "config->$name"; - my $test = "config->$name != $default"; - - $out = "%d" if ($type eq "int"); - $val = "config->$name ? \"yes\" : \"no\"" if ($type eq "boolean"); - - if ($string) - { - $out = "\\\"%s\\\""; - $test = "strcmp(config->$name, \"$default\") != 0"; - } - - $config_dump .= "#ifdef $ifdef\n" if ($ifdef ne ""); - $config_dump .= "\tif (!ignore_defaults || $test)\n"; - $config_dump .= "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n"; - $config_dump .= "#endif /* $ifdef */\n" if ($ifdef ne ""); - $config_dump .= "\n"; -} - -$config_apply .= "\t/* Still here -- unknown directive */\n"; -$config_apply .= "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n"; -$config_apply .= "\treturn -1;\n"; -$config_apply .= "}\n\n"; -$config_defaults .= "}\n\n"; -$config_free .= "}\n\n"; -$config_dump .= "}\n\n"; - -open GENIMPL, ">gen_config.c" || die "Unable to write source file"; -print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n"; -print GENIMPL $config_defaults; -print GENIMPL $config_apply; -print GENIMPL $config_free; -print GENIMPL $config_dump; - - -sub get_data($) -{ - my $p = shift; - - my $short = ""; - my $example = ""; - my $description = ""; - my $since = ""; - my $ifdef = ""; - - $short = $p->getElementsByTagName("short")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("short")->getLength()); - $since = $p->getElementsByTagName("since")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("since")->getLength()); - $example = $p->getElementsByTagName("example")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("example")->getLength()); - $description = $p->getElementsByTagName("description")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("description")->getLength()); - my $check = $p->getElementsByTagName("check")->item(0); - $ifdef = $p->getElementsByTagName("ifdef")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("ifdef")->getLength()); - - my @data = ( - $p->getAttribute("type"), - $p->getAttribute("name"), - $p->getAttribute("default"), - $p->getAttribute("advanced"), - $short, - $description, - $since, - $example, - $check, - $ifdef - ); - return @data; -} - -# Write header file -sub write_c_header(@) -{ - my @data = @_; - - open GENHEAD, ">gen_config.h" || die "Unable to write header file"; - print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n"; - print GENHEAD "struct hub_config\n{\n"; - - foreach my $option (@data) - { - my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check, $ifdef) = @$option; - - my $string = ($type =~ /(string|file|message)/); - - print GENHEAD "#ifdef $ifdef\n" if ($ifdef ne ""); - - print GENHEAD "\t"; - print GENHEAD "int " if ($type eq "int"); - print GENHEAD "int " if ($type eq "boolean"); - print GENHEAD "char*" if ($string); - print GENHEAD " " . $name . ";"; - - my $comment = ""; - if ($type eq "message") - { - $comment = "\"" . $default . "\""; - } - elsif (defined $short && length $short > 0) - { - $comment = $short; - if (defined $default) - { - $comment .= " (default: "; - $comment .= "\"" if ($string); - $comment .= $default; - $comment .= "\"" if ($string); - $comment .= ")"; - } - } - - if (length $comment > 0) - { - my $pad = ""; - for (my $i = length $name; $i < 32; $i++) - { - $pad .= " "; - } - $comment = $pad . "/*<<< " . $comment . " */"; - } - print GENHEAD $comment . "\n"; - print GENHEAD "#endif /* $ifdef */\n" if ($ifdef ne ""); - } - - print GENHEAD "};\n\n"; -} - - -sub write_sql_dump(@) -{ - my @data = @_; - - # Write SQL dump code - open GENSQL, ">gen_config.sql" || die "Unable to write SQL dump"; - print GENSQL "START TRANSACTION;\n\n - DROP TABLE uhub_config IF EXISTS;\n\n - CREATE TABLE uhub_config ( - name VARCHAR(32) UNIQUE NOT NULL, - defaultValue TINYTEXT NOT NULL, - description LONGTEXT NOT NULL, - type TINYTEXT NOT NULL, - advanced BOOLEAN, - example LONGTEXT, - since TINYTEXT - );\n\n"; - - foreach my $option (@data) - { - my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check, $ifdef) = @$option; - - if ($type =~ /(string|file|message)/ ) - { - $default = "\\\"$default\\\""; - } - - $desc =~ s/\"/\\\"/g; - $type =~ s/^int$/integer/; - - my $stmt = "INSERT INTO uhub_config VALUES("; - $stmt .= "\"$name\", "; - $stmt .= "\"$default\", "; - $stmt .= "\"$desc\", "; - $stmt .= "\"$type\", "; - - if (defined $example) - { - my $example_str = $example; - $example_str =~ s/\\/\\\\/g; - $example_str =~ s/\"/\\\"/g; - $stmt .= "\"$example_str\", "; - } else { - $stmt .= "NULL, "; - } - - if (defined $since) { - $stmt .= "\"$since\", "; - } else { - $stmt .= "NULL, "; - } - - if (defined $advanced) { - $stmt .= "\"$advanced\""; - } else { - $stmt .= "NULL"; - } - - $stmt .= ");\n"; - - print GENSQL $stmt; - } - print GENSQL "\n\nCOMMIT;\n\n"; -} diff --git a/src/core/config.py b/src/core/config.py new file mode 100755 index 0000000..733e23e --- /dev/null +++ b/src/core/config.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python +""" + uhub - A tiny ADC p2p connection hub + Copyright (C) 2007-2013, Jan Vidar Krey +""" + +from xml.dom import minidom, Node +from datetime import datetime +import argparse + +class OptionParseError(Exception): + pass + +class Option(object): + def _get(self, node, name): + self.__dict__[name] = None + if (node.getElementsByTagName(name)): + self.__dict__[name] = node.getElementsByTagName(name)[0].firstChild.nodeValue + + def _attr(self, node, name, required = False): + try: + return node.attributes[name].value + except Exception: + pass + if (required): + raise OptionParseError("Option %s is required but not found!" % name) + return None + + def __init__(self, node): + self.otype = self._attr(node, 'type', True) + + # Verify that the type is known + if not self.otype in ["int", "boolean", "string", "message", "file"]: + raise OptionParseError("Option %s has unknown type" % self.name) + + self.name = self._attr(node, 'name', True) + self.default = self._attr(node, 'default', True) + self.advanced = self._attr(node, 'advanced', False) + self.is_string = self.otype in ["string", "message", "file"] + + self._get(node, "short"); + self._get(node, "description"); + self._get(node, "syntax"); + self._get(node, "since"); + self._get(node, "example"); + + check = node.getElementsByTagName("check") + if (check): + check = node.getElementsByTagName("check")[0] + self.check_min = self._attr(check, 'min', False) + self.check_max = self._attr(check, 'max', False) + self.check_regexp = self._attr(check, 'regexp', False) + else: + self.check_min = None + self.check_max = None + self.check_regexp = None + + + def c_type(self): + if self.otype == "boolean": + return "int" + elif self.is_string: + return "char*" + else: + return self.otype + + def sql_type(self): + if self.otype == "int": + return "integer" + return self.otype + + def c_comment(self): + comment = "" + if (self.otype == "message"): + comment = self.formatted_default() + elif len(self.short): + comment = "%s (default: %s)" % (self.short, self.formatted_default()) + return comment + + def formatted_default(self): + if self.is_string: + return "\"%s\"" % self.default + return self.default + +class SourceGenerator(object): + def __init__(self, filename, cppStyle = True): + print "Generating %s..." % filename + self.f = open(filename, 'w'); + + def write_header(self, Comment = True): + if Comment: + s = "/*\n * uhub - A tiny ADC p2p connection hub\n" + s += " * Copyright (C) 2007-%s, Jan Vidar Krey\n *\n" % datetime.now().strftime("%Y") + s += " * THIS FILE IS AUTOGENERATED - DO NOT MODIFY\n" + s += " * Created %s, by config.py\n */\n\n" % datetime.now().strftime("%Y-%m-%d %H:%M") + self.f.write(s) + +class CHeaderGenerator(SourceGenerator): + def __init__(self, filename): + super(CHeaderGenerator, self).__init__(filename) + + def _write_declaration(self, option): + comment = ' ' * (32 - len(option.name)) + "/*<<< %s */" % option.c_comment() + ptype = option.c_type() + (5 - len(option.c_type())) * ' ' + self.f.write("\t%(type)s %(name)s;%(comment)s\n" % { + "type": ptype, + "name": option.name, + "comment": comment}) + + def write(self, options): + self.write_header() + self.f.write("struct hub_config\n{\n") + for option in options: + self._write_declaration(option) + self.f.write("};\n\n") + +class CSourceGenerator(SourceGenerator): + def __init__(self, filename): + super(CSourceGenerator, self).__init__(filename) + + def _write_default_impl(self, option): + s = "\tconfig->%s = " % option.name + if option.is_string: + s += "hub_strdup(%s);\n" % option.formatted_default() + else: + s += option.formatted_default() + ";\n" + self.f.write(s) + + def _write_apply_impl(self, option): + s = "\tif (!strcmp(key, \"%s\"))\n\t{\n" % option.name + if option.otype == "int": + s_min = "0" + s_max = "0" + if (option.check_min): + s += "\t\tmin = %s;\n" % option.check_min + s_min = "&min" + if (option.check_max): + s += "\t\tmax = %s;\n" % option.check_max + s_max = "&max" + s+= "\t\tif (!apply_integer(key, data, &config->%s, %s, %s))\n" % (option.name, s_min, s_max) + elif option.otype == "boolean": + s += "\t\tif (!apply_boolean(key, data, &config->%s))\n" % option.name + elif option.is_string: + s += "\t\tif (!apply_string(key, data, &config->%s, (char*) \"\"))\n" % option.name + s += "\t\t{\n\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n\t\t\treturn -1;\n\t\t}\n\t\treturn 0;\n\t}\n\n" + self.f.write(s) + + def _write_free_impl(self, option): + if option.is_string: + self.f.write("\thub_free(config->%s);\n\n" % option.name) + + def _write_dump_impl(self, option): + s = "" + fmt = "%s" + val = "config->%s" % option.name + test = "config->%s != %s" % (option.name, option.default) + + if (option.otype == "int"): + fmt = "%d" + elif (option.otype == "boolean"): + val = "config->%s ? \"yes\" : \"no\"" % option.name + elif (option.is_string): + fmt = "\\\"%s\\\""; + test = "strcmp(config->%s, %s) != 0" % (option.name, option.formatted_default()) + + s += "\tif (!ignore_defaults || %s)\n" % test; + s += "\t\tfprintf(stdout, \"%s = %s\\n\", %s);\n\n" % (option.name, fmt, val) + self.f.write(s) + + def write(self, options): + self.write_header() + self.f.write("void config_defaults(struct hub_config* config)\n{\n") + for option in options: + self._write_default_impl(option) + self.f.write("}\n\n") + self.f.write("static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n") + for option in options: + self._write_apply_impl(option) + self.f.write("\t/* Still here -- unknown directive */\n\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n\treturn -1;\n}\n\n") + self.f.write("void free_config(struct hub_config* config)\n{\n") + for option in options: + self._write_free_impl(option) + self.f.write("}\n\n") + self.f.write("void dump_config(struct hub_config* config, int ignore_defaults)\n{\n") + for option in options: + self._write_dump_impl(option) + self.f.write("}\n\n") + +class SqlWebsiteDocsGenerator(SourceGenerator): + def __init__(self, filename, sqlite_support = False): + self.sqlite_support = sqlite_support + super(SqlWebsiteDocsGenerator, self).__init__(filename) + + def _sql_escape(self, s): + if self.sqlite_support: + return s.replace("\"", "\"\"") + return s.replace("\"", "\\\"") + + + def _write_or_null(self, s): + if (not s or len(s) == 0): + return "NULL" + return "\"%s\"" % self._sql_escape(s) + + def write(self, options): + self.write_header(False) + table = "uhub_config" + + s = "" + if not self.sqlite_support: + s += "START TRANSACTION;\n\nDROP TABLE %(table)s IF EXISTS;" % { "table": table } + s += "\n\nCREATE TABLE %(table)s (\n\tname VARCHAR(32) UNIQUE NOT NULL,\n\tdefaultValue TINYTEXT NOT NULL,\n\tdescription LONGTEXT NOT NULL,\n\ttype TINYTEXT NOT NULL,\n\tadvanced BOOLEAN,\n\texample LONGTEXT,\n\tsince TINYTEXT\n);\n\n" % { "table": table } + self.f.write(s) + + for option in options: + s = "INSERT INTO %(table)s VALUES(\"%(name)s\", \"%(default)s\", \"%(description)s\", \"%(type)s\", %(example)s, %(since)s, %(advanced)s);\n" % { + "table": table, + "name": self._sql_escape(option.name), + "default": self._sql_escape(option.formatted_default()), + "description": self._sql_escape(option.description), + "type": option.sql_type(), + "example": self._write_or_null(option.example), + "since": self._write_or_null(option.since), + "advanced": self._write_or_null(option.example), + } + self.f.write(s) + + if not self.sqlite_support: + self.f.write("\n\nCOMMIT;\n\n") + +if __name__ == "__main__": + # parser = argparse.ArgumentParser(description = "Configuration file parser and source generator") + # parser.add_argument("--in", nargs=1, type=argparse.FileType('r'), default="config.xml", help="Input file (config.xml)", required = True) + # parser.add_argument("--c-decl", nargs=1, type=argparse.FileType('w'), default="gen_config.h", help="Output file for C declarations (gen_config.h)") + # parser.add_argument("--c-impl", nargs=1, type=argparse.FileType('w'), default="gen_config.c", help="Output file for C implementation (gen_config.c)") + # parser.add_argument("--doc-sql", nargs=1, type=argparse.FileType('w'), help="Output file for SQL documentation") + # args = parser.parse_args() + + xmldoc = minidom.parse("./config.xml") + opt_tags = xmldoc.getElementsByTagName('option') + options = [] + for option in opt_tags: + opt = Option(option) + options.append(opt) + + header = CHeaderGenerator("./gen_config.h"); + header.write(options); + + source = CSourceGenerator("./gen_config.c"); + source.write(options); + + #sql = SqlWebsiteDocsGenerator("./gen_config.sql", True); + #sql.write(options); + + diff --git a/src/core/eventid.h b/src/core/eventid.h index 83bb85c..6e54150 100644 --- a/src/core/eventid.h +++ b/src/core/eventid.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/eventqueue.c b/src/core/eventqueue.c index 5215f9c..9433504 100644 --- a/src/core/eventqueue.c +++ b/src/core/eventqueue.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -32,20 +32,20 @@ int event_queue_initialize(struct event_queue** queue, event_queue_callback call *queue = (struct event_queue*) hub_malloc_zero(sizeof(struct event_queue)); if (!(*queue)) return -1; - + (*queue)->q1 = list_create(); (*queue)->q2 = list_create(); - + if (!(*queue)->q1 || !(*queue)->q2) { list_destroy((*queue)->q1); list_destroy((*queue)->q2); return -1; } - + (*queue)->callback = callback; (*queue)->callback_data = ptr; - + return 0; } @@ -73,35 +73,27 @@ int event_queue_process(struct event_queue* queue) struct event_data* data; if (queue->locked) return 0; - + /* lock primary queue, and handle the primary queue messages. */ queue->locked = 1; - - data = (struct event_data*) list_get_first(queue->q1); - while (data) + + LIST_FOREACH(struct event_data*, data, queue->q1, { #ifdef EQ_DEBUG eq_debug("EXEC", data); #endif queue->callback(queue->callback_data, data); - data = (struct event_data*) list_get_next(queue->q1); - } - + }); + list_clear(queue->q1, event_queue_cleanup_callback); uhub_assert(list_size(queue->q1) == 0); - + /* unlock queue */ queue->locked = 0; - + /* transfer from secondary queue to the primary queue. */ - data = (struct event_data*) list_get_first(queue->q2); - while (data) - { - list_remove(queue->q2, data); - list_append(queue->q1, data); - data = (struct event_data*) list_get_first(queue->q2); - } - + list_append_list(queue->q1, queue->q2); + /* if more events exist, schedule it */ if (list_size(queue->q1)) { @@ -114,18 +106,18 @@ void event_queue_post(struct event_queue* queue, struct event_data* message) { struct linked_list* q = (!queue->locked) ? queue->q1 : queue->q2; struct event_data* data; - + data = (struct event_data*) hub_malloc(sizeof(struct event_data)); if (data) { data->id = message->id; data->ptr = message->ptr; data->flags = message->flags; - + #ifdef EQ_DEBUG eq_debug("POST", data); #endif - + list_append(q, data); } else diff --git a/src/core/eventqueue.h b/src/core/eventqueue.h index f370cab..10b385f 100644 --- a/src/core/eventqueue.h +++ b/src/core/eventqueue.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/gen_config.c b/src/core/gen_config.c index 063db97..8372a7c 100644 --- a/src/core/gen_config.c +++ b/src/core/gen_config.c @@ -1,4 +1,10 @@ -/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2013, Jan Vidar Krey + * + * THIS FILE IS AUTOGENERATED - DO NOT MODIFY + * Created 2013-04-22 21:57, by config.py + */ void config_defaults(struct hub_config* config) { diff --git a/src/core/gen_config.h b/src/core/gen_config.h index a6effe1..26ed499 100644 --- a/src/core/gen_config.h +++ b/src/core/gen_config.h @@ -1,4 +1,10 @@ -/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2013, Jan Vidar Krey + * + * THIS FILE IS AUTOGENERATED - DO NOT MODIFY + * Created 2013-04-22 21:57, by config.py + */ struct hub_config { diff --git a/src/core/hub.c b/src/core/hub.c index 7eb6570..dde63c2 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -1320,9 +1320,7 @@ void hub_logout_log(struct hub_info* hub, struct hub_user* user) list_append(hub->logout_info, loginfo); while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log) { - struct hub_logout_info* entry = list_get_first(hub->logout_info); - list_remove(hub->logout_info, entry); - hub_free(entry); + list_remove_first(hub->logout_info, hub_free); } } diff --git a/src/core/hub.h b/src/core/hub.h index 4962c7e..7c4c5b7 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -55,7 +55,7 @@ enum status_message status_msg_proto_no_common_hash = -50, /* No common hash algorithms */ status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */ - + }; diff --git a/src/core/hubevent.c b/src/core/hubevent.c index f25b4f4..ed60207 100644 --- a/src/core/hubevent.c +++ b/src/core/hubevent.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/hubevent.h b/src/core/hubevent.h index 1d25054..7669e8b 100644 --- a/src/core/hubevent.h +++ b/src/core/hubevent.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/inf.c b/src/core/inf.c index 704abdc..2bf1dea 100644 --- a/src/core/inf.c +++ b/src/core/inf.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -109,14 +109,14 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes hub_free(pid); return status_msg_inf_error_cid_invalid; } - + if (strlen(pid) != MAX_CID_LEN) { hub_free(cid); hub_free(pid); return status_msg_inf_error_pid_invalid; } - + for (pos = 0; pos < MAX_CID_LEN; pos++) { if (!is_valid_base32_char(cid[pos])) @@ -133,18 +133,18 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes return status_msg_inf_error_pid_invalid; } } - + if (!check_hash_tiger(cid, pid)) { hub_free(cid); hub_free(pid); return status_msg_inf_error_cid_invalid; } - + /* Set the cid in the user object */ memcpy(user->id.cid, cid, MAX_CID_LEN); user->id.cid[MAX_CID_LEN] = 0; - + hub_free(cid); hub_free(pid); return 0; @@ -154,7 +154,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { int num = 0; - + num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID); if (num != 1) { @@ -162,7 +162,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use return status_msg_inf_error_cid_missing; return status_msg_inf_error_cid_invalid; } - + num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); if (num != 1) { @@ -190,7 +190,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { const char* address = user_get_address(user); - + /* Check for NAT override address */ if (acl_is_ip_nat_override(hub->acl, address)) { @@ -236,12 +236,12 @@ static int nick_length_ok(const char* nick) { return nick_invalid_short; } - + if (length > MAX_NICK_LEN) { return nick_invalid_long; } - + return nick_ok; } @@ -249,16 +249,16 @@ static int nick_length_ok(const char* nick) static int nick_bad_characters(const char* nick) { const char* tmp; - + /* Nick must not start with a space */ if (nick[0] == ' ') return nick_invalid_spaces; - + /* Check for ASCII values below 32 */ for (tmp = nick; *tmp; tmp++) if ((*tmp < 32) && (*tmp > 0)) return nick_invalid_bad_ascii; - + return nick_ok; } @@ -286,7 +286,7 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me nick = adc_msg_unescape(tmp); free(tmp); tmp = 0; if (!nick) return 0; - + status = nick_length_ok(nick); if (status != nick_ok) { @@ -295,7 +295,7 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me return status_msg_inf_error_nick_short; return status_msg_inf_error_nick_long; } - + status = nick_bad_characters(nick); if (status != nick_ok) { @@ -304,20 +304,20 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me return status_msg_inf_error_nick_spaces; return status_msg_inf_error_nick_bad_chars; } - + status = nick_is_utf8(nick); if (status != nick_ok) { hub_free(nick); return status_msg_inf_error_nick_not_utf8; } - + if (user_is_connecting(user)) { memcpy(user->id.nick, nick, strlen(nick)); user->id.nick[strlen(nick)] = 0; } - + hub_free(nick); return 0; } @@ -327,12 +327,12 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a { struct hub_user* lookup1 = uman_get_user_by_nick(hub->users, user->id.nick); struct hub_user* lookup2 = uman_get_user_by_cid(hub->users, user->id.cid); - + if (lookup1 == user) { return 0; } - + if (lookup1 || lookup2) { if (lookup1 == lookup2) @@ -368,7 +368,7 @@ static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct { char* ua_encoded = 0; char* ua = 0; - + /* Get client user agent version */ ua_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT); if (ua_encoded) @@ -391,7 +391,7 @@ static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_mes { return status_msg_ban_permanently; } - + if (acl_is_user_banned(hub->acl, user->id.nick)) { return status_msg_ban_permanently; @@ -401,7 +401,7 @@ static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_mes { return status_msg_inf_error_nick_restricted; } - + return 0; } @@ -470,7 +470,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_ hub_free(arg); arg = 0; } - + arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS); if (arg) { @@ -534,7 +534,7 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a { int ret = 0; struct auth_info* info = acl_get_access_info(hub, user->id.nick); - + if (info) { user->credentials = info->credentials; @@ -550,11 +550,11 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a { case auth_cred_none: break; - + case auth_cred_bot: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT); break; - + case auth_cred_guest: /* Nothing to be added to the info message */ break; @@ -566,7 +566,7 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a case auth_cred_operator: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR); break; - + case auth_cred_super: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER); break; @@ -578,7 +578,7 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a case auth_cred_link: break; } - + return ret; } @@ -611,10 +611,10 @@ static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd { /* Remove server restricted flags */ remove_server_restricted_flags(cmd); - + /* Update/set the feature cast flags. */ set_feature_cast_supports(user, cmd); - + return 0; } @@ -635,7 +635,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DESCRIPTION); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_EMAIL); } - + return 0; } @@ -680,20 +680,20 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad { return status_msg_hub_full; } - + if (check_registered_users_only(hub, user)) { return status_msg_hub_registered_users_only; } - + INF_CHECK(check_limits, hub, user, cmd); - + /* strip off stuff if low_bandwidth_mode is enabled */ hub_handle_info_low_bandwidth(hub, user, cmd); - + /* Set initial user info */ user_set_info(user, cmd); - + return code; } diff --git a/src/core/inf.h b/src/core/inf.h index 0ce8ba5..edc09db 100644 --- a/src/core/inf.h +++ b/src/core/inf.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/ioqueue.c b/src/core/ioqueue.c index ab55fb0..4ec0e72 100644 --- a/src/core/ioqueue.c +++ b/src/core/ioqueue.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -72,7 +72,7 @@ size_t ioq_recv_set(struct ioq_recv* q, void* buf, size_t bufsize) q->buf = 0; q->size = 0; } - + if (!bufsize) { return 0; @@ -130,7 +130,7 @@ void ioq_send_add(struct ioq_send* q, struct adc_message* msg_) q->size += msg->length; } -void ioq_send_remove(struct ioq_send* q, struct adc_message* msg) +static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg) { #ifdef DEBUG_SENDQ debug_msg("ioq_send_remove", msg); diff --git a/src/core/ioqueue.h b/src/core/ioqueue.h index 2624b24..358f3c6 100644 --- a/src/core/ioqueue.h +++ b/src/core/ioqueue.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/main.c b/src/core/main.c index bb78672..c5ed178 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -19,6 +19,10 @@ #include "uhub.h" +#ifdef SYSTEMD +#include +#endif + static int arg_verbose = 5; static int arg_fork = 0; static int arg_check_config = 0; @@ -83,7 +87,7 @@ void setup_signal_handlers(struct hub_info* hub) act.sa_mask = sig_set; act.sa_flags = SA_ONSTACK | SA_RESTART; act.sa_handler = hub_handle_signal; - + for (i = 0; signals[i]; i++) { if (sigaction(signals[i], &act, 0) != 0) @@ -120,7 +124,7 @@ int main_loop() hub_log_initialize(arg_log, arg_log_syslog); hub_set_log_verbosity(arg_verbose); } - + if (read_config(arg_config, &configuration, !arg_have_config) == -1) return -1; @@ -145,7 +149,16 @@ int main_loop() } #if !defined(WIN32) setup_signal_handlers(hub); -#endif +#ifdef SYSTEMD + /* Notify the service manager that this daemon has + * been successfully initalized and shall enter the + * main loop. + */ + sd_notifyf(0, "READY=1\n" + "MAINPID=%lu", (unsigned long) getpid()); +#endif /* SYSTEMD */ + +#endif /* ! WIN32 */ } hub_set_variables(hub, &acl); @@ -161,7 +174,7 @@ int main_loop() #if !defined(WIN32) shutdown_signal_handlers(hub); #endif - + if (hub) { hub_shutdown_service(hub); @@ -216,13 +229,17 @@ void print_usage(char* program) " -q Quiet mode - no output\n" " -f Fork to background\n" " -l Log messages to given file (default: stderr)\n" - " -L Log messages to syslog\n" " -c Specify configuration file (default: " SERVER_CONFIG ")\n" " -C Check configuration and return\n" " -s Show configuration parameters\n" " -S Show configuration parameters, but ignore defaults\n" " -h This message\n" #ifndef WIN32 +#ifdef SYSTEMD + " -L Log messages to journal\n" +#else + " -L Log messages to syslog\n" +#endif " -u Run as given user\n" " -g Run with given group permissions\n" " -p Store pid in file (process id)\n" @@ -271,7 +288,7 @@ void parse_command_line(int argc, char** argv) arg_dump_config = 1; arg_check_config = 1; break; - + case 'S': arg_dump_config = 2; arg_check_config = 1; @@ -280,7 +297,7 @@ void parse_command_line(int argc, char** argv) case 'l': arg_log = optarg; break; - + case 'L': arg_log_syslog = 1; break; diff --git a/src/core/netevent.c b/src/core/netevent.c index 7c31f69..f8beb47 100644 --- a/src/core/netevent.c +++ b/src/core/netevent.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/netevent.h b/src/core/netevent.h index 2628999..ce54bcb 100644 --- a/src/core/netevent.h +++ b/src/core/netevent.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/plugincallback.c b/src/core/plugincallback.c index fb782fb..7005877 100644 --- a/src/core/plugincallback.c +++ b/src/core/plugincallback.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -40,14 +40,11 @@ static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix); - cmdh = (struct plugin_command_handle*) list_get_first(data->commands); - while (cmdh) + LIST_FOREACH(struct plugin_command_handle*, cmdh, data->commands, { if (strcmp(cmdh->prefix, cmd->prefix) == 0) return cmdh->handler(plugin, puser, pcommand); - - cmdh = (struct plugin_command_handle*) list_get_next(data->commands); - } + }); return 0; } @@ -104,7 +101,6 @@ static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_comman cmdh->internal_handle = command; list_append(data->commands, cmdh); command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin); - printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh); return 0; } @@ -113,7 +109,6 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman struct plugin_callback_data* data = get_callback_data(plugin); struct command_handle* command = (struct command_handle*) cmdh->internal_handle; - printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh); list_remove(data->commands, cmdh); command_del(plugin_get_hub(plugin)->commands, command); hub_free(command); @@ -158,7 +153,7 @@ static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str) char* new_str = adc_msg_escape(str ? str : hub->config->hub_name); adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str); - + // Broadcast hub name command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8)); adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str); @@ -175,7 +170,7 @@ static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char* char* new_str = adc_msg_escape(str ? str : hub->config->hub_description); adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str); - + // Broadcast hub description command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8)); adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str); diff --git a/src/core/plugincallback.h b/src/core/plugincallback.h index 923790a..0ce3a5d 100644 --- a/src/core/plugincallback.h +++ b/src/core/plugincallback.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/plugininvoke.c b/src/core/plugininvoke.c index d5645f5..501a089 100644 --- a/src/core/plugininvoke.c +++ b/src/core/plugininvoke.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -27,13 +27,12 @@ PLUGIN_DEBUG(HUB, # FUNCNAME) \ if (HUB->plugins && HUB->plugins->loaded) \ { \ - struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(HUB->plugins->loaded); \ - while (plugin) \ + struct plugin_handle* plugin;\ + LIST_FOREACH(struct plugin_handle*, plugin, HUB->plugins->loaded, \ { \ if (plugin->funcs.FUNCNAME) \ CODE \ - plugin = (struct plugin_handle*) list_get_next(HUB->plugins->loaded); \ - } \ + }); \ } #define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \ diff --git a/src/core/plugininvoke.h b/src/core/plugininvoke.h index 56c71a4..cdd9dd7 100644 --- a/src/core/plugininvoke.h +++ b/src/core/plugininvoke.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/pluginloader.c b/src/core/pluginloader.c index 4c117ba..08ec426 100644 --- a/src/core/pluginloader.c +++ b/src/core/pluginloader.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -229,16 +229,16 @@ int plugin_initialize(struct hub_config* config, struct hub_info* hub) return 0; } +static void plugin_unload_ptr(void* ptr) +{ + struct plugin_handle* plugin = (struct plugin_handle*) ptr; + plugin_unload(plugin); +} + + void plugin_shutdown(struct uhub_plugins* handle) { - struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(handle->loaded); - while (plugin) - { - list_remove(handle->loaded, plugin); - plugin_unload(plugin); - plugin = (struct plugin_handle*) list_get_first(handle->loaded); - } - + list_clear(handle->loaded, plugin_unload_ptr); list_destroy(handle->loaded); } diff --git a/src/core/pluginloader.h b/src/core/pluginloader.h index 1929f9b..4428a65 100644 --- a/src/core/pluginloader.h +++ b/src/core/pluginloader.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/probe.c b/src/core/probe.c index c217d34..7869f6a 100644 --- a/src/core/probe.c +++ b/src/core/probe.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -73,7 +73,7 @@ static void probe_net_event(struct net_connection* con, int events, void *arg) } #ifdef SSL_SUPPORT else if (bytes >= 11 && - probe_recvbuf[0] == 22 && + probe_recvbuf[0] == 22 && probe_recvbuf[1] == 3 && /* protocol major version */ probe_recvbuf[5] == 1 && /* message type */ probe_recvbuf[9] == probe_recvbuf[1]) diff --git a/src/core/probe.h b/src/core/probe.h index b204efb..0687cff 100644 --- a/src/core/probe.h +++ b/src/core/probe.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/route.c b/src/core/route.c index 0c69c12..c28e13e 100644 --- a/src/core/route.c +++ b/src/core/route.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -28,7 +28,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* case 'B': /* Broadcast to all logged in clients */ route_to_all(hub, msg); break; - + case 'D': target = uman_get_user_by_sid(hub->users, msg->target); if (target) @@ -36,7 +36,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* route_to_user(hub, target, msg); } break; - + case 'E': target = uman_get_user_by_sid(hub->users, msg->target); if (target) @@ -45,11 +45,11 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* route_to_user(hub, u, msg); } break; - + case 'F': route_to_subscribers(hub, msg); - break; - + break; + default: /* Ignore the message */ break; @@ -139,12 +139,11 @@ int route_flush_pipeline(struct hub_info* hub, struct hub_user* u) int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */ { - struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); - while (user) + struct hub_user* user; + LIST_FOREACH(struct hub_user*, user, hub->users->list, { route_to_user(hub, user, command); - user = (struct hub_user*) list_get_next(hub->users->list); - } + }); return 0; } @@ -153,49 +152,40 @@ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* i { int do_send; char* tmp; - - struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); - while (user) + + struct hub_user* user; + LIST_FOREACH(struct hub_user*, user, hub->users->list, { if (user->feature_cast) { do_send = 1; - - tmp = list_get_first(command->feature_cast_include); - while (tmp) + + LIST_FOREACH(char*, tmp, command->feature_cast_include, { if (!user_have_feature_cast_support(user, tmp)) { do_send = 0; break; } - tmp = list_get_next(command->feature_cast_include);; - } - - if (!do_send) { - user = (struct hub_user*) list_get_next(hub->users->list); + }); + + if (!do_send) continue; - } - - tmp = list_get_first(command->feature_cast_exclude); - while (tmp) + + LIST_FOREACH(char*, tmp, command->feature_cast_exclude, { if (user_have_feature_cast_support(user, tmp)) { do_send = 0; break; } - tmp = list_get_next(command->feature_cast_exclude); - } - + }); + if (do_send) - { route_to_user(hub, user, command); - } } - user = (struct hub_user*) list_get_next(hub->users->list); - } - + }); + return 0; } @@ -210,20 +200,17 @@ int route_info_message(struct hub_info* hub, struct hub_user* u) struct adc_message* cmd = adc_msg_copy(u->info); const char* address = user_get_address(u); struct hub_user* user = 0; - + adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address); - - user = (struct hub_user*) list_get_first(hub->users->list); - while (user) + + LIST_FOREACH(struct hub_user*, user, hub->users->list, { if (user_is_nat_override(user)) route_to_user(hub, user, cmd); else route_to_user(hub, user, u->info); - - user = (struct hub_user*) list_get_next(hub->users->list); - } + }); adc_msg_free(cmd); } return 0; diff --git a/src/core/route.h b/src/core/route.h index 378c2b8..d12d7b8 100644 --- a/src/core/route.h +++ b/src/core/route.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/core/user.c b/src/core/user.c index 9f9ab7b..7b6f7d3 100644 --- a/src/core/user.c +++ b/src/core/user.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -38,7 +38,7 @@ static const char* user_log_str(struct hub_user* user) struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr) { struct hub_user* user = NULL; - + LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con)); user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user)); @@ -90,7 +90,7 @@ void user_set_state(struct hub_user* user, enum user_state state) { return; } - + user->state = state; } @@ -135,7 +135,7 @@ void user_update_info(struct hub_user* u, struct adc_message* cmd) prefix[1] = argument[1]; adc_msg_replace_named_argument(cmd_new, prefix, argument+2); } - + hub_free(argument); argument = adc_msg_get_argument(cmd, n++); } @@ -232,15 +232,12 @@ void user_support_remove(struct hub_user* user, int fourcc) int user_have_feature_cast_support(struct hub_user* user, char feature[4]) { - char* tmp = list_get_first(user->feature_cast); - while (tmp) + char* tmp; + LIST_FOREACH(char*, tmp, user->feature_cast, { if (strncmp(tmp, feature, 4) == 0) return 1; - - tmp = list_get_next(user->feature_cast); - } - + }); return 0; } diff --git a/src/core/user.h b/src/core/user.h index 4af9382..b6b3f27 100644 --- a/src/core/user.h +++ b/src/core/user.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -51,7 +51,7 @@ enum user_flags flag_muted = 0x00800000, /** User is muted (cannot chat) */ flag_ignore = 0x01000000, /** Ignore further reads */ flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */ - flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */ + flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */ flag_want_read = 0x08000000, /** Need to read (SSL) */ flag_want_write = 0x10000000, /** Need to write (SSL) */ flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */ @@ -150,7 +150,7 @@ extern void user_destroy(struct hub_user* user); * This associates a INF message to the user. * If the user already has a INF message associated, then this is * released before setting the new one. - * + * * @param info new inf message (can be NULL) */ extern void user_set_info(struct hub_user* user, struct adc_message* info); @@ -244,7 +244,7 @@ extern int user_flag_get(struct hub_user* user, enum user_flags flag); * Check if a user supports 'feature' for feature casting (basis for 'Fxxx' messages) * The feature cast is specified as the 'SU' argument to the user's * INF-message. - * + * * @param feature a feature to lookup (example: 'TCP4' or 'UDP4') * @return 1 if 'feature' supported, or 0 otherwise */ diff --git a/src/core/usermanager.c b/src/core/usermanager.c index 1d462fe..345a98b 100644 --- a/src/core/usermanager.c +++ b/src/core/usermanager.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -28,7 +28,7 @@ static void clear_user_list_callback(void* ptr) if (ptr) { struct hub_user* u = (struct hub_user*) ptr; - + /* Mark the user as already being disconnected. * This prevents the hub from trying to send * quit messages to other users. @@ -38,6 +38,11 @@ static void clear_user_list_callback(void* ptr) } } +static int uman_map_compare(const void* a, const void* b) +{ + return strcmp((const char*) a, (const char*) b); +} + struct hub_user_manager* uman_init() { @@ -46,15 +51,10 @@ struct hub_user_manager* uman_init() return NULL; users->list = list_create(); + users->nickmap = rb_tree_create(uman_map_compare, NULL, NULL); + users->cidmap = rb_tree_create(uman_map_compare, NULL, NULL); users->sids = sid_pool_create(net_get_max_sockets()); - if (!users->list) - { - list_destroy(users->list); - hub_free(users); - return NULL; - } - return users; } @@ -64,11 +64,18 @@ int uman_shutdown(struct hub_user_manager* users) if (!users) return -1; + if (users->nickmap) + rb_tree_destroy(users->nickmap); + + if (users->cidmap) + rb_tree_destroy(users->cidmap); + if (users->list) { list_clear(users->list, &clear_user_list_callback); list_destroy(users->list); } + sid_pool_destroy(users->sids); hub_free(users); @@ -81,6 +88,9 @@ int uman_add(struct hub_user_manager* users, struct hub_user* user) if (!users || !user) return -1; + rb_tree_insert(users->nickmap, user->id.nick, user); + rb_tree_insert(users->cidmap, user->id.cid, user); + list_append(users->list, user); users->count++; users->count_peak = MAX(users->count, users->count_peak); @@ -96,6 +106,8 @@ int uman_remove(struct hub_user_manager* users, struct hub_user* user) return -1; list_remove(users->list, user); + rb_tree_remove(users->nickmap, user->id.nick); + rb_tree_remove(users->cidmap, user->id.cid); if (users->count > 0) { @@ -120,42 +132,29 @@ struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid) struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid) { - struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */ - while (user) - { - if (strcmp(user->id.cid, cid) == 0) - return user; - user = (struct hub_user*) list_get_next(users->list); - } - return NULL; + struct hub_user* user = (struct hub_user*) rb_tree_get(users->cidmap, (const void*) cid); + return user; } struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick) { - struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */ - while (user) - { - if (strcmp(user->id.nick, nick) == 0) - return user; - user = (struct hub_user*) list_get_next(users->list); - } - return NULL; + struct hub_user* user = (struct hub_user*) rb_tree_get(users->nickmap, nick); + return user; } size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range) { size_t num = 0; - struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */ - while (user) + struct hub_user* user; + LIST_FOREACH(struct hub_user*, user, users->list, { if (ip_in_range(&user->id.addr, range)) { list_append(target, user); num++; } - user = (struct hub_user*) list_get_next(users->list); - } + }); return num; } @@ -164,8 +163,8 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st int ret = 1; struct hub_user* user; user_flag_set(target, flag_user_list); - user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on INF or PAS msg */ - while (user) + + LIST_FOREACH(struct hub_user*, user, users->list, { if (user_is_logged_in(user)) { @@ -173,8 +172,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st if (!ret) break; } - user = (struct hub_user*) list_get_next(users->list); - } + }); #if 0 FIXME: FIXME FIXME handle send queue excess diff --git a/src/core/usermanager.h b/src/core/usermanager.h index 28d9e12..e258627 100644 --- a/src/core/usermanager.h +++ b/src/core/usermanager.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -24,10 +24,12 @@ struct hub_user_manager { size_t count; /**<< "Number of all fully connected and logged in users" */ size_t count_peak; /**<< "Peak number of users" */ - struct sid_pool* sids; uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */ uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */ + struct sid_pool* sids; /**<< "Maps SIDs to users (constant time)" */ struct linked_list* list; /**<< "Contains all logged in users" */ + struct rb_tree* nickmap; /**<< "Maps nicknames to users (red black tree)" */ + struct rb_tree* cidmap; /**<< "Maps CIDs to users (red black tree)" */ }; /** @@ -77,7 +79,7 @@ extern sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user* * * NOTE: This function will only search connected users, which means * that SIDs assigned to users who are not yet completely logged in, - * or are in the process of being disconnected will result in this + * or are in the process of being disconnected will result in this * function returning NULL even though the sid is not freely available. * * FIXME: Is that really safe / sensible ? diff --git a/src/network/backend.c b/src/network/backend.c index 678ab9d..9e97b48 100644 --- a/src/network/backend.c +++ b/src/network/backend.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -132,10 +132,11 @@ struct timeout_queue* net_backend_get_timeout_queue() */ int net_backend_process() { - int res; + int res = 0; size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now); - res = g_backend->handler.backend_poll(g_backend->data, secs * 1000); + if (g_backend->common.num) + res = g_backend->handler.backend_poll(g_backend->data, secs * 1000); g_backend->now = time(0); timeout_queue_process(&g_backend->timeout_queue, g_backend->now); diff --git a/src/network/backend.h b/src/network/backend.h index b908f28..39f2172 100644 --- a/src/network/backend.h +++ b/src/network/backend.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/common.h b/src/network/common.h index 8270da2..e33dc14 100644 --- a/src/network/common.h +++ b/src/network/common.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/connection.c b/src/network/connection.c index 23ce0eb..3828d54 100644 --- a/src/network/connection.c +++ b/src/network/connection.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -145,3 +145,364 @@ void net_con_callback(struct net_connection* con, int events) con->callback(con, events, con->ptr); } +struct net_connect_job +{ + struct net_connection* con; + struct net_connect_handle* handle; + struct sockaddr_storage addr; + struct net_connect_job* next; +}; + +struct net_connect_handle +{ + const char* address; + uint16_t port; + void* ptr; + net_connect_cb callback; + struct net_dns_job* dns; + const struct net_dns_result* result; + struct net_connect_job* job4; + struct net_connect_job* job6; +}; + +static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con); +static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr); + +/** + * Check if a connection job is completed. + * @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected). + */ +static int net_connect_job_check(struct net_connect_job* job) +{ + struct net_connection* con = job->con; + int af = job->addr.ss_family; + enum net_connect_status status; + + int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); + if (ret == 0 || (ret == -1 && net_error() == EISCONN)) + { + LOG_TRACE("net_connect_job_check(): Socket connected!"); + job->con = NULL; + net_connect_callback(job->handle, net_connect_status_ok, con); + return 1; + } + else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR)) + { + return 0; + } + LOG_TRACE("net_connect_job_check(): Socket error!"); + + switch (net_error()) + { + case ECONNREFUSED: + status = net_connect_status_refused; + break; + case ENETUNREACH: + status = net_connect_status_unreachable; + break; + + default: + status = net_connect_status_socket_error; + } + + net_connect_callback(job->handle, status, NULL); + return -1; +} + +static void net_connect_job_free(struct net_connect_job* job) +{ + if (job->con) + net_con_close(job->con); + job->handle = NULL; + job->next = NULL; + hub_free(job); +} + +static void net_connect_job_stop(struct net_connect_job* job) +{ + if (job->addr.ss_family == AF_INET6) + { + job->handle->job6 = job->next; + } + else + { + job->handle->job4 = job->next; + } + + net_connect_job_free(job); +} + +static int net_connect_depleted(struct net_connect_handle* handle) +{ + return (!handle->job6 && !handle->job4); +} + +static int net_connect_job_process(struct net_connect_job* job) +{ + int sd; + if (!job->con) + { + sd = net_socket_create(job->addr.ss_family, SOCK_STREAM, IPPROTO_TCP); + if (sd == -1) + { + LOG_DEBUG("net_connect_job_process: Unable to create socket!"); + net_connect_callback(job->handle, net_connect_status_socket_error, NULL); + return -1; // FIXME + } + + job->con = net_con_create(); + net_con_initialize(job->con, sd, net_connect_job_internal_cb, job, NET_EVENT_WRITE); + net_con_set_timeout(job->con, TIMEOUT_CONNECTED); // FIXME: Use a proper timeout value! + } + + return net_connect_job_check(job); +} + + +/* + * Internal callback used to establish an outbound connection. + */ +static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr) +{ + int ret; + struct net_connect_job* job = net_con_get_ptr(con); + struct net_connect_job* next_job = job->next; + struct net_connect_handle* handle = job->handle; + + if (event == NET_EVENT_TIMEOUT) + { + // FIXME: Try next address, or if no more addresses left declare failure to connect. + if (job->addr.ss_family == AF_INET6) + { + net_connect_job_stop(job); + + if (!next_job) + { + LOG_TRACE("No more IPv6 addresses to try!"); + } + + } + else + { + net_connect_job_stop(job); + + if (!next_job) + { + LOG_TRACE("No more IPv4 addresses to try!"); + } + } + + if (net_connect_depleted(handle)) + { + LOG_TRACE("No more addresses left. Unable to connect!"); + net_connect_callback(handle, net_connect_status_timeout, NULL); + } + return; + } + + if (event == NET_EVENT_WRITE) + { + net_connect_job_process(job); + } +} + + +static int net_connect_cancel(struct net_connect_handle* handle) +{ + struct net_connect_job* job; + + job = handle->job6; + while (job) + { + job = job->next; + net_connect_job_free(handle->job6); + handle->job6 = job; + } + + job = handle->job4; + while (job) + { + job = job->next; + net_connect_job_free(handle->job4); + handle->job4 = job; + } +} + + +static int net_connect_process_queue(struct net_connect_handle* handle, struct net_connect_job* job) +{ + int ret; + while (job) + { + ret = net_connect_job_process(job); + if (ret < 0) + { + net_connect_job_stop(job); + continue; + } + else if (ret == 0) + { + // Need to process again + return 0; + } + else + { + // FIXME: Success! + return 1; + } + } + return -1; +} + +static int net_connect_process(struct net_connect_handle* handle) +{ + int ret4, ret6; + + ret6 = net_connect_process_queue(handle, handle->job6); + if (ret6 == 1) + return 1; // Connected - cool! + + net_connect_process_queue(handle, handle->job4); +} + + +static int net_connect_job_schedule(struct net_connect_handle* handle, struct ip_addr_encap* addr) +{ + struct net_connect_job* job; + struct sockaddr_in* addr4; + struct sockaddr_in6* addr6; + + if (addr->af == AF_INET6 && !net_is_ipv6_supported()) + { + LOG_TRACE("net_connect_job_schedule(): Skipping IPv6 support since IPv6 is not supported."); + return 0; + } + else + { + job = hub_malloc_zero(sizeof(struct net_connect_job)); + job->handle = handle; + if (addr->af == AF_INET6) + { + addr6 = (struct sockaddr_in6*) &job->addr; + LOG_TRACE("net_connect_job_schedule(): Scheduling IPv6 connect job."); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = htons(handle->port); + memcpy(&addr6->sin6_addr, &addr->internal_ip_data.in6, sizeof(struct in6_addr)); + + // prepend + job->next = handle->job6; + handle->job6 = job; + } + else + { + addr4 = (struct sockaddr_in*) &job->addr; + LOG_TRACE("net_connect_job_schedule(): Scheduling IPv4 connect job."); + addr4->sin_family = AF_INET; + addr4->sin_port = htons(handle->port); + memcpy(&addr4->sin_addr, &addr->internal_ip_data.in, sizeof(struct in_addr)); + + // prepend + job->next = handle->job4; + handle->job4 = job; + } + } + return 1; +} + + +/* + * Callback when the DNS results are ready. + * Create a list of IPv6 and IPv4 addresses, then + * start connecting to them one by one until one succeeds. + */ +static int net_con_connect_dns_callback(struct net_dns_job* job, const struct net_dns_result* result) +{ + struct ip_addr_encap* addr; + struct net_connect_handle* handle = (struct net_connect_handle*) net_dns_job_get_ptr(job); + handle->dns = NULL; + size_t usable = 0; + int ret; + + LOG_TRACE("net_con_connect(): async - Got DNS results"); + if (!result) + { + LOG_DEBUG("net_con_connect() - Unable to lookup host!"); + net_connect_callback(handle, net_connect_status_dns_error, NULL); + return 1; + } + + if (!net_dns_result_size(result)) + { + LOG_DEBUG("net_con_connect() - Host not found!"); + net_connect_callback(handle, net_connect_status_host_not_found, NULL); + return 1; + } + + handle->result = result; + + // Extract results into a separate list of IPv4 and IPv6 addresses. + addr = net_dns_result_first(result); + while (addr) + { + if (net_connect_job_schedule(handle, addr)) + usable++; + addr = net_dns_result_next(result); + } + + net_connect_process(handle); + + return 0; +} + +// typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_handle_code, struct net_connection* con); + +struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr) +{ + struct net_connect_handle* handle = hub_malloc_zero(sizeof(struct net_connect_handle)); + + handle->address = hub_strdup(address); + handle->port = port; + handle->ptr = ptr; + handle->callback = callback; + + // FIXME: Check if DNS resolving is necessary ? + handle->dns = net_dns_gethostbyname(address, AF_UNSPEC, net_con_connect_dns_callback, handle); + if (!handle->dns) + { + LOG_TRACE("net_con_connect(): Unable to create DNS lookup job."); + hub_free((char*) handle->address); + hub_free(handle); + return NULL; + } + + return handle; +} + +void net_connect_destroy(struct net_connect_handle* handle) +{ + hub_free((char*) handle->address); + + // cancel DNS job if pending + if (handle->dns) + net_dns_job_cancel(handle->dns); + + // Stop any connect jobs. + net_connect_cancel(handle); + + // free any DNS results + net_dns_result_free(handle->result); + + hub_free(handle); +} + +static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con) +{ + uhub_assert(handle->callback != NULL); + + // Call the callback + handle->callback(handle, status, con, handle->ptr); + handle->callback = NULL; + + // Cleanup + net_connect_destroy(handle); +} diff --git a/src/network/connection.h b/src/network/connection.h index 84cc96a..f48b794 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -34,10 +34,41 @@ struct net_connection NET_CON_STRUCT_COMMON }; +struct net_connect_handle; + +enum net_connect_status +{ + net_connect_status_ok = 0, + net_connect_status_host_not_found = -1, + net_connect_status_no_address = -2, + net_connect_status_dns_error = -3, + net_connect_status_refused = -4, + net_connect_status_unreachable = -5, + net_connect_status_timeout = -6, + net_connect_status_socket_error = -7, +}; + +typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_status status, struct net_connection* con, void* ptr); + extern int net_con_get_sd(struct net_connection* con); extern void* net_con_get_ptr(struct net_connection* con); extern struct net_connection* net_con_create(); + +/** + * Establish an outbound TCP connection. + * This will resolve the IP-addresses, and connect to + * either an IPv4 or IPv6 address depending if it is supported, + * and using the happy eyeballs algorithm. + * + * @param address Hostname, IPv4 or IPv6 address + * @param port TCP port number + * @param callback A callback to be called once the connection is established, or failed. + * @returns a handle to the connection establishment job, or NULL if an immediate error. + */ +extern struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr); +extern void net_connect_destroy(struct net_connect_handle* handle); + extern void net_con_destroy(struct net_connection*); extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events); extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events); diff --git a/src/network/dnsresolver.c b/src/network/dnsresolver.c index 65a4465..e1bf5e5 100644 --- a/src/network/dnsresolver.c +++ b/src/network/dnsresolver.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -120,7 +120,7 @@ void net_dns_process() 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)) + LIST_FOREACH(struct net_dns_result*, result, g_dns->results, { struct net_dns_job* job = result->job; #ifdef DEBUG_LOOKUP_TIME @@ -146,7 +146,7 @@ void net_dns_process() result->job = NULL; free_job(job); } - } + }); list_clear(g_dns->results, &dummy_free); uhub_mutex_unlock(&g_dns->mutex); @@ -273,14 +273,14 @@ extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, n 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)) + LIST_FOREACH(struct net_dns_job*, it, g_dns->jobs, { if (it == job) { list_remove(g_dns->jobs, it); return job; } - } + }); return NULL; } @@ -288,14 +288,14 @@ 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_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)) + LIST_FOREACH(struct net_dns_result*, it, g_dns->results, { if (it->job == job) { list_remove(g_dns->results, it); return it; } - } + }); return NULL; } @@ -366,21 +366,24 @@ extern size_t net_dns_result_size(const struct net_dns_result* res) 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)); + LOG_TRACE("net_dns_result_first() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no address)"); 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)); + LOG_TRACE("net_dns_result_next() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no more addresses)"); return ipaddr; } -extern void net_dns_result_free(struct net_dns_result* res) +extern void net_dns_result_free(const struct net_dns_result* res) { + if (!res) + return; + list_clear(res->addr_list, &hub_free); list_destroy(res->addr_list); free_job(res->job); - hub_free(res); + hub_free((struct net_dns_result*) res); } diff --git a/src/network/dnsresolver.h b/src/network/dnsresolver.h index 6937422..7d1d2b0 100644 --- a/src/network/dnsresolver.h +++ b/src/network/dnsresolver.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -114,6 +114,6 @@ extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*); 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*); +extern void net_dns_result_free(const struct net_dns_result*); #endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */ diff --git a/src/network/epoll.c b/src/network/epoll.c index 7385a74..907ca9b 100644 --- a/src/network/epoll.c +++ b/src/network/epoll.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/ipcalc.c b/src/network/ipcalc.c index 388bc52..9c3b7ef 100644 --- a/src/network/ipcalc.c +++ b/src/network/ipcalc.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -25,10 +25,10 @@ int ip_is_valid_ipv4(const char* address) int o = 0; /* octet number */ int n = 0; /* numbers after each dot */ int d = 0; /* dots */ - + if (!address || strlen(address) > 15 || strlen(address) < 7) return 0; - + for (; i < strlen(address); i++) { if (is_num(address[i])) @@ -49,9 +49,9 @@ int ip_is_valid_ipv4(const char* address) return 0; } } - + if (n == 0 || n > 3 || o > 255 || d != 3) return 0; - + return 1; } @@ -107,9 +107,9 @@ int ip_convert_address(const char* text_address, int port, struct sockaddr* addr struct sockaddr_in addr4; size_t sockaddr_size; const char* taddr = 0; - + int ipv6sup = net_is_ipv6_supported(); - + if (strcmp(text_address, "any") == 0) { if (ipv6sup) @@ -136,8 +136,8 @@ int ip_convert_address(const char* text_address, int port, struct sockaddr* addr { taddr = text_address; } - - + + if (ip_is_valid_ipv6(taddr) && ipv6sup) { sockaddr_size = sizeof(struct sockaddr_in6); @@ -152,7 +152,7 @@ int ip_convert_address(const char* text_address, int port, struct sockaddr* addr memcpy(addr, &addr6, sockaddr_size); *addr_len = sockaddr_size; - + } else if (ip_is_valid_ipv4(taddr)) { @@ -185,28 +185,28 @@ int ip_mask_create_left(int af, int bits, struct ip_addr_encap* result) memset(result, 0, sizeof(struct ip_addr_encap)); result->af = af; - + if (bits < 0) bits = 0; - + if (af == AF_INET) { if (bits > 32) bits = 32; mask = (0xffffffff << (32 - bits)); if (bits == 0) mask = 0; - + result->internal_ip_data.in.s_addr = (((uint8_t*) &mask)[0] << 24) | (((uint8_t*) &mask)[1] << 16) | (((uint8_t*) &mask)[2] << 8) | (((uint8_t*) &mask)[3] << 0); } else if (af == AF_INET6) { if (bits > 128) bits = 128; - + fill = (128-bits) / 8; remain_bits = (128-bits) % 8; mask = (0xff << (8 - remain_bits)); for (n = 0; n < fill; n++) ((uint8_t*) &result->internal_ip_data.in6)[n] = (uint8_t) 0xff; - + if (fill < 16) ((uint8_t*) &result->internal_ip_data.in6)[fill] = (uint8_t) mask; } @@ -233,32 +233,32 @@ int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result) memset(result, 0, sizeof(struct ip_addr_encap)); result->af = af; - + if (bits < 0) bits = 0; - + if (af == AF_INET) { if (bits > 32) bits = 32; mask = (0xffffffff >> (32-bits)); if (bits == 0) mask = 0; result->internal_ip_data.in.s_addr = (((uint8_t*) &mask)[0] << 24) | (((uint8_t*) &mask)[1] << 16) | (((uint8_t*) &mask)[2] << 8) | (((uint8_t*) &mask)[3] << 0); - + } else if (af == AF_INET6) { if (bits > 128) bits = 128; - + fill = (128-bits) / 8; remain_bits = (128-bits) % 8; mask8 = (0xff >> (8 - remain_bits)); start = 16-fill; - + for (n = 0; n < start; n++) ((uint8_t*) &result->internal_ip_data.in6)[n] = (uint8_t) 0x00; - + for (n = start; n < 16; n++) ((uint8_t*) &result->internal_ip_data.in6)[n] = (uint8_t) 0xff; - + if (start > 0) ((uint8_t*) &result->internal_ip_data.in6)[start-1] = (uint8_t) mask8; } @@ -266,13 +266,13 @@ int ip_mask_create_right(int af, int bits, struct ip_addr_encap* result) { return -1; } - + #ifdef IP_CALC_DEBUG char* r_str = hub_strdup(ip_convert_to_string(result)); LOG_DUMP("Created right mask: %s", r_str); hub_free(r_str); #endif - + return 0; } @@ -281,7 +281,7 @@ void ip_mask_apply_AND(struct ip_addr_encap* addr, struct ip_addr_encap* mask, s { memset(result, 0, sizeof(struct ip_addr_encap)); result->af = addr->af; - + if (addr->af == AF_INET) { result->internal_ip_data.in.s_addr = addr->internal_ip_data.in.s_addr & mask->internal_ip_data.in.s_addr; @@ -294,19 +294,19 @@ void ip_mask_apply_AND(struct ip_addr_encap* addr, struct ip_addr_encap* mask, s for (n = 0; n < 4; n++) { offset = n * 4; - + A = (((uint8_t*) &addr->internal_ip_data.in6)[offset+0] << 24) | (((uint8_t*) &addr->internal_ip_data.in6)[offset+1] << 16) | (((uint8_t*) &addr->internal_ip_data.in6)[offset+2] << 8) | (((uint8_t*) &addr->internal_ip_data.in6)[offset+3] << 0); - + B = (((uint8_t*) &mask->internal_ip_data.in6)[offset+0] << 24) | (((uint8_t*) &mask->internal_ip_data.in6)[offset+1] << 16) | (((uint8_t*) &mask->internal_ip_data.in6)[offset+2] << 8) | (((uint8_t*) &mask->internal_ip_data.in6)[offset+3] << 0); - + C = A & B; - + D = (((uint8_t*) &C)[0] << 24) | (((uint8_t*) &C)[1] << 16) | (((uint8_t*) &C)[2] << 8) | @@ -321,7 +321,7 @@ void ip_mask_apply_OR(struct ip_addr_encap* addr, struct ip_addr_encap* mask, st { memset(result, 0, sizeof(struct ip_addr_encap)); result->af = addr->af; - + if (addr->af == AF_INET) { result->internal_ip_data.in.s_addr = addr->internal_ip_data.in.s_addr | mask->internal_ip_data.in.s_addr; @@ -334,19 +334,19 @@ void ip_mask_apply_OR(struct ip_addr_encap* addr, struct ip_addr_encap* mask, st for (n = 0; n < 4; n++) { offset = n * 4; - + A = (((uint8_t*) &addr->internal_ip_data.in6)[offset+0] << 24) | (((uint8_t*) &addr->internal_ip_data.in6)[offset+1] << 16) | (((uint8_t*) &addr->internal_ip_data.in6)[offset+2] << 8) | (((uint8_t*) &addr->internal_ip_data.in6)[offset+3] << 0); - + B = (((uint8_t*) &mask->internal_ip_data.in6)[offset+0] << 24) | (((uint8_t*) &mask->internal_ip_data.in6)[offset+1] << 16) | (((uint8_t*) &mask->internal_ip_data.in6)[offset+2] << 8) | (((uint8_t*) &mask->internal_ip_data.in6)[offset+3] << 0); - + C = A | B; - + D = (((uint8_t*) &C)[0] << 24) | (((uint8_t*) &C)[1] << 16) | (((uint8_t*) &C)[2] << 8) | @@ -368,7 +368,7 @@ int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b) (((uint8_t*) &a->internal_ip_data.in.s_addr)[1] << 16) | (((uint8_t*) &a->internal_ip_data.in.s_addr)[2] << 8) | (((uint8_t*) &a->internal_ip_data.in.s_addr)[3] << 0); - + B = (((uint8_t*) &b->internal_ip_data.in.s_addr)[0] << 24) | (((uint8_t*) &b->internal_ip_data.in.s_addr)[1] << 16) | (((uint8_t*) &b->internal_ip_data.in.s_addr)[2] << 8) | @@ -386,19 +386,19 @@ int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b) (((uint8_t*) &a->internal_ip_data.in6)[offset+1] << 16) | (((uint8_t*) &a->internal_ip_data.in6)[offset+2] << 8) | (((uint8_t*) &a->internal_ip_data.in6)[offset+3] << 0); - + B = (((uint8_t*) &b->internal_ip_data.in6)[offset+0] << 24) | (((uint8_t*) &b->internal_ip_data.in6)[offset+1] << 16) | (((uint8_t*) &b->internal_ip_data.in6)[offset+2] << 8) | (((uint8_t*) &b->internal_ip_data.in6)[offset+3] << 0); - + if (A == B) continue; - + return A - B; } return 0; } - + #ifdef IP_CALC_DEBUG char* a_str = hub_strdup(ip_convert_to_string(a)); char* b_str = hub_strdup(ip_convert_to_string(b)); @@ -406,7 +406,7 @@ int ip_compare(struct ip_addr_encap* a, struct ip_addr_encap* b) hub_free(a_str); hub_free(b_str); #endif - + return ret; } diff --git a/src/network/ipcalc.h b/src/network/ipcalc.h index e6a10e2..5d00fe4 100644 --- a/src/network/ipcalc.h +++ b/src/network/ipcalc.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -18,7 +18,7 @@ */ /* - * This file is used for fiddling with IP-addresses, + * This file is used for fiddling with IP-addresses, * primarily used for IP-banning in uhub. */ diff --git a/src/network/kqueue.c b/src/network/kqueue.c index 014702d..27da92b 100644 --- a/src/network/kqueue.c +++ b/src/network/kqueue.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/network.c b/src/network/network.c index 327fe89..57af998 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -449,7 +449,7 @@ int net_is_ipv6_supported() is_ipv6_supported = 0; return 0; } - + net_error_out(ret, "net_is_ipv6_supported"); } else @@ -508,7 +508,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t size_t size; LPSOCKADDR addr; DWORD len = cnt; - + switch (af) { case AF_INET: @@ -531,7 +531,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t default: return NULL; } - + if (WSAAddressToStringA(addr, size, NULL, dst, &len) == 0) { return dst; @@ -602,15 +602,15 @@ const char* net_get_peer_address(int fd) struct sockaddr_in* name4; struct sockaddr* name; socklen_t namelen; - + memset(address, 0, INET6_ADDRSTRLEN); namelen = sizeof(struct sockaddr_storage); memset(&storage, 0, namelen); - + name6 = (struct sockaddr_in6*) &storage; name4 = (struct sockaddr_in*) &storage; name = (struct sockaddr*) &storage; - + if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1) { int af = storage.ss_family; diff --git a/src/network/network.h b/src/network/network.h index 964cedb..d5d0805 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/openssl.c b/src/network/openssl.c index 671d37f..db2daf3 100644 --- a/src/network/openssl.c +++ b/src/network/openssl.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -73,7 +73,7 @@ int net_ssl_library_shutdown() ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); - + // sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); return 1; } diff --git a/src/network/select.c b/src/network/select.c index c1958d8..31ba406 100644 --- a/src/network/select.c +++ b/src/network/select.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/timeout.c b/src/network/timeout.c index 1efc6f5..c7ba463 100644 --- a/src/network/timeout.c +++ b/src/network/timeout.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -42,6 +42,7 @@ void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max) { t->last = now; t->max = max; + memset(&t->lock, 0, sizeof(t->lock)); t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*)); } @@ -52,12 +53,56 @@ void timeout_queue_shutdown(struct timeout_queue* t) t->max = 0; } +static int timeout_queue_locked(struct timeout_queue* t) +{ + return t->lock.ptr != NULL; +} + +static int timeout_queue_lock(struct timeout_queue* t) +{ + t->lock.ptr = t; +} + +// unlock and flush the locked events to the main timeout queue. +static int timeout_queue_unlock(struct timeout_queue* t) +{ + struct timeout_evt* evt, *tmp, *first; + size_t pos; + t->lock.ptr = NULL; + + evt = t->lock.next; + while (evt) + { + tmp = evt->next; + pos = evt->timestamp % t->max; + first = t->events[pos]; + if (first) + { + first->prev->next = evt; + evt->prev = first->prev; + first->prev = evt; + } + else + { + t->events[pos] = evt; + evt->prev = evt; + } + evt->next = 0; + evt = tmp; + } + + t->lock.next = 0; + t->lock.prev = 0; +} + + size_t timeout_queue_process(struct timeout_queue* t, time_t now) { size_t pos = (size_t) t->last; size_t events = 0; struct timeout_evt* evt = 0; t->last = now; + timeout_queue_lock(t); for (; pos <= now; pos++) { while ((evt = t->events[pos % t->max])) @@ -67,6 +112,7 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now) events++; } } + timeout_queue_unlock(t); return events; } @@ -82,6 +128,61 @@ size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now) return seconds; } +static void timeout_queue_insert_locked(struct timeout_queue* t, struct timeout_evt* evt) +{ + /* All events point back to the sentinel. + * this means the event is considered schedule (see timeout_evt_is_scheduled), + * and it is easy to tell if the event is in the wait queue or not. + */ + evt->prev = &t->lock; + evt->next = NULL; + + // The sentinel next points to the first event in the locked queue + // The sentinel prev points to the last evetnt in the locked queue. + // NOTE: if prev is != NULL then next also must be != NULL. + if (t->lock.prev) + { + t->lock.prev->next = evt; + t->lock.prev = evt; + } + else + { + t->lock.next = evt; + t->lock.prev = evt; + } + return; +} + +static void timeout_queue_remove_locked(struct timeout_queue* t, struct timeout_evt* evt) +{ + uhub_assert(evt->prev == &t->lock); + if (t->lock.next == evt) + { + t->lock.next = evt->next; + if (t->lock.prev == evt) + t->lock.prev = evt->next; + } + else + { + struct timeout_evt *prev, *it; + prev = 0; + it = t->lock.next; + while (it) + { + prev = it; + it = it->next; + if (it == evt) + { + prev->next = it->next; + if (!prev->next) + t->lock.prev = prev; + } + } + } + timeout_evt_reset(evt); +} + + void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) { @@ -89,9 +190,15 @@ void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size size_t pos = ((t->last + seconds) % t->max); evt->timestamp = t->last + seconds; evt->next = 0; - + + if (timeout_queue_locked(t)) + { + timeout_queue_insert_locked(t, evt); + return; + } + first = t->events[pos]; - + if (first) { uhub_assert(first->timestamp == evt->timestamp); @@ -112,6 +219,13 @@ void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt) size_t pos = (evt->timestamp % t->max); struct timeout_evt* first = t->events[pos]; + // Removing a locked event + if (evt->prev == &t->lock) + { + timeout_queue_remove_locked(t, evt); + return; + } + if (!first || !evt->prev) return; diff --git a/src/network/timeout.h b/src/network/timeout.h index b40abd9..c48efaf 100644 --- a/src/network/timeout.h +++ b/src/network/timeout.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -43,6 +43,7 @@ struct timeout_queue { time_t last; size_t max; + struct timeout_evt lock; struct timeout_evt** events; }; diff --git a/src/network/timer.c b/src/network/timer.c index 48911d5..70b8dbb 100644 --- a/src/network/timer.c +++ b/src/network/timer.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/network/tls.h b/src/network/tls.h index e40a558..f66bd92 100644 --- a/src/network/tls.h +++ b/src/network/tls.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugin_api/command_api.h b/src/plugin_api/command_api.h index 021d933..b00c506 100644 --- a/src/plugin_api/command_api.h +++ b/src/plugin_api/command_api.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugin_api/handle.h b/src/plugin_api/handle.h index 56c17e2..643d648 100644 --- a/src/plugin_api/handle.h +++ b/src/plugin_api/handle.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugin_api/message_api.h b/src/plugin_api/message_api.h index 8903f8f..91e13e7 100644 --- a/src/plugin_api/message_api.h +++ b/src/plugin_api/message_api.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugin_api/types.h b/src/plugin_api/types.h index 4fce255..afb5f64 100644 --- a/src/plugin_api/types.h +++ b/src/plugin_api/types.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugins/mod_auth_simple.c b/src/plugins/mod_auth_simple.c index d4c35d3..29c86eb 100644 --- a/src/plugins/mod_auth_simple.c +++ b/src/plugins/mod_auth_simple.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -177,16 +177,15 @@ static void unload_acl(struct acl_data* data) static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data) { struct acl_data* acl = (struct acl_data*) plugin->ptr; - struct auth_info* info = (struct auth_info*) list_get_first(acl->users); - while (info) + struct auth_info* info; + LIST_FOREACH(struct auth_info*, info, acl->users, { if (strcasecmp((char*)info->nickname, nickname) == 0) { memcpy(data, info, sizeof(struct auth_info)); return st_allow; } - info = (struct auth_info*) list_get_next(acl->users); - } + }); if (acl->exclusive) return st_deny; return st_default; diff --git a/src/plugins/mod_auth_sqlite.c b/src/plugins/mod_auth_sqlite.c index ab36674..ec25959 100644 --- a/src/plugins/mod_auth_sqlite.c +++ b/src/plugins/mod_auth_sqlite.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -199,7 +199,7 @@ static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, st sqlite3_free(errMsg); return st_default; } - + if (result.found) return st_allow; return st_default; @@ -222,7 +222,7 @@ static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* u return st_deny; } return st_allow; - + } static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user) @@ -243,7 +243,7 @@ static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* use return st_deny; } return st_allow; - + } static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user) diff --git a/src/plugins/mod_chat_history.c b/src/plugins/mod_chat_history.c index 67d9105..0850f91 100644 --- a/src/plugins/mod_chat_history.c +++ b/src/plugins/mod_chat_history.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -50,9 +50,7 @@ static void history_add(struct plugin_handle* plugin, struct plugin_user* from, list_append(data->chat_history, log); while (list_size(data->chat_history) > data->history_max) { - char* msg = list_get_first(data->chat_history); - list_remove(data->chat_history, msg); - hub_free(msg); + list_remove_first(data->chat_history, hub_free); } } @@ -79,16 +77,14 @@ static size_t get_messages(struct chat_history_data* data, size_t num, struct cb skiplines = total - num; cbuf_append(outbuf, "\n"); - message = (char*) list_get_first(messages); - while (message) + LIST_FOREACH(char*, message, messages, { if (--skiplines < 0) { cbuf_append(outbuf, message); lines++; } - message = (char*) list_get_next(messages); - } + }); cbuf_append(outbuf, "\n"); return lines; } @@ -139,7 +135,7 @@ static int command_history(struct plugin_handle* plugin, struct plugin_user* use maxlines = arg->data.integer; else maxlines = data->history_default; - + buf = cbuf_create(MAX_HISTORY_SIZE); cbuf_append_format(buf, "*** %s: Chat History:\n", cmd->prefix); get_messages(data, maxlines, buf); diff --git a/src/plugins/mod_chat_history_sqlite.c b/src/plugins/mod_chat_history_sqlite.c new file mode 100644 index 0000000..c83233b --- /dev/null +++ b/src/plugins/mod_chat_history_sqlite.c @@ -0,0 +1,347 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2013, 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 "plugin_api/handle.h" +#include "plugin_api/command_api.h" +#include "util/config_token.h" +#include +#include "util/memory.h" +#include "util/misc.h" +#include "util/list.h" +#include "util/cbuffer.h" + +#define MAX_HISTORY_SIZE 16384 + +struct chat_history_data +{ + size_t history_max; ///<<< "the maximum number of chat messages kept in history." + size_t history_default; ///<<< "the default number of chat messages returned if no limit was provided" + size_t history_connect; ///<<< "the number of chat messages provided when users connect to the hub." + sqlite3* db; ///<<< "The chat history storage database." + struct plugin_command_handle* command_history_handle; ///<<< "A handle to the !history command." + struct plugin_command_handle* command_historycleanup_handle; ///<<< "A handle to the !historycleanup command." +}; + +struct chat_history_line +{ + char message[MAX_HISTORY_SIZE]; + char from[MAX_NICK_LEN]; + char time[20]; +}; + +static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; } + +static const char* sql_escape_string(const char* str) +{ + static char out[1024]; + size_t i = 0; + size_t n = 0; + for (; n < strlen(str); n++) + { + if (str[n] == '\'') + out[i++] = '\''; + out[i++] = str[n]; + } + out[i++] = '\0'; + return out; +} + +static int sql_execute(struct chat_history_data* sql, int (*callback)(void* ptr, int argc, char **argv, char **colName), void* ptr, const char* sql_fmt, ...) +{ + va_list args; + char query[1024]; + char* errMsg; + int rc; + + va_start(args, sql_fmt); + vsnprintf(query, sizeof(query), sql_fmt, args); + + rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg); + if (rc != SQLITE_OK) + { + sqlite3_free(errMsg); + return -rc; + } + + rc = sqlite3_changes(sql->db); + return rc; +} + +static void create_tables(struct plugin_handle* plugin) +{ + const char* table_create = "CREATE TABLE IF NOT EXISTS chat_history" + "(" + "from_nick CHAR," + "message TEXT," + "time TIMESTAMP DEFAULT (DATETIME('NOW'))" + ");"; + + struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; + sql_execute(data, null_callback, NULL, table_create); +} +/** + * Add a chat message to history. + */ +static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags) +{ + struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; + char* history_line = strdup(sql_escape_string(message)); + char* history_nick = strdup(sql_escape_string(from->nick)); + + sql_execute(data, null_callback, NULL, "INSERT INTO chat_history (from_nick, message) VALUES('%s', '%s');DELETE FROM chat_history WHERE time <= (SELECT time FROM chat_history ORDER BY time DESC LIMIT %d,1);", history_nick, history_line, data->history_max); + + hub_free(history_line); + hub_free(history_nick); +} + +/** + * Obtain messages from the chat history as a linked list + */ + +static int get_messages_callback(void* ptr, int argc, char **argv, char **colName) +{ + struct linked_list* messages = (struct linked_list*) ptr; + struct chat_history_line* line = hub_malloc(sizeof(struct chat_history_line)); + int i = 0; + + memset(line, 0, sizeof(struct chat_history_line)); + + for (; i < argc; i++) { + if (strcmp(colName[i], "from_nick") == 0) + strncpy(line->from, argv[i], MAX_NICK_LEN); + else if (strcmp(colName[i], "message") == 0) + strncpy(line->message, argv[i], MAX_HISTORY_SIZE); + else if (strcmp(colName[i], "time") == 0) + strncpy(line->time, argv[i], 20); + } + + list_append(messages, line); + + return 0; +} + +void user_login(struct plugin_handle* plugin, struct plugin_user* user) +{ + struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; + struct cbuffer* buf = NULL; + struct linked_list* found = (struct linked_list*) list_create(); + + sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", (int) data->history_connect); + + if (data->history_connect > 0 && list_size(found) > 0) + { + buf = cbuf_create(MAX_HISTORY_SIZE); + cbuf_append(buf, "Chat history:\n\n"); + struct chat_history_line* history_line; + history_line = (struct chat_history_line*) list_get_last(found); + while (history_line) + { + cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message); + list_remove(found, history_line); + hub_free(history_line); + history_line = (struct chat_history_line*) list_get_last(found); + } + plugin->hub.send_message(plugin, user, cbuf_get(buf)); + cbuf_destroy(buf); + } + list_clear(found, &hub_free); + list_destroy(found); +} + +/** + * The callback function for handling the !history command. + */ +static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) +{ + struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; + struct cbuffer* buf = cbuf_create(MAX_HISTORY_SIZE); + struct linked_list* found = (struct linked_list*) list_create(); + struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer); + int maxlines; + + if (arg) + maxlines = arg->data.integer; + else + maxlines = data->history_default; + + sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", maxlines); + + size_t linecount = list_size(found); + + if (linecount > 0) + { + cbuf_append_format(buf, "*** %s: Chat History:\n\n", cmd->prefix); + struct chat_history_line* history_line; + history_line = (struct chat_history_line*) list_get_last(found); + while (history_line) + { + cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message); + list_remove(found, history_line); + hub_free(history_line); + history_line = (struct chat_history_line*) list_get_last(found); + } + } + else + { + cbuf_append_format(buf, "*** %s: No messages found.", cmd->prefix); + } + + plugin->hub.send_message(plugin, user, cbuf_get(buf)); + cbuf_destroy(buf); + list_clear(found, &hub_free); + list_destroy(found); + + return 0; +} + +static int command_historycleanup(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) +{ + struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; + struct cbuffer* buf = cbuf_create(128); + int rc = 0; + + rc = sql_execute(data, null_callback, NULL, "DELETE FROM chat_history;"); + + if (!rc) + cbuf_append_format(buf, "*** %s: Unable to clean chat history table.", cmd->prefix); + else + cbuf_append_format(buf, "*** %s: Cleaned chat history table.", cmd->prefix); + + plugin->hub.send_message(plugin, user, cbuf_get(buf)); + cbuf_destroy(buf); + + return 0; +} + +static void set_error_message(struct plugin_handle* plugin, const char* msg) +{ + plugin->error_msg = msg; +} + +static struct chat_history_data* parse_config(const char* line, struct plugin_handle* plugin) +{ + struct chat_history_data* data = (struct chat_history_data*) hub_malloc_zero(sizeof(struct chat_history_data)); + struct cfg_tokens* tokens = cfg_tokenize(line); + char* token = cfg_token_get_first(tokens); + + uhub_assert(data != NULL); + + data->history_max = 200; + data->history_default = 25; + data->history_connect = 5; + + while (token) + { + struct cfg_settings* setting = cfg_settings_split(token); + + if (!setting) + { + set_error_message(plugin, "Unable to parse startup parameters"); + cfg_tokens_free(tokens); + hub_free(data); + return 0; + } + + if (strcmp(cfg_settings_get_key(setting), "file") == 0) + { + if (!data->db) + { + if (sqlite3_open(cfg_settings_get_value(setting), &data->db)) + { + cfg_tokens_free(tokens); + cfg_settings_free(setting); + hub_free(data); + set_error_message(plugin, "Unable to open database file"); + return 0; + } + } + } + else if (strcmp(cfg_settings_get_key(setting), "history_max") == 0) + { + data->history_max = (size_t) uhub_atoi(cfg_settings_get_value(setting)); + } + else if (strcmp(cfg_settings_get_key(setting), "history_default") == 0) + { + data->history_default = (size_t) uhub_atoi(cfg_settings_get_value(setting)); + } + else if (strcmp(cfg_settings_get_key(setting), "history_connect") == 0) + { + data->history_connect = (size_t) uhub_atoi(cfg_settings_get_value(setting)); + } + else + { + set_error_message(plugin, "Unknown startup parameters given"); + cfg_tokens_free(tokens); + cfg_settings_free(setting); + hub_free(data); + return 0; + } + + cfg_settings_free(setting); + token = cfg_token_get_next(tokens); + } + cfg_tokens_free(tokens); + return data; +} + +int plugin_register(struct plugin_handle* plugin, const char* config) +{ + struct chat_history_data* data; + PLUGIN_INITIALIZE(plugin, "SQLite chat history plugin", "1.0", "Provide a global chat history log."); + + plugin->funcs.on_user_chat_message = history_add; + plugin->funcs.on_user_login = user_login; + data = parse_config(config, plugin); + + if (!data) + return -1; + + plugin->ptr = data; + + create_tables(plugin); + + data->command_history_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle)); + PLUGIN_COMMAND_INITIALIZE(data->command_history_handle, plugin, "history", "?N", auth_cred_guest, &command_history, "Show chat message history."); + plugin->hub.command_add(plugin, data->command_history_handle); + + data->command_historycleanup_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle)); + PLUGIN_COMMAND_INITIALIZE(data->command_historycleanup_handle, plugin, "historycleanup", "", auth_cred_admin, &command_historycleanup, "Clean chat message history."); + plugin->hub.command_add(plugin, data->command_historycleanup_handle); + + return 0; +} + +int plugin_unregister(struct plugin_handle* plugin) +{ + struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; + + if (data) + { + sqlite3_close(data->db); + + plugin->hub.command_del(plugin, data->command_history_handle); + plugin->hub.command_del(plugin, data->command_historycleanup_handle); + hub_free(data->command_history_handle); + hub_free(data->command_historycleanup_handle); + hub_free(data); + } + + return 0; +} + diff --git a/src/plugins/mod_chat_is_privileged.c b/src/plugins/mod_chat_is_privileged.c new file mode 100644 index 0000000..e59e84d --- /dev/null +++ b/src/plugins/mod_chat_is_privileged.c @@ -0,0 +1,171 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2013, 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 "plugin_api/handle.h" +#include "util/memory.h" + +struct user_info +{ + sid_t sid; + int warnings; +}; + +struct chat_restrictions_data +{ + size_t num_users; // number of users tracked. + size_t max_users; // max users (hard limit max 1M users due to limitations in the SID (20 bits)). + struct user_info* users; // array of max_users + + enum auth_credentials allow_privchat; // minimum credentials to allow using private chat + enum auth_credentials allow_op_contact; // minimum credentials to allow private chat to operators (including super and admins). + enum auth_credentials allow_mainchat; // minimum credentials to allow using main chat +}; + +static struct chat_data* parse_config(struct plugin_handle* plugin, const char* line) +{ + struct chat_data* data = (struct chat_data*) hub_malloc(sizeof(struct chat_data)); + struct cfg_tokens* tokens = cfg_tokenize(line); + char* token = cfg_token_get_first(tokens); + + // defaults + data->num_users = 0; + data->max_users = 512; + data->users = hub_malloc_zero(sizeof(struct user_info) * data->max_users); + data->allow_mainchat = auth_cred_guest; + data->allow_op_contact = auth_cred_guest; + data->allow_privchat = auth_cred_guest; + + while (token) + { + struct cfg_settings* setting = cfg_settings_split(token); + + if (!setting) + { + set_error_message(plugin, "Unable to parse startup parameters"); + cfg_tokens_free(tokens); + hub_free(data); + return 0; + } + + if (strcmp(cfg_settings_get_key(setting), "allow_privchat") == 0) + { + if (!string_to_boolean(cfg_settings_get_value(setting), &data->allow_privchat)) + data->allow_privchat = 0; + } + else if (strcmp(cfg_settings_get_key(setting), "minimum_access") == 0) + { + } + else + { + set_error_message(plugin, "Unknown startup parameters given"); + cfg_tokens_free(tokens); + cfg_settings_free(setting); + hub_free(data); + return 0; + } + + cfg_settings_free(setting); + token = cfg_token_get_next(tokens); + } + cfg_tokens_free(tokens); + + return data; +} + +static struct user_info* get_user_info(struct chat_data* data, sid_t sid) +{ + struct user_info* u; + + // resize buffer if needed. + if (sid >= data->max_users) + { + u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1)); + memcpy(u, data->users, data->max_users); + hub_free(data->users); + data->users = u; + data->max_users = sid; + u = NULL; + } + + u = &data->users[sid]; + + // reset counters if the user was not previously known. + if (!u->sid) + { + u->sid = sid; + u->warnings = 0; + data->num_users++; + } + return u; +} + +static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user) +{ + struct chat_data* data = (struct chat_data*) plugin->ptr; + /*struct user_info* info = */ + get_user_info(data, user->sid); +} + +static void on_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason) +{ + struct chat_data* data = (struct chat_data*) plugin->ptr; + struct user_info* info = get_user_info(data, user->sid); + if (info->sid) + data->num_users--; + info->warnings = 0; + info->sid = 0; +} + +plugin_st on_chat_msg(struct plugin_handle* plugin, struct plugin_user* from, const char* message) +{ + struct chat_data* data = (struct chat_data*) plugin->ptr; + if (from->credentials >= + return st_default; +} + +plugin_st on_private_msg(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* message) +{ + return st_default; +} + + +int plugin_register(struct plugin_handle* plugin, const char* config) +{ + PLUGIN_INITIALIZE(plugin, "Privileged chat hub", "1.0", "Only registered users can send messages on the main chat."); + plugin->ptr = cip_initialize(); + + plugin->funcs.on_user_login = on_user_login; + plugin->funcs.on_user_logout = on_user_logout; + plugin->funcs.on_chat_msg = on_chat_msg; + plugin->funcs.on_private_msg = on_private_msg; + + return 0; +} + +int plugin_unregister(struct plugin_handle* plugin) +{ + struct chat_data* data = (struct chat_data*) plugin->ptr; + if (data) + { + hub_free(data->users); + hub_free(data); + } + return 0; +} + diff --git a/src/plugins/mod_chat_only.c b/src/plugins/mod_chat_only.c index e705ce9..648ba39 100644 --- a/src/plugins/mod_chat_only.c +++ b/src/plugins/mod_chat_only.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugins/mod_example.c b/src/plugins/mod_example.c index b5d77bc..376544b 100644 --- a/src/plugins/mod_example.c +++ b/src/plugins/mod_example.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugins/mod_logging.c b/src/plugins/mod_logging.c index 3dcace0..75d19d6 100644 --- a/src/plugins/mod_logging.c +++ b/src/plugins/mod_logging.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugins/mod_no_guest_downloads.c b/src/plugins/mod_no_guest_downloads.c index e949021..3469aac 100644 --- a/src/plugins/mod_no_guest_downloads.c +++ b/src/plugins/mod_no_guest_downloads.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugins/mod_topic.c b/src/plugins/mod_topic.c index bbc43f2..5fc1bf1 100644 --- a/src/plugins/mod_topic.c +++ b/src/plugins/mod_topic.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/plugins/mod_welcome.c b/src/plugins/mod_welcome.c index 1bd53c5..3bb8856 100644 --- a/src/plugins/mod_welcome.c +++ b/src/plugins/mod_welcome.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/system.h b/src/system.h index 98b1d85..e939237 100644 --- a/src/system.h +++ b/src/system.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -127,6 +127,10 @@ */ #endif +#ifdef __GNU__ +#define POSIX_THREAD_SUPPORT +#endif + #define USE_SELECT #ifndef WINSOCK #include diff --git a/src/tools/adcclient.c b/src/tools/adcclient.c index 6e8f210..29b7686 100644 --- a/src/tools/adcclient.c +++ b/src/tools/adcclient.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -30,7 +30,6 @@ 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 */ @@ -68,7 +67,7 @@ struct ADC_client struct net_connection* con; struct net_timer* timer; struct sockaddr_storage addr; - struct net_dns_job* dns_job; + struct net_connect_handle* connect_job; struct ADC_client_address address; char* nick; char* desc; @@ -109,7 +108,6 @@ 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", @@ -164,18 +162,12 @@ 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) { client->callback(client, ADC_CLIENT_DISCONNECTED, 0); return; } - - if (events & NET_EVENT_WRITE) - ADC_client_connect_internal(client); break; #ifdef SSL_SUPPORT @@ -374,7 +366,7 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line, } */ break; - + default: break; } @@ -539,11 +531,6 @@ struct ADC_client* ADC_client_create(const char* nickname, const char* descripti ADC_TRACE; struct ADC_client* client = (struct ADC_client*) hub_malloc_zero(sizeof(struct ADC_client)); - int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sd == -1) return NULL; - - client->con = net_con_create(); - net_con_initialize(client->con, sd, event_callback, client, 0); ADC_client_set_state(client, ps_none); client->nick = hub_strdup(nickname); @@ -570,40 +557,42 @@ void ADC_client_destroy(struct ADC_client* client) hub_free(client); } +static void connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con, void* ptr) +{ + struct ADC_client* client = (struct ADC_client*) ptr; + client->connect_job = NULL; + switch (status) + { + case net_connect_status_ok: + client->con = con; + net_con_reinitialize(client->con, event_callback, client, 0); + ADC_client_on_connected(client); + break; + + case net_connect_status_host_not_found: + case net_connect_status_no_address: + case net_connect_status_dns_error: + case net_connect_status_refused: + case net_connect_status_unreachable: + case net_connect_status_timeout: + case net_connect_status_socket_error: + ADC_client_disconnect(client); + break; + } +} + int ADC_client_connect(struct ADC_client* client, const char* address) { ADC_TRACE; if (client->state == ps_none) { - // Parse address and start name resolving! if (!ADC_client_parse_address(client, address)) return 0; - return 1; - } - return ADC_client_connect_internal(client); -} - -int ADC_client_connect_internal(struct ADC_client* client) -{ - int ret; - if (client->state == ps_dns) - { - // Done name resolving! - client->callback(client, ADC_CLIENT_CONNECTING, 0); - ADC_client_set_state(client, ps_conn); } - 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)) - { - ADC_client_on_connected(client); - } - else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR)) - { - net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); - ADC_client_set_state(client, ps_conn); - } - else + ADC_client_set_state(client, ps_conn); + client->connect_job = net_con_connect(client->address.hostname, client->address.port, connect_callback, client); + if (!client->connect_job) { ADC_client_on_disconnected(client); return 0; @@ -611,6 +600,7 @@ int ADC_client_connect_internal(struct ADC_client* client) return 1; } + static void ADC_client_on_connected(struct ADC_client* client) { ADC_TRACE; @@ -674,43 +664,6 @@ 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; @@ -753,9 +706,6 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg) client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]); - 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 47c067f..06a8548 100644 --- a/src/tools/adcclient.h +++ b/src/tools/adcclient.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/tools/adcrush.c b/src/tools/adcrush.c index fdc72ad..d42c277 100644 --- a/src/tools/adcrush.c +++ b/src/tools/adcrush.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -77,7 +77,7 @@ const char* chat_messages[MAX_CHAT_MSGS] = { "can anyone help me, pls?", "wtf?", "bullshit", - "resistance is futile.", + "resistance is futile.", "You crossed the line first, sir. You squeezed them, you hammered them to the point of desperation. And in their desperation they turned to a man they didn't fully understand.", "beam me up, scotty", "morning", @@ -87,10 +87,10 @@ const char* chat_messages[MAX_CHAT_MSGS] = { "*punt*", "*nudge*", "that's ok", - "...anyway", + "...anyway", "hola", "hey", - "hi", + "hi", "nevermind", "i think so", "dunno", @@ -173,7 +173,7 @@ static void perf_chat(struct ADC_client* client, int priv) else cmd = adc_msg_construct_source(ADC_CMD_BMSG, ADC_client_get_sid(client), strlen(msg)); hub_free(msg); - + ADC_client_send(client, cmd); } @@ -237,7 +237,6 @@ static void perf_update(struct ADC_client* client) static void client_disconnect(struct AdcFuzzUser* c) { ADC_client_destroy(c->client); - hub_free(c->client); c->client = 0; timeout_queue_remove(net_backend_get_timeout_queue(), c->timer); @@ -294,7 +293,7 @@ static void perf_normal_action(struct ADC_client* client) bot_output(client, LVL_VERBOSE, "timeout -> chat"); if (user->logged_in) perf_chat(client, 0); - + } break; @@ -486,7 +485,7 @@ int parse_address(const char* arg) { if (!arg || strlen(arg) < 9) return 0; - + if (strncmp(arg, "adc://", 6) && strncmp(arg, "adcs://", 7)) return 0; @@ -537,7 +536,7 @@ int main(int argc, char** argv) { parse_command_line(argc, argv); - + net_initialize(); net_stats_get(&stats_intermediate, &stats_total); diff --git a/src/tools/admin.c b/src/tools/admin.c index 3709368..63b030d 100644 --- a/src/tools/admin.c +++ b/src/tools/admin.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -65,17 +65,14 @@ static void on_message(struct ADC_chat_message* chat) lines = list_create(); ret = split_string(chat->message, "\n", lines, 1); - line = (char*) list_get_first(lines); - ret = 0; - while (line) + LIST_FOREACH(char*, line, lines, { if (ret > 0) printf(" "); printf("%s\n", line); ret++; - line = (char*) list_get_next(lines); - } + }); list_clear(lines, &hub_free); list_destroy(lines); @@ -135,7 +132,7 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type, break; case ADC_CLIENT_USER_JOIN: - + user_add(data->user); break; diff --git a/src/tools/fuzzer.h b/src/tools/fuzzer.h index d26ece5..b7792ab 100644 --- a/src/tools/fuzzer.h +++ b/src/tools/fuzzer.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/tools/uhub-passwd.c b/src/tools/uhub-passwd.c index 09b0aaa..512e006 100644 --- a/src/tools/uhub-passwd.c +++ b/src/tools/uhub-passwd.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -319,7 +319,7 @@ static int pass(size_t argc, const char** argv) fprintf(stderr, "Unable to change password for user \"%s\"\n", argv[0]); return 1; } - + return 0; } diff --git a/src/uhub.h b/src/uhub.h index 4ba9672..f078d76 100644 --- a/src/uhub.h +++ b/src/uhub.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -69,6 +69,7 @@ extern "C" { #include "util/misc.h" #include "util/tiger.h" #include "util/threads.h" +#include "util/rbtree.h" #include "adc/sid.h" #include "adc/message.h" diff --git a/src/util/cbuffer.c b/src/util/cbuffer.c index 3075011..d263c0a 100644 --- a/src/util/cbuffer.c +++ b/src/util/cbuffer.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/cbuffer.h b/src/util/cbuffer.h index 0c47c12..f6cccf7 100644 --- a/src/util/cbuffer.h +++ b/src/util/cbuffer.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/config_token.c b/src/util/config_token.c index 705b79c..827767b 100644 --- a/src/util/config_token.c +++ b/src/util/config_token.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/config_token.h b/src/util/config_token.h index 1b40f23..7aa4b8b 100644 --- a/src/util/config_token.h +++ b/src/util/config_token.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/credentials.c b/src/util/credentials.c index 46ce076..722f0cf 100644 --- a/src/util/credentials.c +++ b/src/util/credentials.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -71,7 +71,7 @@ const char* auth_cred_to_string(enum auth_credentials cred) case auth_cred_link: return "link"; case auth_cred_admin: return "admin"; } - + return ""; }; diff --git a/src/util/credentials.h b/src/util/credentials.h index 8323988..6a77f57 100644 --- a/src/util/credentials.h +++ b/src/util/credentials.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/floodctl.c b/src/util/floodctl.c index 58ebdc8..64b2c79 100644 --- a/src/util/floodctl.c +++ b/src/util/floodctl.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/floodctl.h b/src/util/floodctl.h index 4fea4a4..4f83b3b 100644 --- a/src/util/floodctl.h +++ b/src/util/floodctl.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -36,7 +36,7 @@ void flood_control_reset(struct flood_control*); * @param max_count Max count for flood control * @param window Time window for max_count to appear. * @param now The current time. - * + * * @return 0 if flood no flood detected. * 1 if flood detected. */ diff --git a/src/util/getopt.c b/src/util/getopt.c index dedee4c..5e8c7e4 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/getopt.h b/src/util/getopt.h index 37ca71d..6cfe0f6 100644 --- a/src/util/getopt.h +++ b/src/util/getopt.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/list.c b/src/util/list.c index 4f5253e..c9b1a31 100644 --- a/src/util/list.c +++ b/src/util/list.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -65,7 +65,7 @@ void list_append(struct linked_list* list, void* data_ptr) return; } new_node->ptr = data_ptr; - + if (list->last) { list->last->next = new_node; @@ -80,6 +80,35 @@ void list_append(struct linked_list* list, void* data_ptr) list->size++; } +void list_append_list(struct linked_list* list, struct linked_list* other) +{ + /* Anything to move? */ + if (!other->size) + return; + + if (!list->size) + { + /* If the list is empty, just move the pointers */ + list->size = other->size; + list->first = other->first; + list->last = other->last; + list->iterator = other->iterator; + } + else + { + other->first->prev = list->last; + list->last->next = other->first; + list->last = other->last; + list->size += other->size; + } + + /* Make sure the original list appears empty */ + other->size = 0; + other->first = NULL; + other->last = NULL; + other->iterator = NULL; +} + void list_remove(struct linked_list* list, void* data_ptr) { @@ -94,10 +123,10 @@ void list_remove(struct linked_list* list, void* data_ptr) { if (node->next) node->next->prev = node->prev; - + if (node->prev) node->prev->next = node->next; - + if (node == list->last) list->last = node->prev; @@ -113,6 +142,30 @@ void list_remove(struct linked_list* list, void* data_ptr) } } +void list_remove_first(struct linked_list* list, void (*free_handle)(void* ptr)) +{ + struct node* node = list->first; + + list->iterator = NULL; + + if (!node) + return; + + list->first = node->next; + + if (list->first) + list->first->prev = NULL; + + if (list->last == node) + list->last = NULL; + + list->size--; + + if (free_handle) + free_handle(node->ptr); + hub_free(node); +} + size_t list_size(struct linked_list* list) { @@ -141,7 +194,7 @@ void* list_get_first(struct linked_list* list) list->iterator = list->first; if (list->iterator == NULL) return NULL; - + return list->iterator->ptr; } @@ -150,7 +203,7 @@ struct node* list_get_first_node(struct linked_list* list) list->iterator = list->first; if (list->iterator == NULL) return NULL; - + return list->iterator; } @@ -159,7 +212,7 @@ void* list_get_last(struct linked_list* list) list->iterator = list->last; if (list->iterator == NULL) return NULL; - + return list->iterator->ptr; } @@ -168,9 +221,9 @@ struct node* list_get_last_node(struct linked_list* list) list->iterator = list->last; if (list->iterator == NULL) return NULL; - + return list->iterator; - + } void* list_get_next(struct linked_list* list) @@ -179,7 +232,7 @@ void* list_get_next(struct linked_list* list) list->iterator = list->first; else list->iterator = list->iterator->next; - + if (list->iterator == NULL) return NULL; @@ -191,9 +244,9 @@ void* list_get_prev(struct linked_list* list) { if (list->iterator == NULL) return NULL; - + list->iterator = list->iterator->prev; - + if (list->iterator == NULL) return NULL; diff --git a/src/util/list.h b/src/util/list.h index 7ea9de1..89cc42d 100644 --- a/src/util/list.h +++ b/src/util/list.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -42,6 +42,13 @@ extern void list_clear(struct linked_list*, void (*free_handle)(void* ptr) ); extern void list_append(struct linked_list* list, void* data_ptr); +/** + * A special list append that moves all nodes from other_list to list. + * The other list will be empty. + */ +extern void list_append_list(struct linked_list* list, struct linked_list* other); + + /** * Remove data_ptr from the list. If multiple versions occur, only the first one is removed. */ @@ -57,5 +64,15 @@ extern void* list_get_prev(struct linked_list*); extern struct node* list_get_first_node(struct linked_list*); extern struct node* list_get_last_node(struct linked_list*); +/** + * Remove the first element, and call the free_handle function (if not NULL) + * to ensure the data is freed also. + */ +extern void list_remove_first(struct linked_list* list, void (*free_handle)(void* ptr)); + +#define LIST_FOREACH(TYPE, ITEM, LIST, BLOCK) \ + for (ITEM = (TYPE) list_get_first(LIST); ITEM; ITEM = (TYPE) list_get_next(LIST)) \ + BLOCK + #endif /* HAVE_UHUB_LINKED_LIST_H */ diff --git a/src/util/log.c b/src/util/log.c index 42badb3..e49acbb 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -21,7 +21,15 @@ #include #ifndef WIN32 + +#ifdef SYSTEMD +#define SD_JOURNAL_SUPPRESS_LOCATION +#include + +#else #include +#endif + static int use_syslog = 0; #endif @@ -78,22 +86,24 @@ void hub_log_initialize(const char* file, int syslog) return; } #endif - + #ifndef WIN32 if (syslog) { use_syslog = 1; + #ifndef SYSTEMD openlog("uhub", LOG_PID, LOG_USER); + #endif } #endif - + if (!file) { logfile = stderr; return; } - + logfile = fopen(file, "a"); if (!logfile) { @@ -127,12 +137,14 @@ void hub_log_shutdown() netdump = NULL; } #endif - + #ifndef WIN32 if (use_syslog) { use_syslog = 0; + #ifndef SYSTEMD closelog(); + #endif } #endif } @@ -174,7 +186,7 @@ void hub_log(int log_verbosity, const char *format, ...) return; } #endif - + if (log_verbosity < verbosity) { t = time(NULL); @@ -183,7 +195,7 @@ void hub_log(int log_verbosity, const char *format, ...) va_start(args, format); vsnprintf(logmsg, 1024, format, args); va_end(args); - + if (logfile) { fprintf(logfile, "%s %6s: %s\n", timestamp, prefixes[log_verbosity], logmsg); @@ -199,34 +211,44 @@ void hub_log(int log_verbosity, const char *format, ...) if (use_syslog) { int level = 0; - + if (verbosity < log_info) return; - + va_start(args, format); vsnprintf(logmsg, 1024, format, args); va_end(args); - + switch (log_verbosity) { case log_fatal: level = LOG_CRIT; break; case log_error: level = LOG_ERR; break; case log_warning: level = LOG_WARNING; break; - case log_user: level = LOG_INFO | LOG_AUTH; break; + #ifdef SYSTEMD + case log_user: level = LOG_INFO; break; + + #else + case log_user: level = LOG_INFO | LOG_AUTH; break; + #endif case log_info: level = LOG_INFO; break; case log_debug: level = LOG_DEBUG; break; - + default: level = 0; break; } - + if (level == 0) return; - + + #ifdef SYSTEMD + sd_journal_print(level, "%s", logmsg); + + #else level |= (LOG_USER | LOG_DAEMON); syslog(level, "%s", logmsg); + #endif } #endif - + } diff --git a/src/util/log.h b/src/util/log.h index 1fcd42e..1f8a075 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/memory.c b/src/util/memory.c index e980e87..c1ef45b 100644 --- a/src/util/memory.c +++ b/src/util/memory.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -48,7 +48,7 @@ void internal_debug_print_leaks() size_t leak = 0; size_t count = 0; LOG_MEMORY("--- exit (allocs: %d, size: " PRINTF_SIZE_T ") ---", hub_alloc_count, hub_alloc_size); - + for (; n < UHUB_MAX_ALLOCS; n++) { if (hub_allocs[n].ptr) @@ -58,7 +58,7 @@ void internal_debug_print_leaks() LOG_MEMORY("leak %p size: " PRINTF_SIZE_T " (bt: %p %p)", hub_allocs[n].ptr, hub_allocs[n].size, hub_allocs[n].stack1, hub_allocs[n].stack2); } } - + LOG_MEMORY("--- done (allocs: %d, size: " PRINTF_SIZE_T ", peak: %d/" PRINTF_SIZE_T ", oom: " PRINTF_SIZE_T ") ---", count, leak, hub_alloc_peak_count, hub_alloc_peak_size, hub_alloc_oom); } #endif /* REALTIME_MALLOC_TRACKING */ @@ -67,9 +67,9 @@ void* internal_debug_mem_malloc(size_t size, const char* where) { size_t n = 0; char* ptr = malloc(size); - + #ifdef REALTIME_MALLOC_TRACKING - + /* Make sure the malloc info struct is initialized */ if (!hub_alloc_count) { @@ -81,17 +81,17 @@ void* internal_debug_mem_malloc(size_t size, const char* where) hub_allocs[n].stack1 = 0; hub_allocs[n].stack2 = 0; } - + atexit(&internal_debug_print_leaks); } - + if (ptr) { if (malloc_slot != -1) n = (size_t) malloc_slot; else n = 0; - + for (; n < UHUB_MAX_ALLOCS; n++) { if (!hub_allocs[n].ptr) @@ -100,13 +100,13 @@ void* internal_debug_mem_malloc(size_t size, const char* where) hub_allocs[n].size = size; hub_allocs[n].stack1 = __builtin_return_address(1); hub_allocs[n].stack2 = __builtin_return_address(2); - + hub_alloc_size += size; hub_alloc_count++; - + hub_alloc_peak_count = MAX(hub_alloc_count, hub_alloc_peak_count); hub_alloc_peak_size = MAX(hub_alloc_size, hub_alloc_peak_size); - + LOG_MEMORY("%s %p (%d bytes) (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", where, ptr, (int) size, hub_allocs[n].stack1, hub_allocs[n].stack2, hub_alloc_count, hub_alloc_size); break; } @@ -147,7 +147,7 @@ void internal_debug_mem_free(void* ptr) return; } } - + malloc_slot = -1; abort(); LOG_MEMORY("free %p *** NOT ALLOCATED *** (bt: %p %p)", ptr, stack1, stack2); diff --git a/src/util/memory.h b/src/util/memory.h index 55baab7..d01fc18 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2010, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/misc.c b/src/util/misc.c index 3a7851c..b0f3138 100644 --- a/src/util/misc.c +++ b/src/util/misc.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2011, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -37,7 +37,7 @@ static int is_printable(unsigned char c) { if (c >= 32) return 1; - + if (c == '\t' || c == '\r' || c == '\n') return 1; return 0; @@ -59,7 +59,7 @@ char* strip_white_space(char* string) /* Strip appending whitespace */ pos = &string[strlen(string)-1]; while (&string[0] < &pos[0] && is_white_space(pos[0])) { pos[0] = 0; pos--; } - + return string; } @@ -68,9 +68,9 @@ static int is_valid_utf8_str(const char* string, size_t length) int expect = 0; char div = 0; size_t pos = 0; - + if (length == 0) return 1; - + for (pos = 0; pos < length; pos++) { if (expect) @@ -243,7 +243,7 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler) LOG_ERROR("Unable to open file %s: %s", file, strerror(errno)); return -2; } - + ret = read(fd, buf, MAX_RECV_BUF-1); close(fd); @@ -274,12 +274,12 @@ int uhub_atoi(const char* value) { int val = 0; int i = 0; for (; i < len; i++) - if (value[i] > '9' || value[i] < '0') + if (value[i] > '9' || value[i] < '0') offset++; - - for (i = offset; i< len; i++) + + for (i = offset; i< len; i++) val = val*10 + (value[i] - '0'); - + return value[0] == '-' ? -val : val; } @@ -360,7 +360,7 @@ void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_ char* c_buf = (char*) haystack; char* c_pat = (char*) needle; char* ptr = memchr(c_buf, c_pat[0], haystacklen); - + while (ptr && ((size_t) (&ptr[0] - &c_buf[0]) < haystacklen)) { if (!memcmp(ptr, c_pat, needlelen)) @@ -382,7 +382,7 @@ int split_string(const char* string, const char* split, struct linked_list* list for (;;) { tmp1 = strstr(string, split); - + if (tmp1) tmp2 = hub_strndup(string, tmp1 - string); else tmp2 = hub_strdup(string); diff --git a/src/util/misc.h b/src/util/misc.h index 9841c7f..52b9be4 100644 --- a/src/util/misc.h +++ b/src/util/misc.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/rbtree.c b/src/util/rbtree.c index 167ab8d..33f7841 100644 --- a/src/util/rbtree.c +++ b/src/util/rbtree.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -157,7 +157,7 @@ static struct rb_node* rb_tree_insert_r(struct rb_tree* tree, struct rb_node* no struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree_free f) { - struct rb_tree* tree = a(sizeof(struct rb_tree)); + struct rb_tree* tree = a ? a(sizeof(struct rb_tree)) : hub_malloc(sizeof(struct rb_tree)); tree->compare = compare; tree->alloc = a ? a : hub_malloc; tree->free = f ? f : hub_free; diff --git a/src/util/rbtree.h b/src/util/rbtree.h index e3dd5fb..e47a503 100644 --- a/src/util/rbtree.h +++ b/src/util/rbtree.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/threads.c b/src/util/threads.c index b76ef91..b4e098e 100644 --- a/src/util/threads.c +++ b/src/util/threads.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/threads.h b/src/util/threads.h index 0e4a9ac..604777d 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/util/tiger.c b/src/util/tiger.c index ee1e288..1f6fe0b 100644 --- a/src/util/tiger.c +++ b/src/util/tiger.c @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -57,7 +57,7 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) { a = state[0]; b = state[1]; c = state[2]; - + x0 = str[0]; x1 = str[1]; x2 = str[2]; @@ -70,7 +70,7 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) { aa = a; bb = b; cc = c; - + PASS(a, b, c, 5); x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; @@ -91,7 +91,7 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) { x7 -= x6 ^ 0x0123456789ABCDEFULL; PASS(c, a, b, 7); - + x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; @@ -130,9 +130,9 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) { x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL; - + PASS(a, b, c, 9); - + swap = a; a = c; c = b; @@ -143,7 +143,7 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) { a ^= aa; b -= bb; c += cc; - + state[0] = a; state[1] = b; state[2] = c; @@ -207,7 +207,7 @@ void tiger(uint64_t* str, uint64_t length, uint64_t res[3]) { } for (; j < 56; j++) temp[j] = 0; - + ((uint64_t*) (&(temp[56])))[0] = ((uint64_t) length) << 3; tiger_compress(((uint64_t*) temp), res); diff --git a/src/util/tiger.h b/src/util/tiger.h index b8381c2..7eb391d 100644 --- a/src/util/tiger.h +++ b/src/util/tiger.h @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2009, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 diff --git a/src/version.h.in b/src/version.h.in index 88b6038..4e5d961 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,6 +1,6 @@ /* * uhub - A tiny ADC p2p connection hub - * Copyright (C) 2007-2012, Jan Vidar Krey + * Copyright (C) 2007-2013, 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 @@ -32,5 +32,5 @@ #define PRODUCT_STRING PRODUCT "/" GIT_VERSION #ifndef COPYRIGHT -#define COPYRIGHT "Copyright (c) 2007-2012, Jan Vidar Krey " +#define COPYRIGHT "Copyright (c) 2007-2013, Jan Vidar Krey " #endif diff --git a/tools/uhub-adc-redirector.py b/tools/uhub-adc-redirector.py new file mode 100755 index 0000000..85f336f --- /dev/null +++ b/tools/uhub-adc-redirector.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +""" +A simple ADC redirector service. +""" + +import SocketServer + +# The target hub we want to redirect clients to +redirect_uri = "adcs://adcs.uhub.org:1511" + +# A message to be sent to users while they are being redirected. +message = "This hub has been permanently moved." + +# The chat name of the message. +bot_name = "Redirector" + +# The local address and port to bind the redirector to. +bind_addr = "0.0.0.0" +bind_port = 1411 + +class AdcRedirector(SocketServer.BaseRequestHandler): + + def escape(self, str): + modified = str.replace("\\", "\\\\").replace(" ", "\\s").replace("\n", "\\n") + return modified; + + def handle(self): + supports = False; + while True: + data = self.request.recv(1024) + if (data.startswith("HSUP") and not supports): + self.request.sendall("ISUP ADBASE ADTIGR\nISID AAAX\nIINF CT32 NI%(botname)s VEuhub-adc-redirector/0.1\n" % { "address": redirect_uri, "botname": self.escape(bot_name), "message": self.escape(message) }) + supports = True + elif (data.startswith("BINF") and supports): + self.request.sendall("IMSG %(message)s\nIQUI AAAX RD%(address)s\n" % {"message": self.escape(message), "address": redirect_uri }) + break + else: + break + +if __name__ == "__main__": + server = SocketServer.TCPServer((bind_addr, bind_port), AdcRedirector) + server.allow_reuse_address = True + server.serve_forever() diff --git a/tools/uhub-nmdc-redirector.py b/tools/uhub-nmdc-redirector.py new file mode 100755 index 0000000..50b7d4b --- /dev/null +++ b/tools/uhub-nmdc-redirector.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +""" +A simple NMDC to ADC redirector service. +""" + +import SocketServer + +# The target hub we want to redirect clients to +redirect_uri = "adcs://adcs.uhub.org:1511" + +# A message to be sent to users while they are being redirected. +message = "This hub has been permanently moved." + +# The chat name of the message. +bot_name = "Redirector" + +# The local address and port to bind the redirector to. +bind_addr = "0.0.0.0" +bind_port = 1411 + +class NmdcRedirector(SocketServer.BaseRequestHandler): + + def setup(self): + self.request.sendall("<%(botname)s> %(message)s|$ForceMove %(address)s|" % { "address": redirect_uri, "botname": bot_name, "message": message }) + return False + +if __name__ == "__main__": + server = SocketServer.TCPServer((bind_addr, bind_port), NmdcRedirector) + server.allow_reuse_address = True + server.serve_forever()