Compare commits

..

1 Commits

Author SHA1 Message Date
Jan Vidar Krey
f1cd5bb535 Branched off 0.2.x stable branch (0.2.x-stable) 2009-05-29 14:43:41 +02:00
208 changed files with 7124 additions and 24777 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/\//-}

23
.gitignore vendored
View File

@ -1,23 +0,0 @@
*~
*.[oa]
*.lib
*.exe
*.manifest
*.gch
CMakeFiles/*
CMakeCache.txt
cmake_install.cmake
mod_*.dll
mod_*.exp
mod_*.so
uhub-admin
adcrush
uhub
build-stamp
debian/files
debian/uhub.debhelper.log
debian/uhub.postinst.debhelper
debian/uhub.postrm.debhelper
debian/uhub.prerm.debhelper
debian/uhub.substvars
uhub-passwd

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "thirdparty/sqlite"]
path = thirdparty/sqlite
url = https://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

11
AUTHORS
View File

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

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 +0,0 @@
##
## Makefile for uhub
## Copyright (C) 2007-2013, Jan Vidar Krey <janvidar@extatic.org>
#
cmake_minimum_required (VERSION 2.8.2)
project (uhub NONE)
enable_language(C)
set (UHUB_VERSION_MAJOR 0)
set (UHUB_VERSION_MINOR 5)
set (UHUB_VERSION_PATCH 1)
set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src")
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/Modules)
option(RELEASE "Release build, debug build if disabled" ON)
option(LOWLEVEL_DEBUG, "Enable low level debug messages." OFF)
option(SSL_SUPPORT "Enable SSL support" ON)
option(USE_OPENSSL "Use OpenSSL's SSL support" ON )
option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF)
option(ADC_STRESS "Enable the stress tester client" OFF)
find_package(Git)
find_package(Sqlite3)
include(TestBigEndian)
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 (USE_OPENSSL)
find_package(OpenSSL)
else()
find_package(GnuTLS)
endif()
if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND)
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS 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()
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
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_BINARY_DIR}")
include_directories(${SQLITE3_INCLUDE_DIRS})
link_directories(${SQLITE3_LIBRARY_DIRS})
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c)
list (REMOVE_ITEM uhub_SOURCES
${PROJECT_SOURCE_DIR}/core/gen_config.c
${PROJECT_SOURCE_DIR}/core/main.c
)
file (GLOB adc_SOURCES ${PROJECT_SOURCE_DIR}/adc/*.c)
file (GLOB network_SOURCES ${PROJECT_SOURCE_DIR}/network/*.c)
file (GLOB utils_SOURCES ${PROJECT_SOURCE_DIR}/util/*.c)
set (adcclient_SOURCES
${PROJECT_SOURCE_DIR}/tools/adcclient.c
${PROJECT_SOURCE_DIR}/core/ioqueue.c
)
add_library(adc STATIC ${adc_SOURCES})
add_library(network STATIC ${network_SOURCES})
add_library(utils STATIC ${utils_SOURCES})
if ("${CMAKE_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(network utils)
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_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c)
add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${PROJECT_SOURCE_DIR}/adc/sid.c)
add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c )
add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c )
add_library(mod_chat_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c )
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c)
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c)
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
set_target_properties(
mod_example
mod_welcome
mod_logging
mod_auth_simple
mod_auth_sqlite
mod_chat_history
mod_chat_history_sqlite
mod_chat_only
mod_no_guest_downloads
mod_topic
PROPERTIES PREFIX "")
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils)
target_link_libraries(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)
add_library(adcclient STATIC ${adcclient_SOURCES})
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c)
target_link_libraries(uhub-admin adcclient adc network utils pthread)
target_link_libraries(uhub pthread)
target_link_libraries(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()
if (NOT UHUB_REVISION AND GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE UHUB_REVISION_TEMP
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (UHUB_REVISION_TEMP)
set (UHUB_REVISION "git-${UHUB_REVISION_TEMP}")
endif()
endif()
if (NOT UHUB_REVISION)
set (UHUB_REVISION "release")
endif()
set (UHUB_GIT_VERSION "${UHUB_VERSION_MAJOR}.${UHUB_VERSION_MINOR}.${UHUB_VERSION_PATCH}-${UHUB_REVISION}")
message (STATUS "Configuring uhub version: ${UHUB_GIT_VERSION}")
if(OPENSSL_FOUND)
set(SSL_LIBS ${OPENSSL_LIBRARIES})
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_OPENSSL=1)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
if (GNUTLS_FOUND)
set(SSL_LIBS ${GNUTLS_LIBRARIES})
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_GNUTLS=1 ${GNUTLS_DEFINITIONS})
include_directories(${GNUTLS_INCLUDE_DIR})
endif()
if(SSL_SUPPORT)
target_link_libraries(uhub ${SSL_LIBS})
target_link_libraries(autotest-bin ${SSL_LIBS})
if(UNIX)
target_link_libraries(uhub-admin ${SSL_LIBS})
endif()
target_link_libraries(mod_welcome ${SSL_LIBS})
target_link_libraries(mod_logging ${SSL_LIBS})
if (ADC_STRESS)
target_link_libraries(adcrush ${SSL_LIBS})
endif()
endif()
if (SYSTEMD_SUPPORT)
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")
configure_file ("${PROJECT_SOURCE_DIR}/system.h.in" "${PROJECT_BINARY_DIR}/system.h")
# mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
# if (RELEASE)
# set(CMAKE_BUILD_TYPE Release)
# add_definitions(-DNDEBUG)
#else()
# set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG)
#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()

View File

@ -1,25 +0,0 @@
OpenSSL License Exception
-------------------------
Copyright (c) 2007-2012, Jan Vidar Krey
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License 3 (GPL) as published by
the Free Software Foundation.
The full text the GPL can be found in the COPYING file.
In addition this distribution of uhub may be linked against OpenSSL
according to the terms described here:
You have permission to copy, modify, propagate, and distribute a work
formed by combining OpenSSL with uhub, or a work derivative of such a
combination, even if such copying, modification, propagation, or
distribution would otherwise violate the terms of the GPL. You must
comply with the GPL in all respects for all of the code used other than
OpenSSL.
You may include this OpenSSL exception and its grant of permissions when
you distribute uhub. Inclusion of this notice with such a distribution
constitutes a grant of such permission. If you do not wish to grant these
permissions, delete this file.

119
ChangeLog
View File

@ -1,122 +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:
- Cleaned up code generator for config file parsing.
- Merge pull request #5 from yorhel/master
- Print error message in case of shutting down due to errors loading plugins.
- Fix Windows file read discrepancy.
- convert_to_sqlite.pl: Update to the latest SQL schema + be more Perlish
- Fix VS2010 project file - missing .c file.
- Merge https://github.com/Tilka/uhub
- use "I64u" instead of PRIu64 on Windows
- remove obsolete settings in uhub.conf
- fix uhub_itoa() and uhub_ulltoa()
- marked plugin callbacks that are not called yet
- add on_change_nick() to struct plugin_funcs
- minimal changes
- Updated init script in Debian package.
- Updated list of man pages in Debian package.
- Added man page for uhub-passwd.
- Merge branch 'master' of https://github.com/Tilka/uhub
- Fix issue with QUI messages being allowed through the hub
- don't show error on SIGTERM in select() backend
- fix dependency of 'install' target
- changed all calls to assert() to uhub_assert()
- Don't strip the U4/U6 port numbers if updated after login.
- Fix compile issue with double typedefs.
- Remove list assertion when removing element that is not in the list. Breaks autotest.
- Cleaned up command handling code, by splitting into multiple files.
- Fix bug #183 - Added proper OpenSSL license exception for the GPL.
- OMG OPTIMIZED
- use dh_prep instead of dh_clean -k
- fix double free
- use "0" instead of "false"
- fix use of uninitialized struct ip_range
- fix random crashes upon !reload
- fix command syntax
- use arg parser in !broadcast
- Fixed tiny memory leak on reload/shutdown.
- Merge https://github.com/Tilka/uhub
- fix multiple optional arguments
- small cleanup
- also clean uhub-passwd
- ignore files generated by dpkg-buildpackage
- automatically clean up plugin commands
- minimal documentation fixes
- update client software link
- update compile howto link
- fix Debian changelog
- Fix bug #158 - Added plugin for setting topic (hub description).
- Command arguments handling + cleanups
0.3.2:
- Fixed bugs in the kqueue network backend (OSX/BSD)
- Rewrote the configuration backend code.
- Added support for escaping characters in the configuration files.
- Updated the !broadcast command to send private messages instead of main chat messages.
- Adding support for redirecting clients to other hubs when they fail to log in.
- Fix some out of memory related crashes.
- Fixed minor memory leaks.
0.3.1:
- Fixed bug where !getip did not work.
- Added flood control configuration options.
- Added configuration options to disallow old/obsolete ADC clients.
- Fixed crash bugs, an freezes.
- SSL/TLS fix for tls_require configuration option.
- Fixed disconnect messages, so that clients can interpret them.
- Fixed bugs where share limits could be circumvented.
- Added support for listening to multiple ports.
- kqueue backend for Mac OS X, and BSD systems.
0.3.0:
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
- Experimental SSL support
- Large rewrite of the network stack in order to support SSL.
- Added rule file for defining hub rules.
- Many crash fixes and other important bug fixes.
- Optimizations: O(1) timeout scheduler
- New sid allocation code.
- Added configurable server_listen_backlog (default 50).
- Added init.d scripts for RedHat/CentOS
0.2.8:
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
- Fix bug #10: Improve logging, ensure logs are machine readable.

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"]

270
GNUmakefile Normal file
View File

@ -0,0 +1,270 @@
##
## Makefile for uhub (Use GNU make)
## Copyright (C) 2007-2008, Jan Vidar Krey <janvidar@extatic.org>
#
CC = gcc
LD := $(CC)
MV := mv
RANLIB := ranlib
CFLAGS += -pipe -Wall
USE_PCH ?= YES
USE_SSL ?= NO
USE_BIGENDIAN ?= AUTO
BITS ?= AUTO
SILENT ?= YES
LDLIBS += -levent
TERSE ?= NO
STACK_PROTECT ?= NO
ifeq ($(OS), Windows_NT)
WINDOWS ?= YES
endif
ifeq ($(WINDOWS),YES)
USE_BIGENDIAN := NO
LDLIBS += -lws2_32
UHUB_CONF_DIR ?= c:/uhub/
UHUB_PREFIX ?= c:/uhub/
CFLAGS += -mno-cygwin
LDFLAGS += -mno-cygwin
BIN_EXT ?= .exe
else
DESTDIR ?= /
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
UHUB_PREFIX ?= $(DESTDIR)/usr/local
CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib
BIN_EXT ?=
endif
ifeq ($(SILENT),YES)
MSG_CC=@echo " CC:" $(notdir $^) &&
MSG_PCH=@echo " PCH:" $(notdir $@) &&
MSG_LD=@echo " LD:" $(notdir $@) &&
MSG_AR=@echo " AR:" $(notdir $@) &&
else
MSG_CC=
MSG_PCH=
MSG_LD=
MSG_AR=
endif
ifeq ($(TERSE), YES)
MSG_CC=@
MSG_PCH=@
MSG_LD=@
MSG_AR=@
MSG_CLEAN=-n ""
else
MSG_CLEAN="Clean as a whistle"
endif
CFLAGS += -I/source/libevent
LDFLAGS += -L/source/libevent
-include release_setup.mk
ifeq ($(RELEASE),YES)
CFLAGS += -Os -DNDEBUG
else
CFLAGS += -g -DDEBUG
endif
ifeq ($(STACK_PROTECT),YES)
CFLAGS += -fstack-protector-all
endif
ifeq ($(PROFILING),YES)
CFLAGS += -pg
LDFLAGS += -pg
endif
ifeq ($(FUNCTRACE),YES)
CFLAGS += -finstrument-functions
CFLAGS += -DDEBUG_FUNCTION_TRACE
endif
ifeq ($(USE_PCH),YES)
PCHSRC=src/uhub.h
PCH=src/uhub.h.gch
else
PCH=
endif
ifneq ($(BITS), AUTO)
ifeq ($(BITS), 64)
CFLAGS += -m64
LDFLAGS += -m64
else
ifeq ($(BITS), 32)
CFLAGS += -m32
LDFLAGS += -m32
endif
endif
endif
ifeq ($(USE_BIGENDIAN),AUTO)
ifeq ($(shell perl -e 'print pack("L", 0x554E4958)'),UNIX)
CFLAGS += -DARCH_BIGENDIAN
endif
else
ifeq ($(USE_BIGENDIAN),YES)
CFLAGS += -DARCH_BIGENDIAN
endif
endif
ifeq ($(USE_SSL),YES)
CFLAGS += -DSSL_SUPPORT
LDLIBS += -lssl
endif
ifneq ($(LIBEVENT_PATH),)
CFLAGS += -I$(LIBEVENT_PATH)
LDFLAGS += -L$(LIBEVENT_PATH)
endif
# Sources
libuhub_SOURCES := \
src/auth.c \
src/commands.c \
src/config.c \
src/eventqueue.c \
src/hubevent.c \
src/hub.c \
src/inf.c \
src/ipcalc.c \
src/list.c \
src/log.c \
src/memory.c \
src/message.c \
src/misc.c \
src/netevent.c \
src/network.c \
src/rbtree.c \
src/route.c \
src/sid.c \
src/tiger.c \
src/user.c \
src/usermanager.c
uhub_SOURCES := src/main.c
adcrush_SOURCES := src/adcrush.c
uhub_HEADERS := \
src/adcconst.h \
src/auth.h \
src/config.h \
src/eventid.h \
src/eventqueue.h \
src/hubevent.h \
src/hub.h \
src/inf.h \
src/ipcalc.h \
src/list.h \
src/log.h \
src/memory.h \
src/message.h \
src/misc.h \
src/netevent.h \
src/network.h \
src/rbtree.h \
src/route.h \
src/sid.h \
src/tiger.h \
src/uhub.h \
src/user.h \
src/usermanager.h
autotest_SOURCES := \
autotest/test_message.tcc \
autotest/test_list.tcc \
autotest/test_memory.tcc \
autotest/test_ipfilter.tcc \
autotest/test_inf.tcc \
autotest/test_hub.tcc \
autotest/test_misc.tcc \
autotest/test_tiger.tcc \
autotest/test_usermanager.tcc \
autotest/test_eventqueue.tcc
autotest_OBJECTS = autotest.o
# Source to objects
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS)
LIBUHUB=libuhub.a
uhub_BINARY=uhub$(BIN_EXT)
adcrush_BINARY=adcrush$(BIN_EXT)
autotest_BINARY=autotest/test$(BIN_EXT)
%.o: %.c
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@.tmp $^ && \
$(MV) $@.tmp $@
all: $(uhub_BINARY) $(PCH)
$(adcrush_BINARY): $(PCH) $(LIBUHUB) $(adcrush_OBJECTS)
$(MSG_LD) $(CC) -o $@.tmp $(adcrush_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
$(MV) $@.tmp $@
$(uhub_BINARY): $(PCH) $(LIBUHUB) $(uhub_OBJECTS)
$(MSG_LD) $(CC) -o $@.tmp $(uhub_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
$(MV) $@.tmp $@
$(LIBUHUB): $(libuhub_OBJECTS)
$(MSG_AR) $(AR) rc $@.tmp $^ && \
$(RANLIB) $@.tmp && \
$(MV) $@.tmp $@
ifeq ($(USE_PCH),YES)
$(PCH): $(uhub_HEADERS)
$(MSG_PCH) $(CC) $(CFLAGS) -o $@.tmp $(PCHSRC) && \
$(MV) $@.tmp $@
endif
autotest.c: $(autotest_SOURCES)
$(shell exotic --standalone $(autotest_SOURCES) > $@)
$(autotest_OBJECTS): autotest.c
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@.tmp $< && \
$(MV) $@.tmp $@
$(autotest_BINARY): $(autotest_OBJECTS) $(LIBUHUB)
$(MSG_LD) $(CC) -o $@.tmp $^ $(LDFLAGS) $(LDLIBS) && \
$(MV) $@.tmp $@
autotest: $(autotest_BINARY)
@./$(autotest_BINARY) -s -f
ifeq ($(WINDOWS),YES)
install:
@echo "Cannot install automatically on windows."
else
install: $(uhub_BINARY)
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
@if [ ! -d $(UHUB_CONF_DIR) ]; then echo Creating $(UHUB_CONF_DIR); mkdir -p $(UHUB_CONF_DIR); fi
@if [ ! -f $(UHUB_CONF_DIR)/uhub.conf ]; then cp doc/uhub.conf $(UHUB_CONF_DIR); fi
@if [ ! -f $(UHUB_CONF_DIR)/users.conf ]; then cp doc/users.conf $(UHUB_CONF_DIR); fi
@touch $(UHUB_CONF_DIR)/motd.txt
@echo done.
endif
dist-clean:
@rm -rf $(all_OBJECTS) $(PCH) *~ core
clean:
@rm -rf $(libuhub_OBJECTS) $(PCH) *~ core $(uhub_BINARY) $(LIBUHUB) $(all_OBJECTS) && \
echo $(MSG_CLEAN)
-include release_targets.mk

5
README Normal file
View File

@ -0,0 +1,5 @@
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
For the official documentation, bugs and other information, please visit:
http://www.extatic.org/uhub/

View File

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

0
TODO
View File

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
on high-end servers, or a small private hub on embedded hardware.
.
Homepage: https://www.uhub.org/
Homepage: http://www.extatic.org/uhub/
EOF
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

@ -1,251 +0,0 @@
#include <uhub.h>
static struct hub_info* hub = NULL;
static struct hub_command* cmd = NULL;
static struct hub_user user;
static struct command_base* cbase = NULL;
static struct command_handle* c_test1 = NULL;
static struct command_handle* c_test2 = NULL;
static struct command_handle* c_test3 = NULL;
static struct command_handle* c_test4 = NULL;
static struct command_handle* c_test5 = NULL;
static struct command_handle* c_test6 = NULL;
static struct command_handle* c_test7 = NULL;
// for results:
static int result = 0;
EXO_TEST(setup, {
hub = hub_malloc_zero(sizeof(struct hub_info));
cbase = command_initialize(hub);
hub->commands = cbase;
hub->users = uman_init();
return cbase && hub && hub->users;
});
static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
{
printf("test_handler\n");
result = 1;
return 0;
}
static struct command_handle* create_handler(const char* prefix, const char* args, enum auth_credentials cred)
{
struct command_handle* c = hub_malloc_zero(sizeof(struct command_handle));
c->prefix = prefix;
c->length = strlen(prefix);
c->args = args;
c->cred = cred;
c->handler = test_handler;
c->description = "A handler added by autotest.";
c->origin = "exotic test";
c->ptr = &c->ptr;
return c;
}
EXO_TEST(command_setup_user, {
memset(&user, 0, sizeof(user));
user.id.sid = 1;
strcpy(user.id.nick, "tester");
strcpy(user.id.cid, "3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
user.credentials = auth_cred_guest;
return 1;
});
#define ADD_TEST(var, prefix, args, cred) \
var = create_handler(prefix, args, cred); \
if (!command_add(cbase, var, NULL)) \
return 0;
#define DEL_TEST(var) \
if (var) \
{ \
if (!command_del(cbase, var)) \
return 0; \
hub_free(var); \
var = NULL; \
}
EXO_TEST(command_create, {
ADD_TEST(c_test1, "test1", "", auth_cred_guest);
ADD_TEST(c_test2, "test2", "", auth_cred_operator);
ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest);
ADD_TEST(c_test4, "test4", "u", auth_cred_guest);
ADD_TEST(c_test5, "test5", "i", auth_cred_guest);
ADD_TEST(c_test6, "test6", "?c", auth_cred_guest);
ADD_TEST(c_test6, "test7", "C", auth_cred_guest);
return 1;
});
extern void command_destroy(struct hub_command* cmd);
static int verify(const char* str, enum command_parse_status expected)
{
struct hub_command* cmd = command_parse(cbase, hub, &user, str);
enum command_parse_status status = cmd->status;
command_free(cmd);
return status == expected;
}
static struct hub_command_arg_data* verify_argument(struct hub_command* cmd, enum hub_command_arg_type type)
{
return hub_command_arg_next(cmd, type);
}
static int verify_arg_integer(struct hub_command* cmd, int expected)
{
struct hub_command_arg_data* data = verify_argument(cmd, type_integer);
return data->data.integer == expected;
}
static int verify_arg_user(struct hub_command* cmd, struct hub_user* expected)
{
struct hub_command_arg_data* data = verify_argument(cmd, type_user);
return data->data.user == expected;
}
static int verify_arg_cred(struct hub_command* cmd, enum auth_credentials cred)
{
struct hub_command_arg_data* data = verify_argument(cmd, type_credentials);
return data->data.credentials == cred;
}
EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); });
EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); });
EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); });
EXO_TEST(command_syntax_1, { return verify("", cmd_status_syntax_error); });
EXO_TEST(command_syntax_2, { return verify("!", cmd_status_syntax_error); });
EXO_TEST(command_missing_args_1, { return verify("!test3", cmd_status_missing_args); });
EXO_TEST(command_missing_args_2, { return verify("!test3 12345", cmd_status_ok); });
EXO_TEST(command_missing_args_3, { return verify("!test3 1 2 345", cmd_status_ok); });
EXO_TEST(command_number_1, { return verify("!test3 abc", cmd_status_arg_number); });
EXO_TEST(command_number_2, { return verify("!test3 -", cmd_status_arg_number); });
EXO_TEST(command_number_3, { return verify("!test3 -12", cmd_status_ok); });
EXO_TEST(command_user_1, { return verify("!test4 tester", cmd_status_arg_nick); });
EXO_TEST(command_user_2, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_arg_cid); });
EXO_TEST(command_user_3, { return uman_add(hub->users, &user) == 0; });
EXO_TEST(command_user_4, { return verify("!test4 tester", cmd_status_ok); });
EXO_TEST(command_user_5, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_ok); });
EXO_TEST(command_command_1, { return verify("!test6 test1", cmd_status_ok); });
EXO_TEST(command_command_2, { return verify("!test6 test2", cmd_status_ok); });
EXO_TEST(command_command_3, { return verify("!test6 test3", cmd_status_ok); });
EXO_TEST(command_command_4, { return verify("!test6 test4", cmd_status_ok); });
EXO_TEST(command_command_5, { return verify("!test6 test5", cmd_status_ok); });
EXO_TEST(command_command_6, { return verify("!test6 test6", cmd_status_ok); });
EXO_TEST(command_command_7, { return verify("!test6 fail", cmd_status_arg_command); });
EXO_TEST(command_command_8, { return verify("!test6", cmd_status_ok); });
EXO_TEST(command_cred_1, { return verify("!test7 guest", cmd_status_ok); });
EXO_TEST(command_cred_2, { return verify("!test7 user", cmd_status_ok); });
EXO_TEST(command_cred_3, { return verify("!test7 operator", cmd_status_ok); });
EXO_TEST(command_cred_4, { return verify("!test7 super", cmd_status_ok); });
EXO_TEST(command_cred_5, { return verify("!test7 admin", cmd_status_ok); });
EXO_TEST(command_cred_6, { return verify("!test7 nobody", cmd_status_arg_cred); });
EXO_TEST(command_cred_7, { return verify("!test7 bot", cmd_status_ok); });
EXO_TEST(command_cred_8, { return verify("!test7 link", cmd_status_ok); });
#if 0
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
};
#endif
// command not found
EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
// built-in command
EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); });
#define SETUP_COMMAND(string) \
do { \
if (cmd) command_free(cmd); \
cmd = command_parse(cbase, hub, &user, string); \
} while(0)
EXO_TEST(command_argument_integer_1, {
SETUP_COMMAND("!test3");
return verify_argument(cmd, type_integer) == NULL;
});
EXO_TEST(command_argument_integer_2, {
SETUP_COMMAND("!test3 10 42");
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL;
});
EXO_TEST(command_argument_integer_3, {
SETUP_COMMAND("!test3 10 42 6784");
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784);
});
EXO_TEST(command_argument_user_1, {
SETUP_COMMAND("!test4 tester");
return verify_arg_user(cmd, &user) ;
});
EXO_TEST(command_argument_cid_1, {
SETUP_COMMAND("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
return verify_arg_user(cmd, &user) ;
});
EXO_TEST(command_argument_cred_1, {
SETUP_COMMAND("!test7 admin");
return verify_arg_cred(cmd, auth_cred_admin);;
});
EXO_TEST(command_argument_cred_2, {
SETUP_COMMAND("!test7 op");
return verify_arg_cred(cmd, auth_cred_operator);;
});
EXO_TEST(command_argument_cred_3, {
SETUP_COMMAND("!test7 operator");
return verify_arg_cred(cmd, auth_cred_operator);
});
EXO_TEST(command_argument_cred_4, {
SETUP_COMMAND("!test7 super");
return verify_arg_cred(cmd, auth_cred_super);
});
EXO_TEST(command_argument_cred_5, {
SETUP_COMMAND("!test7 guest");
return verify_arg_cred(cmd, auth_cred_guest);
});
EXO_TEST(command_argument_cred_6, {
SETUP_COMMAND("!test7 user");
return verify_arg_cred(cmd, auth_cred_user);
});
#undef SETUP_COMMAND
EXO_TEST(command_user_destroy, { return uman_remove(hub->users, &user) == 0; });
EXO_TEST(command_destroy, {
command_free(cmd);
cmd = NULL;
DEL_TEST(c_test1);
DEL_TEST(c_test2);
DEL_TEST(c_test3);
DEL_TEST(c_test4);
DEL_TEST(c_test5);
DEL_TEST(c_test6);
DEL_TEST(c_test7);
return 1;
});
EXO_TEST(cleanup, {
uman_shutdown(hub->users);
command_shutdown(hub->commands);
hub_free(hub);
return 1;
});

View File

@ -1,24 +0,0 @@
#include <uhub.h>
EXO_TEST(cred_to_string_1, { return !strcmp(auth_cred_to_string(auth_cred_none), "none"); });
EXO_TEST(cred_to_string_2, { return !strcmp(auth_cred_to_string(auth_cred_bot), "bot"); });
EXO_TEST(cred_to_string_3, { return !strcmp(auth_cred_to_string(auth_cred_guest), "guest"); });
EXO_TEST(cred_to_string_4, { return !strcmp(auth_cred_to_string(auth_cred_user), "user"); });
EXO_TEST(cred_to_string_5, { return !strcmp(auth_cred_to_string(auth_cred_operator), "operator"); });
EXO_TEST(cred_to_string_6, { return !strcmp(auth_cred_to_string(auth_cred_super), "super"); });
EXO_TEST(cred_to_string_7, { return !strcmp(auth_cred_to_string(auth_cred_link), "link"); });
EXO_TEST(cred_to_string_8, { return !strcmp(auth_cred_to_string(auth_cred_admin), "admin"); });
#define CRED_FROM_STRING(STR, EXPECT) enum auth_credentials cred; return auth_string_to_cred(STR, &cred) && cred == EXPECT;
EXO_TEST(cred_from_string_1, { CRED_FROM_STRING("none", auth_cred_none); });
EXO_TEST(cred_from_string_2, { CRED_FROM_STRING("bot", auth_cred_bot); });
EXO_TEST(cred_from_string_3, { CRED_FROM_STRING("guest", auth_cred_guest); });
EXO_TEST(cred_from_string_4, { CRED_FROM_STRING("user", auth_cred_user); });
EXO_TEST(cred_from_string_5, { CRED_FROM_STRING("reg", auth_cred_user); });
EXO_TEST(cred_from_string_6, { CRED_FROM_STRING("operator", auth_cred_operator); });
EXO_TEST(cred_from_string_7, { CRED_FROM_STRING("op", auth_cred_operator); });
EXO_TEST(cred_from_string_8, { CRED_FROM_STRING("super", auth_cred_super); });
EXO_TEST(cred_from_string_9, { CRED_FROM_STRING("link", auth_cred_link); });
EXO_TEST(cred_from_string_10, { CRED_FROM_STRING("admin", auth_cred_admin); });

View File

@ -10,8 +10,8 @@ static void create_test_user()
if (g_user)
return;
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
memset(g_user, 0, sizeof(struct hub_user));
g_user = (struct user*) malloc(sizeof(struct user));
memset(g_user, 0, sizeof(struct user));
memcpy(g_user->id.nick, "exotic-tester", 13);
g_user->sid = 1;
}
@ -23,7 +23,6 @@ EXO_TEST(hub_net_startup, {
EXO_TEST(hub_config_initialize, {
config_defaults(&g_config);
g_config.server_port = 65111;
return 1;
});
@ -68,5 +67,5 @@ EXO_TEST(hub_service_shutdown, {
});
EXO_TEST(hub_net_shutdown, {
return (net_destroy() != -1);
return (net_shutdown() != -1);
});

View File

@ -5,17 +5,18 @@
#define USER_NICK "Friend"
#define USER_SID "AAAB"
static struct hub_user* inf_user = 0;
static struct user* inf_user = 0;
static struct hub_info* inf_hub = 0;
extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
extern int hub_handle_info_login(struct hub_info* hub, struct user* user, struct adc_message* cmd);
static void inf_create_hub()
{
net_initialize();
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
inf_hub->users = (struct user_manager*) hub_malloc_zero(sizeof(struct user_manager));
inf_hub->users->list = list_create();
inf_hub->users->free_sid = 1;
inf_hub->users = uman_init();
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));
@ -25,21 +26,23 @@ static void inf_create_hub()
static void inf_destroy_hub()
{
uman_shutdown(inf_hub->users);
/* FIXME */
list_destroy(inf_hub->users->list);
acl_shutdown(inf_hub->acl);
free_config(inf_hub->config);
hub_free(inf_hub->users);
hub_free(inf_hub->acl);
hub_free(inf_hub->config);
hub_free(inf_hub);
net_destroy();
}
static void inf_create_user()
{
if (inf_user) return;
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
inf_user = (struct user*) hub_malloc_zero(sizeof(struct user));
inf_user->id.sid = 1;
inf_user->sd = -1;
inf_user->limits.upload_slots = 1;
}
@ -60,14 +63,13 @@ EXO_TEST(inf_create_setup,
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
#define CHECK_INF(MSG, EXPECT) \
do { \
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \
if (ok == EXPECT) \
user_set_info(inf_user, 0); \
return ok == EXPECT; \
} while(0)
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \
if (ok == EXPECT) \
user_set_info(inf_user, 0); \
return ok == EXPECT;
EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
@ -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_10, {
const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n";
int ok;
char nick[10];
struct adc_message* msg;
nick[0] = 0xf7; nick[1] = 0x80; nick[2] = 0x7f; nick[3] = 0x81; nick[4] = 0x98; nick[5] = 0x00;
msg = adc_msg_parse_verify(inf_user, line, strlen(line));
struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line));
adc_msg_add_named_argument(msg, "NI", nick);
ok = hub_handle_info_login(inf_hub, inf_user, msg);
int ok = hub_handle_info_login(inf_hub, inf_user, msg);
adc_msg_free(msg);
if (ok != status_msg_inf_error_nick_not_utf8)
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);

View File

@ -9,8 +9,8 @@ static struct ip_addr_encap ip6_a;
static struct ip_addr_encap ip6_b;
static struct ip_addr_encap ip6_c;
static struct ip_addr_encap mask;
static struct ip_range ban6;
static struct ip_range ban4;
static struct ip_ban_record ban6;
static struct ip_ban_record ban4;
EXO_TEST(prepare_network, {
return net_initialize() == 0;
@ -405,81 +405,74 @@ EXO_TEST(check_ban_setup_1, {
EXO_TEST(check_ban_ipv4_1, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.0", &addr);
return ip_in_range(&addr, &ban4);
return acl_check_ip_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_2, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.1", &addr);
return ip_in_range(&addr, &ban4);
return acl_check_ip_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_3, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.255", &addr);
return ip_in_range(&addr, &ban4);
return acl_check_ip_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_4, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.1.0", &addr);
return !ip_in_range(&addr, &ban4);
return !acl_check_ip_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_5, {
struct ip_addr_encap addr; ip_convert_to_binary("192.167.255.255", &addr);
return !ip_in_range(&addr, &ban4);
return !acl_check_ip_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv6_1, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
return ip_in_range(&addr, &ban6);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
return acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_2, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
return ip_in_range(&addr, &ban6);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
return acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_3, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
return ip_in_range(&addr, &ban6);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
return acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_4, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
return ip_in_range(&addr, &ban6);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
return acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_5, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
return !ip_in_range(&addr, &ban6);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
return !acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_6, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !ip_in_range(&addr, &ban6);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(check_ban_afmix_1, {
struct ip_addr_encap addr;
if (!ipv6) return 1;
ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !ip_in_range(&addr, &ban4);
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !acl_check_ip_range(&addr, &ban4);
});
EXO_TEST(check_ban_afmix_2, {
struct ip_addr_encap addr; ip_convert_to_binary("10.20.30.40", &addr);
return !ip_in_range(&addr, &ban6);
return !acl_check_ip_range(&addr, &ban6);
});
EXO_TEST(ip4_bitwise_AND_1, {
@ -601,30 +594,6 @@ EXO_TEST(ip6_bitwise_OR_3, {
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111:ffff:ffff:ffff:1c1c");
});
EXO_TEST(ip_range_1, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.1", &range) && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) == 0;
});
EXO_TEST(ip_range_2, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
});
EXO_TEST(ip_range_3, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.0/16", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
});
EXO_TEST(ip_range_4, {
struct ip_range range1;
struct ip_range 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;
});
EXO_TEST(shutdown_network, {
return net_destroy() == 0;
return net_shutdown() == 0;
});

View File

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

View File

@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
});
EXO_TEST(test_message_refc_2, {
return g_msg->references == 1;
return g_msg->references == 0; // 0
});
EXO_TEST(test_message_refc_3, {
adc_msg_incref(g_msg);
return g_msg->references == 2;
return g_msg->references == 1; // 1
});
EXO_TEST(test_message_refc_4, {
adc_msg_incref(g_msg);
return g_msg->references == 3;
return g_msg->references == 2; // 2
});
EXO_TEST(test_message_refc_5, {
adc_msg_free(g_msg);
return g_msg->references == 2;
return g_msg->references == 1; // 1
});
EXO_TEST(test_message_refc_6, {
adc_msg_free(g_msg);
return g_msg->references == 1;
return g_msg->references == 0; // 0
});
EXO_TEST(test_message_refc_7, {

View File

@ -1,5 +1,5 @@
#include <uhub.h>
static struct hub_user* g_user = 0;
static struct user* g_user = 0;
static const char* test_string1 = "IINF AAfoo BBbar CCwhat\n";
static const char* test_string2 = "BMSG AAAB Hello\\sWorld!\n";
static const char* test_string3 = "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1 AW\n";
@ -11,8 +11,8 @@ static void create_test_user()
if (g_user)
return;
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
memset(g_user, 0, sizeof(struct hub_user));
g_user = (struct user*) malloc(sizeof(struct user));
memset(g_user, 0, sizeof(struct user));
memcpy(g_user->id.nick, "exotic-tester", 13);
g_user->id.sid = 1;
}
@ -31,9 +31,7 @@ EXO_TEST(adc_message_parse_1, {
EXO_TEST(adc_message_parse_2, {
struct adc_message* msg = adc_msg_create(test_string2);
int ok = (msg != NULL);
adc_msg_free(msg);
return ok;
return msg == NULL;
});
EXO_TEST(adc_message_parse_3, {
@ -174,102 +172,91 @@ EXO_TEST(adc_message_parse_24, {
EXO_TEST(adc_message_add_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_add_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_named_argument(msg, "XX", "wtf?");
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat XXwtf?\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA");
ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB");
ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC");
ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_remove_arg_4, {
/* this ensures we can remove the last element also */
int ok;
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3));
adc_msg_remove_named_argument(msg, "AW");
ok = strcmp(msg->cache, "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1\n") == 0;
int ok = strcmp(msg->cache, "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "AA");
ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "BB");
ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_replace_arg_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_remove_named_argument(msg, "CC");
ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_get_arg_1, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 0);
ok = strcmp(c, "AAfoo") == 0;
int ok = strcmp(c, "AAfoo") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
});
EXO_TEST(adc_message_get_arg_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
char* c = adc_msg_get_argument(msg, 1);
ok = strcmp(c, "BBbar") == 0;
int ok = strcmp(c, "BBbar") == 0;
adc_msg_free(msg);
hub_free(c);
return ok;
@ -351,31 +338,28 @@ EXO_TEST(adc_message_has_named_arg_3, {
});
EXO_TEST(adc_message_has_named_arg_4, {
int n;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
n = adc_msg_has_named_argument(msg, "XX");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 1;
});
EXO_TEST(adc_message_has_named_arg_5, {
int n;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo");
n = adc_msg_has_named_argument(msg, "XX");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 2;
});
EXO_TEST(adc_message_has_named_arg_6, {
int n;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXone");
adc_msg_add_argument(msg, "XXtwo");
adc_msg_add_argument(msg, "XXthree");
n = adc_msg_has_named_argument(msg, "XX");
int n = adc_msg_has_named_argument(msg, "XX");
adc_msg_free(msg);
return n == 3;
});
@ -388,70 +372,63 @@ EXO_TEST(adc_message_has_named_arg_7, {
});
EXO_TEST(adc_message_terminate_1, {
int ok;
struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat");
adc_msg_unterminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_2, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_3, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
adc_msg_unterminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_4, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_terminate(msg);
adc_msg_terminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_5, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_terminate(msg);
adc_msg_terminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat\n") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_terminate_6, {
int ok;
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_unterminate(msg);
adc_msg_unterminate(msg);
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_escape_1, {
int ok;
char* s = adc_msg_escape(test_string1);
ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
int ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
hub_free(s);
return ok;
});

View File

@ -97,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_2, { return is_valid_utf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); });
EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
static const char test_utf_seq_1[] = { 0x65, 0x00 }; // valid
static const char test_utf_seq_2[] = { 0xD8, 0x00 }; // invalid
static const char test_utf_seq_3[] = { 0x24, 0x00 }; // valid
static const char test_utf_seq_4[] = { 0xC2, 0x24, 0x00}; // invalid
static const char test_utf_seq_5[] = { 0xC2, 0xA2, 0x00}; // valid
static const char test_utf_seq_6[] = { 0xE2, 0x82, 0xAC, 0x00}; // valid
static const char test_utf_seq_7[] = { 0xC2, 0x32, 0x00}; // invalid
static const char test_utf_seq_8[] = { 0xE2, 0x82, 0x32, 0x00}; // invalid
static const char test_utf_seq_9[] = { 0xE2, 0x32, 0x82, 0x00}; // invalid
static const char test_utf_seq_10[] = { 0xF0, 0x9F, 0x98, 0x81, 0x00}; // valid
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });
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

@ -1,138 +0,0 @@
#include <uhub.h>
static struct sid_pool* sid_pool = 0;
struct dummy_user
{
sid_t sid;
};
static struct dummy_user* last = 0;
sid_t last_sid = 0;
EXO_TEST(sid_create_pool, {
sid_pool = sid_pool_create(4);
return sid_pool != 0;
});
EXO_TEST(sid_check_0a, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
return user == 0;
});
EXO_TEST(sid_check_0b, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5);
return user == 0;
});
EXO_TEST(sid_alloc_1, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last = user;
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_1a, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last == user;
});
EXO_TEST(sid_check_1b, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1);
return user == 0;
});
EXO_TEST(sid_alloc_2, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_2, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_3, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_3, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_4, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_4, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_5, {
struct dummy_user user;
sid_t sid;
sid = sid_alloc(sid_pool, (struct hub_user*) &user);
return sid == 0;
});
EXO_TEST(sid_check_6, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
return user == 0;
});
EXO_TEST(sid_list_all_1, {
sid_t s;
size_t n = 0;
int ok = 1;
for (s = last->sid; s <= last_sid; s++)
{
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s);
if (s != (user ? user->sid : -1))
{
ok = 0;
break;
}
n++;
}
return ok && n == 4;
});
#define FREE_SID(N) \
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \
sid_free(sid_pool, N); \
hub_free(user); \
return sid_lookup(sid_pool, N) == NULL;
EXO_TEST(sid_remove_1, {
FREE_SID(2);
});
EXO_TEST(sid_remove_2, {
FREE_SID(1);
});
EXO_TEST(sid_remove_3, {
FREE_SID(4);
});
EXO_TEST(sid_remove_4, {
FREE_SID(3);
});
EXO_TEST(sid_destroy_pool, {
sid_pool_destroy(sid_pool);
sid_pool = 0;
return sid_pool == 0;
});

View File

@ -1,125 +0,0 @@
#include <uhub.h>
#define MAX_EVENTS 15
static struct timeout_queue* g_queue;
static time_t g_now;
static size_t g_max;
static struct timeout_evt g_events[MAX_EVENTS];
static size_t g_triggered;
static void timeout_cb(struct timeout_evt* t)
{
g_triggered++;
}
/*
typedef void (*timeout_evt_cb)(struct timeout_evt*);
struct timeout_evt
{
time_t timestamp;
timeout_evt_cb callback;
void* ptr;
struct timeout_evt* prev;
struct timeout_evt* next;
};
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
void timeout_evt_reset(struct timeout_evt*);
int timeout_evt_is_scheduled(struct timeout_evt*);
struct timeout_queue
{
time_t last;
size_t max;
struct timeout_evt** events;
};
void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
void timeout_queue_shutdown(struct timeout_queue*);
size_t timeout_queue_process(struct timeout_queue*, time_t now);
void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now);
*/
EXO_TEST(timer_setup,{
size_t n;
g_queue = hub_malloc_zero(sizeof(struct timeout_queue));
g_now = 0;
g_max = 5;
g_triggered = 0;
timeout_queue_initialize(g_queue, g_now, g_max);
memset(g_events, 0, sizeof(g_events));
for (n = 0; n < MAX_EVENTS; n++)
{
timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]);
}
return g_queue != NULL;
});
EXO_TEST(timer_check_timeout_0,{
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
EXO_TEST(timer_add_event_1,{
timeout_queue_insert(g_queue, &g_events[0], 2);
return g_events[0].prev != NULL;
});
EXO_TEST(timer_check_timeout_1,{
return timeout_queue_get_next_timeout(g_queue, g_now) == 2;
});
EXO_TEST(timer_remove_event_1,{
timeout_queue_remove(g_queue, &g_events[0]);
return g_events[0].prev == NULL;
});
EXO_TEST(timer_check_timeout_2,{
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
/* test re-removing an event - should not crash! */
EXO_TEST(timer_remove_event_1_no_crash,{
timeout_queue_remove(g_queue, &g_events[0]);
return g_events[0].prev == NULL;
});
EXO_TEST(timer_add_5_events_1,{
timeout_queue_insert(g_queue, &g_events[0], 0);
timeout_queue_insert(g_queue, &g_events[1], 1);
timeout_queue_insert(g_queue, &g_events[2], 2);
timeout_queue_insert(g_queue, &g_events[3], 3);
timeout_queue_insert(g_queue, &g_events[4], 4);
return (g_events[0].prev != NULL &&
g_events[1].prev != NULL &&
g_events[2].prev != NULL &&
g_events[3].prev != NULL &&
g_events[4].prev != NULL);
});
EXO_TEST(timer_check_5_events_1,{
return timeout_queue_get_next_timeout(g_queue, g_now) == 1;
});
EXO_TEST(timer_process_5_events_1,{
g_now = 4;
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

@ -1,110 +0,0 @@
#include <uhub.h>
#define SETUP(X, STR) struct cfg_tokens* tokens = cfg_tokenize(STR)
#define CLEANUP_LIST(X) do { list_clear(X, hub_free); list_destroy(X); } while(0)
#define CLEANUP_TOKENS(X) do { cfg_tokens_free(X); } while(0)
static int match_str(const char* str1, char* str2)
{
size_t i;
int ret;
for (i = 0; i < strlen(str2); i++)
if (str2[i] == '_')
str2[i] = ' ';
else if (str2[i] == '|')
str2[i] = '\t';
ret = strcmp(str1, str2);
if (ret) {
fprintf(stderr, "\n Mismatch: \"%s\" != \"%s\"\n", str1, str2);
}
return ret;
}
static int count(const char* STR, size_t EXPECT) {
SETUP(tokens, STR);
int pass = cfg_token_count(tokens) == EXPECT;
CLEANUP_TOKENS(tokens);
return pass;
}
static int compare(const char* str, const char* ref) {
size_t i, max;
int pass;
struct linked_list* compare = list_create();
SETUP(tokens, str);
split_string(ref, " ", compare, 0);
pass = cfg_token_count(tokens) == list_size(compare);
if (pass) {
max = cfg_token_count(tokens);
for (i = 0; i < max; i++) {
char* token = (char*) cfg_token_get(tokens, i);
char* refer = (char*) list_get_index(compare, i);
if (match_str(token, refer)) {
pass = 0;
break;
}
}
}
CLEANUP_TOKENS(tokens);
CLEANUP_LIST(compare);
return pass;
}
EXO_TEST(tokenizer_basic_0, { return count("", 0); });
EXO_TEST(tokenizer_basic_1, { return count("a", 1); });
EXO_TEST(tokenizer_basic_1a, { return count(" a", 1); })
EXO_TEST(tokenizer_basic_1b, { return count("\ta", 1); })
EXO_TEST(tokenizer_basic_1c, { return count(" a", 1); })
EXO_TEST(tokenizer_basic_1d, { return count(" a ", 1); })
EXO_TEST(tokenizer_basic_1e, { return count(" a ", 1); })
EXO_TEST(tokenizer_basic_2, { return count("a b", 2); });
EXO_TEST(tokenizer_basic_2a, { return count(" a b ", 2); });
EXO_TEST(tokenizer_basic_3, { return count("a b c", 3); });
EXO_TEST(tokenizer_basic_3a, { return count("a b c", 3); });
EXO_TEST(tokenizer_basic_3b, { return count("a b\tc", 3); });
EXO_TEST(tokenizer_basic_3c, { return count("a b c ", 3); });
EXO_TEST(tokenizer_basic_3d, { return count("a b c ", 3); });
EXO_TEST(tokenizer_basic_compare_0, { return compare("value1 value2 value3", "value1 value2 value3"); });
EXO_TEST(tokenizer_basic_compare_1, { return compare("a b c", "a b c"); });
EXO_TEST(tokenizer_basic_compare_2, { return compare("a b c", "a b c"); });
EXO_TEST(tokenizer_basic_compare_3, { return compare(" a b c", "a b c"); });
EXO_TEST(tokenizer_basic_compare_4, { return compare(" a b c ", "a b c"); });
EXO_TEST(tokenizer_basic_compare_5, { return compare("a b c ", "a b c"); });
EXO_TEST(tokenizer_basic_compare_6, { return compare("a b c ", "a b c"); });
EXO_TEST(tokenizer_comment_1, { return compare("value1 value2 # value3", "value1 value2"); });
EXO_TEST(tokenizer_comment_2, { return compare("value1 value2\\# value3", "value1 value2# value3"); });
EXO_TEST(tokenizer_comment_3, { return compare("value1 \"value2#\" value3", "value1 value2# value3"); });
EXO_TEST(tokenizer_escape_1, { return compare("\"value1\" value2", "value1 value2"); });
EXO_TEST(tokenizer_escape_2, { return compare("\"value1\\\"\" value2", "value1\" value2"); });
EXO_TEST(tokenizer_escape_3, { return compare("\"value1\" \"value 2\"", "value1 value_2"); });
EXO_TEST(tokenizer_escape_4, { return compare("\"value1\" value\\ 2", "value1 value_2"); });
EXO_TEST(tokenizer_escape_5, { return compare("\"value1\" value\\\\2", "value1 value\\2"); });
EXO_TEST(tokenizer_escape_6, { return compare("\"value1\" value\\\t2", "value1 value|2"); });
EXO_TEST(tokenizer_escape_7, { return compare("\"value1\" \"value\t2\"", "value1 value|2"); });
static int test_setting(const char* str, const char* expected_key, const char* expected_value)
{
int success = 0;
struct cfg_settings* setting = cfg_settings_split(str);
if (!setting) return expected_key == NULL;
success = (!strcmp(cfg_settings_get_key(setting), expected_key) && !strcmp(cfg_settings_get_value(setting), expected_value));
cfg_settings_free(setting);
return success;
}
EXO_TEST(tokenizer_settings_1, { return test_setting("foo=bar", "foo", "bar"); });
EXO_TEST(tokenizer_settings_2, { return test_setting("foo =bar", "foo", "bar"); });
EXO_TEST(tokenizer_settings_3, { return test_setting("foo= bar", "foo", "bar"); });
EXO_TEST(tokenizer_settings_4, { return test_setting("\tfoo=bar", "foo", "bar"); });
EXO_TEST(tokenizer_settings_5, { return test_setting("foo=bar\t", "foo", "bar"); });
EXO_TEST(tokenizer_settings_6, { return test_setting("\tfoo=bar\t", "foo", "bar"); });
EXO_TEST(tokenizer_settings_7, { return test_setting("\tfoo\t=\tbar\t", "foo", "bar"); });
EXO_TEST(tokenizer_settings_8, { return test_setting("foo=", "foo", ""); });
EXO_TEST(tokenizer_settings_9, { return test_setting("=bar", NULL, ""); });

View File

@ -1,89 +0,0 @@
#include <uhub.h>
#define MAX_USERS 64
static struct hub_user_manager* uman = 0;
static struct hub_user um_user[MAX_USERS];
EXO_TEST(um_init_1, {
sid_t s;
uman = uman_init();
for (s = 0; s < MAX_USERS; s++)
{
memset(&um_user[s], 0, sizeof(struct hub_user));
um_user[s].id.sid = s;
}
return !!uman;
});
EXO_TEST(um_shutdown_1, {
return uman_shutdown(0) == -1;
});
EXO_TEST(um_shutdown_2, {
return uman_shutdown(uman) == 0;
});
EXO_TEST(um_init_2, {
uman = uman_init();
return !!uman;
});
EXO_TEST(um_add_1, {
return uman_add(uman, &um_user[0]) == 0;
});
EXO_TEST(um_size_1, {
return uman->count == 1;
});
EXO_TEST(um_remove_1, {
return uman_remove(uman, &um_user[0]) == 0;
});
EXO_TEST(um_size_2, {
return uman->count == 0;
});
EXO_TEST(um_add_2, {
int i;
for (i = 0; i < MAX_USERS; i++)
{
if (uman_add(uman, &um_user[i]) != 0)
return 0;
}
return 1;
});
EXO_TEST(um_size_3, {
return uman->count == MAX_USERS;
});
EXO_TEST(um_remove_2, {
int i;
for (i = 0; i < MAX_USERS; i++)
{
if (uman_remove(uman, &um_user[i]) != 0)
return 0;
}
return 1;
});
/* Last test */
EXO_TEST(um_shutdown_4, {
return uman_shutdown(uman) == 0;
});

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 )

25
debian/changelog vendored
View File

@ -1,25 +0,0 @@
uhub (0.3.2-1) unstable; urgency=low
* Updated upstream version.
-- Jan Vidar Krey <janvidar@extatic.org> Mon, 30 May 2010 18:00:00 +0200
uhub (0.3.1-1) unstable; urgency=low
* Updated version number.
-- Jan Vidar Krey <janvidar@extatic.org> Mon, 04 Apr 2010 16:44:21 +0200
uhub (0.3.0-2) unstable; urgency=low
* Fixed init.d scripts.
* Fixed lintian warnings.
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 19:02:02 +0100
uhub (0.3.0-1) unstable; urgency=low
* Initial Release.
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 18:59:02 +0100

1
debian/compat vendored
View File

@ -1 +0,0 @@
7

24
debian/control vendored
View File

@ -1,24 +0,0 @@
Source: uhub
Section: net
Priority: optional
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
Build-Depends: debhelper (>= 7.0.0)
Standards-Version: 3.8.3.0
Package: uhub
Architecture: any
Depends: ${shlibs:Depends}
Description: High performance ADC p2p hub
uhub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users on
high-end servers, or a small private hub on embedded hardware.
.
Key features:
- High performance and low memory usage
- IPv4 and IPv6 support
- Experimental SSL support (optional)
- Advanced access control support
- Easy configuration
.
Homepage: https://www.uhub.org/

19
debian/copyright vendored
View File

@ -1,19 +0,0 @@
uhub - High performance ADC p2p hub.
Copyright (C) 2010 Jan Vidar Krey <janvidar@extatic.org>
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/>.
On Debian GNU/Linux systems, the complete text of the GNU General Public
License can be found in `/usr/share/common-licenses/GPL'.

45
debian/rules vendored
View File

@ -1,45 +0,0 @@
#!/usr/bin/make -f
# export DH_VERBOSE=1
makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \
UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \
RELEASE=YES SILENT=YES
build: build-stamp
build-stamp:
dh_testdir
make $(makeopts)
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
make clean
dh_clean
binary-indep: build
binary-arch: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
$(MAKE) install $(makeopts)
dh_installdocs
dh_installinit
dh_installlogrotate
dh_installman -A
dh_installchangelogs ChangeLog
dh_strip
dh_compress
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary

4
debian/uhub.default vendored
View File

@ -1,4 +0,0 @@
# uhub - high performance adc hub.
UHUB_ENABLE=0

6
debian/uhub.dirs vendored
View File

@ -1,6 +0,0 @@
etc/default
etc/init.d
etc/logrotate.d
etc/uhub
usr/bin
var/log/uhub

5
debian/uhub.docs vendored
View File

@ -1,5 +0,0 @@
AUTHORS
README
BUGS
TODO
doc/getstarted.txt

97
debian/uhub.init vendored
View File

@ -1,97 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: uhub
# Required-Start: $remote_fs $network
# Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
NAME=uhub
DESC="ADC hub"
DAEMON=/usr/bin/uhub
PIDFILE=/var/run/uhub/uhub.pid
LOGFILE=/var/log/uhub/uhub.log
SCRIPTNAME=/etc/init.d/uhub
DEFAULTFILE=/etc/default/uhub
[ -r $DEFAULTFILE ] && . $DEFAULTFILE
DAEMON_ENABLE="${UHUB_ENABLE}"
DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}"
test -x $DAEMON || exit 0
. /lib/lsb/init-functions
ulimit -n 65536
mkdir -p /var/run/uhub/
set -e
case "$1" in
start)
if [ "$DAEMON_ENABLE" != "true" ]; then
log_daemon_msg "Disabled $DESC" $NAME
log_end_msg 0
exit 0
fi
log_daemon_msg "Starting $DESC" $NAME
if ! start-stop-daemon --start --quiet --oknodo \
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
then
log_end_msg 1
else
log_end_msg 0
fi
;;
stop)
log_daemon_msg "Stopping $DESC" $NAME
if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \
--pidfile $PIDFILE --exec $DAEMON
then
rm -f $PIDFILE
log_end_msg 0
else
log_end_msg 1
fi
;;
reload)
log_daemon_msg "Reloading $DESC configuration" $NAME
if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \
--quiet --pidfile $PIDFILE --exec $DAEMON
then
if start-stop-daemon --start --quiet \
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then
log_end_msg 0
else
log_end_msg 1
fi
else
log_end_msg 1
fi
;;
restart|force-reload)
$0 stop
$0 start
;;
status)
status_of_proc $DAEMON $NAME && exit 0 || exit $?
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2
exit 1
;;
esac
exit 0

View File

@ -1,9 +0,0 @@
/var/log/uhub/*.log
{
compress
size 10M
rotate 10
missingok
notifempty
}

View File

@ -1,2 +0,0 @@
doc/uhub.1
doc/uhub-passwd.1

27
debian/uhub.postinst vendored
View File

@ -1,27 +0,0 @@
#!/bin/sh
set -e
case "$1" in
configure)
chmod 0750 /var/log/uhub
if [ -x /etc/init.d/uhub ]; then
update-rc.d uhub defaults >/dev/null
if [ -x /usr/sbin/invoke-rc.d ]; then
invoke-rc.d uhub restart
else
/etc/init.d/uhub restart
fi
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst: error: unknown argument: $1" >&2
exit 1
;;
esac

6
debian/uhub.postrm vendored
View File

@ -1,6 +0,0 @@
#!/bin/sh -e
if [ "$1" = purge ]; then
update-rc.d uhub remove >/dev/null
fi

10
debian/uhub.prerm vendored
View File

@ -1,10 +0,0 @@
#!/bin/sh -e
if [ "$1" = remove ]; then
if command -v invoke-rc.d >/dev/null 2>&1; then
invoke-rc.d uhub stop || true
else
/etc/init.d/uhub stop
fi
fi

View File

@ -1,13 +1,13 @@
= Architecture of uHub =
uHub is single-threaded and handles network and timer events using the
uHub is single threaded and handles network and timer events using the
libevent library.
For each state there is a read event (and sometimes a write event) and timeout
event in case an expected read (or write) event does not occur.
== Protocol overview ==
uHub "speaks" the ADC protocol, which works in short as follows:
uHub use "speak" the ADC protocol, which works in short as follows:
(C = client, S = server aka uHub).
C: HSUP ADBASE
@ -67,7 +67,7 @@ Accepting new users
| | |
| V |
| --------------------- ---------------------
| | Send password | ------> | Receive and check |
| | Send password | ------> | Reveive and check |
| | request, if needed| | password. |
| --------------------- ---------------------
| |

View File

@ -1,25 +1,26 @@
How to compile:
---------------
See the official compiling howto: https://www.uhub.org/compile.php
See the official compiling howto: http://www.extatic.org/uhub/compile.html
Prerequisites
Before you try to compile µHub, please make sure the following prerequisites are met.
* GNU make
* gcc > 3.0 (or MinGW on Windows)
* libevent >= 1.3
* Perl 5
* openssl > 0.9.8 (or use "make USE_SSL=NO")
* sqlite > 3.x
or read https://www.uhub.org/compile.php for more info.
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
-------------------------------------------
Linux and Mac OSX
-----------------
Simply, run:
% make
FreeBSD, NetBSD and OpenBSD
---------------------------
Use GNU make, not BSD make:
% gmake
If you have an old gcc compiler, try disabling pre-compiled headers like this:
gmake USE_PCH=NO

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).
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 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 icomming communication.
If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
and resume in passive mode.

View File

@ -1,6 +1,8 @@
Getting started guide
---------------------
(This document is maintained at http://www.extatic.org/uhub/getstarted.html )
Unpack your binaries
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.
As root, or use sudo.
% mkdir /etc/uhub
% cp doc/uhub.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.
% ps aux | grep uhub
% kill -HUP <pid of uhub>
Or, for the lazy people
% 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.
@ -43,25 +41,6 @@ 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.
Example:
% 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.
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)
* soft nofile 4096
* hard nofile 4096
Or, you can use (as root):
% 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!

View File

@ -1,113 +0,0 @@
#!/bin/sh
#
# chkconfig: - 91 35
# description: Starts and stops the Uhub ( https://www.uhub.org ) daemons on RHEL\CentOS \
# used to provide p2p network services.
#
# pidfile: /var/run/uhub.pid
# config: /etc/uhub/uhub.conf
# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 1
fi
# Avoid using root's TMPDIR
unset TMPDIR
# Source networking configuration.
. /etc/sysconfig/network
if [ -f /etc/sysconfig/uhub ]; then
. /etc/sysconfig/uhub
fi
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
# Check that bin and uhub.conf exists.
[ -f $UHUBBINFILE ] || exit 6
[ -f /etc/uhub/uhub.conf ] || exit 6
RETVAL=0
start() {
KIND="Uhub"
echo -n $"Starting $KIND services: "
daemon $UHUBBINFILE $UHUBOPTIONS
RETVAL=$?
echo ""
return $RETVAL
}
stop() {
KIND="Uhub"
echo -n $"Shutting down $KIND services: "
killproc $UHUBBINFILE
RETVAL=$?
echo ""
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading uhub.conf / user.conf file: "
killproc uhub -HUP
RETVAL=$?
echo ""
return $RETVAL
}
relog() {
echo -n $"Reopen main log file: "
killproc uhub -SIGHUP
RETVAL=$?
echo ""
return $RETVAL
}
rhstatus() {
status $UHUBBINFILE
RETVAL=$?
if [ $RETVAL -ne 0 ] ; then
return $RETVAL
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
relog)
relog
;;
status)
rhstatus
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|relog|status}"
exit 2
esac
exit $?

View File

@ -1,14 +0,0 @@
# Log rotate for Uhub
# see man logrotate
#
#
/var/log/uhub.log {
compress
size 10M
rotate 10
missingok
notifempty
}

View File

@ -1,16 +0,0 @@
# locate bin file
UHUBBINFILE=/usr/bin/uhub
# Options to UHUB
# -v Verbose mode. Add more -v's for higher verbosity.
# -q Quiet mode - no output
# -f Fork to background
# -l <file> Log messages to given file (default: stderr)
# -L Log messages to syslog
# -c <file> Specify configuration file (default: /etc/uhub/uhub.conf)
# -S Show configuration parameters, but ignore defaults
# -u <user> Run as given user
# -g <group> Run with given group permissions
# -p <file> Store pid in file (process id)
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"

View File

@ -1,71 +0,0 @@
# ATTENTION!
# Plugins are invoked in the order of listing in the plugin config file.
# Sqlite based user authentication.
#
# This plugin provides a Sqlite based authentication database for
# registered users.
# Use the uhub-passwd utility to create the database and add/remove users.
#
# Parameters:
# file: path/filename for database.
#
plugin /usr/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
#
# Parameters:
# file: path/filename for log file.
# syslog: if true then syslog is used instead of writing to a file (Unix only)
plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
# A simple example plugin
#plugin /usr/lib/uhub/mod_example.so
# A plugin sending a welcome message.
#
# This plugin provides the following commands:
# !motd - Message of the day
# !rules - Show hub rules.
#
# Parameters:
# motd: path/filename for the welcome message (message of the day)
# rules: path/filename for the rules file
#
# NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted.
#
# The motd/rules files can do the following substitutions:
# %n - Nickname of the user who entered the hub or issued the command.
# %a - IP address of the user
# %c - The credentials of the user (guest, user, op, super, admin).
# %% - Becomes '%'
# %H - Hour 24-hour format (00-23) (Hub local time)
# %I - Hour 12-hour format (01-12) (Hub local time)
# %P - 'AM' or 'PM'
# %p - 'am' or 'pm'
# %M - Minutes (00-59) (Hub local time)
# %S - Seconds (00-60) (Hub local time)
plugin /usr/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rules.txt"
# Load the chat history plugin.
#
# This plugin provides chat history when users are connecting, or
# when users invoke the !history command.
# The history command can optionally take a parameter to indicate how many lines of history is requested.
#
# Parameters:
# history_max: the maximum number of messages to keep in history
# history_default: when !history is provided without arguments, then this default number of messages are returned.
# history_connect: the number of chat history messages to send when users connect (0 = do not send any history)
plugin /usr/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5"

View File

@ -1,5 +0,0 @@
1. rule #1
2. rule #2
3. rule #3
......
34. Rule #34

View File

@ -1,42 +0,0 @@
.TH UHUB-PASSWD "1" "May 2012"
.SH NAME
uhub-passwd \- small utility for manipulating passwords which are
used by uhub daemon
.SH SYNOPSIS
.B uhub-passwd
\fIfilename command \fR[...]
.SH DESCRIPTION
uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware.
.SH "OPTIONS"
.TP
.BI \^create
.TP
.BI \^add " username password [credentials = user]"
.TP
.BI \^del " username"
.TP
.BI \^mod " username credentials"
.TP
.BI \^pass " username password"
.TP
.BI \^list
.SH "PARAMETERS"
.TP
.B 'filename'
is a database file
.TP
.B 'username'
is a nickname (UTF\-8, up to 64 bytes)
.TP
.B 'password'
is a password (UTF\-8, up to 64 bytes)
.TP
.B 'credentials'
is one of 'admin', 'super', 'op', 'user'
.SH AUTHOR
This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS"
If you find a bug in uhub please report it to
.B https://github.com/janvidar/uhub/issues

View File

@ -23,7 +23,7 @@ on high-end servers, or a small private hub on embedded hardware.
.SH "OPTIONS"
.TP
.BI \^\-v
Verbose mode, add more \-v's for higher verbosity.
Verbose mode, add more -v's for higher verbosity.
.TP
.BI \^\-q
Quiet mode, if quiet mode is enabled no output or logs are made.
@ -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>
.SH "BUG REPORTS"
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

@ -1,11 +1,10 @@
# uhub.conf - A example configuration file.
# You should normally place this file in /etc/uhub/uhub.conf
# and customize some of the settings below.
# And change the file_acl and file_motd 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
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
# All configuration directives: https://www.uhub.org/config.php
# HUP signal to it, to reparse configuration (only on UNIX).
# Bind to this port and address
# server_bind_addr=any means listen to "::" if IPv6 is supported
@ -13,18 +12,12 @@
server_port=1511
server_bind_addr=any
# Alternative server ports
# server_alt_ports = 1512, 1513
# The maximum amount of users allowed on the hub.
max_users=500
# If 1, will show a "Powered by uHub/{VERSION}".
# If 1, will show a "This hub is running uhub/version".
show_banner=1
# If enabled then operating system and cpu architecture is part of the banner.
show_banner_sys_info=1
# Allow only registered users on the hub if set to 1.
registered_users_only=0
@ -38,46 +31,12 @@ hub_enabled=1
# Access control list (user database)
file_acl=/etc/uhub/users.conf
# This file can contain a conf for plugin subsystem
file_plugins = /etc/uhub/plugins.conf
# Slots/share/hubs limits
limit_max_hubs_user = 0
limit_max_hubs_reg = 0
limit_max_hubs_op = 0
limit_max_hubs = 0
limit_min_hubs_user = 0
limit_min_hubs_reg = 0
limit_min_hubs_op = 0
limit_min_share = 0
# Example:
# To require users to share at least 1 GB in order to enter the hub:
# limit_min_share = 1024
limit_max_share = 0
limit_min_slots = 0
limit_max_slots = 0
# Flood control support:
# set the interval to 5 seconds
flood_ctl_interval = 5
# Then the maximum chat, connect, search, updates etc will be measured over 5 seconds.
# So, 3 chat messages per 5 seconds allowed.
flood_ctl_chat=3
flood_ctl_connect=20
flood_ctl_search=1
flood_ctl_update=2
flood_ctl_extras=5
# chat control
# if chat_is_privileged=yes only registered users may write in main chat
chat_is_privileged = no
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
# defaults obsolete_clients=1
obsolete_clients=1
# This file can contain a message of the day. A welcome
# message send to any client when connecting.
# If the file does not exist, is empty, or cannot be opened
# the motd will not be sent to the clients.
# Normally this message is sent to clients when connecting.
file_motd=/etc/uhub/motd.txt
# Configure status message as sent to clients in different circumstances.
msg_hub_full = Hub is full
@ -102,23 +61,6 @@ msg_ban_permanently = Banned permanently
msg_ban_temporarily = Banned temporarily
msg_auth_invalid_password = Password is wrong
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_high = User is sharing too much
msg_user_slots_low = User has too few upload slots
msg_user_slots_high = User has too many upload slots
msg_user_hub_limit_low = User is on too few hubs
msg_user_hub_limit_high = User is on too many hubs
msg_error_no_memory = Out of memory
msg_user_flood_chat = Chat flood detected, messages are dropped.
msg_user_flood_connect = Connect flood detected, connection refused.
msg_user_flood_search = Search flood detected, search is stopped.
msg_user_flood_update = Update flood detected.
msg_user_flood_extras = Flood detected.
msg_error_no_memory = No memory
# If a client that supports ADC but not a compatible hash algorithm (tiger),
# then the hub cannot accept the client:
msg_proto_no_common_hash = No common hash algorithm.
# Message to be shown to old clients using an older version of ADC than ADC/1.0
msg_proto_obsolete_adc0 = Client is using an obsolete ADC protocol version.

View File

@ -1,42 +0,0 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
inherit eutils
if [ "$PV" != "9999" ]; then
SRC_URI="https://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
KEYWORDS="~amd64 ~x86"
else
inherit git
SRC_URI=""
EGIT_REPO_URI="git://github.com/janvidar/uhub.git"
KEYWORDS=""
fi
EAPI="2"
DESCRIPTION="High performance ADC hub"
HOMEPAGE="https://www.uhub.org/"
LICENSE="GPL-3"
SLOT="0"
IUSE="+ssl"
DEPEND="=dev-lang/perl-5*
ssl? ( >=dev-libs/openssl-0.9.8 )
"
RDEPEND="${DEPEND}"
src_compile() {
$opts=""
use ssl && opts="USE_SSL=YES $opts"
emake $opts
}
src_install() {
dodir /usr/bin
dodir /etc/uhub
emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed"
newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub
}
pkg_postinst() {
enewuser uhub
}

View File

@ -1,102 +0,0 @@
Summary: High performance ADC p2p hub.
Name: uhub
Version: 0.4.0
Release: 2
License: GPLv3
Group: Networking/File transfer
Source: uhub-%{version}.tar.gz
URL: https://www.uhub.org
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: sqlite-devel
BuildRequires: openssl-devel
%description
uhub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users on
high-end servers, or a small private hub on embedded hardware.
Key features:
- High performance and low memory usage
- IPv4 and IPv6 support
- Experimental SSL support (optional)
- Advanced access control support
- Easy configuration
- plugin support
- mod_welcome - MOTD\RULES messages
- mod_auth_sipmle - auth with sqlite DB
- mod_logging - log hub activity
%prep
%setup -q -n %{name}-%{version}
%build
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
make
%install
mkdir -p $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT/etc/uhub
mkdir -p $RPM_BUILD_ROOT/etc/init.d
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
mkdir -p $RPM_BUILD_ROOT/usr/lib/uhub
install uhub $RPM_BUILD_ROOT/usr/bin/
install uhub-passwd $RPM_BUILD_ROOT/usr/bin/
> doc/motd.txt
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt doc/plugins.conf doc/users.db $RPM_BUILD_ROOT/etc/uhub
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
install -m644 mod_*.so $RPM_BUILD_ROOT/usr/lib/uhub
%files
%defattr(-,root,root)
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
%config(noreplace) /etc/uhub/uhub.conf
#%{_sysconfdir}/uhub/uhub.conf
%config(noreplace) %{_sysconfdir}/uhub/users.conf
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
%config(noreplace) %{_sysconfdir}/uhub/plugins.conf
%config(noreplace) %{_sysconfdir}/uhub/users.db
%{_sysconfdir}/init.d/uhub
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
/usr/share/man/man1/uhub.1.gz
%{_bindir}/uhub
%{_libdir}/uhub/mod_*.so
%clean
rm -rf $RPM_BUILD_ROOT
%post
/sbin/chkconfig --add uhub
if [ $1 -gt 1 ] ; then
/etc/rc.d/init.d/uhub restart >/dev/null || :
fi
# need more information 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 ||:
# write SSL create
echo "PLS see /usr/share/doc/uhub/"
%changelog
* Fri Dec 30 2011 E_zombie
- add users.db
- add new doc
* Tue Jun 26 2010 E_zombie
- add plugins.conf
* Tue Jan 31 2010 E_zombie
- change GROUP
- chmod for files
- add postinstall scripts
- fix "License"
* Tue Jan 26 2010 E_zombie
- first .spec release

View File

@ -1,28 +0,0 @@
# uHub - a lightweight but high-performance hub for the ADC
# peer-to-peer protocol.
description "uHub - High performance ADC peer-to-peer hub"
# Start and stop conditions.
start on filesystem or runlevel [2345]
stop on runlevel [!2345]
# 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.
respawn
respawn limit 10 5
# The program is going to fork, and upstart needs to know this
# so it can track the change in PID.
expect fork
# Set the mode the process should create files in.
umask 022
# Make sure the log folder exists.
pre-start script
mkdir -p -m0755 /var/log/uhub
end script
# Command to run it.
exec /usr/bin/uhub -f -u uhub -g uhub -l /var/log/uhub/uhub.log -c /etc/uhub/uhub.conf

View File

@ -12,8 +12,8 @@
# 'ban_cid' - banned user by cid
# Administrator
# user_admin userA:password1
# user_op userB:password2
user_admin Dj_Offset:uhub
user_op janvidar:password
# We don't want users with these names
deny_nick Hub-Security

View File

@ -1,155 +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"
const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
char* sid_to_string(sid_t sid_)
{
static char t_sid[5];
sid_t sid = (sid_ & 0xFFFFF); /* 20 bits only */
sid_t A, B, C, D = 0;
D = (sid % 32);
sid = (sid - D) / 32;
C = (sid % 32);
sid = (sid - C) / 32;
B = (sid % 32);
sid = (sid - B) / 32;
A = (sid % 32);
t_sid[0] = BASE32_ALPHABET[A];
t_sid[1] = BASE32_ALPHABET[B];
t_sid[2] = BASE32_ALPHABET[C];
t_sid[3] = BASE32_ALPHABET[D];
t_sid[4] = 0;
return t_sid;
}
sid_t string_to_sid(const char* sid)
{
sid_t nsid = 0;
sid_t n, x;
sid_t factors[] = { 32768, 1024, 32, 1};
if (!sid || strlen(sid) != 4) return 0;
for (n = 0; n < 4; n++) {
for (x = 0; x < strlen(BASE32_ALPHABET); x++)
if (sid[n] == BASE32_ALPHABET[x]) break;
if (x == 32) return 0;
nsid += x * factors[n];
}
return nsid;
}
/*
* Session IDs are heavily reused, since they are a fairly scarce
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
* value and 'AAAA' (0) is reserved for the hub.
*
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
*
* When allocating a session ID:
* - If 'count' is less than the pool size (max-min), then allocate within the pool
* - Increase the pool size (see below)
* - If unable to do that, hub is really full - don't let anyone in!
*
* When freeing a session ID:
* - If the session ID being freed is 'max', then decrease the pool size by one.
*
*/
struct sid_pool
{
sid_t min;
sid_t max;
sid_t count;
struct hub_user** map;
};
struct sid_pool* sid_pool_create(sid_t max)
{
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
if (!pool)
return 0;
pool->min = 1;
pool->max = max + 1;
pool->count = 0;
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
if (!pool->map)
{
hub_free(pool);
return 0;
}
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
#endif
return pool;
}
void sid_pool_destroy(struct sid_pool* pool)
{
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
#endif
hub_free(pool->map);
hub_free(pool);
}
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
{
sid_t n;
if (pool->count >= (pool->max - pool->min))
{
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
#endif
return 0;
}
n = (++pool->count);
for (; (pool->map[n % pool->max]); n++) ;
#ifdef DEBUG_SID
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
#endif
pool->map[n] = user;
return n;
}
void sid_free(struct sid_pool* pool, sid_t sid)
{
#ifdef DEBUG_SID
LOG_DUMP("SID_FREE: %d", (int) sid);
#endif
pool->map[sid] = 0;
pool->count--;
}
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
{
if (!sid || (sid >= pool->max))
return 0;
return pool->map[sid];
}

View File

@ -1,41 +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_SID_H
#define HAVE_UHUB_SID_H
#define SID_MAX 1048576
struct sid_pool;
struct hub_user;
extern char* sid_to_string(sid_t sid_);
extern sid_t string_to_sid(const char* sid);
extern struct sid_pool* sid_pool_create(sid_t max);
extern void sid_pool_destroy(struct sid_pool*);
extern sid_t sid_alloc(struct sid_pool*, struct hub_user*);
extern void sid_free(struct sid_pool*, sid_t);
extern struct hub_user* sid_lookup(struct sid_pool*, sid_t);
#endif /* HAVE_UHUB_SID_H */

View File

@ -1,6 +1,6 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -13,18 +13,14 @@
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_ADC_CONSTANTS_H
#define HAVE_UHUB_ADC_CONSTANTS_H
#ifndef SID_T_DEFINED
typedef uint32_t sid_t;
#define SID_T_DEFINED
#endif
typedef uint32_t fourcc_t;
/* Internal uhub limit */
@ -33,7 +29,7 @@ typedef uint32_t fourcc_t;
#define FOURCC(a,b,c,d) (fourcc_t) ((a << 24) | (b << 16) | (c << 8) | d)
/* default welcome protocol support message, as sent by this server */
#define ADC_PROTO_SUPPORT "ADBASE ADTIGR ADPING ADUCMD"
#define ADC_PROTO_SUPPORT "ADBASE ADTIGR ADPING"
/* Server sent commands */
#define ADC_CMD_ISID FOURCC('I','S','I','D')
@ -64,11 +60,6 @@ typedef uint32_t fourcc_t;
#define ADC_CMD_FSCH FOURCC('F','S','C','H')
#define ADC_CMD_DRES FOURCC('D','R','E','S')
/* invalid search results (spam) */
#define ADC_CMD_BRES FOURCC('B','R','E','S')
#define ADC_CMD_ERES FOURCC('E','R','E','S')
#define ADC_CMD_FRES FOURCC('F','R','E','S')
/* connection setup */
#define ADC_CMD_DCTM FOURCC('D','C','T','M')
#define ADC_CMD_DRCM FOURCC('D','R','C','M')
@ -85,23 +76,10 @@ typedef uint32_t fourcc_t;
#define ADC_CMD_DINF FOURCC('D','I','N','F')
#define ADC_CMD_EINF FOURCC('E','I','N','F')
#define ADC_CMD_FINF FOURCC('F','I','N','F')
#define ADC_CMD_BQUI FOURCC('B','Q','U','I')
#define ADC_CMD_DQUI FOURCC('D','Q','U','I')
#define ADC_CMD_EQUI FOURCC('E','Q','U','I')
#define ADC_CMD_FQUI FOURCC('F','Q','U','I')
/* Extension messages */
#define ADC_CMD_HCHK FOURCC('H','C','H','K')
/* UCMD Extension */
#define ADC_CMD_BCMD FOURCC('B','C','M','D')
#define ADC_CMD_DCMD FOURCC('D','C','M','D')
#define ADC_CMD_ECMD FOURCC('E','C','M','D')
#define ADC_CMD_FCMD FOURCC('F','C','M','D')
#define ADC_CMD_HCMD FOURCC('H','C','M','D')
#define ADC_CMD_ICMD FOURCC('I','C','M','D')
#define ADC_INF_FLAG_IPV4_ADDR "I4" /* ipv4 address */
#define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */
#define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */
@ -111,15 +89,12 @@ typedef uint32_t fourcc_t;
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
#define ADC_INF_FLAG_NICK "NI" /* nick name */
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
#define ADC_INF_FLAG_USER_AGENT_PRODUCT "AP" /* software name */
#define ADC_INF_FLAG_USER_AGENT_VERSION "VE" /* software version */
#define ADC_INF_FLAG_USER_AGENT "VE" /* software version */
#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_FILES "SF" /* number of files shared */
#define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed achieved in bytes/sec */
#define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download 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 acheived in bytes/sec */
#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_MAX "AM" /* maximum number of automatic slots */
@ -134,7 +109,7 @@ typedef uint32_t fourcc_t;
#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_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_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 */
@ -156,10 +131,9 @@ typedef uint32_t fourcc_t;
#define ADC_SUP_FLAG_ADD "AD"
#define ADC_SUP_FLAG_REMOVE "RM"
#define ADC_CLIENT_TYPE_BOT "1"
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
#define ADC_CLIENT_TYPE_OPERATOR "4"
#define ADC_CLIENT_TYPE_HUBBOT "5" /* 1 + 4 */
#define ADC_CLIENT_TYPE_BOT "1"
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
#define ADC_CLIENT_TYPE_OPERATOR "4"
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */

951
src/adcrush.c Normal file
View File

@ -0,0 +1,951 @@
/**
* An ADC client emulator.
*/
#include "uhub.h"
#define ADC_CLIENTS_DEFAULT 100
#define ADC_MAX_CLIENTS 25000
#define ADC_BUFSIZE 16384
#define ADC_SIDSIZE 4
#define ADC_CID_SIZE 39
#define BIG_BUFSIZE 131072
#define TIGERSIZE 24
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR\n"
#define ADCRUSH "adcrush/0.2"
#define ADC_NICK "[BOT]adcrush"
#define ADC_DESC "crash\\stest\\sdummy"
struct ADC_client;
static void ADC_client_on_disconnected(struct ADC_client*);
static void ADC_client_on_connected(struct ADC_client*);
static void ADC_client_on_login(struct ADC_client*);
static void ADC_client_connect(struct ADC_client*);
static void ADC_client_disconnect(struct ADC_client*);
static int ADC_client_create(struct ADC_client* client, int num);
static void ADC_client_destroy(struct ADC_client* client);
static int cfg_mode = 0; // See enum operationMode
static char* cfg_host = 0;
static int cfg_port = 0;
static int cfg_debug = 0; /* debug level */
static int cfg_level = 1; /* activity level (0..3) */
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
static int cfg_quiet = 0; /* quiet mode (no output) */
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
static int running = 1;
static struct sockaddr_in saddr;
enum commandMode
{
cm_bcast = 0x01, /* B - broadcast */
cm_dir = 0x02, /* D - direct message */
cm_echo = 0x04, /* E - echo message */
cm_fcast = 0x08, /* F - feature cast message */
cm_c2h = 0x10, /* H - client to hub message */
cm_h2c = 0x20, /* I - hub to client message */
cm_c2c = 0x40, /* C - client to client message */
cm_udp = 0x80, /* U - udp message (client to client) */
};
enum commandValidity
{
cv_protocol = 0x01,
cv_identify = 0x02,
cv_verify = 0x04,
cv_normal = 0x08,
};
enum protocolState
{
ps_none = 0x00, /* none or disconnected */
ps_conn = 0x01, /* connecting... */
ps_protocol = 0x02,
ps_identify = 0x04,
ps_verify = 0x08,
ps_normal = 0x10,
};
enum operationMode
{
mode_performance = 0x01,
mode_bugs = 0x02,
mode_security = 0x04,
mode_log = 0x08,
};
struct commandPattern
{
unsigned char mode; /* see enum commandMode */
char cmd[3];
unsigned char validity; /* see enum commandValidity */
};
const struct commandPattern patterns[] =
{
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
{ cm_h2c, "QUI", cv_normal }, /* quit message */
{ cm_h2c, "GPA", cv_identify }, /* password request */
{ cm_c2h, "PAS", cv_verify } /* password response */
};
#define MAX_CHAT_MSGS 35
const char* chat_messages[MAX_CHAT_MSGS] = {
"hello",
"I'm an annoying robot, configured to chat in order to measure performance of the hub.",
"I apologize for the inconvenience.",
".",
":)",
"can anyone help me, pls?",
"wtf?",
"bullshit",
"resistance is futile.",
"You crossed the line first, sir. You squeezed them, you hammered them to the point of desperation. And in their desperation they turned to a man they didn't fully understand.",
"beam me up, scotty",
"morning",
"You know where Harvey is? You know who he is?",
"gtg",
"thanks",
"*punt*",
"*nudge*",
"that's ok",
"...anyway",
"hola",
"hey",
"hi",
"nevermind",
"i think so",
"dunno",
"debian ftw",
"oops",
"how do I search?",
"how do I enable active mode?",
"home, sweet home...",
"later",
"Good evening, ladies and gentlemen. We are tonight's entertainment! I only have one question. Where is Harvey Dent?",
"You know where I can find Harvey? I need to talk to him about something. Just something, a little.",
"We really should stop fighting, we'll miss the fireworks!",
"Wanna know how I got these scars?",
};
#define MAX_SEARCH_MSGS 10
const char* search_messages[MAX_SEARCH_MSGS] = {
"ANmp3 TOauto",
"ANxxx TOauto",
"ANdivx TOauto",
"ANtest ANfoo TOauto",
"ANwmv TO1289718",
"ANbabe TO8981884",
"ANpr0n TOauto",
"ANmusic TOauto",
"ANvideo TOauto",
"ANburnout ANps3 TOauto",
};
struct ADC_client
{
int sd;
int num;
sid_t sid;
enum protocolState state;
char info[ADC_BUFSIZE];
char recvbuf[BIG_BUFSIZE];
char sendbuf[BIG_BUFSIZE];
size_t s_offset;
size_t r_offset;
struct event ev_read;
struct event ev_write;
struct event ev_timer;
size_t timeout;
};
static void bot_output(struct ADC_client* client, const char* format, ...)
{
char logmsg[1024];
va_list args;
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
if (cfg_mode == mode_log)
{
fprintf(stdout, "%s\n", logmsg);
}
else
{
if (cfg_debug)
fprintf(stdout, "* [%4d] %s\n", client->num, logmsg);
}
}
static void adc_cid_pid(struct ADC_client* client)
{
char seed[64];
char pid[64];
char cid[64];
uint64_t tiger_res1[3];
uint64_t tiger_res2[3];
/* create cid+pid pair */
memset(seed, 0, 64);
snprintf(seed, 64, ADCRUSH "%p/%d", client, (int) client->num);
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
cid[ADC_CID_SIZE] = 0;
pid[ADC_CID_SIZE] = 0;
strcat(client->info, " PD");
strcat(client->info, pid);
strcat(client->info, " ID");
strcat(client->info, cid);
}
static size_t get_wait_rand(size_t max)
{
static size_t next = 0;
if (next == 0) next = (size_t) time(0);
next = (next * 1103515245) + 12345;
return ((size_t )(next / 65536) % max);
}
static void client_reschedule_timeout(struct ADC_client* client)
{
size_t next_timeout = 0;
struct timeval timeout = { 0, 0 };
switch (client->state)
{
case ps_conn: next_timeout = 30; break;
case ps_protocol: next_timeout = 30; break;
case ps_identify: next_timeout = 30; break;
case ps_verify: next_timeout = 30; break;
case ps_normal: next_timeout = 120; break;
case ps_none: next_timeout = 120; break;
}
if (client->state == ps_normal || client->state == ps_none)
{
switch (cfg_level)
{
case 0: /* polite */
next_timeout *= 4;
break;
case 1: /* normal */
break;
case 2: /* aggressive */
next_timeout /= 8;
break;
case 3: /* excessive */
next_timeout /= 16;
case 4: /* excessive */
next_timeout /= 32;
}
}
if (client->state == ps_conn)
client->timeout = MAX(next_timeout, 1);
else
client->timeout = get_wait_rand(MAX(next_timeout, 1));
if (!client->timeout) client->timeout++;
timeout.tv_sec = (time_t) client->timeout;
evtimer_add(&client->ev_timer, &timeout);
}
static void set_state_timeout(struct ADC_client* client, enum protocolState state)
{
client->state = state;
client_reschedule_timeout(client);
}
static void send_client(struct ADC_client* client, char* msg)
{
int ret = net_send(client->sd, msg, strlen(msg), UHUB_SEND_SIGNAL);
if (cfg_debug > 1)
{
char* dump = strdup(msg);
dump[strlen(msg) - 1] = 0;
bot_output(client, "- SEND: '%s'", dump);
free(dump);
}
if (ret != strlen(msg))
{
if (ret == -1)
{
if (net_error() != EWOULDBLOCK)
ADC_client_on_disconnected(client);
}
else
{
/* FIXME: Not all data sent! */
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
}
}
}
static void ADC_client_on_connected(struct ADC_client* client)
{
send_client(client, ADC_HANDSHAKE);
set_state_timeout(client, ps_protocol);
bot_output(client, "connected.");
}
static void ADC_client_on_disconnected(struct ADC_client* client)
{
event_del(&client->ev_read);
event_del(&client->ev_write);
net_close(client->sd);
client->sd = -1;
bot_output(client, "disconnected.");
set_state_timeout(client, ps_none);
}
static void ADC_client_on_login(struct ADC_client* client)
{
bot_output(client, "logged in.");
set_state_timeout(client, ps_normal);
}
static void send_client_info(struct ADC_client* client)
{
client->info[0] = 0;
strcat(client->info, "BINF ");
strcat(client->info, sid_to_string(client->sid));
strcat(client->info, " NI" ADC_NICK);
if (cfg_clients > 1)
{
strcat(client->info, "_");
strcat(client->info, uhub_itoa(client->num));
}
strcat(client->info, " VE" ADCRUSH);
strcat(client->info, " DE" ADC_DESC);
strcat(client->info, " I40.0.0.0");
strcat(client->info, " EMuhub@extatic.org");
strcat(client->info, " SL3");
strcat(client->info, " HN1");
strcat(client->info, " HR1");
strcat(client->info, " HO1");
adc_cid_pid(client);
strcat(client->info, "\n");
send_client(client, client->info);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
static int recv_client(struct ADC_client* client)
{
ssize_t size = 0;
if (cfg_mode != mode_performance || (cfg_mode == mode_performance && (get_wait_rand(100) < (90 - (15 * cfg_level)))))
{
size = net_recv(client->sd, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset, 0);
}
else
{
if (get_wait_rand(1000) == 99)
return -1; /* Can break tings badly! :-) */
else
return 0;
}
if (size == 0 || ((size == -1 && net_error() != EWOULDBLOCK)))
return -1;
client->recvbuf[client->r_offset + size] = 0;
char* start = client->recvbuf;
char* pos;
char* lastPos;
while ((pos = strchr(start, '\n')))
{
lastPos = pos;
pos[0] = 0;
if (cfg_debug > 1)
{
bot_output(client, "- RECV: '%s'", start);
}
fourcc_t cmd = 0;
if (strlen(start) < 4)
{
bot_output(client, "Unexpected response from hub: '%s'", start);
start = &pos[1];
continue;
}
cmd = FOURCC(start[0], start[1], start[2], start[3]);
switch (cmd)
{
case ADC_CMD_ISUP:
break;
case ADC_CMD_ISID:
if (client->state == ps_protocol)
{
client->sid = string_to_sid(&start[5]);
client->state = ps_identify;
send_client_info(client);
}
break;
case ADC_CMD_IINF:
break;
case ADC_CMD_BSCH:
case ADC_CMD_FSCH:
{
if (get_wait_rand(100) > (90 - (10 * cfg_level)) && cfg_mode == mode_performance)
{
sid_t target = string_to_sid(&start[5]);
const char* what = strstr(&start[5], " AN");
const char* token = strstr(&start[5], " TO");
char* split = 0;
if (!token || !what) break;
token += 3;
what += 3;
split = strchr(what, ' ');
if (!split) break;
else split[0] = '0';
split = strchr(token, ' ');
if (split) split[0] = '0';
perf_result(client, target, what, token);
}
break;
}
case ADC_CMD_BINF:
{
if (strlen(start) > 9)
{
char t = start[9]; start[9] = 0; sid_t sid = string_to_sid(&start[5]); start[9] = t;
if (sid == client->sid)
{
if (client->state == ps_verify || client->state == ps_identify)
{
ADC_client_on_login(client);
}
}
}
break;
}
case ADC_CMD_ISTA:
if (strncmp(start, "ISTA 000", 8))
{
bot_output(client, "status: '%s'\n", (start + 9));
}
break;
default:
break;
}
start = &pos[1];
}
client->r_offset = strlen(lastPos);
memmove(client->recvbuf, lastPos, strlen(lastPos));
memset(&client->recvbuf[client->r_offset], 0, ADC_BUFSIZE-client->r_offset);
return 0;
}
void ADC_client_connect(struct ADC_client* client)
{
struct timeval timeout = { TIMEOUT_IDLE, 0 };
net_connect(client->sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in));
set_state_timeout(client, ps_conn);
event_add(&client->ev_read, &timeout);
event_add(&client->ev_write, &timeout);
bot_output(client, "connecting...");
}
void ADC_client_wait_connect(struct ADC_client* client)
{
set_state_timeout(client, ps_none);
}
void ADC_client_disconnect(struct ADC_client* client)
{
if (client->sd != -1)
{
net_close(client->sd);
client->sd = -1;
event_del(&client->ev_read);
event_del(&client->ev_write);
bot_output(client, "disconnected.");
if (running)
{
ADC_client_destroy(client);
ADC_client_create(client, client->num);
ADC_client_connect(client);
}
}
}
static void perf_chat(struct ADC_client* client, int priv)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_CHAT_MSGS-1);
char* msg = adc_msg_escape(chat_messages[r]);
if (priv)
{
strcat(buf, "EMSG ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
}
else
{
strcat(buf, "BMSG ");
strcat(buf, sid_to_string(client->sid));
}
strcat(buf, " ");
strcat(buf, msg);
hub_free(msg);
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_search(struct ADC_client* client)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_SEARCH_MSGS-1);
size_t pst = get_wait_rand(100);
if (pst > 80)
{
strcat(buf, "FSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " +TCP4 ");
}
else
{
strcat(buf, "BSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
}
strcat(buf, search_messages[r]);
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
{
char buf[1024] = { 0, };
strcat(buf, "DRES ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(target));
strcat(buf, " FN" "test/");
strcat(buf, what);
strcat(buf, ".dat");
strcat(buf, " SL" "0");
strcat(buf, " SI" "908987128912");
strcat(buf, " TR" "5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
strcat(buf, " TO");
strcat(buf, token);
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_ctm(struct ADC_client* client)
{
char buf[1024] = { 0, };
strcat(buf, "DCTM ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, "ADC/1.0");
strcat(buf, " TOKEN111");
strcat(buf, sid_to_string(client->sid));
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_update(struct ADC_client* client)
{
char buf[1024] = { 0, };
int n = (int) get_wait_rand(10)+1;
strcat(buf, "BINF ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " HN");
strcat(buf, uhub_itoa(n));
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_normal_action(struct ADC_client* client)
{
size_t r = get_wait_rand(5);
size_t p = get_wait_rand(100);
switch (r)
{
case 0:
if (p > (90 - (10 * cfg_level)))
{
if (cfg_debug > 1) bot_output(client, "timeout -> disconnect");
ADC_client_disconnect(client);
}
break;
case 1:
if (cfg_chat)
{
if (cfg_debug > 1) bot_output(client, "timeout -> chat");
perf_chat(client, 0);
}
break;
case 2:
if (cfg_debug > 1) bot_output(client, "timeout -> search");
perf_search(client);
break;
case 3:
if (cfg_debug > 1) bot_output(client, "timeout -> update");
perf_update(client);
break;
case 4:
if (cfg_debug > 1) bot_output(client, "timeout -> privmsg");
perf_chat(client, 1);
break;
case 5:
if (cfg_debug > 1) bot_output(client, "timeout -> ctm/rcm");
perf_ctm(client);
break;
}
client_reschedule_timeout(client);
}
void event_callback(int fd, short ev, void *arg)
{
struct ADC_client* client = (struct ADC_client*) arg;
if (ev & EV_READ)
{
if (recv_client(client) == -1)
{
ADC_client_on_disconnected(client);
}
}
if (ev & EV_TIMEOUT)
{
if (client->state == ps_none)
{
if (client->sd == -1)
{
ADC_client_create(client, client->num);
}
ADC_client_connect(client);
}
if (fd == -1)
{
if (client->state == ps_normal && cfg_mode == mode_performance)
{
perf_normal_action(client);
}
}
}
if (ev & EV_WRITE)
{
if (client->state == ps_conn)
{
ADC_client_on_connected(client);
}
else
{
/* FIXME: Call send again */
}
}
}
int ADC_client_create(struct ADC_client* client, int num)
{
struct timeval timeout = { 0, 0 };
memset(client, 0, sizeof(struct ADC_client));
client->num = num;
client->sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client->sd == -1) return -1;
event_set(&client->ev_write, client->sd, EV_WRITE, event_callback, client);
event_set(&client->ev_read, client->sd, EV_READ | EV_PERSIST, event_callback, client);
net_set_nonblocking(client->sd, 1);
timeout.tv_sec = client->timeout;
evtimer_set(&client->ev_timer, event_callback, client);
set_state_timeout(client, ps_none);
return 0;
}
void ADC_client_destroy(struct ADC_client* client)
{
ADC_client_disconnect(client);
evtimer_del(&client->ev_timer);
}
void runloop(size_t clients)
{
size_t n = 0;
struct ADC_client* client[ADC_MAX_CLIENTS];
for (n = 0; n < clients; n++)
{
struct ADC_client* c = malloc(sizeof(struct ADC_client));
client[n] = c;
ADC_client_create(c, n);
if (n == 0)
{
ADC_client_connect(c);
}
else
{
ADC_client_wait_connect(c);
}
}
event_dispatch();
for (n = 0; n < clients; n++)
{
ADC_client_destroy(client[n]);
free(client[n]);
}
}
static void print_version()
{
printf(ADCRUSH "\n");
printf("Copyright (C) 2008-2009, Jan Vidar Krey\n");
printf("\n");
}
static void print_usage(const char* program)
{
print_version();
printf("Usage: %s <mode> (adc://<host>:<port>) [options]\n", program);
printf("\n");
printf(" Modes\n");
printf(" perf Do performance testing using multiple clients\n");
printf(" bugs Bugs mode, use fuzzer to construct pseudo-random commands.\n");
printf(" security Perform security tests for the hub.\n");
printf(" log Connect one client to the hub and log the output hub.\n");
printf("\n");
printf(" General options\n");
printf(" -c Allow broadcasting chat messages.\n");
printf(" -d Enable debug output.\n");
printf(" -q Quiet mode (no output).\n");
printf("\n");
printf(" Performance options:\n");
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
printf(" -n <num> Number of concurrent connections\n");
printf("\n");
exit(0);
}
int set_defaults()
{
switch (cfg_mode)
{
case mode_performance:
break;
case mode_bugs:
break;
case mode_security:
break;
case mode_log:
cfg_quiet = 0;
cfg_debug = 2;
cfg_clients = 1;
break;
}
return 1;
}
int parse_mode(const char* arg)
{
cfg_mode = 0;
if (!strcmp(arg, "perf"))
cfg_mode = mode_performance;
else if (!strcmp(arg, "bugs"))
cfg_mode = mode_bugs;
else if (!strcmp(arg, "security"))
cfg_mode = mode_security;
else if (!strcmp(arg, "log"))
cfg_mode = mode_log;
return cfg_mode;
}
int parse_address(const char* arg)
{
char* split;
struct hostent* dns;
struct in_addr* addr;
if (!arg)
return 0;
if (strlen(arg) < 9)
return 0;
if (strncmp(arg, "adc://", 6))
return 0;
split = strrchr(arg+6, ':');
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0;
cfg_port = strtol(split+1, NULL, 10);
if (cfg_port <= 0 || cfg_port > 65535)
return 0;
split[0] = 0;
dns = gethostbyname(arg+6);
if (dns)
{
addr = (struct in_addr*) dns->h_addr_list[0];
cfg_host = strdup(inet_ntoa(*addr));
}
if (!cfg_host)
return 0;
return 1;
}
int parse_arguments(int argc, char** argv)
{
int ok = 1;
int opt;
for (opt = 3; opt < argc; opt++)
{
if (!strcmp(argv[opt], "-c"))
cfg_chat = 1;
else if (!strncmp(argv[opt], "-d", 2))
cfg_debug += strlen(argv[opt]) - 1;
else if (!strcmp(argv[opt], "-q"))
cfg_quiet = 1;
else if (!strcmp(argv[opt], "-l") && (++opt) < argc)
{
cfg_level = MIN(MAX(uhub_atoi(argv[opt]), 0), 3);
}
else if (!strcmp(argv[opt], "-n") && (++opt) < argc)
{
cfg_clients = MIN(MAX(uhub_atoi(argv[opt]), 1), ADC_MAX_CLIENTS);
}
}
return ok;
}
void parse_command_line(int argc, char** argv)
{
if (argc < 2 ||
!parse_mode(argv[1]) ||
!set_defaults() ||
!parse_address(argv[2]) ||
!parse_arguments(argc, argv))
{
print_usage(argv[0]);
}
}
int main(int argc, char** argv)
{
parse_command_line(argc, argv);
net_initialize();
event_init();
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(cfg_port);
net_string_to_address(AF_INET, cfg_host, &saddr.sin_addr);
runloop(cfg_clients);
net_shutdown();
return 0;
}

View File

@ -1,6 +1,6 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@ -23,25 +23,44 @@
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
const char* get_user_credential_string(enum user_credentials cred)
{
switch (cred)
{
case cred_none: return "none";
case cred_bot: return "bot";
case cred_guest: return "guest";
case cred_user: return "user";
case cred_operator: return "operator";
case cred_super: return "super";
case cred_admin: return "admin";
case cred_link: return "link";
}
return "";
};
static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count)
{
char* data;
char* data_extra;
if (!strncmp(line, cmd, strlen(cmd)))
{
data = &line[strlen(cmd)];
data_extra = 0;
data[0] = '\0';
data++;
data = strip_white_space(data);
if (!*data)
{
LOG_FATAL("ACL parse error on line %d", line_count);
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
}
list_append(list, hub_strdup(data));
LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd);
hub_log(log_debug, "ACL: Deny access for: '%s' (%s)", data, cmd);
return 1;
}
return 0;
@ -51,30 +70,30 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
{
char* data;
char* data_extra;
struct auth_info* info = 0;
struct user_access_info* info = 0;
if (!strncmp(line, cmd, strlen(cmd)))
{
data = &line[strlen(cmd)];
data_extra = 0;
data[0] = '\0';
data++;
data = strip_white_space(data);
if (!*data)
{
LOG_FATAL("ACL parse error on line %d", line_count);
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
}
info = hub_malloc_zero(sizeof(struct auth_info));
info = hub_malloc_zero(sizeof(struct user_access_info));
if (!info)
{
LOG_ERROR("ACL parse error. Out of memory!");
hub_log(log_error, "ACL parse error. Out of memory!");
return -1;
}
if (strncmp(cmd, "user_", 5) == 0)
{
data_extra = strrchr(data, ':');
@ -84,24 +103,23 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
data_extra++;
}
}
strncpy(info->nickname, data, MAX_NICK_LEN);
if (data_extra)
strncpy(info->password, data_extra, MAX_PASS_LEN);
info->credentials = status;
info->username = hub_strdup(data);
info->password = data_extra ? hub_strdup(data_extra) : 0;
info->status = status;
list_append(list, info);
LOG_DEBUG("ACL: Added user '%s' (%s)", info->nickname, auth_cred_to_string(info->credentials));
hub_log(log_debug, "ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
return 1;
}
return 0;
}
static void add_ip_range(struct linked_list* list, struct ip_range* info)
static void add_ip_range(struct linked_list* list, struct ip_ban_record* info)
{
char buf1[INET6_ADDRSTRLEN+1];
char buf2[INET6_ADDRSTRLEN+1];
if (info->lo.af == AF_INET)
{
net_address_to_string(AF_INET, &info->lo.internal_ip_data.in.s_addr, buf1, INET6_ADDRSTRLEN);
@ -112,44 +130,125 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
}
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
hub_log(log_debug, "ACL: Deny access for: %s-%s", buf1, buf2);
list_append(list, info);
}
static int check_ip_range(const char* lo, const char* hi, struct ip_ban_record* info)
{
int ret1, ret2;
if ((ip_is_valid_ipv4(lo) && ip_is_valid_ipv4(hi)) ||
(ip_is_valid_ipv6(lo) && ip_is_valid_ipv6(hi)))
{
ret1 = ip_convert_to_binary(lo, &info->lo);
ret2 = ip_convert_to_binary(hi, &info->hi);
if (ret1 == -1 || ret2 == -1 || ret1 != ret2)
{
return -1;
}
return 0;
}
return -1;
}
static int check_ip_mask(const char* text_addr, int bits, struct ip_ban_record* info)
{
hub_log(log_debug, "ACL: Deny access for: %s/%d", text_addr, bits);
if (ip_is_valid_ipv4(text_addr) ||
ip_is_valid_ipv6(text_addr))
{
struct ip_addr_encap addr;
struct ip_addr_encap mask1;
struct ip_addr_encap mask2;
int af = ip_convert_to_binary(text_addr, &addr); /* 192.168.1.2 */
int maxbits = af == AF_INET6 ? 128 : 32;
ip_mask_create_left(af, bits, &mask1); /* 255.255.255.0 */
ip_mask_create_right(af, maxbits - bits, &mask2); /* 0.0.0.255 */
ip_mask_apply_AND(&addr, &mask1, &info->lo); /* 192.168.1.0 */
ip_mask_apply_OR(&info->lo, &mask2, &info->hi); /* 192.168.1.255 */
return 0;
}
return -1;
}
static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line, int line_count)
{
char* data;
struct ip_range* range = 0;
char* data1;
char* data2;
struct ip_ban_record* info = 0;
int cidr_bits = 0;
if (!strncmp(line, cmd, strlen(cmd)))
{
data = &line[strlen(cmd)];
data[0] = '\0';
data++;
data = strip_white_space(data);
if (!*data)
data1 = &line[strlen(cmd)];
data2 = 0;
data1[0] = '\0';
data1++;
data1 = strip_white_space(data1);
if (!*data1)
{
LOG_FATAL("ACL parse error on line %d", line_count);
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
}
range = hub_malloc_zero(sizeof(struct ip_range));
if (!range)
info = hub_malloc_zero(sizeof(struct ip_ban_record));
if (!info)
{
LOG_ERROR("ACL parse error. Out of memory!");
hub_log(log_error, "ACL parse error. Out of memory!");
return -1;
}
if (ip_convert_address_to_range(data, range))
/* Extract IP-range */
data2 = strrchr(data1, '-');
if (data2)
{
add_ip_range(list, range);
cidr_bits = -1;
data2[0] = 0;
data2++;
if (check_ip_range(data1, data2, info) == -1)
{
hub_free(info);
return 0;
}
add_ip_range(list, info);
return 1;
}
else
{
/* Extract IP-bitmask */
data2 = strrchr(data1, '/');
if (data2)
{
data2[0] = 0;
data2++;
cidr_bits = uhub_atoi(data2);
}
else
{
cidr_bits = 128;
}
if (check_ip_mask(data1, cidr_bits, info) == -1)
{
hub_free(info);
return 0;
}
add_ip_range(list, info);
return 1;
}
hub_free(range);
}
return 0;
}
@ -158,33 +257,46 @@ static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line,
static int acl_parse_line(char* line, int line_count, void* ptr_data)
{
char* pos;
struct acl_handle* handle = (struct acl_handle*) ptr_data;
int ret;
strip_off_ini_line_comments(line, line_count);
line = strip_white_space(line);
if ((pos = strchr(line, '#')) != NULL)
{
pos[0] = 0;
}
if (!*line)
return 0;
LOG_DEBUG("acl_parse_line: '%s'", line);
#ifdef ACL_DEBUG
hub_log(log_trace, "acl_parse_line(): '%s'", line);
#endif
line = strip_white_space(line);
if (!*line)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
}
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_super", handle->users, auth_cred_super);
ACL_ADD_USER("user_op", handle->users, auth_cred_operator);
ACL_ADD_USER("user_reg", handle->users, auth_cred_user);
ACL_ADD_USER("link", handle->users, auth_cred_link);
#ifdef ACL_DEBUG
hub_log(log_trace, "acl_parse_line: '%s'", line);
#endif
ACL_ADD_USER("bot", handle->users, cred_bot);
ACL_ADD_USER("user_admin", handle->users, cred_admin);
ACL_ADD_USER("user_super", handle->users, cred_super);
ACL_ADD_USER("user_op", handle->users, cred_operator);
ACL_ADD_USER("user_reg", handle->users, cred_user);
ACL_ADD_USER("link", handle->users, cred_link);
ACL_ADD_BOOL("deny_nick", handle->users_denied);
ACL_ADD_BOOL("ban_nick", handle->users_banned);
ACL_ADD_BOOL("ban_cid", handle->cids);
ACL_ADD_ADDR("deny_ip", handle->networks);
ACL_ADD_ADDR("nat_ip", handle->nat_override);
LOG_ERROR("Unknown ACL command on line %d: '%s'", line_count, line);
hub_log(log_error, "Unknown ACL command on line %d: '%s'", line_count, line);
return -1;
}
@ -193,18 +305,18 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
{
int ret;
memset(handle, 0, sizeof(struct acl_handle));
handle->users = list_create();
handle->users_denied = list_create();
handle->users_banned = list_create();
handle->cids = list_create();
handle->networks = list_create();
handle->nat_override = list_create();
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
{
LOG_FATAL("acl_initialize: Out of memory");
hub_log(log_fatal, "acl_initialize: Out of memory");
list_destroy(handle->users);
list_destroy(handle->users_denied);
list_destroy(handle->users_banned);
@ -213,11 +325,11 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
list_destroy(handle->nat_override);
return -1;
}
if (config)
{
if (!*config->file_acl) return 0;
ret = file_read_lines(config->file_acl, handle, &acl_parse_line);
if (ret == -1)
return -1;
@ -228,9 +340,11 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
static void acl_free_access_info(void* ptr)
{
struct auth_info* info = (struct auth_info*) ptr;
struct user_access_info* info = (struct user_access_info*) ptr;
if (info)
{
hub_free(info->username);
hub_free(info->password);
hub_free(info);
}
}
@ -252,240 +366,189 @@ int acl_shutdown(struct acl_handle* handle)
list_clear(handle->users, &acl_free_access_info);
list_destroy(handle->users);
}
if (handle->users_denied)
{
list_clear(handle->users_denied, &hub_free);
list_destroy(handle->users_denied);
}
if (handle->users_banned)
{
list_clear(handle->users_banned, &hub_free);
list_destroy(handle->users_banned);
}
if (handle->cids)
{
list_clear(handle->cids, &hub_free);
list_destroy(handle->cids);
}
if (handle->networks)
{
list_clear(handle->networks, &acl_free_ip_info);
list_destroy(handle->networks);
}
if (handle->nat_override)
{
list_clear(handle->nat_override, &acl_free_ip_info);
list_destroy(handle->nat_override);
}
memset(handle, 0, sizeof(struct acl_handle));
return 0;
}
extern int acl_register_user(struct hub_info* hub, struct auth_info* info)
{
if (plugin_auth_register_user(hub, info) != st_allow)
{
return 0;
}
return 1;
}
extern int acl_update_user(struct hub_info* hub, struct auth_info* info)
struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
{
if (plugin_auth_update_user(hub, info) != st_allow)
struct user_access_info* info = (struct user_access_info*) list_get_first(handle->users);
while (info)
{
return 0;
if (strcasecmp(info->username, name) == 0)
{
return info;
}
info = (struct user_access_info*) list_get_next(handle->users);
}
return 1;
}
extern int acl_delete_user(struct hub_info* hub, const char* name)
{
struct auth_info data;
strncpy(data.nickname, name, MAX_NICK_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[0] = '\0';
data.credentials = auth_cred_none;
if (plugin_auth_delete_user(hub, &data) != st_allow)
{
return 0;
}
return 1;
}
struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name)
{
struct auth_info* info = 0;
info = (struct auth_info*) hub_malloc(sizeof(struct auth_info));
if (plugin_auth_get_user(hub, name, info) != st_allow)
{
hub_free(info);
return NULL;
}
return info;
return NULL;
}
#define STR_LIST_CONTAINS(LIST, STR) \
LIST_FOREACH(char*, str, LIST, \
char* str = (char*) list_get_first(LIST); \
while (str) \
{ \
if (strcasecmp(str, STR) == 0) \
return 1; \
}); \
str = (char*) list_get_next(LIST); \
} \
return 0
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
{
char* str;
if (!handle) return 0;
STR_LIST_CONTAINS(handle->cids, data);
}
int acl_is_user_banned(struct acl_handle* handle, const char* data)
{
char* str;
if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_banned, data);
}
int acl_is_user_denied(struct acl_handle* handle, const char* data)
{
char* str;
if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_denied, data);
}
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
{
char* data = hub_strdup(nick);
if (!data)
{
LOG_ERROR("ACL error: Out of memory!");
return -1;
}
list_append(handle->users_banned, data);
return 0;
}
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
{
char* data = hub_strdup(cid);
if (!data)
{
LOG_ERROR("ACL error: Out of memory!");
return -1;
}
list_append(handle->cids, data);
return 0;
}
int acl_user_unban_nick(struct acl_handle* handle, const char* nick)
{
return -1;
}
int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
{
return -1;
}
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_range* info;
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->networks);
ip_convert_to_binary(ip_address, &raw);
LIST_FOREACH(struct ip_range*, info, handle->networks,
while (info)
{
if (ip_in_range(&raw, info))
if (acl_check_ip_range(&raw, info))
{
return 1;
});
}
info = (struct ip_ban_record*) list_get_next(handle->networks);
}
return 0;
}
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_range* info;
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->nat_override);
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 (acl_check_ip_range(&raw, info))
{
return 1;
});
}
info = (struct ip_ban_record*) list_get_next(handle->nat_override);
}
return 0;
}
int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info)
{
return (addr->af == info->lo.af && ip_compare(&info->lo, addr) <= 0 && ip_compare(addr, &info->hi) <= 0);
}
/*
* This will generate the same challenge to the same user, always.
* The challenge is made up of the time of the user connected
* seconds since the unix epoch (modulus 1 million)
* and the SID of the user (0-1 million).
*/
const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user)
const char* password_generate_challenge(struct user* user)
{
char buf[64];
char buf[32];
uint64_t tiger_res[3];
static char tiger_buf[MAX_CID_LEN+1];
// FIXME: Generate a better nonce scheme.
snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection));
snprintf(buf, 32, "%d%d%d", (int) user->tm_connected, (int) user->id.sid, (int) user->sd);
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
tiger_buf[MAX_CID_LEN] = 0;
#ifdef ACL_DEBUG
hub_log(log_trace, "Generating challenge for user %s: '%s'", user->id.nick, tiger_buf);
#endif
return (const char*) tiger_buf;
}
int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password)
int password_verify(struct user* user, const char* password)
{
char buf[1024];
struct auth_info* access;
struct user_access_info* access;
const char* challenge;
char raw_challenge[64];
char password_calc[64];
uint64_t tiger_res[3];
size_t password_len;
if (!password || !user || strlen(password) != MAX_CID_LEN)
return 0;
return password_invalid;
access = acl_get_access_info(hub, user->id.nick);
if (!access)
return 0;
access = acl_get_access_info(user->hub->acl, user->id.nick);
if (!access || !access->password)
return password_invalid;
challenge = acl_password_generate_challenge(hub, user);
if (TIGERSIZE+strlen(access->password) >= 1024)
return password_invalid;
challenge = password_generate_challenge(user);
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
password_len = strlen(access->password);
memcpy(&buf[0], access->password, password_len);
memcpy(&buf[password_len], raw_challenge, TIGERSIZE);
tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res);
memcpy(&buf[0], (char*) access->password, strlen(access->password));
memcpy(&buf[strlen(access->password)], raw_challenge, TIGERSIZE);
tiger((uint64_t*) buf, TIGERSIZE+strlen(access->password), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
password_calc[MAX_CID_LEN] = 0;
hub_free(access);
#ifdef ACL_DEBUG
hub_log(log_trace, "Checking password %s against %s", password, password_calc);
#endif
if (strcasecmp(password, password_calc) == 0)
{
return 1;
return password_ok;
}
return 0;
return password_invalid;
}

View File

@ -1,6 +1,6 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -13,7 +13,7 @@
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@ -21,10 +21,48 @@
#define HAVE_UHUB_ACL_H
struct hub_config;
struct hub_info;
struct hub_user;
struct user;
struct ip_addr_encap;
enum password_status
{
password_invalid = 0,
password_ok = 1,
};
enum acl_status
{
acl_not_found = 0,
acl_found = 1,
};
enum user_credentials
{
cred_none, /**<<< "User has no credentials (not yet logged in)" */
cred_bot, /**<<< "User is a robot" */
cred_guest, /**<<< "User is a guest (unregistered user)" */
cred_user, /**<<< "User is identified as a registered user" */
cred_operator, /**<<< "User is identified as a hub operator" */
cred_super, /**<<< "User is a super user" (not used) */
cred_admin, /**<<< "User is identified as a hub administrator/owner" */
cred_link, /**<<< "User is a link (not used currently)" */
};
const char* get_user_credential_string(enum user_credentials cred);
struct user_access_info
{
char* username; /* name of user, cid or IP range */
char* password; /* password */
enum user_credentials status;
};
struct ip_ban_record
{
struct ip_addr_encap lo;
struct ip_addr_encap hi;
};
struct acl_handle
{
struct linked_list* users; /* Known users. See enum user_status */
@ -39,12 +77,7 @@ struct acl_handle
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
extern int acl_shutdown(struct acl_handle* handle);
extern struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name);
extern int acl_register_user(struct hub_info* hub, struct auth_info* info);
extern int acl_update_user(struct hub_info* hub, struct auth_info* info);
extern int acl_delete_user(struct hub_info* hub, const char* name);
extern struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
@ -52,19 +85,9 @@ extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_addr
extern int acl_is_user_banned(struct acl_handle* handle, const char* name);
extern int acl_is_user_denied(struct acl_handle* handle, const char* name);
extern int acl_user_ban_nick(struct acl_handle* handle, const char* nick);
extern int acl_user_ban_cid(struct acl_handle* handle, const char* cid);
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
/**
* Verify a password.
*
* @param password the hashed password (based on the nonce).
* @return 1 if the password matches, or 0 if the password is incorrect.
*/
extern int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password);
extern const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user);
extern int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info);
extern const char* password_generate_challenge(struct user* user);
extern int password_verify(struct user* user, const char* password);
#endif /* HAVE_UHUB_ACL_H */

218
src/commands.c Normal file
View File

@ -0,0 +1,218 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
typedef int (*command_handler)(struct hub_info* hub, struct user* user, const char* message);
struct commands_handler
{
const char* prefix;
size_t length;
enum user_credentials cred;
command_handler handler;
const char* description;
};
static struct commands_handler command_handlers[];
static void send_message(struct hub_info* hub, struct user* user, 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_user(user, command);
adc_msg_free(command);
hub_free(buffer);
}
static int command_access_denied(struct hub_info* hub, struct user* user, const char* command)
{
char temp[128];
snprintf(temp, 128, "*** Access denied: \"%s\"", command);
send_message(hub, user, temp);
return 0;
}
static int command_not_found(struct hub_info* hub, struct user* user, const char* command)
{
char temp[128];
snprintf(temp, 128, "*** Command not found: \"%s\"", command);
send_message(hub, user, temp);
return 0;
}
static int command_status(struct hub_info* hub, struct user* user, const char* command, const char* message)
{
char temp[1024];
snprintf(temp, 1024, "*** %s: %s", command, message);
send_message(hub, user, temp);
return 0;
}
static int command_stats(struct hub_info* hub, struct user* user, const char* message)
{
char temp[128];
snprintf(temp, 128, "%zu users, peak: %zu. 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(hub, user, "stats", message);
}
static int command_help(struct hub_info* hub, struct user* user, const char* message)
{
#define MAX_HELP_MSG 1024
size_t n;
char msg[MAX_HELP_MSG];
msg[0] = 0;
strcat(msg, "Available commands:\n");
for (n = 0; command_handlers[n].prefix; n++)
{
if (command_handlers[n].cred <= user->credentials)
{
strcat(msg, "!");
strcat(msg, command_handlers[n].prefix);
strcat(msg, " - ");
strcat(msg, command_handlers[n].description);
strcat(msg, "\n");
}
}
return command_status(hub, user, "help", msg);
}
static int command_uptime(struct hub_info* hub, struct user* user, const char* message)
{
char tmp[128];
size_t d;
size_t h;
size_t m;
size_t D = (size_t) difftime(time(0), hub->tm_started);
d = D / (24 * 3600);
D = D % (24 * 3600);
h = D / 3600;
D = D % 3600;
m = D / 60;
tmp[0] = 0;
if (d)
{
strcat(tmp, uhub_itoa((int) d));
strcat(tmp, " day");
if (d != 1) strcat(tmp, "s");
strcat(tmp, ", ");
}
if (h < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) h));
strcat(tmp, ":");
if (m < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) m));
return command_status(hub, user, "uptime", tmp);
}
static int command_kick(struct hub_info* hub, struct user* user, const char* message)
{
if (strlen(message) < 7)
{
return command_status(hub, user, "kick", "No nickname given");
}
const char* nick = &message[7];
struct user* target = uman_get_user_by_nick(hub, nick);
if (!target)
{
return command_status(hub, user, "kick", "No such user");
}
if (target == user)
{
return command_status(hub, user, "kick", "Cannot kick yourself");
}
user_disconnect(target, quit_kicked);
return command_status(hub, user, "kick", nick);
}
static int command_reload(struct hub_info* hub, struct user* user, const char* message)
{
hub->status = hub_status_restart;
return command_status(hub, user, "reload", "Reloading configuration...");
}
static int command_shutdown(struct hub_info* hub, struct user* user, const char* message)
{
hub->status = hub_status_shutdown;
return command_status(hub, user, "shutdown", "Hub shutting down...");
}
static int command_version(struct hub_info* hub, struct user* user, const char* message)
{
return command_status(hub, user, "version", "Powered by " PRODUCT "/" VERSION);
}
static int command_myip(struct hub_info* hub, struct user* user, const char* message)
{
char tmp[128];
snprintf(tmp, 128, "Your IP is \"%s\"", ip_convert_to_string(&user->ipaddr));
return command_status(hub, user, "myip", tmp);
}
int command_dipatcher(struct hub_info* hub, struct user* user, const char* message)
{
size_t n = 0;
for (n = 0; command_handlers[n].prefix; n++)
{
if (!strncmp(message, command_handlers[n].prefix, command_handlers[n].length))
{
if (command_handlers[n].cred <= user->credentials)
{
return command_handlers[n].handler(hub, user, message);
}
else
{
return command_access_denied(hub, user, command_handlers[n].prefix);
}
}
}
command_not_found(hub, user, message);
return 1;
}
static struct commands_handler command_handlers[] = {
{ "help", 4, cred_guest, command_help, "Show this help message." },
{ "stats", 5, cred_super, command_stats, "Show hub statistics." },
{ "version", 7, cred_guest, command_version, "Show hub version info." },
{ "uptime", 6, cred_guest, command_uptime, "Display hub uptime info." },
{ "kick", 4, cred_operator, command_kick, "Kick a user" },
{ "reload", 6, cred_admin, command_reload, "Reload configuration files." },
{ "shutdown", 8, cred_admin, command_shutdown, "Shutdown hub." },
{ "myip", 4, cred_guest, command_myip, "Show your own IP." },
{ 0, 0, cred_none, command_help, "" }
};

View File

@ -1,6 +1,6 @@
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -13,18 +13,23 @@
* 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/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef NEED_GETOPT
#define CHAT_MSG_HANDLED 1
#define CHAT_MSG_IGNORED 0
#define CHAT_MSG_INVALID -1
extern char* optarg;
extern int optind;
typedef int (*plugin_event_chat_message)(struct hub_info*, struct user*, struct adc_message*);
extern int getopt(int argc, char* const argv[], const char *optstring);
#endif /* NEED_GETOPT */
struct command_info
{
const char* prefix;
enum user_credentials cred;
plugin_event_chat_message function;
};
int command_dipatcher(struct hub_info* hub, struct user* user, const char* message);

524
src/config.c Normal file
View File

@ -0,0 +1,524 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifndef INT_MAX
#define INT_MAX 0x7fffffff
#endif
#ifndef INT_MIN
#define INT_MIN (-0x7fffffff - 1)
#endif
#define CFG_APPLY_BOOLEAN(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
if (strlen(data) == 1 && (data[0] == '1')) TARGET = 1; \
else if (strlen(data) == 1 && (data[0] == '0')) TARGET = 0; \
else if (strncasecmp(data, "true", 4) == 0) TARGET = 1; \
else if (strncasecmp(data, "false", 5) == 0) TARGET = 0; \
else if (strncasecmp(data, "yes", 3) == 0) TARGET = 1; \
else if (strncasecmp(data, "no", 2) == 0) TARGET = 0; \
else if (strncasecmp(data, "on", 2) == 0) TARGET = 1; \
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
else\
{ \
hub_log(log_fatal, "Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
return -1; \
} \
TARGET |= 0x80000000; \
return 0; \
}
#define CFG_APPLY_STRING(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
TARGET = hub_strdup(data); \
return 0; \
}
#define CFG_APPLY_INTEGER(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
char* endptr; \
int val; \
errno = 0; \
val = strtol(data, &endptr, 10); \
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
hub_log(log_fatal, "Configuration error on line %d: '%s' must be a number", line_count, key); \
return -1; \
} \
TARGET = val; \
return 0; \
}
#define DEFAULT_STRING(KEY, VALUE) \
{ \
if (config->KEY == 0) \
config->KEY = hub_strdup(VALUE); \
}
#define DEFAULT_INTEGER(KEY, VALUE) \
{ \
if (config->KEY == 0) \
config->KEY = VALUE; \
}
#define DEFAULT_BOOLEAN(KEY, VALUE) \
{ \
if (config->KEY & 0x80000000) \
{ \
config->KEY = config->KEY & 0x000000ff; \
} \
else \
{ \
config->KEY = VALUE; \
} \
}
#define GET_STR(NAME) CFG_APPLY_STRING ( #NAME , config->NAME )
#define GET_INT(NAME) CFG_APPLY_INTEGER( #NAME , config->NAME )
#define GET_BOOL(NAME) CFG_APPLY_BOOLEAN( #NAME , config->NAME )
#define IGNORED(NAME) \
if (strcmp(#NAME, key) == 0) \
{ \
hub_log(log_warning, "Configuration option %s deprecated and ingnored.", key); \
return 0; \
} \
/* default configuration values */
#define DEF_SERVER_BIND_ADDR "any"
#define DEF_SERVER_PORT 1511
#define DEF_HUB_NAME "uhub"
#define DEF_HUB_DESCRIPTION ""
#define DEF_HUB_ENABLED 1
#define DEF_FILE_ACL ""
#define DEF_FILE_MOTD ""
#define DEF_MAX_USERS 500
#define DEF_MAX_RECV_BUFFER 4096
#define DEF_MAX_SEND_BUFFER 131072
#define DEF_MAX_SEND_BUFFER_SOFT 98304
#define DEF_SHOW_BANNER 1
#define DEF_REGISTERED_USERS_ONLY 0
#define DEF_CHAT_ONLY 0
#define DEF_CHAT_IS_PRIVILEGED 0
#define DEF_LOW_BANDWIDTH_MODE 0
#define DEF_LIMIT_MAX_HUBS_USER 0
#define DEF_LIMIT_MAX_HUBS_REG 0
#define DEF_LIMIT_MAX_HUBS_OP 0
#define DEF_LIMIT_MAX_HUBS 0
#define DEF_LIMIT_MIN_HUBS_USER 0
#define DEF_LIMIT_MIN_HUBS_REG 0
#define DEF_LIMIT_MIN_HUBS_OP 0
#define DEF_LIMIT_MIN_SHARE 0
#define DEF_LIMIT_MAX_SHARE 0
#define DEF_LIMIT_MIN_SLOTS 0
#define DEF_LIMIT_MAX_SLOTS 0
#define DEF_MSG_HUB_FULL "Hub is full"
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
#define DEF_MSG_INF_ERROR_NICK_MISSING "No nickname given"
#define DEF_MSG_INF_ERROR_NICK_MULTIPLE "Multiple nicknames given"
#define DEF_MSG_INF_ERROR_NICK_INVALID "Nickname is invalid"
#define DEF_MSG_INF_ERROR_NICK_LONG "Nickname too long"
#define DEF_MSG_INF_ERROR_NICK_SHORT "Nickname too short"
#define DEF_MSG_INF_ERROR_NICK_SPACES "Nickname cannot start with spaces"
#define DEF_MSG_INF_ERROR_NICK_BAD_CHARS "Nickname contains invalid characters"
#define DEF_MSG_INF_ERROR_NICK_NOT_UTF8 "Nickname is not valid utf8"
#define DEF_MSG_INF_ERROR_NICK_TAKEN "Nickname is already in use"
#define DEF_MSG_INF_ERROR_NICK_RESTRICTED "Nickname cannot be used on this hub"
#define DEF_MSG_INF_ERROR_CID_INVALID "CID is not valid"
#define DEF_MSG_INF_ERROR_CID_MISSING "CID is not specified"
#define DEF_MSG_INF_ERROR_CID_TAKEN "CID is taken"
#define DEF_MSG_INF_ERROR_PID_MISSING "PID is not specified"
#define DEF_MSG_INF_ERROR_PID_INVALID "PID is invalid"
#define DEF_MSG_BAN_PERMANENTLY "Banned permanently"
#define DEF_MSG_BAN_TEMPORARILY "Banned temporarily"
#define DEF_MSG_AUTH_INVALID_PASSWORD "Password is wrong"
#define DEF_MSG_AUTH_USER_NOT_FOUND "User not found in password database"
#define DEF_MSG_ERROR_NO_MEMORY "No memory"
#define DEF_MSG_USER_SHARE_SIZE_LOW "User is not sharing enough"
#define DEF_MSG_USER_SHARE_SIZE_HIGH "User is sharing too much"
#define DEF_MSG_USER_SLOTS_LOW "User have too few upload slots."
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
void config_defaults(struct hub_config* config)
{
DEFAULT_STRING (server_bind_addr, DEF_SERVER_BIND_ADDR);
DEFAULT_STRING (hub_name, DEF_HUB_NAME);
DEFAULT_STRING (hub_description, DEF_HUB_DESCRIPTION);
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
/* Limits enforced on users */
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
DEFAULT_INTEGER(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
DEFAULT_INTEGER(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
DEFAULT_INTEGER(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
DEFAULT_INTEGER(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
DEFAULT_INTEGER(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
DEFAULT_INTEGER(limit_min_share, DEF_LIMIT_MIN_SHARE);
DEFAULT_INTEGER(limit_max_share, DEF_LIMIT_MAX_SHARE);
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
/* Status/error strings */
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
DEFAULT_STRING (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
DEFAULT_STRING (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
DEFAULT_STRING (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
DEFAULT_STRING (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
DEFAULT_STRING (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
DEFAULT_STRING (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
DEFAULT_STRING (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
DEFAULT_STRING (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
DEFAULT_STRING (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
DEFAULT_STRING (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
DEFAULT_STRING (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
DEFAULT_STRING (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
DEFAULT_STRING (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
DEFAULT_STRING (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
DEFAULT_STRING (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
DEFAULT_STRING (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
DEFAULT_STRING (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
DEFAULT_STRING (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
DEFAULT_STRING (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
DEFAULT_STRING (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
DEFAULT_STRING (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
DEFAULT_STRING (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
DEFAULT_STRING (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
DEFAULT_STRING (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
DEFAULT_INTEGER(tls_enable, 0);
DEFAULT_INTEGER(tls_require, 0);
DEFAULT_STRING (tls_certificate, "");
DEFAULT_STRING (tls_private_key, "");
}
static int apply_config(struct hub_config* config, char* key, char* data, int line_count)
{
GET_STR (file_acl);
GET_STR (file_motd);
GET_STR (server_bind_addr);
GET_INT (server_port);
GET_STR (hub_name);
GET_STR (hub_description);
GET_BOOL(hub_enabled);
GET_INT (max_users);
GET_INT (max_recv_buffer);
GET_INT (max_send_buffer);
GET_INT (max_send_buffer_soft);
GET_BOOL(show_banner);
GET_BOOL(chat_only);
GET_BOOL(chat_is_privileged);
GET_BOOL(low_bandwidth_mode);
GET_BOOL(registered_users_only);
/* Limits enforced on users */
GET_INT(limit_max_hubs_user);
GET_INT(limit_max_hubs_reg);
GET_INT(limit_max_hubs_op);
GET_INT(limit_min_hubs_user);
GET_INT(limit_min_hubs_reg);
GET_INT(limit_min_hubs_op);
GET_INT(limit_max_hubs);
GET_INT(limit_min_share);
GET_INT(limit_max_share);
GET_INT(limit_min_slots);
GET_INT(limit_max_slots);
/* Status/error strings */
GET_STR (msg_hub_full);
GET_STR (msg_hub_disabled);
GET_STR (msg_hub_registered_users_only);
GET_STR (msg_inf_error_nick_missing);
GET_STR (msg_inf_error_nick_multiple);
GET_STR (msg_inf_error_nick_invalid);
GET_STR (msg_inf_error_nick_long);
GET_STR (msg_inf_error_nick_short);
GET_STR (msg_inf_error_nick_spaces);
GET_STR (msg_inf_error_nick_bad_chars);
GET_STR (msg_inf_error_nick_not_utf8);
GET_STR (msg_inf_error_nick_taken);
GET_STR (msg_inf_error_nick_restricted);
GET_STR (msg_inf_error_cid_invalid);
GET_STR (msg_inf_error_cid_missing);
GET_STR (msg_inf_error_cid_taken);
GET_STR (msg_inf_error_pid_missing);
GET_STR (msg_inf_error_pid_invalid);
GET_STR (msg_ban_permanently);
GET_STR (msg_ban_temporarily);
GET_STR (msg_auth_invalid_password);
GET_STR (msg_auth_user_not_found);
GET_STR (msg_error_no_memory);
GET_STR (msg_user_share_size_low);
GET_STR (msg_user_share_size_high);
GET_STR (msg_user_slots_low);
GET_STR (msg_user_slots_high);
GET_STR (msg_user_hub_limit_low);
GET_STR (msg_user_hub_limit_high);
GET_BOOL(tls_enable);
GET_BOOL(tls_require);
GET_STR (tls_certificate);
GET_STR (tls_private_key);
/* Still here -- unknown directive */
hub_log(log_fatal, "Unknown configuration directive: '%s'", key);
return -1;
}
void free_config(struct hub_config* config)
{
hub_free(config->server_bind_addr);
hub_free(config->file_motd);
hub_free(config->file_acl);
hub_free(config->hub_name);
hub_free(config->hub_description);
hub_free(config->msg_hub_full);
hub_free(config->msg_hub_disabled);
hub_free(config->msg_hub_registered_users_only);
hub_free(config->msg_inf_error_nick_missing);
hub_free(config->msg_inf_error_nick_multiple);
hub_free(config->msg_inf_error_nick_invalid);
hub_free(config->msg_inf_error_nick_long);
hub_free(config->msg_inf_error_nick_short);
hub_free(config->msg_inf_error_nick_spaces);
hub_free(config->msg_inf_error_nick_bad_chars);
hub_free(config->msg_inf_error_nick_not_utf8);
hub_free(config->msg_inf_error_nick_taken);
hub_free(config->msg_inf_error_nick_restricted);
hub_free(config->msg_inf_error_cid_invalid);
hub_free(config->msg_inf_error_cid_missing);
hub_free(config->msg_inf_error_cid_taken);
hub_free(config->msg_inf_error_pid_missing);
hub_free(config->msg_inf_error_pid_invalid);
hub_free(config->msg_ban_permanently);
hub_free(config->msg_ban_temporarily);
hub_free(config->msg_auth_invalid_password);
hub_free(config->msg_auth_user_not_found);
hub_free(config->msg_error_no_memory);
hub_free(config->msg_user_share_size_low);
hub_free(config->msg_user_share_size_high);
hub_free(config->msg_user_slots_low);
hub_free(config->msg_user_slots_high);
hub_free(config->msg_user_hub_limit_low);
hub_free(config->msg_user_hub_limit_high);
hub_free(config->tls_certificate);
hub_free(config->tls_private_key);
memset(config, 0, sizeof(struct hub_config));
}
#define DUMP_STR(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (strcmp(config->NAME, DEFAULT) != 0) \
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
} \
else \
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
#define DUMP_INT(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (config->NAME != DEFAULT) \
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
} \
else \
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
#define DUMP_BOOL(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (config->NAME != DEFAULT) \
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no")); \
} \
else \
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no"));
void dump_config(struct hub_config* config, int ignore_defaults)
{
DUMP_STR (file_acl, DEF_FILE_ACL);
DUMP_STR (file_motd, DEF_FILE_MOTD);
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
DUMP_INT (server_port, DEF_SERVER_PORT);
DUMP_STR (hub_name, DEF_HUB_NAME);
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
DUMP_INT (max_users, DEF_MAX_USERS);
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
/* Limits enforced on users */
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
DUMP_INT(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
DUMP_INT(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
DUMP_INT(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
DUMP_INT(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
DUMP_INT(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
DUMP_INT(limit_min_share, DEF_LIMIT_MIN_SHARE);
DUMP_INT(limit_max_share, DEF_LIMIT_MAX_SHARE);
DUMP_INT(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
DUMP_INT(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
/* Status/error strings */
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
DUMP_STR (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
DUMP_STR (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
DUMP_STR (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
DUMP_STR (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
DUMP_STR (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
DUMP_STR (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
DUMP_STR (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
DUMP_STR (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
DUMP_STR (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
DUMP_STR (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
DUMP_STR (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
DUMP_STR (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
DUMP_STR (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
DUMP_STR (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
DUMP_STR (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
DUMP_STR (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
DUMP_STR (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
DUMP_STR (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
DUMP_STR (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
DUMP_STR (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
DUMP_STR (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
DUMP_STR (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
DUMP_STR (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
DUMP_STR (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
}
static int config_parse_line(char* line, int line_count, void* ptr_data)
{
char* pos;
char* key;
char* data;
struct hub_config* config = (struct hub_config*) ptr_data;
if ((pos = strchr(line, '#')) != NULL)
{
pos[0] = 0;
}
if (!*line) return 0;
#ifdef CONFIG_DUMP
hub_log(log_trace, "config_parse_line(): '%s'", line);
#endif
if (!is_valid_utf8(line))
{
hub_log(log_warning, "Invalid utf-8 characters on line %d", line_count);
}
if ((pos = strchr(line, '=')) != NULL)
{
pos[0] = 0;
}
else
{
return 0;
}
key = line;
data = &pos[1];
key = strip_white_space(key);
data = strip_white_space(data);
if (!*key || !*data)
{
hub_log(log_fatal, "Configuration parse error on line %d", line_count);
return -1;
}
#ifdef CONFIG_DUMP
hub_log(log_trace, "config_parse_line: '%s' => '%s'", key, data);
#endif
return apply_config(config, key, data, line_count);
}
int read_config(const char* file, struct hub_config* config, int allow_missing)
{
int ret;
memset(config, 0, sizeof(struct hub_config));
ret = file_read_lines(file, config, &config_parse_line);
if (ret < 0)
{
if (allow_missing && ret == -2)
{
hub_log(log_debug, "Using default configuration.");
}
else
{
return -1;
}
}
config_defaults(config);
return 0;
}

122
src/config.h Normal file
View File

@ -0,0 +1,122 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_CONFIG_H
#define HAVE_UHUB_CONFIG_H
struct hub_config
{
int server_port; /**<<< "Server port to bind to (default: 1511)" */
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
int show_banner; /**<<< "Show banner on connect (default: 1)" */
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
/* Limits enforced on users */
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
int limit_max_hubs_op; /**<<< "Max concurrent hubs as operator. (0=off, default: 10)" */
int limit_min_hubs_user; /**<<< "Min concurrent hubs as a user. (0=off, default: 0)" */
int limit_min_hubs_reg; /**<<< "Min concurrent hubs as registered user. (0=off, default: 0)" */
int limit_min_hubs_op; /**<<< "Min concurrent hubs as operator. (0=off, default: 0)" */
int limit_max_hubs; /**<<< "Max total hub connections allowed, user/reg/op combined. (0=off, default: 25)" */
int limit_min_share; /**<<< "Limit minimum share size in megabytes (MiB) (0=off, default: 0)" */
int limit_max_share; /**<<< "Limit maximum share size in megabytes (MiB) (0=off, default: 0)" */
int limit_min_slots; /**<<< "Limit minimum number of slots open per user (0=off, default: 0)" */
int limit_max_slots; /**<<< "Limit maximum number of slots open per user (0=off, default: 0)" */
/* Messages that can be sent to a user */
char* msg_hub_full; /**<<< "hub is full" */
char* msg_hub_disabled; /**<<< "hub is disabled" */
char* msg_hub_registered_users_only; /**<<< "hub is for registered users only" */
char* msg_inf_error_nick_missing; /**<<< "no nickname given" */
char* msg_inf_error_nick_multiple; /**<<< "multiple nicknames given" */
char* msg_inf_error_nick_invalid; /**<<< "generic/unkown" */
char* msg_inf_error_nick_long; /**<<< "nickname too long" */
char* msg_inf_error_nick_short; /**<<< "nickname too short" */
char* msg_inf_error_nick_spaces; /**<<< "nickname cannot start with spaces" */
char* msg_inf_error_nick_bad_chars; /**<<< "nickname contains chars below ascii 32" */
char* msg_inf_error_nick_not_utf8; /**<<< "nickname is not valid utf8" */
char* msg_inf_error_nick_taken; /**<<< "nickname is in use" */
char* msg_inf_error_nick_restricted; /**<<< "nickname cannot be used on this hub" */
char* msg_inf_error_cid_invalid; /**<<< "CID is not valid" */
char* msg_inf_error_cid_missing; /**<<< "CID is not specified" */
char* msg_inf_error_cid_taken; /**<<< "CID is taken" */
char* msg_inf_error_pid_missing; /**<<< "PID is not specified" */
char* msg_inf_error_pid_invalid; /**<<< "PID is invalid" */
char* msg_ban_permanently; /**<<< "Banned permanently" */
char* msg_ban_temporarily; /**<<< "Banned temporarily" */
char* msg_auth_invalid_password; /**<<< "Password is wrong" */
char* msg_auth_user_not_found; /**<<< "User not found in password database" */
char* msg_error_no_memory; /**<<< "No memory" */
char* msg_user_share_size_low; /**<<< "User is not sharing enough" */
char* msg_user_share_size_high; /**<<< "User is sharing too much" */
char* msg_user_slots_low; /**<<< "User have too few upload slots." */
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
char* tls_certificate; /**<<< "Certificate file (PEM)" */
char* tls_private_key; /**<<< "Private key" */
};
/**
* This initializes the configuration variables, and sets the default
* variables.
*
* NOTE: Any variable is set to it's default variable if zero.
* This function is automatically called in read_config to set any
* configuration that was missing there.
*/
extern void config_defaults(struct hub_config* config);
/**
* Read configuration from file, and use the default variables for
* the missing variables.
*
* @return -1 on error, 0 on success.
*/
extern int read_config(const char* file, struct hub_config* config, int allow_missing);
/**
* Free the configuration data (allocated by read_config, or config_defaults).
*/
extern void free_config(struct hub_config* config);
/**
* Print all configuration data to standard out.
*/
extern void dump_config(struct hub_config* config, int ignore_defaults);
#endif /* HAVE_UHUB_CONFIG_H */

View File

@ -1,299 +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 void hub_command_args_free(struct hub_command* cmd)
{
struct hub_command_arg_data* data = NULL;
if (!cmd->args)
return;
LIST_FOREACH(struct hub_command_arg_data*, data, cmd->args,
{
switch (data->type)
{
case type_string:
hub_free(data->data.string);
break;
case type_range:
hub_free(data->data.range);
break;
default:
break;
}
});
list_clear(cmd->args, hub_free);
list_destroy(cmd->args);
cmd->args = NULL;
}
void command_free(struct hub_command* cmd)
{
if (!cmd) return;
hub_free(cmd->prefix);
hub_command_args_free(cmd);
hub_free(cmd);
}
static enum command_parse_status command_extract_arguments(struct hub_info* hub, const struct hub_user* user, struct command_handle* command, struct linked_list* tokens, struct linked_list* args)
{
int arg = 0;
int opt = 0;
int greedy = 0;
char arg_code;
char* token = NULL;
char* tmp = NULL;
size_t size = 0;
size_t offset = 0;
struct hub_command_arg_data* data = NULL;
enum command_parse_status status = cmd_status_ok;
// Ignore the first token since it is the prefix.
token = list_get_first(tokens);
list_remove(tokens, token);
hub_free(token);
while (status == cmd_status_ok && (arg_code = command->args[arg++]))
{
if (greedy)
{
size = 1;
LIST_FOREACH(char*, tmp, tokens, { size += (strlen(tmp) + 1); });
token = hub_malloc_zero(size);
while ((tmp = list_get_first(tokens)))
{
if (offset > 0)
token[offset++] = ' ';
memcpy(token + offset, tmp, strlen(tmp));
offset += strlen(tmp);
list_remove(tokens, tmp);
hub_free(tmp);
}
}
else
{
token = list_get_first(tokens);
}
if (!token || !*token)
{
if (arg_code == '?' || opt == 1)
status = cmd_status_ok;
else
status = cmd_status_missing_args;
break;
}
switch (arg_code)
{
case '?':
opt = 1;
continue;
case '+':
greedy = 1;
continue;
case 'u':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_nick(hub->users, token);
if (!data->data.user)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_nick;
}
break;
case 'i':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_cid(hub->users, token);
if (!data->data.user)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_cid;
}
break;
case 'a':
data = hub_malloc(sizeof(*data));
data->type = type_address;
if (ip_convert_to_binary(token, data->data.address) == -1)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
case 'r':
data = hub_malloc(sizeof(*data));
data->type = type_range;
data->data.range = hub_malloc_zero(sizeof(struct ip_range));
if (!ip_convert_address_to_range(token, data->data.range))
{
hub_free(data->data.range);
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
case 'n':
case 'm':
case 'p':
data = hub_malloc(sizeof(*data));
data->type = type_string;
data->data.string = strdup(token);
break;
case 'c':
data = hub_malloc(sizeof(*data));
data->type = type_command;
data->data.command = command_handler_lookup(hub->commands, token);
if (!data->data.command)
{
hub_free(data);
data = NULL;
status = cmd_status_arg_command;
}
break;
case 'C':
data = hub_malloc(sizeof(*data));
data->type = type_credentials;
if (!auth_string_to_cred(token, &data->data.credentials))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_cred;
}
break;
case 'N':
data = hub_malloc(sizeof(*data));
data->type = type_integer;
if (!is_number(token, &data->data.integer))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_number;
}
break;
case '\0':
if (!opt)
{
status = cmd_status_missing_args;
}
else
{
status = cmd_status_ok;
}
}
if (data)
{
list_append(args, data);
data = NULL;
}
list_remove(tokens, token);
hub_free(token);
}
hub_free(data);
return status;
}
static struct command_handle* command_get_handler(struct command_base* cbase, const char* prefix, const struct hub_user* user, struct hub_command* cmd)
{
struct command_handle* handler = NULL;
uhub_assert(cmd != NULL);
if (prefix && prefix[0] && prefix[1])
{
handler = command_handler_lookup(cbase, prefix + 1);
if (handler)
{
cmd->ptr = handler->ptr;
cmd->handler = handler->handler;
cmd->status = command_is_available(handler, user->credentials) ? cmd_status_ok : cmd_status_access_error;
}
else
{
cmd->status = cmd_status_not_found;
}
}
else
{
cmd->status = cmd_status_syntax_error;
}
return handler;
}
/**
* Parse a command and break it down into a struct hub_command.
*/
struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message)
{
struct linked_list* tokens = list_create();
struct hub_command* cmd = NULL;
struct command_handle* handle = NULL;
cmd = hub_malloc_zero(sizeof(struct hub_command));
cmd->status = cmd_status_ok;
cmd->message = message;
cmd->prefix = NULL;
cmd->args = list_create();
cmd->user = user;
if (split_string(message, " ", tokens, 0) <= 0)
{
cmd->status = cmd_status_syntax_error;
goto command_parse_cleanup;
}
// Setup hub command.
cmd->prefix = strdup(((char*) list_get_first(tokens)) + 1);
// Find a matching command handler
handle = command_get_handler(cbase, list_get_first(tokens), user, cmd);
if (cmd->status != cmd_status_ok)
goto command_parse_cleanup;
// Parse arguments
cmd->status = command_extract_arguments(hub, user, handle, tokens, cmd->args);
goto command_parse_cleanup;
command_parse_cleanup:
list_clear(tokens, &hub_free);
list_destroy(tokens);
return cmd;
}

View File

@ -1,131 +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_COMMAND_PARSER_H
#define HAVE_UHUB_COMMAND_PARSER_H
struct hub_command;
struct hub_user;
struct command_base;
/**
* Parse a message as a command and return a status indicating if the command
* is valid and that the arguments are sane.
*
* @param cbase Command base pointer.
* @param user User who invoked the command.
* @param message The message that is to be interpreted as a command (including the invocation prefix '!' or '+')
*
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
*/
extern struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message);
/**
* Free a hub_command that was created in command_parse().
*/
extern void command_free(struct hub_command* command);
enum command_parse_status
{
cmd_status_ok, /** <<< "Everything seems to OK" */
cmd_status_not_found, /** <<< "Command was not found" */
cmd_status_access_error, /** <<< "You don't have access to this command" */
cmd_status_syntax_error, /** <<< "Not a valid command." */
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
};
enum hub_command_arg_type
{
type_integer,
type_string,
type_user,
type_address,
type_range,
type_credentials,
type_command
};
struct hub_command_arg_data
{
enum hub_command_arg_type type;
union {
int integer;
char* string;
struct hub_user* user;
struct ip_addr_encap* address;
struct ip_range* range;
enum auth_credentials credentials;
struct command_handle* command;
} data;
};
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
/**
* This struct contains all information needed to invoke
* a command, which includes the whole message, the prefix,
* the decoded arguments (according to parameter list), and
* the user pointer (ptr) which comes from the command it was matched to.
*
* The message and prefix is generally always available, but args only
* if status == cmd_status_ok.
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
*/
struct hub_command
{
const char* message; /**<<< "The complete message." */
char* prefix; /**<<< "The prefix extracted from the message." */
struct linked_list* args; /**<<< "List of arguments of type struct hub_command_arg_data. Parsed from message." */
enum command_parse_status status; /**<<< "Status of the parsed hub_command." */
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
const struct hub_user* user; /**<<< "The user who invoked this command." */
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
};
/**
* Reset the command argument iterator and return the number of arguments
* that can be extracted from a parsed command.
*
* @param cmd the command to start iterating arguments
* @return returns the number of arguments provided for the command
*/
extern size_t hub_command_arg_reset(struct hub_command* cmd);
/**
* Obtain the current argument and place it in data and increments the iterator.
* If no argument exists, or the argument is of a different type than \param type, then 0 is returned.
*
* NOTE: when calling hub_command_arg_next the first time during a command callback it is safe to assume
* that the first argument will be extracted. Thus you don't need to call hub_command_arg_reset().
*
* @param cmd the command used for iterating arguments.
* @param type the expected type of this argument
* @return NULL if no argument is found or if the argument found does not match the expected type.
*/
extern struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type);
#endif /* HAVE_UHUB_COMMAND_PARSER_H */

View File

@ -1,623 +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"
#ifdef DEBUG
// #define DEBUG_UNLOAD_PLUGINS
#endif
#define MAX_HELP_MSG 16384
#define MAX_HELP_LINE 512
static int send_command_access_denied(struct command_base* cbase, struct hub_user* user, const char* prefix);
static int send_command_not_found(struct command_base* cbase, struct hub_user* user, const char* prefix);
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);
struct command_base
{
struct hub_info* hub;
struct linked_list* handlers;
size_t prefix_length_max;
};
struct command_base* command_initialize(struct hub_info* hub)
{
struct command_base* cbase = (struct command_base*) hub_malloc(sizeof(struct command_base));
uhub_assert(cbase != NULL);
// uhub_assert(hub != NULL);
cbase->hub = hub;
cbase->handlers = (struct linked_list*) list_create();
cbase->prefix_length_max = 0;
uhub_assert(cbase->handlers != NULL);
commands_builtin_add(cbase);
return cbase;
}
void command_shutdown(struct command_base* cbase)
{
commands_builtin_remove(cbase);
uhub_assert(list_size(cbase->handlers) == 0);
list_destroy(cbase->handlers);
hub_free(cbase);
}
int command_add(struct command_base* cbase, struct command_handle* cmd, void* ptr)
{
uhub_assert(cbase != NULL);
uhub_assert(cmd != NULL);
uhub_assert(cmd->length == strlen(cmd->prefix));
uhub_assert(cmd->handler != NULL);
uhub_assert(cmd->description && *cmd->description);
list_append(cbase->handlers, cmd);
cbase->prefix_length_max = MAX(cmd->length, cbase->prefix_length_max);
cmd->ptr = ptr;
return 1;
}
int command_del(struct command_base* cbase, struct command_handle* cmd)
{
uhub_assert(cbase != NULL);
uhub_assert(cmd != NULL);
list_remove(cbase->handlers, cmd);
return 1;
}
int command_is_available(struct command_handle* handle, enum auth_credentials credentials)
{
uhub_assert(handle != NULL);
return handle->cred <= credentials;
}
struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix)
{
struct command_handle* handler = NULL;
size_t prefix_len = strlen(prefix);
LIST_FOREACH(struct command_handle*, handler, cbase->handlers,
{
if (prefix_len != handler->length)
continue;
if (!memcmp(prefix, handler->prefix, handler->length))
return handler;
});
return NULL;
}
void command_get_syntax(struct command_handle* handler, struct cbuffer* buf)
{
size_t n, arg_count;
int opt = 0;
char arg_code, last_arg = -1;
cbuf_append_format(buf, "!%s", handler->prefix);
if (handler->args)
{
arg_count = strlen(handler->args);
for (n = 0; n < arg_count; n++)
{
if (!strchr("?+", last_arg))
cbuf_append(buf, " ");
arg_code = handler->args[n];
switch (arg_code)
{
case '?': cbuf_append(buf, "["); opt++; break;
case '+': /* ignore */ break;
case 'n': cbuf_append(buf, "<nick>"); break;
case 'u': cbuf_append(buf, "<user>"); break;
case 'i': cbuf_append(buf, "<cid>"); break;
case 'a': cbuf_append(buf, "<addr>"); break;
case 'r': cbuf_append(buf, "<addr range>"); break;
case 'm': cbuf_append(buf, "<message>"); break;
case 'p': cbuf_append(buf, "<password>"); break;
case 'C': cbuf_append(buf, "<credentials>"); break;
case 'c': cbuf_append(buf, "<command>"); break;
case 'N': cbuf_append(buf, "<number>"); break;
default: LOG_ERROR("unknown argument code '%c'", arg_code);
}
last_arg = arg_code;
}
while (opt--)
cbuf_append(buf, "]");
}
}
void send_message(struct command_base* cbase, struct hub_user* user, struct cbuffer* buf)
{
char* buffer = adc_msg_escape(cbuf_get(buf));
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(cbase->hub, user, command);
adc_msg_free(command);
hub_free(buffer);
cbuf_destroy(buf);
}
static int send_command_access_denied(struct command_base* cbase, struct hub_user* user, const char* prefix)
{
struct cbuffer* buf = cbuf_create(128);
cbuf_append_format(buf, "*** %s: Access denied.", prefix);
send_message(cbase, user, buf);
return 0;
}
static int send_command_not_found(struct command_base* cbase, struct hub_user* user, const char* prefix)
{
struct cbuffer* buf = cbuf_create(128);
cbuf_append_format(buf, "*** %s: Command not found.", prefix);
send_message(cbase, user, buf);
return 0;
}
static int send_command_syntax_error(struct command_base* cbase, struct hub_user* user)
{
struct cbuffer* buf = cbuf_create(128);
cbuf_append(buf, "*** Syntax error.");
send_message(cbase, user, buf);
return 0;
}
static int send_command_missing_arguments(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(512);
cbuf_append_format(buf, "*** Missing argument: See !help %s\n", cmd->prefix);
send_message(cbase, user, buf);
return 0;
}
static size_t command_count_required_args(struct command_handle* handler)
{
size_t n = 0;
for (n = 0; n < strlen(handler->args); n++)
{
if (handler->args[n] == '?')
break;
}
return n;
}
int command_check_args(struct hub_command* cmd, struct command_handle* handler)
{
if (!handler->args)
return 1;
if (list_size(cmd->args) >= command_count_required_args(handler))
return 1;
return 0;
}
int command_invoke(struct command_base* cbase, struct hub_user* user, const char* message)
{
int ret = 0;
struct hub_command* cmd = command_parse(cbase, cbase->hub, user, message);
switch (cmd->status)
{
case cmd_status_ok:
ret = cmd->handler(cbase, user, cmd);
break;
case cmd_status_not_found:
ret = send_command_not_found(cbase, user, cmd->prefix);
break;
case cmd_status_access_error:
ret = send_command_access_denied(cbase, user, cmd->prefix);
break;
case cmd_status_missing_args:
ret = send_command_missing_arguments(cbase, user, cmd);
break;
case cmd_status_syntax_error:
case cmd_status_arg_nick:
case cmd_status_arg_cid:
case cmd_status_arg_address:
case cmd_status_arg_number:
case cmd_status_arg_cred:
case cmd_status_arg_command:
ret = send_command_syntax_error(cbase, user);
break;
}
command_free(cmd);
return ret;
}
size_t hub_command_arg_reset(struct hub_command* cmd)
{
cmd->args->iterator = NULL;
return list_size(cmd->args);
}
struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type)
{
struct hub_command_arg_data* ptr = (struct hub_command_arg_data*) list_get_next(cmd->args);
if (!ptr)
return NULL;
uhub_assert(ptr->type == type);
if (ptr->type != type)
return NULL;
return ptr;
}
static int command_status(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd, struct cbuffer* msg)
{
struct cbuffer* buf = cbuf_create(cbuf_size(msg) + strlen(cmd->prefix) + 7);
cbuf_append_format(buf, "*** %s: %s", cmd->prefix, cbuf_get(msg));
send_message(cbase, user, buf);
cbuf_destroy(msg);
return 0;
}
static int command_help(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
size_t n;
struct cbuffer* buf = cbuf_create(MAX_HELP_LINE);
struct hub_command_arg_data* data = hub_command_arg_next(cmd, type_command);
struct command_handle* command;
if (!data)
{
cbuf_append(buf, "Available commands:\n");
LIST_FOREACH(struct command_handle*, command, cbase->handlers,
{
if (command_is_available(command, user->credentials))
{
cbuf_append_format(buf, "!%s", command->prefix);
for (n = strlen(command->prefix); n < cbase->prefix_length_max; n++)
cbuf_append(buf, " ");
cbuf_append_format(buf, " - %s\n", command->description);
}
});
}
else
{
command = data->data.command;
if (command_is_available(command, user->credentials))
{
cbuf_append_format(buf, "Usage: ");
command_get_syntax(command, buf);
cbuf_append_format(buf, "\n%s\n", command->description);
}
else
{
cbuf_append(buf, "This command is not available to you.\n");
}
}
return command_status(cbase, user, cmd, buf);
}
static int command_uptime(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
size_t d;
size_t h;
size_t m;
size_t D = (size_t) difftime(time(0), cbase->hub->tm_started);
d = D / (24 * 3600);
D = D % (24 * 3600);
h = D / 3600;
D = D % 3600;
m = D / 60;
if (d)
cbuf_append_format(buf, "%d day%s, ", (int) d, d != 1 ? "s" : "");
cbuf_append_format(buf, "%02d:%02d", (int) h, (int) m);
return command_status(cbase, user, cmd, buf);
}
static int command_kick(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf;
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user);
struct hub_user* target = arg->data.user;
buf = cbuf_create(128);
if (target == user)
{
cbuf_append(buf, "Cannot kick yourself.");
}
else
{
cbuf_append_format(buf, "Kicking user \"%s\".", target->id.nick);
hub_disconnect_user(cbase->hub, target, quit_kicked);
}
return command_status(cbase, user, cmd, buf);
}
static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
cbase->hub->status = hub_status_restart;
return command_status(cbase, user, cmd, cbuf_create_const("Reloading configuration..."));
}
#ifdef DEBUG_UNLOAD_PLUGINS
int hub_plugins_load(struct hub_info* hub);
int hub_plugins_unload(struct hub_info* hub);
static int command_load(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
hub_plugins_load(cbase->hub);
return command_status(cbase, user, cmd, cbuf_create_const("Loading plugins..."));
}
static int command_unload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
hub_plugins_unload(cbase->hub);
return command_status(cbase, user, cmd, cbuf_create_const("Unloading plugins..."));
}
#endif /* DEBUG_UNLOAD_PLUGINS */
static int command_shutdown_hub(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
cbase->hub->status = hub_status_shutdown;
return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down..."));
}
static int command_version(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf;
if (cbase->hub->config->show_banner_sys_info)
buf = cbuf_create_const("Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO);
else
buf = cbuf_create_const("Powered by " PRODUCT_STRING);
return command_status(cbase, user, cmd, buf);
}
static int command_myip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
cbuf_append_format(buf, "Your address is \"%s\"", user_get_address(user));
return command_status(cbase, user, cmd, buf);
}
static int command_getip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user);
cbuf_append_format(buf, "\"%s\" has address \"%s\"", arg->data.user->id.nick, user_get_address(arg->data.user));
return command_status(cbase, user, cmd, buf);
}
static int command_whoip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf;
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_range);
struct linked_list* users = (struct linked_list*) list_create();
struct hub_user* u;
int ret = 0;
ret = uman_get_user_by_addr(cbase->hub->users, users, arg->data.range);
if (!ret)
{
list_clear(users, NULL);
list_destroy(users);
return command_status(cbase, user, cmd, cbuf_create_const("No users found."));
}
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" : ""));
LIST_FOREACH(struct hub_user*, u, users,
{
cbuf_append_format(buf, "%s (%s)\n", u->id.nick, user_get_address(u));
});
cbuf_append(buf, "\n");
send_message(cbase, user, buf);
list_clear(users, NULL);
list_destroy(users);
return 0;
}
static int command_broadcast(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_string);
char* message = arg->data.string;
size_t message_len = strlen(message);
char pm_flag[7] = "PM";
char from_sid[5];
size_t recipients = 0;
struct hub_user* target;
struct cbuffer* buf = cbuf_create(128);
struct adc_message* command = NULL;
memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid));
memcpy(pm_flag + 2, from_sid, sizeof(from_sid));
LIST_FOREACH(struct hub_user*, target, cbase->hub->users->list,
{
if (target != user)
{
recipients++;
command = adc_msg_construct(ADC_CMD_DMSG, message_len + 23);
if (!command)
break;
adc_msg_add_argument(command, from_sid);
adc_msg_add_argument(command, sid_to_string(target->id.sid));
adc_msg_add_argument(command, message);
adc_msg_add_argument(command, pm_flag);
route_to_user(cbase->hub, target, command);
adc_msg_free(command);
}
});
cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : ""));
send_message(cbase, user, buf);
return 0;
}
static int command_log(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf;
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_string);
struct linked_list* messages = cbase->hub->logout_info;
struct hub_logout_info* log;
char* search = arg ? arg->data.string : "";
size_t search_len = strlen(search);
size_t search_hits = 0;
if (!list_size(messages))
{
return command_status(cbase, user, cmd, cbuf_create_const("No entries logged."));
}
buf = cbuf_create(128);
cbuf_append_format(buf, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
if (search_len)
{
cbuf_append_format(buf, ", searching for \"%s\"", search);
}
command_status(cbase, user, cmd, buf);
buf = cbuf_create(MAX_HELP_LINE);
LIST_FOREACH(struct hub_logout_info*, log, messages,
{
const char* address = ip_convert_to_string(&log->addr);
int show = 0;
if (search_len)
{
if (memmem(log->cid, MAX_CID_LEN, search, search_len) || memmem(log->nick, MAX_NICK_LEN, search, search_len) || memmem(address, strlen(address), search, search_len))
{
search_hits++;
show = 1;
}
}
else
{
show = 1;
}
if (show)
{
cbuf_append_format(buf, "* %s %s, %s [%s] - %s", get_timestamp(log->time), log->cid, log->nick, ip_convert_to_string(&log->addr), user_get_quit_reason_string(log->reason));
send_message(cbase, user, buf);
buf = cbuf_create(MAX_HELP_LINE);
}
});
if (search_len)
{
cbuf_append_format(buf, PRINTF_SIZE_T " entries shown.", search_hits);
command_status(cbase, user, cmd, buf);
buf = NULL;
}
if (buf)
cbuf_destroy(buf);
return 0;
}
static int command_stats(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct hub_info* hub = cbase->hub;
static char rxbuf[64] = { "0 B" };
static char txbuf[64] = { "0 B" };
cbuf_append(buf, "Hub statistics: ");
cbuf_append_format(buf, PRINTF_SIZE_T "/" PRINTF_SIZE_T " users (peak %d). ", hub->users->count, hub->config->max_users, hub->users->count_peak);
format_size(hub->stats.net_rx, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx, txbuf, sizeof(txbuf));
cbuf_append_format(buf, "Network: tx=%s/s, rx=%s/s", txbuf, rxbuf);
#ifdef SHOW_PEAK_NET_STATS /* currently disabled */
format_size(hub->stats.net_rx_peak, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx_peak, txbuf, sizeof(txbuf));
cbuf_append_format(buf, ", peak_tx=%s/s, peak_rx=%s/s", txbuf, rxbuf);
#endif
format_size(hub->stats.net_rx_total, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx_total, txbuf, sizeof(txbuf));
cbuf_append_format(buf, ", total_tx=%s", txbuf);
cbuf_append_format(buf, ", total_rx=%s", rxbuf);
return command_status(cbase, user, cmd, buf);
}
static struct command_handle* add_builtin(struct command_base* cbase, const char* prefix, const char* args, enum auth_credentials cred, command_handler handler, const char* description)
{
struct command_handle* handle = (struct command_handle*) hub_malloc_zero(sizeof(struct command_handle));
handle->prefix = prefix;
handle->length = strlen(prefix);
handle->args = args;
handle->cred = cred;
handle->handler = handler;
handle->description = description;
handle->origin = "built-in";
handle->ptr = cbase;
return handle;
}
#define ADD_COMMAND(PREFIX, LENGTH, ARGS, CREDENTIALS, FUNCTION, DESCRIPTION) \
command_add(cbase, add_builtin(cbase, PREFIX, ARGS, CREDENTIALS, FUNCTION, DESCRIPTION), NULL)
void commands_builtin_add(struct command_base* cbase)
{
ADD_COMMAND("broadcast", 9, "+m",auth_cred_operator, command_broadcast,"Send a message to all users" );
ADD_COMMAND("getip", 5, "u", auth_cred_operator, command_getip, "Show IP address for a user" );
ADD_COMMAND("help", 4, "?c",auth_cred_guest, command_help, "Show this help message." );
ADD_COMMAND("kick", 4, "u", auth_cred_operator, command_kick, "Kick a user" );
ADD_COMMAND("log", 3, "?m",auth_cred_operator, command_log, "Display log" ); // fail
ADD_COMMAND("myip", 4, "", auth_cred_guest, command_myip, "Show your own IP." );
ADD_COMMAND("reload", 6, "", auth_cred_admin, command_reload, "Reload configuration files." );
ADD_COMMAND("shutdown", 8, "", auth_cred_admin, command_shutdown_hub, "Shutdown hub." );
ADD_COMMAND("stats", 5, "", auth_cred_super, command_stats, "Show hub statistics." );
ADD_COMMAND("uptime", 6, "", auth_cred_guest, command_uptime, "Display hub uptime info." );
ADD_COMMAND("version", 7, "", auth_cred_guest, command_version, "Show hub version info." );
ADD_COMMAND("whoip", 5, "r", auth_cred_operator, command_whoip, "Show users matching IP range" );
#ifdef DEBUG_UNLOAD_PLUGINS
ADD_COMMAND("load", 4, "", auth_cred_admin, command_load, "Load plugins." );
ADD_COMMAND("unload", 6, "", auth_cred_admin, command_unload, "Unload plugins." );
#endif /* DEBUG_UNLOAD_PLUGINS */
}
void commands_builtin_remove(struct command_base* cbase)
{
struct command_handle* command;
while ((command = list_get_first(cbase->handlers)))
{
command_del(cbase, command);
hub_free(command);
}
}

View File

@ -1,109 +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_COMMANDS_H
#define HAVE_UHUB_COMMANDS_H
struct command_base;
struct command_handle;
struct hub_command;
/**
* Argument codes are used to automatically parse arguments
* for a a hub command.
*
* u = user (must exist in hub session, or will cause error)
* n = nick name (string)
* i = CID (must exist in hub)
* a = (IP) address (must be a valid IPv4 or IPv6 address)
* r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work)
* m = message (string)
* p = password (string)
* C = credentials (see auth_string_to_cred).
* c = command (name of command)
* N = number (integer)
*
* Prefix an argument with ? to make it optional.
* Prefix with + to make the argument greedy, which causes it to grab the rest of the line ignoring boundaries (only supported for string types).
*
* NOTE: if an argument is optional then all following arguments must also be optional.
* NOTE: You can combine optional and greedy, example: "?+m" would match "", "a", "a b c", etc.
*
* Example:
* "nia" means "nick cid ip"
* "n?p" means "nick [password]" where password is optional.
* "?N?N" means zero, one, or two integers.
* "?NN" means zero or two integers.
* "?+m" means an optional string which may contain spaces that would otherwise be split into separate arguments.
*/
struct command_handle
{
const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */
size_t length; /**<<< "Length of the prefix" */
const char* args; /**<<< "Argument codes (see above)" */
enum auth_credentials cred; /**<<< "Minimum access level for the command" */
command_handler handler; /**<<< "Function pointer for the command" */
const char* description; /**<<< "Description for the command" */
const char* origin; /**<<< "Name of module where the command is implemented." */
void* ptr; /**<<< "A pointer which will be passed along to the handler. @See hub_command::ptr" */
};
/**
* Returns NULL on error, or handle
*/
extern struct command_base* command_initialize(struct hub_info* hub);
extern void command_shutdown(struct command_base* cbase);
/**
* Add a new command to the command base.
* Returns 1 on success, or 0 on error.
*/
extern int command_add(struct command_base*, struct command_handle*, void* ptr);
/**
* Remove a command from the command base.
* Returns 1 on success, or 0 on error.
*/
extern int command_del(struct command_base*, struct command_handle*);
/**
* Dispatch a message and forward it as a command.
* Returns 1 if the message should be forwarded as a chat message, or 0 if
* it is supposed to be handled internally in the dispatcher.
*
* This will break the message down into a struct hub_command and invoke the command handler
* for that command if the sufficient access credentials are met.
*/
extern int command_invoke(struct command_base*, struct hub_user* user, const char* message);
/**
* Returns 1 if the command handle can be used with the given credentials, 0 otherwise.
*/
int command_is_available(struct command_handle* handle, enum auth_credentials credentials);
/**
* Lookup a command handle based on prefix.
* If no matching command handle is found then NULL is returned.
*/
struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix);
extern void commands_builtin_add(struct command_base*);
extern void commands_builtin_remove(struct command_base*);
#endif /* HAVE_UHUB_COMMANDS_H */

View File

@ -1,140 +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"
#ifndef INT_MAX
#define INT_MAX 0x7fffffff
#endif
#ifndef INT_MIN
#define INT_MIN (-0x7fffffff - 1)
#endif
static int apply_boolean(const char* key, const char* data, int* target)
{
return string_to_boolean(data, target);
}
static int apply_string(const char* key, const char* data, char** target, char* regexp)
{
(void) regexp;
// FIXME: Add regexp checks for correct data
if (*target)
hub_free(*target);
*target = hub_strdup(data);
return 1;
}
static int apply_integer(const char* key, const char* data, int* target, int* min, int* max)
{
char* endptr;
int val;
errno = 0;
val = strtol(data, &endptr, 10);
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data)
return 0;
if (min && val < *min)
return 0;
if (max && val > *max)
return 0;
*target = val;
return 1;
}
#include "gen_config.c"
static int config_parse_line(char* line, int line_count, void* ptr_data)
{
char* pos;
char* key;
char* data;
struct hub_config* config = (struct hub_config*) ptr_data;
strip_off_ini_line_comments(line, line_count);
if (!*line) return 0;
LOG_DUMP("config_parse_line(): '%s'", line);
if (!is_valid_utf8(line))
{
LOG_WARN("Invalid utf-8 characters on line %d", line_count);
}
if ((pos = strchr(line, '=')) != NULL)
{
pos[0] = 0;
}
else
{
return 0;
}
key = line;
data = &pos[1];
key = strip_white_space(key);
data = strip_white_space(data);
data = strip_off_quotes(data);
if (!*key || !*data)
{
LOG_FATAL("Configuration parse error on line %d", line_count);
return -1;
}
LOG_DUMP("config_parse_line: '%s' => '%s'", key, data);
return apply_config(config, key, data, line_count);
}
int read_config(const char* file, struct hub_config* config, int allow_missing)
{
int ret;
memset(config, 0, sizeof(struct hub_config));
config_defaults(config);
ret = file_read_lines(file, config, &config_parse_line);
if (ret < 0)
{
if (allow_missing && ret == -2)
{
LOG_DUMP("Using default configuration.");
}
else
{
return -1;
}
}
return 0;
}

View File

@ -1,55 +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_CONFIG_H
#define HAVE_UHUB_CONFIG_H
#include "gen_config.h"
/**
* This initializes the configuration variables, and sets the default
* variables.
*
* NOTE: Any variable is set to it's default variable if zero.
* This function is automatically called in read_config to set any
* configuration that was missing there.
*/
extern void config_defaults(struct hub_config* config);
/**
* Read configuration from file, and use the default variables for
* the missing variables.
*
* @return -1 on error, 0 on success.
*/
extern int read_config(const char* file, struct hub_config* config, int allow_missing);
/**
* Free the configuration data (allocated by read_config, or config_defaults).
*/
extern void free_config(struct hub_config* config);
/**
* Print all configuration data to standard out.
*/
extern void dump_config(struct hub_config* config, int ignore_defaults);
#endif /* HAVE_UHUB_CONFIG_H */

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

@ -1,695 +0,0 @@
<?xml version='1.0' standalone="yes" ?>
<config>
<option name="hub_enabled" type="boolean" default="1">
<short>Is server enabled</short>
<description><![CDATA[
Use this to disable the hub for a while.
]]></description>
<since>0.1.3</since>
</option>
<option name="server_port" type="int" default="1511">
<check min="1" max="65535" />
<since>0.1.0</since>
<short>Server port to bind to</short>
<description><![CDATA[This specifies the port number the hub should listen on.]]></description>
</option>
<option name="server_bind_addr" type="string" default="any">
<check regexp="[\x:.]+|any|loopback" />
<short>Server bind address</short>
<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 />
When "any" or "loopback" is used, the hub will automatically detect if IPv6 is supported and prefer that.
]]></description>
<syntax>
IPv4 address, IPv6 address, "any" or "loopback"
</syntax>
<since>0.1.2</since>
<example><![CDATA[
<p>
To listen to a specific IP:<br />
server_bind_addr = "192.168.12.69"
</p>
<p>
To listen to any IPv4 address:<br />
server_bind_addr = "0.0.0.0"
</p>
<p>
Or to listen to any address including IPv6 (if supported):<br />
server_bind_addr = "any"
</p>
]]></example>
</option>
<option name="server_listen_backlog" type="int" default="50">
<check min="5" />
<short>Server listen backlog</short>
<description><![CDATA[
<p>
This specifies the number of connections the hub will be able to accept in the backlog before they must be processed by the hub.
</p>
<p>
A too low number here will mean the hub will not accept connections fast enough when users are reconnecting really fast. The hub should under normal circumstances be able to empty the listen backlog several times per second.
</p>
]]></description>
<since>0.3.0</since>
</option>
<option name="server_alt_ports" type="string" default="">
<check regexp="\d+(,\d+)*" />
<short>Comma separated list of alternative ports to listen to</short>
<description><![CDATA[
In addition to the server_port the hub can listen to a list of alternative ports.
]]></description>
<example><![CDATA[
server_alt_ports = 1295,1512,53990
]]></example>
<since>0.3.0</since>
</option>
<option name="show_banner" type="boolean" default="1">
<short>Show banner on connect</short>
<description><![CDATA[
If enabled, the hub will announce the software version running to clients when they connect with a message like: "Powered by uhub/0.x.y"
]]></description>
<since>0.1.0</since>
</option>
<option name="show_banner_sys_info" type="boolean" default="1">
<short>Show banner on connect</short>
<description><![CDATA[
If enabled, the hub will announce the operating system and CPU architecture to clients when they join.<br />
This option has no effect if show_banner is disabled.
]]></description>
<since>0.3.0</since>
</option>
<option name="max_users" type="int" default="500">
<check min="1" max="1048576" />
<short>Maximum number of users allowed on the hub</short>
<description><![CDATA[
The maximum amount of users allowed on the hub.
No new users will be allowed to enter the hub if this number is exceeded, however privileged users (operators, admins, etc) are still able to log in.
]]></description>
<since>0.1.0</since>
<example><![CDATA[
To run a hub for max 25 users:<br />
max_users = 25
]]></example>
</option>
<option name="registered_users_only" type="boolean" default="0">
<short>Allow registered users only</short>
<description><![CDATA[
If this is enabled only registered users will be able to use the hub. A user must be registered in the acl file (file_acl).
]]></description>
<since>0.1.1</since>
</option>
<option name="register_self" type="boolean" default="0">
<short>Allow users to register themselves on the hub.</short>
<description><![CDATA[
If this is enabled guests can register their nickname on the hub using !register command.
Otherwise only operators can register users.
]]></description>
<since>0.4.0</since>
</option>
<option name="obsolete_clients" type="boolean" default="0">
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
<description><![CDATA[
If this is enabled users using old ADC clients are allowed to enter the hub,
however they cannot log in using passwords since the protocols are incompatible.
]]></description>
<since>0.3.1</since>
</option>
<option name="chat_is_privileged" type="boolean" default="0">
<short>Allow chat for operators and above only</short>
<description><![CDATA[
If enabled only operators and admins are allowed to chat in the main chat.
]]></description>
<since>0.2.4</since>
</option>
<option name="hub_name" type="string" default="uhub">
<short>Name of hub</short>
<description><![CDATA[
Configures the name of the hub
]]></description>
<since>0.1.0</since>
<example><![CDATA[
hub_name = "my hub"
]]></example>
</option>
<option name="hub_description" type="string" default="no description">
<short>Short hub description, topic or subject.</short>
<description><![CDATA[
This is the description of the hub, as seen by users and hub lists.
]]></description>
<since>0.1.0</since>
<example><![CDATA[
hub_description = "a friendly hub for friendly people"
]]></example>
</option>
<option name="redirect_addr" type="string" default="">
<check regexp="(adcs?|dchub)://.*" />
<short>A common hub redirect address.</short>
<description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
]]></description>
<since>0.3.2</since>
</option>
<option name="max_recv_buffer" type="int" default="4096" advanced="true" >
<check min="1024" max="1048576" />
<short>Max read buffer before parse, per user</short>
<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.
]]></description>
<since>0.1.3</since>
</option>
<option name="max_send_buffer" type="int" default="131072" advanced="true" >
<check min="2048" />
<short>Max send buffer before disconnect, per user</short>
<description><![CDATA[
Maximum amount of bytes allowed to be queued for sending to any particular user before the hub will disconnect the user. The lower the limit, the more aggressive the hub will be to disconnect slow clients. Use with caution.
]]></description>
<since>0.1.3</since>
</option>
<option name="max_send_buffer_soft" type="int" default="98304" advanced="true" >
<check min="1024" />
<short>Max send buffer before message drops, per user</short>
<description><![CDATA[
Same as max_send_buffer, however low priority messages may be discarded if this limit is reached. Use with caution.
]]></description>
<since>0.1.3</since>
</option>
<option name="low_bandwidth_mode" type="boolean" default="0" advanced="true" >
<short>Enable bandwidth saving measures</short>
<description><![CDATA[
If this is enabled the hub will remove excessive information from each user's info message before broadcasting to all connected users.
Description, e-mail address will be removed. This saves upload bandwidth for the hub.
]]></description>
<since>0.2.2</since>
</option>
<option name="max_chat_history" type="int" default="20">
<check min="0" max="250" />
<short>Number of chat messages kept in history</short>
<description><![CDATA[
This specifies the number of main chat messages that are kept in the history buffer.
Users can use the "!history" command to list these messages.
]]></description>
<since>0.3.0</since>
</option>
<option name="max_logout_log" type="int" default="20">
<check min="0" max="2000" />
<short>Number of log entries for people leaving the hub</short>
<description><![CDATA[
Operators can use the "!log" command to list users who have recently left the hub.
This option specifies the maximum size of this log.
]]></description>
<since>0.3.0</since>
</option>
<option name="limit_max_hubs_user" type="int" default="10">
<check min="0" />
<short>Max concurrent hubs as a guest user</short>
<description><![CDATA[
This limits the number of hubs a user can be logged into as a guest user. If this number is exceeded, the user will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_max_hubs_reg" type="int" default="10">
<check min="0" />
<short>Max concurrent hubs as a registered user</short>
<description><![CDATA[
This limits the number of hubs a user can be logged into as a registered user. If this number is exceeded, the user will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_max_hubs_op" type="int" default="10">
<check min="0" />
<short>Max concurrent hubs as a operator (or admin)</short>
<description><![CDATA[
This limits the number of hubs a user can be logged into as an operator. If this number is exceeded, the user will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_max_hubs" type="int" default="25">
<check min="0" />
<short>Max total hub connections allowed, user/reg/op combined.</short>
<description><![CDATA[
Limit the number of hubs a user can be logged into in total regardless of registrations or privileges.
If this number is exceeded, the user will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_min_hubs_user" type="int" default="0">
<check min="0" />
<short>Minimum concurrent hubs as a guest user</short>
<description><![CDATA[
Only allow users that are logged into other hubs with guest privileges to enter this hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_min_hubs_reg" type="int" default="0">
<check min="0" />
<short>Minimum concurrent hubs as a registered user</short>
<description><![CDATA[
Only allow users that are logged into other hubs as a registered user to enter this hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_min_hubs_op" type="int" default="0">
<check min="0" />
<short>Minimum concurrent hubs as a operator (or admin)</short>
<description><![CDATA[
Only allow users that are logged into other hubs with operator privileges to enter this hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_min_share" type="int" default="0">
<check min="0" />
<short>Limit minimum share size in megabytes</short>
<description><![CDATA[
Minimum share limit in megabytes (MiB). Users sharing less than this will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
<example><![CDATA[
To require users to share at least 1 GB in order to enter the hub:<br />
limit_min_share = 1024
]]></example>
</option>
<option name="limit_max_share" type="int" default="0">
<check min="0" />
<short>Limit maximum share size in megabytes</short>
<description><![CDATA[
Maximum share limit in megabytes (MiB). Users sharing more than this will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_min_slots" type="int" default="0">
<check min="0" />
<short>Limit minimum number of upload slots open per user</short>
<description><![CDATA[
Minimum number of upload slots required. Users with less than this will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="limit_max_slots" type="int" default="0">
<check min="0" />
<short>Limit minimum number of upload slots open per user</short>
<description><![CDATA[
Maximum number of upload slots allowed. Users with more than this will not be allowed to enter the hub.
]]></description>
<syntax>0 = off</syntax>
<since>0.2.0</since>
</option>
<option name="flood_ctl_interval" type="int" default="0">
<check min="1" max="60" />
<short>Time interval in seconds for flood control check.</short>
<description><![CDATA[
This is the time interval that will be used for all flood control calculations.
If this is 0 then all flood control is disabled.
]]></description>
<example><![CDATA[
To limit maximum chat messages to 5 messages on 10 seconds: <br />
flood_ctl_interval = 10 <br />
flood_ctl_chat = 5<br />
]]></example>
<syntax>0 = off</syntax>
<since>0.3.1</since>
</option>
<option name="flood_ctl_chat" type="int" default="0">
<short>Max chat messages allowed in time interval</short>
<description><![CDATA[
If this is 0 then no flood control is disabled for chat messages.
]]></description>
<syntax>0 = off</syntax>
<since>0.3.1</since>
</option>
<option name="flood_ctl_connect" type="int" default="0">
<short>Max connections requests allowed in time interval</short>
<description><![CDATA[
If this is 0 then no flood control is disabled for connection requests.
]]></description>
<syntax>0 = off</syntax>
<since>0.3.1</since>
</option>
<option name="flood_ctl_search" type="int" default="0">
<short>Max search requests allowed in time interval</short>
<description><![CDATA[
If this is 0 then no flood control is disabled for search requests.
]]></description>
<syntax>0 = off</syntax>
<since>0.3.1</since>
</option>
<option name="flood_ctl_update" type="int" default="0">
<short>Max updates allowed in time interval</short>
<description><![CDATA[
If this is 0 then no flood control is disabled for info updates (INF messages).
]]></description>
<syntax>0 = off</syntax>
<since>0.3.1</since>
</option>
<option name="flood_ctl_extras" type="int" default="0">
<short>Max extra messages allowed in time interval</short>
<description><![CDATA[
Extra messages are messages that don't fit into the category of chat, search, update or connect.
]]></description>
<syntax>0 = off</syntax>
<since>0.3.1</since>
</option>
<option name="tls_enable" type="boolean" default="0">
<short>Enable SSL/TLS support</short>
<description><![CDATA[
Enables/disables TLS/SSL support. tls_certificate and tls_private_key must be set if this is enabled.
]]></description>
<since>0.3.0</since>
</option>
<option name="tls_require" type="boolean" default="0">
<short>If SSL/TLS enabled, should it be required</short>
<description><![CDATA[
If TLS/SSL support is enabled it can either be optional or mandatory.
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
This option has no effect unless tls_enable is enabled.
]]></description>
<since>0.3.0</since>
</option>
<option name="tls_require_redirect_addr" type="string" default="">
<check regexp="(adcs?|dchub)://.*" />
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
<description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not using ADCS.
For instance a hub at adc://adc.example.com might redirect to adcs://adc.example.com
]]></description>
<since>0.3.3</since>
</option>
<option name="tls_certificate" type="file" default="">
<short>Certificate file</short>
<description><![CDATA[
Path to a TLS/SSL certificate or certificate chain (PEM format).
]]></description>
<since>0.3.0</since>
</option>
<option name="tls_private_key" type="file" default="">
<short>Private key file</short>
<description><![CDATA[
Path to a TLS/SSL private key (PEM format).
]]></description>
<since>0.3.0</since>
</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="">
<short>File containing access control lists</short>
<description><![CDATA[
This is an access control list (acl) file.
In this file all registered users, bans, etc should be stored.
If the file is missing, or empty no registered users, or ban records are used.
]]></description>
<since>0.1.3</since>
<example><![CDATA[
<p>
Unix users: <br />
file_acl = "/etc/uhub/users.conf"
</p>
<p>
Windows users: <br />
file_acl = "c:\uhub\users.conf"
</p>
]]></example>
</option>
<option name="file_plugins" type="file" default="">
<short>Plugin configuration file</short>
<description><![CDATA[
Plugin configuration file.
]]></description>
<since>0.3.3</since>
<example><![CDATA[
<p>
file_plugins = "/etc/uhub/plugins.conf"
</p>
]]></example>
</option>
<option name="msg_hub_full" type="message" default="Hub is full" >
<description><![CDATA[This will be sent if the hub is full]]></description>
<since>0.2.0</since>
</option>
<option name="msg_hub_disabled" type="message" default="Hub is disabled" >
<description><![CDATA[This will be sent if the hub is disabled (hub_enable = off)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_hub_registered_users_only" type="message" default="Hub is for registered users only" >
<description><![CDATA[This will be sent if the hub is configured to only accept registered users (registered_users_only = yes)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_missing" type="message" default="No nickname given">
<description><![CDATA[This is an error message that will be sent to clients that do not provide a nickname.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_multiple" type="message" default="Multiple nicknames given">
<description><![CDATA[This is an error message that will be sent to clients that provide multiple nicknames.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_invalid" type="message" default="Nickname is invalid">
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid nickname.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_long" type="message" default="Nickname too long">
<description><![CDATA[This is an error message that will be sent to clients that provides a too long nickname.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_short" type="message" default="Nickname too short">
<description><![CDATA[This is an error message that will be sent to clients that provides a too short nickname.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_spaces" type="message" default="Nickname cannot start with spaces">
<description><![CDATA[This is an error message that will be sent to clients that provides a nickname that starts with a space.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_bad_chars" type="message" default="Nickname contains invalid characters">
<description><![CDATA[This is an error message that will be sent to clients that provides invalid characters in the nickname.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_not_utf8" type="message" default="Nickname is not valid UTF-8">
<description><![CDATA[This is an error message that will be sent to clients that provides a nick name that is not valid UTF-8 encoded.]]></description>
<since>0.2.0</since>
</option>
<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>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_nick_restricted" type="message" default="Nickname cannot be used on this hub">
<description><![CDATA[This message will be sent to clients if they provide a restricted nickname. Restricted names can be configured in the acl.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_cid_invalid" type="message" default="CID is not valid">
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid client ID (CID)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_cid_missing" type="message" default="CID is not specified">
<description><![CDATA[This is an error message that will be sent to clients that does not provide a client ID (CID)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_cid_taken" type="message" default="CID is taken">
<description><![CDATA[This is an error message that will be sent to clients that provides a client ID (CID) already in use on the hub.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_pid_missing" type="message" default="PID is not specified">
<description><![CDATA[This is an error message that will be sent to clients that does not provide a private ID (PID)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_inf_error_pid_invalid" type="message" default="PID is invalid">
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid private ID (PID)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_ban_permanently" type="message" default="Banned permanently">
<description><![CDATA[This message is sent to users if they are banned (see acl)]]></description>
<since>0.2.0</since>
</option>
<option name="msg_ban_temporarily" type="message" default="Banned temporarily">
<description><![CDATA[This message is sent to users if they are banned temporarily]]></description>
<since>0.2.0</since>
</option>
<option name="msg_auth_invalid_password" type="message" default="Password is wrong">
<description><![CDATA[This message is sent to users if they provide a wrong password.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_auth_user_not_found" type="message" default="User not found in password database">
<description><![CDATA[This message is used if a user cannot be found in the password database.]]></description>
<since>0.2.0</since> <!-- FIXME? -->
</option>
<option name="msg_error_no_memory" type="message" default="No memory">
<description><![CDATA[Hub has no more memory]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_share_size_low" type="message" default="User is not sharing enough">
<description><![CDATA[This message is sent to users if they are not sharing enough.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_share_size_high" type="message" default="User is sharing too much">
<description><![CDATA[This message is sent to users if they are sharing too much.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_slots_low" type="message" default="User have too few upload slots.">
<description><![CDATA[This message is sent to users if they do not have enough upload slots.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_slots_high" type="message" default="User have too many upload slots.">
<description><![CDATA[This message is sent to users if they have too many upload slots.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_hub_limit_low" type="message" default="User is on too few hubs.">
<description><![CDATA[This message is sent to users if they are on too few other hubs.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_hub_limit_high" type="message" default="User is on too many hubs.">
<description><![CDATA[This message is sent to users if they are on too many other hubs.]]></description>
<since>0.2.0</since>
</option>
<option name="msg_user_flood_chat" type="message" default="Chat flood detected, messages are dropped.">
<description><![CDATA[This message is sent once to users who are flooding the chat.]]></description>
<since>0.3.1</since>
</option>
<option name="msg_user_flood_connect" type="message" default="Connect flood detected, connection refused.">
<description><![CDATA[This message is sent once to users who are sending too many connect requests too fast.]]></description>
<since>0.3.1</since>
</option>
<option name="msg_user_flood_search" type="message" default="Search flood detected, search is stopped.">
<description><![CDATA[This message is sent once to users who are sending too many search requests too fast.]]></description>
<since>0.3.1</since>
</option>
<option name="msg_user_flood_update" type="message" default="Update flood detected.">
<description><![CDATA[This message is sent once to users who are sending too many updates too fast.]]></description>
<since>0.3.1</since>
</option>
<option name="msg_user_flood_extras" type="message" default="Flood detected.">
<description><![CDATA[This message is sent once to users who are sending too many messages to the hub that neither are chat, searhes, updates nor connection requests..]]></description>
<since>0.3.1</since>
</option>
<option name="msg_proto_no_common_hash" type="message" default="No common hash algorithm.">
<description><![CDATA[This message is sent if a client connects that does support ADC/1.0 but not a hash algorithm that the hub supports.]]></description>
<since>0.3.1</since>
</option>
<option name="msg_proto_obsolete_adc0" type="message" default="Client is using an obsolete ADC protocol version.">
<description><![CDATA[This message is sent if a client connects that does not support ADC/1.0, but rather the obsolete ADC/0.1 version.]]></description>
<since>0.3.1</since>
</option>
</config>

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
/*
* 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
{
int hub_enabled; /*<<< Is server enabled (default: 1) */
int server_port; /*<<< Server port to bind to (default: 1511) */
char* server_bind_addr; /*<<< Server bind address (default: "any") */
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: "") */
int show_banner; /*<<< Show banner on connect (default: 1) */
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
int registered_users_only; /*<<< Allow registered users only (default: 0) */
int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
char* hub_name; /*<<< Name of hub (default: "uhub") */
char* hub_description; /*<<< Short hub description, topic or subject. (default: "no description") */
char* redirect_addr; /*<<< A common hub redirect address. (default: "") */
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
int low_bandwidth_mode; /*<<< Enable bandwidth saving measures (default: 0) */
int max_chat_history; /*<<< Number of chat messages kept in history (default: 20) */
int max_logout_log; /*<<< Number of log entries for people leaving the hub (default: 20) */
int limit_max_hubs_user; /*<<< Max concurrent hubs as a guest user (default: 10) */
int limit_max_hubs_reg; /*<<< Max concurrent hubs as a registered user (default: 10) */
int limit_max_hubs_op; /*<<< Max concurrent hubs as a operator (or admin) (default: 10) */
int limit_max_hubs; /*<<< Max total hub connections allowed, user/reg/op combined. (default: 25) */
int limit_min_hubs_user; /*<<< Minimum concurrent hubs as a guest user (default: 0) */
int limit_min_hubs_reg; /*<<< Minimum concurrent hubs as a registered user (default: 0) */
int limit_min_hubs_op; /*<<< Minimum concurrent hubs as a operator (or admin) (default: 0) */
int limit_min_share; /*<<< Limit minimum share size in megabytes (default: 0) */
int limit_max_share; /*<<< Limit maximum share size in megabytes (default: 0) */
int limit_min_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
int limit_max_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
int flood_ctl_interval; /*<<< Time interval in seconds for flood control check. (default: 0) */
int flood_ctl_chat; /*<<< Max chat messages allowed in time interval (default: 0) */
int flood_ctl_connect; /*<<< Max connections requests allowed in time interval (default: 0) */
int flood_ctl_search; /*<<< Max search requests allowed in time interval (default: 0) */
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) */
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_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_plugins; /*<<< Plugin configuration file (default: "") */
char* msg_hub_full; /*<<< "Hub is full" */
char* msg_hub_disabled; /*<<< "Hub is disabled" */
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
char* msg_inf_error_nick_missing; /*<<< "No nickname given" */
char* msg_inf_error_nick_multiple; /*<<< "Multiple nicknames given" */
char* msg_inf_error_nick_invalid; /*<<< "Nickname is invalid" */
char* msg_inf_error_nick_long; /*<<< "Nickname too long" */
char* msg_inf_error_nick_short; /*<<< "Nickname too short" */
char* msg_inf_error_nick_spaces; /*<<< "Nickname cannot start with spaces" */
char* msg_inf_error_nick_bad_chars; /*<<< "Nickname contains invalid characters" */
char* msg_inf_error_nick_not_utf8; /*<<< "Nickname is not valid UTF-8" */
char* msg_inf_error_nick_taken; /*<<< "Nickname is already in use" */
char* msg_inf_error_nick_restricted; /*<<< "Nickname cannot be used on this hub" */
char* msg_inf_error_cid_invalid; /*<<< "CID is not valid" */
char* msg_inf_error_cid_missing; /*<<< "CID is not specified" */
char* msg_inf_error_cid_taken; /*<<< "CID is taken" */
char* msg_inf_error_pid_missing; /*<<< "PID is not specified" */
char* msg_inf_error_pid_invalid; /*<<< "PID is invalid" */
char* msg_ban_permanently; /*<<< "Banned permanently" */
char* msg_ban_temporarily; /*<<< "Banned temporarily" */
char* msg_auth_invalid_password; /*<<< "Password is wrong" */
char* msg_auth_user_not_found; /*<<< "User not found in password database" */
char* msg_error_no_memory; /*<<< "No memory" */
char* msg_user_share_size_low; /*<<< "User is not sharing enough" */
char* msg_user_share_size_high; /*<<< "User is sharing too much" */
char* msg_user_slots_low; /*<<< "User have too few upload slots." */
char* msg_user_slots_high; /*<<< "User have too many upload slots." */
char* msg_user_hub_limit_low; /*<<< "User is on too few hubs." */
char* msg_user_hub_limit_high; /*<<< "User is on too many hubs." */
char* msg_user_flood_chat; /*<<< "Chat flood detected, messages are dropped." */
char* msg_user_flood_connect; /*<<< "Connect flood detected, connection refused." */
char* msg_user_flood_search; /*<<< "Search flood detected, search is stopped." */
char* msg_user_flood_update; /*<<< "Update flood detected." */
char* msg_user_flood_extras; /*<<< "Flood detected." */
char* msg_proto_no_common_hash; /*<<< "No common hash algorithm." */
char* msg_proto_obsolete_adc0; /*<<< "Client is using an obsolete ADC protocol version." */
};

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +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"
#include "plugin_api/handle.h"
/* Notify plugins, etc */
void on_login_success(struct hub_info* hub, struct hub_user* u)
{
/* Send user list of all existing users */
if (!uman_send_user_list(hub, hub->users, u))
return;
/* Mark as being in the normal state, and add user to the user list */
user_set_state(u, state_normal);
uman_add(hub->users, u);
/* Announce new user to all connected users */
if (user_is_logged_in(u))
route_info_message(hub, u);
plugin_log_user_login_success(hub, u);
/* reset timeout */
net_con_clear_timeout(u->connection);
}
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
{
plugin_log_user_login_error(hub, u, hub_get_status_message_log(hub, msg));
hub_send_status(hub, u, msg, status_level_fatal);
hub_disconnect_user(hub, u, quit_logon_error);
}
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
{
plugin_log_user_update_error(hub, u, hub_get_status_message_log(hub, msg));
hub_send_status(hub, u, msg, status_level_fatal);
hub_disconnect_user(hub, u, quit_update_error);
}
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
{
if (user_is_logged_in(u))
{
plugin_log_user_nick_change(hub, u, nick);
}
}
void on_logout_user(struct hub_info* hub, struct hub_user* user)
{
const char* reason = user_get_quit_reason_string(user->quit_reason);
plugin_log_user_logout(hub, user, reason);
hub_logout_log(hub, user);
}

View File

@ -1,172 +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"
#ifdef DEBUG_SENDQ
static void debug_msg(const char* prefix, struct adc_message* msg)
{
size_t n;
char* buf = strdup(msg->cache);
for (n = 0; n < msg->length; n++)
{
if (buf[n] == '\r' || buf[n] == '\n')
buf[n] = '_';
}
LOG_TRACE("%s: [%s] (%d bytes)", prefix, buf, (int) msg->length);
free(buf);
}
#endif
struct ioq_recv* ioq_recv_create()
{
struct ioq_recv* q = hub_malloc_zero(sizeof(struct ioq_recv));
return q;
}
void ioq_recv_destroy(struct ioq_recv* q)
{
if (q)
{
hub_free(q->buf);
hub_free(q);
}
}
size_t ioq_recv_get(struct ioq_recv* q, void* buf, size_t bufsize)
{
uhub_assert(bufsize >= q->size);
if (q->size)
{
size_t n = q->size;
memcpy(buf, q->buf, n);
hub_free(q->buf);
q->buf = 0;
q->size = 0;
return n;
}
return 0;
}
size_t ioq_recv_set(struct ioq_recv* q, void* buf, size_t bufsize)
{
if (q->buf)
{
hub_free(q->buf);
q->buf = 0;
q->size = 0;
}
if (!bufsize)
{
return 0;
}
q->buf = hub_malloc(bufsize);
if (!q->buf)
return 0;
q->size = bufsize;
memcpy(q->buf, buf, bufsize);
return bufsize;
}
struct ioq_send* ioq_send_create()
{
struct ioq_send* q = hub_malloc_zero(sizeof(struct ioq_send));
if (!q)
return 0;
q->queue = list_create();
if (!q->queue)
{
hub_free(q);
return 0;
}
return q;
}
static void clear_send_queue_callback(void* ptr)
{
adc_msg_free((struct adc_message*) ptr);
}
void ioq_send_destroy(struct ioq_send* q)
{
if (q)
{
list_clear(q->queue, &clear_send_queue_callback);
list_destroy(q->queue);
hub_free(q);
}
}
void ioq_send_add(struct ioq_send* q, struct adc_message* msg_)
{
struct adc_message* msg = adc_msg_incref(msg_);
#ifdef DEBUG_SENDQ
debug_msg("ioq_send_add", msg);
#endif
uhub_assert(msg->cache && *msg->cache);
list_append(q->queue, msg);
q->size += msg->length;
}
static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
debug_msg("ioq_send_remove", msg);
#endif
list_remove(q->queue, msg);
q->size -= msg->length;
adc_msg_free(msg);
q->offset = 0;
}
int ioq_send_send(struct ioq_send* q, struct net_connection* con)
{
int ret;
struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0;
uhub_assert(msg->cache && *msg->cache);
ret = net_con_send(con, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0)
{
q->offset += ret;
if (msg->length - q->offset > 0)
return 0;
ioq_send_remove(q, msg);
return 1;
}
return ret;
}
int ioq_send_is_empty(struct ioq_send* q)
{
return (q->size - q->offset) == 0;
}
size_t ioq_send_get_bytes(struct ioq_send* q)
{
return q->size - q->offset;
}

View File

@ -1,106 +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_IO_QUEUE_H
#define HAVE_UHUB_IO_QUEUE_H
struct adc_message;
struct linked_list;
typedef int (*ioq_write)(void* desc, const void* buf, size_t len);
typedef int (*ioq_read)(void* desc, void* buf, size_t len);
struct ioq_send
{
size_t size; /** Size of send queue (in bytes, not messages) */
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
#ifdef SSL_SUPPORT
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
#endif
struct linked_list* queue; /** List of queued messages (struct adc_message) */
};
struct ioq_recv
{
char* buf;
size_t size;
};
/**
* Create a send queue
*/
extern struct ioq_send* ioq_send_create();
/**
* Destroy a send queue, and delete any queued messages.
*/
extern void ioq_send_destroy(struct ioq_send*);
/**
* Add a message to the send queue.
*/
extern void ioq_send_add(struct ioq_send*, struct adc_message* msg);
/**
* Process the send queue, and send as many messages as possible.
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
*/
extern int ioq_send_send(struct ioq_send*, struct net_connection* con);
/**
* @returns 1 if send queue is empty, 0 otherwise.
*/
extern int ioq_send_is_empty(struct ioq_send*);
/**
* @returns the number of bytes remaining to be sent in the queue.
*/
extern size_t ioq_send_get_bytes(struct ioq_send*);
/**
* Create a receive queue.
*/
extern struct ioq_recv* ioq_recv_create();
/**
* Destroy a receive queue.
*/
extern void ioq_recv_destroy(struct ioq_recv*);
/**
* Gets the buffer, copies it into buf and deallocates it.
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
* @return the number of bytes copied into buf.
*/
extern size_t ioq_recv_get(struct ioq_recv*, void* buf, size_t bufsize);
/**
* Sets the buffer
*/
extern size_t ioq_recv_set(struct ioq_recv*, void* buf, size_t bufsize);
/**
* @return 1 if size is zero, 0 otherwise.
*/
extern int ioq_recv_is_empty(struct ioq_recv* buf);
#endif /* HAVE_UHUB_IO_QUEUE_H */

View File

@ -1,223 +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>
#include "ioqueue.h"
#include "probe.h"
int handle_net_read(struct hub_user* user)
{
static char buf[MAX_RECV_BUF];
struct ioq_recv* q = user->recv_queue;
size_t buf_size = ioq_recv_get(q, buf, MAX_RECV_BUF);
ssize_t size;
if (user_flag_get(user, flag_maxbuf))
buf_size = 0;
size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size);
if (size > 0)
buf_size += size;
if (size < 0)
{
if (size == -1)
return quit_disconnected;
else
return quit_socket_error;
}
else if (size == 0)
{
return 0;
}
else
{
char* lastPos = 0;
char* start = buf;
char* pos = 0;
size_t remaining = buf_size;
while ((pos = memchr(start, '\n', remaining)))
{
lastPos = pos+1;
pos[0] = '\0';
#ifdef DEBUG_SENDQ
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
#endif
if (user_flag_get(user, flag_maxbuf))
{
user_flag_unset(user, flag_maxbuf);
}
else
{
if (((pos - start) > 0) && user->hub->config->max_recv_buffer > (pos - start))
{
if (hub_handle_message(user->hub, user, start, (pos - start)) == -1)
{
return quit_protocol_error;
}
}
}
pos[0] = '\n'; /* FIXME: not needed */
pos ++;
remaining -= (pos - start);
start = pos;
}
if (lastPos || remaining)
{
if (remaining < (size_t) user->hub->config->max_recv_buffer)
{
ioq_recv_set(q, lastPos ? lastPos : buf, remaining);
}
else
{
ioq_recv_set(q, 0, 0);
user_flag_set(user, flag_maxbuf);
LOG_WARN("Received message past max_recv_buffer, dropping message.");
}
}
else
{
ioq_recv_set(q, 0, 0);
}
}
return 0;
}
int handle_net_write(struct hub_user* user)
{
int ret = 0;
while (ioq_send_get_bytes(user->send_queue))
{
ret = ioq_send_send(user->send_queue, user->connection);
if (ret <= 0)
break;
}
if (ret < 0)
return quit_socket_error;
if (ioq_send_get_bytes(user->send_queue))
{
user_net_io_want_write(user);
}
else
{
user_net_io_want_read(user);
}
return 0;
}
void net_event(struct net_connection* con, int event, void *arg)
{
struct hub_user* user = (struct hub_user*) arg;
int flag_close = 0;
#ifdef DEBUG_SENDQ
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
#endif
if (event == NET_EVENT_ERROR)
{
hub_disconnect_user(user->hub, user, quit_socket_error);
return;
}
if (event == NET_EVENT_TIMEOUT)
{
if (user_is_connecting(user))
{
hub_disconnect_user(user->hub, user, quit_timeout);
}
return;
}
if (event & NET_EVENT_READ)
{
flag_close = handle_net_read(user);
if (flag_close)
{
hub_disconnect_user(user->hub, user, flag_close);
return;
}
}
if (event & NET_EVENT_WRITE)
{
flag_close = handle_net_write(user);
if (flag_close)
{
hub_disconnect_user(user->hub, user, flag_close);
return;
}
}
}
void net_on_accept(struct net_connection* con, int event, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
struct hub_probe* probe = 0;
struct ip_addr_encap ipaddr;
int server_fd = net_con_get_sd(con);
plugin_st status;
for (;;)
{
int fd = net_accept(server_fd, &ipaddr);
if (fd == -1)
{
#ifdef WINSOCK
if (net_error() == WSAEWOULDBLOCK)
#else
if (net_error() == EWOULDBLOCK)
#endif
{
break;
}
else
{
LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error()));
break;
}
}
status = plugin_check_ip_early(hub, &ipaddr);
if (status == st_deny)
{
plugin_log_connection_denied(hub, &ipaddr);
net_close(fd);
continue;
}
plugin_log_connection_accepted(hub, &ipaddr);
probe = probe_create(hub, fd, &ipaddr);
if (!probe)
{
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
net_close(fd);
break;
}
}
}

View File

@ -1,242 +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"
#include "plugin_api/command_api.h"
struct plugin_callback_data
{
struct linked_list* commands;
};
static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin)
{
return get_internals(plugin)->callback_data;
}
static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct plugin_handle* plugin = (struct plugin_handle*) cmd->ptr;
struct plugin_callback_data* data = get_callback_data(plugin);
struct plugin_command_handle* cmdh;
struct plugin_user* puser = (struct plugin_user*) user; // FIXME: Use a proper conversion function instead.
struct plugin_command* pcommand = (struct plugin_command*) cmd; // FIXME: Use a proper conversion function instead.
LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix);
LIST_FOREACH(struct plugin_command_handle*, cmdh, data->commands,
{
if (strcmp(cmdh->prefix, cmd->prefix) == 0)
return cmdh->handler(plugin, puser, pcommand);
});
return 0;
}
static struct hub_user* convert_user_type(struct plugin_user* user)
{
struct hub_user* huser = (struct hub_user*) user;
return huser;
}
static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, 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_user(plugin_get_hub(plugin), convert_user_type(user), command);
adc_msg_free(command);
hub_free(buffer);
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)
{
char code_str[4];
char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10);
snprintf(code_str, sizeof(code_str), "%03d", code);
adc_msg_add_argument(command, code_str);
adc_msg_add_argument(command, buffer);
route_to_user(plugin_get_hub(plugin), convert_user_type(user), command);
adc_msg_free(command);
hub_free(buffer);
return 1;
}
static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user)
{
hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked);
return 0;
}
static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_command_handle* cmdh)
{
struct plugin_callback_data* data = get_callback_data(plugin);
struct command_handle* command = (struct command_handle*) hub_malloc_zero(sizeof(struct command_handle));
command->prefix = cmdh->prefix;
command->length = cmdh->length;
command->args = cmdh->args;
command->cred = cmdh->cred;
command->description = cmdh->description;
command->origin = cmdh->origin;
command->handler = plugin_command_dispatch;
cmdh->internal_handle = command;
list_append(data->commands, cmdh);
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
return 0;
}
static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_command_handle* cmdh)
{
struct plugin_callback_data* data = get_callback_data(plugin);
struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
list_remove(data->commands, cmdh);
command_del(plugin_get_hub(plugin)->commands, command);
hub_free(command);
cmdh->internal_handle = NULL;
return 0;
}
size_t cbfunc_command_arg_reset(struct plugin_handle* plugin, struct plugin_command* cmd)
{
// TODO: Use proper function for rewriting for plugin_command -> hub_command
return hub_command_arg_reset((struct hub_command*) cmd);
}
struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* plugin, struct plugin_command* cmd, enum plugin_command_arg_type t)
{
// TODO: Use proper function for rewriting for plugin_command -> hub_command
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)
{
struct hub_info* hub = plugin_get_hub(plugin);
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_NICK);
char* str = adc_msg_unescape(str_encoded);
hub_free(str_encoded);
return str;
}
static char* cbfunc_get_hub_description(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION);
char* str = adc_msg_unescape(str_encoded);
hub_free(str_encoded);
return str;
}
static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str)
{
struct hub_info* hub = plugin_get_hub(plugin);
struct adc_message* command;
char* new_str = adc_msg_escape(str ? str : hub->config->hub_name);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str);
// Broadcast hub name
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str);
route_to_all(hub, command);
adc_msg_free(command);
hub_free(new_str);
}
static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char* str)
{
struct hub_info* hub = plugin_get_hub(plugin);
struct adc_message* command;
char* new_str = adc_msg_escape(str ? str : hub->config->hub_description);
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str);
// Broadcast hub description
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str);
route_to_all(hub, command);
adc_msg_free(command);
hub_free(new_str);
}
void plugin_register_callback_functions(struct plugin_handle* handle)
{
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.user_disconnect = cbfunc_user_disconnect;
handle->hub.command_add = cbfunc_command_add;
handle->hub.command_del = cbfunc_command_del;
handle->hub.command_arg_reset = cbfunc_command_arg_reset;
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.set_name = cbfunc_set_hub_name;
handle->hub.get_description = cbfunc_get_hub_description;
handle->hub.set_description = cbfunc_set_hub_description;
}
void plugin_unregister_callback_functions(struct plugin_handle* handle)
{
}
struct plugin_callback_data* plugin_callback_data_create()
{
struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data));
LOG_PLUGIN("plugin_callback_data_create()");
data->commands = list_create();
return data;
}
void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data)
{
LOG_PLUGIN("plugin_callback_data_destroy()");
if (data->commands)
{
// delete commands not deleted by the plugin itself:
struct plugin_command_handle* cmd;
while ( (cmd = list_get_first(data->commands)) )
cbfunc_command_del(plugin, cmd);
list_destroy(data->commands);
}
hub_free(data);
}

View File

@ -1,32 +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_PLUGIN_CALLBACK_H
#define HAVE_UHUB_PLUGIN_CALLBACK_H
struct plugin_handle;
struct uhub_plugin;
extern struct plugin_callback_data* plugin_callback_data_create();
extern void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data);
extern void plugin_register_callback_functions(struct plugin_handle* plugin);
extern void plugin_unregister_callback_functions(struct plugin_handle* plugin);
#endif /* HAVE_UHUB_PLUGIN_CALLBACK_H */

View File

@ -1,197 +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"
#include "plugin_api/handle.h"
#define PLUGIN_DEBUG(hub, name) LOG_PLUGIN("Invoke %s on %d plugins", name, (int) (hub->plugins ? list_size(hub->plugins->loaded) : -1));
#define INVOKE(HUB, FUNCNAME, CODE) \
PLUGIN_DEBUG(HUB, # FUNCNAME) \
if (HUB->plugins && HUB->plugins->loaded) \
{ \
struct plugin_handle* plugin;\
LIST_FOREACH(struct plugin_handle*, plugin, HUB->plugins->loaded, \
{ \
if (plugin->funcs.FUNCNAME) \
CODE \
}); \
}
#define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \
do { \
plugin_st status = st_default; \
INVOKE(HUB, FUNCNAME, { \
status = plugin->funcs.FUNCNAME(plugin, ARG1); \
if (status != st_default) \
break; \
}); \
return status; \
} while(0)
#define PLUGIN_INVOKE_STATUS_2(HUB, FUNCNAME, ARG1, ARG2) \
do { \
plugin_st status = st_default; \
INVOKE(HUB, FUNCNAME, { \
status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); \
if (status != st_default) \
break; \
}); \
return status; \
} while(0)
#define PLUGIN_INVOKE_STATUS_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) \
do { \
plugin_st status = st_default; \
INVOKE(HUB, FUNCNAME, { \
status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); \
if (status != st_default) \
break; \
}); \
return status; \
} while(0)
#define PLUGIN_INVOKE_1(HUB, FUNCNAME, ARG1) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1); })
#define PLUGIN_INVOKE_2(HUB, FUNCNAME, ARG1, ARG2) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); })
#define PLUGIN_INVOKE_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); })
static struct plugin_user* convert_user_type(struct hub_user* user)
{
struct plugin_user* puser = (struct plugin_user*) user;
return puser;
}
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr)
{
PLUGIN_INVOKE_STATUS_1(hub, on_check_ip_early, addr);
}
plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* who, struct ip_addr_encap* addr)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_STATUS_2(hub, on_check_ip_late, user, addr);
}
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)
{
PLUGIN_INVOKE_1(hub, on_connection_accepted, ipaddr);
}
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr)
{
PLUGIN_INVOKE_1(hub, on_connection_refused, ipaddr);
}
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* who)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_1(hub, on_user_login, user);
}
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* who, const char* reason)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_2(hub, on_user_login_error, user, reason);
}
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* who, const char* reason)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_2(hub, on_user_logout, user, reason);
}
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* who, const char* new_nick)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_2(hub, on_user_nick_change, user, new_nick);
}
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* who, const char* reason)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_2(hub, on_user_update_error, user, reason);
}
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* who, const char* message, int flags)
{
struct plugin_user* user = convert_user_type(who);
PLUGIN_INVOKE_3(hub, on_user_chat_message, user, message, flags);
}
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags)
{
struct plugin_user* user = convert_user_type(from);
PLUGIN_INVOKE_STATUS_2(hub, on_chat_msg, user, message);
}
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags)
{
struct plugin_user* user1 = convert_user_type(from);
struct plugin_user* user2 = convert_user_type(to);
PLUGIN_INVOKE_STATUS_3(hub, on_private_msg, user1, user2, message);
}
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* from, const char* data)
{
struct plugin_user* user = convert_user_type(from);
PLUGIN_INVOKE_STATUS_2(hub, on_search, user, data);
}
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data)
{
struct plugin_user* user1 = convert_user_type(from);
struct plugin_user* user2 = convert_user_type(to);
PLUGIN_INVOKE_STATUS_3(hub, on_search_result, user1, user2, data);
}
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
{
struct plugin_user* user1 = convert_user_type(from);
struct plugin_user* user2 = convert_user_type(to);
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_connect, user1, user2);
}
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
{
struct plugin_user* user1 = convert_user_type(from);
struct plugin_user* user2 = convert_user_type(to);
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_revconnect, user1, user2);
}
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info)
{
PLUGIN_INVOKE_STATUS_2(hub, auth_get_user, nickname, info);
}
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* info)
{
PLUGIN_INVOKE_STATUS_1(hub, auth_register_user, info);
}
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* info)
{
PLUGIN_INVOKE_STATUS_1(hub, auth_update_user, info);
}
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* info)
{
PLUGIN_INVOKE_STATUS_1(hub, auth_delete_user, info);
}

View File

@ -1,66 +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_PLUGIN_INVOKE_H
#define HAVE_UHUB_PLUGIN_INVOKE_H
#include "uhub.h"
#include "plugin_api/handle.h"
struct hub_info;
struct ip_addr_encap;
/* All log related functions */
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr);
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr);
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user);
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user, const char* reason);
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user, const char* reason);
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* user, const char* new_nick);
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* user, const char* reason);
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
/* IP ban related */
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* user, struct ip_addr_encap* addr);
/* Nickname allow/deny handling */
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);
plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick);
/* Handle chat messages */
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags);
/* Handle searches */
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* user, const char* data);
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data);
/* Handle p2p connections */
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
/* Authentication related */
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info);
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* user);
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* user);
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* user);
#endif // HAVE_UHUB_PLUGIN_INVOKE_H

View File

@ -1,251 +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"
#include "plugin_api/handle.h"
struct plugin_callback_data;
struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
{
struct plugin_hub_internals* internals;
uhub_assert(handle && handle->handle && handle->handle->internals);
internals = (struct plugin_hub_internals*) handle->handle->internals;
return internals;
}
struct uhub_plugin* plugin_open(const char* filename)
{
struct uhub_plugin* plugin;
LOG_PLUGIN("plugin_open: \"%s\"", filename);
plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin));
if (!plugin)
{
return 0;
}
#ifdef HAVE_DLOPEN
plugin->handle = dlopen(filename, RTLD_LAZY);
#else
plugin->handle = LoadLibraryExA(filename, NULL, 0);
#endif
if (!plugin->handle)
{
#ifdef HAVE_DLOPEN
LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror());
#else
LOG_ERROR("Unable to open plugin %s: %d", filename, GetLastError());
#endif
hub_free(plugin);
return 0;
}
plugin->filename = strdup(filename);
plugin->internals = hub_malloc_zero(sizeof(struct plugin_hub_internals));
return plugin;
}
void plugin_close(struct uhub_plugin* plugin)
{
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename);
plugin_callback_data_destroy(plugin->handle, internals->callback_data);
hub_free(internals);
plugin->internals = NULL;
#ifdef HAVE_DLOPEN
dlclose(plugin->handle);
#else
FreeLibrary((HMODULE) plugin->handle);
#endif
hub_free(plugin->filename);
hub_free(plugin);
}
void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
{
#ifdef HAVE_DLOPEN
void* addr = dlsym(plugin->handle, symbol);
return addr;
#else
FARPROC addr = GetProcAddress((HMODULE) plugin->handle, symbol);
return (void*) addr;
#endif
}
struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub)
{
plugin_register_f register_f;
plugin_unregister_f unregister_f;
int ret;
struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle));
struct uhub_plugin* plugin = plugin_open(filename);
if (!plugin)
return NULL;
if (!handle)
{
plugin_close(plugin);
return NULL;
}
handle->handle = plugin;
register_f = plugin_lookup_symbol(plugin, "plugin_register");
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
// register hub internals
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
internals->unregister = unregister_f;
internals->hub = hub;
internals->callback_data = plugin_callback_data_create();
// setup callback functions, where the plugin can contact the hub.
plugin_register_callback_functions(handle);
if (register_f && unregister_f)
{
ret = register_f(handle, config);
if (ret == 0)
{
if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs))
{
LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version);
LOG_PLUGIN("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size);
return handle;
}
else
{
LOG_ERROR("Unable to load plugin: %s - API version mistmatch", filename);
}
}
else
{
LOG_ERROR("Unable to load plugin: %s - Failed to initialize: %s", filename, handle->error_msg);
}
}
plugin_close(plugin);
hub_free(handle);
return NULL;
}
void plugin_unload(struct plugin_handle* plugin)
{
struct plugin_hub_internals* internals = get_internals(plugin);
internals->unregister(plugin);
plugin_unregister_callback_functions(plugin);
plugin_close(plugin->handle);
hub_free(plugin);
}
static int plugin_parse_line(char* line, int line_count, void* ptr_data)
{
struct hub_info* hub = (struct hub_info*) ptr_data;
struct uhub_plugins* handle = hub->plugins;
struct cfg_tokens* tokens = cfg_tokenize(line);
struct plugin_handle* plugin;
char *directive, *soname, *params;
if (cfg_token_count(tokens) == 0)
{
cfg_tokens_free(tokens);
return 0;
}
if (cfg_token_count(tokens) < 2)
{
cfg_tokens_free(tokens);
return -1;
}
directive = cfg_token_get_first(tokens);
soname = cfg_token_get_next(tokens);
params = cfg_token_get_next(tokens);
if (strcmp(directive, "plugin") == 0 && soname && *soname)
{
if (!params)
params = "";
LOG_PLUGIN("Load plugin: \"%s\", params=\"%s\"", soname, params);
plugin = plugin_load(soname, params, hub);
if (plugin)
{
list_append(handle->loaded, plugin);
cfg_tokens_free(tokens);
return 0;
}
}
cfg_tokens_free(tokens);
return -1;
}
int plugin_initialize(struct hub_config* config, struct hub_info* hub)
{
int ret;
hub->plugins->loaded = list_create();
if (!hub->plugins->loaded)
return -1;
if (config)
{
if (!*config->file_plugins)
return 0;
ret = file_read_lines(config->file_plugins, hub, &plugin_parse_line);
if (ret == -1)
{
list_clear(hub->plugins->loaded, hub_free);
list_destroy(hub->plugins->loaded);
hub->plugins->loaded = 0;
return -1;
}
}
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)
{
list_clear(handle->loaded, plugin_unload_ptr);
list_destroy(handle->loaded);
}
// Used internally only
struct hub_info* plugin_get_hub(struct plugin_handle* plugin)
{
struct plugin_hub_internals* data = get_internals(plugin);
return data->hub;
}

View File

@ -1,67 +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_PLUGIN_LOADER_H
#define HAVE_UHUB_PLUGIN_LOADER_H
#include "plugin_api/handle.h"
struct hub_config;
struct hub_info;
struct linked_list;
struct plugin_handle;
struct uhub_plugin
{
void* handle;
plugin_unregister_f unregister;
char* filename;
void* internals; // Hub-internal stuff (struct plugin_hub_internals)
};
struct uhub_plugins
{
struct linked_list* loaded;
};
// High level plugin loader code
extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub);
extern void plugin_unload(struct plugin_handle* plugin);
// extern void plugin_unload(struct plugin_handle*);
extern int plugin_initialize(struct hub_config* config, struct hub_info* hub);
extern void plugin_shutdown(struct uhub_plugins* handle);
// Low level plugin loader code (used internally)
extern struct uhub_plugin* plugin_open(const char* filename);
extern void plugin_close(struct uhub_plugin*);
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
// Used internally only
struct plugin_hub_internals
{
struct hub_info* hub;
plugin_unregister_f unregister; /* The unregister function. */
struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */
};
extern struct plugin_hub_internals* get_internals(struct plugin_handle*);
extern struct hub_info* plugin_get_hub(struct plugin_handle*);
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */

View File

@ -1,145 +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"
#include "probe.h"
#define PROBE_RECV_SIZE 12
static char probe_recvbuf[PROBE_RECV_SIZE];
static void probe_net_event(struct net_connection* con, int events, void *arg)
{
struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
if (events == NET_EVENT_TIMEOUT)
{
probe_destroy(probe);
return;
}
if (events & NET_EVENT_READ)
{
int bytes = net_con_peek(con, probe_recvbuf, PROBE_RECV_SIZE);
if (bytes < 0)
{
probe_destroy(probe);
return;
}
if (bytes >= 4)
{
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
{
LOG_TRACE("Probed ADC");
#ifdef SSL_SUPPORT
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
{
LOG_TRACE("Not TLS connection - closing connection.");
if (*probe->hub->config->tls_require_redirect_addr)
{
char buf[512];
ssize_t len = snprintf(buf, sizeof(buf), "ISUP " ADC_PROTO_SUPPORT "\nISID AAAB\nIINF NIRedirecting...\nIQUI AAAB RD%s\n", probe->hub->config->tls_require_redirect_addr);
net_con_send(con, buf, (size_t) len);
LOG_TRACE("Not TLS connection - Redirecting to %s.", probe->hub->config->tls_require_redirect_addr);
}
else
{
LOG_TRACE("Not TLS connection - closing connection.");
}
}
else
#endif
if (user_create(probe->hub, probe->connection, &probe->addr))
{
probe->connection = 0;
}
probe_destroy(probe);
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
else if (bytes >= 11 &&
probe_recvbuf[0] == 22 &&
probe_recvbuf[1] == 3 && /* protocol major version */
probe_recvbuf[5] == 1 && /* message type */
probe_recvbuf[9] == probe_recvbuf[1])
{
if (probe->hub->config->tls_enable)
{
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)
{
LOG_TRACE("TLS handshake negotiation failed.");
}
else if (user_create(probe->hub, probe->connection, &probe->addr))
{
probe->connection = 0;
}
}
else
{
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[9], (int) probe_recvbuf[10]);
}
}
else
{
LOG_TRACE("Probed unsupported protocol: %x%x%x%x.", (int) probe_recvbuf[0], (int) probe_recvbuf[1], (int) probe_recvbuf[2], (int) probe_recvbuf[3]);
}
#endif
probe_destroy(probe);
return;
}
}
}
struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr)
{
struct hub_probe* probe = (struct hub_probe*) hub_malloc_zero(sizeof(struct hub_probe));
if (probe == NULL)
return NULL; /* OOM */
LOG_TRACE("probe_create(): %p", probe);
probe->hub = hub;
probe->connection = net_con_create();
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
net_con_set_timeout(probe->connection, TIMEOUT_CONNECTED);
memcpy(&probe->addr, addr, sizeof(struct ip_addr_encap));
return probe;
}
void probe_destroy(struct hub_probe* probe)
{
LOG_TRACE("probe_destroy(): %p (connection=%p)", probe, probe->connection);
if (probe->connection)
{
net_con_close(probe->connection);
probe->connection = 0;
}
hub_free(probe);
}

View File

@ -1,35 +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_PROBE_H
#define HAVE_UHUB_PROBE_H
#include "uhub.h"
struct hub_probe
{
struct hub_info* hub; /** The hub instance this probe belong to */
struct net_connection* connection; /** Connection data */
struct ip_addr_encap addr; /** IP address */
};
extern struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr);
extern void probe_destroy(struct hub_probe* probe);
#endif /* HAVE_UHUB_PROBE_H */

View File

@ -1,220 +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"
int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg)
{
struct hub_user* target = NULL;
switch (msg->cache[0])
{
case 'B': /* Broadcast to all logged in clients */
route_to_all(hub, msg);
break;
case 'D':
target = uman_get_user_by_sid(hub->users, msg->target);
if (target)
{
route_to_user(hub, target, msg);
}
break;
case 'E':
target = uman_get_user_by_sid(hub->users, msg->target);
if (target)
{
route_to_user(hub, target, msg);
route_to_user(hub, u, msg);
}
break;
case 'F':
route_to_subscribers(hub, msg);
break;
default:
/* Ignore the message */
break;
}
return 0;
}
static size_t get_max_send_queue(struct hub_info* hub)
{
/* TODO: More dynamic send queue limit, for instance:
* return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
*/
return hub->config->max_send_buffer;
}
static size_t get_max_send_queue_soft(struct hub_info* hub)
{
return hub->config->max_send_buffer_soft;
}
/*
* @return 1 if send queue is OK.
* -1 if send queue is overflowed
* 0 if soft send queue is overflowed (not implemented at the moment)
*/
static int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
{
if (user_flag_get(user, flag_user_list))
return 1;
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.");
return -1;
}
if (user->send_queue->size > get_max_send_queue_soft(hub))
{
user_flag_set(user, flag_choke);
LOG_WARN("send queue soft overflowed.");
return 0;
}
user_flag_unset(user, flag_choke);
return 1;
}
int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
char* data = strndup(msg->cache, msg->length-1);
LOG_PROTO("send %s: \"%s\"", sid_to_string(user->id.sid), data);
free(data);
#endif
if (!user->connection)
return 0;
uhub_assert(msg->cache && *msg->cache);
if (ioq_send_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
{
/* Perform oportunistic write */
ioq_send_add(user->send_queue, msg);
handle_net_write(user);
}
else
{
if (check_send_queue(hub, user, msg) >= 0)
{
ioq_send_add(user->send_queue, msg);
if (!user_flag_get(user, flag_pipeline))
user_net_io_want_write(user);
}
}
return 1;
}
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
{
if (ioq_send_is_empty(u->send_queue))
return 0;
handle_net_write(u);
user_flag_unset(u, flag_pipeline);
return 1;
}
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
struct hub_user* user;
LIST_FOREACH(struct hub_user*, user, hub->users->list,
{
route_to_user(hub, user, command);
});
return 0;
}
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
int do_send;
char* tmp;
struct hub_user* user;
LIST_FOREACH(struct hub_user*, user, hub->users->list,
{
if (user->feature_cast)
{
do_send = 1;
LIST_FOREACH(char*, tmp, command->feature_cast_include,
{
if (!user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
});
if (!do_send)
continue;
LIST_FOREACH(char*, tmp, command->feature_cast_exclude,
{
if (user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
});
if (do_send)
route_to_user(hub, user, command);
}
});
return 0;
}
int route_info_message(struct hub_info* hub, struct hub_user* u)
{
if (!user_is_nat_override(u))
{
return route_to_all(hub, u->info);
}
else
{
struct adc_message* cmd = adc_msg_copy(u->info);
const char* address = user_get_address(u);
struct hub_user* user = 0;
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
LIST_FOREACH(struct hub_user*, user, hub->users->list,
{
if (user_is_nat_override(user))
route_to_user(hub, user, cmd);
else
route_to_user(hub, user, u->info);
});
adc_msg_free(cmd);
}
return 0;
}

View File

@ -1,348 +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"
#ifdef DEBUG_SENDQ
static const char* user_log_str(struct hub_user* user)
{
static char buf[128];
if (user)
{
snprintf(buf, 128, "user={ %p, \"%s\", %s/%s}", user, user->id.nick, sid_to_string(user->id.sid), user->id.cid);
}
else
{
snprintf(buf, 128, "user={ %p }", user);
}
return buf;
}
#endif
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
{
struct hub_user* user = NULL;
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL)
return NULL; /* OOM */
user->send_queue = ioq_send_create();
user->recv_queue = ioq_recv_create();
user->connection = con;
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
user_set_state(user, state_protocol);
flood_control_reset(&user->flood_chat);
flood_control_reset(&user->flood_connect);
flood_control_reset(&user->flood_search);
flood_control_reset(&user->flood_update);
flood_control_reset(&user->flood_extras);
user->hub = hub;
return user;
}
void user_destroy(struct hub_user* user)
{
LOG_TRACE("user_destroy(), user=%p", user);
ioq_recv_destroy(user->recv_queue);
ioq_send_destroy(user->send_queue);
if (user->connection)
{
LOG_TRACE("user_destory() -> net_con_close(%p)", user->connection);
net_con_close(user->connection);
}
adc_msg_free(user->info);
user_clear_feature_cast_support(user);
hub_free(user);
}
void user_set_state(struct hub_user* user, enum user_state state)
{
if ((user->state == state_cleanup && state != state_disconnected) || (user->state == state_disconnected))
{
return;
}
user->state = state;
}
void user_set_info(struct hub_user* user, struct adc_message* cmd)
{
adc_msg_free(user->info);
if (cmd)
{
user->info = adc_msg_incref(cmd);
}
else
{
user->info = 0;
}
}
void user_update_info(struct hub_user* u, struct adc_message* cmd)
{
char prefix[2];
char* argument;
size_t n = 0;
struct adc_message* cmd_new = adc_msg_copy(u->info);
if (!cmd_new)
{
/* FIXME: OOM! */
return;
}
/*
* FIXME: Optimization potential:
*
* remove parts of cmd that do not really change anything in cmd_new.
* this can save bandwidth if clients send multiple updates for information
* that does not really change anything.
*/
argument = adc_msg_get_argument(cmd, n++);
while (argument)
{
if (strlen(argument) >= 2)
{
prefix[0] = argument[0];
prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
}
hub_free(argument);
argument = adc_msg_get_argument(cmd, n++);
}
user_set_info(u, cmd_new);
adc_msg_free(cmd_new);
}
static int convert_support_fourcc(int fourcc)
{
switch (fourcc)
{
case FOURCC('B','A','S','0'):
return feature_bas0;
case FOURCC('B','A','S','E'):
return feature_base;
case FOURCC('A','U','T','0'):
return feature_auto;
case FOURCC('U','C','M','0'):
case FOURCC('U','C','M','D'):
return feature_ucmd;
case FOURCC('Z','L','I','F'):
return feature_zlif;
case FOURCC('B','B','S','0'):
return feature_bbs;
case FOURCC('T','I','G','R'):
return feature_tiger;
case FOURCC('B','L','O','M'):
case FOURCC('B','L','O','0'):
return feature_bloom;
case FOURCC('P','I','N','G'):
return feature_ping;
case FOURCC('L','I','N','K'):
return feature_link;
case FOURCC('A','D','C','S'):
return feature_adcs;
// ignore these extensions, they are not useful for the hub.
case FOURCC('D','H','T','0'):
return 0;
default:
LOG_DEBUG("Unknown extension: %x", fourcc);
return 0;
}
}
void user_support_add(struct hub_user* user, int fourcc)
{
int feature_mask = convert_support_fourcc(fourcc);
user->flags |= feature_mask;
}
int user_flag_get(struct hub_user* user, enum user_flags flag)
{
return user->flags & flag;
}
void user_flag_set(struct hub_user* user, enum user_flags flag)
{
user->flags |= flag;
}
void user_flag_unset(struct hub_user* user, enum user_flags flag)
{
user->flags &= ~flag;
}
void user_set_nat_override(struct hub_user* user)
{
user_flag_set(user, flag_nat);
}
int user_is_nat_override(struct hub_user* user)
{
return user_flag_get(user, flag_nat);
}
void user_support_remove(struct hub_user* user, int fourcc)
{
int feature_mask = convert_support_fourcc(fourcc);
user->flags &= ~feature_mask;
}
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
{
char* tmp;
LIST_FOREACH(char*, tmp, user->feature_cast,
{
if (strncmp(tmp, feature, 4) == 0)
return 1;
});
return 0;
}
int user_set_feature_cast_support(struct hub_user* u, char feature[4])
{
if (!u->feature_cast)
{
u->feature_cast = list_create();
}
if (!u->feature_cast)
{
return 0; /* OOM! */
}
list_append(u->feature_cast, hub_strndup(feature, 4));
return 1;
}
void user_clear_feature_cast_support(struct hub_user* u)
{
if (u->feature_cast)
{
list_clear(u->feature_cast, &hub_free);
list_destroy(u->feature_cast);
u->feature_cast = 0;
}
}
int user_is_logged_in(struct hub_user* user)
{
if (user->state == state_normal)
return 1;
return 0;
}
int user_is_connecting(struct hub_user* user)
{
if (user->state == state_protocol || user->state == state_identify || user->state == state_verify)
return 1;
return 0;
}
int user_is_protocol_negotiating(struct hub_user* user)
{
if (user->state == state_protocol)
return 1;
return 0;
}
int user_is_disconnecting(struct hub_user* user)
{
if (user->state == state_cleanup || user->state == state_disconnected)
return 1;
return 0;
}
int user_is_protected(struct hub_user* user)
{
return auth_cred_is_protected(user->credentials);
}
/**
* Returns 1 if a user is registered.
* Only registered users will be let in if the hub is configured for registered
* users only.
*/
int user_is_registered(struct hub_user* user)
{
return auth_cred_is_registered(user->credentials);
}
void user_net_io_want_write(struct hub_user* user)
{
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
}
void user_net_io_want_read(struct hub_user* user)
{
net_con_update(user->connection, NET_EVENT_READ);
}
const char* user_get_quit_reason_string(enum user_quit_reason reason)
{
switch (reason)
{
case quit_unknown: return "unknown"; break;
case quit_disconnected: return "disconnected"; break;
case quit_kicked: return "kicked"; break;
case quit_banned: return "banned"; break;
case quit_timeout: return "timeout"; break;
case quit_send_queue: return "send queue"; break;
case quit_memory_error: return "out of memory"; break;
case quit_socket_error: return "socket error"; break;
case quit_protocol_error: return "protocol error"; break;
case quit_logon_error: return "login error"; break;
case quit_update_error: return "update error"; break;
case quit_hub_disabled: return "hub disabled"; break;
case quit_ghost_timeout: return "ghost"; break;
}
return "unknown";
}
const char* user_get_address(struct hub_user* user)
{
return ip_convert_to_string(&user->id.addr);
}

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