Compare commits

..

1 Commits
0.4.1 ... cmake

Author SHA1 Message Date
Jan Vidar Krey
bc043ec7cd Use correct source directory for building outside of source. 2012-10-04 21:59:20 +00:00
60 changed files with 863 additions and 4222 deletions

View File

@@ -3,9 +3,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
FleetCommand, Hub topic
MiMic, Implemented user commands
Boris Pek (tehnick), Debian/Ubuntu packaging
Tillmann Karras (Tilka), Misc. bug fixes
Yoran Heling (Yorhel), TLS/SSL handshake detection bugfixes
Blair Bonnett, Misc. bug fixes
tehnick, Debian and Ubuntu packaging.

View File

@@ -5,8 +5,7 @@
cmake_minimum_required (VERSION 2.8.3)
project (uhub NONE)
enable_language(C)
project (uhub)
set (UHUB_VERSION_MAJOR 0)
set (UHUB_VERSION_MINOR 4)
@@ -17,21 +16,12 @@ set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src")
option(RELEASE "Release build, debug build if disabled" ON)
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(ADC_STRESS "Enable the stress tester client" OFF)
find_package(Git)
if (SSL_SUPPORT)
if (USE_OPENSSL)
find_package(OpenSSL)
else()
find_package(GnuTLS)
endif()
if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND)
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS are not found!")
endif()
find_package(OpenSSL REQUIRED)
endif()
if (MSVC)
@@ -40,57 +30,90 @@ endif()
include_directories("${PROJECT_SOURCE_DIR}")
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c)
list (REMOVE_ITEM uhub_SOURCES
${PROJECT_SOURCE_DIR}/core/gen_config.c
${PROJECT_SOURCE_DIR}/core/main.c
set (network_SOURCES
${PROJECT_SOURCE_DIR}/network/backend.c
${PROJECT_SOURCE_DIR}/network/connection.c
${PROJECT_SOURCE_DIR}/network/epoll.c
${PROJECT_SOURCE_DIR}/network/kqueue.c
${PROJECT_SOURCE_DIR}/network/select.c
${PROJECT_SOURCE_DIR}/network/timeout.c
${PROJECT_SOURCE_DIR}/network/timer.c
${PROJECT_SOURCE_DIR}/network/network.c
${PROJECT_SOURCE_DIR}/util/ipcalc.c
)
file (GLOB adc_SOURCES ${PROJECT_SOURCE_DIR}/adc/*.c)
file (GLOB network_SOURCES ${PROJECT_SOURCE_DIR}/network/*.c)
file (GLOB utils_SOURCES ${PROJECT_SOURCE_DIR}/util/*.c)
set (uhub_SOURCES
${PROJECT_SOURCE_DIR}/core/auth.c
${PROJECT_SOURCE_DIR}/core/command_parser.c
${PROJECT_SOURCE_DIR}/core/commands.c
${PROJECT_SOURCE_DIR}/core/config.c
${PROJECT_SOURCE_DIR}/core/eventqueue.c
${PROJECT_SOURCE_DIR}/core/hub.c
${PROJECT_SOURCE_DIR}/core/hubevent.c
${PROJECT_SOURCE_DIR}/core/inf.c
${PROJECT_SOURCE_DIR}/core/ioqueue.c
${PROJECT_SOURCE_DIR}/core/netevent.c
${PROJECT_SOURCE_DIR}/core/probe.c
${PROJECT_SOURCE_DIR}/core/route.c
${PROJECT_SOURCE_DIR}/core/user.c
${PROJECT_SOURCE_DIR}/core/usermanager.c
${PROJECT_SOURCE_DIR}/core/plugincallback.c
${PROJECT_SOURCE_DIR}/core/plugininvoke.c
${PROJECT_SOURCE_DIR}/core/pluginloader.c
)
set (adc_SOURCES
${PROJECT_SOURCE_DIR}/adc/message.c
${PROJECT_SOURCE_DIR}/adc/sid.c
)
set (utils_SOURCES
${PROJECT_SOURCE_DIR}/util/cbuffer.c
${PROJECT_SOURCE_DIR}/util/config_token.c
${PROJECT_SOURCE_DIR}/util/credentials.c
${PROJECT_SOURCE_DIR}/util/floodctl.c
${PROJECT_SOURCE_DIR}/util/getopt.c
${PROJECT_SOURCE_DIR}/util/list.c
${PROJECT_SOURCE_DIR}/util/log.c
${PROJECT_SOURCE_DIR}/util/memory.c
${PROJECT_SOURCE_DIR}/util/misc.c
${PROJECT_SOURCE_DIR}/util/rbtree.c
${PROJECT_SOURCE_DIR}/util/tiger.c
)
set (adcclient_SOURCES
${PROJECT_SOURCE_DIR}/tools/adcclient.c
${PROJECT_SOURCE_DIR}/core/ioqueue.c
)
add_library(adc STATIC ${adc_SOURCES})
add_library(network STATIC ${network_SOURCES})
add_library(utils STATIC ${utils_SOURCES})
if(CMAKE_COMPILER_IS_GNUCC)
set_target_properties(utils PROPERTIES COMPILE_FLAGS -fPIC)
set_target_properties(network PROPERTIES COMPILE_FLAGS -fPIC)
endif()
add_dependencies(adc utils)
add_dependencies(network utils)
add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} )
add_executable(test ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} )
add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c)
add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c)
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_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)
add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c ${utils_SOURCES})
add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c ${utils_SOURCES} ${network_SOURCES})
add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${utils_SOURCES} ${PROJECT_SOURCE_DIR}/adc/sid.c ${network_SOURCES})
add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c ${utils_SOURCES})
add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c ${utils_SOURCES})
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c ${utils_SOURCES})
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c ${utils_SOURCES})
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)
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c ${utils_SOURCES})
add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c ${PROJECT_SOURCE_DIR}/util/misc.c ${PROJECT_SOURCE_DIR}/util/memory.c ${PROJECT_SOURCE_DIR}/util/log.c ${PROJECT_SOURCE_DIR}/util/list.c)
target_link_libraries(mod_auth_sqlite sqlite3 utils)
target_link_libraries(uhub-passwd sqlite3 utils)
target_link_libraries(mod_auth_sqlite sqlite3)
target_link_libraries(uhub-passwd sqlite3)
set_target_properties(mod_auth_sqlite PROPERTIES PREFIX "")
endif()
if(WIN32)
target_link_libraries(uhub ws2_32)
target_link_libraries(test ws2_32)
target_link_libraries(mod_logging ws2_32)
target_link_libraries(mod_welcome ws2_32)
endif()
@@ -102,77 +125,32 @@ set_target_properties(
mod_auth_simple
mod_chat_history
mod_chat_only
mod_no_guest_downloads
mod_topic
PROPERTIES PREFIX "")
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(mod_example utils)
target_link_libraries(mod_welcome utils)
target_link_libraries(mod_auth_simple utils)
target_link_libraries(mod_chat_history utils)
target_link_libraries(mod_no_guest_downloads utils)
target_link_libraries(mod_chat_only utils)
target_link_libraries(mod_logging utils)
target_link_libraries(mod_topic utils)
target_link_libraries(utils network)
target_link_libraries(mod_welcome network)
target_link_libraries(mod_logging network)
if(UNIX)
add_library(adcclient STATIC ${adcclient_SOURCES})
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c)
target_link_libraries(uhub-admin adcclient adc network utils pthread)
target_link_libraries(uhub pthread)
target_link_libraries(test pthread)
if (ADC_STRESS)
add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES})
target_link_libraries(adcrush adcclient adc network utils pthread)
endif()
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c ${adcclient_SOURCES})
target_link_libraries(uhub-admin adcclient adc network utils)
endif()
if (NOT UHUB_REVISION AND GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE UHUB_REVISION_TEMP
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (UHUB_REVISION_TEMP)
set (UHUB_REVISION "git-${UHUB_REVISION_TEMP}")
endif()
if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h OUTPUT_VARIABLE UHUB_REVISION)
set (UHUB_GIT_VERSION "${UHUB_VERSION_MAJOR}.${UHUB_VERSION_MINOR}.${UHUB_VERSION_PATCH}-git-${UHUB_REVISION}")
else()
endif()
if (NOT UHUB_REVISION)
set (UHUB_REVISION "release")
endif()
set (UHUB_GIT_VERSION "${UHUB_VERSION_MAJOR}.${UHUB_VERSION_MINOR}.${UHUB_VERSION_PATCH}-${UHUB_REVISION}")
message (STATUS "Configuring uhub version: ${UHUB_GIT_VERSION}")
if(OPENSSL_FOUND)
set(SSL_LIBS ${OPENSSL_LIBRARIES})
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_OPENSSL=1)
add_definitions(-DSSL_SUPPORT=1)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
if (GNUTLS_FOUND)
set(SSL_LIBS ${GNUTLS_LIBRARIES})
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_GNUTLS=1 ${GNUTLS_DEFINITIONS})
include_directories(${GNUTLS_INCLUDE_DIR})
endif()
if(SSL_SUPPORT)
target_link_libraries(uhub ${SSL_LIBS})
target_link_libraries(test ${SSL_LIBS})
target_link_libraries(uhub ${OPENSSL_LIBRARIES})
if(UNIX)
target_link_libraries(uhub-admin ${SSL_LIBS})
endif()
target_link_libraries(mod_welcome ${SSL_LIBS})
target_link_libraries(mod_logging ${SSL_LIBS})
if (ADC_STRESS)
target_link_libraries(adcrush ${SSL_LIBS})
target_link_libraries(uhub-admin ${OPENSSL_LIBRARIES})
endif()
target_link_libraries(mod_welcome ${OPENSSL_LIBRARIES})
target_link_libraries(mod_logging ${OPENSSL_LIBRARIES})
endif()
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")
@@ -182,17 +160,11 @@ if (RELEASE)
set(CMAKE_BUILD_TYPE Release)
else()
set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG)
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( 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()

View File

@@ -1,18 +1,3 @@
0.4.1:
- Converted to CMake which replaces Visual Studio project files and GNU makefiles
- Fix issues with SSL causing excessive CPU usage.
- Fix TLS/SSL handshake detection issues
- Fixed crash in mod_chat_only.
- Implemented red-black tree for better performance for certain lookups.
- Better network statistics using the !stats command.
- Improved protocol parsing, especially escape handling.
- Fix cbuffer initialization.
- Install plugins in /usr/lib/uhub, not /var/lib/uhub.
- Improved init scripts and added a upstart script.
- Work-around client security bugs by disallowing UCMD messages from being relayed.
- Added asynchronous DNS resolver.
0.4.0:
- Cleaned up code generator for config file parsing.
- Merge pull request #5 from yorhel/master

View File

@@ -1,372 +0,0 @@
#!/usr/bin/perl -w
# exotic 0.4
# Copyright (c) 2007-2012, Jan Vidar Krey
use strict;
my $program = $0;
my $file;
my $line;
my @tests;
my $found;
my $test;
my @files;
if ($#ARGV == -1)
{
die "Usage: $program files\n";
}
my $version = "0.4";
foreach my $arg (@ARGV)
{
push(@files, $arg);
}
print "/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */\n";
print "/* exotic/$version (Mon Nov 7 11:15:31 CET 2011) */\n\n";
print "#define __EXOTIC__STANDALONE__\n";
standalone_include_exotic_h();
if ($#ARGV >= 0)
{
foreach $file (@ARGV)
{
$found = 0;
open( FILE, "$file") || next;
my @data = <FILE>;
my $comment = 0;
foreach $line (@data) {
chomp($line);
if ($comment == 1)
{
if ($line =~ /^(.*\*\/)(.*)/)
{
$line = $2;
$comment = 0;
}
else
{
next; # ignore comment data
}
}
if ($line =~ /^(.*)\/\*(.*)\*\/(.*)$/)
{
$line = $1 . " " . $3; # exclude comment stuff in between "/*" and "*/".
}
if ($line =~ /^(.*)(\/\/.*)$/) {
$line = $1; # exclude stuff after "//" (FIXME: does not work if they are inside a string)
}
if ($line =~ /\/\*/) {
$comment = 1;
next;
}
if ($line =~ /^\s*EXO_TEST\(\s*(\w+)\s*,/)
{
$found++;
push(@tests, $1);
}
}
if ($found > 0) {
print "#include \"" . $file . "\"\n";
}
close(FILE);
}
print "\n";
}
# Write a main() that will start the test run
print "int main(int argc, char** argv)\n{\n";
print "\tstruct exotic_handle handle;\n\n";
print "\tif (exotic_initialize(&handle, argc, argv) == -1)\n\t\treturn -1;\n\n";
if ($#tests > 0)
{
print "\t/* Register the tests to be run */\n";
foreach $test (@tests)
{
print "\texotic_add_test(&handle, &exotic_test_" . $test . ", \"" . $test . "\");\n";
}
}
else
{
print "\t/* No tests are found! */\n";
}
print "\n";
print "\treturn exotic_run(&handle);\n";
print "}\n\n";
standalone_include_exotic_c();
sub standalone_include_exotic_h {
print '
/*
* Exotic (EXtatic.Org Test InfrastuCture)
* Copyright (c) 2007, Jan Vidar Krey
*/
#ifndef EXO_TEST
#define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block
#endif
#ifndef HAVE_EXOTIC_AUTOTEST_H
#define HAVE_EXOTIC_AUTOTEST_H
#ifdef __cplusplus
extern "C" {
#endif
typedef int(*exo_test_t)();
enum exo_toggle { cfg_default, cfg_off, cfg_on };
struct exotic_handle
{
enum exo_toggle config_show_summary;
enum exo_toggle config_show_pass;
enum exo_toggle config_show_fail;
unsigned int fail;
unsigned int pass;
struct exo_test_data* first;
struct exo_test_data* current;
};
extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv);
extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name);
extern int exotic_run(struct exotic_handle* handle);
#ifdef __cplusplus
}
#endif
#endif /* HAVE_EXOTIC_AUTOTEST_H */
'; }
sub standalone_include_exotic_c {
print '
/*
* Exotic - C/C++ source code testing
* Copyright (c) 2007, Jan Vidar Krey
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void exotic_version();
#ifndef __EXOTIC__STANDALONE__
#include "autotest.h"
static void exotic_version()
{
printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n");
printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n");
printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n");
}
#endif
struct exo_test_data
{
exo_test_t test;
char* name;
struct exo_test_data* next;
};
static void exotic_summary(struct exotic_handle* handle)
{
int total = handle->pass + handle->fail;
int pass_rate = total ? (100*handle->pass / total) : 0;
int fail_rate = total ? (100*handle->fail / total) : 0;
printf("\n");
printf("--------------------------------------------\n");
printf("Results:\n");
printf(" * Total tests run: %8d\n", total);
printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate);
printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate);
printf("--------------------------------------------\n");
}
static void exotic_help(const char* program)
{
printf("Usage: %s [OPTIONS]\n\n", program);
printf("Options:\n");
printf(" --help -h Show this message\n");
printf(" --version -v Show version\n");
printf(" --summary -s show only summary)\n");
printf(" --fail -f show only test failures\n");
printf(" --pass -p show only test passes\n");
printf("\nExamples:\n");
printf(" %s -s -f\n\n", program);
}
int exotic_initialize(struct exotic_handle* handle, int argc, char** argv)
{
int n;
if (!handle || !argv) return -1;
memset(handle, 0, sizeof(struct exotic_handle));
for (n = 1; n < argc; n++)
{
if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help"))
{
exotic_help(argv[0]);
exit(0);
}
if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version"))
{
exotic_version();
exit(0);
}
if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary"))
{
handle->config_show_summary = cfg_on;
continue;
}
if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail"))
{
handle->config_show_fail = cfg_on;
continue;
}
if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass"))
{
handle->config_show_pass = cfg_on;
continue;
}
fprintf(stderr, "Unknown argument: %s\n\n", argv[n]);
exotic_help(argv[0]);
exit(0);
}
if (handle->config_show_summary == cfg_on)
{
if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off;
if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off;
}
else if (handle->config_show_pass == cfg_on)
{
if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off;
if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off;
}
else if (handle->config_show_fail == cfg_on)
{
if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off;
if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off;
}
else
{
if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on;
if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on;
if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on;
}
return 0;
}
void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name)
{
struct exo_test_data* test;
if (!handle)
{
fprintf(stderr, "exotic_add_test: failed, no handle!\n");
exit(-1);
}
test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data));
if (!test)
{
fprintf(stderr, "exotic_add_test: out of memory!\n");
exit(-1);
}
/* Create the test */
memset(test, 0, sizeof(struct exo_test_data));
test->test = func;
test->name = strdup(name);
/* Register the test in the handle */
if (!handle->first)
{
handle->first = test;
handle->current = test;
}
else
{
handle->current->next = test;
handle->current = test;
}
}
int exotic_run(struct exotic_handle* handle)
{
struct exo_test_data* tmp = NULL;
if (!handle)
{
fprintf(stderr, "Error: exotic is not initialized\n");
return -1;
}
handle->current = handle->first;
while (handle->current)
{
tmp = handle->current;
if (handle->current->test()) {
if (handle->config_show_pass == cfg_on) printf("* PASS test \'%s\'\n", tmp->name);
handle->pass++;
} else {
if (handle->config_show_fail == cfg_on) printf("* FAIL test \'%s\'\n", tmp->name);
handle->fail++;
}
handle->current = handle->current->next;
free(tmp->name);
free(tmp);
}
if (!handle->first)
{
printf("(No tests added)\n");
}
if (handle->config_show_summary == cfg_on)
exotic_summary(handle);
return (handle->fail) ? handle->fail : 0;
}
static void exotic_version() {
printf("exotic 0.4-standalone\n\n");
printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n");
printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n");
}
'; }

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,6 @@ extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, st
static void inf_create_hub()
{
net_initialize();
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
inf_hub->users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
inf_hub->users->list = list_create();
@@ -36,7 +35,6 @@ static void inf_destroy_hub()
hub_free(inf_hub->acl);
hub_free(inf_hub->config);
hub_free(inf_hub);
net_destroy();
}
@@ -65,14 +63,13 @@ EXO_TEST(inf_create_setup,
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
#define CHECK_INF(MSG, EXPECT) \
do { \
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \
if (ok == EXPECT) \
user_set_info(inf_user, 0); \
return ok == EXPECT; \
} while(0)
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \
if (ok == EXPECT) \
user_set_info(inf_user, 0); \
return ok == EXPECT;
EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
@@ -110,15 +107,12 @@ EXO_TEST(inf_nick_08, { CHECK_INF("BINF AAAB NIa\\nc IDGNSSMURMD7K466NGZIHU65TP3
EXO_TEST(inf_nick_09, { CHECK_INF("BINF AAAB NIabc NIdef IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_multiple); });
EXO_TEST(inf_nick_10, {
const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n";
int ok;
char nick[10];
struct adc_message* msg;
nick[0] = 0xf7; nick[1] = 0x80; nick[2] = 0x7f; nick[3] = 0x81; nick[4] = 0x98; nick[5] = 0x00;
msg = adc_msg_parse_verify(inf_user, line, strlen(line));
struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line));
adc_msg_add_named_argument(msg, "NI", nick);
ok = hub_handle_info_login(inf_hub, inf_user, msg);
int ok = hub_handle_info_login(inf_hub, inf_user, msg);
adc_msg_free(msg);
if (ok != status_msg_inf_error_nick_not_utf8)
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);

View File

@@ -429,51 +429,44 @@ EXO_TEST(check_ban_ipv4_5, {
});
EXO_TEST(check_ban_ipv6_1, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_2, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_3, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_4, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_5, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_6, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_afmix_1, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !ip_in_range(&addr, &ban4);
});
@@ -617,10 +610,8 @@ EXO_TEST(ip_range_3, {
});
EXO_TEST(ip_range_4, {
struct ip_range range1;
struct ip_range range2;
memset(&range1, 0, sizeof(range1));
memset(&range2, 0, sizeof(range2));
struct ip_range range1; memset(&range1, 0, sizeof(range1));
struct ip_range range2; memset(&range2, 0, sizeof(range2));
return ip_convert_address_to_range("192.168.0.0/16", &range1) && ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range2) && memcmp(&range1, &range2, sizeof(struct ip_range)) == 0;
});

View File

@@ -174,102 +174,91 @@ EXO_TEST(adc_message_parse_24, {
EXO_TEST(adc_message_add_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_add_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_named_argument(msg, "XX", "wtf?");
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA");
ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB");
ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC");
ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_4, {
/* this ensures we can remove the last element also */
int ok;
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3));
adc_msg_remove_named_argument(msg, "AW");
ok = strcmp(msg->cache, "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1\n") == 0;
int ok = strcmp(msg->cache, "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA");
ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB");
ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC");
ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_get_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 0);
ok = strcmp(c, "AAfoo") == 0;
int ok = strcmp(c, "AAfoo") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 1);
ok = strcmp(c, "BBbar") == 0;
int ok = strcmp(c, "BBbar") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
@@ -351,31 +340,28 @@ EXO_TEST(adc_message_has_named_arg_3, {
});
EXO_TEST(adc_message_has_named_arg_4, {
int n;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
n = adc_msg_has_named_argument(msg, "XX");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 1;
});
EXO_TEST(adc_message_has_named_arg_5, {
int n;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo");
n = adc_msg_has_named_argument(msg, "XX");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 2;
});
EXO_TEST(adc_message_has_named_arg_6, {
int n;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo");
adc_msg_add_argument(msg, "XXthree");
n = adc_msg_has_named_argument(msg, "XX");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 3;
});
@@ -388,70 +374,63 @@ EXO_TEST(adc_message_has_named_arg_7, {
});
EXO_TEST(adc_message_terminate_1, {
int ok;
struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat");
adc_msg_unterminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
adc_msg_unterminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_4, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
adc_msg_terminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_5, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_terminate(msg);
adc_msg_terminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_6, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_unterminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_escape_1, {
int ok;
char* s = adc_msg_escape(test_string1);
ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
int ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
hub_free(s);
return ok;
});

View File

@@ -97,25 +97,15 @@ EXO_TEST(base32_invalid_31, { return !is_valid_base32_char('@'); });
EXO_TEST(utf8_valid_1, { return is_valid_utf8("abcdefghijklmnopqrstuvwxyz"); });
EXO_TEST(utf8_valid_2, { return is_valid_utf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); });
EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
static const char test_utf_seq_1[] = { 0x65, 0x00 }; // valid
static const char test_utf_seq_2[] = { 0xD8, 0x00 }; // invalid
static const char test_utf_seq_3[] = { 0x24, 0x00 }; // valid
static const char test_utf_seq_4[] = { 0xC2, 0x24, 0x00}; // invalid
static const char test_utf_seq_5[] = { 0xC2, 0xA2, 0x00}; // valid
static const char test_utf_seq_6[] = { 0xE2, 0x82, 0xAC, 0x00}; // valid
static const char test_utf_seq_7[] = { 0xC2, 0x32, 0x00}; // invalid
static const char test_utf_seq_8[] = { 0xE2, 0x82, 0x32, 0x00}; // invalid
static const char test_utf_seq_9[] = { 0xE2, 0x32, 0x82, 0x00}; // invalid
EXO_TEST(utf8_valid_4, { return is_valid_utf8(test_utf_seq_1); });
EXO_TEST(utf8_valid_5, { return !is_valid_utf8(test_utf_seq_2); });
EXO_TEST(utf8_valid_6, { return is_valid_utf8(test_utf_seq_3); });
EXO_TEST(utf8_valid_7, { return !is_valid_utf8(test_utf_seq_4); });
EXO_TEST(utf8_valid_8, { return is_valid_utf8(test_utf_seq_5); });
EXO_TEST(utf8_valid_9, { return is_valid_utf8(test_utf_seq_6); });
EXO_TEST(utf8_valid_10, { return !is_valid_utf8(test_utf_seq_7); });
EXO_TEST(utf8_valid_11, { return !is_valid_utf8(test_utf_seq_8); });
EXO_TEST(utf8_valid_12, { return !is_valid_utf8(test_utf_seq_9); });
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });

View File

@@ -1,144 +0,0 @@
#include <uhub.h>
#include <util/rbtree.h>
#define MAX_NODES 10000
static struct rb_tree* tree = NULL;
int test_tree_compare(const void* a, const void* b)
{
return strcmp((const char*) a, (const char*) b);
}
EXO_TEST(rbtree_create_destroy, {
int ok = 0;
struct rb_tree* atree;
atree = rb_tree_create(test_tree_compare, &hub_malloc, &hub_free);
if (atree) ok = 1;
rb_tree_destroy(atree);
return ok;
});
EXO_TEST(rbtree_create_1, {
tree = rb_tree_create(test_tree_compare, &hub_malloc, &hub_free);
return tree != NULL;
});
EXO_TEST(rbtree_size_0, { return rb_tree_size(tree) == 0; });
EXO_TEST(rbtree_insert_1, {
return rb_tree_insert(tree, "one", "1");
});
EXO_TEST(rbtree_insert_2, {
return rb_tree_insert(tree, "two", "2");
});
EXO_TEST(rbtree_insert_3, {
return rb_tree_insert(tree, "three", "3");
});
EXO_TEST(rbtree_insert_3_again, {
return !rb_tree_insert(tree, "three", "3-again");
});
EXO_TEST(rbtree_size_1, { return rb_tree_size(tree) == 3; });
static int test_check_search(const char* key, const char* expect)
{
const char* value = (const char*) rb_tree_get(tree, key);
if (!value) return !expect;
if (!expect) return 0;
return strcmp(value, expect) == 0;
}
EXO_TEST(rbtree_search_1, { return test_check_search("one", "1"); });
EXO_TEST(rbtree_search_2, { return test_check_search("two", "2"); });
EXO_TEST(rbtree_search_3, { return test_check_search("three", "3"); });
EXO_TEST(rbtree_search_4, { return test_check_search("four", NULL); });
EXO_TEST(rbtree_remove_1, {
return rb_tree_remove(tree, "one");
});
EXO_TEST(rbtree_size_2, { return rb_tree_size(tree) == 2; });
EXO_TEST(rbtree_remove_2, {
return rb_tree_remove(tree, "two");
});
EXO_TEST(rbtree_remove_3, {
return rb_tree_remove(tree, "three");
});
EXO_TEST(rbtree_remove_3_again, {
return !rb_tree_remove(tree, "three");
});
EXO_TEST(rbtree_search_5, { return test_check_search("one", NULL); });
EXO_TEST(rbtree_search_6, { return test_check_search("two", NULL); });
EXO_TEST(rbtree_search_7, { return test_check_search("three", NULL); });
EXO_TEST(rbtree_search_8, { return test_check_search("four", NULL); });
EXO_TEST(rbtree_size_3, { return rb_tree_size(tree) == 0; });
EXO_TEST(rbtree_insert_10000, {
int i;
for (i = 0; i < MAX_NODES ; i++)
{
const char* key = strdup(uhub_itoa(i));
const char* val = strdup(uhub_itoa(i + 16384));
if (!rb_tree_insert(tree, key, val))
return 0;
}
return 1;
});
EXO_TEST(rbtree_size_4, { return rb_tree_size(tree) == MAX_NODES ; });
EXO_TEST(rbtree_check_10000, {
int i;
for (i = 0; i < MAX_NODES ; i++)
{
char* key = strdup(uhub_itoa(i));
const char* expect = uhub_itoa(i + 16384);
if (!test_check_search(key, expect))
return 0;
hub_free(key);
}
return 1;
});
EXO_TEST(rbtree_iterate_10000, {
int i = 0;
struct rb_node* n = (struct rb_node*) rb_tree_first(tree);
while (n)
{
struct rb_node* p = n;
n = (struct rb_node*) rb_tree_next(tree);
i++;
}
return i == MAX_NODES ;
});
static void free_node(struct rb_node* n)
{
hub_free((void*) n->key);
hub_free((void*) n->value);
}
EXO_TEST(rbtree_remove_5000, {
int i = 0;
struct rb_node* n = (struct rb_node*) rb_tree_first(tree);
for (i = 0; i < MAX_NODES ; i += 2)
{
const char* key = uhub_itoa(i);
rb_tree_remove_node(tree, key, &free_node);
}
return 1;
});

View File

@@ -7,15 +7,13 @@
static int match_str(const char* str1, char* str2)
{
size_t i;
int ret;
for (i = 0; i < strlen(str2); i++)
if (str2[i] == '_')
str2[i] = ' ';
else if (str2[i] == '|')
str2[i] = '\t';
ret = strcmp(str1, str2);
int ret = strcmp(str1, str2);
if (ret) {
fprintf(stderr, "\n Mismatch: \"%s\" != \"%s\"\n", str1, str2);
}
@@ -31,11 +29,10 @@ static int count(const char* STR, size_t EXPECT) {
static int compare(const char* str, const char* ref) {
size_t i, max;
int pass;
struct linked_list* compare = list_create();
SETUP(tokens, str);
split_string(ref, " ", compare, 0);
pass = cfg_token_count(tokens) == list_size(compare);
int pass = cfg_token_count(tokens) == list_size(compare);
if (pass) {
max = cfg_token_count(tokens);
for (i = 0; i < max; i++) {

View File

@@ -1,4 +0,0 @@
#!/bin/sh
./exotic *.tcc > test.c

View File

@@ -11,7 +11,7 @@
# Parameters:
# file: path/filename for database.
#
plugin /usr/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
plugin /var/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
# Log file writer
@@ -19,10 +19,10 @@ plugin /usr/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
# Parameters:
# file: path/filename for log file.
# syslog: if true then syslog is used instead of writing to a file (Unix only)
plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
plugin /var/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
# A simple example plugin
# plugin /usr/lib/uhub/mod_example.so
# plugin /var/lib/uhub/mod_example.so
# A plugin sending a welcome message.
#
# This plugin provides the following commands:
@@ -46,7 +46,7 @@ plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
# %p - 'am' or 'pm'
# %M - Minutes (00-59) (Hub local time)
# %S - Seconds (00-60) (Hub local time)
plugin /usr/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rules.txt"
plugin /var/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rules.txt"
# Load the chat history plugin.
#
@@ -58,5 +58,5 @@ plugin /usr/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rul
# history_max: the maximum number of messages to keep in history
# history_default: when !history is provided without arguments, then this default number of messages are returned.
# history_connect: the number of chat history messages to send when users connect (0 = do not send any history)
plugin /usr/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5"
plugin /var/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5"

View File

@@ -41,7 +41,7 @@ mkdir -p $RPM_BUILD_ROOT/etc/init.d
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
mkdir -p $RPM_BUILD_ROOT/usr/lib/uhub
mkdir -p $RPM_BUILD_ROOT/var/lib/uhub
install uhub $RPM_BUILD_ROOT/usr/bin/
install uhub-passwd $RPM_BUILD_ROOT/usr/bin/
@@ -52,7 +52,7 @@ install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfi
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
install -m644 mod_*.so $RPM_BUILD_ROOT/usr/lib/uhub
install -m644 mod_*.so $RPM_BUILD_ROOT/var/lib/uhub
%files

View File

@@ -532,9 +532,9 @@ struct adc_message* adc_msg_create(const char* line)
return adc_msg_parse(line, strlen(line));
}
struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size)
extern struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size)
{
struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 1);
struct adc_message* msg = adc_msg_construct(fourcc, size + 4);
if (!msg)
return NULL;
@@ -543,20 +543,6 @@ struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size
return msg;
}
struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size)
{
struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 4 + 1);
if (!msg)
return NULL;
adc_msg_add_argument(msg, sid_to_string(source));
adc_msg_add_argument(msg, sid_to_string(dest));
msg->source = source;
msg->target = dest;
return msg;
}
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
{
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));

View File

@@ -96,7 +96,6 @@ extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
* in addition pre-allocate 'size' bytes at the end of the message.
*/
extern struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size);
extern struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size);
/**
* Remove a named argument from the command.

View File

@@ -557,28 +557,14 @@ static int command_stats(struct command_base* cbase, struct hub_user* user, stru
{
struct cbuffer* buf = cbuf_create(128);
struct hub_info* hub = cbase->hub;
static char rxbuf[64] = { "0 B" };
static char txbuf[64] = { "0 B" };
cbuf_append(buf, "Hub statistics: ");
cbuf_append_format(buf, PRINTF_SIZE_T "/" PRINTF_SIZE_T " users (peak %d). ", hub->users->count, hub->config->max_users, hub->users->count_peak);
format_size(hub->stats.net_rx, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx, txbuf, sizeof(txbuf));
cbuf_append_format(buf, "Network: tx=%s/s, rx=%s/s", txbuf, rxbuf);
#ifdef SHOW_PEAK_NET_STATS /* currently disabled */
format_size(hub->stats.net_rx_peak, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx_peak, txbuf, sizeof(txbuf));
cbuf_append_format(buf, ", peak_tx=%s/s, peak_rx=%s/s", txbuf, rxbuf);
#endif
format_size(hub->stats.net_rx_total, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx_total, txbuf, sizeof(txbuf));
cbuf_append_format(buf, ", total_tx=%s", txbuf);
cbuf_append_format(buf, ", total_rx=%s", rxbuf);
cbuf_append_format(buf, PRINTF_SIZE_T " users, peak: " PRINTF_SIZE_T ". Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
return command_status(cbase, user, cmd, buf);
}

View File

@@ -600,31 +600,6 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
}
}
static void hub_update_stats(struct hub_info* hub)
{
const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
hub->stats.net_tx = (intermediate->tx / factor);
hub->stats.net_rx = (intermediate->rx / factor);
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
hub->stats.net_tx_total = total->tx;
hub->stats.net_rx_total = total->rx;
net_stats_reset();
}
static void hub_timer_statistics(struct timeout_evt* t)
{
struct hub_info* hub = (struct hub_info*) t->ptr;
hub_update_stats(hub);
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS);
}
static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
{
struct net_connection* server;
@@ -731,25 +706,41 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
{
if (config->tls_enable)
{
hub->ctx = net_ssl_context_create();
if (ssl_load_certificate(hub->ctx, config->tls_certificate) &&
ssl_load_private_key(hub->ctx, config->tls_private_key) &&
ssl_check_private_key(hub->ctx))
hub->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
/* Disable SSLv2 */
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_quiet_shutdown(hub->ssl_ctx, 1);
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
{
LOG_INFO("Enabling TLS (%s), using certificate: %s, private key: %s", net_ssl_get_provider(), config->tls_certificate, config->tls_private_key);
return 1;
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
}
return 0;
if (SSL_CTX_use_PrivateKey_file(hub->ssl_ctx, config->tls_private_key, SSL_FILETYPE_PEM) < 0)
{
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
}
if (SSL_CTX_check_private_key(hub->ssl_ctx) != 1)
{
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
}
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
}
return 1;
}
static void unload_ssl_certificates(struct hub_info* hub)
{
if (hub->ctx)
net_ssl_context_destroy(hub->ctx);
if (hub->ssl_ctx)
{
SSL_CTX_free(hub->ssl_ctx);
}
}
#endif /* SSL_SUPPORT */
#endif
struct hub_info* hub_start_service(struct hub_config* config)
{
@@ -825,13 +816,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
g_hub = hub;
if (net_backend_get_timeout_queue())
{
hub->stats.timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(hub->stats.timeout, hub_timer_statistics, hub);
timeout_queue_insert(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS);
}
// Start the hub command sub-system
hub->commands = command_initialize(hub);
return hub;
@@ -842,12 +826,6 @@ void hub_shutdown_service(struct hub_info* hub)
{
LOG_DEBUG("hub_shutdown_service()");
if (net_backend_get_timeout_queue())
{
timeout_queue_remove(net_backend_get_timeout_queue(), hub->stats.timeout);
hub_free(hub->stats.timeout);
}
#ifdef SSL_SUPPORT
unload_ssl_certificates(hub);
#endif

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2011, 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
@@ -81,7 +81,6 @@ struct hub_stats
size_t net_rx_peak;
size_t net_tx_total;
size_t net_rx_total;
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
};
struct hub_logout_info
@@ -116,7 +115,8 @@ struct hub_info
struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */
#ifdef SSL_SUPPORT
struct ssl_context_handle* ctx;
SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
#endif /* SSL_SUPPORT */
};

View File

@@ -141,13 +141,13 @@ void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
q->offset = 0;
}
int ioq_send_send(struct ioq_send* q, struct net_connection* con)
int ioq_send_send(struct ioq_send* q, struct hub_user* user)
{
int ret;
struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0;
uhub_assert(msg->cache && *msg->cache);
ret = net_con_send(con, msg->cache + q->offset, msg->length - q->offset);
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0)
{

View File

@@ -60,7 +60,7 @@ extern void ioq_send_add(struct ioq_send*, struct adc_message* msg);
* Process the send queue, and send as many messages as possible.
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
*/
extern int ioq_send_send(struct ioq_send*, struct net_connection* con);
extern int ioq_send_send(struct ioq_send*, struct hub_user*);
/**
* @returns 1 if send queue is empty, 0 otherwise.

View File

@@ -136,13 +136,7 @@ int main_loop()
{
hub = hub_start_service(&configuration);
if (!hub)
{
acl_shutdown(&acl);
free_config(&configuration);
net_destroy();
hub_log_shutdown();
return -1;
}
#if !defined(WIN32)
setup_signal_handlers(hub);
#endif

View File

@@ -55,7 +55,7 @@ int handle_net_read(struct hub_user* user)
while ((pos = memchr(start, '\n', remaining)))
{
lastPos = pos+1;
lastPos = pos;
pos[0] = '\0';
#ifdef DEBUG_SENDQ
@@ -109,7 +109,7 @@ int handle_net_write(struct hub_user* user)
int ret = 0;
while (ioq_send_get_bytes(user->send_queue))
{
ret = ioq_send_send(user->send_queue, user->connection);
ret = ioq_send_send(user->send_queue, user);
if (ret <= 0)
break;
}

View File

@@ -85,7 +85,7 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
{
probe->connection = 0;
}
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ctx);
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
}
else
{

View File

@@ -38,6 +38,42 @@ static void clear_user_list_callback(void* ptr)
}
}
#ifdef STATS_SUPPORT
void uman_update_stats(struct hub_user_manager* users)
{
const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
users->stats.net_tx = (intermediate->tx / factor);
users->stats.net_rx = (intermediate->rx / factor);
users->stats.net_tx_peak = MAX(users->stats.net_tx, users->stats.net_tx_peak);
users->stats.net_rx_peak = MAX(users->stats.net_rx, users->stats.net_rx_peak);
users->stats.net_tx_total = total->tx;
users->stats.net_rx_total = total->rx;
net_stats_reset();
}
void uman_print_stats(struct hub_user_manager* users)
{
LOG_INFO("Statistics users=" PRINTF_SIZE_T " (peak_users=" PRINTF_SIZE_T "), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
users->users->count,
users->users->count_peak,
(int) users->stats.net_tx / 1024,
(int) users->stats.net_rx / 1024,
(int) users->stats.net_tx_peak / 1024,
(int) users->stats.net_rx_peak / 1024);
}
static void timer_statistics(struct timeout_evt* t)
{
struct hub_user_manager* users = (struct hub_user_manager*) t->ptr;
uman_update_stats(users);
timeout_queue_reschedule(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
}
#endif // STATS_SUPPORT
struct hub_user_manager* uman_init()
{
@@ -55,6 +91,15 @@ struct hub_user_manager* uman_init()
return NULL;
}
#ifdef STATS_SUPPORT
if (net_backend_get_timeout_queue())
{
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(users->timeout, timer_statistics, hub);
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
}
#endif // STATS_SUPPORT
return users;
}
@@ -64,6 +109,14 @@ int uman_shutdown(struct hub_user_manager* users)
if (!users)
return -1;
#ifdef STATS_SUPPORT
if (net_backend_get_timeout_queue())
{
timeout_queue_remove(net_backend_get_timeout_queue(), users->timeout);
hub_free(users->timeout);
}
#endif
if (users->list)
{
list_clear(users->list, &clear_user_list_callback);

View File

@@ -28,6 +28,9 @@ struct hub_user_manager
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 linked_list* list; /**<< "Contains all logged in users" */
#ifdef STATS_SUPPORT
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
#endif
};
/**

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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
@@ -146,9 +146,6 @@ int net_backend_process()
return 0;
}
// Process pending DNS results
net_dns_process();
g_backend->handler.backend_process(g_backend->data, res);
net_cleanup_process(g_backend->cleaner);
@@ -184,8 +181,11 @@ void net_con_close(struct net_connection* con)
#ifdef SSL_SUPPORT
if (con->ssl)
net_ssl_shutdown(con);
#endif /* SSL_SUPPORT */
{
SSL_shutdown(con->ssl);
SSL_clear(con->ssl);
}
#endif
net_close(con->sd);
con->sd = -1;

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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
@@ -20,10 +20,11 @@
#define NET_WANT_READ NET_EVENT_READ
#define NET_WANT_WRITE NET_EVENT_WRITE
#define NET_WANT_ACCEPT NET_EVENT_READ
#define NET_SSL_ANY NET_WANT_SSL_READ | NET_WANT_SSL_WRITE | NET_WANT_SSL_ACCEPT | NET_WANT_SSL_CONNECT | NET_WANT_SSL_X509_LOOKUP
struct ssl_handle; /* abstract type */
#define NET_WANT_SSL_READ 0x0010
#define NET_WANT_SSL_WRITE 0x0020
#define NET_WANT_SSL_ACCEPT 0x0040
#define NET_WANT_SSL_CONNECT 0x0080
#define NET_WANT_SSL_X509_LOOKUP 0x0100
#define NET_CLEANUP 0x8000
@@ -35,7 +36,9 @@ struct ssl_handle; /* abstract type */
struct timeout_evt* timeout; /** timeout event handler */
#define NET_CON_STRUCT_SSL \
struct ssl_handle* ssl; /** SSL handle */
SSL* ssl; /** SSL handle */ \
uint32_t ssl_state; /** SSL state */ \
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
#ifdef SSL_SUPPORT
#define NET_CON_STRUCT_COMMON \

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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
@@ -20,18 +20,132 @@
#include "uhub.h"
#include "network/common.h"
static int is_blocked_or_interrupted()
#ifdef SSL_SUPPORT
enum uhub_tls_state
{
int err = net_error();
return
#ifdef WINSOCK
err == WSAEWOULDBLOCK
#else
err == EWOULDBLOCK
#endif
|| err == EINTR;
tls_st_none,
tls_st_error,
tls_st_accepting,
tls_st_connecting,
tls_st_connected,
tls_st_disconnecting,
};
static int handle_openssl_error(struct net_connection* con, int ret)
{
uhub_assert(con);
int error = SSL_get_error(con->ssl, ret);
switch (error)
{
case SSL_ERROR_ZERO_RETURN:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
con->ssl_state = tls_st_error;
return -1;
case SSL_ERROR_WANT_READ:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
con->flags |= NET_WANT_SSL_READ;
net_con_update(con, NET_EVENT_READ);
return 0;
case SSL_ERROR_WANT_WRITE:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
con->flags |= NET_WANT_SSL_WRITE;
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
return 0;
case SSL_ERROR_SYSCALL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
/* if ret == 0, connection closed, if ret == -1, check with errno */
if (ret == 0)
return -1;
else
return -net_error();
case SSL_ERROR_SSL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
/* internal openssl error */
con->ssl_state = tls_st_error;
return -1;
}
return -1;
}
ssize_t net_con_ssl_accept(struct net_connection* con)
{
uhub_assert(con);
con->ssl_state = tls_st_accepting;
ssize_t ret = SSL_accept(con->ssl);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_accept() ret=%d", ret);
#endif
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
con->ssl_state = tls_st_connected;
}
else
{
return handle_openssl_error(con, ret);
}
return ret;
}
ssize_t net_con_ssl_connect(struct net_connection* con)
{
uhub_assert(con);
con->ssl_state = tls_st_connecting;
ssize_t ret = SSL_connect(con->ssl);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_connect() ret=%d", ret);
#endif
if (ret > 0)
{
con->ssl_state = tls_st_connected;
net_con_update(con, NET_EVENT_READ);
}
else
{
return handle_openssl_error(con, ret);
}
return ret;
}
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx)
{
uhub_assert(con);
SSL* ssl = 0;
if (ssl_mode == net_con_ssl_mode_server)
{
ssl = SSL_new(ssl_ctx);
if (!ssl)
{
LOG_ERROR("Unable to create new SSL stream\n");
return -1;
}
SSL_set_fd(ssl, con->sd);
net_con_set_ssl(con, ssl);
return net_con_ssl_accept(con);
}
else
{
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
SSL_set_fd(ssl, con->sd);
net_con_set_ssl(con, ssl);
return net_con_ssl_connect(con);
}
}
#endif /* SSL_SUPPORT */
#ifdef SSL_SUPPORT
void net_stats_add_tx(size_t bytes);
void net_stats_add_rx(size_t bytes);
#endif
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
{
int ret;
@@ -42,7 +156,13 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
if (ret == -1)
{
if (is_blocked_or_interrupted())
if (
#ifdef WINSOCK
net_error() == WSAEWOULDBLOCK
#else
net_error() == EWOULDBLOCK
#endif
|| net_error() == EINTR)
return 0;
return -1;
}
@@ -50,9 +170,19 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
}
else
{
ret = net_ssl_send(con, buf, len);
con->write_len = len;
ret = SSL_write(con->ssl, buf, len);
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret <= 0)
{
return handle_openssl_error(con, ret);
}
else
{
net_stats_add_tx(ret);
}
}
#endif /* SSL_SUPPORT */
#endif
return ret;
}
@@ -60,13 +190,19 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{
int ret;
#ifdef SSL_SUPPORT
if (!con->ssl)
if (!net_con_is_ssl(con))
{
#endif
ret = net_recv(con->sd, buf, len, 0);
if (ret == -1)
{
if (is_blocked_or_interrupted())
if (
#ifdef WINSOCK
net_error() == WSAEWOULDBLOCK
#else
net_error() == EWOULDBLOCK
#endif
|| net_error() == EINTR)
return 0;
return -net_error();
}
@@ -78,9 +214,22 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
}
else
{
ret = net_ssl_recv(con, buf, len);
if (con->ssl_state == tls_st_error)
return -1;
ret = SSL_read(con->ssl, buf, len);
LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
net_stats_add_rx(ret);
}
else
{
return handle_openssl_error(con, ret);
}
}
#endif /* SSL_SUPPORT */
#endif
return ret;
}
@@ -89,7 +238,13 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
if (ret == -1)
{
if (is_blocked_or_interrupted())
if (
#ifdef WINSOCK
net_error() == WSAEWOULDBLOCK
#else
net_error() == EWOULDBLOCK
#endif
|| net_error() == EINTR)
return 0;
return -net_error();
}
@@ -99,10 +254,19 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
}
#ifdef SSL_SUPPORT
int net_con_is_ssl(struct net_connection* con)
{
return !!con->ssl;
return con->ssl != 0;
}
SSL* net_con_get_ssl(struct net_connection* con)
{
return con->ssl;
}
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
{
con->ssl = ssl;
}
#endif /* SSL_SUPPORT */
@@ -119,8 +283,7 @@ void* net_con_get_ptr(struct net_connection* con)
void net_con_destroy(struct net_connection* con)
{
#ifdef SSL_SUPPORT
if (con->ssl)
net_ssl_destroy(con);
SSL_free(con->ssl);
#endif
hub_free(con);
}
@@ -138,10 +301,62 @@ void net_con_callback(struct net_connection* con, int events)
}
#ifdef SSL_SUPPORT
if (con->ssl)
net_ssl_callback(con, events);
else
if (!con->ssl)
{
#endif
con->callback(con, events, con->ptr);
#ifdef SSL_SUPPORT
}
else
{
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
#endif
switch (con->ssl_state)
{
case tls_st_none:
con->callback(con, events, con->ptr);
break;
case tls_st_error:
con->callback(con, NET_EVENT_READ, con->ptr);
break;
case tls_st_accepting:
if (net_con_ssl_accept(con) < 0)
{
con->callback(con, NET_EVENT_READ, con->ptr);
}
break;
case tls_st_connecting:
if (net_con_ssl_connect(con) < 0)
{
con->callback(con, NET_EVENT_READ, con->ptr);
}
break;
case tls_st_connected:
LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : "");
if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ)
{
con->callback(con, events & NET_EVENT_READ, con->ptr);
return;
}
if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
{
con->callback(con, events & NET_EVENT_READ, con->ptr);
return;
}
con->callback(con, events, con->ptr);
break;
case tls_st_disconnecting:
return;
}
}
#endif
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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
@@ -23,7 +23,6 @@
#include "uhub.h"
#include "network/common.h"
#include "network/backend.h"
#include "network/tls.h"
#define NET_EVENT_TIMEOUT 0x0001
#define NET_EVENT_READ 0x0002
@@ -84,5 +83,29 @@ extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len);
extern void net_con_set_timeout(struct net_connection* con, int seconds);
extern void net_con_clear_timeout(struct net_connection* con);
#ifdef SSL_SUPPORT
/**
* Start SSL_accept()
*/
extern ssize_t net_con_ssl_accept(struct net_connection*);
/**
* Start SSL_connect()
*/
extern ssize_t net_con_ssl_connect(struct net_connection*);
enum net_con_ssl_mode
{
net_con_ssl_mode_server,
net_con_ssl_mode_client,
};
extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx);
extern int net_con_is_ssl(struct net_connection* con);
extern SSL* net_con_get_ssl(struct net_connection* con);
extern void net_con_set_ssl(struct net_connection* con, SSL*);
#endif /* SSL_SUPPORT */
#endif /* HAVE_UHUB_NETWORK_CONNECTION_H */

View File

@@ -1,386 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
static struct net_dns_job* find_and_remove_job(struct net_dns_job* job);
static struct net_dns_result* find_and_remove_result(struct net_dns_job* job);
struct net_dns_job
{
net_dns_job_cb callback;
void* ptr;
char* host;
int af;
#ifdef DEBUG_LOOKUP_TIME
struct timeval time_start;
struct timeval time_finish;
#endif
uhub_thread_t* thread_handle;
};
struct net_dns_result
{
struct linked_list* addr_list;
struct net_dns_job* job;
};
static void free_job(struct net_dns_job* job)
{
if (job)
{
hub_free(job->host);
hub_free(job);
}
}
static void shutdown_free_jobs(void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) ptr;
uhub_thread_cancel(job->thread_handle);
uhub_thread_join(job->thread_handle);
free_job(job);
}
static void shutdown_free_results(void* ptr)
{
struct net_dns_result* result = (struct net_dns_result*) ptr;
uhub_thread_join(result->job->thread_handle);
net_dns_result_free(result);
}
// NOTE: Any job manipulating the members of this
// struct must lock the mutex!
struct net_dns_subsystem
{
struct linked_list* jobs; // currently running jobs
struct linked_list* results; // queue of results that are awaiting being delivered to callback.
uhub_mutex_t mutex;
};
static struct net_dns_subsystem* g_dns = NULL;
void net_dns_initialize()
{
LOG_TRACE("net_dns_initialize()");
g_dns = (struct net_dns_subsystem*) hub_malloc_zero(sizeof(struct net_dns_subsystem));
g_dns->jobs = list_create();
g_dns->results = list_create();
uhub_mutex_init(&g_dns->mutex);
}
void net_dns_destroy()
{
struct net_dns_job* job;
struct net_dns_result* result;
uhub_mutex_lock(&g_dns->mutex);
LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs));
list_clear(g_dns->jobs, &shutdown_free_jobs);
LOG_TRACE("net_dns_destroy(): results=%d", (int) list_size(g_dns->results));
list_clear(g_dns->results, &shutdown_free_results);
uhub_mutex_unlock(&g_dns->mutex);
list_destroy(g_dns->jobs);
list_destroy(g_dns->results);
uhub_mutex_destroy(&g_dns->mutex);
hub_free(g_dns);
g_dns = NULL;
}
static void dummy_free(void* ptr)
{
}
void net_dns_process()
{
struct net_dns_result* result;
uhub_mutex_lock(&g_dns->mutex);
LOG_DUMP("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results));
for (result = (struct net_dns_result*) list_get_first(g_dns->results); result; result = (struct net_dns_result*) list_get_next(g_dns->results))
{
struct net_dns_job* job = result->job;
#ifdef DEBUG_LOOKUP_TIME
struct timeval time_result;
timersub(&result->job->time_finish, &result->job->time_start, &time_result);
LOG_TRACE("DNS lookup took %d ms", (time_result.tv_sec * 1000) + (time_result.tv_usec / 1000));
#endif
// wait for the work thread to finish
uhub_thread_join(job->thread_handle);
// callback - should we delete the data immediately?
if (job->callback(job, result))
{
net_dns_result_free(result);
}
else
{
/* Caller wants to keep the result data, and
* thus needs to call net_dns_result_free() to release it later.
* We only clean up the job data here and keep the results intact.
*/
result->job = NULL;
free_job(job);
}
}
list_clear(g_dns->results, &dummy_free);
uhub_mutex_unlock(&g_dns->mutex);
}
static void* job_thread_resolve_name(void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) ptr;
struct addrinfo hints, *result, *it;
struct net_dns_result* dns_results;
int ret;
memset(&hints, 0, sizeof(hints));
hints.ai_family = job->af;
hints.ai_protocol = IPPROTO_TCP;
ret = getaddrinfo(job->host, NULL, &hints, &result);
if (ret != 0 && ret != EAI_NONAME)
{
LOG_TRACE("getaddrinfo() failed: %s", gai_strerror(ret));
return NULL;
}
dns_results = (struct net_dns_result*) hub_malloc(sizeof(struct net_dns_result));
dns_results->addr_list = list_create();
dns_results->job = job;
if (ret != EAI_NONAME)
{
for (it = result; it; it = it->ai_next)
{
struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap));
ipaddr->af = it->ai_family;
if (it->ai_family == AF_INET)
{
struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr;
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
}
else if (it->ai_family == AF_INET6)
{
struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr;
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
}
else
{
LOG_TRACE("getaddrinfo() returned result with unknown address family: %d", it->ai_family);
hub_free(ipaddr);
continue;
}
LOG_DUMP("getaddrinfo() - Address (%d) %s for \"%s\"", ret++, ip_convert_to_string(ipaddr), job->host);
list_append(dns_results->addr_list, ipaddr);
}
freeaddrinfo(result);
}
else
{
/* hm */
}
#ifdef DEBUG_LOOKUP_TIME
gettimeofday(&job->time_finish, NULL);
#endif
uhub_mutex_lock(&g_dns->mutex);
list_remove(g_dns->jobs, job);
list_append(g_dns->results, dns_results);
uhub_mutex_unlock(&g_dns->mutex);
return dns_results;
}
extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job));
job->host = strdup(host);
job->af = af;
job->callback = callback;
job->ptr = ptr;
#ifdef DEBUG_LOOKUP_TIME
gettimeofday(&job->time_start, NULL);
#endif
// FIXME - scheduling - what about a max number of threads?
uhub_mutex_lock(&g_dns->mutex);
job->thread_handle = uhub_thread_create(job_thread_resolve_name, job);
if (!job->thread_handle)
{
LOG_WARN("Unable to create thread");
free_job(job);
job = NULL;
}
else
{
list_append(g_dns->jobs, job);
}
uhub_mutex_unlock(&g_dns->mutex);
return job;
}
extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job));
// job->host = strdup(addr);
job->af = ipaddr->af;
job->callback = callback;
job->ptr = ptr;
// if (pthread_create(&job->thread_handle, NULL, start_job, job))
// {
// free_job(job);
// return NULL;
// }
return job;
}
// NOTE: mutex must be locked first!
static struct net_dns_job* find_and_remove_job(struct net_dns_job* job)
{
struct net_dns_job* it;
for (it = (struct net_dns_job*) list_get_first(g_dns->jobs); it; it = (struct net_dns_job*) list_get_next(g_dns->jobs))
{
if (it == job)
{
list_remove(g_dns->jobs, it);
return job;
}
}
return NULL;
}
// NOTE: mutex must be locked first!
static struct net_dns_result* find_and_remove_result(struct net_dns_job* job)
{
struct net_dns_result* it;
for (it = (struct net_dns_result*) list_get_first(g_dns->results); it; it = (struct net_dns_result*) list_get_next(g_dns->results))
{
if (it->job == job)
{
list_remove(g_dns->results, it);
return it;
}
}
return NULL;
}
extern int net_dns_job_cancel(struct net_dns_job* job)
{
int retval = 0;
struct net_dns_result* res;
LOG_TRACE("net_dns_job_cancel(): job=%p, name=%s", job, job->host);
/*
* This function looks up the job in the jobs queue (which contains only active jobs)
* If that is found then the thread is cancelled, and the object is deleted.
* If the job was not found, that is either because it was an invalid job, or because
* it was already finished. At which point it was not deleted.
* If the job is already finished, but the result has not been delivered, then this
* deletes the result and the job.
*/
uhub_mutex_lock(&g_dns->mutex);
if (find_and_remove_job(job))
{
// job still active - cancel it, then close it.
uhub_thread_cancel(job->thread_handle);
uhub_thread_join(job->thread_handle);
free_job(job);
retval = 1;
}
else if ((res = find_and_remove_result(job)))
{
// job already finished - close it.
uhub_thread_join(job->thread_handle);
net_dns_result_free(res);
}
uhub_mutex_unlock(&g_dns->mutex);
return retval;
}
extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job)
{
struct net_dns_result* res = NULL;
// Wait for job to finish (if not already)
// This should make sure the job is removed from jobs and a result is
// present in results.
uhub_thread_join(job->thread_handle);
// Remove the result in order to prevent the callback from being called.
uhub_mutex_lock(&g_dns->mutex);
res = find_and_remove_result(job);
uhub_assert(res != NULL);
res->job = NULL;
free_job(job);
uhub_mutex_unlock(&g_dns->mutex);
return res;
}
void* net_dns_job_get_ptr(const struct net_dns_job* job)
{
return job->ptr;
}
extern size_t net_dns_result_size(const struct net_dns_result* res)
{
return list_size(res->addr_list);
}
extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_first(res->addr_list);
LOG_TRACE("net_dns_result_first() - Address: %s", ip_convert_to_string(ipaddr));
return ipaddr;
}
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_next(res->addr_list);
LOG_TRACE("net_dns_result_next() - Address: %s", ip_convert_to_string(ipaddr));
return ipaddr;
}
extern void net_dns_result_free(struct net_dns_result* res)
{
list_clear(res->addr_list, &hub_free);
list_destroy(res->addr_list);
free_job(res->job);
hub_free(res);
}

View File

@@ -1,119 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_DNS_RESOLVER_H
#define HAVE_UHUB_NETWORK_DNS_RESOLVER_H
struct net_dns_job;
struct net_dns_result;
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// Initialize the DNS subsystem
void net_dns_initialize();
/// Shutdown and destroy the DNS subsystem. This will cancel any pending DNS jobs.
void net_dns_destroy();
/// Process finished DNS lookups.
void net_dns_process();
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* Callback to be called when the DNS job has finished.
* If the name or address could not be resolved to an IP address (host not found, or found but has no address)
* then 'result' contains an empty list (@see net_dns_result_size()).
* If resolving caused an error then result is NULL.
*
* After this callback is called the job is considered done, and is freed.
*
* @param If 1 is returned then result is deleted immediately after the callback,
* otherwise the callback becomes owner of the result data which must be freed with net_dns_result_free().
*/
typedef int (*net_dns_job_cb)(struct net_dns_job*, const struct net_dns_result* result);
/**
* Resolve a hostname.
*
* @param host the hostname to be resolved.
* @param af the indicated address family. Should be AF_INET, AF_INET6 (or AF_UNSPEC - which means both AF_INET and AF_INET6.
* @param callback the callback to be called when the hostname has been resolved.
* @param ptr A user-defined pointer value.
*
* @return A resolve job handle if the job has successfully started or NULL if unable to start resolving.
*/
extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr);
/**
* Perform a reverse DNS lookup for a given IP address.
*
* @see net_dns_gethostbyname()
* @return A resolve job handle if the job has successfully started or NULL if unable to start resolving.
*/
extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr);
/**
* Cancel a DNS lookup job.
*
* It is only allowed to call this once after a job has been started (@see net_dns_gethostbyname(), @see net_dns_gethostbyaddr())
* but before it has finished and delivered a to the callback address (@see net_dns_job_cb).
*
* @returns 1 if cancelled, or 0 if not cancelled (because the job was not found!)
*/
extern int net_dns_job_cancel(struct net_dns_job* job);
/**
* Wait in a synchronous manner for a running DNS job to finished and
* return the result here.
* The job must be started with net_dns_gethostbyaddr/net_dns_gethostbyname
* and not finished or cancelled.
*
* If this function is invoked then the callback function will not be called and
* can therefore be NULL.
*
* <code>
* struct net_dns_job* job = net_dns_gethostbyname("www.example.com", AF_INET, NULL, NULL);
* struct net_dns_result* net_dns_job_sync_wait(job);
* </code>
*/
extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job);
/**
* Returns the user specified pointer assigned to the resolving job
*/
extern void* net_dns_job_get_ptr(const struct net_dns_job* job);
/// Returns the number of results provided. This is 0 if the host could not be found (or has no matching IP address).
extern size_t net_dns_result_size(const struct net_dns_result*);
/// Returns the first result (if net_dns_result_size > 0), or NULL if not first result exists.
extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*);
/// Returns the next result or NULL if no next result exists.
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*);
/// When finished with the results
extern void net_dns_result_free(struct net_dns_result*);
#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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
@@ -49,21 +49,21 @@ int net_initialize()
}
#endif /* WINSOCK */
if (!net_backend_init()
#ifdef SSL_SUPPORT
|| !net_ssl_library_init()
#endif
)
if (!net_backend_init())
{
#ifdef WINSOCK
WSACleanup();
#endif
return -1;
}
net_dns_initialize();
net_stats_initialize();
#ifdef SSL_SUPPORT
LOG_TRACE("Initializing OpenSSL...");
SSL_library_init();
SSL_load_error_strings();
#endif /* SSL_SUPPORT */
net_initialized = 1;
return 0;
}
@@ -97,13 +97,13 @@ int net_destroy()
{
LOG_TRACE("Shutting down network monitor");
net_dns_destroy();
net_backend_shutdown();
#ifdef SSL_SUPPORT
net_ssl_library_shutdown();
#endif /* SSL_SUPPORT */
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
#endif
#ifdef WINSOCK
WSACleanup();
@@ -495,6 +495,7 @@ int net_socket_create(int af, int type, int protocol)
}
}
#endif
return sd;
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2010, 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
@@ -31,7 +31,6 @@ struct net_statistics
};
struct net_socket_t;
struct ip_addr_encap;
/**
* Initialize the socket monitor subsystem.

View File

@@ -1,351 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#include "network/common.h"
#include "network/tls.h"
#ifdef SSL_SUPPORT
#ifdef SSL_USE_OPENSSL
void net_stats_add_tx(size_t bytes);
void net_stats_add_rx(size_t bytes);
struct net_ssl_openssl
{
SSL* ssl;
BIO* bio;
enum ssl_state state;
uint32_t flags;
size_t bytes_rx;
size_t bytes_tx;
};
struct net_context_openssl
{
SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
};
static struct net_ssl_openssl* get_handle(struct net_connection* con)
{
uhub_assert(con);
return (struct net_ssl_openssl*) con->ssl;
}
const char* net_ssl_get_provider()
{
return OPENSSL_VERSION_TEXT;
}
int net_ssl_library_init()
{
LOG_TRACE("Initializing OpenSSL...");
SSL_library_init();
SSL_load_error_strings();
return 1;
}
int net_ssl_library_shutdown()
{
ERR_clear_error();
ERR_remove_state(0);
ENGINE_cleanup();
CONF_modules_unload(1);
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
// sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
return 1;
}
static void add_io_stats(struct net_ssl_openssl* handle)
{
if (handle->bio->num_read > handle->bytes_rx)
{
net_stats_add_rx(handle->bio->num_read - handle->bytes_rx);
handle->bytes_rx = handle->bio->num_read;
}
if (handle->bio->num_write > handle->bytes_tx)
{
net_stats_add_tx(handle->bio->num_write - handle->bytes_tx);
handle->bytes_tx = handle->bio->num_write;
}
}
/**
* Create a new SSL context.
*/
struct ssl_context_handle* net_ssl_context_create()
{
struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl));
ctx->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */
ctx->ssl_ctx = SSL_CTX_new(ctx->ssl_method);
/* Disable SSLv2 */
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2);
#ifdef SSL_OP_NO_COMPRESSION
/* Disable compression? */
LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_COMPRESSION);
#endif
SSL_CTX_set_quiet_shutdown(ctx->ssl_ctx, 1);
return (struct ssl_context_handle*) ctx;
}
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx_)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
SSL_CTX_free(ctx->ssl_ctx);
hub_free(ctx);
}
int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem_file, SSL_FILETYPE_PEM) < 0)
{
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
}
return 1;
}
int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem_file, SSL_FILETYPE_PEM) < 0)
{
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
}
return 1;
}
int ssl_check_private_key(struct ssl_context_handle* ctx_)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_check_private_key(ctx->ssl_ctx) != 1)
{
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
}
return 1;
}
static int handle_openssl_error(struct net_connection* con, int ret, enum ssl_state forced_rwstate)
{
struct net_ssl_openssl* handle = get_handle(con);
int err = SSL_get_error(handle->ssl, ret);
switch (err)
{
case SSL_ERROR_ZERO_RETURN:
// Not really an error, but SSL was shut down.
return -1;
case SSL_ERROR_WANT_READ:
handle->state = forced_rwstate;
net_con_update(con, NET_EVENT_READ);
return 0;
case SSL_ERROR_WANT_WRITE:
handle->state = forced_rwstate;
net_con_update(con, NET_EVENT_WRITE);
return 0;
case SSL_ERROR_SYSCALL:
handle->state = tls_st_error;
return -2;
}
}
ssize_t net_con_ssl_accept(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
handle->state = tls_st_accepting;
ssize_t ret;
ret = SSL_accept(handle->ssl);
LOG_PROTO("SSL_accept() ret=%d", ret);
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
handle->state = tls_st_connected;
return ret;
}
return handle_openssl_error(con, ret, tls_st_accepting);
}
ssize_t net_con_ssl_connect(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
ssize_t ret;
handle->state = tls_st_connecting;
ret = SSL_connect(handle->ssl);
LOG_PROTO("SSL_connect() ret=%d", ret);
if (ret > 0)
{
handle->state = tls_st_connected;
net_con_update(con, NET_EVENT_READ);
return ret;
}
return handle_openssl_error(con, ret, tls_st_connecting);
}
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx)
{
uhub_assert(con);
struct net_context_openssl* ctx = (struct net_context_openssl*) ssl_ctx;
struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl));
if (ssl_mode == net_con_ssl_mode_server)
{
handle->ssl = SSL_new(ctx->ssl_ctx);
if (!handle->ssl)
{
LOG_ERROR("Unable to create new SSL stream\n");
return -1;
}
SSL_set_fd(handle->ssl, con->sd);
handle->bio = SSL_get_rbio(handle->ssl);
con->ssl = (struct ssl_handle*) handle;
return net_con_ssl_accept(con);
}
else
{
handle->ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
SSL_set_fd(handle->ssl, con->sd);
handle->bio = SSL_get_rbio(handle->ssl);
con->ssl = (struct ssl_handle*) handle;
return net_con_ssl_connect(con);
}
}
ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len)
{
struct net_ssl_openssl* handle = get_handle(con);
uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_write);
ERR_clear_error();
ssize_t ret = SSL_write(handle->ssl, buf, len);
add_io_stats(handle);
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret > 0)
{
handle->state = tls_st_connected;
return ret;
}
return handle_openssl_error(con, ret, tls_st_need_write);
}
ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len)
{
struct net_ssl_openssl* handle = get_handle(con);
ssize_t ret;
if (handle->state == tls_st_error)
return -2;
uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_read);
ERR_clear_error();
ret = SSL_read(handle->ssl, buf, len);
add_io_stats(handle);
LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret > 0)
{
handle->state = tls_st_connected;
return ret;
}
return handle_openssl_error(con, ret, tls_st_need_read);
}
void net_ssl_shutdown(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
SSL_shutdown(handle->ssl);
SSL_clear(handle->ssl);
}
void net_ssl_destroy(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
SSL_free(handle->ssl);
}
void net_ssl_callback(struct net_connection* con, int events)
{
struct net_ssl_openssl* handle = get_handle(con);
switch (handle->state)
{
case tls_st_none:
con->callback(con, events, con->ptr);
break;
case tls_st_error:
con->callback(con, NET_EVENT_READ, con->ptr);
break;
case tls_st_accepting:
if (net_con_ssl_accept(con) != 0)
con->callback(con, NET_EVENT_READ, con->ptr);
break;
case tls_st_connecting:
if (net_con_ssl_connect(con) != 0)
con->callback(con, NET_EVENT_READ, con->ptr);
break;
case tls_st_need_read:
con->callback(con, NET_EVENT_READ, con->ptr);
break;
case tls_st_need_write:
con->callback(con, NET_EVENT_WRITE, con->ptr);
break;
case tls_st_connected:
con->callback(con, events, con->ptr);
break;
case tls_st_disconnecting:
return;
}
}
#endif /* SSL_USE_OPENSSL */
#endif /* SSL_SUPPORT */

View File

@@ -1,104 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_TLS_H
#define HAVE_UHUB_NETWORK_TLS_H
#include "uhub.h"
#ifdef SSL_SUPPORT
enum ssl_state
{
tls_st_none,
tls_st_error,
tls_st_accepting,
tls_st_connecting,
tls_st_connected,
tls_st_need_read, /* special case of connected */
tls_st_need_write, /* special case of connected */
tls_st_disconnecting,
};
enum net_con_ssl_mode
{
net_con_ssl_mode_server,
net_con_ssl_mode_client,
};
struct ssl_context_handle;
/**
* Returns a string describing the TLS/SSL provider information
*/
extern const char* net_ssl_get_provider();
/**
* return 0 if error, 1 on success.
*/
extern int net_ssl_library_init();
extern int net_ssl_library_shutdown();
/**
* Create a new SSL context.
*/
extern struct ssl_context_handle* net_ssl_context_create();
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx);
/**
* Return 0 on error, 1 otherwise.
*/
extern int ssl_load_certificate(struct ssl_context_handle* ctx, const char* pem_file);
/**
* Return 0 on error, 1 otherwise.
*/
extern int ssl_load_private_key(struct ssl_context_handle* ctx, const char* pem_file);
/**
* Return 0 if private key does not match certificate, 1 if everything is OK.
*/
extern int ssl_check_private_key(struct ssl_context_handle* ctx);
/**
* Start SSL_accept()
*/
extern ssize_t net_con_ssl_accept(struct net_connection*);
/**
* Start SSL_connect()
*/
extern ssize_t net_con_ssl_connect(struct net_connection*);
extern ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len);
extern ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len);
extern void net_ssl_shutdown(struct net_connection* con);
extern void net_ssl_destroy(struct net_connection* con);
extern void net_ssl_callback(struct net_connection* con, int events);
extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, struct ssl_context_handle* ssl_ctx);
extern int net_con_is_ssl(struct net_connection* con);
#endif /* SSL_SUPPORT */
#endif /* HAVE_UHUB_NETWORK_TLS_H */

View File

@@ -26,7 +26,7 @@
#include "system.h"
#include "util/credentials.h"
#include "network/ipcalc.h"
#include "util/ipcalc.h"
#include "plugin_api/types.h"
typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*);

View File

@@ -20,6 +20,7 @@
#include "plugin_api/handle.h"
#include "util/memory.h"
#include "util/list.h"
#include "util/ipcalc.h"
#include "util/misc.h"
#include "util/log.h"
#include "util/config_token.h"

View File

@@ -21,6 +21,7 @@
#include <sqlite3.h>
#include "util/memory.h"
#include "util/list.h"
#include "util/ipcalc.h"
#include "util/misc.h"
#include "util/log.h"
#include "util/config_token.h"

View File

@@ -64,13 +64,13 @@ static struct user_info* get_user_info(struct chat_only_data* data, sid_t sid)
struct user_info* u;
// resize buffer if needed.
if (sid >= data->max_users)
if (sid > data->max_users) // FIXME: >= ?
{
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 + 1;
data->max_users = sid;
u = NULL;
}

View File

@@ -21,7 +21,7 @@
#include "adc/adcconst.h"
#include "adc/sid.h"
#include "util/memory.h"
#include "network/ipcalc.h"
#include "util/ipcalc.h"
#include "plugin_api/handle.h"
#include "util/misc.h"

View File

@@ -1,60 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "plugin_api/handle.h"
#include "util/memory.h"
static plugin_st on_search_result(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* search_data)
{
if (to->credentials >= auth_cred_user)
return st_default;
return st_deny;
}
static plugin_st on_search(struct plugin_handle* plugin, struct plugin_user* user, const char* search_data)
{
// Registered users are allowed to search.
if (user->credentials >= auth_cred_user)
return st_default;
return st_deny;
}
static plugin_st on_p2p_connect(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to)
{
if (from->credentials >= auth_cred_user)
return st_default;
return st_deny;
}
int plugin_register(struct plugin_handle* plugin, const char* config)
{
PLUGIN_INITIALIZE(plugin, "No guest downloading", "0.1", "This plug-in only allows registered users to search and initiate transfers.");
plugin->ptr = NULL;
plugin->funcs.on_search = on_search;
plugin->funcs.on_search_result = on_search_result;
plugin->funcs.on_p2p_connect = on_p2p_connect;
// plugin->funcs.on_p2p_revconnect = on_p2p_connect;
return 0;
}
int plugin_unregister(struct plugin_handle* plugin)
{
return 0;
}

View File

@@ -22,7 +22,7 @@
#include "adc/sid.h"
#include "util/cbuffer.h"
#include "util/memory.h"
#include "network/ipcalc.h"
#include "util/ipcalc.h"
#include "plugin_api/handle.h"
#include "plugin_api/command_api.h"

View File

@@ -34,7 +34,6 @@
#ifndef WINSOCK
#define WINSOCK
#endif
#define WINTHREAD_SUPPORT 1
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__)
@@ -100,13 +99,8 @@
#endif
#ifdef SSL_SUPPORT
#ifdef SSL_USE_OPENSSL
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif /* SSL_USE_OPENSSL */
#ifdef SSL_USE_GNUTLS
#include <gnutls/gnutls.h>
#endif /* SSL_USE_GNUTLS */
#endif
#include "version.h"
@@ -114,13 +108,11 @@
#define uhub_assert assert
#ifdef __linux__
#define POSIX_THREAD_SUPPORT
#define USE_EPOLL
#include <sys/epoll.h>
#endif
#ifdef BSD_LIKE
#define POSIX_THREAD_SUPPORT
/*
#define USE_KQUEUE
#include <sys/event.h>
@@ -132,7 +124,7 @@
#include <sys/select.h>
#endif
#if ( defined(BSD_LIKE) && !defined(__FreeBSD_kernel__) ) || defined(__sun__)
#if defined(BSD_LIKE) || defined(__sun__)
#undef HAVE_STRNDUP
#undef HAVE_MEMMEM
#endif
@@ -282,10 +274,6 @@ typedef unsigned __int64 uint64_t;
#define NEED_GETOPT
#endif
#ifdef POSIX_THREAD_SUPPORT
#include <pthread.h>
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
#define PLUGIN_API __declspec(dllexport)
#else

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2011, 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
@@ -23,59 +23,9 @@
#define ADC_CID_SIZE 39
#define BIG_BUFSIZE 32768
#define TIGERSIZE 24
#define MAX_RECV_BUFFER 65536
// #define ADCC_DEBUG
// #define ADC_CLIENT_DEBUG_PROTO
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 */
ps_identify, /* Have sent BINF */
ps_verify, /* Have sent HPAS */
ps_normal, /* Are fully logged in */
};
enum ADC_client_flags
{
cflag_none = 0,
cflag_ssl = 1,
cflag_choke = 2,
cflag_pipe = 4,
};
struct ADC_client_address
{
enum Protocol { ADC, ADCS } protocol;
char* hostname;
uint16_t port;
};
struct ADC_client
{
sid_t sid;
enum ADC_client_state state;
struct adc_message* info;
struct ioq_recv* recv_queue;
struct ioq_send* send_queue;
adc_client_cb callback;
size_t s_offset;
size_t r_offset;
size_t timeout;
struct net_connection* con;
struct net_timer* timer;
struct sockaddr_storage addr;
struct net_dns_job* dns_job;
struct ADC_client_address address;
char* nick;
char* desc;
int flags;
void* ptr;
};
static ssize_t ADC_client_recv(struct ADC_client* client);
static void ADC_client_send_info(struct ADC_client* client);
@@ -86,8 +36,7 @@ static void ADC_client_on_connected_ssl(struct ADC_client* client);
static void ADC_client_on_disconnected(struct ADC_client* client);
static void ADC_client_on_login(struct ADC_client* client);
static int ADC_client_parse_address(struct ADC_client* client, const char* arg);
static int ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length);
static int ADC_client_send_queue(struct ADC_client* client);
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length);
static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
{
@@ -109,7 +58,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,9 +112,6 @@ 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)
{
@@ -175,7 +120,7 @@ static void event_callback(struct net_connection* con, int events, void *arg)
}
if (events & NET_EVENT_WRITE)
ADC_client_connect_internal(client);
ADC_client_connect(client, 0);
break;
#ifdef SSL_SUPPORT
@@ -201,7 +146,7 @@ static void event_callback(struct net_connection* con, int events, void *arg)
if (events & NET_EVENT_WRITE)
{
ADC_client_send_queue(client);
/* FIXME: Call send again */
}
}
}
@@ -239,7 +184,7 @@ static void event_callback(struct net_connection* con, int events, void *arg)
} while (0)
static int ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
{
struct ADC_chat_message chat;
struct ADC_client_callback_data data;
@@ -254,13 +199,13 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line,
if (!msg)
{
ADC_client_debug(client, "WARNING: Message cannot be decoded: \"%s\"", line);
return -1;
return;
}
if (length < 4)
{
ADC_client_debug(client, "Unexpected response from hub: '%s'", line);
return -1;
return;
}
switch (msg->cmd)
@@ -380,134 +325,75 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line,
}
adc_msg_free(msg);
return 0;
}
static ssize_t ADC_client_recv(struct ADC_client* client)
{
static char buf[BIG_BUFSIZE];
struct ioq_recv* q = client->recv_queue;
size_t buf_size = ioq_recv_get(q, buf, BIG_BUFSIZE);
ssize_t size;
ADC_TRACE;
ssize_t size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset);
if (size <= 0)
return size;
if (client->flags & cflag_choke)
buf_size = 0;
size = net_con_recv(client->con, buf + buf_size, BIG_BUFSIZE - buf_size);
client->r_offset += size;
client->recvbuf[client->r_offset] = 0;
if (size > 0)
buf_size += size;
char* start = client->recvbuf;
char* pos;
char* lastPos = 0;
size_t remaining = client->r_offset;
if (size < 0)
return -1;
else if (size == 0)
return 0;
else
while ((pos = memchr(start, '\n', remaining)))
{
char* lastPos = 0;
char* start = buf;
char* pos = 0;
size_t remaining = buf_size;
pos[0] = 0;
while ((pos = memchr(start, '\n', remaining)))
{
lastPos = pos+1;
pos[0] = '\0';
ADC_client_on_recv_line(client, start, pos - start);
#ifdef DEBUG_SENDQ
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
pos++;
remaining -= (pos - start);
start = pos;
lastPos = pos;
}
if (lastPos)
{
memmove(client->recvbuf, lastPos, remaining);
client->r_offset = remaining;
}
return 0;
}
void ADC_client_send(struct ADC_client* client, char* msg)
{
ADC_TRACE;
int ret = net_con_send(client->con, msg, strlen(msg));
#ifdef ADC_CLIENT_DEBUG_PROTO
char* dump = strdup(msg);
dump[strlen(msg) - 1] = 0;
ADC_client_debug(client, "- SEND: '%s'", dump);
free(dump);
#endif
if (client->flags & cflag_choke)
client->flags &= ~cflag_choke;
else
{
if (((pos - start) > 0) && MAX_RECV_BUFFER > (pos - start))
{
if (ADC_client_on_recv_line(client, start, pos - start) == -1)
return -1;
}
}
pos[0] = '\n'; /* FIXME: not needed */
pos ++;
remaining -= (pos - start);
start = pos;
}
if (lastPos || remaining)
if (ret != strlen(msg))
{
if (ret == -1)
{
if (remaining < (size_t) MAX_RECV_BUFFER)
{
ioq_recv_set(q, lastPos ? lastPos : buf, remaining);
}
else
{
ioq_recv_set(q, 0, 0);
client->flags |= cflag_choke;
LOG_WARN("Received message past MAX_RECV_BUFFER (%d), dropping message.", MAX_RECV_BUFFER);
}
if (net_error() != EWOULDBLOCK)
ADC_client_on_disconnected(client);
}
else
{
ioq_recv_set(q, 0, 0);
/* FIXME: Not all data sent! */
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
}
}
return 0;
}
static int ADC_client_send_queue(struct ADC_client* client)
{
int ret = 0;
while (ioq_send_get_bytes(client->send_queue))
{
ret = ioq_send_send(client->send_queue, client->con);
if (ret <= 0)
break;
}
if (ret < 0)
return quit_socket_error;
if (ioq_send_get_bytes(client->send_queue))
{
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
}
else
{
net_con_update(client->con, NET_EVENT_READ);
}
return 0;
}
void ADC_client_send(struct ADC_client* client, struct adc_message* msg)
{
ADC_TRACE;
uhub_assert(client->con != NULL);
uhub_assert(msg->cache && *msg->cache);
if (ioq_send_is_empty(client->send_queue) && !(client->flags & cflag_pipe))
{
/* Perform oportunistic write */
ioq_send_add(client->send_queue, msg);
ADC_client_send_queue(client);
}
else
{
ioq_send_add(client->send_queue, msg);
if (!(client->flags & cflag_pipe))
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
}
}
void ADC_client_send_info(struct ADC_client* client)
{
ADC_TRACE;
client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96);
client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 64);
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick);
@@ -516,84 +402,65 @@ void ADC_client_send_info(struct ADC_client* client)
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc);
}
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT " " VERSION);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SLOTS, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_SIZE, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_FILES, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_NORMAL, 1);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_REGISTER, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_OPERATOR, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_DOWNLOAD_SPEED, 5 * 1024 * 1024);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024);
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION);
adc_cid_pid(client);
ADC_client_send(client, client->info);
ADC_client_send(client, client->info->cache);
}
struct ADC_client* ADC_client_create(const char* nickname, const char* description, void* ptr)
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description)
{
ADC_TRACE;
struct ADC_client* client = (struct ADC_client*) hub_malloc_zero(sizeof(struct ADC_client));
memset(client, 0, sizeof(struct ADC_client));
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1) return NULL;
if (sd == -1) return -1;
client->con = net_con_create();
#if 0
/* FIXME */
client->timer = 0; /* FIXME: hub_malloc(sizeof(struct net_timer)); */
#endif
net_con_initialize(client->con, sd, event_callback, client, 0);
#if 0
/* FIXME */
net_timer_initialize(client->timer, timer_callback, client);
#endif
ADC_client_set_state(client, ps_none);
client->nick = hub_strdup(nickname);
client->desc = hub_strdup(description);
client->send_queue = ioq_send_create();
client->recv_queue = ioq_recv_create();
client->ptr = ptr;
return client;
return 0;
}
void ADC_client_destroy(struct ADC_client* client)
{
ADC_TRACE;
ADC_client_disconnect(client);
ioq_send_destroy(client->send_queue);
ioq_recv_destroy(client->recv_queue);
#if 0
/* FIXME */
net_timer_shutdown(client->timer);
#endif
hub_free(client->timer);
adc_msg_free(client->info);
hub_free(client->nick);
hub_free(client->desc);
hub_free(client->address.hostname);
hub_free(client);
hub_free(client->hub_address);
}
int ADC_client_connect(struct ADC_client* client, const char* address)
{
ADC_TRACE;
if (client->state == ps_none)
if (!client->hub_address)
{
// 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));
int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
ADC_client_on_connected(client);
@@ -615,23 +482,19 @@ static void ADC_client_on_connected(struct ADC_client* client)
{
ADC_TRACE;
#ifdef SSL_SUPPORT
if (client->flags & cflag_ssl)
if (client->ssl_enabled)
{
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0);
ADC_client_set_state(client, ps_conn_ssl);
net_con_ssl_handshake(client->con, net_con_ssl_mode_client, NULL);
}
else
#endif
{
struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE);
net_con_update(client->con, NET_EVENT_READ);
client->callback(client, ADC_CLIENT_CONNECTED, 0);
ADC_client_send(client, handshake);
ADC_client_send(client, ADC_HANDSHAKE);
ADC_client_set_state(client, ps_protocol);
adc_msg_free(handshake);
}
}
@@ -639,13 +502,10 @@ static void ADC_client_on_connected(struct ADC_client* client)
static void ADC_client_on_connected_ssl(struct ADC_client* client)
{
ADC_TRACE;
struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE);
client->callback(client, ADC_CLIENT_SSL_OK, 0);
client->callback(client, ADC_CLIENT_CONNECTED, 0);
net_con_update(client->con, NET_EVENT_READ);
ADC_client_send(client, handshake);
client->callback(client, ADC_CLIENT_CONNECTED, 0);
ADC_client_send(client, ADC_HANDSHAKE);
ADC_client_set_state(client, ps_protocol);
adc_msg_free(handshake);
}
#endif
@@ -674,88 +534,58 @@ void ADC_client_disconnect(struct ADC_client* client)
}
}
int ADC_client_dns_callback(struct net_dns_job* job, const struct net_dns_result* result)
{
struct ADC_client* client = (struct ADC_client*) net_dns_job_get_ptr(job);
struct ip_addr_encap* ipaddr;
LOG_WARN("ADC_client_dns_callback(): result=%p (%d)", result, net_dns_result_size(result));
memset(&client->addr, 0, sizeof(client->addr));
ipaddr = net_dns_result_first(result);
switch (ipaddr->af)
{
case AF_INET:
{
struct sockaddr_in* addr4 = (struct sockaddr_in*) &client->addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(client->address.port);
memcpy(&addr4->sin_addr, &ipaddr->internal_ip_data.in, sizeof(struct in_addr));
break;
}
case AF_INET6:
{
struct sockaddr_in6* addr6 = (struct sockaddr_in6*) &client->addr;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(client->address.port);
memcpy(&addr6->sin6_addr, &ipaddr->internal_ip_data.in6, sizeof(struct in6_addr));
break;
}
default:
LOG_WARN("Unknown ipaddr!");
}
ADC_client_connect_internal(client);
return 1;
}
static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
{
ADC_TRACE;
const char* hub_address = arg;
char* split;
int ssl = 0;
struct hostent* dns;
struct in_addr* addr;
if (!arg)
return 0;
client->hub_address = hub_strdup(arg);
/* Minimum length of a valid address */
if (strlen(arg) < 9)
return 0;
/* Check for ADC or ADCS */
if (!strncmp(arg, "adc://", 6))
{
client->flags &= ~cflag_ssl;
client->address.protocol = ADC;
}
client->ssl_enabled = 0;
else if (!strncmp(arg, "adcs://", 7))
{
client->flags |= cflag_ssl;
client->ssl_enabled = 1;
ssl = 1;
client->address.protocol = ADCS;
}
else
return 0;
/* Split hostname and port (if possible) */
hub_address = arg + 6 + ssl;
split = strrchr(hub_address, ':');
split = strrchr(client->hub_address + 6 + ssl, ':');
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0;
/* Ensure port number is valid */
client->address.port = strtol(split+1, NULL, 10);
if (client->address.port <= 0 || client->address.port > 65535)
int port = strtol(split+1, NULL, 10);
if (port <= 0 || port > 65535)
return 0;
client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]);
split[0] = 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);
/* Resolve IP address (FIXME: blocking call) */
dns = gethostbyname(client->hub_address + 6 + ssl);
if (dns)
{
addr = (struct in_addr*) dns->h_addr_list[0];
}
// Initialize the sockaddr struct.
memset(&client->addr, 0, sizeof(client->addr));
client->addr.sin_family = AF_INET;
client->addr.sin_port = htons(port);
memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr));
return 1;
}
@@ -764,23 +594,3 @@ void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb)
ADC_TRACE;
client->callback = cb;
}
sid_t ADC_client_get_sid(const struct ADC_client* client)
{
return client->sid;
}
const char* ADC_client_get_nick(const struct ADC_client* client)
{
return client->nick;
}
const char* ADC_client_get_description(const struct ADC_client* client)
{
return client->desc;
}
void* ADC_client_get_ptr(const struct ADC_client* client)
{
return client->ptr;
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2011, 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,11 +24,21 @@
#define ADC_BUFSIZE 16384
enum ADC_client_state
{
ps_none, /* Not connected */
ps_conn, /* Connecting... */
ps_conn_ssl, /* SSL handshake */
ps_protocol, /* Have sent HSUP */
ps_identify, /* Have sent BINF */
ps_verify, /* Have sent HPAS */
ps_normal, /* Are fully logged in */
};
struct ADC_client;
enum ADC_client_callback_type
{
ADC_CLIENT_NAME_LOOKUP = 1000,
ADC_CLIENT_CONNECTING = 1001,
ADC_CLIENT_CONNECTED = 1002,
ADC_CLIENT_DISCONNECTED = 1003,
@@ -106,19 +116,38 @@ struct ADC_client_callback_data
};
};
sid_t ADC_client_get_sid(const struct ADC_client* client);
const char* ADC_client_get_nick(const struct ADC_client* client);
const char* ADC_client_get_description(const struct ADC_client* client);
void* ADC_client_get_ptr(const struct ADC_client* client);
typedef int (*adc_client_cb)(struct ADC_client*, enum ADC_client_callback_type, struct ADC_client_callback_data* data);
struct ADC_client* ADC_client_create(const char* nickname, const char* description, void* ptr);
struct ADC_client
{
sid_t sid;
enum ADC_client_state state;
struct adc_message* info;
char recvbuf[ADC_BUFSIZE];
char sendbuf[ADC_BUFSIZE];
adc_client_cb callback;
size_t s_offset;
size_t r_offset;
size_t timeout;
struct net_connection* con;
struct net_timer* timer;
struct sockaddr_in addr;
char* hub_address;
char* nick;
char* desc;
int ssl_enabled;
#ifdef SSL_SUPPORT
const SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
#endif /* SSL_SUPPORT */
};
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description);
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb);
void ADC_client_destroy(struct ADC_client* client);
int ADC_client_connect(struct ADC_client* client, const char* address);
void ADC_client_disconnect(struct ADC_client* client);
void ADC_client_send(struct ADC_client* client, struct adc_message* msg);
void ADC_client_send(struct ADC_client* client, char* msg);
#endif /* HAVE_UHUB_ADC_CLIENT_H */

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2011, 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,12 +24,10 @@
#define ADC_CID_SIZE 39
#define BIG_BUFSIZE 32768
#define TIGERSIZE 24
#define STATS_INTERVAL 3
#define ADCRUSH "adcrush/0.3"
#define ADC_NICK "[BOT]adcrush"
#define ADC_DESC "crash\\stest\\sdummy"
#define LVL_INFO 1
#define LVL_DEBUG 2
#define LVL_VERBOSE 3
@@ -40,32 +38,6 @@ static int cfg_level = 1; /* activity level (0..3) */
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
static int cfg_quiet = 0; /* quiet mode (no output) */
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
static int cfg_netstats_interval = STATS_INTERVAL;
static int running = 1;
static int logged_in = 0;
static int blank = 0;
static struct net_statistics* stats_intermediate;
static struct net_statistics* stats_total;
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data);
static void timer_callback(struct timeout_evt* t);
static void do_blank(int n)
{
n++;
while (n > 0)
{
fprintf(stdout, " ");
n--;
}
}
struct AdcFuzzUser
{
struct ADC_client* client;
struct timeout_evt* timer;
int logged_in;
};
#define MAX_CHAT_MSGS 35
const char* chat_messages[MAX_CHAT_MSGS] = {
@@ -131,14 +103,10 @@ static void bot_output(struct ADC_client* client, int level, const char* format,
va_end(args);
if (cfg_debug >= level)
{
int num = fprintf(stdout, "* [%p] %s", client, logmsg);
do_blank(blank - num);
fprintf(stdout, "\n");
}
fprintf(stdout, "* [%p] %s\n", client, logmsg);
}
#if 0
static size_t get_wait_rand(size_t max)
{
static size_t next = 0;
@@ -147,144 +115,120 @@ static size_t get_wait_rand(size_t max)
return ((size_t )(next / 65536) % max);
}
static size_t get_next_timeout_evt()
{
switch (cfg_level)
{
case 0: return get_wait_rand(120);
case 1: return get_wait_rand(60);
case 2: return get_wait_rand(15);
case 3: return get_wait_rand(5);
}
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
static void perf_chat(struct ADC_client* client, int priv)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_CHAT_MSGS-1);
char* msg = adc_msg_escape(chat_messages[r]);
struct adc_message* cmd = NULL;
if (priv)
cmd = adc_msg_construct_source_dest(ADC_CMD_DMSG, ADC_client_get_sid(client), ADC_client_get_sid(client), strlen(msg));
{
strcat(buf, "EMSG ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
}
else
cmd = adc_msg_construct_source(ADC_CMD_BMSG, ADC_client_get_sid(client), strlen(msg));
{
strcat(buf, "BMSG ");
strcat(buf, sid_to_string(client->sid));
}
strcat(buf, " ");
strcat(buf, msg);
hub_free(msg);
ADC_client_send(client, cmd);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_search(struct ADC_client* client)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_SEARCH_MSGS-1);
size_t pst = get_wait_rand(100);
struct adc_message* cmd = NULL;
if (pst > 80)
{
cmd = adc_msg_construct_source(ADC_CMD_FSCH, ADC_client_get_sid(client), strlen(search_messages[r]) + 6);
adc_msg_add_argument(cmd, "+TCP4");
strcat(buf, "FSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " +TCP4 ");
}
else
{
cmd = adc_msg_construct_source(ADC_CMD_BSCH, ADC_client_get_sid(client), strlen(search_messages[r]) + 6);
adc_msg_add_argument(cmd, "+TCP4");
strcat(buf, "BSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
}
ADC_client_send(client, cmd);
strcat(buf, search_messages[r]);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
{
char tmp[256];
struct adc_message* cmd = adc_msg_construct_source_dest(ADC_CMD_DRES, ADC_client_get_sid(client), target, strlen(what) + strlen(token) + 64);
snprintf(tmp, sizeof(tmp), "FNtest/%s.dat", what);
adc_msg_add_argument(cmd, tmp);
adc_msg_add_argument(cmd, "SL0");
adc_msg_add_argument(cmd, "SI1209818412");
adc_msg_add_argument(cmd, "TR5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
snprintf(tmp, sizeof(tmp), "TO%s", token);
adc_msg_add_argument(cmd, tmp);
ADC_client_send(client, cmd);
char buf[1024] = { 0, };
strcat(buf, "DRES ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(target));
strcat(buf, " FN" "test/");
strcat(buf, what);
strcat(buf, ".dat");
strcat(buf, " SL" "0");
strcat(buf, " SI" "908987128912");
strcat(buf, " TR" "5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
strcat(buf, " TO");
strcat(buf, token);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_ctm(struct ADC_client* client)
{
char buf[1024] = { 0, };
struct adc_message* cmd = adc_msg_construct_source_dest(ADC_CMD_DCTM, ADC_client_get_sid(client), ADC_client_get_sid(client), 32);
adc_msg_add_argument(cmd, "ADC/1.0");
adc_msg_add_argument(cmd, "TOKEN123456");
adc_msg_add_argument(cmd, sid_to_string(ADC_client_get_sid(client)));
ADC_client_send(client, cmd);
strcat(buf, "DCTM ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, "ADC/1.0");
strcat(buf, " TOKEN111");
strcat(buf, sid_to_string(client->sid));
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_update(struct ADC_client* client)
{
char buf[16] = { 0, };
char buf[1024] = { 0, };
int n = (int) get_wait_rand(10)+1;
struct adc_message* cmd = adc_msg_construct_source(ADC_CMD_BINF, ADC_client_get_sid(client), 32);
snprintf(buf, sizeof(buf), "HN%d", n);
adc_msg_add_argument(cmd, buf);
ADC_client_send(client, cmd);
}
strcat(buf, "BINF ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " HN");
strcat(buf, uhub_itoa(n));
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);
hub_free(c->timer);
c->timer = 0;
c->logged_in = 0;
}
static void client_connect(struct AdcFuzzUser* c, const char* nick, const char* description)
{
size_t timeout = get_next_timeout_evt();
struct ADC_client* client = ADC_client_create(nick, description, c);
c->client = client;
c->timer = (struct timeout_evt*) hub_malloc(sizeof(struct timeout_evt));
timeout_evt_initialize(c->timer, timer_callback, c);
timeout_queue_insert(net_backend_get_timeout_queue(), c->timer, timeout);
bot_output(client, LVL_VERBOSE, "Initial timeout: %d seconds", timeout);
c->logged_in = 0;
ADC_client_set_callback(client, handle);
ADC_client_connect(client, cfg_uri);
strcat(buf, "\n");
ADC_client_send(client, buf);
}
static void perf_normal_action(struct ADC_client* client)
{
struct AdcFuzzUser* user = (struct AdcFuzzUser*) ADC_client_get_ptr(client);
size_t r = get_wait_rand(5);
size_t p = get_wait_rand(100);
switch (r)
{
case 0:
// if (p > (90 - (10 * cfg_level)))
if (p > (90 - (10 * cfg_level)))
{
struct ADC_client* c;
char* nick = hub_strdup(ADC_client_get_nick(client));
char* desc = hub_strdup(ADC_client_get_description(client));
bot_output(client, LVL_VERBOSE, "timeout -> disconnect");
client_disconnect(user);
client_connect(user, nick, desc);
hub_free(nick);
hub_free(desc);
ADC_client_disconnect(client);
}
break;
@@ -292,43 +236,37 @@ static void perf_normal_action(struct ADC_client* client)
if (cfg_chat)
{
bot_output(client, LVL_VERBOSE, "timeout -> chat");
if (user->logged_in)
perf_chat(client, 0);
perf_chat(client, 0);
}
break;
case 2:
bot_output(client, LVL_VERBOSE, "timeout -> search");
if (user->logged_in)
perf_search(client);
perf_search(client);
break;
case 3:
bot_output(client, LVL_VERBOSE, "timeout -> update");
if (user->logged_in)
perf_update(client);
perf_update(client);
break;
case 4:
bot_output(client, LVL_VERBOSE, "timeout -> privmsg");
if (user->logged_in)
perf_chat(client, 1);
perf_chat(client, 1);
break;
case 5:
bot_output(client, LVL_VERBOSE, "timeout -> ctm/rcm");
if (user->logged_in)
perf_ctm(client);
perf_ctm(client);
break;
}
}
#endif
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data)
{
struct AdcFuzzUser* user = (struct AdcFuzzUser*) ADC_client_get_ptr(client);
switch (type)
{
case ADC_CLIENT_CONNECTING:
@@ -336,7 +274,7 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
break;
case ADC_CLIENT_CONNECTED:
// bot_output(client, LVL_DEBUG, "*** Connected.");
bot_output(client, LVL_DEBUG, "*** Connected.");
break;
case ADC_CLIENT_DISCONNECTED:
@@ -344,40 +282,38 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
break;
case ADC_CLIENT_LOGGING_IN:
// bot_output(client, LVL_DEBUG, "*** Logging in...");
bot_output(client, LVL_DEBUG, "*** Logging in...");
break;
case ADC_CLIENT_PASSWORD_REQ:
//bot_output(client, LVL_DEBUG, "*** Requesting password.");
break;
bot_output(client, LVL_DEBUG, "*** Requesting password.");
case ADC_CLIENT_LOGGED_IN:
bot_output(client, LVL_DEBUG, "*** Logged in.");
user->logged_in = 1;
break;
case ADC_CLIENT_LOGIN_ERROR:
bot_output(client, LVL_DEBUG, "*** Login error");
break;
case ADC_CLIENT_SSL_HANDSHAKE:
case ADC_CLIENT_SSL_OK:
break;
case ADC_CLIENT_MESSAGE:
// bot_output(client, LVL_DEBUG, " <%s> %s", sid_to_string(data->chat->from_sid), data->chat->message);
bot_output(client, LVL_DEBUG, " <%s> %s", sid_to_string(data->chat->from_sid), data->chat->message);
break;
case ADC_CLIENT_USER_JOIN:
bot_output(client, LVL_VERBOSE, " JOIN: %s", data->user->name);
break;
case ADC_CLIENT_USER_QUIT:
bot_output(client, LVL_VERBOSE, " QUIT");
break;
case ADC_CLIENT_SEARCH_REQ:
break;
case ADC_CLIENT_HUB_INFO:
bot_output(client, LVL_DEBUG, " Hub: \"%s\" [%s]\n"
" \"%s\"\n", data->hubinfo->name, data->hubinfo->version, data->hubinfo->description);
break;
default:
@@ -388,78 +324,40 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
return 1;
}
static void timer_callback(struct timeout_evt* t)
{
size_t timeout = get_next_timeout_evt();
struct AdcFuzzUser* client = (struct AdcFuzzUser*) t->ptr;
if (client->logged_in)
{
perf_normal_action(client->client);
bot_output(client->client, LVL_VERBOSE, "Next timeout: %d seconds", (int) timeout);
}
timeout_queue_reschedule(net_backend_get_timeout_queue(), client->timer, timeout);
}
static struct AdcFuzzUser client[ADC_MAX_CLIENTS];
void p_status()
{
static char rxbuf[64] = { "0 B" };
static char txbuf[64] = { "0 B" };
int logged_in = 0;
size_t n;
static size_t rx = 0, tx = 0;
for (n = 0; n < cfg_clients; n++)
{
if (client[n].logged_in)
logged_in++;
}
if (difftime(time(NULL), stats_intermediate->timestamp) >= cfg_netstats_interval)
{
net_stats_get(&stats_intermediate, &stats_total);
rx = stats_intermediate->rx / cfg_netstats_interval;
tx = stats_intermediate->tx / cfg_netstats_interval;
net_stats_reset();
format_size(rx, rxbuf, sizeof(rxbuf));
format_size(tx, txbuf, sizeof(txbuf));
}
n = blank;
blank = printf("Connected bots: %d/%d, network: rx=%s/s, tx=%s/s", logged_in, cfg_clients, rxbuf, txbuf);
if (n > blank)
do_blank(n-blank);
printf("\r");
}
void runloop(size_t clients)
{
size_t n = 0;
blank = 0;
struct ADC_client* client[ADC_MAX_CLIENTS];
for (n = 0; n < clients; n++)
{
struct ADC_client* c = malloc(sizeof(struct ADC_client));
client[n] = c;
char nick[20];
snprintf(nick, 20, "adcrush_%d", (int) n);
client_connect(&client[n], nick, "stresstester");
ADC_client_create(c, nick, "stresstester");
ADC_client_set_callback(c, handle);
ADC_client_connect(c, cfg_uri);
}
while (running && net_backend_process())
while (net_backend_process())
{
p_status();
}
for (n = 0; n < clients; n++)
{
struct AdcFuzzUser* c = &client[n];
client_disconnect(c);
ADC_client_destroy(client[n]);
free(client[n]);
client[n] = 0;
}
}
static void print_version()
{
printf(ADCRUSH "\n");
printf("Copyright (C) 2008-2012, Jan Vidar Krey\n");
printf("Copyright (C) 2008-2009, Jan Vidar Krey\n");
printf("\n");
}
@@ -476,7 +374,6 @@ static void print_usage(const char* program)
printf(" -c Allow broadcasting chat messages.\n");
printf(" -d Enable debug output.\n");
printf(" -q Quiet mode (no output).\n");
printf(" -i <num> Average network statistics for given interval (default: 3)\n");
printf("\n");
exit(0);
@@ -510,10 +407,6 @@ int parse_arguments(int argc, char** argv)
{
cfg_level = MIN(MAX(uhub_atoi(argv[opt]), 0), 3);
}
else if (!strcmp(argv[opt], "-i") && (++opt) < argc)
{
cfg_netstats_interval = MAX(uhub_atoi(argv[opt]), 1);
}
else if (!strcmp(argv[opt], "-n") && (++opt) < argc)
{
cfg_clients = MIN(MAX(uhub_atoi(argv[opt]), 1), ADC_MAX_CLIENTS);
@@ -535,15 +428,13 @@ void parse_command_line(int argc, char** argv)
int main(int argc, char** argv)
{
parse_command_line(argc, argv);
net_initialize();
net_stats_get(&stats_intermediate, &stats_total);
hub_log_initialize(NULL, 0);
hub_set_log_verbosity(1000);
setvbuf(stdout, NULL, _IONBF, 0);
runloop(cfg_clients);
net_destroy();

View File

@@ -35,6 +35,7 @@ static struct ADC_user* user_get(sid_t sid)
return user;
}
static void user_remove(const struct ADC_client_quit_reason* quit)
{
struct ADC_user* user = user_get(quit->sid);
@@ -90,10 +91,6 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
{
switch (type)
{
case ADC_CLIENT_NAME_LOOKUP:
status("Looking up hostname...");
break;
case ADC_CLIENT_CONNECTING:
status("Connecting...");
break;
@@ -110,9 +107,6 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
status("SSL handshake.");
break;
case ADC_CLIENT_SSL_OK:
break;
case ADC_CLIENT_LOGGING_IN:
status("Logging in...");
break;
@@ -161,68 +155,6 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
static int running = 1;
#if !defined(WIN32)
void adm_handle_signal(int sig)
{
switch (sig)
{
case SIGINT:
LOG_INFO("Interrupted. Shutting down...");
running = 0;
break;
case SIGTERM:
LOG_INFO("Terminated. Shutting down...");
running = 0;
break;
case SIGPIPE:
break;
case SIGHUP:
break;
default:
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
running = 0;
break;
}
}
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
SIGPIPE, /* prevent sigpipe from kills the application */
SIGHUP, /* reload configuration */
0
};
void adm_setup_signal_handlers()
{
sigset_t sig_set;
struct sigaction act;
int i;
sigemptyset(&sig_set);
act.sa_mask = sig_set;
act.sa_flags = SA_ONSTACK | SA_RESTART;
act.sa_handler = adm_handle_signal;
for (i = 0; signals[i]; i++)
{
if (sigaction(signals[i], &act, 0) != 0)
{
LOG_ERROR("Error setting signal handler %d", signals[i]);
}
}
}
void adm_shutdown_signal_handlers()
{
}
#endif /* !WIN32 */
int main(int argc, char** argv)
{
if (argc < 2)
@@ -231,23 +163,19 @@ int main(int argc, char** argv)
return 1;
}
hub_set_log_verbosity(5);
adm_setup_signal_handlers();
struct ADC_client* client;
struct ADC_client client;
net_initialize();
memset(g_usermap, 0, sizeof(g_usermap));
client = ADC_client_create("uhub-admin", "stresstester", NULL);
ADC_client_set_callback(client, handle);
ADC_client_connect(client, argv[1]);
ADC_client_create(&client, "uhub-admin", "stresstester");
ADC_client_set_callback(&client, handle);
ADC_client_connect(&client, argv[1]);
while (running && net_backend_process()) { }
ADC_client_destroy(client);
ADC_client_destroy(&client);
net_destroy();
adm_shutdown_signal_handlers();
return 0;
}

View File

@@ -41,7 +41,7 @@
#define TIMEOUT_CONNECTED 15
#define TIMEOUT_HANDSHAKE 30
#define TIMEOUT_SENDQ 120
#define TIMEOUT_STATS 10
#define TIMEOUT_STATS 60
#define MAX_CID_LEN 39
#define MAX_NICK_LEN 64
@@ -63,20 +63,18 @@ extern "C" {
#include "util/credentials.h"
#include "util/floodctl.h"
#include "util/getopt.h"
#include "util/ipcalc.h"
#include "util/list.h"
#include "util/log.h"
#include "util/memory.h"
#include "util/misc.h"
#include "util/tiger.h"
#include "util/threads.h"
#include "adc/sid.h"
#include "adc/message.h"
#include "network/network.h"
#include "network/connection.h"
#include "network/dnsresolver.h"
#include "network/ipcalc.h"
#include "network/timeout.h"
#include "core/auth.h"

View File

@@ -36,7 +36,6 @@ extern struct cbuffer* cbuf_create(size_t capacity)
buf->size = 0;
buf->flags = 0;
buf->buf = hub_malloc(capacity + 1);
buf->buf[0] = '\0';
return buf;
}

View File

@@ -305,27 +305,6 @@ int is_number(const char* value, int* num)
}
const char* format_size(size_t bytes, char* buf, size_t bufsize)
{
static const char* quant[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" };
size_t b = bytes;
size_t factor = 0;
size_t divisor = 1;
while (b > 1024)
{
factor++;
b = (b >> 10);
divisor = (divisor << 10);
}
uhub_assert(factor < (sizeof(quant) / sizeof(const char*)));
if (factor >= 2)
snprintf(buf, bufsize, "%.1f %s", (double) bytes / (double) divisor, quant[factor]);
else
snprintf(buf, bufsize, PRINTF_SIZE_T " %s", bytes / divisor, quant[factor]);
return buf;
}
const char* uhub_itoa(int val)
{
static char buf[22];

View File

@@ -42,19 +42,6 @@ extern char* strip_off_quotes(char* line);
*/
extern int is_number(const char* str, int* num);
/**
* Convert the 'bytes' number into a formatted byte size string.
* E.g. "129012" becomes "125.99 KB".
* Note, if the output buffer is not large enough then the output
* will be truncated. The buffer will always be \0 terminated.
*
* @param bytes the number that should be formatted.
* @param[out] buf the buffer the string should be formatted into
* @param bufsize the size of 'buf'
* @return A pointer to buf.
*/
extern const char* format_size(size_t bytes, char* buf, size_t bufsize);
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
/**

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2009, 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
@@ -17,141 +17,84 @@
*
*/
#include "uhub.h"
#if 0
#include <sys/types.h>
#include "rbtree.h"
// #define RB_TREE_CHECKS
#define RED 0
#define BLACK 1
struct rb_node
{
const void* key;
const void* value; /* data */
int color;
struct rb_node* parent;
struct rb_node* left;
struct rb_node* right;
};
struct rb_tree
{
struct rb_node* root;
size_t elements;
rb_tree_alloc alloc;
rb_tree_free free;
rb_tree_compare compare;
};
/* returns the grandparent of a node, if it exits */
static inline struct rb_node* get_grandparent(struct rb_node* n)
{
if (n->parent)
return n->parent->parent;
return 0;
}
static struct rb_node* get_uncle(struct rb_node* n)
{
struct rb_node* gparent = n->parent ? n->parent->parent : 0;
if (gparent)
return (n->parent == gparent->left) ? gparent->right : gparent->left;
return 0;
}
static struct rb_node* tree_search(struct rb_tree* tree, const void* key)
{
struct rb_node* node = tree->root;
while (node)
{
int res = tree->compare(node->key, key);
if (!res)
break;
node = node->link[res < 0];
int res = tree->compare(key, node->key);
if (res < 0) node = node->left;
else if (res > 0) node = node->right;
else return node;
}
return node;
return 0;
}
static struct rb_node* create_node(struct rb_tree* tree, const void* key, const void* value)
static struct rb_node* tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
struct rb_node* node = tree->alloc(sizeof(struct rb_node));
node->key = key;
node->value = value;
node->red = 1;
node->link[0] = 0;
node->link[1] = 0;
return node;
}
struct rb_node* node = tree->root;
struct rb_node* newnode = tree->alloc(sizeof(struct rb_node));
newnode->key = key;
newnode->value = value;
newnode->color = RED;
static int is_red(struct rb_node* node)
{
return node && node->red;
}
#ifdef RB_TREE_CHECKS
int rb_tree_check(struct rb_tree* tree, struct rb_node* node)
{
int lh, rh;
if (node == NULL)
return 1;
else
while (node)
{
struct rb_node *ln = node->link[0];
struct rb_node *rn = node->link[1];
/* Consecutive red links */
if (is_red(node)) {
if (is_red(ln) || is_red(rn))
{
puts("Red violation");
return 0;
}
}
lh = rb_tree_check(tree, ln);
rh = rb_tree_check(tree, rn);
/* Invalid binary search tree - not sorted correctly */
if ((ln && tree->compare(ln->key, node->key) >= 0) || (rn && tree->compare(rn->key, node->key) <= 0))
{
puts("Binary tree violation");
return 0;
}
/* Black height mismatch */
if ( lh != 0 && rh != 0 && lh != rh ) {
puts ( "Black violation" );
return 0;
}
/* Only count black links */
if (lh != 0 && rh != 0)
return is_red(node) ? lh : lh + 1;
int res = tree->compare(key, node->key);
if (res < 0) node = node->left;
else if (res > 0) node = node->right;
else
return 0;
}
}
#endif // RB_TREE_CHECKS
static struct rb_node* rb_tree_rotate_single(struct rb_node* node, int dir)
{
struct rb_node* other = node->link[!dir];
node->link[!dir] = other->link[dir];
other->link[dir] = node;
node->red = 1;
other->red = 0;
return other;
}
static struct rb_node* rb_tree_rotate_double(struct rb_node* node, int dir)
{
node->link[!dir] = rb_tree_rotate_single(node->link[!dir], !dir);
return rb_tree_rotate_single(node, dir);
}
static struct rb_node* rb_tree_insert_r(struct rb_tree* tree, struct rb_node* node, const void* key, const void* value)
{
int res;
if (!node)
return create_node(tree, key, value);
res = tree->compare(node->key, key);
if (!res)
{
puts("Node already exists!");
return NULL;
}
else
{
int dir = res < 0;
node->link[dir] = rb_tree_insert_r(tree, node->link[dir], key, value);
if (is_red(node->link[dir]))
{
if (is_red(node->link[!dir]))
{
/* Case 1 */
node->red = 1;
node->link[0]->red = 0;
node->link[1]->red = 0;
}
else
{
/* Cases 2 & 3 */
if (is_red(node->link[dir]->link[dir]))
node = rb_tree_rotate_single(node, !dir);
else if (is_red(node->link[dir]->link[!dir]))
node = rb_tree_rotate_double(node, !dir);
}
/* key already exists in tree */
return node;
}
}
return node;
return newnode;
}
@@ -159,224 +102,36 @@ struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc a, rb_tree
{
struct rb_tree* tree = a(sizeof(struct rb_tree));
tree->compare = compare;
tree->alloc = a ? a : hub_malloc;
tree->free = f ? f : hub_free;
tree->root = NULL;
tree->elements = 0;
tree->iterator.node = NULL;
tree->iterator.stack = list_create();
tree->alloc = a;
tree->free = f;
return tree;
}
void rb_tree_destroy(struct rb_tree* tree)
{
list_destroy(tree->iterator.stack);
tree->free(tree);
rb_tree_free f = tree->free;
f(tree);
}
int rb_tree_insert(struct rb_tree* tree, const void* key, const void* value)
void* rb_tree_insert(struct rb_tree* tree, const void* key, const void* value)
{
struct rb_node* node;
if (tree_search(tree, key))
return 0;
node = rb_tree_insert_r(tree, tree->root, key, value);
tree->root = node;
tree->root->red = 0;
tree->elements++;
#ifdef RB_TREE_CHECKS
rb_tree_check(tree, node);
#endif
return 1;
struct rb_node* node = tree_insert(tree, key, value);
if (node)
return (void*) node->value;
return 0;
}
void null_node_free(struct rb_node* n) { }
int rb_tree_remove(struct rb_tree* tree, const void* key)
void* rb_tree_remove(struct rb_tree* tree, const void* key)
{
return rb_tree_remove_node(tree, key, &null_node_free);
}
int rb_tree_remove_node(struct rb_tree* tree, const void* key, rb_tree_free_node freecb)
{
struct rb_node head = {0}; /* False tree root */
struct rb_node *q, *p, *g; /* Helpers */
struct rb_node *f = NULL; /* Found item */
int dir = 1;
if (!tree->root)
return 0;
/* Set up helpers */
q = &head;
g = p = NULL;
q->link[1] = tree->root;
/* Search and push a red down */
while (q->link[dir])
{
int last = dir;
int res;
/* Update helpers */
g = p, p = q;
q = q->link[dir];
res = tree->compare(q->key, key);
dir = res < 0;
/* Save found node */
if (!res)
f = q;
/* Push the red node down */
if (!is_red(q) && !is_red(q->link[dir]))
{
if (is_red(q->link[!dir]))
p = p->link[last] = rb_tree_rotate_single(q, dir);
else if (!is_red(q->link[!dir]))
{
struct rb_node* s = p->link[!last];
if (s)
{
if (!is_red(s->link[!last]) && !is_red (s->link[last]))
{
/* Color flip */
p->red = 0;
s->red = 1;
q->red = 1;
}
else
{
int dir2 = g->link[1] == p;
if (is_red(s->link[last]))
g->link[dir2] = rb_tree_rotate_double(p, last);
else if (is_red(s->link[!last]))
g->link[dir2] = rb_tree_rotate_single(p, last);
/* Ensure correct coloring */
q->red = g->link[dir2]->red = 1;
g->link[dir2]->link[0]->red = 0;
g->link[dir2]->link[1]->red = 0;
}
}
}
}
}
/* Replace and remove if found */
if (f)
{
freecb(f);
f->key = q->key;
f->value = q->value;
p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
tree->free(q);
tree->elements--;
}
/* Update root and make it black */
tree->root = head.link[1];
if (tree->root != NULL)
tree->root->red = 0;
#ifdef RB_TREE_CHECKS
rb_tree_check(tree, tree->root);
#endif
return f != NULL;
}
void* rb_tree_get(struct rb_tree* tree, const void* key)
{
struct rb_node* node = tree_search(tree, key);
if (node)
return (void*) node->value;
return node->value;
return 0;
}
size_t rb_tree_size(struct rb_tree* tree)
{
return tree->elements;
}
static void push(struct rb_tree* tree, struct rb_node* n)
{
list_append(tree->iterator.stack, n);
}
static struct rb_node* pop(struct rb_tree* tree)
{
struct rb_node* n = list_get_last(tree->iterator.stack);
if (n)
list_remove(tree->iterator.stack, n);
return n;
}
static struct rb_node* rb_it_set(struct rb_tree* tree, struct rb_node* n)
{
tree->iterator.node = n;
return n;
}
static void null_free(void* ptr) { }
struct rb_node* rb_tree_first(struct rb_tree* tree)
{
struct rb_node* n = tree->root;
list_clear(tree->iterator.stack, &null_free);
while (n->link[0])
{
push(tree, n);
n = n->link[0];
}
return rb_it_set(tree, n);
};
static struct rb_node* rb_tree_traverse(struct rb_tree* tree, int dir)
{
struct rb_node* n = tree->iterator.node;
struct rb_node* p; /* parent */
if (n->link[dir])
{
push(tree, n);
n = n->link[dir];
while (n->link[!dir])
{
list_append(tree->iterator.stack, n);
n = n->link[!dir];
}
return rb_it_set(tree, n);
}
// Need to walk upwards to the parent node.
p = pop(tree);
if (p)
{
// walk up in opposite direction
if (p->link[!dir] == n)
return rb_it_set(tree, p);
// walk up in hte current direction
while (p->link[dir] == n)
{
n = p;
p = pop(tree);
if (!p)
return rb_it_set(tree, NULL);
}
return rb_it_set(tree, p);
}
return rb_it_set(tree, NULL);
}
struct rb_node* rb_tree_next(struct rb_tree* tree)
{
return rb_tree_traverse(tree, 1);
}
struct rb_node* rb_tree_prev(struct rb_tree* tree)
{
return rb_tree_traverse(tree, 0);
}
#endif

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2009, 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
@@ -20,121 +20,18 @@
#ifndef HAVE_UHUB_RED_BLACK_TREE_H
#define HAVE_UHUB_RED_BLACK_TREE_H
struct rb_node
{
const void* key;
const void* value; /* data */
int red;
struct rb_node* link[2];
};
struct rb_tree;
typedef int (*rb_tree_compare)(const void* a, const void* b);
typedef void* (*rb_tree_alloc)(size_t);
typedef void (*rb_tree_free)(void*);
typedef void (*rb_tree_free_node)(struct rb_node*);
struct rb_iterator
{
struct rb_node* node; // current node.
struct linked_list* stack; // stack from the top -- needed since we don't have parent pointers.
};
struct rb_tree
{
struct rb_node* root;
size_t elements;
rb_tree_alloc alloc;
rb_tree_free free;
rb_tree_compare compare;
struct rb_iterator iterator;
};
/**
* Create a tree.
*
* @param compare Comparison function
* @param alloc Allocator (if NULL then hub_malloc() is used)
* @param dealloc Deallocator (if NULL then hub_free() is used)
* @return a tree handle.
*/
extern struct rb_tree* rb_tree_create(rb_tree_compare compare, rb_tree_alloc alloc, rb_tree_free dealloc);
/**
* Deletes the tree and all the nodes.
* But not the content inside the nodes.
*/
extern struct rb_tree* rb_tree_create(rb_tree_compare, rb_tree_alloc, rb_tree_free);
extern void rb_tree_destroy(struct rb_tree*);
/**
* Insert a key into the tree, returns 1 if successful,
* or 0 if the key already existed.
*/
extern int rb_tree_insert(struct rb_tree* tree, const void* key, const void* data);
/**
* Remove a key from the tree.
* Returns 1 if the node was removed, or 0 if it was not removed (i.e. not found!)
*
* NOTE: the content of the node is not freed if it needs to be then use rb_tree_remove_node
* where you can specify a callback cleanup function.
*/
extern int rb_tree_remove(struct rb_tree* tree, const void* key);
/**
* Remove the node, but call the free callback before the node is removed.
* This is useful in cases where you need to deallocate the key and/or value from the node.
* Returns 1 if the node was removed, or 0 if not found.
*/
extern int rb_tree_remove_node(struct rb_tree* tree, const void* key, rb_tree_free_node free);
/**
* Returns NULL if the key was not found in the tree.
*/
extern void* rb_tree_get(struct rb_tree* tree, const void* key);
/**
* Returns the number of elements inside the tree.
*/
extern size_t rb_tree_size(struct rb_tree* tree);
/**
* Returns the first node in the tree.
* (leftmost, or lowest value in sorted order).
*
* Example:
*
* <code>
* struct rb_node* it;
* for (it = rb_tree_first(tree); it; it = rb_tree_next())
* {
* void* key = rb_iterator_key(it);
* void* value = rb_iterator_value(it);
* }
* </code>
*/
extern struct rb_node* rb_tree_first(struct rb_tree* tree);
/**
* Points the iterator at the next node.
* If the next node is NULL then the iterator becomes NULL too.
*/
extern struct rb_node* rb_tree_next(struct rb_tree* tree);
extern struct rb_node* rb_tree_prev(struct rb_tree* tree);
/**
* Returnst the key of the node pointed to by the iterator.
* If this iterator is the same as rb_tree_end() then NULL is returned.
*/
extern void* rb_iterator_key(struct rb_iterator* it);
/**
* Returnst the value of the node pointed to by the iterator.
* If this iterator is the same as rb_tree_end() then the behavior is undefined.
*/
extern void* rb_iterator_value(struct rb_iterator* it);
extern void* rb_tree_insert(struct rb_tree* tree, const void* key, const void* data);
extern void* rb_tree_remove(struct rb_tree* tree, const void* key);
extern void* rb_tree_get(struct rb_tree* tree, const void* key);
#endif /* HAVE_UHUB_RED_BLACK_TREE_H */

View File

@@ -1,149 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef POSIX_THREAD_SUPPORT
struct pthread_data
{
pthread_t handle;
};
void uhub_mutex_init(uhub_mutex_t* mutex)
{
pthread_mutex_init(mutex, NULL);
}
void uhub_mutex_destroy(uhub_mutex_t* mutex)
{
pthread_mutex_destroy(mutex);
}
void uhub_mutex_lock(uhub_mutex_t* mutex)
{
pthread_mutex_lock(mutex);
}
void uhub_mutex_unlock(uhub_mutex_t* mutex)
{
pthread_mutex_unlock(mutex);
}
int uhub_mutex_trylock(uhub_mutex_t* mutex)
{
int ret = pthread_mutex_trylock(mutex);
return (ret == 0);
}
uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg)
{
struct pthread_data* thread = (struct pthread_data*) hub_malloc_zero(sizeof(struct pthread_data));
int ret = pthread_create(&thread->handle, NULL, start, arg);
if (ret != 0)
{
hub_free(thread);
thread = NULL;
}
return thread;
}
void uhub_thread_cancel(uhub_thread_t* thread)
{
pthread_cancel(thread->handle);
}
void* uhub_thread_join(uhub_thread_t* thread)
{
void* ret = NULL;
pthread_join(thread->handle, &ret);
hub_free(thread);
return ret;
}
#endif /* POSIX_THREAD_SUPPORT */
#ifdef WINTHREAD_SUPPORT
struct winthread_data
{
uhub_thread_t* handle;
uhub_thread_start start;
void* arg;
};
static DWORD WINAPI uhub_winthread_start(void* ptr)
{
struct winthread_data* data = (struct winthread_data*) ptr;
DWORD ret = (DWORD) data->start(data->arg);
return ret;
}
void uhub_mutex_init(uhub_mutex_t* mutex)
{
InitializeCriticalSection(mutex);
}
void uhub_mutex_destroy(uhub_mutex_t* mutex)
{
DeleteCriticalSection(mutex);
}
void uhub_mutex_lock(uhub_mutex_t* mutex)
{
EnterCriticalSection(mutex);
}
void uhub_mutex_unlock(uhub_mutex_t* mutex)
{
LeaveCriticalSection(mutex);
}
int uhub_mutex_trylock(uhub_mutex_t* mutex)
{
return TryEnterCriticalSection(mutex);
}
uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg)
{
struct winthread_data* thread = (struct winthread_data*) hub_malloc_zero(sizeof(struct winthread_data));
thread->start = start;
thread->arg = arg;
thread->handle = CreateThread(NULL, 0, uhub_winthread_start, thread, 0, 0);
return thread;
}
void uhub_thread_cancel(uhub_thread_t* thread)
{
TerminateThread(thread->handle, 0);
}
void* uhub_thread_join(uhub_thread_t* thread)
{
void* ret = NULL;
DWORD exitCode;
WaitForSingleObject(thread->handle, INFINITE);
GetExitCodeThread(thread->handle, &exitCode);
ret = &exitCode;
CloseHandle(thread->handle);
hub_free(thread);
return ret;
}
#endif /* WINTHREAD_SUPPORT */

View File

@@ -1,49 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_UTIL_THREADS_H
#define HAVE_UHUB_UTIL_THREADS_H
typedef void*(*uhub_thread_start)(void*) ;
#ifdef POSIX_THREAD_SUPPORT
typedef struct pthread_data uhub_thread_t;
typedef pthread_mutex_t uhub_mutex_t;
#endif
#ifdef WINTHREAD_SUPPORT
struct winthread_data;
typedef struct winthread_data uhub_thread_t;
typedef CRITICAL_SECTION uhub_mutex_t;
#endif
// Mutexes
extern void uhub_mutex_init(uhub_mutex_t* mutex);
extern void uhub_mutex_destroy(uhub_mutex_t* mutex);
extern void uhub_mutex_lock(uhub_mutex_t* mutex);
extern void uhub_mutex_unlock(uhub_mutex_t* mutex);
extern int uhub_mutex_trylock(uhub_mutex_t* mutex);
// Threads
uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg);
void uhub_thread_cancel(uhub_thread_t* thread);
void* uhub_thread_join(uhub_thread_t* thread);
#endif /* HAVE_UHUB_UTIL_THREADS_H */

View File

@@ -23,12 +23,14 @@
#define VERSION "@UHUB_VERSION_MAJOR@.@UHUB_VERSION_MINOR@.@UHUB_VERSION_PATCH@"
#endif
#define GIT_REVISION "@UHUB_REVISION@"
#define GIT_VERSION "@UHUB_GIT_VERSION@"
#ifndef PRODUCT
#define PRODUCT "uhub"
#endif
#define REVISION GIT_REVISION
#define PRODUCT_STRING PRODUCT "/" GIT_VERSION
#ifndef COPYRIGHT