Compare commits

..

103 Commits

Author SHA1 Message Date
Jan Vidar Krey
05edfa48b2 Merge pull request #25 from schreda/master
added broadcast message and getter for user count in plugin API
2014-10-17 00:09:56 +02:00
Jan Vidar Krey
204544298b Cleanup debug logging. 2014-10-16 23:14:12 +02:00
Jan Vidar Krey
418db22931 Merge branch 'master' of github.com:janvidar/uhub 2014-10-16 23:10:28 +02:00
Jan Vidar Krey
037ceff0a5 Disable SSLv3 explicitly also. 2014-10-16 23:09:50 +02:00
Jan Vidar Krey
44708e8433 Move some network, timer code. 2014-10-16 23:09:12 +02:00
Jan Vidar Krey
76ff2a1a13 Fix TLS protocol mismatch assert causing the hub to shutdown. 2014-10-16 23:08:17 +02:00
Jan Vidar Krey
280e28a6d4 Merge pull request #26 from Tilka/foo
Release all memory in tests
2014-10-06 22:28:41 +02:00
Tillmann Karras
c0ee55325c Release all memory in tests and fix comment 2014-10-06 21:06:33 +02:00
Tillmann Karras
3d0b652ec9 Remove some unused variables 2014-10-06 21:02:08 +02:00
Andre Schreder
2d45a37536 added broadcast message and getter for user count in plugin API 2014-10-03 15:23:36 +02:00
Jan Vidar Krey
1da917e5b9 Fix crash due to negative max copy length. 2014-09-23 00:01:15 +02:00
Jan Vidar Krey
f71bc59527 Release version 0.5.0. 2014-08-06 20:56:07 +02:00
Jan Vidar Krey
d7c8c9426d Fix memory leak by creating the SSL context once for ADC client.
This is done using reference counted global memory.
2014-08-06 17:37:06 +02:00
Jan Vidar Krey
4919aea8d5 Send information through ADC client interface about the TLS connection. 2014-08-05 17:45:32 +02:00
Jan Vidar Krey
95de69efeb Added functionality to fetch the TLS version and cipher info for a connection. 2014-08-05 17:43:24 +02:00
Jan Vidar Krey
b3b4876c08 Use TLS 1.2 when connecting to a hub when using TLS. 2014-08-05 17:42:18 +02:00
Jan Vidar Krey
ac543e3df4 Clear connection timeout timer when successfully connecting. 2014-08-05 17:40:55 +02:00
Jan Vidar Krey
46bdc77066 Added a notification mechanism for sending messages from
another thread to the mainthread in a safe manner.

This is used for the DNS lookup code, and can also
be used by the signal handler to safely report actions back
to the application mainloop without using global variables.
2014-08-05 16:21:56 +02:00
Jan Vidar Krey
1526d63403 Simplify list_clear(), allow NULL as free() function pointer.
This makes it redundant to create a null_free() or dummy_free() function
that does nothing.
2014-08-05 13:08:46 +02:00
klondike
d33695435b Add propper check for stdint.h 2014-08-05 10:48:42 +02:00
klondike
bfdf707490 Remove unnecessary include 2014-08-05 10:48:34 +02:00
klondike
b8209d9d0a Check for ssize_t properly 2014-08-05 10:48:26 +02:00
klondike
5c8d99d8ff _GNU_SOURCE is now defined by CMake 2014-08-05 10:48:10 +02:00
klondike
4c5038c26d Add automatic strndup detection instead of the previous hack 2014-08-05 10:48:01 +02:00
klondike
aeb006beb6 Add automatic memmem detction instead of the previous hack 2014-08-05 10:47:49 +02:00
klondike
3b6c338ee8 Start generating system.h dynamicallly 2014-08-05 10:47:29 +02:00
Jan Vidar Krey
652ac5f9b9 Fix #211 - ADC IINF should have flag AP for application name, and VE for version.
x# Please enter the commit message for your changes. Lines starting
2014-08-03 22:51:47 +02:00
Jan Vidar Krey
4263750bc5 Merge branch 'ssl_fixes' 2014-07-30 11:47:27 +02:00
Jan Vidar Krey
2182feb052 Added support for probing HTTP, enough to tell browsers to stop calling. 2014-07-30 11:46:54 +02:00
Jan Vidar Krey
48b76f7bd1 The DEBUG macro never got set, causes verbose log messages to never be compiled in. 2014-07-30 11:46:03 +02:00
Jan Vidar Krey
b5bedfe9e4 uhub-admin: don't busy loop before a connection has been established.
This happened due to the network polling mechanism had nothing to poll
for, so it returned immediately only to be called again (during DNS lookup).

This fix introduces a control pipe that is polled for reading, althoug nothing
is ever sent to that pipe. But, it can be used instead of the signal
handler approach which is currently used for terminating the program.
2014-07-29 17:35:58 +02:00
Jan Vidar Krey
cbe0b4e108 Potential crash fix for tools. 2014-07-29 17:35:14 +02:00
Jan Vidar Krey
b85381c0f5 Added configuration options for TLS cipher suites and TLS versions. 2014-07-29 13:31:42 +02:00
Hector Martin
0426cb523a Fix: Rework SSL poll event handling to avoid infinite loops
The downstream connection callback must only be invoked when the event
that SSL requests for the connection to make progress has actually
occured. Otherwise, the downstream callback might do nothing but
re-queue an unrelated event (e.g. in user_net_io_want_write), and the
event loop comes around instantly while making no progress. Track the
SSL-requested events separately and deliver the required downstream
event when they fire.

Sample strace:

epoll_wait(0, {{EPOLLIN, {u32=96, u64=96}}}, 91, 10000) = 1
: net_ssl_callback in state tls_st_need_write calls cb NET_EVENT_WRITE
: User writes data, OpenSSL tries to write data
write(96, <snip>..., 170) = -1 EAGAIN (Resource temporarily unavailable)
: handle_openssl_error requests NET_EVENT_WRITE
epoll_ctl(0, EPOLL_CTL_MOD, 96, {EPOLLOUT, {u32=96, u64=96}}) = 0
: User callback then requests NET_EVENT_READ|NET_EVENT_WRITE
epoll_ctl(0, EPOLL_CTL_MOD, 96, {EPOLLIN|EPOLLOUT, {u32=96, u64=96}}) =
: Data available for *reading*
epoll_wait(0, {{EPOLLIN, {u32=96, u64=96}}}, 91, 10000) = 1
: net_ssl_callback in state tls_st_need_write calls cb NET_EVENT_WRITE
: again...
2014-07-29 12:09:07 +02:00
Jan Vidar Krey
9f78a2e85f Merge branch 'master' of github.com:janvidar/uhub 2014-05-30 15:06:23 +02:00
Jan Vidar Krey
f472fc9424 Fix Clang compile warnings. 2014-05-14 21:00:42 +02:00
Jan Vidar Krey
7706e1cb8a Fix copyright year. 2014-05-14 11:39:18 +02:00
Jan Vidar Krey
24b98358d3 Remove usage of strcat, since OpenBSD does not like that. 2014-05-14 11:00:18 +02:00
Jan Vidar Krey
12ce522a6d Fix crashing autotest due to wrong initialization of the usermanager. 2014-05-14 11:00:14 +02:00
Jan Vidar Krey
5e06b46deb Fix compile warning due to missing newline at EOF. 2014-05-14 11:00:04 +02:00
Jan Vidar Krey
a1f8c5bdbb Merge pull request #24 from tehnick/travis-ci
Add support of Travis CI.
2014-05-12 10:04:03 +02:00
Jan Vidar Krey
992aa8c4af Fix compile warning due to missing return value. 2014-05-12 00:05:07 +02:00
Jan Vidar Krey
60393ca9d0 Merge pull request #23 from tehnick/fix-clang
Fix build with Clang.
2014-05-12 00:01:50 +02:00
Boris Pek
89aef4ddaf Add support of Travis CI. 2014-05-11 16:07:38 +04:00
Boris Pek
a38a82e318 Fix build with clang. 2014-05-11 15:22:14 +04:00
Jan Vidar Krey
3e8699ab24 Fix typo. 2014-05-10 01:08:32 +02:00
Jan Vidar Krey
3b38898045 Merge pull request #22 from tehnick/cmake-fix
Delete extra option from cmake rules.
2014-05-10 00:45:23 +02:00
Jan Vidar Krey
1b8762c7ee Merge pull request #20 from tehnick/cmake-sqlite3-fix
Fix cmake script for searching sqlite3 properly.
2014-05-10 00:44:28 +02:00
Boris Pek
ce06269128 Delete extra option from cmake rules. 2014-05-10 02:03:04 +04:00
Boris Pek
e75a759693 Fix cmake script for searching sqlite3 properly.
This is important for Debian, Ubuntu and other systems based on them. Details:
  https://wiki.debian.org/Multiarch
  https://wiki.ubuntu.com/MultiarchSpec

Have in mind that there are MIPS, ARM and many other architectures...
2014-05-08 22:52:10 +04:00
Jan Vidar Krey
7f2ffd7e1c Fix CMake/SQLite path issues on 64-bit Ubuntu 14.04 2014-05-08 13:33:45 +02:00
Jan Vidar Krey
e2b0757f4a Improved flood control counting to strictly not allow more than
the given amount of messages in the configured interval.

The previous behavior allowed n+2 messages in the interval, due to
two off by one comparison rules.

In addition, if flooding is detected then each new message after the flooding
is detected will reset the interval timer, which means the client
cannot send another message until the timeout interval expires.
2014-05-08 13:30:09 +02:00
Jan Vidar Krey
c26e8aaefe Merge pull request #19 from Tilka/master
Bunch of fixes
2013-09-10 01:38:29 -07:00
Tillmann Karras
c295461f4e mod_topic: check argument for NULL
Better safe than sorry.
2013-09-10 08:30:27 +02:00
Tillmann Karras
8b442018a7 Fix struct mixup 2013-09-06 21:17:43 +02:00
Tillmann Karras
fa782e3d2c Fix memleak 2013-09-06 21:17:31 +02:00
Tilka
591d0ba5bb Support certificate chains 2013-09-06 01:44:25 +02:00
Tilka
a81757c483 Merge remote-tracking branch 'upstream/master' 2013-09-06 01:43:10 +02:00
Jan Vidar Krey
cf9be754aa Rewrote the configuration file parser generator.
Converted from Perl to Python for a better
and cleaner object oriented design.
2013-04-22 21:58:06 +02:00
Jan Vidar Krey
22292e493e fixup! Fix for #193 - Can't build on OpenBSD 2013-04-17 22:40:04 +02:00
Jan Vidar Krey
419e8888d0 Fix for #193 - Can't build on OpenBSD 2013-04-16 00:24:42 +02:00
Jan Vidar Krey
73b4d51393 fixup! fixup! Updated copyright year. 2013-03-24 20:17:51 +01:00
Jan Vidar Krey
50b6221874 fixup! Updated copyright year. 2013-03-24 20:17:51 +01:00
Jan Vidar Krey
bb5865d368 Fix double free() 2013-03-24 09:47:32 +01:00
Jan Vidar Krey
550740f715 Fix bug #198 - Timers could cause infinite loops
This could essentially happen due to time drift,
high load, or the process being put in sleep for a while.

The reason is that recurring timers could be added to the same time slot
as the timeslot being handled.
2013-03-24 09:47:32 +01:00
Jan Vidar Krey
d73d213bc4 Remove the chat_is_privileged_plugin because it fails to compile 2013-03-23 22:47:32 +01:00
mimicmod
5672ba14e3 Added mod_chat_history_sqlite and mod_chat_is_privileged.
Use file=/path/to/db to specify the database file where chat history should be stored. Other config variables are the same as those for mod_chat_history.

Code merged adapted and merged from Mimicmod's repository:
https://github.com/mimicmod/uhub.git
2013-03-23 22:47:32 +01:00
Jan Vidar Krey
cd5c4ee622 Optimize lookups by CID and nick.
This used to be a linear search O(n), but is now done
as a red-black tree O(log n) instead.

These operations can be further opimized with a hash-table
which would acheive near constant time lookups.
2013-03-23 22:11:05 +01:00
Jan Vidar Krey
52211a6bac Updated copyright year. 2013-03-22 20:00:40 +01:00
Jan Vidar Krey
f25015927a Clean up white space. 2013-03-22 20:00:40 +01:00
Jan Vidar Krey
5835a06676 Removed redundant debug printf. 2013-03-22 20:00:40 +01:00
Jan Vidar Krey
6c55ae1146 Simple compile fix. 2013-03-22 20:00:40 +01:00
Jan Vidar Krey
2d6f69d299 Cleaned up usage of linked lists and added missing functionality.
- Added a list_remove_first() which is generally better than list_remove()
  provided you want to remove the first element.
- Added a list_append_list() to append and move all nodes from one list to
  another.
2013-03-22 20:00:40 +01:00
Jan Vidar Krey
b81bb2cbd9 Cleaned up all list iterations, added macro named LIST_FOREACH.
Previously you would have to do something like this:

for (type foo = (type) list_get_first(list); foo; foo = (type) list_get_next(list)
{
    /* code */
}

Now, you can instead write this as:

LIST_FOREACH(type, foo, list,
{
    /* code */
})

Basically, boilerplate stuff including the casting is gone.
2013-03-22 00:58:14 +01:00
Jan Vidar Krey
50e720861e Detect if system is big endian (e.g. PPC64) 2013-02-20 00:30:02 +01:00
Jan Vidar Krey
d48ef710d8 Added an ADC hub redirector written in python. 2013-02-10 22:56:36 +01:00
Jan Vidar Krey
cfa210b3f3 Added a python version of the NMDC redirector. 2013-02-10 21:25:34 +01:00
Jan Vidar Krey
f6f7c7a3a4 Make sure we compile release builds with NDEBUG defined (to disable asserts). 2013-02-05 22:44:31 +01:00
Jan Vidar Krey
1fbde2b0fd Re-factored the ADC client code to use the new connection establishment API. 2013-02-05 22:43:59 +01:00
Jan Vidar Krey
92b65a0e14 Created a connection establishment API.
This API provides transparent asynchronous DNS lookups
with both IPv4 and IPv6 support, and in addition will try
to connect to all addresses until one of them work.

This implements the "happy eyeballs" algorithm provided that the client supports IPv6
and that the DNS records provides both IPv6 and IPv4 addresses.
2013-02-05 22:40:20 +01:00
Jan Vidar Krey
4d438e1e90 Don't poll the connection monitor if there are no connections added.
This caused the backends to return an error code, which
in turn ended the mainloop. However, several other things
also might occur in the main loop, such as DNS lookups which
come prior to creating any connections that in turn would be monitored.
2013-02-05 22:38:13 +01:00
Jan Vidar Krey
4f3c71234b Merge branch 'master' of https://github.com/3M3RY/uhub 2012-11-22 22:26:46 +01:00
Jan Vidar Krey
fdaadccb99 Merge pull request #18 from tehnick/fix-build-on-hurd-i386
(tehnick) Fix build in Debian GNU/Hurd.
2012-11-23 02:25:36 -08:00
Jan Vidar Krey
41251f8d32 Install uhub-passwd also. 2012-11-20 22:53:27 +01:00
Jan Vidar Krey
3b18ae251e Automatically find Sqlite3 - removed option to disable it.
This means Sqlite3 is now mandatory.
2012-11-20 22:53:27 +01:00
Boris Pek
b452488431 Fix build in Debian GNU/Hurd. 2012-11-20 22:41:38 +02:00
Emery
143b68588a Systemd notify support 2012-11-17 09:57:14 -06:00
Jan Vidar Krey
5f2b7bc069 Merge pull request #16 from 3M3RY/master
Systemd journaling support
2012-11-11 23:56:51 -08:00
Emery
ce68c446d1 Optional systemd journal logging 2012-11-11 15:21:00 -06:00
Tillmann Karras
37c80fd403 rename !cleartopic to !resettopic
The command resets the topic to the default as configured in uhub.conf.
"clear" wrongly implies that the topic will be emptied.

Also added a plugin description in plugins.conf.
2012-11-08 15:14:58 +01:00
Tillmann Karras
dcc7aa4018 some regex adjustments
IP addresses are now checked for correct charset rather than allowing
everything.
2012-11-08 12:36:37 +01:00
Tilka
9dce6693f6 fix error messages and comments 2012-11-08 12:27:08 +01:00
Jan Vidar Krey
6af0f293a6 Updated changelog for 0.4.1 release. 2012-11-07 20:24:06 +01:00
Jan Vidar Krey
a492f30950 Update authors file. 2012-11-07 20:08:28 +01:00
Jan Vidar Krey
a43953bc0d Added simple plugin that blocks downloads for non-registered users (guests). 2012-11-01 22:07:55 +01:00
Jan Vidar Krey
594801df46 Fix windows compile issues. 2012-11-01 21:52:33 +01:00
Jan Vidar Krey
3dcbb63a31 Implemented a simlpe red-black tree which should give better performance
for certain lookups.

The rb_tree will act as a general purpose key/value storage, and
also give a performance boost in the cases where the other
simple alternative would be to use a linked_list.

On average this should give on average O(log n) lookups, while the linked_list
would be O(n) at worst.
2012-11-01 21:46:44 +01:00
Jan Vidar Krey
5d6184961b Fix a failing test on Windows. 2012-11-01 21:18:49 +01:00
Jan Vidar Krey
b17e88573e Fixed Windows VC compile issues with autotests. 2012-11-01 21:10:51 +01:00
Jan Vidar Krey
2d2ccc0039 Merge branch 'async_dns_api' 2012-11-01 10:42:19 +01:00
Jan Vidar Krey
0a2f9c4b79 Merge branch 'autotest' 2012-11-01 10:40:51 +01:00
Jan Vidar Krey
ae62c35cb9 Disable SSL compression. 2012-11-01 10:39:31 +01:00
Jan Vidar Krey
2ec2e73f16 Make sure we always build the autotests.
Caveat, need to run the update script manually after changing the tests (adding or removing tests).
However, modifying existing tests does not require running the update script.

Added a copy of exotic in the repository

exotic automatically generates the skeleton code around the autotests in order to schedule
the tests.
2012-10-25 17:27:45 +02:00
138 changed files with 5224 additions and 1263 deletions

1
.gitignore vendored
View File

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

11
.travis.yml Normal file
View File

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

10
AUTHORS
View File

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

View File

@@ -1,27 +1,47 @@
##
## Makefile for uhub
## Copyright (C) 2007-2012, Jan Vidar Krey <janvidar@extatic.org>
## Copyright (C) 2007-2013, Jan Vidar Krey <janvidar@extatic.org>
#
cmake_minimum_required (VERSION 2.8.3)
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 (UHUB_VERSION_MINOR 5)
set (UHUB_VERSION_PATCH 0)
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(LOWLEVEL_DEBUG, "Enable low level debug messages." OFF)
option(SSL_SUPPORT "Enable SSL support" ON)
option(USE_OPENSSL "Use OpenSSL's SSL support" ON )
option(SQLITE_SUPPORT "Enable SQLite support" ON)
option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF)
option(ADC_STRESS "Enable the stress tester client" OFF)
find_package(Git)
find_package(Sqlite3)
include(TestBigEndian)
include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckTypeSize)
#Some functions need this to be found
add_definitions(-D_GNU_SOURCE)
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE")
TEST_BIG_ENDIAN(BIGENDIAN)
if (BIGENDIAN)
add_definitions(-DARCH_BIGENDIAN)
endif()
if (NOT RELEASE)
add_definitions(-DDEBUG)
endif()
if (SSL_SUPPORT)
if (USE_OPENSSL)
@@ -30,15 +50,32 @@ if (SSL_SUPPORT)
find_package(GnuTLS)
endif()
if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND)
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS are not found!")
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS were 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()
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
if (HAVE_SYS_TYPES_H)
set (CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} "sys/types.h")
endif()
check_type_size( ssize_t SSIZE_T )
check_symbol_exists(memmem string.h HAVE_MEMMEM)
check_symbol_exists(strndup string.h HAVE_STRNDUP)
include_directories("${PROJECT_SOURCE_DIR}")
include_directories(${SQLITE3_INCLUDE_DIRS})
link_directories(${SQLITE3_LIBRARY_DIRS})
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c)
list (REMOVE_ITEM uhub_SOURCES
@@ -58,7 +95,7 @@ set (adcclient_SOURCES
add_library(adc STATIC ${adc_SOURCES})
add_library(network STATIC ${network_SOURCES})
add_library(utils STATIC ${utils_SOURCES})
if(CMAKE_COMPILER_IS_GNUCC)
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set_target_properties(utils PROPERTIES COMPILE_FLAGS -fPIC)
set_target_properties(network PROPERTIES COMPILE_FLAGS -fPIC)
endif()
@@ -67,27 +104,23 @@ 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_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c )
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c)
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
if (SQLITE_SUPPORT)
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c)
target_link_libraries(mod_auth_sqlite sqlite3 utils)
target_link_libraries(uhub-passwd sqlite3 utils)
set_target_properties(mod_auth_sqlite PROPERTIES PREFIX "")
endif()
add_library(mod_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()
@@ -97,16 +130,24 @@ set_target_properties(
mod_welcome
mod_logging
mod_auth_simple
mod_auth_sqlite
mod_chat_history
mod_chat_history_sqlite
mod_chat_only
mod_no_guest_downloads
mod_topic
PROPERTIES PREFIX "")
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils)
target_link_libraries(test ${CMAKE_DL_LIBS} adc network utils)
target_link_libraries(mod_example utils)
target_link_libraries(mod_welcome utils)
target_link_libraries(mod_auth_simple utils)
target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils)
target_link_libraries(mod_chat_history utils)
target_link_libraries(mod_chat_history_sqlite ${SQLITE3_LIBRARIES} utils)
target_link_libraries(mod_no_guest_downloads utils)
target_link_libraries(mod_chat_only utils)
target_link_libraries(mod_logging utils)
target_link_libraries(mod_topic utils)
@@ -114,11 +155,13 @@ 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})
@@ -157,6 +200,7 @@ 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()
@@ -167,24 +211,38 @@ if(SSL_SUPPORT)
endif()
endif()
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")
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()
mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
if (RELEASE)
set(CMAKE_BUILD_TYPE Release)
else()
set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG)
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h")
configure_file ("${PROJECT_SOURCE_DIR}/system.h.in" "${PROJECT_SOURCE_DIR}/system.h")
# mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
# if (RELEASE)
# set(CMAKE_BUILD_TYPE Release)
# add_definitions(-DNDEBUG)
#else()
# set(CMAKE_BUILD_TYPE Debug)
# add_definitions(-DDEBUG)
#endif()
if (LOWLEVEL_DEBUG)
add_definitions(-DLOWLEVEL_DEBUG)
endif()
if (UNIX)
install( TARGETS uhub 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 DESTINATION /usr/lib/uhub/ OPTIONAL )
install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin )
install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL )
install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL )
if (SQLITE_SUPPORT)
install( TARGETS uhub-passwd RUNTIME DESTINATION bin )
endif()
endif()

View File

@@ -1,3 +1,38 @@
0.5.0:
- Use TLS 1.2 and strong ciphers by default, but made this configurable.
- Fix TLS event handling which caused some busy loops
- TLS: Support certificate chains
- Fix bug #211: Better Hublist pinger support by adding the AP flag of the INF message.
- Fix bug #198: Timers could cause infinite loops
- Sqlite3 is now mandatory
- Added mod_chat_history_sqlite and mod_chat_is_privileged.
- Support for systemd notify and journal logging
- Improved flood control counting to strictly not allow more than the given amount of messages in the configured interval.
- Optimize lookups by CID and nick.
- Added an NMDC and ADC hub redirectors written in Python.
- Fix all Clang compile warnings.
- Install uhub-passwd also.
- Add support for detecting HTTP connections to the hub. Enough to tell browsers to stop calling.
- Compile fixes for OpenBSD, including warnings about strcat.
- Fix crashing autotest due to wrong initialization of the usermanager.
- mod_topic: check argument for NULL
- rename !cleartopic to !resettopic
0.4.1:
- Converted to CMake which replaces Visual Studio project files and GNU makefiles
- Fix issues with SSL causing excessive CPU usage.
- Fix TLS/SSL handshake detection issues
- Fixed crash in mod_chat_only.
- Implemented red-black tree for better performance for certain lookups.
- Better network statistics using the !stats command.
- Improved protocol parsing, especially escape handling.
- Fix cbuffer initialization.
- Install plugins in /usr/lib/uhub, not /var/lib/uhub.
- Improved init scripts and added a upstart script.
- Work-around client security bugs by disallowing UCMD messages from being relayed.
- Added asynchronous DNS resolver.
0.4.0:
- Cleaned up code generator for config file parsing.
- Merge pull request #5 from yorhel/master

372
autotest/exotic Executable file
View File

@@ -0,0 +1,372 @@
#!/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");
}
'; }

1042
autotest/test.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

150
autotest/test_rbtree.tcc Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

4
autotest/update.sh Executable file
View File

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

View File

@@ -0,0 +1,78 @@
# - 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/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/usr/local/lib
/usr/lib64
/usr/local/lib64
/opt/lib64
)
IF ( _sqlite3_include_DIR AND _sqlite3_link_DIR )
SET ( _sqlite3_FOUND TRUE )
ENDIF ( _sqlite3_include_DIR AND _sqlite3_link_DIR )
IF ( _sqlite3_FOUND )
SET ( SQLITE3_INCLUDE_DIRS ${_sqlite3_include_DIR} )
SET ( SQLITE3_LIBRARIES ${_sqlite3_link_DIR} )
ENDIF ( _sqlite3_FOUND )
# Report results
IF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
SET( SQLITE3_FOUND 1 )
MESSAGE( STATUS "Found sqlite3: ${SQLITE3_LIBRARIES} ${SQLITE3_INCLUDE_DIRS}" )
ELSE ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
IF ( Sqlite3_FIND_REQUIRED )
MESSAGE( SEND_ERROR "Could NOT find sqlite3" )
ELSE ( Sqlite3_FIND_REQUIRED )
MESSAGE( STATUS "Could NOT find sqlite3" )
ENDIF ( Sqlite3_FIND_REQUIRED )
ENDIF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
ENDIF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND )
# Hide advanced variables from CMake GUIs
MARK_AS_ADVANCED( SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS )

View File

@@ -13,6 +13,15 @@
#
plugin /usr/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
# Topic commands.
# Note: "topic" == "hub description" (as configured in uhub.conf)
#
# !topic - change the topic (op required)
# !showtopic - show the topic
# !resettopic - reset the topic to the default (op required)
#
# This plugins takes no parameters.
#plugin /usr/lib/uhub/mod_topic.so
# Log file writer
#
@@ -22,7 +31,8 @@ plugin /usr/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
# A simple example plugin
# plugin /usr/lib/uhub/mod_example.so
#plugin /usr/lib/uhub/mod_example.so
# A plugin sending a welcome message.
#
# This plugin provides the following commands:

View File

@@ -104,11 +104,11 @@ msg_auth_invalid_password = Password is wrong
msg_auth_user_not_found = User not found in password database
msg_user_share_size_low = User is not sharing enough
msg_user_share_size_high = User is sharing too much
msg_user_slots_low = User have too few upload slots
msg_user_slots_high = User have too many upload slots
msg_user_slots_low = User has too few upload slots
msg_user_slots_high = User has too many upload slots
msg_user_hub_limit_low = User is on too few hubs
msg_user_hub_limit_high = User is on too many hubs
msg_error_no_memory = No memory
msg_error_no_memory = Out of memory
msg_user_flood_chat = Chat flood detected, messages are dropped.
msg_user_flood_connect = Connect flood detected, connection refused.
msg_user_flood_search = Search flood detected, search is stopped.

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -111,7 +111,10 @@ typedef uint32_t fourcc_t;
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
#define ADC_INF_FLAG_NICK "NI" /* nick name */
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
#define ADC_INF_FLAG_USER_AGENT "VE" /* software version */
#define ADC_INF_FLAG_USER_AGENT_PRODUCT "AP" /* software name */
#define ADC_INF_FLAG_USER_AGENT_VERSION "VE" /* software version */
#define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */
#define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */
#define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -283,23 +283,19 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
if (cmd->feature_cast_include)
{
copy->feature_cast_include = list_create();
tmp = list_get_first(cmd->feature_cast_include);
while (tmp)
LIST_FOREACH(char*, tmp, cmd->feature_cast_include,
{
list_append(copy->feature_cast_include, hub_strdup(tmp));
tmp = list_get_next(cmd->feature_cast_include);
}
});
}
if (cmd->feature_cast_exclude)
{
copy->feature_cast_exclude = list_create();
tmp = list_get_first(cmd->feature_cast_exclude);
while (tmp)
LIST_FOREACH(char*, tmp, cmd->feature_cast_exclude,
{
list_append(copy->feature_cast_exclude, hub_strdup(tmp));
tmp = list_get_next(cmd->feature_cast_exclude);
}
});
}
ADC_MSG_ASSERT(copy);

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -330,13 +330,11 @@ struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name)
}
#define STR_LIST_CONTAINS(LIST, STR) \
str = (char*) list_get_first(LIST); \
while (str) \
LIST_FOREACH(char*, str, LIST, \
{ \
if (strcasecmp(str, STR) == 0) \
return 1; \
str = (char*) list_get_next(LIST); \
} \
}); \
return 0
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
@@ -400,34 +398,28 @@ int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
ip_convert_to_binary(ip_address, &raw);
struct ip_range* info;
while (info)
ip_convert_to_binary(ip_address, &raw);
LIST_FOREACH(struct ip_range*, info, handle->networks,
{
if (ip_in_range(&raw, info))
{
return 1;
}
info = (struct ip_range*) list_get_next(handle->networks);
}
});
return 0;
}
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
ip_convert_to_binary(ip_address, &raw);
struct ip_range* info;
while (info)
ip_convert_to_binary(ip_address, &raw);
LIST_FOREACH(struct ip_range*, info, handle->nat_override,
{
if (ip_in_range(&raw, info))
{
return 1;
}
info = (struct ip_range*) list_get_next(handle->nat_override);
}
});
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

255
src/core/config.py Executable file
View File

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

View File

@@ -17,7 +17,7 @@
</option>
<option name="server_bind_addr" type="string" default="any">
<check regexp="(\d\.\d\.\d\.\d\)|(any)|(loopback)|(.*)" /><!-- FIXME: add better IPv6 regexp in the future! -->
<check regexp="[\x:.]+|any|loopback" />
<short>Server bind address</short>
<description><![CDATA[
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
@@ -58,7 +58,7 @@
</option>
<option name="server_alt_ports" type="string" default="">
<check regexp="((\d+)(,(\d+))*)?" />
<check regexp="\d+(,\d+)*" />
<short>Comma separated list of alternative ports to listen to</short>
<description><![CDATA[
In addition to the server_port the hub can listen to a list of alternative ports.
@@ -157,7 +157,7 @@
</option>
<option name="redirect_addr" type="string" default="">
<check regexp="(adc|adcs|dchub)://.*" />
<check regexp="(adcs?|dchub)://.*" />
<short>A common hub redirect address.</short>
<description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
@@ -419,7 +419,7 @@
</option>
<option name="tls_require_redirect_addr" type="string" default="">
<check regexp="(adc|adcs|dchub)://.*" />
<check regexp="(adcs?|dchub)://.*" />
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
<description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not using ADCS.
@@ -428,11 +428,10 @@
<since>0.3.3</since>
</option>
<option name="tls_certificate" type="file" default="">
<short>Certificate file</short>
<description><![CDATA[
Path to a TLS/SSL certificate (PEM format).
Path to a TLS/SSL certificate or certificate chain (PEM format).
]]></description>
<since>0.3.0</since>
</option>
@@ -445,6 +444,40 @@
<since>0.3.0</since>
</option>
<option name="tls_ciphersuite" type="string" default="ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS">
<short>List of TLS ciphers to use</short>
<description><![CDATA[
This is a colon separated list of preferred ciphers in the OpenSSL format.
]]></description>
<since>0.5.0</since>
<example><![CDATA[
<p>
High security with emphasis on forward secrecy:<br />
tls_ciphersuite = "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS"
</p>
<p>
Allow ChaCha20/Poly1305 which are secure, yet generally faster:<br />
tls_ciphersuite = "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
</p>
]]></example>
</option>
<option name="tls_version" type="string" default="1.2">
<short>Specify minimum TLS version supported.</short>
<description><![CDATA[
<p>
This allows you to specify the minimum TLS version the hub requires from connecting clients in order to
connect to the hub.
</p>
<p>
TLS version 1.2 is recommended and enabled by default.
TLS version 1.1 is acceptable without any known flaws, and allows for older clients to connect.
TLS version 1.0 should be avoided, even though it is the most compatible with older ADC clients.
</p>
]]></description>
<since>0.5.0</since>
</option>
<option name="file_acl" type="file" default="">
<short>File containing access control lists</short>
<description><![CDATA[

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -77,15 +77,13 @@ int event_queue_process(struct event_queue* queue)
/* lock primary queue, and handle the primary queue messages. */
queue->locked = 1;
data = (struct event_data*) list_get_first(queue->q1);
while (data)
LIST_FOREACH(struct event_data*, data, queue->q1,
{
#ifdef EQ_DEBUG
eq_debug("EXEC", data);
#endif
queue->callback(queue->callback_data, data);
data = (struct event_data*) list_get_next(queue->q1);
}
});
list_clear(queue->q1, event_queue_cleanup_callback);
uhub_assert(list_size(queue->q1) == 0);
@@ -94,13 +92,7 @@ int event_queue_process(struct event_queue* queue)
queue->locked = 0;
/* transfer from secondary queue to the primary queue. */
data = (struct event_data*) list_get_first(queue->q2);
while (data)
{
list_remove(queue->q2, data);
list_append(queue->q1, data);
data = (struct event_data*) list_get_first(queue->q2);
}
list_append_list(queue->q1, queue->q2);
/* if more events exist, schedule it */
if (list_size(queue->q1))

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -731,7 +731,11 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
{
if (config->tls_enable)
{
hub->ctx = net_ssl_context_create();
hub->ctx = net_ssl_context_create(config->tls_version, config->tls_ciphersuite);
if (!hub->ctx)
return 0;
if (ssl_load_certificate(hub->ctx, config->tls_certificate) &&
ssl_load_private_key(hub->ctx, config->tls_private_key) &&
ssl_check_private_key(hub->ctx))
@@ -905,7 +909,8 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
if (hub->command_info)
{
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT, server);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT_PRODUCT, PRODUCT);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT_VERSION, GIT_VERSION);
tmp = adc_msg_escape(hub->config->hub_name);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp);
@@ -1320,9 +1325,7 @@ void hub_logout_log(struct hub_info* hub, struct hub_user* user)
list_append(hub->logout_info, loginfo);
while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log)
{
struct hub_logout_info* entry = list_get_first(hub->logout_info);
list_remove(hub->logout_info, entry);
hub_free(entry);
list_remove_first(hub->logout_info, hub_free);
}
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@ enum status_message
status_msg_hub_registered_users_only = -3, /* hub is for registered users only */
status_msg_inf_error_nick_missing = -4, /* no nickname given */
status_msg_inf_error_nick_multiple = -5, /* multiple nicknames given */
status_msg_inf_error_nick_invalid = -6, /* generic/unkown */
status_msg_inf_error_nick_invalid = -6, /* generic/unknown */
status_msg_inf_error_nick_long = -7, /* nickname too long */
status_msg_inf_error_nick_short = -8, /* nickname too short */
status_msg_inf_error_nick_spaces = -9, /* nickname cannot start with spaces */
@@ -50,8 +50,8 @@ enum status_message
status_msg_user_share_size_high = -41, /* User is sharing too much. */
status_msg_user_slots_low = -42, /* User has too few slots open. */
status_msg_user_slots_high = -43, /* User has too many slots open. */
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
status_msg_user_hub_limit_low = -44, /* User is on too few hubs. */
status_msg_user_hub_limit_high = -45, /* User is on too many hubs. */
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -366,21 +366,37 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a
*/
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* ua_encoded = 0;
char* ua = 0;
char* ua_name_encoded = 0;
char* ua_version_encoded = 0;
char* str = 0;
size_t offset = 0;
/* Get client user agent version */
ua_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
if (ua_encoded)
ua_name_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT);
ua_version_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_VERSION);
if (ua_name_encoded)
{
ua = adc_msg_unescape(ua_encoded);
if (ua)
str = adc_msg_unescape(ua_name_encoded);
if (str)
{
memcpy(user->id.user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
hub_free(ua);
offset = strlen(str);
memcpy(user->id.user_agent, str, MIN(offset, MAX_UA_LEN));
hub_free(str);
}
}
hub_free(ua_encoded);
if (ua_version_encoded)
{
str = adc_msg_unescape(ua_version_encoded);
if (str)
{
memcpy(user->id.user_agent + offset, str, MIN(strlen(str), MAX_UA_LEN - offset));
hub_free(str);
}
}
hub_free(ua_name_encoded);
hub_free(ua_version_encoded);
return 0;
}
@@ -622,7 +638,8 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
{
if (hub->config->low_bandwidth_mode)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_VERSION);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -130,7 +130,7 @@ void ioq_send_add(struct ioq_send* q, struct adc_message* msg_)
q->size += msg->length;
}
void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
debug_msg("ioq_send_remove", msg);

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,10 @@
#include "uhub.h"
#ifdef SYSTEMD
#include <systemd/sd-daemon.h>
#endif
static int arg_verbose = 5;
static int arg_fork = 0;
static int arg_check_config = 0;
@@ -145,7 +149,16 @@ int main_loop()
}
#if !defined(WIN32)
setup_signal_handlers(hub);
#endif
#ifdef SYSTEMD
/* Notify the service manager that this daemon has
* been successfully initalized and shall enter the
* main loop.
*/
sd_notifyf(0, "READY=1\n"
"MAINPID=%lu", (unsigned long) getpid());
#endif /* SYSTEMD */
#endif /* ! WIN32 */
}
hub_set_variables(hub, &acl);
@@ -216,13 +229,17 @@ void print_usage(char* program)
" -q Quiet mode - no output\n"
" -f Fork to background\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 Check configuration and return\n"
" -s Show configuration parameters\n"
" -S Show configuration parameters, but ignore defaults\n"
" -h This message\n"
#ifndef WIN32
#ifdef SYSTEMD
" -L Log messages to journal\n"
#else
" -L Log messages to syslog\n"
#endif
" -u <user> Run as given user\n"
" -g <group> Run with given group permissions\n"
" -p <file> Store pid in file (process id)\n"

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,14 +40,11 @@ static int plugin_command_dispatch(struct command_base* cbase, struct hub_user*
LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix);
cmdh = (struct plugin_command_handle*) list_get_first(data->commands);
while (cmdh)
LIST_FOREACH(struct plugin_command_handle*, cmdh, data->commands,
{
if (strcmp(cmdh->prefix, cmd->prefix) == 0)
return cmdh->handler(plugin, puser, pcommand);
cmdh = (struct plugin_command_handle*) list_get_next(data->commands);
}
});
return 0;
}
@@ -68,6 +65,17 @@ static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user*
return 1;
}
static int cbfunc_send_broadcast(struct plugin_handle* plugin, const char* message)
{
char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_all(plugin_get_hub(plugin), command);
adc_msg_free(command);
hub_free(buffer);
return 1;
}
static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
{
char code_str[4];
@@ -104,7 +112,6 @@ static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_comman
cmdh->internal_handle = command;
list_append(data->commands, cmdh);
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
return 0;
}
@@ -113,7 +120,6 @@ static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_comman
struct plugin_callback_data* data = get_callback_data(plugin);
struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
list_remove(data->commands, cmdh);
command_del(plugin_get_hub(plugin)->commands, command);
hub_free(command);
@@ -133,6 +139,12 @@ struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* pl
return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t);
}
static size_t cbfunc_get_usercount(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
return hub->users->count;
}
static char* cbfunc_get_hub_name(struct plugin_handle* plugin)
{
struct hub_info* hub = plugin_get_hub(plugin);
@@ -188,12 +200,14 @@ static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char*
void plugin_register_callback_functions(struct plugin_handle* handle)
{
handle->hub.send_message = cbfunc_send_message;
handle->hub.send_broadcast_message = cbfunc_send_broadcast;
handle->hub.send_status_message = cbfunc_send_status;
handle->hub.user_disconnect = cbfunc_user_disconnect;
handle->hub.command_add = cbfunc_command_add;
handle->hub.command_del = cbfunc_command_del;
handle->hub.command_arg_reset = cbfunc_command_arg_reset;
handle->hub.command_arg_next = cbfunc_command_arg_next;
handle->hub.get_usercount = cbfunc_get_usercount;
handle->hub.get_name = cbfunc_get_hub_name;
handle->hub.set_name = cbfunc_set_hub_name;
handle->hub.get_description = cbfunc_get_hub_description;

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,13 +27,12 @@
PLUGIN_DEBUG(HUB, # FUNCNAME) \
if (HUB->plugins && HUB->plugins->loaded) \
{ \
struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(HUB->plugins->loaded); \
while (plugin) \
struct plugin_handle* plugin;\
LIST_FOREACH(struct plugin_handle*, plugin, HUB->plugins->loaded, \
{ \
if (plugin->funcs.FUNCNAME) \
CODE \
plugin = (struct plugin_handle*) list_get_next(HUB->plugins->loaded); \
} \
}); \
}
#define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -229,16 +229,16 @@ int plugin_initialize(struct hub_config* config, struct hub_info* hub)
return 0;
}
static void plugin_unload_ptr(void* ptr)
{
struct plugin_handle* plugin = (struct plugin_handle*) ptr;
plugin_unload(plugin);
}
void plugin_shutdown(struct uhub_plugins* handle)
{
struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(handle->loaded);
while (plugin)
{
list_remove(handle->loaded, plugin);
plugin_unload(plugin);
plugin = (struct plugin_handle*) list_get_first(handle->loaded);
}
list_clear(handle->loaded, plugin_unload_ptr);
list_destroy(handle->loaded);
}

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,6 +71,15 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
probe_destroy(probe);
return;
}
else if ((memcmp(probe_recvbuf, "GET ", 4) == 0) ||
(memcmp(probe_recvbuf, "POST", 4) == 0) ||
(memcmp(probe_recvbuf, "HEAD", 4) == 0))
{
/* Looks like HTTP - Not supported, but we log it. */
LOG_TRACE("Probed HTTP connection. Not supported closing connection (%s)", ip_convert_to_string(&probe->addr));
const char* buf = "501 Not implemented\r\n\r\n";
net_con_send(con, buf, strlen(buf));
}
#ifdef SSL_SUPPORT
else if (bytes >= 11 &&
probe_recvbuf[0] == 22 &&

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -139,12 +139,11 @@ int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
struct hub_user* user;
LIST_FOREACH(struct hub_user*, user, hub->users->list,
{
route_to_user(hub, user, command);
user = (struct hub_user*) list_get_next(hub->users->list);
}
});
return 0;
}
@@ -154,47 +153,38 @@ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* i
int do_send;
char* tmp;
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
struct hub_user* user;
LIST_FOREACH(struct hub_user*, user, hub->users->list,
{
if (user->feature_cast)
{
do_send = 1;
tmp = list_get_first(command->feature_cast_include);
while (tmp)
LIST_FOREACH(char*, tmp, command->feature_cast_include,
{
if (!user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
tmp = list_get_next(command->feature_cast_include);;
}
});
if (!do_send) {
user = (struct hub_user*) list_get_next(hub->users->list);
if (!do_send)
continue;
}
tmp = list_get_first(command->feature_cast_exclude);
while (tmp)
LIST_FOREACH(char*, tmp, command->feature_cast_exclude,
{
if (user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
tmp = list_get_next(command->feature_cast_exclude);
}
});
if (do_send)
{
route_to_user(hub, user, command);
}
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
});
return 0;
}
@@ -214,16 +204,13 @@ int route_info_message(struct hub_info* hub, struct hub_user* u)
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
LIST_FOREACH(struct hub_user*, user, hub->users->list,
{
if (user_is_nat_override(user))
route_to_user(hub, user, cmd);
else
route_to_user(hub, user, u->info);
user = (struct hub_user*) list_get_next(hub->users->list);
}
});
adc_msg_free(cmd);
}
return 0;

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -232,15 +232,12 @@ void user_support_remove(struct hub_user* user, int fourcc)
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
{
char* tmp = list_get_first(user->feature_cast);
while (tmp)
char* tmp;
LIST_FOREACH(char*, tmp, user->feature_cast,
{
if (strncmp(tmp, feature, 4) == 0)
return 1;
tmp = list_get_next(user->feature_cast);
}
});
return 0;
}

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -38,6 +38,11 @@ static void clear_user_list_callback(void* ptr)
}
}
static int uman_map_compare(const void* a, const void* b)
{
return strcmp((const char*) a, (const char*) b);
}
struct hub_user_manager* uman_init()
{
@@ -46,15 +51,10 @@ struct hub_user_manager* uman_init()
return NULL;
users->list = list_create();
users->nickmap = rb_tree_create(uman_map_compare, NULL, NULL);
users->cidmap = rb_tree_create(uman_map_compare, NULL, NULL);
users->sids = sid_pool_create(net_get_max_sockets());
if (!users->list)
{
list_destroy(users->list);
hub_free(users);
return NULL;
}
return users;
}
@@ -64,11 +64,18 @@ int uman_shutdown(struct hub_user_manager* users)
if (!users)
return -1;
if (users->nickmap)
rb_tree_destroy(users->nickmap);
if (users->cidmap)
rb_tree_destroy(users->cidmap);
if (users->list)
{
list_clear(users->list, &clear_user_list_callback);
list_destroy(users->list);
}
sid_pool_destroy(users->sids);
hub_free(users);
@@ -81,6 +88,9 @@ int uman_add(struct hub_user_manager* users, struct hub_user* user)
if (!users || !user)
return -1;
rb_tree_insert(users->nickmap, user->id.nick, user);
rb_tree_insert(users->cidmap, user->id.cid, user);
list_append(users->list, user);
users->count++;
users->count_peak = MAX(users->count, users->count_peak);
@@ -96,6 +106,8 @@ int uman_remove(struct hub_user_manager* users, struct hub_user* user)
return -1;
list_remove(users->list, user);
rb_tree_remove(users->nickmap, user->id.nick);
rb_tree_remove(users->cidmap, user->id.cid);
if (users->count > 0)
{
@@ -120,42 +132,29 @@ struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid)
struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid)
{
struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (strcmp(user->id.cid, cid) == 0)
return user;
user = (struct hub_user*) list_get_next(users->list);
}
return NULL;
struct hub_user* user = (struct hub_user*) rb_tree_get(users->cidmap, (const void*) cid);
return user;
}
struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick)
{
struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (strcmp(user->id.nick, nick) == 0)
return user;
user = (struct hub_user*) list_get_next(users->list);
}
return NULL;
struct hub_user* user = (struct hub_user*) rb_tree_get(users->nickmap, nick);
return user;
}
size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range)
{
size_t num = 0;
struct hub_user* user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on incoming INF msg */
while (user)
struct hub_user* user;
LIST_FOREACH(struct hub_user*, user, users->list,
{
if (ip_in_range(&user->id.addr, range))
{
list_append(target, user);
num++;
}
user = (struct hub_user*) list_get_next(users->list);
}
});
return num;
}
@@ -164,8 +163,8 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st
int ret = 1;
struct hub_user* user;
user_flag_set(target, flag_user_list);
user = (struct hub_user*) list_get_first(users->list); /* iterate users - only on INF or PAS msg */
while (user)
LIST_FOREACH(struct hub_user*, user, users->list,
{
if (user_is_logged_in(user))
{
@@ -173,8 +172,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, st
if (!ret)
break;
}
user = (struct hub_user*) list_get_next(users->list);
}
});
#if 0
FIXME: FIXME FIXME handle send queue excess

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,10 +24,12 @@ struct hub_user_manager
{
size_t count; /**<< "Number of all fully connected and logged in users" */
size_t count_peak; /**<< "Peak number of users" */
struct sid_pool* sids;
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct sid_pool* sids; /**<< "Maps SIDs to users (constant time)" */
struct linked_list* list; /**<< "Contains all logged in users" */
struct rb_tree* nickmap; /**<< "Maps nicknames to users (red black tree)" */
struct rb_tree* cidmap; /**<< "Maps CIDs to users (red black tree)" */
};
/**

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -102,14 +102,7 @@ void net_backend_shutdown()
}
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_update(struct net_connection* con, int events)
void net_backend_update(struct net_connection* con, int events)
{
g_backend->handler.con_mod(g_backend->data, con, events);
}
@@ -132,10 +125,11 @@ struct timeout_queue* net_backend_get_timeout_queue()
*/
int net_backend_process()
{
int res;
int res = 0;
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
if (g_backend->common.num)
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
g_backend->now = time(0);
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
@@ -147,7 +141,7 @@ int net_backend_process()
}
// Process pending DNS results
net_dns_process();
// net_dns_process();
g_backend->handler.backend_process(g_backend->data, res);
@@ -165,8 +159,8 @@ void net_con_initialize(struct net_connection* con, int sd, net_connection_cb ca
{
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
net_set_nonblocking(con->sd, 1);
net_set_nosigpipe(con->sd, 1);
net_set_nonblocking(net_con_get_sd(con), 1);
net_set_nosigpipe(net_con_get_sd(con), 1);
g_backend->handler.con_add(g_backend->data, con, events);
g_backend->common.num++;

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -75,6 +75,14 @@ extern void net_backend_shutdown();
*/
extern int net_backend_process();
/**
* Update the event mask.
*
* @param con Connection handle.
* @param events Event mask (NET_EVENT_*)
*/
extern void net_backend_update(struct net_connection* con, int events);
/**
* Get the current time.
*/

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
#include "uhub.h"
#include "network/common.h"
#include "network/backend.h"
static int is_blocked_or_interrupted()
{
@@ -116,10 +117,27 @@ void* net_con_get_ptr(struct net_connection* con)
return con->ptr;
}
void net_con_destroy(struct net_connection* con)
void net_con_update(struct net_connection* con, int events)
{
#ifdef SSL_SUPPORT
if (con->ssl)
net_ssl_update(con, events);
else
#endif
net_backend_update(con, events);
}
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_destroy(struct net_connection* con)
{
#ifdef SSL_SUPPORT
if (con && con->ssl)
net_ssl_destroy(con);
#endif
hub_free(con);
@@ -145,3 +163,395 @@ void net_con_callback(struct net_connection* con, int events)
con->callback(con, events, con->ptr);
}
struct net_connect_job
{
struct net_connection* con;
struct net_connect_handle* handle;
struct sockaddr_storage addr;
struct net_connect_job* next;
};
struct net_connect_handle
{
const char* address;
uint16_t port;
void* ptr;
net_connect_cb callback;
struct net_dns_job* dns;
const struct net_dns_result* result;
struct net_connect_job* job4;
struct net_connect_job* job6;
};
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con);
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr);
/**
* Check if a connection job is completed.
* @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected).
*/
static int net_connect_job_check(struct net_connect_job* job)
{
struct net_connection* con = job->con;
int af = job->addr.ss_family;
enum net_connect_status status;
int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{
LOG_TRACE("net_connect_job_check(): Socket connected!");
job->con = NULL;
net_con_clear_timeout(con);
net_connect_callback(job->handle, net_connect_status_ok, con);
return 1;
}
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
{
return 0;
}
LOG_TRACE("net_connect_job_check(): Socket error!");
switch (net_error())
{
case ECONNREFUSED:
status = net_connect_status_refused;
break;
case ENETUNREACH:
status = net_connect_status_unreachable;
break;
default:
status = net_connect_status_socket_error;
}
net_connect_callback(job->handle, status, NULL);
return -1;
}
static void net_connect_job_free(struct net_connect_job* job)
{
if (job->con)
net_con_close(job->con);
job->handle = NULL;
job->next = NULL;
hub_free(job);
}
static void net_connect_job_stop(struct net_connect_job* job)
{
if (job->addr.ss_family == AF_INET6)
{
job->handle->job6 = job->next;
}
else
{
job->handle->job4 = job->next;
}
net_connect_job_free(job);
}
static int net_connect_depleted(struct net_connect_handle* handle)
{
return (!handle->job6 && !handle->job4);
}
static int net_connect_job_process(struct net_connect_job* job)
{
int sd;
if (!job->con)
{
sd = net_socket_create(job->addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
if (sd == -1)
{
LOG_DEBUG("net_connect_job_process: Unable to create socket!");
net_connect_callback(job->handle, net_connect_status_socket_error, NULL);
return -1; // FIXME
}
job->con = net_con_create();
net_con_initialize(job->con, sd, net_connect_job_internal_cb, job, NET_EVENT_WRITE);
net_con_set_timeout(job->con, TIMEOUT_CONNECTED); // FIXME: Use a proper timeout value!
}
return net_connect_job_check(job);
}
/*
* Internal callback used to establish an outbound connection.
*/
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr)
{
struct net_connect_job* job = net_con_get_ptr(con);
struct net_connect_job* next_job = job->next;
struct net_connect_handle* handle = job->handle;
if (event == NET_EVENT_TIMEOUT)
{
// FIXME: Try next address, or if no more addresses left declare failure to connect.
if (job->addr.ss_family == AF_INET6)
{
net_connect_job_stop(job);
if (!next_job)
{
LOG_TRACE("No more IPv6 addresses to try!");
}
}
else
{
net_connect_job_stop(job);
if (!next_job)
{
LOG_TRACE("No more IPv4 addresses to try!");
}
}
if (net_connect_depleted(handle))
{
LOG_TRACE("No more addresses left. Unable to connect!");
net_connect_callback(handle, net_connect_status_timeout, NULL);
}
return;
}
if (event == NET_EVENT_WRITE)
{
net_connect_job_process(job);
}
}
static void net_connect_cancel(struct net_connect_handle* handle)
{
struct net_connect_job* job;
job = handle->job6;
while (job)
{
job = job->next;
net_connect_job_free(handle->job6);
handle->job6 = job;
}
job = handle->job4;
while (job)
{
job = job->next;
net_connect_job_free(handle->job4);
handle->job4 = job;
}
}
static int net_connect_process_queue(struct net_connect_handle* handle, struct net_connect_job* job)
{
int ret;
while (job)
{
ret = net_connect_job_process(job);
if (ret < 0)
{
net_connect_job_stop(job);
continue;
}
else if (ret == 0)
{
// Need to process again
return 0;
}
else
{
// FIXME: Success!
return 1;
}
}
return -1;
}
static int net_connect_process(struct net_connect_handle* handle)
{
int ret4, ret6;
ret6 = net_connect_process_queue(handle, handle->job6);
if (ret6 == 1)
return 1; // Connected - cool!
net_connect_process_queue(handle, handle->job4);
return 0;
}
static int net_connect_job_schedule(struct net_connect_handle* handle, struct ip_addr_encap* addr)
{
struct net_connect_job* job;
struct sockaddr_in* addr4;
struct sockaddr_in6* addr6;
if (addr->af == AF_INET6 && !net_is_ipv6_supported())
{
LOG_TRACE("net_connect_job_schedule(): Skipping IPv6 support since IPv6 is not supported.");
return 0;
}
else
{
job = hub_malloc_zero(sizeof(struct net_connect_job));
job->handle = handle;
if (addr->af == AF_INET6)
{
addr6 = (struct sockaddr_in6*) &job->addr;
LOG_TRACE("net_connect_job_schedule(): Scheduling IPv6 connect job.");
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(handle->port);
memcpy(&addr6->sin6_addr, &addr->internal_ip_data.in6, sizeof(struct in6_addr));
// prepend
job->next = handle->job6;
handle->job6 = job;
}
else
{
addr4 = (struct sockaddr_in*) &job->addr;
LOG_TRACE("net_connect_job_schedule(): Scheduling IPv4 connect job.");
addr4->sin_family = AF_INET;
addr4->sin_port = htons(handle->port);
memcpy(&addr4->sin_addr, &addr->internal_ip_data.in, sizeof(struct in_addr));
// prepend
job->next = handle->job4;
handle->job4 = job;
}
}
return 1;
}
/*
* Callback when the DNS results are ready.
* Create a list of IPv6 and IPv4 addresses, then
* start connecting to them one by one until one succeeds.
*/
static int net_con_connect_dns_callback(struct net_dns_job* job, const struct net_dns_result* result)
{
struct ip_addr_encap* addr;
struct net_connect_handle* handle = (struct net_connect_handle*) net_dns_job_get_ptr(job);
handle->dns = NULL;
size_t usable = 0;
LOG_TRACE("net_con_connect(): async - Got DNS results");
if (!result)
{
LOG_DEBUG("net_con_connect() - Unable to lookup host!");
net_connect_callback(handle, net_connect_status_dns_error, NULL);
return 1;
}
if (!net_dns_result_size(result))
{
LOG_DEBUG("net_con_connect() - Host not found!");
net_connect_callback(handle, net_connect_status_host_not_found, NULL);
return 1;
}
handle->result = result;
// Extract results into a separate list of IPv4 and IPv6 addresses.
addr = net_dns_result_first(result);
while (addr)
{
if (net_connect_job_schedule(handle, addr))
usable++;
addr = net_dns_result_next(result);
}
net_connect_process(handle);
return 0;
}
// typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_handle_code, struct net_connection* con);
struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr)
{
struct net_connect_handle* handle = hub_malloc_zero(sizeof(struct net_connect_handle));
handle->address = hub_strdup(address);
handle->port = port;
handle->ptr = ptr;
handle->callback = callback;
// FIXME: Check if DNS resolving is necessary ?
handle->dns = net_dns_gethostbyname(address, AF_UNSPEC, net_con_connect_dns_callback, handle);
if (!handle->dns)
{
LOG_TRACE("net_con_connect(): Unable to create DNS lookup job.");
hub_free((char*) handle->address);
hub_free(handle);
return NULL;
}
return handle;
}
void net_connect_destroy(struct net_connect_handle* handle)
{
hub_free((char*) handle->address);
// cancel DNS job if pending
if (handle->dns)
net_dns_job_cancel(handle->dns);
// Stop any connect jobs.
net_connect_cancel(handle);
// free any DNS results
net_dns_result_free(handle->result);
hub_free(handle);
}
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con)
{
uhub_assert(handle->callback != NULL);
// Call the callback
handle->callback(handle, status, con, handle->ptr);
handle->callback = NULL;
// Cleanup
net_connect_destroy(handle);
}
static void timeout_callback(struct timeout_evt* evt)
{
net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
if (!con->timeout)
{
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(con->timeout, timeout_callback, con);
timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
}
else
{
timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
}
}
void net_con_clear_timeout(struct net_connection* con)
{
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
{
timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
hub_free(con->timeout);
con->timeout = 0;
}
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,16 +28,48 @@
#define NET_EVENT_TIMEOUT 0x0001
#define NET_EVENT_READ 0x0002
#define NET_EVENT_WRITE 0x0004
#define NET_EVENT_ERROR 0x1000
struct net_connection
{
NET_CON_STRUCT_COMMON
};
struct net_connect_handle;
enum net_connect_status
{
net_connect_status_ok = 0,
net_connect_status_host_not_found = -1,
net_connect_status_no_address = -2,
net_connect_status_dns_error = -3,
net_connect_status_refused = -4,
net_connect_status_unreachable = -5,
net_connect_status_timeout = -6,
net_connect_status_socket_error = -7,
};
typedef void (*net_connect_cb)(struct net_connect_handle*, enum net_connect_status status, struct net_connection* con, void* ptr);
extern int net_con_get_sd(struct net_connection* con);
extern void* net_con_get_ptr(struct net_connection* con);
extern struct net_connection* net_con_create();
/**
* Establish an outbound TCP connection.
* This will resolve the IP-addresses, and connect to
* either an IPv4 or IPv6 address depending if it is supported,
* and using the happy eyeballs algorithm.
*
* @param address Hostname, IPv4 or IPv6 address
* @param port TCP port number
* @param callback A callback to be called once the connection is established, or failed.
* @returns a handle to the connection establishment job, or NULL if an immediate error.
*/
extern struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr);
extern void net_connect_destroy(struct net_connect_handle* handle);
extern void net_con_destroy(struct net_connection*);
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,6 +68,11 @@ static void shutdown_free_results(void* ptr)
net_dns_result_free(result);
}
static void notify_callback(struct uhub_notify_handle* handle, void* ptr)
{
net_dns_process();
}
// NOTE: Any job manipulating the members of this
// struct must lock the mutex!
@@ -76,6 +81,8 @@ struct net_dns_subsystem
struct linked_list* jobs; // currently running jobs
struct linked_list* results; // queue of results that are awaiting being delivered to callback.
uhub_mutex_t mutex;
struct uhub_notify_handle* notify_handle; // used to signal back to the event loop that there is something to process.
};
static struct net_dns_subsystem* g_dns = NULL;
@@ -87,13 +94,11 @@ void net_dns_initialize()
g_dns->jobs = list_create();
g_dns->results = list_create();
uhub_mutex_init(&g_dns->mutex);
g_dns->notify_handle = net_notify_create(notify_callback, g_dns);
}
void net_dns_destroy()
{
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);
@@ -105,22 +110,18 @@ void net_dns_destroy()
list_destroy(g_dns->jobs);
list_destroy(g_dns->results);
uhub_mutex_destroy(&g_dns->mutex);
net_notify_destroy(g_dns->notify_handle);
hub_free(g_dns);
g_dns = NULL;
}
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));
LOG_TRACE("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results));
for (result = (struct net_dns_result*) list_get_first(g_dns->results); result; result = (struct net_dns_result*) list_get_next(g_dns->results))
LIST_FOREACH(struct net_dns_result*, result, g_dns->results,
{
struct net_dns_job* job = result->job;
#ifdef DEBUG_LOOKUP_TIME
@@ -146,9 +147,9 @@ void net_dns_process()
result->job = NULL;
free_job(job);
}
}
});
list_clear(g_dns->results, &dummy_free);
list_clear(g_dns->results, NULL);
uhub_mutex_unlock(&g_dns->mutex);
}
@@ -215,6 +216,7 @@ static void* job_thread_resolve_name(void* ptr)
uhub_mutex_lock(&g_dns->mutex);
list_remove(g_dns->jobs, job);
list_append(g_dns->results, dns_results);
net_notify_signal(g_dns->notify_handle, 1);
uhub_mutex_unlock(&g_dns->mutex);
return dns_results;
@@ -273,14 +275,14 @@ extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, n
static struct net_dns_job* find_and_remove_job(struct net_dns_job* job)
{
struct net_dns_job* it;
for (it = (struct net_dns_job*) list_get_first(g_dns->jobs); it; it = (struct net_dns_job*) list_get_next(g_dns->jobs))
LIST_FOREACH(struct net_dns_job*, it, g_dns->jobs,
{
if (it == job)
{
list_remove(g_dns->jobs, it);
return job;
}
}
});
return NULL;
}
@@ -288,14 +290,14 @@ static struct net_dns_job* find_and_remove_job(struct net_dns_job* job)
static struct net_dns_result* find_and_remove_result(struct net_dns_job* job)
{
struct net_dns_result* it;
for (it = (struct net_dns_result*) list_get_first(g_dns->results); it; it = (struct net_dns_result*) list_get_next(g_dns->results))
LIST_FOREACH(struct net_dns_result*, it, g_dns->results,
{
if (it->job == job)
{
list_remove(g_dns->results, it);
return it;
}
}
});
return NULL;
}
@@ -366,21 +368,24 @@ extern size_t net_dns_result_size(const struct net_dns_result* res)
extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_first(res->addr_list);
LOG_TRACE("net_dns_result_first() - Address: %s", ip_convert_to_string(ipaddr));
LOG_TRACE("net_dns_result_first() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no address)");
return ipaddr;
}
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_next(res->addr_list);
LOG_TRACE("net_dns_result_next() - Address: %s", ip_convert_to_string(ipaddr));
LOG_TRACE("net_dns_result_next() - Address: %s", ipaddr ? ip_convert_to_string(ipaddr) : "(no more addresses)");
return ipaddr;
}
extern void net_dns_result_free(struct net_dns_result* res)
extern void net_dns_result_free(const struct net_dns_result* res)
{
if (!res)
return;
list_clear(res->addr_list, &hub_free);
list_destroy(res->addr_list);
free_job(res->job);
hub_free(res);
hub_free((struct net_dns_result*) res);
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -114,6 +114,6 @@ extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*);
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*);
/// When finished with the results
extern void net_dns_result_free(struct net_dns_result*);
extern void net_dns_result_free(const struct net_dns_result*);
#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

102
src/network/notify.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
struct uhub_notify_handle
{
net_notify_callback callback;
void* ptr;
#ifndef WIN32
int pipe_fd[2];
struct net_connection* con;
#endif
};
/*
* This contains a mechanism to wake up the main thread
* in a thread safe manner while it would be blocking
* in select() or something equivalent typically invoked from
* net_backend_process().
*
* The main usage is for the DNS resolver to notify the
* main thread that there are DNS results to be
* processed.
*/
/**
* Create a notification handle.
*/
#ifndef WIN32
static void notify_callback(struct net_connection* con, int event, void* ptr)
{
LOG_TRACE("notify_callback()");
struct uhub_notify_handle* handle = (struct uhub_notify_handle*) ptr;
char buf;
int ret = read(handle->pipe_fd[0], &buf, 1);
if (ret == 1)
{
if (handle->callback)
handle->callback(handle, handle->ptr);
}
}
#endif
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr)
{
LOG_TRACE("net_notify_create()");
struct uhub_notify_handle* handle = (struct uhub_notify_handle*) hub_malloc(sizeof(struct uhub_notify_handle));
handle->callback = cb;
handle->ptr = ptr;
#ifndef WIN32
int ret = pipe(handle->pipe_fd);
if (ret == -1)
{
LOG_ERROR("Unable to setup notification pipes.");
hub_free(handle);
return 0;
}
handle->con = net_con_create();
net_con_initialize(handle->con, handle->pipe_fd[0], notify_callback, handle, NET_EVENT_READ);
#endif
return handle;
}
void net_notify_destroy(struct uhub_notify_handle* handle)
{
LOG_TRACE("net_notify_destroy()");
#ifndef WIN32
net_con_destroy(handle->con);
close(handle->pipe_fd[0]);
close(handle->pipe_fd[1]);
handle->pipe_fd[0] = -1;
handle->pipe_fd[0] = -1;
#endif
hub_free(handle);
}
void net_notify_signal(struct uhub_notify_handle* handle, char data)
{
LOG_TRACE("net_notify_signal()");
#ifndef WIN32
write(handle->pipe_fd[1], &data, 1);
#endif
}

56
src/network/notify.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_NOTIFY_API_H
#define HAVE_UHUB_NETWORK_NOTIFY_API_H
struct uhub_notify_handle;
typedef void (*net_notify_callback)(struct uhub_notify_handle* handle, void* ptr);
/*
* This contains a mechanism to wake up the main thread
* in a thread safe manner while it would be blocking
* in select() or something equivalent typically invoked from
* net_backend_process().
*
* The main usage is for the DNS resolver to notify the
* main thread that there are DNS results to be
* processed.
*/
/**
* Create a notification handle.
*/
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr);
/**
* Destroy a notification handle.
*/
void net_notify_destroy(struct uhub_notify_handle*);
/**
* Signal the notification handle, this will surely
* interrupt the net_backend_process(), and force it to
* process messages.
*/
void net_notify_signal(struct uhub_notify_handle*, char data);
#endif /* HAVE_UHUB_NETWORK_NOTIFY_API_H */

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@
#include "uhub.h"
#include "network/common.h"
#include "network/tls.h"
#include "network/backend.h"
#ifdef SSL_SUPPORT
#ifdef SSL_USE_OPENSSL
@@ -32,6 +33,9 @@ struct net_ssl_openssl
SSL* ssl;
BIO* bio;
enum ssl_state state;
int events;
int ssl_read_events;
int ssl_write_events;
uint32_t flags;
size_t bytes_rx;
size_t bytes_tx;
@@ -39,8 +43,7 @@ struct net_ssl_openssl
struct net_context_openssl
{
SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
SSL_CTX* ssl;
};
static struct net_ssl_openssl* get_handle(struct net_connection* con)
@@ -49,6 +52,29 @@ static struct net_ssl_openssl* get_handle(struct net_connection* con)
return (struct net_ssl_openssl*) con->ssl;
}
#ifdef DEBUG
static const char* get_state_str(enum ssl_state state)
{
switch (state)
{
case tls_st_none: return "tls_st_none";
case tls_st_error: return "tls_st_error";
case tls_st_accepting: return "tls_st_accepting";
case tls_st_connecting: return "tls_st_connecting";
case tls_st_connected: return "tls_st_connected";
case tls_st_disconnecting: return "tls_st_disconnecting";
}
uhub_assert(!"This should not happen - invalid state!");
return "(UNKNOWN STATE)";
}
#endif
static void net_ssl_set_state(struct net_ssl_openssl* handle, enum ssl_state new_state)
{
LOG_DEBUG("net_ssl_set_state(): prev_state=%s, new_state=%s", get_state_str(handle->state), get_state_str(new_state));
handle->state = new_state;
}
const char* net_ssl_get_provider()
{
return OPENSSL_VERSION_TEXT;
@@ -70,9 +96,9 @@ int net_ssl_library_shutdown()
ENGINE_cleanup();
CONF_modules_unload(1);
ERR_free_strings();
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
CRYPTO_cleanup_all_ex_data();
// sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
return 1;
@@ -93,36 +119,83 @@ static void add_io_stats(struct net_ssl_openssl* handle)
}
}
static const SSL_METHOD* get_ssl_method(const char* tls_version)
{
if (!tls_version || !*tls_version)
{
LOG_ERROR("tls_version is not set.");
return 0;
}
if (!strcmp(tls_version, "1.0"))
return TLSv1_method();
if (!strcmp(tls_version, "1.1"))
return TLSv1_1_method();
if (!strcmp(tls_version, "1.2"))
return TLSv1_2_method();
LOG_ERROR("Unable to recognize tls_version.");
return 0;
}
/**
* Create a new SSL context.
*/
struct ssl_context_handle* net_ssl_context_create()
struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl));
ctx->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */
ctx->ssl_ctx = SSL_CTX_new(ctx->ssl_method);
const SSL_METHOD* ssl_method = get_ssl_method(tls_version);
if (!ssl_method)
{
hub_free(ctx);
return 0;
}
ctx->ssl = SSL_CTX_new(ssl_method);
/* Disable SSLv2 */
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_quiet_shutdown(ctx->ssl_ctx, 1);
SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_SSLv2);
// #ifdef SSL_OP_NO_SSLv3
/* Disable SSLv3 */
SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_SSLv3);
// #endif
// FIXME: Why did we need this again?
SSL_CTX_set_quiet_shutdown(ctx->ssl, 1);
#ifdef SSL_OP_NO_COMPRESSION
/* Disable compression */
LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */
SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_COMPRESSION);
#endif
/* Set preferred cipher suite */
if (SSL_CTX_set_cipher_list(ctx->ssl, tls_ciphersuite) != 1)
{
LOG_ERROR("Unable to set cipher suite.");
SSL_CTX_free(ctx->ssl);
hub_free(ctx);
return 0;
}
return (struct ssl_context_handle*) ctx;
}
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx_)
void net_ssl_context_destroy(struct ssl_context_handle* ctx_)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
SSL_CTX_free(ctx->ssl_ctx);
SSL_CTX_free(ctx->ssl);
hub_free(ctx);
}
int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file)
{
struct net_context_openssl* ctx = (struct net_context_openssl*) ctx_;
if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem_file, SSL_FILETYPE_PEM) < 0)
if (SSL_CTX_use_certificate_chain_file(ctx->ssl, pem_file) < 0)
{
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
LOG_ERROR("SSL_CTX_use_certificate_chain_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
}
@@ -132,7 +205,7 @@ int ssl_load_certificate(struct ssl_context_handle* ctx_, const char* pem_file)
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)
if (SSL_CTX_use_PrivateKey_file(ctx->ssl, pem_file, SSL_FILETYPE_PEM) < 0)
{
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
@@ -143,7 +216,7 @@ int ssl_load_private_key(struct ssl_context_handle* ctx_, const char* pem_file)
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)
if (SSL_CTX_check_private_key(ctx->ssl) != 1)
{
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
return 0;
@@ -151,7 +224,7 @@ int ssl_check_private_key(struct ssl_context_handle* ctx_)
return 1;
}
static int handle_openssl_error(struct net_connection* con, int ret, enum ssl_state forced_rwstate)
static int handle_openssl_error(struct net_connection* con, int ret, int read)
{
struct net_ssl_openssl* handle = get_handle(con);
int err = SSL_get_error(handle->ssl, ret);
@@ -162,33 +235,43 @@ static int handle_openssl_error(struct net_connection* con, int ret, enum ssl_st
return -1;
case SSL_ERROR_WANT_READ:
handle->state = forced_rwstate;
net_con_update(con, NET_EVENT_READ);
if (read)
handle->ssl_read_events = NET_EVENT_READ;
else
handle->ssl_write_events = NET_EVENT_READ;
return 0;
case SSL_ERROR_WANT_WRITE:
handle->state = forced_rwstate;
net_con_update(con, NET_EVENT_WRITE);
if (read)
handle->ssl_read_events = NET_EVENT_WRITE;
else
handle->ssl_write_events = NET_EVENT_WRITE;
return 0;
case SSL_ERROR_SSL:
net_ssl_set_state(handle, tls_st_error);
return -2;
case SSL_ERROR_SYSCALL:
handle->state = tls_st_error;
net_ssl_set_state(handle, tls_st_error);
return -2;
}
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;
net_ssl_set_state(handle, tls_st_accepting);
ret = SSL_accept(handle->ssl);
LOG_PROTO("SSL_accept() ret=%d", ret);
if (ret > 0)
{
net_con_update(con, NET_EVENT_READ);
handle->state = tls_st_connected;
net_ssl_set_state(handle, tls_st_connected);
return ret;
}
return handle_openssl_error(con, ret, tls_st_accepting);
@@ -198,30 +281,34 @@ 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;
net_ssl_set_state(handle, 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);
net_ssl_set_state(handle, tls_st_connected);
return ret;
}
return handle_openssl_error(con, ret, tls_st_connecting);
ret = handle_openssl_error(con, ret, tls_st_connecting);
LOG_ERROR("net_con_ssl_connect: ret=%d", ret);
return ret;
}
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, struct ssl_context_handle* ssl_ctx)
{
uhub_assert(con);
uhub_assert(ssl_ctx);
struct net_context_openssl* ctx = (struct net_context_openssl*) ssl_ctx;
struct net_ssl_openssl* handle = (struct net_ssl_openssl*) hub_malloc_zero(sizeof(struct net_ssl_openssl));
if (ssl_mode == net_con_ssl_mode_server)
{
handle->ssl = SSL_new(ctx->ssl_ctx);
handle->ssl = SSL_new(ctx->ssl);
if (!handle->ssl)
{
LOG_ERROR("Unable to create new SSL stream\n");
@@ -234,31 +321,37 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
}
else
{
handle->ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
handle->ssl = SSL_new(ctx->ssl);
SSL_set_fd(handle->ssl, con->sd);
handle->bio = SSL_get_rbio(handle->ssl);
con->ssl = (struct ssl_handle*) handle;
return net_con_ssl_connect(con);
}
}
ssize_t net_ssl_send(struct net_connection* con, const void* buf, size_t len)
{
struct net_ssl_openssl* handle = get_handle(con);
uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_write);
LOG_ERROR("net_ssl_send(), state=%d", (int) handle->state);
if (handle->state == tls_st_error)
return -2;
uhub_assert(handle->state == tls_st_connected);
ERR_clear_error();
ssize_t ret = SSL_write(handle->ssl, buf, len);
add_io_stats(handle);
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret > 0)
{
handle->state = tls_st_connected;
return ret;
}
return handle_openssl_error(con, ret, tls_st_need_write);
handle->ssl_write_events = 0;
else
ret = handle_openssl_error(con, ret, 0);
net_ssl_update(con, handle->events); // Update backend only
return ret;
}
ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len)
@@ -269,7 +362,10 @@ ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t len)
if (handle->state == tls_st_error)
return -2;
uhub_assert(handle->state == tls_st_connected || handle->state == tls_st_need_read);
if (handle->state == tls_st_accepting || handle->state == tls_st_connecting)
return -1;
uhub_assert(handle->state == tls_st_connected);
ERR_clear_error();
@@ -277,29 +373,43 @@ ssize_t net_ssl_recv(struct net_connection* con, void* buf, size_t 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);
handle->ssl_read_events = 0;
else
ret = handle_openssl_error(con, ret, 1);
net_ssl_update(con, handle->events); // Update backend only
return ret;
}
void net_ssl_update(struct net_connection* con, int events)
{
struct net_ssl_openssl* handle = get_handle(con);
handle->events = events;
net_backend_update(con, handle->events | handle->ssl_read_events | handle->ssl_write_events);
}
void net_ssl_shutdown(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
SSL_shutdown(handle->ssl);
SSL_clear(handle->ssl);
if (handle)
{
SSL_shutdown(handle->ssl);
SSL_clear(handle->ssl);
}
}
void net_ssl_destroy(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
LOG_TRACE("net_ssl_destroy: %p", con);
SSL_free(handle->ssl);
hub_free(handle);
}
void net_ssl_callback(struct net_connection* con, int events)
{
struct net_ssl_openssl* handle = get_handle(con);
int ret;
switch (handle->state)
{
@@ -308,7 +418,7 @@ void net_ssl_callback(struct net_connection* con, int events)
break;
case tls_st_error:
con->callback(con, NET_EVENT_READ, con->ptr);
con->callback(con, NET_EVENT_ERROR, con->ptr);
break;
case tls_st_accepting:
@@ -317,19 +427,27 @@ void net_ssl_callback(struct net_connection* con, int events)
break;
case tls_st_connecting:
if (net_con_ssl_connect(con) != 0)
ret = net_con_ssl_connect(con);
if (ret == 0)
return;
if (ret > 0)
{
LOG_DEBUG("%p SSL connected!", con);
con->callback(con, NET_EVENT_READ, con->ptr);
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);
}
else
{
LOG_DEBUG("%p SSL handshake failed!", con);
con->callback(con, NET_EVENT_ERROR, con->ptr);
}
break;
case tls_st_connected:
if (handle->ssl_read_events & events)
events |= NET_EVENT_READ;
if (handle->ssl_write_events & events)
events |= NET_EVENT_WRITE;
con->callback(con, events, con->ptr);
break;
@@ -338,6 +456,18 @@ void net_ssl_callback(struct net_connection* con, int events)
}
}
const char* net_ssl_get_tls_version(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
return SSL_get_version(handle->ssl);
}
const char* net_ssl_get_tls_cipher(struct net_connection* con)
{
struct net_ssl_openssl* handle = get_handle(con);
const SSL_CIPHER *cipher = SSL_get_current_cipher(handle->ssl);
return SSL_CIPHER_get_name(cipher);
}
#endif /* SSL_USE_OPENSSL */
#endif /* SSL_SUPPORT */

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,6 +42,7 @@ void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
{
t->last = now;
t->max = max;
memset(&t->lock, 0, sizeof(t->lock));
t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*));
}
@@ -52,12 +53,56 @@ void timeout_queue_shutdown(struct timeout_queue* t)
t->max = 0;
}
static int timeout_queue_locked(struct timeout_queue* t)
{
return t->lock.ptr != NULL;
}
static void timeout_queue_lock(struct timeout_queue* t)
{
t->lock.ptr = t;
}
// unlock and flush the locked events to the main timeout queue.
static void timeout_queue_unlock(struct timeout_queue* t)
{
struct timeout_evt* evt, *tmp, *first;
size_t pos;
t->lock.ptr = NULL;
evt = t->lock.next;
while (evt)
{
tmp = evt->next;
pos = evt->timestamp % t->max;
first = t->events[pos];
if (first)
{
first->prev->next = evt;
evt->prev = first->prev;
first->prev = evt;
}
else
{
t->events[pos] = evt;
evt->prev = evt;
}
evt->next = 0;
evt = tmp;
}
t->lock.next = 0;
t->lock.prev = 0;
}
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
{
size_t pos = (size_t) t->last;
size_t events = 0;
struct timeout_evt* evt = 0;
t->last = now;
timeout_queue_lock(t);
for (; pos <= now; pos++)
{
while ((evt = t->events[pos % t->max]))
@@ -67,6 +112,7 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
events++;
}
}
timeout_queue_unlock(t);
return events;
}
@@ -82,6 +128,61 @@ size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now)
return seconds;
}
static void timeout_queue_insert_locked(struct timeout_queue* t, struct timeout_evt* evt)
{
/* All events point back to the sentinel.
* this means the event is considered schedule (see timeout_evt_is_scheduled),
* and it is easy to tell if the event is in the wait queue or not.
*/
evt->prev = &t->lock;
evt->next = NULL;
// The sentinel next points to the first event in the locked queue
// The sentinel prev points to the last evetnt in the locked queue.
// NOTE: if prev is != NULL then next also must be != NULL.
if (t->lock.prev)
{
t->lock.prev->next = evt;
t->lock.prev = evt;
}
else
{
t->lock.next = evt;
t->lock.prev = evt;
}
return;
}
static void timeout_queue_remove_locked(struct timeout_queue* t, struct timeout_evt* evt)
{
uhub_assert(evt->prev == &t->lock);
if (t->lock.next == evt)
{
t->lock.next = evt->next;
if (t->lock.prev == evt)
t->lock.prev = evt->next;
}
else
{
struct timeout_evt *prev, *it;
prev = 0;
it = t->lock.next;
while (it)
{
prev = it;
it = it->next;
if (it == evt)
{
prev->next = it->next;
if (!prev->next)
t->lock.prev = prev;
}
}
}
timeout_evt_reset(evt);
}
void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
{
@@ -90,6 +191,12 @@ void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size
evt->timestamp = t->last + seconds;
evt->next = 0;
if (timeout_queue_locked(t))
{
timeout_queue_insert_locked(t, evt);
return;
}
first = t->events[pos];
if (first)
@@ -112,6 +219,13 @@ void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
size_t pos = (evt->timestamp % t->max);
struct timeout_evt* first = t->events[pos];
// Removing a locked event
if (evt->prev == &t->lock)
{
timeout_queue_remove_locked(t, evt);
return;
}
if (!first || !evt->prev)
return;

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,6 +43,7 @@ struct timeout_queue
{
time_t last;
size_t max;
struct timeout_evt lock;
struct timeout_evt** events;
};

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,31 +20,4 @@
#include "uhub.h"
#include "network/connection.h"
static void timeout_callback(struct timeout_evt* evt)
{
net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
if (!con->timeout)
{
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(con->timeout, timeout_callback, con);
timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
}
else
{
timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
}
}
void net_con_clear_timeout(struct net_connection* con)
{
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
{
timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
hub_free(con->timeout);
con->timeout = 0;
}
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,8 +32,6 @@ enum ssl_state
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,
};
@@ -58,8 +56,9 @@ extern int net_ssl_library_shutdown();
/**
* Create a new SSL context.
* Specify a TLS version as a string: "1.2" for TLS 1.2.
*/
extern struct ssl_context_handle* net_ssl_context_create();
extern struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite);
extern void net_ssl_context_destroy(struct ssl_context_handle* ctx);
/**
@@ -90,15 +89,26 @@ 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);
/**
* Update the event mask. Additional events may be requested depending on the
* needs of the TLS layer.
*
* @param con Connection handle.
* @param events Event mask (NET_EVENT_*)
*/
extern void net_ssl_update(struct net_connection* con, int events);
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);
extern const char* net_ssl_get_tls_version(struct net_connection* con);
extern const char* net_ssl_get_tls_cipher(struct net_connection* con);
#endif /* SSL_SUPPORT */
#endif /* HAVE_UHUB_NETWORK_TLS_H */

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -110,6 +110,7 @@ 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_broadcast_message)(struct plugin_handle*, const char* message);
typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message);
typedef int (*hfunc_user_disconnect)(struct plugin_handle*, struct plugin_user* user);
typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*);
@@ -118,6 +119,8 @@ typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_ha
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 size_t (*hfunc_get_usercount)(struct plugin_handle*);
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*);
@@ -130,12 +133,14 @@ typedef void (*hfunc_set_hub_description)(struct plugin_handle*, const char*);
struct plugin_hub_funcs
{
hfunc_send_message send_message;
hfunc_send_broadcast_message send_broadcast_message;
hfunc_send_status send_status_message;
hfunc_user_disconnect user_disconnect;
hfunc_command_add command_add;
hfunc_command_del command_del;
hfunc_command_arg_reset command_arg_reset;
hfunc_command_arg_next command_arg_next;
hfunc_get_usercount get_usercount;
hfunc_get_hub_name get_name;
hfunc_set_hub_name set_name;
hfunc_get_hub_description get_description;

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2011, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -177,16 +177,15 @@ static void unload_acl(struct acl_data* data)
static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data)
{
struct acl_data* acl = (struct acl_data*) plugin->ptr;
struct auth_info* info = (struct auth_info*) list_get_first(acl->users);
while (info)
struct auth_info* info;
LIST_FOREACH(struct auth_info*, info, acl->users,
{
if (strcasecmp((char*)info->nickname, nickname) == 0)
{
memcpy(data, info, sizeof(struct auth_info));
return st_allow;
}
info = (struct auth_info*) list_get_next(acl->users);
}
});
if (acl->exclusive)
return st_deny;
return st_default;

View File

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

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,9 +50,7 @@ static void history_add(struct plugin_handle* plugin, struct plugin_user* from,
list_append(data->chat_history, log);
while (list_size(data->chat_history) > data->history_max)
{
char* msg = list_get_first(data->chat_history);
list_remove(data->chat_history, msg);
hub_free(msg);
list_remove_first(data->chat_history, hub_free);
}
}
@@ -79,16 +77,14 @@ static size_t get_messages(struct chat_history_data* data, size_t num, struct cb
skiplines = total - num;
cbuf_append(outbuf, "\n");
message = (char*) list_get_first(messages);
while (message)
LIST_FOREACH(char*, message, messages,
{
if (--skiplines < 0)
{
cbuf_append(outbuf, message);
lines++;
}
message = (char*) list_get_next(messages);
}
});
cbuf_append(outbuf, "\n");
return lines;
}

View File

@@ -0,0 +1,347 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "plugin_api/handle.h"
#include "plugin_api/command_api.h"
#include "util/config_token.h"
#include <sqlite3.h>
#include "util/memory.h"
#include "util/misc.h"
#include "util/list.h"
#include "util/cbuffer.h"
#define MAX_HISTORY_SIZE 16384
struct chat_history_data
{
size_t history_max; ///<<< "the maximum number of chat messages kept in history."
size_t history_default; ///<<< "the default number of chat messages returned if no limit was provided"
size_t history_connect; ///<<< "the number of chat messages provided when users connect to the hub."
sqlite3* db; ///<<< "The chat history storage database."
struct plugin_command_handle* command_history_handle; ///<<< "A handle to the !history command."
struct plugin_command_handle* command_historycleanup_handle; ///<<< "A handle to the !historycleanup command."
};
struct chat_history_line
{
char message[MAX_HISTORY_SIZE];
char from[MAX_NICK_LEN];
char time[20];
};
static int null_callback(void* ptr, int argc, char **argv, char **colName) { return 0; }
static const char* sql_escape_string(const char* str)
{
static char out[1024];
size_t i = 0;
size_t n = 0;
for (; n < strlen(str); n++)
{
if (str[n] == '\'')
out[i++] = '\'';
out[i++] = str[n];
}
out[i++] = '\0';
return out;
}
static int sql_execute(struct chat_history_data* sql, int (*callback)(void* ptr, int argc, char **argv, char **colName), void* ptr, const char* sql_fmt, ...)
{
va_list args;
char query[1024];
char* errMsg;
int rc;
va_start(args, sql_fmt);
vsnprintf(query, sizeof(query), sql_fmt, args);
rc = sqlite3_exec(sql->db, query, callback, ptr, &errMsg);
if (rc != SQLITE_OK)
{
sqlite3_free(errMsg);
return -rc;
}
rc = sqlite3_changes(sql->db);
return rc;
}
static void create_tables(struct plugin_handle* plugin)
{
const char* table_create = "CREATE TABLE IF NOT EXISTS chat_history"
"("
"from_nick CHAR,"
"message TEXT,"
"time TIMESTAMP DEFAULT (DATETIME('NOW'))"
");";
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
sql_execute(data, null_callback, NULL, table_create);
}
/**
* Add a chat message to history.
*/
static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags)
{
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
char* history_line = strdup(sql_escape_string(message));
char* history_nick = strdup(sql_escape_string(from->nick));
sql_execute(data, null_callback, NULL, "INSERT INTO chat_history (from_nick, message) VALUES('%s', '%s');DELETE FROM chat_history WHERE time <= (SELECT time FROM chat_history ORDER BY time DESC LIMIT %d,1);", history_nick, history_line, data->history_max);
hub_free(history_line);
hub_free(history_nick);
}
/**
* Obtain messages from the chat history as a linked list
*/
static int get_messages_callback(void* ptr, int argc, char **argv, char **colName)
{
struct linked_list* messages = (struct linked_list*) ptr;
struct chat_history_line* line = hub_malloc(sizeof(struct chat_history_line));
int i = 0;
memset(line, 0, sizeof(struct chat_history_line));
for (; i < argc; i++) {
if (strcmp(colName[i], "from_nick") == 0)
strncpy(line->from, argv[i], MAX_NICK_LEN);
else if (strcmp(colName[i], "message") == 0)
strncpy(line->message, argv[i], MAX_HISTORY_SIZE);
else if (strcmp(colName[i], "time") == 0)
strncpy(line->time, argv[i], 20);
}
list_append(messages, line);
return 0;
}
void user_login(struct plugin_handle* plugin, struct plugin_user* user)
{
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
struct cbuffer* buf = NULL;
struct linked_list* found = (struct linked_list*) list_create();
sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", (int) data->history_connect);
if (data->history_connect > 0 && list_size(found) > 0)
{
buf = cbuf_create(MAX_HISTORY_SIZE);
cbuf_append(buf, "Chat history:\n\n");
struct chat_history_line* history_line;
history_line = (struct chat_history_line*) list_get_last(found);
while (history_line)
{
cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message);
list_remove(found, history_line);
hub_free(history_line);
history_line = (struct chat_history_line*) list_get_last(found);
}
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
}
list_clear(found, &hub_free);
list_destroy(found);
}
/**
* The callback function for handling the !history command.
*/
static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
struct cbuffer* buf = cbuf_create(MAX_HISTORY_SIZE);
struct linked_list* found = (struct linked_list*) list_create();
struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer);
int maxlines;
if (arg)
maxlines = arg->data.integer;
else
maxlines = data->history_default;
sql_execute(data, get_messages_callback, found, "SELECT * FROM chat_history ORDER BY time DESC LIMIT 0,%d;", maxlines);
size_t linecount = list_size(found);
if (linecount > 0)
{
cbuf_append_format(buf, "*** %s: Chat History:\n\n", cmd->prefix);
struct chat_history_line* history_line;
history_line = (struct chat_history_line*) list_get_last(found);
while (history_line)
{
cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message);
list_remove(found, history_line);
hub_free(history_line);
history_line = (struct chat_history_line*) list_get_last(found);
}
}
else
{
cbuf_append_format(buf, "*** %s: No messages found.", cmd->prefix);
}
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
list_clear(found, &hub_free);
list_destroy(found);
return 0;
}
static int command_historycleanup(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
{
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
struct cbuffer* buf = cbuf_create(128);
int rc = 0;
rc = sql_execute(data, null_callback, NULL, "DELETE FROM chat_history;");
if (!rc)
cbuf_append_format(buf, "*** %s: Unable to clean chat history table.", cmd->prefix);
else
cbuf_append_format(buf, "*** %s: Cleaned chat history table.", cmd->prefix);
plugin->hub.send_message(plugin, user, cbuf_get(buf));
cbuf_destroy(buf);
return 0;
}
static void set_error_message(struct plugin_handle* plugin, const char* msg)
{
plugin->error_msg = msg;
}
static struct chat_history_data* parse_config(const char* line, struct plugin_handle* plugin)
{
struct chat_history_data* data = (struct chat_history_data*) hub_malloc_zero(sizeof(struct chat_history_data));
struct cfg_tokens* tokens = cfg_tokenize(line);
char* token = cfg_token_get_first(tokens);
uhub_assert(data != NULL);
data->history_max = 200;
data->history_default = 25;
data->history_connect = 5;
while (token)
{
struct cfg_settings* setting = cfg_settings_split(token);
if (!setting)
{
set_error_message(plugin, "Unable to parse startup parameters");
cfg_tokens_free(tokens);
hub_free(data);
return 0;
}
if (strcmp(cfg_settings_get_key(setting), "file") == 0)
{
if (!data->db)
{
if (sqlite3_open(cfg_settings_get_value(setting), &data->db))
{
cfg_tokens_free(tokens);
cfg_settings_free(setting);
hub_free(data);
set_error_message(plugin, "Unable to open database file");
return 0;
}
}
}
else if (strcmp(cfg_settings_get_key(setting), "history_max") == 0)
{
data->history_max = (size_t) uhub_atoi(cfg_settings_get_value(setting));
}
else if (strcmp(cfg_settings_get_key(setting), "history_default") == 0)
{
data->history_default = (size_t) uhub_atoi(cfg_settings_get_value(setting));
}
else if (strcmp(cfg_settings_get_key(setting), "history_connect") == 0)
{
data->history_connect = (size_t) uhub_atoi(cfg_settings_get_value(setting));
}
else
{
set_error_message(plugin, "Unknown startup parameters given");
cfg_tokens_free(tokens);
cfg_settings_free(setting);
hub_free(data);
return 0;
}
cfg_settings_free(setting);
token = cfg_token_get_next(tokens);
}
cfg_tokens_free(tokens);
return data;
}
int plugin_register(struct plugin_handle* plugin, const char* config)
{
struct chat_history_data* data;
PLUGIN_INITIALIZE(plugin, "SQLite chat history plugin", "1.0", "Provide a global chat history log.");
plugin->funcs.on_user_chat_message = history_add;
plugin->funcs.on_user_login = user_login;
data = parse_config(config, plugin);
if (!data)
return -1;
plugin->ptr = data;
create_tables(plugin);
data->command_history_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle));
PLUGIN_COMMAND_INITIALIZE(data->command_history_handle, plugin, "history", "?N", auth_cred_guest, &command_history, "Show chat message history.");
plugin->hub.command_add(plugin, data->command_history_handle);
data->command_historycleanup_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle));
PLUGIN_COMMAND_INITIALIZE(data->command_historycleanup_handle, plugin, "historycleanup", "", auth_cred_admin, &command_historycleanup, "Clean chat message history.");
plugin->hub.command_add(plugin, data->command_historycleanup_handle);
return 0;
}
int plugin_unregister(struct plugin_handle* plugin)
{
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
if (data)
{
sqlite3_close(data->db);
plugin->hub.command_del(plugin, data->command_history_handle);
plugin->hub.command_del(plugin, data->command_historycleanup_handle);
hub_free(data->command_history_handle);
hub_free(data->command_historycleanup_handle);
hub_free(data);
}
return 0;
}

View File

@@ -0,0 +1,171 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2014, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "plugin_api/handle.h"
#include "util/memory.h"
struct user_info
{
sid_t sid;
int warnings;
};
struct chat_restrictions_data
{
size_t num_users; // number of users tracked.
size_t max_users; // max users (hard limit max 1M users due to limitations in the SID (20 bits)).
struct user_info* users; // array of max_users
enum auth_credentials allow_privchat; // minimum credentials to allow using private chat
enum auth_credentials allow_op_contact; // minimum credentials to allow private chat to operators (including super and admins).
enum auth_credentials allow_mainchat; // minimum credentials to allow using main chat
};
static struct chat_data* parse_config(struct plugin_handle* plugin, const char* line)
{
struct chat_data* data = (struct chat_data*) hub_malloc(sizeof(struct chat_data));
struct cfg_tokens* tokens = cfg_tokenize(line);
char* token = cfg_token_get_first(tokens);
// defaults
data->num_users = 0;
data->max_users = 512;
data->users = hub_malloc_zero(sizeof(struct user_info) * data->max_users);
data->allow_mainchat = auth_cred_guest;
data->allow_op_contact = auth_cred_guest;
data->allow_privchat = auth_cred_guest;
while (token)
{
struct cfg_settings* setting = cfg_settings_split(token);
if (!setting)
{
set_error_message(plugin, "Unable to parse startup parameters");
cfg_tokens_free(tokens);
hub_free(data);
return 0;
}
if (strcmp(cfg_settings_get_key(setting), "allow_privchat") == 0)
{
if (!string_to_boolean(cfg_settings_get_value(setting), &data->allow_privchat))
data->allow_privchat = 0;
}
else if (strcmp(cfg_settings_get_key(setting), "minimum_access") == 0)
{
}
else
{
set_error_message(plugin, "Unknown startup parameters given");
cfg_tokens_free(tokens);
cfg_settings_free(setting);
hub_free(data);
return 0;
}
cfg_settings_free(setting);
token = cfg_token_get_next(tokens);
}
cfg_tokens_free(tokens);
return data;
}
static struct user_info* get_user_info(struct chat_data* data, sid_t sid)
{
struct user_info* u;
// resize buffer if needed.
if (sid >= data->max_users)
{
u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1));
memcpy(u, data->users, data->max_users);
hub_free(data->users);
data->users = u;
data->max_users = sid;
u = NULL;
}
u = &data->users[sid];
// reset counters if the user was not previously known.
if (!u->sid)
{
u->sid = sid;
u->warnings = 0;
data->num_users++;
}
return u;
}
static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user)
{
struct chat_data* data = (struct chat_data*) plugin->ptr;
/*struct user_info* info = */
get_user_info(data, user->sid);
}
static void on_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason)
{
struct chat_data* data = (struct chat_data*) plugin->ptr;
struct user_info* info = get_user_info(data, user->sid);
if (info->sid)
data->num_users--;
info->warnings = 0;
info->sid = 0;
}
plugin_st on_chat_msg(struct plugin_handle* plugin, struct plugin_user* from, const char* message)
{
struct chat_data* data = (struct chat_data*) plugin->ptr;
if (from->credentials >=
return st_default;
}
plugin_st on_private_msg(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* message)
{
return st_default;
}
int plugin_register(struct plugin_handle* plugin, const char* config)
{
PLUGIN_INITIALIZE(plugin, "Privileged chat hub", "1.0", "Only registered users can send messages on the main chat.");
plugin->ptr = cip_initialize();
plugin->funcs.on_user_login = on_user_login;
plugin->funcs.on_user_logout = on_user_logout;
plugin->funcs.on_chat_msg = on_chat_msg;
plugin->funcs.on_private_msg = on_private_msg;
return 0;
}
int plugin_unregister(struct plugin_handle* plugin)
{
struct chat_data* data = (struct chat_data*) plugin->ptr;
if (data)
{
hub_free(data->users);
hub_free(data);
}
return 0;
}

View File

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

View File

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

View File

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

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