Compare commits

..

1 Commits

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
158 changed files with 1977 additions and 7806 deletions

View File

@ -1,17 +0,0 @@
kind: pipeline
name: default
steps:
- name: docker
image: plugins/docker
network_mode: bridge
settings:
repo: sneak/uhub
username:
from_secret: docker_username
password:
from_secret: docker_password
tags:
- ${DRONE_BRANCH//\//-}-${DRONE_COMMIT_SHA:0:8}
- ${DRONE_COMMIT_SHA}
- ${DRONE_BRANCH/\//-}

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ debian/uhub.postrm.debhelper
debian/uhub.prerm.debhelper debian/uhub.prerm.debhelper
debian/uhub.substvars debian/uhub.substvars
uhub-passwd uhub-passwd
src/version.h

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "thirdparty/sqlite"] [submodule "thirdparty/sqlite"]
path = thirdparty/sqlite path = thirdparty/sqlite
url = https://github.com/janvidar/sqlite.git url = git://github.com/janvidar/sqlite.git

View File

@ -1,14 +0,0 @@
language: cpp
dist: xenial
compiler:
- gcc
- clang
env:
- CONFIG=minimal
- CONFIG=full
install:
- autotest/travis/install-build-depends.sh
script:
- autotest/travis/build-and-test.sh
dist: xenial

10
AUTHORS
View File

@ -3,9 +3,7 @@ Authors of uhub
Jan Vidar Krey, Design and implementation Jan Vidar Krey, Design and implementation
E_zombie, Centos/RedHat customization scripts and heavy load testing E_zombie, Centos/RedHat customization scripts and heavy load testing
FleetCommand, Hub topic plugin code FleetCommand, Hub topic
MiMic, Implemented user commands, and plugins MiMic, Implemented user commands
Boris Pek (tehnick), Debian/Ubuntu packaging tehnick, Debian and Ubuntu packaging.
Tillmann Karras (Tilka), Misc. bug fixes
Yoran Heling (Yorhel), TLS/SSL handshake detection bugfixes
Blair Bonnett, Misc. bug fixes

3
BUGS
View File

@ -1 +1,2 @@
Bugs are tracked on: https://github.com/janvidar/uhub/issues Bugs are tracked on: http://bugs.extatic.org/

View File

@ -1,246 +1,170 @@
## ##
## Makefile for uhub ## Makefile for uhub
## Copyright (C) 2007-2013, Jan Vidar Krey <janvidar@extatic.org> ## Copyright (C) 2007-2012, Jan Vidar Krey <janvidar@extatic.org>
# #
cmake_minimum_required (VERSION 2.8.2) cmake_minimum_required (VERSION 2.8.3)
project (uhub NONE) project (uhub)
enable_language(C)
set (UHUB_VERSION_MAJOR 0) set (UHUB_VERSION_MAJOR 0)
set (UHUB_VERSION_MINOR 5) set (UHUB_VERSION_MINOR 4)
set (UHUB_VERSION_PATCH 1) set (UHUB_VERSION_PATCH 1)
set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src") set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src")
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/Modules)
option(RELEASE "Release build, debug build if disabled" ON) option(RELEASE "Release build, debug build if disabled" ON)
option(LOWLEVEL_DEBUG, "Enable low level debug messages." OFF) option(LINK_SUPPORT "Allow hub linking" OFF)
option(SSL_SUPPORT "Enable SSL support" ON) option(SSL_SUPPORT "Enable SSL support" ON)
option(USE_OPENSSL "Use OpenSSL's SSL support" ON ) option(SQLITE_SUPPORT "Enable SQLite support" ON)
option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF)
option(ADC_STRESS "Enable the stress tester client" OFF)
find_package(Git) find_package(Git)
find_package(Sqlite3)
include(TestBigEndian)
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckTypeSize)
#Some functions need this to be found
add_definitions(-D_GNU_SOURCE)
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE")
TEST_BIG_ENDIAN(BIGENDIAN)
if (BIGENDIAN)
add_definitions(-DARCH_BIGENDIAN)
endif()
if (NOT RELEASE)
add_definitions(-DDEBUG)
endif()
if (SSL_SUPPORT) if (SSL_SUPPORT)
if (USE_OPENSSL) find_package(OpenSSL REQUIRED)
find_package(OpenSSL)
else()
find_package(GnuTLS)
endif()
if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND)
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS were found!")
endif()
endif()
if (NOT SQLITE3_FOUND)
message(FATAL_ERROR "SQLite3 is not found!")
endif()
if (SYSTEMD_SUPPORT)
INCLUDE(FindPkgConfig)
pkg_search_module(SD REQUIRED libsystemd)
endif() endif()
if (MSVC) if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif() endif()
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
if (HAVE_SYS_TYPES_H)
set (CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} "sys/types.h")
endif()
check_type_size( ssize_t SSIZE_T )
check_symbol_exists(memmem string.h HAVE_MEMMEM)
check_symbol_exists(strndup string.h HAVE_STRNDUP)
include_directories("${PROJECT_SOURCE_DIR}") include_directories("${PROJECT_SOURCE_DIR}")
include_directories("${PROJECT_BINARY_DIR}")
include_directories(${SQLITE3_INCLUDE_DIRS})
link_directories(${SQLITE3_LIBRARY_DIRS})
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c) set (network_SOURCES
list (REMOVE_ITEM uhub_SOURCES ${PROJECT_SOURCE_DIR}/network/backend.c
${PROJECT_SOURCE_DIR}/core/gen_config.c ${PROJECT_SOURCE_DIR}/network/connection.c
${PROJECT_SOURCE_DIR}/core/main.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) set (uhub_SOURCES
file (GLOB network_SOURCES ${PROJECT_SOURCE_DIR}/network/*.c) ${PROJECT_SOURCE_DIR}/core/auth.c
file (GLOB utils_SOURCES ${PROJECT_SOURCE_DIR}/util/*.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 set (adcclient_SOURCES
${PROJECT_SOURCE_DIR}/tools/adcclient.c ${PROJECT_SOURCE_DIR}/tools/adcclient.c
${PROJECT_SOURCE_DIR}/core/ioqueue.c
) )
add_library(adc STATIC ${adc_SOURCES}) add_library(adc STATIC ${adc_SOURCES})
add_library(network STATIC ${network_SOURCES}) add_library(network STATIC ${network_SOURCES})
add_library(utils STATIC ${utils_SOURCES}) add_library(utils STATIC ${utils_SOURCES})
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set_target_properties(utils PROPERTIES COMPILE_FLAGS -fPIC)
set_target_properties(network PROPERTIES COMPILE_FLAGS -fPIC)
endif()
add_dependencies(adc utils) add_dependencies(adc utils)
add_dependencies(network utils) add_dependencies(network utils)
add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} ) add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} )
add_executable(autotest-bin ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} )
add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c)
add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c) add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c ${utils_SOURCES})
add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c) 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 ${PROJECT_SOURCE_DIR}/adc/sid.c) 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 ) 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 ) add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c ${utils_SOURCES})
add_library(mod_chat_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c ) add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c ${utils_SOURCES})
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 ${utils_SOURCES})
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c) if (SQLITE_SUPPORT)
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c) add_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)
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(mod_logging ws2_32)
target_link_libraries(mod_welcome ws2_32)
endif()
set_target_properties( set_target_properties(
mod_example mod_example
mod_welcome mod_welcome
mod_logging mod_logging
mod_auth_simple mod_auth_simple
mod_auth_sqlite
mod_chat_history mod_chat_history
mod_chat_history_sqlite
mod_chat_only mod_chat_only
mod_no_guest_downloads
mod_topic mod_topic
PROPERTIES PREFIX "") PROPERTIES PREFIX "")
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils) target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils)
target_link_libraries(autotest-bin ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(mod_example utils)
target_link_libraries(mod_welcome network utils)
target_link_libraries(mod_auth_simple utils)
target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils)
target_link_libraries(mod_chat_history utils)
target_link_libraries(mod_chat_history_sqlite ${SQLITE3_LIBRARIES} utils)
target_link_libraries(mod_no_guest_downloads utils)
target_link_libraries(mod_chat_only utils)
target_link_libraries(mod_logging network utils)
target_link_libraries(mod_topic utils)
target_link_libraries(utils network)
if(WIN32)
target_link_libraries(uhub ws2_32)
target_link_libraries(autotest-bin ws2_32)
target_link_libraries(mod_logging ws2_32)
target_link_libraries(mod_welcome ws2_32)
endif()
if(UNIX) if(UNIX)
add_library(adcclient STATIC ${adcclient_SOURCES}) add_library(adcclient STATIC ${adcclient_SOURCES})
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c) add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c ${adcclient_SOURCES})
target_link_libraries(uhub-admin adcclient adc network utils pthread) target_link_libraries(uhub-admin adcclient adc network utils)
target_link_libraries(uhub pthread)
target_link_libraries(autotest-bin 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()
endif() endif()
if (NOT UHUB_REVISION AND GIT_FOUND) if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h OUTPUT_VARIABLE UHUB_REVISION)
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} set (UHUB_GIT_VERSION "${UHUB_VERSION_MAJOR}.${UHUB_VERSION_MINOR}.${UHUB_VERSION_PATCH}-git-${UHUB_REVISION}")
OUTPUT_VARIABLE UHUB_REVISION_TEMP else()
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (UHUB_REVISION_TEMP)
set (UHUB_REVISION "git-${UHUB_REVISION_TEMP}")
endif()
endif() 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) if(OPENSSL_FOUND)
set(SSL_LIBS ${OPENSSL_LIBRARIES}) add_definitions(-DSSL_SUPPORT=1)
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_OPENSSL=1)
include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${OPENSSL_INCLUDE_DIR})
endif() target_link_libraries(uhub ${OPENSSL_LIBRARIES})
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(autotest-bin ${SSL_LIBS})
if(UNIX) if(UNIX)
target_link_libraries(uhub-admin ${SSL_LIBS}) target_link_libraries(uhub-admin ${OPENSSL_LIBRARIES})
endif()
target_link_libraries(mod_welcome ${SSL_LIBS})
target_link_libraries(mod_logging ${SSL_LIBS})
if (ADC_STRESS)
target_link_libraries(adcrush ${SSL_LIBS})
endif() endif()
target_link_libraries(mod_welcome ${OPENSSL_LIBRARIES})
target_link_libraries(mod_logging ${OPENSSL_LIBRARIES})
endif() endif()
if (SYSTEMD_SUPPORT) configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")
target_link_libraries(uhub ${SD_LIBRARIES})
target_link_libraries(autotest-bin ${SD_LIBRARIES})
target_link_libraries(uhub-passwd ${SD_LIBRARIES})
target_link_libraries(uhub-admin ${SD_LIBRARIES})
include_directories(${SD_INCLUDE_DIRS})
add_definitions(-DSYSTEMD)
endif()
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h") mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
configure_file ("${PROJECT_SOURCE_DIR}/system.h.in" "${PROJECT_BINARY_DIR}/system.h") if (RELEASE)
set(CMAKE_BUILD_TYPE Release)
# mark_as_advanced(FORCE CMAKE_BUILD_TYPE) else()
# if (RELEASE) set(CMAKE_BUILD_TYPE Debug)
# set(CMAKE_BUILD_TYPE Release)
# add_definitions(-DNDEBUG)
#else()
# set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG)
#endif()
if (LOWLEVEL_DEBUG)
add_definitions(-DLOWLEVEL_DEBUG)
endif()
if (UNIX)
install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin )
install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL )
install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL )
endif() endif()

View File

@ -1,38 +1,3 @@
0.5.0:
- Use TLS 1.2 and strong ciphers by default, but made this configurable.
- Fix TLS event handling which caused some busy loops
- TLS: Support certificate chains
- Fix bug #211: Better Hublist pinger support by adding the AP flag of the INF message.
- Fix bug #198: Timers could cause infinite loops
- Sqlite3 is now mandatory
- Added mod_chat_history_sqlite and mod_chat_is_privileged.
- Support for systemd notify and journal logging
- Improved flood control counting to strictly not allow more than the given amount of messages in the configured interval.
- Optimize lookups by CID and nick.
- Added an NMDC and ADC hub redirectors written in Python.
- Fix all Clang compile warnings.
- Install uhub-passwd also.
- Add support for detecting HTTP connections to the hub. Enough to tell browsers to stop calling.
- Compile fixes for OpenBSD, including warnings about strcat.
- Fix crashing autotest due to wrong initialization of the usermanager.
- mod_topic: check argument for NULL
- rename !cleartopic to !resettopic
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: 0.4.0:
- Cleaned up code generator for config file parsing. - Cleaned up code generator for config file parsing.
- Merge pull request #5 from yorhel/master - Merge pull request #5 from yorhel/master
@ -47,8 +12,8 @@
- marked plugin callbacks that are not called yet - marked plugin callbacks that are not called yet
- add on_change_nick() to struct plugin_funcs - add on_change_nick() to struct plugin_funcs
- minimal changes - minimal changes
- Updated init script in Debian package. - Updated init script in debian package.
- Updated list of man pages in Debian package. - Updated list of man pages in debian package.
- Added man page for uhub-passwd. - Added man page for uhub-passwd.
- Merge branch 'master' of https://github.com/Tilka/uhub - Merge branch 'master' of https://github.com/Tilka/uhub
- Fix issue with QUI messages being allowed through the hub - Fix issue with QUI messages being allowed through the hub
@ -78,7 +43,7 @@
- minimal documentation fixes - minimal documentation fixes
- update client software link - update client software link
- update compile howto link - update compile howto link
- fix Debian changelog - fix debian changelog
- Fix bug #158 - Added plugin for setting topic (hub description). - Fix bug #158 - Added plugin for setting topic (hub description).
- Command arguments handling + cleanups - Command arguments handling + cleanups

View File

@ -1,19 +0,0 @@
FROM alpine:latest as builder
RUN apk update && apk upgrade && apk add --no-cache bash util-linux cmake make gcc git sqlite-dev openssl-dev git build-base
WORKDIR /app
COPY . .
RUN cmake . && make
RUN sed -i 's/\/usr\/lib\/uhub\//\/libs\//g' ./doc/*.conf && \
sed -i 's/\/usr\/lib\/uhub\//\/libs\//g' ./doc/rules.txt && \
sed -i 's/\/etc\/uhub\//\/conf\//g' ./doc/*.conf && \
sed -i 's/\/etc\/uhub\//\/conf\//g' ./doc/rules.txt && \
echo 'Welcome to uHub' > ./doc/motd.txt
FROM alpine:latest
RUN apk update && apk upgrade && apk add --no-cache bash util-linux openssl-dev sqlite-dev
WORKDIR /app
COPY --from=builder /app/uhub .
COPY --from=builder /app/doc/plugins.conf /app/doc/uhub.conf /app/doc/users.conf /app/doc/rules.txt /app/doc/motd.txt /conf/
COPY --from=builder /app/*.so /libs/
ENTRYPOINT ["./uhub"]
CMD ["-c","/conf/uhub.conf"]

View File

@ -1,13 +1,8 @@
# uhub
Welcome and thanks for downloading uHub, a high performance ADC p2p hub. Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
For the official documentation, bugs and other information, please visit: For the official documentation, bugs and other information, please visit:
https://www.uhub.org/ http://www.uhub.org/
For a list of compatible ADC clients, see: For a list of compatible ADC clients, see:
https://en.wikipedia.org/wiki/Comparison_of_ADC_software#Client_software http://en.wikipedia.org/wiki/Advanced_Direct_Connect#Client_software
# on dockerhub
* https://hub.docker.com/r/sneak/uhub

View File

@ -78,7 +78,7 @@ Description: a high performance hub for the ADC peer-to-peer network
Its low memory footprint allows it to handle several thousand users Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware. on high-end servers, or a small private hub on embedded hardware.
. .
Homepage: https://www.uhub.org/ Homepage: http://www.extatic.org/uhub/
EOF EOF
cd .. cd ..

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,10 +12,11 @@ extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, st
static void inf_create_hub() static void inf_create_hub()
{ {
net_initialize();
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info)); 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();
inf_hub->users->sids = sid_pool_create(500);
inf_hub->users = uman_init();
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle)); inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config)); inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
@ -25,13 +26,15 @@ static void inf_create_hub()
static void inf_destroy_hub() static void inf_destroy_hub()
{ {
uman_shutdown(inf_hub->users); /* FIXME */
list_destroy(inf_hub->users->list);
sid_pool_destroy(inf_hub->users->sids);
acl_shutdown(inf_hub->acl); acl_shutdown(inf_hub->acl);
free_config(inf_hub->config); free_config(inf_hub->config);
hub_free(inf_hub->users);
hub_free(inf_hub->acl); hub_free(inf_hub->acl);
hub_free(inf_hub->config); hub_free(inf_hub->config);
hub_free(inf_hub); hub_free(inf_hub);
net_destroy();
} }
@ -60,14 +63,13 @@ EXO_TEST(inf_create_setup,
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */ /* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
#define CHECK_INF(MSG, EXPECT) \ #define CHECK_INF(MSG, EXPECT) \
do { \ struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
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 */ \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \ adc_msg_free(msg); \
adc_msg_free(msg); \ if (ok == EXPECT) \
if (ok == EXPECT) \ user_set_info(inf_user, 0); \
user_set_info(inf_user, 0); \ return ok == EXPECT;
return ok == EXPECT; \
} while(0)
EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); }); EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
@ -105,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_09, { CHECK_INF("BINF AAAB NIabc NIdef IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_multiple); });
EXO_TEST(inf_nick_10, { EXO_TEST(inf_nick_10, {
const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n"; const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n";
int ok;
char nick[10]; 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; 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); 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); adc_msg_free(msg);
if (ok != status_msg_inf_error_nick_not_utf8) if (ok != status_msg_inf_error_nick_not_utf8)
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok); 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, { EXO_TEST(check_ban_ipv6_1, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return ip_in_range(&addr, &ban6);
}); });
EXO_TEST(check_ban_ipv6_2, { EXO_TEST(check_ban_ipv6_2, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return ip_in_range(&addr, &ban6);
}); });
EXO_TEST(check_ban_ipv6_3, { EXO_TEST(check_ban_ipv6_3, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return ip_in_range(&addr, &ban6);
}); });
EXO_TEST(check_ban_ipv6_4, { EXO_TEST(check_ban_ipv6_4, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return ip_in_range(&addr, &ban6);
}); });
EXO_TEST(check_ban_ipv6_5, { EXO_TEST(check_ban_ipv6_5, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return !ip_in_range(&addr, &ban6);
}); });
EXO_TEST(check_ban_ipv6_6, { EXO_TEST(check_ban_ipv6_6, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return !ip_in_range(&addr, &ban6);
}); });
EXO_TEST(check_ban_afmix_1, { EXO_TEST(check_ban_afmix_1, {
struct ip_addr_encap addr;
if (!ipv6) return 1; 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); return !ip_in_range(&addr, &ban4);
}); });
@ -617,10 +610,8 @@ EXO_TEST(ip_range_3, {
}); });
EXO_TEST(ip_range_4, { EXO_TEST(ip_range_4, {
struct ip_range range1; struct ip_range range1; memset(&range1, 0, sizeof(range1));
struct ip_range range2; struct ip_range range2; memset(&range2, 0, sizeof(range2));
memset(&range1, 0, sizeof(range1));
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; 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

@ -1,16 +1,10 @@
#include <uhub.h> #include <uhub.h>
static struct linked_list* list = NULL; static struct linked_list* list = NULL;
static struct linked_list* list2 = NULL;
static char A[2] = { 'A', 0 }; static char A[2] = { 'A', 0 };
static char B[2] = { 'B', 0 }; static char B[2] = { 'B', 0 };
static char C[2] = { 'C', 0 }; static char C[2] = { 'C', 0 };
static char A2[2] = { 'a', 0 };
static char B2[2] = { 'b', 0 };
static char C2[2] = { 'c', 0 };
static void null_free(void* ptr) static void null_free(void* ptr)
{ {
@ -130,83 +124,6 @@ EXO_TEST(list_clear, {
return list->size == 0 && list->first == 0 && list->last == 0 && list->iterator == 0; return list->size == 0 && list->first == 0 && list->last == 0 && list->iterator == 0;
}); });
static int g_remove_flag = 0;
static void null_free_inc_flag(void* ptr)
{
(void) ptr;
g_remove_flag++;
}
EXO_TEST(list_remove_first_1_1,
{
list_append(list, A);
list_append(list, B);
list_append(list, C);
return list->size == 3;
});
EXO_TEST(list_remove_first_1_2,
{
g_remove_flag = 0;
list_remove_first(list, null_free_inc_flag);
return list->size == 2 && g_remove_flag == 1;
});
EXO_TEST(list_remove_first_1_3,
{
list_remove_first(list, NULL);
return list->size == 1;
});
EXO_TEST(list_remove_first_1_4,
{
list_remove_first(list, NULL);
return list->size == 0;
});
EXO_TEST(list_remove_first_1_5,
{
list_remove_first(list, NULL);
return list->size == 0;
});
EXO_TEST(list_append_list_1,
{
list_append(list, A);
list_append(list, B);
list_append(list, C);
list2 = list_create();
list_append(list2, A2);
list_append(list2, B2);
list_append(list2, C2);
return list->size == 3 && list2->size == 3;
});
EXO_TEST(list_append_list_2,
{
list_append_list(list, list2);
return list->size == 6 && list2->size == 0;
});
EXO_TEST(list_append_list_3,
{
list_destroy(list2);
return list_get_index(list, 0) == A &&
list_get_index(list, 1) == B &&
list_get_index(list, 2) == C &&
list_get_index(list, 3) == A2 &&
list_get_index(list, 4) == B2 &&
list_get_index(list, 5) == C2;
});
EXO_TEST(list_clear_list_last,
{
list_clear(list, &null_free);
return 1;
});
EXO_TEST(list_destroy_1, { EXO_TEST(list_destroy_1, {
list_destroy(list); list_destroy(list);

View File

@ -174,102 +174,91 @@ EXO_TEST(adc_message_parse_24, {
EXO_TEST(adc_message_add_arg_1, { EXO_TEST(adc_message_add_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_add_arg_2, { EXO_TEST(adc_message_add_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_named_argument(msg, "XX", "wtf?"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_remove_arg_1, { EXO_TEST(adc_message_remove_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_remove_arg_2, { EXO_TEST(adc_message_remove_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_remove_arg_3, { EXO_TEST(adc_message_remove_arg_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_remove_arg_4, { EXO_TEST(adc_message_remove_arg_4, {
/* this ensures we can remove the last element also */ /* 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)); struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3));
adc_msg_remove_named_argument(msg, "AW"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_replace_arg_1, { EXO_TEST(adc_message_replace_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_replace_arg_2, { EXO_TEST(adc_message_replace_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_replace_arg_3, { EXO_TEST(adc_message_replace_arg_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC"); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_get_arg_1, { EXO_TEST(adc_message_get_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 0); char* c = adc_msg_get_argument(msg, 0);
ok = strcmp(c, "AAfoo") == 0; int ok = strcmp(c, "AAfoo") == 0;
adc_msg_free(msg); adc_msg_free(msg);
hub_free(c); hub_free(c);
return ok; return ok;
}); });
EXO_TEST(adc_message_get_arg_2, { EXO_TEST(adc_message_get_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 1); char* c = adc_msg_get_argument(msg, 1);
ok = strcmp(c, "BBbar") == 0; int ok = strcmp(c, "BBbar") == 0;
adc_msg_free(msg); adc_msg_free(msg);
hub_free(c); hub_free(c);
return ok; return ok;
@ -351,31 +340,28 @@ EXO_TEST(adc_message_has_named_arg_3, {
}); });
EXO_TEST(adc_message_has_named_arg_4, { EXO_TEST(adc_message_has_named_arg_4, {
int n;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?"); 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); adc_msg_free(msg);
return n == 1; return n == 1;
}); });
EXO_TEST(adc_message_has_named_arg_5, { EXO_TEST(adc_message_has_named_arg_5, {
int n;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone"); adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo"); 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); adc_msg_free(msg);
return n == 2; return n == 2;
}); });
EXO_TEST(adc_message_has_named_arg_6, { EXO_TEST(adc_message_has_named_arg_6, {
int n;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone"); adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo"); adc_msg_add_argument(msg, "XXtwo");
adc_msg_add_argument(msg, "XXthree"); 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); adc_msg_free(msg);
return n == 3; return n == 3;
}); });
@ -388,70 +374,63 @@ EXO_TEST(adc_message_has_named_arg_7, {
}); });
EXO_TEST(adc_message_terminate_1, { EXO_TEST(adc_message_terminate_1, {
int ok;
struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat"); struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat");
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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_terminate_2, { EXO_TEST(adc_message_terminate_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg); 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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_terminate_3, { EXO_TEST(adc_message_terminate_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg); adc_msg_unterminate(msg);
adc_msg_terminate(msg); adc_msg_terminate(msg);
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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_terminate_4, { EXO_TEST(adc_message_terminate_4, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg); adc_msg_unterminate(msg);
adc_msg_terminate(msg); adc_msg_terminate(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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_terminate_5, { EXO_TEST(adc_message_terminate_5, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_terminate(msg); adc_msg_terminate(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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_terminate_6, { EXO_TEST(adc_message_terminate_6, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1); struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg); adc_msg_unterminate(msg);
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); adc_msg_free(msg);
return ok; return ok;
}); });
EXO_TEST(adc_message_escape_1, { EXO_TEST(adc_message_escape_1, {
int ok;
char* s = adc_msg_escape(test_string1); 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); hub_free(s);
return ok; return ok;
}); });

View File

@ -97,82 +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_1, { return is_valid_utf8("abcdefghijklmnopqrstuvwxyz"); });
EXO_TEST(utf8_valid_2, { 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_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 EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
static const char test_utf_seq_2[] = { 0xD8, 0x00 }; // invalid EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
static const char test_utf_seq_3[] = { 0x24, 0x00 }; // valid EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
static const char test_utf_seq_4[] = { 0xC2, 0x24, 0x00}; // invalid EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
static const char test_utf_seq_5[] = { 0xC2, 0xA2, 0x00}; // valid EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
static const char test_utf_seq_6[] = { 0xE2, 0x82, 0xAC, 0x00}; // valid EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
static const char test_utf_seq_7[] = { 0xC2, 0x32, 0x00}; // invalid EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });
static const char test_utf_seq_8[] = { 0xE2, 0x82, 0x32, 0x00}; // invalid
static const char test_utf_seq_9[] = { 0xE2, 0x32, 0x82, 0x00}; // invalid
static const char test_utf_seq_10[] = { 0xF0, 0x9F, 0x98, 0x81, 0x00}; // valid
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_13, { return is_valid_utf8(test_utf_seq_10); });
// Limits of utf-8
static const char test_utf_seq_11[] = { 0x7F, 0x00 }; // valid last 7-bit character
static const char test_utf_seq_12[] = { 0x80, 0x00 }; // invalid truncated string
static const char test_utf_seq_13[] = { 0xBF, 0x00 }; // invalid truncated string
static const char test_utf_seq_14[] = { 0xC0, 0x80, 0x00 }; // invalid out of 2 bytes range
static const char test_utf_seq_15[] = { 0xC1, 0x7F, 0x00 }; // invalid out of 2 bytes range
static const char test_utf_seq_16[] = { 0xC2, 0x00 }; // invalid truncated string
static const char test_utf_seq_17[] = { 0xC2, 0x80, 0x00 }; // valid
static const char test_utf_seq_18[] = { 0xDF, 0xBF, 0x00 }; // valid
static const char test_utf_seq_19[] = { 0xE0, 0x80, 0x80, 0x00 }; // invalid out of 3 bytes range
static const char test_utf_seq_20[] = { 0xE0, 0x9F, 0xBF, 0x00 }; // invalid out of 3 bytes range
static const char test_utf_seq_21[] = { 0xE0, 0x00 }; // invalid truncated string
static const char test_utf_seq_22[] = { 0xE0, 0xA0, 0x00 }; // invalid truncated string
static const char test_utf_seq_23[] = { 0xE0, 0xA0, 0x80, 0x00 }; // valid
static const char test_utf_seq_24[] = { 0xEC, 0x9F, 0xBF, 0x00 }; // valid
static const char test_utf_seq_25[] = { 0xED, 0xA0, 0x80, 0x00 }; // invalid surrogate
static const char test_utf_seq_26[] = { 0xED, 0xBF, 0xBF, 0x00 }; // invalid surrogate
static const char test_utf_seq_27[] = { 0xEF, 0x80, 0x80, 0x00 }; // valid
static const char test_utf_seq_28[] = { 0xEF, 0xBF, 0xBF, 0x00 }; // valid
static const char test_utf_seq_29[] = { 0xF0, 0x80, 0x80, 0x80, 0x00 }; // invalid out of 4 bytes range
static const char test_utf_seq_30[] = { 0xF0, 0x8F, 0xBF, 0xBF, 0x00 }; // invalid out of 4 bytes range
static const char test_utf_seq_31[] = { 0xF0, 0x00 }; // invalid truncated string
static const char test_utf_seq_32[] = { 0xF0, 0x90, 0x00 }; // invalid truncated string
static const char test_utf_seq_33[] = { 0xF0, 0x90, 0x80, 0x00 }; // invalid truncated string
static const char test_utf_seq_34[] = { 0xF0, 0x90, 0x80, 0x80, 0x00 }; // valid
static const char test_utf_seq_35[] = { 0xF4, 0x8F, 0xBF, 0xBF, 0x00 }; // valid
static const char test_utf_seq_36[] = { 0xF4, 0x90, 0x80, 0x80, 0x00 }; // invalid out of 4 bytes range
static const char test_utf_seq_37[] = { 0xFF, 0xBF, 0xBF, 0xBF, 0x00 }; // invalid out of 4 bytes range
EXO_TEST(utf8_valid_14, { return is_valid_utf8(test_utf_seq_11); });
EXO_TEST(utf8_valid_15, { return !is_valid_utf8(test_utf_seq_12); });
EXO_TEST(utf8_valid_16, { return !is_valid_utf8(test_utf_seq_13); });
EXO_TEST(utf8_valid_17, { return !is_valid_utf8(test_utf_seq_14); });
EXO_TEST(utf8_valid_18, { return !is_valid_utf8(test_utf_seq_15); });
EXO_TEST(utf8_valid_19, { return !is_valid_utf8(test_utf_seq_16); });
EXO_TEST(utf8_valid_20, { return is_valid_utf8(test_utf_seq_17); });
EXO_TEST(utf8_valid_21, { return is_valid_utf8(test_utf_seq_18); });
EXO_TEST(utf8_valid_22, { return !is_valid_utf8(test_utf_seq_19); });
EXO_TEST(utf8_valid_23, { return !is_valid_utf8(test_utf_seq_20); });
EXO_TEST(utf8_valid_24, { return !is_valid_utf8(test_utf_seq_21); });
EXO_TEST(utf8_valid_25, { return !is_valid_utf8(test_utf_seq_22); });
EXO_TEST(utf8_valid_26, { return is_valid_utf8(test_utf_seq_23); });
EXO_TEST(utf8_valid_27, { return is_valid_utf8(test_utf_seq_24); });
EXO_TEST(utf8_valid_28, { return !is_valid_utf8(test_utf_seq_25); });
EXO_TEST(utf8_valid_29, { return !is_valid_utf8(test_utf_seq_26); });
EXO_TEST(utf8_valid_30, { return is_valid_utf8(test_utf_seq_27); });
EXO_TEST(utf8_valid_31, { return is_valid_utf8(test_utf_seq_28); });
EXO_TEST(utf8_valid_32, { return !is_valid_utf8(test_utf_seq_29); });
EXO_TEST(utf8_valid_33, { return !is_valid_utf8(test_utf_seq_30); });
EXO_TEST(utf8_valid_34, { return !is_valid_utf8(test_utf_seq_31); });
EXO_TEST(utf8_valid_35, { return !is_valid_utf8(test_utf_seq_32); });
EXO_TEST(utf8_valid_36, { return !is_valid_utf8(test_utf_seq_33); });
EXO_TEST(utf8_valid_37, { return is_valid_utf8(test_utf_seq_34); });
EXO_TEST(utf8_valid_38, { return is_valid_utf8(test_utf_seq_35); });
EXO_TEST(utf8_valid_39, { return !is_valid_utf8(test_utf_seq_36); });
EXO_TEST(utf8_valid_40, { return !is_valid_utf8(test_utf_seq_37); });

View File

@ -1,150 +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)
{
n = (struct rb_node*) rb_tree_next(tree);
i++;
}
return i == MAX_NODES;
});
static int freed_nodes = 0;
static void free_node(struct rb_node* n)
{
hub_free((void*) n->key);
hub_free((void*) n->value);
freed_nodes += 1;
}
EXO_TEST(rbtree_remove_10000, {
int i;
int j;
for (j = 0; j < 2; j++)
{
for (i = j; i < MAX_NODES; i += 2)
{
const char* key = uhub_itoa(i);
rb_tree_remove_node(tree, key, &free_node);
}
}
return freed_nodes == MAX_NODES;
});
EXO_TEST(rbtree_destroy_1, {
rb_tree_destroy(tree);
return 1;
});

View File

@ -117,9 +117,3 @@ EXO_TEST(timer_process_5_events_1,{
g_now = 4; g_now = 4;
return timeout_queue_process(g_queue, g_now) == g_triggered; return timeout_queue_process(g_queue, g_now) == g_triggered;
}); });
EXO_TEST(timer_shutdown,{
timeout_queue_shutdown(g_queue);
hub_free(g_queue);
return 1;
});

View File

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

View File

@ -1,43 +0,0 @@
#!/bin/sh
set -x
set -e
export CFLAGS="$(dpkg-buildflags --get CFLAGS) $(dpkg-buildflags --get CPPFLAGS)"
export LDFLAGS="$(dpkg-buildflags --get LDFLAGS) -Wl,--as-needed"
mkdir -p builddir
cd builddir
CMAKEOPTS="..
-DCMAKE_INSTALL_PREFIX=/usr"
if [ "${CONFIG}" = "full" ]; then
CMAKEOPTS="${CMAKEOPTS}
-DRELEASE=OFF
-DLOWLEVEL_DEBUG=ON
-DSSL_SUPPORT=ON
-DUSE_OPENSSL=ON
-DADC_STRESS=ON"
else
CMAKEOPTS="${CMAKEOPTS}
-DRELEASE=ON
-DLOWLEVEL_DEBUG=OFF
-DSSL_SUPPORT=OFF
-DADC_STRESS=OFF"
fi
cmake ${CMAKEOPTS} \
-DCMAKE_C_FLAGS="${CFLAGS}" \
-DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}"
make VERBOSE=1
make VERBOSE=1 autotest-bin
./autotest-bin
sudo make install
du -shc /etc/uhub/ /usr/bin/uhub* /usr/lib/uhub/

View File

@ -1,10 +0,0 @@
#!/bin/sh
sudo apt-get update -qq
sudo apt-get install -qq cmake
if [ "${CONFIG}" = "full" ]; then
sudo apt-get install -qq libsqlite3-dev libssl-dev
fi

View File

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

View File

@ -1,78 +0,0 @@
# - Try to find sqlite3
# Find sqlite3 headers, libraries and the answer to all questions.
#
# SQLITE3_FOUND True if sqlite3 got found
# SQLITE3_INCLUDEDIR Location of sqlite3 headers
# SQLITE3_LIBRARIES List of libraries to use sqlite3
# SQLITE3_DEFINITIONS Definitions to compile sqlite3
#
# Copyright (c) 2007 Juha Tuomala <tuju@iki.fi>
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
INCLUDE( FindPkgConfig )
# Take care about sqlite3.pc settings
IF ( Sqlite3_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "REQUIRED" )
ELSE ( Sqlite3_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "" )
ENDIF ( Sqlite3_FIND_REQUIRED )
IF ( SQLITE3_MIN_VERSION )
PKG_SEARCH_MODULE( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3>=${SQLITE3_MIN_VERSION} )
ELSE ( SQLITE3_MIN_VERSION )
pkg_search_module( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3 )
ENDIF ( SQLITE3_MIN_VERSION )
# Look for sqlite3 include dir and libraries w/o pkgconfig
IF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND )
FIND_PATH( _sqlite3_include_DIR sqlite3.h
PATHS
/opt/local/include/
/sw/include/
/usr/local/include/
/usr/include/
)
FIND_LIBRARY( _sqlite3_link_DIR sqlite3
PATHS
/opt/local/lib
/sw/lib
/usr/lib
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/usr/local/lib
/usr/lib64
/usr/local/lib64
/opt/lib64
)
IF ( _sqlite3_include_DIR AND _sqlite3_link_DIR )
SET ( _sqlite3_FOUND TRUE )
ENDIF ( _sqlite3_include_DIR AND _sqlite3_link_DIR )
IF ( _sqlite3_FOUND )
SET ( SQLITE3_INCLUDE_DIRS ${_sqlite3_include_DIR} )
SET ( SQLITE3_LIBRARIES ${_sqlite3_link_DIR} )
ENDIF ( _sqlite3_FOUND )
# Report results
IF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
SET( SQLITE3_FOUND 1 )
MESSAGE( STATUS "Found sqlite3: ${SQLITE3_LIBRARIES} ${SQLITE3_INCLUDE_DIRS}" )
ELSE ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
IF ( Sqlite3_FIND_REQUIRED )
MESSAGE( SEND_ERROR "Could NOT find sqlite3" )
ELSE ( Sqlite3_FIND_REQUIRED )
MESSAGE( STATUS "Could NOT find sqlite3" )
ENDIF ( Sqlite3_FIND_REQUIRED )
ENDIF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
ENDIF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND )
# Hide advanced variables from CMake GUIs
MARK_AS_ADVANCED( SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS )

2
debian/control vendored
View File

@ -20,5 +20,5 @@ Description: High performance ADC p2p hub
- Advanced access control support - Advanced access control support
- Easy configuration - Easy configuration
. .
Homepage: https://www.uhub.org/ Homepage: http://www.uhub.org/

2
debian/copyright vendored
View File

@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
On Debian GNU/Linux systems, the complete text of the GNU General Public On Debian GNU/Linux systems, the complete text of the GNU General Public
License can be found in `/usr/share/common-licenses/GPL'. License can be found in `/usr/share/common-licenses/GPL'.

View File

@ -67,7 +67,7 @@ Accepting new users
| | | | | |
| V | | V |
| --------------------- --------------------- | --------------------- ---------------------
| | Send password | ------> | Receive and check | | | Send password | ------> | Reveive and check |
| | request, if needed| | password. | | | request, if needed| | password. |
| --------------------- --------------------- | --------------------- ---------------------
| | | |

View File

@ -1,7 +1,7 @@
How to compile: How to compile:
--------------- ---------------
See the official compiling howto: https://www.uhub.org/compile.php See the official compiling howto: http://www.uhub.org/compile.php
Prerequisites Prerequisites
@ -12,7 +12,7 @@ Before you try to compile µHub, please make sure the following prerequisites ar
* openssl > 0.9.8 (or use "make USE_SSL=NO") * openssl > 0.9.8 (or use "make USE_SSL=NO")
* sqlite > 3.x * sqlite > 3.x
or read https://www.uhub.org/compile.php for more info. or read http://www.uhub.org/compile.php for more info.
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD

View File

@ -28,10 +28,10 @@ The UDP packet SHOULD be echoed by the hub.
This UDP packet should contain simply 'HECH {cid} {token}' (Hub echo). This UDP packet should contain simply 'HECH {cid} {token}' (Hub echo).
The hub should send a packet containing the token back: The hub should send a packet containing the token back:
'IECH {token} {host:port}', as well as the same message via TCP. 'IECH {token} {host:port}', aswell as the same message via TCP.
If the client receives the message via UDP, it should now be able to determine the type of NAT. If the client receives the message via UDP, it should now be able to determine the type of NAT.
If the client receives the message via TCP only it knows it has a firewall blocking incoming communication. If the client receives the message via TCP only it knows it has a firewall blocking incomming communication.
If the client does not receive the message, it should assume a firewall is blocking all UDP communication, If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
and resume in passive mode. and resume in passive mode.

View File

@ -1,6 +1,8 @@
Getting started guide Getting started guide
--------------------- ---------------------
(This document is maintained at http://www.extatic.org/uhub/getstarted.html )
Unpack your binaries Unpack your binaries
Example: Example:
@ -15,7 +17,6 @@ Create configuration files.
If no configuration files are created, uhub will use the default parameters, so you can skip this step if you are in a hurry to see it run. If no configuration files are created, uhub will use the default parameters, so you can skip this step if you are in a hurry to see it run.
As root, or use sudo. As root, or use sudo.
% mkdir /etc/uhub % mkdir /etc/uhub
% cp doc/uhub.conf /etc/uhub % cp doc/uhub.conf /etc/uhub
% cp doc/users.conf /etc/uhub % cp doc/users.conf /etc/uhub
@ -31,11 +32,8 @@ NOTE: It is important to use the "adc://" prefix, and the port number when using
If you modify the configuration files in /etc/uhub you will have to notify uhub by sending a HUP signal. If you modify the configuration files in /etc/uhub you will have to notify uhub by sending a HUP signal.
% ps aux | grep uhub
% kill -HUP <pid of uhub> % kill -HUP <pid of uhub>
Or, for the lazy people Or, for the lazy people
% killall -HUP uhub % killall -HUP uhub
In order to run uhub as a daemon, start it with the -f switch which will make it fork into the background. In order to run uhub as a daemon, start it with the -f switch which will make it fork into the background.
@ -43,25 +41,17 @@ In addition, use the -l to specify a log file instead of stdout. One can also sp
if one wishes to run uhub as a specific user using the -u and -g switches. if one wishes to run uhub as a specific user using the -u and -g switches.
Example: Example:
% uhub -f -l mylog.txt -u nobody -g nogroup % uhub -f -l mylog.txt -u nobody -g nogroup
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed. If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
This limit needs to be higher than the configured max_users in uhub.conf. This limit needs to be higher than the configured max_users in uhub.conf.
In Linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users) In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
* soft nofile 4096 * soft nofile 4096
* hard nofile 4096 * hard nofile 4096
Or, you can use (as root): Or, you can use (as root):
% ulimit -n 4096 % ulimit -n 4096
You can interact with uhub in your hub main chat using the `!` prefix, followed by a command:
Example :
* to display help and the command you can use:
!help
Your mileage may vary -- Good luck! Your mileage may vary -- Good luck!

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# chkconfig: - 91 35 # chkconfig: - 91 35
# description: Starts and stops the Uhub ( https://www.uhub.org ) daemons on RHEL\CentOS \ # description: Starts and stops the Uhub ( http://www.uhub.org ) daemons on RHEL\CentOS \
# used to provide p2p network services. # used to provide p2p network services.
# #
# pidfile: /var/run/uhub.pid # pidfile: /var/run/uhub.pid

View File

@ -11,28 +11,18 @@
# Parameters: # Parameters:
# file: path/filename for database. # 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"
# Topic commands.
# Note: "topic" == "hub description" (as configured in uhub.conf)
#
# !topic - change the topic (op required)
# !showtopic - show the topic
# !resettopic - reset the topic to the default (op required)
#
# This plugins takes no parameters.
#plugin /usr/lib/uhub/mod_topic.so
# Log file writer # Log file writer
# #
# Parameters: # Parameters:
# file: path/filename for log file. # file: path/filename for log file.
# syslog: if true then syslog is used instead of writing to a file (Unix only) # 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 # A simple example plugin
#plugin /usr/lib/uhub/mod_example.so # plugin /var/lib/uhub/mod_example.so
# A plugin sending a welcome message. # A plugin sending a welcome message.
# #
# This plugin provides the following commands: # This plugin provides the following commands:
@ -41,7 +31,7 @@ plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
# #
# Parameters: # Parameters:
# motd: path/filename for the welcome message (message of the day) # motd: path/filename for the welcome message (message of the day)
# rules: path/filename for the rules file # rules: path/filenam for the rules file
# #
# NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted. # NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted.
# #
@ -56,7 +46,7 @@ plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
# %p - 'am' or 'pm' # %p - 'am' or 'pm'
# %M - Minutes (00-59) (Hub local time) # %M - Minutes (00-59) (Hub local time)
# %S - Seconds (00-60) (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. # Load the chat history plugin.
# #
@ -68,4 +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_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_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) # 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

@ -39,4 +39,4 @@ is one of 'admin', 'super', 'op', 'user'
This program was written by Jan Vidar Krey <janvidar@extatic.org> This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS" .SH "BUG REPORTS"
If you find a bug in uhub please report it to If you find a bug in uhub please report it to
.B https://github.com/janvidar/uhub/issues .B http://bugs.extatic.org/

View File

@ -69,4 +69,4 @@ To run uhub as a daemon, and log to a file:
This program was written by Jan Vidar Krey <janvidar@extatic.org> This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS" .SH "BUG REPORTS"
If you find a bug in uhub please report it to If you find a bug in uhub please report it to
.B https://github.com/janvidar/uhub/issues .B http://bugs.extatic.org/

View File

@ -2,10 +2,10 @@
# You should normally place this file in /etc/uhub/uhub.conf # You should normally place this file in /etc/uhub/uhub.conf
# and customize some of the settings below. # and customize some of the settings below.
# #
# This file is read only to the uhub daemon, and if you # This file is read only to the uhub deamon, and if you
# make changes to it while uhub is running you can send a # make changes to it while uhub is running you can send a
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX). # HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
# All configuration directives: https://www.uhub.org/config.php # All configuration directives: http://www.uhub.org/config.php
# Bind to this port and address # Bind to this port and address
# server_bind_addr=any means listen to "::" if IPv6 is supported # server_bind_addr=any means listen to "::" if IPv6 is supported
@ -104,11 +104,11 @@ msg_auth_invalid_password = Password is wrong
msg_auth_user_not_found = User not found in password database msg_auth_user_not_found = User not found in password database
msg_user_share_size_low = User is not sharing enough msg_user_share_size_low = User is not sharing enough
msg_user_share_size_high = User is sharing too much msg_user_share_size_high = User is sharing too much
msg_user_slots_low = User has too few upload slots msg_user_slots_low = User have too few upload slots
msg_user_slots_high = User has too many upload slots msg_user_slots_high = User have too many upload slots
msg_user_hub_limit_low = User is on too few hubs msg_user_hub_limit_low = User is on too few hubs
msg_user_hub_limit_high = User is on too many hubs msg_user_hub_limit_high = User is on too many hubs
msg_error_no_memory = Out of memory msg_error_no_memory = No memory
msg_user_flood_chat = Chat flood detected, messages are dropped. msg_user_flood_chat = Chat flood detected, messages are dropped.
msg_user_flood_connect = Connect flood detected, connection refused. msg_user_flood_connect = Connect flood detected, connection refused.
msg_user_flood_search = Search flood detected, search is stopped. msg_user_flood_search = Search flood detected, search is stopped.

View File

@ -4,7 +4,7 @@
inherit eutils inherit eutils
if [ "$PV" != "9999" ]; then if [ "$PV" != "9999" ]; then
SRC_URI="https://www.extatic.org/downloads/uhub/${P}-src.tar.bz2" SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
KEYWORDS="~amd64 ~x86" KEYWORDS="~amd64 ~x86"
else else
inherit git inherit git
@ -16,7 +16,7 @@ fi
EAPI="2" EAPI="2"
DESCRIPTION="High performance ADC hub" DESCRIPTION="High performance ADC hub"
HOMEPAGE="https://www.uhub.org/" HOMEPAGE="http://www.uhub.org/"
LICENSE="GPL-3" LICENSE="GPL-3"
SLOT="0" SLOT="0"

View File

@ -5,7 +5,7 @@ Release: 2
License: GPLv3 License: GPLv3
Group: Networking/File transfer Group: Networking/File transfer
Source: uhub-%{version}.tar.gz Source: uhub-%{version}.tar.gz
URL: https://www.uhub.org URL: http://www.uhub.org
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: sqlite-devel BuildRequires: sqlite-devel
@ -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/logrotate.d
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1 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 $RPM_BUILD_ROOT/usr/bin/
install uhub-passwd $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/ 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 && /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 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 %files
@ -80,7 +80,7 @@ rm -rf $RPM_BUILD_ROOT
if [ $1 -gt 1 ] ; then if [ $1 -gt 1 ] ; then
/etc/rc.d/init.d/uhub restart >/dev/null || : /etc/rc.d/init.d/uhub restart >/dev/null || :
fi fi
# need more information about add services and users in system # need more informations about add services and users in system
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||: /usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
# write SSL create # write SSL create
echo "PLS see /usr/share/doc/uhub/" echo "PLS see /usr/share/doc/uhub/"

View File

@ -8,7 +8,7 @@ start on filesystem or runlevel [2345]
stop on runlevel [!2345] stop on runlevel [!2345]
# Allow the service to respawn, but if its happening too often # Allow the service to respawn, but if its happening too often
# (10 times in 5 seconds) there's a problem and we should stop trying. # (10 times in 5 seconds) theres a problem and we should stop trying.
respawn respawn
respawn limit 10 5 respawn limit 10 5

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -111,15 +111,12 @@ typedef uint32_t fourcc_t;
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */ #define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
#define ADC_INF_FLAG_NICK "NI" /* nick name */ #define ADC_INF_FLAG_NICK "NI" /* nick name */
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */ #define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
#define ADC_INF_FLAG_USER_AGENT "VE" /* software version */
#define ADC_INF_FLAG_USER_AGENT_PRODUCT "AP" /* software name */
#define ADC_INF_FLAG_USER_AGENT_VERSION "VE" /* software version */
#define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */ #define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */
#define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */ #define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */
#define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */ #define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */
#define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed achieved in bytes/sec */ #define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed acheived in bytes/sec */
#define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download speed achieved in bytes/sec */ #define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download speed acheived in bytes/sec */
#define ADC_INF_FLAG_UPLOAD_SLOTS "SL" /* maximum upload slots (concurrent uploads) */ #define ADC_INF_FLAG_UPLOAD_SLOTS "SL" /* maximum upload slots (concurrent uploads) */
#define ADC_INF_FLAG_AUTO_SLOTS "AS" /* automatic slot if upload speed is less than this in bytes/sec */ #define ADC_INF_FLAG_AUTO_SLOTS "AS" /* automatic slot if upload speed is less than this in bytes/sec */
#define ADC_INF_FLAG_AUTO_SLOTS_MAX "AM" /* maximum number of automatic slots */ #define ADC_INF_FLAG_AUTO_SLOTS_MAX "AM" /* maximum number of automatic slots */
@ -134,7 +131,7 @@ typedef uint32_t fourcc_t;
#define ADC_MSG_FLAG_PRIVATE "PM" /* message is a private message */ #define ADC_MSG_FLAG_PRIVATE "PM" /* message is a private message */
#define ADC_SCH_FLAG_INCLUDE "AN" /* include given search term */ #define ADC_SCH_FLAG_INCLUDE "AN" /* include given search term */
#define ADC_SCH_FLAG_EXCLUDE "NO" /* exclude given search term */ #define ADC_SCH_FLAG_EXCLUDE "NO" /* exclude given serach term */
#define ADC_SCH_FLAG_FILE_EXTENSION "EX" /* search only for files with the given file extension */ #define ADC_SCH_FLAG_FILE_EXTENSION "EX" /* search only for files with the given file extension */
#define ADC_SCH_FLAG_FILE_TYPE "TY" /* search only for files with this file type (separate type) */ #define ADC_SCH_FLAG_FILE_TYPE "TY" /* search only for files with this file type (separate type) */
#define ADC_SCH_FLAG_LESS_THAN "LE" /* search for files with this size or less */ #define ADC_SCH_FLAG_LESS_THAN "LE" /* search for files with this size or less */
@ -156,10 +153,9 @@ typedef uint32_t fourcc_t;
#define ADC_SUP_FLAG_ADD "AD" #define ADC_SUP_FLAG_ADD "AD"
#define ADC_SUP_FLAG_REMOVE "RM" #define ADC_SUP_FLAG_REMOVE "RM"
#define ADC_CLIENT_TYPE_BOT "1" #define ADC_CLIENT_TYPE_BOT "1"
#define ADC_CLIENT_TYPE_REGISTERED_USER "2" #define ADC_CLIENT_TYPE_REGISTERED_USER "2"
#define ADC_CLIENT_TYPE_OPERATOR "4" #define ADC_CLIENT_TYPE_OPERATOR "4"
#define ADC_CLIENT_TYPE_HUBBOT "5" /* 1 + 4 */
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */ #define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */ #define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */ #define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -24,6 +24,7 @@
uhub_assert(X); \ uhub_assert(X); \
uhub_assert(X->cache); \ uhub_assert(X->cache); \
uhub_assert(X->capacity); \ uhub_assert(X->capacity); \
uhub_assert(X->length); \
uhub_assert(X->length <= X->capacity); \ uhub_assert(X->length <= X->capacity); \
uhub_assert(X->references > 0); \ uhub_assert(X->references > 0); \
uhub_assert(X->length == strlen(X->cache)); uhub_assert(X->length == strlen(X->cache));
@ -167,24 +168,24 @@ int adc_msg_get_arg_offset(struct adc_message* msg)
{ {
if (!msg || !msg->cache) if (!msg || !msg->cache)
return -1; return -1;
switch (msg->cache[0]) switch (msg->cache[0])
{ {
/* These *SHOULD* never be seen on a hub */ /* These *SHOULD* never be seen on a hub */
case 'U': case 'U':
case 'C': case 'C':
return 4; /* Actually: 4 + strlen(cid). */ return 4; /* Actually: 4 + strlen(cid). */
case 'I': case 'I':
case 'H': case 'H':
return 4; return 4;
case 'B': case 'B':
return 9; return 9;
case 'F': case 'F':
return (10 + (list_size(msg->feature_cast_include)*5) + (list_size(msg->feature_cast_exclude)*5)); return (10 + (list_size(msg->feature_cast_include)*5) + (list_size(msg->feature_cast_exclude)*5));
case 'D': case 'D':
case 'E': case 'E':
return 14; return 14;
@ -199,10 +200,10 @@ int adc_msg_is_empty(struct adc_message* msg)
if (offset == -1) if (offset == -1)
return -1; return -1;
if ((msg->length - 1) == (size_t) offset) if ((msg->length - 1) == (size_t) offset)
return 1; return 1;
return 0; return 0;
} }
@ -282,19 +283,23 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
if (cmd->feature_cast_include) if (cmd->feature_cast_include)
{ {
copy->feature_cast_include = list_create(); copy->feature_cast_include = list_create();
LIST_FOREACH(char*, tmp, cmd->feature_cast_include, tmp = list_get_first(cmd->feature_cast_include);
while (tmp)
{ {
list_append(copy->feature_cast_include, hub_strdup(tmp)); list_append(copy->feature_cast_include, hub_strdup(tmp));
}); tmp = list_get_next(cmd->feature_cast_include);
}
} }
if (cmd->feature_cast_exclude) if (cmd->feature_cast_exclude)
{ {
copy->feature_cast_exclude = list_create(); copy->feature_cast_exclude = list_create();
LIST_FOREACH(char*, tmp, cmd->feature_cast_exclude, tmp = list_get_first(cmd->feature_cast_exclude);
while (tmp)
{ {
list_append(copy->feature_cast_exclude, hub_strdup(tmp)); list_append(copy->feature_cast_exclude, hub_strdup(tmp));
}); tmp = list_get_next(cmd->feature_cast_exclude);
}
} }
ADC_MSG_ASSERT(copy); ADC_MSG_ASSERT(copy);
@ -306,17 +311,17 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length) struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length)
{ {
struct adc_message* command = adc_msg_parse(line, length); struct adc_message* command = adc_msg_parse(line, length);
if (!command) if (!command)
return 0; return 0;
if (command->source && (!u || (command->source != u->id.sid && !auth_cred_is_unrestricted(u->credentials)))) if (command->source && (!u || command->source != u->id.sid))
{ {
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0)); LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
adc_msg_free(command); adc_msg_free(command);
return 0; return 0;
} }
return command; return command;
} }
@ -330,7 +335,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
int ok = 1; int ok = 1;
int need_terminate = 0; int need_terminate = 0;
struct linked_list* feature_cast_list; struct linked_list* feature_cast_list;
if (command == NULL) if (command == NULL)
return NULL; /* OOM */ return NULL; /* OOM */
@ -527,9 +532,9 @@ struct adc_message* adc_msg_create(const char* line)
return adc_msg_parse(line, strlen(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) if (!msg)
return NULL; return NULL;
@ -538,20 +543,6 @@ struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size
return msg; 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* adc_msg_construct(fourcc_t fourcc, size_t size)
{ {
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message)); struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
@ -594,14 +585,14 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2]
int found = 0; int found = 0;
int arg_offset = adc_msg_get_arg_offset(cmd); int arg_offset = adc_msg_get_arg_offset(cmd);
size_t temp_len = 0; size_t temp_len = 0;
adc_msg_unterminate(cmd); adc_msg_unterminate(cmd);
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3); start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
while (start) while (start)
{ {
endInfo = &cmd->cache[cmd->length]; endInfo = &cmd->cache[cmd->length];
if (&start[0] < &endInfo[0]) if (&start[0] < &endInfo[0])
{ {
end = memchr(&start[1], ' ', &endInfo[0]-&start[1]); end = memchr(&start[1], ' ', &endInfo[0]-&start[1]);
@ -610,13 +601,13 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2]
{ {
end = NULL; end = NULL;
} }
if (end) if (end)
{ {
temp_len = &end[0] - &start[0]; // strlen(start); temp_len = &end[0] - &start[0]; // strlen(start);
endlen = strlen(end); endlen = strlen(end);
memmove(start, end, endlen); memmove(start, end, endlen);
start[endlen] = '\0'; start[endlen] = '\0';
found++; found++;
@ -631,9 +622,9 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2]
} }
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3); start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
} }
adc_msg_terminate(cmd); adc_msg_terminate(cmd);
return found; return found;
} }
@ -682,7 +673,7 @@ char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2])
length = &end[0] - &start[0]; length = &end[0] - &start[0];
argument = hub_strndup(start, length); argument = hub_strndup(start, length);
if (length > 0 && argument[length-1] == '\n') if (length > 0 && argument[length-1] == '\n')
{ {
argument[length-1] = 0; argument[length-1] = 0;

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -51,7 +51,7 @@ enum msg_status_level
extern struct adc_message* adc_msg_incref(struct adc_message* msg); extern struct adc_message* adc_msg_incref(struct adc_message* msg);
/** /**
* Decrease the reference counter, and free the memory when appropriate. * Decrease the reference counter, and free the memory when apropriate.
*/ */
extern void adc_msg_free(struct adc_message* msg); extern void adc_msg_free(struct adc_message* msg);
@ -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. * 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(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. * Remove a named argument from the command.
@ -159,7 +158,7 @@ extern char* adc_msg_get_argument(struct adc_message* cmd, int offset);
* *
* @arg prefix a 2 character argument prefix * @arg prefix a 2 character argument prefix
* @arg string must be escaped (see adc_msg_escape). * @arg string must be escaped (see adc_msg_escape).
* @return 0 if successful, or -1 if an error occurred. * @return 0 if successful, or -1 if an error occured.
*/ */
extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string); extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
@ -167,7 +166,7 @@ extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char pr
* Append an argument * Append an argument
* *
* @arg string must be escaped (see adc_msg_escape). * @arg string must be escaped (see adc_msg_escape).
* @return 0 if successful, or -1 if an error occurred (out of memory). * @return 0 if successful, or -1 if an error occured (out of memory).
*/ */
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string); extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
@ -176,7 +175,7 @@ extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
* *
* @arg prefix a 2 character argument prefix * @arg prefix a 2 character argument prefix
* @arg string must be escaped (see adc_msg_escape). * @arg string must be escaped (see adc_msg_escape).
* @return 0 if successful, or -1 if an error occurred (out of memory). * @return 0 if successful, or -1 if an error occured (out of memory).
*/ */
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string); extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
@ -186,7 +185,7 @@ extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix
* *
* @arg prefix a 2 character argument prefix * @arg prefix a 2 character argument prefix
* @arg string must NOT be escaped * @arg string must NOT be escaped
* @return 0 if successful, or -1 if an error occurred (out of memory). * @return 0 if successful, or -1 if an error occured (out of memory).
*/ */
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string); extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
@ -229,7 +228,7 @@ void adc_msg_unterminate(struct adc_message* cmd);
/** /**
* @return the offset for the first command argument in msg->cache. * @return the offset for the first command argument in msg->cache.
* or -1 if the command is not understood. * or -1 if the command is not understood.
* NOTE: for 'U' and 'C' commands (normally not seen by hubs), * NOTE: for 'U' and 'C' commands (normally not seen by hubs),
* this returns 4. Should be 4 + lengthOf(cid). * this returns 4. Should be 4 + lengthOf(cid).
*/ */
int adc_msg_get_arg_offset(struct adc_message* msg); int adc_msg_get_arg_offset(struct adc_message* msg);

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -47,7 +47,7 @@ sid_t string_to_sid(const char* sid)
sid_t nsid = 0; sid_t nsid = 0;
sid_t n, x; sid_t n, x;
sid_t factors[] = { 32768, 1024, 32, 1}; sid_t factors[] = { 32768, 1024, 32, 1};
if (!sid || strlen(sid) != 4) return 0; if (!sid || strlen(sid) != 4) return 0;
for (n = 0; n < 4; n++) { for (n = 0; n < 4; n++) {

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -26,20 +26,20 @@
static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count) static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count)
{ {
char* data; char* data;
if (!strncmp(line, cmd, strlen(cmd))) if (!strncmp(line, cmd, strlen(cmd)))
{ {
data = &line[strlen(cmd)]; data = &line[strlen(cmd)];
data[0] = '\0'; data[0] = '\0';
data++; data++;
data = strip_white_space(data); data = strip_white_space(data);
if (!*data) if (!*data)
{ {
LOG_FATAL("ACL parse error on line %d", line_count); LOG_FATAL("ACL parse error on line %d", line_count);
return -1; return -1;
} }
list_append(list, hub_strdup(data)); list_append(list, hub_strdup(data));
LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd); LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd);
return 1; return 1;
@ -170,9 +170,6 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
LOG_DEBUG("acl_parse_line: '%s'", line); LOG_DEBUG("acl_parse_line: '%s'", line);
ACL_ADD_USER("bot", handle->users, auth_cred_bot); ACL_ADD_USER("bot", handle->users, auth_cred_bot);
ACL_ADD_USER("ubot", handle->users, auth_cred_ubot);
ACL_ADD_USER("opbot", handle->users, auth_cred_opbot);
ACL_ADD_USER("opubot", handle->users, auth_cred_opubot);
ACL_ADD_USER("user_admin", handle->users, auth_cred_admin); ACL_ADD_USER("user_admin", handle->users, auth_cred_admin);
ACL_ADD_USER("user_super", handle->users, auth_cred_super); ACL_ADD_USER("user_super", handle->users, auth_cred_super);
ACL_ADD_USER("user_op", handle->users, auth_cred_operator); ACL_ADD_USER("user_op", handle->users, auth_cred_operator);
@ -193,18 +190,18 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
{ {
int ret; int ret;
memset(handle, 0, sizeof(struct acl_handle)); memset(handle, 0, sizeof(struct acl_handle));
handle->users = list_create(); handle->users = list_create();
handle->users_denied = list_create(); handle->users_denied = list_create();
handle->users_banned = list_create(); handle->users_banned = list_create();
handle->cids = list_create(); handle->cids = list_create();
handle->networks = list_create(); handle->networks = list_create();
handle->nat_override = list_create(); handle->nat_override = list_create();
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override) if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
{ {
LOG_FATAL("acl_initialize: Out of memory"); LOG_FATAL("acl_initialize: Out of memory");
list_destroy(handle->users); list_destroy(handle->users);
list_destroy(handle->users_denied); list_destroy(handle->users_denied);
list_destroy(handle->users_banned); list_destroy(handle->users_banned);
@ -213,11 +210,11 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
list_destroy(handle->nat_override); list_destroy(handle->nat_override);
return -1; return -1;
} }
if (config) if (config)
{ {
if (!*config->file_acl) return 0; if (!*config->file_acl) return 0;
ret = file_read_lines(config->file_acl, handle, &acl_parse_line); ret = file_read_lines(config->file_acl, handle, &acl_parse_line);
if (ret == -1) if (ret == -1)
return -1; return -1;
@ -252,26 +249,26 @@ int acl_shutdown(struct acl_handle* handle)
list_clear(handle->users, &acl_free_access_info); list_clear(handle->users, &acl_free_access_info);
list_destroy(handle->users); list_destroy(handle->users);
} }
if (handle->users_denied) if (handle->users_denied)
{ {
list_clear(handle->users_denied, &hub_free); list_clear(handle->users_denied, &hub_free);
list_destroy(handle->users_denied); list_destroy(handle->users_denied);
} }
if (handle->users_banned) if (handle->users_banned)
{ {
list_clear(handle->users_banned, &hub_free); list_clear(handle->users_banned, &hub_free);
list_destroy(handle->users_banned); list_destroy(handle->users_banned);
} }
if (handle->cids) if (handle->cids)
{ {
list_clear(handle->cids, &hub_free); list_clear(handle->cids, &hub_free);
list_destroy(handle->cids); list_destroy(handle->cids);
} }
if (handle->networks) if (handle->networks)
{ {
list_clear(handle->networks, &acl_free_ip_info); list_clear(handle->networks, &acl_free_ip_info);
@ -333,11 +330,13 @@ struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name)
} }
#define STR_LIST_CONTAINS(LIST, STR) \ #define STR_LIST_CONTAINS(LIST, STR) \
LIST_FOREACH(char*, str, LIST, \ str = (char*) list_get_first(LIST); \
while (str) \
{ \ { \
if (strcasecmp(str, STR) == 0) \ if (strcasecmp(str, STR) == 0) \
return 1; \ return 1; \
}); \ str = (char*) list_get_next(LIST); \
} \
return 0 return 0
int acl_is_cid_banned(struct acl_handle* handle, const char* data) int acl_is_cid_banned(struct acl_handle* handle, const char* data)
@ -401,28 +400,34 @@ int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address) int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
{ {
struct ip_addr_encap raw; struct ip_addr_encap raw;
struct ip_range* info; struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
ip_convert_to_binary(ip_address, &raw); ip_convert_to_binary(ip_address, &raw);
LIST_FOREACH(struct ip_range*, info, handle->networks,
while (info)
{ {
if (ip_in_range(&raw, info)) if (ip_in_range(&raw, info))
{
return 1; return 1;
}); }
info = (struct ip_range*) list_get_next(handle->networks);
}
return 0; return 0;
} }
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address) int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
{ {
struct ip_addr_encap raw; struct ip_addr_encap raw;
struct ip_range* info; struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
ip_convert_to_binary(ip_address, &raw); ip_convert_to_binary(ip_address, &raw);
LIST_FOREACH(struct ip_range*, info, handle->nat_override,
while (info)
{ {
if (ip_in_range(&raw, info)) if (ip_in_range(&raw, info))
{
return 1; return 1;
}); }
info = (struct ip_range*) list_get_next(handle->nat_override);
}
return 0; return 0;
} }
@ -471,10 +476,10 @@ int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char*
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN); base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
password_len = strlen(access->password); password_len = strlen(access->password);
memcpy(&buf[0], access->password, password_len); memcpy(&buf[0], access->password, password_len);
memcpy(&buf[password_len], raw_challenge, TIGERSIZE); memcpy(&buf[password_len], raw_challenge, TIGERSIZE);
tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res); tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc); base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
password_calc[MAX_CID_LEN] = 0; password_calc[MAX_CID_LEN] = 0;

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -26,7 +26,7 @@ static void hub_command_args_free(struct hub_command* cmd)
if (!cmd->args) if (!cmd->args)
return; return;
LIST_FOREACH(struct hub_command_arg_data*, data, cmd->args, for (data = (struct hub_command_arg_data*) list_get_first(cmd->args); data; data = (struct hub_command_arg_data*) list_get_next(cmd->args))
{ {
switch (data->type) switch (data->type)
{ {
@ -39,7 +39,7 @@ static void hub_command_args_free(struct hub_command* cmd)
default: default:
break; break;
} }
}); }
list_clear(cmd->args, hub_free); list_clear(cmd->args, hub_free);
list_destroy(cmd->args); list_destroy(cmd->args);
@ -64,7 +64,6 @@ static enum command_parse_status command_extract_arguments(struct hub_info* hub,
char* token = NULL; char* token = NULL;
char* tmp = NULL; char* tmp = NULL;
size_t size = 0; size_t size = 0;
size_t offset = 0;
struct hub_command_arg_data* data = NULL; struct hub_command_arg_data* data = NULL;
enum command_parse_status status = cmd_status_ok; enum command_parse_status status = cmd_status_ok;
@ -78,15 +77,15 @@ static enum command_parse_status command_extract_arguments(struct hub_info* hub,
if (greedy) if (greedy)
{ {
size = 1; size = 1;
LIST_FOREACH(char*, tmp, tokens, { size += (strlen(tmp) + 1); }); for (tmp = (char*) list_get_first(tokens); tmp; tmp = (char*) list_get_next(tokens))
size += (strlen(tmp) + 1);
token = hub_malloc_zero(size); token = hub_malloc_zero(size);
while ((tmp = list_get_first(tokens))) while ((tmp = list_get_first(tokens)))
{ {
if (offset > 0) if (*token)
token[offset++] = ' '; strcat(token, " ");
memcpy(token + offset, tmp, strlen(tmp)); strcat(token, tmp);
offset += strlen(tmp);
list_remove(tokens, tmp); list_remove(tokens, tmp);
hub_free(tmp); hub_free(tmp);
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -30,7 +30,7 @@ struct command_base;
* *
* @param cbase Command base pointer. * @param cbase Command base pointer.
* @param user User who invoked the command. * @param user User who invoked the command.
* @param message The message that is to be interpreted as a command (including the invocation prefix '!' or '+') * @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+')
* *
* @return a hub_command that must be freed with command_free(). @See struct hub_command. * @return a hub_command that must be freed with command_free(). @See struct hub_command.
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -31,6 +31,8 @@ static int send_command_not_found(struct command_base* cbase, struct hub_user* u
static int send_command_syntax_error(struct command_base* cbase, struct hub_user* user); static int send_command_syntax_error(struct command_base* cbase, struct hub_user* user);
static int send_command_missing_arguments(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd); static int send_command_missing_arguments(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
static void null_free(void* ptr) { }
struct command_base struct command_base
{ {
struct hub_info* hub; struct hub_info* hub;
@ -96,14 +98,14 @@ struct command_handle* command_handler_lookup(struct command_base* cbase, const
struct command_handle* handler = NULL; struct command_handle* handler = NULL;
size_t prefix_len = strlen(prefix); size_t prefix_len = strlen(prefix);
LIST_FOREACH(struct command_handle*, handler, cbase->handlers, for (handler = (struct command_handle*) list_get_first(cbase->handlers); handler; handler = (struct command_handle*) list_get_next(cbase->handlers))
{ {
if (prefix_len != handler->length) if (prefix_len != handler->length)
continue; continue;
if (!memcmp(prefix, handler->prefix, handler->length)) if (!memcmp(prefix, handler->prefix, handler->length))
return handler; return handler;
}); }
return NULL; return NULL;
} }
@ -290,7 +292,7 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
{ {
cbuf_append(buf, "Available commands:\n"); cbuf_append(buf, "Available commands:\n");
LIST_FOREACH(struct command_handle*, command, cbase->handlers, for (command = (struct command_handle*) list_get_first(cbase->handlers); command; command = (struct command_handle*) list_get_next(cbase->handlers))
{ {
if (command_is_available(command, user->credentials)) if (command_is_available(command, user->credentials))
{ {
@ -299,7 +301,7 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
cbuf_append(buf, " "); cbuf_append(buf, " ");
cbuf_append_format(buf, " - %s\n", command->description); cbuf_append_format(buf, " - %s\n", command->description);
} }
}); }
} }
else else
{ {
@ -422,7 +424,7 @@ static int command_whoip(struct command_base* cbase, struct hub_user* user, stru
ret = uman_get_user_by_addr(cbase->hub->users, users, arg->data.range); ret = uman_get_user_by_addr(cbase->hub->users, users, arg->data.range);
if (!ret) if (!ret)
{ {
list_clear(users, NULL); list_clear(users, &null_free);
list_destroy(users); list_destroy(users);
return command_status(cbase, user, cmd, cbuf_create_const("No users found.")); return command_status(cbase, user, cmd, cbuf_create_const("No users found."));
} }
@ -430,14 +432,16 @@ static int command_whoip(struct command_base* cbase, struct hub_user* user, stru
buf = cbuf_create(128 + ((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret)); buf = cbuf_create(128 + ((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret));
cbuf_append_format(buf, "*** %s: Found %d match%s:\n", cmd->prefix, ret, ((ret != 1) ? "es" : "")); cbuf_append_format(buf, "*** %s: Found %d match%s:\n", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
LIST_FOREACH(struct hub_user*, u, users, u = (struct hub_user*) list_get_first(users);
while (u)
{ {
cbuf_append_format(buf, "%s (%s)\n", u->id.nick, user_get_address(u)); cbuf_append_format(buf, "%s (%s)\n", u->id.nick, user_get_address(u));
}); u = (struct hub_user*) list_get_next(users);
}
cbuf_append(buf, "\n"); cbuf_append(buf, "\n");
send_message(cbase, user, buf); send_message(cbase, user, buf);
list_clear(users, NULL); list_clear(users, &null_free);
list_destroy(users); list_destroy(users);
return 0; return 0;
} }
@ -458,7 +462,8 @@ static int command_broadcast(struct command_base* cbase, struct hub_user* user,
memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid)); memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid));
memcpy(pm_flag + 2, from_sid, sizeof(from_sid)); memcpy(pm_flag + 2, from_sid, sizeof(from_sid));
LIST_FOREACH(struct hub_user*, target, cbase->hub->users->list, target = (struct hub_user*) list_get_first(cbase->hub->users->list);
while (target)
{ {
if (target != user) if (target != user)
{ {
@ -475,7 +480,8 @@ static int command_broadcast(struct command_base* cbase, struct hub_user* user,
route_to_user(cbase->hub, target, command); route_to_user(cbase->hub, target, command);
adc_msg_free(command); adc_msg_free(command);
} }
}); target = (struct hub_user*) list_get_next(cbase->hub->users->list);
}
cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : "")); cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : ""));
send_message(cbase, user, buf); send_message(cbase, user, buf);
@ -507,7 +513,8 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct
command_status(cbase, user, cmd, buf); command_status(cbase, user, cmd, buf);
buf = cbuf_create(MAX_HELP_LINE); buf = cbuf_create(MAX_HELP_LINE);
LIST_FOREACH(struct hub_logout_info*, log, messages, log = (struct hub_logout_info*) list_get_first(messages);
while (log)
{ {
const char* address = ip_convert_to_string(&log->addr); const char* address = ip_convert_to_string(&log->addr);
int show = 0; int show = 0;
@ -531,7 +538,8 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct
send_message(cbase, user, buf); send_message(cbase, user, buf);
buf = cbuf_create(MAX_HELP_LINE); buf = cbuf_create(MAX_HELP_LINE);
} }
}); log = (struct hub_logout_info*) list_get_next(messages);
}
if (search_len) if (search_len)
{ {
@ -549,28 +557,14 @@ static int command_stats(struct command_base* cbase, struct hub_user* user, stru
{ {
struct cbuffer* buf = cbuf_create(128); struct cbuffer* buf = cbuf_create(128);
struct hub_info* hub = cbase->hub; 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); return command_status(cbase, user, cmd, buf);
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -76,7 +76,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
struct hub_config* config = (struct hub_config*) ptr_data; struct hub_config* config = (struct hub_config*) ptr_data;
strip_off_ini_line_comments(line, line_count); strip_off_ini_line_comments(line, line_count);
if (!*line) return 0; if (!*line) return 0;
LOG_DUMP("config_parse_line(): '%s'", line); LOG_DUMP("config_parse_line(): '%s'", line);

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

289
src/core/config.pl Executable file
View File

@ -0,0 +1,289 @@
#!/usr/bin/perl -w
use strict;
use XML::DOM;
sub write_c_header(@);
sub write_sql_dump(@);
sub get_data($);
my $dump_to_sql = 0;
# initialize parser and read the file
my $input = "./config.xml";
my $parser = new XML::DOM::Parser;
my $tree = $parser->parsefile($input) || die "Unable to parse XML file.";
# Get data
my $nodes = $tree->getElementsByTagName("option");
my @options = ();
for (my $i = 0; $i < $nodes->getLength; $i++)
{
my @data = get_data($nodes->item($i));
push @options, \@data;
}
write_c_header(@options);
write_sql_dump(@options) if ($dump_to_sql);
my $config_defaults = "void config_defaults(struct hub_config* config)\n{\n";
my $config_apply = "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
my $config_free = "void free_config(struct hub_config* config)\n{\n";
my $config_dump = "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n";
foreach my $option (@options)
{
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check, $ifdef) = @$option;
my $string = ($type =~ /(string|file|message)/);
my $min = undef;
my $max = undef;
my $regexp = undef;
if (defined $check)
{
$min = $check->getAttribute("min");
$max = $check->getAttribute("max");
$regexp = $check->getAttribute("regexp");
$max = undef if ($max eq "");
$min = undef if ($min eq "");
$regexp = undef if ($regexp eq "");
}
$config_defaults .= "#ifdef $ifdef\n" if ($ifdef ne "");
$config_defaults .= "\tconfig->$name = ";
$config_defaults .= "hub_strdup(\"" if ($string);
$config_defaults .= $default;
$config_defaults .= "\")" if ($string);
$config_defaults .= ";\n";
$config_defaults .= "#endif /* $ifdef */\n" if ($ifdef ne "");
$config_apply .= "#ifdef $ifdef\n" if ($ifdef ne "");
$config_apply .= "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n";
if ($type eq "int")
{
$config_apply .= "\t\tmin = $min;\n" if (defined $min);
$config_apply .= "\t\tmax = $max;\n" if (defined $max);
$config_apply .= "\t\tif (!apply_integer(key, data, &config->$name, ";
if (defined $min) { $config_apply .= "&min"; } else { $config_apply .= "0"; }
$config_apply .= ", ";
if (defined $max) { $config_apply .= "&max"; } else { $config_apply .= "0"; }
$config_apply .= "))\n";
}
elsif ($type eq "boolean")
{
$config_apply .= "\t\tif (!apply_boolean(key, data, &config->$name))\n";
}
elsif ($string)
{
$config_apply .="\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
}
$config_apply .= "\t\t{\n" .
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
"\t\t\treturn -1;\n" .
"\t\t}\n" .
"\t\treturn 0;\n" .
"\t}\n";
$config_apply .= "#endif /* $ifdef */\n" if ($ifdef ne "");
$config_apply .= "\n";
if ($string)
{
$config_free .= "#ifdef $ifdef\n" if ($ifdef ne "");
$config_free .= "\thub_free(config->" . $name . ");\n";
$config_free .= "#endif /* $ifdef */\n" if ($ifdef ne "");
$config_free .= "\n";
}
my $out = "%s";
my $val = "config->$name";
my $test = "config->$name != $default";
$out = "%d" if ($type eq "int");
$val = "config->$name ? \"yes\" : \"no\"" if ($type eq "boolean");
if ($string)
{
$out = "\\\"%s\\\"";
$test = "strcmp(config->$name, \"$default\") != 0";
}
$config_dump .= "#ifdef $ifdef\n" if ($ifdef ne "");
$config_dump .= "\tif (!ignore_defaults || $test)\n";
$config_dump .= "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n";
$config_dump .= "#endif /* $ifdef */\n" if ($ifdef ne "");
$config_dump .= "\n";
}
$config_apply .= "\t/* Still here -- unknown directive */\n";
$config_apply .= "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n";
$config_apply .= "\treturn -1;\n";
$config_apply .= "}\n\n";
$config_defaults .= "}\n\n";
$config_free .= "}\n\n";
$config_dump .= "}\n\n";
open GENIMPL, ">gen_config.c" || die "Unable to write source file";
print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
print GENIMPL $config_defaults;
print GENIMPL $config_apply;
print GENIMPL $config_free;
print GENIMPL $config_dump;
sub get_data($)
{
my $p = shift;
my $short = "";
my $example = "";
my $description = "";
my $since = "";
my $ifdef = "";
$short = $p->getElementsByTagName("short")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("short")->getLength());
$since = $p->getElementsByTagName("since")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("since")->getLength());
$example = $p->getElementsByTagName("example")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("example")->getLength());
$description = $p->getElementsByTagName("description")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("description")->getLength());
my $check = $p->getElementsByTagName("check")->item(0);
$ifdef = $p->getElementsByTagName("ifdef")->item(0)->getFirstChild()->getData() if ($p->getElementsByTagName("ifdef")->getLength());
my @data = (
$p->getAttribute("type"),
$p->getAttribute("name"),
$p->getAttribute("default"),
$p->getAttribute("advanced"),
$short,
$description,
$since,
$example,
$check,
$ifdef
);
return @data;
}
# Write header file
sub write_c_header(@)
{
my @data = @_;
open GENHEAD, ">gen_config.h" || die "Unable to write header file";
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
print GENHEAD "struct hub_config\n{\n";
foreach my $option (@data)
{
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check, $ifdef) = @$option;
my $string = ($type =~ /(string|file|message)/);
print GENHEAD "#ifdef $ifdef\n" if ($ifdef ne "");
print GENHEAD "\t";
print GENHEAD "int " if ($type eq "int");
print GENHEAD "int " if ($type eq "boolean");
print GENHEAD "char*" if ($string);
print GENHEAD " " . $name . ";";
my $comment = "";
if ($type eq "message")
{
$comment = "\"" . $default . "\"";
}
elsif (defined $short && length $short > 0)
{
$comment = $short;
if (defined $default)
{
$comment .= " (default: ";
$comment .= "\"" if ($string);
$comment .= $default;
$comment .= "\"" if ($string);
$comment .= ")";
}
}
if (length $comment > 0)
{
my $pad = "";
for (my $i = length $name; $i < 32; $i++)
{
$pad .= " ";
}
$comment = $pad . "/*<<< " . $comment . " */";
}
print GENHEAD $comment . "\n";
print GENHEAD "#endif /* $ifdef */\n" if ($ifdef ne "");
}
print GENHEAD "};\n\n";
}
sub write_sql_dump(@)
{
my @data = @_;
# Write SQL dump code
open GENSQL, ">gen_config.sql" || die "Unable to write SQL dump";
print GENSQL "START TRANSACTION;\n\n
DROP TABLE uhub_config IF EXISTS;\n\n
CREATE TABLE uhub_config (
name VARCHAR(32) UNIQUE NOT NULL,
defaultValue TINYTEXT NOT NULL,
description LONGTEXT NOT NULL,
type TINYTEXT NOT NULL,
advanced BOOLEAN,
example LONGTEXT,
since TINYTEXT
);\n\n";
foreach my $option (@data)
{
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $check, $ifdef) = @$option;
if ($type =~ /(string|file|message)/ )
{
$default = "\\\"$default\\\"";
}
$desc =~ s/\"/\\\"/g;
$type =~ s/^int$/integer/;
my $stmt = "INSERT INTO uhub_config VALUES(";
$stmt .= "\"$name\", ";
$stmt .= "\"$default\", ";
$stmt .= "\"$desc\", ";
$stmt .= "\"$type\", ";
if (defined $example)
{
my $example_str = $example;
$example_str =~ s/\\/\\\\/g;
$example_str =~ s/\"/\\\"/g;
$stmt .= "\"$example_str\", ";
} else {
$stmt .= "NULL, ";
}
if (defined $since) {
$stmt .= "\"$since\", ";
} else {
$stmt .= "NULL, ";
}
if (defined $advanced) {
$stmt .= "\"$advanced\"";
} else {
$stmt .= "NULL";
}
$stmt .= ");\n";
print GENSQL $stmt;
}
print GENSQL "\n\nCOMMIT;\n\n";
}

View File

@ -1,255 +0,0 @@
#!/usr/bin/env python
"""
uhub - A tiny ADC p2p connection hub
Copyright (C) 2007-2013, Jan Vidar Krey
"""
from xml.dom import minidom, Node
from datetime import datetime
import argparse
class OptionParseError(Exception):
pass
class Option(object):
def _get(self, node, name):
self.__dict__[name] = None
if (node.getElementsByTagName(name)):
self.__dict__[name] = node.getElementsByTagName(name)[0].firstChild.nodeValue
def _attr(self, node, name, required = False):
try:
return node.attributes[name].value
except Exception:
pass
if (required):
raise OptionParseError("Option %s is required but not found!" % name)
return None
def __init__(self, node):
self.otype = self._attr(node, 'type', True)
# Verify that the type is known
if not self.otype in ["int", "boolean", "string", "message", "file"]:
raise OptionParseError("Option %s has unknown type" % self.name)
self.name = self._attr(node, 'name', True)
self.default = self._attr(node, 'default', True)
self.advanced = self._attr(node, 'advanced', False)
self.is_string = self.otype in ["string", "message", "file"]
self._get(node, "short");
self._get(node, "description");
self._get(node, "syntax");
self._get(node, "since");
self._get(node, "example");
check = node.getElementsByTagName("check")
if (check):
check = node.getElementsByTagName("check")[0]
self.check_min = self._attr(check, 'min', False)
self.check_max = self._attr(check, 'max', False)
self.check_regexp = self._attr(check, 'regexp', False)
else:
self.check_min = None
self.check_max = None
self.check_regexp = None
def c_type(self):
if self.otype == "boolean":
return "int"
elif self.is_string:
return "char*"
else:
return self.otype
def sql_type(self):
if self.otype == "int":
return "integer"
return self.otype
def c_comment(self):
comment = ""
if (self.otype == "message"):
comment = self.formatted_default()
elif len(self.short):
comment = "%s (default: %s)" % (self.short, self.formatted_default())
return comment
def formatted_default(self):
if self.is_string:
return "\"%s\"" % self.default
return self.default
class SourceGenerator(object):
def __init__(self, filename, cppStyle = True):
print ("Generating %s..." % filename)
self.f = open(filename, 'w');
def write_header(self, Comment = True):
if Comment:
s = "/*\n * uhub - A tiny ADC p2p connection hub\n"
s += " * Copyright (C) 2007-%s, Jan Vidar Krey\n *\n" % datetime.now().strftime("%Y")
s += " * THIS FILE IS AUTOGENERATED - DO NOT MODIFY\n"
s += " * Created %s, by config.py\n */\n\n" % datetime.now().strftime("%Y-%m-%d %H:%M")
self.f.write(s)
class CHeaderGenerator(SourceGenerator):
def __init__(self, filename):
super(CHeaderGenerator, self).__init__(filename)
def _write_declaration(self, option):
comment = ' ' * (32 - len(option.name)) + "/*<<< %s */" % option.c_comment()
ptype = option.c_type() + (5 - len(option.c_type())) * ' '
self.f.write("\t%(type)s %(name)s;%(comment)s\n" % {
"type": ptype,
"name": option.name,
"comment": comment})
def write(self, options):
self.write_header()
self.f.write("struct hub_config\n{\n")
for option in options:
self._write_declaration(option)
self.f.write("};\n\n")
class CSourceGenerator(SourceGenerator):
def __init__(self, filename):
super(CSourceGenerator, self).__init__(filename)
def _write_default_impl(self, option):
s = "\tconfig->%s = " % option.name
if option.is_string:
s += "hub_strdup(%s);\n" % option.formatted_default()
else:
s += option.formatted_default() + ";\n"
self.f.write(s)
def _write_apply_impl(self, option):
s = "\tif (!strcmp(key, \"%s\"))\n\t{\n" % option.name
if option.otype == "int":
s_min = "0"
s_max = "0"
if (option.check_min):
s += "\t\tmin = %s;\n" % option.check_min
s_min = "&min"
if (option.check_max):
s += "\t\tmax = %s;\n" % option.check_max
s_max = "&max"
s+= "\t\tif (!apply_integer(key, data, &config->%s, %s, %s))\n" % (option.name, s_min, s_max)
elif option.otype == "boolean":
s += "\t\tif (!apply_boolean(key, data, &config->%s))\n" % option.name
elif option.is_string:
s += "\t\tif (!apply_string(key, data, &config->%s, (char*) \"\"))\n" % option.name
s += "\t\t{\n\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n\t\t\treturn -1;\n\t\t}\n\t\treturn 0;\n\t}\n\n"
self.f.write(s)
def _write_free_impl(self, option):
if option.is_string:
self.f.write("\thub_free(config->%s);\n\n" % option.name)
def _write_dump_impl(self, option):
s = ""
fmt = "%s"
val = "config->%s" % option.name
test = "config->%s != %s" % (option.name, option.default)
if (option.otype == "int"):
fmt = "%d"
elif (option.otype == "boolean"):
val = "config->%s ? \"yes\" : \"no\"" % option.name
elif (option.is_string):
fmt = "\\\"%s\\\"";
test = "strcmp(config->%s, %s) != 0" % (option.name, option.formatted_default())
s += "\tif (!ignore_defaults || %s)\n" % test;
s += "\t\tfprintf(stdout, \"%s = %s\\n\", %s);\n\n" % (option.name, fmt, val)
self.f.write(s)
def write(self, options):
self.write_header()
self.f.write("void config_defaults(struct hub_config* config)\n{\n")
for option in options:
self._write_default_impl(option)
self.f.write("}\n\n")
self.f.write("static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n")
for option in options:
self._write_apply_impl(option)
self.f.write("\t/* Still here -- unknown directive */\n\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n\treturn -1;\n}\n\n")
self.f.write("void free_config(struct hub_config* config)\n{\n")
for option in options:
self._write_free_impl(option)
self.f.write("}\n\n")
self.f.write("void dump_config(struct hub_config* config, int ignore_defaults)\n{\n")
for option in options:
self._write_dump_impl(option)
self.f.write("}\n\n")
class SqlWebsiteDocsGenerator(SourceGenerator):
def __init__(self, filename, sqlite_support = False):
self.sqlite_support = sqlite_support
super(SqlWebsiteDocsGenerator, self).__init__(filename)
def _sql_escape(self, s):
if self.sqlite_support:
return s.replace("\"", "\"\"")
return s.replace("\"", "\\\"")
def _write_or_null(self, s):
if (not s or len(s) == 0):
return "NULL"
return "\"%s\"" % self._sql_escape(s)
def write(self, options):
self.write_header(False)
table = "uhub_config"
s = ""
if not self.sqlite_support:
s += "START TRANSACTION;\n\nDROP TABLE %(table)s IF EXISTS;" % { "table": table }
s += "\n\nCREATE TABLE %(table)s (\n\tname VARCHAR(32) UNIQUE NOT NULL,\n\tdefaultValue TINYTEXT NOT NULL,\n\tdescription LONGTEXT NOT NULL,\n\ttype TINYTEXT NOT NULL,\n\tadvanced BOOLEAN,\n\texample LONGTEXT,\n\tsince TINYTEXT\n);\n\n" % { "table": table }
self.f.write(s)
for option in options:
s = "INSERT INTO %(table)s VALUES(\"%(name)s\", \"%(default)s\", \"%(description)s\", \"%(type)s\", %(example)s, %(since)s, %(advanced)s);\n" % {
"table": table,
"name": self._sql_escape(option.name),
"default": self._sql_escape(option.formatted_default()),
"description": self._sql_escape(option.description),
"type": option.sql_type(),
"example": self._write_or_null(option.example),
"since": self._write_or_null(option.since),
"advanced": self._write_or_null(option.example),
}
self.f.write(s)
if not self.sqlite_support:
self.f.write("\n\nCOMMIT;\n\n")
if __name__ == "__main__":
# parser = argparse.ArgumentParser(description = "Configuration file parser and source generator")
# parser.add_argument("--in", nargs=1, type=argparse.FileType('r'), default="config.xml", help="Input file (config.xml)", required = True)
# parser.add_argument("--c-decl", nargs=1, type=argparse.FileType('w'), default="gen_config.h", help="Output file for C declarations (gen_config.h)")
# parser.add_argument("--c-impl", nargs=1, type=argparse.FileType('w'), default="gen_config.c", help="Output file for C implementation (gen_config.c)")
# parser.add_argument("--doc-sql", nargs=1, type=argparse.FileType('w'), help="Output file for SQL documentation")
# args = parser.parse_args()
xmldoc = minidom.parse("./config.xml")
opt_tags = xmldoc.getElementsByTagName('option')
options = []
for option in opt_tags:
opt = Option(option)
options.append(opt)
header = CHeaderGenerator("./gen_config.h");
header.write(options);
source = CSourceGenerator("./gen_config.c");
source.write(options);
#sql = SqlWebsiteDocsGenerator("./gen_config.sql", True);
#sql.write(options);

View File

@ -17,7 +17,7 @@
</option> </option>
<option name="server_bind_addr" type="string" default="any"> <option name="server_bind_addr" type="string" default="any">
<check regexp="[\x:.]+|any|loopback" /> <check regexp="(\d\.\d\.\d\.\d\)|(any)|(loopback)|(.*)" /><!-- FIXME: add better IPv6 regexp in the future! -->
<short>Server bind address</short> <short>Server bind address</short>
<description><![CDATA[ <description><![CDATA[
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br /> Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
@ -58,7 +58,7 @@
</option> </option>
<option name="server_alt_ports" type="string" default=""> <option name="server_alt_ports" type="string" default="">
<check regexp="\d+(,\d+)*" /> <check regexp="((\d+)(,(\d+))*)?" />
<short>Comma separated list of alternative ports to listen to</short> <short>Comma separated list of alternative ports to listen to</short>
<description><![CDATA[ <description><![CDATA[
In addition to the server_port the hub can listen to a list of alternative ports. In addition to the server_port the hub can listen to a list of alternative ports.
@ -111,7 +111,7 @@
<option name="register_self" type="boolean" default="0"> <option name="register_self" type="boolean" default="0">
<short>Allow users to register themselves on the hub.</short> <short>Allow users to register themselves on the hub.</short>
<description><![CDATA[ <description><![CDATA[
If this is enabled guests can register their nickname on the hub using !register command. If this is enabled guests can register their nickname on the hub.
Otherwise only operators can register users. Otherwise only operators can register users.
]]></description> ]]></description>
<since>0.4.0</since> <since>0.4.0</since>
@ -157,7 +157,7 @@
</option> </option>
<option name="redirect_addr" type="string" default=""> <option name="redirect_addr" type="string" default="">
<check regexp="(adcs?|dchub)://.*" /> <check regexp="(adc|adcs|dchub)://.*" />
<short>A common hub redirect address.</short> <short>A common hub redirect address.</short>
<description><![CDATA[ <description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements. This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
@ -170,7 +170,7 @@
<check min="1024" max="1048576" /> <check min="1024" max="1048576" />
<short>Max read buffer before parse, per user</short> <short>Max read buffer before parse, per user</short>
<description><![CDATA[ <description><![CDATA[
Maximum receive buffer allowed before commands are processed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution. Maximum receive buffer allowed before commands are procesed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution.
]]></description> ]]></description>
<since>0.1.3</since> <since>0.1.3</since>
</option> </option>
@ -419,7 +419,7 @@
</option> </option>
<option name="tls_require_redirect_addr" type="string" default=""> <option name="tls_require_redirect_addr" type="string" default="">
<check regexp="(adcs?|dchub)://.*" /> <check regexp="(adc|adcs|dchub)://.*" />
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short> <short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
<description><![CDATA[ <description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not using ADCS. This is the redirect address used when the hub wants to redirect a client for not using ADCS.
@ -428,10 +428,11 @@
<since>0.3.3</since> <since>0.3.3</since>
</option> </option>
<option name="tls_certificate" type="file" default=""> <option name="tls_certificate" type="file" default="">
<short>Certificate file</short> <short>Certificate file</short>
<description><![CDATA[ <description><![CDATA[
Path to a TLS/SSL certificate or certificate chain (PEM format). Path to a TLS/SSL certificate (PEM format).
]]></description> ]]></description>
<since>0.3.0</since> <since>0.3.0</since>
</option> </option>
@ -444,40 +445,6 @@
<since>0.3.0</since> <since>0.3.0</since>
</option> </option>
<option name="tls_ciphersuite" type="string" default="ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS">
<short>List of TLS ciphers to use</short>
<description><![CDATA[
This is a colon separated list of preferred ciphers in the OpenSSL format.
]]></description>
<since>0.5.0</since>
<example><![CDATA[
<p>
High security with emphasis on forward secrecy:<br />
tls_ciphersuite = "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"
</p>
<p>
Allow ChaCha20/Poly1305 which are secure, yet generally faster:<br />
tls_ciphersuite = "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
</p>
]]></example>
</option>
<option name="tls_version" type="string" default="1.2">
<short>Specify minimum TLS version supported.</short>
<description><![CDATA[
<p>
This allows you to specify the minimum TLS version the hub requires from connecting clients in order to
connect to the hub.
</p>
<p>
TLS version 1.2 is recommended and enabled by default.
TLS version 1.1 is acceptable without any known flaws, and allows for older clients to connect.
TLS version 1.0 should be avoided, even though it is the most compatible with older ADC clients.
</p>
]]></description>
<since>0.5.0</since>
</option>
<option name="file_acl" type="file" default=""> <option name="file_acl" type="file" default="">
<short>File containing access control lists</short> <short>File containing access control lists</short>
<description><![CDATA[ <description><![CDATA[
@ -567,7 +534,7 @@
</option> </option>
<option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use"> <option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use">
<description><![CDATA[This message will be sent to clients if their provided nickname is already in use on the hub.]]></description> <description><![CDATA[This message will be sent to clients if their provided nickname is alredy in use on the hub.]]></description>
<since>0.2.0</since> <since>0.2.0</since>
</option> </option>

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -32,20 +32,20 @@ int event_queue_initialize(struct event_queue** queue, event_queue_callback call
*queue = (struct event_queue*) hub_malloc_zero(sizeof(struct event_queue)); *queue = (struct event_queue*) hub_malloc_zero(sizeof(struct event_queue));
if (!(*queue)) if (!(*queue))
return -1; return -1;
(*queue)->q1 = list_create(); (*queue)->q1 = list_create();
(*queue)->q2 = list_create(); (*queue)->q2 = list_create();
if (!(*queue)->q1 || !(*queue)->q2) if (!(*queue)->q1 || !(*queue)->q2)
{ {
list_destroy((*queue)->q1); list_destroy((*queue)->q1);
list_destroy((*queue)->q2); list_destroy((*queue)->q2);
return -1; return -1;
} }
(*queue)->callback = callback; (*queue)->callback = callback;
(*queue)->callback_data = ptr; (*queue)->callback_data = ptr;
return 0; return 0;
} }
@ -73,27 +73,35 @@ int event_queue_process(struct event_queue* queue)
struct event_data* data; struct event_data* data;
if (queue->locked) if (queue->locked)
return 0; return 0;
/* lock primary queue, and handle the primary queue messages. */ /* lock primary queue, and handle the primary queue messages. */
queue->locked = 1; queue->locked = 1;
LIST_FOREACH(struct event_data*, data, queue->q1, data = (struct event_data*) list_get_first(queue->q1);
while (data)
{ {
#ifdef EQ_DEBUG #ifdef EQ_DEBUG
eq_debug("EXEC", data); eq_debug("EXEC", data);
#endif #endif
queue->callback(queue->callback_data, data); queue->callback(queue->callback_data, data);
}); data = (struct event_data*) list_get_next(queue->q1);
}
list_clear(queue->q1, event_queue_cleanup_callback); list_clear(queue->q1, event_queue_cleanup_callback);
uhub_assert(list_size(queue->q1) == 0); uhub_assert(list_size(queue->q1) == 0);
/* unlock queue */ /* unlock queue */
queue->locked = 0; queue->locked = 0;
/* transfer from secondary queue to the primary queue. */ /* transfer from secondary queue to the primary queue. */
list_append_list(queue->q1, queue->q2); data = (struct event_data*) list_get_first(queue->q2);
while (data)
{
list_remove(queue->q2, data);
list_append(queue->q1, data);
data = (struct event_data*) list_get_first(queue->q2);
}
/* if more events exist, schedule it */ /* if more events exist, schedule it */
if (list_size(queue->q1)) if (list_size(queue->q1))
{ {
@ -106,18 +114,18 @@ void event_queue_post(struct event_queue* queue, struct event_data* message)
{ {
struct linked_list* q = (!queue->locked) ? queue->q1 : queue->q2; struct linked_list* q = (!queue->locked) ? queue->q1 : queue->q2;
struct event_data* data; struct event_data* data;
data = (struct event_data*) hub_malloc(sizeof(struct event_data)); data = (struct event_data*) hub_malloc(sizeof(struct event_data));
if (data) if (data)
{ {
data->id = message->id; data->id = message->id;
data->ptr = message->ptr; data->ptr = message->ptr;
data->flags = message->flags; data->flags = message->flags;
#ifdef EQ_DEBUG #ifdef EQ_DEBUG
eq_debug("POST", data); eq_debug("POST", data);
#endif #endif
list_append(q, data); list_append(q, data);
} }
else else

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,10 +1,4 @@
/* /* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* THIS FILE IS AUTOGENERATED - DO NOT MODIFY
* Created 2014-07-29 12:22, by config.py
*/
void config_defaults(struct hub_config* config) void config_defaults(struct hub_config* config)
{ {
@ -51,8 +45,6 @@ void config_defaults(struct hub_config* config)
config->tls_require_redirect_addr = hub_strdup(""); config->tls_require_redirect_addr = hub_strdup("");
config->tls_certificate = hub_strdup(""); config->tls_certificate = hub_strdup("");
config->tls_private_key = hub_strdup(""); config->tls_private_key = hub_strdup("");
config->tls_ciphersuite = hub_strdup("ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS");
config->tls_version = hub_strdup("1.2");
config->file_acl = hub_strdup(""); config->file_acl = hub_strdup("");
config->file_plugins = hub_strdup(""); config->file_plugins = hub_strdup("");
config->msg_hub_full = hub_strdup("Hub is full"); config->msg_hub_full = hub_strdup("Hub is full");
@ -554,26 +546,6 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
return 0; return 0;
} }
if (!strcmp(key, "tls_ciphersuite"))
{
if (!apply_string(key, data, &config->tls_ciphersuite, (char*) ""))
{
LOG_ERROR("Configuration parse error on line %d", line_count);
return -1;
}
return 0;
}
if (!strcmp(key, "tls_version"))
{
if (!apply_string(key, data, &config->tls_version, (char*) ""))
{
LOG_ERROR("Configuration parse error on line %d", line_count);
return -1;
}
return 0;
}
if (!strcmp(key, "file_acl")) if (!strcmp(key, "file_acl"))
{ {
if (!apply_string(key, data, &config->file_acl, (char*) "")) if (!apply_string(key, data, &config->file_acl, (char*) ""))
@ -977,10 +949,6 @@ void free_config(struct hub_config* config)
hub_free(config->tls_private_key); hub_free(config->tls_private_key);
hub_free(config->tls_ciphersuite);
hub_free(config->tls_version);
hub_free(config->file_acl); hub_free(config->file_acl);
hub_free(config->file_plugins); hub_free(config->file_plugins);
@ -1190,12 +1158,6 @@ void dump_config(struct hub_config* config, int ignore_defaults)
if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0) if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0)
fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key); fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key);
if (!ignore_defaults || strcmp(config->tls_ciphersuite, "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS") != 0)
fprintf(stdout, "tls_ciphersuite = \"%s\"\n", config->tls_ciphersuite);
if (!ignore_defaults || strcmp(config->tls_version, "1.2") != 0)
fprintf(stdout, "tls_version = \"%s\"\n", config->tls_version);
if (!ignore_defaults || strcmp(config->file_acl, "") != 0) if (!ignore_defaults || strcmp(config->file_acl, "") != 0)
fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl); fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl);

View File

@ -1,10 +1,4 @@
/* /* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* THIS FILE IS AUTOGENERATED - DO NOT MODIFY
* Created 2014-07-29 12:22, by config.py
*/
struct hub_config struct hub_config
{ {
@ -51,8 +45,6 @@ struct hub_config
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */ char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */
char* tls_certificate; /*<<< Certificate file (default: "") */ char* tls_certificate; /*<<< Certificate file (default: "") */
char* tls_private_key; /*<<< Private key file (default: "") */ char* tls_private_key; /*<<< Private key file (default: "") */
char* tls_ciphersuite; /*<<< List of TLS ciphers to use (default: "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS") */
char* tls_version; /*<<< Specify minimum TLS version supported. (default: "1.2") */
char* file_acl; /*<<< File containing access control lists (default: "") */ char* file_acl; /*<<< File containing access control lists (default: "") */
char* file_plugins; /*<<< Plugin configuration file (default: "") */ char* file_plugins; /*<<< Plugin configuration file (default: "") */
char* msg_hub_full; /*<<< "Hub is full" */ char* msg_hub_full; /*<<< "Hub is full" */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -23,7 +23,7 @@ struct hub_info* g_hub = 0;
/* FIXME: Flood control should be done in a plugin! */ /* FIXME: Flood control should be done in a plugin! */
#define CHECK_FLOOD(TYPE, WARN) \ #define CHECK_FLOOD(TYPE, WARN) \
if (flood_control_check(&u->flood_ ## TYPE , hub->config->flood_ctl_ ## TYPE, hub->config->flood_ctl_interval, net_get_time()) && !auth_cred_is_unrestricted(u->credentials)) \ if (flood_control_check(&u->flood_ ## TYPE , hub->config->flood_ctl_ ## TYPE, hub->config->flood_ctl_interval, net_get_time())) \
{ \ { \
if (WARN) \ if (WARN) \
{ \ { \
@ -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) static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
{ {
struct net_connection* server; struct net_connection* server;
@ -731,29 +706,41 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
{ {
if (config->tls_enable) if (config->tls_enable)
{ {
hub->ctx = net_ssl_context_create(config->tls_version, config->tls_ciphersuite); hub->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
if (!hub->ctx) /* Disable SSLv2 */
return 0; SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_quiet_shutdown(hub->ssl_ctx, 1);
if (ssl_load_certificate(hub->ctx, config->tls_certificate) && if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
ssl_load_private_key(hub->ctx, config->tls_private_key) &&
ssl_check_private_key(hub->ctx))
{ {
LOG_INFO("Enabling TLS (%s), using certificate: %s, private key: %s", net_ssl_get_provider(), config->tls_certificate, config->tls_private_key); LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 1;
} }
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; return 1;
} }
static void unload_ssl_certificates(struct hub_info* hub) static void unload_ssl_certificates(struct hub_info* hub)
{ {
if (hub->ctx) if (hub->ssl_ctx)
net_ssl_context_destroy(hub->ctx); {
SSL_CTX_free(hub->ssl_ctx);
}
} }
#endif /* SSL_SUPPORT */ #endif
struct hub_info* hub_start_service(struct hub_config* config) struct hub_info* hub_start_service(struct hub_config* config)
{ {
@ -829,13 +816,6 @@ struct hub_info* hub_start_service(struct hub_config* config)
g_hub = hub; 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 // Start the hub command sub-system
hub->commands = command_initialize(hub); hub->commands = command_initialize(hub);
return hub; return hub;
@ -846,12 +826,6 @@ void hub_shutdown_service(struct hub_info* hub)
{ {
LOG_DEBUG("hub_shutdown_service()"); 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 #ifdef SSL_SUPPORT
unload_ssl_certificates(hub); unload_ssl_certificates(hub);
#endif #endif
@ -909,8 +883,7 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
if (hub->command_info) if (hub->command_info)
{ {
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT_PRODUCT, PRODUCT); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT, server);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT_VERSION, GIT_VERSION);
tmp = adc_msg_escape(hub->config->hub_name); tmp = adc_msg_escape(hub->config->hub_name);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp);
@ -1325,7 +1298,9 @@ void hub_logout_log(struct hub_info* hub, struct hub_user* user)
list_append(hub->logout_info, loginfo); list_append(hub->logout_info, loginfo);
while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log) while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log)
{ {
list_remove_first(hub->logout_info, hub_free); struct hub_logout_info* entry = list_get_first(hub->logout_info);
list_remove(hub->logout_info, entry);
hub_free(entry);
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -27,7 +27,7 @@ enum status_message
status_msg_hub_registered_users_only = -3, /* hub is for registered users only */ status_msg_hub_registered_users_only = -3, /* hub is for registered users only */
status_msg_inf_error_nick_missing = -4, /* no nickname given */ status_msg_inf_error_nick_missing = -4, /* no nickname given */
status_msg_inf_error_nick_multiple = -5, /* multiple nicknames given */ status_msg_inf_error_nick_multiple = -5, /* multiple nicknames given */
status_msg_inf_error_nick_invalid = -6, /* generic/unknown */ status_msg_inf_error_nick_invalid = -6, /* generic/unkown */
status_msg_inf_error_nick_long = -7, /* nickname too long */ status_msg_inf_error_nick_long = -7, /* nickname too long */
status_msg_inf_error_nick_short = -8, /* nickname too short */ status_msg_inf_error_nick_short = -8, /* nickname too short */
status_msg_inf_error_nick_spaces = -9, /* nickname cannot start with spaces */ status_msg_inf_error_nick_spaces = -9, /* nickname cannot start with spaces */
@ -50,12 +50,12 @@ enum status_message
status_msg_user_share_size_high = -41, /* User is sharing too much. */ status_msg_user_share_size_high = -41, /* User is sharing too much. */
status_msg_user_slots_low = -42, /* User has too few slots open. */ status_msg_user_slots_low = -42, /* User has too few slots open. */
status_msg_user_slots_high = -43, /* User has too many slots open. */ status_msg_user_slots_high = -43, /* User has too many slots open. */
status_msg_user_hub_limit_low = -44, /* User is on too few hubs. */ status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
status_msg_user_hub_limit_high = -45, /* User is on too many hubs. */ status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */ status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */ status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
}; };
@ -81,7 +81,6 @@ struct hub_stats
size_t net_rx_peak; size_t net_rx_peak;
size_t net_tx_total; size_t net_tx_total;
size_t net_rx_total; size_t net_rx_total;
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
}; };
struct hub_logout_info struct hub_logout_info
@ -116,7 +115,8 @@ struct hub_info
struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */ struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
struct ssl_context_handle* ctx; SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
#endif /* SSL_SUPPORT */ #endif /* SSL_SUPPORT */
}; };

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -88,7 +88,7 @@ static int check_hash_tiger(const char* cid, const char* pid)
/* /*
* FIXME: Only works for tiger hash. If a client doesn't support tiger we cannot let it in! * FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
*/ */
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
@ -109,14 +109,14 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
hub_free(pid); hub_free(pid);
return status_msg_inf_error_cid_invalid; return status_msg_inf_error_cid_invalid;
} }
if (strlen(pid) != MAX_CID_LEN) if (strlen(pid) != MAX_CID_LEN)
{ {
hub_free(cid); hub_free(cid);
hub_free(pid); hub_free(pid);
return status_msg_inf_error_pid_invalid; return status_msg_inf_error_pid_invalid;
} }
for (pos = 0; pos < MAX_CID_LEN; pos++) for (pos = 0; pos < MAX_CID_LEN; pos++)
{ {
if (!is_valid_base32_char(cid[pos])) if (!is_valid_base32_char(cid[pos]))
@ -133,18 +133,18 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
return status_msg_inf_error_pid_invalid; return status_msg_inf_error_pid_invalid;
} }
} }
if (!check_hash_tiger(cid, pid)) if (!check_hash_tiger(cid, pid))
{ {
hub_free(cid); hub_free(cid);
hub_free(pid); hub_free(pid);
return status_msg_inf_error_cid_invalid; return status_msg_inf_error_cid_invalid;
} }
/* Set the cid in the user object */ /* Set the cid in the user object */
memcpy(user->id.cid, cid, MAX_CID_LEN); memcpy(user->id.cid, cid, MAX_CID_LEN);
user->id.cid[MAX_CID_LEN] = 0; user->id.cid[MAX_CID_LEN] = 0;
hub_free(cid); hub_free(cid);
hub_free(pid); hub_free(pid);
return 0; return 0;
@ -154,7 +154,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
int num = 0; int num = 0;
num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID); num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
if (num != 1) if (num != 1)
{ {
@ -162,7 +162,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use
return status_msg_inf_error_cid_missing; return status_msg_inf_error_cid_missing;
return status_msg_inf_error_cid_invalid; return status_msg_inf_error_cid_invalid;
} }
num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); num = adc_msg_has_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
if (num != 1) if (num != 1)
{ {
@ -190,7 +190,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use
static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
const char* address = user_get_address(user); const char* address = user_get_address(user);
/* Check for NAT override address */ /* Check for NAT override address */
if (acl_is_ip_nat_override(hub->acl, address)) if (acl_is_ip_nat_override(hub->acl, address))
{ {
@ -236,12 +236,12 @@ static int nick_length_ok(const char* nick)
{ {
return nick_invalid_short; return nick_invalid_short;
} }
if (length > MAX_NICK_LEN) if (length > MAX_NICK_LEN)
{ {
return nick_invalid_long; return nick_invalid_long;
} }
return nick_ok; return nick_ok;
} }
@ -249,16 +249,16 @@ static int nick_length_ok(const char* nick)
static int nick_bad_characters(const char* nick) static int nick_bad_characters(const char* nick)
{ {
const char* tmp; const char* tmp;
/* Nick must not start with a space */ /* Nick must not start with a space */
if (nick[0] == ' ') if (nick[0] == ' ')
return nick_invalid_spaces; return nick_invalid_spaces;
/* Check for ASCII values below 32 */ /* Check for ASCII values below 32 */
for (tmp = nick; *tmp; tmp++) for (tmp = nick; *tmp; tmp++)
if ((*tmp < 32) && (*tmp > 0)) if ((*tmp < 32) && (*tmp > 0))
return nick_invalid_bad_ascii; return nick_invalid_bad_ascii;
return nick_ok; return nick_ok;
} }
@ -286,7 +286,7 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me
nick = adc_msg_unescape(tmp); nick = adc_msg_unescape(tmp);
free(tmp); tmp = 0; free(tmp); tmp = 0;
if (!nick) return 0; if (!nick) return 0;
status = nick_length_ok(nick); status = nick_length_ok(nick);
if (status != nick_ok) if (status != nick_ok)
{ {
@ -295,7 +295,7 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me
return status_msg_inf_error_nick_short; return status_msg_inf_error_nick_short;
return status_msg_inf_error_nick_long; return status_msg_inf_error_nick_long;
} }
status = nick_bad_characters(nick); status = nick_bad_characters(nick);
if (status != nick_ok) if (status != nick_ok)
{ {
@ -304,20 +304,20 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me
return status_msg_inf_error_nick_spaces; return status_msg_inf_error_nick_spaces;
return status_msg_inf_error_nick_bad_chars; return status_msg_inf_error_nick_bad_chars;
} }
status = nick_is_utf8(nick); status = nick_is_utf8(nick);
if (status != nick_ok) if (status != nick_ok)
{ {
hub_free(nick); hub_free(nick);
return status_msg_inf_error_nick_not_utf8; return status_msg_inf_error_nick_not_utf8;
} }
if (user_is_connecting(user)) if (user_is_connecting(user))
{ {
memcpy(user->id.nick, nick, strlen(nick)); memcpy(user->id.nick, nick, strlen(nick));
user->id.nick[strlen(nick)] = 0; user->id.nick[strlen(nick)] = 0;
} }
hub_free(nick); hub_free(nick);
return 0; return 0;
} }
@ -327,29 +327,19 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a
{ {
struct hub_user* lookup1 = uman_get_user_by_nick(hub->users, user->id.nick); struct hub_user* lookup1 = uman_get_user_by_nick(hub->users, user->id.nick);
struct hub_user* lookup2 = uman_get_user_by_cid(hub->users, user->id.cid); struct hub_user* lookup2 = uman_get_user_by_cid(hub->users, user->id.cid);
if (lookup1 == user) if (lookup1 == user)
{ {
return 0; return 0;
} }
if (lookup1 || lookup2) if (lookup1 || lookup2)
{ {
if (lookup1 == lookup2) if (lookup1 == lookup2)
{ {
if (user_flag_get(lookup1, flag_choke)) LOG_DEBUG("check_logged_in: exact same user is logged in: %s", user->id.nick);
{ hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
LOG_DEBUG("check_logged_in: exact same user is already logged in, but likely ghost: %s", user->id.nick); return 0;
// Old user unable to swallow data.
// Disconnect the existing user, and allow new user to enter.
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
}
else
{
LOG_DEBUG("check_logged_in: exact same user is already logged in: %s", user->id.nick);
return status_msg_inf_error_cid_taken;
}
} }
else else
{ {
@ -376,37 +366,21 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a
*/ */
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
char* ua_name_encoded = 0; char* ua_encoded = 0;
char* ua_version_encoded = 0; char* ua = 0;
char* str = 0;
size_t offset = 0;
/* Get client user agent version */ /* Get client user agent version */
ua_name_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT); ua_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
ua_version_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_VERSION); if (ua_encoded)
if (ua_name_encoded)
{ {
str = adc_msg_unescape(ua_name_encoded); ua = adc_msg_unescape(ua_encoded);
if (str) if (ua)
{ {
offset = strlen(str); memcpy(user->id.user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
memcpy(user->id.user_agent, str, MIN(offset, MAX_UA_LEN)); hub_free(ua);
hub_free(str);
} }
} }
hub_free(ua_encoded);
if (ua_version_encoded)
{
str = adc_msg_unescape(ua_version_encoded);
if (str)
{
memcpy(user->id.user_agent + offset, str, MIN(strlen(str), MAX_UA_LEN - offset));
hub_free(str);
}
}
hub_free(ua_name_encoded);
hub_free(ua_version_encoded);
return 0; return 0;
} }
@ -417,7 +391,7 @@ static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_mes
{ {
return status_msg_ban_permanently; return status_msg_ban_permanently;
} }
if (acl_is_user_banned(hub->acl, user->id.nick)) if (acl_is_user_banned(hub->acl, user->id.nick))
{ {
return status_msg_ban_permanently; return status_msg_ban_permanently;
@ -427,7 +401,7 @@ static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_mes
{ {
return status_msg_inf_error_nick_restricted; return status_msg_inf_error_nick_restricted;
} }
return 0; return 0;
} }
@ -496,7 +470,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
hub_free(arg); hub_free(arg);
arg = 0; arg = 0;
} }
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS); arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS);
if (arg) if (arg)
{ {
@ -560,7 +534,7 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
{ {
int ret = 0; int ret = 0;
struct auth_info* info = acl_get_access_info(hub, user->id.nick); struct auth_info* info = acl_get_access_info(hub, user->id.nick);
if (info) if (info)
{ {
user->credentials = info->credentials; user->credentials = info->credentials;
@ -576,15 +550,11 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
{ {
case auth_cred_none: case auth_cred_none:
break; break;
case auth_cred_bot: case auth_cred_bot:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
break; break;
case auth_cred_ubot:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
break;
case auth_cred_guest: case auth_cred_guest:
/* Nothing to be added to the info message */ /* Nothing to be added to the info message */
break; break;
@ -596,15 +566,7 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
case auth_cred_operator: case auth_cred_operator:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
break; break;
case auth_cred_opbot:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_HUBBOT);
break;
case auth_cred_opubot:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_HUBBOT);
break;
case auth_cred_super: case auth_cred_super:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
break; break;
@ -616,7 +578,7 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
case auth_cred_link: case auth_cred_link:
break; break;
} }
return ret; return ret;
} }
@ -649,10 +611,10 @@ static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd
{ {
/* Remove server restricted flags */ /* Remove server restricted flags */
remove_server_restricted_flags(cmd); remove_server_restricted_flags(cmd);
/* Update/set the feature cast flags. */ /* Update/set the feature cast flags. */
set_feature_cast_supports(user, cmd); set_feature_cast_supports(user, cmd);
return 0; return 0;
} }
@ -660,8 +622,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
{ {
if (hub->config->low_bandwidth_mode) if (hub->config->low_bandwidth_mode)
{ {
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_VERSION); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
@ -674,7 +635,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DESCRIPTION); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DESCRIPTION);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_EMAIL); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_EMAIL);
} }
return 0; return 0;
} }
@ -719,20 +680,20 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
{ {
return status_msg_hub_full; return status_msg_hub_full;
} }
if (check_registered_users_only(hub, user)) if (check_registered_users_only(hub, user))
{ {
return status_msg_hub_registered_users_only; return status_msg_hub_registered_users_only;
} }
INF_CHECK(check_limits, hub, user, cmd); INF_CHECK(check_limits, hub, user, cmd);
/* strip off stuff if low_bandwidth_mode is enabled */ /* strip off stuff if low_bandwidth_mode is enabled */
hub_handle_info_low_bandwidth(hub, user, cmd); hub_handle_info_low_bandwidth(hub, user, cmd);
/* Set initial user info */ /* Set initial user info */
user_set_info(user, cmd); user_set_info(user, cmd);
return code; return code;
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -72,7 +72,7 @@ size_t ioq_recv_set(struct ioq_recv* q, void* buf, size_t bufsize)
q->buf = 0; q->buf = 0;
q->size = 0; q->size = 0;
} }
if (!bufsize) if (!bufsize)
{ {
return 0; return 0;
@ -130,7 +130,7 @@ void ioq_send_add(struct ioq_send* q, struct adc_message* msg_)
q->size += msg->length; q->size += msg->length;
} }
static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg) void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
{ {
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
debug_msg("ioq_send_remove", msg); debug_msg("ioq_send_remove", msg);
@ -141,13 +141,13 @@ static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
q->offset = 0; 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; int ret;
struct adc_message* msg = list_get_first(q->queue); struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0; if (!msg) return 0;
uhub_assert(msg->cache && *msg->cache); 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) if (ret > 0)
{ {

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2012, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -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. * 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. * @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. * @returns 1 if send queue is empty, 0 otherwise.

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,16 +13,12 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "uhub.h" #include "uhub.h"
#ifdef SYSTEMD
#include <systemd/sd-daemon.h>
#endif
static int arg_verbose = 5; static int arg_verbose = 5;
static int arg_fork = 0; static int arg_fork = 0;
static int arg_check_config = 0; static int arg_check_config = 0;
@ -87,7 +83,7 @@ void setup_signal_handlers(struct hub_info* hub)
act.sa_mask = sig_set; act.sa_mask = sig_set;
act.sa_flags = SA_ONSTACK | SA_RESTART; act.sa_flags = SA_ONSTACK | SA_RESTART;
act.sa_handler = hub_handle_signal; act.sa_handler = hub_handle_signal;
for (i = 0; signals[i]; i++) for (i = 0; signals[i]; i++)
{ {
if (sigaction(signals[i], &act, 0) != 0) if (sigaction(signals[i], &act, 0) != 0)
@ -124,7 +120,7 @@ int main_loop()
hub_log_initialize(arg_log, arg_log_syslog); hub_log_initialize(arg_log, arg_log_syslog);
hub_set_log_verbosity(arg_verbose); hub_set_log_verbosity(arg_verbose);
} }
if (read_config(arg_config, &configuration, !arg_have_config) == -1) if (read_config(arg_config, &configuration, !arg_have_config) == -1)
return -1; return -1;
@ -140,25 +136,10 @@ int main_loop()
{ {
hub = hub_start_service(&configuration); hub = hub_start_service(&configuration);
if (!hub) if (!hub)
{
acl_shutdown(&acl);
free_config(&configuration);
net_destroy();
hub_log_shutdown();
return -1; return -1;
}
#if !defined(WIN32) #if !defined(WIN32)
setup_signal_handlers(hub); setup_signal_handlers(hub);
#ifdef SYSTEMD #endif
/* Notify the service manager that this daemon has
* been successfully initialized and shall enter the
* main loop.
*/
sd_notifyf(0, "READY=1\n"
"MAINPID=%lu", (unsigned long) getpid());
#endif /* SYSTEMD */
#endif /* ! WIN32 */
} }
hub_set_variables(hub, &acl); hub_set_variables(hub, &acl);
@ -174,7 +155,7 @@ int main_loop()
#if !defined(WIN32) #if !defined(WIN32)
shutdown_signal_handlers(hub); shutdown_signal_handlers(hub);
#endif #endif
if (hub) if (hub)
{ {
hub_shutdown_service(hub); hub_shutdown_service(hub);
@ -229,17 +210,13 @@ void print_usage(char* program)
" -q Quiet mode - no output\n" " -q Quiet mode - no output\n"
" -f Fork to background\n" " -f Fork to background\n"
" -l <file> Log messages to given file (default: stderr)\n" " -l <file> Log messages to given file (default: stderr)\n"
" -L Log messages to syslog\n"
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n" " -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
" -C Check configuration and return\n" " -C Check configuration and return\n"
" -s Show configuration parameters\n" " -s Show configuration parameters\n"
" -S Show configuration parameters, but ignore defaults\n" " -S Show configuration parameters, but ignore defaults\n"
" -h This message\n" " -h This message\n"
#ifndef WIN32 #ifndef WIN32
#ifdef SYSTEMD
" -L Log messages to journal\n"
#else
" -L Log messages to syslog\n"
#endif
" -u <user> Run as given user\n" " -u <user> Run as given user\n"
" -g <group> Run with given group permissions\n" " -g <group> Run with given group permissions\n"
" -p <file> Store pid in file (process id)\n" " -p <file> Store pid in file (process id)\n"
@ -288,7 +265,7 @@ void parse_command_line(int argc, char** argv)
arg_dump_config = 1; arg_dump_config = 1;
arg_check_config = 1; arg_check_config = 1;
break; break;
case 'S': case 'S':
arg_dump_config = 2; arg_dump_config = 2;
arg_check_config = 1; arg_check_config = 1;
@ -297,7 +274,7 @@ void parse_command_line(int argc, char** argv)
case 'l': case 'l':
arg_log = optarg; arg_log = optarg;
break; break;
case 'L': case 'L':
arg_log_syslog = 1; arg_log_syslog = 1;
break; break;
@ -471,7 +448,7 @@ int main(int argc, char** argv)
} }
else if (ret == 0) else if (ret == 0)
{ {
/* child process - detach from TTY */ /* child process - detatch from TTY */
fclose(stdin); fclose(stdin);
fclose(stdout); fclose(stdout);
fclose(stderr); fclose(stderr);

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -55,7 +55,7 @@ int handle_net_read(struct hub_user* user)
while ((pos = memchr(start, '\n', remaining))) while ((pos = memchr(start, '\n', remaining)))
{ {
lastPos = pos+1; lastPos = pos;
pos[0] = '\0'; pos[0] = '\0';
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
@ -109,7 +109,7 @@ int handle_net_write(struct hub_user* user)
int ret = 0; int ret = 0;
while (ioq_send_get_bytes(user->send_queue)) 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) if (ret <= 0)
break; break;
} }
@ -137,12 +137,6 @@ void net_event(struct net_connection* con, int event, void *arg)
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg); LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
#endif #endif
if (event == NET_EVENT_ERROR)
{
hub_disconnect_user(user->hub, user, quit_socket_error);
return;
}
if (event == NET_EVENT_TIMEOUT) if (event == NET_EVENT_TIMEOUT)
{ {
if (user_is_connecting(user)) if (user_is_connecting(user))

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -40,11 +40,14 @@ static int plugin_command_dispatch(struct command_base* cbase, struct hub_user*
LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix); LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix);
LIST_FOREACH(struct plugin_command_handle*, cmdh, data->commands, cmdh = (struct plugin_command_handle*) list_get_first(data->commands);
while (cmdh)
{ {
if (strcmp(cmdh->prefix, cmd->prefix) == 0) if (strcmp(cmdh->prefix, cmd->prefix) == 0)
return cmdh->handler(plugin, puser, pcommand); return cmdh->handler(plugin, puser, pcommand);
});
cmdh = (struct plugin_command_handle*) list_get_next(data->commands);
}
return 0; return 0;
} }
@ -65,17 +68,6 @@ static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user*
return 1; return 1;
} }
static int cbfunc_send_broadcast(struct plugin_handle* plugin, const char* message)
{
char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_all(plugin_get_hub(plugin), command);
adc_msg_free(command);
hub_free(buffer);
return 1;
}
static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message) static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
{ {
char code_str[4]; char code_str[4];
@ -112,6 +104,7 @@ static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_comman
cmdh->internal_handle = command; cmdh->internal_handle = command;
list_append(data->commands, cmdh); list_append(data->commands, cmdh);
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin); command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
return 0; return 0;
} }
@ -120,6 +113,7 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman
struct plugin_callback_data* data = get_callback_data(plugin); struct plugin_callback_data* data = get_callback_data(plugin);
struct command_handle* command = (struct command_handle*) cmdh->internal_handle; struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
list_remove(data->commands, cmdh); list_remove(data->commands, cmdh);
command_del(plugin_get_hub(plugin)->commands, command); command_del(plugin_get_hub(plugin)->commands, command);
hub_free(command); hub_free(command);
@ -139,12 +133,6 @@ struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* pl
return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t); return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t);
} }
static size_t cbfunc_get_usercount(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
return hub->users->count;
}
static char* cbfunc_get_hub_name(struct plugin_handle* plugin) static char* cbfunc_get_hub_name(struct plugin_handle* plugin)
{ {
struct hub_info* hub = plugin_get_hub(plugin); struct hub_info* hub = plugin_get_hub(plugin);
@ -170,7 +158,7 @@ static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str)
char* new_str = adc_msg_escape(str ? str : hub->config->hub_name); char* new_str = adc_msg_escape(str ? str : hub->config->hub_name);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str); adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str);
// Broadcast hub name // Broadcast hub name
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8)); command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str); adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str);
@ -187,7 +175,7 @@ static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char*
char* new_str = adc_msg_escape(str ? str : hub->config->hub_description); char* new_str = adc_msg_escape(str ? str : hub->config->hub_description);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str); adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str);
// Broadcast hub description // Broadcast hub description
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8)); command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str); adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str);
@ -200,14 +188,12 @@ static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char*
void plugin_register_callback_functions(struct plugin_handle* handle) void plugin_register_callback_functions(struct plugin_handle* handle)
{ {
handle->hub.send_message = cbfunc_send_message; handle->hub.send_message = cbfunc_send_message;
handle->hub.send_broadcast_message = cbfunc_send_broadcast;
handle->hub.send_status_message = cbfunc_send_status; handle->hub.send_status_message = cbfunc_send_status;
handle->hub.user_disconnect = cbfunc_user_disconnect; handle->hub.user_disconnect = cbfunc_user_disconnect;
handle->hub.command_add = cbfunc_command_add; handle->hub.command_add = cbfunc_command_add;
handle->hub.command_del = cbfunc_command_del; handle->hub.command_del = cbfunc_command_del;
handle->hub.command_arg_reset = cbfunc_command_arg_reset; handle->hub.command_arg_reset = cbfunc_command_arg_reset;
handle->hub.command_arg_next = cbfunc_command_arg_next; handle->hub.command_arg_next = cbfunc_command_arg_next;
handle->hub.get_usercount = cbfunc_get_usercount;
handle->hub.get_name = cbfunc_get_hub_name; handle->hub.get_name = cbfunc_get_hub_name;
handle->hub.set_name = cbfunc_set_hub_name; handle->hub.set_name = cbfunc_set_hub_name;
handle->hub.get_description = cbfunc_get_hub_description; handle->hub.get_description = cbfunc_get_hub_description;

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -27,12 +27,13 @@
PLUGIN_DEBUG(HUB, # FUNCNAME) \ PLUGIN_DEBUG(HUB, # FUNCNAME) \
if (HUB->plugins && HUB->plugins->loaded) \ if (HUB->plugins && HUB->plugins->loaded) \
{ \ { \
struct plugin_handle* plugin;\ struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(HUB->plugins->loaded); \
LIST_FOREACH(struct plugin_handle*, plugin, HUB->plugins->loaded, \ while (plugin) \
{ \ { \
if (plugin->funcs.FUNCNAME) \ if (plugin->funcs.FUNCNAME) \
CODE \ CODE \
}); \ plugin = (struct plugin_handle*) list_get_next(HUB->plugins->loaded); \
} \
} }
#define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \ #define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -102,6 +102,7 @@ struct plugin_handle* plugin_load(const char* filename, const char* config, stru
int ret; int ret;
struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle)); struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle));
struct uhub_plugin* plugin = plugin_open(filename); struct uhub_plugin* plugin = plugin_open(filename);
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
if (!plugin) if (!plugin)
return NULL; return NULL;
@ -117,7 +118,6 @@ struct plugin_handle* plugin_load(const char* filename, const char* config, stru
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister"); unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
// register hub internals // register hub internals
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
internals->unregister = unregister_f; internals->unregister = unregister_f;
internals->hub = hub; internals->hub = hub;
internals->callback_data = plugin_callback_data_create(); internals->callback_data = plugin_callback_data_create();
@ -229,16 +229,16 @@ int plugin_initialize(struct hub_config* config, struct hub_info* hub)
return 0; return 0;
} }
static void plugin_unload_ptr(void* ptr)
{
struct plugin_handle* plugin = (struct plugin_handle*) ptr;
plugin_unload(plugin);
}
void plugin_shutdown(struct uhub_plugins* handle) void plugin_shutdown(struct uhub_plugins* handle)
{ {
list_clear(handle->loaded, plugin_unload_ptr); struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(handle->loaded);
while (plugin)
{
list_remove(handle->loaded, plugin);
plugin_unload(plugin);
plugin = (struct plugin_handle*) list_get_first(handle->loaded);
}
list_destroy(handle->loaded); list_destroy(handle->loaded);
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -71,18 +71,9 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
probe_destroy(probe); probe_destroy(probe);
return; return;
} }
else if ((memcmp(probe_recvbuf, "GET ", 4) == 0) ||
(memcmp(probe_recvbuf, "POST", 4) == 0) ||
(memcmp(probe_recvbuf, "HEAD", 4) == 0))
{
/* Looks like HTTP - Not supported, but we log it. */
LOG_TRACE("Probed HTTP connection. Not supported closing connection (%s)", ip_convert_to_string(&probe->addr));
const char* buf = "501 Not implemented\r\n\r\n";
net_con_send(con, buf, strlen(buf));
}
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
else if (bytes >= 11 && else if (bytes >= 11 &&
probe_recvbuf[0] == 22 && probe_recvbuf[0] == 22 &&
probe_recvbuf[1] == 3 && /* protocol major version */ probe_recvbuf[1] == 3 && /* protocol major version */
probe_recvbuf[5] == 1 && /* message type */ probe_recvbuf[5] == 1 && /* message type */
probe_recvbuf[9] == probe_recvbuf[1]) probe_recvbuf[9] == probe_recvbuf[1])
@ -90,14 +81,11 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
if (probe->hub->config->tls_enable) if (probe->hub->config->tls_enable)
{ {
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[9], (int) probe_recvbuf[10]); LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[9], (int) probe_recvbuf[10]);
if (net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ctx) < 0) if (user_create(probe->hub, probe->connection, &probe->addr))
{
LOG_TRACE("TLS handshake negotiation failed.");
}
else if (user_create(probe->hub, probe->connection, &probe->addr))
{ {
probe->connection = 0; probe->connection = 0;
} }
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
} }
else else
{ {

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -28,7 +28,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
case 'B': /* Broadcast to all logged in clients */ case 'B': /* Broadcast to all logged in clients */
route_to_all(hub, msg); route_to_all(hub, msg);
break; break;
case 'D': case 'D':
target = uman_get_user_by_sid(hub->users, msg->target); target = uman_get_user_by_sid(hub->users, msg->target);
if (target) if (target)
@ -36,7 +36,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
route_to_user(hub, target, msg); route_to_user(hub, target, msg);
} }
break; break;
case 'E': case 'E':
target = uman_get_user_by_sid(hub->users, msg->target); target = uman_get_user_by_sid(hub->users, msg->target);
if (target) if (target)
@ -45,11 +45,11 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
route_to_user(hub, u, msg); route_to_user(hub, u, msg);
} }
break; break;
case 'F': case 'F':
route_to_subscribers(hub, msg); route_to_subscribers(hub, msg);
break; break;
default: default:
/* Ignore the message */ /* Ignore the message */
break; break;
@ -82,19 +82,16 @@ static int check_send_queue(struct hub_info* hub, struct hub_user* user, struct
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub)) if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
{ {
user_flag_set(user, flag_choke);
LOG_WARN("send queue overflowed, message discarded."); LOG_WARN("send queue overflowed, message discarded.");
return -1; return -1;
} }
if (user->send_queue->size > get_max_send_queue_soft(hub)) if (user->send_queue->size > get_max_send_queue_soft(hub))
{ {
user_flag_set(user, flag_choke);
LOG_WARN("send queue soft overflowed."); LOG_WARN("send queue soft overflowed.");
return 0; return 0;
} }
user_flag_unset(user, flag_choke);
return 1; return 1;
} }
@ -142,11 +139,12 @@ int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */ int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
{ {
struct hub_user* user; struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
LIST_FOREACH(struct hub_user*, user, hub->users->list, while (user)
{ {
route_to_user(hub, user, command); route_to_user(hub, user, command);
}); user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0; return 0;
} }
@ -155,40 +153,49 @@ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* i
{ {
int do_send; int do_send;
char* tmp; char* tmp;
struct hub_user* user; struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
LIST_FOREACH(struct hub_user*, user, hub->users->list, while (user)
{ {
if (user->feature_cast) if (user->feature_cast)
{ {
do_send = 1; do_send = 1;
LIST_FOREACH(char*, tmp, command->feature_cast_include, tmp = list_get_first(command->feature_cast_include);
while (tmp)
{ {
if (!user_have_feature_cast_support(user, tmp)) if (!user_have_feature_cast_support(user, tmp))
{ {
do_send = 0; do_send = 0;
break; break;
} }
}); tmp = list_get_next(command->feature_cast_include);;
}
if (!do_send)
if (!do_send) {
user = (struct hub_user*) list_get_next(hub->users->list);
continue; continue;
}
LIST_FOREACH(char*, tmp, command->feature_cast_exclude,
tmp = list_get_first(command->feature_cast_exclude);
while (tmp)
{ {
if (user_have_feature_cast_support(user, tmp)) if (user_have_feature_cast_support(user, tmp))
{ {
do_send = 0; do_send = 0;
break; break;
} }
}); tmp = list_get_next(command->feature_cast_exclude);
}
if (do_send) if (do_send)
{
route_to_user(hub, user, command); route_to_user(hub, user, command);
}
} }
}); user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0; return 0;
} }
@ -203,17 +210,20 @@ int route_info_message(struct hub_info* hub, struct hub_user* u)
struct adc_message* cmd = adc_msg_copy(u->info); struct adc_message* cmd = adc_msg_copy(u->info);
const char* address = user_get_address(u); const char* address = user_get_address(u);
struct hub_user* user = 0; struct hub_user* user = 0;
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address); adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
LIST_FOREACH(struct hub_user*, user, hub->users->list, user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{ {
if (user_is_nat_override(user)) if (user_is_nat_override(user))
route_to_user(hub, user, cmd); route_to_user(hub, user, cmd);
else else
route_to_user(hub, user, u->info); route_to_user(hub, user, u->info);
});
user = (struct hub_user*) list_get_next(hub->users->list);
}
adc_msg_free(cmd); adc_msg_free(cmd);
} }
return 0; return 0;

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -38,7 +38,7 @@ static const char* user_log_str(struct hub_user* user)
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr) struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
{ {
struct hub_user* user = NULL; struct hub_user* user = NULL;
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con)); LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user)); user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
@ -90,7 +90,7 @@ void user_set_state(struct hub_user* user, enum user_state state)
{ {
return; return;
} }
user->state = state; user->state = state;
} }
@ -135,7 +135,7 @@ void user_update_info(struct hub_user* u, struct adc_message* cmd)
prefix[1] = argument[1]; prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2); adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
} }
hub_free(argument); hub_free(argument);
argument = adc_msg_get_argument(cmd, n++); argument = adc_msg_get_argument(cmd, n++);
} }
@ -232,12 +232,15 @@ void user_support_remove(struct hub_user* user, int fourcc)
int user_have_feature_cast_support(struct hub_user* user, char feature[4]) int user_have_feature_cast_support(struct hub_user* user, char feature[4])
{ {
char* tmp; char* tmp = list_get_first(user->feature_cast);
LIST_FOREACH(char*, tmp, user->feature_cast, while (tmp)
{ {
if (strncmp(tmp, feature, 4) == 0) if (strncmp(tmp, feature, 4) == 0)
return 1; return 1;
});
tmp = list_get_next(user->feature_cast);
}
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -51,7 +51,7 @@ enum user_flags
flag_muted = 0x00800000, /** User is muted (cannot chat) */ flag_muted = 0x00800000, /** User is muted (cannot chat) */
flag_ignore = 0x01000000, /** Ignore further reads */ flag_ignore = 0x01000000, /** Ignore further reads */
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */ flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */ flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
flag_want_read = 0x08000000, /** Need to read (SSL) */ flag_want_read = 0x08000000, /** Need to read (SSL) */
flag_want_write = 0x10000000, /** Need to write (SSL) */ flag_want_write = 0x10000000, /** Need to write (SSL) */
flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */ flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */
@ -68,7 +68,7 @@ enum user_quit_reason
quit_timeout = 4, /** User timed out (no data for a while) */ quit_timeout = 4, /** User timed out (no data for a while) */
quit_send_queue = 5, /** User's send queue was overflowed */ quit_send_queue = 5, /** User's send queue was overflowed */
quit_memory_error = 6, /** Not enough memory available */ quit_memory_error = 6, /** Not enough memory available */
quit_socket_error = 7, /** A socket error occurred */ quit_socket_error = 7, /** A socket error occured */
quit_protocol_error = 8, /** Fatal protocol error */ quit_protocol_error = 8, /** Fatal protocol error */
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */ quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */ quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
@ -76,7 +76,7 @@ enum user_quit_reason
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */ quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
}; };
/** Returns an appropriate string for the given quit reason */ /** Returns an apropriate string for the given quit reason */
extern const char* user_get_quit_reason_string(enum user_quit_reason); extern const char* user_get_quit_reason_string(enum user_quit_reason);
struct hub_user_info struct hub_user_info
@ -150,7 +150,7 @@ extern void user_destroy(struct hub_user* user);
* This associates a INF message to the user. * This associates a INF message to the user.
* If the user already has a INF message associated, then this is * If the user already has a INF message associated, then this is
* released before setting the new one. * released before setting the new one.
* *
* @param info new inf message (can be NULL) * @param info new inf message (can be NULL)
*/ */
extern void user_set_info(struct hub_user* user, struct adc_message* info); extern void user_set_info(struct hub_user* user, struct adc_message* info);
@ -244,7 +244,7 @@ extern int user_flag_get(struct hub_user* user, enum user_flags flag);
* Check if a user supports 'feature' for feature casting (basis for 'Fxxx' messages) * Check if a user supports 'feature' for feature casting (basis for 'Fxxx' messages)
* The feature cast is specified as the 'SU' argument to the user's * The feature cast is specified as the 'SU' argument to the user's
* INF-message. * INF-message.
* *
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4') * @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
* @return 1 if 'feature' supported, or 0 otherwise * @return 1 if 'feature' supported, or 0 otherwise
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -28,7 +28,7 @@ static void clear_user_list_callback(void* ptr)
if (ptr) if (ptr)
{ {
struct hub_user* u = (struct hub_user*) ptr; struct hub_user* u = (struct hub_user*) ptr;
/* Mark the user as already being disconnected. /* Mark the user as already being disconnected.
* This prevents the hub from trying to send * This prevents the hub from trying to send
* quit messages to other users. * quit messages to other users.
@ -38,11 +38,42 @@ static void clear_user_list_callback(void* ptr)
} }
} }
static int uman_map_compare(const void* a, const void* b) #ifdef STATS_SUPPORT
void uman_update_stats(struct hub_user_manager* users)
{ {
return strcmp((const char*) a, (const char*) b); 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() struct hub_user_manager* uman_init()
{ {
@ -51,10 +82,24 @@ struct hub_user_manager* uman_init()
return NULL; return NULL;
users->list = list_create(); users->list = list_create();
users->nickmap = rb_tree_create(uman_map_compare, NULL, NULL);
users->cidmap = rb_tree_create(uman_map_compare, NULL, NULL);
users->sids = sid_pool_create(net_get_max_sockets()); users->sids = sid_pool_create(net_get_max_sockets());
if (!users->list)
{
list_destroy(users->list);
hub_free(users);
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; return users;
} }
@ -64,18 +109,19 @@ int uman_shutdown(struct hub_user_manager* users)
if (!users) if (!users)
return -1; return -1;
if (users->nickmap) #ifdef STATS_SUPPORT
rb_tree_destroy(users->nickmap); if (net_backend_get_timeout_queue())
{
if (users->cidmap) timeout_queue_remove(net_backend_get_timeout_queue(), users->timeout);
rb_tree_destroy(users->cidmap); hub_free(users->timeout);
}
#endif
if (users->list) if (users->list)
{ {
list_clear(users->list, &clear_user_list_callback); list_clear(users->list, &clear_user_list_callback);
list_destroy(users->list); list_destroy(users->list);
} }
sid_pool_destroy(users->sids); sid_pool_destroy(users->sids);
hub_free(users); hub_free(users);
@ -88,9 +134,6 @@ int uman_add(struct hub_user_manager* users, struct hub_user* user)
if (!users || !user) if (!users || !user)
return -1; return -1;
rb_tree_insert(users->nickmap, user->id.nick, user);
rb_tree_insert(users->cidmap, user->id.cid, user);
list_append(users->list, user); list_append(users->list, user);
users->count++; users->count++;
users->count_peak = MAX(users->count, users->count_peak); users->count_peak = MAX(users->count, users->count_peak);
@ -106,8 +149,6 @@ int uman_remove(struct hub_user_manager* users, struct hub_user* user)
return -1; return -1;
list_remove(users->list, user); list_remove(users->list, user);
rb_tree_remove(users->nickmap, user->id.nick);
rb_tree_remove(users->cidmap, user->id.cid);
if (users->count > 0) if (users->count > 0)
{ {
@ -132,29 +173,42 @@ struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid)
struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid) struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid)
{ {
struct hub_user* user = (struct hub_user*) rb_tree_get(users->cidmap, (const void*) cid); struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */
return user; while (user)
{
if (strcmp(user->id.cid, cid) == 0)
return user;
user = (struct hub_user*) list_get_next(users->list);
}
return NULL;
} }
struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick) struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick)
{ {
struct hub_user* user = (struct hub_user*) rb_tree_get(users->nickmap, nick); struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */
return user; while (user)
{
if (strcmp(user->id.nick, nick) == 0)
return user;
user = (struct hub_user*) list_get_next(users->list);
}
return NULL;
} }
size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range) size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range)
{ {
size_t num = 0; size_t num = 0;
struct hub_user* user; struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */
LIST_FOREACH(struct hub_user*, user, users->list, while (user)
{ {
if (ip_in_range(&user->id.addr, range)) if (ip_in_range(&user->id.addr, range))
{ {
list_append(target, user); list_append(target, user);
num++; num++;
} }
}); user = (struct hub_user*) list_get_next(users->list);
}
return num; return num;
} }
@ -163,8 +217,8 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st
int ret = 1; int ret = 1;
struct hub_user* user; struct hub_user* user;
user_flag_set(target, flag_user_list); user_flag_set(target, flag_user_list);
user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on INF or PAS msg */
LIST_FOREACH(struct hub_user*, user, users->list, while (user)
{ {
if (user_is_logged_in(user)) if (user_is_logged_in(user))
{ {
@ -172,7 +226,8 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st
if (!ret) if (!ret)
break; break;
} }
}); user = (struct hub_user*) list_get_next(users->list);
}
#if 0 #if 0
FIXME: FIXME FIXME handle send queue excess FIXME: FIXME FIXME handle send queue excess

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -24,12 +24,13 @@ struct hub_user_manager
{ {
size_t count; /**<< "Number of all fully connected and logged in users" */ size_t count; /**<< "Number of all fully connected and logged in users" */
size_t count_peak; /**<< "Peak number of users" */ size_t count_peak; /**<< "Peak number of users" */
struct sid_pool* sids;
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */ uint64_t shared_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." */ uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct sid_pool* sids; /**<< "Maps SIDs to users (constant time)" */
struct linked_list* list; /**<< "Contains all logged in users" */ struct linked_list* list; /**<< "Contains all logged in users" */
struct rb_tree* nickmap; /**<< "Maps nicknames to users (red black tree)" */ #ifdef STATS_SUPPORT
struct rb_tree* cidmap; /**<< "Maps CIDs to users (red black tree)" */ struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
#endif
}; };
/** /**
@ -42,7 +43,7 @@ extern struct hub_user_manager* uman_init();
* Shuts down the user manager. * Shuts down the user manager.
* All users will be disconnected and deleted as part of this. * All users will be disconnected and deleted as part of this.
* *
* @return 0 on success, or -1 in an error occurred (invalid pointer). * @return 0 on success, or -1 in an error occured (invalid pointer).
*/ */
extern int uman_shutdown(struct hub_user_manager* users); extern int uman_shutdown(struct hub_user_manager* users);
@ -79,7 +80,7 @@ extern sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user*
* *
* NOTE: This function will only search connected users, which means * NOTE: This function will only search connected users, which means
* that SIDs assigned to users who are not yet completely logged in, * that SIDs assigned to users who are not yet completely logged in,
* or are in the process of being disconnected will result in this * or are in the process of being disconnected will result in this
* function returning NULL even though the sid is not freely available. * function returning NULL even though the sid is not freely available.
* *
* FIXME: Is that really safe / sensible ? * FIXME: Is that really safe / sensible ?
@ -106,7 +107,7 @@ extern struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, co
* *
* @param[out] target the list of users matching the address * @param[out] target the list of users matching the address
* @param range the IP range of users to match * @param range the IP range of users to match
* @return The number of users matching the addresses, or -1 on error (mask is wrong). * @return The number of users matching the addressess, or -1 on error (mask is wrong).
*/ */
extern size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range); extern size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range);

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -102,7 +102,14 @@ void net_backend_shutdown()
} }
void net_backend_update(struct net_connection* con, int events) void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_update(struct net_connection* con, int events)
{ {
g_backend->handler.con_mod(g_backend->data, con, events); g_backend->handler.con_mod(g_backend->data, con, events);
} }
@ -125,11 +132,10 @@ struct timeout_queue* net_backend_get_timeout_queue()
*/ */
int net_backend_process() int net_backend_process()
{ {
int res = 0; int res;
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now); size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
if (g_backend->common.num) res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
g_backend->now = time(0); g_backend->now = time(0);
timeout_queue_process(&g_backend->timeout_queue, g_backend->now); timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
@ -140,9 +146,6 @@ int net_backend_process()
return 0; return 0;
} }
// Process pending DNS results
// net_dns_process();
g_backend->handler.backend_process(g_backend->data, res); g_backend->handler.backend_process(g_backend->data, res);
net_cleanup_process(g_backend->cleaner); net_cleanup_process(g_backend->cleaner);
@ -159,8 +162,8 @@ void net_con_initialize(struct net_connection* con, int sd, net_connection_cb ca
{ {
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr); g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
net_set_nonblocking(net_con_get_sd(con), 1); net_set_nonblocking(con->sd, 1);
net_set_nosigpipe(net_con_get_sd(con), 1); net_set_nosigpipe(con->sd, 1);
g_backend->handler.con_add(g_backend->data, con, events); g_backend->handler.con_add(g_backend->data, con, events);
g_backend->common.num++; g_backend->common.num++;
@ -178,8 +181,11 @@ void net_con_close(struct net_connection* con)
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (con->ssl) if (con->ssl)
net_ssl_shutdown(con); {
#endif /* SSL_SUPPORT */ SSL_shutdown(con->ssl);
SSL_clear(con->ssl);
}
#endif
net_close(con->sd); net_close(con->sd);
con->sd = -1; con->sd = -1;

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -75,14 +75,6 @@ extern void net_backend_shutdown();
*/ */
extern int net_backend_process(); extern int net_backend_process();
/**
* Update the event mask.
*
* @param con Connection handle.
* @param events Event mask (NET_EVENT_*)
*/
extern void net_backend_update(struct net_connection* con, int events);
/** /**
* Get the current time. * Get the current time.
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,17 +13,18 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#define NET_WANT_READ NET_EVENT_READ #define NET_WANT_READ NET_EVENT_READ
#define NET_WANT_WRITE NET_EVENT_WRITE #define NET_WANT_WRITE NET_EVENT_WRITE
#define NET_WANT_ACCEPT NET_EVENT_READ #define NET_WANT_ACCEPT NET_EVENT_READ
#define NET_WANT_SSL_READ 0x0010
#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 #define NET_WANT_SSL_WRITE 0x0020
#define NET_WANT_SSL_ACCEPT 0x0040
struct ssl_handle; /* abstract type */ #define NET_WANT_SSL_CONNECT 0x0080
#define NET_WANT_SSL_X509_LOOKUP 0x0100
#define NET_CLEANUP 0x8000 #define NET_CLEANUP 0x8000
@ -35,7 +36,9 @@ struct ssl_handle; /* abstract type */
struct timeout_evt* timeout; /** timeout event handler */ struct timeout_evt* timeout; /** timeout event handler */
#define NET_CON_STRUCT_SSL \ #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 #ifdef SSL_SUPPORT
#define NET_CON_STRUCT_COMMON \ #define NET_CON_STRUCT_COMMON \

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,26 +13,139 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "uhub.h" #include "uhub.h"
#include "network/common.h" #include "network/common.h"
#include "network/backend.h"
static int is_blocked_or_interrupted() #ifdef SSL_SUPPORT
enum uhub_tls_state
{ {
int err = net_error(); tls_st_none,
return tls_st_error,
#ifdef WINSOCK tls_st_accepting,
err == WSAEWOULDBLOCK tls_st_connecting,
#else tls_st_connected,
err == EWOULDBLOCK tls_st_disconnecting,
#endif };
|| err == EINTR;
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) ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
{ {
int ret; int ret;
@ -43,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); ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
if (ret == -1) 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 0;
return -1; return -1;
} }
@ -51,9 +170,19 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
} }
else 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; return ret;
} }
@ -61,13 +190,19 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{ {
int ret; int ret;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (!con->ssl) if (!net_con_is_ssl(con))
{ {
#endif #endif
ret = net_recv(con->sd, buf, len, 0); ret = net_recv(con->sd, buf, len, 0);
if (ret == -1) 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 0;
return -net_error(); return -net_error();
} }
@ -79,9 +214,22 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
} }
else 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; return ret;
} }
@ -90,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); int ret = net_recv(con->sd, buf, len, MSG_PEEK);
if (ret == -1) 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 0;
return -net_error(); return -net_error();
} }
@ -100,10 +254,19 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
} }
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
int net_con_is_ssl(struct net_connection* con) 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 */ #endif /* SSL_SUPPORT */
@ -117,28 +280,10 @@ void* net_con_get_ptr(struct net_connection* con)
return con->ptr; return con->ptr;
} }
void net_con_update(struct net_connection* con, int events)
{
#ifdef SSL_SUPPORT
if (con->ssl)
net_ssl_update(con, events);
else
#endif
net_backend_update(con, events);
}
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_destroy(struct net_connection* con) void net_con_destroy(struct net_connection* con)
{ {
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (con && con->ssl) SSL_free(con->ssl);
net_ssl_destroy(con);
#endif #endif
hub_free(con); hub_free(con);
} }
@ -156,402 +301,62 @@ void net_con_callback(struct net_connection* con, int events)
} }
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (con->ssl) if (!con->ssl)
net_ssl_callback(con, events); {
else
#endif #endif
con->callback(con, events, con->ptr); con->callback(con, events, con->ptr);
} #ifdef SSL_SUPPORT
struct net_connect_job
{
struct net_connection* con;
struct net_connect_handle* handle;
struct sockaddr_storage addr;
struct net_connect_job* next;
};
struct net_connect_handle
{
const char* address;
uint16_t port;
void* ptr;
net_connect_cb callback;
struct net_dns_job* dns;
const struct net_dns_result* result;
struct net_connect_job* job4;
struct net_connect_job* job6;
};
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con);
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr);
/**
* Check if a connection job is completed.
* @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected).
*/
static int net_connect_job_check(struct net_connect_job* job)
{
struct net_connection* con = job->con;
int af = job->addr.ss_family;
enum net_connect_status status;
int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
LOG_TRACE("net_connect_job_check(): Socket connected!");
job->con = NULL;
net_con_clear_timeout(con);
net_connect_callback(job->handle, net_connect_status_ok, con);
return 1;
}
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
{
return 0;
}
LOG_TRACE("net_connect_job_check(): Socket error!");
switch (net_error())
{
case ECONNREFUSED:
status = net_connect_status_refused;
break;
case ENETUNREACH:
status = net_connect_status_unreachable;
break;
default:
status = net_connect_status_socket_error;
}
net_connect_callback(job->handle, status, NULL);
return -1;
}
static void net_connect_job_free(struct net_connect_job* job)
{
if (job->con)
net_con_close(job->con);
job->handle = NULL;
job->next = NULL;
hub_free(job);
}
static void net_connect_job_stop(struct net_connect_job* job)
{
if (job->addr.ss_family == AF_INET6)
{
job->handle->job6 = job->next;
} }
else else
{ {
job->handle->job4 = job->next; #ifdef NETWORK_DUMP_DEBUG
} LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
#endif
net_connect_job_free(job); switch (con->ssl_state)
}
static int net_connect_depleted(struct net_connect_handle* handle)
{
return (!handle->job6 && !handle->job4);
}
static int net_connect_job_process(struct net_connect_job* job)
{
int sd;
if (!job->con)
{
sd = net_socket_create(job->addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1)
{ {
LOG_DEBUG("net_connect_job_process: Unable to create socket!"); case tls_st_none:
net_connect_callback(job->handle, net_connect_status_socket_error, NULL); con->callback(con, events, con->ptr);
return -1; // FIXME break;
}
job->con = net_con_create(); case tls_st_error:
net_con_initialize(job->con, sd, net_connect_job_internal_cb, job, NET_EVENT_WRITE); con->callback(con, NET_EVENT_READ, con->ptr);
net_con_set_timeout(job->con, TIMEOUT_CONNECTED); // FIXME: Use a proper timeout value! break;
}
return net_connect_job_check(job); 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:
* Internal callback used to establish an outbound connection. 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)
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr) {
{ con->callback(con, events & NET_EVENT_READ, con->ptr);
struct net_connect_job* job = net_con_get_ptr(con); return;
struct net_connect_job* next_job = job->next; }
struct net_connect_handle* handle = job->handle;
if (event == NET_EVENT_TIMEOUT) if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
{ {
// FIXME: Try next address, or if no more addresses left declare failure to connect. con->callback(con, events & NET_EVENT_READ, con->ptr);
if (job->addr.ss_family == AF_INET6) return;
{ }
net_connect_job_stop(job);
if (!next_job) con->callback(con, events, con->ptr);
{ break;
LOG_TRACE("No more IPv6 addresses to try!");
}
} case tls_st_disconnecting:
else return;
{
net_connect_job_stop(job);
if (!next_job)
{
LOG_TRACE("No more IPv4 addresses to try!");
}
}
if (net_connect_depleted(handle))
{
LOG_TRACE("No more addresses left. Unable to connect!");
net_connect_callback(handle, net_connect_status_timeout, NULL);
}
return;
}
if (event == NET_EVENT_WRITE)
{
net_connect_job_process(job);
}
}
static void net_connect_cancel(struct net_connect_handle* handle)
{
struct net_connect_job* job;
job = handle->job6;
while (job)
{
job = job->next;
net_connect_job_free(handle->job6);
handle->job6 = job;
}
job = handle->job4;
while (job)
{
job = job->next;
net_connect_job_free(handle->job4);
handle->job4 = job;
}
}
static int net_connect_process_queue(struct net_connect_handle* handle, struct net_connect_job* job)
{
int ret;
while (job)
{
ret = net_connect_job_process(job);
if (ret < 0)
{
net_connect_job_stop(job);
continue;
}
else if (ret == 0)
{
// Need to process again
return 0;
}
else
{
// FIXME: Success!
return 1;
} }
} }
return -1; #endif
}
static int net_connect_process(struct net_connect_handle* handle)
{
int ret4, ret6;
ret6 = net_connect_process_queue(handle, handle->job6);
if (ret6 == 1)
return 1; // Connected - cool!
net_connect_process_queue(handle, handle->job4);
return 0;
}
static int net_connect_job_schedule(struct net_connect_handle* handle, struct ip_addr_encap* addr)
{
struct net_connect_job* job;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
if (addr->af == AF_INET6 && !net_is_ipv6_supported())
{
LOG_TRACE("net_connect_job_schedule(): Skipping IPv6 support since IPv6 is not supported.");
return 0;
}
else
{
job = hub_malloc_zero(sizeof(struct net_connect_job));
job->handle = handle;
if (addr->af == AF_INET6)
{
addr6 = (struct sockaddr_in6*) &job->addr;
LOG_TRACE("net_connect_job_schedule(): Scheduling IPv6 connect job.");
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(handle->port);
memcpy(&addr6->sin6_addr, &addr->internal_ip_data.in6, sizeof(struct in6_addr));
// prepend
job->next = handle->job6;
handle->job6 = job;
}
else
{
addr4 = (struct sockaddr_in*) &job->addr;
LOG_TRACE("net_connect_job_schedule(): Scheduling IPv4 connect job.");
addr4->sin_family = AF_INET;
addr4->sin_port = htons(handle->port);
memcpy(&addr4->sin_addr, &addr->internal_ip_data.in, sizeof(struct in_addr));
// prepend
job->next = handle->job4;
handle->job4 = job;
}
}
return 1;
}
/*
* Callback when the DNS results are ready.
* Create a list of IPv6 and IPv4 addresses, then
* start connecting to them one by one until one succeeds.
*/
static int net_con_connect_dns_callback(struct net_dns_job* job, const struct net_dns_result* result)
{
struct ip_addr_encap* addr;
struct net_connect_handle* handle = (struct net_connect_handle*) net_dns_job_get_ptr(job);
handle->dns = NULL;
size_t usable = 0;
LOG_TRACE("net_con_connect(): async - Got DNS results");
if (!result)
{
LOG_DEBUG("net_con_connect() - Unable to lookup host!");
net_connect_callback(handle, net_connect_status_dns_error, NULL);
return 1;
}
if (!net_dns_result_size(result))
{
LOG_DEBUG("net_con_connect() - Host not found!");
net_connect_callback(handle, net_connect_status_host_not_found, NULL);
return 1;
}
handle->result = result;
// Extract results into a separate list of IPv4 and IPv6 addresses.
addr = net_dns_result_first(result);
while (addr)
{
if (net_connect_job_schedule(handle, addr))
usable++;
addr = net_dns_result_next(result);
}
net_connect_process(handle);
return 0;
}
// typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_handle_code, struct net_connection* con);
struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr)
{
struct net_connect_handle* handle = hub_malloc_zero(sizeof(struct net_connect_handle));
handle->address = hub_strdup(address);
handle->port = port;
handle->ptr = ptr;
handle->callback = callback;
// FIXME: Check if DNS resolving is necessary ?
handle->dns = net_dns_gethostbyname(address, AF_UNSPEC, net_con_connect_dns_callback, handle);
if (!handle->dns)
{
LOG_TRACE("net_con_connect(): Unable to create DNS lookup job.");
hub_free((char*) handle->address);
hub_free(handle);
return NULL;
}
return handle;
}
void net_connect_destroy(struct net_connect_handle* handle)
{
hub_free((char*) handle->address);
// cancel DNS job if pending
if (handle->dns)
net_dns_job_cancel(handle->dns);
// Stop any connect jobs.
net_connect_cancel(handle);
// free any DNS results
net_dns_result_free(handle->result);
hub_free(handle);
}
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con)
{
uhub_assert(handle->callback != NULL);
// Call the callback
handle->callback(handle, status, con, handle->ptr);
handle->callback = NULL;
// Cleanup
net_connect_destroy(handle);
}
static void timeout_callback(struct timeout_evt* evt)
{
net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
if (!con->timeout)
{
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(con->timeout, timeout_callback, con);
timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
}
else
{
timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
}
}
void net_con_clear_timeout(struct net_connection* con)
{
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
{
timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
hub_free(con->timeout);
con->timeout = 0;
}
} }

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -23,53 +23,20 @@
#include "uhub.h" #include "uhub.h"
#include "network/common.h" #include "network/common.h"
#include "network/backend.h" #include "network/backend.h"
#include "network/tls.h"
#define NET_EVENT_TIMEOUT 0x0001 #define NET_EVENT_TIMEOUT 0x0001
#define NET_EVENT_READ 0x0002 #define NET_EVENT_READ 0x0002
#define NET_EVENT_WRITE 0x0004 #define NET_EVENT_WRITE 0x0004
#define NET_EVENT_ERROR 0x1000
struct net_connection struct net_connection
{ {
NET_CON_STRUCT_COMMON NET_CON_STRUCT_COMMON
}; };
struct net_connect_handle;
enum net_connect_status
{
net_connect_status_ok = 0,
net_connect_status_host_not_found = -1,
net_connect_status_no_address = -2,
net_connect_status_dns_error = -3,
net_connect_status_refused = -4,
net_connect_status_unreachable = -5,
net_connect_status_timeout = -6,
net_connect_status_socket_error = -7,
};
typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_status status, struct net_connection* con, void* ptr);
extern int net_con_get_sd(struct net_connection* con); extern int net_con_get_sd(struct net_connection* con);
extern void* net_con_get_ptr(struct net_connection* con); extern void* net_con_get_ptr(struct net_connection* con);
extern struct net_connection* net_con_create(); extern struct net_connection* net_con_create();
/**
* Establish an outbound TCP connection.
* This will resolve the IP-addresses, and connect to
* either an IPv4 or IPv6 address depending if it is supported,
* and using the happy eyeballs algorithm.
*
* @param address Hostname, IPv4 or IPv6 address
* @param port TCP port number
* @param callback A callback to be called once the connection is established, or failed.
* @returns a handle to the connection establishment job, or NULL if an immediate error.
*/
extern struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr);
extern void net_connect_destroy(struct net_connect_handle* handle);
extern void net_con_destroy(struct net_connection*); extern void net_con_destroy(struct net_connection*);
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events); extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events); extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
@ -88,7 +55,7 @@ extern void net_con_close(struct net_connection* con);
* *
* @return returns the number of bytes sent. * @return returns the number of bytes sent.
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR) * 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
* <0 if an error occurred, the negative number contains the error code. * <0 if an error occured, the negative number contains the error code.
*/ */
extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len); extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len);
@ -97,7 +64,7 @@ extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t
* *
* @return returns the number of bytes sent. * @return returns the number of bytes sent.
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR) * 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
* <0 if an error occurred, the negative number contains the error code. * <0 if an error occured, the negative number contains the error code.
*/ */
extern ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len); extern ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len);
@ -109,12 +76,36 @@ extern ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len);
extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len); extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len);
/** /**
* Set timeout for connection. * Set timeout for connetion.
* *
* @param seconds the number of seconds into the future. * @param seconds the number of seconds into the future.
*/ */
extern void net_con_set_timeout(struct net_connection* con, int seconds); extern void net_con_set_timeout(struct net_connection* con, int seconds);
extern void net_con_clear_timeout(struct net_connection* con); 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 */ #endif /* HAVE_UHUB_NETWORK_CONNECTION_H */

View File

@ -1,391 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, 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 <https://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);
}
static void notify_callback(struct uhub_notify_handle* handle, void* ptr)
{
net_dns_process();
}
// 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;
struct uhub_notify_handle* notify_handle; // used to signal back to the event loop that there is something to process.
};
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);
g_dns->notify_handle = net_notify_create(notify_callback, g_dns);
}
void net_dns_destroy()
{
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);
net_notify_destroy(g_dns->notify_handle);
hub_free(g_dns);
g_dns = NULL;
}
void net_dns_process()
{
struct net_dns_result* result;
uhub_mutex_lock(&g_dns->mutex);
LOG_TRACE("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results));
LIST_FOREACH(struct net_dns_result*, result, 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, NULL);
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);
net_notify_signal(g_dns->notify_handle, 1);
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;
LIST_FOREACH(struct net_dns_job*, it, 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;
LIST_FOREACH(struct net_dns_result*, it, 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", ipaddr ? ip_convert_to_string(ipaddr) : "(no address)");
return ipaddr;
}
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_next(res->addr_list);
LOG_TRACE("net_dns_result_next() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no more addresses)");
return ipaddr;
}
extern void net_dns_result_free(const struct net_dns_result* res)
{
if (!res)
return;
list_clear(res->addr_list, &hub_free);
list_destroy(res->addr_list);
free_job(res->job);
hub_free((struct net_dns_result*) res);
}

View File

@ -1,119 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, 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 <https://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(const struct net_dns_result*);
#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2019, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -49,21 +49,21 @@ int net_initialize()
} }
#endif /* WINSOCK */ #endif /* WINSOCK */
if (!net_backend_init() if (!net_backend_init())
#ifdef SSL_SUPPORT
|| !net_ssl_library_init()
#endif
)
{ {
#ifdef WINSOCK #ifdef WINSOCK
WSACleanup(); WSACleanup();
#endif #endif
return -1; return -1;
} }
net_dns_initialize();
net_stats_initialize(); net_stats_initialize();
#ifdef SSL_SUPPORT
LOG_TRACE("Initializing OpenSSL...");
SSL_library_init();
SSL_load_error_strings();
#endif /* SSL_SUPPORT */
net_initialized = 1; net_initialized = 1;
return 0; return 0;
} }
@ -97,13 +97,13 @@ int net_destroy()
{ {
LOG_TRACE("Shutting down network monitor"); LOG_TRACE("Shutting down network monitor");
net_dns_destroy();
net_backend_shutdown(); net_backend_shutdown();
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
net_ssl_library_shutdown(); ERR_free_strings();
#endif /* SSL_SUPPORT */ EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
#endif
#ifdef WINSOCK #ifdef WINSOCK
WSACleanup(); WSACleanup();
@ -449,7 +449,7 @@ int net_is_ipv6_supported()
is_ipv6_supported = 0; is_ipv6_supported = 0;
return 0; return 0;
} }
net_error_out(ret, "net_is_ipv6_supported"); net_error_out(ret, "net_is_ipv6_supported");
} }
else else
@ -495,6 +495,7 @@ int net_socket_create(int af, int type, int protocol)
} }
} }
#endif #endif
return sd; return sd;
} }
@ -508,7 +509,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
size_t size; size_t size;
LPSOCKADDR addr; LPSOCKADDR addr;
DWORD len = cnt; DWORD len = cnt;
switch (af) switch (af)
{ {
case AF_INET: case AF_INET:
@ -531,7 +532,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
default: default:
return NULL; return NULL;
} }
if (WSAAddressToStringA(addr, size, NULL, dst, &len) == 0) if (WSAAddressToStringA(addr, size, NULL, dst, &len) == 0)
{ {
return dst; return dst;
@ -602,15 +603,15 @@ const char* net_get_peer_address(int fd)
struct sockaddr_in* name4; struct sockaddr_in* name4;
struct sockaddr* name; struct sockaddr* name;
socklen_t namelen; socklen_t namelen;
memset(address, 0, INET6_ADDRSTRLEN); memset(address, 0, INET6_ADDRSTRLEN);
namelen = sizeof(struct sockaddr_storage); namelen = sizeof(struct sockaddr_storage);
memset(&storage, 0, namelen); memset(&storage, 0, namelen);
name6 = (struct sockaddr_in6*) &storage; name6 = (struct sockaddr_in6*) &storage;
name4 = (struct sockaddr_in*) &storage; name4 = (struct sockaddr_in*) &storage;
name = (struct sockaddr*) &storage; name = (struct sockaddr*) &storage;
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1) if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
{ {
int af = storage.ss_family; int af = storage.ss_family;
@ -805,22 +806,4 @@ void net_stats_add_close()
stats.closed++; stats.closed++;
} }
void net_stats_tls_add_accept()
{
stats.tls_accept++;
}
void net_stats_tls_add_connect()
{
stats.tls_connect++;
}
void net_stats_tls_add_error()
{
stats.tls_error++;
}
void net_stats_tls_add_close()
{
stats.tls_close++;
}

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2019, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@ -28,14 +28,9 @@ struct net_statistics
size_t accept; size_t accept;
size_t closed; size_t closed;
size_t errors; size_t errors;
size_t tls_accept;
size_t tls_connect;
size_t tls_error;
size_t tls_close;
}; };
struct net_socket_t; struct net_socket_t;
struct ip_addr_encap;
/** /**
* Initialize the socket monitor subsystem. * Initialize the socket monitor subsystem.
@ -57,7 +52,7 @@ extern int net_initialize();
extern int net_destroy(); extern int net_destroy();
/** /**
* @return the number of sockets currently being monitored. * @return the number of sockets currrently being monitored.
*/ */
extern int net_monitor_count(); extern int net_monitor_count();
@ -67,7 +62,7 @@ extern int net_monitor_count();
extern int net_monitor_capacity(); extern int net_monitor_capacity();
/** /**
* @return the last error code occurred. * @return the last error code occured.
* *
* NOTE: On Windows this is the last error code from the socket library, but * NOTE: On Windows this is the last error code from the socket library, but
* on UNIX this is the errno variable that can be overwritten by any * on UNIX this is the errno variable that can be overwritten by any
@ -251,14 +246,9 @@ extern void net_stats_report();
extern void net_stats_reset(); extern void net_stats_reset();
extern void net_stats_add_tx(size_t bytes); extern void net_stats_add_tx(size_t bytes);
extern void net_stats_add_rx(size_t bytes); extern void net_stats_add_rx(size_t bytes);
extern void net_stats_tls_add_accept();
extern void net_stats_tls_add_connect();
extern void net_stats_tls_add_error();
extern void net_stats_tls_add_close();
extern void net_stats_add_accept(); extern void net_stats_add_accept();
extern void net_stats_add_error(); extern void net_stats_add_error();
extern void net_stats_add_close(); extern void net_stats_add_close();
extern void net_stats_add_connect();
extern int net_stats_timeout(); extern int net_stats_timeout();
extern void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total); extern void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total);

View File

@ -1,102 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, 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 <https://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
struct uhub_notify_handle
{
net_notify_callback callback;
void* ptr;
#ifndef WIN32
int pipe_fd[2];
struct net_connection* con;
#endif
};
/*
* This contains a mechanism to wake up the main thread
* in a thread safe manner while it would be blocking
* in select() or something equivalent typically invoked from
* net_backend_process().
*
* The main usage is for the DNS resolver to notify the
* main thread that there are DNS results to be
* processed.
*/
/**
* Create a notification handle.
*/
#ifndef WIN32
static void notify_callback(struct net_connection* con, int event, void* ptr)
{
LOG_TRACE("notify_callback()");
struct uhub_notify_handle* handle = (struct uhub_notify_handle*) ptr;
char buf;
int ret = read(handle->pipe_fd[0], &buf, 1);
if (ret == 1)
{
if (handle->callback)
handle->callback(handle, handle->ptr);
}
}
#endif
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr)
{
LOG_TRACE("net_notify_create()");
struct uhub_notify_handle* handle = (struct uhub_notify_handle*) hub_malloc(sizeof(struct uhub_notify_handle));
handle->callback = cb;
handle->ptr = ptr;
#ifndef WIN32
int ret = pipe(handle->pipe_fd);
if (ret == -1)
{
LOG_ERROR("Unable to setup notification pipes.");
hub_free(handle);
return 0;
}
handle->con = net_con_create();
net_con_initialize(handle->con, handle->pipe_fd[0], notify_callback, handle, NET_EVENT_READ);
#endif
return handle;
}
void net_notify_destroy(struct uhub_notify_handle* handle)
{
LOG_TRACE("net_notify_destroy()");
#ifndef WIN32
net_con_destroy(handle->con);
close(handle->pipe_fd[0]);
close(handle->pipe_fd[1]);
handle->pipe_fd[0] = -1;
handle->pipe_fd[0] = -1;
#endif
hub_free(handle);
}
void net_notify_signal(struct uhub_notify_handle* handle, char data)
{
LOG_TRACE("net_notify_signal()");
#ifndef WIN32
write(handle->pipe_fd[1], &data, 1);
#endif
}

View File

@ -1,56 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, 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 <https://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_NOTIFY_API_H
#define HAVE_UHUB_NETWORK_NOTIFY_API_H
struct uhub_notify_handle;
typedef void (*net_notify_callback)(struct uhub_notify_handle* handle, void* ptr);
/*
* This contains a mechanism to wake up the main thread
* in a thread safe manner while it would be blocking
* in select() or something equivalent typically invoked from
* net_backend_process().
*
* The main usage is for the DNS resolver to notify the
* main thread that there are DNS results to be
* processed.
*/
/**
* Create a notification handle.
*/
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr);
/**
* Destroy a notification handle.
*/
void net_notify_destroy(struct uhub_notify_handle*);
/**
* Signal the notification handle, this will surely
* interrupt the net_backend_process(), and force it to
* process messages.
*/
void net_notify_signal(struct uhub_notify_handle*, char data);
#endif /* HAVE_UHUB_NETWORK_NOTIFY_API_H */

View File

@ -1,564 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2019, 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 <https://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#include "network/common.h"
#include "network/tls.h"
#include "network/backend.h"
#ifdef SSL_SUPPORT
#ifdef SSL_USE_OPENSSL
void net_stats_add_tx(size_t bytes);
void net_stats_add_rx(size_t bytes);
void net_stats_tls_add_accept();
void net_stats_tls_add_errors();
void net_stats_tls_add_accept();
struct net_ssl_openssl
{
SSL* ssl;
BIO* bio;
enum ssl_state state;
int events;
int ssl_read_events;
int ssl_write_events;
uint32_t flags;
size_t bytes_rx;
size_t bytes_tx;
};
struct net_context_openssl
{
SSL_CTX* ssl;
};
static struct net_ssl_openssl* get_handle(struct net_connection* con)
{
uhub_assert(con);
return (struct net_ssl_openssl*) con->ssl;
}
#ifdef DEBUG
static const char* get_state_str(enum ssl_state state)
{
switch (state)
{
case tls_st_none: return "tls_st_none";
case tls_st_error: return "tls_st_error";
case tls_st_accepting: return "tls_st_accepting";
case tls_st_connecting: return "tls_st_connecting";
case tls_st_connected: return "tls_st_connected";
case tls_st_disconnecting: return "tls_st_disconnecting";
}
uhub_assert(!"This should not happen - invalid state!");
return "(UNKNOWN STATE)";
}
#endif
static void net_ssl_set_state(struct net_ssl_openssl* handle, enum ssl_state new_state)
{
LOG_DEBUG("net_ssl_set_state(): prev_state=%s, new_state=%s", get_state_str(handle->state), get_state_str(new_state));
handle->state = new_state;
}
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();
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_remove_state(0);
#endif
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 OPENSSL_VERSION_NUMBER < 0x10100000L
unsigned long num_read = handle->bio->num_read;
unsigned long num_write = handle->bio->num_write;
#else
unsigned long num_read = BIO_number_read(handle->bio);
unsigned long num_write = BIO_number_written(handle->bio);
#endif
if (num_read > handle->bytes_rx)
{
net_stats_add_rx(num_read - handle->bytes_rx);
handle->bytes_rx = num_read;
}
if (num_write > handle->bytes_tx)
{
net_stats_add_tx(num_write - handle->bytes_tx);
handle->bytes_tx = num_write;
}
}
static const SSL_METHOD* get_ssl_method(const char* tls_version, long* flags)
{
if (!flags)
{
LOG_ERROR("flags is null");
return 0;
}
if (!tls_version || !*tls_version)
{
LOG_ERROR("tls_version is not set.");
return 0;
}
*flags = 0;
*flags |= SSL_OP_NO_SSLv2;
*flags |= SSL_OP_NO_SSLv3;
if (!strcmp(tls_version, "1.0"))
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return TLSv1_method();
#endif
}
else if (!strcmp(tls_version, "1.1"))
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return TLSv1_1_method();
#else
*flags |= SSL_OP_NO_TLSv1;
#endif
}
else if (!strcmp(tls_version, "1.2"))
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return TLSv1_2_method();
#else
*flags |= SSL_OP_NO_TLSv1;
*flags |= SSL_OP_NO_TLSv1_1;
#endif
}
else if (!strcmp(tls_version, "1.3"))
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
LOG_ERROR("TLS 1.3 is not supported by this version of OpenSSL");
return 0;
#else
*flags |= SSL_OP_NO_TLSv1;
*flags |= SSL_OP_NO_TLSv1_1;
*flags |= SSL_OP_NO_TLSv1_2;
#endif
}
else
{
LOG_ERROR("Unable to recognize tls_version: %s", tls_version);
return 0;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
// never gets here!
#else
return TLS_method();
#endif
}
/**
* List of supported protocols for ALPN.
* We only support "adc" protocol.
*/
unsigned char alpn_protocols[] = {
3, 'a', 'd', 'c',
};
/**
* Callback for the server to select a protocol from the list
* sent by the client via ALPN.
*/
static int alpn_server_select_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *arg)
{
int res = SSL_select_next_proto((unsigned char **)out, outlen,
alpn_protocols, sizeof(alpn_protocols), in, inlen);
if (res == OPENSSL_NPN_NO_OVERLAP)
{
// set default protocol
*out = alpn_protocols;
*outlen = 1+alpn_protocols[0];
}
return SSL_TLSEXT_ERR_OK;
}
/**
* Create a new SSL context.
*/
struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl));
long flags = 0;
const SSL_METHOD* ssl_method = get_ssl_method(tls_version, &flags);
if (!ssl_method)
{
hub_free(ctx);
return 0;
}
ctx->ssl = SSL_CTX_new(ssl_method);
// FIXME: Why did we need this again?
SSL_CTX_set_quiet_shutdown(ctx->ssl, 1);
#ifdef SSL_OP_NO_COMPRESSION
/* Disable compression */
LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */
flags |= SSL_OP_NO_COMPRESSION;
#endif
// Set flags
SSL_CTX_set_options(ctx->ssl, flags);
/* Set preferred cipher suite */
if (SSL_CTX_set_cipher_list(ctx->ssl, tls_ciphersuite) != 1)
{
LOG_ERROR("Unable to set cipher suite.");
SSL_CTX_free(ctx->ssl);
hub_free(ctx);
return 0;
}
SSL_CTX_set_alpn_select_cb(ctx->ssl, alpn_server_select_protocol, NULL);
return (struct ssl_context_handle*) ctx;
}
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);
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_chain_file(ctx->ssl, pem_file) < 0)
{
LOG_ERROR("SSL_CTX_use_certificate_chain_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, 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) != 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, int read)
{
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:
if (read)
handle->ssl_read_events = NET_EVENT_READ;
else
handle->ssl_write_events = NET_EVENT_READ;
return 0;
case SSL_ERROR_WANT_WRITE:
if (read)
handle->ssl_read_events = NET_EVENT_WRITE;
else
handle->ssl_write_events = NET_EVENT_WRITE;
return 0;
case SSL_ERROR_SSL:
net_ssl_set_state(handle, tls_st_error);
net_stats_tls_add_error();
return -2;
case SSL_ERROR_SYSCALL:
net_ssl_set_state(handle, tls_st_error);
net_stats_tls_add_error();
return -2;
}
net_stats_tls_add_error();
return -2;
}
ssize_t net_con_ssl_accept(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
ssize_t ret;
net_ssl_set_state(handle, tls_st_accepting);
ret = SSL_accept(handle->ssl);
LOG_PROTO("SSL_accept() ret=%d", ret);
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
net_ssl_set_state(handle, tls_st_connected);
net_stats_tls_add_accept();
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;
net_ssl_set_state(handle, tls_st_connecting);
ret = SSL_connect(handle->ssl);
LOG_PROTO("SSL_connect() ret=%d", ret);
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
net_ssl_set_state(handle, tls_st_connected);
net_stats_tls_add_connect();
return ret;
}
ret = handle_openssl_error(con, ret, tls_st_connecting);
if (ret != 0)
LOG_ERROR("net_con_ssl_connect: ret=%d", ret);
return ret;
}
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);
uhub_assert(ssl_ctx);
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);
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(ctx->ssl);
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);
LOG_TRACE("net_ssl_send(), state=%d", (int) handle->state);
if (handle->state == tls_st_error)
return -2;
uhub_assert(handle->state == tls_st_connected);
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->ssl_write_events = 0;
else
ret = handle_openssl_error(con, ret, 0);
net_ssl_update(con, handle->events); // Update backend only
return ret;
}
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;
if (handle->state == tls_st_accepting || handle->state == tls_st_connecting)
return -1;
uhub_assert(handle->state == tls_st_connected);
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->ssl_read_events = 0;
else
ret = handle_openssl_error(con, ret, 1);
net_ssl_update(con, handle->events); // Update backend only
return ret;
}
void net_ssl_update(struct net_connection* con, int events)
{
struct net_ssl_openssl* handle = get_handle(con);
handle->events = events;
net_backend_update(con, handle->events | handle->ssl_read_events | handle->ssl_write_events);
}
void net_ssl_shutdown(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
if (handle)
{
SSL_shutdown(handle->ssl);
SSL_clear(handle->ssl);
}
}
void net_ssl_destroy(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
LOG_TRACE("net_ssl_destroy: %p", con);
SSL_free(handle->ssl);
hub_free(handle);
}
void net_ssl_callback(struct net_connection* con, int events)
{
struct net_ssl_openssl* handle = get_handle(con);
int ret;
switch (handle->state)
{
case tls_st_none:
con->callback(con, events, con->ptr);
break;
case tls_st_error:
con->callback(con, NET_EVENT_ERROR, 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:
ret = net_con_ssl_connect(con);
if (ret == 0)
return;
if (ret > 0)
{
LOG_DEBUG("%p SSL connected!", con);
con->callback(con, NET_EVENT_READ, con->ptr);
}
else
{
LOG_DEBUG("%p SSL handshake failed!", con);
con->callback(con, NET_EVENT_ERROR, con->ptr);
}
break;
case tls_st_connected:
if (handle->ssl_read_events & events)
events |= NET_EVENT_READ;
if (handle->ssl_write_events & events)
events |= NET_EVENT_WRITE;
con->callback(con, events, con->ptr);
break;
case tls_st_disconnecting:
return;
}
}
const char* net_ssl_get_tls_version(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
return SSL_get_version(handle->ssl);
}
const char* net_ssl_get_tls_cipher(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
const SSL_CIPHER *cipher = SSL_get_current_cipher(handle->ssl);
return SSL_CIPHER_get_name(cipher);
}
#endif /* SSL_USE_OPENSSL */
#endif /* SSL_SUPPORT */

View File

@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

Some files were not shown because too many files have changed in this diff Show More