Compare commits
456 Commits
plugin_wor
...
master
Author | SHA1 | Date | |
---|---|---|---|
fdc1ccc68e | |||
0875ba15f5 | |||
|
35d8088b44 | ||
|
cff10910ad | ||
|
78a7039240 | ||
|
0ae96b0da8 | ||
|
022a9895ec | ||
|
891adb84fb | ||
|
9762b9389d | ||
|
076e75897b | ||
|
bc8974b9a3 | ||
|
1eb00ac04a | ||
|
cf3a6e06df | ||
|
cb04255006 | ||
|
2a57dc859d | ||
|
212064c166 | ||
|
56426f7b2a | ||
|
00bd8ba24d | ||
|
46906a9a9c | ||
|
566cd9a9db | ||
|
b27c44e633 | ||
|
d25fead3a8 | ||
|
ef83b31cec | ||
|
be1ad4f475 | ||
|
3435d53478 | ||
|
9038f56efe | ||
|
de01486c0f | ||
|
c383a53105 | ||
|
f0b67ea4cd | ||
|
ac96ace7df | ||
|
7970f80114 | ||
|
62216a7afe | ||
|
99711a5c6e | ||
|
e43aea35cc | ||
|
d54d723c59 | ||
|
c813231c8d | ||
|
debbca572f | ||
|
a8ee6e7f60 | ||
|
f0e9b2ffd9 | ||
|
ba19048ebc | ||
|
fd05f13fe4 | ||
|
11538d6909 | ||
|
90d05c9a19 | ||
|
ed5a59b16c | ||
|
70f2a43f67 | ||
|
dc80644471 | ||
|
889807da1b | ||
|
5151badbeb | ||
|
96cc46117f | ||
|
5e63ab2ccd | ||
|
32b7e68f00 | ||
|
5c5918a89d | ||
|
3f2641595b | ||
|
0e27e4219d | ||
|
e32bb3ff7a | ||
|
32c65ada49 | ||
|
77704f6e67 | ||
|
77323fa98d | ||
|
7840e09884 | ||
|
6ad5efea6d | ||
|
076daec846 | ||
|
223e01937e | ||
|
19068de088 | ||
|
c15f201d70 | ||
|
7bda215ad4 | ||
|
d86ef503b3 | ||
|
7865277324 | ||
|
8a7e892aeb | ||
|
05edfa48b2 | ||
|
204544298b | ||
|
418db22931 | ||
|
037ceff0a5 | ||
|
44708e8433 | ||
|
76ff2a1a13 | ||
|
280e28a6d4 | ||
|
c0ee55325c | ||
|
3d0b652ec9 | ||
|
2d45a37536 | ||
|
1da917e5b9 | ||
|
f71bc59527 | ||
|
d7c8c9426d | ||
|
4919aea8d5 | ||
|
95de69efeb | ||
|
b3b4876c08 | ||
|
ac543e3df4 | ||
|
46bdc77066 | ||
|
1526d63403 | ||
|
d33695435b | ||
|
bfdf707490 | ||
|
b8209d9d0a | ||
|
5c8d99d8ff | ||
|
4c5038c26d | ||
|
aeb006beb6 | ||
|
3b6c338ee8 | ||
|
652ac5f9b9 | ||
|
4263750bc5 | ||
|
2182feb052 | ||
|
48b76f7bd1 | ||
|
b5bedfe9e4 | ||
|
cbe0b4e108 | ||
|
b85381c0f5 | ||
|
0426cb523a | ||
|
9f78a2e85f | ||
|
f472fc9424 | ||
|
7706e1cb8a | ||
|
24b98358d3 | ||
|
12ce522a6d | ||
|
5e06b46deb | ||
|
a1f8c5bdbb | ||
|
992aa8c4af | ||
|
60393ca9d0 | ||
|
89aef4ddaf | ||
|
a38a82e318 | ||
|
3e8699ab24 | ||
|
3b38898045 | ||
|
1b8762c7ee | ||
|
ce06269128 | ||
|
e75a759693 | ||
|
7f2ffd7e1c | ||
|
e2b0757f4a | ||
|
c26e8aaefe | ||
|
c295461f4e | ||
|
8b442018a7 | ||
|
fa782e3d2c | ||
|
591d0ba5bb | ||
|
a81757c483 | ||
|
cf9be754aa | ||
|
22292e493e | ||
|
419e8888d0 | ||
|
73b4d51393 | ||
|
50b6221874 | ||
|
bb5865d368 | ||
|
550740f715 | ||
|
d73d213bc4 | ||
|
5672ba14e3 | ||
|
cd5c4ee622 | ||
|
52211a6bac | ||
|
f25015927a | ||
|
5835a06676 | ||
|
6c55ae1146 | ||
|
2d6f69d299 | ||
|
b81bb2cbd9 | ||
|
50e720861e | ||
|
d48ef710d8 | ||
|
cfa210b3f3 | ||
|
f6f7c7a3a4 | ||
|
1fbde2b0fd | ||
|
92b65a0e14 | ||
|
4d438e1e90 | ||
|
4f3c71234b | ||
|
fdaadccb99 | ||
|
41251f8d32 | ||
|
3b18ae251e | ||
|
b452488431 | ||
|
143b68588a | ||
|
5f2b7bc069 | ||
|
ce68c446d1 | ||
|
37c80fd403 | ||
|
dcc7aa4018 | ||
|
9dce6693f6 | ||
|
6af0f293a6 | ||
|
a492f30950 | ||
|
a43953bc0d | ||
|
594801df46 | ||
|
3dcbb63a31 | ||
|
5d6184961b | ||
|
b17e88573e | ||
|
2d2ccc0039 | ||
|
0a2f9c4b79 | ||
|
ae62c35cb9 | ||
|
2ec2e73f16 | ||
|
d4763e54db | ||
|
38b19f633d | ||
|
d106ecdc65 | ||
|
99a2307d1d | ||
|
470c936e63 | ||
|
168fc5bfcc | ||
|
b34b90f95a | ||
|
793790d089 | ||
|
19559f4974 | ||
|
b999068555 | ||
|
4385266bb7 | ||
|
c50eb90bee | ||
|
1e0927f510 | ||
|
b9d43c784c | ||
|
46d365cafe | ||
|
2f830d3132 | ||
|
5884983a2f | ||
|
c43acd97bd | ||
|
b1f2c93738 | ||
|
50912bdf75 | ||
|
3a8c91004e | ||
|
deaadd053b | ||
|
c28a5d3a9b | ||
|
8b06a75d8e | ||
|
e6cb7a7e10 | ||
|
82caa6b81f | ||
|
ddfbb919a7 | ||
|
7fae42aa4d | ||
|
ba59e1a00e | ||
|
4fcfee8e82 | ||
|
63171b0ce2 | ||
|
dcfcf3110d | ||
|
53a5f5a243 | ||
|
f3922bb3e0 | ||
|
af083efb0c | ||
|
e7aa63f3bd | ||
|
279c932b67 | ||
|
69603ff70f | ||
|
f20c42d05f | ||
|
3ea38c59af | ||
|
50292cb8c9 | ||
|
e4fc91dde1 | ||
|
8086d89e23 | ||
|
cc2ead8136 | ||
|
10d8157477 | ||
|
0a7cb86014 | ||
|
2e8c99b7ec | ||
|
cb6236691b | ||
|
5136525abc | ||
|
07da142e65 | ||
|
aa21556600 | ||
|
16ee65422d | ||
|
f0b11dadf1 | ||
|
61073bd304 | ||
|
20a847e1b4 | ||
|
a90807fccb | ||
|
25c82076da | ||
|
089966d918 | ||
|
e95a892fb7 | ||
|
564f09ad65 | ||
|
a33851b13d | ||
|
20e445bf94 | ||
|
133707ef57 | ||
|
62d14a9c52 | ||
|
ab9dda1c61 | ||
|
37e78eada1 | ||
|
5b4467acd5 | ||
|
ff2e2a3d4c | ||
|
a599b29b9d | ||
|
fc52f0e030 | ||
|
35bfefa717 | ||
|
845aefc941 | ||
|
4fcf3ffc83 | ||
|
ac39ebf38a | ||
|
3f777ce5e2 | ||
|
b0aa690cb4 | ||
|
fb11589bb0 | ||
|
03c4292eea | ||
|
ccaf755da3 | ||
|
cba0121574 | ||
|
166a105e33 | ||
|
a32ea42754 | ||
|
949b54fcdd | ||
|
b9005b1724 | ||
|
9651a99d46 | ||
|
571abddd98 | ||
|
9ea85ad1ac | ||
|
3ae6da4a64 | ||
|
f3754fb4e4 | ||
|
79ca108f48 | ||
|
210d5d276e | ||
|
a6d87f95ef | ||
|
274f17bce0 | ||
|
53b3087735 | ||
|
8365278cbf | ||
|
eb49174ab3 | ||
|
9e52ea7eff | ||
|
05fd6bb723 | ||
|
7b77f7dc31 | ||
|
685e56f4c6 | ||
|
d19e78941a | ||
|
c5516b5729 | ||
|
3aaabbc543 | ||
|
ccb66ced4f | ||
|
dce8b97bba | ||
|
d49127b507 | ||
|
ccded3f642 | ||
|
216757a1f4 | ||
|
458c7fa741 | ||
|
74ca5a0a33 | ||
|
9efe4bce57 | ||
|
e4cf01ff1f | ||
|
82615fc86e | ||
|
b72f5a407a | ||
|
776f7d0bff | ||
|
27ceb7ad33 | ||
|
c5036a3ff8 | ||
|
832277f653 | ||
|
c525e59fa5 | ||
|
781f22edab | ||
|
55030935a7 | ||
|
4f0c8e0356 | ||
|
e925db2b98 | ||
|
0cbb382b14 | ||
|
303dbadac2 | ||
|
e408ae3eba | ||
|
5b6ab7e1d2 | ||
|
2298f09c0f | ||
|
ad5e5d2837 | ||
|
106574008f | ||
|
1dba731cc3 | ||
|
df7bbc094f | ||
|
390b63e80a | ||
|
5068fe8351 | ||
|
e4df1884d2 | ||
|
8607b40278 | ||
|
a9b5c6db38 | ||
|
0ae8a08f55 | ||
|
ff639d87c3 | ||
|
5edf2b60d4 | ||
|
66215cc535 | ||
|
eee2636582 | ||
|
f44a420970 | ||
|
fcf6827a68 | ||
|
ca3782c570 | ||
|
875f55a401 | ||
|
a9ed03cf38 | ||
|
b0a8c3251b | ||
|
2ebd916992 | ||
|
3c6254d007 | ||
|
7b392acbf5 | ||
|
66c77d5170 | ||
|
c2e25453f6 | ||
|
1700a27619 | ||
|
aa01fd40e5 | ||
|
5b7382a27c | ||
|
a5b02d1672 | ||
|
fe15c4cb58 | ||
|
ecedd44fee | ||
|
24e2c2090e | ||
|
2a190859bd | ||
|
88dd1341d2 | ||
|
b24d4b85cd | ||
|
f34f0328a3 | ||
|
f31fc65e1d | ||
|
7325b15786 | ||
|
ec3afc3a44 | ||
|
ba26f4c5e2 | ||
|
68dc3cafc7 | ||
|
583900cec5 | ||
|
93caa9b3c1 | ||
|
f2cb84180a | ||
|
fc5e09aa9e | ||
|
b4779bfb12 | ||
|
6d609e18a2 | ||
|
ebd3ccf98e | ||
|
b28417c3a3 | ||
|
aec89fc125 | ||
|
9377fb537a | ||
|
afda1d7b9d | ||
|
2352e5a0dd | ||
|
1dc79c641c | ||
|
41824ce2bf | ||
|
65c2652a22 | ||
|
fb89307b0a | ||
|
8d607dff13 | ||
|
7825c413d4 | ||
|
318163c066 | ||
|
78ed83840b | ||
|
e972b03f38 | ||
|
9f16298688 | ||
|
c17b43e77f | ||
|
675e6af3ba | ||
|
2396d8555c | ||
|
9981acca08 | ||
|
99e644597d | ||
|
3a39a36fbb | ||
|
1102a86463 | ||
|
bad4512a37 | ||
|
3b4a199673 | ||
|
f8d057f15a | ||
|
39572c3684 | ||
|
0d8283930f | ||
|
33b94d8eb4 | ||
|
324bfcd2c8 | ||
|
87535ff0d6 | ||
|
800f6a70f9 | ||
|
5d2a25a1be | ||
|
70f13158d3 | ||
|
9327615448 | ||
|
ebe54bcf27 | ||
|
e4aa565fab | ||
|
998f5a57e2 | ||
|
472c489ae1 | ||
|
bba7c0d05b | ||
|
169b8a4a75 | ||
|
f13bcd8c28 | ||
|
a79fcd796e | ||
|
474e2be308 | ||
|
47cf3326fd | ||
|
3353049ae3 | ||
|
3ccce614d0 | ||
|
e30505b54e | ||
|
3bc764adf5 | ||
|
6becadc984 | ||
|
4a03accc34 | ||
|
d01813ef48 | ||
|
e5bb7057de | ||
|
bf4ad5624a | ||
|
03b4252ab5 | ||
|
863e0e9844 | ||
|
4c238dd946 | ||
|
e20b15ef74 | ||
|
9b57279628 | ||
|
e82ac17452 | ||
|
adb6641a17 | ||
|
67eabb5a98 | ||
|
eaf867d513 | ||
|
4ede1b2d8a | ||
|
d4accea32c | ||
|
50e44f5272 | ||
|
3b3862fa8d | ||
|
d86e1b8f0b | ||
|
b993e97bb4 | ||
|
4f8e3ba10b | ||
|
16fc3ea68e | ||
|
a934dfaa70 | ||
|
21c22288a2 | ||
|
ff8b8f5175 | ||
|
1af7e26c52 | ||
|
35b055f9b7 | ||
|
4c960cb977 | ||
|
5419d07efe | ||
|
c2b7ecd49c | ||
|
0c6a58d35a | ||
|
4a977da514 | ||
|
04c02d3f2f | ||
|
e03b4ff0c1 | ||
|
4bf882d385 | ||
|
dbf790bb93 | ||
|
f9abd40ff9 | ||
|
5d135bb5b7 | ||
|
7c1e38602c | ||
|
55ffe46a38 | ||
|
93be2c584e | ||
|
c75090cdf2 | ||
|
97feb3635e | ||
|
920d696ff5 | ||
|
350791cdf8 | ||
|
c6cf03614f | ||
|
1ff0f54a4b | ||
|
bdcf35b63d | ||
|
d41d649353 | ||
|
56e5557146 | ||
|
e4977606a7 | ||
|
f386e57de8 | ||
|
ccb318547d | ||
|
394c8a5f95 | ||
|
4b22ccb73c | ||
|
849a791f79 | ||
|
b4fa508265 | ||
|
490f7dd835 | ||
|
7b96e2c912 | ||
|
0810982b57 | ||
|
ac5811633e |
17
.drone.yml
Normal file
17
.drone.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
network_mode: bridge
|
||||||
|
settings:
|
||||||
|
repo: sneak/uhub
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
tags:
|
||||||
|
- ${DRONE_BRANCH//\//-}-${DRONE_COMMIT_SHA:0:8}
|
||||||
|
- ${DRONE_COMMIT_SHA}
|
||||||
|
- ${DRONE_BRANCH/\//-}
|
17
.gitignore
vendored
17
.gitignore
vendored
@ -1,8 +1,23 @@
|
|||||||
*~
|
*~
|
||||||
*.[oa]
|
*.[oa]
|
||||||
|
*.lib
|
||||||
*.exe
|
*.exe
|
||||||
|
*.manifest
|
||||||
*.gch
|
*.gch
|
||||||
|
CMakeFiles/*
|
||||||
|
CMakeCache.txt
|
||||||
|
cmake_install.cmake
|
||||||
|
mod_*.dll
|
||||||
|
mod_*.exp
|
||||||
|
mod_*.so
|
||||||
uhub-admin
|
uhub-admin
|
||||||
adcrush
|
adcrush
|
||||||
uhub
|
uhub
|
||||||
|
build-stamp
|
||||||
|
debian/files
|
||||||
|
debian/uhub.debhelper.log
|
||||||
|
debian/uhub.postinst.debhelper
|
||||||
|
debian/uhub.postrm.debhelper
|
||||||
|
debian/uhub.prerm.debhelper
|
||||||
|
debian/uhub.substvars
|
||||||
|
uhub-passwd
|
||||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "thirdparty/sqlite"]
|
||||||
|
path = thirdparty/sqlite
|
||||||
|
url = https://github.com/janvidar/sqlite.git
|
14
.travis.yml
Normal file
14
.travis.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
language: cpp
|
||||||
|
dist: xenial
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
- clang
|
||||||
|
env:
|
||||||
|
- CONFIG=minimal
|
||||||
|
- CONFIG=full
|
||||||
|
install:
|
||||||
|
- autotest/travis/install-build-depends.sh
|
||||||
|
script:
|
||||||
|
- autotest/travis/build-and-test.sh
|
||||||
|
dist: xenial
|
||||||
|
|
9
AUTHORS
9
AUTHORS
@ -1,6 +1,11 @@
|
|||||||
Authors of uHub
|
Authors of uhub
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Jan Vidar Krey, Design and implementation
|
Jan Vidar Krey, Design and implementation
|
||||||
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
||||||
|
FleetCommand, Hub topic plugin code
|
||||||
|
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
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
GMAKE=gmake
|
|
||||||
|
|
||||||
all:
|
|
||||||
@${GMAKE} ${.TARGETS}
|
|
||||||
|
|
||||||
${.TARGETS}: all
|
|
||||||
|
|
3
BUGS
3
BUGS
@ -1,2 +1 @@
|
|||||||
Bugs are tracked on: http://bugs.extatic.org/
|
Bugs are tracked on: https://github.com/janvidar/uhub/issues
|
||||||
|
|
||||||
|
246
CMakeLists.txt
Normal file
246
CMakeLists.txt
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
##
|
||||||
|
## Makefile for uhub
|
||||||
|
## Copyright (C) 2007-2013, Jan Vidar Krey <janvidar@extatic.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required (VERSION 2.8.2)
|
||||||
|
|
||||||
|
project (uhub NONE)
|
||||||
|
enable_language(C)
|
||||||
|
|
||||||
|
set (UHUB_VERSION_MAJOR 0)
|
||||||
|
set (UHUB_VERSION_MINOR 5)
|
||||||
|
set (UHUB_VERSION_PATCH 1)
|
||||||
|
|
||||||
|
set (PROJECT_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src")
|
||||||
|
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/Modules)
|
||||||
|
|
||||||
|
option(RELEASE "Release build, debug build if disabled" ON)
|
||||||
|
option(LOWLEVEL_DEBUG, "Enable low level debug messages." OFF)
|
||||||
|
option(SSL_SUPPORT "Enable SSL support" ON)
|
||||||
|
option(USE_OPENSSL "Use OpenSSL's SSL support" ON )
|
||||||
|
option(SYSTEMD_SUPPORT "Enable systemd notify and journal logging" OFF)
|
||||||
|
option(ADC_STRESS "Enable the stress tester client" OFF)
|
||||||
|
|
||||||
|
find_package(Git)
|
||||||
|
find_package(Sqlite3)
|
||||||
|
|
||||||
|
include(TestBigEndian)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
|
||||||
|
#Some functions need this to be found
|
||||||
|
add_definitions(-D_GNU_SOURCE)
|
||||||
|
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE")
|
||||||
|
|
||||||
|
TEST_BIG_ENDIAN(BIGENDIAN)
|
||||||
|
if (BIGENDIAN)
|
||||||
|
add_definitions(-DARCH_BIGENDIAN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT RELEASE)
|
||||||
|
add_definitions(-DDEBUG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (SSL_SUPPORT)
|
||||||
|
if (USE_OPENSSL)
|
||||||
|
find_package(OpenSSL)
|
||||||
|
else()
|
||||||
|
find_package(GnuTLS)
|
||||||
|
endif()
|
||||||
|
if (NOT GNUTLS_FOUND AND NOT OPENSSL_FOUND)
|
||||||
|
message(FATAL_ERROR "Neither OpenSSL nor GnuTLS were found!")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT SQLITE3_FOUND)
|
||||||
|
message(FATAL_ERROR "SQLite3 is not found!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (SYSTEMD_SUPPORT)
|
||||||
|
INCLUDE(FindPkgConfig)
|
||||||
|
pkg_search_module(SD REQUIRED libsystemd)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_include_file(stdint.h HAVE_STDINT_H)
|
||||||
|
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||||
|
if (HAVE_SYS_TYPES_H)
|
||||||
|
set (CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} "sys/types.h")
|
||||||
|
endif()
|
||||||
|
check_type_size( ssize_t SSIZE_T )
|
||||||
|
check_symbol_exists(memmem string.h HAVE_MEMMEM)
|
||||||
|
check_symbol_exists(strndup string.h HAVE_STRNDUP)
|
||||||
|
|
||||||
|
include_directories("${PROJECT_SOURCE_DIR}")
|
||||||
|
include_directories("${PROJECT_BINARY_DIR}")
|
||||||
|
include_directories(${SQLITE3_INCLUDE_DIRS})
|
||||||
|
link_directories(${SQLITE3_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
file (GLOB uhub_SOURCES ${PROJECT_SOURCE_DIR}/core/*.c)
|
||||||
|
list (REMOVE_ITEM uhub_SOURCES
|
||||||
|
${PROJECT_SOURCE_DIR}/core/gen_config.c
|
||||||
|
${PROJECT_SOURCE_DIR}/core/main.c
|
||||||
|
)
|
||||||
|
|
||||||
|
file (GLOB adc_SOURCES ${PROJECT_SOURCE_DIR}/adc/*.c)
|
||||||
|
file (GLOB network_SOURCES ${PROJECT_SOURCE_DIR}/network/*.c)
|
||||||
|
file (GLOB utils_SOURCES ${PROJECT_SOURCE_DIR}/util/*.c)
|
||||||
|
|
||||||
|
set (adcclient_SOURCES
|
||||||
|
${PROJECT_SOURCE_DIR}/tools/adcclient.c
|
||||||
|
${PROJECT_SOURCE_DIR}/core/ioqueue.c
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(adc STATIC ${adc_SOURCES})
|
||||||
|
add_library(network STATIC ${network_SOURCES})
|
||||||
|
add_library(utils STATIC ${utils_SOURCES})
|
||||||
|
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
set_target_properties(utils PROPERTIES COMPILE_FLAGS -fPIC)
|
||||||
|
set_target_properties(network PROPERTIES COMPILE_FLAGS -fPIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_dependencies(adc utils)
|
||||||
|
add_dependencies(network utils)
|
||||||
|
|
||||||
|
add_executable(uhub ${PROJECT_SOURCE_DIR}/core/main.c ${uhub_SOURCES} )
|
||||||
|
add_executable(autotest-bin ${CMAKE_SOURCE_DIR}/autotest/test.c ${uhub_SOURCES} )
|
||||||
|
add_executable(uhub-passwd ${PROJECT_SOURCE_DIR}/tools/uhub-passwd.c)
|
||||||
|
|
||||||
|
add_library(mod_example MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_example.c)
|
||||||
|
add_library(mod_welcome MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_welcome.c)
|
||||||
|
add_library(mod_logging MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_logging.c ${PROJECT_SOURCE_DIR}/adc/sid.c)
|
||||||
|
add_library(mod_auth_simple MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_simple.c )
|
||||||
|
add_library(mod_chat_history MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history.c )
|
||||||
|
add_library(mod_chat_history_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_history_sqlite.c )
|
||||||
|
add_library(mod_chat_only MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_chat_only.c)
|
||||||
|
add_library(mod_topic MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_topic.c)
|
||||||
|
add_library(mod_no_guest_downloads MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_no_guest_downloads.c)
|
||||||
|
add_library(mod_auth_sqlite MODULE ${PROJECT_SOURCE_DIR}/plugins/mod_auth_sqlite.c)
|
||||||
|
|
||||||
|
set_target_properties(
|
||||||
|
mod_example
|
||||||
|
mod_welcome
|
||||||
|
mod_logging
|
||||||
|
mod_auth_simple
|
||||||
|
mod_auth_sqlite
|
||||||
|
mod_chat_history
|
||||||
|
mod_chat_history_sqlite
|
||||||
|
mod_chat_only
|
||||||
|
mod_no_guest_downloads
|
||||||
|
mod_topic
|
||||||
|
PROPERTIES PREFIX "")
|
||||||
|
|
||||||
|
target_link_libraries(uhub ${CMAKE_DL_LIBS} adc network utils)
|
||||||
|
target_link_libraries(uhub-passwd ${SQLITE3_LIBRARIES} utils)
|
||||||
|
target_link_libraries(autotest-bin ${CMAKE_DL_LIBS} adc network utils)
|
||||||
|
target_link_libraries(mod_example utils)
|
||||||
|
target_link_libraries(mod_welcome network utils)
|
||||||
|
target_link_libraries(mod_auth_simple utils)
|
||||||
|
target_link_libraries(mod_auth_sqlite ${SQLITE3_LIBRARIES} utils)
|
||||||
|
target_link_libraries(mod_chat_history utils)
|
||||||
|
target_link_libraries(mod_chat_history_sqlite ${SQLITE3_LIBRARIES} utils)
|
||||||
|
target_link_libraries(mod_no_guest_downloads utils)
|
||||||
|
target_link_libraries(mod_chat_only utils)
|
||||||
|
target_link_libraries(mod_logging network utils)
|
||||||
|
target_link_libraries(mod_topic utils)
|
||||||
|
target_link_libraries(utils network)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(uhub ws2_32)
|
||||||
|
target_link_libraries(autotest-bin ws2_32)
|
||||||
|
target_link_libraries(mod_logging ws2_32)
|
||||||
|
target_link_libraries(mod_welcome ws2_32)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
add_library(adcclient STATIC ${adcclient_SOURCES})
|
||||||
|
add_executable(uhub-admin ${PROJECT_SOURCE_DIR}/tools/admin.c)
|
||||||
|
target_link_libraries(uhub-admin adcclient adc network utils pthread)
|
||||||
|
target_link_libraries(uhub pthread)
|
||||||
|
target_link_libraries(autotest-bin pthread)
|
||||||
|
|
||||||
|
if (ADC_STRESS)
|
||||||
|
add_executable(adcrush ${PROJECT_SOURCE_DIR}/tools/adcrush.c ${adcclient_SOURCES})
|
||||||
|
target_link_libraries(adcrush adcclient adc network utils pthread)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT UHUB_REVISION AND GIT_FOUND)
|
||||||
|
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --pretty=format:%h
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE UHUB_REVISION_TEMP
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if (UHUB_REVISION_TEMP)
|
||||||
|
set (UHUB_REVISION "git-${UHUB_REVISION_TEMP}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT UHUB_REVISION)
|
||||||
|
set (UHUB_REVISION "release")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set (UHUB_GIT_VERSION "${UHUB_VERSION_MAJOR}.${UHUB_VERSION_MINOR}.${UHUB_VERSION_PATCH}-${UHUB_REVISION}")
|
||||||
|
message (STATUS "Configuring uhub version: ${UHUB_GIT_VERSION}")
|
||||||
|
|
||||||
|
if(OPENSSL_FOUND)
|
||||||
|
set(SSL_LIBS ${OPENSSL_LIBRARIES})
|
||||||
|
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_OPENSSL=1)
|
||||||
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (GNUTLS_FOUND)
|
||||||
|
set(SSL_LIBS ${GNUTLS_LIBRARIES})
|
||||||
|
add_definitions(-DSSL_SUPPORT=1 -DSSL_USE_GNUTLS=1 ${GNUTLS_DEFINITIONS})
|
||||||
|
include_directories(${GNUTLS_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SSL_SUPPORT)
|
||||||
|
target_link_libraries(uhub ${SSL_LIBS})
|
||||||
|
target_link_libraries(autotest-bin ${SSL_LIBS})
|
||||||
|
if(UNIX)
|
||||||
|
target_link_libraries(uhub-admin ${SSL_LIBS})
|
||||||
|
endif()
|
||||||
|
target_link_libraries(mod_welcome ${SSL_LIBS})
|
||||||
|
target_link_libraries(mod_logging ${SSL_LIBS})
|
||||||
|
if (ADC_STRESS)
|
||||||
|
target_link_libraries(adcrush ${SSL_LIBS})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (SYSTEMD_SUPPORT)
|
||||||
|
target_link_libraries(uhub ${SD_LIBRARIES})
|
||||||
|
target_link_libraries(autotest-bin ${SD_LIBRARIES})
|
||||||
|
target_link_libraries(uhub-passwd ${SD_LIBRARIES})
|
||||||
|
target_link_libraries(uhub-admin ${SD_LIBRARIES})
|
||||||
|
include_directories(${SD_INCLUDE_DIRS})
|
||||||
|
add_definitions(-DSYSTEMD)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file ("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h")
|
||||||
|
configure_file ("${PROJECT_SOURCE_DIR}/system.h.in" "${PROJECT_BINARY_DIR}/system.h")
|
||||||
|
|
||||||
|
# mark_as_advanced(FORCE CMAKE_BUILD_TYPE)
|
||||||
|
# if (RELEASE)
|
||||||
|
# set(CMAKE_BUILD_TYPE Release)
|
||||||
|
# add_definitions(-DNDEBUG)
|
||||||
|
#else()
|
||||||
|
# set(CMAKE_BUILD_TYPE Debug)
|
||||||
|
# add_definitions(-DDEBUG)
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
if (LOWLEVEL_DEBUG)
|
||||||
|
add_definitions(-DLOWLEVEL_DEBUG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (UNIX)
|
||||||
|
install( TARGETS uhub uhub-passwd RUNTIME DESTINATION bin )
|
||||||
|
install( TARGETS mod_example mod_welcome mod_logging mod_auth_simple mod_auth_sqlite mod_chat_history mod_chat_history_sqlite mod_chat_only mod_topic mod_no_guest_downloads DESTINATION /usr/lib/uhub/ OPTIONAL )
|
||||||
|
install( FILES ${CMAKE_SOURCE_DIR}/doc/uhub.conf ${CMAKE_SOURCE_DIR}/doc/plugins.conf ${CMAKE_SOURCE_DIR}/doc/rules.txt ${CMAKE_SOURCE_DIR}/doc/motd.txt DESTINATION /etc/uhub OPTIONAL )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
25
COPYING.OpenSSL
Normal file
25
COPYING.OpenSSL
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
OpenSSL License Exception
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2007-2012, Jan Vidar Krey
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License 3 (GPL) as published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
The full text the GPL can be found in the COPYING file.
|
||||||
|
|
||||||
|
In addition this distribution of uhub may be linked against OpenSSL
|
||||||
|
according to the terms described here:
|
||||||
|
|
||||||
|
You have permission to copy, modify, propagate, and distribute a work
|
||||||
|
formed by combining OpenSSL with uhub, or a work derivative of such a
|
||||||
|
combination, even if such copying, modification, propagation, or
|
||||||
|
distribution would otherwise violate the terms of the GPL. You must
|
||||||
|
comply with the GPL in all respects for all of the code used other than
|
||||||
|
OpenSSL.
|
||||||
|
|
||||||
|
You may include this OpenSSL exception and its grant of permissions when
|
||||||
|
you distribute uhub. Inclusion of this notice with such a distribution
|
||||||
|
constitutes a grant of such permission. If you do not wish to grant these
|
||||||
|
permissions, delete this file.
|
||||||
|
|
95
ChangeLog
95
ChangeLog
@ -1,3 +1,98 @@
|
|||||||
|
0.5.0:
|
||||||
|
- Use TLS 1.2 and strong ciphers by default, but made this configurable.
|
||||||
|
- Fix TLS event handling which caused some busy loops
|
||||||
|
- TLS: Support certificate chains
|
||||||
|
- Fix bug #211: Better Hublist pinger support by adding the AP flag of the INF message.
|
||||||
|
- Fix bug #198: Timers could cause infinite loops
|
||||||
|
- Sqlite3 is now mandatory
|
||||||
|
- Added mod_chat_history_sqlite and mod_chat_is_privileged.
|
||||||
|
- Support for systemd notify and journal logging
|
||||||
|
- Improved flood control counting to strictly not allow more than the given amount of messages in the configured interval.
|
||||||
|
- Optimize lookups by CID and nick.
|
||||||
|
- Added an NMDC and ADC hub redirectors written in Python.
|
||||||
|
- Fix all Clang compile warnings.
|
||||||
|
- Install uhub-passwd also.
|
||||||
|
- Add support for detecting HTTP connections to the hub. Enough to tell browsers to stop calling.
|
||||||
|
- Compile fixes for OpenBSD, including warnings about strcat.
|
||||||
|
- Fix crashing autotest due to wrong initialization of the usermanager.
|
||||||
|
- mod_topic: check argument for NULL
|
||||||
|
- rename !cleartopic to !resettopic
|
||||||
|
|
||||||
|
0.4.1:
|
||||||
|
- Converted to CMake which replaces Visual Studio project files and GNU makefiles
|
||||||
|
- Fix issues with SSL causing excessive CPU usage.
|
||||||
|
- Fix TLS/SSL handshake detection issues
|
||||||
|
- Fixed crash in mod_chat_only.
|
||||||
|
- Implemented red-black tree for better performance for certain lookups.
|
||||||
|
- Better network statistics using the !stats command.
|
||||||
|
- Improved protocol parsing, especially escape handling.
|
||||||
|
- Fix cbuffer initialization.
|
||||||
|
- Install plugins in /usr/lib/uhub, not /var/lib/uhub.
|
||||||
|
- Improved init scripts and added a upstart script.
|
||||||
|
- Work-around client security bugs by disallowing UCMD messages from being relayed.
|
||||||
|
- Added asynchronous DNS resolver.
|
||||||
|
|
||||||
|
|
||||||
|
0.4.0:
|
||||||
|
- Cleaned up code generator for config file parsing.
|
||||||
|
- Merge pull request #5 from yorhel/master
|
||||||
|
- Print error message in case of shutting down due to errors loading plugins.
|
||||||
|
- Fix Windows file read discrepancy.
|
||||||
|
- convert_to_sqlite.pl: Update to the latest SQL schema + be more Perlish
|
||||||
|
- Fix VS2010 project file - missing .c file.
|
||||||
|
- Merge https://github.com/Tilka/uhub
|
||||||
|
- use "I64u" instead of PRIu64 on Windows
|
||||||
|
- remove obsolete settings in uhub.conf
|
||||||
|
- fix uhub_itoa() and uhub_ulltoa()
|
||||||
|
- marked plugin callbacks that are not called yet
|
||||||
|
- add on_change_nick() to struct plugin_funcs
|
||||||
|
- minimal changes
|
||||||
|
- Updated init script in Debian package.
|
||||||
|
- Updated list of man pages in Debian package.
|
||||||
|
- Added man page for uhub-passwd.
|
||||||
|
- Merge branch 'master' of https://github.com/Tilka/uhub
|
||||||
|
- Fix issue with QUI messages being allowed through the hub
|
||||||
|
- don't show error on SIGTERM in select() backend
|
||||||
|
- fix dependency of 'install' target
|
||||||
|
- changed all calls to assert() to uhub_assert()
|
||||||
|
- Don't strip the U4/U6 port numbers if updated after login.
|
||||||
|
- Fix compile issue with double typedefs.
|
||||||
|
- Remove list assertion when removing element that is not in the list. Breaks autotest.
|
||||||
|
- Cleaned up command handling code, by splitting into multiple files.
|
||||||
|
- Fix bug #183 - Added proper OpenSSL license exception for the GPL.
|
||||||
|
- OMG OPTIMIZED
|
||||||
|
- use dh_prep instead of dh_clean -k
|
||||||
|
- fix double free
|
||||||
|
- use "0" instead of "false"
|
||||||
|
- fix use of uninitialized struct ip_range
|
||||||
|
- fix random crashes upon !reload
|
||||||
|
- fix command syntax
|
||||||
|
- use arg parser in !broadcast
|
||||||
|
- Fixed tiny memory leak on reload/shutdown.
|
||||||
|
- Merge https://github.com/Tilka/uhub
|
||||||
|
- fix multiple optional arguments
|
||||||
|
- small cleanup
|
||||||
|
- also clean uhub-passwd
|
||||||
|
- ignore files generated by dpkg-buildpackage
|
||||||
|
- automatically clean up plugin commands
|
||||||
|
- minimal documentation fixes
|
||||||
|
- update client software link
|
||||||
|
- update compile howto link
|
||||||
|
- fix Debian changelog
|
||||||
|
- Fix bug #158 - Added plugin for setting topic (hub description).
|
||||||
|
- Command arguments handling + cleanups
|
||||||
|
|
||||||
|
|
||||||
|
0.3.2:
|
||||||
|
- Fixed bugs in the kqueue network backend (OSX/BSD)
|
||||||
|
- Rewrote the configuration backend code.
|
||||||
|
- Added support for escaping characters in the configuration files.
|
||||||
|
- Updated the !broadcast command to send private messages instead of main chat messages.
|
||||||
|
- Adding support for redirecting clients to other hubs when they fail to log in.
|
||||||
|
- Fix some out of memory related crashes.
|
||||||
|
- Fixed minor memory leaks.
|
||||||
|
|
||||||
|
|
||||||
0.3.1:
|
0.3.1:
|
||||||
- Fixed bug where !getip did not work.
|
- Fixed bug where !getip did not work.
|
||||||
- Added flood control configuration options.
|
- Added flood control configuration options.
|
||||||
|
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM alpine:latest as builder
|
||||||
|
RUN apk update && apk upgrade && apk add --no-cache bash util-linux cmake make gcc git sqlite-dev openssl-dev git build-base
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN cmake . && make
|
||||||
|
RUN sed -i 's/\/usr\/lib\/uhub\//\/libs\//g' ./doc/*.conf && \
|
||||||
|
sed -i 's/\/usr\/lib\/uhub\//\/libs\//g' ./doc/rules.txt && \
|
||||||
|
sed -i 's/\/etc\/uhub\//\/conf\//g' ./doc/*.conf && \
|
||||||
|
sed -i 's/\/etc\/uhub\//\/conf\//g' ./doc/rules.txt && \
|
||||||
|
echo 'Welcome to uHub' > ./doc/motd.txt
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN apk update && apk upgrade && apk add --no-cache bash util-linux openssl-dev sqlite-dev
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/uhub .
|
||||||
|
COPY --from=builder /app/doc/plugins.conf /app/doc/uhub.conf /app/doc/users.conf /app/doc/rules.txt /app/doc/motd.txt /conf/
|
||||||
|
COPY --from=builder /app/*.so /libs/
|
||||||
|
ENTRYPOINT ["./uhub"]
|
||||||
|
CMD ["-c","/conf/uhub.conf"]
|
289
GNUmakefile
289
GNUmakefile
@ -1,289 +0,0 @@
|
|||||||
##
|
|
||||||
## Makefile for uhub (Use GNU make)
|
|
||||||
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
|
||||||
#
|
|
||||||
|
|
||||||
-include Makefile.private
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
LD := $(CC)
|
|
||||||
MV := mv
|
|
||||||
RANLIB := ranlib
|
|
||||||
CFLAGS += -pipe -Wall
|
|
||||||
USE_SSL ?= NO
|
|
||||||
USE_BIGENDIAN ?= AUTO
|
|
||||||
USE_PLUGINS ?= YES
|
|
||||||
BITS ?= AUTO
|
|
||||||
SILENT ?= YES
|
|
||||||
TERSE ?= NO
|
|
||||||
STACK_PROTECT ?= NO
|
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
|
||||||
WINDOWS ?= YES
|
|
||||||
OPSYS ?= Windows
|
|
||||||
else
|
|
||||||
OPSYS ?= $(shell uname)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OPSYS),SunOS)
|
|
||||||
LDLIBS += -lsocket -lnsl
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OPSYS),Haiku)
|
|
||||||
LDLIBS += -lnetwork
|
|
||||||
endif
|
|
||||||
|
|
||||||
CFLAGS += -I./src/
|
|
||||||
|
|
||||||
ifeq ($(OPSYS),Windows)
|
|
||||||
USE_BIGENDIAN := NO
|
|
||||||
LDLIBS += -lws2_32
|
|
||||||
UHUB_CONF_DIR ?= c:/uhub/
|
|
||||||
UHUB_PREFIX ?= c:/uhub/
|
|
||||||
CFLAGS += -mno-cygwin
|
|
||||||
LDFLAGS += -mno-cygwin
|
|
||||||
BIN_EXT ?= .exe
|
|
||||||
USE_PLUGINS := NO
|
|
||||||
else
|
|
||||||
DESTDIR ?= /
|
|
||||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
|
||||||
UHUB_PREFIX ?= $(DESTDIR)/usr/local
|
|
||||||
CFLAGS += -I/usr/local/include
|
|
||||||
LDFLAGS += -L/usr/local/lib
|
|
||||||
BIN_EXT ?=
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(SILENT),YES)
|
|
||||||
MSG_CC=@echo " CC:" $(notdir $<) &&
|
|
||||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
|
||||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
|
||||||
else
|
|
||||||
MSG_CC=
|
|
||||||
MSG_LD=
|
|
||||||
MSG_AR=
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(TERSE), YES)
|
|
||||||
MSG_CC=@
|
|
||||||
MSG_LD=@
|
|
||||||
MSG_AR=@
|
|
||||||
MSG_CLEAN=-n ""
|
|
||||||
else
|
|
||||||
MSG_CLEAN="Clean as a whistle"
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(RELEASE),YES)
|
|
||||||
CFLAGS += -O3 -DNDEBUG
|
|
||||||
else
|
|
||||||
CFLAGS += -ggdb -DDEBUG
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(STACK_PROTECT),YES)
|
|
||||||
CFLAGS += -fstack-protector-all
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(PROFILING),YES)
|
|
||||||
CFLAGS += -pg
|
|
||||||
LDFLAGS += -pg
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(FUNCTRACE),YES)
|
|
||||||
CFLAGS += -finstrument-functions
|
|
||||||
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(BITS), AUTO)
|
|
||||||
ifeq ($(BITS), 64)
|
|
||||||
CFLAGS += -m64
|
|
||||||
LDFLAGS += -m64
|
|
||||||
else
|
|
||||||
ifeq ($(BITS), 32)
|
|
||||||
CFLAGS += -m32
|
|
||||||
LDFLAGS += -m32
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(USE_BIGENDIAN),AUTO)
|
|
||||||
ifeq ($(shell perl -e 'print pack("L", 0x554E4958)'),UNIX)
|
|
||||||
CFLAGS += -DARCH_BIGENDIAN
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
ifeq ($(USE_BIGENDIAN),YES)
|
|
||||||
CFLAGS += -DARCH_BIGENDIAN
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(USE_SSL),YES)
|
|
||||||
CFLAGS += -DSSL_SUPPORT
|
|
||||||
LDLIBS += -lssl
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(USE_PLUGINS),YES)
|
|
||||||
CFLAGS += -DPLUGIN_SUPPORT
|
|
||||||
LDLIBS += -ldl
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
|
|
||||||
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
|
||||||
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
libuhub_SOURCES := \
|
|
||||||
src/core/auth.c \
|
|
||||||
src/core/commands.c \
|
|
||||||
src/core/config.c \
|
|
||||||
src/core/eventqueue.c \
|
|
||||||
src/core/floodctl.c \
|
|
||||||
src/core/hub.c \
|
|
||||||
src/core/hubevent.c \
|
|
||||||
src/core/hubio.c \
|
|
||||||
src/core/inf.c \
|
|
||||||
src/core/netevent.c \
|
|
||||||
src/core/probe.c \
|
|
||||||
src/core/route.c \
|
|
||||||
src/core/user.c \
|
|
||||||
src/core/usermanager.c \
|
|
||||||
src/core/plugininvoke.c \
|
|
||||||
src/core/pluginloader.c \
|
|
||||||
src/network/backend.c \
|
|
||||||
src/network/connection.c \
|
|
||||||
src/network/epoll.c \
|
|
||||||
src/network/kqueue.c \
|
|
||||||
src/network/network.c \
|
|
||||||
src/network/select.c \
|
|
||||||
src/network/timeout.c \
|
|
||||||
src/network/timer.c \
|
|
||||||
src/util/ipcalc.c \
|
|
||||||
src/util/list.c \
|
|
||||||
src/util/log.c \
|
|
||||||
src/util/memory.c \
|
|
||||||
src/util/misc.c \
|
|
||||||
src/util/rbtree.c \
|
|
||||||
src/util/tiger.c
|
|
||||||
|
|
||||||
libadc_common_SOURCES := \
|
|
||||||
src/adc/message.c \
|
|
||||||
src/adc/sid.c
|
|
||||||
|
|
||||||
libadc_client_SOURCES := \
|
|
||||||
src/tools/adcclient.c
|
|
||||||
|
|
||||||
uhub_SOURCES := src/core/main.c
|
|
||||||
|
|
||||||
adcrush_SOURCES := src/tools/adcrush.c
|
|
||||||
|
|
||||||
admin_SOURCES := src/tools/admin.c
|
|
||||||
|
|
||||||
autotest_SOURCES := \
|
|
||||||
autotest/test_eventqueue.tcc \
|
|
||||||
autotest/test_hub.tcc \
|
|
||||||
autotest/test_inf.tcc \
|
|
||||||
autotest/test_ipfilter.tcc \
|
|
||||||
autotest/test_list.tcc \
|
|
||||||
autotest/test_memory.tcc \
|
|
||||||
autotest/test_message.tcc \
|
|
||||||
autotest/test_misc.tcc \
|
|
||||||
autotest/test_sid.tcc \
|
|
||||||
autotest/test_tiger.tcc \
|
|
||||||
autotest/test_timer.tcc \
|
|
||||||
autotest/test_usermanager.tcc
|
|
||||||
|
|
||||||
autotest_OBJECTS = autotest.o
|
|
||||||
|
|
||||||
plugin_example_SOURCES := src/plugins/mod_example.c
|
|
||||||
plugin_example_TARGET := $(plugin_example_SOURCES:.c=.so)
|
|
||||||
|
|
||||||
plugin_logging_SOURCES := src/plugins/mod_logging.c
|
|
||||||
plugin_logging_TARGET := $(plugin_example_SOURCES:.c=.so)
|
|
||||||
|
|
||||||
|
|
||||||
# Source to objects
|
|
||||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
|
||||||
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
|
||||||
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
|
|
||||||
|
|
||||||
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
|
||||||
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
|
||||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
|
||||||
|
|
||||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
|
||||||
all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET)
|
|
||||||
|
|
||||||
uhub_BINARY=uhub$(BIN_EXT)
|
|
||||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
|
||||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
|
||||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
|
||||||
|
|
||||||
ifeq ($(USE_PLUGINS),YES)
|
|
||||||
all_OBJECTS += $(plugins)
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: revision.h.tmp
|
|
||||||
|
|
||||||
%.so: %.c
|
|
||||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $< $(CFLAGS)
|
|
||||||
|
|
||||||
%.o: %.c version.h revision.h
|
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
|
||||||
|
|
||||||
all: $(uhub_BINARY)
|
|
||||||
|
|
||||||
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
|
||||||
|
|
||||||
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
|
||||||
|
|
||||||
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
|
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
|
||||||
|
|
||||||
autotest.c: $(autotest_SOURCES)
|
|
||||||
$(shell exotic --standalone $(autotest_SOURCES) > $@)
|
|
||||||
|
|
||||||
revision.h.tmp:
|
|
||||||
@rm -f $@
|
|
||||||
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
|
|
||||||
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
|
|
||||||
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
|
|
||||||
|
|
||||||
version.h: revision.h
|
|
||||||
|
|
||||||
revision.h: revision.h.tmp
|
|
||||||
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
|
|
||||||
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
|
|
||||||
|
|
||||||
$(autotest_OBJECTS): autotest.c
|
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
|
||||||
|
|
||||||
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
|
||||||
|
|
||||||
autotest: $(autotest_BINARY)
|
|
||||||
@./$(autotest_BINARY) -s -f
|
|
||||||
|
|
||||||
ifeq ($(WINDOWS),YES)
|
|
||||||
install:
|
|
||||||
@echo "Cannot install automatically on windows."
|
|
||||||
else
|
|
||||||
install: $(uhub_BINARY)
|
|
||||||
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
|
|
||||||
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
|
|
||||||
@if [ ! -d $(UHUB_CONF_DIR) ]; then echo Creating $(UHUB_CONF_DIR); mkdir -p $(UHUB_CONF_DIR); fi
|
|
||||||
@if [ ! -f $(UHUB_CONF_DIR)/uhub.conf ]; then cp doc/uhub.conf $(UHUB_CONF_DIR); fi
|
|
||||||
@if [ ! -f $(UHUB_CONF_DIR)/users.conf ]; then cp doc/users.conf $(UHUB_CONF_DIR); fi
|
|
||||||
@touch $(UHUB_CONF_DIR)/motd.txt
|
|
||||||
@echo done.
|
|
||||||
endif
|
|
||||||
|
|
||||||
dist-clean:
|
|
||||||
@rm -rf $(all_OBJECTS) *~ core
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c revision.h revision.h.tmp && \
|
|
||||||
echo $(MSG_CLEAN)
|
|
||||||
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
|||||||
|
# uhub
|
||||||
|
|
||||||
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
||||||
|
|
||||||
For the official documentation, bugs and other information, please visit:
|
For the official documentation, bugs and other information, please visit:
|
||||||
http://www.uhub.org/
|
https://www.uhub.org/
|
||||||
|
|
||||||
For a list of compatible ADC clients, see:
|
For a list of compatible ADC clients, see:
|
||||||
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software
|
https://en.wikipedia.org/wiki/Comparison_of_ADC_software#Client_software
|
||||||
|
|
||||||
|
# on dockerhub
|
||||||
|
|
||||||
|
* https://hub.docker.com/r/sneak/uhub
|
@ -78,7 +78,7 @@ Description: a high performance hub for the ADC peer-to-peer network
|
|||||||
Its low memory footprint allows it to handle several thousand users
|
Its low memory footprint allows it to handle several thousand users
|
||||||
on high-end servers, or a small private hub on embedded hardware.
|
on high-end servers, or a small private hub on embedded hardware.
|
||||||
.
|
.
|
||||||
Homepage: http://www.extatic.org/uhub/
|
Homepage: https://www.uhub.org/
|
||||||
EOF
|
EOF
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
372
autotest/exotic
Executable file
372
autotest/exotic
Executable 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");
|
||||||
|
}
|
||||||
|
'; }
|
||||||
|
|
1070
autotest/test.c
Normal file
1070
autotest/test.c
Normal file
File diff suppressed because it is too large
Load Diff
251
autotest/test_commands.tcc
Normal file
251
autotest/test_commands.tcc
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
static struct hub_info* hub = NULL;
|
||||||
|
static struct hub_command* cmd = NULL;
|
||||||
|
static struct hub_user user;
|
||||||
|
static struct command_base* cbase = NULL;
|
||||||
|
static struct command_handle* c_test1 = NULL;
|
||||||
|
static struct command_handle* c_test2 = NULL;
|
||||||
|
static struct command_handle* c_test3 = NULL;
|
||||||
|
static struct command_handle* c_test4 = NULL;
|
||||||
|
static struct command_handle* c_test5 = NULL;
|
||||||
|
static struct command_handle* c_test6 = NULL;
|
||||||
|
static struct command_handle* c_test7 = NULL;
|
||||||
|
|
||||||
|
// for results:
|
||||||
|
static int result = 0;
|
||||||
|
|
||||||
|
EXO_TEST(setup, {
|
||||||
|
hub = hub_malloc_zero(sizeof(struct hub_info));
|
||||||
|
cbase = command_initialize(hub);
|
||||||
|
hub->commands = cbase;
|
||||||
|
hub->users = uman_init();
|
||||||
|
return cbase && hub && hub->users;
|
||||||
|
});
|
||||||
|
|
||||||
|
static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
|
||||||
|
{
|
||||||
|
printf("test_handler\n");
|
||||||
|
result = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct command_handle* create_handler(const char* prefix, const char* args, enum auth_credentials cred)
|
||||||
|
{
|
||||||
|
struct command_handle* c = hub_malloc_zero(sizeof(struct command_handle));
|
||||||
|
c->prefix = prefix;
|
||||||
|
c->length = strlen(prefix);
|
||||||
|
c->args = args;
|
||||||
|
c->cred = cred;
|
||||||
|
c->handler = test_handler;
|
||||||
|
c->description = "A handler added by autotest.";
|
||||||
|
c->origin = "exotic test";
|
||||||
|
c->ptr = &c->ptr;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXO_TEST(command_setup_user, {
|
||||||
|
memset(&user, 0, sizeof(user));
|
||||||
|
user.id.sid = 1;
|
||||||
|
strcpy(user.id.nick, "tester");
|
||||||
|
strcpy(user.id.cid, "3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
||||||
|
user.credentials = auth_cred_guest;
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
#define ADD_TEST(var, prefix, args, cred) \
|
||||||
|
var = create_handler(prefix, args, cred); \
|
||||||
|
if (!command_add(cbase, var, NULL)) \
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#define DEL_TEST(var) \
|
||||||
|
if (var) \
|
||||||
|
{ \
|
||||||
|
if (!command_del(cbase, var)) \
|
||||||
|
return 0; \
|
||||||
|
hub_free(var); \
|
||||||
|
var = NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
EXO_TEST(command_create, {
|
||||||
|
ADD_TEST(c_test1, "test1", "", auth_cred_guest);
|
||||||
|
ADD_TEST(c_test2, "test2", "", auth_cred_operator);
|
||||||
|
ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest);
|
||||||
|
ADD_TEST(c_test4, "test4", "u", auth_cred_guest);
|
||||||
|
ADD_TEST(c_test5, "test5", "i", auth_cred_guest);
|
||||||
|
ADD_TEST(c_test6, "test6", "?c", auth_cred_guest);
|
||||||
|
ADD_TEST(c_test6, "test7", "C", auth_cred_guest);
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
extern void command_destroy(struct hub_command* cmd);
|
||||||
|
|
||||||
|
static int verify(const char* str, enum command_parse_status expected)
|
||||||
|
{
|
||||||
|
struct hub_command* cmd = command_parse(cbase, hub, &user, str);
|
||||||
|
enum command_parse_status status = cmd->status;
|
||||||
|
command_free(cmd);
|
||||||
|
return status == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hub_command_arg_data* verify_argument(struct hub_command* cmd, enum hub_command_arg_type type)
|
||||||
|
{
|
||||||
|
return hub_command_arg_next(cmd, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_arg_integer(struct hub_command* cmd, int expected)
|
||||||
|
{
|
||||||
|
struct hub_command_arg_data* data = verify_argument(cmd, type_integer);
|
||||||
|
return data->data.integer == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_arg_user(struct hub_command* cmd, struct hub_user* expected)
|
||||||
|
{
|
||||||
|
struct hub_command_arg_data* data = verify_argument(cmd, type_user);
|
||||||
|
return data->data.user == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_arg_cred(struct hub_command* cmd, enum auth_credentials cred)
|
||||||
|
{
|
||||||
|
struct hub_command_arg_data* data = verify_argument(cmd, type_credentials);
|
||||||
|
return data->data.credentials == cred;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); });
|
||||||
|
EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); });
|
||||||
|
|
||||||
|
EXO_TEST(command_syntax_1, { return verify("", cmd_status_syntax_error); });
|
||||||
|
EXO_TEST(command_syntax_2, { return verify("!", cmd_status_syntax_error); });
|
||||||
|
|
||||||
|
EXO_TEST(command_missing_args_1, { return verify("!test3", cmd_status_missing_args); });
|
||||||
|
EXO_TEST(command_missing_args_2, { return verify("!test3 12345", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_missing_args_3, { return verify("!test3 1 2 345", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_number_1, { return verify("!test3 abc", cmd_status_arg_number); });
|
||||||
|
EXO_TEST(command_number_2, { return verify("!test3 -", cmd_status_arg_number); });
|
||||||
|
EXO_TEST(command_number_3, { return verify("!test3 -12", cmd_status_ok); });
|
||||||
|
|
||||||
|
EXO_TEST(command_user_1, { return verify("!test4 tester", cmd_status_arg_nick); });
|
||||||
|
EXO_TEST(command_user_2, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_arg_cid); });
|
||||||
|
EXO_TEST(command_user_3, { return uman_add(hub->users, &user) == 0; });
|
||||||
|
EXO_TEST(command_user_4, { return verify("!test4 tester", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_user_5, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_ok); });
|
||||||
|
|
||||||
|
EXO_TEST(command_command_1, { return verify("!test6 test1", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_command_2, { return verify("!test6 test2", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_command_3, { return verify("!test6 test3", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_command_4, { return verify("!test6 test4", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_command_5, { return verify("!test6 test5", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_command_6, { return verify("!test6 test6", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_command_7, { return verify("!test6 fail", cmd_status_arg_command); });
|
||||||
|
EXO_TEST(command_command_8, { return verify("!test6", cmd_status_ok); });
|
||||||
|
|
||||||
|
EXO_TEST(command_cred_1, { return verify("!test7 guest", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_cred_2, { return verify("!test7 user", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_cred_3, { return verify("!test7 operator", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_cred_4, { return verify("!test7 super", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_cred_5, { return verify("!test7 admin", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_cred_6, { return verify("!test7 nobody", cmd_status_arg_cred); });
|
||||||
|
EXO_TEST(command_cred_7, { return verify("!test7 bot", cmd_status_ok); });
|
||||||
|
EXO_TEST(command_cred_8, { return verify("!test7 link", cmd_status_ok); });
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// command not found
|
||||||
|
EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
|
||||||
|
|
||||||
|
// built-in command
|
||||||
|
EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); });
|
||||||
|
|
||||||
|
|
||||||
|
#define SETUP_COMMAND(string) \
|
||||||
|
do { \
|
||||||
|
if (cmd) command_free(cmd); \
|
||||||
|
cmd = command_parse(cbase, hub, &user, string); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_integer_1, {
|
||||||
|
SETUP_COMMAND("!test3");
|
||||||
|
return verify_argument(cmd, type_integer) == NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_integer_2, {
|
||||||
|
SETUP_COMMAND("!test3 10 42");
|
||||||
|
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_integer_3, {
|
||||||
|
SETUP_COMMAND("!test3 10 42 6784");
|
||||||
|
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_user_1, {
|
||||||
|
SETUP_COMMAND("!test4 tester");
|
||||||
|
return verify_arg_user(cmd, &user) ;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cid_1, {
|
||||||
|
SETUP_COMMAND("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
||||||
|
return verify_arg_user(cmd, &user) ;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cred_1, {
|
||||||
|
SETUP_COMMAND("!test7 admin");
|
||||||
|
return verify_arg_cred(cmd, auth_cred_admin);;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cred_2, {
|
||||||
|
SETUP_COMMAND("!test7 op");
|
||||||
|
return verify_arg_cred(cmd, auth_cred_operator);;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cred_3, {
|
||||||
|
SETUP_COMMAND("!test7 operator");
|
||||||
|
return verify_arg_cred(cmd, auth_cred_operator);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cred_4, {
|
||||||
|
SETUP_COMMAND("!test7 super");
|
||||||
|
return verify_arg_cred(cmd, auth_cred_super);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cred_5, {
|
||||||
|
SETUP_COMMAND("!test7 guest");
|
||||||
|
return verify_arg_cred(cmd, auth_cred_guest);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(command_argument_cred_6, {
|
||||||
|
SETUP_COMMAND("!test7 user");
|
||||||
|
return verify_arg_cred(cmd, auth_cred_user);
|
||||||
|
});
|
||||||
|
|
||||||
|
#undef SETUP_COMMAND
|
||||||
|
|
||||||
|
EXO_TEST(command_user_destroy, { return uman_remove(hub->users, &user) == 0; });
|
||||||
|
|
||||||
|
EXO_TEST(command_destroy, {
|
||||||
|
|
||||||
|
command_free(cmd);
|
||||||
|
cmd = NULL;
|
||||||
|
|
||||||
|
DEL_TEST(c_test1);
|
||||||
|
DEL_TEST(c_test2);
|
||||||
|
DEL_TEST(c_test3);
|
||||||
|
DEL_TEST(c_test4);
|
||||||
|
DEL_TEST(c_test5);
|
||||||
|
DEL_TEST(c_test6);
|
||||||
|
DEL_TEST(c_test7);
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(cleanup, {
|
||||||
|
uman_shutdown(hub->users);
|
||||||
|
command_shutdown(hub->commands);
|
||||||
|
hub_free(hub);
|
||||||
|
return 1;
|
||||||
|
});
|
24
autotest/test_credentials.tcc
Normal file
24
autotest/test_credentials.tcc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
EXO_TEST(cred_to_string_1, { return !strcmp(auth_cred_to_string(auth_cred_none), "none"); });
|
||||||
|
EXO_TEST(cred_to_string_2, { return !strcmp(auth_cred_to_string(auth_cred_bot), "bot"); });
|
||||||
|
EXO_TEST(cred_to_string_3, { return !strcmp(auth_cred_to_string(auth_cred_guest), "guest"); });
|
||||||
|
EXO_TEST(cred_to_string_4, { return !strcmp(auth_cred_to_string(auth_cred_user), "user"); });
|
||||||
|
EXO_TEST(cred_to_string_5, { return !strcmp(auth_cred_to_string(auth_cred_operator), "operator"); });
|
||||||
|
EXO_TEST(cred_to_string_6, { return !strcmp(auth_cred_to_string(auth_cred_super), "super"); });
|
||||||
|
EXO_TEST(cred_to_string_7, { return !strcmp(auth_cred_to_string(auth_cred_link), "link"); });
|
||||||
|
EXO_TEST(cred_to_string_8, { return !strcmp(auth_cred_to_string(auth_cred_admin), "admin"); });
|
||||||
|
|
||||||
|
#define CRED_FROM_STRING(STR, EXPECT) enum auth_credentials cred; return auth_string_to_cred(STR, &cred) && cred == EXPECT;
|
||||||
|
|
||||||
|
EXO_TEST(cred_from_string_1, { CRED_FROM_STRING("none", auth_cred_none); });
|
||||||
|
EXO_TEST(cred_from_string_2, { CRED_FROM_STRING("bot", auth_cred_bot); });
|
||||||
|
EXO_TEST(cred_from_string_3, { CRED_FROM_STRING("guest", auth_cred_guest); });
|
||||||
|
EXO_TEST(cred_from_string_4, { CRED_FROM_STRING("user", auth_cred_user); });
|
||||||
|
EXO_TEST(cred_from_string_5, { CRED_FROM_STRING("reg", auth_cred_user); });
|
||||||
|
EXO_TEST(cred_from_string_6, { CRED_FROM_STRING("operator", auth_cred_operator); });
|
||||||
|
EXO_TEST(cred_from_string_7, { CRED_FROM_STRING("op", auth_cred_operator); });
|
||||||
|
EXO_TEST(cred_from_string_8, { CRED_FROM_STRING("super", auth_cred_super); });
|
||||||
|
EXO_TEST(cred_from_string_9, { CRED_FROM_STRING("link", auth_cred_link); });
|
||||||
|
EXO_TEST(cred_from_string_10, { CRED_FROM_STRING("admin", auth_cred_admin); });
|
||||||
|
|
@ -12,11 +12,10 @@ extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, st
|
|||||||
|
|
||||||
static void inf_create_hub()
|
static void inf_create_hub()
|
||||||
{
|
{
|
||||||
|
net_initialize();
|
||||||
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
|
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
|
||||||
inf_hub->users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
|
|
||||||
inf_hub->users->list = list_create();
|
|
||||||
inf_hub->users->sids = sid_pool_create(500);
|
|
||||||
|
|
||||||
|
inf_hub->users = uman_init();
|
||||||
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
|
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
|
||||||
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
|
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
|
||||||
|
|
||||||
@ -26,15 +25,13 @@ static void inf_create_hub()
|
|||||||
|
|
||||||
static void inf_destroy_hub()
|
static void inf_destroy_hub()
|
||||||
{
|
{
|
||||||
/* FIXME */
|
uman_shutdown(inf_hub->users);
|
||||||
list_destroy(inf_hub->users->list);
|
|
||||||
sid_pool_destroy(inf_hub->users->sids);
|
|
||||||
acl_shutdown(inf_hub->acl);
|
acl_shutdown(inf_hub->acl);
|
||||||
free_config(inf_hub->config);
|
free_config(inf_hub->config);
|
||||||
hub_free(inf_hub->users);
|
|
||||||
hub_free(inf_hub->acl);
|
hub_free(inf_hub->acl);
|
||||||
hub_free(inf_hub->config);
|
hub_free(inf_hub->config);
|
||||||
hub_free(inf_hub);
|
hub_free(inf_hub);
|
||||||
|
net_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,13 +60,14 @@ EXO_TEST(inf_create_setup,
|
|||||||
|
|
||||||
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
|
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
|
||||||
#define CHECK_INF(MSG, EXPECT) \
|
#define CHECK_INF(MSG, EXPECT) \
|
||||||
|
do { \
|
||||||
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
|
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
|
||||||
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
|
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
|
||||||
adc_msg_free(msg); \
|
adc_msg_free(msg); \
|
||||||
if (ok == EXPECT) \
|
if (ok == EXPECT) \
|
||||||
user_set_info(inf_user, 0); \
|
user_set_info(inf_user, 0); \
|
||||||
return ok == EXPECT;
|
return ok == EXPECT; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
|
EXO_TEST(inf_ok_1, { CHECK_INF("BINF AAAB NIFriend IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", 0); });
|
||||||
|
|
||||||
@ -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_09, { CHECK_INF("BINF AAAB NIabc NIdef IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n", status_msg_inf_error_nick_multiple); });
|
||||||
EXO_TEST(inf_nick_10, {
|
EXO_TEST(inf_nick_10, {
|
||||||
const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n";
|
const char* line = "BINF AAAB IDGNSSMURMD7K466NGZIHU65TP3S3UZSQ6MN5B2RI PD3A4545WFVGZLSGUXZLG7OS6ULQUVG3HM2T63I7Y\n";
|
||||||
|
int ok;
|
||||||
char nick[10];
|
char nick[10];
|
||||||
|
struct adc_message* msg;
|
||||||
|
|
||||||
nick[0] = 0xf7; nick[1] = 0x80; nick[2] = 0x7f; nick[3] = 0x81; nick[4] = 0x98; nick[5] = 0x00;
|
nick[0] = 0xf7; nick[1] = 0x80; nick[2] = 0x7f; nick[3] = 0x81; nick[4] = 0x98; nick[5] = 0x00;
|
||||||
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);
|
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);
|
adc_msg_free(msg);
|
||||||
if (ok != status_msg_inf_error_nick_not_utf8)
|
if (ok != status_msg_inf_error_nick_not_utf8)
|
||||||
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);
|
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);
|
||||||
|
@ -429,44 +429,51 @@ EXO_TEST(check_ban_ipv4_5, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_1, {
|
EXO_TEST(check_ban_ipv6_1, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return ip_in_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_2, {
|
EXO_TEST(check_ban_ipv6_2, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return ip_in_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_3, {
|
EXO_TEST(check_ban_ipv6_3, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return ip_in_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_4, {
|
EXO_TEST(check_ban_ipv6_4, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return ip_in_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_5, {
|
EXO_TEST(check_ban_ipv6_5, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return !ip_in_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_ipv6_6, {
|
EXO_TEST(check_ban_ipv6_6, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return !ip_in_range(&addr, &ban6);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(check_ban_afmix_1, {
|
EXO_TEST(check_ban_afmix_1, {
|
||||||
|
struct ip_addr_encap addr;
|
||||||
if (!ipv6) return 1;
|
if (!ipv6) return 1;
|
||||||
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);
|
return !ip_in_range(&addr, &ban4);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -610,8 +617,10 @@ EXO_TEST(ip_range_3, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(ip_range_4, {
|
EXO_TEST(ip_range_4, {
|
||||||
struct ip_range range1; memset(&range1, 0, sizeof(range1));
|
struct ip_range range1;
|
||||||
struct ip_range range2; memset(&range2, 0, sizeof(range2));
|
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;
|
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;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
#include <uhub.h>
|
#include <uhub.h>
|
||||||
|
|
||||||
static struct linked_list* list = NULL;
|
static struct linked_list* list = NULL;
|
||||||
|
static struct linked_list* list2 = NULL;
|
||||||
|
|
||||||
static char A[2] = { 'A', 0 };
|
static char A[2] = { 'A', 0 };
|
||||||
static char B[2] = { 'B', 0 };
|
static char B[2] = { 'B', 0 };
|
||||||
static char C[2] = { 'C', 0 };
|
static char C[2] = { 'C', 0 };
|
||||||
|
static char A2[2] = { 'a', 0 };
|
||||||
|
static char B2[2] = { 'b', 0 };
|
||||||
|
static char C2[2] = { 'c', 0 };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void null_free(void* ptr)
|
static void null_free(void* ptr)
|
||||||
{
|
{
|
||||||
@ -124,6 +130,83 @@ EXO_TEST(list_clear, {
|
|||||||
return list->size == 0 && list->first == 0 && list->last == 0 && list->iterator == 0;
|
return list->size == 0 && list->first == 0 && list->last == 0 && list->iterator == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static int g_remove_flag = 0;
|
||||||
|
static void null_free_inc_flag(void* ptr)
|
||||||
|
{
|
||||||
|
(void) ptr;
|
||||||
|
g_remove_flag++;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXO_TEST(list_remove_first_1_1,
|
||||||
|
{
|
||||||
|
list_append(list, A);
|
||||||
|
list_append(list, B);
|
||||||
|
list_append(list, C);
|
||||||
|
return list->size == 3;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(list_remove_first_1_2,
|
||||||
|
{
|
||||||
|
g_remove_flag = 0;
|
||||||
|
list_remove_first(list, null_free_inc_flag);
|
||||||
|
return list->size == 2 && g_remove_flag == 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(list_remove_first_1_3,
|
||||||
|
{
|
||||||
|
list_remove_first(list, NULL);
|
||||||
|
return list->size == 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(list_remove_first_1_4,
|
||||||
|
{
|
||||||
|
list_remove_first(list, NULL);
|
||||||
|
return list->size == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(list_remove_first_1_5,
|
||||||
|
{
|
||||||
|
list_remove_first(list, NULL);
|
||||||
|
return list->size == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(list_append_list_1,
|
||||||
|
{
|
||||||
|
list_append(list, A);
|
||||||
|
list_append(list, B);
|
||||||
|
list_append(list, C);
|
||||||
|
list2 = list_create();
|
||||||
|
list_append(list2, A2);
|
||||||
|
list_append(list2, B2);
|
||||||
|
list_append(list2, C2);
|
||||||
|
return list->size == 3 && list2->size == 3;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(list_append_list_2,
|
||||||
|
{
|
||||||
|
list_append_list(list, list2);
|
||||||
|
return list->size == 6 && list2->size == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(list_append_list_3,
|
||||||
|
{
|
||||||
|
list_destroy(list2);
|
||||||
|
return list_get_index(list, 0) == A &&
|
||||||
|
list_get_index(list, 1) == B &&
|
||||||
|
list_get_index(list, 2) == C &&
|
||||||
|
list_get_index(list, 3) == A2 &&
|
||||||
|
list_get_index(list, 4) == B2 &&
|
||||||
|
list_get_index(list, 5) == C2;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(list_clear_list_last,
|
||||||
|
{
|
||||||
|
list_clear(list, &null_free);
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
EXO_TEST(list_destroy_1, {
|
EXO_TEST(list_destroy_1, {
|
||||||
list_destroy(list);
|
list_destroy(list);
|
||||||
|
@ -174,91 +174,102 @@ EXO_TEST(adc_message_parse_24, {
|
|||||||
|
|
||||||
|
|
||||||
EXO_TEST(adc_message_add_arg_1, {
|
EXO_TEST(adc_message_add_arg_1, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_add_argument(msg, "XXwtf?");
|
adc_msg_add_argument(msg, "XXwtf?");
|
||||||
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);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_add_arg_2, {
|
EXO_TEST(adc_message_add_arg_2, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_add_named_argument(msg, "XX", "wtf?");
|
adc_msg_add_named_argument(msg, "XX", "wtf?");
|
||||||
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);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_remove_arg_1, {
|
EXO_TEST(adc_message_remove_arg_1, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_remove_named_argument(msg, "AA");
|
adc_msg_remove_named_argument(msg, "AA");
|
||||||
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
|
ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_remove_arg_2, {
|
EXO_TEST(adc_message_remove_arg_2, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_remove_named_argument(msg, "BB");
|
adc_msg_remove_named_argument(msg, "BB");
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_remove_arg_3, {
|
EXO_TEST(adc_message_remove_arg_3, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_remove_named_argument(msg, "CC");
|
adc_msg_remove_named_argument(msg, "CC");
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_remove_arg_4, {
|
EXO_TEST(adc_message_remove_arg_4, {
|
||||||
/* this ensures we can remove the last element also */
|
/* this ensures we can remove the last element also */
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3));
|
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string3, strlen(test_string3));
|
||||||
adc_msg_remove_named_argument(msg, "AW");
|
adc_msg_remove_named_argument(msg, "AW");
|
||||||
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);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_replace_arg_1, {
|
EXO_TEST(adc_message_replace_arg_1, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_remove_named_argument(msg, "AA");
|
adc_msg_remove_named_argument(msg, "AA");
|
||||||
int ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
|
ok = strcmp(msg->cache, "IINF BBbar CCwhat\n") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_replace_arg_2, {
|
EXO_TEST(adc_message_replace_arg_2, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_remove_named_argument(msg, "BB");
|
adc_msg_remove_named_argument(msg, "BB");
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo CCwhat\n") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_replace_arg_3, {
|
EXO_TEST(adc_message_replace_arg_3, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_remove_named_argument(msg, "CC");
|
adc_msg_remove_named_argument(msg, "CC");
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo BBbar\n") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_get_arg_1, {
|
EXO_TEST(adc_message_get_arg_1, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
char* c = adc_msg_get_argument(msg, 0);
|
char* c = adc_msg_get_argument(msg, 0);
|
||||||
int ok = strcmp(c, "AAfoo") == 0;
|
ok = strcmp(c, "AAfoo") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
hub_free(c);
|
hub_free(c);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_get_arg_2, {
|
EXO_TEST(adc_message_get_arg_2, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
char* c = adc_msg_get_argument(msg, 1);
|
char* c = adc_msg_get_argument(msg, 1);
|
||||||
int ok = strcmp(c, "BBbar") == 0;
|
ok = strcmp(c, "BBbar") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
hub_free(c);
|
hub_free(c);
|
||||||
return ok;
|
return ok;
|
||||||
@ -340,28 +351,31 @@ EXO_TEST(adc_message_has_named_arg_3, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_has_named_arg_4, {
|
EXO_TEST(adc_message_has_named_arg_4, {
|
||||||
|
int n;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_add_argument(msg, "XXwtf?");
|
adc_msg_add_argument(msg, "XXwtf?");
|
||||||
int n = adc_msg_has_named_argument(msg, "XX");
|
n = adc_msg_has_named_argument(msg, "XX");
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return n == 1;
|
return n == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_has_named_arg_5, {
|
EXO_TEST(adc_message_has_named_arg_5, {
|
||||||
|
int n;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_add_argument(msg, "XXone");
|
adc_msg_add_argument(msg, "XXone");
|
||||||
adc_msg_add_argument(msg, "XXtwo");
|
adc_msg_add_argument(msg, "XXtwo");
|
||||||
int n = adc_msg_has_named_argument(msg, "XX");
|
n = adc_msg_has_named_argument(msg, "XX");
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return n == 2;
|
return n == 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_has_named_arg_6, {
|
EXO_TEST(adc_message_has_named_arg_6, {
|
||||||
|
int n;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_add_argument(msg, "XXone");
|
adc_msg_add_argument(msg, "XXone");
|
||||||
adc_msg_add_argument(msg, "XXtwo");
|
adc_msg_add_argument(msg, "XXtwo");
|
||||||
adc_msg_add_argument(msg, "XXthree");
|
adc_msg_add_argument(msg, "XXthree");
|
||||||
int n = adc_msg_has_named_argument(msg, "XX");
|
n = adc_msg_has_named_argument(msg, "XX");
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return n == 3;
|
return n == 3;
|
||||||
});
|
});
|
||||||
@ -374,63 +388,70 @@ EXO_TEST(adc_message_has_named_arg_7, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_terminate_1, {
|
EXO_TEST(adc_message_terminate_1, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat");
|
struct adc_message* msg = adc_msg_create("IINF AAfoo BBbar CCwhat");
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_terminate_2, {
|
EXO_TEST(adc_message_terminate_2, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
adc_msg_terminate(msg);
|
adc_msg_terminate(msg);
|
||||||
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);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_terminate_3, {
|
EXO_TEST(adc_message_terminate_3, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
adc_msg_terminate(msg);
|
adc_msg_terminate(msg);
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_terminate_4, {
|
EXO_TEST(adc_message_terminate_4, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
adc_msg_terminate(msg);
|
adc_msg_terminate(msg);
|
||||||
adc_msg_terminate(msg);
|
adc_msg_terminate(msg);
|
||||||
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);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_terminate_5, {
|
EXO_TEST(adc_message_terminate_5, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_terminate(msg);
|
adc_msg_terminate(msg);
|
||||||
adc_msg_terminate(msg);
|
adc_msg_terminate(msg);
|
||||||
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);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_terminate_6, {
|
EXO_TEST(adc_message_terminate_6, {
|
||||||
|
int ok;
|
||||||
struct adc_message* msg = adc_msg_create(test_string1);
|
struct adc_message* msg = adc_msg_create(test_string1);
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
adc_msg_unterminate(msg);
|
adc_msg_unterminate(msg);
|
||||||
int ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
|
ok = strcmp(msg->cache, "IINF AAfoo BBbar CCwhat") == 0;
|
||||||
adc_msg_free(msg);
|
adc_msg_free(msg);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_escape_1, {
|
EXO_TEST(adc_message_escape_1, {
|
||||||
|
int ok;
|
||||||
char* s = adc_msg_escape(test_string1);
|
char* s = adc_msg_escape(test_string1);
|
||||||
int ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
|
ok = strcmp(s, "IINF\\sAAfoo\\sBBbar\\sCCwhat\\n") == 0;
|
||||||
hub_free(s);
|
hub_free(s);
|
||||||
return ok;
|
return ok;
|
||||||
});
|
});
|
||||||
|
@ -97,15 +97,82 @@ EXO_TEST(base32_invalid_31, { return !is_valid_base32_char('@'); });
|
|||||||
EXO_TEST(utf8_valid_1, { return is_valid_utf8("abcdefghijklmnopqrstuvwxyz"); });
|
EXO_TEST(utf8_valid_1, { return is_valid_utf8("abcdefghijklmnopqrstuvwxyz"); });
|
||||||
EXO_TEST(utf8_valid_2, { return is_valid_utf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); });
|
EXO_TEST(utf8_valid_2, { return is_valid_utf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); });
|
||||||
EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
|
EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
|
||||||
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
|
|
||||||
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
|
|
||||||
|
|
||||||
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
|
static const char test_utf_seq_1[] = { 0x65, 0x00 }; // valid
|
||||||
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
|
static const char test_utf_seq_2[] = { 0xD8, 0x00 }; // invalid
|
||||||
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
|
static const char test_utf_seq_3[] = { 0x24, 0x00 }; // valid
|
||||||
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
|
static const char test_utf_seq_4[] = { 0xC2, 0x24, 0x00}; // invalid
|
||||||
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
|
static const char test_utf_seq_5[] = { 0xC2, 0xA2, 0x00}; // valid
|
||||||
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
|
static const char test_utf_seq_6[] = { 0xE2, 0x82, 0xAC, 0x00}; // valid
|
||||||
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });
|
static const char test_utf_seq_7[] = { 0xC2, 0x32, 0x00}; // invalid
|
||||||
|
static const char test_utf_seq_8[] = { 0xE2, 0x82, 0x32, 0x00}; // invalid
|
||||||
|
static const char test_utf_seq_9[] = { 0xE2, 0x32, 0x82, 0x00}; // invalid
|
||||||
|
static const char test_utf_seq_10[] = { 0xF0, 0x9F, 0x98, 0x81, 0x00}; // valid
|
||||||
|
|
||||||
|
EXO_TEST(utf8_valid_4, { return is_valid_utf8(test_utf_seq_1); });
|
||||||
|
EXO_TEST(utf8_valid_5, { return !is_valid_utf8(test_utf_seq_2); });
|
||||||
|
EXO_TEST(utf8_valid_6, { return is_valid_utf8(test_utf_seq_3); });
|
||||||
|
EXO_TEST(utf8_valid_7, { return !is_valid_utf8(test_utf_seq_4); });
|
||||||
|
EXO_TEST(utf8_valid_8, { return is_valid_utf8(test_utf_seq_5); });
|
||||||
|
EXO_TEST(utf8_valid_9, { return is_valid_utf8(test_utf_seq_6); });
|
||||||
|
EXO_TEST(utf8_valid_10, { return !is_valid_utf8(test_utf_seq_7); });
|
||||||
|
EXO_TEST(utf8_valid_11, { return !is_valid_utf8(test_utf_seq_8); });
|
||||||
|
EXO_TEST(utf8_valid_12, { return !is_valid_utf8(test_utf_seq_9); });
|
||||||
|
EXO_TEST(utf8_valid_13, { return is_valid_utf8(test_utf_seq_10); });
|
||||||
|
|
||||||
|
// Limits of utf-8
|
||||||
|
static const char test_utf_seq_11[] = { 0x7F, 0x00 }; // valid last 7-bit character
|
||||||
|
static const char test_utf_seq_12[] = { 0x80, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_13[] = { 0xBF, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_14[] = { 0xC0, 0x80, 0x00 }; // invalid out of 2 bytes range
|
||||||
|
static const char test_utf_seq_15[] = { 0xC1, 0x7F, 0x00 }; // invalid out of 2 bytes range
|
||||||
|
static const char test_utf_seq_16[] = { 0xC2, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_17[] = { 0xC2, 0x80, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_18[] = { 0xDF, 0xBF, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_19[] = { 0xE0, 0x80, 0x80, 0x00 }; // invalid out of 3 bytes range
|
||||||
|
static const char test_utf_seq_20[] = { 0xE0, 0x9F, 0xBF, 0x00 }; // invalid out of 3 bytes range
|
||||||
|
static const char test_utf_seq_21[] = { 0xE0, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_22[] = { 0xE0, 0xA0, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_23[] = { 0xE0, 0xA0, 0x80, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_24[] = { 0xEC, 0x9F, 0xBF, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_25[] = { 0xED, 0xA0, 0x80, 0x00 }; // invalid surrogate
|
||||||
|
static const char test_utf_seq_26[] = { 0xED, 0xBF, 0xBF, 0x00 }; // invalid surrogate
|
||||||
|
static const char test_utf_seq_27[] = { 0xEF, 0x80, 0x80, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_28[] = { 0xEF, 0xBF, 0xBF, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_29[] = { 0xF0, 0x80, 0x80, 0x80, 0x00 }; // invalid out of 4 bytes range
|
||||||
|
static const char test_utf_seq_30[] = { 0xF0, 0x8F, 0xBF, 0xBF, 0x00 }; // invalid out of 4 bytes range
|
||||||
|
static const char test_utf_seq_31[] = { 0xF0, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_32[] = { 0xF0, 0x90, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_33[] = { 0xF0, 0x90, 0x80, 0x00 }; // invalid truncated string
|
||||||
|
static const char test_utf_seq_34[] = { 0xF0, 0x90, 0x80, 0x80, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_35[] = { 0xF4, 0x8F, 0xBF, 0xBF, 0x00 }; // valid
|
||||||
|
static const char test_utf_seq_36[] = { 0xF4, 0x90, 0x80, 0x80, 0x00 }; // invalid out of 4 bytes range
|
||||||
|
static const char test_utf_seq_37[] = { 0xFF, 0xBF, 0xBF, 0xBF, 0x00 }; // invalid out of 4 bytes range
|
||||||
|
|
||||||
|
EXO_TEST(utf8_valid_14, { return is_valid_utf8(test_utf_seq_11); });
|
||||||
|
EXO_TEST(utf8_valid_15, { return !is_valid_utf8(test_utf_seq_12); });
|
||||||
|
EXO_TEST(utf8_valid_16, { return !is_valid_utf8(test_utf_seq_13); });
|
||||||
|
EXO_TEST(utf8_valid_17, { return !is_valid_utf8(test_utf_seq_14); });
|
||||||
|
EXO_TEST(utf8_valid_18, { return !is_valid_utf8(test_utf_seq_15); });
|
||||||
|
EXO_TEST(utf8_valid_19, { return !is_valid_utf8(test_utf_seq_16); });
|
||||||
|
EXO_TEST(utf8_valid_20, { return is_valid_utf8(test_utf_seq_17); });
|
||||||
|
EXO_TEST(utf8_valid_21, { return is_valid_utf8(test_utf_seq_18); });
|
||||||
|
EXO_TEST(utf8_valid_22, { return !is_valid_utf8(test_utf_seq_19); });
|
||||||
|
EXO_TEST(utf8_valid_23, { return !is_valid_utf8(test_utf_seq_20); });
|
||||||
|
EXO_TEST(utf8_valid_24, { return !is_valid_utf8(test_utf_seq_21); });
|
||||||
|
EXO_TEST(utf8_valid_25, { return !is_valid_utf8(test_utf_seq_22); });
|
||||||
|
EXO_TEST(utf8_valid_26, { return is_valid_utf8(test_utf_seq_23); });
|
||||||
|
EXO_TEST(utf8_valid_27, { return is_valid_utf8(test_utf_seq_24); });
|
||||||
|
EXO_TEST(utf8_valid_28, { return !is_valid_utf8(test_utf_seq_25); });
|
||||||
|
EXO_TEST(utf8_valid_29, { return !is_valid_utf8(test_utf_seq_26); });
|
||||||
|
EXO_TEST(utf8_valid_30, { return is_valid_utf8(test_utf_seq_27); });
|
||||||
|
EXO_TEST(utf8_valid_31, { return is_valid_utf8(test_utf_seq_28); });
|
||||||
|
EXO_TEST(utf8_valid_32, { return !is_valid_utf8(test_utf_seq_29); });
|
||||||
|
EXO_TEST(utf8_valid_33, { return !is_valid_utf8(test_utf_seq_30); });
|
||||||
|
EXO_TEST(utf8_valid_34, { return !is_valid_utf8(test_utf_seq_31); });
|
||||||
|
EXO_TEST(utf8_valid_35, { return !is_valid_utf8(test_utf_seq_32); });
|
||||||
|
EXO_TEST(utf8_valid_36, { return !is_valid_utf8(test_utf_seq_33); });
|
||||||
|
EXO_TEST(utf8_valid_37, { return is_valid_utf8(test_utf_seq_34); });
|
||||||
|
EXO_TEST(utf8_valid_38, { return is_valid_utf8(test_utf_seq_35); });
|
||||||
|
EXO_TEST(utf8_valid_39, { return !is_valid_utf8(test_utf_seq_36); });
|
||||||
|
EXO_TEST(utf8_valid_40, { return !is_valid_utf8(test_utf_seq_37); });
|
||||||
|
150
autotest/test_rbtree.tcc
Normal file
150
autotest/test_rbtree.tcc
Normal 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;
|
||||||
|
});
|
@ -117,3 +117,9 @@ EXO_TEST(timer_process_5_events_1,{
|
|||||||
g_now = 4;
|
g_now = 4;
|
||||||
return timeout_queue_process(g_queue, g_now) == g_triggered;
|
return timeout_queue_process(g_queue, g_now) == g_triggered;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_shutdown,{
|
||||||
|
timeout_queue_shutdown(g_queue);
|
||||||
|
hub_free(g_queue);
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
110
autotest/test_tokenizer.tcc
Normal file
110
autotest/test_tokenizer.tcc
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
#define SETUP(X, STR) struct cfg_tokens* tokens = cfg_tokenize(STR)
|
||||||
|
#define CLEANUP_LIST(X) do { list_clear(X, hub_free); list_destroy(X); } while(0)
|
||||||
|
#define CLEANUP_TOKENS(X) do { cfg_tokens_free(X); } while(0)
|
||||||
|
|
||||||
|
static int match_str(const char* str1, char* str2)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (i = 0; i < strlen(str2); i++)
|
||||||
|
if (str2[i] == '_')
|
||||||
|
str2[i] = ' ';
|
||||||
|
else if (str2[i] == '|')
|
||||||
|
str2[i] = '\t';
|
||||||
|
|
||||||
|
ret = strcmp(str1, str2);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "\n Mismatch: \"%s\" != \"%s\"\n", str1, str2);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int count(const char* STR, size_t EXPECT) {
|
||||||
|
SETUP(tokens, STR);
|
||||||
|
int pass = cfg_token_count(tokens) == EXPECT;
|
||||||
|
CLEANUP_TOKENS(tokens);
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compare(const char* str, const char* ref) {
|
||||||
|
size_t i, max;
|
||||||
|
int pass;
|
||||||
|
struct linked_list* compare = list_create();
|
||||||
|
SETUP(tokens, str);
|
||||||
|
split_string(ref, " ", compare, 0);
|
||||||
|
pass = cfg_token_count(tokens) == list_size(compare);
|
||||||
|
if (pass) {
|
||||||
|
max = cfg_token_count(tokens);
|
||||||
|
for (i = 0; i < max; i++) {
|
||||||
|
char* token = (char*) cfg_token_get(tokens, i);
|
||||||
|
char* refer = (char*) list_get_index(compare, i);
|
||||||
|
if (match_str(token, refer)) {
|
||||||
|
pass = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CLEANUP_TOKENS(tokens);
|
||||||
|
CLEANUP_LIST(compare);
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXO_TEST(tokenizer_basic_0, { return count("", 0); });
|
||||||
|
EXO_TEST(tokenizer_basic_1, { return count("a", 1); });
|
||||||
|
EXO_TEST(tokenizer_basic_1a, { return count(" a", 1); })
|
||||||
|
EXO_TEST(tokenizer_basic_1b, { return count("\ta", 1); })
|
||||||
|
EXO_TEST(tokenizer_basic_1c, { return count(" a", 1); })
|
||||||
|
EXO_TEST(tokenizer_basic_1d, { return count(" a ", 1); })
|
||||||
|
EXO_TEST(tokenizer_basic_1e, { return count(" a ", 1); })
|
||||||
|
EXO_TEST(tokenizer_basic_2, { return count("a b", 2); });
|
||||||
|
EXO_TEST(tokenizer_basic_2a, { return count(" a b ", 2); });
|
||||||
|
EXO_TEST(tokenizer_basic_3, { return count("a b c", 3); });
|
||||||
|
EXO_TEST(tokenizer_basic_3a, { return count("a b c", 3); });
|
||||||
|
EXO_TEST(tokenizer_basic_3b, { return count("a b\tc", 3); });
|
||||||
|
EXO_TEST(tokenizer_basic_3c, { return count("a b c ", 3); });
|
||||||
|
EXO_TEST(tokenizer_basic_3d, { return count("a b c ", 3); });
|
||||||
|
|
||||||
|
EXO_TEST(tokenizer_basic_compare_0, { return compare("value1 value2 value3", "value1 value2 value3"); });
|
||||||
|
EXO_TEST(tokenizer_basic_compare_1, { return compare("a b c", "a b c"); });
|
||||||
|
EXO_TEST(tokenizer_basic_compare_2, { return compare("a b c", "a b c"); });
|
||||||
|
EXO_TEST(tokenizer_basic_compare_3, { return compare(" a b c", "a b c"); });
|
||||||
|
EXO_TEST(tokenizer_basic_compare_4, { return compare(" a b c ", "a b c"); });
|
||||||
|
EXO_TEST(tokenizer_basic_compare_5, { return compare("a b c ", "a b c"); });
|
||||||
|
EXO_TEST(tokenizer_basic_compare_6, { return compare("a b c ", "a b c"); });
|
||||||
|
|
||||||
|
EXO_TEST(tokenizer_comment_1, { return compare("value1 value2 # value3", "value1 value2"); });
|
||||||
|
EXO_TEST(tokenizer_comment_2, { return compare("value1 value2\\# value3", "value1 value2# value3"); });
|
||||||
|
EXO_TEST(tokenizer_comment_3, { return compare("value1 \"value2#\" value3", "value1 value2# value3"); });
|
||||||
|
|
||||||
|
EXO_TEST(tokenizer_escape_1, { return compare("\"value1\" value2", "value1 value2"); });
|
||||||
|
EXO_TEST(tokenizer_escape_2, { return compare("\"value1\\\"\" value2", "value1\" value2"); });
|
||||||
|
EXO_TEST(tokenizer_escape_3, { return compare("\"value1\" \"value 2\"", "value1 value_2"); });
|
||||||
|
EXO_TEST(tokenizer_escape_4, { return compare("\"value1\" value\\ 2", "value1 value_2"); });
|
||||||
|
EXO_TEST(tokenizer_escape_5, { return compare("\"value1\" value\\\\2", "value1 value\\2"); });
|
||||||
|
EXO_TEST(tokenizer_escape_6, { return compare("\"value1\" value\\\t2", "value1 value|2"); });
|
||||||
|
EXO_TEST(tokenizer_escape_7, { return compare("\"value1\" \"value\t2\"", "value1 value|2"); });
|
||||||
|
|
||||||
|
static int test_setting(const char* str, const char* expected_key, const char* expected_value)
|
||||||
|
{
|
||||||
|
int success = 0;
|
||||||
|
struct cfg_settings* setting = cfg_settings_split(str);
|
||||||
|
if (!setting) return expected_key == NULL;
|
||||||
|
success = (!strcmp(cfg_settings_get_key(setting), expected_key) && !strcmp(cfg_settings_get_value(setting), expected_value));
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXO_TEST(tokenizer_settings_1, { return test_setting("foo=bar", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_2, { return test_setting("foo =bar", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_3, { return test_setting("foo= bar", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_4, { return test_setting("\tfoo=bar", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_5, { return test_setting("foo=bar\t", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_6, { return test_setting("\tfoo=bar\t", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_7, { return test_setting("\tfoo\t=\tbar\t", "foo", "bar"); });
|
||||||
|
EXO_TEST(tokenizer_settings_8, { return test_setting("foo=", "foo", ""); });
|
||||||
|
EXO_TEST(tokenizer_settings_9, { return test_setting("=bar", NULL, ""); });
|
||||||
|
|
||||||
|
|
@ -2,32 +2,19 @@
|
|||||||
|
|
||||||
#define MAX_USERS 64
|
#define MAX_USERS 64
|
||||||
|
|
||||||
static struct hub_info um_hub;
|
static struct hub_user_manager* uman = 0;
|
||||||
static struct hub_user um_user[MAX_USERS];
|
static struct hub_user um_user[MAX_USERS];
|
||||||
// static struct net_connection um_cons[MAX_USERS];
|
|
||||||
|
|
||||||
EXO_TEST(um_test_setup, {
|
|
||||||
int i = 0;
|
|
||||||
memset(&um_hub, 0, sizeof(um_hub));
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
|
||||||
{
|
|
||||||
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
|
|
||||||
um_cons[i].sd = -1;
|
|
||||||
|
|
||||||
memset(&um_user[i], 0, sizeof(struct hub_user));
|
|
||||||
um_user[i].id.sid = i+1;
|
|
||||||
um_user[i].connection = &um_cons[i];*/
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_init_1, {
|
EXO_TEST(um_init_1, {
|
||||||
return uman_init(0) != 0;
|
sid_t s;
|
||||||
});
|
uman = uman_init();
|
||||||
|
|
||||||
EXO_TEST(um_init_2, {
|
for (s = 0; s < MAX_USERS; s++)
|
||||||
return uman_init(&um_hub) == 0;
|
{
|
||||||
|
memset(&um_user[s], 0, sizeof(struct hub_user));
|
||||||
|
um_user[s].id.sid = s;
|
||||||
|
}
|
||||||
|
return !!uman;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_shutdown_1, {
|
EXO_TEST(um_shutdown_1, {
|
||||||
@ -35,32 +22,29 @@ EXO_TEST(um_shutdown_1, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_shutdown_2, {
|
EXO_TEST(um_shutdown_2, {
|
||||||
return uman_shutdown(&um_hub) == 0;
|
return uman_shutdown(uman) == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_shutdown_3, {
|
EXO_TEST(um_init_2, {
|
||||||
return uman_shutdown(&um_hub) == -1;
|
uman = uman_init();
|
||||||
});
|
return !!uman;
|
||||||
|
|
||||||
EXO_TEST(um_init_3, {
|
|
||||||
return uman_init(&um_hub) == 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_add_1, {
|
EXO_TEST(um_add_1, {
|
||||||
return uman_add(&um_hub, &um_user[0]) == 0;
|
return uman_add(uman, &um_user[0]) == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_size_1, {
|
EXO_TEST(um_size_1, {
|
||||||
return hub_get_user_count(&um_hub) == 1;
|
return uman->count == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
EXO_TEST(um_remove_1, {
|
EXO_TEST(um_remove_1, {
|
||||||
return uman_remove(&um_hub, &um_user[0]) == 0;
|
return uman_remove(uman, &um_user[0]) == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_size_2, {
|
EXO_TEST(um_size_2, {
|
||||||
return hub_get_user_count(&um_hub) == 0;
|
return uman->count == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -68,25 +52,21 @@ EXO_TEST(um_add_2, {
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
for (i = 0; i < MAX_USERS; i++)
|
||||||
{
|
{
|
||||||
if (uman_add(&um_hub, &um_user[i]) != 0)
|
if (uman_add(uman, &um_user[i]) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_size_3, {
|
EXO_TEST(um_size_3, {
|
||||||
return hub_get_user_count(&um_hub) == MAX_USERS;
|
return uman->count == MAX_USERS;
|
||||||
});
|
|
||||||
|
|
||||||
EXO_TEST(um_add_3, {
|
|
||||||
return uman_add(&um_hub, &um_user[5]) != 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(um_remove_2, {
|
EXO_TEST(um_remove_2, {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
for (i = 0; i < MAX_USERS; i++)
|
||||||
{
|
{
|
||||||
if (uman_remove(&um_hub, &um_user[i]) != 0)
|
if (uman_remove(uman, &um_user[i]) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -105,5 +85,5 @@ EXO_TEST(um_remove_2, {
|
|||||||
|
|
||||||
/* Last test */
|
/* Last test */
|
||||||
EXO_TEST(um_shutdown_4, {
|
EXO_TEST(um_shutdown_4, {
|
||||||
return uman_shutdown(&um_hub) == 0;
|
return uman_shutdown(uman) == 0;
|
||||||
});
|
});
|
||||||
|
43
autotest/travis/build-and-test.sh
Executable file
43
autotest/travis/build-and-test.sh
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
export CFLAGS="$(dpkg-buildflags --get CFLAGS) $(dpkg-buildflags --get CPPFLAGS)"
|
||||||
|
export LDFLAGS="$(dpkg-buildflags --get LDFLAGS) -Wl,--as-needed"
|
||||||
|
|
||||||
|
mkdir -p builddir
|
||||||
|
cd builddir
|
||||||
|
|
||||||
|
CMAKEOPTS="..
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr"
|
||||||
|
|
||||||
|
if [ "${CONFIG}" = "full" ]; then
|
||||||
|
CMAKEOPTS="${CMAKEOPTS}
|
||||||
|
-DRELEASE=OFF
|
||||||
|
-DLOWLEVEL_DEBUG=ON
|
||||||
|
-DSSL_SUPPORT=ON
|
||||||
|
-DUSE_OPENSSL=ON
|
||||||
|
-DADC_STRESS=ON"
|
||||||
|
else
|
||||||
|
CMAKEOPTS="${CMAKEOPTS}
|
||||||
|
-DRELEASE=ON
|
||||||
|
-DLOWLEVEL_DEBUG=OFF
|
||||||
|
-DSSL_SUPPORT=OFF
|
||||||
|
-DADC_STRESS=OFF"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
cmake ${CMAKEOPTS} \
|
||||||
|
-DCMAKE_C_FLAGS="${CFLAGS}" \
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}"
|
||||||
|
make VERBOSE=1
|
||||||
|
|
||||||
|
|
||||||
|
make VERBOSE=1 autotest-bin
|
||||||
|
./autotest-bin
|
||||||
|
|
||||||
|
|
||||||
|
sudo make install
|
||||||
|
du -shc /etc/uhub/ /usr/bin/uhub* /usr/lib/uhub/
|
||||||
|
|
10
autotest/travis/install-build-depends.sh
Executable file
10
autotest/travis/install-build-depends.sh
Executable 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
4
autotest/update.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
./exotic *.tcc > test.c
|
||||||
|
|
78
cmake/Modules/FindSqlite3.cmake
Normal file
78
cmake/Modules/FindSqlite3.cmake
Normal 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 libraries to use sqlite3
|
||||||
|
# SQLITE3_DEFINITIONS Definitions to compile sqlite3
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 Juha Tuomala <tuju@iki.fi>
|
||||||
|
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
|
||||||
|
# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
|
||||||
|
#
|
||||||
|
# Redistribution and use is allowed according to the terms of the New
|
||||||
|
# BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
#
|
||||||
|
|
||||||
|
INCLUDE( FindPkgConfig )
|
||||||
|
# Take care about sqlite3.pc settings
|
||||||
|
IF ( Sqlite3_FIND_REQUIRED )
|
||||||
|
SET( _pkgconfig_REQUIRED "REQUIRED" )
|
||||||
|
ELSE ( Sqlite3_FIND_REQUIRED )
|
||||||
|
SET( _pkgconfig_REQUIRED "" )
|
||||||
|
ENDIF ( Sqlite3_FIND_REQUIRED )
|
||||||
|
|
||||||
|
IF ( SQLITE3_MIN_VERSION )
|
||||||
|
PKG_SEARCH_MODULE( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3>=${SQLITE3_MIN_VERSION} )
|
||||||
|
ELSE ( SQLITE3_MIN_VERSION )
|
||||||
|
pkg_search_module( SQLITE3 ${_pkgconfig_REQUIRED} sqlite3 )
|
||||||
|
ENDIF ( SQLITE3_MIN_VERSION )
|
||||||
|
|
||||||
|
|
||||||
|
# Look for sqlite3 include dir and libraries w/o pkgconfig
|
||||||
|
IF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||||
|
FIND_PATH( _sqlite3_include_DIR sqlite3.h
|
||||||
|
PATHS
|
||||||
|
/opt/local/include/
|
||||||
|
/sw/include/
|
||||||
|
/usr/local/include/
|
||||||
|
/usr/include/
|
||||||
|
)
|
||||||
|
FIND_LIBRARY( _sqlite3_link_DIR sqlite3
|
||||||
|
PATHS
|
||||||
|
/opt/local/lib
|
||||||
|
/sw/lib
|
||||||
|
/usr/lib
|
||||||
|
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
|
||||||
|
/usr/local/lib
|
||||||
|
/usr/lib64
|
||||||
|
/usr/local/lib64
|
||||||
|
/opt/lib64
|
||||||
|
)
|
||||||
|
IF ( _sqlite3_include_DIR AND _sqlite3_link_DIR )
|
||||||
|
SET ( _sqlite3_FOUND TRUE )
|
||||||
|
ENDIF ( _sqlite3_include_DIR AND _sqlite3_link_DIR )
|
||||||
|
|
||||||
|
|
||||||
|
IF ( _sqlite3_FOUND )
|
||||||
|
SET ( SQLITE3_INCLUDE_DIRS ${_sqlite3_include_DIR} )
|
||||||
|
SET ( SQLITE3_LIBRARIES ${_sqlite3_link_DIR} )
|
||||||
|
ENDIF ( _sqlite3_FOUND )
|
||||||
|
|
||||||
|
# Report results
|
||||||
|
IF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
|
||||||
|
SET( SQLITE3_FOUND 1 )
|
||||||
|
MESSAGE( STATUS "Found sqlite3: ${SQLITE3_LIBRARIES} ${SQLITE3_INCLUDE_DIRS}" )
|
||||||
|
ELSE ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
|
||||||
|
IF ( Sqlite3_FIND_REQUIRED )
|
||||||
|
MESSAGE( SEND_ERROR "Could NOT find sqlite3" )
|
||||||
|
ELSE ( Sqlite3_FIND_REQUIRED )
|
||||||
|
MESSAGE( STATUS "Could NOT find sqlite3" )
|
||||||
|
ENDIF ( Sqlite3_FIND_REQUIRED )
|
||||||
|
ENDIF ( SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS AND _sqlite3_FOUND )
|
||||||
|
|
||||||
|
ENDIF ( NOT SQLITE3_FOUND AND NOT PKG_CONFIG_FOUND )
|
||||||
|
|
||||||
|
# Hide advanced variables from CMake GUIs
|
||||||
|
MARK_AS_ADVANCED( SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIRS )
|
8
debian/changelog
vendored
8
debian/changelog
vendored
@ -1,8 +1,14 @@
|
|||||||
|
uhub (0.3.2-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Updated upstream version.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Mon, 30 May 2010 18:00:00 +0200
|
||||||
|
|
||||||
uhub (0.3.1-1) unstable; urgency=low
|
uhub (0.3.1-1) unstable; urgency=low
|
||||||
|
|
||||||
* Updated version number.
|
* Updated version number.
|
||||||
|
|
||||||
-- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200
|
-- Jan Vidar Krey <janvidar@extatic.org> Mon, 04 Apr 2010 16:44:21 +0200
|
||||||
|
|
||||||
uhub (0.3.0-2) unstable; urgency=low
|
uhub (0.3.0-2) unstable; urgency=low
|
||||||
|
|
||||||
|
2
debian/control
vendored
2
debian/control
vendored
@ -20,5 +20,5 @@ Description: High performance ADC p2p hub
|
|||||||
- Advanced access control support
|
- Advanced access control support
|
||||||
- Easy configuration
|
- Easy configuration
|
||||||
.
|
.
|
||||||
Homepage: http://www.uhub.org/
|
Homepage: https://www.uhub.org/
|
||||||
|
|
||||||
|
2
debian/copyright
vendored
2
debian/copyright
vendored
@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||||
License can be found in `/usr/share/common-licenses/GPL'.
|
License can be found in `/usr/share/common-licenses/GPL'.
|
||||||
|
2
debian/rules
vendored
2
debian/rules
vendored
@ -24,7 +24,7 @@ binary-indep: build
|
|||||||
binary-arch: build
|
binary-arch: build
|
||||||
dh_testdir
|
dh_testdir
|
||||||
dh_testroot
|
dh_testroot
|
||||||
dh_clean -k
|
dh_prep
|
||||||
dh_installdirs
|
dh_installdirs
|
||||||
$(MAKE) install $(makeopts)
|
$(MAKE) install $(makeopts)
|
||||||
dh_installdocs
|
dh_installdocs
|
||||||
|
9
debian/uhub.init
vendored
9
debian/uhub.init
vendored
@ -5,7 +5,8 @@
|
|||||||
# Required-Stop: $remote_fs $network
|
# Required-Stop: $remote_fs $network
|
||||||
# Default-Start: 2 3 4 5
|
# Default-Start: 2 3 4 5
|
||||||
# Default-Stop: 0 1 6
|
# Default-Stop: 0 1 6
|
||||||
# Short-Description: uhub - High performance ADC p2p hub.
|
# Short-Description: Start daemon at boot time
|
||||||
|
# Description: Enable service provided by daemon.
|
||||||
### END INIT INFO
|
### END INIT INFO
|
||||||
|
|
||||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||||
@ -83,8 +84,12 @@ case "$1" in
|
|||||||
$0 start
|
$0 start
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
status_of_proc $DAEMON $NAME && exit 0 || exit $?
|
||||||
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
1
debian/uhub.manpages
vendored
1
debian/uhub.manpages
vendored
@ -1 +1,2 @@
|
|||||||
doc/uhub.1
|
doc/uhub.1
|
||||||
|
doc/uhub-passwd.1
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
= Architecture of uHub =
|
= Architecture of uHub =
|
||||||
|
|
||||||
uHub is single threaded and handles network and timer events using the
|
uHub is single-threaded and handles network and timer events using the
|
||||||
libevent library.
|
libevent library.
|
||||||
For each state there is a read event (and sometimes a write event) and timeout
|
For each state there is a read event (and sometimes a write event) and timeout
|
||||||
event in case an expected read (or write) event does not occur.
|
event in case an expected read (or write) event does not occur.
|
||||||
|
|
||||||
|
|
||||||
== Protocol overview ==
|
== Protocol overview ==
|
||||||
uHub use "speak" the ADC protocol, which works in short as follows:
|
uHub "speaks" the ADC protocol, which works in short as follows:
|
||||||
(C = client, S = server aka uHub).
|
(C = client, S = server aka uHub).
|
||||||
|
|
||||||
C: HSUP ADBASE
|
C: HSUP ADBASE
|
||||||
@ -67,7 +67,7 @@ Accepting new users
|
|||||||
| | |
|
| | |
|
||||||
| V |
|
| V |
|
||||||
| --------------------- ---------------------
|
| --------------------- ---------------------
|
||||||
| | Send password | ------> | Reveive and check |
|
| | Send password | ------> | Receive and check |
|
||||||
| | request, if needed| | password. |
|
| | request, if needed| | password. |
|
||||||
| --------------------- ---------------------
|
| --------------------- ---------------------
|
||||||
| |
|
| |
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
How to compile:
|
How to compile:
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
See the official compiling howto: http://www.extatic.org/uhub/compile.html
|
See the official compiling howto: https://www.uhub.org/compile.php
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
|
|
||||||
@ -9,6 +9,11 @@ Before you try to compile µHub, please make sure the following prerequisites ar
|
|||||||
* GNU make
|
* GNU make
|
||||||
* gcc > 3.0 (or MinGW on Windows)
|
* gcc > 3.0 (or MinGW on Windows)
|
||||||
* Perl 5
|
* Perl 5
|
||||||
|
* openssl > 0.9.8 (or use "make USE_SSL=NO")
|
||||||
|
* sqlite > 3.x
|
||||||
|
|
||||||
|
or read https://www.uhub.org/compile.php for more info.
|
||||||
|
|
||||||
|
|
||||||
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
@ -31,7 +31,7 @@ The hub should send a packet containing the token back:
|
|||||||
'IECH {token} {host:port}', as well as the same message via TCP.
|
'IECH {token} {host:port}', as well as the same message via TCP.
|
||||||
|
|
||||||
If the client receives the message via UDP, it should now be able to determine the type of NAT.
|
If the client receives the message via UDP, it should now be able to determine the type of NAT.
|
||||||
If the client receives the message via TCP only it knows it has a firewall blocking icomming communication.
|
If the client receives the message via TCP only it knows it has a firewall blocking incoming communication.
|
||||||
If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
|
If the client does not receive the message, it should assume a firewall is blocking all UDP communication,
|
||||||
and resume in passive mode.
|
and resume in passive mode.
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
Getting started guide
|
Getting started guide
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
(This document is maintained at http://www.extatic.org/uhub/getstarted.html )
|
|
||||||
|
|
||||||
Unpack your binaries
|
Unpack your binaries
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -17,6 +15,7 @@ Create configuration files.
|
|||||||
If no configuration files are created, uhub will use the default parameters, so you can skip this step if you are in a hurry to see it run.
|
If no configuration files are created, uhub will use the default parameters, so you can skip this step if you are in a hurry to see it run.
|
||||||
|
|
||||||
As root, or use sudo.
|
As root, or use sudo.
|
||||||
|
|
||||||
% mkdir /etc/uhub
|
% mkdir /etc/uhub
|
||||||
% cp doc/uhub.conf /etc/uhub
|
% cp doc/uhub.conf /etc/uhub
|
||||||
% cp doc/users.conf /etc/uhub
|
% cp doc/users.conf /etc/uhub
|
||||||
@ -32,8 +31,11 @@ NOTE: It is important to use the "adc://" prefix, and the port number when using
|
|||||||
|
|
||||||
If you modify the configuration files in /etc/uhub you will have to notify uhub by sending a HUP signal.
|
If you modify the configuration files in /etc/uhub you will have to notify uhub by sending a HUP signal.
|
||||||
|
|
||||||
|
% ps aux | grep uhub
|
||||||
% kill -HUP <pid of uhub>
|
% kill -HUP <pid of uhub>
|
||||||
|
|
||||||
Or, for the lazy people
|
Or, for the lazy people
|
||||||
|
|
||||||
% killall -HUP uhub
|
% killall -HUP uhub
|
||||||
|
|
||||||
In order to run uhub as a daemon, start it with the -f switch which will make it fork into the background.
|
In order to run uhub as a daemon, start it with the -f switch which will make it fork into the background.
|
||||||
@ -41,17 +43,25 @@ In addition, use the -l to specify a log file instead of stdout. One can also sp
|
|||||||
if one wishes to run uhub as a specific user using the -u and -g switches.
|
if one wishes to run uhub as a specific user using the -u and -g switches.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
% uhub -f -l mylog.txt -u nobody -g nogroup
|
|
||||||
|
|
||||||
|
% uhub -f -l mylog.txt -u nobody -g nogroup
|
||||||
|
|
||||||
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
|
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
|
||||||
This limit needs to be higher than the configured max_users in uhub.conf.
|
This limit needs to be higher than the configured max_users in uhub.conf.
|
||||||
|
|
||||||
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
In Linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
||||||
* soft nofile 4096
|
* soft nofile 4096
|
||||||
* hard nofile 4096
|
* hard nofile 4096
|
||||||
|
|
||||||
Or, you can use (as root):
|
Or, you can use (as root):
|
||||||
|
|
||||||
% ulimit -n 4096
|
% ulimit -n 4096
|
||||||
|
|
||||||
|
You can interact with uhub in your hub main chat using the `!` prefix, followed by a command:
|
||||||
|
|
||||||
|
Example :
|
||||||
|
|
||||||
|
* to display help and the command you can use:
|
||||||
|
!help
|
||||||
|
|
||||||
Your mileage may vary -- Good luck!
|
Your mileage may vary -- Good luck!
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# chkconfig: - 91 35
|
# chkconfig: - 91 35
|
||||||
# description: Starts and stops the Uhub ( http://www.extatic.org/uhub ) daemons on RHEL\CentOS \
|
# description: Starts and stops the Uhub ( https://www.uhub.org ) daemons on RHEL\CentOS \
|
||||||
# used to provide p2p network services.
|
# used to provide p2p network services.
|
||||||
#
|
#
|
||||||
# pidfile: /var/run/uhub.pid
|
# pidfile: /var/run/uhub.pid
|
||||||
@ -31,7 +31,8 @@ fi
|
|||||||
# Check that networking is up.
|
# Check that networking is up.
|
||||||
[ ${NETWORKING} = "no" ] && exit 1
|
[ ${NETWORKING} = "no" ] && exit 1
|
||||||
|
|
||||||
# Check that uhub.conf exists.
|
# Check that bin and uhub.conf exists.
|
||||||
|
[ -f $UHUBBINFILE ] || exit 6
|
||||||
[ -f /etc/uhub/uhub.conf ] || exit 6
|
[ -f /etc/uhub/uhub.conf ] || exit 6
|
||||||
|
|
||||||
RETVAL=0
|
RETVAL=0
|
||||||
@ -40,7 +41,7 @@ RETVAL=0
|
|||||||
start() {
|
start() {
|
||||||
KIND="Uhub"
|
KIND="Uhub"
|
||||||
echo -n $"Starting $KIND services: "
|
echo -n $"Starting $KIND services: "
|
||||||
daemon uhub $UHUBOPTIONS
|
daemon $UHUBBINFILE $UHUBOPTIONS
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo ""
|
echo ""
|
||||||
return $RETVAL
|
return $RETVAL
|
||||||
@ -49,7 +50,7 @@ start() {
|
|||||||
stop() {
|
stop() {
|
||||||
KIND="Uhub"
|
KIND="Uhub"
|
||||||
echo -n $"Shutting down $KIND services: "
|
echo -n $"Shutting down $KIND services: "
|
||||||
killproc uhub
|
killproc $UHUBBINFILE
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
echo ""
|
echo ""
|
||||||
return $RETVAL
|
return $RETVAL
|
||||||
@ -68,8 +69,16 @@ reload() {
|
|||||||
return $RETVAL
|
return $RETVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relog() {
|
||||||
|
echo -n $"Reopen main log file: "
|
||||||
|
killproc uhub -SIGHUP
|
||||||
|
RETVAL=$?
|
||||||
|
echo ""
|
||||||
|
return $RETVAL
|
||||||
|
}
|
||||||
|
|
||||||
rhstatus() {
|
rhstatus() {
|
||||||
status uhub
|
status $UHUBBINFILE
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
if [ $RETVAL -ne 0 ] ; then
|
if [ $RETVAL -ne 0 ] ; then
|
||||||
return $RETVAL
|
return $RETVAL
|
||||||
@ -90,11 +99,14 @@ case "$1" in
|
|||||||
reload)
|
reload)
|
||||||
reload
|
reload
|
||||||
;;
|
;;
|
||||||
|
relog)
|
||||||
|
relog
|
||||||
|
;;
|
||||||
status)
|
status)
|
||||||
rhstatus
|
rhstatus
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo $"Usage: $0 {start|stop|restart|reload|status}"
|
echo $"Usage: $0 {start|stop|restart|reload|relog|status}"
|
||||||
exit 2
|
exit 2
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
# locate bin file
|
||||||
|
UHUBBINFILE=/usr/bin/uhub
|
||||||
|
|
||||||
# Options to UHUB
|
# Options to UHUB
|
||||||
# -v Verbose mode. Add more -v's for higher verbosity.
|
# -v Verbose mode. Add more -v's for higher verbosity.
|
||||||
# -q Quiet mode - no output
|
# -q Quiet mode - no output
|
||||||
|
71
doc/plugins.conf
Normal file
71
doc/plugins.conf
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# ATTENTION!
|
||||||
|
# Plugins are invoked in the order of listing in the plugin config file.
|
||||||
|
|
||||||
|
|
||||||
|
# Sqlite based user authentication.
|
||||||
|
#
|
||||||
|
# This plugin provides a Sqlite based authentication database for
|
||||||
|
# registered users.
|
||||||
|
# Use the uhub-passwd utility to create the database and add/remove users.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# file: path/filename for database.
|
||||||
|
#
|
||||||
|
plugin /usr/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
|
||||||
|
|
||||||
|
# Topic commands.
|
||||||
|
# Note: "topic" == "hub description" (as configured in uhub.conf)
|
||||||
|
#
|
||||||
|
# !topic - change the topic (op required)
|
||||||
|
# !showtopic - show the topic
|
||||||
|
# !resettopic - reset the topic to the default (op required)
|
||||||
|
#
|
||||||
|
# This plugins takes no parameters.
|
||||||
|
#plugin /usr/lib/uhub/mod_topic.so
|
||||||
|
|
||||||
|
# Log file writer
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# file: path/filename for log file.
|
||||||
|
# syslog: if true then syslog is used instead of writing to a file (Unix only)
|
||||||
|
plugin /usr/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
|
||||||
|
|
||||||
|
# A simple example plugin
|
||||||
|
#plugin /usr/lib/uhub/mod_example.so
|
||||||
|
|
||||||
|
# A plugin sending a welcome message.
|
||||||
|
#
|
||||||
|
# This plugin provides the following commands:
|
||||||
|
# !motd - Message of the day
|
||||||
|
# !rules - Show hub rules.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# motd: path/filename for the welcome message (message of the day)
|
||||||
|
# rules: path/filename for the rules file
|
||||||
|
#
|
||||||
|
# NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted.
|
||||||
|
#
|
||||||
|
# The motd/rules files can do the following substitutions:
|
||||||
|
# %n - Nickname of the user who entered the hub or issued the command.
|
||||||
|
# %a - IP address of the user
|
||||||
|
# %c - The credentials of the user (guest, user, op, super, admin).
|
||||||
|
# %% - Becomes '%'
|
||||||
|
# %H - Hour 24-hour format (00-23) (Hub local time)
|
||||||
|
# %I - Hour 12-hour format (01-12) (Hub local time)
|
||||||
|
# %P - 'AM' or 'PM'
|
||||||
|
# %p - 'am' or 'pm'
|
||||||
|
# %M - Minutes (00-59) (Hub local time)
|
||||||
|
# %S - Seconds (00-60) (Hub local time)
|
||||||
|
plugin /usr/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rules.txt"
|
||||||
|
|
||||||
|
# Load the chat history plugin.
|
||||||
|
#
|
||||||
|
# This plugin provides chat history when users are connecting, or
|
||||||
|
# when users invoke the !history command.
|
||||||
|
# The history command can optionally take a parameter to indicate how many lines of history is requested.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# history_max: the maximum number of messages to keep in history
|
||||||
|
# history_default: when !history is provided without arguments, then this default number of messages are returned.
|
||||||
|
# history_connect: the number of chat history messages to send when users connect (0 = do not send any history)
|
||||||
|
plugin /usr/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5"
|
42
doc/uhub-passwd.1
Normal file
42
doc/uhub-passwd.1
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
.TH UHUB-PASSWD "1" "May 2012"
|
||||||
|
.SH NAME
|
||||||
|
uhub-passwd \- small utility for manipulating passwords which are
|
||||||
|
used by uhub daemon
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B uhub-passwd
|
||||||
|
\fIfilename command \fR[...]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
uHub is a high performance peer-to-peer hub for the ADC network.
|
||||||
|
Its low memory footprint allows it to handle several thousand users
|
||||||
|
on high-end servers, or a small private hub on embedded hardware.
|
||||||
|
.SH "OPTIONS"
|
||||||
|
.TP
|
||||||
|
.BI \^create
|
||||||
|
.TP
|
||||||
|
.BI \^add " username password [credentials = user]"
|
||||||
|
.TP
|
||||||
|
.BI \^del " username"
|
||||||
|
.TP
|
||||||
|
.BI \^mod " username credentials"
|
||||||
|
.TP
|
||||||
|
.BI \^pass " username password"
|
||||||
|
.TP
|
||||||
|
.BI \^list
|
||||||
|
.SH "PARAMETERS"
|
||||||
|
.TP
|
||||||
|
.B 'filename'
|
||||||
|
is a database file
|
||||||
|
.TP
|
||||||
|
.B 'username'
|
||||||
|
is a nickname (UTF\-8, up to 64 bytes)
|
||||||
|
.TP
|
||||||
|
.B 'password'
|
||||||
|
is a password (UTF\-8, up to 64 bytes)
|
||||||
|
.TP
|
||||||
|
.B 'credentials'
|
||||||
|
is one of 'admin', 'super', 'op', 'user'
|
||||||
|
.SH AUTHOR
|
||||||
|
This program was written by Jan Vidar Krey <janvidar@extatic.org>
|
||||||
|
.SH "BUG REPORTS"
|
||||||
|
If you find a bug in uhub please report it to
|
||||||
|
.B https://github.com/janvidar/uhub/issues
|
@ -23,7 +23,7 @@ on high-end servers, or a small private hub on embedded hardware.
|
|||||||
.SH "OPTIONS"
|
.SH "OPTIONS"
|
||||||
.TP
|
.TP
|
||||||
.BI \^\-v
|
.BI \^\-v
|
||||||
Verbose mode, add more -v's for higher verbosity.
|
Verbose mode, add more \-v's for higher verbosity.
|
||||||
.TP
|
.TP
|
||||||
.BI \^\-q
|
.BI \^\-q
|
||||||
Quiet mode, if quiet mode is enabled no output or logs are made.
|
Quiet mode, if quiet mode is enabled no output or logs are made.
|
||||||
@ -69,4 +69,4 @@ To run uhub as a daemon, and log to a file:
|
|||||||
This program was written by Jan Vidar Krey <janvidar@extatic.org>
|
This program was written by Jan Vidar Krey <janvidar@extatic.org>
|
||||||
.SH "BUG REPORTS"
|
.SH "BUG REPORTS"
|
||||||
If you find a bug in uhub please report it to
|
If you find a bug in uhub please report it to
|
||||||
.B http://bugs.extatic.org/
|
.B https://github.com/janvidar/uhub/issues
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# uhub.conf - A example configuration file.
|
# uhub.conf - A example configuration file.
|
||||||
# You should normally place this file in /etc/uhub/uhub.conf
|
# You should normally place this file in /etc/uhub/uhub.conf
|
||||||
# And change the file_acl and file_motd below.
|
# and customize some of the settings below.
|
||||||
#
|
#
|
||||||
# This file is read only to the uhub deamon, and if you
|
# This file is read only to the uhub daemon, and if you
|
||||||
# make changes to it while uhub is running you can send a
|
# make changes to it while uhub is running you can send a
|
||||||
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
||||||
# All configuration directives: http://www.uhub.org/config.php
|
# All configuration directives: https://www.uhub.org/config.php
|
||||||
|
|
||||||
# Bind to this port and address
|
# Bind to this port and address
|
||||||
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
||||||
@ -38,17 +38,8 @@ hub_enabled=1
|
|||||||
# Access control list (user database)
|
# Access control list (user database)
|
||||||
file_acl=/etc/uhub/users.conf
|
file_acl=/etc/uhub/users.conf
|
||||||
|
|
||||||
# This file can contain a message of the day. A welcome
|
# This file can contain a conf for plugin subsystem
|
||||||
# message send to any client when connecting.
|
file_plugins = /etc/uhub/plugins.conf
|
||||||
# If the file does not exist, is empty, or cannot be opened
|
|
||||||
# the motd will not be sent to the clients.
|
|
||||||
# Normally this message is sent to clients when connecting.
|
|
||||||
file_motd=/etc/uhub/motd.txt
|
|
||||||
|
|
||||||
# This file can contain a rules of the hub.
|
|
||||||
# Normally this message is sent to clients when write in chat !rules
|
|
||||||
file_rules=/etc/uhub/rules.txt
|
|
||||||
|
|
||||||
|
|
||||||
# Slots/share/hubs limits
|
# Slots/share/hubs limits
|
||||||
limit_max_hubs_user = 0
|
limit_max_hubs_user = 0
|
||||||
@ -82,9 +73,6 @@ flood_ctl_extras=5
|
|||||||
# if chat_is_privileged=yes only registered users may write in main chat
|
# if chat_is_privileged=yes only registered users may write in main chat
|
||||||
chat_is_privileged = no
|
chat_is_privileged = no
|
||||||
|
|
||||||
# if chat_only = yes then search and transfer functionality is disabled for
|
|
||||||
# non-operator users.
|
|
||||||
chat_only = no
|
|
||||||
|
|
||||||
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
|
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
|
||||||
# defaults obsolete_clients=1
|
# defaults obsolete_clients=1
|
||||||
@ -116,11 +104,11 @@ msg_auth_invalid_password = Password is wrong
|
|||||||
msg_auth_user_not_found = User not found in password database
|
msg_auth_user_not_found = User not found in password database
|
||||||
msg_user_share_size_low = User is not sharing enough
|
msg_user_share_size_low = User is not sharing enough
|
||||||
msg_user_share_size_high = User is sharing too much
|
msg_user_share_size_high = User is sharing too much
|
||||||
msg_user_slots_low = User have too few upload slots
|
msg_user_slots_low = User has too few upload slots
|
||||||
msg_user_slots_high = User have too many 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_low = User is on too few hubs
|
||||||
msg_user_hub_limit_high = User is on too many hubs
|
msg_user_hub_limit_high = User is on too many hubs
|
||||||
msg_error_no_memory = No memory
|
msg_error_no_memory = Out of memory
|
||||||
msg_user_flood_chat = Chat flood detected, messages are dropped.
|
msg_user_flood_chat = Chat flood detected, messages are dropped.
|
||||||
msg_user_flood_connect = Connect flood detected, connection refused.
|
msg_user_flood_connect = Connect flood detected, connection refused.
|
||||||
msg_user_flood_search = Search flood detected, search is stopped.
|
msg_user_flood_search = Search flood detected, search is stopped.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
inherit eutils
|
inherit eutils
|
||||||
|
|
||||||
if [ "$PV" != "9999" ]; then
|
if [ "$PV" != "9999" ]; then
|
||||||
SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
|
SRC_URI="https://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
|
||||||
KEYWORDS="~amd64 ~x86"
|
KEYWORDS="~amd64 ~x86"
|
||||||
else
|
else
|
||||||
inherit git
|
inherit git
|
||||||
@ -16,7 +16,7 @@ fi
|
|||||||
EAPI="2"
|
EAPI="2"
|
||||||
|
|
||||||
DESCRIPTION="High performance ADC hub"
|
DESCRIPTION="High performance ADC hub"
|
||||||
HOMEPAGE="http://www.uhub.org/"
|
HOMEPAGE="https://www.uhub.org/"
|
||||||
|
|
||||||
LICENSE="GPL-3"
|
LICENSE="GPL-3"
|
||||||
SLOT="0"
|
SLOT="0"
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
Summary: High performance ADC p2p hub.
|
Summary: High performance ADC p2p hub.
|
||||||
Name: uhub
|
Name: uhub
|
||||||
Version: 0.3.1
|
Version: 0.4.0
|
||||||
Release: 3
|
Release: 2
|
||||||
License: GPLv3
|
License: GPLv3
|
||||||
Group: Networking/File transfer
|
Group: Networking/File transfer
|
||||||
Source: uhub-%{version}.tar.gz
|
Source: uhub-%{version}.tar.gz
|
||||||
URL: http://www.uhub.org
|
URL: https://www.uhub.org
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||||
|
|
||||||
|
BuildRequires: sqlite-devel
|
||||||
|
BuildRequires: openssl-devel
|
||||||
|
|
||||||
%description
|
%description
|
||||||
uhub is a high performance peer-to-peer hub for the ADC network.
|
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||||
@ -20,7 +22,10 @@ Key features:
|
|||||||
- Experimental SSL support (optional)
|
- Experimental SSL support (optional)
|
||||||
- Advanced access control support
|
- Advanced access control support
|
||||||
- Easy configuration
|
- Easy configuration
|
||||||
|
- plugin support
|
||||||
|
- mod_welcome - MOTD\RULES messages
|
||||||
|
- mod_auth_sipmle - auth with sqlite DB
|
||||||
|
- mod_logging - log hub activity
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{version}
|
%setup -q -n %{name}-%{version}
|
||||||
@ -36,15 +41,18 @@ mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
|||||||
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
||||||
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||||
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/lib/uhub
|
||||||
|
|
||||||
install uhub $RPM_BUILD_ROOT/usr/bin/
|
install uhub $RPM_BUILD_ROOT/usr/bin/
|
||||||
|
install uhub-passwd $RPM_BUILD_ROOT/usr/bin/
|
||||||
> doc/motd.txt
|
> doc/motd.txt
|
||||||
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt $RPM_BUILD_ROOT/etc/uhub
|
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt doc/plugins.conf doc/users.db $RPM_BUILD_ROOT/etc/uhub
|
||||||
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
||||||
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
||||||
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
||||||
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
||||||
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
||||||
|
install -m644 mod_*.so $RPM_BUILD_ROOT/usr/lib/uhub
|
||||||
|
|
||||||
|
|
||||||
%files
|
%files
|
||||||
@ -55,12 +63,14 @@ install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
|||||||
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
||||||
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
||||||
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/plugins.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/users.db
|
||||||
%{_sysconfdir}/init.d/uhub
|
%{_sysconfdir}/init.d/uhub
|
||||||
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
||||||
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
||||||
/usr/share/man/man1/uhub.1.gz
|
/usr/share/man/man1/uhub.1.gz
|
||||||
%{_bindir}/uhub
|
%{_bindir}/uhub
|
||||||
|
%{_libdir}/uhub/mod_*.so
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
@ -70,10 +80,17 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
if [ $1 -gt 1 ] ; then
|
if [ $1 -gt 1 ] ; then
|
||||||
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
||||||
fi
|
fi
|
||||||
# need more informations about add services and users in system
|
# need more information about add services and users in system
|
||||||
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
||||||
|
# write SSL create
|
||||||
|
echo "PLS see /usr/share/doc/uhub/"
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Dec 30 2011 E_zombie
|
||||||
|
- add users.db
|
||||||
|
- add new doc
|
||||||
|
* Tue Jun 26 2010 E_zombie
|
||||||
|
- add plugins.conf
|
||||||
* Tue Jan 31 2010 E_zombie
|
* Tue Jan 31 2010 E_zombie
|
||||||
- change GROUP
|
- change GROUP
|
||||||
- chmod for files
|
- chmod for files
|
||||||
|
28
doc/upstart/etc/init/uhub.conf
Normal file
28
doc/upstart/etc/init/uhub.conf
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# uHub - a lightweight but high-performance hub for the ADC
|
||||||
|
# peer-to-peer protocol.
|
||||||
|
|
||||||
|
description "uHub - High performance ADC peer-to-peer hub"
|
||||||
|
|
||||||
|
# Start and stop conditions.
|
||||||
|
start on filesystem or runlevel [2345]
|
||||||
|
stop on runlevel [!2345]
|
||||||
|
|
||||||
|
# Allow the service to respawn, but if its happening too often
|
||||||
|
# (10 times in 5 seconds) there's a problem and we should stop trying.
|
||||||
|
respawn
|
||||||
|
respawn limit 10 5
|
||||||
|
|
||||||
|
# The program is going to fork, and upstart needs to know this
|
||||||
|
# so it can track the change in PID.
|
||||||
|
expect fork
|
||||||
|
|
||||||
|
# Set the mode the process should create files in.
|
||||||
|
umask 022
|
||||||
|
|
||||||
|
# Make sure the log folder exists.
|
||||||
|
pre-start script
|
||||||
|
mkdir -p -m0755 /var/log/uhub
|
||||||
|
end script
|
||||||
|
|
||||||
|
# Command to run it.
|
||||||
|
exec /usr/bin/uhub -f -u uhub -g uhub -l /var/log/uhub/uhub.log -c /etc/uhub/uhub.conf
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,14 +13,18 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HAVE_UHUB_ADC_CONSTANTS_H
|
#ifndef HAVE_UHUB_ADC_CONSTANTS_H
|
||||||
#define HAVE_UHUB_ADC_CONSTANTS_H
|
#define HAVE_UHUB_ADC_CONSTANTS_H
|
||||||
|
|
||||||
|
#ifndef SID_T_DEFINED
|
||||||
typedef uint32_t sid_t;
|
typedef uint32_t sid_t;
|
||||||
|
#define SID_T_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef uint32_t fourcc_t;
|
typedef uint32_t fourcc_t;
|
||||||
|
|
||||||
/* Internal uhub limit */
|
/* Internal uhub limit */
|
||||||
@ -29,7 +33,7 @@ typedef uint32_t fourcc_t;
|
|||||||
#define FOURCC(a,b,c,d) (fourcc_t) ((a << 24) | (b << 16) | (c << 8) | d)
|
#define FOURCC(a,b,c,d) (fourcc_t) ((a << 24) | (b << 16) | (c << 8) | d)
|
||||||
|
|
||||||
/* default welcome protocol support message, as sent by this server */
|
/* default welcome protocol support message, as sent by this server */
|
||||||
#define ADC_PROTO_SUPPORT "ADBASE ADTIGR ADPING"
|
#define ADC_PROTO_SUPPORT "ADBASE ADTIGR ADPING ADUCMD"
|
||||||
|
|
||||||
/* Server sent commands */
|
/* Server sent commands */
|
||||||
#define ADC_CMD_ISID FOURCC('I','S','I','D')
|
#define ADC_CMD_ISID FOURCC('I','S','I','D')
|
||||||
@ -60,6 +64,11 @@ typedef uint32_t fourcc_t;
|
|||||||
#define ADC_CMD_FSCH FOURCC('F','S','C','H')
|
#define ADC_CMD_FSCH FOURCC('F','S','C','H')
|
||||||
#define ADC_CMD_DRES FOURCC('D','R','E','S')
|
#define ADC_CMD_DRES FOURCC('D','R','E','S')
|
||||||
|
|
||||||
|
/* invalid search results (spam) */
|
||||||
|
#define ADC_CMD_BRES FOURCC('B','R','E','S')
|
||||||
|
#define ADC_CMD_ERES FOURCC('E','R','E','S')
|
||||||
|
#define ADC_CMD_FRES FOURCC('F','R','E','S')
|
||||||
|
|
||||||
/* connection setup */
|
/* connection setup */
|
||||||
#define ADC_CMD_DCTM FOURCC('D','C','T','M')
|
#define ADC_CMD_DCTM FOURCC('D','C','T','M')
|
||||||
#define ADC_CMD_DRCM FOURCC('D','R','C','M')
|
#define ADC_CMD_DRCM FOURCC('D','R','C','M')
|
||||||
@ -76,10 +85,23 @@ typedef uint32_t fourcc_t;
|
|||||||
#define ADC_CMD_DINF FOURCC('D','I','N','F')
|
#define ADC_CMD_DINF FOURCC('D','I','N','F')
|
||||||
#define ADC_CMD_EINF FOURCC('E','I','N','F')
|
#define ADC_CMD_EINF FOURCC('E','I','N','F')
|
||||||
#define ADC_CMD_FINF FOURCC('F','I','N','F')
|
#define ADC_CMD_FINF FOURCC('F','I','N','F')
|
||||||
|
#define ADC_CMD_BQUI FOURCC('B','Q','U','I')
|
||||||
|
#define ADC_CMD_DQUI FOURCC('D','Q','U','I')
|
||||||
|
#define ADC_CMD_EQUI FOURCC('E','Q','U','I')
|
||||||
|
#define ADC_CMD_FQUI FOURCC('F','Q','U','I')
|
||||||
|
|
||||||
/* Extension messages */
|
/* Extension messages */
|
||||||
#define ADC_CMD_HCHK FOURCC('H','C','H','K')
|
#define ADC_CMD_HCHK FOURCC('H','C','H','K')
|
||||||
|
|
||||||
|
/* UCMD Extension */
|
||||||
|
#define ADC_CMD_BCMD FOURCC('B','C','M','D')
|
||||||
|
#define ADC_CMD_DCMD FOURCC('D','C','M','D')
|
||||||
|
#define ADC_CMD_ECMD FOURCC('E','C','M','D')
|
||||||
|
#define ADC_CMD_FCMD FOURCC('F','C','M','D')
|
||||||
|
#define ADC_CMD_HCMD FOURCC('H','C','M','D')
|
||||||
|
#define ADC_CMD_ICMD FOURCC('I','C','M','D')
|
||||||
|
|
||||||
|
|
||||||
#define ADC_INF_FLAG_IPV4_ADDR "I4" /* ipv4 address */
|
#define ADC_INF_FLAG_IPV4_ADDR "I4" /* ipv4 address */
|
||||||
#define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */
|
#define ADC_INF_FLAG_IPV6_ADDR "I6" /* ipv6 address */
|
||||||
#define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */
|
#define ADC_INF_FLAG_IPV4_UDP_PORT "U4" /* port number */
|
||||||
@ -89,12 +111,15 @@ typedef uint32_t fourcc_t;
|
|||||||
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
|
#define ADC_INF_FLAG_CLIENT_ID "ID" /* client id, aka CID */
|
||||||
#define ADC_INF_FLAG_NICK "NI" /* nick name */
|
#define ADC_INF_FLAG_NICK "NI" /* nick name */
|
||||||
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
|
#define ADC_INF_FLAG_DESCRIPTION "DE" /* user description */
|
||||||
#define ADC_INF_FLAG_USER_AGENT "VE" /* software version */
|
|
||||||
|
#define ADC_INF_FLAG_USER_AGENT_PRODUCT "AP" /* software name */
|
||||||
|
#define ADC_INF_FLAG_USER_AGENT_VERSION "VE" /* software version */
|
||||||
|
|
||||||
#define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */
|
#define ADC_INF_FLAG_SUPPORT "SU" /* support (extensions, feature cast) */
|
||||||
#define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */
|
#define ADC_INF_FLAG_SHARED_SIZE "SS" /* size of total files shared in bytes */
|
||||||
#define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */
|
#define ADC_INF_FLAG_SHARED_FILES "SF" /* number of files shared */
|
||||||
#define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed acheived in bytes/sec */
|
#define ADC_INF_FLAG_UPLOAD_SPEED "US" /* maximum upload speed achieved in bytes/sec */
|
||||||
#define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download speed acheived in bytes/sec */
|
#define ADC_INF_FLAG_DOWNLOAD_SPEED "DS" /* maximum download speed achieved in bytes/sec */
|
||||||
#define ADC_INF_FLAG_UPLOAD_SLOTS "SL" /* maximum upload slots (concurrent uploads) */
|
#define ADC_INF_FLAG_UPLOAD_SLOTS "SL" /* maximum upload slots (concurrent uploads) */
|
||||||
#define ADC_INF_FLAG_AUTO_SLOTS "AS" /* automatic slot if upload speed is less than this in bytes/sec */
|
#define ADC_INF_FLAG_AUTO_SLOTS "AS" /* automatic slot if upload speed is less than this in bytes/sec */
|
||||||
#define ADC_INF_FLAG_AUTO_SLOTS_MAX "AM" /* maximum number of automatic slots */
|
#define ADC_INF_FLAG_AUTO_SLOTS_MAX "AM" /* maximum number of automatic slots */
|
||||||
@ -109,7 +134,7 @@ typedef uint32_t fourcc_t;
|
|||||||
#define ADC_MSG_FLAG_PRIVATE "PM" /* message is a private message */
|
#define ADC_MSG_FLAG_PRIVATE "PM" /* message is a private message */
|
||||||
|
|
||||||
#define ADC_SCH_FLAG_INCLUDE "AN" /* include given search term */
|
#define ADC_SCH_FLAG_INCLUDE "AN" /* include given search term */
|
||||||
#define ADC_SCH_FLAG_EXCLUDE "NO" /* exclude given serach term */
|
#define ADC_SCH_FLAG_EXCLUDE "NO" /* exclude given search term */
|
||||||
#define ADC_SCH_FLAG_FILE_EXTENSION "EX" /* search only for files with the given file extension */
|
#define ADC_SCH_FLAG_FILE_EXTENSION "EX" /* search only for files with the given file extension */
|
||||||
#define ADC_SCH_FLAG_FILE_TYPE "TY" /* search only for files with this file type (separate type) */
|
#define ADC_SCH_FLAG_FILE_TYPE "TY" /* search only for files with this file type (separate type) */
|
||||||
#define ADC_SCH_FLAG_LESS_THAN "LE" /* search for files with this size or less */
|
#define ADC_SCH_FLAG_LESS_THAN "LE" /* search for files with this size or less */
|
||||||
@ -134,6 +159,7 @@ typedef uint32_t fourcc_t;
|
|||||||
#define ADC_CLIENT_TYPE_BOT "1"
|
#define ADC_CLIENT_TYPE_BOT "1"
|
||||||
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
|
#define ADC_CLIENT_TYPE_REGISTERED_USER "2"
|
||||||
#define ADC_CLIENT_TYPE_OPERATOR "4"
|
#define ADC_CLIENT_TYPE_OPERATOR "4"
|
||||||
|
#define ADC_CLIENT_TYPE_HUBBOT "5" /* 1 + 4 */
|
||||||
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
|
#define ADC_CLIENT_TYPE_SUPER_USER "12" /* 8 + 4 */
|
||||||
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
|
#define ADC_CLIENT_TYPE_ADMIN "20" /* 16 + 4 = hub owner */
|
||||||
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */
|
#define ADC_CLIENT_TYPE_HUB "32" /* the hub itself */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,7 +24,6 @@
|
|||||||
uhub_assert(X); \
|
uhub_assert(X); \
|
||||||
uhub_assert(X->cache); \
|
uhub_assert(X->cache); \
|
||||||
uhub_assert(X->capacity); \
|
uhub_assert(X->capacity); \
|
||||||
uhub_assert(X->length); \
|
|
||||||
uhub_assert(X->length <= X->capacity); \
|
uhub_assert(X->length <= X->capacity); \
|
||||||
uhub_assert(X->references > 0); \
|
uhub_assert(X->references > 0); \
|
||||||
uhub_assert(X->length == strlen(X->cache));
|
uhub_assert(X->length == strlen(X->cache));
|
||||||
@ -63,6 +62,33 @@ static void msg_free(void* ptr)
|
|||||||
#define msg_free(X) hub_free(X)
|
#define msg_free(X) hub_free(X)
|
||||||
#endif /* MSG_MEMORY_DEBUG */
|
#endif /* MSG_MEMORY_DEBUG */
|
||||||
|
|
||||||
|
static int msg_check_escapes(const char* string, size_t len)
|
||||||
|
{
|
||||||
|
char* start = (char*) string;
|
||||||
|
while ((start = memchr(start, '\\', len - (start - string))))
|
||||||
|
{
|
||||||
|
if (start+1 == (string + len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (*(++start))
|
||||||
|
{
|
||||||
|
case '\\':
|
||||||
|
case 'n':
|
||||||
|
case 's':
|
||||||
|
/* Increment so we don't check the escaped
|
||||||
|
* character next time around. Not doing so
|
||||||
|
* leads to messages with escaped backslashes
|
||||||
|
* being incorrectly reported as having invalid
|
||||||
|
* escapes. */
|
||||||
|
++start;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||||
{
|
{
|
||||||
@ -127,7 +153,7 @@ static int adc_msg_cache_append(struct adc_message* msg, const char* string, siz
|
|||||||
memcpy(&msg->cache[msg->length], string, len);
|
memcpy(&msg->cache[msg->length], string, len);
|
||||||
adc_msg_set_length(msg, msg->length + len);
|
adc_msg_set_length(msg, msg->length + len);
|
||||||
|
|
||||||
assert(msg->capacity > msg->length);
|
uhub_assert(msg->capacity > msg->length);
|
||||||
msg->cache[msg->length] = 0;
|
msg->cache[msg->length] = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -256,23 +282,19 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
if (cmd->feature_cast_include)
|
if (cmd->feature_cast_include)
|
||||||
{
|
{
|
||||||
copy->feature_cast_include = list_create();
|
copy->feature_cast_include = list_create();
|
||||||
tmp = list_get_first(cmd->feature_cast_include);
|
LIST_FOREACH(char*, tmp, cmd->feature_cast_include,
|
||||||
while (tmp)
|
|
||||||
{
|
{
|
||||||
list_append(copy->feature_cast_include, hub_strdup(tmp));
|
list_append(copy->feature_cast_include, hub_strdup(tmp));
|
||||||
tmp = list_get_next(cmd->feature_cast_include);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd->feature_cast_exclude)
|
if (cmd->feature_cast_exclude)
|
||||||
{
|
{
|
||||||
copy->feature_cast_exclude = list_create();
|
copy->feature_cast_exclude = list_create();
|
||||||
tmp = list_get_first(cmd->feature_cast_exclude);
|
LIST_FOREACH(char*, tmp, cmd->feature_cast_exclude,
|
||||||
while (tmp)
|
|
||||||
{
|
{
|
||||||
list_append(copy->feature_cast_exclude, hub_strdup(tmp));
|
list_append(copy->feature_cast_exclude, hub_strdup(tmp));
|
||||||
tmp = list_get_next(cmd->feature_cast_exclude);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ADC_MSG_ASSERT(copy);
|
ADC_MSG_ASSERT(copy);
|
||||||
@ -288,7 +310,7 @@ struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, s
|
|||||||
if (!command)
|
if (!command)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (command->source && (!u || command->source != u->id.sid))
|
if (command->source && (!u || (command->source != u->id.sid && !auth_cred_is_unrestricted(u->credentials))))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
|
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
|
||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
@ -319,6 +341,13 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!msg_check_escapes(line, length))
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Dropped message with invalid ADC escape.");
|
||||||
|
msg_free(command);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (line[length-1] != '\n')
|
if (line[length-1] != '\n')
|
||||||
{
|
{
|
||||||
need_terminate = 1;
|
need_terminate = 1;
|
||||||
@ -498,6 +527,30 @@ struct adc_message* adc_msg_create(const char* line)
|
|||||||
return adc_msg_parse(line, strlen(line));
|
return adc_msg_parse(line, strlen(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size)
|
||||||
|
{
|
||||||
|
struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 1);
|
||||||
|
if (!msg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
adc_msg_add_argument(msg, sid_to_string(source));
|
||||||
|
msg->source = source;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size)
|
||||||
|
{
|
||||||
|
struct adc_message* msg = adc_msg_construct(fourcc, size + 4 + 4 + 1);
|
||||||
|
if (!msg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
adc_msg_add_argument(msg, sid_to_string(source));
|
||||||
|
adc_msg_add_argument(msg, sid_to_string(dest));
|
||||||
|
msg->source = source;
|
||||||
|
msg->target = dest;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||||
{
|
{
|
||||||
@ -505,9 +558,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
|||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
if (size < sizeof(fourcc)) size = sizeof(fourcc);
|
if (!adc_msg_grow(msg, sizeof(fourcc) + size + 1))
|
||||||
|
|
||||||
if (!adc_msg_grow(msg, size+1))
|
|
||||||
{
|
{
|
||||||
msg_free(msg);
|
msg_free(msg);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
@ -600,7 +651,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
|
|||||||
while (start)
|
while (start)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if ((&start[0] - &cmd->cache[0]) < 1+cmd->length)
|
if ((size_t) (&start[0] - &cmd->cache[0]) < 1+cmd->length)
|
||||||
start = memmem(&start[1], (&cmd->cache[cmd->length] - &start[0]), prefix, 3);
|
start = memmem(&start[1], (&cmd->cache[cmd->length] - &start[0]), prefix, 3);
|
||||||
else
|
else
|
||||||
start = NULL;
|
start = NULL;
|
||||||
@ -877,12 +928,47 @@ char* adc_msg_unescape(const char* string)
|
|||||||
return new_string;
|
return new_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size)
|
||||||
|
{
|
||||||
|
size_t w = 0;
|
||||||
|
char* ptr = (char*) target;
|
||||||
|
char* str = (char*) string;
|
||||||
|
int escaped = 0;
|
||||||
|
|
||||||
|
while (*str && w < (target_size-1))
|
||||||
|
{
|
||||||
|
if (escaped) {
|
||||||
|
if (*str == 's')
|
||||||
|
*ptr++ = ' ';
|
||||||
|
else if (*str == '\\')
|
||||||
|
*ptr++ = '\\';
|
||||||
|
else if (*str == 'n')
|
||||||
|
*ptr++ = '\n';
|
||||||
|
else
|
||||||
|
*ptr++ = *str;
|
||||||
|
w++;
|
||||||
|
escaped = 0;
|
||||||
|
} else {
|
||||||
|
if (*str == '\\')
|
||||||
|
escaped = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ptr++ = *str;
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
*ptr = 0;
|
||||||
|
w++;
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
char* adc_msg_escape(const char* string)
|
char* adc_msg_escape(const char* string)
|
||||||
{
|
{
|
||||||
char* str = hub_malloc(adc_msg_escape_length(string)+1);
|
char* str = hub_malloc(adc_msg_escape_length(string)+1);
|
||||||
int n = 0;
|
size_t n = 0;
|
||||||
int i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < strlen(string); i++)
|
for (i = 0; i < strlen(string); i++)
|
||||||
{
|
{
|
||||||
switch (string[i]) {
|
switch (string[i]) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ enum msg_status_level
|
|||||||
extern struct adc_message* adc_msg_incref(struct adc_message* msg);
|
extern struct adc_message* adc_msg_incref(struct adc_message* msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrease the reference counter, and free the memory when apropriate.
|
* Decrease the reference counter, and free the memory when appropriate.
|
||||||
*/
|
*/
|
||||||
extern void adc_msg_free(struct adc_message* msg);
|
extern void adc_msg_free(struct adc_message* msg);
|
||||||
|
|
||||||
@ -91,6 +91,13 @@ extern struct adc_message* adc_msg_create(const char* string);
|
|||||||
*/
|
*/
|
||||||
extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
|
extern struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a message for the given 'fourcc' and add a source SID to it,
|
||||||
|
* in addition pre-allocate 'size' bytes at the end of the message.
|
||||||
|
*/
|
||||||
|
extern struct adc_message* adc_msg_construct_source(fourcc_t fourcc, sid_t source, size_t size);
|
||||||
|
extern struct adc_message* adc_msg_construct_source_dest(fourcc_t fourcc, sid_t source, sid_t dest, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a named argument from the command.
|
* Remove a named argument from the command.
|
||||||
*
|
*
|
||||||
@ -152,7 +159,7 @@ extern char* adc_msg_get_argument(struct adc_message* cmd, int offset);
|
|||||||
*
|
*
|
||||||
* @arg prefix a 2 character argument prefix
|
* @arg prefix a 2 character argument prefix
|
||||||
* @arg string must be escaped (see adc_msg_escape).
|
* @arg string must be escaped (see adc_msg_escape).
|
||||||
* @return 0 if successful, or -1 if an error occured.
|
* @return 0 if successful, or -1 if an error occurred.
|
||||||
*/
|
*/
|
||||||
extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||||
|
|
||||||
@ -160,7 +167,7 @@ extern int adc_msg_replace_named_argument(struct adc_message* cmd, const char pr
|
|||||||
* Append an argument
|
* Append an argument
|
||||||
*
|
*
|
||||||
* @arg string must be escaped (see adc_msg_escape).
|
* @arg string must be escaped (see adc_msg_escape).
|
||||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
* @return 0 if successful, or -1 if an error occurred (out of memory).
|
||||||
*/
|
*/
|
||||||
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
||||||
|
|
||||||
@ -169,7 +176,7 @@ extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
|||||||
*
|
*
|
||||||
* @arg prefix a 2 character argument prefix
|
* @arg prefix a 2 character argument prefix
|
||||||
* @arg string must be escaped (see adc_msg_escape).
|
* @arg string must be escaped (see adc_msg_escape).
|
||||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
* @return 0 if successful, or -1 if an error occurred (out of memory).
|
||||||
*/
|
*/
|
||||||
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||||
|
|
||||||
@ -179,7 +186,7 @@ extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix
|
|||||||
*
|
*
|
||||||
* @arg prefix a 2 character argument prefix
|
* @arg prefix a 2 character argument prefix
|
||||||
* @arg string must NOT be escaped
|
* @arg string must NOT be escaped
|
||||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
* @return 0 if successful, or -1 if an error occurred (out of memory).
|
||||||
*/
|
*/
|
||||||
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
|
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||||
|
|
||||||
@ -195,6 +202,14 @@ extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char
|
|||||||
*/
|
*/
|
||||||
extern char* adc_msg_unescape(const char* string);
|
extern char* adc_msg_unescape(const char* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a ADC command escaped string to a regular string.
|
||||||
|
* @return The number of bytes written to target. If the target is not large enough then
|
||||||
|
* the -1 is returned, but the string is guaranteed to always be \0 terminated.
|
||||||
|
*/
|
||||||
|
extern int adc_msg_unescape_to_target(const char* string, char* target, size_t target_size);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a string to a ADC command escaped string.
|
* Convert a string to a ADC command escaped string.
|
||||||
* @return adc command escaped string or NULL if out of memory.
|
* @return adc command escaped string or NULL if out of memory.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -119,6 +119,7 @@ void sid_pool_destroy(struct sid_pool* pool)
|
|||||||
|
|
||||||
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
||||||
{
|
{
|
||||||
|
sid_t n;
|
||||||
if (pool->count >= (pool->max - pool->min))
|
if (pool->count >= (pool->max - pool->min))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_SID
|
#ifdef DEBUG_SID
|
||||||
@ -127,7 +128,7 @@ sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sid_t n = (++pool->count);
|
n = (++pool->count);
|
||||||
for (; (pool->map[n % pool->max]); n++) ;
|
for (; (pool->map[n % pool->max]); n++) ;
|
||||||
|
|
||||||
#ifdef DEBUG_SID
|
#ifdef DEBUG_SID
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -25,7 +25,6 @@
|
|||||||
struct sid_pool;
|
struct sid_pool;
|
||||||
struct hub_user;
|
struct hub_user;
|
||||||
|
|
||||||
extern const char* BASE32_ALPHABET;
|
|
||||||
extern char* sid_to_string(sid_t sid_);
|
extern char* sid_to_string(sid_t sid_);
|
||||||
extern sid_t string_to_sid(const char* sid);
|
extern sid_t string_to_sid(const char* sid);
|
||||||
|
|
||||||
|
153
src/core/auth.c
153
src/core/auth.c
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -23,32 +23,13 @@
|
|||||||
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
||||||
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
||||||
|
|
||||||
const char* get_user_credential_string(enum user_credentials cred)
|
|
||||||
{
|
|
||||||
switch (cred)
|
|
||||||
{
|
|
||||||
case cred_none: return "none";
|
|
||||||
case cred_bot: return "bot";
|
|
||||||
case cred_guest: return "guest";
|
|
||||||
case cred_user: return "user";
|
|
||||||
case cred_operator: return "operator";
|
|
||||||
case cred_super: return "super";
|
|
||||||
case cred_admin: return "admin";
|
|
||||||
case cred_link: return "link";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
};
|
|
||||||
|
|
||||||
static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count)
|
static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count)
|
||||||
{
|
{
|
||||||
char* data;
|
char* data;
|
||||||
char* data_extra;
|
|
||||||
|
|
||||||
if (!strncmp(line, cmd, strlen(cmd)))
|
if (!strncmp(line, cmd, strlen(cmd)))
|
||||||
{
|
{
|
||||||
data = &line[strlen(cmd)];
|
data = &line[strlen(cmd)];
|
||||||
data_extra = 0;
|
|
||||||
data[0] = '\0';
|
data[0] = '\0';
|
||||||
data++;
|
data++;
|
||||||
|
|
||||||
@ -70,7 +51,7 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
|||||||
{
|
{
|
||||||
char* data;
|
char* data;
|
||||||
char* data_extra;
|
char* data_extra;
|
||||||
struct hub_user_access_info* info = 0;
|
struct auth_info* info = 0;
|
||||||
|
|
||||||
if (!strncmp(line, cmd, strlen(cmd)))
|
if (!strncmp(line, cmd, strlen(cmd)))
|
||||||
{
|
{
|
||||||
@ -86,7 +67,7 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
info = hub_malloc_zero(sizeof(struct auth_info));
|
||||||
|
|
||||||
if (!info)
|
if (!info)
|
||||||
{
|
{
|
||||||
@ -104,11 +85,12 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info->username = hub_strdup(data);
|
strncpy(info->nickname, data, MAX_NICK_LEN);
|
||||||
info->password = data_extra ? hub_strdup(data_extra) : 0;
|
if (data_extra)
|
||||||
info->status = status;
|
strncpy(info->password, data_extra, MAX_PASS_LEN);
|
||||||
|
info->credentials = status;
|
||||||
list_append(list, info);
|
list_append(list, info);
|
||||||
LOG_DEBUG("ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
|
LOG_DEBUG("ACL: Added user '%s' (%s)", info->nickname, auth_cred_to_string(info->credentials));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -187,12 +169,15 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
|
|
||||||
LOG_DEBUG("acl_parse_line: '%s'", line);
|
LOG_DEBUG("acl_parse_line: '%s'", line);
|
||||||
|
|
||||||
ACL_ADD_USER("bot", handle->users, cred_bot);
|
ACL_ADD_USER("bot", handle->users, auth_cred_bot);
|
||||||
ACL_ADD_USER("user_admin", handle->users, cred_admin);
|
ACL_ADD_USER("ubot", handle->users, auth_cred_ubot);
|
||||||
ACL_ADD_USER("user_super", handle->users, cred_super);
|
ACL_ADD_USER("opbot", handle->users, auth_cred_opbot);
|
||||||
ACL_ADD_USER("user_op", handle->users, cred_operator);
|
ACL_ADD_USER("opubot", handle->users, auth_cred_opubot);
|
||||||
ACL_ADD_USER("user_reg", handle->users, cred_user);
|
ACL_ADD_USER("user_admin", handle->users, auth_cred_admin);
|
||||||
ACL_ADD_USER("link", handle->users, cred_link);
|
ACL_ADD_USER("user_super", handle->users, auth_cred_super);
|
||||||
|
ACL_ADD_USER("user_op", handle->users, auth_cred_operator);
|
||||||
|
ACL_ADD_USER("user_reg", handle->users, auth_cred_user);
|
||||||
|
ACL_ADD_USER("link", handle->users, auth_cred_link);
|
||||||
ACL_ADD_BOOL("deny_nick", handle->users_denied);
|
ACL_ADD_BOOL("deny_nick", handle->users_denied);
|
||||||
ACL_ADD_BOOL("ban_nick", handle->users_banned);
|
ACL_ADD_BOOL("ban_nick", handle->users_banned);
|
||||||
ACL_ADD_BOOL("ban_cid", handle->cids);
|
ACL_ADD_BOOL("ban_cid", handle->cids);
|
||||||
@ -243,11 +228,9 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
|
|||||||
|
|
||||||
static void acl_free_access_info(void* ptr)
|
static void acl_free_access_info(void* ptr)
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = (struct hub_user_access_info*) ptr;
|
struct auth_info* info = (struct auth_info*) ptr;
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
hub_free(info->username);
|
|
||||||
hub_free(info->password);
|
|
||||||
hub_free(info);
|
hub_free(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,34 +284,60 @@ int acl_shutdown(struct acl_handle* handle)
|
|||||||
list_destroy(handle->nat_override);
|
list_destroy(handle->nat_override);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
memset(handle, 0, sizeof(struct acl_handle));
|
memset(handle, 0, sizeof(struct acl_handle));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int acl_register_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
if (plugin_auth_register_user(hub, info) != st_allow)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
|
extern int acl_update_user(struct hub_info* hub, struct auth_info* info)
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = (struct hub_user_access_info*) list_get_first(handle->users);
|
if (plugin_auth_update_user(hub, info) != st_allow)
|
||||||
while (info)
|
|
||||||
{
|
{
|
||||||
if (strcasecmp(info->username, name) == 0)
|
return 0;
|
||||||
{
|
|
||||||
return info;
|
|
||||||
}
|
}
|
||||||
info = (struct hub_user_access_info*) list_get_next(handle->users);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int acl_delete_user(struct hub_info* hub, const char* name)
|
||||||
|
{
|
||||||
|
struct auth_info data;
|
||||||
|
strncpy(data.nickname, name, MAX_NICK_LEN);
|
||||||
|
data.nickname[MAX_NICK_LEN] = '\0';
|
||||||
|
data.password[0] = '\0';
|
||||||
|
data.credentials = auth_cred_none;
|
||||||
|
if (plugin_auth_delete_user(hub, &data) != st_allow)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name)
|
||||||
|
{
|
||||||
|
struct auth_info* info = 0;
|
||||||
|
info = (struct auth_info*) hub_malloc(sizeof(struct auth_info));
|
||||||
|
if (plugin_auth_get_user(hub, name, info) != st_allow)
|
||||||
|
{
|
||||||
|
hub_free(info);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
#define STR_LIST_CONTAINS(LIST, STR) \
|
#define STR_LIST_CONTAINS(LIST, STR) \
|
||||||
str = (char*) list_get_first(LIST); \
|
LIST_FOREACH(char*, str, LIST, \
|
||||||
while (str) \
|
|
||||||
{ \
|
{ \
|
||||||
if (strcasecmp(str, STR) == 0) \
|
if (strcasecmp(str, STR) == 0) \
|
||||||
return 1; \
|
return 1; \
|
||||||
str = (char*) list_get_next(LIST); \
|
}); \
|
||||||
} \
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
||||||
@ -392,34 +401,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)
|
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
|
||||||
{
|
{
|
||||||
struct ip_addr_encap raw;
|
struct ip_addr_encap raw;
|
||||||
struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
|
struct ip_range* info;
|
||||||
ip_convert_to_binary(ip_address, &raw);
|
|
||||||
|
|
||||||
while (info)
|
ip_convert_to_binary(ip_address, &raw);
|
||||||
|
LIST_FOREACH(struct ip_range*, info, handle->networks,
|
||||||
{
|
{
|
||||||
if (ip_in_range(&raw, info))
|
if (ip_in_range(&raw, info))
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
});
|
||||||
info = (struct ip_range*) list_get_next(handle->networks);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
||||||
{
|
{
|
||||||
struct ip_addr_encap raw;
|
struct ip_addr_encap raw;
|
||||||
struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
|
struct ip_range* info;
|
||||||
ip_convert_to_binary(ip_address, &raw);
|
|
||||||
|
|
||||||
while (info)
|
ip_convert_to_binary(ip_address, &raw);
|
||||||
|
LIST_FOREACH(struct ip_range*, info, handle->nat_override,
|
||||||
{
|
{
|
||||||
if (ip_in_range(&raw, info))
|
if (ip_in_range(&raw, info))
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
});
|
||||||
info = (struct ip_range*) list_get_next(handle->nat_override);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,7 +433,7 @@ int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
|||||||
* seconds since the unix epoch (modulus 1 million)
|
* seconds since the unix epoch (modulus 1 million)
|
||||||
* and the SID of the user (0-1 million).
|
* and the SID of the user (0-1 million).
|
||||||
*/
|
*/
|
||||||
const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user)
|
const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user)
|
||||||
{
|
{
|
||||||
char buf[64];
|
char buf[64];
|
||||||
uint64_t tiger_res[3];
|
uint64_t tiger_res[3];
|
||||||
@ -446,36 +449,38 @@ const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password)
|
int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
struct hub_user_access_info* access;
|
struct auth_info* access;
|
||||||
const char* challenge;
|
const char* challenge;
|
||||||
char raw_challenge[64];
|
char raw_challenge[64];
|
||||||
char password_calc[64];
|
char password_calc[64];
|
||||||
uint64_t tiger_res[3];
|
uint64_t tiger_res[3];
|
||||||
|
size_t password_len;
|
||||||
|
|
||||||
if (!password || !user || strlen(password) != MAX_CID_LEN)
|
if (!password || !user || strlen(password) != MAX_CID_LEN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
access = acl_get_access_info(acl, user->id.nick);
|
access = acl_get_access_info(hub, user->id.nick);
|
||||||
if (!access || !access->password)
|
if (!access)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (TIGERSIZE+strlen(access->password) >= 1024)
|
challenge = acl_password_generate_challenge(hub, user);
|
||||||
return 0;
|
|
||||||
|
|
||||||
challenge = acl_password_generate_challenge(acl, user);
|
|
||||||
|
|
||||||
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
|
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
|
||||||
|
|
||||||
memcpy(&buf[0], (char*) access->password, strlen(access->password));
|
password_len = strlen(access->password);
|
||||||
memcpy(&buf[strlen(access->password)], raw_challenge, TIGERSIZE);
|
|
||||||
|
|
||||||
tiger((uint64_t*) buf, TIGERSIZE+strlen(access->password), (uint64_t*) tiger_res);
|
memcpy(&buf[0], access->password, password_len);
|
||||||
|
memcpy(&buf[password_len], raw_challenge, TIGERSIZE);
|
||||||
|
|
||||||
|
tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res);
|
||||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
|
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
|
||||||
password_calc[MAX_CID_LEN] = 0;
|
password_calc[MAX_CID_LEN] = 0;
|
||||||
|
|
||||||
|
hub_free(access);
|
||||||
|
|
||||||
if (strcasecmp(password, password_calc) == 0)
|
if (strcasecmp(password, password_calc) == 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -21,30 +21,10 @@
|
|||||||
#define HAVE_UHUB_ACL_H
|
#define HAVE_UHUB_ACL_H
|
||||||
|
|
||||||
struct hub_config;
|
struct hub_config;
|
||||||
|
struct hub_info;
|
||||||
struct hub_user;
|
struct hub_user;
|
||||||
struct ip_addr_encap;
|
struct ip_addr_encap;
|
||||||
|
|
||||||
enum user_credentials
|
|
||||||
{
|
|
||||||
cred_none, /**<<< "User has no credentials (not yet logged in)" */
|
|
||||||
cred_bot, /**<<< "User is a robot" */
|
|
||||||
cred_guest, /**<<< "User is a guest (unregistered user)" */
|
|
||||||
cred_user, /**<<< "User is identified as a registered user" */
|
|
||||||
cred_operator, /**<<< "User is identified as a hub operator" */
|
|
||||||
cred_super, /**<<< "User is a super user" (not used) */
|
|
||||||
cred_admin, /**<<< "User is identified as a hub administrator/owner" */
|
|
||||||
cred_link, /**<<< "User is a link (not used currently)" */
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* get_user_credential_string(enum user_credentials cred);
|
|
||||||
|
|
||||||
struct hub_user_access_info
|
|
||||||
{
|
|
||||||
char* username; /* name of user, cid or IP range */
|
|
||||||
char* password; /* password */
|
|
||||||
enum user_credentials status;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct acl_handle
|
struct acl_handle
|
||||||
{
|
{
|
||||||
struct linked_list* users; /* Known users. See enum user_status */
|
struct linked_list* users; /* Known users. See enum user_status */
|
||||||
@ -59,7 +39,12 @@ struct acl_handle
|
|||||||
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
|
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
|
||||||
extern int acl_shutdown(struct acl_handle* handle);
|
extern int acl_shutdown(struct acl_handle* handle);
|
||||||
|
|
||||||
extern struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
|
extern struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name);
|
||||||
|
extern int acl_register_user(struct hub_info* hub, struct auth_info* info);
|
||||||
|
extern int acl_update_user(struct hub_info* hub, struct auth_info* info);
|
||||||
|
extern int acl_delete_user(struct hub_info* hub, const char* name);
|
||||||
|
|
||||||
|
|
||||||
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
|
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
|
||||||
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
|
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
|
||||||
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
|
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
|
||||||
@ -72,14 +57,14 @@ extern int acl_user_ban_cid(struct acl_handle* handle, const char* cid);
|
|||||||
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
|
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
|
||||||
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
|
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
|
||||||
|
|
||||||
extern const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify a password.
|
* Verify a password.
|
||||||
*
|
*
|
||||||
* @param password the hashed password (based on the nonce).
|
* @param password the hashed password (based on the nonce).
|
||||||
* @return 1 if the password matches, or 0 if the password is incorrect.
|
* @return 1 if the password matches, or 0 if the password is incorrect.
|
||||||
*/
|
*/
|
||||||
extern int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password);
|
extern int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password);
|
||||||
|
extern const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user);
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_ACL_H */
|
#endif /* HAVE_UHUB_ACL_H */
|
||||||
|
299
src/core/command_parser.c
Normal file
299
src/core/command_parser.c
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
static void hub_command_args_free(struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
struct hub_command_arg_data* data = NULL;
|
||||||
|
|
||||||
|
if (!cmd->args)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LIST_FOREACH(struct hub_command_arg_data*, data, cmd->args,
|
||||||
|
{
|
||||||
|
switch (data->type)
|
||||||
|
{
|
||||||
|
case type_string:
|
||||||
|
hub_free(data->data.string);
|
||||||
|
break;
|
||||||
|
case type_range:
|
||||||
|
hub_free(data->data.range);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
list_clear(cmd->args, hub_free);
|
||||||
|
list_destroy(cmd->args);
|
||||||
|
cmd->args = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void command_free(struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
if (!cmd) return;
|
||||||
|
|
||||||
|
hub_free(cmd->prefix);
|
||||||
|
hub_command_args_free(cmd);
|
||||||
|
hub_free(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum command_parse_status command_extract_arguments(struct hub_info* hub, const struct hub_user* user, struct command_handle* command, struct linked_list* tokens, struct linked_list* args)
|
||||||
|
{
|
||||||
|
int arg = 0;
|
||||||
|
int opt = 0;
|
||||||
|
int greedy = 0;
|
||||||
|
char arg_code;
|
||||||
|
char* token = NULL;
|
||||||
|
char* tmp = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
size_t offset = 0;
|
||||||
|
struct hub_command_arg_data* data = NULL;
|
||||||
|
enum command_parse_status status = cmd_status_ok;
|
||||||
|
|
||||||
|
// Ignore the first token since it is the prefix.
|
||||||
|
token = list_get_first(tokens);
|
||||||
|
list_remove(tokens, token);
|
||||||
|
hub_free(token);
|
||||||
|
|
||||||
|
while (status == cmd_status_ok && (arg_code = command->args[arg++]))
|
||||||
|
{
|
||||||
|
if (greedy)
|
||||||
|
{
|
||||||
|
size = 1;
|
||||||
|
LIST_FOREACH(char*, tmp, tokens, { size += (strlen(tmp) + 1); });
|
||||||
|
token = hub_malloc_zero(size);
|
||||||
|
|
||||||
|
while ((tmp = list_get_first(tokens)))
|
||||||
|
{
|
||||||
|
if (offset > 0)
|
||||||
|
token[offset++] = ' ';
|
||||||
|
memcpy(token + offset, tmp, strlen(tmp));
|
||||||
|
offset += strlen(tmp);
|
||||||
|
list_remove(tokens, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token = list_get_first(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token || !*token)
|
||||||
|
{
|
||||||
|
if (arg_code == '?' || opt == 1)
|
||||||
|
status = cmd_status_ok;
|
||||||
|
else
|
||||||
|
status = cmd_status_missing_args;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (arg_code)
|
||||||
|
{
|
||||||
|
case '?':
|
||||||
|
opt = 1;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case '+':
|
||||||
|
greedy = 1;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_user;
|
||||||
|
data->data.user = uman_get_user_by_nick(hub->users, token);
|
||||||
|
if (!data->data.user)
|
||||||
|
{
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_nick;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_user;
|
||||||
|
data->data.user = uman_get_user_by_cid(hub->users, token);
|
||||||
|
if (!data->data.user)
|
||||||
|
{
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_cid;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_address;
|
||||||
|
if (ip_convert_to_binary(token, data->data.address) == -1)
|
||||||
|
{
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_address;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_range;
|
||||||
|
data->data.range = hub_malloc_zero(sizeof(struct ip_range));
|
||||||
|
if (!ip_convert_address_to_range(token, data->data.range))
|
||||||
|
{
|
||||||
|
hub_free(data->data.range);
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_address;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'm':
|
||||||
|
case 'p':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_string;
|
||||||
|
data->data.string = strdup(token);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_command;
|
||||||
|
data->data.command = command_handler_lookup(hub->commands, token);
|
||||||
|
if (!data->data.command)
|
||||||
|
{
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_command;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_credentials;
|
||||||
|
if (!auth_string_to_cred(token, &data->data.credentials))
|
||||||
|
{
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_cred;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'N':
|
||||||
|
data = hub_malloc(sizeof(*data));
|
||||||
|
data->type = type_integer;
|
||||||
|
if (!is_number(token, &data->data.integer))
|
||||||
|
{
|
||||||
|
hub_free(data);
|
||||||
|
data = NULL;
|
||||||
|
status = cmd_status_arg_number;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\0':
|
||||||
|
if (!opt)
|
||||||
|
{
|
||||||
|
status = cmd_status_missing_args;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = cmd_status_ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
list_append(args, data);
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_remove(tokens, token);
|
||||||
|
hub_free(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(data);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct command_handle* command_get_handler(struct command_base* cbase, const char* prefix, const struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
struct command_handle* handler = NULL;
|
||||||
|
uhub_assert(cmd != NULL);
|
||||||
|
|
||||||
|
if (prefix && prefix[0] && prefix[1])
|
||||||
|
{
|
||||||
|
handler = command_handler_lookup(cbase, prefix + 1);
|
||||||
|
if (handler)
|
||||||
|
{
|
||||||
|
cmd->ptr = handler->ptr;
|
||||||
|
cmd->handler = handler->handler;
|
||||||
|
cmd->status = command_is_available(handler, user->credentials) ? cmd_status_ok : cmd_status_access_error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd->status = cmd_status_not_found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd->status = cmd_status_syntax_error;
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a command and break it down into a struct hub_command.
|
||||||
|
*/
|
||||||
|
struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message)
|
||||||
|
{
|
||||||
|
struct linked_list* tokens = list_create();
|
||||||
|
struct hub_command* cmd = NULL;
|
||||||
|
struct command_handle* handle = NULL;
|
||||||
|
|
||||||
|
cmd = hub_malloc_zero(sizeof(struct hub_command));
|
||||||
|
cmd->status = cmd_status_ok;
|
||||||
|
cmd->message = message;
|
||||||
|
cmd->prefix = NULL;
|
||||||
|
cmd->args = list_create();
|
||||||
|
cmd->user = user;
|
||||||
|
|
||||||
|
if (split_string(message, " ", tokens, 0) <= 0)
|
||||||
|
{
|
||||||
|
cmd->status = cmd_status_syntax_error;
|
||||||
|
goto command_parse_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup hub command.
|
||||||
|
cmd->prefix = strdup(((char*) list_get_first(tokens)) + 1);
|
||||||
|
|
||||||
|
// Find a matching command handler
|
||||||
|
handle = command_get_handler(cbase, list_get_first(tokens), user, cmd);
|
||||||
|
if (cmd->status != cmd_status_ok)
|
||||||
|
goto command_parse_cleanup;
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
|
cmd->status = command_extract_arguments(hub, user, handle, tokens, cmd->args);
|
||||||
|
goto command_parse_cleanup;
|
||||||
|
|
||||||
|
command_parse_cleanup:
|
||||||
|
list_clear(tokens, &hub_free);
|
||||||
|
list_destroy(tokens);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
131
src/core/command_parser.h
Normal file
131
src/core/command_parser.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_COMMAND_PARSER_H
|
||||||
|
#define HAVE_UHUB_COMMAND_PARSER_H
|
||||||
|
|
||||||
|
struct hub_command;
|
||||||
|
struct hub_user;
|
||||||
|
struct command_base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a message as a command and return a status indicating if the command
|
||||||
|
* is valid and that the arguments are sane.
|
||||||
|
*
|
||||||
|
* @param cbase Command base pointer.
|
||||||
|
* @param user User who invoked the command.
|
||||||
|
* @param message The message that is to be interpreted as a command (including the invocation prefix '!' or '+')
|
||||||
|
*
|
||||||
|
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
|
||||||
|
*/
|
||||||
|
extern struct hub_command* command_parse(struct command_base* cbase, struct hub_info* hub, const struct hub_user* user, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a hub_command that was created in command_parse().
|
||||||
|
*/
|
||||||
|
extern void command_free(struct hub_command* command);
|
||||||
|
|
||||||
|
|
||||||
|
enum command_parse_status
|
||||||
|
{
|
||||||
|
cmd_status_ok, /** <<< "Everything seems to OK" */
|
||||||
|
cmd_status_not_found, /** <<< "Command was not found" */
|
||||||
|
cmd_status_access_error, /** <<< "You don't have access to this command" */
|
||||||
|
cmd_status_syntax_error, /** <<< "Not a valid command." */
|
||||||
|
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
|
||||||
|
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
|
||||||
|
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
|
||||||
|
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
|
||||||
|
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
|
||||||
|
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
|
||||||
|
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum hub_command_arg_type
|
||||||
|
{
|
||||||
|
type_integer,
|
||||||
|
type_string,
|
||||||
|
type_user,
|
||||||
|
type_address,
|
||||||
|
type_range,
|
||||||
|
type_credentials,
|
||||||
|
type_command
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hub_command_arg_data
|
||||||
|
{
|
||||||
|
enum hub_command_arg_type type;
|
||||||
|
union {
|
||||||
|
int integer;
|
||||||
|
char* string;
|
||||||
|
struct hub_user* user;
|
||||||
|
struct ip_addr_encap* address;
|
||||||
|
struct ip_range* range;
|
||||||
|
enum auth_credentials credentials;
|
||||||
|
struct command_handle* command;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This struct contains all information needed to invoke
|
||||||
|
* a command, which includes the whole message, the prefix,
|
||||||
|
* the decoded arguments (according to parameter list), and
|
||||||
|
* the user pointer (ptr) which comes from the command it was matched to.
|
||||||
|
*
|
||||||
|
* The message and prefix is generally always available, but args only
|
||||||
|
* if status == cmd_status_ok.
|
||||||
|
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
|
||||||
|
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
|
||||||
|
*/
|
||||||
|
struct hub_command
|
||||||
|
{
|
||||||
|
const char* message; /**<<< "The complete message." */
|
||||||
|
char* prefix; /**<<< "The prefix extracted from the message." */
|
||||||
|
struct linked_list* args; /**<<< "List of arguments of type struct hub_command_arg_data. Parsed from message." */
|
||||||
|
enum command_parse_status status; /**<<< "Status of the parsed hub_command." */
|
||||||
|
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
|
||||||
|
const struct hub_user* user; /**<<< "The user who invoked this command." */
|
||||||
|
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the command argument iterator and return the number of arguments
|
||||||
|
* that can be extracted from a parsed command.
|
||||||
|
*
|
||||||
|
* @param cmd the command to start iterating arguments
|
||||||
|
* @return returns the number of arguments provided for the command
|
||||||
|
*/
|
||||||
|
extern size_t hub_command_arg_reset(struct hub_command* cmd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the current argument and place it in data and increments the iterator.
|
||||||
|
* If no argument exists, or the argument is of a different type than \param type, then 0 is returned.
|
||||||
|
*
|
||||||
|
* NOTE: when calling hub_command_arg_next the first time during a command callback it is safe to assume
|
||||||
|
* that the first argument will be extracted. Thus you don't need to call hub_command_arg_reset().
|
||||||
|
*
|
||||||
|
* @param cmd the command used for iterating arguments.
|
||||||
|
* @param type the expected type of this argument
|
||||||
|
* @return NULL if no argument is found or if the argument found does not match the expected type.
|
||||||
|
*/
|
||||||
|
extern struct hub_command_arg_data* hub_command_arg_next(struct hub_command* cmd, enum hub_command_arg_type type);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_COMMAND_PARSER_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,10 +13,97 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#ifndef HAVE_UHUB_COMMANDS_H
|
||||||
|
#define HAVE_UHUB_COMMANDS_H
|
||||||
|
|
||||||
extern int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message);
|
struct command_base;
|
||||||
|
struct command_handle;
|
||||||
|
struct hub_command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Argument codes are used to automatically parse arguments
|
||||||
|
* for a a hub command.
|
||||||
|
*
|
||||||
|
* u = user (must exist in hub session, or will cause error)
|
||||||
|
* n = nick name (string)
|
||||||
|
* i = CID (must exist in hub)
|
||||||
|
* a = (IP) address (must be a valid IPv4 or IPv6 address)
|
||||||
|
* r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work)
|
||||||
|
* m = message (string)
|
||||||
|
* p = password (string)
|
||||||
|
* C = credentials (see auth_string_to_cred).
|
||||||
|
* c = command (name of command)
|
||||||
|
* N = number (integer)
|
||||||
|
*
|
||||||
|
* Prefix an argument with ? to make it optional.
|
||||||
|
* Prefix with + to make the argument greedy, which causes it to grab the rest of the line ignoring boundaries (only supported for string types).
|
||||||
|
*
|
||||||
|
* NOTE: if an argument is optional then all following arguments must also be optional.
|
||||||
|
* NOTE: You can combine optional and greedy, example: "?+m" would match "", "a", "a b c", etc.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* "nia" means "nick cid ip"
|
||||||
|
* "n?p" means "nick [password]" where password is optional.
|
||||||
|
* "?N?N" means zero, one, or two integers.
|
||||||
|
* "?NN" means zero or two integers.
|
||||||
|
* "?+m" means an optional string which may contain spaces that would otherwise be split into separate arguments.
|
||||||
|
*/
|
||||||
|
struct command_handle
|
||||||
|
{
|
||||||
|
const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */
|
||||||
|
size_t length; /**<<< "Length of the prefix" */
|
||||||
|
const char* args; /**<<< "Argument codes (see above)" */
|
||||||
|
enum auth_credentials cred; /**<<< "Minimum access level for the command" */
|
||||||
|
command_handler handler; /**<<< "Function pointer for the command" */
|
||||||
|
const char* description; /**<<< "Description for the command" */
|
||||||
|
const char* origin; /**<<< "Name of module where the command is implemented." */
|
||||||
|
void* ptr; /**<<< "A pointer which will be passed along to the handler. @See hub_command::ptr" */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns NULL on error, or handle
|
||||||
|
*/
|
||||||
|
extern struct command_base* command_initialize(struct hub_info* hub);
|
||||||
|
extern void command_shutdown(struct command_base* cbase);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new command to the command base.
|
||||||
|
* Returns 1 on success, or 0 on error.
|
||||||
|
*/
|
||||||
|
extern int command_add(struct command_base*, struct command_handle*, void* ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a command from the command base.
|
||||||
|
* Returns 1 on success, or 0 on error.
|
||||||
|
*/
|
||||||
|
extern int command_del(struct command_base*, struct command_handle*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch a message and forward it as a command.
|
||||||
|
* Returns 1 if the message should be forwarded as a chat message, or 0 if
|
||||||
|
* it is supposed to be handled internally in the dispatcher.
|
||||||
|
*
|
||||||
|
* This will break the message down into a struct hub_command and invoke the command handler
|
||||||
|
* for that command if the sufficient access credentials are met.
|
||||||
|
*/
|
||||||
|
extern int command_invoke(struct command_base*, struct hub_user* user, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 1 if the command handle can be used with the given credentials, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int command_is_available(struct command_handle* handle, enum auth_credentials credentials);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup a command handle based on prefix.
|
||||||
|
* If no matching command handle is found then NULL is returned.
|
||||||
|
*/
|
||||||
|
struct command_handle* command_handler_lookup(struct command_base* cbase, const char* prefix);
|
||||||
|
|
||||||
|
extern void commands_builtin_add(struct command_base*);
|
||||||
|
extern void commands_builtin_remove(struct command_base*);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_COMMANDS_H */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -31,17 +31,7 @@
|
|||||||
|
|
||||||
static int apply_boolean(const char* key, const char* data, int* target)
|
static int apply_boolean(const char* key, const char* data, int* target)
|
||||||
{
|
{
|
||||||
if (strlen(data) == 1 && (data[0] == '1')) *target = 1;
|
return string_to_boolean(data, target);
|
||||||
else if (strlen(data) == 1 && (data[0] == '0')) *target = 0;
|
|
||||||
else if (strncasecmp(data, "true", 4) == 0) *target = 1;
|
|
||||||
else if (strncasecmp(data, "false", 5) == 0) *target = 0;
|
|
||||||
else if (strncasecmp(data, "yes", 3) == 0) *target = 1;
|
|
||||||
else if (strncasecmp(data, "no", 2) == 0) *target = 0;
|
|
||||||
else if (strncasecmp(data, "on", 2) == 0) *target = 1;
|
|
||||||
else if (strncasecmp(data, "off", 3) == 0) *target = 0;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int apply_string(const char* key, const char* data, char** target, char* regexp)
|
static int apply_string(const char* key, const char* data, char** target, char* regexp)
|
||||||
@ -110,6 +100,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
|
|
||||||
key = strip_white_space(key);
|
key = strip_white_space(key);
|
||||||
data = strip_white_space(data);
|
data = strip_white_space(data);
|
||||||
|
data = strip_off_quotes(data);
|
||||||
|
|
||||||
if (!*key || !*data)
|
if (!*key || !*data)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,241 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use XML::Twig;
|
|
||||||
|
|
||||||
sub write_c_header(@);
|
|
||||||
sub write_c_impl_defaults(@);
|
|
||||||
sub write_c_impl_apply(@);
|
|
||||||
sub write_c_impl_free(@);
|
|
||||||
sub write_c_impl_dump(@);
|
|
||||||
sub get_data($);
|
|
||||||
|
|
||||||
# initialize parser and read the file
|
|
||||||
my $input = "./config.xml";
|
|
||||||
my $parser = XML::Twig->new();
|
|
||||||
my $tree = $parser->parsefile($input) || die "Unable to parse XML file.";
|
|
||||||
|
|
||||||
# Write header file
|
|
||||||
open GENHEAD, ">gen_config.h" || die "Unable to write header file";
|
|
||||||
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\nstruct hub_config\n{\n";
|
|
||||||
foreach my $p ($tree->root->children("option"))
|
|
||||||
{
|
|
||||||
write_c_header(get_data($p));
|
|
||||||
}
|
|
||||||
print GENHEAD "};\n\n";
|
|
||||||
|
|
||||||
# Write c source file
|
|
||||||
open GENIMPL, ">gen_config.c" || die "Unable to write source file";
|
|
||||||
print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
|
|
||||||
|
|
||||||
# The defaults function
|
|
||||||
print GENIMPL "void config_defaults(struct hub_config* config)\n{\n";
|
|
||||||
foreach my $p ($tree->root->children("option"))
|
|
||||||
{
|
|
||||||
write_c_impl_defaults(get_data($p));
|
|
||||||
}
|
|
||||||
print GENIMPL "}\n\n";
|
|
||||||
|
|
||||||
# apply function
|
|
||||||
print GENIMPL "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
|
|
||||||
|
|
||||||
foreach my $p ($tree->root->children("option"))
|
|
||||||
{
|
|
||||||
write_c_impl_apply(get_data($p));
|
|
||||||
}
|
|
||||||
print GENIMPL "\t/* Still here -- unknown directive */\n";
|
|
||||||
print GENIMPL "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n";
|
|
||||||
print GENIMPL "\t\treturn -1;\n";
|
|
||||||
print GENIMPL "}\n\n";
|
|
||||||
|
|
||||||
# free function (for strings)
|
|
||||||
print GENIMPL "void free_config(struct hub_config* config)\n{\n";
|
|
||||||
foreach my $p ($tree->root->children("option"))
|
|
||||||
{
|
|
||||||
write_c_impl_free(get_data($p));
|
|
||||||
}
|
|
||||||
print GENIMPL "}\n\n";
|
|
||||||
|
|
||||||
# dump function
|
|
||||||
print GENIMPL "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n";
|
|
||||||
foreach my $p ($tree->root->children("option"))
|
|
||||||
{
|
|
||||||
write_c_impl_dump(get_data($p));
|
|
||||||
}
|
|
||||||
print GENIMPL "}\n\n";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sub write_c_header(@)
|
|
||||||
{
|
|
||||||
my @output = @_;
|
|
||||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
|
||||||
|
|
||||||
print GENHEAD "\t";
|
|
||||||
print GENHEAD "int " if ($type eq "int");
|
|
||||||
print GENHEAD "int " if ($type eq "boolean");
|
|
||||||
print GENHEAD "char*" if ($type =~ /(string|file|message)/);
|
|
||||||
print GENHEAD " " . $name . ";";
|
|
||||||
|
|
||||||
my $comment = "";
|
|
||||||
if ($type eq "message")
|
|
||||||
{
|
|
||||||
$comment = "\"" . $default . "\"";
|
|
||||||
}
|
|
||||||
elsif (defined $short && length $short > 0)
|
|
||||||
{
|
|
||||||
$comment = $short;
|
|
||||||
$comment .= " (default: " . $default . ")" if (defined $default);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length $comment > 0)
|
|
||||||
{
|
|
||||||
my $pad = "";
|
|
||||||
for (my $i = length $name; $i < 32; $i++)
|
|
||||||
{
|
|
||||||
$pad .= " ";
|
|
||||||
}
|
|
||||||
$comment = $pad . "/*<<< " . $comment . " */";
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENHEAD $comment . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub write_c_impl_defaults(@)
|
|
||||||
{
|
|
||||||
my @output = @_;
|
|
||||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
|
||||||
my $prefix = "";
|
|
||||||
my $suffix = "";
|
|
||||||
|
|
||||||
print GENIMPL "\tconfig->$name = ";
|
|
||||||
if ($type =~ /(string|file|message)/)
|
|
||||||
{
|
|
||||||
$prefix = "hub_strdup(\"";
|
|
||||||
$suffix = "\")"
|
|
||||||
}
|
|
||||||
print GENIMPL $prefix . $default . $suffix . ";\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub write_c_impl_apply(@)
|
|
||||||
{
|
|
||||||
my @output = @_;
|
|
||||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $p) = @output;
|
|
||||||
|
|
||||||
my $min;
|
|
||||||
my $max;
|
|
||||||
my $regexp;
|
|
||||||
|
|
||||||
if (defined $p)
|
|
||||||
{
|
|
||||||
$min = $p->att("min");
|
|
||||||
$max = $p->att("max");
|
|
||||||
$regexp = $p->att("regexp");
|
|
||||||
|
|
||||||
print "'check' is defined for option $name";
|
|
||||||
print ", min=$min" if (defined $min);
|
|
||||||
print ", max=$max" if (defined $max);
|
|
||||||
print ", regexp=\"$regexp\"" if (defined $regexp);
|
|
||||||
print "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENIMPL "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n";
|
|
||||||
|
|
||||||
if ($type eq "int")
|
|
||||||
{
|
|
||||||
if (defined $min)
|
|
||||||
{
|
|
||||||
print GENIMPL "\t\tmin = $min;\n"
|
|
||||||
}
|
|
||||||
if (defined $max)
|
|
||||||
{
|
|
||||||
print GENIMPL "\t\tmax = $max;\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENIMPL "\t\tif (!apply_integer(key, data, &config->$name, ";
|
|
||||||
|
|
||||||
if (defined $min)
|
|
||||||
{
|
|
||||||
print GENIMPL "&min";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
print GENIMPL "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENIMPL ", ";
|
|
||||||
|
|
||||||
if (defined $max)
|
|
||||||
{
|
|
||||||
print GENIMPL "&max";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
print GENIMPL "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENIMPL "))\n";
|
|
||||||
}
|
|
||||||
elsif ($type eq "boolean")
|
|
||||||
{
|
|
||||||
print GENIMPL "\t\tif (!apply_boolean(key, data, &config->$name))\n";
|
|
||||||
}
|
|
||||||
elsif ($type =~ /(string|file|message)/)
|
|
||||||
{
|
|
||||||
print GENIMPL "\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENIMPL "\t\t{\n" .
|
|
||||||
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
|
|
||||||
"\t\t\treturn -1;\n" .
|
|
||||||
"\t\t}\n" .
|
|
||||||
"\t\treturn 0;\n" .
|
|
||||||
"\t}\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub write_c_impl_free(@)
|
|
||||||
{
|
|
||||||
my @output = @_;
|
|
||||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
|
||||||
|
|
||||||
if ($type =~ /(string|file|message)/)
|
|
||||||
{
|
|
||||||
print GENIMPL "\thub_free(config->" . $name . ");\n\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub write_c_impl_dump(@)
|
|
||||||
{
|
|
||||||
my @output = @_;
|
|
||||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
|
||||||
my $out;
|
|
||||||
my $val = "config->$name";
|
|
||||||
my $test = "config->$name != $default";
|
|
||||||
|
|
||||||
if ($type eq "int")
|
|
||||||
{
|
|
||||||
$out = "%d";
|
|
||||||
}
|
|
||||||
elsif ($type eq "boolean")
|
|
||||||
{
|
|
||||||
$out = "%s";
|
|
||||||
$val = "config->$name ? \"yes\" : \"no\"";
|
|
||||||
}
|
|
||||||
elsif ($type =~ /(string|file|message)/)
|
|
||||||
{
|
|
||||||
$out = "\\\"%s\\\"";
|
|
||||||
$test = "strcmp(config->$name, \"$default\") != 0";
|
|
||||||
}
|
|
||||||
|
|
||||||
print GENIMPL "\tif (!ignore_defaults || $test)\n";
|
|
||||||
print GENIMPL "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_data($)
|
|
||||||
{
|
|
||||||
my $p = shift;
|
|
||||||
my $check = $p->first_child_matches("check");
|
|
||||||
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example"), $check);
|
|
||||||
return @data;
|
|
||||||
}
|
|
||||||
|
|
255
src/core/config.py
Executable file
255
src/core/config.py
Executable 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);
|
||||||
|
|
||||||
|
|
@ -13,11 +13,11 @@
|
|||||||
<check min="1" max="65535" />
|
<check min="1" max="65535" />
|
||||||
<since>0.1.0</since>
|
<since>0.1.0</since>
|
||||||
<short>Server port to bind to</short>
|
<short>Server port to bind to</short>
|
||||||
<description><![CDATA[This is specifies the port number the hub should listen on.]]></description>
|
<description><![CDATA[This specifies the port number the hub should listen on.]]></description>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="server_bind_addr" type="string" default="any">
|
<option name="server_bind_addr" type="string" default="any">
|
||||||
<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>
|
<short>Server bind address</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
|
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
|
||||||
@ -58,7 +58,7 @@
|
|||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="server_alt_ports" type="string" default="">
|
<option name="server_alt_ports" type="string" default="">
|
||||||
<check regexp="((\d+)(,(\d+))*)?" />
|
<check regexp="\d+(,\d+)*" />
|
||||||
<short>Comma separated list of alternative ports to listen to</short>
|
<short>Comma separated list of alternative ports to listen to</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
In addition to the server_port the hub can listen to a list of alternative ports.
|
In addition to the server_port the hub can listen to a list of alternative ports.
|
||||||
@ -108,6 +108,15 @@
|
|||||||
<since>0.1.1</since>
|
<since>0.1.1</since>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
<option name="register_self" type="boolean" default="0">
|
||||||
|
<short>Allow users to register themselves on the hub.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled guests can register their nickname on the hub using !register command.
|
||||||
|
Otherwise only operators can register users.
|
||||||
|
]]></description>
|
||||||
|
<since>0.4.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
<option name="obsolete_clients" type="boolean" default="0">
|
<option name="obsolete_clients" type="boolean" default="0">
|
||||||
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
|
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
@ -117,14 +126,6 @@
|
|||||||
<since>0.3.1</since>
|
<since>0.3.1</since>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="chat_only" type="boolean" default="0">
|
|
||||||
<short>Allow chat only operation on hub</short>
|
|
||||||
<description><![CDATA[
|
|
||||||
If this is enabled the hub will refuse to relay messages for search and connection setup. This effectively makes the hub viable for chat only.
|
|
||||||
]]></description>
|
|
||||||
<since>0.1.1</since>
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option name="chat_is_privileged" type="boolean" default="0">
|
<option name="chat_is_privileged" type="boolean" default="0">
|
||||||
<short>Allow chat for operators and above only</short>
|
<short>Allow chat for operators and above only</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
@ -156,7 +157,7 @@
|
|||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="redirect_addr" type="string" default="">
|
<option name="redirect_addr" type="string" default="">
|
||||||
<check regexp="(adc|adcs|dchub)://.*" />
|
<check regexp="(adcs?|dchub)://.*" />
|
||||||
<short>A common hub redirect address.</short>
|
<short>A common hub redirect address.</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
|
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
|
||||||
@ -169,7 +170,7 @@
|
|||||||
<check min="1024" max="1048576" />
|
<check min="1024" max="1048576" />
|
||||||
<short>Max read buffer before parse, per user</short>
|
<short>Max read buffer before parse, per user</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
Maximum receive buffer allowed before commands are procesed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution.
|
Maximum receive buffer allowed before commands are processed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution.
|
||||||
]]></description>
|
]]></description>
|
||||||
<since>0.1.3</since>
|
<since>0.1.3</since>
|
||||||
</option>
|
</option>
|
||||||
@ -408,7 +409,7 @@
|
|||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="tls_require" type="boolean" default="0">
|
<option name="tls_require" type="boolean" default="0">
|
||||||
<short>If SSL/TLS enabled, should it be required (default: 0)</short>
|
<short>If SSL/TLS enabled, should it be required</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
If TLS/SSL support is enabled it can either be optional or mandatory.
|
If TLS/SSL support is enabled it can either be optional or mandatory.
|
||||||
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
|
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
|
||||||
@ -417,10 +418,20 @@
|
|||||||
<since>0.3.0</since>
|
<since>0.3.0</since>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_require_redirect_addr" type="string" default="">
|
||||||
|
<check regexp="(adcs?|dchub)://.*" />
|
||||||
|
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the redirect address used when the hub wants to redirect a client for not using ADCS.
|
||||||
|
For instance a hub at adc://adc.example.com might redirect to adcs://adc.example.com
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
<option name="tls_certificate" type="file" default="">
|
<option name="tls_certificate" type="file" default="">
|
||||||
<short>Certificate file</short>
|
<short>Certificate file</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
Path to a TLS/SSL certificate (PEM format).
|
Path to a TLS/SSL certificate or certificate chain (PEM format).
|
||||||
]]></description>
|
]]></description>
|
||||||
<since>0.3.0</since>
|
<since>0.3.0</since>
|
||||||
</option>
|
</option>
|
||||||
@ -433,24 +444,40 @@
|
|||||||
<since>0.3.0</since>
|
<since>0.3.0</since>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="file_motd" type="file" default="">
|
<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>File containing the 'message of the day</short>
|
<short>List of TLS ciphers to use</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
This can be specified as a message of the day file. If a valid file is given here it's content will be sent to all users after they have logged in to the hub. If the file is missing or empty this configuration entry will be ignored.
|
This is a colon separated list of preferred ciphers in the OpenSSL format.
|
||||||
]]></description>
|
]]></description>
|
||||||
<since>0.1.3</since>
|
<since>0.5.0</since>
|
||||||
<example><![CDATA[
|
<example><![CDATA[
|
||||||
<p>
|
<p>
|
||||||
Unix users: <br />
|
High security with emphasis on forward secrecy:<br />
|
||||||
file_acl = "/etc/uhub/motd.txt"
|
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>
|
||||||
<p>
|
<p>
|
||||||
Windows users: <br />
|
Allow ChaCha20/Poly1305 which are secure, yet generally faster:<br />
|
||||||
file_acl = "c:\uhub\motd.txt"
|
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>
|
</p>
|
||||||
]]></example>
|
]]></example>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_version" type="string" default="1.2">
|
||||||
|
<short>Specify minimum TLS version supported.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
<p>
|
||||||
|
This allows you to specify the minimum TLS version the hub requires from connecting clients in order to
|
||||||
|
connect to the hub.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
TLS version 1.2 is recommended and enabled by default.
|
||||||
|
TLS version 1.1 is acceptable without any known flaws, and allows for older clients to connect.
|
||||||
|
TLS version 1.0 should be avoided, even though it is the most compatible with older ADC clients.
|
||||||
|
</p>
|
||||||
|
]]></description>
|
||||||
|
<since>0.5.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
<option name="file_acl" type="file" default="">
|
<option name="file_acl" type="file" default="">
|
||||||
<short>File containing access control lists</short>
|
<short>File containing access control lists</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
@ -471,25 +498,6 @@
|
|||||||
]]></example>
|
]]></example>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="file_rules" type="file" default="">
|
|
||||||
<short>File containing hub rules</short>
|
|
||||||
<description><![CDATA[
|
|
||||||
This is a text file that is displayed on login as an extended message of the day.
|
|
||||||
In addition the contents of the file is displayed when a user uses the "!rules" command.
|
|
||||||
]]></description>
|
|
||||||
<since>0.3.0</since>
|
|
||||||
<example><![CDATA[
|
|
||||||
<p>
|
|
||||||
Unix users: <br />
|
|
||||||
file_acl = "/etc/uhub/rules.txt"
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Windows users: <br />
|
|
||||||
file_acl = "c:\uhub\rules.txt"
|
|
||||||
</p>
|
|
||||||
]]></example>
|
|
||||||
</option>
|
|
||||||
|
|
||||||
<option name="file_plugins" type="file" default="">
|
<option name="file_plugins" type="file" default="">
|
||||||
<short>Plugin configuration file</short>
|
<short>Plugin configuration file</short>
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
@ -559,7 +567,7 @@
|
|||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use">
|
<option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use">
|
||||||
<description><![CDATA[This message will be sent to clients if their provided nickname is alredy in use on the hub.]]></description>
|
<description><![CDATA[This message will be sent to clients if their provided nickname is already in use on the hub.]]></description>
|
||||||
<since>0.2.0</since>
|
<since>0.2.0</since>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
@ -615,7 +623,7 @@
|
|||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option name="msg_error_no_memory" type="message" default="No memory">
|
<option name="msg_error_no_memory" type="message" default="No memory">
|
||||||
<description><![CDATA[]]></description>
|
<description><![CDATA[Hub has no more memory]]></description>
|
||||||
<since>0.2.0</since>
|
<since>0.2.0</since>
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -77,30 +77,22 @@ int event_queue_process(struct event_queue* queue)
|
|||||||
/* lock primary queue, and handle the primary queue messages. */
|
/* lock primary queue, and handle the primary queue messages. */
|
||||||
queue->locked = 1;
|
queue->locked = 1;
|
||||||
|
|
||||||
data = (struct event_data*) list_get_first(queue->q1);
|
LIST_FOREACH(struct event_data*, data, queue->q1,
|
||||||
while (data)
|
|
||||||
{
|
{
|
||||||
#ifdef EQ_DEBUG
|
#ifdef EQ_DEBUG
|
||||||
eq_debug("EXEC", data);
|
eq_debug("EXEC", data);
|
||||||
#endif
|
#endif
|
||||||
queue->callback(queue->callback_data, data);
|
queue->callback(queue->callback_data, data);
|
||||||
data = (struct event_data*) list_get_next(queue->q1);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
list_clear(queue->q1, event_queue_cleanup_callback);
|
list_clear(queue->q1, event_queue_cleanup_callback);
|
||||||
assert(list_size(queue->q1) == 0);
|
uhub_assert(list_size(queue->q1) == 0);
|
||||||
|
|
||||||
/* unlock queue */
|
/* unlock queue */
|
||||||
queue->locked = 0;
|
queue->locked = 0;
|
||||||
|
|
||||||
/* transfer from secondary queue to the primary queue. */
|
/* transfer from secondary queue to the primary queue. */
|
||||||
data = (struct event_data*) list_get_first(queue->q2);
|
list_append_list(queue->q1, queue->q2);
|
||||||
while (data)
|
|
||||||
{
|
|
||||||
list_remove(queue->q2, data);
|
|
||||||
list_append(queue->q1, data);
|
|
||||||
data = (struct event_data*) list_get_first(queue->q2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if more events exist, schedule it */
|
/* if more events exist, schedule it */
|
||||||
if (list_size(queue->q1))
|
if (list_size(queue->q1))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -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)
|
void config_defaults(struct hub_config* config)
|
||||||
{
|
{
|
||||||
@ -11,8 +17,8 @@ void config_defaults(struct hub_config* config)
|
|||||||
config->show_banner_sys_info = 1;
|
config->show_banner_sys_info = 1;
|
||||||
config->max_users = 500;
|
config->max_users = 500;
|
||||||
config->registered_users_only = 0;
|
config->registered_users_only = 0;
|
||||||
|
config->register_self = 0;
|
||||||
config->obsolete_clients = 0;
|
config->obsolete_clients = 0;
|
||||||
config->chat_only = 0;
|
|
||||||
config->chat_is_privileged = 0;
|
config->chat_is_privileged = 0;
|
||||||
config->hub_name = hub_strdup("uhub");
|
config->hub_name = hub_strdup("uhub");
|
||||||
config->hub_description = hub_strdup("no description");
|
config->hub_description = hub_strdup("no description");
|
||||||
@ -42,11 +48,12 @@ void config_defaults(struct hub_config* config)
|
|||||||
config->flood_ctl_extras = 0;
|
config->flood_ctl_extras = 0;
|
||||||
config->tls_enable = 0;
|
config->tls_enable = 0;
|
||||||
config->tls_require = 0;
|
config->tls_require = 0;
|
||||||
|
config->tls_require_redirect_addr = hub_strdup("");
|
||||||
config->tls_certificate = hub_strdup("");
|
config->tls_certificate = hub_strdup("");
|
||||||
config->tls_private_key = hub_strdup("");
|
config->tls_private_key = hub_strdup("");
|
||||||
config->file_motd = hub_strdup("");
|
config->tls_ciphersuite = hub_strdup("ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS");
|
||||||
|
config->tls_version = hub_strdup("1.2");
|
||||||
config->file_acl = hub_strdup("");
|
config->file_acl = hub_strdup("");
|
||||||
config->file_rules = hub_strdup("");
|
|
||||||
config->file_plugins = hub_strdup("");
|
config->file_plugins = hub_strdup("");
|
||||||
config->msg_hub_full = hub_strdup("Hub is full");
|
config->msg_hub_full = hub_strdup("Hub is full");
|
||||||
config->msg_hub_disabled = hub_strdup("Hub is disabled");
|
config->msg_hub_disabled = hub_strdup("Hub is disabled");
|
||||||
@ -103,7 +110,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "server_port"))
|
if (!strcmp(key, "server_port"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->server_port, 0, 0))
|
min = 1;
|
||||||
|
max = 65535;
|
||||||
|
if (!apply_integer(key, data, &config->server_port, &min, &max))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -123,7 +132,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "server_listen_backlog"))
|
if (!strcmp(key, "server_listen_backlog"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->server_listen_backlog, 0, 0))
|
min = 5;
|
||||||
|
if (!apply_integer(key, data, &config->server_listen_backlog, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -183,9 +193,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(key, "obsolete_clients"))
|
if (!strcmp(key, "register_self"))
|
||||||
{
|
{
|
||||||
if (!apply_boolean(key, data, &config->obsolete_clients))
|
if (!apply_boolean(key, data, &config->register_self))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -193,9 +203,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(key, "chat_only"))
|
if (!strcmp(key, "obsolete_clients"))
|
||||||
{
|
{
|
||||||
if (!apply_boolean(key, data, &config->chat_only))
|
if (!apply_boolean(key, data, &config->obsolete_clients))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -245,7 +255,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "max_recv_buffer"))
|
if (!strcmp(key, "max_recv_buffer"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->max_recv_buffer, 0, 0))
|
min = 1024;
|
||||||
|
max = 1048576;
|
||||||
|
if (!apply_integer(key, data, &config->max_recv_buffer, &min, &max))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -255,7 +267,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "max_send_buffer"))
|
if (!strcmp(key, "max_send_buffer"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->max_send_buffer, 0, 0))
|
min = 2048;
|
||||||
|
if (!apply_integer(key, data, &config->max_send_buffer, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -265,7 +278,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "max_send_buffer_soft"))
|
if (!strcmp(key, "max_send_buffer_soft"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->max_send_buffer_soft, 0, 0))
|
min = 1024;
|
||||||
|
if (!apply_integer(key, data, &config->max_send_buffer_soft, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -285,7 +299,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "max_chat_history"))
|
if (!strcmp(key, "max_chat_history"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->max_chat_history, 0, 0))
|
min = 0;
|
||||||
|
max = 250;
|
||||||
|
if (!apply_integer(key, data, &config->max_chat_history, &min, &max))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -295,7 +311,9 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "max_logout_log"))
|
if (!strcmp(key, "max_logout_log"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->max_logout_log, 0, 0))
|
min = 0;
|
||||||
|
max = 2000;
|
||||||
|
if (!apply_integer(key, data, &config->max_logout_log, &min, &max))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -305,7 +323,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_max_hubs_user"))
|
if (!strcmp(key, "limit_max_hubs_user"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_max_hubs_user, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_max_hubs_user, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -315,7 +334,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_max_hubs_reg"))
|
if (!strcmp(key, "limit_max_hubs_reg"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_max_hubs_reg, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_max_hubs_reg, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -325,7 +345,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_max_hubs_op"))
|
if (!strcmp(key, "limit_max_hubs_op"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_max_hubs_op, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_max_hubs_op, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -335,7 +356,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_max_hubs"))
|
if (!strcmp(key, "limit_max_hubs"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_max_hubs, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_max_hubs, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -345,7 +367,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_min_hubs_user"))
|
if (!strcmp(key, "limit_min_hubs_user"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_min_hubs_user, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_min_hubs_user, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -355,7 +378,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_min_hubs_reg"))
|
if (!strcmp(key, "limit_min_hubs_reg"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_min_hubs_reg, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_min_hubs_reg, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -365,7 +389,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_min_hubs_op"))
|
if (!strcmp(key, "limit_min_hubs_op"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_min_hubs_op, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_min_hubs_op, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -386,7 +411,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_max_share"))
|
if (!strcmp(key, "limit_max_share"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_max_share, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_max_share, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -396,7 +422,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_min_slots"))
|
if (!strcmp(key, "limit_min_slots"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_min_slots, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_min_slots, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -406,7 +433,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
|
|
||||||
if (!strcmp(key, "limit_max_slots"))
|
if (!strcmp(key, "limit_max_slots"))
|
||||||
{
|
{
|
||||||
if (!apply_integer(key, data, &config->limit_max_slots, 0, 0))
|
min = 0;
|
||||||
|
if (!apply_integer(key, data, &config->limit_max_slots, &min, 0))
|
||||||
{
|
{
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -496,6 +524,16 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(key, "tls_require_redirect_addr"))
|
||||||
|
{
|
||||||
|
if (!apply_string(key, data, &config->tls_require_redirect_addr, (char*) ""))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(key, "tls_certificate"))
|
if (!strcmp(key, "tls_certificate"))
|
||||||
{
|
{
|
||||||
if (!apply_string(key, data, &config->tls_certificate, (char*) ""))
|
if (!apply_string(key, data, &config->tls_certificate, (char*) ""))
|
||||||
@ -516,9 +554,19 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(key, "file_motd"))
|
if (!strcmp(key, "tls_ciphersuite"))
|
||||||
{
|
{
|
||||||
if (!apply_string(key, data, &config->file_motd, (char*) ""))
|
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);
|
LOG_ERROR("Configuration parse error on line %d", line_count);
|
||||||
return -1;
|
return -1;
|
||||||
@ -536,16 +584,6 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(key, "file_rules"))
|
|
||||||
{
|
|
||||||
if (!apply_string(key, data, &config->file_rules, (char*) ""))
|
|
||||||
{
|
|
||||||
LOG_ERROR("Configuration parse error on line %d", line_count);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(key, "file_plugins"))
|
if (!strcmp(key, "file_plugins"))
|
||||||
{
|
{
|
||||||
if (!apply_string(key, data, &config->file_plugins, (char*) ""))
|
if (!apply_string(key, data, &config->file_plugins, (char*) ""))
|
||||||
@ -933,16 +971,18 @@ void free_config(struct hub_config* config)
|
|||||||
|
|
||||||
hub_free(config->redirect_addr);
|
hub_free(config->redirect_addr);
|
||||||
|
|
||||||
|
hub_free(config->tls_require_redirect_addr);
|
||||||
|
|
||||||
hub_free(config->tls_certificate);
|
hub_free(config->tls_certificate);
|
||||||
|
|
||||||
hub_free(config->tls_private_key);
|
hub_free(config->tls_private_key);
|
||||||
|
|
||||||
hub_free(config->file_motd);
|
hub_free(config->tls_ciphersuite);
|
||||||
|
|
||||||
|
hub_free(config->tls_version);
|
||||||
|
|
||||||
hub_free(config->file_acl);
|
hub_free(config->file_acl);
|
||||||
|
|
||||||
hub_free(config->file_rules);
|
|
||||||
|
|
||||||
hub_free(config->file_plugins);
|
hub_free(config->file_plugins);
|
||||||
|
|
||||||
hub_free(config->msg_hub_full);
|
hub_free(config->msg_hub_full);
|
||||||
@ -1048,12 +1088,12 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
|||||||
if (!ignore_defaults || config->registered_users_only != 0)
|
if (!ignore_defaults || config->registered_users_only != 0)
|
||||||
fprintf(stdout, "registered_users_only = %s\n", config->registered_users_only ? "yes" : "no");
|
fprintf(stdout, "registered_users_only = %s\n", config->registered_users_only ? "yes" : "no");
|
||||||
|
|
||||||
|
if (!ignore_defaults || config->register_self != 0)
|
||||||
|
fprintf(stdout, "register_self = %s\n", config->register_self ? "yes" : "no");
|
||||||
|
|
||||||
if (!ignore_defaults || config->obsolete_clients != 0)
|
if (!ignore_defaults || config->obsolete_clients != 0)
|
||||||
fprintf(stdout, "obsolete_clients = %s\n", config->obsolete_clients ? "yes" : "no");
|
fprintf(stdout, "obsolete_clients = %s\n", config->obsolete_clients ? "yes" : "no");
|
||||||
|
|
||||||
if (!ignore_defaults || config->chat_only != 0)
|
|
||||||
fprintf(stdout, "chat_only = %s\n", config->chat_only ? "yes" : "no");
|
|
||||||
|
|
||||||
if (!ignore_defaults || config->chat_is_privileged != 0)
|
if (!ignore_defaults || config->chat_is_privileged != 0)
|
||||||
fprintf(stdout, "chat_is_privileged = %s\n", config->chat_is_privileged ? "yes" : "no");
|
fprintf(stdout, "chat_is_privileged = %s\n", config->chat_is_privileged ? "yes" : "no");
|
||||||
|
|
||||||
@ -1141,21 +1181,24 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
|||||||
if (!ignore_defaults || config->tls_require != 0)
|
if (!ignore_defaults || config->tls_require != 0)
|
||||||
fprintf(stdout, "tls_require = %s\n", config->tls_require ? "yes" : "no");
|
fprintf(stdout, "tls_require = %s\n", config->tls_require ? "yes" : "no");
|
||||||
|
|
||||||
|
if (!ignore_defaults || strcmp(config->tls_require_redirect_addr, "") != 0)
|
||||||
|
fprintf(stdout, "tls_require_redirect_addr = \"%s\"\n", config->tls_require_redirect_addr);
|
||||||
|
|
||||||
if (!ignore_defaults || strcmp(config->tls_certificate, "") != 0)
|
if (!ignore_defaults || strcmp(config->tls_certificate, "") != 0)
|
||||||
fprintf(stdout, "tls_certificate = \"%s\"\n", config->tls_certificate);
|
fprintf(stdout, "tls_certificate = \"%s\"\n", config->tls_certificate);
|
||||||
|
|
||||||
if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0)
|
if (!ignore_defaults || strcmp(config->tls_private_key, "") != 0)
|
||||||
fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key);
|
fprintf(stdout, "tls_private_key = \"%s\"\n", config->tls_private_key);
|
||||||
|
|
||||||
if (!ignore_defaults || strcmp(config->file_motd, "") != 0)
|
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, "file_motd = \"%s\"\n", config->file_motd);
|
fprintf(stdout, "tls_ciphersuite = \"%s\"\n", config->tls_ciphersuite);
|
||||||
|
|
||||||
|
if (!ignore_defaults || strcmp(config->tls_version, "1.2") != 0)
|
||||||
|
fprintf(stdout, "tls_version = \"%s\"\n", config->tls_version);
|
||||||
|
|
||||||
if (!ignore_defaults || strcmp(config->file_acl, "") != 0)
|
if (!ignore_defaults || strcmp(config->file_acl, "") != 0)
|
||||||
fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl);
|
fprintf(stdout, "file_acl = \"%s\"\n", config->file_acl);
|
||||||
|
|
||||||
if (!ignore_defaults || strcmp(config->file_rules, "") != 0)
|
|
||||||
fprintf(stdout, "file_rules = \"%s\"\n", config->file_rules);
|
|
||||||
|
|
||||||
if (!ignore_defaults || strcmp(config->file_plugins, "") != 0)
|
if (!ignore_defaults || strcmp(config->file_plugins, "") != 0)
|
||||||
fprintf(stdout, "file_plugins = \"%s\"\n", config->file_plugins);
|
fprintf(stdout, "file_plugins = \"%s\"\n", config->file_plugins);
|
||||||
|
|
||||||
|
@ -1,22 +1,28 @@
|
|||||||
/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* THIS FILE IS AUTOGENERATED - DO NOT MODIFY
|
||||||
|
* Created 2014-07-29 12:22, by config.py
|
||||||
|
*/
|
||||||
|
|
||||||
struct hub_config
|
struct hub_config
|
||||||
{
|
{
|
||||||
int hub_enabled; /*<<< Is server enabled (default: 1) */
|
int hub_enabled; /*<<< Is server enabled (default: 1) */
|
||||||
int server_port; /*<<< Server port to bind to (default: 1511) */
|
int server_port; /*<<< Server port to bind to (default: 1511) */
|
||||||
char* server_bind_addr; /*<<< Server bind address (default: any) */
|
char* server_bind_addr; /*<<< Server bind address (default: "any") */
|
||||||
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
|
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
|
||||||
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: ) */
|
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: "") */
|
||||||
int show_banner; /*<<< Show banner on connect (default: 1) */
|
int show_banner; /*<<< Show banner on connect (default: 1) */
|
||||||
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
|
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
|
||||||
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
|
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
|
||||||
int registered_users_only; /*<<< Allow registered users only (default: 0) */
|
int registered_users_only; /*<<< Allow registered users only (default: 0) */
|
||||||
|
int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */
|
||||||
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
|
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
|
||||||
int chat_only; /*<<< Allow chat only operation on hub (default: 0) */
|
|
||||||
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
|
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
|
||||||
char* hub_name; /*<<< Name of hub (default: uhub) */
|
char* hub_name; /*<<< Name of hub (default: "uhub") */
|
||||||
char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */
|
char* hub_description; /*<<< Short hub description, topic or subject. (default: "no description") */
|
||||||
char* redirect_addr; /*<<< A common hub redirect address. (default: ) */
|
char* redirect_addr; /*<<< A common hub redirect address. (default: "") */
|
||||||
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
|
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
|
||||||
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
|
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
|
||||||
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
|
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
|
||||||
@ -41,13 +47,14 @@ struct hub_config
|
|||||||
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
|
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
|
||||||
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
|
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
|
||||||
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
|
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
|
||||||
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
|
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) */
|
||||||
char* tls_certificate; /*<<< Certificate file (default: ) */
|
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: "") */
|
||||||
char* tls_private_key; /*<<< Private key file (default: ) */
|
char* tls_certificate; /*<<< Certificate file (default: "") */
|
||||||
char* file_motd; /*<<< File containing the 'message of the day (default: ) */
|
char* tls_private_key; /*<<< Private key file (default: "") */
|
||||||
char* file_acl; /*<<< File containing access control lists (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* file_rules; /*<<< File containing hub rules (default: ) */
|
char* tls_version; /*<<< Specify minimum TLS version supported. (default: "1.2") */
|
||||||
char* file_plugins; /*<<< Plugin configuration file (default: ) */
|
char* file_acl; /*<<< File containing access control lists (default: "") */
|
||||||
|
char* file_plugins; /*<<< Plugin configuration file (default: "") */
|
||||||
char* msg_hub_full; /*<<< "Hub is full" */
|
char* msg_hub_full; /*<<< "Hub is full" */
|
||||||
char* msg_hub_disabled; /*<<< "Hub is disabled" */
|
char* msg_hub_disabled; /*<<< "Hub is disabled" */
|
||||||
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
|
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
|
||||||
|
429
src/core/hub.c
429
src/core/hub.c
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -21,12 +21,9 @@
|
|||||||
|
|
||||||
struct hub_info* g_hub = 0;
|
struct hub_info* g_hub = 0;
|
||||||
|
|
||||||
#define CHECK_CHAT_ONLY \
|
/* FIXME: Flood control should be done in a plugin! */
|
||||||
if (hub->config->chat_only && u->credentials < cred_operator) \
|
|
||||||
break
|
|
||||||
|
|
||||||
#define CHECK_FLOOD(TYPE, WARN) \
|
#define CHECK_FLOOD(TYPE, WARN) \
|
||||||
if (flood_control_check(&u->flood_ ## TYPE , hub->config->flood_ctl_ ## TYPE, hub->config->flood_ctl_interval, net_get_time())) \
|
if (flood_control_check(&u->flood_ ## TYPE , hub->config->flood_ctl_ ## TYPE, hub->config->flood_ctl_interval, net_get_time()) && !auth_cred_is_unrestricted(u->credentials)) \
|
||||||
{ \
|
{ \
|
||||||
if (WARN) \
|
if (WARN) \
|
||||||
{ \
|
{ \
|
||||||
@ -79,7 +76,12 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
|||||||
case ADC_CMD_DINF:
|
case ADC_CMD_DINF:
|
||||||
case ADC_CMD_EINF:
|
case ADC_CMD_EINF:
|
||||||
case ADC_CMD_FINF:
|
case ADC_CMD_FINF:
|
||||||
|
case ADC_CMD_BQUI:
|
||||||
|
case ADC_CMD_DQUI:
|
||||||
|
case ADC_CMD_EQUI:
|
||||||
|
case ADC_CMD_FQUI:
|
||||||
/* these must never be allowed for security reasons, so we ignore them. */
|
/* these must never be allowed for security reasons, so we ignore them. */
|
||||||
|
CHECK_FLOOD(extras, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADC_CMD_EMSG:
|
case ADC_CMD_EMSG:
|
||||||
@ -95,23 +97,46 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
|||||||
case ADC_CMD_ESCH:
|
case ADC_CMD_ESCH:
|
||||||
case ADC_CMD_FSCH:
|
case ADC_CMD_FSCH:
|
||||||
cmd->priority = -1;
|
cmd->priority = -1;
|
||||||
CHECK_CHAT_ONLY;
|
if (plugin_handle_search(hub, u, cmd->cache) == st_deny)
|
||||||
|
break;
|
||||||
CHECK_FLOOD(search, 1);
|
CHECK_FLOOD(search, 1);
|
||||||
ROUTE_MSG;
|
ROUTE_MSG;
|
||||||
|
|
||||||
|
case ADC_CMD_FRES: // spam
|
||||||
|
case ADC_CMD_BRES: // spam
|
||||||
|
case ADC_CMD_ERES: // pointless.
|
||||||
|
CHECK_FLOOD(extras, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case ADC_CMD_DRES:
|
case ADC_CMD_DRES:
|
||||||
cmd->priority = -1;
|
cmd->priority = -1;
|
||||||
CHECK_CHAT_ONLY;
|
if (plugin_handle_search_result(hub, u, uman_get_user_by_sid(hub->users, cmd->target), cmd->cache) == st_deny)
|
||||||
|
break;
|
||||||
/* CHECK_FLOOD(search, 0); */
|
/* CHECK_FLOOD(search, 0); */
|
||||||
ROUTE_MSG;
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DRCM:
|
case ADC_CMD_DRCM:
|
||||||
case ADC_CMD_DCTM:
|
|
||||||
cmd->priority = -1;
|
cmd->priority = -1;
|
||||||
CHECK_CHAT_ONLY;
|
if (plugin_handle_revconnect(hub, u, uman_get_user_by_sid(hub->users, cmd->target)) == st_deny)
|
||||||
|
break;
|
||||||
CHECK_FLOOD(connect, 1);
|
CHECK_FLOOD(connect, 1);
|
||||||
ROUTE_MSG;
|
ROUTE_MSG;
|
||||||
|
|
||||||
|
case ADC_CMD_DCTM:
|
||||||
|
cmd->priority = -1;
|
||||||
|
if (plugin_handle_connect(hub, u, uman_get_user_by_sid(hub->users, cmd->target)) == st_deny)
|
||||||
|
break;
|
||||||
|
CHECK_FLOOD(connect, 1);
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
|
case ADC_CMD_BCMD:
|
||||||
|
case ADC_CMD_DCMD:
|
||||||
|
case ADC_CMD_ECMD:
|
||||||
|
case ADC_CMD_FCMD:
|
||||||
|
case ADC_CMD_HCMD:
|
||||||
|
CHECK_FLOOD(extras, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CHECK_FLOOD(extras, 1);
|
CHECK_FLOOD(extras, 1);
|
||||||
ROUTE_MSG;
|
ROUTE_MSG;
|
||||||
@ -234,7 +259,7 @@ int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_mes
|
|||||||
|
|
||||||
if (u->state == state_verify)
|
if (u->state == state_verify)
|
||||||
{
|
{
|
||||||
if (acl_password_verify(hub->acl, u, password))
|
if (acl_password_verify(hub, u, password))
|
||||||
{
|
{
|
||||||
on_login_success(hub, u);
|
on_login_success(hub, u);
|
||||||
}
|
}
|
||||||
@ -253,20 +278,35 @@ int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_mes
|
|||||||
int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd)
|
int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* message = adc_msg_get_argument(cmd, 0);
|
char* message = adc_msg_get_argument(cmd, 0);
|
||||||
|
char* message_decoded = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int relay = 1;
|
int relay = 1;
|
||||||
|
int broadcast;
|
||||||
|
int private_msg;
|
||||||
|
int command;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if (!message)
|
if (!message)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
message_decoded = adc_msg_unescape(message);
|
||||||
|
if (!message_decoded)
|
||||||
|
{
|
||||||
|
hub_free(message);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!user_is_logged_in(u))
|
if (!user_is_logged_in(u))
|
||||||
{
|
{
|
||||||
hub_free(message);
|
hub_free(message);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmd->cache[0] == 'B') && (message[0] == '!' || message[0] == '+'))
|
broadcast = (cmd->cache[0] == 'B');
|
||||||
|
private_msg = (cmd->cache[0] == 'D' || cmd->cache[0] == 'E');
|
||||||
|
command = (message[0] == '!' || message[0] == '+');
|
||||||
|
|
||||||
|
if (broadcast && command)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* A message such as "++message" is handled as "+message", by removing the first character.
|
* A message such as "++message" is handled as "+message", by removing the first character.
|
||||||
@ -281,48 +321,50 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
relay = command_dipatcher(hub, u, message);
|
relay = command_invoke(hub->commands, u, message_decoded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((hub->config->chat_is_privileged && !user_is_protected(u)) || (user_flag_get(u, flag_muted))) && (cmd->cache[0] == 'B' || cmd->cache[0] == 'F'))
|
/* FIXME: Plugin should do this! */
|
||||||
|
if (relay && (((hub->config->chat_is_privileged && !user_is_protected(u)) || (user_flag_get(u, flag_muted))) && broadcast))
|
||||||
{
|
{
|
||||||
relay = 0;
|
relay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (relay)
|
||||||
|
{
|
||||||
|
plugin_st status = st_default;
|
||||||
|
if (broadcast)
|
||||||
|
{
|
||||||
|
status = plugin_handle_chat_message(hub, u, message_decoded, 0);
|
||||||
|
}
|
||||||
|
else if (private_msg)
|
||||||
|
{
|
||||||
|
struct hub_user* target = uman_get_user_by_sid(hub->users, cmd->target);
|
||||||
|
if (target)
|
||||||
|
status = plugin_handle_private_message(hub, u, target, message_decoded, 0);
|
||||||
|
else
|
||||||
|
relay = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == st_deny)
|
||||||
|
relay = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (relay)
|
if (relay)
|
||||||
{
|
{
|
||||||
/* adc_msg_remove_named_argument(cmd, "PM"); */
|
/* adc_msg_remove_named_argument(cmd, "PM"); */
|
||||||
if (cmd->cache[0] == 'B')
|
if (broadcast)
|
||||||
hub_chat_history_add(hub, u, cmd);
|
{
|
||||||
|
plugin_log_chat_message(hub, u, message_decoded, 0);
|
||||||
|
}
|
||||||
ret = route_message(hub, u, cmd);
|
ret = route_message(hub, u, cmd);
|
||||||
}
|
}
|
||||||
hub_free(message);
|
hub_free(message);
|
||||||
|
hub_free(message_decoded);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
char* msg_esc = adc_msg_get_argument(cmd, 0);
|
|
||||||
char* message = adc_msg_unescape(msg_esc);
|
|
||||||
char* log = hub_malloc(strlen(message) + strlen(user->id.nick) + 14);
|
|
||||||
sprintf(log, "%s <%s> %s\n", get_timestamp(time(NULL)), user->id.nick, message);
|
|
||||||
list_append(hub->chat_history, log);
|
|
||||||
while (list_size(hub->chat_history) > (size_t) hub->config->max_chat_history)
|
|
||||||
{
|
|
||||||
char* msg = list_get_first(hub->chat_history);
|
|
||||||
list_remove(hub->chat_history, msg);
|
|
||||||
hub_free(msg);
|
|
||||||
}
|
|
||||||
hub_free(message);
|
|
||||||
hub_free(msg_esc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_chat_history_clear(struct hub_info* hub)
|
|
||||||
{
|
|
||||||
list_clear(hub->chat_history, &hub_free);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_send_support(struct hub_info* hub, struct hub_user* u)
|
void hub_send_support(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
if (user_is_connecting(u) || user_is_logged_in(u))
|
if (user_is_connecting(u) || user_is_logged_in(u))
|
||||||
@ -339,7 +381,7 @@ void hub_send_sid(struct hub_info* hub, struct hub_user* u)
|
|||||||
if (user_is_connecting(u))
|
if (user_is_connecting(u))
|
||||||
{
|
{
|
||||||
command = adc_msg_construct(ADC_CMD_ISID, 10);
|
command = adc_msg_construct(ADC_CMD_ISID, 10);
|
||||||
sid = uman_get_free_sid(hub, u);
|
sid = uman_get_free_sid(hub->users, u);
|
||||||
adc_msg_add_argument(command, (const char*) sid_to_string(sid));
|
adc_msg_add_argument(command, (const char*) sid_to_string(sid));
|
||||||
route_to_user(hub, u, command);
|
route_to_user(hub, u, command);
|
||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
@ -364,6 +406,7 @@ void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u)
|
|||||||
{
|
{
|
||||||
struct adc_message* info = adc_msg_copy(hub->command_info);
|
struct adc_message* info = adc_msg_copy(hub->command_info);
|
||||||
int value = 0;
|
int value = 0;
|
||||||
|
uint64_t size = 0;
|
||||||
|
|
||||||
if (user_flag_get(u, feature_ping))
|
if (user_flag_get(u, feature_ping))
|
||||||
{
|
{
|
||||||
@ -377,13 +420,13 @@ void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u)
|
|||||||
adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(hub)));
|
adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(hub)));
|
||||||
adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(hub)));
|
adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(hub)));
|
||||||
adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(hub)));
|
adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(hub)));
|
||||||
adc_msg_add_named_argument(info, "SF", uhub_itoa(hub_get_shared_files(hub)));
|
adc_msg_add_named_argument(info, "SF", uhub_ulltoa(hub_get_shared_files(hub)));
|
||||||
|
|
||||||
/* Maximum/minimum share size */
|
/* Maximum/minimum share size */
|
||||||
value = hub_get_max_share(hub);
|
size = hub_get_max_share(hub);
|
||||||
if (value) adc_msg_add_named_argument(info, "XS", uhub_itoa(value));
|
if (size) adc_msg_add_named_argument(info, "XS", uhub_ulltoa(size));
|
||||||
value = hub_get_min_share(hub);
|
size = hub_get_min_share(hub);
|
||||||
if (value) adc_msg_add_named_argument(info, "MS", uhub_itoa(value));
|
if (size) adc_msg_add_named_argument(info, "MS", uhub_ulltoa(size));
|
||||||
|
|
||||||
/* Maximum/minimum upload slots allowed per user */
|
/* Maximum/minimum upload slots allowed per user */
|
||||||
value = hub_get_max_slots(hub);
|
value = hub_get_max_slots(hub);
|
||||||
@ -440,32 +483,11 @@ void hub_send_handshake(struct hub_info* hub, struct hub_user* u)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hub_send_motd(struct hub_info* hub, struct hub_user* u)
|
|
||||||
{
|
|
||||||
if (hub->command_motd)
|
|
||||||
{
|
|
||||||
route_to_user(hub, u, hub->command_motd);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hub_send_rules(struct hub_info* hub, struct hub_user* u)
|
|
||||||
{
|
|
||||||
if (hub->command_rules)
|
|
||||||
{
|
|
||||||
route_to_user(hub, u, hub->command_rules);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u)
|
void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
struct adc_message* igpa;
|
struct adc_message* igpa;
|
||||||
igpa = adc_msg_construct(ADC_CMD_IGPA, 38);
|
igpa = adc_msg_construct(ADC_CMD_IGPA, 38);
|
||||||
adc_msg_add_argument(igpa, acl_password_generate_challenge(hub->acl, u));
|
adc_msg_add_argument(igpa, acl_password_generate_challenge(hub, u));
|
||||||
user_set_state(u, state_verify);
|
user_set_state(u, state_verify);
|
||||||
route_to_user(hub, u, igpa);
|
route_to_user(hub, u, igpa);
|
||||||
adc_msg_free(igpa);
|
adc_msg_free(igpa);
|
||||||
@ -493,11 +515,28 @@ void hub_send_flood_warning(struct hub_info* hub, struct hub_user* u, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_duplicate_logins_ok(struct hub_info* hub, struct hub_user* user)
|
||||||
|
{
|
||||||
|
struct hub_user* lookup1;
|
||||||
|
struct hub_user* lookup2;
|
||||||
|
|
||||||
|
lookup1 = uman_get_user_by_nick(hub->users, user->id.nick);
|
||||||
|
if (lookup1)
|
||||||
|
return status_msg_inf_error_nick_taken;
|
||||||
|
|
||||||
|
lookup2 = uman_get_user_by_cid(hub->users, user->id.cid);
|
||||||
|
if (lookup2)
|
||||||
|
return status_msg_inf_error_cid_taken;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
||||||
{
|
{
|
||||||
|
int status;
|
||||||
struct hub_info* hub = (struct hub_info*) callback_data;
|
struct hub_info* hub = (struct hub_info*) callback_data;
|
||||||
struct hub_user* user = (struct hub_user*) message->ptr;
|
struct hub_user* user = (struct hub_user*) message->ptr;
|
||||||
assert(hub != NULL);
|
uhub_assert(hub != NULL);
|
||||||
|
|
||||||
switch (message->id)
|
switch (message->id)
|
||||||
{
|
{
|
||||||
@ -511,16 +550,26 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
|
|||||||
hub_send_password_challenge(hub, user);
|
hub_send_password_challenge(hub, user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* Race condition, we could have two messages for two logins queued up.
|
||||||
|
So make sure we don't let the second client in. */
|
||||||
|
status = check_duplicate_logins_ok(hub, user);
|
||||||
|
if (!status)
|
||||||
{
|
{
|
||||||
on_login_success(hub, user);
|
on_login_success(hub, user);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
on_login_failure(hub, user, (enum status_message) status);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case UHUB_EVENT_USER_QUIT:
|
case UHUB_EVENT_USER_QUIT:
|
||||||
{
|
{
|
||||||
uman_remove(hub, user);
|
uman_remove(hub->users, user);
|
||||||
uman_send_quit_message(hub, user);
|
uman_send_quit_message(hub, hub->users, user);
|
||||||
on_logout_user(hub, user);
|
on_logout_user(hub, user);
|
||||||
hub_schedule_destroy_user(hub, user);
|
hub_schedule_destroy_user(hub, user);
|
||||||
break;
|
break;
|
||||||
@ -537,7 +586,7 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
|
|||||||
struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list);
|
struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list);
|
||||||
while (u)
|
while (u)
|
||||||
{
|
{
|
||||||
uman_remove(hub, u);
|
uman_remove(hub->users, u);
|
||||||
user_destroy(u);
|
user_destroy(u);
|
||||||
u = (struct hub_user*) list_get_first(hub->users->list);
|
u = (struct hub_user*) list_get_first(hub->users->list);
|
||||||
}
|
}
|
||||||
@ -551,6 +600,31 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void hub_update_stats(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
const int factor = TIMEOUT_STATS;
|
||||||
|
struct net_statistics* total;
|
||||||
|
struct net_statistics* intermediate;
|
||||||
|
net_stats_get(&intermediate, &total);
|
||||||
|
|
||||||
|
hub->stats.net_tx = (intermediate->tx / factor);
|
||||||
|
hub->stats.net_rx = (intermediate->rx / factor);
|
||||||
|
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
|
||||||
|
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
|
||||||
|
hub->stats.net_tx_total = total->tx;
|
||||||
|
hub->stats.net_rx_total = total->rx;
|
||||||
|
|
||||||
|
net_stats_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hub_timer_statistics(struct timeout_evt* t)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = (struct hub_info*) t->ptr;
|
||||||
|
hub_update_stats(hub);
|
||||||
|
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS);
|
||||||
|
}
|
||||||
|
|
||||||
static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
|
static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
|
||||||
{
|
{
|
||||||
struct net_connection* server;
|
struct net_connection* server;
|
||||||
@ -657,40 +731,29 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
|
|||||||
{
|
{
|
||||||
if (config->tls_enable)
|
if (config->tls_enable)
|
||||||
{
|
{
|
||||||
hub->ssl_method = SSLv23_method(); /* TLSv1_method() */
|
hub->ctx = net_ssl_context_create(config->tls_version, config->tls_ciphersuite);
|
||||||
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
|
|
||||||
|
|
||||||
/* Disable SSLv2 */
|
if (!hub->ctx)
|
||||||
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
|
|
||||||
|
|
||||||
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("SSL_CTX_use_certificate_file: %s", ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_CTX_use_PrivateKey_file(hub->ssl_ctx, config->tls_private_key, SSL_FILETYPE_PEM) < 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("SSL_CTX_use_PrivateKey_file: %s", ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_CTX_check_private_key(hub->ssl_ctx) != 1)
|
|
||||||
{
|
|
||||||
LOG_FATAL("SSL_CTX_check_private_key: Private key does not match the certificate public key: %s", ERR_error_string(ERR_get_error(), NULL));
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
LOG_INFO("Enabling TLS (%s), using certificate: %s, private key: %s", net_ssl_get_provider(), config->tls_certificate, config->tls_private_key);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unload_ssl_certificates(struct hub_info* hub)
|
static void unload_ssl_certificates(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
if (hub->ssl_ctx)
|
if (hub->ctx)
|
||||||
{
|
net_ssl_context_destroy(hub->ctx);
|
||||||
SSL_CTX_free(hub->ssl_ctx);
|
|
||||||
}
|
}
|
||||||
}
|
#endif /* SSL_SUPPORT */
|
||||||
#endif
|
|
||||||
|
|
||||||
struct hub_info* hub_start_service(struct hub_config* config)
|
struct hub_info* hub_start_service(struct hub_config* config)
|
||||||
{
|
{
|
||||||
@ -731,7 +794,8 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
hub->config = config;
|
hub->config = config;
|
||||||
hub->users = NULL;
|
hub->users = NULL;
|
||||||
|
|
||||||
if (uman_init(hub) == -1)
|
hub->users = uman_init();
|
||||||
|
if (!hub->users)
|
||||||
{
|
{
|
||||||
net_con_close(hub->server);
|
net_con_close(hub->server);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
@ -741,7 +805,7 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
|
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
|
||||||
{
|
{
|
||||||
net_con_close(hub->server);
|
net_con_close(hub->server);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub->users);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -753,30 +817,27 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
net_con_close(hub->server);
|
net_con_close(hub->server);
|
||||||
hub_free(hub->recvbuf);
|
hub_free(hub->recvbuf);
|
||||||
hub_free(hub->sendbuf);
|
hub_free(hub->sendbuf);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub->users);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hub->chat_history = (struct linked_list*) list_create();
|
|
||||||
hub->logout_info = (struct linked_list*) list_create();
|
hub->logout_info = (struct linked_list*) list_create();
|
||||||
if (!hub->chat_history)
|
|
||||||
{
|
|
||||||
net_con_close(hub->server);
|
|
||||||
list_destroy(hub->chat_history);
|
|
||||||
list_destroy(hub->logout_info);
|
|
||||||
hub_free(hub->recvbuf);
|
|
||||||
hub_free(hub->sendbuf);
|
|
||||||
uman_shutdown(hub);
|
|
||||||
hub_free(hub);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
server_alt_port_start(hub, config);
|
server_alt_port_start(hub, config);
|
||||||
|
|
||||||
hub->status = hub_status_running;
|
hub->status = hub_status_running;
|
||||||
|
|
||||||
g_hub = hub;
|
g_hub = hub;
|
||||||
|
|
||||||
|
if (net_backend_get_timeout_queue())
|
||||||
|
{
|
||||||
|
hub->stats.timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||||
|
timeout_evt_initialize(hub->stats.timeout, hub_timer_statistics, hub);
|
||||||
|
timeout_queue_insert(net_backend_get_timeout_queue(), hub->stats.timeout, TIMEOUT_STATS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the hub command sub-system
|
||||||
|
hub->commands = command_initialize(hub);
|
||||||
return hub;
|
return hub;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,70 +846,61 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
{
|
{
|
||||||
LOG_DEBUG("hub_shutdown_service()");
|
LOG_DEBUG("hub_shutdown_service()");
|
||||||
|
|
||||||
|
if (net_backend_get_timeout_queue())
|
||||||
|
{
|
||||||
|
timeout_queue_remove(net_backend_get_timeout_queue(), hub->stats.timeout);
|
||||||
|
hub_free(hub->stats.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
unload_ssl_certificates(hub);
|
unload_ssl_certificates(hub);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
event_queue_shutdown(hub->queue);
|
event_queue_shutdown(hub->queue);
|
||||||
net_con_close(hub->server);
|
net_con_close(hub->server);
|
||||||
hub_free(hub->server);
|
|
||||||
server_alt_port_stop(hub);
|
server_alt_port_stop(hub);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub->users);
|
||||||
hub->status = hub_status_stopped;
|
hub->status = hub_status_stopped;
|
||||||
hub_free(hub->sendbuf);
|
hub_free(hub->sendbuf);
|
||||||
hub_free(hub->recvbuf);
|
hub_free(hub->recvbuf);
|
||||||
hub_chat_history_clear(hub);
|
|
||||||
list_destroy(hub->chat_history);
|
|
||||||
list_clear(hub->logout_info, &hub_free);
|
list_clear(hub->logout_info, &hub_free);
|
||||||
list_destroy(hub->logout_info);
|
list_destroy(hub->logout_info);
|
||||||
|
command_shutdown(hub->commands);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
hub = 0;
|
hub = 0;
|
||||||
g_hub = 0;
|
g_hub = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
int hub_plugins_load(struct hub_info* hub)
|
||||||
void hub_plugins_load(struct hub_info* hub)
|
|
||||||
{
|
{
|
||||||
if (!hub->config->file_plugins || !*hub->config->file_plugins)
|
if (!hub->config->file_plugins || !*hub->config->file_plugins)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins));
|
hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins));
|
||||||
if (!hub->plugins)
|
if (!hub->plugins)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
if (plugin_initialize(hub->config, hub->plugins) < 0)
|
if (plugin_initialize(hub->config, hub) < 0)
|
||||||
{
|
{
|
||||||
hub_free(hub->plugins);
|
hub_free(hub->plugins);
|
||||||
hub->plugins = 0;
|
hub->plugins = 0;
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_plugins_unload(struct hub_info* hub)
|
void hub_plugins_unload(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
if (!hub->plugins || !hub->plugins->loaded)
|
if (hub->plugins)
|
||||||
{
|
{
|
||||||
return;
|
plugin_shutdown(hub->plugins);
|
||||||
}
|
|
||||||
|
|
||||||
struct uhub_plugin_handle* plugin = (struct uhub_plugin_handle*) list_get_first(hub->plugins->loaded);
|
|
||||||
while (plugin)
|
|
||||||
{
|
|
||||||
plugin_unload(plugin);
|
|
||||||
plugin = (struct uhub_plugin_handle*) list_get_next(hub->plugins->loaded);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_destroy(hub->plugins->loaded);
|
|
||||||
hub_free(hub->plugins->plugin_dir);
|
|
||||||
hub_free(hub->plugins);
|
hub_free(hub->plugins);
|
||||||
hub->plugins = 0;
|
hub->plugins = 0;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||||
{
|
{
|
||||||
int fd, ret;
|
|
||||||
char buf[MAX_RECV_BUF];
|
|
||||||
char* tmp;
|
char* tmp;
|
||||||
char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */
|
char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */
|
||||||
|
|
||||||
@ -857,7 +909,8 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
if (hub->command_info)
|
if (hub->command_info)
|
||||||
{
|
{
|
||||||
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
|
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
|
||||||
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT, 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);
|
tmp = adc_msg_escape(hub->config->hub_name);
|
||||||
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp);
|
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp);
|
||||||
@ -868,39 +921,6 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
hub_free(tmp);
|
hub_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (Re-)read the message of the day */
|
|
||||||
hub->command_motd = 0;
|
|
||||||
fd = (hub->config->file_motd && *hub->config->file_motd) ? open(hub->config->file_motd, 0) : -1;
|
|
||||||
if (fd != -1)
|
|
||||||
{
|
|
||||||
ret = read(fd, buf, MAX_RECV_BUF);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
buf[ret] = 0;
|
|
||||||
tmp = adc_msg_escape(buf);
|
|
||||||
hub->command_motd = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
|
||||||
adc_msg_add_argument(hub->command_motd, tmp);
|
|
||||||
hub_free(tmp);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
hub->command_rules = 0;
|
|
||||||
fd = (hub->config->file_rules && *hub->config->file_rules) ? open(hub->config->file_rules, 0) : -1;
|
|
||||||
if (fd != -1)
|
|
||||||
{
|
|
||||||
ret = read(fd, buf, MAX_RECV_BUF);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
buf[ret] = 0;
|
|
||||||
tmp = adc_msg_escape(buf);
|
|
||||||
hub->command_rules = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
|
||||||
adc_msg_add_argument(hub->command_rules, tmp);
|
|
||||||
hub_free(tmp);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT));
|
hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT));
|
||||||
if (hub->command_support)
|
if (hub->command_support)
|
||||||
{
|
{
|
||||||
@ -919,9 +939,12 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
hub_free(tmp);
|
hub_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
if (hub_plugins_load(hub) < 0)
|
||||||
hub_plugins_load(hub);
|
{
|
||||||
#endif
|
LOG_FATAL("Unable to load plugins.");
|
||||||
|
hub->status = hub_status_shutdown;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
|
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
|
||||||
hub_free(server);
|
hub_free(server);
|
||||||
@ -930,53 +953,13 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
|
|
||||||
void hub_free_variables(struct hub_info* hub)
|
void hub_free_variables(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
hub_plugins_unload(hub);
|
hub_plugins_unload(hub);
|
||||||
#endif
|
|
||||||
|
|
||||||
adc_msg_free(hub->command_info);
|
adc_msg_free(hub->command_info);
|
||||||
adc_msg_free(hub->command_banner);
|
adc_msg_free(hub->command_banner);
|
||||||
|
|
||||||
if (hub->command_motd)
|
|
||||||
adc_msg_free(hub->command_motd);
|
|
||||||
|
|
||||||
if (hub->command_rules)
|
|
||||||
adc_msg_free(hub->command_rules);
|
|
||||||
|
|
||||||
adc_msg_free(hub->command_support);
|
adc_msg_free(hub->command_support);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 1 if nickname is in use, or 0 if not used.
|
|
||||||
*/
|
|
||||||
static inline int is_nick_in_use(struct hub_info* hub, const char* nick)
|
|
||||||
{
|
|
||||||
struct hub_user* lookup = uman_get_user_by_nick(hub, nick);
|
|
||||||
if (lookup)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 1 if CID is in use, or 0 if not used.
|
|
||||||
*/
|
|
||||||
static inline int is_cid_in_use(struct hub_info* hub, const char* cid)
|
|
||||||
{
|
|
||||||
struct hub_user* lookup = uman_get_user_by_cid(hub, cid);
|
|
||||||
if (lookup)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void set_status_code(enum msg_status_level level, int code, char buffer[4])
|
static void set_status_code(enum msg_status_level level, int code, char buffer[4])
|
||||||
{
|
{
|
||||||
buffer[0] = ('0' + (int) level);
|
buffer[0] = ('0' + (int) level);
|
||||||
@ -1062,6 +1045,8 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
|||||||
|
|
||||||
if (level >= status_level_fatal)
|
if (level >= status_level_fatal)
|
||||||
{
|
{
|
||||||
|
adc_msg_add_argument(qui, sid_to_string(user->id.sid));
|
||||||
|
|
||||||
snprintf(buf, 230, "MS%s", escaped_text);
|
snprintf(buf, 230, "MS%s", escaped_text);
|
||||||
adc_msg_add_argument(qui, buf);
|
adc_msg_add_argument(qui, buf);
|
||||||
|
|
||||||
@ -1190,12 +1175,16 @@ uint64_t hub_get_shared_files(struct hub_info* hub)
|
|||||||
|
|
||||||
uint64_t hub_get_min_share(struct hub_info* hub)
|
uint64_t hub_get_min_share(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
return 1024 * 1024 * hub->config->limit_min_share;
|
uint64_t size = hub->config->limit_min_share;
|
||||||
|
size *= (1024 * 1024);
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t hub_get_max_share(struct hub_info* hub)
|
uint64_t hub_get_max_share(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
return 1024 * 1024 * hub->config->limit_max_share;
|
uint64_t size = hub->config->limit_max_share;
|
||||||
|
size *= (1024 * 1024);
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hub_get_min_slots(struct hub_info* hub)
|
size_t hub_get_min_slots(struct hub_info* hub)
|
||||||
@ -1328,17 +1317,15 @@ void hub_logout_log(struct hub_info* hub, struct hub_user* user)
|
|||||||
struct hub_logout_info* loginfo = hub_malloc_zero(sizeof(struct hub_logout_info));
|
struct hub_logout_info* loginfo = hub_malloc_zero(sizeof(struct hub_logout_info));
|
||||||
if (!loginfo) return;
|
if (!loginfo) return;
|
||||||
loginfo->time = time(NULL);
|
loginfo->time = time(NULL);
|
||||||
strcpy(loginfo->cid, user->id.cid);
|
memcpy(loginfo->cid, user->id.cid, sizeof(loginfo->cid));
|
||||||
strcpy(loginfo->nick, user->id.nick);
|
memcpy(loginfo->nick, user->id.nick, sizeof(loginfo->nick));
|
||||||
memcpy(&loginfo->addr, &user->id.addr, sizeof(struct ip_addr_encap));
|
memcpy(&loginfo->addr, &user->id.addr, sizeof(struct ip_addr_encap));
|
||||||
loginfo->reason = user->quit_reason;
|
loginfo->reason = user->quit_reason;
|
||||||
|
|
||||||
list_append(hub->logout_info, loginfo);
|
list_append(hub->logout_info, loginfo);
|
||||||
while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log)
|
while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log)
|
||||||
{
|
{
|
||||||
struct hub_logout_info* entry = list_get_first(hub->logout_info);
|
list_remove_first(hub->logout_info, hub_free);
|
||||||
list_remove(hub->logout_info, entry);
|
|
||||||
hub_free(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ enum status_message
|
|||||||
status_msg_hub_registered_users_only = -3, /* hub is for registered users only */
|
status_msg_hub_registered_users_only = -3, /* hub is for registered users only */
|
||||||
status_msg_inf_error_nick_missing = -4, /* no nickname given */
|
status_msg_inf_error_nick_missing = -4, /* no nickname given */
|
||||||
status_msg_inf_error_nick_multiple = -5, /* multiple nicknames given */
|
status_msg_inf_error_nick_multiple = -5, /* multiple nicknames given */
|
||||||
status_msg_inf_error_nick_invalid = -6, /* generic/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_long = -7, /* nickname too long */
|
||||||
status_msg_inf_error_nick_short = -8, /* nickname too short */
|
status_msg_inf_error_nick_short = -8, /* nickname too short */
|
||||||
status_msg_inf_error_nick_spaces = -9, /* nickname cannot start with spaces */
|
status_msg_inf_error_nick_spaces = -9, /* nickname cannot start with spaces */
|
||||||
@ -50,8 +50,8 @@ enum status_message
|
|||||||
status_msg_user_share_size_high = -41, /* User is sharing too much. */
|
status_msg_user_share_size_high = -41, /* User is sharing too much. */
|
||||||
status_msg_user_slots_low = -42, /* User has too few slots open. */
|
status_msg_user_slots_low = -42, /* User has too few slots open. */
|
||||||
status_msg_user_slots_high = -43, /* User has too many slots open. */
|
status_msg_user_slots_high = -43, /* User has too many slots open. */
|
||||||
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
status_msg_user_hub_limit_low = -44, /* User is on too few hubs. */
|
||||||
status_msg_user_hub_limit_high = -45, /* Use is on too many 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_no_common_hash = -50, /* No common hash algorithms */
|
||||||
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
||||||
@ -81,6 +81,7 @@ struct hub_stats
|
|||||||
size_t net_rx_peak;
|
size_t net_rx_peak;
|
||||||
size_t net_tx_total;
|
size_t net_tx_total;
|
||||||
size_t net_rx_total;
|
size_t net_rx_total;
|
||||||
|
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hub_logout_info
|
struct hub_logout_info
|
||||||
@ -103,24 +104,19 @@ struct hub_info
|
|||||||
struct acl_handle* acl;
|
struct acl_handle* acl;
|
||||||
struct adc_message* command_info; /* The hub's INF command */
|
struct adc_message* command_info; /* The hub's INF command */
|
||||||
struct adc_message* command_support; /* The hub's SUP command */
|
struct adc_message* command_support; /* The hub's SUP command */
|
||||||
struct adc_message* command_motd; /* The message of the day */
|
|
||||||
struct adc_message* command_rules; /* The hub rules */
|
|
||||||
struct adc_message* command_banner; /* The default welcome message */
|
struct adc_message* command_banner; /* The default welcome message */
|
||||||
time_t tm_started;
|
time_t tm_started;
|
||||||
int status;
|
int status;
|
||||||
char* recvbuf; /* Global receive buffer */
|
char* recvbuf; /* Global receive buffer */
|
||||||
char* sendbuf; /* Global send buffer */
|
char* sendbuf; /* Global send buffer */
|
||||||
|
|
||||||
struct linked_list* chat_history; /* Chat history */
|
|
||||||
struct linked_list* logout_info; /* Log of people logging out. */
|
struct linked_list* logout_info; /* Log of people logging out. */
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
struct command_base* commands; /* Hub command handler */
|
||||||
struct uhub_plugins* plugins;
|
struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
SSL_METHOD* ssl_method;
|
struct ssl_context_handle* ctx;
|
||||||
SSL_CTX* ssl_ctx;
|
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -154,16 +150,6 @@ extern int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct
|
|||||||
*/
|
*/
|
||||||
extern int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
extern int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a chat message to the chat history
|
|
||||||
*/
|
|
||||||
extern void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear the chat history.
|
|
||||||
*/
|
|
||||||
extern void hub_chat_history_clear(struct hub_info* hub);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally by hub_handle_info
|
* Used internally by hub_handle_info
|
||||||
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
|
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
|
||||||
@ -206,19 +192,6 @@ extern void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u);
|
|||||||
*/
|
*/
|
||||||
extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
|
extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a welcome message containing the message of the day to
|
|
||||||
* one particular user. This can be sent in any point in time.
|
|
||||||
* @return 1 if the motd were sent.
|
|
||||||
*/
|
|
||||||
extern int hub_send_motd(struct hub_info* hub, struct hub_user* u);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the rules if configured.
|
|
||||||
* @return 1 if the rules were sent.
|
|
||||||
*/
|
|
||||||
extern int hub_send_rules(struct hub_info* hub, struct hub_user* u);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a password challenge to a user.
|
* Send a password challenge to a user.
|
||||||
* This is only used if the user tries to access the hub using a
|
* This is only used if the user tries to access the hub using a
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,76 +13,29 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "plugin_api/handle.h"
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
static void log_user_login(struct hub_user* u)
|
/* Notify plugins, etc */
|
||||||
{
|
|
||||||
const char* cred = get_user_credential_string(u->credentials);
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
LOG_USER("LoginOK %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, cred, u->user_agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_user_login_error(struct hub_user* u, enum status_message msg)
|
|
||||||
{
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
const char* message = hub_get_status_message_log(u->hub, msg);
|
|
||||||
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_user_update_error(struct hub_user* u, enum status_message msg)
|
|
||||||
{
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
const char* message = hub_get_status_message_log(u->hub, msg);
|
|
||||||
LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_user_logout(struct hub_user* u, const char* message)
|
|
||||||
{
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
LOG_USER("Logout %s/%s %s \"%s\" (%s)", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_user_nick_change(struct hub_user* u, const char* nick)
|
|
||||||
{
|
|
||||||
const char* addr = user_get_address(u);
|
|
||||||
LOG_USER("NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Send MOTD, do logging etc */
|
|
||||||
void on_login_success(struct hub_info* hub, struct hub_user* u)
|
void on_login_success(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
/* Send user list of all existing users */
|
/* Send user list of all existing users */
|
||||||
if (!uman_send_user_list(hub, u))
|
if (!uman_send_user_list(hub, hub->users, u))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Mark as being in the normal state, and add user to the user list */
|
/* Mark as being in the normal state, and add user to the user list */
|
||||||
user_set_state(u, state_normal);
|
user_set_state(u, state_normal);
|
||||||
uman_add(hub, u);
|
uman_add(hub->users, u);
|
||||||
|
|
||||||
/* Print log message */
|
|
||||||
log_user_login(u);
|
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
plugin_log_user_login_success(hub, u);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Announce new user to all connected users */
|
/* Announce new user to all connected users */
|
||||||
if (user_is_logged_in(u))
|
if (user_is_logged_in(u))
|
||||||
route_info_message(hub, u);
|
route_info_message(hub, u);
|
||||||
|
|
||||||
/* Send message of the day (if any) */
|
plugin_log_user_login_success(hub, u);
|
||||||
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
|
||||||
hub_send_motd(hub, u);
|
|
||||||
|
|
||||||
/* Send message of the day (if any) */
|
|
||||||
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
|
||||||
hub_send_rules(hub, u);
|
|
||||||
|
|
||||||
/* reset timeout */
|
/* reset timeout */
|
||||||
net_con_clear_timeout(u->connection);
|
net_con_clear_timeout(u->connection);
|
||||||
@ -90,14 +43,14 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
|
|||||||
|
|
||||||
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
||||||
{
|
{
|
||||||
log_user_login_error(u, msg);
|
plugin_log_user_login_error(hub, u, hub_get_status_message_log(hub, msg));
|
||||||
hub_send_status(hub, u, msg, status_level_fatal);
|
hub_send_status(hub, u, msg, status_level_fatal);
|
||||||
hub_disconnect_user(hub, u, quit_logon_error);
|
hub_disconnect_user(hub, u, quit_logon_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
||||||
{
|
{
|
||||||
log_user_update_error(u, msg);
|
plugin_log_user_update_error(hub, u, hub_get_status_message_log(hub, msg));
|
||||||
hub_send_status(hub, u, msg, status_level_fatal);
|
hub_send_status(hub, u, msg, status_level_fatal);
|
||||||
hub_disconnect_user(hub, u, quit_update_error);
|
hub_disconnect_user(hub, u, quit_update_error);
|
||||||
}
|
}
|
||||||
@ -106,19 +59,15 @@ void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
|
|||||||
{
|
{
|
||||||
if (user_is_logged_in(u))
|
if (user_is_logged_in(u))
|
||||||
{
|
{
|
||||||
log_user_nick_change(u, nick);
|
plugin_log_user_nick_change(hub, u, nick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_logout_user(struct hub_info* hub, struct hub_user* user)
|
void on_logout_user(struct hub_info* hub, struct hub_user* user)
|
||||||
{
|
{
|
||||||
const char* reason = user_get_quit_reason_string(user->quit_reason);
|
const char* reason = user_get_quit_reason_string(user->quit_reason);
|
||||||
log_user_logout(user, reason);
|
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
plugin_log_user_logout(hub, user);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
plugin_log_user_logout(hub, user, reason);
|
||||||
hub_logout_log(hub, user);
|
hub_logout_log(hub, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
110
src/core/inf.c
110
src/core/inf.c
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ static int check_hash_tiger(const char* cid, const char* pid)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
|
* FIXME: Only works for tiger hash. If a client doesn't support tiger we cannot let it in!
|
||||||
*/
|
*/
|
||||||
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
@ -226,9 +226,7 @@ static int check_network(struct hub_info* hub, struct hub_user* user, struct adc
|
|||||||
static void strip_network(struct hub_user* user, struct adc_message* cmd)
|
static void strip_network(struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
|
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nick_length_ok(const char* nick)
|
static int nick_length_ok(const char* nick)
|
||||||
@ -327,8 +325,8 @@ static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_me
|
|||||||
|
|
||||||
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
struct hub_user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
|
struct hub_user* lookup1 = uman_get_user_by_nick(hub->users, user->id.nick);
|
||||||
struct hub_user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
|
struct hub_user* lookup2 = uman_get_user_by_cid(hub->users, user->id.cid);
|
||||||
|
|
||||||
if (lookup1 == user)
|
if (lookup1 == user)
|
||||||
{
|
{
|
||||||
@ -339,9 +337,19 @@ static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct a
|
|||||||
{
|
{
|
||||||
if (lookup1 == lookup2)
|
if (lookup1 == lookup2)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("check_logged_in: exact same user is logged in: %s", user->id.nick);
|
if (user_flag_get(lookup1, flag_choke))
|
||||||
|
{
|
||||||
|
LOG_DEBUG("check_logged_in: exact same user is already logged in, but likely ghost: %s", user->id.nick);
|
||||||
|
|
||||||
|
// Old user unable to swallow data.
|
||||||
|
// Disconnect the existing user, and allow new user to enter.
|
||||||
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
|
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
|
||||||
return 0;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DEBUG("check_logged_in: exact same user is already logged in: %s", user->id.nick);
|
||||||
|
return status_msg_inf_error_cid_taken;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -368,21 +376,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)
|
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* ua_encoded = 0;
|
char* ua_name_encoded = 0;
|
||||||
char* ua = 0;
|
char* ua_version_encoded = 0;
|
||||||
|
char* str = 0;
|
||||||
|
size_t offset = 0;
|
||||||
|
|
||||||
/* Get client user agent version */
|
/* Get client user agent version */
|
||||||
ua_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
|
ua_name_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT);
|
||||||
if (ua_encoded)
|
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);
|
str = adc_msg_unescape(ua_name_encoded);
|
||||||
if (ua)
|
if (str)
|
||||||
{
|
{
|
||||||
memcpy(user->user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
|
offset = strlen(str);
|
||||||
hub_free(ua);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +453,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
|
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
ssize_t shared_files = atoll(arg);
|
int shared_files = atoi(arg);
|
||||||
if (shared_files < 0)
|
if (shared_files < 0)
|
||||||
shared_files = 0;
|
shared_files = 0;
|
||||||
|
|
||||||
@ -446,7 +470,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
|
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
ssize_t num = atoll(arg);
|
int num = atoi(arg);
|
||||||
if (num < 0) num = 0;
|
if (num < 0) num = 0;
|
||||||
user->limits.hub_count_user = num;
|
user->limits.hub_count_user = num;
|
||||||
hub_free(arg);
|
hub_free(arg);
|
||||||
@ -456,7 +480,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
|
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
ssize_t num = atoll(arg);
|
int num = atoi(arg);
|
||||||
if (num < 0) num = 0;
|
if (num < 0) num = 0;
|
||||||
user->limits.hub_count_registered = num;
|
user->limits.hub_count_registered = num;
|
||||||
hub_free(arg);
|
hub_free(arg);
|
||||||
@ -466,7 +490,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR);
|
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
ssize_t num = atoll(arg);
|
int num = atoi(arg);
|
||||||
if (num < 0) num = 0;
|
if (num < 0) num = 0;
|
||||||
user->limits.hub_count_operator = num;
|
user->limits.hub_count_operator = num;
|
||||||
hub_free(arg);
|
hub_free(arg);
|
||||||
@ -476,7 +500,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS);
|
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
ssize_t num = atoll(arg);
|
int num = atoi(arg);
|
||||||
if (num < 0) num = 0;
|
if (num < 0) num = 0;
|
||||||
user->limits.upload_slots = num;
|
user->limits.upload_slots = num;
|
||||||
hub_free(arg);
|
hub_free(arg);
|
||||||
@ -535,48 +559,61 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct hub_user_access_info* info = acl_get_access_info(hub->acl, user->id.nick);
|
struct auth_info* info = acl_get_access_info(hub, user->id.nick);
|
||||||
|
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
user->credentials = info->status;
|
user->credentials = info->credentials;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
user->credentials = cred_guest;
|
user->credentials = auth_cred_guest;
|
||||||
}
|
}
|
||||||
|
hub_free(info);
|
||||||
|
|
||||||
switch (user->credentials)
|
switch (user->credentials)
|
||||||
{
|
{
|
||||||
case cred_none:
|
case auth_cred_none:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_bot:
|
case auth_cred_bot:
|
||||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_guest:
|
case auth_cred_ubot:
|
||||||
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case auth_cred_guest:
|
||||||
/* Nothing to be added to the info message */
|
/* Nothing to be added to the info message */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_user:
|
case auth_cred_user:
|
||||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_operator:
|
case auth_cred_operator:
|
||||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_super:
|
case auth_cred_opbot:
|
||||||
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_HUBBOT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case auth_cred_opubot:
|
||||||
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_HUBBOT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case auth_cred_super:
|
||||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_admin:
|
case auth_cred_admin:
|
||||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
|
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cred_link:
|
case auth_cred_link:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,7 +628,7 @@ static int check_is_hub_full(struct hub_info* hub, struct hub_user* user)
|
|||||||
* If hub is full, don't let users in, but we still want to allow
|
* If hub is full, don't let users in, but we still want to allow
|
||||||
* operators and admins to enter the hub.
|
* operators and admins to enter the hub.
|
||||||
*/
|
*/
|
||||||
if (hub->config->max_users && hub->users->count >= hub->config->max_users && !user_is_protected(user))
|
if (hub->config->max_users && hub->users->count >= (size_t) hub->config->max_users && !user_is_protected(user))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -623,7 +660,8 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
|
|||||||
{
|
{
|
||||||
if (hub->config->low_bandwidth_mode)
|
if (hub->config->low_bandwidth_mode)
|
||||||
{
|
{
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
|
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_SHARED_FILES);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,12 +13,11 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "hubio.h"
|
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
static void debug_msg(const char* prefix, struct adc_message* msg)
|
static void debug_msg(const char* prefix, struct adc_message* msg)
|
||||||
@ -35,13 +34,13 @@ static void debug_msg(const char* prefix, struct adc_message* msg)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct hub_recvq* hub_recvq_create()
|
struct ioq_recv* ioq_recv_create()
|
||||||
{
|
{
|
||||||
struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
|
struct ioq_recv* q = hub_malloc_zero(sizeof(struct ioq_recv));
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_recvq_destroy(struct hub_recvq* q)
|
void ioq_recv_destroy(struct ioq_recv* q)
|
||||||
{
|
{
|
||||||
if (q)
|
if (q)
|
||||||
{
|
{
|
||||||
@ -50,9 +49,9 @@ void hub_recvq_destroy(struct hub_recvq* q)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
|
size_t ioq_recv_get(struct ioq_recv* q, void* buf, size_t bufsize)
|
||||||
{
|
{
|
||||||
assert(bufsize >= q->size);
|
uhub_assert(bufsize >= q->size);
|
||||||
if (q->size)
|
if (q->size)
|
||||||
{
|
{
|
||||||
size_t n = q->size;
|
size_t n = q->size;
|
||||||
@ -65,7 +64,7 @@ size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
|
size_t ioq_recv_set(struct ioq_recv* q, void* buf, size_t bufsize)
|
||||||
{
|
{
|
||||||
if (q->buf)
|
if (q->buf)
|
||||||
{
|
{
|
||||||
@ -89,9 +88,9 @@ size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_sendq* hub_sendq_create()
|
struct ioq_send* ioq_send_create()
|
||||||
{
|
{
|
||||||
struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
|
struct ioq_send* q = hub_malloc_zero(sizeof(struct ioq_send));
|
||||||
if (!q)
|
if (!q)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -110,7 +109,7 @@ static void clear_send_queue_callback(void* ptr)
|
|||||||
adc_msg_free((struct adc_message*) ptr);
|
adc_msg_free((struct adc_message*) ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_sendq_destroy(struct hub_sendq* q)
|
void ioq_send_destroy(struct ioq_send* q)
|
||||||
{
|
{
|
||||||
if (q)
|
if (q)
|
||||||
{
|
{
|
||||||
@ -120,21 +119,21 @@ void hub_sendq_destroy(struct hub_sendq* q)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
void ioq_send_add(struct ioq_send* q, struct adc_message* msg_)
|
||||||
{
|
{
|
||||||
struct adc_message* msg = adc_msg_incref(msg_);
|
struct adc_message* msg = adc_msg_incref(msg_);
|
||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
debug_msg("hub_sendq_add", msg);
|
debug_msg("ioq_send_add", msg);
|
||||||
#endif
|
#endif
|
||||||
assert(msg->cache && *msg->cache);
|
uhub_assert(msg->cache && *msg->cache);
|
||||||
list_append(q->queue, msg);
|
list_append(q->queue, msg);
|
||||||
q->size += msg->length;
|
q->size += msg->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
static void ioq_send_remove(struct ioq_send* q, struct adc_message* msg)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
debug_msg("hub_sendq_remove", msg);
|
debug_msg("ioq_send_remove", msg);
|
||||||
#endif
|
#endif
|
||||||
list_remove(q->queue, msg);
|
list_remove(q->queue, msg);
|
||||||
q->size -= msg->length;
|
q->size -= msg->length;
|
||||||
@ -142,13 +141,13 @@ void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
|||||||
q->offset = 0;
|
q->offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
int ioq_send_send(struct ioq_send* q, struct net_connection* con)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct adc_message* msg = list_get_first(q->queue);
|
struct adc_message* msg = list_get_first(q->queue);
|
||||||
if (!msg) return 0;
|
if (!msg) return 0;
|
||||||
assert(msg->cache && *msg->cache);
|
uhub_assert(msg->cache && *msg->cache);
|
||||||
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
ret = net_con_send(con, msg->cache + q->offset, msg->length - q->offset);
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
@ -156,18 +155,18 @@ int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
|||||||
if (msg->length - q->offset > 0)
|
if (msg->length - q->offset > 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hub_sendq_remove(q, msg);
|
ioq_send_remove(q, msg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hub_sendq_is_empty(struct hub_sendq* q)
|
int ioq_send_is_empty(struct ioq_send* q)
|
||||||
{
|
{
|
||||||
return (q->size - q->offset) == 0;
|
return (q->size - q->offset) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hub_sendq_get_bytes(struct hub_sendq* q)
|
size_t ioq_send_get_bytes(struct ioq_send* q)
|
||||||
{
|
{
|
||||||
return q->size - q->offset;
|
return q->size - q->offset;
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,29 +13,29 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HAVE_UHUB_HUB_IO_H
|
#ifndef HAVE_UHUB_IO_QUEUE_H
|
||||||
#define HAVE_UHUB_HUB_IO_H
|
#define HAVE_UHUB_IO_QUEUE_H
|
||||||
|
|
||||||
struct adc_message;
|
struct adc_message;
|
||||||
struct linked_list;
|
struct linked_list;
|
||||||
typedef int (*hub_recvq_write)(void* desc, const void* buf, size_t len);
|
typedef int (*ioq_write)(void* desc, const void* buf, size_t len);
|
||||||
typedef int (*hub_recvq_read)(void* desc, void* buf, size_t len);
|
typedef int (*ioq_read)(void* desc, void* buf, size_t len);
|
||||||
|
|
||||||
struct hub_sendq
|
struct ioq_send
|
||||||
{
|
{
|
||||||
size_t size; /** Size of send queue (in bytes, not messages) */
|
size_t size; /** Size of send queue (in bytes, not messages) */
|
||||||
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
|
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
|
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
|
||||||
#endif
|
#endif
|
||||||
struct linked_list* queue; /** List of queued messages */
|
struct linked_list* queue; /** List of queued messages (struct adc_message) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hub_recvq
|
struct ioq_recv
|
||||||
{
|
{
|
||||||
char* buf;
|
char* buf;
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -44,63 +44,63 @@ struct hub_recvq
|
|||||||
/**
|
/**
|
||||||
* Create a send queue
|
* Create a send queue
|
||||||
*/
|
*/
|
||||||
extern struct hub_sendq* hub_sendq_create();
|
extern struct ioq_send* ioq_send_create();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a send queue, and delete any queued messages.
|
* Destroy a send queue, and delete any queued messages.
|
||||||
*/
|
*/
|
||||||
extern void hub_sendq_destroy(struct hub_sendq*);
|
extern void ioq_send_destroy(struct ioq_send*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a message to the send queue.
|
* Add a message to the send queue.
|
||||||
*/
|
*/
|
||||||
extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
|
extern void ioq_send_add(struct ioq_send*, struct adc_message* msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the send queue, and send as many messages as possible.
|
* Process the send queue, and send as many messages as possible.
|
||||||
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
|
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
|
||||||
*/
|
*/
|
||||||
extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
|
extern int ioq_send_send(struct ioq_send*, struct net_connection* con);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns 1 if send queue is empty, 0 otherwise.
|
* @returns 1 if send queue is empty, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
extern int hub_sendq_is_empty(struct hub_sendq*);
|
extern int ioq_send_is_empty(struct ioq_send*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns the number of bytes remaining to be sent in the queue.
|
* @returns the number of bytes remaining to be sent in the queue.
|
||||||
*/
|
*/
|
||||||
extern size_t hub_sendq_get_bytes(struct hub_sendq*);
|
extern size_t ioq_send_get_bytes(struct ioq_send*);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a receive queue.
|
* Create a receive queue.
|
||||||
*/
|
*/
|
||||||
extern struct hub_recvq* hub_recvq_create();
|
extern struct ioq_recv* ioq_recv_create();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a receive queue.
|
* Destroy a receive queue.
|
||||||
*/
|
*/
|
||||||
extern void hub_recvq_destroy(struct hub_recvq*);
|
extern void ioq_recv_destroy(struct ioq_recv*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the buffer, copies it into buf and deallocates it.
|
* Gets the buffer, copies it into buf and deallocates it.
|
||||||
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
|
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
|
||||||
* @return the number of bytes copied into buf.
|
* @return the number of bytes copied into buf.
|
||||||
*/
|
*/
|
||||||
extern size_t hub_recvq_get(struct hub_recvq*, void* buf, size_t bufsize);
|
extern size_t ioq_recv_get(struct ioq_recv*, void* buf, size_t bufsize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the buffer
|
* Sets the buffer
|
||||||
*/
|
*/
|
||||||
extern size_t hub_recvq_set(struct hub_recvq*, void* buf, size_t bufsize);
|
extern size_t ioq_recv_set(struct ioq_recv*, void* buf, size_t bufsize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 1 if size is zero, 0 otherwise.
|
* @return 1 if size is zero, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
extern int hub_recvq_is_empty(struct hub_recvq* buf);
|
extern int ioq_recv_is_empty(struct ioq_recv* buf);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_HUB_IO_H */
|
#endif /* HAVE_UHUB_IO_QUEUE_H */
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,12 +13,15 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#ifdef SYSTEMD
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static int arg_verbose = 5;
|
static int arg_verbose = 5;
|
||||||
static int arg_fork = 0;
|
static int arg_fork = 0;
|
||||||
@ -115,6 +118,11 @@ int main_loop()
|
|||||||
{
|
{
|
||||||
LOG_INFO("Reloading configuration files...");
|
LOG_INFO("Reloading configuration files...");
|
||||||
LOG_DEBUG("Hub status: %d", (int) hub->status);
|
LOG_DEBUG("Hub status: %d", (int) hub->status);
|
||||||
|
|
||||||
|
/* Reinitialize logs */
|
||||||
|
hub_log_shutdown();
|
||||||
|
hub_log_initialize(arg_log, arg_log_syslog);
|
||||||
|
hub_set_log_verbosity(arg_verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
|
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
|
||||||
@ -132,10 +140,25 @@ int main_loop()
|
|||||||
{
|
{
|
||||||
hub = hub_start_service(&configuration);
|
hub = hub_start_service(&configuration);
|
||||||
if (!hub)
|
if (!hub)
|
||||||
|
{
|
||||||
|
acl_shutdown(&acl);
|
||||||
|
free_config(&configuration);
|
||||||
|
net_destroy();
|
||||||
|
hub_log_shutdown();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
setup_signal_handlers(hub);
|
setup_signal_handlers(hub);
|
||||||
#endif
|
#ifdef SYSTEMD
|
||||||
|
/* Notify the service manager that this daemon has
|
||||||
|
* been successfully initialized and shall enter the
|
||||||
|
* main loop.
|
||||||
|
*/
|
||||||
|
sd_notifyf(0, "READY=1\n"
|
||||||
|
"MAINPID=%lu", (unsigned long) getpid());
|
||||||
|
#endif /* SYSTEMD */
|
||||||
|
|
||||||
|
#endif /* ! WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
hub_set_variables(hub, &acl);
|
hub_set_variables(hub, &acl);
|
||||||
@ -206,13 +229,17 @@ void print_usage(char* program)
|
|||||||
" -q Quiet mode - no output\n"
|
" -q Quiet mode - no output\n"
|
||||||
" -f Fork to background\n"
|
" -f Fork to background\n"
|
||||||
" -l <file> Log messages to given file (default: stderr)\n"
|
" -l <file> Log messages to given file (default: stderr)\n"
|
||||||
" -L Log messages to syslog\n"
|
|
||||||
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
|
" -c <file> Specify configuration file (default: " SERVER_CONFIG ")\n"
|
||||||
" -C Check configuration and return\n"
|
" -C Check configuration and return\n"
|
||||||
" -s Show configuration parameters\n"
|
" -s Show configuration parameters\n"
|
||||||
" -S Show configuration parameters, but ignore defaults\n"
|
" -S Show configuration parameters, but ignore defaults\n"
|
||||||
" -h This message\n"
|
" -h This message\n"
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
#ifdef SYSTEMD
|
||||||
|
" -L Log messages to journal\n"
|
||||||
|
#else
|
||||||
|
" -L Log messages to syslog\n"
|
||||||
|
#endif
|
||||||
" -u <user> Run as given user\n"
|
" -u <user> Run as given user\n"
|
||||||
" -g <group> Run with given group permissions\n"
|
" -g <group> Run with given group permissions\n"
|
||||||
" -p <file> Store pid in file (process id)\n"
|
" -p <file> Store pid in file (process id)\n"
|
||||||
@ -444,7 +471,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
else if (ret == 0)
|
else if (ret == 0)
|
||||||
{
|
{
|
||||||
/* child process - detatch from TTY */
|
/* child process - detach from TTY */
|
||||||
fclose(stdin);
|
fclose(stdin);
|
||||||
fclose(stdout);
|
fclose(stdout);
|
||||||
fclose(stderr);
|
fclose(stderr);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,22 +13,19 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <uhub.h>
|
#include <uhub.h>
|
||||||
#include "hubio.h"
|
#include "ioqueue.h"
|
||||||
#include "probe.h"
|
#include "probe.h"
|
||||||
|
|
||||||
/* FIXME: This should not be needed! */
|
|
||||||
extern struct hub_info* g_hub;
|
|
||||||
|
|
||||||
int handle_net_read(struct hub_user* user)
|
int handle_net_read(struct hub_user* user)
|
||||||
{
|
{
|
||||||
static char buf[MAX_RECV_BUF];
|
static char buf[MAX_RECV_BUF];
|
||||||
struct hub_recvq* q = user->recv_queue;
|
struct ioq_recv* q = user->recv_queue;
|
||||||
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
|
size_t buf_size = ioq_recv_get(q, buf, MAX_RECV_BUF);
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
|
|
||||||
if (user_flag_get(user, flag_maxbuf))
|
if (user_flag_get(user, flag_maxbuf))
|
||||||
@ -58,7 +55,7 @@ int handle_net_read(struct hub_user* user)
|
|||||||
|
|
||||||
while ((pos = memchr(start, '\n', remaining)))
|
while ((pos = memchr(start, '\n', remaining)))
|
||||||
{
|
{
|
||||||
lastPos = pos;
|
lastPos = pos+1;
|
||||||
pos[0] = '\0';
|
pos[0] = '\0';
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
@ -71,9 +68,9 @@ int handle_net_read(struct hub_user* user)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (((pos - start) > 0) && g_hub->config->max_recv_buffer > (pos - start))
|
if (((pos - start) > 0) && user->hub->config->max_recv_buffer > (pos - start))
|
||||||
{
|
{
|
||||||
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
|
if (hub_handle_message(user->hub, user, start, (pos - start)) == -1)
|
||||||
{
|
{
|
||||||
return quit_protocol_error;
|
return quit_protocol_error;
|
||||||
}
|
}
|
||||||
@ -88,20 +85,20 @@ int handle_net_read(struct hub_user* user)
|
|||||||
|
|
||||||
if (lastPos || remaining)
|
if (lastPos || remaining)
|
||||||
{
|
{
|
||||||
if (remaining < g_hub->config->max_recv_buffer)
|
if (remaining < (size_t) user->hub->config->max_recv_buffer)
|
||||||
{
|
{
|
||||||
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
ioq_recv_set(q, lastPos ? lastPos : buf, remaining);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hub_recvq_set(q, 0, 0);
|
ioq_recv_set(q, 0, 0);
|
||||||
user_flag_set(user, flag_maxbuf);
|
user_flag_set(user, flag_maxbuf);
|
||||||
LOG_WARN("Received message past max_recv_buffer, dropping message.");
|
LOG_WARN("Received message past max_recv_buffer, dropping message.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hub_recvq_set(q, 0, 0);
|
ioq_recv_set(q, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -110,9 +107,9 @@ int handle_net_read(struct hub_user* user)
|
|||||||
int handle_net_write(struct hub_user* user)
|
int handle_net_write(struct hub_user* user)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
while (hub_sendq_get_bytes(user->send_queue))
|
while (ioq_send_get_bytes(user->send_queue))
|
||||||
{
|
{
|
||||||
ret = hub_sendq_send(user->send_queue, user);
|
ret = ioq_send_send(user->send_queue, user->connection);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -120,7 +117,7 @@ int handle_net_write(struct hub_user* user)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return quit_socket_error;
|
return quit_socket_error;
|
||||||
|
|
||||||
if (hub_sendq_get_bytes(user->send_queue))
|
if (ioq_send_get_bytes(user->send_queue))
|
||||||
{
|
{
|
||||||
user_net_io_want_write(user);
|
user_net_io_want_write(user);
|
||||||
}
|
}
|
||||||
@ -140,11 +137,17 @@ void net_event(struct net_connection* con, int event, void *arg)
|
|||||||
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
|
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (event == NET_EVENT_ERROR)
|
||||||
|
{
|
||||||
|
hub_disconnect_user(user->hub, user, quit_socket_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (event == NET_EVENT_TIMEOUT)
|
if (event == NET_EVENT_TIMEOUT)
|
||||||
{
|
{
|
||||||
if (user_is_connecting(user))
|
if (user_is_connecting(user))
|
||||||
{
|
{
|
||||||
hub_disconnect_user(g_hub, user, quit_timeout);
|
hub_disconnect_user(user->hub, user, quit_timeout);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,7 +157,7 @@ void net_event(struct net_connection* con, int event, void *arg)
|
|||||||
flag_close = handle_net_read(user);
|
flag_close = handle_net_read(user);
|
||||||
if (flag_close)
|
if (flag_close)
|
||||||
{
|
{
|
||||||
hub_disconnect_user(g_hub, user, flag_close);
|
hub_disconnect_user(user->hub, user, flag_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,7 +167,7 @@ void net_event(struct net_connection* con, int event, void *arg)
|
|||||||
flag_close = handle_net_write(user);
|
flag_close = handle_net_write(user);
|
||||||
if (flag_close)
|
if (flag_close)
|
||||||
{
|
{
|
||||||
hub_disconnect_user(g_hub, user, flag_close);
|
hub_disconnect_user(user->hub, user, flag_close);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,16 +179,18 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
struct hub_probe* probe = 0;
|
struct hub_probe* probe = 0;
|
||||||
struct ip_addr_encap ipaddr;
|
struct ip_addr_encap ipaddr;
|
||||||
int server_fd = net_con_get_sd(con);
|
int server_fd = net_con_get_sd(con);
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
plugin_st status;
|
plugin_st status;
|
||||||
#endif
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int fd = net_accept(server_fd, &ipaddr);
|
int fd = net_accept(server_fd, &ipaddr);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
|
#ifdef WINSOCK
|
||||||
|
if (net_error() == WSAEWOULDBLOCK)
|
||||||
|
#else
|
||||||
if (net_error() == EWOULDBLOCK)
|
if (net_error() == EWOULDBLOCK)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -196,7 +201,6 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
status = plugin_check_ip_early(hub, &ipaddr);
|
status = plugin_check_ip_early(hub, &ipaddr);
|
||||||
if (status == st_deny)
|
if (status == st_deny)
|
||||||
{
|
{
|
||||||
@ -206,7 +210,6 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugin_log_connection_accepted(hub, &ipaddr);
|
plugin_log_connection_accepted(hub, &ipaddr);
|
||||||
#endif
|
|
||||||
|
|
||||||
probe = probe_create(hub, fd, &ipaddr);
|
probe = probe_create(hub, fd, &ipaddr);
|
||||||
if (!probe)
|
if (!probe)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
242
src/core/plugincallback.c
Normal file
242
src/core/plugincallback.c
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "plugin_api/command_api.h"
|
||||||
|
|
||||||
|
struct plugin_callback_data
|
||||||
|
{
|
||||||
|
struct linked_list* commands;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
return get_internals(plugin)->callback_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
struct plugin_handle* plugin = (struct plugin_handle*) cmd->ptr;
|
||||||
|
struct plugin_callback_data* data = get_callback_data(plugin);
|
||||||
|
struct plugin_command_handle* cmdh;
|
||||||
|
struct plugin_user* puser = (struct plugin_user*) user; // FIXME: Use a proper conversion function instead.
|
||||||
|
struct plugin_command* pcommand = (struct plugin_command*) cmd; // FIXME: Use a proper conversion function instead.
|
||||||
|
|
||||||
|
LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix);
|
||||||
|
|
||||||
|
LIST_FOREACH(struct plugin_command_handle*, cmdh, data->commands,
|
||||||
|
{
|
||||||
|
if (strcmp(cmdh->prefix, cmd->prefix) == 0)
|
||||||
|
return cmdh->handler(plugin, puser, pcommand);
|
||||||
|
});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hub_user* convert_user_type(struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct hub_user* huser = (struct hub_user*) user;
|
||||||
|
return huser;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, const char* message)
|
||||||
|
{
|
||||||
|
char* buffer = adc_msg_escape(message);
|
||||||
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||||
|
adc_msg_add_argument(command, buffer);
|
||||||
|
route_to_user(plugin_get_hub(plugin), convert_user_type(user), command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
hub_free(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbfunc_send_broadcast(struct plugin_handle* plugin, const char* message)
|
||||||
|
{
|
||||||
|
char* buffer = adc_msg_escape(message);
|
||||||
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||||
|
adc_msg_add_argument(command, buffer);
|
||||||
|
route_to_all(plugin_get_hub(plugin), command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
hub_free(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
|
||||||
|
{
|
||||||
|
char code_str[4];
|
||||||
|
char* buffer = adc_msg_escape(message);
|
||||||
|
struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10);
|
||||||
|
snprintf(code_str, sizeof(code_str), "%03d", code);
|
||||||
|
adc_msg_add_argument(command, code_str);
|
||||||
|
adc_msg_add_argument(command, buffer);
|
||||||
|
route_to_user(plugin_get_hub(plugin), convert_user_type(user), command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
hub_free(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_command_handle* cmdh)
|
||||||
|
{
|
||||||
|
struct plugin_callback_data* data = get_callback_data(plugin);
|
||||||
|
struct command_handle* command = (struct command_handle*) hub_malloc_zero(sizeof(struct command_handle));
|
||||||
|
|
||||||
|
command->prefix = cmdh->prefix;
|
||||||
|
command->length = cmdh->length;
|
||||||
|
command->args = cmdh->args;
|
||||||
|
command->cred = cmdh->cred;
|
||||||
|
command->description = cmdh->description;
|
||||||
|
command->origin = cmdh->origin;
|
||||||
|
command->handler = plugin_command_dispatch;
|
||||||
|
|
||||||
|
cmdh->internal_handle = command;
|
||||||
|
list_append(data->commands, cmdh);
|
||||||
|
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_command_handle* cmdh)
|
||||||
|
{
|
||||||
|
struct plugin_callback_data* data = get_callback_data(plugin);
|
||||||
|
struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
|
||||||
|
|
||||||
|
list_remove(data->commands, cmdh);
|
||||||
|
command_del(plugin_get_hub(plugin)->commands, command);
|
||||||
|
hub_free(command);
|
||||||
|
cmdh->internal_handle = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cbfunc_command_arg_reset(struct plugin_handle* plugin, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
// TODO: Use proper function for rewriting for plugin_command -> hub_command
|
||||||
|
return hub_command_arg_reset((struct hub_command*) cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct plugin_command_arg_data* cbfunc_command_arg_next(struct plugin_handle* plugin, struct plugin_command* cmd, enum plugin_command_arg_type t)
|
||||||
|
{
|
||||||
|
// TODO: Use proper function for rewriting for plugin_command -> hub_command
|
||||||
|
return (struct plugin_command_arg_data*) hub_command_arg_next((struct hub_command*) cmd, (enum hub_command_arg_type) t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t cbfunc_get_usercount(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = plugin_get_hub(plugin);
|
||||||
|
return hub->users->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* cbfunc_get_hub_name(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = plugin_get_hub(plugin);
|
||||||
|
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_NICK);
|
||||||
|
char* str = adc_msg_unescape(str_encoded);
|
||||||
|
hub_free(str_encoded);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* cbfunc_get_hub_description(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = plugin_get_hub(plugin);
|
||||||
|
char* str_encoded = adc_msg_get_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION);
|
||||||
|
char* str = adc_msg_unescape(str_encoded);
|
||||||
|
hub_free(str_encoded);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cbfunc_set_hub_name(struct plugin_handle* plugin, const char* str)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = plugin_get_hub(plugin);
|
||||||
|
struct adc_message* command;
|
||||||
|
char* new_str = adc_msg_escape(str ? str : hub->config->hub_name);
|
||||||
|
|
||||||
|
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_NICK, new_str);
|
||||||
|
|
||||||
|
// Broadcast hub name
|
||||||
|
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
|
||||||
|
adc_msg_add_named_argument(command, ADC_INF_FLAG_NICK, new_str);
|
||||||
|
route_to_all(hub, command);
|
||||||
|
|
||||||
|
adc_msg_free(command);
|
||||||
|
hub_free(new_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cbfunc_set_hub_description(struct plugin_handle* plugin, const char* str)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = plugin_get_hub(plugin);
|
||||||
|
struct adc_message* command;
|
||||||
|
char* new_str = adc_msg_escape(str ? str : hub->config->hub_description);
|
||||||
|
|
||||||
|
adc_msg_replace_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, new_str);
|
||||||
|
|
||||||
|
// Broadcast hub description
|
||||||
|
command = adc_msg_construct(ADC_CMD_IINF, (strlen(new_str) + 8));
|
||||||
|
adc_msg_add_named_argument(command, ADC_INF_FLAG_DESCRIPTION, new_str);
|
||||||
|
route_to_all(hub, command);
|
||||||
|
|
||||||
|
adc_msg_free(command);
|
||||||
|
hub_free(new_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_register_callback_functions(struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
handle->hub.send_message = cbfunc_send_message;
|
||||||
|
handle->hub.send_broadcast_message = cbfunc_send_broadcast;
|
||||||
|
handle->hub.send_status_message = cbfunc_send_status;
|
||||||
|
handle->hub.user_disconnect = cbfunc_user_disconnect;
|
||||||
|
handle->hub.command_add = cbfunc_command_add;
|
||||||
|
handle->hub.command_del = cbfunc_command_del;
|
||||||
|
handle->hub.command_arg_reset = cbfunc_command_arg_reset;
|
||||||
|
handle->hub.command_arg_next = cbfunc_command_arg_next;
|
||||||
|
handle->hub.get_usercount = cbfunc_get_usercount;
|
||||||
|
handle->hub.get_name = cbfunc_get_hub_name;
|
||||||
|
handle->hub.set_name = cbfunc_set_hub_name;
|
||||||
|
handle->hub.get_description = cbfunc_get_hub_description;
|
||||||
|
handle->hub.set_description = cbfunc_set_hub_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_unregister_callback_functions(struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct plugin_callback_data* plugin_callback_data_create()
|
||||||
|
{
|
||||||
|
struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data));
|
||||||
|
LOG_PLUGIN("plugin_callback_data_create()");
|
||||||
|
data->commands = list_create();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data)
|
||||||
|
{
|
||||||
|
LOG_PLUGIN("plugin_callback_data_destroy()");
|
||||||
|
if (data->commands)
|
||||||
|
{
|
||||||
|
// delete commands not deleted by the plugin itself:
|
||||||
|
struct plugin_command_handle* cmd;
|
||||||
|
while ( (cmd = list_get_first(data->commands)) )
|
||||||
|
cbfunc_command_del(plugin, cmd);
|
||||||
|
list_destroy(data->commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(data);
|
||||||
|
}
|
32
src/core/plugincallback.h
Normal file
32
src/core/plugincallback.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2014, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_CALLBACK_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_CALLBACK_H
|
||||||
|
|
||||||
|
struct plugin_handle;
|
||||||
|
struct uhub_plugin;
|
||||||
|
|
||||||
|
extern struct plugin_callback_data* plugin_callback_data_create();
|
||||||
|
extern void plugin_callback_data_destroy(struct plugin_handle* plugin, struct plugin_callback_data* data);
|
||||||
|
|
||||||
|
extern void plugin_register_callback_functions(struct plugin_handle* plugin);
|
||||||
|
extern void plugin_unregister_callback_functions(struct plugin_handle* plugin);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_CALLBACK_H */
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,77 +13,185 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "plugin_api/handle.h"
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
#define PLUGIN_INVOKE(HUB, FUNCNAME, CODE) \
|
#define PLUGIN_DEBUG(hub, name) LOG_PLUGIN("Invoke %s on %d plugins", name, (int) (hub->plugins ? list_size(hub->plugins->loaded) : -1));
|
||||||
|
|
||||||
|
|
||||||
|
#define INVOKE(HUB, FUNCNAME, CODE) \
|
||||||
|
PLUGIN_DEBUG(HUB, # FUNCNAME) \
|
||||||
if (HUB->plugins && HUB->plugins->loaded) \
|
if (HUB->plugins && HUB->plugins->loaded) \
|
||||||
{ \
|
{ \
|
||||||
struct uhub_plugin_handle* plugin = (struct uhub_plugin_handle*) list_get_first(HUB->plugins->loaded); \
|
struct plugin_handle* plugin;\
|
||||||
while (plugin) \
|
LIST_FOREACH(struct plugin_handle*, plugin, HUB->plugins->loaded, \
|
||||||
{ \
|
{ \
|
||||||
if (plugin->funcs.FUNCNAME) \
|
if (plugin->funcs.FUNCNAME) \
|
||||||
CODE \
|
CODE \
|
||||||
plugin = (struct uhub_plugin_handle*) list_get_next(HUB->plugins->loaded); \
|
}); \
|
||||||
} \
|
}
|
||||||
|
|
||||||
|
#define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \
|
||||||
|
do { \
|
||||||
|
plugin_st status = st_default; \
|
||||||
|
INVOKE(HUB, FUNCNAME, { \
|
||||||
|
status = plugin->funcs.FUNCNAME(plugin, ARG1); \
|
||||||
|
if (status != st_default) \
|
||||||
|
break; \
|
||||||
|
}); \
|
||||||
|
return status; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define PLUGIN_INVOKE_STATUS_2(HUB, FUNCNAME, ARG1, ARG2) \
|
||||||
|
do { \
|
||||||
|
plugin_st status = st_default; \
|
||||||
|
INVOKE(HUB, FUNCNAME, { \
|
||||||
|
status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); \
|
||||||
|
if (status != st_default) \
|
||||||
|
break; \
|
||||||
|
}); \
|
||||||
|
return status; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define PLUGIN_INVOKE_STATUS_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) \
|
||||||
|
do { \
|
||||||
|
plugin_st status = st_default; \
|
||||||
|
INVOKE(HUB, FUNCNAME, { \
|
||||||
|
status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); \
|
||||||
|
if (status != st_default) \
|
||||||
|
break; \
|
||||||
|
}); \
|
||||||
|
return status; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define PLUGIN_INVOKE_1(HUB, FUNCNAME, ARG1) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1); })
|
||||||
|
#define PLUGIN_INVOKE_2(HUB, FUNCNAME, ARG1, ARG2) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); })
|
||||||
|
#define PLUGIN_INVOKE_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); })
|
||||||
|
|
||||||
|
|
||||||
|
static struct plugin_user* convert_user_type(struct hub_user* user)
|
||||||
|
{
|
||||||
|
struct plugin_user* puser = (struct plugin_user*) user;
|
||||||
|
return puser;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr)
|
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr)
|
||||||
{
|
{
|
||||||
plugin_st status = st_default;
|
PLUGIN_INVOKE_STATUS_1(hub, on_check_ip_early, addr);
|
||||||
PLUGIN_INVOKE(hub, login_check_ip_early, {
|
|
||||||
status = plugin->funcs.login_check_ip_early(addr);
|
|
||||||
if (status != st_default)
|
|
||||||
break;
|
|
||||||
});
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr)
|
plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* who, struct ip_addr_encap* addr)
|
||||||
{
|
{
|
||||||
plugin_st status = st_default;
|
struct plugin_user* user = convert_user_type(who);
|
||||||
PLUGIN_INVOKE(hub, login_check_ip_late, {
|
PLUGIN_INVOKE_STATUS_2(hub, on_check_ip_late, user, addr);
|
||||||
status = plugin->funcs.login_check_ip_late(addr);
|
|
||||||
if (status != st_default)
|
|
||||||
break;
|
|
||||||
});
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||||
{
|
{
|
||||||
const char* addr = ip_convert_to_string(ipaddr);
|
PLUGIN_INVOKE_1(hub, on_connection_accepted, ipaddr);
|
||||||
LOG_TRACE("Got connection from %s", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||||
{
|
{
|
||||||
const char* addr = ip_convert_to_string(ipaddr);
|
PLUGIN_INVOKE_1(hub, on_connection_refused, ipaddr);
|
||||||
LOG_INFO("Denied connection from %s", addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user)
|
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* who)
|
||||||
{
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_1(hub, on_user_login, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user)
|
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||||
{
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_login_error, user, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user)
|
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||||
{
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_logout, user, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* who, const char* new_nick)
|
||||||
void convert_user_to_plugin_user(struct plugin_user* puser, struct hub_user* user)
|
|
||||||
{
|
{
|
||||||
puser->sid = user->id.sid;
|
struct plugin_user* user = convert_user_type(who);
|
||||||
puser->nick = user->id.nick;
|
PLUGIN_INVOKE_2(hub, on_user_nick_change, user, new_nick);
|
||||||
puser->cid = user->id.cid;
|
}
|
||||||
puser->addr = user->id.addr;
|
|
||||||
|
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_update_error, user, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* who, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_3(hub, on_user_chat_message, user, message, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(from);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_chat_msg, user, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_3(hub, on_private_msg, user1, user2, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* from, const char* data)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(from);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_search, user, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_3(hub, on_search_result, user1, user2, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_connect, user1, user2);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_revconnect, user1, user2);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, auth_get_user, nickname, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, auth_register_user, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, auth_update_user, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, auth_delete_user, info);
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -23,24 +23,44 @@
|
|||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "plugin_api/handle.h"
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
|
|
||||||
struct hub_info;
|
struct hub_info;
|
||||||
struct ip_addr_encap;
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
/* All log related functions */
|
||||||
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr);
|
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr);
|
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user);
|
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user);
|
||||||
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user);
|
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||||
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user);
|
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||||
|
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* user, const char* new_nick);
|
||||||
|
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||||
|
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
|
||||||
|
|
||||||
|
/* IP ban related */
|
||||||
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
|
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr);
|
plugin_st plugin_check_ip_late(struct hub_info* hub, struct hub_user* user, struct ip_addr_encap* addr);
|
||||||
|
|
||||||
|
/* Nickname allow/deny handling */
|
||||||
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);
|
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);
|
||||||
plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick);
|
plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick);
|
||||||
|
|
||||||
|
/* Handle chat messages */
|
||||||
|
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
|
||||||
|
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags);
|
||||||
|
|
||||||
#endif
|
/* Handle searches */
|
||||||
|
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* user, const char* data);
|
||||||
|
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data);
|
||||||
|
|
||||||
|
/* Handle p2p connections */
|
||||||
|
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
|
||||||
|
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
|
||||||
|
|
||||||
|
/* Authentication related */
|
||||||
|
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info);
|
||||||
|
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* user);
|
||||||
|
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* user);
|
||||||
|
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* user);
|
||||||
|
|
||||||
#endif // HAVE_UHUB_PLUGIN_INVOKE_H
|
#endif // HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,46 +13,73 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
#include "plugin_api/handle.h"
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
struct plugin_callback_data;
|
||||||
|
|
||||||
|
struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
struct plugin_hub_internals* internals;
|
||||||
|
uhub_assert(handle && handle->handle && handle->handle->internals);
|
||||||
|
internals = (struct plugin_hub_internals*) handle->handle->internals;
|
||||||
|
return internals;
|
||||||
|
}
|
||||||
|
|
||||||
struct uhub_plugin* plugin_open(const char* filename)
|
struct uhub_plugin* plugin_open(const char* filename)
|
||||||
{
|
{
|
||||||
LOG_TRACE("plugin_open: \"%s\"", filename);
|
struct uhub_plugin* plugin;
|
||||||
#ifdef HAVE_DLOPEN
|
LOG_PLUGIN("plugin_open: \"%s\"", filename);
|
||||||
struct uhub_plugin* plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin));
|
|
||||||
|
plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin));
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
plugin->handle = dlopen(filename, RTLD_LAZY);
|
plugin->handle = dlopen(filename, RTLD_LAZY);
|
||||||
|
#else
|
||||||
|
plugin->handle = LoadLibraryExA(filename, NULL, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!plugin->handle)
|
if (!plugin->handle)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror());
|
LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror());
|
||||||
|
#else
|
||||||
|
LOG_ERROR("Unable to open plugin %s: %d", filename, GetLastError());
|
||||||
|
#endif
|
||||||
hub_free(plugin);
|
hub_free(plugin);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin->filename = strdup(filename);
|
||||||
|
plugin->internals = hub_malloc_zero(sizeof(struct plugin_hub_internals));
|
||||||
return plugin;
|
return plugin;
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_close(struct uhub_plugin* plugin)
|
void plugin_close(struct uhub_plugin* plugin)
|
||||||
{
|
{
|
||||||
|
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
|
||||||
|
|
||||||
|
LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename);
|
||||||
|
plugin_callback_data_destroy(plugin->handle, internals->callback_data);
|
||||||
|
hub_free(internals);
|
||||||
|
plugin->internals = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
dlclose(plugin->handle);
|
dlclose(plugin->handle);
|
||||||
hub_free(plugin);
|
#else
|
||||||
|
FreeLibrary((HMODULE) plugin->handle);
|
||||||
#endif
|
#endif
|
||||||
|
hub_free(plugin->filename);
|
||||||
|
hub_free(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
|
void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
|
||||||
@ -61,16 +88,19 @@ void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
|
|||||||
void* addr = dlsym(plugin->handle, symbol);
|
void* addr = dlsym(plugin->handle, symbol);
|
||||||
return addr;
|
return addr;
|
||||||
#else
|
#else
|
||||||
return 0;
|
FARPROC addr = GetProcAddress((HMODULE) plugin->handle, symbol);
|
||||||
|
return (void*) addr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct uhub_plugin_handle* plugin_load(const char* filename, const char* config)
|
|
||||||
|
|
||||||
|
struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub)
|
||||||
{
|
{
|
||||||
plugin_register_f register_f;
|
plugin_register_f register_f;
|
||||||
plugin_unregister_f unregister_f;
|
plugin_unregister_f unregister_f;
|
||||||
int ret;
|
int ret;
|
||||||
struct uhub_plugin_handle* handle = hub_malloc_zero(sizeof(struct uhub_plugin_handle));
|
struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle));
|
||||||
struct uhub_plugin* plugin = plugin_open(filename);
|
struct uhub_plugin* plugin = plugin_open(filename);
|
||||||
|
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
@ -86,6 +116,15 @@ struct uhub_plugin_handle* plugin_load(const char* filename, const char* config)
|
|||||||
register_f = plugin_lookup_symbol(plugin, "plugin_register");
|
register_f = plugin_lookup_symbol(plugin, "plugin_register");
|
||||||
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
|
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
|
||||||
|
|
||||||
|
// register hub internals
|
||||||
|
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
|
||||||
|
internals->unregister = unregister_f;
|
||||||
|
internals->hub = hub;
|
||||||
|
internals->callback_data = plugin_callback_data_create();
|
||||||
|
|
||||||
|
// setup callback functions, where the plugin can contact the hub.
|
||||||
|
plugin_register_callback_functions(handle);
|
||||||
|
|
||||||
if (register_f && unregister_f)
|
if (register_f && unregister_f)
|
||||||
{
|
{
|
||||||
ret = register_f(handle, config);
|
ret = register_f(handle, config);
|
||||||
@ -94,8 +133,7 @@ struct uhub_plugin_handle* plugin_load(const char* filename, const char* config)
|
|||||||
if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs))
|
if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs))
|
||||||
{
|
{
|
||||||
LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version);
|
LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version);
|
||||||
LOG_TRACE("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size);
|
LOG_PLUGIN("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size);
|
||||||
plugin->unregister = unregister_f;
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -105,7 +143,7 @@ struct uhub_plugin_handle* plugin_load(const char* filename, const char* config)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to load plugin: %s - Failed to initialize", filename);
|
LOG_ERROR("Unable to load plugin: %s - Failed to initialize: %s", filename, handle->error_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,61 +152,64 @@ struct uhub_plugin_handle* plugin_load(const char* filename, const char* config)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_unload(struct uhub_plugin_handle* plugin)
|
void plugin_unload(struct plugin_handle* plugin)
|
||||||
{
|
{
|
||||||
plugin->handle->unregister(plugin);
|
struct plugin_hub_internals* internals = get_internals(plugin);
|
||||||
|
internals->unregister(plugin);
|
||||||
|
plugin_unregister_callback_functions(plugin);
|
||||||
plugin_close(plugin->handle);
|
plugin_close(plugin->handle);
|
||||||
|
hub_free(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int plugin_parse_line(char* line, int line_count, void* ptr_data)
|
static int plugin_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
{
|
{
|
||||||
struct uhub_plugins* handle = (struct uhub_plugins*) ptr_data;
|
struct hub_info* hub = (struct hub_info*) ptr_data;
|
||||||
char* pos;
|
struct uhub_plugins* handle = hub->plugins;
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
struct plugin_handle* plugin;
|
||||||
|
char *directive, *soname, *params;
|
||||||
|
|
||||||
strip_off_ini_line_comments(line, line_count);
|
if (cfg_token_count(tokens) == 0)
|
||||||
|
|
||||||
line = strip_white_space(line);
|
|
||||||
if (!*line)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
LOG_TRACE("plugin: parse line %d: \"%s\"", line_count, line);
|
|
||||||
|
|
||||||
// Set plugin directory.
|
|
||||||
pos = strstr(line, "plugin_directory");
|
|
||||||
if (pos && is_white_space(line[(pos - line) + strlen("plugin_directory")]))
|
|
||||||
{
|
{
|
||||||
if (handle->plugin_dir)
|
cfg_tokens_free(tokens);
|
||||||
hub_free(handle->plugin_dir);
|
|
||||||
handle->plugin_dir = strdup(strip_white_space(pos + strlen("plugin_directory") + 1));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load plugin
|
if (cfg_token_count(tokens) < 2)
|
||||||
pos = strstr(line, "plugin");
|
|
||||||
if (pos && is_white_space(line[(pos - line) + strlen("plugin")]))
|
|
||||||
{
|
{
|
||||||
char* data = strip_white_space(pos + strlen("plugin") + 1);
|
cfg_tokens_free(tokens);
|
||||||
if (*data)
|
|
||||||
{
|
|
||||||
LOG_TRACE("Load plugin: \"%s\"", data);
|
|
||||||
struct uhub_plugin_handle* plugin = plugin_load(data, "");
|
|
||||||
if (plugin)
|
|
||||||
{
|
|
||||||
list_append(handle->loaded, plugin);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int plugin_initialize(struct hub_config* config, struct uhub_plugins* handle)
|
directive = cfg_token_get_first(tokens);
|
||||||
|
soname = cfg_token_get_next(tokens);
|
||||||
|
params = cfg_token_get_next(tokens);
|
||||||
|
|
||||||
|
if (strcmp(directive, "plugin") == 0 && soname && *soname)
|
||||||
|
{
|
||||||
|
if (!params)
|
||||||
|
params = "";
|
||||||
|
|
||||||
|
LOG_PLUGIN("Load plugin: \"%s\", params=\"%s\"", soname, params);
|
||||||
|
plugin = plugin_load(soname, params, hub);
|
||||||
|
if (plugin)
|
||||||
|
{
|
||||||
|
list_append(handle->loaded, plugin);
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_initialize(struct hub_config* config, struct hub_info* hub)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
handle->loaded = list_create();
|
hub->plugins->loaded = list_create();
|
||||||
if (!handle->loaded)
|
if (!hub->plugins->loaded)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (config)
|
if (config)
|
||||||
@ -176,12 +217,35 @@ int plugin_initialize(struct hub_config* config, struct uhub_plugins* handle)
|
|||||||
if (!*config->file_plugins)
|
if (!*config->file_plugins)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = file_read_lines(config->file_plugins, handle, &plugin_parse_line);
|
ret = file_read_lines(config->file_plugins, hub, &plugin_parse_line);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
list_clear(hub->plugins->loaded, hub_free);
|
||||||
|
list_destroy(hub->plugins->loaded);
|
||||||
|
hub->plugins->loaded = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void plugin_unload_ptr(void* ptr)
|
||||||
|
{
|
||||||
|
struct plugin_handle* plugin = (struct plugin_handle*) ptr;
|
||||||
|
plugin_unload(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void plugin_shutdown(struct uhub_plugins* handle)
|
||||||
|
{
|
||||||
|
list_clear(handle->loaded, plugin_unload_ptr);
|
||||||
|
list_destroy(handle->loaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used internally only
|
||||||
|
struct hub_info* plugin_get_hub(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct plugin_hub_internals* data = get_internals(plugin);
|
||||||
|
return data->hub;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* PLUGIN_SUPPORT */
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -22,41 +22,46 @@
|
|||||||
|
|
||||||
#include "plugin_api/handle.h"
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
#ifdef PLUGIN_SUPPORT
|
|
||||||
|
|
||||||
struct hub_config;
|
struct hub_config;
|
||||||
|
struct hub_info;
|
||||||
struct linked_list;
|
struct linked_list;
|
||||||
struct uhub_plugin_handle;
|
struct plugin_handle;
|
||||||
|
|
||||||
struct uhub_plugin
|
struct uhub_plugin
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DLOPEN
|
|
||||||
void* handle;
|
void* handle;
|
||||||
#endif
|
|
||||||
plugin_unregister_f unregister;
|
plugin_unregister_f unregister;
|
||||||
|
char* filename;
|
||||||
|
void* internals; // Hub-internal stuff (struct plugin_hub_internals)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uhub_plugins
|
struct uhub_plugins
|
||||||
{
|
{
|
||||||
struct linked_list* loaded;
|
struct linked_list* loaded;
|
||||||
char* plugin_dir;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// High level plugin loader ode
|
// High level plugin loader code
|
||||||
extern struct uhub_plugin_handle* plugin_load(const char* filename, const char* config);
|
extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub);
|
||||||
extern void plugin_unload(struct uhub_plugin_handle* plugin);
|
extern void plugin_unload(struct plugin_handle* plugin);
|
||||||
|
|
||||||
// extern void plugin_unload(struct uhub_plugin_handle*);
|
// extern void plugin_unload(struct plugin_handle*);
|
||||||
extern int plugin_initialize(struct hub_config* config, struct uhub_plugins* handle);
|
extern int plugin_initialize(struct hub_config* config, struct hub_info* hub);
|
||||||
|
extern void plugin_shutdown(struct uhub_plugins* handle);
|
||||||
|
|
||||||
// Low level plugin loader code (used internally)
|
// Low level plugin loader code (used internally)
|
||||||
extern struct uhub_plugin* plugin_open(const char* filename);
|
extern struct uhub_plugin* plugin_open(const char* filename);
|
||||||
extern void plugin_close(struct uhub_plugin*);
|
extern void plugin_close(struct uhub_plugin*);
|
||||||
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
|
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
|
||||||
|
|
||||||
|
// Used internally only
|
||||||
|
struct plugin_hub_internals
|
||||||
|
{
|
||||||
|
struct hub_info* hub;
|
||||||
|
plugin_unregister_f unregister; /* The unregister function. */
|
||||||
|
struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct plugin_hub_internals* get_internals(struct plugin_handle*);
|
||||||
#endif /* PLUGIN_SUPPORT */
|
extern struct hub_info* plugin_get_hub(struct plugin_handle*);
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */
|
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -50,6 +50,17 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
|
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Not TLS connection - closing connection.");
|
LOG_TRACE("Not TLS connection - closing connection.");
|
||||||
|
if (*probe->hub->config->tls_require_redirect_addr)
|
||||||
|
{
|
||||||
|
char buf[512];
|
||||||
|
ssize_t len = snprintf(buf, sizeof(buf), "ISUP " ADC_PROTO_SUPPORT "\nISID AAAB\nIINF NIRedirecting...\nIQUI AAAB RD%s\n", probe->hub->config->tls_require_redirect_addr);
|
||||||
|
net_con_send(con, buf, (size_t) len);
|
||||||
|
LOG_TRACE("Not TLS connection - Redirecting to %s.", probe->hub->config->tls_require_redirect_addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_TRACE("Not TLS connection - closing connection.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -60,42 +71,46 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
probe_destroy(probe);
|
probe_destroy(probe);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if ((memcmp(probe_recvbuf, "GET ", 4) == 0) ||
|
||||||
|
(memcmp(probe_recvbuf, "POST", 4) == 0) ||
|
||||||
|
(memcmp(probe_recvbuf, "HEAD", 4) == 0))
|
||||||
|
{
|
||||||
|
/* Looks like HTTP - Not supported, but we log it. */
|
||||||
|
LOG_TRACE("Probed HTTP connection. Not supported closing connection (%s)", ip_convert_to_string(&probe->addr));
|
||||||
|
const char* buf = "501 Not implemented\r\n\r\n";
|
||||||
|
net_con_send(con, buf, strlen(buf));
|
||||||
|
}
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
if (bytes >= 11 &&
|
else if (bytes >= 11 &&
|
||||||
probe_recvbuf[0] == 22 &&
|
probe_recvbuf[0] == 22 &&
|
||||||
probe_recvbuf[1] == 3 && /* protocol major version */
|
probe_recvbuf[1] == 3 && /* protocol major version */
|
||||||
probe_recvbuf[5] == 1 && /* message type */
|
probe_recvbuf[5] == 1 && /* message type */
|
||||||
probe_recvbuf[9] == probe_recvbuf[1] &&
|
probe_recvbuf[9] == probe_recvbuf[1])
|
||||||
probe_recvbuf[10] == probe_recvbuf[2])
|
|
||||||
{
|
{
|
||||||
if (probe->hub->config->tls_enable)
|
if (probe->hub->config->tls_enable)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[9], (int) probe_recvbuf[10]);
|
||||||
if (user_create(probe->hub, probe->connection, &probe->addr))
|
if (net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ctx) < 0)
|
||||||
|
{
|
||||||
|
LOG_TRACE("TLS handshake negotiation failed.");
|
||||||
|
}
|
||||||
|
else if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||||
{
|
{
|
||||||
probe->connection = 0;
|
probe->connection = 0;
|
||||||
}
|
}
|
||||||
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[9], (int) probe_recvbuf[10]);
|
||||||
}
|
}
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
LOG_TRACE("Probed unsupported protocol: %x%x%x%x.", (int) probe_recvbuf[0], (int) probe_recvbuf[1], (int) probe_recvbuf[2], (int) probe_recvbuf[3]);
|
||||||
|
|
||||||
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
probe_destroy(probe);
|
|
||||||
return;
|
|
||||||
#endif
|
#endif
|
||||||
|
probe_destroy(probe);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,6 +122,8 @@ struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_enca
|
|||||||
if (probe == NULL)
|
if (probe == NULL)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
|
LOG_TRACE("probe_create(): %p", probe);
|
||||||
|
|
||||||
probe->hub = hub;
|
probe->hub = hub;
|
||||||
probe->connection = net_con_create();
|
probe->connection = net_con_create();
|
||||||
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
|
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
|
||||||
@ -118,6 +135,7 @@ struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_enca
|
|||||||
|
|
||||||
void probe_destroy(struct hub_probe* probe)
|
void probe_destroy(struct hub_probe* probe)
|
||||||
{
|
{
|
||||||
|
LOG_TRACE("probe_destroy(): %p (connection=%p)", probe, probe->connection);
|
||||||
if (probe->connection)
|
if (probe->connection)
|
||||||
{
|
{
|
||||||
net_con_close(probe->connection);
|
net_con_close(probe->connection);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
target = uman_get_user_by_sid(hub, msg->target);
|
target = uman_get_user_by_sid(hub->users, msg->target);
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
route_to_user(hub, target, msg);
|
route_to_user(hub, target, msg);
|
||||||
@ -38,7 +38,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'E':
|
case 'E':
|
||||||
target = uman_get_user_by_sid(hub, msg->target);
|
target = uman_get_user_by_sid(hub->users, msg->target);
|
||||||
if (target)
|
if (target)
|
||||||
{
|
{
|
||||||
route_to_user(hub, target, msg);
|
route_to_user(hub, target, msg);
|
||||||
@ -57,7 +57,7 @@ int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message*
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t get_max_send_queue(struct hub_info* hub)
|
static size_t get_max_send_queue(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
/* TODO: More dynamic send queue limit, for instance:
|
/* TODO: More dynamic send queue limit, for instance:
|
||||||
* return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
|
* return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
|
||||||
@ -65,7 +65,7 @@ static inline size_t get_max_send_queue(struct hub_info* hub)
|
|||||||
return hub->config->max_send_buffer;
|
return hub->config->max_send_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t get_max_send_queue_soft(struct hub_info* hub)
|
static size_t get_max_send_queue_soft(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
return hub->config->max_send_buffer_soft;
|
return hub->config->max_send_buffer_soft;
|
||||||
}
|
}
|
||||||
@ -75,23 +75,26 @@ static inline size_t get_max_send_queue_soft(struct hub_info* hub)
|
|||||||
* -1 if send queue is overflowed
|
* -1 if send queue is overflowed
|
||||||
* 0 if soft send queue is overflowed (not implemented at the moment)
|
* 0 if soft send queue is overflowed (not implemented at the moment)
|
||||||
*/
|
*/
|
||||||
static inline int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
|
static int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
|
||||||
{
|
{
|
||||||
if (user_flag_get(user, flag_user_list))
|
if (user_flag_get(user, flag_user_list))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
|
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
|
||||||
{
|
{
|
||||||
|
user_flag_set(user, flag_choke);
|
||||||
LOG_WARN("send queue overflowed, message discarded.");
|
LOG_WARN("send queue overflowed, message discarded.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user->send_queue->size > get_max_send_queue_soft(hub))
|
if (user->send_queue->size > get_max_send_queue_soft(hub))
|
||||||
{
|
{
|
||||||
|
user_flag_set(user, flag_choke);
|
||||||
LOG_WARN("send queue soft overflowed.");
|
LOG_WARN("send queue soft overflowed.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user_flag_unset(user, flag_choke);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,19 +109,19 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
|||||||
if (!user->connection)
|
if (!user->connection)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
assert(msg->cache && *msg->cache);
|
uhub_assert(msg->cache && *msg->cache);
|
||||||
|
|
||||||
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
if (ioq_send_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||||
{
|
{
|
||||||
/* Perform oportunistic write */
|
/* Perform oportunistic write */
|
||||||
hub_sendq_add(user->send_queue, msg);
|
ioq_send_add(user->send_queue, msg);
|
||||||
handle_net_write(user);
|
handle_net_write(user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (check_send_queue(hub, user, msg) >= 0)
|
if (check_send_queue(hub, user, msg) >= 0)
|
||||||
{
|
{
|
||||||
hub_sendq_add(user->send_queue, msg);
|
ioq_send_add(user->send_queue, msg);
|
||||||
if (!user_flag_get(user, flag_pipeline))
|
if (!user_flag_get(user, flag_pipeline))
|
||||||
user_net_io_want_write(user);
|
user_net_io_want_write(user);
|
||||||
}
|
}
|
||||||
@ -128,7 +131,7 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
|||||||
|
|
||||||
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
|
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
if (hub_sendq_is_empty(u->send_queue))
|
if (ioq_send_is_empty(u->send_queue))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
handle_net_write(u);
|
handle_net_write(u);
|
||||||
@ -139,12 +142,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 */
|
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);
|
struct hub_user* user;
|
||||||
while (user)
|
LIST_FOREACH(struct hub_user*, user, hub->users->list,
|
||||||
{
|
{
|
||||||
route_to_user(hub, user, command);
|
route_to_user(hub, user, command);
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -154,47 +156,38 @@ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* i
|
|||||||
int do_send;
|
int do_send;
|
||||||
char* tmp;
|
char* tmp;
|
||||||
|
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
|
struct hub_user* user;
|
||||||
while (user)
|
LIST_FOREACH(struct hub_user*, user, hub->users->list,
|
||||||
{
|
{
|
||||||
if (user->feature_cast)
|
if (user->feature_cast)
|
||||||
{
|
{
|
||||||
do_send = 1;
|
do_send = 1;
|
||||||
|
|
||||||
tmp = list_get_first(command->feature_cast_include);
|
LIST_FOREACH(char*, tmp, command->feature_cast_include,
|
||||||
while (tmp)
|
|
||||||
{
|
{
|
||||||
if (!user_have_feature_cast_support(user, tmp))
|
if (!user_have_feature_cast_support(user, tmp))
|
||||||
{
|
{
|
||||||
do_send = 0;
|
do_send = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tmp = list_get_next(command->feature_cast_include);;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (!do_send) {
|
if (!do_send)
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
tmp = list_get_first(command->feature_cast_exclude);
|
LIST_FOREACH(char*, tmp, command->feature_cast_exclude,
|
||||||
while (tmp)
|
|
||||||
{
|
{
|
||||||
if (user_have_feature_cast_support(user, tmp))
|
if (user_have_feature_cast_support(user, tmp))
|
||||||
{
|
{
|
||||||
do_send = 0;
|
do_send = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tmp = list_get_next(command->feature_cast_exclude);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (do_send)
|
if (do_send)
|
||||||
{
|
|
||||||
route_to_user(hub, user, command);
|
route_to_user(hub, user, command);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -214,16 +207,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_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||||
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
|
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
|
||||||
|
|
||||||
user = (struct hub_user*) list_get_first(hub->users->list);
|
LIST_FOREACH(struct hub_user*, user, hub->users->list,
|
||||||
while (user)
|
|
||||||
{
|
{
|
||||||
if (user_is_nat_override(user))
|
if (user_is_nat_override(user))
|
||||||
route_to_user(hub, user, cmd);
|
route_to_user(hub, user, cmd);
|
||||||
else
|
else
|
||||||
route_to_user(hub, user, u->info);
|
route_to_user(hub, user, u->info);
|
||||||
|
});
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
adc_msg_free(cmd);
|
adc_msg_free(cmd);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -46,8 +46,8 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
|
|||||||
if (user == NULL)
|
if (user == NULL)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
user->send_queue = hub_sendq_create();
|
user->send_queue = ioq_send_create();
|
||||||
user->recv_queue = hub_recvq_create();
|
user->recv_queue = ioq_recv_create();
|
||||||
|
|
||||||
user->connection = con;
|
user->connection = con;
|
||||||
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
|
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
|
||||||
@ -60,6 +60,8 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
|
|||||||
flood_control_reset(&user->flood_search);
|
flood_control_reset(&user->flood_search);
|
||||||
flood_control_reset(&user->flood_update);
|
flood_control_reset(&user->flood_update);
|
||||||
flood_control_reset(&user->flood_extras);
|
flood_control_reset(&user->flood_extras);
|
||||||
|
|
||||||
|
user->hub = hub;
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,8 +70,14 @@ void user_destroy(struct hub_user* user)
|
|||||||
{
|
{
|
||||||
LOG_TRACE("user_destroy(), user=%p", user);
|
LOG_TRACE("user_destroy(), user=%p", user);
|
||||||
|
|
||||||
hub_recvq_destroy(user->recv_queue);
|
ioq_recv_destroy(user->recv_queue);
|
||||||
hub_sendq_destroy(user->send_queue);
|
ioq_send_destroy(user->send_queue);
|
||||||
|
|
||||||
|
if (user->connection)
|
||||||
|
{
|
||||||
|
LOG_TRACE("user_destory() -> net_con_close(%p)", user->connection);
|
||||||
|
net_con_close(user->connection);
|
||||||
|
}
|
||||||
|
|
||||||
adc_msg_free(user->info);
|
adc_msg_free(user->info);
|
||||||
user_clear_feature_cast_support(user);
|
user_clear_feature_cast_support(user);
|
||||||
@ -175,6 +183,10 @@ static int convert_support_fourcc(int fourcc)
|
|||||||
case FOURCC('A','D','C','S'):
|
case FOURCC('A','D','C','S'):
|
||||||
return feature_adcs;
|
return feature_adcs;
|
||||||
|
|
||||||
|
// ignore these extensions, they are not useful for the hub.
|
||||||
|
case FOURCC('D','H','T','0'):
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_DEBUG("Unknown extension: %x", fourcc);
|
LOG_DEBUG("Unknown extension: %x", fourcc);
|
||||||
return 0;
|
return 0;
|
||||||
@ -220,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])
|
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
|
||||||
{
|
{
|
||||||
char* tmp = list_get_first(user->feature_cast);
|
char* tmp;
|
||||||
while (tmp)
|
LIST_FOREACH(char*, tmp, user->feature_cast,
|
||||||
{
|
{
|
||||||
if (strncmp(tmp, feature, 4) == 0)
|
if (strncmp(tmp, feature, 4) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
});
|
||||||
tmp = list_get_next(user->feature_cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,18 +297,7 @@ int user_is_disconnecting(struct hub_user* user)
|
|||||||
|
|
||||||
int user_is_protected(struct hub_user* user)
|
int user_is_protected(struct hub_user* user)
|
||||||
{
|
{
|
||||||
switch (user->credentials)
|
return auth_cred_is_protected(user->credentials);
|
||||||
{
|
|
||||||
case cred_bot:
|
|
||||||
case cred_operator:
|
|
||||||
case cred_super:
|
|
||||||
case cred_admin:
|
|
||||||
case cred_link:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -309,19 +307,7 @@ int user_is_protected(struct hub_user* user)
|
|||||||
*/
|
*/
|
||||||
int user_is_registered(struct hub_user* user)
|
int user_is_registered(struct hub_user* user)
|
||||||
{
|
{
|
||||||
switch (user->credentials)
|
return auth_cred_is_registered(user->credentials);
|
||||||
{
|
|
||||||
case cred_bot:
|
|
||||||
case cred_user:
|
|
||||||
case cred_operator:
|
|
||||||
case cred_super:
|
|
||||||
case cred_admin:
|
|
||||||
case cred_link:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_net_io_want_write(struct hub_user* user)
|
void user_net_io_want_write(struct hub_user* user)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ enum user_quit_reason
|
|||||||
quit_timeout = 4, /** User timed out (no data for a while) */
|
quit_timeout = 4, /** User timed out (no data for a while) */
|
||||||
quit_send_queue = 5, /** User's send queue was overflowed */
|
quit_send_queue = 5, /** User's send queue was overflowed */
|
||||||
quit_memory_error = 6, /** Not enough memory available */
|
quit_memory_error = 6, /** Not enough memory available */
|
||||||
quit_socket_error = 7, /** A socket error occured */
|
quit_socket_error = 7, /** A socket error occurred */
|
||||||
quit_protocol_error = 8, /** Fatal protocol error */
|
quit_protocol_error = 8, /** Fatal protocol error */
|
||||||
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
||||||
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
|
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
|
||||||
@ -76,14 +76,15 @@ enum user_quit_reason
|
|||||||
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
|
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Returns an apropriate string for the given quit reason */
|
/** Returns an appropriate string for the given quit reason */
|
||||||
extern const char* user_get_quit_reason_string(enum user_quit_reason);
|
extern const char* user_get_quit_reason_string(enum user_quit_reason);
|
||||||
|
|
||||||
struct hub_user_info
|
struct hub_user_info
|
||||||
{
|
{
|
||||||
sid_t sid; /** session ID */
|
sid_t sid; /** session ID */
|
||||||
char cid[MAX_CID_LEN+1]; /** global client ID */
|
|
||||||
char nick[MAX_NICK_LEN+1]; /** User's nick name */
|
char nick[MAX_NICK_LEN+1]; /** User's nick name */
|
||||||
|
char cid[MAX_CID_LEN+1]; /** global client ID */
|
||||||
|
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
||||||
struct ip_addr_encap addr; /** User's IP address */
|
struct ip_addr_encap addr; /** User's IP address */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,16 +106,15 @@ struct hub_user_limits
|
|||||||
|
|
||||||
struct hub_user
|
struct hub_user
|
||||||
{
|
{
|
||||||
enum user_state state; /** see enum user_state */
|
|
||||||
enum user_credentials credentials; /** see enum user_credentials */
|
|
||||||
struct hub_user_info id; /** Contains nick name and CID */
|
struct hub_user_info id; /** Contains nick name and CID */
|
||||||
uint32_t flags; /** see enum user_features */
|
enum auth_credentials credentials; /** see enum user_credentials */
|
||||||
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
enum user_state state; /** see enum user_state */
|
||||||
|
uint32_t flags; /** see enum user_flags */
|
||||||
struct linked_list* feature_cast; /** Features supported by feature cast */
|
struct linked_list* feature_cast; /** Features supported by feature cast */
|
||||||
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
|
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
|
||||||
struct hub_info* hub; /** The hub instance this user belong to */
|
struct hub_info* hub; /** The hub instance this user belong to */
|
||||||
struct hub_recvq* recv_queue;
|
struct ioq_recv* recv_queue;
|
||||||
struct hub_sendq* send_queue;
|
struct ioq_send* send_queue;
|
||||||
struct net_connection* connection; /** Connection data */
|
struct net_connection* connection; /** Connection data */
|
||||||
struct hub_user_limits limits; /** Data used for limitation */
|
struct hub_user_limits limits; /** Data used for limitation */
|
||||||
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -33,201 +33,138 @@ static void clear_user_list_callback(void* ptr)
|
|||||||
* This prevents the hub from trying to send
|
* This prevents the hub from trying to send
|
||||||
* quit messages to other users.
|
* quit messages to other users.
|
||||||
*/
|
*/
|
||||||
u->credentials = cred_none;
|
u->credentials = auth_cred_none;
|
||||||
user_destroy(u);
|
user_destroy(u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uman_update_stats(struct hub_info* hub)
|
static int uman_map_compare(const void* a, const void* b)
|
||||||
{
|
{
|
||||||
const int factor = TIMEOUT_STATS;
|
return strcmp((const char*) a, (const char*) b);
|
||||||
struct net_statistics* total;
|
|
||||||
struct net_statistics* intermediate;
|
|
||||||
net_stats_get(&intermediate, &total);
|
|
||||||
|
|
||||||
hub->stats.net_tx = (intermediate->tx / factor);
|
|
||||||
hub->stats.net_rx = (intermediate->rx / factor);
|
|
||||||
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
|
|
||||||
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
|
|
||||||
hub->stats.net_tx_total = total->tx;
|
|
||||||
hub->stats.net_rx_total = total->rx;
|
|
||||||
|
|
||||||
net_stats_reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uman_print_stats(struct hub_info* hub)
|
|
||||||
|
struct hub_user_manager* uman_init()
|
||||||
{
|
{
|
||||||
LOG_INFO("Statistics users=" PRINTF_SIZE_T " (peak_users=" PRINTF_SIZE_T "), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
|
struct hub_user_manager* users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
|
||||||
hub->users->count,
|
if (!users)
|
||||||
hub->users->count_peak,
|
return NULL;
|
||||||
(int) hub->stats.net_tx / 1024,
|
|
||||||
(int) hub->stats.net_rx / 1024,
|
users->list = list_create();
|
||||||
(int) hub->stats.net_tx_peak / 1024,
|
users->nickmap = rb_tree_create(uman_map_compare, NULL, NULL);
|
||||||
(int) hub->stats.net_rx_peak / 1024);
|
users->cidmap = rb_tree_create(uman_map_compare, NULL, NULL);
|
||||||
|
users->sids = sid_pool_create(net_get_max_sockets());
|
||||||
|
|
||||||
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timer_statistics(struct timeout_evt* t)
|
|
||||||
{
|
|
||||||
struct hub_info* hub = (struct hub_info*) t->ptr;
|
|
||||||
uman_update_stats(hub);
|
|
||||||
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->users->timeout, TIMEOUT_STATS);
|
|
||||||
}
|
|
||||||
|
|
||||||
int uman_init(struct hub_info* hub)
|
int uman_shutdown(struct hub_user_manager* users)
|
||||||
{
|
{
|
||||||
struct hub_user_manager* users = NULL;
|
|
||||||
if (!hub)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
|
|
||||||
if (!users)
|
if (!users)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
users->list = list_create();
|
if (users->nickmap)
|
||||||
users->sids = sid_pool_create(net_get_max_sockets());
|
rb_tree_destroy(users->nickmap);
|
||||||
|
|
||||||
if (!users->list)
|
if (users->cidmap)
|
||||||
|
rb_tree_destroy(users->cidmap);
|
||||||
|
|
||||||
|
if (users->list)
|
||||||
{
|
{
|
||||||
|
list_clear(users->list, &clear_user_list_callback);
|
||||||
list_destroy(users->list);
|
list_destroy(users->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
sid_pool_destroy(users->sids);
|
||||||
|
|
||||||
hub_free(users);
|
hub_free(users);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (net_backend_get_timeout_queue())
|
|
||||||
{
|
|
||||||
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
|
||||||
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
|
||||||
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
|
||||||
}
|
|
||||||
|
|
||||||
hub->users = users;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uman_shutdown(struct hub_info* hub)
|
int uman_add(struct hub_user_manager* users, struct hub_user* user)
|
||||||
{
|
{
|
||||||
if (!hub || !hub->users)
|
if (!users || !user)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (net_backend_get_timeout_queue())
|
rb_tree_insert(users->nickmap, user->id.nick, user);
|
||||||
{
|
rb_tree_insert(users->cidmap, user->id.cid, user);
|
||||||
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
|
||||||
hub_free(hub->users->timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hub->users->list)
|
|
||||||
{
|
|
||||||
list_clear(hub->users->list, &clear_user_list_callback);
|
|
||||||
list_destroy(hub->users->list);
|
|
||||||
}
|
|
||||||
sid_pool_destroy(hub->users->sids);
|
|
||||||
hub_free(hub->users);
|
|
||||||
hub->users = 0;
|
|
||||||
|
|
||||||
|
list_append(users->list, user);
|
||||||
|
users->count++;
|
||||||
|
users->count_peak = MAX(users->count, users->count_peak);
|
||||||
|
|
||||||
|
users->shared_size += user->limits.shared_size;
|
||||||
|
users->shared_files += user->limits.shared_files;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uman_remove(struct hub_user_manager* users, struct hub_user* user)
|
||||||
int uman_add(struct hub_info* hub, struct hub_user* user)
|
|
||||||
{
|
{
|
||||||
if (!hub || !user)
|
if (!users || !user)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (user->hub)
|
list_remove(users->list, user);
|
||||||
return -1;
|
rb_tree_remove(users->nickmap, user->id.nick);
|
||||||
|
rb_tree_remove(users->cidmap, user->id.cid);
|
||||||
|
|
||||||
list_append(hub->users->list, user);
|
if (users->count > 0)
|
||||||
hub->users->count++;
|
|
||||||
hub->users->count_peak = MAX(hub->users->count, hub->users->count_peak);
|
|
||||||
|
|
||||||
hub->users->shared_size += user->limits.shared_size;
|
|
||||||
hub->users->shared_files += user->limits.shared_files;
|
|
||||||
|
|
||||||
user->hub = hub;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int uman_remove(struct hub_info* hub, struct hub_user* user)
|
|
||||||
{
|
{
|
||||||
if (!hub || !user)
|
users->count--;
|
||||||
return -1;
|
|
||||||
|
|
||||||
list_remove(hub->users->list, user);
|
|
||||||
|
|
||||||
if (hub->users->count > 0)
|
|
||||||
{
|
|
||||||
hub->users->count--;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(!"negative count!");
|
uhub_assert(!"negative count!");
|
||||||
}
|
}
|
||||||
|
|
||||||
hub->users->shared_size -= user->limits.shared_size;
|
users->shared_size -= user->limits.shared_size;
|
||||||
hub->users->shared_files -= user->limits.shared_files;
|
users->shared_files -= user->limits.shared_files;
|
||||||
|
|
||||||
user->hub = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid)
|
struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid)
|
||||||
{
|
{
|
||||||
return sid_lookup(hub->users->sids, sid);
|
return sid_lookup(users->sids, sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid)
|
struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid)
|
||||||
{
|
{
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
|
struct hub_user* user = (struct hub_user*) rb_tree_get(users->cidmap, (const void*) cid);
|
||||||
while (user)
|
|
||||||
{
|
|
||||||
if (strcmp(user->id.cid, cid) == 0)
|
|
||||||
return user;
|
return user;
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick)
|
struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick)
|
||||||
{
|
{
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
|
struct hub_user* user = (struct hub_user*) rb_tree_get(users->nickmap, nick);
|
||||||
while (user)
|
|
||||||
{
|
|
||||||
if (strcmp(user->id.nick, nick) == 0)
|
|
||||||
return user;
|
return user;
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range)
|
size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range)
|
||||||
{
|
{
|
||||||
size_t num = 0;
|
size_t num = 0;
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
|
struct hub_user* user;
|
||||||
while (user)
|
LIST_FOREACH(struct hub_user*, user, users->list,
|
||||||
{
|
{
|
||||||
if (ip_in_range(&user->id.addr, range))
|
if (ip_in_range(&user->id.addr, range))
|
||||||
{
|
{
|
||||||
list_append(users, user);
|
list_append(target, user);
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
});
|
||||||
}
|
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* target)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
struct hub_user* user;
|
struct hub_user* user;
|
||||||
user_flag_set(target, flag_user_list);
|
user_flag_set(target, flag_user_list);
|
||||||
user = (struct hub_user*) list_get_first(hub->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))
|
if (user_is_logged_in(user))
|
||||||
{
|
{
|
||||||
@ -235,8 +172,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
FIXME: FIXME FIXME handle send queue excess
|
FIXME: FIXME FIXME handle send queue excess
|
||||||
@ -248,7 +184,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
void uman_send_quit_message(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* leaving)
|
||||||
{
|
{
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
||||||
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
|
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
|
||||||
@ -261,9 +197,9 @@ void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
|
|||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
|
sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user* user)
|
||||||
{
|
{
|
||||||
sid_t sid = sid_alloc(hub->users->sids, user);
|
sid_t sid = sid_alloc(users->sids, user);
|
||||||
user->id.sid = sid;
|
user->id.sid = sid;
|
||||||
return sid;
|
return sid;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,40 +24,41 @@ struct hub_user_manager
|
|||||||
{
|
{
|
||||||
size_t count; /**<< "Number of all fully connected and logged in users" */
|
size_t count; /**<< "Number of all fully connected and logged in users" */
|
||||||
size_t count_peak; /**<< "Peak number of users" */
|
size_t count_peak; /**<< "Peak number of users" */
|
||||||
struct sid_pool* sids;
|
|
||||||
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
||||||
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
||||||
|
struct sid_pool* sids; /**<< "Maps SIDs to users (constant time)" */
|
||||||
struct linked_list* list; /**<< "Contains all logged in users" */
|
struct linked_list* list; /**<< "Contains all logged in users" */
|
||||||
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
|
struct rb_tree* nickmap; /**<< "Maps nicknames to users (red black tree)" */
|
||||||
|
struct rb_tree* cidmap; /**<< "Maps CIDs to users (red black tree)" */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the user manager.
|
* Initializes the user manager.
|
||||||
* @return 0 on success, or -1 if error (out of memory).
|
* @return 0 on success, or -1 if error (out of memory).
|
||||||
*/
|
*/
|
||||||
extern int uman_init(struct hub_info* hub);
|
extern struct hub_user_manager* uman_init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuts down the user manager.
|
* Shuts down the user manager.
|
||||||
* All users will be disconnected and deleted as part of this.
|
* All users will be disconnected and deleted as part of this.
|
||||||
*
|
*
|
||||||
* @return 0 on success, or -1 in an error occured (hub is invalid).
|
* @return 0 on success, or -1 in an error occurred (invalid pointer).
|
||||||
*/
|
*/
|
||||||
extern int uman_shutdown(struct hub_info* hub);
|
extern int uman_shutdown(struct hub_user_manager* users);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate statistics for logfiles.
|
* Generate statistics for logfiles.
|
||||||
*/
|
*/
|
||||||
extern void uman_update_stats(struct hub_info* hub);
|
extern void uman_update_stats(struct hub_user_manager* users);
|
||||||
extern void uman_print_stats(struct hub_info* hub);
|
extern void uman_print_stats(struct hub_user_manager* users);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a user to the user manager.
|
* Add a user to the user manager.
|
||||||
*
|
*
|
||||||
* @param hub The hub to add the user to
|
* @param users The usermanager to add the user to
|
||||||
* @param user The user to be added to the hub.
|
* @param user The user to be added to the hub.
|
||||||
*/
|
*/
|
||||||
extern int uman_add(struct hub_info* hub, struct hub_user* user);
|
extern int uman_add(struct hub_user_manager* users, struct hub_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a user from the user manager.
|
* Remove a user from the user manager.
|
||||||
@ -66,12 +67,12 @@ extern int uman_add(struct hub_info* hub, struct hub_user* user);
|
|||||||
*
|
*
|
||||||
* @return 0 if successfully removed, -1 if error.
|
* @return 0 if successfully removed, -1 if error.
|
||||||
*/
|
*/
|
||||||
extern int uman_remove(struct hub_info* hub, struct hub_user* user);
|
extern int uman_remove(struct hub_user_manager* users, struct hub_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns and allocates an unused session ID (SID).
|
* Returns and allocates an unused session ID (SID).
|
||||||
*/
|
*/
|
||||||
extern sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user);
|
extern sid_t uman_get_free_sid(struct hub_user_manager* users, struct hub_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup a user based on the session ID (SID).
|
* Lookup a user based on the session ID (SID).
|
||||||
@ -86,26 +87,28 @@ extern sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user);
|
|||||||
*
|
*
|
||||||
* @return a user if found, or NULL if not found
|
* @return a user if found, or NULL if not found
|
||||||
*/
|
*/
|
||||||
extern struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid);
|
extern struct hub_user* uman_get_user_by_sid(struct hub_user_manager* users, sid_t sid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup a user based on the client ID (CID).
|
* Lookup a user based on the client ID (CID).
|
||||||
* @return a user if found, or NULL if not found
|
* @return a user if found, or NULL if not found
|
||||||
*/
|
*/
|
||||||
extern struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid);
|
extern struct hub_user* uman_get_user_by_cid(struct hub_user_manager* users, const char* cid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup a user based on the nick name.
|
* Lookup a user based on the nick name.
|
||||||
* @return a user if found, or NULL if not found
|
* @return a user if found, or NULL if not found
|
||||||
*/
|
*/
|
||||||
extern struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
|
extern struct hub_user* uman_get_user_by_nick(struct hub_user_manager* users, const char* nick);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup users based on an ip address range.
|
* Lookup users based on an ip address range.
|
||||||
*
|
*
|
||||||
* @return The number of users matching the addressess, or -1 on error (mask is wrong).
|
* @param[out] target the list of users matching the address
|
||||||
|
* @param range the IP range of users to match
|
||||||
|
* @return The number of users matching the addresses, or -1 on error (mask is wrong).
|
||||||
*/
|
*/
|
||||||
extern size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range);
|
extern size_t uman_get_user_by_addr(struct hub_user_manager* users, struct linked_list* target, struct ip_range* range);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the user list of connected clients to 'user'.
|
* Send the user list of connected clients to 'user'.
|
||||||
@ -113,13 +116,13 @@ extern size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* us
|
|||||||
*
|
*
|
||||||
* @return 1 if sending the user list succeeded, 0 otherwise.
|
* @return 1 if sending the user list succeeded, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
extern int uman_send_user_list(struct hub_info* hub, struct hub_user* user);
|
extern int uman_send_user_list(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a quit message to all connected users when 'user' is
|
* Send a quit message to all connected users when 'user' is
|
||||||
* leaving the hub (for whatever reason).
|
* leaving the hub (for whatever reason).
|
||||||
*/
|
*/
|
||||||
extern void uman_send_quit_message(struct hub_info* hub, struct hub_user* user);
|
extern void uman_send_quit_message(struct hub_info* hub, struct hub_user_manager* users, struct hub_user* user);
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_USER_MANAGER_H */
|
#endif /* HAVE_UHUB_USER_MANAGER_H */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ static net_backend_init_t net_backend_init_funcs[] = {
|
|||||||
int net_backend_init()
|
int net_backend_init()
|
||||||
{
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
g_backend = hub_malloc_zero(sizeof(struct net_backend));
|
g_backend = (struct net_backend*) hub_malloc_zero(sizeof(struct net_backend));
|
||||||
g_backend->common.num = 0;
|
g_backend->common.num = 0;
|
||||||
g_backend->common.max = net_get_max_sockets();
|
g_backend->common.max = net_get_max_sockets();
|
||||||
g_backend->now = time(0);
|
g_backend->now = time(0);
|
||||||
@ -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)
|
void net_backend_update(struct net_connection* con, int events)
|
||||||
{
|
|
||||||
con->callback = callback;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
net_con_update(con, events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_update(struct net_connection* con, int events)
|
|
||||||
{
|
{
|
||||||
g_backend->handler.con_mod(g_backend->data, con, events);
|
g_backend->handler.con_mod(g_backend->data, con, events);
|
||||||
}
|
}
|
||||||
@ -132,9 +125,10 @@ struct timeout_queue* net_backend_get_timeout_queue()
|
|||||||
*/
|
*/
|
||||||
int net_backend_process()
|
int net_backend_process()
|
||||||
{
|
{
|
||||||
int res;
|
int res = 0;
|
||||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||||
|
|
||||||
|
if (g_backend->common.num)
|
||||||
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
||||||
|
|
||||||
g_backend->now = time(0);
|
g_backend->now = time(0);
|
||||||
@ -146,6 +140,9 @@ int net_backend_process()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process pending DNS results
|
||||||
|
// net_dns_process();
|
||||||
|
|
||||||
g_backend->handler.backend_process(g_backend->data, res);
|
g_backend->handler.backend_process(g_backend->data, res);
|
||||||
|
|
||||||
net_cleanup_process(g_backend->cleaner);
|
net_cleanup_process(g_backend->cleaner);
|
||||||
@ -162,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);
|
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
||||||
|
|
||||||
net_set_nonblocking(con->sd, 1);
|
net_set_nonblocking(net_con_get_sd(con), 1);
|
||||||
net_set_nosigpipe(con->sd, 1);
|
net_set_nosigpipe(net_con_get_sd(con), 1);
|
||||||
|
|
||||||
g_backend->handler.con_add(g_backend->data, con, events);
|
g_backend->handler.con_add(g_backend->data, con, events);
|
||||||
g_backend->common.num++;
|
g_backend->common.num++;
|
||||||
@ -179,6 +176,11 @@ void net_con_close(struct net_connection* con)
|
|||||||
|
|
||||||
g_backend->handler.con_del(g_backend->data, con);
|
g_backend->handler.con_del(g_backend->data, con);
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (con->ssl)
|
||||||
|
net_ssl_shutdown(con);
|
||||||
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
net_close(con->sd);
|
net_close(con->sd);
|
||||||
con->sd = -1;
|
con->sd = -1;
|
||||||
|
|
||||||
@ -196,6 +198,7 @@ struct net_cleanup_handler* net_cleanup_initialize(size_t max)
|
|||||||
|
|
||||||
void net_cleanup_shutdown(struct net_cleanup_handler* handler)
|
void net_cleanup_shutdown(struct net_cleanup_handler* handler)
|
||||||
{
|
{
|
||||||
|
net_cleanup_process(handler);
|
||||||
hub_free(handler->queue);
|
hub_free(handler->queue);
|
||||||
hub_free(handler);
|
hub_free(handler);
|
||||||
}
|
}
|
||||||
@ -213,7 +216,7 @@ void net_cleanup_process(struct net_cleanup_handler* handler)
|
|||||||
{
|
{
|
||||||
struct net_connection* con = handler->queue[n];
|
struct net_connection* con = handler->queue[n];
|
||||||
LOG_TRACE("net_cleanup_process: free: %p", con);
|
LOG_TRACE("net_cleanup_process: free: %p", con);
|
||||||
hub_free(con);
|
net_con_destroy(con);
|
||||||
}
|
}
|
||||||
handler->num = 0;
|
handler->num = 0;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ typedef void (*net_con_backend_init)(struct net_backend*, struct net_connection*
|
|||||||
typedef void (*net_con_backend_add)(struct net_backend*, struct net_connection*, int mask);
|
typedef void (*net_con_backend_add)(struct net_backend*, struct net_connection*, int mask);
|
||||||
typedef void (*net_con_backend_mod)(struct net_backend*, struct net_connection*, int mask);
|
typedef void (*net_con_backend_mod)(struct net_backend*, struct net_connection*, int mask);
|
||||||
typedef void (*net_con_backend_del)(struct net_backend*,struct net_connection*);
|
typedef void (*net_con_backend_del)(struct net_backend*,struct net_connection*);
|
||||||
typedef const char* (*net_con_backend_name)(void);
|
typedef const char* (*net_con_backend_name)();
|
||||||
|
|
||||||
struct net_backend_handler
|
struct net_backend_handler
|
||||||
{
|
{
|
||||||
@ -75,6 +75,14 @@ extern void net_backend_shutdown();
|
|||||||
*/
|
*/
|
||||||
extern int net_backend_process();
|
extern int net_backend_process();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the event mask.
|
||||||
|
*
|
||||||
|
* @param con Connection handle.
|
||||||
|
* @param events Event mask (NET_EVENT_*)
|
||||||
|
*/
|
||||||
|
extern void net_backend_update(struct net_connection* con, int events);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current time.
|
* Get the current time.
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,18 +13,17 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NET_WANT_READ NET_EVENT_READ
|
#define NET_WANT_READ NET_EVENT_READ
|
||||||
#define NET_WANT_WRITE NET_EVENT_WRITE
|
#define NET_WANT_WRITE NET_EVENT_WRITE
|
||||||
#define NET_WANT_ACCEPT NET_EVENT_READ
|
#define NET_WANT_ACCEPT NET_EVENT_READ
|
||||||
#define NET_WANT_SSL_READ 0x0010
|
|
||||||
#define NET_WANT_SSL_WRITE 0x0020
|
#define NET_SSL_ANY NET_WANT_SSL_READ | NET_WANT_SSL_WRITE | NET_WANT_SSL_ACCEPT | NET_WANT_SSL_CONNECT | NET_WANT_SSL_X509_LOOKUP
|
||||||
#define NET_WANT_SSL_ACCEPT 0x0040
|
|
||||||
#define NET_WANT_SSL_CONNECT 0x0080
|
struct ssl_handle; /* abstract type */
|
||||||
#define NET_WANT_SSL_X509_LOOKUP 0x0100
|
|
||||||
|
|
||||||
#define NET_CLEANUP 0x8000
|
#define NET_CLEANUP 0x8000
|
||||||
|
|
||||||
@ -36,9 +35,7 @@
|
|||||||
struct timeout_evt* timeout; /** timeout event handler */
|
struct timeout_evt* timeout; /** timeout event handler */
|
||||||
|
|
||||||
#define NET_CON_STRUCT_SSL \
|
#define NET_CON_STRUCT_SSL \
|
||||||
SSL* ssl; /** SSL handle */ \
|
struct ssl_handle* ssl; /** SSL handle */
|
||||||
uint32_t ssl_state; /** SSL state */ \
|
|
||||||
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
#define NET_CON_STRUCT_COMMON \
|
#define NET_CON_STRUCT_COMMON \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* uhub - A tiny ADC p2p connection hub
|
* 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
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -13,130 +13,25 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "network/common.h"
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
static int is_blocked_or_interrupted()
|
||||||
|
|
||||||
enum uhub_tls_state
|
|
||||||
{
|
{
|
||||||
tls_st_none,
|
int err = net_error();
|
||||||
tls_st_error,
|
return
|
||||||
tls_st_accepting,
|
#ifdef WINSOCK
|
||||||
tls_st_connecting,
|
err == WSAEWOULDBLOCK
|
||||||
tls_st_connected,
|
#else
|
||||||
tls_st_disconnecting,
|
err == EWOULDBLOCK
|
||||||
};
|
|
||||||
|
|
||||||
static int handle_openssl_error(struct net_connection* con, int ret)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
|
|
||||||
int error = SSL_get_error(con->ssl, ret);
|
|
||||||
switch (error)
|
|
||||||
{
|
|
||||||
case SSL_ERROR_ZERO_RETURN:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
|
|
||||||
con->ssl_state = tls_st_error;
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case SSL_ERROR_WANT_READ:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
|
|
||||||
con->flags |= NET_WANT_SSL_READ;
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case SSL_ERROR_WANT_WRITE:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
|
|
||||||
con->flags |= NET_WANT_SSL_WRITE;
|
|
||||||
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case SSL_ERROR_SYSCALL:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
|
|
||||||
/* if ret == 0, connection closed, if ret == -1, check with errno */
|
|
||||||
if (ret == 0)
|
|
||||||
return -1;
|
|
||||||
else
|
|
||||||
return -net_error();
|
|
||||||
|
|
||||||
case SSL_ERROR_SSL:
|
|
||||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
|
|
||||||
/* internal openssl error */
|
|
||||||
con->ssl_state = tls_st_error;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_ssl_accept(struct net_connection* con)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
con->ssl_state = tls_st_accepting;
|
|
||||||
ssize_t ret = SSL_accept(con->ssl);
|
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
|
||||||
LOG_PROTO("SSL_accept() ret=%d", ret);
|
|
||||||
#endif
|
#endif
|
||||||
if (ret > 0)
|
|| err == EINTR;
|
||||||
{
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
con->ssl_state = tls_st_connected;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_ssl_connect(struct net_connection* con)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
|
|
||||||
con->ssl_state = tls_st_connecting;
|
|
||||||
ssize_t ret = SSL_connect(con->ssl);
|
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
|
||||||
LOG_PROTO("SSL_connect() ret=%d", ret);
|
|
||||||
#endif
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
con->ssl_state = tls_st_connected;
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx)
|
|
||||||
{
|
|
||||||
uhub_assert(con);
|
|
||||||
SSL* ssl = 0;
|
|
||||||
|
|
||||||
if (ssl_mode == net_con_ssl_mode_server)
|
|
||||||
{
|
|
||||||
ssl = SSL_new(ssl_ctx);
|
|
||||||
SSL_set_fd(ssl, con->sd);
|
|
||||||
net_con_set_ssl(con, ssl);
|
|
||||||
return net_con_ssl_accept(con);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
|
|
||||||
SSL_set_fd(ssl, con->sd);
|
|
||||||
net_con_set_ssl(con, ssl);
|
|
||||||
return net_con_ssl_connect(con);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* SSL_SUPPORT */
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
||||||
{
|
{
|
||||||
@ -148,7 +43,7 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
|||||||
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
|
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
if (is_blocked_or_interrupted())
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -156,15 +51,9 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
con->write_len = len;
|
ret = net_ssl_send(con, buf, len);
|
||||||
ret = SSL_write(con->ssl, buf, len);
|
|
||||||
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
|
||||||
if (ret <= 0)
|
|
||||||
{
|
|
||||||
return -handle_openssl_error(con, ret);
|
|
||||||
}
|
}
|
||||||
}
|
#endif /* SSL_SUPPORT */
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,13 +61,13 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
if (!net_con_is_ssl(con))
|
if (!con->ssl)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
ret = net_recv(con->sd, buf, len, 0);
|
ret = net_recv(con->sd, buf, len, 0);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
if (is_blocked_or_interrupted())
|
||||||
return 0;
|
return 0;
|
||||||
return -net_error();
|
return -net_error();
|
||||||
}
|
}
|
||||||
@ -190,21 +79,9 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (con->ssl_state == tls_st_error)
|
ret = net_ssl_recv(con, buf, len);
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = SSL_read(con->ssl, buf, len);
|
|
||||||
LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
net_con_update(con, NET_EVENT_READ);
|
|
||||||
}
|
}
|
||||||
else
|
#endif /* SSL_SUPPORT */
|
||||||
{
|
|
||||||
return -handle_openssl_error(con, ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +90,7 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
|
|||||||
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
|
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
if (is_blocked_or_interrupted())
|
||||||
return 0;
|
return 0;
|
||||||
return -net_error();
|
return -net_error();
|
||||||
}
|
}
|
||||||
@ -223,19 +100,10 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
|
|
||||||
int net_con_is_ssl(struct net_connection* con)
|
int net_con_is_ssl(struct net_connection* con)
|
||||||
{
|
{
|
||||||
return con->ssl != 0;
|
return !!con->ssl;
|
||||||
}
|
|
||||||
|
|
||||||
SSL* net_con_get_ssl(struct net_connection* con)
|
|
||||||
{
|
|
||||||
return con->ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
|
|
||||||
{
|
|
||||||
con->ssl = ssl;
|
|
||||||
}
|
}
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
@ -249,8 +117,29 @@ void* net_con_get_ptr(struct net_connection* con)
|
|||||||
return con->ptr;
|
return con->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void net_con_update(struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (con->ssl)
|
||||||
|
net_ssl_update(con, events);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
net_backend_update(con, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
||||||
|
{
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
net_con_update(con, events);
|
||||||
|
}
|
||||||
|
|
||||||
void net_con_destroy(struct net_connection* con)
|
void net_con_destroy(struct net_connection* con)
|
||||||
{
|
{
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (con && con->ssl)
|
||||||
|
net_ssl_destroy(con);
|
||||||
|
#endif
|
||||||
hub_free(con);
|
hub_free(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,68 +150,408 @@ void net_con_callback(struct net_connection* con, int events)
|
|||||||
|
|
||||||
if (events == NET_EVENT_TIMEOUT)
|
if (events == NET_EVENT_TIMEOUT)
|
||||||
{
|
{
|
||||||
LOG_TRACE("net_con_callback(%p, TIMEOUT", con);
|
LOG_TRACE("net_con_callback(%p, TIMEOUT)", con);
|
||||||
con->callback(con, events, con->ptr);
|
con->callback(con, events, con->ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
if (!con->ssl)
|
if (con->ssl)
|
||||||
{
|
net_ssl_callback(con, events);
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
con->callback(con, events, con->ptr);
|
con->callback(con, events, con->ptr);
|
||||||
#ifdef SSL_SUPPORT
|
}
|
||||||
|
|
||||||
|
struct net_connect_job
|
||||||
|
{
|
||||||
|
struct net_connection* con;
|
||||||
|
struct net_connect_handle* handle;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct net_connect_job* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_connect_handle
|
||||||
|
{
|
||||||
|
const char* address;
|
||||||
|
uint16_t port;
|
||||||
|
void* ptr;
|
||||||
|
net_connect_cb callback;
|
||||||
|
struct net_dns_job* dns;
|
||||||
|
const struct net_dns_result* result;
|
||||||
|
struct net_connect_job* job4;
|
||||||
|
struct net_connect_job* job6;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void net_connect_callback(struct net_connect_handle* handle, enum net_connect_status status, struct net_connection* con);
|
||||||
|
static void net_connect_job_internal_cb(struct net_connection* con, int event, void* ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a connection job is completed.
|
||||||
|
* @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected).
|
||||||
|
*/
|
||||||
|
static int net_connect_job_check(struct net_connect_job* job)
|
||||||
|
{
|
||||||
|
struct net_connection* con = job->con;
|
||||||
|
int af = job->addr.ss_family;
|
||||||
|
enum net_connect_status status;
|
||||||
|
|
||||||
|
int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
|
||||||
|
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
|
||||||
|
{
|
||||||
|
LOG_TRACE("net_connect_job_check(): Socket connected!");
|
||||||
|
job->con = NULL;
|
||||||
|
net_con_clear_timeout(con);
|
||||||
|
net_connect_callback(job->handle, net_connect_status_ok, con);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LOG_TRACE("net_connect_job_check(): Socket error!");
|
||||||
|
|
||||||
|
switch (net_error())
|
||||||
|
{
|
||||||
|
case ECONNREFUSED:
|
||||||
|
status = net_connect_status_refused;
|
||||||
|
break;
|
||||||
|
case ENETUNREACH:
|
||||||
|
status = net_connect_status_unreachable;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
status = net_connect_status_socket_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_connect_callback(job->handle, status, NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_connect_job_free(struct net_connect_job* job)
|
||||||
|
{
|
||||||
|
if (job->con)
|
||||||
|
net_con_close(job->con);
|
||||||
|
job->handle = NULL;
|
||||||
|
job->next = NULL;
|
||||||
|
hub_free(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_connect_job_stop(struct net_connect_job* job)
|
||||||
|
{
|
||||||
|
if (job->addr.ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
job->handle->job6 = job->next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef NETWORK_DUMP_DEBUG
|
job->handle->job4 = job->next;
|
||||||
LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
|
|
||||||
#endif
|
|
||||||
switch (con->ssl_state)
|
|
||||||
{
|
|
||||||
case tls_st_none:
|
|
||||||
con->callback(con, events, con->ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_error:
|
|
||||||
con->callback(con, NET_EVENT_READ, con->ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_accepting:
|
|
||||||
if (net_con_ssl_accept(con) < 0)
|
|
||||||
{
|
|
||||||
con->callback(con, NET_EVENT_READ, con->ptr);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_connecting:
|
net_connect_job_free(job);
|
||||||
if (net_con_ssl_connect(con) < 0)
|
|
||||||
{
|
|
||||||
con->callback(con, NET_EVENT_READ, con->ptr);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_connected:
|
static int net_connect_depleted(struct net_connect_handle* handle)
|
||||||
LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : "");
|
|
||||||
if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ)
|
|
||||||
{
|
{
|
||||||
con->callback(con, events & NET_EVENT_READ, con->ptr);
|
return (!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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
|
if (event == NET_EVENT_WRITE)
|
||||||
{
|
{
|
||||||
con->callback(con, events & NET_EVENT_READ, con->ptr);
|
net_connect_job_process(job);
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con->callback(con, events, con->ptr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case tls_st_disconnecting:
|
static void net_connect_cancel(struct net_connect_handle* handle)
|
||||||
return;
|
{
|
||||||
}
|
struct net_connect_job* job;
|
||||||
}
|
|
||||||
#endif
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user