Compare commits

..

1 Commits

Author SHA1 Message Date
Jan Vidar Krey
714d110a94 Fix bug #185 - Args of !commands lost/damaged.
All string arguments were incorrectly freed after being added to the argument list for a command.
Instead this fix makes sure it is properly copied into a new string, and by doing so this requires
a new API for dealing with hub command arguments in a type safe manner, and also allows for each
argument to be cleaned up properly when the command is no longer needed.

This also fixes issues with parse errors for certain types, and optional arguments (previously it was impossible
to tell the difference for an integer with value 0 or if no integer was given).
2012-03-12 01:21:08 +01:00
126 changed files with 3176 additions and 7262 deletions

17
.gitignore vendored
View File

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

View File

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

8
BSDmakefile Normal file
View File

@@ -0,0 +1,8 @@
GMAKE=gmake
all:
@${GMAKE} ${.TARGETS}
${.TARGETS}: all

View File

@@ -1,212 +0,0 @@
##
## Makefile for uhub
## Copyright (C) 2007-2012, 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 4)
set (UHUB_VERSION_PATCH 1)
set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src")
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/Modules)
option(RELEASE "Release build, debug build if disabled" ON)
option(LINK_SUPPORT "Allow hub linking" 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)
if (SSL_SUPPORT)
if (USE_OPENSSL)
find_package(OpenSSL)
else()
find_package(GnuTLS)
endif()
if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND)
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS are not found!")
endif()
endif()
if (SYSTEMD_SUPPORT)
INCLUDE(FindPkgConfig)
pkg_search_module(SD_DAEMON REQUIRED libsystemd-daemon)
pkg_search_module(SD_JOURNAL REQUIRED libsystemd-journal)
endif()
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
include_directories("${PROJECT_SOURCE_DIR}")
include_directories(${SQLITE3_INCLUDE_DIRS})
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_COMPILER_IS_GNUCC)
set_target_properties(utils PROPERTIES COMPILE_FLAGS -fPIC)
set_target_properties(network PROPERTIES COMPILE_FLAGS -fPIC)
endif()
add_dependencies(adc utils)
add_dependencies(network utils)
add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} )
add_executable(test ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} )
add_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_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)
if(WIN32)
target_link_libraries(uhub ws2_32)
target_link_libraries(test ws2_32)
target_link_libraries(mod_logging ws2_32)
target_link_libraries(mod_welcome ws2_32)
endif()
set_target_properties(
mod_example
mod_welcome
mod_logging
mod_auth_simple
mod_auth_sqlite
mod_chat_history
mod_chat_only
mod_no_guest_downloads
mod_topic
PROPERTIES PREFIX "")
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils)
target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(mod_example utils)
target_link_libraries(mod_welcome utils)
target_link_libraries(mod_auth_simple utils)
target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils)
target_link_libraries(mod_chat_history utils)
target_link_libraries(mod_no_guest_downloads utils)
target_link_libraries(mod_chat_only utils)
target_link_libraries(mod_logging utils)
target_link_libraries(mod_topic utils)
target_link_libraries(utils network)
target_link_libraries(mod_welcome network)
target_link_libraries(mod_logging network)
if(UNIX)
add_library(adcclient STATIC ${adcclient_SOURCES})
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c)
target_link_libraries(uhub-admin adcclient adc network utils pthread)
target_link_libraries(uhub pthread)
target_link_libraries(test pthread)
if (ADC_STRESS)
add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES})
target_link_libraries(adcrush adcclient adc network utils pthread)
endif()
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(test ${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_DAEMON_LIBRARIES})
target_link_libraries(uhub ${SD_JOURNAL_LIBRARIES})
target_link_libraries(test ${SD_DAEMON_LIBRARIES})
target_link_libraries(test ${SD_JOURNAL_LIBRARIES})
target_link_libraries(uhub-passwd ${SD_JOURNAL_LIBRARIES})
target_link_libraries(uhub-admin ${SD_JOURNAL_LIBRARIES})
include_directories(${SD_DAEMON_INCLUDE_DIRS})
include_directories(${SD_JOURNAL_INCLUDE_DIRS})
add_definitions(-DSYSTEMD)
endif()
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")
mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
if (RELEASE)
set(CMAKE_BUILD_TYPE Release)
add_definitions(-DNDEBUG)
else()
set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG)
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_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.

View File

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

354
GNUmakefile Normal file
View File

@@ -0,0 +1,354 @@
##
## Makefile for uhub (Use GNU make)
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
#
-include Makefile.private
CC = gcc
LD := $(CC)
MV := mv
RANLIB := ranlib
CFLAGS += -pipe -Wall
USE_SSL ?= YES
USE_PLUGINS ?= YES
USE_BIGENDIAN ?= AUTO
BITS ?= AUTO
SILENT ?= YES
TERSE ?= NO
STACK_PROTECT ?= NO
NEED_LIBDL ?= NO
ifeq ($(OS), Windows_NT)
WINDOWS ?= YES
OPSYS ?= Windows
else
OPSYS ?= $(shell uname)
endif
ifeq ($(OPSYS),SunOS)
LDLIBS += -lsocket -lnsl
endif
ifeq ($(OPSYS),Haiku)
LDLIBS += -lnetwork
endif
ifeq ($(OPSYS),Linux)
NEED_LIBDL = YES
endif
CFLAGS += -I./src/
ifeq ($(OPSYS),Windows)
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
UHUB_MOD_DIR ?= $(DESTDIR)/var/lib/uhub
CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib
BIN_EXT ?=
endif
ifeq ($(SILENT),YES)
MSG_CC=@echo " CC:" $(notdir $<) &&
MSG_LD=@echo " LD:" $(notdir $@) &&
MSG_AR=@echo " AR:" $(notdir $@) &&
else
MSG_CC=
MSG_LD=
MSG_AR=
endif
ifeq ($(TERSE), YES)
MSG_CC=@
MSG_LD=@
MSG_AR=@
MSG_CLEAN=-n ""
else
MSG_CLEAN="Clean as a whistle"
endif
ifeq ($(RELEASE),YES)
CFLAGS += -O3 -DNDEBUG
else
CFLAGS += -ggdb -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
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 -lcrypto
endif
ifeq ($(NEED_LIBDL),YES)
LDLIBS += -ldl
endif
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
# Sources
libuhub_SOURCES := \
src/core/auth.c \
src/core/commands.c \
src/core/config.c \
src/core/eventqueue.c \
src/core/hub.c \
src/core/hubevent.c \
src/core/hubio.c \
src/core/inf.c \
src/core/netevent.c \
src/core/probe.c \
src/core/route.c \
src/core/user.c \
src/core/usermanager.c \
src/core/plugincallback.c \
src/core/plugininvoke.c \
src/core/pluginloader.c \
src/network/backend.c \
src/network/connection.c \
src/network/epoll.c \
src/network/kqueue.c \
src/network/select.c \
src/network/timeout.c \
src/network/timer.c
libadc_common_SOURCES := \
src/adc/message.c \
src/adc/sid.c
libutils_SOURCES := \
src/util/cbuffer.c \
src/util/config_token.c \
src/util/credentials.c \
src/util/floodctl.c \
src/util/ipcalc.c \
src/util/list.c \
src/util/log.c \
src/util/memory.c \
src/util/misc.c \
src/network/network.c \
src/util/rbtree.c \
src/util/tiger.c
libadc_client_SOURCES := \
src/tools/adcclient.c
uhub_SOURCES := src/core/main.c
uhub-passwd_SOURCES := src/tools/uhub-passwd.c
uhub-passwd_LIBS := -lsqlite3
adcrush_SOURCES := src/tools/adcrush.c
admin_SOURCES := src/tools/admin.c
autotest_SOURCES := \
autotest/test_commands.tcc \
autotest/test_credentials.tcc \
autotest/test_eventqueue.tcc \
autotest/test_hub.tcc \
autotest/test_inf.tcc \
autotest/test_ipfilter.tcc \
autotest/test_list.tcc \
autotest/test_memory.tcc \
autotest/test_message.tcc \
autotest/test_misc.tcc \
autotest/test_sid.tcc \
autotest/test_tiger.tcc \
autotest/test_timer.tcc \
autotest/test_tokenizer.tcc \
autotest/test_usermanager.tcc
autotest_OBJECTS = autotest.o
# Plugin targets:
plugin_example_SOURCES := src/plugins/mod_example.c
plugin_example_TARGET := mod_example.so
plugin_welcome_SOURCES := src/plugins/mod_welcome.c
plugin_welcome_TARGET := mod_welcome.so
plugin_logging_SOURCES := src/plugins/mod_logging.c
plugin_logging_TARGET := mod_logging.so
plugin_auth_SOURCES := src/plugins/mod_auth_simple.c
plugin_auth_TARGET := mod_auth_simple.so
plugin_auth_sqlite_SOURCES := src/plugins/mod_auth_sqlite.c
plugin_auth_sqlite_TARGET := mod_auth_sqlite.so
plugin_auth_sqlite_LIBS := -lsqlite3
plugin_chat_history_SOURCE := src/plugins/mod_chat_history.c
plugin_chat_history_TARGET := mod_chat_history.so
plugin_chat_only_SOURCE := src/plugins/mod_chat_only.c
plugin_chat_only_TARGET := mod_chat_only.so
# Source to objects
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
libutils_OBJECTS := $(libutils_SOURCES:.c=.o)
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
uhub-passwd_OBJECTS := $(uhub-passwd_SOURCES:.c=.o)
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
admin_OBJECTS := $(admin_SOURCES:.c=.o)
all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET) $(plugin_welcome_TARGET) $(plugin_chat_history_TARGET) $(plugin_chat_only_TARGET)
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
all_OBJECTS += $(all_plugins)
uhub_BINARY=uhub$(BIN_EXT)
uhub-passwd_BINARY=uhub-passwd$(BIN_EXT)
adcrush_BINARY=adcrush$(BIN_EXT)
admin_BINARY=uhub-admin$(BIN_EXT)
autotest_BINARY=autotest/test$(BIN_EXT)
.PHONY: revision.h.tmp all plugins
%.o: %.c version.h revision.h
$(MSG_CC) $(CC) -fPIC -c $(CFLAGS) -o $@ $<
#%.so: %.c
# $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
all: $(uhub_BINARY) $(uhub-passwd_BINARY) plugins
plugins: $(uhub_BINARY) $(all_plugins)
$(plugin_auth_TARGET): $(plugin_auth_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_auth_sqlite_TARGET): $(plugin_auth_sqlite_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(LDFLAGS) $(plugin_auth_sqlite_LIBS)
$(plugin_example_TARGET): $(plugin_example_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_logging_TARGET): $(plugin_logging_SOURCES) $(libutils_OBJECTS) $(libadc_common_OBJECTS) src/network/network.o
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_chat_history_TARGET): $(plugin_chat_history_SOURCE) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_chat_only_TARGET): $(plugin_chat_only_SOURCE) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(plugin_welcome_TARGET): $(plugin_welcome_SOURCES) $(libutils_OBJECTS)
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(uhub-passwd_BINARY): $(uhub-passwd_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(uhub-passwd_LIBS)
autotest.c: $(autotest_SOURCES)
$(shell exotic --standalone $(autotest_SOURCES) > $@)
revision.h.tmp:
@rm -f $@
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
version.h: revision.h
revision.h: revision.h.tmp
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
$(autotest_OBJECTS): autotest.c
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
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/
@cp $(uhub-passwd_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)/rules.txt ]; then cp doc/rules.txt $(UHUB_CONF_DIR); fi
@if [ ! -f $(UHUB_CONF_DIR)/plugins.conf ]; then cp doc/plugins.conf $(UHUB_CONF_DIR); fi
@if [ ! -d $(UHUB_MOD_DIR) ]; then echo Creating $(UHUB_MOD_DIR); mkdir -p $(UHUB_MOD_DIR); fi
@cp -f mod_*.so $(UHUB_MOD_DIR)
@touch $(UHUB_CONF_DIR)/motd.txt
@echo done.
endif
dist-clean:
@rm -rf $(all_OBJECTS) *~ core
clean:
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) $(all_plugins) autotest.c revision.h revision.h.tmp && \
echo $(MSG_CLEAN)

2
README
View File

@@ -4,5 +4,5 @@ For the official documentation, bugs and other information, please visit:
http://www.uhub.org/ http://www.uhub.org/
For a list of compatible ADC clients, see: For a list of compatible ADC clients, see:
http://en.wikipedia.org/wiki/Advanced_Direct_Connect#Client_software http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software

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,7 +1,6 @@
#include <uhub.h> #include <uhub.h>
static struct hub_info* hub = NULL; static struct hub_info* hub = NULL;
static struct hub_command* cmd = NULL;
static struct hub_user user; static struct hub_user user;
static struct command_base* cbase = NULL; static struct command_base* cbase = NULL;
static struct command_handle* c_test1 = NULL; static struct command_handle* c_test1 = NULL;
@@ -18,14 +17,11 @@ static int result = 0;
EXO_TEST(setup, { EXO_TEST(setup, {
hub = hub_malloc_zero(sizeof(struct hub_info)); hub = hub_malloc_zero(sizeof(struct hub_info));
cbase = command_initialize(hub); cbase = command_initialize(hub);
hub->commands = cbase; return cbase && hub && uman_init(hub) == 0;
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) static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
{ {
printf("test_handler\n");
result = 1; result = 1;
return 0; return 0;
} }
@@ -39,7 +35,7 @@ static struct command_handle* create_handler(const char* prefix, const char* arg
c->cred = cred; c->cred = cred;
c->handler = test_handler; c->handler = test_handler;
c->description = "A handler added by autotest."; c->description = "A handler added by autotest.";
c->origin = "exotic test"; c->description = "exotic";
c->ptr = &c->ptr; c->ptr = &c->ptr;
return c; return c;
} }
@@ -71,7 +67,7 @@ EXO_TEST(command_create, {
ADD_TEST(c_test1, "test1", "", auth_cred_guest); ADD_TEST(c_test1, "test1", "", auth_cred_guest);
ADD_TEST(c_test2, "test2", "", auth_cred_operator); ADD_TEST(c_test2, "test2", "", auth_cred_operator);
ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest); ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest);
ADD_TEST(c_test4, "test4", "u", auth_cred_guest); ADD_TEST(c_test4, "test4", "n", auth_cred_guest);
ADD_TEST(c_test5, "test5", "i", 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, "test6", "?c", auth_cred_guest);
ADD_TEST(c_test6, "test7", "C", auth_cred_guest); ADD_TEST(c_test6, "test7", "C", auth_cred_guest);
@@ -82,36 +78,12 @@ extern void command_destroy(struct hub_command* cmd);
static int verify(const char* str, enum command_parse_status expected) static int verify(const char* str, enum command_parse_status expected)
{ {
struct hub_command* cmd = command_parse(cbase, hub, &user, str); struct hub_command* cmd = command_parse(cbase, &user, str);
enum command_parse_status status = cmd->status; enum command_parse_status status = cmd->status;
command_free(cmd); command_free(cmd);
return status == expected; 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_1, { return verify("!test1", cmd_status_ok); });
EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); }); 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_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); });
@@ -128,7 +100,7 @@ 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_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_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_3, { return uman_add(hub, &user) == 0; });
EXO_TEST(command_user_4, { return verify("!test4 tester", cmd_status_ok); }); 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_user_5, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_ok); });
@@ -162,77 +134,7 @@ EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
// built-in command // built-in command
EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); }); 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, { EXO_TEST(command_destroy, {
command_free(cmd);
cmd = NULL;
DEL_TEST(c_test1); DEL_TEST(c_test1);
DEL_TEST(c_test2); DEL_TEST(c_test2);
DEL_TEST(c_test3); DEL_TEST(c_test3);
@@ -242,10 +144,3 @@ EXO_TEST(command_destroy, {
DEL_TEST(c_test7); DEL_TEST(c_test7);
return 1; return 1;
}); });
EXO_TEST(cleanup, {
uman_shutdown(hub->users);
command_shutdown(hub->commands);
hub_free(hub);
return 1;
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
#include <uhub.h> #include <uhub.h>
#define MAX_EVENTS 100 #define MAX_EVENTS 15
static struct timeout_queue* g_queue; static struct timeout_queue* g_queue;
static time_t g_now; static time_t g_now;
static size_t g_max; static size_t g_max;
@@ -117,28 +117,3 @@ EXO_TEST(timer_process_5_events_1,{
g_now = 4; g_now = 4;
return timeout_queue_process(g_queue, g_now) == g_triggered; return timeout_queue_process(g_queue, g_now) == g_triggered;
}); });
EXO_TEST(timer_clear_1,{
size_t n;
for (n = 0; n < MAX_EVENTS; n++)
timeout_queue_remove(g_queue, &g_events[n]);
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
EXO_TEST(timer_bulk_1,{
size_t n;
g_now = 10;
for (n = 0; n < MAX_EVENTS; n++)
{
timeout_queue_insert(g_queue, &g_events[0], 0);
}
return timeout_queue_process(g_queue, g_now) == 10;
});
EXO_TEST(timer_bulk_2,{
g_now = 110;
return timeout_queue_process(g_queue, g_now) == 90;
});

View File

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

View File

@@ -2,19 +2,32 @@
#define MAX_USERS 64 #define MAX_USERS 64
static struct hub_user_manager* uman = 0; static struct hub_info um_hub;
static struct hub_user um_user[MAX_USERS]; static struct hub_user um_user[MAX_USERS];
// static struct net_connection um_cons[MAX_USERS];
EXO_TEST(um_test_setup, {
int i = 0;
memset(&um_hub, 0, sizeof(um_hub));
for (i = 0; i < MAX_USERS; i++)
{
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
um_cons[i].sd = -1;
memset(&um_user[i], 0, sizeof(struct hub_user));
um_user[i].id.sid = i+1;
um_user[i].connection = &um_cons[i];*/
}
return 1;
});
EXO_TEST(um_init_1, { EXO_TEST(um_init_1, {
sid_t s; return uman_init(0) != 0;
uman = uman_init(); });
for (s = 0; s < MAX_USERS; s++) EXO_TEST(um_init_2, {
{ return uman_init(&um_hub) == 0;
memset(&um_user[s], 0, sizeof(struct hub_user));
um_user[s].id.sid = s;
}
return !!uman;
}); });
EXO_TEST(um_shutdown_1, { EXO_TEST(um_shutdown_1, {
@@ -22,29 +35,32 @@ EXO_TEST(um_shutdown_1, {
}); });
EXO_TEST(um_shutdown_2, { EXO_TEST(um_shutdown_2, {
return uman_shutdown(uman) == 0; return uman_shutdown(&um_hub) == 0;
}); });
EXO_TEST(um_init_2, { EXO_TEST(um_shutdown_3, {
uman = uman_init(); return uman_shutdown(&um_hub) == -1;
return !!uman; });
EXO_TEST(um_init_3, {
return uman_init(&um_hub) == 0;
}); });
EXO_TEST(um_add_1, { EXO_TEST(um_add_1, {
return uman_add(uman, &um_user[0]) == 0; return uman_add(&um_hub, &um_user[0]) == 0;
}); });
EXO_TEST(um_size_1, { EXO_TEST(um_size_1, {
return uman->count == 1; return hub_get_user_count(&um_hub) == 1;
}); });
EXO_TEST(um_remove_1, { EXO_TEST(um_remove_1, {
return uman_remove(uman, &um_user[0]) == 0; return uman_remove(&um_hub, &um_user[0]) == 0;
}); });
EXO_TEST(um_size_2, { EXO_TEST(um_size_2, {
return uman->count == 0; return hub_get_user_count(&um_hub) == 0;
}); });
@@ -52,21 +68,25 @@ EXO_TEST(um_add_2, {
int i; int i;
for (i = 0; i < MAX_USERS; i++) for (i = 0; i < MAX_USERS; i++)
{ {
if (uman_add(uman, &um_user[i]) != 0) if (uman_add(&um_hub, &um_user[i]) != 0)
return 0; return 0;
} }
return 1; return 1;
}); });
EXO_TEST(um_size_3, { EXO_TEST(um_size_3, {
return uman->count == MAX_USERS; return hub_get_user_count(&um_hub) == MAX_USERS;
});
EXO_TEST(um_add_3, {
return uman_add(&um_hub, &um_user[5]) != 0;
}); });
EXO_TEST(um_remove_2, { EXO_TEST(um_remove_2, {
int i; int i;
for (i = 0; i < MAX_USERS; i++) for (i = 0; i < MAX_USERS; i++)
{ {
if (uman_remove(uman, &um_user[i]) != 0) if (uman_remove(&um_hub, &um_user[i]) != 0)
return 0; return 0;
} }
return 1; return 1;
@@ -85,5 +105,5 @@ EXO_TEST(um_remove_2, {
/* Last test */ /* Last test */
EXO_TEST(um_shutdown_4, { EXO_TEST(um_shutdown_4, {
return uman_shutdown(uman) == 0; return uman_shutdown(&um_hub) == 0;
}); });

View File

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

View File

@@ -1,77 +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 libaries 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/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 )

4
debian/changelog vendored
View File

@@ -2,13 +2,13 @@ uhub (0.3.2-1) unstable; urgency=low
* Updated upstream version. * Updated upstream version.
-- Jan Vidar Krey <janvidar@extatic.org> Mon, 30 May 2010 18:00:00 +0200 -- Jan Vidar Krey <janvidar@extatic.org> Mon 30 May 2010 18:00:00 +0200
uhub (0.3.1-1) unstable; urgency=low uhub (0.3.1-1) unstable; urgency=low
* Updated version number. * Updated version number.
-- Jan Vidar Krey <janvidar@extatic.org> Mon, 04 Apr 2010 16:44:21 +0200 -- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200
uhub (0.3.0-2) unstable; urgency=low uhub (0.3.0-2) unstable; urgency=low

2
debian/rules vendored
View File

@@ -24,7 +24,7 @@ binary-indep: build
binary-arch: build binary-arch: build
dh_testdir dh_testdir
dh_testroot dh_testroot
dh_prep dh_clean -k
dh_installdirs dh_installdirs
$(MAKE) install $(makeopts) $(MAKE) install $(makeopts)
dh_installdocs dh_installdocs

9
debian/uhub.init vendored
View File

@@ -5,8 +5,7 @@
# Required-Stop: $remote_fs $network # Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time # Short-Description: uhub - High performance ADC p2p hub.
# Description: Enable service provided by daemon.
### END INIT INFO ### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin PATH=/sbin:/bin:/usr/sbin:/usr/bin
@@ -84,12 +83,8 @@ case "$1" in
$0 start $0 start
;; ;;
status)
status_of_proc $DAEMON $NAME && exit 0 || exit $?
;;
*) *)
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2 echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
exit 1 exit 1
;; ;;
esac esac

View File

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

View File

@@ -1,13 +1,13 @@
= Architecture of uHub = = 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. libevent library.
For each state there is a read event (and sometimes a write event) and timeout 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. event in case an expected read (or write) event does not occur.
== Protocol overview == == 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 = client, S = server aka uHub).
C: HSUP ADBASE C: HSUP ADBASE

View File

@@ -1,7 +1,7 @@
How to compile: How to compile:
--------------- ---------------
See the official compiling howto: http://www.uhub.org/compile.php See the official compiling howto: http://www.extatic.org/uhub/compile.html
Prerequisites Prerequisites

View File

@@ -31,7 +31,7 @@ The hub should send a packet containing the token back:
'IECH {token} {host:port}', aswell as the same message via TCP. 'IECH {token} {host:port}', aswell as the same message via TCP.
If the client receives the message via UDP, it should now be able to determine the type of NAT. If the client receives the message via UDP, it should now be able to determine the type of NAT.
If the client receives the message via TCP only it knows it has a firewall blocking incomming 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, If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
and resume in passive mode. and resume in passive mode.

View File

@@ -31,8 +31,7 @@ fi
# Check that networking is up. # Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1 [ ${NETWORKING} = "no" ] && exit 1
# Check that bin and uhub.conf exists. # Check that uhub.conf exists.
[ -f $UHUBBINFILE ] || exit 6
[ -f /etc/uhub/uhub.conf ] || exit 6 [ -f /etc/uhub/uhub.conf ] || exit 6
RETVAL=0 RETVAL=0
@@ -41,7 +40,7 @@ RETVAL=0
start() { start() {
KIND="Uhub" KIND="Uhub"
echo -n $"Starting $KIND services: " echo -n $"Starting $KIND services: "
daemon $UHUBBINFILE $UHUBOPTIONS daemon uhub $UHUBOPTIONS
RETVAL=$? RETVAL=$?
echo "" echo ""
return $RETVAL return $RETVAL
@@ -50,7 +49,7 @@ start() {
stop() { stop() {
KIND="Uhub" KIND="Uhub"
echo -n $"Shutting down $KIND services: " echo -n $"Shutting down $KIND services: "
killproc $UHUBBINFILE killproc uhub
RETVAL=$? RETVAL=$?
echo "" echo ""
return $RETVAL return $RETVAL
@@ -78,7 +77,7 @@ relog() {
} }
rhstatus() { rhstatus() {
status $UHUBBINFILE status uhub
RETVAL=$? RETVAL=$?
if [ $RETVAL -ne 0 ] ; then if [ $RETVAL -ne 0 ] ; then
return $RETVAL return $RETVAL

View File

@@ -1,6 +1,3 @@
# locate bin file
UHUBBINFILE=/usr/bin/uhub
# Options to UHUB # Options to UHUB
# -v Verbose mode. Add more -v's for higher verbosity. # -v Verbose mode. Add more -v's for higher verbosity.
# -q Quiet mode - no output # -q Quiet mode - no output

View File

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

View File

@@ -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 http://bugs.extatic.org/

View File

@@ -1,6 +1,6 @@
# uhub.conf - A example configuration file. # uhub.conf - A example configuration file.
# You should normally place this file in /etc/uhub/uhub.conf # You should normally place this file in /etc/uhub/uhub.conf
# and customize some of the settings below. # And change the file_acl and file_motd below.
# #
# This file is read only to the uhub deamon, and if you # This file is read only to the uhub deamon, and if you
# make changes to it while uhub is running you can send a # make changes to it while uhub is running you can send a
@@ -38,6 +38,17 @@ hub_enabled=1
# Access control list (user database) # Access control list (user database)
file_acl=/etc/uhub/users.conf file_acl=/etc/uhub/users.conf
# 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
# This file can contain a rules of the hub.
# Normally this message is sent to clients when write in chat !rules
file_rules=/etc/uhub/rules.txt
# This file can contain a conf for plugin subsystem # This file can contain a conf for plugin subsystem
file_plugins = /etc/uhub/plugins.conf file_plugins = /etc/uhub/plugins.conf

View File

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

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) theres 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

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ typedef uint32_t fourcc_t;
#define FOURCC(a,b,c,d) (fourcc_t) ((a << 24) | (b << 16) | (c << 8) | d) #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 */ /* 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 */ /* Server sent commands */
#define ADC_CMD_ISID FOURCC('I','S','I','D') #define ADC_CMD_ISID FOURCC('I','S','I','D')
@@ -85,23 +85,10 @@ typedef uint32_t fourcc_t;
#define ADC_CMD_DINF FOURCC('D','I','N','F') #define ADC_CMD_DINF FOURCC('D','I','N','F')
#define ADC_CMD_EINF FOURCC('E','I','N','F') #define ADC_CMD_EINF FOURCC('E','I','N','F')
#define ADC_CMD_FINF FOURCC('F','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 */ /* Extension messages */
#define ADC_CMD_HCHK FOURCC('H','C','H','K') #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_IPV4_ADDR "I4" /* ipv4 address */
#define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */ #define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */
#define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */ #define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */

View File

@@ -63,33 +63,6 @@ static void msg_free(void* ptr)
#define msg_free(X) hub_free(X) #define msg_free(X) hub_free(X)
#endif /* MSG_MEMORY_DEBUG */ #endif /* MSG_MEMORY_DEBUG */
static int msg_check_escapes(const char* string, size_t len)
{
char* start = (char*) string;
while ((start = memchr(start, '\\', len - (start - string))))
{
if (start+1 == (string + len))
return 0;
switch (*(++start))
{
case '\\':
case 'n':
case 's':
/* Increment so we don't check the escaped
* character next time around. Not doing so
* leads to messages with escaped backslashes
* being incorrectly reported as having invalid
* escapes. */
++start;
break;
default:
return 0;
}
}
return 1;
}
struct adc_message* adc_msg_incref(struct adc_message* msg) struct adc_message* adc_msg_incref(struct adc_message* msg)
{ {
@@ -154,7 +127,7 @@ static int adc_msg_cache_append(struct adc_message* msg, const char* string, siz
memcpy(&msg->cache[msg->length], string, len); memcpy(&msg->cache[msg->length], string, len);
adc_msg_set_length(msg, msg->length + len); adc_msg_set_length(msg, msg->length + len);
uhub_assert(msg->capacity > msg->length); assert(msg->capacity > msg->length);
msg->cache[msg->length] = 0; msg->cache[msg->length] = 0;
return 1; return 1;
} }
@@ -346,13 +319,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
return NULL; return NULL;
} }
if (!msg_check_escapes(line, length))
{
LOG_DEBUG("Dropped message with invalid ADC escape.");
msg_free(command);
return NULL;
}
if (line[length-1] != '\n') if (line[length-1] != '\n')
{ {
need_terminate = 1; need_terminate = 1;
@@ -532,30 +498,6 @@ struct adc_message* adc_msg_create(const char* line)
return adc_msg_parse(line, strlen(line)); return adc_msg_parse(line, strlen(line));
} }
struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size)
{
struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 1);
if (!msg)
return NULL;
adc_msg_add_argument(msg, sid_to_string(source));
msg->source = source;
return msg;
}
struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size)
{
struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 4 + 1);
if (!msg)
return NULL;
adc_msg_add_argument(msg, sid_to_string(source));
adc_msg_add_argument(msg, sid_to_string(dest));
msg->source = source;
msg->target = dest;
return msg;
}
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size) struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
{ {
@@ -563,7 +505,9 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
if (!msg) if (!msg)
return NULL; /* OOM */ return NULL; /* OOM */
if (!adc_msg_grow(msg, sizeof(fourcc) + size + 1)) if (size < sizeof(fourcc)) size = sizeof(fourcc);
if (!adc_msg_grow(msg, size+1))
{ {
msg_free(msg); msg_free(msg);
return NULL; /* OOM */ return NULL; /* OOM */
@@ -787,13 +731,6 @@ int adc_msg_add_argument(struct adc_message* cmd, const char* string)
return 0; return 0;
} }
int adc_msg_add_argument_string(struct adc_message* cmd, const char* string)
{
char* escaped = adc_msg_escape(string);
int ret = adc_msg_add_argument(cmd, escaped);
hub_free(escaped);
return ret;
}
char* adc_msg_get_argument(struct adc_message* cmd, int offset) char* adc_msg_get_argument(struct adc_message* cmd, int offset)
{ {
@@ -873,6 +810,8 @@ int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
return -1; return -1;
} }
int adc_msg_escape_length(const char* str) int adc_msg_escape_length(const char* str)
{ {
int add = 0; int add = 0;
@@ -938,41 +877,6 @@ char* adc_msg_unescape(const char* string)
return new_string; return new_string;
} }
int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size)
{
size_t w = 0;
char* ptr = (char*) target;
char* str = (char*) string;
int escaped = 0;
while (*str && w < (target_size-1))
{
if (escaped) {
if (*str == 's')
*ptr++ = ' ';
else if (*str == '\\')
*ptr++ = '\\';
else if (*str == 'n')
*ptr++ = '\n';
else
*ptr++ = *str;
w++;
escaped = 0;
} else {
if (*str == '\\')
escaped = 1;
else
{
*ptr++ = *str;
w++;
}
}
str++;
}
*ptr = 0;
w++;
return w;
}
char* adc_msg_escape(const char* string) char* adc_msg_escape(const char* string)
{ {

View File

@@ -91,13 +91,6 @@ extern struct adc_message* adc_msg_create(const char* string);
*/ */
extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size); extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
/**
* Construct a message for the given 'fourcc' and add a source SID to it,
* in addition pre-allocate 'size' bytes at the end of the message.
*/
extern struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size);
extern struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size);
/** /**
* Remove a named argument from the command. * Remove a named argument from the command.
* *
@@ -171,12 +164,6 @@ extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char pr
*/ */
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string); extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
/**
* Add an argument string, the string will be automatcally escaped.
* @return 0 if successful, or -1 if an error occured (out of memory).
*/
extern int adc_msg_add_argument_string(struct adc_message* cmd, const char* string);
/** /**
* Append a named argument * Append a named argument
* *
@@ -208,21 +195,6 @@ extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char
*/ */
extern char* adc_msg_unescape(const char* string); extern char* adc_msg_unescape(const char* string);
/**
* Convert a ADC command escaped string to a regular string.
* @return The number of bytes written to target. If the target is not large enough then
* the -1 is returned, but the string is guaranteed to always be \0 terminated.
*/
extern int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size);
/**
* Returns the length of the string once escaped with
* adc_msg_escape().
*
* The string must be NULL terminated.
*/
extern int adc_msg_escape_length(const char* str);
/** /**
* Convert a string to a ADC command escaped string. * Convert a string to a ADC command escaped string.
* @return adc command escaped string or NULL if out of memory. * @return adc command escaped string or NULL if out of memory.
@@ -247,5 +219,4 @@ void adc_msg_unterminate(struct adc_message* cmd);
*/ */
int adc_msg_get_arg_offset(struct adc_message* msg); int adc_msg_get_arg_offset(struct adc_message* msg);
#endif /* HAVE_UHUB_COMMAND_H */ #endif /* HAVE_UHUB_COMMAND_H */

View File

@@ -1,298 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
static void hub_command_args_free(struct hub_command* cmd)
{
struct hub_command_arg_data* data = NULL;
if (!cmd->args)
return;
for (data = (struct hub_command_arg_data*) list_get_first(cmd->args); data; data = (struct hub_command_arg_data*) list_get_next(cmd->args))
{
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;
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;
for (tmp = (char*) list_get_first(tokens); tmp; tmp = (char*) list_get_next(tokens))
size += (strlen(tmp) + 1);
token = hub_malloc_zero(size);
while ((tmp = list_get_first(tokens)))
{
if (*token)
strcat(token, " ");
strcat(token, 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-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_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 invokation 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

@@ -20,6 +20,7 @@
#include "uhub.h" #include "uhub.h"
#ifdef DEBUG #ifdef DEBUG
// #define CRASH_DEBUG
// #define DEBUG_UNLOAD_PLUGINS // #define DEBUG_UNLOAD_PLUGINS
#endif #endif
@@ -38,6 +39,7 @@ struct command_base
struct hub_info* hub; struct hub_info* hub;
struct linked_list* handlers; struct linked_list* handlers;
size_t prefix_length_max; size_t prefix_length_max;
struct ip_range range; // cached for parsing. Only one can be used per parameter.
}; };
struct command_base* command_initialize(struct hub_info* hub) struct command_base* command_initialize(struct hub_info* hub)
@@ -60,7 +62,7 @@ struct command_base* command_initialize(struct hub_info* hub)
void command_shutdown(struct command_base* cbase) void command_shutdown(struct command_base* cbase)
{ {
commands_builtin_remove(cbase); commands_builtin_remove(cbase);
uhub_assert(list_size(cbase->handlers) == 0); assert(list_size(cbase->handlers) == 0);
list_destroy(cbase->handlers); list_destroy(cbase->handlers);
hub_free(cbase); hub_free(cbase);
} }
@@ -86,14 +88,47 @@ int command_del(struct command_base* cbase, struct command_handle* cmd)
return 1; return 1;
} }
int command_is_available(struct command_handle* handle, enum auth_credentials credentials) static int command_is_available(struct command_handle* handle, const struct hub_user* user)
{ {
uhub_assert(handle != NULL); uhub_assert(handle != NULL);
return handle->cred <= credentials; uhub_assert(user != NULL);
return handle->cred <= user->credentials;
} }
void hub_command_args_free(struct hub_command* cmd)
{
struct hub_command_arg_data* data = NULL;
struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix) if (!cmd->args)
return;
for (data = (struct hub_command_arg_data*) list_get_first(cmd->args); data; data = (struct hub_command_arg_data*) list_get_next(cmd->args))
{
switch (data->type)
{
case type_string:
hub_free(data->data.string);
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 struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix)
{ {
struct command_handle* handler = NULL; struct command_handle* handler = NULL;
size_t prefix_len = strlen(prefix); size_t prefix_len = strlen(prefix);
@@ -110,41 +145,239 @@ struct command_handle* command_handler_lookup(struct command_base* cbase, const
} }
void command_get_syntax(struct command_handle* handler, struct cbuffer* buf) static enum command_parse_status command_extract_arguments(struct command_base* cbase, const struct hub_user* user, struct command_handle* command, struct linked_list* tokens, struct linked_list* args)
{ {
size_t n, arg_count; int arg = 0;
int opt = 0; int opt = 0;
char arg_code, last_arg = -1; char arg_code;
char* token = NULL;
struct hub_command_arg_data* data = NULL;
enum command_parse_status status = cmd_status_ok;
cbuf_append_format(buf, "!%s", handler->prefix); // Ignore the first token since it is the prefix.
if (handler->args) token = list_get_first(tokens);
list_remove(tokens, token);
hub_free(token);
while (status == cmd_status_ok && (arg_code = command->args[arg++]))
{ {
arg_count = strlen(handler->args); token = list_get_first(tokens);
for (n = 0; n < arg_count; n++) if (!token || !*token)
{ {
if (!strchr("?+", last_arg)) status = (arg_code == '?' ? cmd_status_ok : cmd_status_missing_args);
cbuf_append(buf, " "); break;
arg_code = handler->args[n]; }
switch (arg_code) switch (arg_code)
{ {
case '?': cbuf_append(buf, "["); opt++; break; case '?':
case '+': /* ignore */ break; opt = 1;
continue;
case 'n':
data = hub_malloc(sizeof(*data));
data->type = type_user;
data->data.user = uman_get_user_by_nick(cbase->hub, 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(cbase->hub, 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;
if (!ip_convert_address_to_range(token, data->data.range))
{
hub_free(data);
data = NULL;
status = cmd_status_arg_address;
}
break;
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(cbase, 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->type = type_integer;
if (!is_number(token, &data->data.integer))
{
hub_free(data);
data = NULL;
return 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) ? 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, 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(cbase, user, handle, tokens, cmd->args);
goto command_parse_cleanup;
command_parse_cleanup:
list_clear(tokens, &hub_free);
list_destroy(tokens);
return cmd;
}
void command_get_syntax(struct command_handle* handler, struct cbuffer* buf)
{
size_t n = 0;
int opt = 0;
if (handler->args)
{
for (n = 0; n < strlen(handler->args); n++)
{
if (n > 0 && !opt) cbuf_append(buf, " ");
switch (handler->args[n])
{
case '?': cbuf_append(buf, "["); opt = 1; continue;
case 'n': cbuf_append(buf, "<nick>"); break; case 'n': cbuf_append(buf, "<nick>"); break;
case 'u': cbuf_append(buf, "<user>"); break;
case 'i': cbuf_append(buf, "<cid>"); break; case 'i': cbuf_append(buf, "<cid>"); break;
case 'a': cbuf_append(buf, "<addr>"); break; case 'a': cbuf_append(buf, "<addr>"); break;
case 'r': cbuf_append(buf, "<addr range>"); break;
case 'm': cbuf_append(buf, "<message>"); break; case 'm': cbuf_append(buf, "<message>"); break;
case 'p': cbuf_append(buf, "<password>"); break; case 'p': cbuf_append(buf, "<password>"); break;
case 'C': cbuf_append(buf, "<credentials>"); break; case 'C': cbuf_append(buf, "<credentials>"); break;
case 'c': cbuf_append(buf, "<command>"); break; case 'c': cbuf_append(buf, "<command>"); break;
case 'N': cbuf_append(buf, "<number>"); break; case 'N': cbuf_append(buf, "<number>"); break;
default: LOG_ERROR("unknown argument code '%c'", arg_code);
} }
last_arg = arg_code; if (opt)
} {
while (opt--)
cbuf_append(buf, "]"); cbuf_append(buf, "]");
opt = 0;
}
}
} }
} }
@@ -217,7 +450,7 @@ int command_check_args(struct hub_command* cmd, struct command_handle* handler)
int command_invoke(struct command_base* cbase, struct hub_user* user, const char* message) int command_invoke(struct command_base* cbase, struct hub_user* user, const char* message)
{ {
int ret = 0; int ret = 0;
struct hub_command* cmd = command_parse(cbase, cbase->hub, user, message); struct hub_command* cmd = command_parse(cbase, user, message);
switch (cmd->status) switch (cmd->status)
{ {
@@ -233,11 +466,14 @@ int command_invoke(struct command_base* cbase, struct hub_user* user, const char
ret = send_command_access_denied(cbase, user, cmd->prefix); ret = send_command_access_denied(cbase, user, cmd->prefix);
break; break;
case cmd_status_syntax_error:
ret = send_command_syntax_error(cbase, user);
break;
case cmd_status_missing_args: case cmd_status_missing_args:
ret = send_command_missing_arguments(cbase, user, cmd); ret = send_command_missing_arguments(cbase, user, cmd);
break; break;
case cmd_status_syntax_error:
case cmd_status_arg_nick: case cmd_status_arg_nick:
case cmd_status_arg_cid: case cmd_status_arg_cid:
case cmd_status_arg_address: case cmd_status_arg_address:
@@ -253,28 +489,9 @@ int command_invoke(struct command_base* cbase, struct hub_user* user, const char
return ret; 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) 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); struct cbuffer* buf = cbuf_create(cbuf_size(msg) + strlen(cmd->prefix) + 8);
cbuf_append_format(buf, "*** %s: %s", cmd->prefix, cbuf_get(msg)); cbuf_append_format(buf, "*** %s: %s", cmd->prefix, cbuf_get(msg));
send_message(cbase, user, buf); send_message(cbase, user, buf);
cbuf_destroy(msg); cbuf_destroy(msg);
@@ -285,16 +502,16 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
{ {
size_t n; size_t n;
struct cbuffer* buf = cbuf_create(MAX_HELP_LINE); struct cbuffer* buf = cbuf_create(MAX_HELP_LINE);
struct hub_command_arg_data* data = hub_command_arg_next(cmd, type_command); struct hub_command_arg_data* data = list_get_first(cmd->args);
struct command_handle* command; struct command_handle* command = data->data.command;
if (!data) if (!command)
{ {
cbuf_append(buf, "Available commands:\n"); cbuf_append(buf, "Available commands:\n");
for (command = (struct command_handle*) list_get_first(cbase->handlers); command; command = (struct command_handle*) list_get_next(cbase->handlers)) for (command = (struct command_handle*) list_get_first(cbase->handlers); command; command = (struct command_handle*) list_get_next(cbase->handlers))
{ {
if (command_is_available(command, user->credentials)) if (command_is_available(command, user))
{ {
cbuf_append_format(buf, "!%s", command->prefix); cbuf_append_format(buf, "!%s", command->prefix);
for (n = strlen(command->prefix); n < cbase->prefix_length_max; n++) for (n = strlen(command->prefix); n < cbase->prefix_length_max; n++)
@@ -305,10 +522,9 @@ static int command_help(struct command_base* cbase, struct hub_user* user, struc
} }
else else
{ {
command = data->data.command; if (command_is_available(command, user))
if (command_is_available(command, user->credentials))
{ {
cbuf_append_format(buf, "Usage: "); cbuf_append_format(buf, "Usage: !%s ", command->prefix);
command_get_syntax(command, buf); command_get_syntax(command, buf);
cbuf_append_format(buf, "\n%s\n", command->description); cbuf_append_format(buf, "\n%s\n", command->description);
} }
@@ -343,8 +559,7 @@ static int command_uptime(struct command_base* cbase, struct hub_user* user, str
static int command_kick(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_kick(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user); struct hub_user* target = list_get_first(cmd->args);
struct hub_user* target = arg->data.user;
buf = cbuf_create(128); buf = cbuf_create(128);
if (target == user) if (target == user)
@@ -353,17 +568,58 @@ static int command_kick(struct command_base* cbase, struct hub_user* user, struc
} }
else else
{ {
hub_notify(cbase->hub, notify_info, "Kicking user \"%s\" (%s)", target->id.nick, user->id.nick);
cbuf_append_format(buf, "Kicking user \"%s\".", target->id.nick); cbuf_append_format(buf, "Kicking user \"%s\".", target->id.nick);
hub_disconnect_user(cbase->hub, target, quit_kicked); hub_disconnect_user(cbase->hub, target, quit_kicked);
} }
return command_status(cbase, user, cmd, buf); return command_status(cbase, user, cmd, buf);
} }
static int command_ban(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct hub_user* target = list_get_first(cmd->args);
if (target == user)
{
cbuf_append(buf, "Cannot kick/ban yourself");
}
else
{
cbuf_append_format(buf, "Banning user \"%s\"", target->id.nick);
hub_disconnect_user(cbase->hub, target, quit_kicked);
acl_user_ban_nick(cbase->hub->acl, target->id.nick);
acl_user_ban_cid(cbase->hub->acl, target->id.cid);
}
return command_status(cbase, user, cmd, buf);
}
static int command_unban(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented"));
}
static int command_mute(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct hub_user* target = list_get_first(cmd->args);
struct cbuffer* buf = cbuf_create(128);
if (strlen(cmd->prefix) == 4)
{
cbuf_append_format(buf, "Muted \"%s\"", target->id.nick);
user_flag_set(target, flag_muted);
}
else
{
cbuf_append_format(buf, "Unmuted \"%s\"", target->id.nick);
user_flag_unset(target, flag_muted);
}
return command_status(cbase, user, cmd, buf);
}
static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_reload(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
cbase->hub->status = hub_status_restart; cbase->hub->status = hub_status_restart;
hub_notify(cbase->hub, notify_info, "Reloading configuration (%s)", user->id.nick);
return command_status(cbase, user, cmd, cbuf_create_const("Reloading configuration...")); return command_status(cbase, user, cmd, cbuf_create_const("Reloading configuration..."));
} }
@@ -386,7 +642,6 @@ static int command_unload(struct command_base* cbase, struct hub_user* user, str
static int command_shutdown_hub(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_shutdown_hub(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
hub_notify(cbase->hub, notify_warn, "Shutting down hub (%s)", user->id.nick);
cbase->hub->status = hub_status_shutdown; cbase->hub->status = hub_status_shutdown;
return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down...")); return command_status(cbase, user, cmd, cbuf_create_const("Hub shutting down..."));
} }
@@ -411,20 +666,20 @@ static int command_myip(struct command_base* cbase, struct hub_user* user, struc
static int command_getip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_getip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf = cbuf_create(128); struct cbuffer* buf = cbuf_create(128);
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_user); struct hub_user* target = list_get_first(cmd->args);
cbuf_append_format(buf, "\"%s\" has address \"%s\"", arg->data.user->id.nick, user_get_address(arg->data.user)); cbuf_append_format(buf, "\"%s\" has address \"%s\"", target->id.nick, user_get_address(target));
return command_status(cbase, user, cmd, buf); return command_status(cbase, user, cmd, buf);
} }
static int command_whoip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_whoip(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct hub_command_arg_data* arg = hub_command_arg_next(cmd, type_range); struct ip_range* range = list_get_first(cmd->args);
struct linked_list* users = (struct linked_list*) list_create(); struct linked_list* users = (struct linked_list*) list_create();
struct hub_user* u; struct hub_user* u;
int ret = 0; int ret = 0;
ret = uman_get_user_by_addr(cbase->hub->users, users, arg->data.range); ret = uman_get_user_by_addr(cbase->hub, users, range);
if (!ret) if (!ret)
{ {
list_clear(users, &null_free); list_clear(users, &null_free);
@@ -452,9 +707,9 @@ static int command_whoip(struct command_base* cbase, struct hub_user* user, stru
static int command_broadcast(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) 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); size_t offset = 11;
char* message = arg->data.string; size_t message_len = strlen(cmd->message + offset);
size_t message_len = strlen(message); char* message = adc_msg_escape(cmd->message + offset);
char pm_flag[7] = "PM"; char pm_flag[7] = "PM";
char from_sid[5]; char from_sid[5];
size_t recipients = 0; size_t recipients = 0;
@@ -488,17 +743,17 @@ static int command_broadcast(struct command_base* cbase, struct hub_user* user,
cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : "")); cbuf_append_format(buf, "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : ""));
send_message(cbase, user, buf); send_message(cbase, user, buf);
hub_free(message);
return 0; return 0;
} }
static int command_log(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_log(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf; 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 linked_list* messages = cbase->hub->logout_info;
struct hub_logout_info* log; struct hub_logout_info* log;
char* search = arg ? arg->data.string : ""; char* search = 0;
size_t search_len = strlen(search); size_t search_len = 0;
size_t search_hits = 0; size_t search_hits = 0;
if (!list_size(messages)) if (!list_size(messages))
@@ -509,9 +764,15 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct
buf = cbuf_create(128); buf = cbuf_create(128);
cbuf_append_format(buf, "Logged entries: " PRINTF_SIZE_T, list_size(messages)); cbuf_append_format(buf, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
search = list_get_first(cmd->args);
if (search)
{
search_len = strlen(search);
}
if (search_len) if (search_len)
{ {
cbuf_append_format(buf, ", searching for \"%s\"", search); cbuf_append_format(buf, ", searching for \"%s\"", list_size(messages), search);
} }
command_status(cbase, user, cmd, buf); command_status(cbase, user, cmd, buf);
@@ -556,32 +817,127 @@ static int command_log(struct command_base* cbase, struct hub_user* user, struct
return 0; return 0;
} }
static int command_register(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct auth_info data;
struct hub_command_arg_data* args = (struct hub_command_arg_data*) list_get_first(cmd->args);
char* password = args->data.string;
strncpy(data.nickname, user->id.nick, MAX_NICK_LEN);
strncpy(data.password, password, MAX_PASS_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[MAX_PASS_LEN] = '\0';
data.credentials = auth_cred_user;
if (acl_register_user(cbase->hub, &data))
{
cbuf_append_format(buf, "User \"%s\" registered.", user->id.nick);
}
else
{
cbuf_append_format(buf, "Unable to register user \"%s\".", user->id.nick);
}
return command_status(cbase, user, cmd, buf);
}
static int command_password(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct auth_info data;
struct hub_command_arg_data* args = (struct hub_command_arg_data*) list_get_first(cmd->args);
char* password = args->data.string;
strncpy(data.nickname, user->id.nick, MAX_NICK_LEN);
strncpy(data.password, password, MAX_PASS_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[MAX_PASS_LEN] = '\0';
data.credentials = user->credentials;
if (acl_update_user(cbase->hub, &data))
{
cbuf_append(buf, "Password changed.");
}
else
{
cbuf_append_format(buf, "Unable to change password for user \"%s\".", user->id.nick);
}
return command_status(cbase, user, cmd, buf);
}
static int command_useradd(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct auth_info data;
char* nick = list_get_first(cmd->args);
char* pass = list_get_next(cmd->args);
char* cred = list_get_next(cmd->args);
enum auth_credentials credentials;
if (!(cred && auth_string_to_cred(cred, &credentials)))
credentials = auth_cred_user;
strncpy(data.nickname, nick, MAX_NICK_LEN);
strncpy(data.password, pass, MAX_PASS_LEN);
data.nickname[MAX_NICK_LEN] = '\0';
data.password[MAX_PASS_LEN] = '\0';
data.credentials = credentials;
if (acl_register_user(cbase->hub, &data))
cbuf_append_format(buf, "User \"%s\" registered.", nick);
else
cbuf_append_format(buf, "Unable to register user \"%s\".", nick);
return command_status(cbase, user, cmd, buf);
}
static int command_userdel(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
char* nick = list_get_first(cmd->args);
if (acl_delete_user(cbase->hub, nick))
cbuf_append_format(buf, "User \"%s\" is deleted.", nick);
else
cbuf_append_format(buf, "Unable to delete user \"%s\".", nick);
return command_status(cbase, user, cmd, buf);
}
static int command_usermod(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented!"));
}
static int command_userinfo(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented!"));
}
static int command_userpass(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
return command_status(cbase, user, cmd, cbuf_create_const("Not implemented!"));
}
#ifdef CRASH_DEBUG
static int command_crash(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{
void (*crash)(void) = NULL;
crash();
return 0;
}
#endif
static int command_stats(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int command_stats(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
{ {
struct cbuffer* buf = cbuf_create(128); struct cbuffer* buf = cbuf_create(128);
struct hub_info* hub = cbase->hub; struct hub_info* hub = cbase->hub;
static char rxbuf[64] = { "0 B" };
static char txbuf[64] = { "0 B" };
cbuf_append(buf, "Hub statistics: ");
cbuf_append_format(buf, PRINTF_SIZE_T "/" PRINTF_SIZE_T " users (peak %d). ", hub->users->count, hub->config->max_users, hub->users->count_peak);
format_size(hub->stats.net_rx, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx, txbuf, sizeof(txbuf));
cbuf_append_format(buf, "Network: tx=%s/s, rx=%s/s", txbuf, rxbuf);
#ifdef SHOW_PEAK_NET_STATS /* currently disabled */
format_size(hub->stats.net_rx_peak, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx_peak, txbuf, sizeof(txbuf));
cbuf_append_format(buf, ", peak_tx=%s/s, peak_rx=%s/s", txbuf, rxbuf);
#endif
format_size(hub->stats.net_rx_total, rxbuf, sizeof(rxbuf));
format_size(hub->stats.net_tx_total, txbuf, sizeof(txbuf));
cbuf_append_format(buf, ", total_tx=%s", txbuf);
cbuf_append_format(buf, ", total_rx=%s", rxbuf);
cbuf_append_format(buf, PRINTF_SIZE_T " users, peak: " PRINTF_SIZE_T ". Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
return command_status(cbase, user, cmd, buf); return command_status(cbase, user, cmd, buf);
} }
@@ -604,18 +960,32 @@ static struct command_handle* add_builtin(struct command_base* cbase, const char
void commands_builtin_add(struct command_base* cbase) 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("ban", 3, "n", auth_cred_operator, command_ban, "Ban a user" );
ADD_COMMAND("getip", 5, "u", auth_cred_operator, command_getip, "Show IP address for a user" ); ADD_COMMAND("broadcast", 9, "m", auth_cred_operator, command_broadcast,"Send a message to all users" );
#ifdef CRASH_DEBUG
ADD_COMMAND("crash", 5, "", auth_cred_admin, command_crash, "Crash the hub (DEBUG)." );
#endif
ADD_COMMAND("getip", 5, "n", 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("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("kick", 4, "n", auth_cred_operator, command_kick, "Kick a user" );
ADD_COMMAND("log", 3, "?m", auth_cred_operator, command_log, "Display log" ); // fail ADD_COMMAND("log", 3, "?m", auth_cred_operator, command_log, "Display log" ); // fail
ADD_COMMAND("mute", 4, "n", auth_cred_operator, command_mute, "Mute user" );
ADD_COMMAND("myip", 4, "", auth_cred_guest, command_myip, "Show your own IP." ); ADD_COMMAND("myip", 4, "", auth_cred_guest, command_myip, "Show your own IP." );
ADD_COMMAND("register", 8, "p", auth_cred_guest, command_register, "Register your username." ); // fail
ADD_COMMAND("reload", 6, "", auth_cred_admin, command_reload, "Reload configuration files." ); ADD_COMMAND("reload", 6, "", auth_cred_admin, command_reload, "Reload configuration files." );
ADD_COMMAND("password", 8, "p", auth_cred_user, command_password, "Change your own password." ); // fail
ADD_COMMAND("shutdown", 8, "", auth_cred_admin, command_shutdown_hub, "Shutdown hub." ); 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("stats", 5, "", auth_cred_super, command_stats, "Show hub statistics." );
ADD_COMMAND("unban", 5, "n", auth_cred_operator, command_unban, "Lift ban on a user" ); // not implemented
ADD_COMMAND("unmute", 6, "n", auth_cred_operator, command_mute, "Unmute user" );
ADD_COMMAND("uptime", 6, "", auth_cred_guest, command_uptime, "Display hub uptime info." ); ADD_COMMAND("uptime", 6, "", auth_cred_guest, command_uptime, "Display hub uptime info." );
ADD_COMMAND("useradd", 7, "np",auth_cred_operator, command_useradd, "Register a new user." ); // fail
ADD_COMMAND("userdel", 7, "n", auth_cred_operator, command_userdel, "Delete a registered user." ); // fail
ADD_COMMAND("userinfo", 8, "n", auth_cred_operator, command_userinfo, "Show registered user info." ); // fail
ADD_COMMAND("usermod", 7, "nC",auth_cred_admin, command_usermod, "Modify user credentials." ); // fail
ADD_COMMAND("userpass", 8, "np",auth_cred_operator, command_userpass, "Change password for a user." ); // fail
ADD_COMMAND("version", 7, "", auth_cred_guest, command_version, "Show hub version 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" ); ADD_COMMAND("whoip", 5, "a", auth_cred_operator, command_whoip, "Show users matching IP range" ); // ok
#ifdef DEBUG_UNLOAD_PLUGINS #ifdef DEBUG_UNLOAD_PLUGINS
ADD_COMMAND("load", 4, "", auth_cred_admin, command_load, "Load plugins." ); ADD_COMMAND("load", 4, "", auth_cred_admin, command_load, "Load plugins." );

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -24,12 +24,77 @@ struct command_base;
struct command_handle; struct command_handle;
struct hub_command; struct hub_command;
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
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')" */
};
struct hub_command_arg_data
{
enum Type {
type_integer,
type_string,
type_user,
type_address,
type_range,
type_credentials,
type_command
} 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;
struct hub_command_arg_data* next;
};
void hub_command_args_free(struct hub_command* command);
/**
* 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 all parsed arguments from the message. Type depends on expectations." */
enum command_parse_status status; /**<<< "Status of the 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" */
};
/** /**
* Argument codes are used to automatically parse arguments * Argument codes are used to automatically parse arguments
* for a a hub command. * for a a hub command.
* *
* u = user (must exist in hub session, or will cause error) * n = nick name (must exist in hub session)
* n = nick name (string)
* i = CID (must exist in hub) * i = CID (must exist in hub)
* a = (IP) address (must be a valid IPv4 or IPv6 address) * 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) * r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work)
@@ -40,17 +105,12 @@ struct hub_command;
* N = number (integer) * N = number (integer)
* *
* Prefix an argument with ? to make it optional. * 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: 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: * Example:
* "nia" means "nick cid ip" * "nia" means "nick cid ip"
* "n?p" means "nick [password]" where password is optional. * "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 struct command_handle
{ {
@@ -93,15 +153,22 @@ extern int command_del(struct command_base*, struct command_handle*);
extern int command_invoke(struct command_base*, struct hub_user* user, const char* message); 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. * 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 invokation prefix '!' or '+')
*
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
*/ */
int command_is_available(struct command_handle* handle, enum auth_credentials credentials); extern struct hub_command* command_parse(struct command_base* cbase, const struct hub_user* user, const char* message);
/** /**
* Lookup a command handle based on prefix. * Free a hub_command that was created in command_parse().
* 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 command_free(struct hub_command* command);
extern void commands_builtin_add(struct command_base*); extern void commands_builtin_add(struct command_base*);
extern void commands_builtin_remove(struct command_base*); extern void commands_builtin_remove(struct command_base*);

View File

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

View File

@@ -13,7 +13,7 @@
<check min="1" max="65535" /> <check min="1" max="65535" />
<since>0.1.0</since> <since>0.1.0</since>
<short>Server port to bind to</short> <short>Server port to bind to</short>
<description><![CDATA[This specifies the port number the hub should listen on.]]></description> <description><![CDATA[This is specifies the port number the hub should listen on.]]></description>
</option> </option>
<option name="server_bind_addr" type="string" default="any"> <option name="server_bind_addr" type="string" default="any">
@@ -409,7 +409,7 @@
</option> </option>
<option name="tls_require" type="boolean" default="0"> <option name="tls_require" type="boolean" default="0">
<short>If SSL/TLS enabled, should it be required</short> <short>If SSL/TLS enabled, should it be required (default: 0)</short>
<description><![CDATA[ <description><![CDATA[
If TLS/SSL support is enabled it can either be optional or mandatory. 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. 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.
@@ -590,7 +590,7 @@
</option> </option>
<option name="msg_error_no_memory" type="message" default="No memory"> <option name="msg_error_no_memory" type="message" default="No memory">
<description><![CDATA[Hub has no more memory]]></description> <description><![CDATA[]]></description>
<since>0.2.0</since> <since>0.2.0</since>
</option> </option>

View File

@@ -88,7 +88,7 @@ int event_queue_process(struct event_queue* queue)
} }
list_clear(queue->q1, event_queue_cleanup_callback); list_clear(queue->q1, event_queue_cleanup_callback);
uhub_assert(list_size(queue->q1) == 0); assert(list_size(queue->q1) == 0);
/* unlock queue */ /* unlock queue */
queue->locked = 0; queue->locked = 0;

View File

@@ -102,9 +102,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "server_port")) if (!strcmp(key, "server_port"))
{ {
min = 1; if (!apply_integer(key, data, &config->server_port, 0, 0))
max = 65535;
if (!apply_integer(key, data, &config->server_port, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -124,8 +122,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "server_listen_backlog")) if (!strcmp(key, "server_listen_backlog"))
{ {
min = 5; if (!apply_integer(key, data, &config->server_listen_backlog, 0, 0))
if (!apply_integer(key, data, &config->server_listen_backlog, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -247,9 +244,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_recv_buffer")) if (!strcmp(key, "max_recv_buffer"))
{ {
min = 1024; if (!apply_integer(key, data, &config->max_recv_buffer, 0, 0))
max = 1048576;
if (!apply_integer(key, data, &config->max_recv_buffer, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -259,8 +254,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_send_buffer")) if (!strcmp(key, "max_send_buffer"))
{ {
min = 2048; if (!apply_integer(key, data, &config->max_send_buffer, 0, 0))
if (!apply_integer(key, data, &config->max_send_buffer, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -270,8 +264,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_send_buffer_soft")) if (!strcmp(key, "max_send_buffer_soft"))
{ {
min = 1024; if (!apply_integer(key, data, &config->max_send_buffer_soft, 0, 0))
if (!apply_integer(key, data, &config->max_send_buffer_soft, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -291,9 +284,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_chat_history")) if (!strcmp(key, "max_chat_history"))
{ {
min = 0; if (!apply_integer(key, data, &config->max_chat_history, 0, 0))
max = 250;
if (!apply_integer(key, data, &config->max_chat_history, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -303,9 +294,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "max_logout_log")) if (!strcmp(key, "max_logout_log"))
{ {
min = 0; if (!apply_integer(key, data, &config->max_logout_log, 0, 0))
max = 2000;
if (!apply_integer(key, data, &config->max_logout_log, &min, &max))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -315,8 +304,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs_user")) if (!strcmp(key, "limit_max_hubs_user"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_max_hubs_user, 0, 0))
if (!apply_integer(key, data, &config->limit_max_hubs_user, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -326,8 +314,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs_reg")) if (!strcmp(key, "limit_max_hubs_reg"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_max_hubs_reg, 0, 0))
if (!apply_integer(key, data, &config->limit_max_hubs_reg, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -337,8 +324,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs_op")) if (!strcmp(key, "limit_max_hubs_op"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_max_hubs_op, 0, 0))
if (!apply_integer(key, data, &config->limit_max_hubs_op, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -348,8 +334,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_hubs")) if (!strcmp(key, "limit_max_hubs"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_max_hubs, 0, 0))
if (!apply_integer(key, data, &config->limit_max_hubs, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -359,8 +344,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_hubs_user")) if (!strcmp(key, "limit_min_hubs_user"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_min_hubs_user, 0, 0))
if (!apply_integer(key, data, &config->limit_min_hubs_user, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -370,8 +354,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_hubs_reg")) if (!strcmp(key, "limit_min_hubs_reg"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_min_hubs_reg, 0, 0))
if (!apply_integer(key, data, &config->limit_min_hubs_reg, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -381,8 +364,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_hubs_op")) if (!strcmp(key, "limit_min_hubs_op"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_min_hubs_op, 0, 0))
if (!apply_integer(key, data, &config->limit_min_hubs_op, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -403,8 +385,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_share")) if (!strcmp(key, "limit_max_share"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_max_share, 0, 0))
if (!apply_integer(key, data, &config->limit_max_share, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -414,8 +395,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_min_slots")) if (!strcmp(key, "limit_min_slots"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_min_slots, 0, 0))
if (!apply_integer(key, data, &config->limit_min_slots, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;
@@ -425,8 +405,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
if (!strcmp(key, "limit_max_slots")) if (!strcmp(key, "limit_max_slots"))
{ {
min = 0; if (!apply_integer(key, data, &config->limit_max_slots, 0, 0))
if (!apply_integer(key, data, &config->limit_max_slots, &min, 0))
{ {
LOG_ERROR("Configuration parse error on line %d", line_count); LOG_ERROR("Configuration parse error on line %d", line_count);
return -1; return -1;

View File

@@ -4,9 +4,9 @@ struct hub_config
{ {
int hub_enabled; /*<<< Is server enabled (default: 1) */ int hub_enabled; /*<<< Is server enabled (default: 1) */
int server_port; /*<<< Server port to bind to (default: 1511) */ int server_port; /*<<< Server port to bind to (default: 1511) */
char* server_bind_addr; /*<<< Server bind address (default: "any") */ char* server_bind_addr; /*<<< Server bind address (default: any) */
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */ int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: "") */ 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; /*<<< Show banner on connect (default: 1) */
int show_banner_sys_info; /*<<< 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 max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
@@ -14,9 +14,9 @@ struct hub_config
int register_self; /*<<< Allow users to register themselves on the hub. (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 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) */ int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
char* hub_name; /*<<< Name of hub (default: "uhub") */ char* hub_name; /*<<< Name of hub (default: uhub) */
char* hub_description; /*<<< Short hub description, topic or subject. (default: "no description") */ char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */
char* redirect_addr; /*<<< A common hub redirect address. (default: "") */ char* redirect_addr; /*<<< A common hub redirect address. (default: ) */
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */ 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; /*<<< 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 max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
@@ -41,12 +41,12 @@ struct hub_config
int flood_ctl_update; /*<<< Max updates 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 flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */ int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) */ int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */ char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: ) */
char* tls_certificate; /*<<< Certificate file (default: "") */ char* tls_certificate; /*<<< Certificate file (default: ) */
char* tls_private_key; /*<<< Private key file (default: "") */ char* tls_private_key; /*<<< Private key file (default: ) */
char* file_acl; /*<<< File containing access control lists (default: "") */ char* file_acl; /*<<< File containing access control lists (default: ) */
char* file_plugins; /*<<< Plugin configuration file (default: "") */ char* file_plugins; /*<<< Plugin configuration file (default: ) */
char* msg_hub_full; /*<<< "Hub is full" */ char* msg_hub_full; /*<<< "Hub is full" */
char* msg_hub_disabled; /*<<< "Hub is disabled" */ char* msg_hub_disabled; /*<<< "Hub is disabled" */
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */ char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -76,10 +76,6 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
case ADC_CMD_DINF: case ADC_CMD_DINF:
case ADC_CMD_EINF: case ADC_CMD_EINF:
case ADC_CMD_FINF: case ADC_CMD_FINF:
case ADC_CMD_BQUI:
case ADC_CMD_DQUI:
case ADC_CMD_EQUI:
case ADC_CMD_FQUI:
/* these must never be allowed for security reasons, so we ignore them. */ /* these must never be allowed for security reasons, so we ignore them. */
CHECK_FLOOD(extras, 1); CHECK_FLOOD(extras, 1);
break; break;
@@ -110,33 +106,25 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
case ADC_CMD_DRES: case ADC_CMD_DRES:
cmd->priority = -1; cmd->priority = -1;
if (plugin_handle_search_result(hub, u, uman_get_user_by_sid(hub->users, cmd->target), cmd->cache) == st_deny) if (plugin_handle_search_result(hub, u, uman_get_user_by_sid(hub, cmd->target), cmd->cache) == st_deny)
break; break;
/* CHECK_FLOOD(search, 0); */ /* CHECK_FLOOD(search, 0); */
ROUTE_MSG; ROUTE_MSG;
case ADC_CMD_DRCM: case ADC_CMD_DRCM:
cmd->priority = -1; cmd->priority = -1;
if (plugin_handle_revconnect(hub, u, uman_get_user_by_sid(hub->users, cmd->target)) == st_deny) if (plugin_handle_revconnect(hub, u, uman_get_user_by_sid(hub, cmd->target)) == st_deny)
break; break;
CHECK_FLOOD(connect, 1); CHECK_FLOOD(connect, 1);
ROUTE_MSG; ROUTE_MSG;
case ADC_CMD_DCTM: case ADC_CMD_DCTM:
cmd->priority = -1; cmd->priority = -1;
if (plugin_handle_connect(hub, u, uman_get_user_by_sid(hub->users, cmd->target)) == st_deny) if (plugin_handle_connect(hub, u, uman_get_user_by_sid(hub, cmd->target)) == st_deny)
break; break;
CHECK_FLOOD(connect, 1); CHECK_FLOOD(connect, 1);
ROUTE_MSG; ROUTE_MSG;
case ADC_CMD_BCMD:
case ADC_CMD_DCMD:
case ADC_CMD_ECMD:
case ADC_CMD_FCMD:
case ADC_CMD_HCMD:
CHECK_FLOOD(extras, 1);
break;
default: default:
CHECK_FLOOD(extras, 1); CHECK_FLOOD(extras, 1);
ROUTE_MSG; ROUTE_MSG;
@@ -340,7 +328,7 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
} }
else if (private_msg) else if (private_msg)
{ {
struct hub_user* target = uman_get_user_by_sid(hub->users, cmd->target); struct hub_user* target = uman_get_user_by_sid(hub, cmd->target);
if (target) if (target)
status = plugin_handle_private_message(hub, u, target, message_decoded, 0); status = plugin_handle_private_message(hub, u, target, message_decoded, 0);
else else
@@ -381,7 +369,7 @@ void hub_send_sid(struct hub_info* hub, struct hub_user* u)
if (user_is_connecting(u)) if (user_is_connecting(u))
{ {
command = adc_msg_construct(ADC_CMD_ISID, 10); command = adc_msg_construct(ADC_CMD_ISID, 10);
sid = uman_get_free_sid(hub->users, u); sid = uman_get_free_sid(hub, u);
adc_msg_add_argument(command, (const char*) sid_to_string(sid)); adc_msg_add_argument(command, (const char*) sid_to_string(sid));
route_to_user(hub, u, command); route_to_user(hub, u, command);
adc_msg_free(command); adc_msg_free(command);
@@ -520,11 +508,11 @@ static int check_duplicate_logins_ok(struct hub_info* hub, struct hub_user* user
struct hub_user* lookup1; struct hub_user* lookup1;
struct hub_user* lookup2; struct hub_user* lookup2;
lookup1 = uman_get_user_by_nick(hub->users, user->id.nick); lookup1 = uman_get_user_by_nick(hub, user->id.nick);
if (lookup1) if (lookup1)
return status_msg_inf_error_nick_taken; return status_msg_inf_error_nick_taken;
lookup2 = uman_get_user_by_cid(hub->users, user->id.cid); lookup2 = uman_get_user_by_cid(hub, user->id.cid);
if (lookup2) if (lookup2)
return status_msg_inf_error_cid_taken; return status_msg_inf_error_cid_taken;
@@ -536,7 +524,7 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
int status; int status;
struct hub_info* hub = (struct hub_info*) callback_data; struct hub_info* hub = (struct hub_info*) callback_data;
struct hub_user* user = (struct hub_user*) message->ptr; struct hub_user* user = (struct hub_user*) message->ptr;
uhub_assert(hub != NULL); assert(hub != NULL);
switch (message->id) switch (message->id)
{ {
@@ -568,8 +556,8 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
case UHUB_EVENT_USER_QUIT: case UHUB_EVENT_USER_QUIT:
{ {
uman_remove(hub->users, user); uman_remove(hub, user);
uman_send_quit_message(hub, hub->users, user); uman_send_quit_message(hub, user);
on_logout_user(hub, user); on_logout_user(hub, user);
hub_schedule_destroy_user(hub, user); hub_schedule_destroy_user(hub, user);
break; break;
@@ -586,7 +574,7 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list); struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list);
while (u) while (u)
{ {
uman_remove(hub->users, u); uman_remove(hub, u);
user_destroy(u); user_destroy(u);
u = (struct hub_user*) list_get_first(hub->users->list); u = (struct hub_user*) list_get_first(hub->users->list);
} }
@@ -600,31 +588,6 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
} }
} }
static void hub_update_stats(struct hub_info* hub)
{
const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
hub->stats.net_tx = (intermediate->tx / factor);
hub->stats.net_rx = (intermediate->rx / factor);
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
hub->stats.net_tx_total = total->tx;
hub->stats.net_rx_total = total->rx;
net_stats_reset();
}
static void hub_timer_statistics(struct timeout_evt* t)
{
struct hub_info* hub = (struct hub_info*) t->ptr;
hub_update_stats(hub);
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS);
}
static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub) static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
{ {
struct net_connection* server; struct net_connection* server;
@@ -653,7 +616,6 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
if (ret == -1) if (ret == -1)
{ {
LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error())); LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
hub_notify(hub, notify_error, "Unable to bind to network address %s on port %d: %s (%d)", bind_addr, port, net_error_string(net_error()), net_error());
net_close(sd); net_close(sd);
return 0; return 0;
} }
@@ -672,60 +634,6 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
return server; return server;
} }
int hub_is_running(struct hub_info* hub)
{
return hub->status == hub_status_running || hub->status == hub_status_restart;
}
void hub_notify(struct hub_info* hub, enum notify_verbosity verbosity, const char* fmt, ...)
{
struct cbuffer* buf;
struct adc_message* msg;
va_list args;
char temp[1024];
va_start(args, fmt);
vsnprintf(temp, sizeof(temp), fmt, args);
va_end(args);
buf = cbuf_create(strlen(temp) + 8);
switch (verbosity)
{
case notify_error:
cbuf_append(buf, "ERROR: ");
LOG_ERROR(temp);
break;
case notify_warn:
cbuf_append(buf, "WARN: ");
LOG_WARN(temp);
break;
case notify_info:
cbuf_append(buf, "INFO: ");
LOG_INFO(temp);
break;
case notify_debug:
cbuf_append(buf, "DEBUG: ");
LOG_DEBUG(temp);
break;
}
cbuf_append(buf, temp);
if (hub_is_running(hub))
{
msg = adc_msg_construct(ADC_CMD_IMSG, 5 + adc_msg_escape_length(cbuf_get(buf)) + 2);
adc_msg_add_argument_string(msg, cbuf_get(buf));
route_to_operators(hub, msg);
adc_msg_free(msg);
}
cbuf_destroy(buf);
}
struct server_alt_port_data struct server_alt_port_data
{ {
struct hub_info* hub; struct hub_info* hub;
@@ -786,73 +694,41 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
{ {
if (config->tls_enable) if (config->tls_enable)
{ {
hub->ctx = net_ssl_context_create(); hub->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */
if (ssl_load_certificate(hub->ctx, config->tls_certificate) && hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
ssl_load_private_key(hub->ctx, config->tls_private_key) &&
ssl_check_private_key(hub->ctx)) /* Disable SSLv2 */
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_quiet_shutdown(hub->ssl_ctx, 1);
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
{ {
LOG_INFO("Enabling TLS (%s), using certificate: %s, private key: %s", net_ssl_get_provider(), config->tls_certificate, config->tls_private_key); LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 1;
} }
if (SSL_CTX_use_PrivateKey_file(hub->ssl_ctx, config->tls_private_key, SSL_FILETYPE_PEM) < 0)
{
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
}
if (SSL_CTX_check_private_key(hub->ssl_ctx) != 1)
{
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
return 0; return 0;
} }
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
}
return 1; return 1;
} }
static void unload_ssl_certificates(struct hub_info* hub) static void unload_ssl_certificates(struct hub_info* hub)
{ {
if (hub->ctx) if (hub->ssl_ctx)
net_ssl_context_destroy(hub->ctx);
}
#endif /* SSL_SUPPORT */
// #ifdef BOT_SUPPORT
static void route_privmsg_to_operators(struct hub_user* bot, sid_t from, const char* escaped_msg, int action)
{ {
struct hub_info* hub = bot->hub; SSL_CTX_free(hub->ssl_ctx);
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (from != user->id.sid && user_flag_get(user, flag_opnotify))
{
struct adc_message* msg = adc_msg_construct_source_dest(ADC_CMD_EMSG, from, user->id.sid, strlen(escaped_msg) + (action * 4) + 7);
adc_msg_add_argument(msg, escaped_msg);
adc_msg_add_named_argument(msg, ADC_MSG_FLAG_PRIVATE, sid_to_string(bot->id.sid));
if (action) adc_msg_add_named_argument(msg, ADC_MSG_FLAG_ACTION, "1");
route_to_user(hub, user, msg);
adc_msg_free(msg);
}
user = (struct hub_user*) list_get_next(hub->users->list);
} }
} }
#endif
/// This receives private messages and transmits them to the connected operators.
static void hub_bot_op_notify_handle(struct hub_user* bot, struct adc_message* msg)
{
char* chat;
LOG_TRACE("Invoked hub_bot_op_notify_handle()");
switch (msg->cmd)
{
case ADC_CMD_EMSG:
case ADC_CMD_DMSG:
chat = adc_msg_get_argument(msg, 0);
LOG_DEBUG("Hub chat: \"%s\"", chat);
route_privmsg_to_operators(bot, msg->source, chat, adc_msg_has_named_argument(msg, ADC_MSG_FLAG_ACTION) ? 1 : 0);
hub_free(chat);
break;
default:
/* ignore these messages! */
break;
}
}
static void hub_bot_op_notify_create(struct hub_info* hub)
{
struct hub_user* opcom = user_create_bot(hub, "Operations", "Hub operators", hub_bot_op_notify_handle);
uman_add(hub->users, opcom);
}
// #endif
struct hub_info* hub_start_service(struct hub_config* config) struct hub_info* hub_start_service(struct hub_config* config)
{ {
@@ -893,8 +769,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
hub->config = config; hub->config = config;
hub->users = NULL; hub->users = NULL;
hub->users = uman_init(); if (uman_init(hub) == -1)
if (!hub->users)
{ {
net_con_close(hub->server); net_con_close(hub->server);
hub_free(hub); hub_free(hub);
@@ -904,7 +779,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1) if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
{ {
net_con_close(hub->server); net_con_close(hub->server);
uman_shutdown(hub->users); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
return 0; return 0;
} }
@@ -916,7 +791,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
net_con_close(hub->server); net_con_close(hub->server);
hub_free(hub->recvbuf); hub_free(hub->recvbuf);
hub_free(hub->sendbuf); hub_free(hub->sendbuf);
uman_shutdown(hub->users); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
return 0; return 0;
} }
@@ -928,17 +803,8 @@ struct hub_info* hub_start_service(struct hub_config* config)
g_hub = hub; g_hub = hub;
if (net_backend_get_timeout_queue())
{
hub->stats.timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(hub->stats.timeout, hub_timer_statistics, hub);
timeout_queue_insert(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS);
}
// Start the hub command sub-system // Start the hub command sub-system
hub->commands = command_initialize(hub); hub->commands = command_initialize(hub);
hub_bot_op_notify_create(hub);
return hub; return hub;
} }
@@ -947,12 +813,6 @@ void hub_shutdown_service(struct hub_info* hub)
{ {
LOG_DEBUG("hub_shutdown_service()"); LOG_DEBUG("hub_shutdown_service()");
if (net_backend_get_timeout_queue())
{
timeout_queue_remove(net_backend_get_timeout_queue(), hub->stats.timeout);
hub_free(hub->stats.timeout);
}
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
unload_ssl_certificates(hub); unload_ssl_certificates(hub);
#endif #endif
@@ -960,7 +820,7 @@ void hub_shutdown_service(struct hub_info* hub)
event_queue_shutdown(hub->queue); event_queue_shutdown(hub->queue);
net_con_close(hub->server); net_con_close(hub->server);
server_alt_port_stop(hub); server_alt_port_stop(hub);
uman_shutdown(hub->users); uman_shutdown(hub);
hub->status = hub_status_stopped; hub->status = hub_status_stopped;
hub_free(hub->sendbuf); hub_free(hub->sendbuf);
hub_free(hub->recvbuf); hub_free(hub->recvbuf);
@@ -1041,7 +901,6 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
if (hub_plugins_load(hub) < 0) if (hub_plugins_load(hub) < 0)
{ {
LOG_FATAL("Unable to load plugins.");
hub->status = hub_status_shutdown; hub->status = hub_status_shutdown;
} }
else else

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -81,7 +81,6 @@ struct hub_stats
size_t net_rx_peak; size_t net_rx_peak;
size_t net_tx_total; size_t net_tx_total;
size_t net_rx_total; size_t net_rx_total;
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
}; };
struct hub_logout_info struct hub_logout_info
@@ -106,7 +105,7 @@ struct hub_info
struct adc_message* command_support; /* The hub's SUP command */ struct adc_message* command_support; /* The hub's SUP command */
struct adc_message* command_banner; /* The default welcome message */ struct adc_message* command_banner; /* The default welcome message */
time_t tm_started; time_t tm_started;
enum hub_state status; int status;
char* recvbuf; /* Global receive buffer */ char* recvbuf; /* Global receive buffer */
char* sendbuf; /* Global send buffer */ char* sendbuf; /* Global send buffer */
@@ -116,7 +115,8 @@ struct hub_info
struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */ struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
struct ssl_context_handle* ctx; SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
#endif /* SSL_SUPPORT */ #endif /* SSL_SUPPORT */
}; };
@@ -233,20 +233,6 @@ extern void hub_set_variables(struct hub_info* hub, struct acl_handle* acl);
*/ */
extern void hub_free_variables(struct hub_info* hub); extern void hub_free_variables(struct hub_info* hub);
enum notify_verbosity
{
notify_error = 0,
notify_warn = 1,
notify_info = 2,
notify_debug = 3,
};
/**
* Send a notification message to operators.
*/
extern void hub_notify(struct hub_info* hub, enum notify_verbosity verbosity, const char* fmt, ...);
/** /**
* Returns a string for the given status_message (See enum status_message). * Returns a string for the given status_message (See enum status_message).
*/ */
@@ -364,10 +350,6 @@ extern void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int
*/ */
extern void hub_logout_log(struct hub_info* hub, struct hub_user* user); extern void hub_logout_log(struct hub_info* hub, struct hub_user* user);
/**
* Returns 1 if the hub is running, and 0 otherwise.
*/
extern int hub_is_running(struct hub_info* hub);
#endif /* HAVE_UHUB_HUB_H */ #endif /* HAVE_UHUB_HUB_H */

View File

@@ -24,16 +24,12 @@
void on_login_success(struct hub_info* hub, struct hub_user* u) void on_login_success(struct hub_info* hub, struct hub_user* u)
{ {
/* Send user list of all existing users */ /* Send user list of all existing users */
if (!uman_send_user_list(hub, hub->users, u)) if (!uman_send_user_list(hub, u))
return; return;
/* Mark as being in the normal state, and add user to the user list */ /* Mark as being in the normal state, and add user to the user list */
user_set_state(u, state_normal); user_set_state(u, state_normal);
uman_add(hub->users, u); uman_add(hub, u);
// Make operators receive hub notifications by default.
if (user_is_protected(u))
user_flag_set(u, flag_opnotify);
/* Announce new user to all connected users */ /* Announce new user to all connected users */
if (user_is_logged_in(u)) if (user_is_logged_in(u))

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
*/ */
#include "uhub.h" #include "uhub.h"
#include "hubio.h"
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
static void debug_msg(const char* prefix, struct adc_message* msg) static void debug_msg(const char* prefix, struct adc_message* msg)
@@ -34,13 +35,13 @@ static void debug_msg(const char* prefix, struct adc_message* msg)
} }
#endif #endif
struct ioq_recv* ioq_recv_create() struct hub_recvq* hub_recvq_create()
{ {
struct ioq_recv* q = hub_malloc_zero(sizeof(struct ioq_recv)); struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
return q; return q;
} }
void ioq_recv_destroy(struct ioq_recv* q) void hub_recvq_destroy(struct hub_recvq* q)
{ {
if (q) if (q)
{ {
@@ -49,9 +50,9 @@ void ioq_recv_destroy(struct ioq_recv* q)
} }
} }
size_t ioq_recv_get(struct ioq_recv* q, void* buf, size_t bufsize) size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
{ {
uhub_assert(bufsize >= q->size); assert(bufsize >= q->size);
if (q->size) if (q->size)
{ {
size_t n = q->size; size_t n = q->size;
@@ -64,7 +65,7 @@ size_t ioq_recv_get(struct ioq_recv* q, void* buf, size_t bufsize)
return 0; return 0;
} }
size_t ioq_recv_set(struct ioq_recv* q, void* buf, size_t bufsize) size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
{ {
if (q->buf) if (q->buf)
{ {
@@ -88,9 +89,9 @@ size_t ioq_recv_set(struct ioq_recv* q, void* buf, size_t bufsize)
} }
struct ioq_send* ioq_send_create() struct hub_sendq* hub_sendq_create()
{ {
struct ioq_send* q = hub_malloc_zero(sizeof(struct ioq_send)); struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
if (!q) if (!q)
return 0; return 0;
@@ -109,7 +110,7 @@ static void clear_send_queue_callback(void* ptr)
adc_msg_free((struct adc_message*) ptr); adc_msg_free((struct adc_message*) ptr);
} }
void ioq_send_destroy(struct ioq_send* q) void hub_sendq_destroy(struct hub_sendq* q)
{ {
if (q) if (q)
{ {
@@ -119,21 +120,21 @@ void ioq_send_destroy(struct ioq_send* q)
} }
} }
void ioq_send_add(struct ioq_send* q, struct adc_message* msg_) void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
{ {
struct adc_message* msg = adc_msg_incref(msg_); struct adc_message* msg = adc_msg_incref(msg_);
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
debug_msg("ioq_send_add", msg); debug_msg("hub_sendq_add", msg);
#endif #endif
uhub_assert(msg->cache && *msg->cache); assert(msg->cache && *msg->cache);
list_append(q->queue, msg); list_append(q->queue, msg);
q->size += msg->length; q->size += msg->length;
} }
void ioq_send_remove(struct ioq_send* q, struct adc_message* msg) void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
{ {
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
debug_msg("ioq_send_remove", msg); debug_msg("hub_sendq_remove", msg);
#endif #endif
list_remove(q->queue, msg); list_remove(q->queue, msg);
q->size -= msg->length; q->size -= msg->length;
@@ -141,13 +142,13 @@ void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
q->offset = 0; q->offset = 0;
} }
int ioq_send_send(struct ioq_send* q, struct net_connection* con) int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
{ {
int ret; int ret;
struct adc_message* msg = list_get_first(q->queue); struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0; if (!msg) return 0;
uhub_assert(msg->cache && *msg->cache); assert(msg->cache && *msg->cache);
ret = net_con_send(con, msg->cache + q->offset, msg->length - q->offset); ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0) if (ret > 0)
{ {
@@ -155,18 +156,18 @@ int ioq_send_send(struct ioq_send* q, struct net_connection* con)
if (msg->length - q->offset > 0) if (msg->length - q->offset > 0)
return 0; return 0;
ioq_send_remove(q, msg); hub_sendq_remove(q, msg);
return 1; return 1;
} }
return ret; return ret;
} }
int ioq_send_is_empty(struct ioq_send* q) int hub_sendq_is_empty(struct hub_sendq* q)
{ {
return (q->size - q->offset) == 0; return (q->size - q->offset) == 0;
} }
size_t ioq_send_get_bytes(struct ioq_send* q) size_t hub_sendq_get_bytes(struct hub_sendq* q)
{ {
return q->size - q->offset; return q->size - q->offset;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -17,25 +17,25 @@
* *
*/ */
#ifndef HAVE_UHUB_IO_QUEUE_H #ifndef HAVE_UHUB_HUB_IO_H
#define HAVE_UHUB_IO_QUEUE_H #define HAVE_UHUB_HUB_IO_H
struct adc_message; struct adc_message;
struct linked_list; struct linked_list;
typedef int (*ioq_write)(void* desc, const void* buf, size_t len); typedef int (*hub_recvq_write)(void* desc, const void* buf, size_t len);
typedef int (*ioq_read)(void* desc, void* buf, size_t len); typedef int (*hub_recvq_read)(void* desc, void* buf, size_t len);
struct ioq_send struct hub_sendq
{ {
size_t size; /** Size of send queue (in bytes, not messages) */ 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. */ size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
#ifdef SSL_SUPPORT #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. */ size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
#endif #endif
struct linked_list* queue; /** List of queued messages (struct adc_message) */ struct linked_list* queue; /** List of queued messages */
}; };
struct ioq_recv struct hub_recvq
{ {
char* buf; char* buf;
size_t size; size_t size;
@@ -44,63 +44,63 @@ struct ioq_recv
/** /**
* Create a send queue * Create a send queue
*/ */
extern struct ioq_send* ioq_send_create(); extern struct hub_sendq* hub_sendq_create();
/** /**
* Destroy a send queue, and delete any queued messages. * Destroy a send queue, and delete any queued messages.
*/ */
extern void ioq_send_destroy(struct ioq_send*); extern void hub_sendq_destroy(struct hub_sendq*);
/** /**
* Add a message to the send queue. * Add a message to the send queue.
*/ */
extern void ioq_send_add(struct ioq_send*, struct adc_message* msg); extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
/** /**
* Process the send queue, and send as many messages as possible. * Process the send queue, and send as many messages as possible.
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent. * @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
*/ */
extern int ioq_send_send(struct ioq_send*, struct net_connection* con); extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
/** /**
* @returns 1 if send queue is empty, 0 otherwise. * @returns 1 if send queue is empty, 0 otherwise.
*/ */
extern int ioq_send_is_empty(struct ioq_send*); extern int hub_sendq_is_empty(struct hub_sendq*);
/** /**
* @returns the number of bytes remaining to be sent in the queue. * @returns the number of bytes remaining to be sent in the queue.
*/ */
extern size_t ioq_send_get_bytes(struct ioq_send*); extern size_t hub_sendq_get_bytes(struct hub_sendq*);
/** /**
* Create a receive queue. * Create a receive queue.
*/ */
extern struct ioq_recv* ioq_recv_create(); extern struct hub_recvq* hub_recvq_create();
/** /**
* Destroy a receive queue. * Destroy a receive queue.
*/ */
extern void ioq_recv_destroy(struct ioq_recv*); extern void hub_recvq_destroy(struct hub_recvq*);
/** /**
* Gets the buffer, copies it into buf and deallocates it. * Gets the buffer, copies it into buf and deallocates it.
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts. * NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
* @return the number of bytes copied into buf. * @return the number of bytes copied into buf.
*/ */
extern size_t ioq_recv_get(struct ioq_recv*, void* buf, size_t bufsize); extern size_t hub_recvq_get(struct hub_recvq*, void* buf, size_t bufsize);
/** /**
* Sets the buffer * Sets the buffer
*/ */
extern size_t ioq_recv_set(struct ioq_recv*, void* buf, size_t bufsize); extern size_t hub_recvq_set(struct hub_recvq*, void* buf, size_t bufsize);
/** /**
* @return 1 if size is zero, 0 otherwise. * @return 1 if size is zero, 0 otherwise.
*/ */
extern int ioq_recv_is_empty(struct ioq_recv* buf); extern int hub_recvq_is_empty(struct hub_recvq* buf);
#endif /* HAVE_UHUB_IO_QUEUE_H */ #endif /* HAVE_UHUB_HUB_IO_H */

View File

@@ -226,7 +226,9 @@ static int check_network(struct hub_info* hub, struct hub_user* user, struct adc
static void strip_network(struct hub_user* user, struct adc_message* cmd) static void strip_network(struct hub_user* user, struct adc_message* cmd)
{ {
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
} }
static int nick_length_ok(const char* nick) static int nick_length_ok(const char* nick)
@@ -325,8 +327,8 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
struct hub_user* lookup1 = uman_get_user_by_nick(hub->users, user->id.nick); struct hub_user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
struct hub_user* lookup2 = uman_get_user_by_cid(hub->users, user->id.cid); struct hub_user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
if (lookup1 == user) if (lookup1 == user)
{ {

View File

@@ -19,10 +19,6 @@
#include "uhub.h" #include "uhub.h"
#ifdef SYSTEMD
#include <systemd/sd-daemon.h>
#endif
static int arg_verbose = 5; static int arg_verbose = 5;
static int arg_fork = 0; static int arg_fork = 0;
static int arg_check_config = 0; static int arg_check_config = 0;
@@ -140,25 +136,10 @@ int main_loop()
{ {
hub = hub_start_service(&configuration); hub = hub_start_service(&configuration);
if (!hub) if (!hub)
{
acl_shutdown(&acl);
free_config(&configuration);
net_destroy();
hub_log_shutdown();
return -1; return -1;
}
#if !defined(WIN32) #if !defined(WIN32)
setup_signal_handlers(hub); setup_signal_handlers(hub);
#ifdef SYSTEMD #endif
/* Notify the service manager that this daemon has
* been successfully initalized and shall enter the
* main loop.
*/
sd_notifyf(0, "READY=1\n"
"MAINPID=%lu", (unsigned long) getpid());
#endif /* SYSTEMD */
#endif /* ! WIN32 */
} }
hub_set_variables(hub, &acl); hub_set_variables(hub, &acl);
@@ -229,17 +210,13 @@ void print_usage(char* program)
" -q Quiet mode - no output\n" " -q Quiet mode - no output\n"
" -f Fork to background\n" " -f Fork to background\n"
" -l <file> Log messages to given file (default: stderr)\n" " -l <file> Log messages to given file (default: stderr)\n"
" -L Log messages to syslog\n"
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n" " -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
" -C Check configuration and return\n" " -C Check configuration and return\n"
" -s Show configuration parameters\n" " -s Show configuration parameters\n"
" -S Show configuration parameters, but ignore defaults\n" " -S Show configuration parameters, but ignore defaults\n"
" -h This message\n" " -h This message\n"
#ifndef WIN32 #ifndef WIN32
#ifdef SYSTEMD
" -L Log messages to journal\n"
#else
" -L Log messages to syslog\n"
#endif
" -u <user> Run as given user\n" " -u <user> Run as given user\n"
" -g <group> Run with given group permissions\n" " -g <group> Run with given group permissions\n"
" -p <file> Store pid in file (process id)\n" " -p <file> Store pid in file (process id)\n"

View File

@@ -18,14 +18,17 @@
*/ */
#include <uhub.h> #include <uhub.h>
#include "ioqueue.h" #include "hubio.h"
#include "probe.h" #include "probe.h"
/* FIXME: This should not be needed! */
extern struct hub_info* g_hub;
int handle_net_read(struct hub_user* user) int handle_net_read(struct hub_user* user)
{ {
static char buf[MAX_RECV_BUF]; static char buf[MAX_RECV_BUF];
struct ioq_recv* q = user->recv_queue; struct hub_recvq* q = user->recv_queue;
size_t buf_size = ioq_recv_get(q, buf, MAX_RECV_BUF); size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
ssize_t size; ssize_t size;
if (user_flag_get(user, flag_maxbuf)) if (user_flag_get(user, flag_maxbuf))
@@ -55,7 +58,7 @@ int handle_net_read(struct hub_user* user)
while ((pos = memchr(start, '\n', remaining))) while ((pos = memchr(start, '\n', remaining)))
{ {
lastPos = pos+1; lastPos = pos;
pos[0] = '\0'; pos[0] = '\0';
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
@@ -68,9 +71,9 @@ int handle_net_read(struct hub_user* user)
} }
else else
{ {
if (((pos - start) > 0) && user->hub->config->max_recv_buffer > (pos - start)) if (((pos - start) > 0) && g_hub->config->max_recv_buffer > (pos - start))
{ {
if (hub_handle_message(user->hub, user, start, (pos - start)) == -1) if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
{ {
return quit_protocol_error; return quit_protocol_error;
} }
@@ -85,20 +88,20 @@ int handle_net_read(struct hub_user* user)
if (lastPos || remaining) if (lastPos || remaining)
{ {
if (remaining < (size_t) user->hub->config->max_recv_buffer) if (remaining < (size_t) g_hub->config->max_recv_buffer)
{ {
ioq_recv_set(q, lastPos ? lastPos : buf, remaining); hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
} }
else else
{ {
ioq_recv_set(q, 0, 0); hub_recvq_set(q, 0, 0);
user_flag_set(user, flag_maxbuf); user_flag_set(user, flag_maxbuf);
LOG_WARN("Received message past max_recv_buffer, dropping message."); LOG_WARN("Received message past max_recv_buffer, dropping message.");
} }
} }
else else
{ {
ioq_recv_set(q, 0, 0); hub_recvq_set(q, 0, 0);
} }
} }
return 0; return 0;
@@ -107,9 +110,9 @@ int handle_net_read(struct hub_user* user)
int handle_net_write(struct hub_user* user) int handle_net_write(struct hub_user* user)
{ {
int ret = 0; int ret = 0;
while (ioq_send_get_bytes(user->send_queue)) while (hub_sendq_get_bytes(user->send_queue))
{ {
ret = ioq_send_send(user->send_queue, user->connection); ret = hub_sendq_send(user->send_queue, user);
if (ret <= 0) if (ret <= 0)
break; break;
} }
@@ -117,7 +120,7 @@ int handle_net_write(struct hub_user* user)
if (ret < 0) if (ret < 0)
return quit_socket_error; return quit_socket_error;
if (ioq_send_get_bytes(user->send_queue)) if (hub_sendq_get_bytes(user->send_queue))
{ {
user_net_io_want_write(user); user_net_io_want_write(user);
} }
@@ -141,7 +144,7 @@ void net_event(struct net_connection* con, int event, void *arg)
{ {
if (user_is_connecting(user)) if (user_is_connecting(user))
{ {
hub_disconnect_user(user->hub, user, quit_timeout); hub_disconnect_user(g_hub, user, quit_timeout);
} }
return; return;
} }
@@ -151,7 +154,7 @@ void net_event(struct net_connection* con, int event, void *arg)
flag_close = handle_net_read(user); flag_close = handle_net_read(user);
if (flag_close) if (flag_close)
{ {
hub_disconnect_user(user->hub, user, flag_close); hub_disconnect_user(g_hub, user, flag_close);
return; return;
} }
} }
@@ -161,7 +164,7 @@ void net_event(struct net_connection* con, int event, void *arg)
flag_close = handle_net_write(user); flag_close = handle_net_write(user);
if (flag_close) if (flag_close)
{ {
hub_disconnect_user(user->hub, user, flag_close); hub_disconnect_user(g_hub, user, flag_close);
return; return;
} }
} }

View File

@@ -27,7 +27,10 @@ struct plugin_callback_data
static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin) static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin)
{ {
return get_internals(plugin)->callback_data; struct plugin_callback_data* data;
uhub_assert(plugin && plugin->handle && plugin->handle->internals);
data = (struct plugin_callback_data*) plugin->handle->internals;
return data;
} }
static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd) static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
@@ -51,6 +54,26 @@ static int plugin_command_dispatch(struct command_base* cbase, struct hub_user*
return 0; return 0;
} }
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_callback_data* data)
{
LOG_PLUGIN("plugin_callback_data_destroy()");
if (data->commands)
{
uhub_assert(list_size(data->commands) == 0);
list_destroy(data->commands);
}
hub_free(data);
}
static struct hub_user* convert_user_type(struct plugin_user* user) static struct hub_user* convert_user_type(struct plugin_user* user)
{ {
struct hub_user* huser = (struct hub_user*) user; struct hub_user* huser = (struct hub_user*) user;
@@ -59,6 +82,7 @@ static struct hub_user* convert_user_type(struct plugin_user* user)
static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, const char* message) static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, const char* message)
{ {
// struct plugin_callback_data* data = get_callback_data(plugin);
char* buffer = adc_msg_escape(message); char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6); struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer); adc_msg_add_argument(command, buffer);
@@ -70,6 +94,7 @@ static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user*
static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message) static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
{ {
// struct plugin_callback_data* data = get_callback_data(plugin);
char code_str[4]; char code_str[4];
char* buffer = adc_msg_escape(message); char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10); struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10);
@@ -84,6 +109,7 @@ static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user*
static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user) static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user)
{ {
// struct plugin_callback_data* data = get_callback_data(plugin);
hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked); hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked);
return 0; return 0;
} }
@@ -104,7 +130,7 @@ static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_comman
cmdh->internal_handle = command; cmdh->internal_handle = command;
list_append(data->commands, cmdh); list_append(data->commands, cmdh);
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin); command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
LOG_DEBUG("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh); printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
return 0; return 0;
} }
@@ -113,7 +139,7 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman
struct plugin_callback_data* data = get_callback_data(plugin); struct plugin_callback_data* data = get_callback_data(plugin);
struct command_handle* command = (struct command_handle*) cmdh->internal_handle; struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
LOG_DEBUG("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh); printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
list_remove(data->commands, cmdh); list_remove(data->commands, cmdh);
command_del(plugin_get_hub(plugin)->commands, command); command_del(plugin_get_hub(plugin)->commands, command);
hub_free(command); hub_free(command);
@@ -121,69 +147,6 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman
return 0; 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 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) void plugin_register_callback_functions(struct plugin_handle* handle)
{ {
@@ -192,37 +155,8 @@ void plugin_register_callback_functions(struct plugin_handle* handle)
handle->hub.user_disconnect = cbfunc_user_disconnect; handle->hub.user_disconnect = cbfunc_user_disconnect;
handle->hub.command_add = cbfunc_command_add; handle->hub.command_add = cbfunc_command_add;
handle->hub.command_del = cbfunc_command_del; handle->hub.command_del = cbfunc_command_del;
handle->hub.command_arg_reset = cbfunc_command_arg_reset;
handle->hub.command_arg_next = cbfunc_command_arg_next;
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) 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

@@ -24,7 +24,7 @@ struct plugin_handle;
struct uhub_plugin; struct uhub_plugin;
extern struct plugin_callback_data* plugin_callback_data_create(); 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_callback_data_destroy(struct plugin_callback_data* data);
extern void plugin_register_callback_functions(struct plugin_handle* plugin); extern void plugin_register_callback_functions(struct plugin_handle* plugin);
extern void plugin_unregister_callback_functions(struct plugin_handle* plugin); extern void plugin_unregister_callback_functions(struct plugin_handle* plugin);

View File

@@ -82,13 +82,12 @@ static struct plugin_user* convert_user_type(struct hub_user* user)
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr) 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_INVOKE_STATUS_1(hub, login_check_ip_early, addr);
} }
plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* who, struct ip_addr_encap* addr) plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr)
{ {
struct plugin_user* user = convert_user_type(who); PLUGIN_INVOKE_STATUS_1(hub, login_check_ip_late, addr);
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) void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)

View File

@@ -38,7 +38,7 @@ void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const
/* IP ban related */ /* IP ban related */
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr); 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); plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr);
/* Nickname allow/deny handling */ /* Nickname allow/deny handling */
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick); plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);

View File

@@ -23,10 +23,17 @@
struct plugin_callback_data; struct plugin_callback_data;
struct plugin_hub_internals* get_internals(struct plugin_handle* handle) 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 */
};
static struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
{ {
struct plugin_hub_internals* internals; struct plugin_hub_internals* internals;
uhub_assert(handle && handle->handle && handle->handle->internals); assert(handle && handle->handle && handle->handle->internals);
internals = (struct plugin_hub_internals*) handle->handle->internals; internals = (struct plugin_hub_internals*) handle->handle->internals;
return internals; return internals;
} }
@@ -69,7 +76,7 @@ void plugin_close(struct uhub_plugin* plugin)
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals; struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename); LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename);
plugin_callback_data_destroy(plugin->handle, internals->callback_data); plugin_callback_data_destroy(internals->callback_data);
hub_free(internals); hub_free(internals);
plugin->internals = NULL; plugin->internals = NULL;
@@ -155,8 +162,8 @@ struct plugin_handle* plugin_load(const char* filename, const char* config, stru
void plugin_unload(struct plugin_handle* plugin) void plugin_unload(struct plugin_handle* plugin)
{ {
struct plugin_hub_internals* internals = get_internals(plugin); struct plugin_hub_internals* internals = get_internals(plugin);
internals->unregister(plugin);
plugin_unregister_callback_functions(plugin); plugin_unregister_callback_functions(plugin);
internals->unregister(plugin);
plugin_close(plugin->handle); plugin_close(plugin->handle);
hub_free(plugin); hub_free(plugin);
} }

View File

@@ -32,7 +32,7 @@ struct uhub_plugin
void* handle; void* handle;
plugin_unregister_f unregister; plugin_unregister_f unregister;
char* filename; char* filename;
void* internals; // Hub-internal stuff (struct plugin_hub_internals) void* internals; // Hub internal stuff
}; };
struct uhub_plugins struct uhub_plugins
@@ -40,7 +40,7 @@ struct uhub_plugins
struct linked_list* loaded; struct linked_list* loaded;
}; };
// High level plugin loader code // High level plugin loader ode
extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub); 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* plugin);
@@ -54,14 +54,7 @@ extern void plugin_close(struct uhub_plugin*);
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol); extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
// Used internally only // 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*); extern struct hub_info* plugin_get_hub(struct plugin_handle*);
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */ #endif /* HAVE_UHUB_PLUGIN_LOADER_H */

View File

@@ -76,20 +76,21 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
probe_recvbuf[0] == 22 && probe_recvbuf[0] == 22 &&
probe_recvbuf[1] == 3 && /* protocol major version */ probe_recvbuf[1] == 3 && /* protocol major version */
probe_recvbuf[5] == 1 && /* message type */ probe_recvbuf[5] == 1 && /* message type */
probe_recvbuf[9] == probe_recvbuf[1]) probe_recvbuf[9] == probe_recvbuf[1] &&
probe_recvbuf[10] == probe_recvbuf[2])
{ {
if (probe->hub->config->tls_enable) if (probe->hub->config->tls_enable)
{ {
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[9], (int) probe_recvbuf[10]); LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
if (user_create(probe->hub, probe->connection, &probe->addr)) if (user_create(probe->hub, probe->connection, &probe->addr))
{ {
probe->connection = 0; probe->connection = 0;
} }
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ctx); net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
} }
else else
{ {
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[9], (int) probe_recvbuf[10]); LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
} }
} }
else else

View File

@@ -30,7 +30,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
break; break;
case 'D': case 'D':
target = uman_get_user_by_sid(hub->users, msg->target); target = uman_get_user_by_sid(hub, msg->target);
if (target) if (target)
{ {
route_to_user(hub, target, msg); route_to_user(hub, target, msg);
@@ -38,7 +38,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
break; break;
case 'E': case 'E':
target = uman_get_user_by_sid(hub->users, msg->target); target = uman_get_user_by_sid(hub, msg->target);
if (target) if (target)
{ {
route_to_user(hub, target, msg); route_to_user(hub, target, msg);
@@ -104,33 +104,21 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
#endif #endif
if (!user->connection) if (!user->connection)
{
switch (user->type)
{
case user_type_client:
return 0; // No connection - we're about to drop this user.
case user_type_bot:
{
bot_recv_msg handler = (bot_recv_msg) user->ptr;
handler(user, msg);
return 0; return 0;
}
}
}
uhub_assert(msg->cache && *msg->cache); assert(msg->cache && *msg->cache);
if (ioq_send_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline)) if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
{ {
/* Perform oportunistic write */ /* Perform oportunistic write */
ioq_send_add(user->send_queue, msg); hub_sendq_add(user->send_queue, msg);
handle_net_write(user); handle_net_write(user);
} }
else else
{ {
if (check_send_queue(hub, user, msg) >= 0) if (check_send_queue(hub, user, msg) >= 0)
{ {
ioq_send_add(user->send_queue, msg); hub_sendq_add(user->send_queue, msg);
if (!user_flag_get(user, flag_pipeline)) if (!user_flag_get(user, flag_pipeline))
user_net_io_want_write(user); user_net_io_want_write(user);
} }
@@ -140,7 +128,7 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u) int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
{ {
if (ioq_send_is_empty(u->send_queue)) if (hub_sendq_is_empty(u->send_queue))
return 0; return 0;
handle_net_write(u); handle_net_write(u);
@@ -161,19 +149,6 @@ int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate u
return 0; return 0;
} }
int route_to_operators(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (user_flag_get(user, flag_opnotify))
route_to_user(hub, user, command);
user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0;
}
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
{ {
int do_send; int do_send;

View File

@@ -40,14 +40,6 @@ extern int route_to_user(struct hub_info* hub, struct hub_user*, struct adc_mess
*/ */
extern int route_to_all(struct hub_info* hub, struct adc_message* command); extern int route_to_all(struct hub_info* hub, struct adc_message* command);
/**
* Send a message to all operators.
* Technically it sends to all users with the flag_opnotify set
* which is intended to be set for only operators - allowing operators to opt-out
* of these messages.
*/
extern int route_to_operators(struct hub_info* hub, struct adc_message* command);
/** /**
* Broadcast message to all users subscribing to the type of message. * Broadcast message to all users subscribing to the type of message.
*/ */

View File

@@ -42,84 +42,34 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con)); LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user)); user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL) if (user == NULL)
return NULL; /* OOM */ return NULL; /* OOM */
user->send_queue = ioq_send_create(); user->send_queue = hub_sendq_create();
user->recv_queue = ioq_recv_create(); user->recv_queue = hub_recvq_create();
user->connection = con; user->connection = con;
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ); net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap)); memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
user_set_state(user, state_protocol); user_set_state(user, state_protocol);
user->type = user_type_client;
flood_control_reset(&user->flood_chat); flood_control_reset(&user->flood_chat);
flood_control_reset(&user->flood_connect); flood_control_reset(&user->flood_connect);
flood_control_reset(&user->flood_search); flood_control_reset(&user->flood_search);
flood_control_reset(&user->flood_update); flood_control_reset(&user->flood_update);
flood_control_reset(&user->flood_extras); flood_control_reset(&user->flood_extras);
user->hub = hub;
return user; return user;
} }
/// generate a semi-stable CID: base32_encode(tiger({hub name} + {nick}))
static const char* generate_bot_cid(struct hub_info* hub, const char* nick)
{
static char result[MAX_CID_LEN+1];
char buf[(MAX_NICK_LEN*2)+1];
uint64_t tiger_res[3];
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%s%s", hub->config->hub_name, nick);
tiger((uint64_t*) buf, sizeof(buf), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, result);
result[MAX_CID_LEN] = 0;
return result;
}
struct hub_user* user_create_bot(struct hub_info* hub, const char* nick, const char* description, bot_recv_msg msg_handler)
{
struct hub_user* user = NULL;
LOG_TRACE("user_create_bot(), hub=%p, nick=\"%s\"", hub, nick);
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL)
return NULL; /* OOM */
strcpy(user->id.nick, nick);
uman_get_free_sid(hub->users, user);
user_set_state(user, state_normal);
user->type = user_type_bot;
user->credentials = auth_cred_bot;
// The message handler
user->ptr = (void*) msg_handler;
user->info = adc_msg_construct(ADC_CMD_BINF, 15);
if (user->info)
{
adc_msg_add_argument(user->info, sid_to_string(user->id.sid));
adc_msg_add_named_argument(user->info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_BOT);
adc_msg_add_named_argument_string(user->info, ADC_INF_FLAG_USER_AGENT, PRODUCT_STRING);
adc_msg_add_named_argument_string(user->info, ADC_INF_FLAG_NICK, nick);
adc_msg_add_named_argument_string(user->info, ADC_INF_FLAG_DESCRIPTION, description);
adc_msg_add_named_argument(user->info, ADC_INF_FLAG_CLIENT_ID, generate_bot_cid(hub, nick));
}
user->hub = hub;
return user;
}
void user_destroy(struct hub_user* user) void user_destroy(struct hub_user* user)
{ {
LOG_TRACE("user_destroy(), user=%p", user); LOG_TRACE("user_destroy(), user=%p", user);
ioq_recv_destroy(user->recv_queue); hub_recvq_destroy(user->recv_queue);
ioq_send_destroy(user->send_queue); hub_sendq_destroy(user->send_queue);
if (user->connection) if (user->connection)
{ {

View File

@@ -47,7 +47,6 @@ enum user_flags
feature_link = 0x00000100, /** LINK: Hub link (not supported) */ feature_link = 0x00000100, /** LINK: Hub link (not supported) */
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */ feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */ feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
flag_opnotify = 0x00200000, /** User should receive operation notifications. NOTE: Only operators should have this flag! */
flag_flood = 0x00400000, /** User has been notified about flooding. */ flag_flood = 0x00400000, /** User has been notified about flooding. */
flag_muted = 0x00800000, /** User is muted (cannot chat) */ flag_muted = 0x00800000, /** User is muted (cannot chat) */
flag_ignore = 0x01000000, /** Ignore further reads */ flag_ignore = 0x01000000, /** Ignore further reads */
@@ -105,30 +104,21 @@ struct hub_user_limits
size_t hub_count_total; /** The number of hubs connected to in total */ size_t hub_count_total; /** The number of hubs connected to in total */
}; };
enum user_type
{
user_type_client, /** A user connected normally as an ADC client */
user_type_bot, /** Not really a user, but a bot inside the hub */
};
typedef void (*bot_recv_msg)(struct hub_user*, struct adc_message* msg);
struct hub_user struct hub_user
{ {
struct hub_user_info id; /** Contains nick name and CID */ struct hub_user_info id; /** Contains nick name and CID */
enum auth_credentials credentials; /** see enum user_credentials */ enum auth_credentials credentials; /** see enum user_credentials */
enum user_state state; /** see enum user_state */ enum user_state state; /** see enum user_state */
enum user_type type; uint32_t flags; /** see enum user_features */
uint32_t flags; /** see enum user_flags */
struct linked_list* feature_cast; /** Features supported by feature cast */ struct linked_list* feature_cast; /** Features supported by feature cast */
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */ struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
struct hub_info* hub; /** The hub instance this user belong to */ struct hub_info* hub; /** The hub instance this user belong to */
void* ptr; struct hub_recvq* recv_queue;
struct ioq_recv* recv_queue; struct hub_sendq* send_queue;
struct ioq_send* send_queue;
struct net_connection* connection; /** Connection data */ struct net_connection* connection; /** Connection data */
struct hub_user_limits limits; /** Data used for limitation */ struct hub_user_limits limits; /** Data used for limitation */
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */ enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
struct flood_control flood_chat; struct flood_control flood_chat;
struct flood_control flood_connect; struct flood_control flood_connect;
struct flood_control flood_search; struct flood_control flood_search;
@@ -148,7 +138,6 @@ struct hub_user
* @return User object or NULL if not enough memory is available. * @return User object or NULL if not enough memory is available.
*/ */
extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr); extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr);
extern struct hub_user* user_create_bot(struct hub_info* hub, const char* nick, const char* description, bot_recv_msg msg_handler);
/** /**
* Delete a user. * Delete a user.

View File

@@ -38,12 +38,50 @@ static void clear_user_list_callback(void* ptr)
} }
} }
void uman_update_stats(struct hub_info* hub)
struct hub_user_manager* uman_init()
{ {
struct hub_user_manager* users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager)); const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
hub->stats.net_tx = (intermediate->tx / factor);
hub->stats.net_rx = (intermediate->rx / factor);
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
hub->stats.net_tx_total = total->tx;
hub->stats.net_rx_total = total->rx;
net_stats_reset();
}
void uman_print_stats(struct hub_info* hub)
{
LOG_INFO("Statistics users=" PRINTF_SIZE_T " (peak_users=" PRINTF_SIZE_T "), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
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);
}
static void timer_statistics(struct timeout_evt* t)
{
struct hub_info* hub = (struct hub_info*) t->ptr;
uman_update_stats(hub);
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->users->timeout, TIMEOUT_STATS);
}
int uman_init(struct hub_info* hub)
{
struct hub_user_manager* users = NULL;
if (!hub)
return -1;
users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
if (!users) if (!users)
return NULL; return -1;
users->list = list_create(); users->list = list_create();
users->sids = sid_pool_create(net_get_max_sockets()); users->sids = sid_pool_create(net_get_max_sockets());
@@ -52,119 +90,143 @@ struct hub_user_manager* uman_init()
{ {
list_destroy(users->list); list_destroy(users->list);
hub_free(users); hub_free(users);
return NULL;
}
return users;
}
int uman_shutdown(struct hub_user_manager* users)
{
if (!users)
return -1; return -1;
if (users->list)
{
list_clear(users->list, &clear_user_list_callback);
list_destroy(users->list);
} }
sid_pool_destroy(users->sids);
hub_free(users); if (net_backend_get_timeout_queue())
{
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(users->timeout, timer_statistics, hub);
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
}
hub->users = users;
return 0; return 0;
} }
int uman_add(struct hub_user_manager* users, struct hub_user* user) int uman_shutdown(struct hub_info* hub)
{ {
if (!users || !user) if (!hub || !hub->users)
return -1; return -1;
list_append(users->list, user); if (net_backend_get_timeout_queue())
users->count++; {
users->count_peak = MAX(users->count, users->count_peak); timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
hub_free(hub->users->timeout);
}
if (hub->users->list)
{
list_clear(hub->users->list, &clear_user_list_callback);
list_destroy(hub->users->list);
}
sid_pool_destroy(hub->users->sids);
hub_free(hub->users);
hub->users = 0;
users->shared_size += user->limits.shared_size;
users->shared_files += user->limits.shared_files;
return 0; return 0;
} }
int uman_remove(struct hub_user_manager* users, struct hub_user* user)
int uman_add(struct hub_info* hub, struct hub_user* user)
{ {
if (!users || !user) if (!hub || !user)
return -1; return -1;
list_remove(users->list, user); if (user->hub)
return -1;
if (users->count > 0) list_append(hub->users->list, user);
hub->users->count++;
hub->users->count_peak = MAX(hub->users->count, hub->users->count_peak);
hub->users->shared_size += user->limits.shared_size;
hub->users->shared_files += user->limits.shared_files;
user->hub = hub;
return 0;
}
int uman_remove(struct hub_info* hub, struct hub_user* user)
{ {
users->count--; if (!hub || !user)
return -1;
list_remove(hub->users->list, user);
if (hub->users->count > 0)
{
hub->users->count--;
} }
else else
{ {
uhub_assert(!"negative count!"); assert(!"negative count!");
} }
users->shared_size -= user->limits.shared_size; hub->users->shared_size -= user->limits.shared_size;
users->shared_files -= user->limits.shared_files; hub->users->shared_files -= user->limits.shared_files;
user->hub = 0;
return 0; return 0;
} }
struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid) struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid)
{ {
return sid_lookup(users->sids, sid); return sid_lookup(hub->users->sids, sid);
} }
struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid) struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid)
{ {
struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */ struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user) while (user)
{ {
if (strcmp(user->id.cid, cid) == 0) if (strcmp(user->id.cid, cid) == 0)
return user; return user;
user = (struct hub_user*) list_get_next(users->list); user = (struct hub_user*) list_get_next(hub->users->list);
} }
return NULL; return NULL;
} }
struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick) struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick)
{ {
struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */ struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user) while (user)
{ {
if (strcmp(user->id.nick, nick) == 0) if (strcmp(user->id.nick, nick) == 0)
return user; return user;
user = (struct hub_user*) list_get_next(users->list); user = (struct hub_user*) list_get_next(hub->users->list);
} }
return NULL; return NULL;
} }
size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range) size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range)
{ {
size_t num = 0; size_t num = 0;
struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */ struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user) while (user)
{ {
if (ip_in_range(&user->id.addr, range)) if (ip_in_range(&user->id.addr, range))
{ {
list_append(target, user); list_append(users, user);
num++; num++;
} }
user = (struct hub_user*) list_get_next(users->list); user = (struct hub_user*) list_get_next(hub->users->list);
} }
return num; return num;
} }
int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* target) int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
{ {
int ret = 1; int ret = 1;
struct hub_user* user; struct hub_user* user;
user_flag_set(target, flag_user_list); user_flag_set(target, flag_user_list);
user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on INF or PAS msg */ user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
while (user) while (user)
{ {
if (user_is_logged_in(user)) if (user_is_logged_in(user))
@@ -173,7 +235,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st
if (!ret) if (!ret)
break; break;
} }
user = (struct hub_user*) list_get_next(users->list); user = (struct hub_user*) list_get_next(hub->users->list);
} }
#if 0 #if 0
@@ -186,7 +248,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st
return ret; return ret;
} }
void uman_send_quit_message(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* leaving) void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
{ {
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6); struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid)); adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
@@ -199,9 +261,9 @@ void uman_send_quit_message(struct hub_info* hub, struct hub_user_manager* users
adc_msg_free(command); adc_msg_free(command);
} }
sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user* user) sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
{ {
sid_t sid = sid_alloc(users->sids, user); sid_t sid = sid_alloc(hub->users->sids, user);
user->id.sid = sid; user->id.sid = sid;
return sid; return sid;
} }

View File

@@ -28,35 +28,36 @@ struct hub_user_manager
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */ uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */ uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct linked_list* list; /**<< "Contains all logged in users" */ struct linked_list* list; /**<< "Contains all logged in users" */
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
}; };
/** /**
* Initializes the user manager. * Initializes the user manager.
* @return 0 on success, or -1 if error (out of memory). * @return 0 on success, or -1 if error (out of memory).
*/ */
extern struct hub_user_manager* uman_init(); extern int uman_init(struct hub_info* hub);
/** /**
* Shuts down the user manager. * Shuts down the user manager.
* All users will be disconnected and deleted as part of this. * All users will be disconnected and deleted as part of this.
* *
* @return 0 on success, or -1 in an error occured (invalid pointer). * @return 0 on success, or -1 in an error occured (hub is invalid).
*/ */
extern int uman_shutdown(struct hub_user_manager* users); extern int uman_shutdown(struct hub_info* hub);
/** /**
* Generate statistics for logfiles. * Generate statistics for logfiles.
*/ */
extern void uman_update_stats(struct hub_user_manager* users); extern void uman_update_stats(struct hub_info* hub);
extern void uman_print_stats(struct hub_user_manager* users); extern void uman_print_stats(struct hub_info* hub);
/** /**
* Add a user to the user manager. * Add a user to the user manager.
* *
* @param users The usermanager to add the user to * @param hub The hub to add the user to
* @param user The user to be added to the hub. * @param user The user to be added to the hub.
*/ */
extern int uman_add(struct hub_user_manager* users, struct hub_user* user); extern int uman_add(struct hub_info* hub, struct hub_user* user);
/** /**
* Remove a user from the user manager. * Remove a user from the user manager.
@@ -65,12 +66,12 @@ extern int uman_add(struct hub_user_manager* users, struct hub_user* user);
* *
* @return 0 if successfully removed, -1 if error. * @return 0 if successfully removed, -1 if error.
*/ */
extern int uman_remove(struct hub_user_manager* users, struct hub_user* user); extern int uman_remove(struct hub_info* hub, struct hub_user* user);
/** /**
* Returns and allocates an unused session ID (SID). * Returns and allocates an unused session ID (SID).
*/ */
extern sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user* user); extern sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user);
/** /**
* Lookup a user based on the session ID (SID). * Lookup a user based on the session ID (SID).
@@ -85,28 +86,26 @@ extern sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user*
* *
* @return a user if found, or NULL if not found * @return a user if found, or NULL if not found
*/ */
extern struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid); extern struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid);
/** /**
* Lookup a user based on the client ID (CID). * Lookup a user based on the client ID (CID).
* @return a user if found, or NULL if not found * @return a user if found, or NULL if not found
*/ */
extern struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid); extern struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid);
/** /**
* Lookup a user based on the nick name. * Lookup a user based on the nick name.
* @return a user if found, or NULL if not found * @return a user if found, or NULL if not found
*/ */
extern struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick); extern struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
/** /**
* Lookup users based on an ip address range. * Lookup users based on an ip address range.
* *
* @param[out] target the list of users matching the address
* @param range the IP range of users to match
* @return The number of users matching the addressess, or -1 on error (mask is wrong). * @return The number of users matching the addressess, or -1 on error (mask is wrong).
*/ */
extern size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range); extern size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range);
/** /**
* Send the user list of connected clients to 'user'. * Send the user list of connected clients to 'user'.
@@ -114,13 +113,13 @@ extern size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linke
* *
* @return 1 if sending the user list succeeded, 0 otherwise. * @return 1 if sending the user list succeeded, 0 otherwise.
*/ */
extern int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* user); extern int uman_send_user_list(struct hub_info* hub, struct hub_user* user);
/** /**
* Send a quit message to all connected users when 'user' is * Send a quit message to all connected users when 'user' is
* leaving the hub (for whatever reason). * leaving the hub (for whatever reason).
*/ */
extern void uman_send_quit_message(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* user); extern void uman_send_quit_message(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_USER_MANAGER_H */ #endif /* HAVE_UHUB_USER_MANAGER_H */

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -132,10 +132,9 @@ struct timeout_queue* net_backend_get_timeout_queue()
*/ */
int net_backend_process() int net_backend_process()
{ {
int res = 0; int res;
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now); size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
if (g_backend->common.num)
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000); res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
g_backend->now = time(0); g_backend->now = time(0);
@@ -147,9 +146,6 @@ int net_backend_process()
return 0; return 0;
} }
// Process pending DNS results
net_dns_process();
g_backend->handler.backend_process(g_backend->data, res); g_backend->handler.backend_process(g_backend->data, res);
net_cleanup_process(g_backend->cleaner); net_cleanup_process(g_backend->cleaner);
@@ -185,8 +181,11 @@ void net_con_close(struct net_connection* con)
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (con->ssl) if (con->ssl)
net_ssl_shutdown(con); {
#endif /* SSL_SUPPORT */ SSL_shutdown(con->ssl);
SSL_clear(con->ssl);
}
#endif
net_close(con->sd); net_close(con->sd);
con->sd = -1; con->sd = -1;

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -20,10 +20,11 @@
#define NET_WANT_READ NET_EVENT_READ #define NET_WANT_READ NET_EVENT_READ
#define NET_WANT_WRITE NET_EVENT_WRITE #define NET_WANT_WRITE NET_EVENT_WRITE
#define NET_WANT_ACCEPT NET_EVENT_READ #define NET_WANT_ACCEPT NET_EVENT_READ
#define NET_WANT_SSL_READ 0x0010
#define NET_SSL_ANY NET_WANT_SSL_READ | NET_WANT_SSL_WRITE | NET_WANT_SSL_ACCEPT | NET_WANT_SSL_CONNECT | NET_WANT_SSL_X509_LOOKUP #define NET_WANT_SSL_WRITE 0x0020
#define NET_WANT_SSL_ACCEPT 0x0040
struct ssl_handle; /* abstract type */ #define NET_WANT_SSL_CONNECT 0x0080
#define NET_WANT_SSL_X509_LOOKUP 0x0100
#define NET_CLEANUP 0x8000 #define NET_CLEANUP 0x8000
@@ -35,7 +36,9 @@ struct ssl_handle; /* abstract type */
struct timeout_evt* timeout; /** timeout event handler */ struct timeout_evt* timeout; /** timeout event handler */
#define NET_CON_STRUCT_SSL \ #define NET_CON_STRUCT_SSL \
struct ssl_handle* ssl; /** SSL handle */ SSL* ssl; /** SSL handle */ \
uint32_t ssl_state; /** SSL state */ \
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
#define NET_CON_STRUCT_COMMON \ #define NET_CON_STRUCT_COMMON \

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2013, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -20,17 +20,131 @@
#include "uhub.h" #include "uhub.h"
#include "network/common.h" #include "network/common.h"
static int is_blocked_or_interrupted() #ifdef SSL_SUPPORT
enum uhub_tls_state
{ {
int err = net_error(); tls_st_none,
return tls_st_error,
#ifdef WINSOCK tls_st_accepting,
err == WSAEWOULDBLOCK tls_st_connecting,
#else tls_st_connected,
err == EWOULDBLOCK tls_st_disconnecting,
#endif };
|| err == EINTR;
static int handle_openssl_error(struct net_connection* con, int ret)
{
uhub_assert(con);
int error = SSL_get_error(con->ssl, ret);
switch (error)
{
case SSL_ERROR_ZERO_RETURN:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
con->ssl_state = tls_st_error;
return -1;
case SSL_ERROR_WANT_READ:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
con->flags |= NET_WANT_SSL_READ;
net_con_update(con, NET_EVENT_READ);
return 0;
case SSL_ERROR_WANT_WRITE:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
con->flags |= NET_WANT_SSL_WRITE;
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
return 0;
case SSL_ERROR_SYSCALL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
/* if ret == 0, connection closed, if ret == -1, check with errno */
if (ret == 0)
return -1;
else
return -net_error();
case SSL_ERROR_SSL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
/* internal openssl error */
con->ssl_state = tls_st_error;
return -1;
} }
return -1;
}
ssize_t net_con_ssl_accept(struct net_connection* con)
{
uhub_assert(con);
con->ssl_state = tls_st_accepting;
ssize_t ret = SSL_accept(con->ssl);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_accept() ret=%d", ret);
#endif
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
con->ssl_state = tls_st_connected;
}
else
{
return handle_openssl_error(con, ret);
}
return ret;
}
ssize_t net_con_ssl_connect(struct net_connection* con)
{
uhub_assert(con);
con->ssl_state = tls_st_connecting;
ssize_t ret = SSL_connect(con->ssl);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_connect() ret=%d", ret);
#endif
if (ret > 0)
{
con->ssl_state = tls_st_connected;
net_con_update(con, NET_EVENT_READ);
}
else
{
return handle_openssl_error(con, ret);
}
return ret;
}
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx)
{
uhub_assert(con);
SSL* ssl = 0;
if (ssl_mode == net_con_ssl_mode_server)
{
ssl = SSL_new(ssl_ctx);
if (!ssl)
{
LOG_ERROR("Unable to create new SSL stream\n");
return -1;
}
SSL_set_fd(ssl, con->sd);
net_con_set_ssl(con, ssl);
return net_con_ssl_accept(con);
}
else
{
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
SSL_set_fd(ssl, con->sd);
net_con_set_ssl(con, ssl);
return net_con_ssl_connect(con);
}
}
#endif /* SSL_SUPPORT */
#ifdef SSL_SUPPORT
void net_stats_add_tx(size_t bytes);
void net_stats_add_rx(size_t bytes);
#endif
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
{ {
@@ -42,7 +156,13 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL); ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
if (ret == -1) if (ret == -1)
{ {
if (is_blocked_or_interrupted()) if (
#ifdef WINSOCK
net_error() == WSAEWOULDBLOCK
#else
net_error() == EWOULDBLOCK
#endif
|| net_error() == EINTR)
return 0; return 0;
return -1; return -1;
} }
@@ -50,9 +170,19 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
} }
else else
{ {
ret = net_ssl_send(con, buf, len); con->write_len = len;
ret = SSL_write(con->ssl, buf, len);
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret <= 0)
{
return handle_openssl_error(con, ret);
} }
#endif /* SSL_SUPPORT */ else
{
net_stats_add_tx(ret);
}
}
#endif
return ret; return ret;
} }
@@ -60,13 +190,19 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{ {
int ret; int ret;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (!con->ssl) if (!net_con_is_ssl(con))
{ {
#endif #endif
ret = net_recv(con->sd, buf, len, 0); ret = net_recv(con->sd, buf, len, 0);
if (ret == -1) if (ret == -1)
{ {
if (is_blocked_or_interrupted()) if (
#ifdef WINSOCK
net_error() == WSAEWOULDBLOCK
#else
net_error() == EWOULDBLOCK
#endif
|| net_error() == EINTR)
return 0; return 0;
return -net_error(); return -net_error();
} }
@@ -78,9 +214,22 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
} }
else else
{ {
ret = net_ssl_recv(con, buf, len); if (con->ssl_state == tls_st_error)
return -1;
ret = SSL_read(con->ssl, buf, len);
LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
net_stats_add_rx(ret);
} }
#endif /* SSL_SUPPORT */ else
{
return handle_openssl_error(con, ret);
}
}
#endif
return ret; return ret;
} }
@@ -89,7 +238,13 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
int ret = net_recv(con->sd, buf, len, MSG_PEEK); int ret = net_recv(con->sd, buf, len, MSG_PEEK);
if (ret == -1) if (ret == -1)
{ {
if (is_blocked_or_interrupted()) if (
#ifdef WINSOCK
net_error() == WSAEWOULDBLOCK
#else
net_error() == EWOULDBLOCK
#endif
|| net_error() == EINTR)
return 0; return 0;
return -net_error(); return -net_error();
} }
@@ -99,10 +254,19 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
} }
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
int net_con_is_ssl(struct net_connection* con) int net_con_is_ssl(struct net_connection* con)
{ {
return !!con->ssl; return con->ssl != 0;
}
SSL* net_con_get_ssl(struct net_connection* con)
{
return con->ssl;
}
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
{
con->ssl = ssl;
} }
#endif /* SSL_SUPPORT */ #endif /* SSL_SUPPORT */
@@ -119,8 +283,7 @@ void* net_con_get_ptr(struct net_connection* con)
void net_con_destroy(struct net_connection* con) void net_con_destroy(struct net_connection* con)
{ {
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (con->ssl) SSL_free(con->ssl);
net_ssl_destroy(con);
#endif #endif
hub_free(con); hub_free(con);
} }
@@ -132,377 +295,68 @@ void net_con_callback(struct net_connection* con, int events)
if (events == NET_EVENT_TIMEOUT) if (events == NET_EVENT_TIMEOUT)
{ {
LOG_TRACE("net_con_callback(%p, TIMEOUT)", con); LOG_TRACE("net_con_callback(%p, TIMEOUT", con);
con->callback(con, events, con->ptr); con->callback(con, events, con->ptr);
return; return;
} }
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (con->ssl) if (!con->ssl)
net_ssl_callback(con, events); {
else
#endif #endif
con->callback(con, events, con->ptr); con->callback(con, events, con->ptr);
} #ifdef SSL_SUPPORT
struct net_connect_job
{
struct net_connection* con;
struct net_connect_handle* handle;
struct sockaddr_storage addr;
struct net_connect_job* next;
};
struct net_connect_handle
{
const char* address;
uint16_t port;
void* ptr;
net_connect_cb callback;
struct net_dns_job* dns;
const struct net_dns_result* result;
struct net_connect_job* job4;
struct net_connect_job* job6;
};
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con);
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr);
/**
* Check if a connection job is completed.
* @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected).
*/
static int net_connect_job_check(struct net_connect_job* job)
{
struct net_connection* con = job->con;
int af = job->addr.ss_family;
enum net_connect_status status;
int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
LOG_TRACE("net_connect_job_check(): Socket connected!");
job->con = NULL;
net_connect_callback(job->handle, net_connect_status_ok, con);
return 1;
}
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
{
return 0;
}
LOG_TRACE("net_connect_job_check(): Socket error!");
switch (net_error())
{
case ECONNREFUSED:
status = net_connect_status_refused;
break;
case ENETUNREACH:
status = net_connect_status_unreachable;
break;
default:
status = net_connect_status_socket_error;
}
net_connect_callback(job->handle, status, NULL);
return -1;
}
static void net_connect_job_free(struct net_connect_job* job)
{
if (job->con)
net_con_close(job->con);
job->handle = NULL;
job->next = NULL;
hub_free(job);
}
static void net_connect_job_stop(struct net_connect_job* job)
{
if (job->addr.ss_family == AF_INET6)
{
job->handle->job6 = job->next;
} }
else else
{ {
job->handle->job4 = job->next; #ifdef NETWORK_DUMP_DEBUG
} LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
#endif
net_connect_job_free(job); switch (con->ssl_state)
}
static int net_connect_depleted(struct net_connect_handle* handle)
{ {
return (!handle->job6 && !handle->job4); case tls_st_none:
con->callback(con, events, con->ptr);
break;
case tls_st_error:
con->callback(con, NET_EVENT_READ, con->ptr);
break;
case tls_st_accepting:
if (net_con_ssl_accept(con) < 0)
{
con->callback(con, NET_EVENT_READ, con->ptr);
} }
break;
static int net_connect_job_process(struct net_connect_job* job) case tls_st_connecting:
if (net_con_ssl_connect(con) < 0)
{ {
int sd; con->callback(con, NET_EVENT_READ, con->ptr);
if (!job->con)
{
sd = net_socket_create(job->addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1)
{
LOG_DEBUG("net_connect_job_process: Unable to create socket!");
net_connect_callback(job->handle, net_connect_status_socket_error, NULL);
return -1; // FIXME
} }
break;
job->con = net_con_create(); case tls_st_connected:
net_con_initialize(job->con, sd, net_connect_job_internal_cb, job, NET_EVENT_WRITE); LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : "");
net_con_set_timeout(job->con, TIMEOUT_CONNECTED); // FIXME: Use a proper timeout value! if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ)
}
return net_connect_job_check(job);
}
/*
* Internal callback used to establish an outbound connection.
*/
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr)
{ {
int ret; con->callback(con, events & NET_EVENT_READ, con->ptr);
struct net_connect_job* job = net_con_get_ptr(con);
struct net_connect_job* next_job = job->next;
struct net_connect_handle* handle = job->handle;
if (event == NET_EVENT_TIMEOUT)
{
// FIXME: Try next address, or if no more addresses left declare failure to connect.
if (job->addr.ss_family == AF_INET6)
{
net_connect_job_stop(job);
if (!next_job)
{
LOG_TRACE("No more IPv6 addresses to try!");
}
}
else
{
net_connect_job_stop(job);
if (!next_job)
{
LOG_TRACE("No more IPv4 addresses to try!");
}
}
if (net_connect_depleted(handle))
{
LOG_TRACE("No more addresses left. Unable to connect!");
net_connect_callback(handle, net_connect_status_timeout, NULL);
}
return; return;
} }
if (event == NET_EVENT_WRITE) if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
{ {
net_connect_job_process(job); con->callback(con, events & NET_EVENT_READ, con->ptr);
} return;
} }
con->callback(con, events, con->ptr);
break;
static int net_connect_cancel(struct net_connect_handle* handle) case tls_st_disconnecting:
{ return;
struct net_connect_job* job;
job = handle->job6;
while (job)
{
job = job->next;
net_connect_job_free(handle->job6);
handle->job6 = job;
}
job = handle->job4;
while (job)
{
job = job->next;
net_connect_job_free(handle->job4);
handle->job4 = job;
} }
} }
#endif
static int net_connect_process_queue(struct net_connect_handle* handle, struct net_connect_job* job)
{
int ret;
while (job)
{
ret = net_connect_job_process(job);
if (ret < 0)
{
net_connect_job_stop(job);
continue;
}
else if (ret == 0)
{
// Need to process again
return 0;
}
else
{
// FIXME: Success!
return 1;
}
}
return -1;
} }
static int net_connect_process(struct net_connect_handle* handle)
{
int ret4, ret6;
ret6 = net_connect_process_queue(handle, handle->job6);
if (ret6 == 1)
return 1; // Connected - cool!
net_connect_process_queue(handle, handle->job4);
}
static int net_connect_job_schedule(struct net_connect_handle* handle, struct ip_addr_encap* addr)
{
struct net_connect_job* job;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
if (addr->af == AF_INET6 && !net_is_ipv6_supported())
{
LOG_TRACE("net_connect_job_schedule(): Skipping IPv6 support since IPv6 is not supported.");
return 0;
}
else
{
job = hub_malloc_zero(sizeof(struct net_connect_job));
job->handle = handle;
if (addr->af == AF_INET6)
{
addr6 = (struct sockaddr_in6*) &job->addr;
LOG_TRACE("net_connect_job_schedule(): Scheduling IPv6 connect job.");
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(handle->port);
memcpy(&addr6->sin6_addr, &addr->internal_ip_data.in6, sizeof(struct in6_addr));
// prepend
job->next = handle->job6;
handle->job6 = job;
}
else
{
addr4 = (struct sockaddr_in*) &job->addr;
LOG_TRACE("net_connect_job_schedule(): Scheduling IPv4 connect job.");
addr4->sin_family = AF_INET;
addr4->sin_port = htons(handle->port);
memcpy(&addr4->sin_addr, &addr->internal_ip_data.in, sizeof(struct in_addr));
// prepend
job->next = handle->job4;
handle->job4 = job;
}
}
return 1;
}
/*
* Callback when the DNS results are ready.
* Create a list of IPv6 and IPv4 addresses, then
* start connecting to them one by one until one succeeds.
*/
static int net_con_connect_dns_callback(struct net_dns_job* job, const struct net_dns_result* result)
{
struct ip_addr_encap* addr;
struct net_connect_handle* handle = (struct net_connect_handle*) net_dns_job_get_ptr(job);
handle->dns = NULL;
size_t usable = 0;
int ret;
LOG_TRACE("net_con_connect(): async - Got DNS results");
if (!result)
{
LOG_DEBUG("net_con_connect() - Unable to lookup host!");
net_connect_callback(handle, net_connect_status_dns_error, NULL);
return 1;
}
if (!net_dns_result_size(result))
{
LOG_DEBUG("net_con_connect() - Host not found!");
net_connect_callback(handle, net_connect_status_host_not_found, NULL);
return 1;
}
handle->result = result;
// Extract results into a separate list of IPv4 and IPv6 addresses.
addr = net_dns_result_first(result);
while (addr)
{
if (net_connect_job_schedule(handle, addr))
usable++;
addr = net_dns_result_next(result);
}
net_connect_process(handle);
return 0;
}
// typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_handle_code, struct net_connection* con);
struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr)
{
struct net_connect_handle* handle = hub_malloc_zero(sizeof(struct net_connect_handle));
handle->address = hub_strdup(address);
handle->port = port;
handle->ptr = ptr;
handle->callback = callback;
// FIXME: Check if DNS resolving is necessary ?
handle->dns = net_dns_gethostbyname(address, AF_UNSPEC, net_con_connect_dns_callback, handle);
if (!handle->dns)
{
LOG_TRACE("net_con_connect(): Unable to create DNS lookup job.");
hub_free((char*) handle->address);
hub_free(handle);
return NULL;
}
return handle;
}
void net_connect_destroy(struct net_connect_handle* handle)
{
hub_free((char*) handle->address);
// cancel DNS job if pending
if (handle->dns)
net_dns_job_cancel(handle->dns);
// Stop any connect jobs.
net_connect_cancel(handle);
// free any DNS results
net_dns_result_free(handle->result);
hub_free(handle);
}
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con)
{
uhub_assert(handle->callback != NULL);
// Call the callback
handle->callback(handle, status, con, handle->ptr);
handle->callback = NULL;
// Cleanup
net_connect_destroy(handle);
}

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2013, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -23,7 +23,6 @@
#include "uhub.h" #include "uhub.h"
#include "network/common.h" #include "network/common.h"
#include "network/backend.h" #include "network/backend.h"
#include "network/tls.h"
#define NET_EVENT_TIMEOUT 0x0001 #define NET_EVENT_TIMEOUT 0x0001
#define NET_EVENT_READ 0x0002 #define NET_EVENT_READ 0x0002
@@ -34,41 +33,10 @@ struct net_connection
NET_CON_STRUCT_COMMON NET_CON_STRUCT_COMMON
}; };
struct net_connect_handle;
enum net_connect_status
{
net_connect_status_ok = 0,
net_connect_status_host_not_found = -1,
net_connect_status_no_address = -2,
net_connect_status_dns_error = -3,
net_connect_status_refused = -4,
net_connect_status_unreachable = -5,
net_connect_status_timeout = -6,
net_connect_status_socket_error = -7,
};
typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_status status, struct net_connection* con, void* ptr);
extern int net_con_get_sd(struct net_connection* con); extern int net_con_get_sd(struct net_connection* con);
extern void* net_con_get_ptr(struct net_connection* con); extern void* net_con_get_ptr(struct net_connection* con);
extern struct net_connection* net_con_create(); extern struct net_connection* net_con_create();
/**
* Establish an outbound TCP connection.
* This will resolve the IP-addresses, and connect to
* either an IPv4 or IPv6 address depending if it is supported,
* and using the happy eyeballs algorithm.
*
* @param address Hostname, IPv4 or IPv6 address
* @param port TCP port number
* @param callback A callback to be called once the connection is established, or failed.
* @returns a handle to the connection establishment job, or NULL if an immediate error.
*/
extern struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr);
extern void net_connect_destroy(struct net_connect_handle* handle);
extern void net_con_destroy(struct net_connection*); extern void net_con_destroy(struct net_connection*);
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events); extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events); extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
@@ -115,5 +83,29 @@ extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len);
extern void net_con_set_timeout(struct net_connection* con, int seconds); extern void net_con_set_timeout(struct net_connection* con, int seconds);
extern void net_con_clear_timeout(struct net_connection* con); extern void net_con_clear_timeout(struct net_connection* con);
#ifdef SSL_SUPPORT
/**
* Start SSL_accept()
*/
extern ssize_t net_con_ssl_accept(struct net_connection*);
/**
* Start SSL_connect()
*/
extern ssize_t net_con_ssl_connect(struct net_connection*);
enum net_con_ssl_mode
{
net_con_ssl_mode_server,
net_con_ssl_mode_client,
};
extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx);
extern int net_con_is_ssl(struct net_connection* con);
extern SSL* net_con_get_ssl(struct net_connection* con);
extern void net_con_set_ssl(struct net_connection* con, SSL*);
#endif /* SSL_SUPPORT */
#endif /* HAVE_UHUB_NETWORK_CONNECTION_H */ #endif /* HAVE_UHUB_NETWORK_CONNECTION_H */

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -49,21 +49,21 @@ int net_initialize()
} }
#endif /* WINSOCK */ #endif /* WINSOCK */
if (!net_backend_init() if (!net_backend_init())
#ifdef SSL_SUPPORT
|| !net_ssl_library_init()
#endif
)
{ {
#ifdef WINSOCK #ifdef WINSOCK
WSACleanup(); WSACleanup();
#endif #endif
return -1; return -1;
} }
net_dns_initialize();
net_stats_initialize(); net_stats_initialize();
#ifdef SSL_SUPPORT
LOG_TRACE("Initializing OpenSSL...");
SSL_library_init();
SSL_load_error_strings();
#endif /* SSL_SUPPORT */
net_initialized = 1; net_initialized = 1;
return 0; return 0;
} }
@@ -97,13 +97,13 @@ int net_destroy()
{ {
LOG_TRACE("Shutting down network monitor"); LOG_TRACE("Shutting down network monitor");
net_dns_destroy();
net_backend_shutdown(); net_backend_shutdown();
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
net_ssl_library_shutdown(); ERR_free_strings();
#endif /* SSL_SUPPORT */ EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
#endif
#ifdef WINSOCK #ifdef WINSOCK
WSACleanup(); WSACleanup();
@@ -114,6 +114,13 @@ int net_destroy()
return -1; return -1;
} }
#ifdef USE_LIBEVENT
struct event_base* net_get_evbase()
{
return net_evbase;
}
#endif
static void net_error_out(int fd, const char* func) static void net_error_out(int fd, const char* func)
{ {
int err = net_error(); int err = net_error();
@@ -495,6 +502,7 @@ int net_socket_create(int af, int type, int protocol)
} }
} }
#endif #endif
return sd; return sd;
} }
@@ -523,7 +531,6 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
sin6.sin6_family = AF_INET6; sin6.sin6_family = AF_INET6;
sin6.sin6_port = 0; sin6.sin6_port = 0;
sin6.sin6_addr = *addr6; sin6.sin6_addr = *addr6;
sin6.sin6_scope_id = 0;
size = sizeof(sin6); size = sizeof(sin6);
addr = (LPSOCKADDR) &sin6; addr = (LPSOCKADDR) &sin6;
break; break;

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -31,7 +31,6 @@ struct net_statistics
}; };
struct net_socket_t; struct net_socket_t;
struct ip_addr_encap;
/** /**
* Initialize the socket monitor subsystem. * Initialize the socket monitor subsystem.
@@ -52,6 +51,8 @@ extern int net_initialize();
*/ */
extern int net_destroy(); extern int net_destroy();
extern struct event_base* net_get_evbase();
/** /**
* @return the number of sockets currrently being monitored. * @return the number of sockets currrently being monitored.
*/ */

View File

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

View File

@@ -55,7 +55,7 @@ int net_backend_poll_select(struct net_backend* data, int ms)
struct net_backend_select* backend = (struct net_backend_select*) data; struct net_backend_select* backend = (struct net_backend_select*) data;
tval.tv_sec = ms / 1000; tval.tv_sec = ms / 1000;
tval.tv_usec = (ms % 1000) * 1000; tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct?
FD_ZERO(&backend->rfds); FD_ZERO(&backend->rfds);
FD_ZERO(&backend->wfds); FD_ZERO(&backend->wfds);
@@ -78,11 +78,10 @@ int net_backend_poll_select(struct net_backend* data, int ms)
res = select(backend->maxfd, &backend->rfds, &backend->wfds, &backend->xfds, &tval); res = select(backend->maxfd, &backend->rfds, &backend->wfds, &backend->xfds, &tval);
if (res == -1) if (res == -1)
{ {
if (net_error() == EINTR)
return 0;
printf("Error: %d\n", net_error()); printf("Error: %d\n", net_error());
} }
if (res == -1 && net_error() == EINTR)
return 0;
return res; return res;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2013, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -57,31 +57,15 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
size_t pos = (size_t) t->last; size_t pos = (size_t) t->last;
size_t events = 0; size_t events = 0;
struct timeout_evt* evt = 0; struct timeout_evt* evt = 0;
uhub_assert(t->last <= now);
t->last = now; t->last = now;
// We can optimize in case we need to wrap around
// the buffer, so we only do it once
if (MAX(pos, now) - MIN(pos, now) > t->max)
{
// FIXME: Double check this calculation
pos = (now - t->max);
}
for (; pos <= now; pos++) for (; pos <= now; pos++)
{ {
evt = t->events[pos % t->max]; while ((evt = t->events[pos % t->max]))
while (evt)
{
if (evt->timestamp < pos)
{ {
timeout_queue_remove(t, evt); timeout_queue_remove(t, evt);
evt->callback(evt); evt->callback(evt);
events++; events++;
} }
evt = evt->next;
}
} }
return events; return events;
} }
@@ -101,22 +85,24 @@ size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now)
void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
{ {
struct timeout_evt* it, *first; struct timeout_evt* first;
size_t pos = ((t->last + seconds) % t->max); size_t pos = ((t->last + seconds) % t->max);
evt->timestamp = t->last + seconds; evt->timestamp = t->last + seconds;
evt->next = 0; evt->next = 0;
first = t->events[pos]; first = t->events[pos];
if (first) if (first)
{ {
for (it = first; it->next; it = it->next) { } uhub_assert(first->timestamp == evt->timestamp);
it->next = evt; first->prev->next = evt;
evt->prev = it; evt->prev = first->prev;
first->prev = evt;
} }
else else
{ {
t->events[pos] = evt; t->events[pos] = evt;
evt->prev = evt; // point to self. evt->prev = evt;
} }
evt->next = 0; evt->next = 0;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2013, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

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

View File

@@ -35,19 +35,6 @@ struct plugin_command
struct linked_list* args; struct linked_list* args;
}; };
struct plugin_command_arg_data
{
enum plugin_command_arg_type type;
union {
int integer;
char* string;
struct plugin_user* user;
struct ip_addr_encap* address;
struct ip_range* range;
enum auth_credentials credentials;
} data;
};
typedef int (*plugin_command_handler)(struct plugin_handle*, struct plugin_user* to, struct plugin_command*); typedef int (*plugin_command_handler)(struct plugin_handle*, struct plugin_user* to, struct plugin_command*);
struct plugin_command_handle struct plugin_command_handle
@@ -75,5 +62,18 @@ struct plugin_command_handle
PTR->description = DESC; \ PTR->description = DESC; \
} while (0) } while (0)
extern int plugin_command_add(struct plugin_handle*, struct plugin_command_handle*);
extern int plugin_command_del(struct plugin_handle*, struct plugin_command_handle*);
/**
* Send a message to a user.
* From the user's perspective the message will originate from the hub.
*/
extern int plugin_command_send_message(struct plugin_handle*, struct plugin_user* to, const char* message);
/**
* Send a reply to a command.
*/
extern int plugin_command_send_reply(struct plugin_handle*, struct plugin_user* user, struct plugin_command* command, const char* message);
#endif /* HAVE_UHUB_PLUGIN_API_H */ #endif /* HAVE_UHUB_PLUGIN_API_H */

View File

@@ -26,9 +26,16 @@
#include "system.h" #include "system.h"
#include "util/credentials.h" #include "util/credentials.h"
#include "network/ipcalc.h" #include "util/ipcalc.h"
#include "plugin_api/types.h" #include "plugin_api/types.h"
typedef plugin_st (*on_chat_msg_t)(struct plugin_handle*, struct plugin_user* from, const char* message);
typedef plugin_st (*on_private_msg_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* message);
typedef plugin_st (*on_search_t)(struct plugin_handle*, struct plugin_user* from, const char* data);
typedef plugin_st (*on_search_result_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* data);
typedef plugin_st (*on_p2p_connect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*); typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*);
typedef void (*on_connection_refused_t)(struct plugin_handle*, struct ip_addr_encap*); typedef void (*on_connection_refused_t)(struct plugin_handle*, struct ip_addr_encap*);
@@ -44,18 +51,12 @@ typedef void (*on_hub_reloaded_t)(struct plugin_handle*, struct plugin_hub_info*
typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*); typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*);
typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message); typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message);
typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*);
typedef plugin_st (*on_check_ip_late_t)(struct plugin_handle*, struct plugin_user*, struct ip_addr_encap*);
typedef plugin_st (*on_validate_nick_t)(struct plugin_handle*, const char* nick);
typedef plugin_st (*on_validate_cid_t)(struct plugin_handle*, const char* cid);
typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick); typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick);
typedef plugin_st (*on_chat_msg_t)(struct plugin_handle*, struct plugin_user* from, const char* message); typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*);
typedef plugin_st (*on_private_msg_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* message); typedef plugin_st (*on_check_ip_late_t)(struct plugin_handle*, struct ip_addr_encap*);
typedef plugin_st (*on_search_t)(struct plugin_handle*, struct plugin_user* from, const char* data); typedef plugin_st (*on_validate_nick_t)(struct plugin_handle*, const char* nick);
typedef plugin_st (*on_search_result_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* data); typedef plugin_st (*on_validate_cid_t)(struct plugin_handle*, const char* cid);
typedef plugin_st (*on_p2p_connect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
typedef plugin_st (*auth_get_user_t)(struct plugin_handle*, const char* nickname, struct auth_info* info); typedef plugin_st (*auth_get_user_t)(struct plugin_handle*, const char* nickname, struct auth_info* info);
typedef plugin_st (*auth_register_user_t)(struct plugin_handle*, struct auth_info* user); typedef plugin_st (*auth_register_user_t)(struct plugin_handle*, struct auth_info* user);
@@ -64,7 +65,6 @@ typedef plugin_st (*auth_delete_user_t)(struct plugin_handle*, struct auth_info*
/** /**
* These are callbacks used for the hub to invoke functions in plugins. * These are callbacks used for the hub to invoke functions in plugins.
* The marked ones are not being called yet.
*/ */
struct plugin_funcs struct plugin_funcs
{ {
@@ -76,20 +76,17 @@ struct plugin_funcs
on_user_login_t on_user_login; /* A user has successfully logged in to the hub */ on_user_login_t on_user_login; /* A user has successfully logged in to the hub */
on_user_login_error_t on_user_login_error; /* A user has failed to log in to the hub */ on_user_login_error_t on_user_login_error; /* A user has failed to log in to the hub */
on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */ on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */
/* ! */ on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */ on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */
on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */ on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */
on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */ on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */
// Log hub events // Log hub events
/* ! */ on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */ on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */
/* ! */ on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */ on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */
/* ! */ on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */ on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */
/* ! */ on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */ on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */
// Activity events (can be intercepted and refused/accepted by a plugin) // Activity events (can be intercepted and refused/accepted by a plugin)
on_check_ip_early_t on_check_ip_early; /* A user has just connected (can be intercepted) */
/* ! */ on_check_ip_late_t on_check_ip_late; /* A user has logged in (can be intercepted) */
/* ! */ on_change_nick_t on_change_nick; /* A user wants to change his nick (can be intercepted) */
on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */ on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */
on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */ on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */
on_search_t on_search; /* A search is about to be sent (can be intercepted) */ on_search_t on_search; /* A search is about to be sent (can be intercepted) */
@@ -103,11 +100,12 @@ struct plugin_funcs
auth_update_user_t auth_update_user; /* Update a registered user */ auth_update_user_t auth_update_user; /* Update a registered user */
auth_delete_user_t auth_delete_user; /* Delete a registered user */ auth_delete_user_t auth_delete_user; /* Delete a registered user */
// Login check functions
on_check_ip_early_t login_check_ip_early;
on_check_ip_late_t login_check_ip_late;
}; };
struct plugin_command_handle; struct plugin_command_handle;
struct plugin_command;
struct plugin_command_arg_data;
typedef int (*hfunc_send_message)(struct plugin_handle*, struct plugin_user* user, const char* message); typedef int (*hfunc_send_message)(struct plugin_handle*, struct plugin_user* user, const char* message);
typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message); typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message);
@@ -115,14 +113,6 @@ typedef int (*hfunc_user_disconnect)(struct plugin_handle*, struct plugin_user*
typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*); typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*);
typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_handle*); typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_handle*);
typedef size_t (*hfunc_command_arg_reset)(struct plugin_handle*, struct plugin_command*);
typedef struct plugin_command_arg_data* (*hfunc_command_arg_next)(struct plugin_handle*, struct plugin_command*, enum plugin_command_arg_type);
typedef char* (*hfunc_get_hub_name)(struct plugin_handle*);
typedef void (*hfunc_set_hub_name)(struct plugin_handle*, const char*);
typedef char* (*hfunc_get_hub_description)(struct plugin_handle*);
typedef void (*hfunc_set_hub_description)(struct plugin_handle*, const char*);
/** /**
* These are functions created and initialized by the hub and which can be used * These are functions created and initialized by the hub and which can be used
* by plugins to access functionality internal to the hub. * by plugins to access functionality internal to the hub.
@@ -134,14 +124,9 @@ struct plugin_hub_funcs
hfunc_user_disconnect user_disconnect; hfunc_user_disconnect user_disconnect;
hfunc_command_add command_add; hfunc_command_add command_add;
hfunc_command_del command_del; hfunc_command_del command_del;
hfunc_command_arg_reset command_arg_reset;
hfunc_command_arg_next command_arg_next;
hfunc_get_hub_name get_name;
hfunc_set_hub_name set_name;
hfunc_get_hub_description get_description;
hfunc_set_hub_description set_description;
}; };
struct plugin_handle struct plugin_handle
{ {
struct uhub_plugin* handle; /* Must NOT be modified by the plugin */ struct uhub_plugin* handle; /* Must NOT be modified by the plugin */

View File

@@ -93,15 +93,4 @@ struct ban_info
time_t expiry; /* Time when the ban record expires */ time_t expiry; /* Time when the ban record expires */
}; };
enum plugin_command_arg_type
{
plugin_cmd_arg_type_integer,
plugin_cmd_arg_type_string,
plugin_cmd_arg_type_user,
plugin_cmd_arg_type_address,
plugin_cmd_arg_type_range,
plugin_cmd_arg_type_credentials,
};
#endif /* HAVE_UHUB_PLUGIN_TYPES_H */ #endif /* HAVE_UHUB_PLUGIN_TYPES_H */

View File

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

View File

@@ -21,6 +21,7 @@
#include <sqlite3.h> #include <sqlite3.h>
#include "util/memory.h" #include "util/memory.h"
#include "util/list.h" #include "util/list.h"
#include "util/ipcalc.h"
#include "util/misc.h" #include "util/misc.h"
#include "util/log.h" #include "util/log.h"
#include "util/config_token.h" #include "util/config_token.h"
@@ -38,37 +39,6 @@ struct sql_data
sqlite3* db; sqlite3* db;
}; };
static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; }
static int sql_execute(struct sql_data* sql, int (*callback)(void* ptr, int argc, char **argv, char **colName), void* ptr, const char* sql_fmt, ...)
{
va_list args;
char query[1024];
char* errMsg;
int rc;
va_start(args, sql_fmt);
vsnprintf(query, sizeof(query), sql_fmt, args);
#ifdef DEBUG_SQL
printf("SQL: %s\n", query);
#endif
rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg);
if (rc != SQLITE_OK)
{
#ifdef DEBUG_SQL
fprintf(stderr, "ERROR: %s\n", errMsg);
#endif
sqlite3_free(errMsg);
return -rc;
}
rc = sqlite3_changes(sql->db);
return rc;
}
static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin) static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin)
{ {
struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data)); struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data));
@@ -208,42 +178,17 @@ static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, st
static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user) static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
{ {
struct sql_data* sql = (struct sql_data*) plugin->ptr; struct sql_data* sql = (struct sql_data*) plugin->ptr;
char* nick = strdup(sql_escape_string(user->nickname)); if (sql->exclusive)
char* pass = strdup(sql_escape_string(user->password));
const char* cred = auth_cred_to_string(user->credentials);
int rc = sql_execute(sql, null_callback, NULL, "INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", nick, pass, cred);
free(nick);
free(pass);
if (rc <= 0)
{
fprintf(stderr, "Unable to add user \"%s\"\n", user->nickname);
return st_deny; return st_deny;
} return st_default;
return st_allow;
} }
static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user) static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
{ {
struct sql_data* sql = (struct sql_data*) plugin->ptr; struct sql_data* sql = (struct sql_data*) plugin->ptr;
if (sql->exclusive)
char* nick = strdup(sql_escape_string(user->nickname));
char* pass = strdup(sql_escape_string(user->password));
const char* cred = auth_cred_to_string(user->credentials);
int rc = sql_execute(sql, null_callback, NULL, "INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", nick, pass, cred);
free(nick);
free(pass);
if (rc <= 0)
{
fprintf(stderr, "Unable to add user \"%s\"\n", user->nickname);
return st_deny; return st_deny;
} return st_default;
return st_allow;
} }
static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user) static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
@@ -256,7 +201,7 @@ static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* use
int plugin_register(struct plugin_handle* plugin, const char* config) int plugin_register(struct plugin_handle* plugin, const char* config)
{ {
PLUGIN_INITIALIZE(plugin, "SQLite authentication plugin", "1.0", "Authenticate users based on a SQLite database."); PLUGIN_INITIALIZE(plugin, "SQLite authentication plugin", "0.1", "Authenticate users based on a SQLite database.");
// Authentication actions. // Authentication actions.
plugin->funcs.auth_get_user = get_user; plugin->funcs.auth_get_user = get_user;

View File

@@ -67,7 +67,7 @@ static size_t get_messages(struct chat_history_data* data, size_t num, struct cb
char* message; char* message;
int skiplines = 0; int skiplines = 0;
size_t lines = 0; size_t lines = 0;
size_t total = list_size(messages); int total = list_size(messages);
if (total == 0) if (total == 0)
return 0; return 0;
@@ -129,14 +129,13 @@ static int command_history(struct plugin_handle* plugin, struct plugin_user* use
{ {
struct cbuffer* buf; struct cbuffer* buf;
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer); int maxlines = 0;
int maxlines;
if (!list_size(data->chat_history)) if (!list_size(data->chat_history))
return command_status(plugin, user, cmd, cbuf_create_const("No messages.")); return command_status(plugin, user, cmd, cbuf_create_const("No messages."));
if (arg) if (list_size(cmd->args) > 0)
maxlines = arg->data.integer; maxlines = (int) (intptr_t) ((intptr_t*) (void*) list_get_first(cmd->args));
else else
maxlines = data->history_default; maxlines = data->history_default;
@@ -160,7 +159,7 @@ static struct chat_history_data* parse_config(const char* line, struct plugin_ha
struct cfg_tokens* tokens = cfg_tokenize(line); struct cfg_tokens* tokens = cfg_tokenize(line);
char* token = cfg_token_get_first(tokens); char* token = cfg_token_get_first(tokens);
uhub_assert(data != NULL); assert(data != NULL);
data->history_max = 200; data->history_max = 200;
data->history_default = 25; data->history_default = 25;

View File

@@ -64,13 +64,13 @@ static struct user_info* get_user_info(struct chat_only_data* data, sid_t sid)
struct user_info* u; struct user_info* u;
// resize buffer if needed. // resize buffer if needed.
if (sid >= data->max_users) if (sid > data->max_users) // FIXME: >= ?
{ {
u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1)); u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1));
memcpy(u, data->users, data->max_users); memcpy(u, data->users, data->max_users);
hub_free(data->users); hub_free(data->users);
data->users = u; data->users = u;
data->max_users = sid + 1; data->max_users = sid;
u = NULL; u = NULL;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -21,14 +21,12 @@
#include "adc/adcconst.h" #include "adc/adcconst.h"
#include "adc/sid.h" #include "adc/sid.h"
#include "util/memory.h" #include "util/memory.h"
#include "network/ipcalc.h" #include "util/ipcalc.h"
#include "plugin_api/handle.h" #include "plugin_api/handle.h"
#include "util/misc.h" #include "util/misc.h"
#include "util/config_token.h" #include "util/config_token.h"
#ifndef WIN32
#include <syslog.h> #include <syslog.h>
#endif
struct ip_addr_encap; struct ip_addr_encap;
@@ -62,13 +60,11 @@ static int log_open_file(struct plugin_handle* plugin, struct log_data* data)
return (data->fd != -1); return (data->fd != -1);
} }
#ifndef WIN32
static int log_open_syslog(struct plugin_handle* plugin) static int log_open_syslog(struct plugin_handle* plugin)
{ {
openlog("uhub", 0, LOG_USER); openlog("uhub", 0, LOG_USER);
return 1; return 1;
} }
#endif
static struct log_data* parse_config(const char* line, struct plugin_handle* plugin) static struct log_data* parse_config(const char* line, struct plugin_handle* plugin)
{ {
@@ -98,7 +94,6 @@ static struct log_data* parse_config(const char* line, struct plugin_handle* plu
data->logfile = strdup(cfg_settings_get_value(setting)); data->logfile = strdup(cfg_settings_get_value(setting));
data->logmode = mode_file; data->logmode = mode_file;
} }
#ifndef WIN32
else if (strcmp(cfg_settings_get_key(setting), "syslog") == 0) else if (strcmp(cfg_settings_get_key(setting), "syslog") == 0)
{ {
int use_syslog = 0; int use_syslog = 0;
@@ -107,7 +102,6 @@ static struct log_data* parse_config(const char* line, struct plugin_handle* plu
data->logmode = (use_syslog) ? mode_syslog : mode_file; data->logmode = (use_syslog) ? mode_syslog : mode_file;
} }
} }
#endif
else else
{ {
set_error_message(plugin, "Unknown startup parameters given"); set_error_message(plugin, "Unknown startup parameters given");
@@ -140,7 +134,6 @@ static struct log_data* parse_config(const char* line, struct plugin_handle* plu
return 0; return 0;
} }
} }
#ifndef WIN32
else else
{ {
if (!log_open_syslog(plugin)) if (!log_open_syslog(plugin))
@@ -151,7 +144,7 @@ static struct log_data* parse_config(const char* line, struct plugin_handle* plu
return 0; return 0;
} }
} }
#endif
return data; return data;
} }
@@ -162,12 +155,10 @@ static void log_close(struct log_data* data)
hub_free(data->logfile); hub_free(data->logfile);
close(data->fd); close(data->fd);
} }
#ifndef WIN32
else else
{ {
closelog(); closelog();
} }
#endif
hub_free(data); hub_free(data);
} }
@@ -195,25 +186,19 @@ static void log_message(struct log_data* data, const char *format, ...)
} }
else else
{ {
#ifdef WIN32
_commit(data->fd);
#else
#if defined _POSIX_SYNCHRONIZED_IO && _POSIX_SYNCHRONIZED_IO > 0 #if defined _POSIX_SYNCHRONIZED_IO && _POSIX_SYNCHRONIZED_IO > 0
fdatasync(data->fd); fdatasync(data->fd);
#else #else
fsync(data->fd); fsync(data->fd);
#endif
#endif #endif
} }
} }
#ifndef WIN32
else else
{ {
va_start(args, format); va_start(args, format);
vsyslog(LOG_INFO, format, args); vsyslog(LOG_INFO, format, args);
va_end(args); va_end(args);
} }
#endif
} }
static void log_user_login(struct plugin_handle* plugin, struct plugin_user* user) static void log_user_login(struct plugin_handle* plugin, struct plugin_user* user)

View File

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

View File

@@ -1,102 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "plugin_api/handle.h"
#include "plugin_api/command_api.h"
#include "util/memory.h"
#include "util/cbuffer.h"
struct topic_plugin_data
{
struct plugin_command_handle* topic;
struct plugin_command_handle* cleartopic;
struct plugin_command_handle* showtopic;
};
static int command_topic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_string);
plugin->hub.set_description(plugin, arg ? arg->data.string : NULL);
cbuf_append_format(buf, "*** %s: Topic set to \"%s\"", cmd->prefix, arg->data.string);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static int command_cleartopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
plugin->hub.set_description(plugin, NULL);
cbuf_append_format(buf, "*** %s: Topic cleared.", cmd->prefix);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static int command_showtopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct cbuffer* buf = cbuf_create(128);
char* topic = plugin->hub.get_description(plugin);
cbuf_append_format(buf, "*** %s: Current topic is: \"%s\"", cmd->prefix, topic);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
hub_free(topic);
return 0;
}
int plugin_register(struct plugin_handle* plugin, const char* config)
{
struct topic_plugin_data* data = (struct topic_plugin_data*) hub_malloc(sizeof(struct topic_plugin_data));
data->topic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
data->cleartopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
data->showtopic = (struct plugin_command_handle*) hub_malloc_zero(sizeof(struct plugin_command_handle));
PLUGIN_INITIALIZE(plugin, "Topic plugin", "1.0", "Add commands for changing the hub topic (description)");
PLUGIN_COMMAND_INITIALIZE(data->topic, (void*) data, "topic", "+m", auth_cred_operator, command_topic_handler, "Set new topic");
PLUGIN_COMMAND_INITIALIZE(data->cleartopic, (void*) data, "cleartopic", "", auth_cred_operator, command_cleartopic_handler, "Clear the current topic");
PLUGIN_COMMAND_INITIALIZE(data->showtopic, (void*) data, "showtopic", "", auth_cred_guest, command_showtopic_handler, "Shows the current topic");
plugin->hub.command_add(plugin, data->topic);
plugin->hub.command_add(plugin, data->cleartopic);
plugin->hub.command_add(plugin, data->showtopic);
plugin->ptr = data;
return 0;
}
int plugin_unregister(struct plugin_handle* plugin)
{
struct topic_plugin_data* data = (struct topic_plugin_data*) plugin->ptr;
plugin->hub.command_del(plugin, data->topic);
plugin->hub.command_del(plugin, data->cleartopic);
plugin->hub.command_del(plugin, data->showtopic);
hub_free(data->topic);
hub_free(data->cleartopic);
hub_free(data->showtopic);
hub_free(data);
plugin->ptr = NULL;
return 0;
}

View File

@@ -22,12 +22,13 @@
#include "adc/sid.h" #include "adc/sid.h"
#include "util/cbuffer.h" #include "util/cbuffer.h"
#include "util/memory.h" #include "util/memory.h"
#include "network/ipcalc.h" #include "util/ipcalc.h"
#include "plugin_api/handle.h" #include "plugin_api/handle.h"
#include "plugin_api/command_api.h" #include "plugin_api/command_api.h"
#include "util/misc.h" #include "util/misc.h"
#include "util/config_token.h" #include "util/config_token.h"
#include <syslog.h>
#define MAX_WELCOME_SIZE 16384 #define MAX_WELCOME_SIZE 16384

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2009, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -34,7 +34,6 @@
#ifndef WINSOCK #ifndef WINSOCK
#define WINSOCK #define WINSOCK
#endif #endif
#define WINTHREAD_SUPPORT 1
#endif #endif
#if defined(__CYGWIN__) || defined(__MINGW32__) #if defined(__CYGWIN__) || defined(__MINGW32__)
@@ -74,7 +73,6 @@
#include <time.h> #include <time.h>
#if !defined(WIN32) #if !defined(WIN32)
#include <inttypes.h>
#include <unistd.h> #include <unistd.h>
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
@@ -90,53 +88,41 @@
#define HAVE_GETRLIMIT #define HAVE_GETRLIMIT
#endif #endif
/* printf support for size_t and uint64_t */ /* printf and size_t support */
#if defined(WIN32) #if defined(WIN32)
/* Windows uses %Iu for size_t */
#define PRINTF_SIZE_T "%Iu" #define PRINTF_SIZE_T "%Iu"
#define PRINTF_UINT64_T "%I64u"
#else #else
#define PRINTF_SIZE_T "%zu" #define PRINTF_SIZE_T "%zu"
#define PRINTF_UINT64_T ("%" PRIu64)
#endif #endif
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
#ifdef SSL_USE_OPENSSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#endif /* SSL_USE_OPENSSL */
#ifdef SSL_USE_GNUTLS
#include <gnutls/gnutls.h>
#endif /* SSL_USE_GNUTLS */
#endif #endif
#include "version.h" #include "../version.h"
#define uhub_assert assert #define uhub_assert assert
#ifdef __linux__ #ifdef __linux__
#define POSIX_THREAD_SUPPORT
#define USE_EPOLL #define USE_EPOLL
#include <sys/epoll.h> #include <sys/epoll.h>
#endif #endif
#ifdef BSD_LIKE #ifdef BSD_LIKE
#define POSIX_THREAD_SUPPORT
/* /*
#define USE_KQUEUE #define USE_KQUEUE
#include <sys/event.h> #include <sys/event.h>
*/ */
#endif #endif
#ifdef __GNU__
#define POSIX_THREAD_SUPPORT
#endif
#define USE_SELECT #define USE_SELECT
#ifndef WINSOCK #ifndef WINSOCK
#include <sys/select.h> #include <sys/select.h>
#endif #endif
#if ( defined(BSD_LIKE) && !defined(__FreeBSD_kernel__) ) || defined(__sun__) #if defined(BSD_LIKE) || defined(__sun__)
#undef HAVE_STRNDUP #undef HAVE_STRNDUP
#undef HAVE_MEMMEM #undef HAVE_MEMMEM
#endif #endif
@@ -282,14 +268,9 @@ typedef unsigned __int64 uint64_t;
#define open _open #define open _open
#define close _close #define close _close
#define read _read #define read _read
#define write _write
#define NEED_GETOPT #define NEED_GETOPT
#endif #endif
#ifdef POSIX_THREAD_SUPPORT
#include <pthread.h>
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER) #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
#define PLUGIN_API __declspec(dllexport) #define PLUGIN_API __declspec(dllexport)
#else #else

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -23,58 +23,7 @@
#define ADC_CID_SIZE 39 #define ADC_CID_SIZE 39
#define BIG_BUFSIZE 32768 #define BIG_BUFSIZE 32768
#define TIGERSIZE 24 #define TIGERSIZE 24
#define MAX_RECV_BUFFER 65536
// #define ADCC_DEBUG // #define ADCC_DEBUG
// #define ADC_CLIENT_DEBUG_PROTO
enum ADC_client_state
{
ps_none, /* Not connected */
ps_conn, /* Connecting... */
ps_conn_ssl, /* SSL handshake */
ps_protocol, /* Have sent HSUP */
ps_identify, /* Have sent BINF */
ps_verify, /* Have sent HPAS */
ps_normal, /* Are fully logged in */
};
enum ADC_client_flags
{
cflag_none = 0,
cflag_ssl = 1,
cflag_choke = 2,
cflag_pipe = 4,
};
struct ADC_client_address
{
enum Protocol { ADC, ADCS } protocol;
char* hostname;
uint16_t port;
};
struct ADC_client
{
sid_t sid;
enum ADC_client_state state;
struct adc_message* info;
struct ioq_recv* recv_queue;
struct ioq_send* send_queue;
adc_client_cb callback;
size_t s_offset;
size_t r_offset;
size_t timeout;
struct net_connection* con;
struct net_timer* timer;
struct sockaddr_storage addr;
struct net_connect_handle* connect_job;
struct ADC_client_address address;
char* nick;
char* desc;
int flags;
void* ptr;
};
static ssize_t ADC_client_recv(struct ADC_client* client); static ssize_t ADC_client_recv(struct ADC_client* client);
static void ADC_client_send_info(struct ADC_client* client); static void ADC_client_send_info(struct ADC_client* client);
@@ -85,8 +34,7 @@ static void ADC_client_on_connected_ssl(struct ADC_client* client);
static void ADC_client_on_disconnected(struct ADC_client* client); static void ADC_client_on_disconnected(struct ADC_client* client);
static void ADC_client_on_login(struct ADC_client* client); static void ADC_client_on_login(struct ADC_client* client);
static int ADC_client_parse_address(struct ADC_client* client, const char* arg); static int ADC_client_parse_address(struct ADC_client* client, const char* arg);
static int ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length); static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length);
static int ADC_client_send_queue(struct ADC_client* client);
static void ADC_client_debug(struct ADC_client* client, const char* format, ...) static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
{ {
@@ -168,6 +116,9 @@ static void event_callback(struct net_connection* con, int events, void *arg)
client->callback(client, ADC_CLIENT_DISCONNECTED, 0); client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
return; return;
} }
if (events & NET_EVENT_WRITE)
ADC_client_connect(client, 0);
break; break;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
@@ -193,7 +144,7 @@ static void event_callback(struct net_connection* con, int events, void *arg)
if (events & NET_EVENT_WRITE) if (events & NET_EVENT_WRITE)
{ {
ADC_client_send_queue(client); /* FIXME: Call send again */
} }
} }
} }
@@ -205,25 +156,12 @@ static void event_callback(struct net_connection* con, int events, void *arg)
TARGET = NULL; \ TARGET = NULL; \
hub_free(TMP); hub_free(TMP);
#define UNESCAPE_ARG_X(TMP, TARGET, SIZE) \
if (TMP) \
adc_msg_unescape_to_target(TMP, TARGET, SIZE); \
else \
TARGET[0] = '\0'; \
hub_free(TMP);
#define EXTRACT_NAMED_ARG(MSG, NAME, TARGET) \ #define EXTRACT_NAMED_ARG(MSG, NAME, TARGET) \
do { \ do { \
char* tmp = adc_msg_get_named_argument(MSG, NAME); \ char* tmp = adc_msg_get_named_argument(MSG, NAME); \
UNESCAPE_ARG(tmp, TARGET); \ UNESCAPE_ARG(tmp, TARGET); \
} while (0) } while (0)
#define EXTRACT_NAMED_ARG_X(MSG, NAME, TARGET, SIZE) \
do { \
char* tmp = adc_msg_get_named_argument(MSG, NAME); \
UNESCAPE_ARG_X(tmp, TARGET, SIZE); \
} while(0)
#define EXTRACT_POS_ARG(MSG, POS, TARGET) \ #define EXTRACT_POS_ARG(MSG, POS, TARGET) \
do { \ do { \
char* tmp = adc_msg_get_argument(MSG, POS); \ char* tmp = adc_msg_get_argument(MSG, POS); \
@@ -231,14 +169,11 @@ static void event_callback(struct net_connection* con, int events, void *arg)
} while (0) } while (0)
static int ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length) static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
{ {
struct ADC_chat_message chat;
struct ADC_client_callback_data data;
ADC_TRACE; ADC_TRACE;
#ifdef ADC_CLIENT_DEBUG_PROTO #ifdef ADC_CLIENT_DEBUG_PROTO
ADC_client_debug(client, "- LINE: '%s'", line); ADC_client_debug(client, "- LINE: '%s'", start);
#endif #endif
/* Parse message */ /* Parse message */
@@ -246,13 +181,13 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line,
if (!msg) if (!msg)
{ {
ADC_client_debug(client, "WARNING: Message cannot be decoded: \"%s\"", line); ADC_client_debug(client, "WARNING: Message cannot be decoded: \"%s\"", line);
return -1; return;
} }
if (length < 4) if (length < 4)
{ {
ADC_client_debug(client, "Unexpected response from hub: '%s'", line); ADC_client_debug(client, "Unexpected response from hub: '%s'", line);
return -1; return;
} }
switch (msg->cmd) switch (msg->cmd)
@@ -275,18 +210,12 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line,
case ADC_CMD_DMSG: case ADC_CMD_DMSG:
case ADC_CMD_IMSG: case ADC_CMD_IMSG:
{ {
struct ADC_chat_message chat;
struct ADC_client_callback_data data;
chat.from_sid = msg->source; chat.from_sid = msg->source;
chat.to_sid = msg->target; chat.to_sid = msg->target;
data.chat = &chat; data.chat = &chat;
EXTRACT_POS_ARG(msg, 0, chat.message); EXTRACT_POS_ARG(msg, 0, chat.message);
chat.flags = 0;
if (adc_msg_has_named_argument(msg, ADC_MSG_FLAG_ACTION))
chat.flags |= chat_flags_action;
if (adc_msg_has_named_argument(msg, ADC_MSG_FLAG_PRIVATE))
chat.flags |= chat_flags_private;
client->callback(client, ADC_CLIENT_MESSAGE, &data); client->callback(client, ADC_CLIENT_MESSAGE, &data);
hub_free(chat.message); hub_free(chat.message);
break; break;
@@ -330,33 +259,24 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line,
{ {
struct ADC_user user; struct ADC_user user;
user.sid = msg->source; user.sid = msg->source;
EXTRACT_NAMED_ARG_X(msg, "NI", user.name, sizeof(user.name)); EXTRACT_NAMED_ARG(msg, "NI", user.name);
EXTRACT_NAMED_ARG_X(msg, "DE", user.description, sizeof(user.description)); EXTRACT_NAMED_ARG(msg, "DE", user.description);
EXTRACT_NAMED_ARG_X(msg, "VE", user.version, sizeof(user.version)); EXTRACT_NAMED_ARG(msg, "VE", user.version);
EXTRACT_NAMED_ARG_X(msg, "ID", user.cid, sizeof(user.cid)); EXTRACT_NAMED_ARG(msg, "ID", user.cid);
EXTRACT_NAMED_ARG_X(msg, "I4", user.address, sizeof(user.address)); EXTRACT_NAMED_ARG(msg, "I4", user.address);
struct ADC_client_callback_data data; struct ADC_client_callback_data data;
data.user = &user; data.user = &user;
client->callback(client, ADC_CLIENT_USER_JOIN, &data); client->callback(client, ADC_CLIENT_USER_JOIN, &data);
hub_free(user.name);
hub_free(user.description);
hub_free(user.version);
hub_free(user.cid);
hub_free(user.address);
} }
} }
} }
break;
case ADC_CMD_IQUI:
{
struct ADC_client_quit_reason reason;
memset(&reason, 0, sizeof(reason));
reason.sid = string_to_sid(&line[5]);
if (adc_msg_has_named_argument(msg, ADC_QUI_FLAG_DISCONNECT))
reason.flags |= 1;
data.quit = &reason;
client->callback(client, ADC_CLIENT_USER_QUIT, &data);
break;
}
case ADC_CMD_ISTA: case ADC_CMD_ISTA:
/* /*
@@ -372,134 +292,77 @@ static int ADC_client_on_recv_line(struct ADC_client* client, const char* line,
} }
adc_msg_free(msg); adc_msg_free(msg);
return 0;
} }
static ssize_t ADC_client_recv(struct ADC_client* client) static ssize_t ADC_client_recv(struct ADC_client* client)
{ {
static char buf[BIG_BUFSIZE];
struct ioq_recv* q = client->recv_queue;
size_t buf_size = ioq_recv_get(q, buf, BIG_BUFSIZE);
ssize_t size;
ADC_TRACE; ADC_TRACE;
ssize_t size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset);
if (size <= 0)
return size;
if (client->flags & cflag_choke) client->r_offset += size;
buf_size = 0; client->recvbuf[client->r_offset] = 0;
size = net_con_recv(client->con, buf + buf_size, BIG_BUFSIZE - buf_size);
if (size > 0) char* start = client->recvbuf;
buf_size += size; char* pos;
if (size < 0)
return -1;
else if (size == 0)
return 0;
else
{
char* lastPos = 0; char* lastPos = 0;
char* start = buf; size_t remaining = client->r_offset;
char* pos = 0;
size_t remaining = buf_size;
while ((pos = memchr(start, '\n', remaining))) while ((pos = memchr(start, '\n', remaining)))
{ {
lastPos = pos+1; pos[0] = 0;
pos[0] = '\0';
#ifdef DEBUG_SENDQ ADC_client_on_recv_line(client, start, pos - start);
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
#endif
if (client->flags & cflag_choke)
client->flags &= ~cflag_choke;
else
{
if (((pos - start) > 0) && MAX_RECV_BUFFER > (pos - start))
{
if (ADC_client_on_recv_line(client, start, pos - start) == -1)
return -1;
}
}
pos[0] = '\n'; /* FIXME: not needed */
pos++; pos++;
remaining -= (pos - start); remaining -= (pos - start);
start = pos; start = pos;
lastPos = pos;
} }
if (lastPos || remaining) if (lastPos)
{ {
if (remaining < (size_t) MAX_RECV_BUFFER) memmove(client->recvbuf, lastPos, remaining);
{ client->r_offset = remaining;
ioq_recv_set(q, lastPos ? lastPos : buf, remaining);
}
else
{
ioq_recv_set(q, 0, 0);
client->flags |= cflag_choke;
LOG_WARN("Received message past MAX_RECV_BUFFER (%d), dropping message.", MAX_RECV_BUFFER);
}
}
else
{
ioq_recv_set(q, 0, 0);
}
}
return 0;
}
static int ADC_client_send_queue(struct ADC_client* client)
{
int ret = 0;
while (ioq_send_get_bytes(client->send_queue))
{
ret = ioq_send_send(client->send_queue, client->con);
if (ret <= 0)
break;
}
if (ret < 0)
return quit_socket_error;
if (ioq_send_get_bytes(client->send_queue))
{
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
}
else
{
net_con_update(client->con, NET_EVENT_READ);
} }
return 0; return 0;
} }
void ADC_client_send(struct ADC_client* client, struct adc_message* msg) void ADC_client_send(struct ADC_client* client, char* msg)
{ {
ADC_TRACE; ADC_TRACE;
int ret = net_con_send(client->con, msg, strlen(msg));
uhub_assert(client->con != NULL); #ifdef ADC_CLIENT_DEBUG_PROTO
uhub_assert(msg->cache && *msg->cache); char* dump = strdup(msg);
dump[strlen(msg) - 1] = 0;
ADC_client_debug(client, "- SEND: '%s'", dump);
free(dump);
#endif
if (ioq_send_is_empty(client->send_queue) && !(client->flags & cflag_pipe)) if (ret != strlen(msg))
{ {
/* Perform oportunistic write */ if (ret == -1)
ioq_send_add(client->send_queue, msg); {
ADC_client_send_queue(client); if (net_error() != EWOULDBLOCK)
ADC_client_on_disconnected(client);
} }
else else
{ {
ioq_send_add(client->send_queue, msg); /* FIXME: Not all data sent! */
if (!(client->flags & cflag_pipe)) printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); }
} }
} }
void ADC_client_send_info(struct ADC_client* client) void ADC_client_send_info(struct ADC_client* client)
{ {
ADC_TRACE; ADC_TRACE;
client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96); char binf[11];
snprintf(binf, 11, "BINF %s\n", sid_to_string(client->sid));
client->info = adc_msg_create(binf);
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick);
@@ -508,91 +371,75 @@ void ADC_client_send_info(struct ADC_client* client)
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc);
} }
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT " " VERSION); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SLOTS, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_SIZE, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_FILES, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_NORMAL, 1);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_REGISTER, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_OPERATOR, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_DOWNLOAD_SPEED, 5 * 1024 * 1024);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024);
adc_cid_pid(client); adc_cid_pid(client);
ADC_client_send(client, client->info->cache);
ADC_client_send(client, client->info);
} }
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description)
struct ADC_client* ADC_client_create(const char* nickname, const char* description, void* ptr)
{ {
ADC_TRACE; ADC_TRACE;
struct ADC_client* client = (struct ADC_client*) hub_malloc_zero(sizeof(struct ADC_client)); memset(client, 0, sizeof(struct ADC_client));
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1) return -1;
client->con = net_con_create();
#if 0
/* FIXME */
client->timer = 0; /* FIXME: hub_malloc(sizeof(struct net_timer)); */
#endif
net_con_initialize(client->con, sd, event_callback, client, 0);
#if 0
/* FIXME */
net_timer_initialize(client->timer, timer_callback, client);
#endif
ADC_client_set_state(client, ps_none); ADC_client_set_state(client, ps_none);
client->nick = hub_strdup(nickname); client->nick = hub_strdup(nickname);
client->desc = hub_strdup(description); client->desc = hub_strdup(description);
client->send_queue = ioq_send_create(); return 0;
client->recv_queue = ioq_recv_create();
client->ptr = ptr;
return client;
} }
void ADC_client_destroy(struct ADC_client* client) void ADC_client_destroy(struct ADC_client* client)
{ {
ADC_TRACE; ADC_TRACE;
ADC_client_disconnect(client); ADC_client_disconnect(client);
ioq_send_destroy(client->send_queue); #if 0
ioq_recv_destroy(client->recv_queue); /* FIXME */
net_timer_shutdown(client->timer);
#endif
hub_free(client->timer); hub_free(client->timer);
adc_msg_free(client->info); adc_msg_free(client->info);
hub_free(client->nick); hub_free(client->nick);
hub_free(client->desc); hub_free(client->desc);
hub_free(client->address.hostname); hub_free(client->hub_address);
hub_free(client);
}
static void connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con, void* ptr)
{
struct ADC_client* client = (struct ADC_client*) ptr;
client->connect_job = NULL;
switch (status)
{
case net_connect_status_ok:
client->con = con;
net_con_reinitialize(client->con, event_callback, client, 0);
ADC_client_on_connected(client);
break;
case net_connect_status_host_not_found:
case net_connect_status_no_address:
case net_connect_status_dns_error:
case net_connect_status_refused:
case net_connect_status_unreachable:
case net_connect_status_timeout:
case net_connect_status_socket_error:
ADC_client_disconnect(client);
break;
}
} }
int ADC_client_connect(struct ADC_client* client, const char* address) int ADC_client_connect(struct ADC_client* client, const char* address)
{ {
ADC_TRACE; ADC_TRACE;
if (client->state == ps_none) if (!client->hub_address)
{ {
if (!ADC_client_parse_address(client, address)) if (!ADC_client_parse_address(client, address))
return 0; return 0;
client->callback(client, ADC_CLIENT_CONNECTING, 0);
} }
int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
ADC_client_on_connected(client);
}
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
{
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
ADC_client_set_state(client, ps_conn); ADC_client_set_state(client, ps_conn);
client->connect_job = net_con_connect(client->address.hostname, client->address.port, connect_callback, client); }
if (!client->connect_job) else
{ {
ADC_client_on_disconnected(client); ADC_client_on_disconnected(client);
return 0; return 0;
@@ -600,28 +447,23 @@ int ADC_client_connect(struct ADC_client* client, const char* address)
return 1; return 1;
} }
static void ADC_client_on_connected(struct ADC_client* client) static void ADC_client_on_connected(struct ADC_client* client)
{ {
ADC_TRACE; ADC_TRACE;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (client->flags & cflag_ssl) if (client->ssl_enabled)
{ {
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE); net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0); client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0);
ADC_client_set_state(client, ps_conn_ssl); ADC_client_set_state(client, ps_conn_ssl);
net_con_ssl_handshake(client->con, net_con_ssl_mode_client, NULL);
} }
else else
#endif #endif
{ {
struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE);
net_con_update(client->con, NET_EVENT_READ); net_con_update(client->con, NET_EVENT_READ);
client->callback(client, ADC_CLIENT_CONNECTED, 0); client->callback(client, ADC_CLIENT_CONNECTED, 0);
ADC_client_send(client, handshake); ADC_client_send(client, ADC_HANDSHAKE);
ADC_client_set_state(client, ps_protocol); ADC_client_set_state(client, ps_protocol);
adc_msg_free(handshake);
} }
} }
@@ -629,13 +471,10 @@ static void ADC_client_on_connected(struct ADC_client* client)
static void ADC_client_on_connected_ssl(struct ADC_client* client) static void ADC_client_on_connected_ssl(struct ADC_client* client)
{ {
ADC_TRACE; ADC_TRACE;
struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE);
client->callback(client, ADC_CLIENT_SSL_OK, 0);
client->callback(client, ADC_CLIENT_CONNECTED, 0);
net_con_update(client->con, NET_EVENT_READ); net_con_update(client->con, NET_EVENT_READ);
ADC_client_send(client, handshake); client->callback(client, ADC_CLIENT_CONNECTED, 0);
ADC_client_send(client, ADC_HANDSHAKE);
ADC_client_set_state(client, ps_protocol); ADC_client_set_state(client, ps_protocol);
adc_msg_free(handshake);
} }
#endif #endif
@@ -667,45 +506,55 @@ void ADC_client_disconnect(struct ADC_client* client)
static int ADC_client_parse_address(struct ADC_client* client, const char* arg) static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
{ {
ADC_TRACE; ADC_TRACE;
const char* hub_address = arg;
char* split; char* split;
int ssl = 0; int ssl = 0;
struct hostent* dns;
struct in_addr* addr;
if (!arg) if (!arg)
return 0; return 0;
client->hub_address = hub_strdup(arg);
/* Minimum length of a valid address */ /* Minimum length of a valid address */
if (strlen(arg) < 9) if (strlen(arg) < 9)
return 0; return 0;
/* Check for ADC or ADCS */ /* Check for ADC or ADCS */
if (!strncmp(arg, "adc://", 6)) if (!strncmp(arg, "adc://", 6))
{ client->ssl_enabled = 0;
client->flags &= ~cflag_ssl;
client->address.protocol = ADC;
}
else if (!strncmp(arg, "adcs://", 7)) else if (!strncmp(arg, "adcs://", 7))
{ {
client->flags |= cflag_ssl; client->ssl_enabled = 1;
ssl = 1; ssl = 1;
client->address.protocol = ADCS;
} }
else else
return 0; return 0;
/* Split hostname and port (if possible) */ /* Split hostname and port (if possible) */
hub_address = arg + 6 + ssl; split = strrchr(client->hub_address + 6 + ssl, ':');
split = strrchr(hub_address, ':');
if (split == 0 || strlen(split) < 2 || strlen(split) > 6) if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0; return 0;
/* Ensure port number is valid */ /* Ensure port number is valid */
client->address.port = strtol(split+1, NULL, 10); int port = strtol(split+1, NULL, 10);
if (client->address.port <= 0 || client->address.port > 65535) if (port <= 0 || port > 65535)
return 0; return 0;
client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]); split[0] = 0;
/* Resolve IP address (FIXME: blocking call) */
dns = gethostbyname(client->hub_address + 6 + ssl);
if (dns)
{
addr = (struct in_addr*) dns->h_addr_list[0];
}
// Initialize the sockaddr struct.
memset(&client->addr, 0, sizeof(client->addr));
client->addr.sin_family = AF_INET;
client->addr.sin_port = htons(port);
memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr));
return 1; return 1;
} }
@@ -714,23 +563,3 @@ void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb)
ADC_TRACE; ADC_TRACE;
client->callback = cb; client->callback = cb;
} }
sid_t ADC_client_get_sid(const struct ADC_client* client)
{
return client->sid;
}
const char* ADC_client_get_nick(const struct ADC_client* client)
{
return client->nick;
}
const char* ADC_client_get_description(const struct ADC_client* client)
{
return client->desc;
}
void* ADC_client_get_ptr(const struct ADC_client* client)
{
return client->ptr;
}

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -24,11 +24,21 @@
#define ADC_BUFSIZE 16384 #define ADC_BUFSIZE 16384
enum ADC_client_state
{
ps_none, /* Not connected */
ps_conn, /* Connecting... */
ps_conn_ssl, /* SSL handshake */
ps_protocol, /* Have sent HSUP */
ps_identify, /* Have sent BINF */
ps_verify, /* Have sent HPAS */
ps_normal, /* Are fully logged in */
};
struct ADC_client; struct ADC_client;
enum ADC_client_callback_type enum ADC_client_callback_type
{ {
ADC_CLIENT_NAME_LOOKUP = 1000,
ADC_CLIENT_CONNECTING = 1001, ADC_CLIENT_CONNECTING = 1001,
ADC_CLIENT_CONNECTED = 1002, ADC_CLIENT_CONNECTED = 1002,
ADC_CLIENT_DISCONNECTED = 1003, ADC_CLIENT_DISCONNECTED = 1003,
@@ -61,13 +71,6 @@ struct ADC_hub_info
char* version; char* version;
}; };
enum ADC_chat_message_flags
{
chat_flags_none = 0,
chat_flags_action = 1,
chat_flags_private = 2
};
struct ADC_chat_message struct ADC_chat_message
{ {
sid_t from_sid; sid_t from_sid;
@@ -76,23 +79,14 @@ struct ADC_chat_message
int flags; int flags;
}; };
#define MAX_DESC_LEN 128
struct ADC_user struct ADC_user
{ {
sid_t sid; sid_t sid;
char cid[MAX_CID_LEN+1]; char* cid;
char name[MAX_NICK_LEN+1]; char* name;
char description[MAX_DESC_LEN+1]; char* description;
char address[INET6_ADDRSTRLEN+1]; char* address;
char version[MAX_UA_LEN+1]; char* version;
};
struct ADC_client_quit_reason
{
sid_t sid;
sid_t initator; // 0 = default/hub.
char message[128]; // optional
int flags;
}; };
@@ -102,23 +96,41 @@ struct ADC_client_callback_data
struct ADC_hub_info* hubinfo; struct ADC_hub_info* hubinfo;
struct ADC_chat_message* chat; struct ADC_chat_message* chat;
struct ADC_user* user; struct ADC_user* user;
struct ADC_client_quit_reason* quit;
}; };
}; };
sid_t ADC_client_get_sid(const struct ADC_client* client);
const char* ADC_client_get_nick(const struct ADC_client* client);
const char* ADC_client_get_description(const struct ADC_client* client);
void* ADC_client_get_ptr(const struct ADC_client* client);
typedef int (*adc_client_cb)(struct ADC_client*, enum ADC_client_callback_type, struct ADC_client_callback_data* data); typedef int (*adc_client_cb)(struct ADC_client*, enum ADC_client_callback_type, struct ADC_client_callback_data* data);
struct ADC_client* ADC_client_create(const char* nickname, const char* description, void* ptr); struct ADC_client
{
sid_t sid;
enum ADC_client_state state;
struct adc_message* info;
char recvbuf[ADC_BUFSIZE];
char sendbuf[ADC_BUFSIZE];
adc_client_cb callback;
size_t s_offset;
size_t r_offset;
size_t timeout;
struct net_connection* con;
struct net_timer* timer;
struct sockaddr_in addr;
char* hub_address;
char* nick;
char* desc;
int ssl_enabled;
#ifdef SSL_SUPPORT
const SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
#endif /* SSL_SUPPORT */
};
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description);
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb); void ADC_client_set_callback(struct ADC_client* client, adc_client_cb);
void ADC_client_destroy(struct ADC_client* client); void ADC_client_destroy(struct ADC_client* client);
int ADC_client_connect(struct ADC_client* client, const char* address); int ADC_client_connect(struct ADC_client* client, const char* address);
void ADC_client_disconnect(struct ADC_client* client); void ADC_client_disconnect(struct ADC_client* client);
void ADC_client_send(struct ADC_client* client, struct adc_message* msg); void ADC_client_send(struct ADC_client* client, char* msg);
#endif /* HAVE_UHUB_ADC_CLIENT_H */ #endif /* HAVE_UHUB_ADC_CLIENT_H */

View File

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

View File

@@ -19,128 +19,52 @@
#include "adcclient.h" #include "adcclient.h"
static struct ADC_user g_usermap[SID_MAX];
static void user_add(const struct ADC_user* user)
{
printf(" >> JOIN: %s (%s)\n", user->name, user->address);
memcpy(&g_usermap[user->sid], user, sizeof(struct ADC_user));
}
static struct ADC_user* user_get(sid_t sid)
{
struct ADC_user* user = &g_usermap[sid];
uhub_assert(user->sid != 0);
return user;
}
static void user_remove(const struct ADC_client_quit_reason* quit)
{
struct ADC_user* user = user_get(quit->sid);
printf(" << QUIT: %s (%s)\n", user->name, quit->message);
memset(&g_usermap[quit->sid], 0, sizeof(struct ADC_user));
}
static void on_message(struct ADC_chat_message* chat)
{
struct ADC_user* user;
const char* pm = (chat->flags & chat_flags_private) ? "PM" : " ";
const char* brack1 = (chat->flags & chat_flags_action) ? "*" : "<";
const char* brack2 = (chat->flags & chat_flags_action) ? "" : ">";
struct linked_list* lines;
int ret;
char* line;
if (!chat->from_sid)
{
printf("HUB ");
}
else
{
user = user_get(chat->from_sid);
printf(" %s %s%s%s ", pm, brack1, user->name, brack2);
}
lines = list_create();
ret = split_string(chat->message, "\n", lines, 1);
line = (char*) list_get_first(lines);
ret = 0;
while (line)
{
if (ret > 0)
printf(" ");
printf("%s\n", line);
ret++;
line = (char*) list_get_next(lines);
}
list_clear(lines, &hub_free);
list_destroy(lines);
}
static void status(const char* msg)
{
printf("*** %s\n", msg);
}
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data) static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data)
{ {
switch (type) switch (type)
{ {
case ADC_CLIENT_NAME_LOOKUP:
status("Looking up hostname...");
break;
case ADC_CLIENT_CONNECTING: case ADC_CLIENT_CONNECTING:
status("Connecting..."); puts("*** Connecting...");
break; break;
case ADC_CLIENT_CONNECTED: case ADC_CLIENT_CONNECTED:
status("Connected."); puts("*** Connected.");
break; break;
case ADC_CLIENT_DISCONNECTED: case ADC_CLIENT_DISCONNECTED:
status("Disconnected."); puts("*** Disconnected.");
break; break;
case ADC_CLIENT_SSL_HANDSHAKE: case ADC_CLIENT_SSL_HANDSHAKE:
status("SSL handshake."); puts("*** SSL handshake.");
break;
case ADC_CLIENT_SSL_OK:
break; break;
case ADC_CLIENT_LOGGING_IN: case ADC_CLIENT_LOGGING_IN:
status("Logging in..."); puts("*** Logging in...");
break; break;
case ADC_CLIENT_PASSWORD_REQ: case ADC_CLIENT_PASSWORD_REQ:
status("Requesting password."); puts("*** Requesting password.");
break; break;
case ADC_CLIENT_LOGGED_IN: case ADC_CLIENT_LOGGED_IN:
status("Logged in."); puts("*** Logged in.");
break; break;
case ADC_CLIENT_LOGIN_ERROR: case ADC_CLIENT_LOGIN_ERROR:
status("Login error"); puts("*** Login error");
break; break;
case ADC_CLIENT_MESSAGE: case ADC_CLIENT_MESSAGE:
on_message(data->chat); printf(" <%s> %s\n", sid_to_string(data->chat->from_sid), data->chat->message);
break; break;
case ADC_CLIENT_USER_JOIN: case ADC_CLIENT_USER_JOIN:
printf(" JOIN: %s %s\n", sid_to_string(data->user->sid), data->user->name);
user_add(data->user);
break; break;
case ADC_CLIENT_USER_QUIT: case ADC_CLIENT_USER_QUIT:
user_remove(data->quit); printf(" QUIT\n");
break; break;
case ADC_CLIENT_SEARCH_REQ: case ADC_CLIENT_SEARCH_REQ:
@@ -161,68 +85,6 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
static int running = 1; static int running = 1;
#if !defined(WIN32)
void adm_handle_signal(int sig)
{
switch (sig)
{
case SIGINT:
LOG_INFO("Interrupted. Shutting down...");
running = 0;
break;
case SIGTERM:
LOG_INFO("Terminated. Shutting down...");
running = 0;
break;
case SIGPIPE:
break;
case SIGHUP:
break;
default:
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
running = 0;
break;
}
}
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
SIGPIPE, /* prevent sigpipe from kills the application */
SIGHUP, /* reload configuration */
0
};
void adm_setup_signal_handlers()
{
sigset_t sig_set;
struct sigaction act;
int i;
sigemptyset(&sig_set);
act.sa_mask = sig_set;
act.sa_flags = SA_ONSTACK | SA_RESTART;
act.sa_handler = adm_handle_signal;
for (i = 0; signals[i]; i++)
{
if (sigaction(signals[i], &act, 0) != 0)
{
LOG_ERROR("Error setting signal handler %d", signals[i]);
}
}
}
void adm_shutdown_signal_handlers()
{
}
#endif /* !WIN32 */
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc < 2) if (argc < 2)
@@ -231,23 +93,17 @@ int main(int argc, char** argv)
return 1; return 1;
} }
hub_set_log_verbosity(5); struct ADC_client client;
adm_setup_signal_handlers();
struct ADC_client* client;
net_initialize(); net_initialize();
memset(g_usermap, 0, sizeof(g_usermap)); ADC_client_create(&client, "uhub-admin", "stresstester");
ADC_client_set_callback(&client, handle);
client = ADC_client_create("uhub-admin", "stresstester", NULL); ADC_client_connect(&client, argv[1]);
ADC_client_set_callback(client, handle);
ADC_client_connect(client, argv[1]);
while (running && net_backend_process()) { } while (running && net_backend_process()) { }
ADC_client_destroy(client); ADC_client_destroy(&client);
net_destroy(); net_destroy();
adm_shutdown_signal_handlers();
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2011, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -18,7 +18,6 @@
*/ */
#include "uhub.h" #include "uhub.h"
#include "util/misc.h"
#include <sqlite3.h> #include <sqlite3.h>
// #define DEBUG_SQL // #define DEBUG_SQL
@@ -105,59 +104,6 @@ static const char* validate_cred(const char* cred_str)
exit(1); exit(1);
} }
static const char* validate_username(const char* username)
{
const char* tmp;
// verify length
if (strlen(username) > MAX_NICK_LEN)
{
fprintf(stderr, "User name is too long.\n");
exit(1);
}
/* Nick must not start with a space */
if (is_white_space(username[0]))
{
fprintf(stderr, "User name cannot start with white space.\n");
exit(1);
}
/* Check for ASCII values below 32 */
for (tmp = username; *tmp; tmp++)
if ((*tmp < 32) && (*tmp > 0))
{
fprintf(stderr, "User name contains illegal characters.\n");
exit(1);
}
if (!is_valid_utf8(username))
{
fprintf(stderr, "User name must be utf-8 encoded.\n");
exit(1);
}
return username;
}
static const char* validate_password(const char* password)
{
// verify length
if (strlen(password) > MAX_PASS_LEN)
{
fprintf(stderr, "Password is too long.\n");
exit(1);
}
if (!is_valid_utf8(password))
{
fprintf(stderr, "Password must be utf-8 encoded.\n");
exit(1);
}
return password;
}
static void open_database() static void open_database()
{ {
@@ -256,8 +202,8 @@ static int add(size_t argc, const char** argv)
if (argc < 2) if (argc < 2)
print_usage("username password [credentials = user]"); print_usage("username password [credentials = user]");
user = sql_escape_string(validate_username(argv[0])); user = sql_escape_string(argv[0]);
pass = sql_escape_string(validate_password(argv[1])); pass = sql_escape_string(argv[1]);
cred = validate_cred(argv[2] ? argv[2] : "user"); cred = validate_cred(argv[2] ? argv[2] : "user");
rc = sql_execute("INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", user, pass, cred); rc = sql_execute("INSERT INTO users (nickname, password, credentials) VALUES('%s', '%s', '%s');", user, pass, cred);
@@ -307,7 +253,7 @@ static int pass(size_t argc, const char** argv)
print_usage("username password"); print_usage("username password");
user = sql_escape_string(argv[0]); user = sql_escape_string(argv[0]);
pass = sql_escape_string(validate_password(argv[1])); pass = sql_escape_string(argv[1]);
rc = sql_execute("UPDATE users SET password = '%s' WHERE nickname = '%s';", pass, user); rc = sql_execute("UPDATE users SET password = '%s' WHERE nickname = '%s';", pass, user);
@@ -329,7 +275,7 @@ static int del(size_t argc, const char** argv)
char* user = NULL; char* user = NULL;
int rc; int rc;
if (argc < 1) if (argc < 2)
print_usage("username"); print_usage("username");
user = sql_escape_string(argv[0]); user = sql_escape_string(argv[0]);
@@ -361,11 +307,11 @@ void main_usage(const char* binary)
"\n" "\n"
"Parameters:\n" "Parameters:\n"
" 'filename' is a database file\n" " 'filename' is a database file\n"
" 'username' is a nickname (UTF-8, up to %i bytes)\n" " 'username' is a nickname (UTF-8, up to 64 bytes)\n"
" 'password' is a password (UTF-8, up to %i bytes)\n" " 'password' is a password (UTF-8, up to 64 bytes)\n"
" 'credentials' is one of 'admin', 'super', 'op', 'user'\n" " 'credentials' is one of 'admin', 'super', 'op', 'user'\n"
"\n" "\n"
, binary, MAX_NICK_LEN, MAX_PASS_LEN); , binary);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@@ -384,7 +330,7 @@ int main(int argc, char** argv)
for (; n < sizeof(COMMANDS) / sizeof(COMMANDS[0]); n++) for (; n < sizeof(COMMANDS) / sizeof(COMMANDS[0]); n++)
{ {
if (!strcmp(command, COMMANDS[n].command)) if (!strcmp(command, COMMANDS[n].command))
return COMMANDS[n].handle(argc - 3, (const char**) &argv[3]); return COMMANDS[n].handle(argc - 2, (const char**) &argv[3]);
} }
// Unknown command! // Unknown command!

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@
#define TIMEOUT_CONNECTED 15 #define TIMEOUT_CONNECTED 15
#define TIMEOUT_HANDSHAKE 30 #define TIMEOUT_HANDSHAKE 30
#define TIMEOUT_SENDQ 120 #define TIMEOUT_SENDQ 120
#define TIMEOUT_STATS 10 #define TIMEOUT_STATS 60
#define MAX_CID_LEN 39 #define MAX_CID_LEN 39
#define MAX_NICK_LEN 64 #define MAX_NICK_LEN 64
@@ -63,20 +63,18 @@ extern "C" {
#include "util/credentials.h" #include "util/credentials.h"
#include "util/floodctl.h" #include "util/floodctl.h"
#include "util/getopt.h" #include "util/getopt.h"
#include "util/ipcalc.h"
#include "util/list.h" #include "util/list.h"
#include "util/log.h" #include "util/log.h"
#include "util/memory.h" #include "util/memory.h"
#include "util/misc.h" #include "util/misc.h"
#include "util/tiger.h" #include "util/tiger.h"
#include "util/threads.h"
#include "adc/sid.h" #include "adc/sid.h"
#include "adc/message.h" #include "adc/message.h"
#include "network/network.h" #include "network/network.h"
#include "network/connection.h" #include "network/connection.h"
#include "network/dnsresolver.h"
#include "network/ipcalc.h"
#include "network/timeout.h" #include "network/timeout.h"
#include "core/auth.h" #include "core/auth.h"
@@ -84,13 +82,12 @@ extern "C" {
#include "core/eventid.h" #include "core/eventid.h"
#include "core/eventqueue.h" #include "core/eventqueue.h"
#include "core/netevent.h" #include "core/netevent.h"
#include "core/ioqueue.h" #include "core/hubio.h"
#include "core/user.h" #include "core/user.h"
#include "core/usermanager.h" #include "core/usermanager.h"
#include "core/route.h" #include "core/route.h"
#include "core/pluginloader.h" #include "core/pluginloader.h"
#include "core/hub.h" #include "core/hub.h"
#include "core/command_parser.h"
#include "core/commands.h" #include "core/commands.h"
#include "core/inf.h" #include "core/inf.h"
#include "core/hubevent.h" #include "core/hubevent.h"

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