Compare commits
260 Commits
0.3.0
...
command_cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
714d110a94 | ||
|
|
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 | ||
|
|
aa26052479 | ||
|
|
7b96e2c912 | ||
|
|
ccaa4860b4 | ||
|
|
7218011449 | ||
|
|
0810982b57 | ||
|
|
baeba01835 | ||
|
|
07d4e4470c | ||
|
|
ac5811633e | ||
|
|
ed53034ad5 | ||
|
|
fc8965f1c5 | ||
|
|
b3ed3a5526 | ||
|
|
1480b7e9c0 | ||
|
|
50fde1c5c8 | ||
|
|
77faac0494 | ||
|
|
473ff0e159 | ||
|
|
62333c5f39 | ||
|
|
44860c8477 | ||
|
|
c70119870a | ||
|
|
b29f34af4a | ||
|
|
076492f1b9 | ||
|
|
b6fb2b41bd | ||
|
|
c82f8ba167 | ||
|
|
6c9cd4ca50 | ||
|
|
201acad409 | ||
|
|
51c5b6169c | ||
|
|
b7e62b46cc | ||
|
|
321cddad8e | ||
|
|
8ec55a59f5 | ||
|
|
d3ebc409cb | ||
|
|
2fa5c01050 | ||
|
|
45462595ac | ||
|
|
0a3fe10f16 | ||
|
|
8e816fd196 | ||
|
|
88a22659a1 | ||
|
|
3393ee6a85 | ||
|
|
58630fde08 | ||
|
|
8815118fde | ||
|
|
5454ae279a | ||
|
|
8e579f4601 | ||
|
|
e220357176 | ||
|
|
8bed952022 | ||
|
|
c4604a7e94 | ||
|
|
236daeae53 | ||
|
|
862c6a1baf | ||
|
|
198d86a1ee | ||
|
|
2ded9f3e09 | ||
|
|
59ed268f4d | ||
|
|
963416ad73 | ||
|
|
29c162727c | ||
|
|
1ce258bccf | ||
|
|
0de66286fa | ||
|
|
1a98bb6810 | ||
|
|
5e6879dffb | ||
|
|
1b56adb8c0 | ||
|
|
685597c795 | ||
|
|
782f091637 | ||
|
|
82eeaa1fba | ||
|
|
977b57a385 | ||
|
|
19b9f72337 | ||
|
|
56605f7dcb | ||
|
|
bf1b64db53 | ||
|
|
915cb56448 | ||
|
|
6992043f9d | ||
|
|
896bbfcb5d | ||
|
|
6ac78e1a10 | ||
|
|
74a2191350 | ||
|
|
be8db21561 | ||
|
|
8065903604 | ||
|
|
78ae9fb3ce | ||
|
|
4715815ba2 | ||
|
|
cb9625f6a5 | ||
|
|
9934bde050 | ||
|
|
9a1c5ee548 | ||
|
|
11df912162 | ||
|
|
c8bc2f64fd | ||
|
|
2dc95eca47 | ||
|
|
7637d9ba68 | ||
|
|
4e9488dd4d | ||
|
|
e0003ebbb2 | ||
|
|
8e7e8c68f5 | ||
|
|
db32eaeafc | ||
|
|
1599f63134 | ||
|
|
c3ad006d07 | ||
|
|
1faca92167 | ||
|
|
f0a13b4c23 | ||
|
|
ccd1c8f160 | ||
|
|
41418f21e7 | ||
|
|
7a8a737cad | ||
|
|
ac48ad01fb | ||
|
|
31a69b1f3f | ||
|
|
d7a1a52c1a | ||
|
|
f54e8dbbba | ||
|
|
de72d4ae63 | ||
|
|
01efc6cc20 | ||
|
|
7cf1181e6b | ||
|
|
4b64b28777 | ||
|
|
e9f0331ca8 | ||
|
|
f263534aaf | ||
|
|
788b644c80 | ||
|
|
2d7ffa37fe | ||
|
|
fbaac98483 | ||
|
|
bd9d8229ff | ||
|
|
dfa6d07455 | ||
|
|
6bbdd24cb7 | ||
|
|
e3a644a853 | ||
|
|
928225fb7b | ||
|
|
e3cf41cb97 | ||
|
|
59f67f9e17 | ||
|
|
bfc7c184a7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,7 +2,8 @@
|
|||||||
*.[oa]
|
*.[oa]
|
||||||
*.exe
|
*.exe
|
||||||
*.gch
|
*.gch
|
||||||
|
mod_*.so
|
||||||
uhub-admin
|
uhub-admin
|
||||||
adcrush
|
adcrush
|
||||||
uhub
|
uhub
|
||||||
|
revision.h*
|
||||||
|
|||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "thirdparty/sqlite"]
|
||||||
|
path = thirdparty/sqlite
|
||||||
|
url = git://github.com/janvidar/sqlite.git
|
||||||
7
AUTHORS
7
AUTHORS
@@ -1,6 +1,9 @@
|
|||||||
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
|
||||||
|
FleetCommand, Hub topic
|
||||||
|
MiMic, Implemented user commands
|
||||||
|
tehnick, Debian and Ubuntu packaging.
|
||||||
|
|
||||||
|
|||||||
8
BSDmakefile
Normal file
8
BSDmakefile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
GMAKE=gmake
|
||||||
|
|
||||||
|
all:
|
||||||
|
@${GMAKE} ${.TARGETS}
|
||||||
|
|
||||||
|
${.TARGETS}: all
|
||||||
|
|
||||||
34
ChangeLog
34
ChangeLog
@@ -1,3 +1,37 @@
|
|||||||
|
0.3.2:
|
||||||
|
- Fixed bugs in the kqueue network backend (OSX/BSD)
|
||||||
|
- Rewrote the configuration backend code.
|
||||||
|
- Added support for escaping characters in the configuration files.
|
||||||
|
- Updated the !broadcast command to send private messages instead of main chat messages.
|
||||||
|
- Adding support for redirecting clients to other hubs when they fail to log in.
|
||||||
|
- Fix some out of memory related crashes.
|
||||||
|
- Fixed minor memory leaks.
|
||||||
|
|
||||||
|
|
||||||
|
0.3.1:
|
||||||
|
- Fixed bug where !getip did not work.
|
||||||
|
- Added flood control configuration options.
|
||||||
|
- Added configuration options to disallow old/obsolete ADC clients.
|
||||||
|
- Fixed crash bugs, an freezes.
|
||||||
|
- SSL/TLS fix for tls_require configuration option.
|
||||||
|
- Fixed disconnect messages, so that clients can interpret them.
|
||||||
|
- Fixed bugs where share limits could be circumvented.
|
||||||
|
- Added support for listening to multiple ports.
|
||||||
|
- kqueue backend for Mac OS X, and BSD systems.
|
||||||
|
|
||||||
|
|
||||||
|
0.3.0:
|
||||||
|
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
||||||
|
- Experimental SSL support
|
||||||
|
- Large rewrite of the network stack in order to support SSL.
|
||||||
|
- Added rule file for defining hub rules.
|
||||||
|
- Many crash fixes and other important bug fixes.
|
||||||
|
- Optimizations: O(1) timeout scheduler
|
||||||
|
- New sid allocation code.
|
||||||
|
- Added configurable server_listen_backlog (default 50).
|
||||||
|
- Added init.d scripts for RedHat/CentOS
|
||||||
|
|
||||||
|
|
||||||
0.2.8:
|
0.2.8:
|
||||||
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
||||||
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
||||||
|
|||||||
181
GNUmakefile
181
GNUmakefile
@@ -3,29 +3,44 @@
|
|||||||
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
||||||
#
|
#
|
||||||
|
|
||||||
|
-include Makefile.private
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
LD := $(CC)
|
LD := $(CC)
|
||||||
MV := mv
|
MV := mv
|
||||||
RANLIB := ranlib
|
RANLIB := ranlib
|
||||||
CFLAGS += -pipe -Wall
|
CFLAGS += -pipe -Wall
|
||||||
USE_SSL ?= NO
|
USE_SSL ?= YES
|
||||||
|
USE_PLUGINS ?= YES
|
||||||
USE_BIGENDIAN ?= AUTO
|
USE_BIGENDIAN ?= AUTO
|
||||||
BITS ?= AUTO
|
BITS ?= AUTO
|
||||||
SILENT ?= YES
|
SILENT ?= YES
|
||||||
TERSE ?= NO
|
TERSE ?= NO
|
||||||
STACK_PROTECT ?= NO
|
STACK_PROTECT ?= NO
|
||||||
|
NEED_LIBDL ?= NO
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
WINDOWS ?= YES
|
WINDOWS ?= YES
|
||||||
|
OPSYS ?= Windows
|
||||||
|
else
|
||||||
|
OPSYS ?= $(shell uname)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (SOLARIS,YES)
|
ifeq ($(OPSYS),SunOS)
|
||||||
LDLIBS += -lsocket -lnsl
|
LDLIBS += -lsocket -lnsl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OPSYS),Haiku)
|
||||||
|
LDLIBS += -lnetwork
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OPSYS),Linux)
|
||||||
|
NEED_LIBDL = YES
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += -I./src/
|
CFLAGS += -I./src/
|
||||||
|
|
||||||
ifeq ($(WINDOWS),YES)
|
ifeq ($(OPSYS),Windows)
|
||||||
USE_BIGENDIAN := NO
|
USE_BIGENDIAN := NO
|
||||||
LDLIBS += -lws2_32
|
LDLIBS += -lws2_32
|
||||||
UHUB_CONF_DIR ?= c:/uhub/
|
UHUB_CONF_DIR ?= c:/uhub/
|
||||||
@@ -33,18 +48,18 @@ UHUB_PREFIX ?= c:/uhub/
|
|||||||
CFLAGS += -mno-cygwin
|
CFLAGS += -mno-cygwin
|
||||||
LDFLAGS += -mno-cygwin
|
LDFLAGS += -mno-cygwin
|
||||||
BIN_EXT ?= .exe
|
BIN_EXT ?= .exe
|
||||||
GIT_REVISION ?= NO
|
|
||||||
else
|
else
|
||||||
DESTDIR ?= /
|
DESTDIR ?= /
|
||||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
||||||
UHUB_PREFIX ?= $(DESTDIR)/usr/local
|
UHUB_PREFIX ?= $(DESTDIR)/usr/local
|
||||||
|
UHUB_MOD_DIR ?= $(DESTDIR)/var/lib/uhub
|
||||||
CFLAGS += -I/usr/local/include
|
CFLAGS += -I/usr/local/include
|
||||||
LDFLAGS += -L/usr/local/lib
|
LDFLAGS += -L/usr/local/lib
|
||||||
BIN_EXT ?=
|
BIN_EXT ?=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SILENT),YES)
|
ifeq ($(SILENT),YES)
|
||||||
MSG_CC=@echo " CC:" $(notdir $^) &&
|
MSG_CC=@echo " CC:" $(notdir $<) &&
|
||||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
MSG_LD=@echo " LD:" $(notdir $@) &&
|
||||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
MSG_AR=@echo " AR:" $(notdir $@) &&
|
||||||
else
|
else
|
||||||
@@ -64,10 +79,8 @@ endif
|
|||||||
|
|
||||||
ifeq ($(RELEASE),YES)
|
ifeq ($(RELEASE),YES)
|
||||||
CFLAGS += -O3 -DNDEBUG
|
CFLAGS += -O3 -DNDEBUG
|
||||||
GIT_REVISION ?= NO
|
|
||||||
else
|
else
|
||||||
CFLAGS += -ggdb -DDEBUG
|
CFLAGS += -ggdb -DDEBUG
|
||||||
GIT_REVISION ?= YES
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(STACK_PROTECT),YES)
|
ifeq ($(STACK_PROTECT),YES)
|
||||||
@@ -109,13 +122,17 @@ endif
|
|||||||
|
|
||||||
ifeq ($(USE_SSL),YES)
|
ifeq ($(USE_SSL),YES)
|
||||||
CFLAGS += -DSSL_SUPPORT
|
CFLAGS += -DSSL_SUPPORT
|
||||||
LDLIBS += -lssl
|
LDLIBS += -lssl -lcrypto
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(GIT_REVISION),YES)
|
ifeq ($(NEED_LIBDL),YES)
|
||||||
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
|
LDLIBS += -ldl
|
||||||
endif
|
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
|
# Sources
|
||||||
libuhub_SOURCES := \
|
libuhub_SOURCES := \
|
||||||
src/core/auth.c \
|
src/core/auth.c \
|
||||||
@@ -131,85 +148,179 @@ libuhub_SOURCES := \
|
|||||||
src/core/route.c \
|
src/core/route.c \
|
||||||
src/core/user.c \
|
src/core/user.c \
|
||||||
src/core/usermanager.c \
|
src/core/usermanager.c \
|
||||||
|
src/core/plugincallback.c \
|
||||||
|
src/core/plugininvoke.c \
|
||||||
|
src/core/pluginloader.c \
|
||||||
src/network/backend.c \
|
src/network/backend.c \
|
||||||
src/network/connection.c \
|
src/network/connection.c \
|
||||||
src/network/epoll.c \
|
src/network/epoll.c \
|
||||||
src/network/network.c \
|
src/network/kqueue.c \
|
||||||
src/network/select.c \
|
src/network/select.c \
|
||||||
src/network/timer.c \
|
src/network/timeout.c \
|
||||||
|
src/network/timer.c
|
||||||
|
|
||||||
|
|
||||||
|
libadc_common_SOURCES := \
|
||||||
|
src/adc/message.c \
|
||||||
|
src/adc/sid.c
|
||||||
|
|
||||||
|
libutils_SOURCES := \
|
||||||
|
src/util/cbuffer.c \
|
||||||
|
src/util/config_token.c \
|
||||||
|
src/util/credentials.c \
|
||||||
|
src/util/floodctl.c \
|
||||||
src/util/ipcalc.c \
|
src/util/ipcalc.c \
|
||||||
src/util/list.c \
|
src/util/list.c \
|
||||||
src/util/log.c \
|
src/util/log.c \
|
||||||
src/util/memory.c \
|
src/util/memory.c \
|
||||||
src/util/misc.c \
|
src/util/misc.c \
|
||||||
|
src/network/network.c \
|
||||||
src/util/rbtree.c \
|
src/util/rbtree.c \
|
||||||
src/util/timeout.c \
|
|
||||||
src/util/tiger.c
|
src/util/tiger.c
|
||||||
|
|
||||||
libadc_common_SOURCES := \
|
|
||||||
src/adc/message.c \
|
|
||||||
src/adc/sid.c
|
|
||||||
|
|
||||||
libadc_client_SOURCES := \
|
libadc_client_SOURCES := \
|
||||||
src/tools/adcclient.c
|
src/tools/adcclient.c
|
||||||
|
|
||||||
uhub_SOURCES := src/core/main.c
|
uhub_SOURCES := src/core/main.c
|
||||||
|
|
||||||
|
uhub-passwd_SOURCES := src/tools/uhub-passwd.c
|
||||||
|
uhub-passwd_LIBS := -lsqlite3
|
||||||
|
|
||||||
adcrush_SOURCES := src/tools/adcrush.c
|
adcrush_SOURCES := src/tools/adcrush.c
|
||||||
|
|
||||||
admin_SOURCES := src/tools/admin.c
|
admin_SOURCES := src/tools/admin.c
|
||||||
|
|
||||||
autotest_SOURCES := \
|
autotest_SOURCES := \
|
||||||
autotest/test_message.tcc \
|
autotest/test_commands.tcc \
|
||||||
|
autotest/test_credentials.tcc \
|
||||||
|
autotest/test_eventqueue.tcc \
|
||||||
|
autotest/test_hub.tcc \
|
||||||
|
autotest/test_inf.tcc \
|
||||||
|
autotest/test_ipfilter.tcc \
|
||||||
autotest/test_list.tcc \
|
autotest/test_list.tcc \
|
||||||
autotest/test_memory.tcc \
|
autotest/test_memory.tcc \
|
||||||
autotest/test_ipfilter.tcc \
|
autotest/test_message.tcc \
|
||||||
autotest/test_inf.tcc \
|
|
||||||
autotest/test_hub.tcc \
|
|
||||||
autotest/test_misc.tcc \
|
autotest/test_misc.tcc \
|
||||||
|
autotest/test_sid.tcc \
|
||||||
autotest/test_tiger.tcc \
|
autotest/test_tiger.tcc \
|
||||||
autotest/test_usermanager.tcc \
|
autotest/test_timer.tcc \
|
||||||
autotest/test_eventqueue.tcc
|
autotest/test_tokenizer.tcc \
|
||||||
|
autotest/test_usermanager.tcc
|
||||||
|
|
||||||
autotest_OBJECTS = autotest.o
|
autotest_OBJECTS = autotest.o
|
||||||
|
|
||||||
|
# Plugin targets:
|
||||||
|
plugin_example_SOURCES := src/plugins/mod_example.c
|
||||||
|
plugin_example_TARGET := mod_example.so
|
||||||
|
|
||||||
|
plugin_welcome_SOURCES := src/plugins/mod_welcome.c
|
||||||
|
plugin_welcome_TARGET := mod_welcome.so
|
||||||
|
|
||||||
|
plugin_logging_SOURCES := src/plugins/mod_logging.c
|
||||||
|
plugin_logging_TARGET := mod_logging.so
|
||||||
|
|
||||||
|
plugin_auth_SOURCES := src/plugins/mod_auth_simple.c
|
||||||
|
plugin_auth_TARGET := mod_auth_simple.so
|
||||||
|
|
||||||
|
plugin_auth_sqlite_SOURCES := src/plugins/mod_auth_sqlite.c
|
||||||
|
plugin_auth_sqlite_TARGET := mod_auth_sqlite.so
|
||||||
|
plugin_auth_sqlite_LIBS := -lsqlite3
|
||||||
|
|
||||||
|
plugin_chat_history_SOURCE := src/plugins/mod_chat_history.c
|
||||||
|
plugin_chat_history_TARGET := mod_chat_history.so
|
||||||
|
|
||||||
|
plugin_chat_only_SOURCE := src/plugins/mod_chat_only.c
|
||||||
|
plugin_chat_only_TARGET := mod_chat_only.so
|
||||||
|
|
||||||
# Source to objects
|
# Source to objects
|
||||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||||
|
libutils_OBJECTS := $(libutils_SOURCES:.c=.o)
|
||||||
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
||||||
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
|
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
|
||||||
|
|
||||||
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
||||||
|
uhub-passwd_OBJECTS := $(uhub-passwd_SOURCES:.c=.o)
|
||||||
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
||||||
admin_OBJECTS := $(admin_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) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET) $(plugin_welcome_TARGET) $(plugin_chat_history_TARGET) $(plugin_chat_only_TARGET)
|
||||||
|
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
|
all_OBJECTS += $(all_plugins)
|
||||||
|
|
||||||
uhub_BINARY=uhub$(BIN_EXT)
|
uhub_BINARY=uhub$(BIN_EXT)
|
||||||
|
uhub-passwd_BINARY=uhub-passwd$(BIN_EXT)
|
||||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
adcrush_BINARY=adcrush$(BIN_EXT)
|
||||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
admin_BINARY=uhub-admin$(BIN_EXT)
|
||||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
autotest_BINARY=autotest/test$(BIN_EXT)
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
all: $(uhub_BINARY)
|
.PHONY: revision.h.tmp all plugins
|
||||||
|
|
||||||
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
%.o: %.c version.h revision.h
|
||||||
|
$(MSG_CC) $(CC) -fPIC -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
#%.so: %.c
|
||||||
|
# $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
all: $(uhub_BINARY) $(uhub-passwd_BINARY) plugins
|
||||||
|
|
||||||
|
plugins: $(uhub_BINARY) $(all_plugins)
|
||||||
|
|
||||||
|
$(plugin_auth_TARGET): $(plugin_auth_SOURCES) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(plugin_auth_sqlite_TARGET): $(plugin_auth_sqlite_SOURCES) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(LDFLAGS) $(plugin_auth_sqlite_LIBS)
|
||||||
|
|
||||||
|
$(plugin_example_TARGET): $(plugin_example_SOURCES) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(plugin_logging_TARGET): $(plugin_logging_SOURCES) $(libutils_OBJECTS) $(libadc_common_OBJECTS) src/network/network.o
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(plugin_chat_history_TARGET): $(plugin_chat_history_SOURCE) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(plugin_chat_only_TARGET): $(plugin_chat_only_SOURCE) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(plugin_welcome_TARGET): $(plugin_welcome_SOURCES) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
|
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
|
$(uhub-passwd_BINARY): $(uhub-passwd_OBJECTS)
|
||||||
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(uhub-passwd_LIBS)
|
||||||
|
|
||||||
|
|
||||||
autotest.c: $(autotest_SOURCES)
|
autotest.c: $(autotest_SOURCES)
|
||||||
$(shell exotic --standalone $(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
|
$(autotest_OBJECTS): autotest.c
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
||||||
|
|
||||||
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
autotest: $(autotest_BINARY)
|
autotest: $(autotest_BINARY)
|
||||||
@@ -222,9 +333,13 @@ else
|
|||||||
install: $(uhub_BINARY)
|
install: $(uhub_BINARY)
|
||||||
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
|
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
|
||||||
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
|
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
|
||||||
|
@cp $(uhub-passwd_BINARY) $(UHUB_PREFIX)/bin/
|
||||||
@if [ ! -d $(UHUB_CONF_DIR) ]; then echo Creating $(UHUB_CONF_DIR); mkdir -p $(UHUB_CONF_DIR); fi
|
@if [ ! -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)/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
|
@if [ ! -f $(UHUB_CONF_DIR)/rules.txt ]; then cp doc/rules.txt $(UHUB_CONF_DIR); fi
|
||||||
|
@if [ ! -f $(UHUB_CONF_DIR)/plugins.conf ]; then cp doc/plugins.conf $(UHUB_CONF_DIR); fi
|
||||||
|
@if [ ! -d $(UHUB_MOD_DIR) ]; then echo Creating $(UHUB_MOD_DIR); mkdir -p $(UHUB_MOD_DIR); fi
|
||||||
|
@cp -f mod_*.so $(UHUB_MOD_DIR)
|
||||||
@touch $(UHUB_CONF_DIR)/motd.txt
|
@touch $(UHUB_CONF_DIR)/motd.txt
|
||||||
@echo done.
|
@echo done.
|
||||||
endif
|
endif
|
||||||
@@ -233,7 +348,7 @@ dist-clean:
|
|||||||
@rm -rf $(all_OBJECTS) *~ core
|
@rm -rf $(all_OBJECTS) *~ core
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c && \
|
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) $(all_plugins) autotest.c revision.h revision.h.tmp && \
|
||||||
echo $(MSG_CLEAN)
|
echo $(MSG_CLEAN)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
5
README
5
README
@@ -1,5 +1,8 @@
|
|||||||
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.extatic.org/uhub/
|
http://www.uhub.org/
|
||||||
|
|
||||||
|
For a list of compatible ADC clients, see:
|
||||||
|
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software
|
||||||
|
|
||||||
|
|||||||
146
autotest/test_commands.tcc
Normal file
146
autotest/test_commands.tcc
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
static struct hub_info* hub = 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);
|
||||||
|
return cbase && hub && uman_init(hub) == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
|
||||||
|
{
|
||||||
|
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->description = "exotic";
|
||||||
|
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", "n", 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, &user, str);
|
||||||
|
enum command_parse_status status = cmd->status;
|
||||||
|
command_free(cmd);
|
||||||
|
return status == expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, &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); });
|
||||||
|
|
||||||
|
EXO_TEST(command_destroy, {
|
||||||
|
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;
|
||||||
|
});
|
||||||
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); });
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ EXO_TEST(hub_net_startup, {
|
|||||||
|
|
||||||
EXO_TEST(hub_config_initialize, {
|
EXO_TEST(hub_config_initialize, {
|
||||||
config_defaults(&g_config);
|
config_defaults(&g_config);
|
||||||
g_config.server_port = 15111;
|
g_config.server_port = 65111;
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ static void inf_create_user()
|
|||||||
{
|
{
|
||||||
if (inf_user) return;
|
if (inf_user) return;
|
||||||
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||||
inf_user->connection = net_con_create();
|
|
||||||
inf_user->id.sid = 1;
|
inf_user->id.sid = 1;
|
||||||
inf_user->limits.upload_slots = 1;
|
inf_user->limits.upload_slots = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_2, {
|
EXO_TEST(test_message_refc_2, {
|
||||||
return g_msg->references == 0; // 0
|
return g_msg->references == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_3, {
|
EXO_TEST(test_message_refc_3, {
|
||||||
adc_msg_incref(g_msg);
|
adc_msg_incref(g_msg);
|
||||||
return g_msg->references == 1; // 1
|
return g_msg->references == 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_4, {
|
EXO_TEST(test_message_refc_4, {
|
||||||
adc_msg_incref(g_msg);
|
adc_msg_incref(g_msg);
|
||||||
return g_msg->references == 2; // 2
|
return g_msg->references == 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_5, {
|
EXO_TEST(test_message_refc_5, {
|
||||||
adc_msg_free(g_msg);
|
adc_msg_free(g_msg);
|
||||||
return g_msg->references == 1; // 1
|
return g_msg->references == 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_6, {
|
EXO_TEST(test_message_refc_6, {
|
||||||
adc_msg_free(g_msg);
|
adc_msg_free(g_msg);
|
||||||
return g_msg->references == 0; // 0
|
return g_msg->references == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(test_message_refc_7, {
|
EXO_TEST(test_message_refc_7, {
|
||||||
|
|||||||
138
autotest/test_sid.tcc
Normal file
138
autotest/test_sid.tcc
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
static struct sid_pool* sid_pool = 0;
|
||||||
|
|
||||||
|
struct dummy_user
|
||||||
|
{
|
||||||
|
sid_t sid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dummy_user* last = 0;
|
||||||
|
sid_t last_sid = 0;
|
||||||
|
|
||||||
|
EXO_TEST(sid_create_pool, {
|
||||||
|
sid_pool = sid_pool_create(4);
|
||||||
|
return sid_pool != 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_0a, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_0b, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_1, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last = user;
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_1a, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last == user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_1b, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_2, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_2, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last != user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_3, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_3, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last != user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_4, {
|
||||||
|
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||||
|
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||||
|
last_sid = user->sid;
|
||||||
|
return (user->sid > 0 && user->sid < 1048576);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_4, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||||
|
return last != user;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_alloc_5, {
|
||||||
|
struct dummy_user user;
|
||||||
|
sid_t sid;
|
||||||
|
sid = sid_alloc(sid_pool, (struct hub_user*) &user);
|
||||||
|
return sid == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_check_6, {
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
|
||||||
|
return user == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(sid_list_all_1, {
|
||||||
|
sid_t s;
|
||||||
|
size_t n = 0;
|
||||||
|
int ok = 1;
|
||||||
|
for (s = last->sid; s <= last_sid; s++)
|
||||||
|
{
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s);
|
||||||
|
if (s != (user ? user->sid : -1))
|
||||||
|
{
|
||||||
|
ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return ok && n == 4;
|
||||||
|
});
|
||||||
|
|
||||||
|
#define FREE_SID(N) \
|
||||||
|
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \
|
||||||
|
sid_free(sid_pool, N); \
|
||||||
|
hub_free(user); \
|
||||||
|
return sid_lookup(sid_pool, N) == NULL;
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_1, {
|
||||||
|
FREE_SID(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_2, {
|
||||||
|
FREE_SID(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_3, {
|
||||||
|
FREE_SID(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_remove_4, {
|
||||||
|
FREE_SID(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(sid_destroy_pool, {
|
||||||
|
sid_pool_destroy(sid_pool);
|
||||||
|
sid_pool = 0;
|
||||||
|
return sid_pool == 0;
|
||||||
|
});
|
||||||
119
autotest/test_timer.tcc
Normal file
119
autotest/test_timer.tcc
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#include <uhub.h>
|
||||||
|
|
||||||
|
#define MAX_EVENTS 15
|
||||||
|
static struct timeout_queue* g_queue;
|
||||||
|
static time_t g_now;
|
||||||
|
static size_t g_max;
|
||||||
|
static struct timeout_evt g_events[MAX_EVENTS];
|
||||||
|
|
||||||
|
static size_t g_triggered;
|
||||||
|
|
||||||
|
static void timeout_cb(struct timeout_evt* t)
|
||||||
|
{
|
||||||
|
g_triggered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef void (*timeout_evt_cb)(struct timeout_evt*);
|
||||||
|
|
||||||
|
struct timeout_evt
|
||||||
|
{
|
||||||
|
time_t timestamp;
|
||||||
|
timeout_evt_cb callback;
|
||||||
|
void* ptr;
|
||||||
|
struct timeout_evt* prev;
|
||||||
|
struct timeout_evt* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
|
||||||
|
void timeout_evt_reset(struct timeout_evt*);
|
||||||
|
int timeout_evt_is_scheduled(struct timeout_evt*);
|
||||||
|
|
||||||
|
|
||||||
|
struct timeout_queue
|
||||||
|
{
|
||||||
|
time_t last;
|
||||||
|
size_t max;
|
||||||
|
struct timeout_evt** events;
|
||||||
|
};
|
||||||
|
|
||||||
|
void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
|
||||||
|
void timeout_queue_shutdown(struct timeout_queue*);
|
||||||
|
size_t timeout_queue_process(struct timeout_queue*, time_t now);
|
||||||
|
void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
|
||||||
|
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
|
||||||
|
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
|
||||||
|
|
||||||
|
size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(timer_setup,{
|
||||||
|
size_t n;
|
||||||
|
g_queue = hub_malloc_zero(sizeof(struct timeout_queue));
|
||||||
|
g_now = 0;
|
||||||
|
g_max = 5;
|
||||||
|
g_triggered = 0;
|
||||||
|
timeout_queue_initialize(g_queue, g_now, g_max);
|
||||||
|
|
||||||
|
memset(g_events, 0, sizeof(g_events));
|
||||||
|
for (n = 0; n < MAX_EVENTS; n++)
|
||||||
|
{
|
||||||
|
timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_queue != NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_timeout_0,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
EXO_TEST(timer_add_event_1,{
|
||||||
|
timeout_queue_insert(g_queue, &g_events[0], 2);
|
||||||
|
return g_events[0].prev != NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_timeout_1,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == 2;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_remove_event_1,{
|
||||||
|
timeout_queue_remove(g_queue, &g_events[0]);
|
||||||
|
return g_events[0].prev == NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_timeout_2,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* test re-removing an event - should not crash! */
|
||||||
|
EXO_TEST(timer_remove_event_1_no_crash,{
|
||||||
|
timeout_queue_remove(g_queue, &g_events[0]);
|
||||||
|
return g_events[0].prev == NULL;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_add_5_events_1,{
|
||||||
|
timeout_queue_insert(g_queue, &g_events[0], 0);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[1], 1);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[2], 2);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[3], 3);
|
||||||
|
timeout_queue_insert(g_queue, &g_events[4], 4);
|
||||||
|
|
||||||
|
return (g_events[0].prev != NULL &&
|
||||||
|
g_events[1].prev != NULL &&
|
||||||
|
g_events[2].prev != NULL &&
|
||||||
|
g_events[3].prev != NULL &&
|
||||||
|
g_events[4].prev != NULL);
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_check_5_events_1,{
|
||||||
|
return timeout_queue_get_next_timeout(g_queue, g_now) == 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
EXO_TEST(timer_process_5_events_1,{
|
||||||
|
g_now = 4;
|
||||||
|
return timeout_queue_process(g_queue, g_now) == g_triggered;
|
||||||
|
});
|
||||||
107
autotest/test_tokenizer.tcc
Normal file
107
autotest/test_tokenizer.tcc
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#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;
|
||||||
|
for (i = 0; i < strlen(str2); i++)
|
||||||
|
if (str2[i] == '_')
|
||||||
|
str2[i] = ' ';
|
||||||
|
else if (str2[i] == '|')
|
||||||
|
str2[i] = '\t';
|
||||||
|
|
||||||
|
int 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;
|
||||||
|
struct linked_list* compare = list_create();
|
||||||
|
SETUP(tokens, str);
|
||||||
|
split_string(ref, " ", compare, 0);
|
||||||
|
int 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, ""); });
|
||||||
|
|
||||||
|
|
||||||
25
debian/changelog
vendored
Normal file
25
debian/changelog
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
uhub (0.3.2-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Updated upstream version.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Mon 30 May 2010 18:00:00 +0200
|
||||||
|
|
||||||
|
uhub (0.3.1-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Updated version number.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200
|
||||||
|
|
||||||
|
uhub (0.3.0-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fixed init.d scripts.
|
||||||
|
* Fixed lintian warnings.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 19:02:02 +0100
|
||||||
|
|
||||||
|
uhub (0.3.0-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Initial Release.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 18:59:02 +0100
|
||||||
|
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
7
|
||||||
24
debian/control
vendored
Normal file
24
debian/control
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Source: uhub
|
||||||
|
Section: net
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
|
||||||
|
Build-Depends: debhelper (>= 7.0.0)
|
||||||
|
Standards-Version: 3.8.3.0
|
||||||
|
|
||||||
|
Package: uhub
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}
|
||||||
|
Description: High performance ADC p2p hub
|
||||||
|
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||||
|
Its low memory footprint allows it to handle several thousand users on
|
||||||
|
high-end servers, or a small private hub on embedded hardware.
|
||||||
|
.
|
||||||
|
Key features:
|
||||||
|
- High performance and low memory usage
|
||||||
|
- IPv4 and IPv6 support
|
||||||
|
- Experimental SSL support (optional)
|
||||||
|
- Advanced access control support
|
||||||
|
- Easy configuration
|
||||||
|
.
|
||||||
|
Homepage: http://www.uhub.org/
|
||||||
|
|
||||||
19
debian/copyright
vendored
Normal file
19
debian/copyright
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
uhub - High performance ADC p2p hub.
|
||||||
|
Copyright (C) 2010 Jan Vidar Krey <janvidar@extatic.org>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||||
|
License can be found in `/usr/share/common-licenses/GPL'.
|
||||||
|
|
||||||
45
debian/rules
vendored
Executable file
45
debian/rules
vendored
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
# export DH_VERBOSE=1
|
||||||
|
|
||||||
|
makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \
|
||||||
|
UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \
|
||||||
|
RELEASE=YES SILENT=YES
|
||||||
|
|
||||||
|
build: build-stamp
|
||||||
|
build-stamp:
|
||||||
|
dh_testdir
|
||||||
|
make $(makeopts)
|
||||||
|
touch build-stamp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
rm -f build-stamp
|
||||||
|
make clean
|
||||||
|
dh_clean
|
||||||
|
|
||||||
|
binary-indep: build
|
||||||
|
|
||||||
|
binary-arch: build
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
dh_clean -k
|
||||||
|
dh_installdirs
|
||||||
|
$(MAKE) install $(makeopts)
|
||||||
|
dh_installdocs
|
||||||
|
dh_installinit
|
||||||
|
dh_installlogrotate
|
||||||
|
dh_installman -A
|
||||||
|
dh_installchangelogs ChangeLog
|
||||||
|
dh_strip
|
||||||
|
dh_compress
|
||||||
|
dh_installdeb
|
||||||
|
dh_shlibdeps
|
||||||
|
dh_gencontrol
|
||||||
|
dh_md5sums
|
||||||
|
dh_builddeb
|
||||||
|
|
||||||
|
binary: binary-indep binary-arch
|
||||||
|
.PHONY: build clean binary-indep binary-arch binary
|
||||||
|
|
||||||
4
debian/uhub.default
vendored
Normal file
4
debian/uhub.default
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# uhub - high performance adc hub.
|
||||||
|
|
||||||
|
UHUB_ENABLE=0
|
||||||
|
|
||||||
6
debian/uhub.dirs
vendored
Normal file
6
debian/uhub.dirs
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
etc/default
|
||||||
|
etc/init.d
|
||||||
|
etc/logrotate.d
|
||||||
|
etc/uhub
|
||||||
|
usr/bin
|
||||||
|
var/log/uhub
|
||||||
5
debian/uhub.docs
vendored
Normal file
5
debian/uhub.docs
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
AUTHORS
|
||||||
|
README
|
||||||
|
BUGS
|
||||||
|
TODO
|
||||||
|
doc/getstarted.txt
|
||||||
92
debian/uhub.init
vendored
Normal file
92
debian/uhub.init
vendored
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: uhub
|
||||||
|
# Required-Start: $remote_fs $network
|
||||||
|
# Required-Stop: $remote_fs $network
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: uhub - High performance ADC p2p hub.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||||
|
|
||||||
|
NAME=uhub
|
||||||
|
DESC="ADC hub"
|
||||||
|
DAEMON=/usr/bin/uhub
|
||||||
|
PIDFILE=/var/run/uhub/uhub.pid
|
||||||
|
LOGFILE=/var/log/uhub/uhub.log
|
||||||
|
SCRIPTNAME=/etc/init.d/uhub
|
||||||
|
|
||||||
|
DEFAULTFILE=/etc/default/uhub
|
||||||
|
[ -r $DEFAULTFILE ] && . $DEFAULTFILE
|
||||||
|
|
||||||
|
DAEMON_ENABLE="${UHUB_ENABLE}"
|
||||||
|
DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}"
|
||||||
|
|
||||||
|
test -x $DAEMON || exit 0
|
||||||
|
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
ulimit -n 65536
|
||||||
|
mkdir -p /var/run/uhub/
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
if [ "$DAEMON_ENABLE" != "true" ]; then
|
||||||
|
log_daemon_msg "Disabled $DESC" $NAME
|
||||||
|
log_end_msg 0
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_daemon_msg "Starting $DESC" $NAME
|
||||||
|
if ! start-stop-daemon --start --quiet --oknodo \
|
||||||
|
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
|
||||||
|
then
|
||||||
|
log_end_msg 1
|
||||||
|
else
|
||||||
|
log_end_msg 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
log_daemon_msg "Stopping $DESC" $NAME
|
||||||
|
if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \
|
||||||
|
--pidfile $PIDFILE --exec $DAEMON
|
||||||
|
then
|
||||||
|
rm -f $PIDFILE
|
||||||
|
log_end_msg 0
|
||||||
|
else
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
reload)
|
||||||
|
log_daemon_msg "Reloading $DESC configuration" $NAME
|
||||||
|
if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \
|
||||||
|
--quiet --pidfile $PIDFILE --exec $DAEMON
|
||||||
|
then
|
||||||
|
if start-stop-daemon --start --quiet \
|
||||||
|
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then
|
||||||
|
log_end_msg 0
|
||||||
|
else
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart|force-reload)
|
||||||
|
$0 stop
|
||||||
|
$0 start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
9
debian/uhub.logrotate
vendored
Normal file
9
debian/uhub.logrotate
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/var/log/uhub/*.log
|
||||||
|
{
|
||||||
|
compress
|
||||||
|
size 10M
|
||||||
|
rotate 10
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
}
|
||||||
|
|
||||||
1
debian/uhub.manpages
vendored
Normal file
1
debian/uhub.manpages
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
doc/uhub.1
|
||||||
27
debian/uhub.postinst
vendored
Normal file
27
debian/uhub.postinst
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
configure)
|
||||||
|
chmod 0750 /var/log/uhub
|
||||||
|
|
||||||
|
if [ -x /etc/init.d/uhub ]; then
|
||||||
|
update-rc.d uhub defaults >/dev/null
|
||||||
|
|
||||||
|
if [ -x /usr/sbin/invoke-rc.d ]; then
|
||||||
|
invoke-rc.d uhub restart
|
||||||
|
else
|
||||||
|
/etc/init.d/uhub restart
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
abort-upgrade|abort-remove|abort-deconfigure)
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "postinst: error: unknown argument: $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
6
debian/uhub.postrm
vendored
Normal file
6
debian/uhub.postrm
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if [ "$1" = purge ]; then
|
||||||
|
update-rc.d uhub remove >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
10
debian/uhub.prerm
vendored
Normal file
10
debian/uhub.prerm
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if [ "$1" = remove ]; then
|
||||||
|
if command -v invoke-rc.d >/dev/null 2>&1; then
|
||||||
|
invoke-rc.d uhub stop || true
|
||||||
|
else
|
||||||
|
/etc/init.d/uhub stop
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -8,19 +8,18 @@ Prerequisites
|
|||||||
Before you try to compile µHub, please make sure the following prerequisites are met.
|
Before you try to compile µHub, please make sure the following prerequisites are met.
|
||||||
* GNU make
|
* GNU make
|
||||||
* gcc > 3.0 (or MinGW on Windows)
|
* gcc > 3.0 (or MinGW on Windows)
|
||||||
* libevent >= 1.3
|
|
||||||
* Perl 5
|
* Perl 5
|
||||||
|
* openssl > 0.9.8 (or use "make USE_SSL=NO")
|
||||||
|
* sqlite > 3.x
|
||||||
|
|
||||||
Linux and Mac OSX
|
or read http://www.uhub.org/compile.php for more info.
|
||||||
-----------------
|
|
||||||
|
|
||||||
|
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
||||||
|
-------------------------------------------
|
||||||
Simply, run:
|
Simply, run:
|
||||||
% make
|
% make
|
||||||
|
|
||||||
FreeBSD, NetBSD and OpenBSD
|
|
||||||
---------------------------
|
|
||||||
Use GNU make, not BSD make:
|
|
||||||
% gmake
|
|
||||||
|
|
||||||
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
||||||
gmake USE_PCH=NO
|
gmake USE_PCH=NO
|
||||||
|
|
||||||
|
|||||||
@@ -43,4 +43,15 @@ 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.
|
||||||
|
This limit needs to be higher than the configured max_users in uhub.conf.
|
||||||
|
|
||||||
|
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
||||||
|
* soft nofile 4096
|
||||||
|
* hard nofile 4096
|
||||||
|
|
||||||
|
Or, you can use (as root):
|
||||||
|
% ulimit -n 4096
|
||||||
|
|
||||||
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 ( http://www.uhub.org ) daemons on RHEL\CentOS \
|
||||||
# used to provide p2p network services.
|
# used to provide p2p network services.
|
||||||
#
|
#
|
||||||
# pidfile: /var/run/uhub.pid
|
# pidfile: /var/run/uhub.pid
|
||||||
@@ -38,7 +38,7 @@ RETVAL=0
|
|||||||
|
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
KIND="UHUB"
|
KIND="Uhub"
|
||||||
echo -n $"Starting $KIND services: "
|
echo -n $"Starting $KIND services: "
|
||||||
daemon uhub $UHUBOPTIONS
|
daemon uhub $UHUBOPTIONS
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
@@ -47,7 +47,7 @@ start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
KIND="UHUB"
|
KIND="Uhub"
|
||||||
echo -n $"Shutting down $KIND services: "
|
echo -n $"Shutting down $KIND services: "
|
||||||
killproc uhub
|
killproc uhub
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
@@ -68,6 +68,14 @@ reload() {
|
|||||||
return $RETVAL
|
return $RETVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relog() {
|
||||||
|
echo -n $"Reopen main log file: "
|
||||||
|
killproc uhub -SIGHUP
|
||||||
|
RETVAL=$?
|
||||||
|
echo ""
|
||||||
|
return $RETVAL
|
||||||
|
}
|
||||||
|
|
||||||
rhstatus() {
|
rhstatus() {
|
||||||
status uhub
|
status uhub
|
||||||
RETVAL=$?
|
RETVAL=$?
|
||||||
@@ -90,11 +98,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
|
||||||
|
|
||||||
|
|||||||
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Log rotate for Uhub
|
||||||
|
# see man logrotate
|
||||||
|
#
|
||||||
|
#
|
||||||
|
/var/log/uhub.log {
|
||||||
|
compress
|
||||||
|
size 10M
|
||||||
|
rotate 10
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Log rotate for Uhub
|
|
||||||
# see man logrotate
|
|
||||||
#
|
|
||||||
#
|
|
||||||
/var/log/uhub.log {
|
|
||||||
compress
|
|
||||||
size 10M
|
|
||||||
rotate 10
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,5 @@
|
|||||||
# -u <user> Run as given user
|
# -u <user> Run as given user
|
||||||
# -g <group> Run with given group permissions
|
# -g <group> Run with given group permissions
|
||||||
# -p <file> Store pid in file (process id)
|
# -p <file> Store pid in file (process id)
|
||||||
|
|
||||||
|
|
||||||
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"
|
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"
|
||||||
|
|
||||||
|
|||||||
62
doc/plugins.conf
Normal file
62
doc/plugins.conf
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# 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 /var/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
|
||||||
|
|
||||||
|
|
||||||
|
# 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 /var/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
|
||||||
|
|
||||||
|
# A simple example plugin
|
||||||
|
# plugin /var/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/filenam for the rules file
|
||||||
|
#
|
||||||
|
# NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted.
|
||||||
|
#
|
||||||
|
# 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 /var/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 /var/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5"
|
||||||
|
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -13,12 +13,18 @@
|
|||||||
server_port=1511
|
server_port=1511
|
||||||
server_bind_addr=any
|
server_bind_addr=any
|
||||||
|
|
||||||
|
# Alternative server ports
|
||||||
|
# server_alt_ports = 1512, 1513
|
||||||
|
|
||||||
# The maximum amount of users allowed on the hub.
|
# The maximum amount of users allowed on the hub.
|
||||||
max_users=500
|
max_users=500
|
||||||
|
|
||||||
# If 1, will show a "This hub is running uhub/version".
|
# If 1, will show a "Powered by uHub/{VERSION}".
|
||||||
show_banner=1
|
show_banner=1
|
||||||
|
|
||||||
|
# If enabled then operating system and cpu architecture is part of the banner.
|
||||||
|
show_banner_sys_info=1
|
||||||
|
|
||||||
# Allow only registered users on the hub if set to 1.
|
# Allow only registered users on the hub if set to 1.
|
||||||
registered_users_only=0
|
registered_users_only=0
|
||||||
|
|
||||||
@@ -43,8 +49,10 @@ file_motd=/etc/uhub/motd.txt
|
|||||||
# Normally this message is sent to clients when write in chat !rules
|
# Normally this message is sent to clients when write in chat !rules
|
||||||
file_rules=/etc/uhub/rules.txt
|
file_rules=/etc/uhub/rules.txt
|
||||||
|
|
||||||
|
# This file can contain a conf for plugin subsystem
|
||||||
|
file_plugins = /etc/uhub/plugins.conf
|
||||||
|
|
||||||
# Slots\share\hubs limits
|
# Slots/share/hubs limits
|
||||||
limit_max_hubs_user = 0
|
limit_max_hubs_user = 0
|
||||||
limit_max_hubs_reg = 0
|
limit_max_hubs_reg = 0
|
||||||
limit_max_hubs_op = 0
|
limit_max_hubs_op = 0
|
||||||
@@ -60,6 +68,27 @@ limit_max_share = 0
|
|||||||
limit_min_slots = 0
|
limit_min_slots = 0
|
||||||
limit_max_slots = 0
|
limit_max_slots = 0
|
||||||
|
|
||||||
|
# Flood control support:
|
||||||
|
# set the interval to 5 seconds
|
||||||
|
flood_ctl_interval = 5
|
||||||
|
|
||||||
|
# Then the maximum chat, connect, search, updates etc will be measured over 5 seconds.
|
||||||
|
# So, 3 chat messages per 5 seconds allowed.
|
||||||
|
flood_ctl_chat=3
|
||||||
|
flood_ctl_connect=20
|
||||||
|
flood_ctl_search=1
|
||||||
|
flood_ctl_update=2
|
||||||
|
flood_ctl_extras=5
|
||||||
|
|
||||||
|
# chat control
|
||||||
|
# if chat_is_privileged=yes only registered users may write in main chat
|
||||||
|
chat_is_privileged = no
|
||||||
|
|
||||||
|
|
||||||
|
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
|
||||||
|
# defaults obsolete_clients=1
|
||||||
|
obsolete_clients=1
|
||||||
|
|
||||||
|
|
||||||
# Configure status message as sent to clients in different circumstances.
|
# Configure status message as sent to clients in different circumstances.
|
||||||
msg_hub_full = Hub is full
|
msg_hub_full = Hub is full
|
||||||
@@ -91,5 +120,16 @@ msg_user_slots_high = User have too many upload slots
|
|||||||
msg_user_hub_limit_low = User is on too few hubs
|
msg_user_hub_limit_low = User is on too few hubs
|
||||||
msg_user_hub_limit_high = User is on too many hubs
|
msg_user_hub_limit_high = User is on too many hubs
|
||||||
msg_error_no_memory = No memory
|
msg_error_no_memory = No memory
|
||||||
|
msg_user_flood_chat = Chat flood detected, messages are dropped.
|
||||||
|
msg_user_flood_connect = Connect flood detected, connection refused.
|
||||||
|
msg_user_flood_search = Search flood detected, search is stopped.
|
||||||
|
msg_user_flood_update = Update flood detected.
|
||||||
|
msg_user_flood_extras = Flood detected.
|
||||||
|
|
||||||
|
# If a client that supports ADC but not a compatible hash algorithm (tiger),
|
||||||
|
# then the hub cannot accept the client:
|
||||||
|
msg_proto_no_common_hash = No common hash algorithm.
|
||||||
|
|
||||||
|
# Message to be shown to old clients using an older version of ADC than ADC/1.0
|
||||||
|
msg_proto_obsolete_adc0 = Client is using an obsolete ADC protocol version.
|
||||||
|
|
||||||
|
|||||||
42
doc/uhub.ebuild
Normal file
42
doc/uhub.ebuild
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Copyright 1999-2010 Gentoo Foundation
|
||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
# $Header: $
|
||||||
|
inherit eutils
|
||||||
|
|
||||||
|
if [ "$PV" != "9999" ]; then
|
||||||
|
SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
|
||||||
|
KEYWORDS="~amd64 ~x86"
|
||||||
|
else
|
||||||
|
inherit git
|
||||||
|
SRC_URI=""
|
||||||
|
EGIT_REPO_URI="git://github.com/janvidar/uhub.git"
|
||||||
|
KEYWORDS=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
EAPI="2"
|
||||||
|
|
||||||
|
DESCRIPTION="High performance ADC hub"
|
||||||
|
HOMEPAGE="http://www.uhub.org/"
|
||||||
|
|
||||||
|
LICENSE="GPL-3"
|
||||||
|
SLOT="0"
|
||||||
|
IUSE="+ssl"
|
||||||
|
|
||||||
|
DEPEND="=dev-lang/perl-5*
|
||||||
|
ssl? ( >=dev-libs/openssl-0.9.8 )
|
||||||
|
"
|
||||||
|
RDEPEND="${DEPEND}"
|
||||||
|
src_compile() {
|
||||||
|
$opts=""
|
||||||
|
use ssl && opts="USE_SSL=YES $opts"
|
||||||
|
emake $opts
|
||||||
|
}
|
||||||
|
src_install() {
|
||||||
|
dodir /usr/bin
|
||||||
|
dodir /etc/uhub
|
||||||
|
emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed"
|
||||||
|
newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub
|
||||||
|
}
|
||||||
|
pkg_postinst() {
|
||||||
|
enewuser uhub
|
||||||
|
}
|
||||||
102
doc/uhub.spec
Normal file
102
doc/uhub.spec
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
Summary: High performance ADC p2p hub.
|
||||||
|
Name: uhub
|
||||||
|
Version: 0.4.0
|
||||||
|
Release: 2
|
||||||
|
License: GPLv3
|
||||||
|
Group: Networking/File transfer
|
||||||
|
Source: uhub-%{version}.tar.gz
|
||||||
|
URL: http://www.uhub.org
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||||
|
|
||||||
|
BuildRequires: sqlite-devel
|
||||||
|
BuildRequires: openssl-devel
|
||||||
|
|
||||||
|
%description
|
||||||
|
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||||
|
Its low memory footprint allows it to handle several thousand users on
|
||||||
|
high-end servers, or a small private hub on embedded hardware.
|
||||||
|
|
||||||
|
Key features:
|
||||||
|
- High performance and low memory usage
|
||||||
|
- IPv4 and IPv6 support
|
||||||
|
- Experimental SSL support (optional)
|
||||||
|
- Advanced access control support
|
||||||
|
- Easy configuration
|
||||||
|
- plugin support
|
||||||
|
- mod_welcome - MOTD\RULES messages
|
||||||
|
- mod_auth_sipmle - auth with sqlite DB
|
||||||
|
- mod_logging - log hub activity
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q -n %{name}-%{version}
|
||||||
|
|
||||||
|
%build
|
||||||
|
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
|
||||||
|
make
|
||||||
|
|
||||||
|
%install
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/uhub
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/var/lib/uhub
|
||||||
|
|
||||||
|
install uhub $RPM_BUILD_ROOT/usr/bin/
|
||||||
|
install uhub-passwd $RPM_BUILD_ROOT/usr/bin/
|
||||||
|
> doc/motd.txt
|
||||||
|
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt doc/plugins.conf doc/users.db $RPM_BUILD_ROOT/etc/uhub
|
||||||
|
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
||||||
|
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
||||||
|
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
||||||
|
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
||||||
|
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
||||||
|
install -m644 mod_*.so $RPM_BUILD_ROOT/var/lib/uhub
|
||||||
|
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
|
||||||
|
%config(noreplace) /etc/uhub/uhub.conf
|
||||||
|
#%{_sysconfdir}/uhub/uhub.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/plugins.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/users.db
|
||||||
|
%{_sysconfdir}/init.d/uhub
|
||||||
|
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
||||||
|
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
||||||
|
/usr/share/man/man1/uhub.1.gz
|
||||||
|
%{_bindir}/uhub
|
||||||
|
%{_libdir}/uhub/mod_*.so
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
%post
|
||||||
|
/sbin/chkconfig --add uhub
|
||||||
|
if [ $1 -gt 1 ] ; then
|
||||||
|
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
||||||
|
fi
|
||||||
|
# need more informations about add services and users in system
|
||||||
|
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
||||||
|
# write SSL create
|
||||||
|
echo "PLS see /usr/share/doc/uhub/"
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Fri Dec 30 2011 E_zombie
|
||||||
|
- add users.db
|
||||||
|
- add new doc
|
||||||
|
* Tue Jun 26 2010 E_zombie
|
||||||
|
- add plugins.conf
|
||||||
|
* Tue Jan 31 2010 E_zombie
|
||||||
|
- change GROUP
|
||||||
|
- chmod for files
|
||||||
|
- add postinstall scripts
|
||||||
|
- fix "License"
|
||||||
|
* Tue Jan 26 2010 E_zombie
|
||||||
|
- first .spec release
|
||||||
|
|
||||||
|
|
||||||
@@ -20,7 +20,11 @@
|
|||||||
#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 */
|
||||||
@@ -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')
|
||||||
|
|||||||
@@ -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-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,7 +26,9 @@
|
|||||||
uhub_assert(X->capacity); \
|
uhub_assert(X->capacity); \
|
||||||
uhub_assert(X->length); \
|
uhub_assert(X->length); \
|
||||||
uhub_assert(X->length <= X->capacity); \
|
uhub_assert(X->length <= X->capacity); \
|
||||||
|
uhub_assert(X->references > 0); \
|
||||||
uhub_assert(X->length == strlen(X->cache));
|
uhub_assert(X->length == strlen(X->cache));
|
||||||
|
#define ADC_MSG_NULL_ON_FREE
|
||||||
#else
|
#else
|
||||||
#define ADC_MSG_ASSERT(X) do { } while(0)
|
#define ADC_MSG_ASSERT(X) do { } while(0)
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
@@ -53,40 +55,18 @@ static void* msg_malloc_zero(size_t size)
|
|||||||
static void msg_free(void* ptr)
|
static void msg_free(void* ptr)
|
||||||
{
|
{
|
||||||
LOG_MEMORY("msg_free: %p", ptr);
|
LOG_MEMORY("msg_free: %p", ptr);
|
||||||
// hub_free(ptr);
|
hub_free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
static void adc_msg_protect(struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
LOG_MEMORY("msg_prot: %p %d", cmd, cmd->capacity);
|
|
||||||
mprotect(cmd, sizeof(cmd), PROT_READ);
|
|
||||||
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adc_msg_unprotect(struct adc_message* cmd)
|
|
||||||
{
|
|
||||||
LOG_MEMORY("msg_unprot: %p %d", cmd, cmd->capacity);
|
|
||||||
mprotect(cmd, sizeof(cmd), PROT_READ | PROT_WRITE);
|
|
||||||
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ | PROT_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define msg_malloc(X) hub_malloc(X)
|
#define msg_malloc(X) hub_malloc(X)
|
||||||
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
||||||
#define msg_free(X) hub_free(X)
|
#define msg_free(X) hub_free(X)
|
||||||
|
|
||||||
#endif /* MSG_MEMORY_DEBUG */
|
#endif /* MSG_MEMORY_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||||
{
|
{
|
||||||
if (!msg) return 0;
|
|
||||||
#ifndef ADC_MESSAGE_INCREF
|
#ifndef ADC_MESSAGE_INCREF
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_unprotect(msg);
|
|
||||||
#endif
|
|
||||||
msg->references++;
|
msg->references++;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
#ifdef MSG_MEMORY_DEBUG
|
||||||
adc_msg_protect(msg);
|
adc_msg_protect(msg);
|
||||||
@@ -108,6 +88,9 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
|||||||
char* buf;
|
char* buf;
|
||||||
size_t newsize = 0;
|
size_t newsize = 0;
|
||||||
|
|
||||||
|
if (!msg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (msg->capacity > size)
|
if (msg->capacity > size)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -204,20 +187,15 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
|
|
||||||
ADC_MSG_ASSERT(msg);
|
ADC_MSG_ASSERT(msg);
|
||||||
|
|
||||||
if (msg->references > 0)
|
|
||||||
{
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_unprotect(msg);
|
|
||||||
#endif
|
|
||||||
msg->references--;
|
msg->references--;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(msg);
|
if (msg->references == 0)
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
#ifdef ADC_MSG_NULL_ON_FREE
|
||||||
adc_msg_unprotect(msg);
|
if (msg->cache)
|
||||||
|
{
|
||||||
|
*msg->cache = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
msg_free(msg->cache);
|
msg_free(msg->cache);
|
||||||
|
|
||||||
@@ -256,20 +234,24 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
copy->length = cmd->length;
|
copy->length = cmd->length;
|
||||||
copy->capacity = 0;
|
copy->capacity = 0;
|
||||||
copy->priority = cmd->priority;
|
copy->priority = cmd->priority;
|
||||||
copy->references = 0;
|
copy->references = 1;
|
||||||
copy->feature_cast_include = 0;
|
copy->feature_cast_include = 0;
|
||||||
copy->feature_cast_exclude = 0;
|
copy->feature_cast_exclude = 0;
|
||||||
|
|
||||||
if (cmd->cache)
|
|
||||||
{
|
|
||||||
if (!adc_msg_grow(copy, copy->length))
|
if (!adc_msg_grow(copy, copy->length))
|
||||||
{
|
{
|
||||||
adc_msg_free(copy);
|
adc_msg_free(copy);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!copy->cache)
|
||||||
|
{
|
||||||
|
adc_msg_free(copy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(copy->cache, cmd->cache, cmd->length);
|
memcpy(copy->cache, cmd->cache, cmd->length);
|
||||||
copy->cache[copy->length] = 0;
|
copy->cache[copy->length] = 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd->feature_cast_include)
|
if (cmd->feature_cast_include)
|
||||||
{
|
{
|
||||||
@@ -295,9 +277,6 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
|||||||
|
|
||||||
ADC_MSG_ASSERT(copy);
|
ADC_MSG_ASSERT(copy);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(copy);
|
|
||||||
#endif
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +339,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
||||||
command->priority = 0;
|
command->priority = 0;
|
||||||
|
command->references = 1;
|
||||||
|
|
||||||
switch (prefix)
|
switch (prefix)
|
||||||
{
|
{
|
||||||
@@ -443,7 +423,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
if (n == 10)
|
if (n == 10)
|
||||||
ok = 0;
|
ok = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
@@ -510,10 +489,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADC_MSG_ASSERT(command);
|
ADC_MSG_ASSERT(command);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(command);
|
|
||||||
#endif
|
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,7 +502,6 @@ struct adc_message* adc_msg_create(const char* line)
|
|||||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||||
{
|
{
|
||||||
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||||
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
@@ -554,11 +528,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
|||||||
|
|
||||||
msg->cmd = fourcc;
|
msg->cmd = fourcc;
|
||||||
msg->priority = 0;
|
msg->priority = 0;
|
||||||
|
msg->references = 1;
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(msg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,7 +600,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;
|
||||||
@@ -698,10 +668,6 @@ void adc_msg_terminate(struct adc_message* cmd)
|
|||||||
adc_msg_cache_append(cmd, "\n", 1);
|
adc_msg_cache_append(cmd, "\n", 1);
|
||||||
}
|
}
|
||||||
ADC_MSG_ASSERT(cmd);
|
ADC_MSG_ASSERT(cmd);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_protect(cmd);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: this looks bogus */
|
/* FIXME: this looks bogus */
|
||||||
@@ -709,10 +675,6 @@ void adc_msg_unterminate(struct adc_message* cmd)
|
|||||||
{
|
{
|
||||||
ADC_MSG_ASSERT(cmd);
|
ADC_MSG_ASSERT(cmd);
|
||||||
|
|
||||||
#ifdef MSG_MEMORY_DEBUG
|
|
||||||
adc_msg_unprotect(cmd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
||||||
{
|
{
|
||||||
cmd->length--;
|
cmd->length--;
|
||||||
@@ -794,7 +756,7 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
argument = hub_strdup(&start[1]);
|
argument = hub_strdup(&start[1]);
|
||||||
if (argument && argument[strlen(argument)-1] == '\n')
|
if (argument && *argument && argument[strlen(argument)-1] == '\n')
|
||||||
argument[strlen(argument)-1] = 0;
|
argument[strlen(argument)-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,9 +846,6 @@ int adc_msg_unescape_length(const char* str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* adc_msg_unescape(const char* string)
|
char* adc_msg_unescape(const char* string)
|
||||||
{
|
{
|
||||||
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
||||||
@@ -905,14 +864,12 @@ char* adc_msg_unescape(const char* string)
|
|||||||
*ptr++ = '\n';
|
*ptr++ = '\n';
|
||||||
else
|
else
|
||||||
*ptr++ = *str;
|
*ptr++ = *str;
|
||||||
|
|
||||||
escaped = 0;
|
escaped = 0;
|
||||||
} else {
|
} else {
|
||||||
if (*str == '\\')
|
if (*str == '\\')
|
||||||
escaped = 1;
|
escaped = 1;
|
||||||
else
|
else
|
||||||
*ptr++ = *str;
|
*ptr++ = *str;
|
||||||
|
|
||||||
}
|
}
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
@@ -924,8 +881,8 @@ char* adc_msg_unescape(const char* string)
|
|||||||
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-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -119,7 +119,16 @@ 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 = (++pool->count);
|
sid_t n;
|
||||||
|
if (pool->count >= (pool->max - pool->min))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_SID
|
||||||
|
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = (++pool->count);
|
||||||
for (; (pool->map[n % pool->max]); n++) ;
|
for (; (pool->map[n % pool->max]); n++) ;
|
||||||
|
|
||||||
#ifdef DEBUG_SID
|
#ifdef DEBUG_SID
|
||||||
@@ -140,7 +149,7 @@ void sid_free(struct sid_pool* pool, sid_t sid)
|
|||||||
|
|
||||||
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
|
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
|
||||||
{
|
{
|
||||||
if (!sid || (sid > pool->max))
|
if (!sid || (sid >= pool->max))
|
||||||
return 0;
|
return 0;
|
||||||
return pool->map[sid];
|
return pool->map[sid];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
156
src/core/auth.c
156
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-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -23,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;
|
||||||
@@ -130,7 +112,7 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
|||||||
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
||||||
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
LOG_DEBUG("ACL: Deny access for: %s-%s", buf1, buf2);
|
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
|
||||||
|
|
||||||
list_append(list, info);
|
list_append(list, info);
|
||||||
}
|
}
|
||||||
@@ -176,14 +158,10 @@ static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line,
|
|||||||
|
|
||||||
static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
{
|
{
|
||||||
char* pos;
|
|
||||||
struct acl_handle* handle = (struct acl_handle*) ptr_data;
|
struct acl_handle* handle = (struct acl_handle*) ptr_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((pos = strchr(line, '#')) != NULL)
|
strip_off_ini_line_comments(line, line_count);
|
||||||
{
|
|
||||||
pos[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
line = strip_white_space(line);
|
line = strip_white_space(line);
|
||||||
if (!*line)
|
if (!*line)
|
||||||
@@ -191,12 +169,12 @@ 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("user_admin", handle->users, auth_cred_admin);
|
||||||
ACL_ADD_USER("user_super", handle->users, cred_super);
|
ACL_ADD_USER("user_super", handle->users, auth_cred_super);
|
||||||
ACL_ADD_USER("user_op", handle->users, cred_operator);
|
ACL_ADD_USER("user_op", handle->users, auth_cred_operator);
|
||||||
ACL_ADD_USER("user_reg", handle->users, cred_user);
|
ACL_ADD_USER("user_reg", handle->users, auth_cred_user);
|
||||||
ACL_ADD_USER("link", handle->users, cred_link);
|
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);
|
||||||
@@ -247,11 +225,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,28 +281,56 @@ 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)
|
||||||
struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
|
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = (struct hub_user_access_info*) list_get_first(handle->users);
|
if (plugin_auth_register_user(hub, info) != st_allow)
|
||||||
while (info)
|
|
||||||
{
|
{
|
||||||
if (strcasecmp(info->username, name) == 0)
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int acl_update_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
if (plugin_auth_update_user(hub, info) != st_allow)
|
||||||
{
|
{
|
||||||
return info;
|
return 0;
|
||||||
}
|
}
|
||||||
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) \
|
||||||
char* str = (char*) list_get_first(LIST); \
|
str = (char*) list_get_first(LIST); \
|
||||||
while (str) \
|
while (str) \
|
||||||
{ \
|
{ \
|
||||||
if (strcasecmp(str, STR) == 0) \
|
if (strcasecmp(str, STR) == 0) \
|
||||||
@@ -337,38 +341,31 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
|
|||||||
|
|
||||||
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
||||||
{
|
{
|
||||||
|
char* str;
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
STR_LIST_CONTAINS(handle->cids, data);
|
STR_LIST_CONTAINS(handle->cids, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
||||||
{
|
{
|
||||||
|
char* str;
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
STR_LIST_CONTAINS(handle->users_banned, data);
|
STR_LIST_CONTAINS(handle->users_banned, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
||||||
{
|
{
|
||||||
|
char* str;
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
STR_LIST_CONTAINS(handle->users_denied, data);
|
STR_LIST_CONTAINS(handle->users_denied, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
||||||
{
|
{
|
||||||
char* data = 0;
|
char* data = hub_strdup(nick);
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
|
||||||
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = hub_strdup(nick);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
LOG_ERROR("ACL error: Out of memory!");
|
||||||
hub_free(info);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,19 +375,10 @@ int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
|||||||
|
|
||||||
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
||||||
{
|
{
|
||||||
char* data;
|
char* data = hub_strdup(cid);
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = hub_strdup(cid);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
LOG_ERROR("ACL error: Out of memory!");
|
||||||
hub_free(info);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +438,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];
|
||||||
@@ -466,36 +454,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-2009, Jan Vidar Krey
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -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 */
|
||||||
|
|||||||
1153
src/core/commands.c
1153
src/core/commands.c
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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,6 +17,160 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
|
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
|
||||||
|
|
||||||
|
enum command_parse_status
|
||||||
|
{
|
||||||
|
cmd_status_ok, /** <<< "Everything seems to OK" */
|
||||||
|
cmd_status_not_found, /** <<< "Command was not found" */
|
||||||
|
cmd_status_access_error, /** <<< "You don't have access to this command" */
|
||||||
|
cmd_status_syntax_error, /** <<< "Not a valid command." */
|
||||||
|
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
|
||||||
|
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
|
||||||
|
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
|
||||||
|
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
|
||||||
|
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
|
||||||
|
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
|
||||||
|
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hub_command_arg_data
|
||||||
|
{
|
||||||
|
enum Type {
|
||||||
|
type_integer,
|
||||||
|
type_string,
|
||||||
|
type_user,
|
||||||
|
type_address,
|
||||||
|
type_range,
|
||||||
|
type_credentials,
|
||||||
|
type_command
|
||||||
|
} type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
int integer;
|
||||||
|
char* string;
|
||||||
|
struct hub_user* user;
|
||||||
|
struct ip_addr_encap* address;
|
||||||
|
struct ip_range* range;
|
||||||
|
enum auth_credentials credentials;
|
||||||
|
struct command_handle* command;
|
||||||
|
} data;
|
||||||
|
|
||||||
|
struct hub_command_arg_data* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void hub_command_args_free(struct hub_command* command);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This struct contains all information needed to invoke
|
||||||
|
* a command, which includes the whole message, the prefix,
|
||||||
|
* the decoded arguments (according to parameter list), and
|
||||||
|
* the user pointer (ptr) which comes from the command it was matched to.
|
||||||
|
*
|
||||||
|
* The message and prefix is generally always available, but args only
|
||||||
|
* if status == cmd_status_ok.
|
||||||
|
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
|
||||||
|
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
|
||||||
|
*/
|
||||||
|
struct hub_command
|
||||||
|
{
|
||||||
|
const char* message; /**<<< "The complete message." */
|
||||||
|
char* prefix; /**<<< "The prefix extracted from the message." */
|
||||||
|
struct linked_list* args; /**<<< "List of all parsed arguments from the message. Type depends on expectations." */
|
||||||
|
enum command_parse_status status; /**<<< "Status of the hub_command." */
|
||||||
|
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
|
||||||
|
const struct hub_user* user; /**<<< "The user who invoked this command." */
|
||||||
|
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Argument codes are used to automatically parse arguments
|
||||||
|
* for a a hub command.
|
||||||
|
*
|
||||||
|
* n = nick name (must exist in hub session)
|
||||||
|
* 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.
|
||||||
|
* NOTE; if an argument is optional then all following arguments must also be optional.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* "nia" means "nick cid ip"
|
||||||
|
* "n?p" means "nick [password]" where password is optional.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a message as a command and return a status indicating if the command
|
||||||
|
* is valid and that the arguments are sane.
|
||||||
|
*
|
||||||
|
* @param cbase Command base pointer.
|
||||||
|
* @param user User who invoked the command.
|
||||||
|
* @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+')
|
||||||
|
*
|
||||||
|
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
|
||||||
|
*/
|
||||||
|
extern struct hub_command* command_parse(struct command_base* cbase, 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);
|
||||||
|
|
||||||
|
|
||||||
|
extern void commands_builtin_add(struct command_base*);
|
||||||
|
extern void commands_builtin_remove(struct command_base*);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_COMMANDS_H */
|
||||||
|
|||||||
@@ -29,450 +29,44 @@
|
|||||||
#define INT_MIN (-0x7fffffff - 1)
|
#define INT_MIN (-0x7fffffff - 1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CFG_APPLY_BOOLEAN(KEY, TARGET) \
|
static int apply_boolean(const char* key, const char* data, int* target)
|
||||||
if (strcmp(KEY, key) == 0) \
|
|
||||||
{ \
|
|
||||||
if (strlen(data) == 1 && (data[0] == '1')) TARGET = 1; \
|
|
||||||
else if (strlen(data) == 1 && (data[0] == '0')) TARGET = 0; \
|
|
||||||
else if (strncasecmp(data, "true", 4) == 0) TARGET = 1; \
|
|
||||||
else if (strncasecmp(data, "false", 5) == 0) TARGET = 0; \
|
|
||||||
else if (strncasecmp(data, "yes", 3) == 0) TARGET = 1; \
|
|
||||||
else if (strncasecmp(data, "no", 2) == 0) TARGET = 0; \
|
|
||||||
else if (strncasecmp(data, "on", 2) == 0) TARGET = 1; \
|
|
||||||
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
|
|
||||||
else\
|
|
||||||
{ \
|
|
||||||
LOG_FATAL("Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
TARGET |= 0x80000000; \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CFG_APPLY_STRING(KEY, TARGET) \
|
|
||||||
if (strcmp(KEY, key) == 0) \
|
|
||||||
{ \
|
|
||||||
TARGET = hub_strdup(data); \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define CFG_APPLY_INTEGER(KEY, TARGET) \
|
|
||||||
if (strcmp(KEY, key) == 0) \
|
|
||||||
{ \
|
|
||||||
char* endptr; \
|
|
||||||
int val; \
|
|
||||||
errno = 0; \
|
|
||||||
val = strtol(data, &endptr, 10); \
|
|
||||||
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
|
|
||||||
LOG_FATAL("Configuration error on line %d: '%s' must be a number", line_count, key); \
|
|
||||||
return -1; \
|
|
||||||
} \
|
|
||||||
TARGET = val; \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_STRING(KEY, VALUE) \
|
|
||||||
{ \
|
|
||||||
if (config->KEY == 0) \
|
|
||||||
config->KEY = hub_strdup(VALUE); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFAULT_INTEGER(KEY, VALUE) \
|
|
||||||
{ \
|
|
||||||
if (config->KEY == 0) \
|
|
||||||
config->KEY = VALUE; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEFAULT_BOOLEAN(KEY, VALUE) \
|
|
||||||
{ \
|
|
||||||
if (config->KEY & 0x80000000) \
|
|
||||||
{ \
|
|
||||||
config->KEY = config->KEY & 0x000000ff; \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
{ \
|
|
||||||
config->KEY = VALUE; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GET_STR(NAME) CFG_APPLY_STRING ( #NAME , config->NAME )
|
|
||||||
#define GET_INT(NAME) CFG_APPLY_INTEGER( #NAME , config->NAME )
|
|
||||||
#define GET_BOOL(NAME) CFG_APPLY_BOOLEAN( #NAME , config->NAME )
|
|
||||||
#define IGNORED(NAME) \
|
|
||||||
if (strcmp(#NAME, key) == 0) \
|
|
||||||
{ \
|
|
||||||
LOG_WARN("Configuration option %s deprecated and ingnored.", key); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
|
|
||||||
/* default configuration values */
|
|
||||||
#define DEF_SERVER_BIND_ADDR "any"
|
|
||||||
#define DEF_SERVER_PORT 1511
|
|
||||||
#define DEF_SERVER_BACKLOG 50
|
|
||||||
#define DEF_HUB_NAME "uhub"
|
|
||||||
#define DEF_HUB_DESCRIPTION ""
|
|
||||||
#define DEF_HUB_ENABLED 1
|
|
||||||
#define DEF_FILE_ACL ""
|
|
||||||
#define DEF_FILE_MOTD ""
|
|
||||||
#define DEF_FILE_RULES ""
|
|
||||||
#define DEF_MAX_USERS 500
|
|
||||||
#define DEF_MAX_CHAT_HISTORY 20
|
|
||||||
#define DEF_MAX_LOGOUT_LOG 100
|
|
||||||
#define DEF_MAX_RECV_BUFFER 4096
|
|
||||||
#define DEF_MAX_SEND_BUFFER 131072
|
|
||||||
#define DEF_MAX_SEND_BUFFER_SOFT 98304
|
|
||||||
#define DEF_SHOW_BANNER 1
|
|
||||||
#define DEF_REGISTERED_USERS_ONLY 0
|
|
||||||
#define DEF_CHAT_ONLY 0
|
|
||||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
|
||||||
#define DEF_LOW_BANDWIDTH_MODE 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS_USER 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS_REG 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS_OP 0
|
|
||||||
#define DEF_LIMIT_MAX_HUBS 0
|
|
||||||
#define DEF_LIMIT_MIN_HUBS_USER 0
|
|
||||||
#define DEF_LIMIT_MIN_HUBS_REG 0
|
|
||||||
#define DEF_LIMIT_MIN_HUBS_OP 0
|
|
||||||
#define DEF_LIMIT_MIN_SHARE 0
|
|
||||||
#define DEF_LIMIT_MAX_SHARE 0
|
|
||||||
#define DEF_LIMIT_MIN_SLOTS 0
|
|
||||||
#define DEF_LIMIT_MAX_SLOTS 0
|
|
||||||
#define DEF_TLS_ENABLE 0
|
|
||||||
#define DEF_TLS_REQUIRE 1
|
|
||||||
#define DEF_TLS_PRIVATE_KEY ""
|
|
||||||
#define DEF_TLS_CERTIFICATE ""
|
|
||||||
#define DEF_MSG_HUB_FULL "Hub is full"
|
|
||||||
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
|
|
||||||
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_MISSING "No nickname given"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_MULTIPLE "Multiple nicknames given"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_INVALID "Nickname is invalid"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_LONG "Nickname too long"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_SHORT "Nickname too short"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_SPACES "Nickname cannot start with spaces"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_BAD_CHARS "Nickname contains invalid characters"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_NOT_UTF8 "Nickname is not valid utf8"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_TAKEN "Nickname is already in use"
|
|
||||||
#define DEF_MSG_INF_ERROR_NICK_RESTRICTED "Nickname cannot be used on this hub"
|
|
||||||
#define DEF_MSG_INF_ERROR_CID_INVALID "CID is not valid"
|
|
||||||
#define DEF_MSG_INF_ERROR_CID_MISSING "CID is not specified"
|
|
||||||
#define DEF_MSG_INF_ERROR_CID_TAKEN "CID is taken"
|
|
||||||
#define DEF_MSG_INF_ERROR_PID_MISSING "PID is not specified"
|
|
||||||
#define DEF_MSG_INF_ERROR_PID_INVALID "PID is invalid"
|
|
||||||
#define DEF_MSG_BAN_PERMANENTLY "Banned permanently"
|
|
||||||
#define DEF_MSG_BAN_TEMPORARILY "Banned temporarily"
|
|
||||||
#define DEF_MSG_AUTH_INVALID_PASSWORD "Password is wrong"
|
|
||||||
#define DEF_MSG_AUTH_USER_NOT_FOUND "User not found in password database"
|
|
||||||
#define DEF_MSG_ERROR_NO_MEMORY "No memory"
|
|
||||||
#define DEF_MSG_USER_SHARE_SIZE_LOW "User is not sharing enough"
|
|
||||||
#define DEF_MSG_USER_SHARE_SIZE_HIGH "User is sharing too much"
|
|
||||||
#define DEF_MSG_USER_SLOTS_LOW "User have too few upload slots."
|
|
||||||
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
|
|
||||||
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
|
|
||||||
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
|
|
||||||
|
|
||||||
void config_defaults(struct hub_config* config)
|
|
||||||
{
|
{
|
||||||
DEFAULT_STRING (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
return string_to_boolean(data, target);
|
||||||
DEFAULT_STRING (hub_name, DEF_HUB_NAME);
|
|
||||||
DEFAULT_STRING (hub_description, DEF_HUB_DESCRIPTION);
|
|
||||||
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
|
||||||
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
|
||||||
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
|
||||||
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
|
|
||||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
|
||||||
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
|
|
||||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
|
||||||
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
|
|
||||||
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
|
|
||||||
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
|
||||||
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
|
||||||
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
|
||||||
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
|
||||||
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
|
|
||||||
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
|
||||||
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
|
||||||
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
|
||||||
DEFAULT_INTEGER(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
|
||||||
DEFAULT_INTEGER(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
|
||||||
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
|
||||||
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
|
||||||
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
|
|
||||||
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
|
|
||||||
DEFAULT_STRING (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
|
||||||
DEFAULT_STRING (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
|
||||||
DEFAULT_STRING (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
|
||||||
DEFAULT_STRING (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
|
||||||
DEFAULT_STRING (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
|
||||||
DEFAULT_STRING (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
|
||||||
DEFAULT_STRING (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
|
||||||
DEFAULT_STRING (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
|
||||||
DEFAULT_STRING (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
|
||||||
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
|
||||||
|
|
||||||
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
|
|
||||||
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
|
|
||||||
DEFAULT_STRING (tls_certificate, DEF_TLS_CERTIFICATE);
|
|
||||||
DEFAULT_STRING (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_string(const char* key, const char* data, char** target, char* regexp)
|
||||||
static int apply_config(struct hub_config* config, char* key, char* data, int line_count)
|
|
||||||
{
|
{
|
||||||
GET_STR (file_acl);
|
(void) regexp;
|
||||||
GET_STR (file_motd);
|
// FIXME: Add regexp checks for correct data
|
||||||
GET_STR (file_rules);
|
|
||||||
GET_STR (server_bind_addr);
|
|
||||||
GET_INT (server_port);
|
|
||||||
GET_INT (server_listen_backlog);
|
|
||||||
GET_STR (hub_name);
|
|
||||||
GET_STR (hub_description);
|
|
||||||
GET_BOOL(hub_enabled);
|
|
||||||
GET_INT (max_users);
|
|
||||||
GET_INT (max_chat_history);
|
|
||||||
GET_INT (max_logout_log);
|
|
||||||
GET_INT (max_recv_buffer);
|
|
||||||
GET_INT (max_send_buffer);
|
|
||||||
GET_INT (max_send_buffer_soft);
|
|
||||||
GET_BOOL(show_banner);
|
|
||||||
GET_BOOL(chat_only);
|
|
||||||
GET_BOOL(chat_is_privileged);
|
|
||||||
GET_BOOL(low_bandwidth_mode);
|
|
||||||
GET_BOOL(registered_users_only);
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
if (*target)
|
||||||
GET_INT(limit_max_hubs_user);
|
hub_free(*target);
|
||||||
GET_INT(limit_max_hubs_reg);
|
|
||||||
GET_INT(limit_max_hubs_op);
|
|
||||||
GET_INT(limit_min_hubs_user);
|
|
||||||
GET_INT(limit_min_hubs_reg);
|
|
||||||
GET_INT(limit_min_hubs_op);
|
|
||||||
GET_INT(limit_max_hubs);
|
|
||||||
GET_INT(limit_min_share);
|
|
||||||
GET_INT(limit_max_share);
|
|
||||||
GET_INT(limit_min_slots);
|
|
||||||
GET_INT(limit_max_slots);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
*target = hub_strdup(data);
|
||||||
GET_STR (msg_hub_full);
|
return 1;
|
||||||
GET_STR (msg_hub_disabled);
|
|
||||||
GET_STR (msg_hub_registered_users_only);
|
|
||||||
GET_STR (msg_inf_error_nick_missing);
|
|
||||||
GET_STR (msg_inf_error_nick_multiple);
|
|
||||||
GET_STR (msg_inf_error_nick_invalid);
|
|
||||||
GET_STR (msg_inf_error_nick_long);
|
|
||||||
GET_STR (msg_inf_error_nick_short);
|
|
||||||
GET_STR (msg_inf_error_nick_spaces);
|
|
||||||
GET_STR (msg_inf_error_nick_bad_chars);
|
|
||||||
GET_STR (msg_inf_error_nick_not_utf8);
|
|
||||||
GET_STR (msg_inf_error_nick_taken);
|
|
||||||
GET_STR (msg_inf_error_nick_restricted);
|
|
||||||
GET_STR (msg_inf_error_cid_invalid);
|
|
||||||
GET_STR (msg_inf_error_cid_missing);
|
|
||||||
GET_STR (msg_inf_error_cid_taken);
|
|
||||||
GET_STR (msg_inf_error_pid_missing);
|
|
||||||
GET_STR (msg_inf_error_pid_invalid);
|
|
||||||
GET_STR (msg_ban_permanently);
|
|
||||||
GET_STR (msg_ban_temporarily);
|
|
||||||
GET_STR (msg_auth_invalid_password);
|
|
||||||
GET_STR (msg_auth_user_not_found);
|
|
||||||
GET_STR (msg_error_no_memory);
|
|
||||||
GET_STR (msg_user_share_size_low);
|
|
||||||
GET_STR (msg_user_share_size_high);
|
|
||||||
GET_STR (msg_user_slots_low);
|
|
||||||
GET_STR (msg_user_slots_high);
|
|
||||||
GET_STR (msg_user_hub_limit_low);
|
|
||||||
GET_STR (msg_user_hub_limit_high);
|
|
||||||
|
|
||||||
GET_BOOL(tls_enable);
|
|
||||||
GET_BOOL(tls_require);
|
|
||||||
GET_STR (tls_certificate);
|
|
||||||
GET_STR (tls_private_key);
|
|
||||||
|
|
||||||
/* Still here -- unknown directive */
|
|
||||||
LOG_ERROR("Unknown configuration directive: '%s'", key);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_integer(const char* key, const char* data, int* target, int* min, int* max)
|
||||||
void free_config(struct hub_config* config)
|
|
||||||
{
|
{
|
||||||
hub_free(config->server_bind_addr);
|
char* endptr;
|
||||||
hub_free(config->file_motd);
|
int val;
|
||||||
hub_free(config->file_acl);
|
errno = 0;
|
||||||
hub_free(config->file_rules);
|
val = strtol(data, &endptr, 10);
|
||||||
hub_free(config->hub_name);
|
|
||||||
hub_free(config->hub_description);
|
|
||||||
|
|
||||||
hub_free(config->msg_hub_full);
|
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data)
|
||||||
hub_free(config->msg_hub_disabled);
|
return 0;
|
||||||
hub_free(config->msg_hub_registered_users_only);
|
|
||||||
hub_free(config->msg_inf_error_nick_missing);
|
|
||||||
hub_free(config->msg_inf_error_nick_multiple);
|
|
||||||
hub_free(config->msg_inf_error_nick_invalid);
|
|
||||||
hub_free(config->msg_inf_error_nick_long);
|
|
||||||
hub_free(config->msg_inf_error_nick_short);
|
|
||||||
hub_free(config->msg_inf_error_nick_spaces);
|
|
||||||
hub_free(config->msg_inf_error_nick_bad_chars);
|
|
||||||
hub_free(config->msg_inf_error_nick_not_utf8);
|
|
||||||
hub_free(config->msg_inf_error_nick_taken);
|
|
||||||
hub_free(config->msg_inf_error_nick_restricted);
|
|
||||||
hub_free(config->msg_inf_error_cid_invalid);
|
|
||||||
hub_free(config->msg_inf_error_cid_missing);
|
|
||||||
hub_free(config->msg_inf_error_cid_taken);
|
|
||||||
hub_free(config->msg_inf_error_pid_missing);
|
|
||||||
hub_free(config->msg_inf_error_pid_invalid);
|
|
||||||
hub_free(config->msg_ban_permanently);
|
|
||||||
hub_free(config->msg_ban_temporarily);
|
|
||||||
hub_free(config->msg_auth_invalid_password);
|
|
||||||
hub_free(config->msg_auth_user_not_found);
|
|
||||||
hub_free(config->msg_error_no_memory);
|
|
||||||
hub_free(config->msg_user_share_size_low);
|
|
||||||
hub_free(config->msg_user_share_size_high);
|
|
||||||
hub_free(config->msg_user_slots_low);
|
|
||||||
hub_free(config->msg_user_slots_high);
|
|
||||||
hub_free(config->msg_user_hub_limit_low);
|
|
||||||
hub_free(config->msg_user_hub_limit_high);
|
|
||||||
|
|
||||||
hub_free(config->tls_certificate);
|
if (min && val < *min)
|
||||||
hub_free(config->tls_private_key);
|
return 0;
|
||||||
|
|
||||||
memset(config, 0, sizeof(struct hub_config));
|
if (max && val > *max)
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
#define DUMP_STR(NAME, DEFAULT) \
|
*target = val;
|
||||||
if (ignore_defaults) \
|
return 1;
|
||||||
{ \
|
|
||||||
if (strcmp(config->NAME, DEFAULT) != 0) \
|
|
||||||
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
|
|
||||||
|
|
||||||
#define DUMP_INT(NAME, DEFAULT) \
|
|
||||||
if (ignore_defaults) \
|
|
||||||
{ \
|
|
||||||
if (config->NAME != DEFAULT) \
|
|
||||||
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
|
|
||||||
|
|
||||||
|
|
||||||
#define DUMP_BOOL(NAME, DEFAULT) \
|
|
||||||
if (ignore_defaults) \
|
|
||||||
{ \
|
|
||||||
if (config->NAME != DEFAULT) \
|
|
||||||
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no")); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no"));
|
|
||||||
|
|
||||||
void dump_config(struct hub_config* config, int ignore_defaults)
|
|
||||||
{
|
|
||||||
DUMP_STR (file_acl, DEF_FILE_ACL);
|
|
||||||
DUMP_STR (file_motd, DEF_FILE_MOTD);
|
|
||||||
DUMP_STR (file_rules, DEF_FILE_RULES);
|
|
||||||
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
|
||||||
DUMP_INT (server_port, DEF_SERVER_PORT);
|
|
||||||
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG);
|
|
||||||
DUMP_STR (hub_name, DEF_HUB_NAME);
|
|
||||||
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
|
||||||
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
|
||||||
DUMP_INT (max_users, DEF_MAX_USERS);
|
|
||||||
DUMP_INT (max_chat_history, DEF_MAX_CHAT_HISTORY);
|
|
||||||
DUMP_INT (max_logout_log, DEF_MAX_LOGOUT_LOG);
|
|
||||||
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
|
||||||
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
|
|
||||||
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
|
||||||
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
|
|
||||||
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
|
|
||||||
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
|
||||||
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
|
||||||
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
DUMP_BOOL(tls_enable, DEF_TLS_ENABLE);
|
|
||||||
DUMP_BOOL(tls_require, DEF_TLS_REQUIRE);
|
|
||||||
DUMP_STR (tls_certificate, DEF_TLS_CERTIFICATE);
|
|
||||||
DUMP_STR (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
|
||||||
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
|
||||||
DUMP_INT(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
|
||||||
DUMP_INT(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
|
||||||
DUMP_INT(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
|
||||||
DUMP_INT(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
|
||||||
DUMP_INT(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
|
||||||
DUMP_INT(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
|
||||||
DUMP_INT(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
|
||||||
DUMP_INT(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
|
||||||
DUMP_INT(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
|
||||||
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
|
|
||||||
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
|
|
||||||
DUMP_STR (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
|
||||||
DUMP_STR (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
|
||||||
DUMP_STR (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
|
||||||
DUMP_STR (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
|
||||||
DUMP_STR (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
|
||||||
DUMP_STR (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
|
||||||
DUMP_STR (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
|
||||||
DUMP_STR (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
|
||||||
DUMP_STR (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
|
||||||
DUMP_STR (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
|
||||||
DUMP_STR (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
|
||||||
DUMP_STR (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
|
||||||
DUMP_STR (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
|
||||||
DUMP_STR (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
|
||||||
DUMP_STR (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
|
||||||
DUMP_STR (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
|
||||||
DUMP_STR (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
|
||||||
DUMP_STR (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
|
||||||
DUMP_STR (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
|
||||||
DUMP_STR (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
|
||||||
DUMP_STR (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
|
||||||
DUMP_STR (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
|
||||||
DUMP_STR (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
|
||||||
DUMP_STR (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
|
||||||
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
|
||||||
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
|
||||||
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "gen_config.c"
|
||||||
|
|
||||||
static int config_parse_line(char* line, int line_count, void* ptr_data)
|
static int config_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
{
|
{
|
||||||
@@ -481,10 +75,7 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
|
|||||||
char* data;
|
char* data;
|
||||||
struct hub_config* config = (struct hub_config*) ptr_data;
|
struct hub_config* config = (struct hub_config*) ptr_data;
|
||||||
|
|
||||||
if ((pos = strchr(line, '#')) != NULL)
|
strip_off_ini_line_comments(line, line_count);
|
||||||
{
|
|
||||||
pos[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*line) return 0;
|
if (!*line) return 0;
|
||||||
|
|
||||||
@@ -509,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)
|
||||||
{
|
{
|
||||||
@@ -527,6 +119,7 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(config, 0, sizeof(struct hub_config));
|
memset(config, 0, sizeof(struct hub_config));
|
||||||
|
config_defaults(config);
|
||||||
|
|
||||||
ret = file_read_lines(file, config, &config_parse_line);
|
ret = file_read_lines(file, config, &config_parse_line);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -541,7 +134,6 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config_defaults(config);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,79 +20,7 @@
|
|||||||
#ifndef HAVE_UHUB_CONFIG_H
|
#ifndef HAVE_UHUB_CONFIG_H
|
||||||
#define HAVE_UHUB_CONFIG_H
|
#define HAVE_UHUB_CONFIG_H
|
||||||
|
|
||||||
struct hub_config
|
#include "gen_config.h"
|
||||||
{
|
|
||||||
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
|
||||||
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
|
||||||
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
|
|
||||||
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
|
||||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
|
||||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
|
||||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
|
||||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
|
||||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
|
||||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
|
||||||
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
|
||||||
char* file_rules; /**<<< "File containing the rules (default: '' - no rules)" */
|
|
||||||
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
|
||||||
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
|
||||||
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
|
||||||
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
|
|
||||||
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
|
|
||||||
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
|
|
||||||
|
|
||||||
int max_chat_history; /**<<< "Number of chat messages kept in history (default: 20)" */
|
|
||||||
int max_logout_log; /**<<< "Number of log entries for people leaving the hub. (default: 100) */
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
|
|
||||||
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
|
|
||||||
int limit_max_hubs_op; /**<<< "Max concurrent hubs as operator. (0=off, default: 10)" */
|
|
||||||
int limit_min_hubs_user; /**<<< "Min concurrent hubs as a user. (0=off, default: 0)" */
|
|
||||||
int limit_min_hubs_reg; /**<<< "Min concurrent hubs as registered user. (0=off, default: 0)" */
|
|
||||||
int limit_min_hubs_op; /**<<< "Min concurrent hubs as operator. (0=off, default: 0)" */
|
|
||||||
int limit_max_hubs; /**<<< "Max total hub connections allowed, user/reg/op combined. (0=off, default: 25)" */
|
|
||||||
int limit_min_share; /**<<< "Limit minimum share size in megabytes (MiB) (0=off, default: 0)" */
|
|
||||||
int limit_max_share; /**<<< "Limit maximum share size in megabytes (MiB) (0=off, default: 0)" */
|
|
||||||
int limit_min_slots; /**<<< "Limit minimum number of slots open per user (0=off, default: 0)" */
|
|
||||||
int limit_max_slots; /**<<< "Limit maximum number of slots open per user (0=off, default: 0)" */
|
|
||||||
|
|
||||||
/* Messages that can be sent to a user */
|
|
||||||
char* msg_hub_full; /**<<< "hub is full" */
|
|
||||||
char* msg_hub_disabled; /**<<< "hub is disabled" */
|
|
||||||
char* msg_hub_registered_users_only; /**<<< "hub is for registered users only" */
|
|
||||||
char* msg_inf_error_nick_missing; /**<<< "no nickname given" */
|
|
||||||
char* msg_inf_error_nick_multiple; /**<<< "multiple nicknames given" */
|
|
||||||
char* msg_inf_error_nick_invalid; /**<<< "generic/unkown" */
|
|
||||||
char* msg_inf_error_nick_long; /**<<< "nickname too long" */
|
|
||||||
char* msg_inf_error_nick_short; /**<<< "nickname too short" */
|
|
||||||
char* msg_inf_error_nick_spaces; /**<<< "nickname cannot start with spaces" */
|
|
||||||
char* msg_inf_error_nick_bad_chars; /**<<< "nickname contains chars below ascii 32" */
|
|
||||||
char* msg_inf_error_nick_not_utf8; /**<<< "nickname is not valid utf8" */
|
|
||||||
char* msg_inf_error_nick_taken; /**<<< "nickname is in use" */
|
|
||||||
char* msg_inf_error_nick_restricted; /**<<< "nickname cannot be used on this hub" */
|
|
||||||
char* msg_inf_error_cid_invalid; /**<<< "CID is not valid" */
|
|
||||||
char* msg_inf_error_cid_missing; /**<<< "CID is not specified" */
|
|
||||||
char* msg_inf_error_cid_taken; /**<<< "CID is taken" */
|
|
||||||
char* msg_inf_error_pid_missing; /**<<< "PID is not specified" */
|
|
||||||
char* msg_inf_error_pid_invalid; /**<<< "PID is invalid" */
|
|
||||||
char* msg_ban_permanently; /**<<< "Banned permanently" */
|
|
||||||
char* msg_ban_temporarily; /**<<< "Banned temporarily" */
|
|
||||||
char* msg_auth_invalid_password; /**<<< "Password is wrong" */
|
|
||||||
char* msg_auth_user_not_found; /**<<< "User not found in password database" */
|
|
||||||
char* msg_error_no_memory; /**<<< "No memory" */
|
|
||||||
char* msg_user_share_size_low; /**<<< "User is not sharing enough" */
|
|
||||||
char* msg_user_share_size_high; /**<<< "User is sharing too much" */
|
|
||||||
char* msg_user_slots_low; /**<<< "User have too few upload slots." */
|
|
||||||
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
|
|
||||||
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
|
|
||||||
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
|
|
||||||
|
|
||||||
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
|
|
||||||
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
|
|
||||||
char* tls_certificate; /**<<< "Certificate file (PEM)" */
|
|
||||||
char* tls_private_key; /**<<< "Private key" */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This initializes the configuration variables, and sets the default
|
* This initializes the configuration variables, and sets the default
|
||||||
|
|||||||
241
src/core/config.pl
Executable file
241
src/core/config.pl
Executable file
@@ -0,0 +1,241 @@
|
|||||||
|
#!/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;
|
||||||
|
}
|
||||||
|
|
||||||
662
src/core/config.xml
Normal file
662
src/core/config.xml
Normal file
@@ -0,0 +1,662 @@
|
|||||||
|
<?xml version='1.0' standalone="yes" ?>
|
||||||
|
<config>
|
||||||
|
|
||||||
|
<option name="hub_enabled" type="boolean" default="1">
|
||||||
|
<short>Is server enabled</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Use this to disable the hub for a while.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_port" type="int" default="1511">
|
||||||
|
<check min="1" max="65535" />
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<short>Server port to bind to</short>
|
||||||
|
<description><![CDATA[This is specifies the port number the hub should listen on.]]></description>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_bind_addr" type="string" default="any">
|
||||||
|
<check regexp="(\d\.\d\.\d\.\d\)|(any)|(loopback)|(.*)" /><!-- FIXME: add better IPv6 regexp in the future! -->
|
||||||
|
<short>Server bind address</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
|
||||||
|
When "any" or "loopback" is used, the hub will automatically detect if IPv6 is supported and prefer that.
|
||||||
|
]]></description>
|
||||||
|
<syntax>
|
||||||
|
IPv4 address, IPv6 address, "any" or "loopback"
|
||||||
|
</syntax>
|
||||||
|
<since>0.1.2</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
To listen to a specific IP:<br />
|
||||||
|
server_bind_addr = "192.168.12.69"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To listen to any IPv4 address:<br />
|
||||||
|
server_bind_addr = "0.0.0.0"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Or to listen to any address including IPv6 (if supported):<br />
|
||||||
|
server_bind_addr = "any"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_listen_backlog" type="int" default="50">
|
||||||
|
<check min="5" />
|
||||||
|
<short>Server listen backlog</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
<p>
|
||||||
|
This specifies the number of connections the hub will be able to accept in the backlog before they must be processed by the hub.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
A too low number here will mean the hub will not accept connections fast enough when users are reconnecting really fast. The hub should under normal circumstances be able to empty the listen backlog several times per second.
|
||||||
|
</p>
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="server_alt_ports" type="string" default="">
|
||||||
|
<check regexp="((\d+)(,(\d+))*)?" />
|
||||||
|
<short>Comma separated list of alternative ports to listen to</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
In addition to the server_port the hub can listen to a list of alternative ports.
|
||||||
|
]]></description>
|
||||||
|
<example><![CDATA[
|
||||||
|
server_alt_ports = 1295,1512,53990
|
||||||
|
]]></example>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="show_banner" type="boolean" default="1">
|
||||||
|
<short>Show banner on connect</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If enabled, the hub will announce the software version running to clients when they connect with a message like: "Powered by uhub/0.x.y"
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="show_banner_sys_info" type="boolean" default="1">
|
||||||
|
<short>Show banner on connect</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If enabled, the hub will announce the operating system and CPU architecture to clients when they join.<br />
|
||||||
|
This option has no effect if show_banner is disabled.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_users" type="int" default="500">
|
||||||
|
<check min="1" max="1048576" />
|
||||||
|
<short>Maximum number of users allowed on the hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
The maximum amount of users allowed on the hub.
|
||||||
|
No new users will be allowed to enter the hub if this number is exceeded, however privileged users (operators, admins, etc) are still able to log in.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
To run a hub for max 25 users:<br />
|
||||||
|
max_users = 25
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="registered_users_only" type="boolean" default="0">
|
||||||
|
<short>Allow registered users only</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled only registered users will be able to use the hub. A user must be registered in the acl file (file_acl).
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="register_self" type="boolean" default="0">
|
||||||
|
<short>Allow users to register themselves on the hub.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled guests can register their nickname on the hub.
|
||||||
|
Otherwise only operators can register users.
|
||||||
|
]]></description>
|
||||||
|
<since>0.4.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="obsolete_clients" type="boolean" default="0">
|
||||||
|
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled users using old ADC clients are allowed to enter the hub,
|
||||||
|
however they cannot log in using passwords since the protocols are incompatible.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="chat_is_privileged" type="boolean" default="0">
|
||||||
|
<short>Allow chat for operators and above only</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If enabled only operators and admins are allowed to chat in the main chat.
|
||||||
|
]]></description>
|
||||||
|
<since>0.2.4</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="hub_name" type="string" default="uhub">
|
||||||
|
<short>Name of hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Configures the name of the hub
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
hub_name = "my hub"
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="hub_description" type="string" default="no description">
|
||||||
|
<short>Short hub description, topic or subject.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the description of the hub, as seen by users and hub lists.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
hub_description = "a friendly hub for friendly people"
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="redirect_addr" type="string" default="">
|
||||||
|
<check regexp="(adc|adcs|dchub)://.*" />
|
||||||
|
<short>A common hub redirect address.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.2</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="max_recv_buffer" type="int" default="4096" advanced="true" >
|
||||||
|
<check min="1024" max="1048576" />
|
||||||
|
<short>Max read buffer before parse, per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum receive buffer allowed before commands are procesed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_send_buffer" type="int" default="131072" advanced="true" >
|
||||||
|
<check min="2048" />
|
||||||
|
<short>Max send buffer before disconnect, per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum amount of bytes allowed to be queued for sending to any particular user before the hub will disconnect the user. The lower the limit, the more aggressive the hub will be to disconnect slow clients. Use with caution.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_send_buffer_soft" type="int" default="98304" advanced="true" >
|
||||||
|
<check min="1024" />
|
||||||
|
<short>Max send buffer before message drops, per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Same as max_send_buffer, however low priority messages may be discarded if this limit is reached. Use with caution.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="low_bandwidth_mode" type="boolean" default="0" advanced="true" >
|
||||||
|
<short>Enable bandwidth saving measures</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled the hub will remove excessive information from each user's info message before broadcasting to all connected users.
|
||||||
|
Description, e-mail address will be removed. This saves upload bandwidth for the hub.
|
||||||
|
]]></description>
|
||||||
|
<since>0.2.2</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_chat_history" type="int" default="20">
|
||||||
|
<check min="0" max="250" />
|
||||||
|
<short>Number of chat messages kept in history</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This specifies the number of main chat messages that are kept in the history buffer.
|
||||||
|
Users can use the "!history" command to list these messages.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="max_logout_log" type="int" default="20">
|
||||||
|
<check min="0" max="2000" />
|
||||||
|
<short>Number of log entries for people leaving the hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Operators can use the "!log" command to list users who have recently left the hub.
|
||||||
|
This option specifies the maximum size of this log.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs_user" type="int" default="10">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max concurrent hubs as a guest user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This limits the number of hubs a user can be logged into as a guest user. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs_reg" type="int" default="10">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max concurrent hubs as a registered user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This limits the number of hubs a user can be logged into as a registered user. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs_op" type="int" default="10">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max concurrent hubs as a operator (or admin)</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This limits the number of hubs a user can be logged into as an operator. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_hubs" type="int" default="25">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Max total hub connections allowed, user/reg/op combined.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Limit the number of hubs a user can be logged into in total regardless of registrations or privileges.
|
||||||
|
If this number is exceeded, the user will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_hubs_user" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Minimum concurrent hubs as a guest user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Only allow users that are logged into other hubs with guest privileges to enter this hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_hubs_reg" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Minimum concurrent hubs as a registered user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Only allow users that are logged into other hubs as a registered user to enter this hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_hubs_op" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Minimum concurrent hubs as a operator (or admin)</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Only allow users that are logged into other hubs with operator privileges to enter this hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_min_share" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit minimum share size in megabytes</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Minimum share limit in megabytes (MiB). Users sharing less than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
To require users to share at least 1 GB in order to enter the hub:<br />
|
||||||
|
limit_min_share = 1024
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_share" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit maximum share size in megabytes</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum share limit in megabytes (MiB). Users sharing more than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="limit_min_slots" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit minimum number of upload slots open per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Minimum number of upload slots required. Users with less than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="limit_max_slots" type="int" default="0">
|
||||||
|
<check min="0" />
|
||||||
|
<short>Limit minimum number of upload slots open per user</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Maximum number of upload slots allowed. Users with more than this will not be allowed to enter the hub.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_interval" type="int" default="0">
|
||||||
|
<check min="1" max="60" />
|
||||||
|
<short>Time interval in seconds for flood control check.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the time interval that will be used for all flood control calculations.
|
||||||
|
If this is 0 then all flood control is disabled.
|
||||||
|
]]></description>
|
||||||
|
<example><![CDATA[
|
||||||
|
To limit maximum chat messages to 5 messages on 10 seconds: <br />
|
||||||
|
flood_ctl_interval = 10 <br />
|
||||||
|
flood_ctl_chat = 5<br />
|
||||||
|
]]></example>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_chat" type="int" default="0">
|
||||||
|
<short>Max chat messages allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for chat messages.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_connect" type="int" default="0">
|
||||||
|
<short>Max connections requests allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for connection requests.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_search" type="int" default="0">
|
||||||
|
<short>Max search requests allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for search requests.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="flood_ctl_update" type="int" default="0">
|
||||||
|
<short>Max updates allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is 0 then no flood control is disabled for info updates (INF messages).
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="flood_ctl_extras" type="int" default="0">
|
||||||
|
<short>Max extra messages allowed in time interval</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Extra messages are messages that don't fit into the category of chat, search, update or connect.
|
||||||
|
]]></description>
|
||||||
|
<syntax>0 = off</syntax>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_enable" type="boolean" default="0">
|
||||||
|
<short>Enable SSL/TLS support</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Enables/disables TLS/SSL support. tls_certificate and tls_private_key must be set if this is enabled.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_require" type="boolean" default="0">
|
||||||
|
<short>If SSL/TLS enabled, should it be required (default: 0)</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If TLS/SSL support is enabled it can either be optional or mandatory.
|
||||||
|
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
|
||||||
|
This option has no effect unless tls_enable is enabled.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_require_redirect_addr" type="string" default="">
|
||||||
|
<check regexp="(adc|adcs|dchub)://.*" />
|
||||||
|
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is the redirect address used when the hub wants to redirect a client for not using ADCS.
|
||||||
|
For instance a hub at adc://adc.example.com might redirect to adcs://adc.example.com
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.3</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="tls_certificate" type="file" default="">
|
||||||
|
<short>Certificate file</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Path to a TLS/SSL certificate (PEM format).
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="tls_private_key" type="file" default="">
|
||||||
|
<short>Private key file</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Path to a TLS/SSL private key (PEM format).
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="file_acl" type="file" default="">
|
||||||
|
<short>File containing access control lists</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is an access control list (acl) file.
|
||||||
|
In this file all registered users, bans, etc should be stored.
|
||||||
|
If the file is missing, or empty no registered users, or ban records are used.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
Unix users: <br />
|
||||||
|
file_acl = "/etc/uhub/users.conf"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Windows users: <br />
|
||||||
|
file_acl = "c:\uhub\users.conf"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="file_plugins" type="file" default="">
|
||||||
|
<short>Plugin configuration file</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
Plugin configuration file.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.3</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
file_plugins = "/etc/uhub/plugins.conf"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_hub_full" type="message" default="Hub is full" >
|
||||||
|
<description><![CDATA[This will be sent if the hub is full]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_hub_disabled" type="message" default="Hub is disabled" >
|
||||||
|
<description><![CDATA[This will be sent if the hub is disabled (hub_enable = off)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_hub_registered_users_only" type="message" default="Hub is for registered users only" >
|
||||||
|
<description><![CDATA[This will be sent if the hub is configured to only accept registered users (registered_users_only = yes)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_missing" type="message" default="No nickname given">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that do not provide a nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_multiple" type="message" default="Multiple nicknames given">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provide multiple nicknames.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_invalid" type="message" default="Nickname is invalid">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_long" type="message" default="Nickname too long">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a too long nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_short" type="message" default="Nickname too short">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a too short nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_spaces" type="message" default="Nickname cannot start with spaces">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a nickname that starts with a space.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_bad_chars" type="message" default="Nickname contains invalid characters">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides invalid characters in the nickname.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_not_utf8" type="message" default="Nickname is not valid UTF-8">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a nick name that is not valid UTF-8 encoded.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use">
|
||||||
|
<description><![CDATA[This message will be sent to clients if their provided nickname is alredy in use on the hub.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_nick_restricted" type="message" default="Nickname cannot be used on this hub">
|
||||||
|
<description><![CDATA[This message will be sent to clients if they provide a restricted nickname. Restricted names can be configured in the acl.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_cid_invalid" type="message" default="CID is not valid">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid client ID (CID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_cid_missing" type="message" default="CID is not specified">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that does not provide a client ID (CID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_cid_taken" type="message" default="CID is taken">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides a client ID (CID) already in use on the hub.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_pid_missing" type="message" default="PID is not specified">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that does not provide a private ID (PID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_inf_error_pid_invalid" type="message" default="PID is invalid">
|
||||||
|
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid private ID (PID)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_ban_permanently" type="message" default="Banned permanently">
|
||||||
|
<description><![CDATA[This message is sent to users if they are banned (see acl)]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_ban_temporarily" type="message" default="Banned temporarily">
|
||||||
|
<description><![CDATA[This message is sent to users if they are banned temporarily]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
|
||||||
|
<option name="msg_auth_invalid_password" type="message" default="Password is wrong">
|
||||||
|
<description><![CDATA[This message is sent to users if they provide a wrong password.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_auth_user_not_found" type="message" default="User not found in password database">
|
||||||
|
<description><![CDATA[This message is used if a user cannot be found in the password database.]]></description>
|
||||||
|
<since>0.2.0</since> <!-- FIXME? -->
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_error_no_memory" type="message" default="No memory">
|
||||||
|
<description><![CDATA[]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_share_size_low" type="message" default="User is not sharing enough">
|
||||||
|
<description><![CDATA[This message is sent to users if they are not sharing enough.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_share_size_high" type="message" default="User is sharing too much">
|
||||||
|
<description><![CDATA[This message is sent to users if they are sharing too much.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_slots_low" type="message" default="User have too few upload slots.">
|
||||||
|
<description><![CDATA[This message is sent to users if they do not have enough upload slots.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_slots_high" type="message" default="User have too many upload slots.">
|
||||||
|
<description><![CDATA[This message is sent to users if they have too many upload slots.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_hub_limit_low" type="message" default="User is on too few hubs.">
|
||||||
|
<description><![CDATA[This message is sent to users if they are on too few other hubs.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_hub_limit_high" type="message" default="User is on too many hubs.">
|
||||||
|
<description><![CDATA[This message is sent to users if they are on too many other hubs.]]></description>
|
||||||
|
<since>0.2.0</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_chat" type="message" default="Chat flood detected, messages are dropped.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are flooding the chat.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_connect" type="message" default="Connect flood detected, connection refused.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many connect requests too fast.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_search" type="message" default="Search flood detected, search is stopped.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many search requests too fast.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_update" type="message" default="Update flood detected.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many updates too fast.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_user_flood_extras" type="message" default="Flood detected.">
|
||||||
|
<description><![CDATA[This message is sent once to users who are sending too many messages to the hub that neither are chat, searhes, updates nor connection requests..]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_proto_no_common_hash" type="message" default="No common hash algorithm.">
|
||||||
|
<description><![CDATA[This message is sent if a client connects that does support ADC/1.0 but not a hash algorithm that the hub supports.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="msg_proto_obsolete_adc0" type="message" default="Client is using an obsolete ADC protocol version.">
|
||||||
|
<description><![CDATA[This message is sent if a client connects that does not support ADC/1.0, but rather the obsolete ADC/0.1 version.]]></description>
|
||||||
|
<since>0.3.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
</config>
|
||||||
1255
src/core/gen_config.c
Normal file
1255
src/core/gen_config.c
Normal file
File diff suppressed because it is too large
Load Diff
87
src/core/gen_config.h
Normal file
87
src/core/gen_config.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */
|
||||||
|
|
||||||
|
struct hub_config
|
||||||
|
{
|
||||||
|
int hub_enabled; /*<<< Is server enabled (default: 1) */
|
||||||
|
int server_port; /*<<< Server port to bind to (default: 1511) */
|
||||||
|
char* server_bind_addr; /*<<< Server bind address (default: any) */
|
||||||
|
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
|
||||||
|
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: ) */
|
||||||
|
int show_banner; /*<<< Show banner on connect (default: 1) */
|
||||||
|
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
|
||||||
|
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
|
||||||
|
int registered_users_only; /*<<< Allow registered users only (default: 0) */
|
||||||
|
int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */
|
||||||
|
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
|
||||||
|
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
|
||||||
|
char* hub_name; /*<<< Name of hub (default: uhub) */
|
||||||
|
char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */
|
||||||
|
char* redirect_addr; /*<<< A common hub redirect address. (default: ) */
|
||||||
|
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
|
||||||
|
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
|
||||||
|
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
|
||||||
|
int low_bandwidth_mode; /*<<< Enable bandwidth saving measures (default: 0) */
|
||||||
|
int max_chat_history; /*<<< Number of chat messages kept in history (default: 20) */
|
||||||
|
int max_logout_log; /*<<< Number of log entries for people leaving the hub (default: 20) */
|
||||||
|
int limit_max_hubs_user; /*<<< Max concurrent hubs as a guest user (default: 10) */
|
||||||
|
int limit_max_hubs_reg; /*<<< Max concurrent hubs as a registered user (default: 10) */
|
||||||
|
int limit_max_hubs_op; /*<<< Max concurrent hubs as a operator (or admin) (default: 10) */
|
||||||
|
int limit_max_hubs; /*<<< Max total hub connections allowed, user/reg/op combined. (default: 25) */
|
||||||
|
int limit_min_hubs_user; /*<<< Minimum concurrent hubs as a guest user (default: 0) */
|
||||||
|
int limit_min_hubs_reg; /*<<< Minimum concurrent hubs as a registered user (default: 0) */
|
||||||
|
int limit_min_hubs_op; /*<<< Minimum concurrent hubs as a operator (or admin) (default: 0) */
|
||||||
|
int limit_min_share; /*<<< Limit minimum share size in megabytes (default: 0) */
|
||||||
|
int limit_max_share; /*<<< Limit maximum share size in megabytes (default: 0) */
|
||||||
|
int limit_min_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
|
||||||
|
int limit_max_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
|
||||||
|
int flood_ctl_interval; /*<<< Time interval in seconds for flood control check. (default: 0) */
|
||||||
|
int flood_ctl_chat; /*<<< Max chat messages allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_connect; /*<<< Max connections requests allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_search; /*<<< Max search requests allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
|
||||||
|
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
|
||||||
|
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
|
||||||
|
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
|
||||||
|
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: ) */
|
||||||
|
char* tls_certificate; /*<<< Certificate file (default: ) */
|
||||||
|
char* tls_private_key; /*<<< Private key file (default: ) */
|
||||||
|
char* file_acl; /*<<< File containing access control lists (default: ) */
|
||||||
|
char* file_plugins; /*<<< Plugin configuration file (default: ) */
|
||||||
|
char* msg_hub_full; /*<<< "Hub is full" */
|
||||||
|
char* msg_hub_disabled; /*<<< "Hub is disabled" */
|
||||||
|
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
|
||||||
|
char* msg_inf_error_nick_missing; /*<<< "No nickname given" */
|
||||||
|
char* msg_inf_error_nick_multiple; /*<<< "Multiple nicknames given" */
|
||||||
|
char* msg_inf_error_nick_invalid; /*<<< "Nickname is invalid" */
|
||||||
|
char* msg_inf_error_nick_long; /*<<< "Nickname too long" */
|
||||||
|
char* msg_inf_error_nick_short; /*<<< "Nickname too short" */
|
||||||
|
char* msg_inf_error_nick_spaces; /*<<< "Nickname cannot start with spaces" */
|
||||||
|
char* msg_inf_error_nick_bad_chars; /*<<< "Nickname contains invalid characters" */
|
||||||
|
char* msg_inf_error_nick_not_utf8; /*<<< "Nickname is not valid UTF-8" */
|
||||||
|
char* msg_inf_error_nick_taken; /*<<< "Nickname is already in use" */
|
||||||
|
char* msg_inf_error_nick_restricted; /*<<< "Nickname cannot be used on this hub" */
|
||||||
|
char* msg_inf_error_cid_invalid; /*<<< "CID is not valid" */
|
||||||
|
char* msg_inf_error_cid_missing; /*<<< "CID is not specified" */
|
||||||
|
char* msg_inf_error_cid_taken; /*<<< "CID is taken" */
|
||||||
|
char* msg_inf_error_pid_missing; /*<<< "PID is not specified" */
|
||||||
|
char* msg_inf_error_pid_invalid; /*<<< "PID is invalid" */
|
||||||
|
char* msg_ban_permanently; /*<<< "Banned permanently" */
|
||||||
|
char* msg_ban_temporarily; /*<<< "Banned temporarily" */
|
||||||
|
char* msg_auth_invalid_password; /*<<< "Password is wrong" */
|
||||||
|
char* msg_auth_user_not_found; /*<<< "User not found in password database" */
|
||||||
|
char* msg_error_no_memory; /*<<< "No memory" */
|
||||||
|
char* msg_user_share_size_low; /*<<< "User is not sharing enough" */
|
||||||
|
char* msg_user_share_size_high; /*<<< "User is sharing too much" */
|
||||||
|
char* msg_user_slots_low; /*<<< "User have too few upload slots." */
|
||||||
|
char* msg_user_slots_high; /*<<< "User have too many upload slots." */
|
||||||
|
char* msg_user_hub_limit_low; /*<<< "User is on too few hubs." */
|
||||||
|
char* msg_user_hub_limit_high; /*<<< "User is on too many hubs." */
|
||||||
|
char* msg_user_flood_chat; /*<<< "Chat flood detected, messages are dropped." */
|
||||||
|
char* msg_user_flood_connect; /*<<< "Connect flood detected, connection refused." */
|
||||||
|
char* msg_user_flood_search; /*<<< "Search flood detected, search is stopped." */
|
||||||
|
char* msg_user_flood_update; /*<<< "Update flood detected." */
|
||||||
|
char* msg_user_flood_extras; /*<<< "Flood detected." */
|
||||||
|
char* msg_proto_no_common_hash; /*<<< "No common hash algorithm." */
|
||||||
|
char* msg_proto_obsolete_adc0; /*<<< "Client is using an obsolete ADC protocol version." */
|
||||||
|
};
|
||||||
|
|
||||||
678
src/core/hub.c
678
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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,6 +21,28 @@
|
|||||||
|
|
||||||
struct hub_info* g_hub = 0;
|
struct hub_info* g_hub = 0;
|
||||||
|
|
||||||
|
/* FIXME: Flood control should be done in a plugin! */
|
||||||
|
#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 (WARN) \
|
||||||
|
{ \
|
||||||
|
hub_send_flood_warning(hub, u, hub->config->msg_user_flood_ ## TYPE); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ROUTE_MSG \
|
||||||
|
if (user_is_logged_in(u)) \
|
||||||
|
{ \
|
||||||
|
ret = route_message(hub, u, cmd); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
ret = -1; \
|
||||||
|
} \
|
||||||
|
break;
|
||||||
|
|
||||||
int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* line, size_t length)
|
int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* line, size_t length)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -36,20 +58,33 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
|||||||
{
|
{
|
||||||
switch (cmd->cmd)
|
switch (cmd->cmd)
|
||||||
{
|
{
|
||||||
case ADC_CMD_HSUP: ret = hub_handle_support(hub, u, cmd); break;
|
case ADC_CMD_HSUP:
|
||||||
case ADC_CMD_HPAS: ret = hub_handle_password(hub, u, cmd); break;
|
CHECK_FLOOD(extras, 0);
|
||||||
case ADC_CMD_BINF: ret = hub_handle_info(hub, u, cmd); break;
|
ret = hub_handle_support(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_HPAS:
|
||||||
|
CHECK_FLOOD(extras, 0);
|
||||||
|
ret = hub_handle_password(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_BINF:
|
||||||
|
CHECK_FLOOD(update, 1);
|
||||||
|
ret = hub_handle_info(hub, u, cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
case ADC_CMD_DINF:
|
case ADC_CMD_DINF:
|
||||||
case ADC_CMD_EINF:
|
case ADC_CMD_EINF:
|
||||||
case ADC_CMD_FINF:
|
case ADC_CMD_FINF:
|
||||||
/* these must never be allowed for security reasons,
|
/* these must never be allowed for security reasons, so we ignore them. */
|
||||||
so we ignore them. */
|
CHECK_FLOOD(extras, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ADC_CMD_EMSG:
|
case ADC_CMD_EMSG:
|
||||||
case ADC_CMD_DMSG:
|
case ADC_CMD_DMSG:
|
||||||
case ADC_CMD_BMSG:
|
case ADC_CMD_BMSG:
|
||||||
case ADC_CMD_FMSG:
|
case ADC_CMD_FMSG:
|
||||||
|
CHECK_FLOOD(chat, 1);
|
||||||
ret = hub_handle_chat_message(hub, u, cmd);
|
ret = hub_handle_chat_message(hub, u, cmd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -57,26 +92,42 @@ int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* lin
|
|||||||
case ADC_CMD_DSCH:
|
case ADC_CMD_DSCH:
|
||||||
case ADC_CMD_ESCH:
|
case ADC_CMD_ESCH:
|
||||||
case ADC_CMD_FSCH:
|
case ADC_CMD_FSCH:
|
||||||
|
cmd->priority = -1;
|
||||||
|
if (plugin_handle_search(hub, u, cmd->cache) == st_deny)
|
||||||
|
break;
|
||||||
|
CHECK_FLOOD(search, 1);
|
||||||
|
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;
|
||||||
|
if (plugin_handle_search_result(hub, u, uman_get_user_by_sid(hub, cmd->target), cmd->cache) == st_deny)
|
||||||
|
break;
|
||||||
|
/* CHECK_FLOOD(search, 0); */
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DRCM:
|
case ADC_CMD_DRCM:
|
||||||
|
cmd->priority = -1;
|
||||||
|
if (plugin_handle_revconnect(hub, u, uman_get_user_by_sid(hub, cmd->target)) == st_deny)
|
||||||
|
break;
|
||||||
|
CHECK_FLOOD(connect, 1);
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DCTM:
|
case ADC_CMD_DCTM:
|
||||||
cmd->priority = -1;
|
cmd->priority = -1;
|
||||||
if (hub->config->chat_only && u->credentials < cred_operator)
|
if (plugin_handle_connect(hub, u, uman_get_user_by_sid(hub, cmd->target)) == st_deny)
|
||||||
{
|
|
||||||
/* These below aren't allowed in chat only hubs */
|
|
||||||
break;
|
break;
|
||||||
}
|
CHECK_FLOOD(connect, 1);
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (user_is_logged_in(u))
|
CHECK_FLOOD(extras, 1);
|
||||||
{
|
ROUTE_MSG;
|
||||||
ret = route_message(hub, u, cmd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
adc_msg_free(cmd);
|
adc_msg_free(cmd);
|
||||||
}
|
}
|
||||||
@@ -137,17 +188,51 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
|||||||
if (u->state == state_protocol)
|
if (u->state == state_protocol)
|
||||||
{
|
{
|
||||||
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
/* disconnect user. Do not send crap during initial handshake! */
|
||||||
|
hub_disconnect_user(hub, u, quit_logon_error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (ok)
|
if (user_flag_get(u, feature_base))
|
||||||
|
{
|
||||||
|
/* User supports ADC/1.0 and a hash we know */
|
||||||
|
if (user_flag_get(u, feature_tiger))
|
||||||
{
|
{
|
||||||
hub_send_handshake(hub, u);
|
hub_send_handshake(hub, u);
|
||||||
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* disconnect user. Do not send crap during initial handshake! */
|
// no common hash algorithm.
|
||||||
|
hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal);
|
||||||
|
hub_disconnect_user(hub, u, quit_protocol_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (user_flag_get(u, feature_bas0))
|
||||||
|
{
|
||||||
|
if (hub->config->obsolete_clients)
|
||||||
|
{
|
||||||
|
hub_send_handshake(hub, u);
|
||||||
|
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* disconnect user for using an obsolete client. */
|
||||||
|
char* tmp = adc_msg_escape(hub->config->msg_proto_obsolete_adc0);
|
||||||
|
struct adc_message* message = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
||||||
|
adc_msg_add_argument(message, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
route_to_user(hub, u, message);
|
||||||
|
adc_msg_free(message);
|
||||||
|
hub_disconnect_user(hub, u, quit_protocol_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not speaking a compatible protocol - just disconnect. */
|
||||||
hub_disconnect_user(hub, u, quit_logon_error);
|
hub_disconnect_user(hub, u, quit_logon_error);
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +247,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);
|
||||||
}
|
}
|
||||||
@@ -181,13 +266,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;
|
||||||
|
|
||||||
if (!message || !user_is_logged_in(u))
|
if (!message)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((cmd->cache[0] == 'B') && (message[0] == '!' || message[0] == '+'))
|
message_decoded = adc_msg_unescape(message);
|
||||||
|
if (!message_decoded)
|
||||||
|
{
|
||||||
|
hub_free(message);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user_is_logged_in(u))
|
||||||
|
{
|
||||||
|
hub_free(message);
|
||||||
|
return 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.
|
||||||
@@ -196,54 +303,56 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
|||||||
if (message[1] == message[0])
|
if (message[1] == message[0])
|
||||||
{
|
{
|
||||||
relay = 1;
|
relay = 1;
|
||||||
int offset = adc_msg_get_arg_offset(cmd);
|
offset = adc_msg_get_arg_offset(cmd);
|
||||||
memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset);
|
memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset);
|
||||||
cmd->length--;
|
cmd->length--;
|
||||||
}
|
}
|
||||||
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, 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))
|
||||||
@@ -285,6 +394,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))
|
||||||
{
|
{
|
||||||
@@ -298,13 +408,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);
|
||||||
@@ -361,39 +471,57 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hub_send_flood_warning(struct hub_info* hub, struct hub_user* u, const char* message)
|
||||||
|
{
|
||||||
|
struct adc_message* msg;
|
||||||
|
char* tmp;
|
||||||
|
|
||||||
|
if (user_flag_get(u, flag_flood))
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg = adc_msg_construct(ADC_CMD_ISTA, 128);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
tmp = adc_msg_escape(message);
|
||||||
|
adc_msg_add_argument(msg, "110");
|
||||||
|
adc_msg_add_argument(msg, tmp);
|
||||||
|
hub_free(tmp);
|
||||||
|
|
||||||
|
route_to_user(hub, u, msg);
|
||||||
|
user_flag_set(u, flag_flood);
|
||||||
|
adc_msg_free(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, user->id.nick);
|
||||||
|
if (lookup1)
|
||||||
|
return status_msg_inf_error_nick_taken;
|
||||||
|
|
||||||
|
lookup2 = uman_get_user_by_cid(hub, 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);
|
assert(hub != NULL);
|
||||||
@@ -410,9 +538,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,6 +634,102 @@ static struct net_connection* start_listening_socket(const char* bind_addr, uint
|
|||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct server_alt_port_data
|
||||||
|
{
|
||||||
|
struct hub_info* hub;
|
||||||
|
struct hub_config* config;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int server_alt_port_start_one(char* line, int count, void* ptr)
|
||||||
|
{
|
||||||
|
struct server_alt_port_data* data = (struct server_alt_port_data*) ptr;
|
||||||
|
|
||||||
|
int port = uhub_atoi(line);
|
||||||
|
struct net_connection* con = start_listening_socket(data->config->server_bind_addr, port, data->config->server_listen_backlog, data->hub);
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
list_append(data->hub->server_alt_ports, con);
|
||||||
|
LOG_INFO("Listening on alternate port %d...", port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_alt_port_start(struct hub_info* hub, struct hub_config* config)
|
||||||
|
{
|
||||||
|
struct server_alt_port_data data;
|
||||||
|
|
||||||
|
if (!config->server_alt_ports || !*config->server_alt_ports)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hub->server_alt_ports = (struct linked_list*) list_create();
|
||||||
|
|
||||||
|
data.hub = hub;
|
||||||
|
data.config = config;
|
||||||
|
|
||||||
|
string_split(config->server_alt_ports, ",", &data, server_alt_port_start_one);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_alt_port_clear(void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) ptr;
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
net_con_close(con);
|
||||||
|
hub_free(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_alt_port_stop(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (hub->server_alt_ports)
|
||||||
|
{
|
||||||
|
list_clear(hub->server_alt_ports, &server_alt_port_clear);
|
||||||
|
list_destroy(hub->server_alt_ports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config)
|
||||||
|
{
|
||||||
|
if (config->tls_enable)
|
||||||
|
{
|
||||||
|
hub->ssl_method = (SSL_METHOD*) SSLv23_method(); /* TLSv1_method() */
|
||||||
|
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
|
||||||
|
|
||||||
|
/* Disable SSLv2 */
|
||||||
|
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
|
||||||
|
SSL_CTX_set_quiet_shutdown(hub->ssl_ctx, 1);
|
||||||
|
|
||||||
|
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
|
||||||
|
{
|
||||||
|
LOG_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;
|
||||||
|
}
|
||||||
|
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unload_ssl_certificates(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (hub->ssl_ctx)
|
||||||
|
{
|
||||||
|
SSL_CTX_free(hub->ssl_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct hub_info* hub_start_service(struct hub_config* config)
|
struct hub_info* hub_start_service(struct hub_config* config)
|
||||||
{
|
{
|
||||||
struct hub_info* hub = 0;
|
struct hub_info* hub = 0;
|
||||||
@@ -525,31 +759,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
if (config->tls_enable)
|
if (!load_ssl_certificates(hub, config))
|
||||||
{
|
{
|
||||||
hub->ssl_method = SSLv23_method(); /* TLSv1_method() */
|
hub_free(hub);
|
||||||
hub->ssl_ctx = SSL_CTX_new(hub->ssl_method);
|
|
||||||
|
|
||||||
/* Disable SSLv2 */
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hub->config = config;
|
hub->config = config;
|
||||||
@@ -582,23 +796,15 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
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)
|
server_alt_port_start(hub, config);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
hub->status = hub_status_running;
|
hub->status = hub_status_running;
|
||||||
|
|
||||||
g_hub = hub;
|
g_hub = hub;
|
||||||
|
|
||||||
|
// Start the hub command sub-system
|
||||||
|
hub->commands = command_initialize(hub);
|
||||||
return hub;
|
return hub;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,33 +813,60 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
{
|
{
|
||||||
LOG_DEBUG("hub_shutdown_service()");
|
LOG_DEBUG("hub_shutdown_service()");
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
unload_ssl_certificates(hub);
|
||||||
|
#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);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub);
|
||||||
hub->status = hub_status_stopped;
|
hub->status = hub_status_stopped;
|
||||||
hub_free(hub->sendbuf);
|
hub_free(hub->sendbuf);
|
||||||
hub_free(hub->recvbuf);
|
hub_free(hub->recvbuf);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SERVER "" PRODUCT "/" VERSION ""
|
int hub_plugins_load(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (!hub->config->file_plugins || !*hub->config->file_plugins)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins));
|
||||||
|
if (!hub->plugins)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (plugin_initialize(hub->config, hub) < 0)
|
||||||
|
{
|
||||||
|
hub_free(hub->plugins);
|
||||||
|
hub->plugins = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_plugins_unload(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (hub->plugins)
|
||||||
|
{
|
||||||
|
plugin_shutdown(hub->plugins);
|
||||||
|
hub_free(hub->plugins);
|
||||||
|
hub->plugins = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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(SERVER); /* FIXME: OOM */
|
char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */
|
||||||
|
|
||||||
hub->acl = acl;
|
hub->acl = acl;
|
||||||
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15 + strlen(server));
|
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15);
|
||||||
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);
|
||||||
@@ -648,54 +881,30 @@ 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)
|
||||||
{
|
{
|
||||||
adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT);
|
adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 25 + strlen(server));
|
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 100 + strlen(server));
|
||||||
if (hub->command_banner)
|
if (hub->command_banner)
|
||||||
{
|
{
|
||||||
tmp = adc_msg_escape("Powered by " SERVER);
|
if (hub->config->show_banner_sys_info)
|
||||||
|
tmp = adc_msg_escape("Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO);
|
||||||
|
else
|
||||||
|
tmp = adc_msg_escape("Powered by " PRODUCT_STRING);
|
||||||
adc_msg_add_argument(hub->command_banner, "000");
|
adc_msg_add_argument(hub->command_banner, "000");
|
||||||
adc_msg_add_argument(hub->command_banner, tmp);
|
adc_msg_add_argument(hub->command_banner, tmp);
|
||||||
hub_free(tmp);
|
hub_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hub_plugins_load(hub) < 0)
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
@@ -703,49 +912,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)
|
||||||
{
|
{
|
||||||
|
hub_plugins_unload(hub);
|
||||||
|
|
||||||
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);
|
||||||
@@ -764,44 +937,56 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
|||||||
{
|
{
|
||||||
struct hub_config* cfg = hub->config;
|
struct hub_config* cfg = hub->config;
|
||||||
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
||||||
if (!cmd) return;
|
struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 512);
|
||||||
char code[4];
|
char code[4];
|
||||||
|
char buf[256];
|
||||||
const char* text = 0;
|
const char* text = 0;
|
||||||
const char* flag = 0;
|
const char* flag = 0;
|
||||||
char* escaped_text = 0;
|
char* escaped_text = 0;
|
||||||
|
int reconnect_time = 0;
|
||||||
|
int redirect = 0;
|
||||||
|
|
||||||
#define STATUS(CODE, MSG, FLAG) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; break
|
if (!cmd || !qui)
|
||||||
|
{
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
adc_msg_free(qui);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STATUS(CODE, MSG, FLAG, RCONTIME, REDIRECT) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; redirect = REDIRECT; break
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
STATUS(11, msg_hub_full, 0);
|
STATUS(11, msg_hub_full, 0, 600, 1); /* FIXME: Proper timeout? */
|
||||||
STATUS(12, msg_hub_disabled, 0);
|
STATUS(12, msg_hub_disabled, 0, -1, 1);
|
||||||
STATUS(26, msg_hub_registered_users_only, 0);
|
STATUS(26, msg_hub_registered_users_only, 0, 0, 1);
|
||||||
STATUS(43, msg_inf_error_nick_missing, 0);
|
STATUS(43, msg_inf_error_nick_missing, 0, 0, 0);
|
||||||
STATUS(43, msg_inf_error_nick_multiple, 0);
|
STATUS(43, msg_inf_error_nick_multiple, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_invalid, 0);
|
STATUS(21, msg_inf_error_nick_invalid, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_long, 0);
|
STATUS(21, msg_inf_error_nick_long, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_short, 0);
|
STATUS(21, msg_inf_error_nick_short, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_spaces, 0);
|
STATUS(21, msg_inf_error_nick_spaces, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_bad_chars, 0);
|
STATUS(21, msg_inf_error_nick_bad_chars, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_not_utf8, 0);
|
STATUS(21, msg_inf_error_nick_not_utf8, 0, 0, 0);
|
||||||
STATUS(22, msg_inf_error_nick_taken, 0);
|
STATUS(22, msg_inf_error_nick_taken, 0, 0, 0);
|
||||||
STATUS(21, msg_inf_error_nick_restricted, 0);
|
STATUS(21, msg_inf_error_nick_restricted, 0, 0, 0);
|
||||||
STATUS(43, msg_inf_error_cid_invalid, "FBID");
|
STATUS(43, msg_inf_error_cid_invalid, "FBID", 0, 0);
|
||||||
STATUS(43, msg_inf_error_cid_missing, "FMID");
|
STATUS(43, msg_inf_error_cid_missing, "FMID", 0, 0);
|
||||||
STATUS(24, msg_inf_error_cid_taken, 0);
|
STATUS(24, msg_inf_error_cid_taken, 0, 0, 0);
|
||||||
STATUS(43, msg_inf_error_pid_missing, "FMPD");
|
STATUS(43, msg_inf_error_pid_missing, "FMPD", 0, 0);
|
||||||
STATUS(27, msg_inf_error_pid_invalid, "FBPD");
|
STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0, 0);
|
||||||
STATUS(31, msg_ban_permanently, 0);
|
STATUS(31, msg_ban_permanently, 0, 0, 0);
|
||||||
STATUS(32, msg_ban_temporarily, "TL600"); /* FIXME: Use a proper timeout */
|
STATUS(32, msg_ban_temporarily, "TL600", 600, 0); /* FIXME: Proper timeout? */
|
||||||
STATUS(23, msg_auth_invalid_password, 0);
|
STATUS(23, msg_auth_invalid_password, 0, 0, 0);
|
||||||
STATUS(20, msg_auth_user_not_found, 0);
|
STATUS(20, msg_auth_user_not_found, 0, 0, 0);
|
||||||
STATUS(30, msg_error_no_memory, 0);
|
STATUS(30, msg_error_no_memory, 0, 0, 0);
|
||||||
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE);
|
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0, 1);
|
||||||
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE);
|
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0, 1);
|
||||||
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
|
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0, 1);
|
||||||
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
|
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0, 1);
|
||||||
STATUS(43, msg_user_hub_limit_low, 0);
|
STATUS(43, msg_user_hub_limit_low, 0, 0, 1);
|
||||||
STATUS(43, msg_user_hub_limit_high, 0);
|
STATUS(43, msg_user_hub_limit_high, 0, 0, 1);
|
||||||
|
STATUS(47, msg_proto_no_common_hash, 0, -1, 1);
|
||||||
|
STATUS(40, msg_proto_obsolete_adc0, 0, -1, 1);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
|
|
||||||
@@ -810,16 +995,37 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
|||||||
adc_msg_add_argument(cmd, code);
|
adc_msg_add_argument(cmd, code);
|
||||||
adc_msg_add_argument(cmd, escaped_text);
|
adc_msg_add_argument(cmd, escaped_text);
|
||||||
|
|
||||||
hub_free(escaped_text);
|
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
adc_msg_add_argument(cmd, flag);
|
adc_msg_add_argument(cmd, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
route_to_user(hub, user, cmd);
|
route_to_user(hub, user, cmd);
|
||||||
adc_msg_free(cmd);
|
|
||||||
|
|
||||||
|
if (level >= status_level_fatal)
|
||||||
|
{
|
||||||
|
adc_msg_add_argument(qui, sid_to_string(user->id.sid));
|
||||||
|
|
||||||
|
snprintf(buf, 230, "MS%s", escaped_text);
|
||||||
|
adc_msg_add_argument(qui, buf);
|
||||||
|
|
||||||
|
if (reconnect_time != 0)
|
||||||
|
{
|
||||||
|
snprintf(buf, 10, "TL%d", reconnect_time);
|
||||||
|
adc_msg_add_argument(qui, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redirect && *hub->config->redirect_addr)
|
||||||
|
{
|
||||||
|
snprintf(buf, 255, "RD%s", hub->config->redirect_addr);
|
||||||
|
adc_msg_add_argument(qui, buf);
|
||||||
|
}
|
||||||
|
route_to_user(hub, user, qui);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(escaped_text);
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
adc_msg_free(qui);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
|
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
|
||||||
@@ -857,6 +1063,8 @@ const char* hub_get_status_message(struct hub_info* hub, enum status_message msg
|
|||||||
STATUS(msg_user_slots_high);
|
STATUS(msg_user_slots_high);
|
||||||
STATUS(msg_user_hub_limit_low);
|
STATUS(msg_user_hub_limit_low);
|
||||||
STATUS(msg_user_hub_limit_high);
|
STATUS(msg_user_hub_limit_high);
|
||||||
|
STATUS(msg_proto_no_common_hash);
|
||||||
|
STATUS(msg_proto_obsolete_adc0);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
@@ -896,6 +1104,8 @@ const char* hub_get_status_message_log(struct hub_info* hub, enum status_message
|
|||||||
STATUS(msg_user_slots_high);
|
STATUS(msg_user_slots_high);
|
||||||
STATUS(msg_user_hub_limit_low);
|
STATUS(msg_user_hub_limit_low);
|
||||||
STATUS(msg_user_hub_limit_high);
|
STATUS(msg_user_hub_limit_high);
|
||||||
|
STATUS(msg_proto_no_common_hash);
|
||||||
|
STATUS(msg_proto_obsolete_adc0);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
return "unknown";
|
return "unknown";
|
||||||
@@ -924,12 +1134,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)
|
||||||
@@ -1062,8 +1276,8 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -53,6 +53,10 @@ enum status_message
|
|||||||
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
||||||
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
||||||
|
|
||||||
|
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
|
||||||
|
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -91,6 +95,7 @@ struct hub_logout_info
|
|||||||
struct hub_info
|
struct hub_info
|
||||||
{
|
{
|
||||||
struct net_connection* server;
|
struct net_connection* server;
|
||||||
|
struct linked_list* server_alt_ports;
|
||||||
struct hub_stats stats;
|
struct hub_stats stats;
|
||||||
struct event_queue* queue;
|
struct event_queue* queue;
|
||||||
struct hub_config* config;
|
struct hub_config* config;
|
||||||
@@ -98,17 +103,17 @@ 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. */
|
||||||
|
|
||||||
|
struct command_base* commands; /* Hub command handler */
|
||||||
|
struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
SSL_METHOD* ssl_method;
|
SSL_METHOD* ssl_method;
|
||||||
SSL_CTX* ssl_ctx;
|
SSL_CTX* ssl_ctx;
|
||||||
@@ -145,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.
|
||||||
@@ -197,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
|
||||||
@@ -222,6 +204,11 @@ extern void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u
|
|||||||
*/
|
*/
|
||||||
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
|
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warn user about flooding.
|
||||||
|
*/
|
||||||
|
extern void hub_send_flood_warning(struct hub_info*, struct hub_user* user, const char* message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates memory, initializes the hub based on the configuration,
|
* Allocates memory, initializes the hub based on the configuration,
|
||||||
* and returns a hub handle.
|
* and returns a hub handle.
|
||||||
|
|||||||
@@ -18,35 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.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_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 */
|
||||||
@@ -57,20 +31,11 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
|
|||||||
user_set_state(u, state_normal);
|
user_set_state(u, state_normal);
|
||||||
uman_add(hub, u);
|
uman_add(hub, u);
|
||||||
|
|
||||||
/* Print log message */
|
|
||||||
log_user_login(u);
|
|
||||||
|
|
||||||
/* 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);
|
||||||
@@ -78,23 +43,31 @@ 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)
|
||||||
|
{
|
||||||
|
plugin_log_user_update_error(hub, u, hub_get_status_message_log(hub, msg));
|
||||||
|
hub_send_status(hub, u, msg, status_level_fatal);
|
||||||
|
hub_disconnect_user(hub, u, quit_update_error);
|
||||||
|
}
|
||||||
|
|
||||||
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
|
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);
|
|
||||||
|
plugin_log_user_logout(hub, user, reason);
|
||||||
hub_logout_log(hub, user);
|
hub_logout_log(hub, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ extern void on_login_success(struct hub_info* hub, struct hub_user* u);
|
|||||||
* This event is triggered whenever a user failed to log in to the hub.
|
* This event is triggered whenever a user failed to log in to the hub.
|
||||||
*/
|
*/
|
||||||
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
||||||
|
extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is triggered whenever a previously logged in user leaves the hub.
|
* This event is triggered whenever a previously logged in user leaves the hub.
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
|||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
debug_msg("hub_sendq_add", msg);
|
debug_msg("hub_sendq_add", msg);
|
||||||
#endif
|
#endif
|
||||||
|
assert(msg->cache && *msg->cache);
|
||||||
list_append(q->queue, msg);
|
list_append(q->queue, msg);
|
||||||
q->size += msg->length;
|
q->size += msg->length;
|
||||||
}
|
}
|
||||||
@@ -143,10 +144,11 @@ void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
|||||||
|
|
||||||
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
int ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -187,7 +187,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use
|
|||||||
* remove any wrong address, and replace it with the correct one
|
* remove any wrong address, and replace it with the correct one
|
||||||
* as seen by the hub.
|
* as seen by the hub.
|
||||||
*/
|
*/
|
||||||
int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
const char* address = user_get_address(user);
|
const char* address = user_get_address(user);
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ int check_network(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_IPV6_UDP_PORT);
|
||||||
@@ -378,7 +378,7 @@ static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct
|
|||||||
ua = adc_msg_unescape(ua_encoded);
|
ua = adc_msg_unescape(ua_encoded);
|
||||||
if (ua)
|
if (ua)
|
||||||
{
|
{
|
||||||
memcpy(user->user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
|
memcpy(user->id.user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
|
||||||
hub_free(ua);
|
hub_free(ua);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,7 +429,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 +446,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 +456,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 +466,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 +476,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);
|
||||||
@@ -526,7 +526,6 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the expected credentials, and returns 1 if authentication is needed,
|
* Set the expected credentials, and returns 1 if authentication is needed,
|
||||||
* or 0 if not.
|
* or 0 if not.
|
||||||
@@ -536,48 +535,49 @@ 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_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_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,7 +592,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;
|
||||||
}
|
}
|
||||||
@@ -648,7 +648,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
|
|||||||
return ret; \
|
return ret; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
/* Make syntax checks. */
|
/* Make syntax checks. */
|
||||||
INF_CHECK(check_required_login_flags, hub, user, cmd);
|
INF_CHECK(check_required_login_flags, hub, user, cmd);
|
||||||
@@ -675,7 +675,6 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
|||||||
/* Private ID must never be broadcasted - drop it! */
|
/* Private ID must never be broadcasted - drop it! */
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||||
|
|
||||||
|
|
||||||
code = set_credentials(hub, user, cmd);
|
code = set_credentials(hub, user, cmd);
|
||||||
|
|
||||||
/* Note: this must be done *after* set_credentials. */
|
/* Note: this must be done *after* set_credentials. */
|
||||||
@@ -715,6 +714,7 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
|||||||
*/
|
*/
|
||||||
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||||
if (!cmd) return -1; /* OOM */
|
if (!cmd) return -1; /* OOM */
|
||||||
|
|
||||||
@@ -737,7 +737,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = hub_handle_info_login(hub, user, cmd);
|
ret = hub_handle_info_login(hub, user, cmd);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
on_login_failure(hub, user, ret);
|
on_login_failure(hub, user, ret);
|
||||||
@@ -775,8 +775,14 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME - What if limits are not met ? */
|
ret = check_limits(hub, user, cmd);
|
||||||
check_limits(hub, user, cmd);
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
on_update_failure(hub, user, ret);
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
strip_network(user, cmd);
|
strip_network(user, cmd);
|
||||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||||
|
|
||||||
@@ -792,3 +798,5 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
|
|
||||||
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-2010, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
|
||||||
|
|
||||||
static int arg_verbose = 5;
|
static int arg_verbose = 5;
|
||||||
static int arg_fork = 0;
|
static int arg_fork = 0;
|
||||||
static int arg_check_config = 0;
|
static int arg_check_config = 0;
|
||||||
@@ -77,12 +76,14 @@ static int signals[] =
|
|||||||
void setup_signal_handlers(struct hub_info* hub)
|
void setup_signal_handlers(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
sigset_t sig_set;
|
sigset_t sig_set;
|
||||||
sigemptyset(&sig_set);
|
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sigemptyset(&sig_set);
|
||||||
act.sa_mask = sig_set;
|
act.sa_mask = sig_set;
|
||||||
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
||||||
act.sa_handler = hub_handle_signal;
|
act.sa_handler = hub_handle_signal;
|
||||||
int i = 0;
|
|
||||||
for (i = 0; signals[i]; i++)
|
for (i = 0; signals[i]; i++)
|
||||||
{
|
{
|
||||||
if (sigaction(signals[i], &act, 0) != 0)
|
if (sigaction(signals[i], &act, 0) != 0)
|
||||||
@@ -113,6 +114,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)
|
||||||
@@ -188,8 +194,8 @@ int check_configuration(int dump)
|
|||||||
|
|
||||||
void print_version()
|
void print_version()
|
||||||
{
|
{
|
||||||
fprintf(stdout, "" PRODUCT " " VERSION "\n");
|
fprintf(stdout, PRODUCT_STRING "\n");
|
||||||
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
|
fprintf(stdout, COPYRIGHT "\n"
|
||||||
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,41 +24,16 @@
|
|||||||
/* FIXME: This should not be needed! */
|
/* FIXME: This should not be needed! */
|
||||||
extern struct hub_info* g_hub;
|
extern struct hub_info* g_hub;
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
void debug_sendq_send(struct hub_user* user, int sent, int total)
|
|
||||||
{
|
|
||||||
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->connection->sd, sent, total);
|
|
||||||
if (sent == -1)
|
|
||||||
{
|
|
||||||
int err = net_error();
|
|
||||||
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_sendq_recv(struct hub_user* user, int received, int max, const char* buffer)
|
|
||||||
{
|
|
||||||
LOG_DUMP("RECV: %d/%d bytes\n", received, (int) max);
|
|
||||||
if (received == -1)
|
|
||||||
{
|
|
||||||
int err = net_error();
|
|
||||||
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
|
|
||||||
}
|
|
||||||
else if (received > 0)
|
|
||||||
{
|
|
||||||
char* data = hub_malloc_zero(received + 1);
|
|
||||||
memcpy(data, buffer, received);
|
|
||||||
LOG_DUMP("RECV: \"%s\"\n", data);
|
|
||||||
hub_free(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 hub_recvq* q = user->recv_queue;
|
||||||
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
|
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
|
||||||
ssize_t size = net_con_recv(user->connection, buf, MAX_RECV_BUF);
|
ssize_t size;
|
||||||
|
|
||||||
|
if (user_flag_get(user, flag_maxbuf))
|
||||||
|
buf_size = 0;
|
||||||
|
size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size);
|
||||||
|
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
buf_size += size;
|
buf_size += size;
|
||||||
@@ -113,7 +88,7 @@ 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) g_hub->config->max_recv_buffer)
|
||||||
{
|
{
|
||||||
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
||||||
}
|
}
|
||||||
@@ -200,15 +175,19 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
struct hub_info* hub = (struct hub_info*) arg;
|
struct hub_info* hub = (struct hub_info*) arg;
|
||||||
struct hub_probe* probe = 0;
|
struct hub_probe* probe = 0;
|
||||||
struct ip_addr_encap ipaddr;
|
struct ip_addr_encap ipaddr;
|
||||||
const char* addr;
|
|
||||||
int server_fd = net_con_get_sd(con);
|
int server_fd = net_con_get_sd(con);
|
||||||
|
plugin_st status;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -219,24 +198,21 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = ip_convert_to_string(&ipaddr);
|
status = plugin_check_ip_early(hub, &ipaddr);
|
||||||
|
if (status == st_deny)
|
||||||
/* FIXME: Should have a plugin log this */
|
|
||||||
LOG_TRACE("Got connection from %s", addr);
|
|
||||||
|
|
||||||
/* FIXME: A plugin should perform this check: is IP banned? */
|
|
||||||
if (acl_is_ip_banned(hub->acl, addr))
|
|
||||||
{
|
{
|
||||||
LOG_INFO("Denied [%s] (IP banned)", addr);
|
plugin_log_connection_denied(hub, &ipaddr);
|
||||||
net_con_close(con);
|
net_close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin_log_connection_accepted(hub, &ipaddr);
|
||||||
|
|
||||||
probe = probe_create(hub, fd, &ipaddr);
|
probe = probe_create(hub, fd, &ipaddr);
|
||||||
if (!probe)
|
if (!probe)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||||
net_con_close(con);
|
net_close(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
162
src/core/plugincallback.c
Normal file
162
src/core/plugincallback.c
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "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)
|
||||||
|
{
|
||||||
|
struct plugin_callback_data* data;
|
||||||
|
uhub_assert(plugin && plugin->handle && plugin->handle->internals);
|
||||||
|
data = (struct plugin_callback_data*) plugin->handle->internals;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
cmdh = (struct plugin_command_handle*) list_get_first(data->commands);
|
||||||
|
while (cmdh)
|
||||||
|
{
|
||||||
|
if (strcmp(cmdh->prefix, cmd->prefix) == 0)
|
||||||
|
return cmdh->handler(plugin, puser, pcommand);
|
||||||
|
|
||||||
|
cmdh = (struct plugin_command_handle*) list_get_next(data->commands);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct plugin_callback_data* plugin_callback_data_create()
|
||||||
|
{
|
||||||
|
struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data));
|
||||||
|
LOG_PLUGIN("plugin_callback_data_create()");
|
||||||
|
data->commands = list_create();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_callback_data_destroy(struct plugin_callback_data* data)
|
||||||
|
{
|
||||||
|
LOG_PLUGIN("plugin_callback_data_destroy()");
|
||||||
|
if (data->commands)
|
||||||
|
{
|
||||||
|
uhub_assert(list_size(data->commands) == 0);
|
||||||
|
list_destroy(data->commands);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hub_user* convert_user_type(struct plugin_user* user)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// struct plugin_callback_data* data = get_callback_data(plugin);
|
||||||
|
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_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
|
||||||
|
{
|
||||||
|
// struct plugin_callback_data* data = get_callback_data(plugin);
|
||||||
|
char code_str[4];
|
||||||
|
char* 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)
|
||||||
|
{
|
||||||
|
// struct plugin_callback_data* data = get_callback_data(plugin);
|
||||||
|
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);
|
||||||
|
printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
|
||||||
|
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;
|
||||||
|
|
||||||
|
printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
|
||||||
|
list_remove(data->commands, cmdh);
|
||||||
|
command_del(plugin_get_hub(plugin)->commands, command);
|
||||||
|
hub_free(command);
|
||||||
|
cmdh->internal_handle = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void plugin_register_callback_functions(struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
handle->hub.send_message = cbfunc_send_message;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_unregister_callback_functions(struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
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-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_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_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 */
|
||||||
197
src/core/plugininvoke.c
Normal file
197
src/core/plugininvoke.c
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
#define PLUGIN_DEBUG(hub, name) LOG_PLUGIN("Invoke %s on %d plugins", name, (int) (hub->plugins ? list_size(hub->plugins->loaded) : -1));
|
||||||
|
|
||||||
|
|
||||||
|
#define INVOKE(HUB, FUNCNAME, CODE) \
|
||||||
|
PLUGIN_DEBUG(HUB, # FUNCNAME) \
|
||||||
|
if (HUB->plugins && HUB->plugins->loaded) \
|
||||||
|
{ \
|
||||||
|
struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(HUB->plugins->loaded); \
|
||||||
|
while (plugin) \
|
||||||
|
{ \
|
||||||
|
if (plugin->funcs.FUNCNAME) \
|
||||||
|
CODE \
|
||||||
|
plugin = (struct 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_INVOKE_STATUS_1(hub, login_check_ip_early, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, login_check_ip_late, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_1(hub, on_connection_accepted, ipaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_1(hub, on_connection_refused, ipaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* who)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_1(hub, on_user_login, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_login_error, user, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_logout, user, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* who, const char* new_nick)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_nick_change, user, new_nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_2(hub, on_user_update_error, user, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* who, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(who);
|
||||||
|
PLUGIN_INVOKE_3(hub, on_user_chat_message, user, message, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(from);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_chat_msg, user, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_3(hub, on_private_msg, user1, user2, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* from, const char* data)
|
||||||
|
{
|
||||||
|
struct plugin_user* user = convert_user_type(from);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_search, user, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_3(hub, on_search_result, user1, user2, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_connect, user1, user2);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
|
||||||
|
{
|
||||||
|
struct plugin_user* user1 = convert_user_type(from);
|
||||||
|
struct plugin_user* user2 = convert_user_type(to);
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_revconnect, user1, user2);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_2(hub, auth_get_user, nickname, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, auth_register_user, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, auth_update_user, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* info)
|
||||||
|
{
|
||||||
|
PLUGIN_INVOKE_STATUS_1(hub, auth_delete_user, info);
|
||||||
|
}
|
||||||
66
src/core/plugininvoke.h
Normal file
66
src/core/plugininvoke.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
struct hub_info;
|
||||||
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
/* All log related functions */
|
||||||
|
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user);
|
||||||
|
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||||
|
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||||
|
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* user, const char* new_nick);
|
||||||
|
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||||
|
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
|
||||||
|
|
||||||
|
/* IP ban related */
|
||||||
|
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||||
|
|
||||||
|
/* Nickname allow/deny handling */
|
||||||
|
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);
|
||||||
|
plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick);
|
||||||
|
|
||||||
|
/* Handle chat messages */
|
||||||
|
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
|
||||||
|
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags);
|
||||||
|
|
||||||
|
/* Handle searches */
|
||||||
|
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* user, const char* data);
|
||||||
|
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data);
|
||||||
|
|
||||||
|
/* Handle p2p connections */
|
||||||
|
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
|
||||||
|
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
|
||||||
|
|
||||||
|
/* Authentication related */
|
||||||
|
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info);
|
||||||
|
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* user);
|
||||||
|
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* user);
|
||||||
|
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* user);
|
||||||
|
|
||||||
|
#endif // HAVE_UHUB_PLUGIN_INVOKE_H
|
||||||
|
|
||||||
258
src/core/pluginloader.c
Normal file
258
src/core/pluginloader.c
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
struct plugin_callback_data;
|
||||||
|
|
||||||
|
struct plugin_hub_internals
|
||||||
|
{
|
||||||
|
struct hub_info* hub;
|
||||||
|
plugin_unregister_f unregister; /* The unregister function. */
|
||||||
|
struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
struct plugin_hub_internals* internals;
|
||||||
|
assert(handle && handle->handle && handle->handle->internals);
|
||||||
|
internals = (struct plugin_hub_internals*) handle->handle->internals;
|
||||||
|
return internals;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct uhub_plugin* plugin_open(const char* filename)
|
||||||
|
{
|
||||||
|
struct uhub_plugin* plugin;
|
||||||
|
LOG_PLUGIN("plugin_open: \"%s\"", filename);
|
||||||
|
|
||||||
|
plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin));
|
||||||
|
if (!plugin)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
plugin->handle = dlopen(filename, RTLD_LAZY);
|
||||||
|
#else
|
||||||
|
plugin->handle = LoadLibraryExA(filename, NULL, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!plugin->handle)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror());
|
||||||
|
#else
|
||||||
|
LOG_ERROR("Unable to open plugin %s: %d", filename, GetLastError());
|
||||||
|
#endif
|
||||||
|
hub_free(plugin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin->filename = strdup(filename);
|
||||||
|
plugin->internals = hub_malloc_zero(sizeof(struct plugin_hub_internals));
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_close(struct uhub_plugin* plugin)
|
||||||
|
{
|
||||||
|
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
|
||||||
|
|
||||||
|
LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename);
|
||||||
|
plugin_callback_data_destroy(internals->callback_data);
|
||||||
|
hub_free(internals);
|
||||||
|
plugin->internals = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
dlclose(plugin->handle);
|
||||||
|
#else
|
||||||
|
FreeLibrary((HMODULE) plugin->handle);
|
||||||
|
#endif
|
||||||
|
hub_free(plugin->filename);
|
||||||
|
hub_free(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
void* addr = dlsym(plugin->handle, symbol);
|
||||||
|
return addr;
|
||||||
|
#else
|
||||||
|
FARPROC addr = GetProcAddress((HMODULE) plugin->handle, symbol);
|
||||||
|
return (void*) addr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub)
|
||||||
|
{
|
||||||
|
plugin_register_f register_f;
|
||||||
|
plugin_unregister_f unregister_f;
|
||||||
|
int ret;
|
||||||
|
struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle));
|
||||||
|
struct uhub_plugin* plugin = plugin_open(filename);
|
||||||
|
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
|
||||||
|
|
||||||
|
if (!plugin)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
plugin_close(plugin);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->handle = plugin;
|
||||||
|
register_f = plugin_lookup_symbol(plugin, "plugin_register");
|
||||||
|
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
|
||||||
|
|
||||||
|
// register hub internals
|
||||||
|
internals->unregister = unregister_f;
|
||||||
|
internals->hub = hub;
|
||||||
|
internals->callback_data = plugin_callback_data_create();
|
||||||
|
|
||||||
|
// setup callback functions, where the plugin can contact the hub.
|
||||||
|
plugin_register_callback_functions(handle);
|
||||||
|
|
||||||
|
if (register_f && unregister_f)
|
||||||
|
{
|
||||||
|
ret = register_f(handle, config);
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs))
|
||||||
|
{
|
||||||
|
LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version);
|
||||||
|
LOG_PLUGIN("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("Unable to load plugin: %s - API version mistmatch", filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("Unable to load plugin: %s - Failed to initialize: %s", filename, handle->error_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin_close(plugin);
|
||||||
|
hub_free(handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_unload(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct plugin_hub_internals* internals = get_internals(plugin);
|
||||||
|
plugin_unregister_callback_functions(plugin);
|
||||||
|
internals->unregister(plugin);
|
||||||
|
plugin_close(plugin->handle);
|
||||||
|
hub_free(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int plugin_parse_line(char* line, int line_count, void* ptr_data)
|
||||||
|
{
|
||||||
|
struct hub_info* hub = (struct hub_info*) ptr_data;
|
||||||
|
struct uhub_plugins* handle = hub->plugins;
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
struct plugin_handle* plugin;
|
||||||
|
char *directive, *soname, *params;
|
||||||
|
|
||||||
|
if (cfg_token_count(tokens) == 0)
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg_token_count(tokens) < 2)
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
directive = cfg_token_get_first(tokens);
|
||||||
|
soname = cfg_token_get_next(tokens);
|
||||||
|
params = cfg_token_get_next(tokens);
|
||||||
|
|
||||||
|
if (strcmp(directive, "plugin") == 0 && soname && *soname)
|
||||||
|
{
|
||||||
|
if (!params)
|
||||||
|
params = "";
|
||||||
|
|
||||||
|
LOG_PLUGIN("Load plugin: \"%s\", params=\"%s\"", soname, params);
|
||||||
|
plugin = plugin_load(soname, params, hub);
|
||||||
|
if (plugin)
|
||||||
|
{
|
||||||
|
list_append(handle->loaded, plugin);
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_initialize(struct hub_config* config, struct hub_info* hub)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
hub->plugins->loaded = list_create();
|
||||||
|
if (!hub->plugins->loaded)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (config)
|
||||||
|
{
|
||||||
|
if (!*config->file_plugins)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = file_read_lines(config->file_plugins, hub, &plugin_parse_line);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
list_clear(hub->plugins->loaded, hub_free);
|
||||||
|
list_destroy(hub->plugins->loaded);
|
||||||
|
hub->plugins->loaded = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plugin_shutdown(struct uhub_plugins* handle)
|
||||||
|
{
|
||||||
|
struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(handle->loaded);
|
||||||
|
while (plugin)
|
||||||
|
{
|
||||||
|
list_remove(handle->loaded, plugin);
|
||||||
|
plugin_unload(plugin);
|
||||||
|
plugin = (struct plugin_handle*) list_get_first(handle->loaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_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;
|
||||||
|
}
|
||||||
|
|
||||||
60
src/core/pluginloader.h
Normal file
60
src/core/pluginloader.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_LOADER_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_LOADER_H
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
struct hub_config;
|
||||||
|
struct hub_info;
|
||||||
|
struct linked_list;
|
||||||
|
struct plugin_handle;
|
||||||
|
|
||||||
|
struct uhub_plugin
|
||||||
|
{
|
||||||
|
void* handle;
|
||||||
|
plugin_unregister_f unregister;
|
||||||
|
char* filename;
|
||||||
|
void* internals; // Hub internal stuff
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uhub_plugins
|
||||||
|
{
|
||||||
|
struct linked_list* loaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
// High level plugin loader ode
|
||||||
|
extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub);
|
||||||
|
extern void plugin_unload(struct plugin_handle* plugin);
|
||||||
|
|
||||||
|
// extern void plugin_unload(struct plugin_handle*);
|
||||||
|
extern int plugin_initialize(struct hub_config* config, struct hub_info* hub);
|
||||||
|
extern void plugin_shutdown(struct uhub_plugins* handle);
|
||||||
|
|
||||||
|
// Low level plugin loader code (used internally)
|
||||||
|
extern struct uhub_plugin* plugin_open(const char* filename);
|
||||||
|
extern void plugin_close(struct uhub_plugin*);
|
||||||
|
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
|
||||||
|
|
||||||
|
// Used internally only
|
||||||
|
extern struct hub_info* plugin_get_hub(struct plugin_handle*);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */
|
||||||
|
|
||||||
@@ -46,6 +46,24 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Probed ADC");
|
LOG_TRACE("Probed ADC");
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
|
||||||
|
{
|
||||||
|
LOG_TRACE("Not TLS connection - closing connection.");
|
||||||
|
if (*probe->hub->config->tls_require_redirect_addr)
|
||||||
|
{
|
||||||
|
char buf[512];
|
||||||
|
ssize_t len = snprintf(buf, sizeof(buf), "ISUP " ADC_PROTO_SUPPORT "\nISID AAAB\nIINF NIRedirecting...\nIQUI AAAB RD%s\n", probe->hub->config->tls_require_redirect_addr);
|
||||||
|
net_con_send(con, buf, (size_t) len);
|
||||||
|
LOG_TRACE("Not TLS connection - Redirecting to %s.", probe->hub->config->tls_require_redirect_addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_TRACE("Not TLS connection - closing connection.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (user_create(probe->hub, probe->connection, &probe->addr))
|
if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||||
{
|
{
|
||||||
probe->connection = 0;
|
probe->connection = 0;
|
||||||
@@ -53,9 +71,8 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
probe_destroy(probe);
|
probe_destroy(probe);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 */
|
||||||
@@ -75,15 +92,10 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
|
|||||||
{
|
{
|
||||||
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[1], (int) probe_recvbuf[2]);
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
probe_destroy(probe);
|
probe_destroy(probe);
|
||||||
@@ -99,6 +111,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);
|
||||||
@@ -110,6 +124,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);
|
||||||
|
|||||||
@@ -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,7 +75,7 @@ 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;
|
||||||
@@ -106,6 +106,8 @@ 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);
|
||||||
|
|
||||||
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||||
{
|
{
|
||||||
/* Perform oportunistic write */
|
/* Perform oportunistic write */
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, s
|
|||||||
|
|
||||||
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
||||||
user_set_state(user, state_protocol);
|
user_set_state(user, state_protocol);
|
||||||
|
|
||||||
|
flood_control_reset(&user->flood_chat);
|
||||||
|
flood_control_reset(&user->flood_connect);
|
||||||
|
flood_control_reset(&user->flood_search);
|
||||||
|
flood_control_reset(&user->flood_update);
|
||||||
|
flood_control_reset(&user->flood_extras);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +71,12 @@ void user_destroy(struct hub_user* user)
|
|||||||
hub_recvq_destroy(user->recv_queue);
|
hub_recvq_destroy(user->recv_queue);
|
||||||
hub_sendq_destroy(user->send_queue);
|
hub_sendq_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);
|
||||||
hub_free(user);
|
hub_free(user);
|
||||||
@@ -83,7 +95,14 @@ void user_set_state(struct hub_user* user, enum user_state state)
|
|||||||
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
adc_msg_free(user->info);
|
adc_msg_free(user->info);
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
user->info = adc_msg_incref(cmd);
|
user->info = adc_msg_incref(cmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user->info = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
||||||
@@ -127,10 +146,9 @@ static int convert_support_fourcc(int fourcc)
|
|||||||
{
|
{
|
||||||
switch (fourcc)
|
switch (fourcc)
|
||||||
{
|
{
|
||||||
case FOURCC('B','A','S','0'): /* Obsolete */
|
case FOURCC('B','A','S','0'):
|
||||||
#ifndef OLD_ADC_SUPPORT
|
return feature_bas0;
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
case FOURCC('B','A','S','E'):
|
case FOURCC('B','A','S','E'):
|
||||||
return feature_base;
|
return feature_base;
|
||||||
|
|
||||||
@@ -163,6 +181,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;
|
||||||
@@ -276,18 +298,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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -297,19 +308,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)
|
||||||
@@ -336,6 +335,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
|||||||
case quit_socket_error: return "socket error"; break;
|
case quit_socket_error: return "socket error"; break;
|
||||||
case quit_protocol_error: return "protocol error"; break;
|
case quit_protocol_error: return "protocol error"; break;
|
||||||
case quit_logon_error: return "login error"; break;
|
case quit_logon_error: return "login error"; break;
|
||||||
|
case quit_update_error: return "update error"; break;
|
||||||
case quit_hub_disabled: return "hub disabled"; break;
|
case quit_hub_disabled: return "hub disabled"; break;
|
||||||
case quit_ghost_timeout: return "ghost"; break;
|
case quit_ghost_timeout: return "ghost"; break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
struct hub_info;
|
struct hub_info;
|
||||||
struct hub_iobuf;
|
struct hub_iobuf;
|
||||||
|
struct flood_control;
|
||||||
|
|
||||||
enum user_state
|
enum user_state
|
||||||
{
|
{
|
||||||
@@ -45,6 +46,8 @@ enum user_flags
|
|||||||
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
||||||
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
||||||
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
|
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
|
||||||
|
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
|
||||||
|
flag_flood = 0x00400000, /** User has been notified about flooding. */
|
||||||
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
||||||
flag_ignore = 0x01000000, /** Ignore further reads */
|
flag_ignore = 0x01000000, /** Ignore further reads */
|
||||||
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
||||||
@@ -68,8 +71,9 @@ enum user_quit_reason
|
|||||||
quit_socket_error = 7, /** A socket error occured */
|
quit_socket_error = 7, /** A socket error occured */
|
||||||
quit_protocol_error = 8, /** Fatal protocol error */
|
quit_protocol_error = 8, /** Fatal protocol error */
|
||||||
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
||||||
quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */
|
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
|
||||||
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */
|
quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */
|
||||||
|
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 apropriate string for the given quit reason */
|
||||||
@@ -78,8 +82,9 @@ 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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,11 +106,10 @@ 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 */
|
||||||
|
enum auth_credentials credentials; /** see enum user_credentials */
|
||||||
|
enum user_state state; /** see enum user_state */
|
||||||
uint32_t flags; /** see enum user_features */
|
uint32_t flags; /** see enum user_features */
|
||||||
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
|
||||||
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 */
|
||||||
@@ -115,6 +119,11 @@ struct hub_user
|
|||||||
struct hub_user_limits limits; /** Data used for limitation */
|
struct hub_user_limits limits; /** Data used for limitation */
|
||||||
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
||||||
|
|
||||||
|
struct flood_control flood_chat;
|
||||||
|
struct flood_control flood_connect;
|
||||||
|
struct flood_control flood_search;
|
||||||
|
struct flood_control flood_update;
|
||||||
|
struct flood_control flood_extras;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,9 +93,12 @@ int uman_init(struct hub_info* hub)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (net_backend_get_timeout_queue())
|
||||||
|
{
|
||||||
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||||
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
||||||
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
||||||
|
}
|
||||||
|
|
||||||
hub->users = users;
|
hub->users = users;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -107,8 +110,11 @@ int uman_shutdown(struct hub_info* hub)
|
|||||||
if (!hub || !hub->users)
|
if (!hub || !hub->users)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (net_backend_get_timeout_queue())
|
||||||
|
{
|
||||||
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
||||||
hub_free(hub->users->timeout);
|
hub_free(hub->users->timeout);
|
||||||
|
}
|
||||||
|
|
||||||
if (hub->users->list)
|
if (hub->users->list)
|
||||||
{
|
{
|
||||||
@@ -218,8 +224,9 @@ size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, st
|
|||||||
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* target)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
struct hub_user* user;
|
||||||
user_flag_set(target, flag_user_list);
|
user_flag_set(target, flag_user_list);
|
||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
|
user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
|
||||||
while (user)
|
while (user)
|
||||||
{
|
{
|
||||||
if (user_is_logged_in(user))
|
if (user_is_logged_in(user))
|
||||||
@@ -241,7 +248,6 @@ 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* leaving)
|
||||||
{
|
{
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
|
||||||
@@ -255,7 +261,6 @@ 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_info* hub, struct hub_user* user)
|
||||||
{
|
{
|
||||||
sid_t sid = sid_alloc(hub->users->sids, user);
|
sid_t sid = sid_alloc(hub->users->sids, user);
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
|
|
||||||
#include "network/connection.h"
|
#include "network/connection.h"
|
||||||
|
|
||||||
|
struct net_backend;
|
||||||
|
struct net_connection;
|
||||||
|
|
||||||
struct net_cleanup_handler
|
struct net_cleanup_handler
|
||||||
{
|
{
|
||||||
size_t num;
|
size_t num;
|
||||||
@@ -28,6 +31,168 @@ struct net_cleanup_handler
|
|||||||
struct net_connection** queue;
|
struct net_connection** queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct net_backend
|
||||||
|
{
|
||||||
|
struct net_backend_common common;
|
||||||
|
time_t now; /* the time now (used for timeout handling) */
|
||||||
|
struct timeout_queue timeout_queue; /* used for timeout handling */
|
||||||
|
struct net_cleanup_handler* cleaner; /* handler to cleanup connections at a safe point */
|
||||||
|
struct net_backend_handler handler; /* backend event handler */
|
||||||
|
struct net_backend* data; /* backend specific data */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct net_backend* g_backend;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_EPOLL
|
||||||
|
extern struct net_backend* net_backend_init_epoll(struct net_backend_handler*, struct net_backend_common*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_KQUEUE
|
||||||
|
extern struct net_backend* net_backend_init_kqueue(struct net_backend_handler*, struct net_backend_common*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SELECT
|
||||||
|
extern struct net_backend* net_backend_init_select(struct net_backend_handler*, struct net_backend_common*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static net_backend_init_t net_backend_init_funcs[] = {
|
||||||
|
#ifdef USE_EPOLL
|
||||||
|
net_backend_init_epoll,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_KQUEUE
|
||||||
|
net_backend_init_kqueue,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SELECT
|
||||||
|
net_backend_init_select,
|
||||||
|
#endif
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
int net_backend_init()
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
g_backend = (struct net_backend*) hub_malloc_zero(sizeof(struct net_backend));
|
||||||
|
g_backend->common.num = 0;
|
||||||
|
g_backend->common.max = net_get_max_sockets();
|
||||||
|
g_backend->now = time(0);
|
||||||
|
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 120); /* FIXME: max 120 secs! */
|
||||||
|
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
||||||
|
|
||||||
|
for (n = 0; net_backend_init_funcs[n]; n++)
|
||||||
|
{
|
||||||
|
g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common);
|
||||||
|
if (g_backend->data)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Initialized %s network backend.", g_backend->handler.backend_name());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_FATAL("Unable to find a suitable network backend");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown()
|
||||||
|
{
|
||||||
|
g_backend->handler.backend_shutdown(g_backend->data);
|
||||||
|
timeout_queue_shutdown(&g_backend->timeout_queue);
|
||||||
|
net_cleanup_shutdown(g_backend->cleaner);
|
||||||
|
hub_free(g_backend);
|
||||||
|
g_backend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
||||||
|
{
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
net_con_update(con, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_update(struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
g_backend->handler.con_mod(g_backend->data, con, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create()
|
||||||
|
{
|
||||||
|
return g_backend->handler.con_create(g_backend->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeout_queue* net_backend_get_timeout_queue()
|
||||||
|
{
|
||||||
|
if (!g_backend)
|
||||||
|
return 0;
|
||||||
|
return &g_backend->timeout_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the network backend.
|
||||||
|
*/
|
||||||
|
int net_backend_process()
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||||
|
|
||||||
|
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
||||||
|
|
||||||
|
g_backend->now = time(0);
|
||||||
|
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
||||||
|
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("backend error.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_backend->handler.backend_process(g_backend->data, res);
|
||||||
|
|
||||||
|
net_cleanup_process(g_backend->cleaner);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t net_get_time()
|
||||||
|
{
|
||||||
|
return g_backend->now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
|
||||||
|
{
|
||||||
|
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
||||||
|
|
||||||
|
net_set_nonblocking(con->sd, 1);
|
||||||
|
net_set_nosigpipe(con->sd, 1);
|
||||||
|
|
||||||
|
g_backend->handler.con_add(g_backend->data, con, events);
|
||||||
|
g_backend->common.num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_close(struct net_connection* con)
|
||||||
|
{
|
||||||
|
if (con->flags & NET_CLEANUP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_backend->common.num--;
|
||||||
|
net_con_clear_timeout(con);
|
||||||
|
|
||||||
|
g_backend->handler.con_del(g_backend->data, con);
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (con->ssl)
|
||||||
|
{
|
||||||
|
SSL_shutdown(con->ssl);
|
||||||
|
SSL_clear(con->ssl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
net_close(con->sd);
|
||||||
|
con->sd = -1;
|
||||||
|
|
||||||
|
net_cleanup_delayed_free(g_backend->cleaner, con);
|
||||||
|
}
|
||||||
|
|
||||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max)
|
struct net_cleanup_handler* net_cleanup_initialize(size_t max)
|
||||||
{
|
{
|
||||||
struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler));
|
struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler));
|
||||||
@@ -39,6 +204,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);
|
||||||
}
|
}
|
||||||
@@ -56,7 +222,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,14 +20,50 @@
|
|||||||
#ifndef HAVE_UHUB_NETWORK_BACKEND_H
|
#ifndef HAVE_UHUB_NETWORK_BACKEND_H
|
||||||
#define HAVE_UHUB_NETWORK_BACKEND_H
|
#define HAVE_UHUB_NETWORK_BACKEND_H
|
||||||
|
|
||||||
|
struct net_backend;
|
||||||
|
struct net_backend_common;
|
||||||
|
struct net_backend_handler;
|
||||||
struct net_cleanup_handler;
|
struct net_cleanup_handler;
|
||||||
struct net_connection;
|
struct net_connection;
|
||||||
|
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct net_backend* (*net_backend_init_t)(struct net_backend_handler* handler, struct net_backend_common* common);
|
||||||
|
typedef int (*net_backend_poll)(struct net_backend*, int ms);
|
||||||
|
typedef void (*net_backend_proc)(struct net_backend*, int res);
|
||||||
|
typedef void (*net_backend_destroy)(struct net_backend*);
|
||||||
|
|
||||||
|
typedef struct net_connection* (*net_con_backend_create)(struct net_backend*);
|
||||||
|
typedef void (*net_con_backend_init)(struct net_backend*, struct net_connection*, int sd, net_connection_cb callback, const void* ptr);
|
||||||
|
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_del)(struct net_backend*,struct net_connection*);
|
||||||
|
typedef const char* (*net_con_backend_name)();
|
||||||
|
|
||||||
|
struct net_backend_handler
|
||||||
|
{
|
||||||
|
net_con_backend_name backend_name;
|
||||||
|
net_backend_poll backend_poll;
|
||||||
|
net_backend_proc backend_process;
|
||||||
|
net_backend_destroy backend_shutdown;
|
||||||
|
net_con_backend_create con_create;
|
||||||
|
net_con_backend_init con_init;
|
||||||
|
net_con_backend_add con_add;
|
||||||
|
net_con_backend_mod con_mod;
|
||||||
|
net_con_backend_del con_del;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend_common
|
||||||
|
{
|
||||||
|
size_t num; /* number of connections monitored by the backend */
|
||||||
|
size_t max; /* max number of connections that can be monitored */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the network backend.
|
* Initialize the network backend.
|
||||||
* Returns 1 on success, or 0 on failure.
|
* Returns 1 on success, or 0 on failure.
|
||||||
*/
|
*/
|
||||||
extern int net_backend_initialize();
|
extern int net_backend_init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shutdown the network connection backend.
|
* Shutdown the network connection backend.
|
||||||
@@ -39,6 +75,11 @@ extern void net_backend_shutdown();
|
|||||||
*/
|
*/
|
||||||
extern int net_backend_process();
|
extern int net_backend_process();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current time.
|
||||||
|
*/
|
||||||
|
time_t net_get_time();
|
||||||
|
|
||||||
extern struct timeout_queue* net_backend_get_timeout_queue();
|
extern struct timeout_queue* net_backend_get_timeout_queue();
|
||||||
|
|
||||||
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ static int handle_openssl_error(struct net_connection* con, int ret)
|
|||||||
con->ssl_state = tls_st_error;
|
con->ssl_state = tls_st_error;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +122,11 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
|
|||||||
if (ssl_mode == net_con_ssl_mode_server)
|
if (ssl_mode == net_con_ssl_mode_server)
|
||||||
{
|
{
|
||||||
ssl = SSL_new(ssl_ctx);
|
ssl = SSL_new(ssl_ctx);
|
||||||
|
if (!ssl)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Unable to create new SSL stream\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
SSL_set_fd(ssl, con->sd);
|
SSL_set_fd(ssl, con->sd);
|
||||||
net_con_set_ssl(con, ssl);
|
net_con_set_ssl(con, ssl);
|
||||||
return net_con_ssl_accept(con);
|
return net_con_ssl_accept(con);
|
||||||
@@ -137,6 +141,10 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
|
|||||||
}
|
}
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
void net_stats_add_tx(size_t bytes);
|
||||||
|
void net_stats_add_rx(size_t bytes);
|
||||||
|
#endif
|
||||||
|
|
||||||
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
||||||
{
|
{
|
||||||
@@ -148,7 +156,13 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
|||||||
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
|
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
if (
|
||||||
|
#ifdef WINSOCK
|
||||||
|
net_error() == WSAEWOULDBLOCK
|
||||||
|
#else
|
||||||
|
net_error() == EWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
|| net_error() == EINTR)
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -161,7 +175,11 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
|||||||
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
{
|
{
|
||||||
return -handle_openssl_error(con, ret);
|
return handle_openssl_error(con, ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
net_stats_add_tx(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -178,7 +196,13 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
|||||||
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 (
|
||||||
|
#ifdef WINSOCK
|
||||||
|
net_error() == WSAEWOULDBLOCK
|
||||||
|
#else
|
||||||
|
net_error() == EWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
|| net_error() == EINTR)
|
||||||
return 0;
|
return 0;
|
||||||
return -net_error();
|
return -net_error();
|
||||||
}
|
}
|
||||||
@@ -198,10 +222,11 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
|||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
net_con_update(con, NET_EVENT_READ);
|
net_con_update(con, NET_EVENT_READ);
|
||||||
|
net_stats_add_rx(ret);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return -handle_openssl_error(con, ret);
|
return handle_openssl_error(con, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -213,7 +238,13 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
|
|||||||
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
|
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
if (
|
||||||
|
#ifdef WINSOCK
|
||||||
|
net_error() == WSAEWOULDBLOCK
|
||||||
|
#else
|
||||||
|
net_error() == EWOULDBLOCK
|
||||||
|
#endif
|
||||||
|
|| net_error() == EINTR)
|
||||||
return 0;
|
return 0;
|
||||||
return -net_error();
|
return -net_error();
|
||||||
}
|
}
|
||||||
@@ -249,6 +280,14 @@ void* net_con_get_ptr(struct net_connection* con)
|
|||||||
return con->ptr;
|
return con->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void net_con_destroy(struct net_connection* con)
|
||||||
|
{
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
SSL_free(con->ssl);
|
||||||
|
#endif
|
||||||
|
hub_free(con);
|
||||||
|
}
|
||||||
|
|
||||||
void net_con_callback(struct net_connection* con, int events)
|
void net_con_callback(struct net_connection* con, int events)
|
||||||
{
|
{
|
||||||
if (con->flags & NET_CLEANUP)
|
if (con->flags & NET_CLEANUP)
|
||||||
|
|||||||
@@ -28,10 +28,6 @@
|
|||||||
#define NET_EVENT_READ 0x0002
|
#define NET_EVENT_READ 0x0002
|
||||||
#define NET_EVENT_WRITE 0x0004
|
#define NET_EVENT_WRITE 0x0004
|
||||||
|
|
||||||
struct net_connection;
|
|
||||||
|
|
||||||
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr);
|
|
||||||
|
|
||||||
struct net_connection
|
struct net_connection
|
||||||
{
|
{
|
||||||
NET_CON_STRUCT_COMMON
|
NET_CON_STRUCT_COMMON
|
||||||
|
|||||||
@@ -33,124 +33,55 @@ struct net_connection_epoll
|
|||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct net_backend
|
struct net_backend_epoll
|
||||||
{
|
{
|
||||||
int epfd;
|
int epfd;
|
||||||
size_t num;
|
|
||||||
size_t max;
|
|
||||||
struct net_connection_epoll** conns;
|
struct net_connection_epoll** conns;
|
||||||
struct epoll_event events[EPOLL_EVBUFFER];
|
struct epoll_event events[EPOLL_EVBUFFER];
|
||||||
time_t now;
|
struct net_backend_common* common;
|
||||||
struct timeout_queue timeout_queue;
|
|
||||||
struct net_cleanup_handler* cleaner;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct net_backend* g_backend = 0;
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
|
||||||
static void net_con_print(const char* prefix, struct net_connection_epoll* con)
|
const char* net_backend_name_epoll()
|
||||||
{
|
{
|
||||||
char buf[512];
|
return "epoll";
|
||||||
int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, ev={ events=%s%s, data.ptr=%p }",
|
|
||||||
prefix, con->sd, con->flags, con->callback, con->ptr, (con->ev.events & EPOLLIN ? "R" : ""),(con->ev.events & EPOLLOUT ? "W" : "") , con->ev.data.ptr);
|
|
||||||
if (con->timeout)
|
|
||||||
{
|
|
||||||
sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(buf + off, ", timeout=NULL");
|
|
||||||
}
|
|
||||||
LOG_TRACE(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int net_backend_poll_epoll(struct net_backend* data, int ms)
|
||||||
* Initialize the network backend.
|
|
||||||
* Returns 1 on success, or 0 on failure.
|
|
||||||
*/
|
|
||||||
int net_backend_initialize()
|
|
||||||
{
|
{
|
||||||
size_t max = net_get_max_sockets();
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
g_backend = hub_malloc(sizeof(struct net_backend));
|
int res = epoll_wait(backend->epfd, backend->events, MIN(backend->common->num, EPOLL_EVBUFFER), ms);
|
||||||
g_backend->epfd = epoll_create(max);
|
if (res == -1 && errno == EINTR)
|
||||||
if (g_backend->epfd == -1)
|
|
||||||
{
|
|
||||||
LOG_WARN("Unable to create epoll socket.");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
return res;
|
||||||
|
|
||||||
g_backend->num = 0;
|
|
||||||
g_backend->max = max;
|
|
||||||
g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * max);
|
|
||||||
memset(g_backend->events, 0, sizeof(g_backend->events));
|
|
||||||
|
|
||||||
g_backend->now = time(0);
|
|
||||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
|
|
||||||
g_backend->cleaner = net_cleanup_initialize(max);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void net_backend_process_epoll(struct net_backend* data, int res)
|
||||||
* Shutdown the network connection backend.
|
|
||||||
*/
|
|
||||||
void net_backend_shutdown()
|
|
||||||
{
|
{
|
||||||
close(g_backend->epfd);
|
int n, ev;
|
||||||
timeout_queue_shutdown(&g_backend->timeout_queue);
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
net_cleanup_shutdown(g_backend->cleaner);
|
|
||||||
hub_free(g_backend->conns);
|
|
||||||
hub_free(g_backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the network backend.
|
|
||||||
*/
|
|
||||||
int net_backend_process()
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
|
||||||
LOG_TRACE("epoll_wait: fd=%d, events=%x, max=%zu, seconds=%d", g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER), (int) secs);
|
|
||||||
int res = epoll_wait(g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER), secs * 1000);
|
|
||||||
|
|
||||||
g_backend->now = time(0);
|
|
||||||
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
|
||||||
|
|
||||||
if (res == -1)
|
|
||||||
{
|
|
||||||
LOG_WARN("epoll_wait returned -1");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (n = 0; n < res; n++)
|
for (n = 0; n < res; n++)
|
||||||
{
|
{
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) g_backend->events[n].data.ptr;
|
struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd];
|
||||||
int ev = 0;
|
if (con)
|
||||||
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
{
|
||||||
if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
ev = 0;
|
||||||
|
if (backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
||||||
|
if (backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
||||||
net_con_callback((struct net_connection*) con, ev);
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
net_cleanup_process(g_backend->cleaner);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timeout_queue* net_backend_get_timeout_queue()
|
struct net_connection* net_con_create_epoll(struct net_backend* data)
|
||||||
{
|
|
||||||
return &g_backend->timeout_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_connection* net_con_create()
|
|
||||||
{
|
{
|
||||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
|
||||||
con->sd = -1;
|
con->sd = -1;
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_destroy(struct net_connection* con)
|
void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
{
|
|
||||||
hub_free(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
|
|
||||||
{
|
{
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
con->sd = sd;
|
con->sd = sd;
|
||||||
@@ -158,35 +89,30 @@ void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb c
|
|||||||
con->callback = callback;
|
con->callback = callback;
|
||||||
con->ev.events = 0;
|
con->ev.events = 0;
|
||||||
con->ptr = (void*) ptr;
|
con->ptr = (void*) ptr;
|
||||||
con->ev.data.ptr = (void*) con;
|
con->ev.data.fd = sd;
|
||||||
|
}
|
||||||
|
|
||||||
net_set_nonblocking(con->sd, 1);
|
void net_con_backend_add_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
net_set_nosigpipe(con->sd, 1);
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = con;
|
||||||
|
|
||||||
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
||||||
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
||||||
|
|
||||||
g_backend->conns[sd] = con;
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
||||||
g_backend->num++;
|
|
||||||
|
|
||||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
|
||||||
{
|
{
|
||||||
LOG_TRACE("epoll_ctl() add failed.");
|
LOG_TRACE("epoll_ctl() add failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
net_con_print("ADD", con);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
void net_con_backend_mod_epoll(struct net_backend* data, 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)
|
|
||||||
{
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
|
||||||
int newev = 0;
|
int newev = 0;
|
||||||
if (events & NET_EVENT_READ) newev |= EPOLLIN;
|
if (events & NET_EVENT_READ) newev |= EPOLLIN;
|
||||||
if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
|
if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
|
||||||
@@ -195,37 +121,67 @@ void net_con_update(struct net_connection* con_, int events)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
con->ev.events = newev;
|
con->ev.events = newev;
|
||||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
||||||
{
|
{
|
||||||
LOG_TRACE("epoll_ctl() modify failed.");
|
LOG_TRACE("epoll_ctl() modify failed.");
|
||||||
}
|
}
|
||||||
net_con_print("MOD", con);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_close(struct net_connection* con_)
|
void net_con_backend_del_epoll(struct net_backend* data, struct net_connection* con_)
|
||||||
{
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
if (con->flags & NET_CLEANUP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (con->sd != -1)
|
backend->conns[con->sd] = 0;
|
||||||
{
|
|
||||||
g_backend->conns[con->sd] = 0;
|
|
||||||
g_backend->num--;
|
|
||||||
}
|
|
||||||
|
|
||||||
net_con_clear_timeout(con_);
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
||||||
|
|
||||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
|
||||||
{
|
{
|
||||||
LOG_WARN("epoll_ctl() delete failed.");
|
LOG_WARN("epoll_ctl() delete failed.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
net_close(con->sd);
|
void net_backend_shutdown_epoll(struct net_backend* data)
|
||||||
con->sd = -1;
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
close(backend->epfd);
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
net_con_print("DEL", con);
|
struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
net_cleanup_delayed_free(g_backend->cleaner, con_);
|
{
|
||||||
|
struct net_backend_epoll* backend;
|
||||||
|
|
||||||
|
if (getenv("EVENT_NOEPOLL"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
backend = hub_malloc_zero(sizeof(struct net_backend_epoll));
|
||||||
|
backend->epfd = epoll_create(common->max);
|
||||||
|
if (backend->epfd == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("Unable to create epoll socket.");
|
||||||
|
hub_free(backend);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * common->max);
|
||||||
|
backend->common = common;
|
||||||
|
|
||||||
|
net_backend_set_handlers(handler);
|
||||||
|
return (struct net_backend*) backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||||
|
{
|
||||||
|
handler->backend_name = net_backend_name_epoll;
|
||||||
|
handler->backend_poll = net_backend_poll_epoll;
|
||||||
|
handler->backend_process = net_backend_process_epoll;
|
||||||
|
handler->backend_shutdown = net_backend_shutdown_epoll;
|
||||||
|
handler->con_create = net_con_create_epoll;
|
||||||
|
handler->con_init = net_con_initialize_epoll;
|
||||||
|
handler->con_add = net_con_backend_add_epoll;
|
||||||
|
handler->con_mod = net_con_backend_mod_epoll;
|
||||||
|
handler->con_del = net_con_backend_del_epoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_EPOLL */
|
#endif /* USE_EPOLL */
|
||||||
|
|||||||
278
src/network/kqueue.c
Normal file
278
src/network/kqueue.c
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#ifdef USE_KQUEUE
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
|
#define KQUEUE_EVBUFFER 512
|
||||||
|
|
||||||
|
struct net_connection_kqueue
|
||||||
|
{
|
||||||
|
NET_CON_STRUCT_COMMON
|
||||||
|
struct kevent ev_r;
|
||||||
|
struct kevent ev_w;
|
||||||
|
int change;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend_kqueue
|
||||||
|
{
|
||||||
|
int kqfd;
|
||||||
|
struct net_connection_kqueue** conns;
|
||||||
|
struct kevent* changes;
|
||||||
|
int* change_list;
|
||||||
|
size_t change_list_len;
|
||||||
|
struct kevent events[KQUEUE_EVBUFFER];
|
||||||
|
struct net_backend_common* common;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHANGE_ACTION_ADD 0x0001
|
||||||
|
#define CHANGE_ACTION_MOD 0x0002
|
||||||
|
#define CHANGE_ACTION_DEL 0x0004
|
||||||
|
#define CHANGE_OP_WANT_READ 0x0100
|
||||||
|
#define CHANGE_OP_WANT_WRITE 0x0200
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
static void add_change(struct net_backend_kqueue* backend, struct net_connection_kqueue* con, int actions);
|
||||||
|
static size_t create_change_list(struct net_backend_kqueue* backend);
|
||||||
|
|
||||||
|
const char* net_backend_name_kqueue()
|
||||||
|
{
|
||||||
|
return "kqueue";
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_backend_poll_kqueue(struct net_backend* data, int ms)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
struct timespec tspec = { 0, };
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
size_t changes;
|
||||||
|
|
||||||
|
tspec.tv_sec = (ms / 1000);
|
||||||
|
tspec.tv_nsec = ((ms % 1000) * 1000000);
|
||||||
|
|
||||||
|
changes = create_change_list(backend);
|
||||||
|
res = kevent(backend->kqfd, backend->changes, changes, backend->events, KQUEUE_EVBUFFER, &tspec);
|
||||||
|
|
||||||
|
if (res == -1 && errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_process_kqueue(struct net_backend* data, int res)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
|
||||||
|
for (n = 0; n < res; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata;
|
||||||
|
if (con && con->sd >= 0 && backend->conns[con->sd])
|
||||||
|
{
|
||||||
|
int ev = 0;
|
||||||
|
if (backend->events[n].filter == EVFILT_READ) ev = NET_EVENT_READ;
|
||||||
|
else if (backend->events[n].filter == EVFILT_WRITE) ev = NET_EVENT_WRITE;
|
||||||
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create_kqueue(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_kqueue));
|
||||||
|
con->sd = -1;
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize_kqueue(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
con->sd = sd;
|
||||||
|
con->flags = 0;
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
int operation;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = con;
|
||||||
|
|
||||||
|
operation = CHANGE_ACTION_ADD;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ)
|
||||||
|
operation |= CHANGE_OP_WANT_READ;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_WRITE)
|
||||||
|
operation |= CHANGE_OP_WANT_WRITE;
|
||||||
|
|
||||||
|
add_change(backend, con, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
|
||||||
|
int operation = CHANGE_ACTION_ADD;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ)
|
||||||
|
operation |= CHANGE_OP_WANT_READ;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_WRITE)
|
||||||
|
operation |= CHANGE_OP_WANT_WRITE;
|
||||||
|
|
||||||
|
add_change(backend, con, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
|
||||||
|
/* No need to remove it from the kqueue filter, the kqueue man page says
|
||||||
|
it is automatically removed when the descriptor is closed... */
|
||||||
|
add_change(backend, con, CHANGE_ACTION_DEL);
|
||||||
|
|
||||||
|
// Unmap the socket descriptor.
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown_kqueue(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
close(backend->kqfd);
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend->changes);
|
||||||
|
hub_free(backend->change_list);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_backend* net_backend_init_kqueue(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend;
|
||||||
|
|
||||||
|
if (getenv("EVENT_NOKQUEUE"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
backend = hub_malloc_zero(sizeof(struct net_backend_kqueue));
|
||||||
|
backend->kqfd = kqueue();
|
||||||
|
if (backend->kqfd == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("Unable to create kqueue socket.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||||
|
backend->changes = hub_malloc_zero(sizeof(struct kevent) * common->max * 2);
|
||||||
|
backend->change_list = hub_malloc_zero(sizeof(int) * common->max);
|
||||||
|
backend->common = common;
|
||||||
|
|
||||||
|
net_backend_set_handlers(handler);
|
||||||
|
return (struct net_backend*) backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||||
|
{
|
||||||
|
handler->backend_name = net_backend_name_kqueue;
|
||||||
|
handler->backend_poll = net_backend_poll_kqueue;
|
||||||
|
handler->backend_process = net_backend_process_kqueue;
|
||||||
|
handler->backend_shutdown = net_backend_shutdown_kqueue;
|
||||||
|
handler->con_create = net_con_create_kqueue;
|
||||||
|
handler->con_init = net_con_initialize_kqueue;
|
||||||
|
handler->con_add = net_con_backend_add_kqueue;
|
||||||
|
handler->con_mod = net_con_backend_mod_kqueue;
|
||||||
|
handler->con_del = net_con_backend_del_kqueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_change(struct net_backend_kqueue* backend, struct net_connection_kqueue* con, int actions)
|
||||||
|
{
|
||||||
|
if (actions && !con->change)
|
||||||
|
{
|
||||||
|
backend->change_list[backend->change_list_len++] = con->sd;
|
||||||
|
con->change = actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t create_change_list(struct net_backend_kqueue* backend)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
size_t changes = 0;
|
||||||
|
int sd;
|
||||||
|
struct net_connection_kqueue* con;
|
||||||
|
unsigned short flags_r = 0;
|
||||||
|
unsigned short flags_w = 0;
|
||||||
|
|
||||||
|
for (; n < backend->change_list_len; n++)
|
||||||
|
{
|
||||||
|
sd = backend->change_list[n];
|
||||||
|
con = backend->conns[sd];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
flags_r = 0;
|
||||||
|
flags_w = 0;
|
||||||
|
|
||||||
|
if (con->change & CHANGE_ACTION_ADD)
|
||||||
|
{
|
||||||
|
flags_r |= EV_ADD;
|
||||||
|
flags_w |= EV_ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->change & CHANGE_OP_WANT_READ)
|
||||||
|
flags_r |= EV_ENABLE;
|
||||||
|
else
|
||||||
|
flags_r |= EV_DISABLE;
|
||||||
|
|
||||||
|
if (con->change & CHANGE_OP_WANT_WRITE)
|
||||||
|
flags_w |= EV_ENABLE;
|
||||||
|
else
|
||||||
|
flags_w |= EV_DISABLE;
|
||||||
|
|
||||||
|
if (con->ev_r.flags != flags_r)
|
||||||
|
{
|
||||||
|
EV_SET(&con->ev_r, sd, EVFILT_READ, flags_r, 0, 0, con);
|
||||||
|
memcpy(&backend->changes[changes++], &con->ev_r, sizeof(struct kevent));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con->ev_w.flags != flags_w)
|
||||||
|
{
|
||||||
|
EV_SET(&con->ev_w, sd, EVFILT_WRITE, flags_w, 0, 0, con);
|
||||||
|
memcpy(&backend->changes[changes++], &con->ev_w, sizeof(struct kevent));
|
||||||
|
}
|
||||||
|
|
||||||
|
con->change = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EV_SET(&backend->changes[changes++], sd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||||
|
EV_SET(&backend->changes[changes++], sd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backend->change_list_len = 0;
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_KQUEUE */
|
||||||
@@ -34,12 +34,14 @@ static struct net_statistics stats_total;
|
|||||||
|
|
||||||
int net_initialize()
|
int net_initialize()
|
||||||
{
|
{
|
||||||
|
#ifdef WINSOCK
|
||||||
|
struct WSAData wsa;
|
||||||
|
#endif
|
||||||
if (!net_initialized)
|
if (!net_initialized)
|
||||||
{
|
{
|
||||||
LOG_TRACE("Initializing network monitor.");
|
LOG_TRACE("Initializing network monitor.");
|
||||||
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
struct WSAData wsa;
|
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR)
|
if (WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to initialize winsock.");
|
LOG_ERROR("Unable to initialize winsock.");
|
||||||
@@ -47,14 +49,19 @@ int net_initialize()
|
|||||||
}
|
}
|
||||||
#endif /* WINSOCK */
|
#endif /* WINSOCK */
|
||||||
|
|
||||||
net_backend_initialize();
|
if (!net_backend_init())
|
||||||
|
{
|
||||||
|
#ifdef WINSOCK
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
net_stats_initialize();
|
net_stats_initialize();
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
LOG_TRACE("Initializing OpenSSL...");
|
LOG_TRACE("Initializing OpenSSL...");
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
net_initialized = 1;
|
net_initialized = 1;
|
||||||
@@ -69,14 +76,13 @@ size_t net_get_max_sockets()
|
|||||||
struct rlimit limits;
|
struct rlimit limits;
|
||||||
if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
|
if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
|
||||||
{
|
{
|
||||||
return limits.rlim_max;
|
return MIN(limits.rlim_max, 65536);
|
||||||
}
|
}
|
||||||
LOG_ERROR("getrlimit() failed");
|
LOG_ERROR("getrlimit() failed");
|
||||||
return 1024;
|
return 1024;
|
||||||
#else
|
#else
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
LOG_WARN("Windows system, limited to 4096 connections.");
|
return FD_SETSIZE;
|
||||||
return 4096;
|
|
||||||
#else
|
#else
|
||||||
LOG_WARN("System does not have getrlimit(): constrained to 1024 sockets");
|
LOG_WARN("System does not have getrlimit(): constrained to 1024 sockets");
|
||||||
return 1024;
|
return 1024;
|
||||||
@@ -94,7 +100,9 @@ int net_destroy()
|
|||||||
net_backend_shutdown();
|
net_backend_shutdown();
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
/* FIXME: Shutdown OpenSSL here. */
|
ERR_free_strings();
|
||||||
|
EVP_cleanup();
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
@@ -351,6 +359,9 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
{
|
{
|
||||||
switch (net_error())
|
switch (net_error())
|
||||||
{
|
{
|
||||||
|
#if defined(__HAIKU__)
|
||||||
|
case ETIMEDOUT:
|
||||||
|
#endif
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
case ENETDOWN:
|
case ENETDOWN:
|
||||||
case EPROTO:
|
case EPROTO:
|
||||||
@@ -361,8 +372,13 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
case EOPNOTSUPP:
|
case EOPNOTSUPP:
|
||||||
errno = EWOULDBLOCK;
|
errno = EWOULDBLOCK;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WINSOCK
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
net_error_out(fd, "net_accept");
|
net_error_out(fd, "net_accept");
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
@@ -376,7 +392,7 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
if (ipaddr)
|
if (ipaddr)
|
||||||
{
|
{
|
||||||
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
||||||
ipaddr->af = addr4->sin_family;
|
ipaddr->af = addr.ss_family;;
|
||||||
if (ipaddr->af == AF_INET6)
|
if (ipaddr->af == AF_INET6)
|
||||||
{
|
{
|
||||||
char address[INET6_ADDRSTRLEN+1] = { 0, };
|
char address[INET6_ADDRSTRLEN+1] = { 0, };
|
||||||
@@ -408,7 +424,11 @@ int net_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen)
|
|||||||
int ret = connect(fd, serv_addr, addrlen);
|
int ret = connect(fd, serv_addr, addrlen);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
|
#ifdef WINSOCK
|
||||||
|
if (net_error() != WSAEINPROGRESS)
|
||||||
|
#else
|
||||||
if (net_error() != EINPROGRESS)
|
if (net_error() != EINPROGRESS)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
net_error_out(fd, "net_connect");
|
net_error_out(fd, "net_connect");
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
@@ -519,7 +539,7 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WSAAddressToString(addr, size, NULL, dst, &len) == 0)
|
if (WSAAddressToStringA(addr, size, NULL, dst, &len) == 0)
|
||||||
{
|
{
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@@ -588,9 +608,10 @@ const char* net_get_peer_address(int fd)
|
|||||||
struct sockaddr_in6* name6;
|
struct sockaddr_in6* name6;
|
||||||
struct sockaddr_in* name4;
|
struct sockaddr_in* name4;
|
||||||
struct sockaddr* name;
|
struct sockaddr* name;
|
||||||
|
socklen_t namelen;
|
||||||
|
|
||||||
memset(address, 0, INET6_ADDRSTRLEN);
|
memset(address, 0, INET6_ADDRSTRLEN);
|
||||||
socklen_t namelen = sizeof(struct sockaddr_storage);
|
namelen = sizeof(struct sockaddr_storage);
|
||||||
memset(&storage, 0, namelen);
|
memset(&storage, 0, namelen);
|
||||||
|
|
||||||
name6 = (struct sockaddr_in6*) &storage;
|
name6 = (struct sockaddr_in6*) &storage;
|
||||||
@@ -599,7 +620,7 @@ const char* net_get_peer_address(int fd)
|
|||||||
|
|
||||||
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
|
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
|
||||||
{
|
{
|
||||||
int af = name4->sin_family;
|
int af = storage.ss_family;
|
||||||
if (af == AF_INET6)
|
if (af == AF_INET6)
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
||||||
@@ -626,9 +647,10 @@ const char* net_get_local_address(int fd)
|
|||||||
struct sockaddr_in6* name6;
|
struct sockaddr_in6* name6;
|
||||||
struct sockaddr_in* name4;
|
struct sockaddr_in* name4;
|
||||||
struct sockaddr* name;
|
struct sockaddr* name;
|
||||||
|
socklen_t namelen;
|
||||||
|
|
||||||
memset(address, 0, INET6_ADDRSTRLEN);
|
memset(address, 0, INET6_ADDRSTRLEN);
|
||||||
socklen_t namelen = sizeof(struct sockaddr_storage);
|
namelen = sizeof(struct sockaddr_storage);
|
||||||
memset(&storage, 0, namelen);
|
memset(&storage, 0, namelen);
|
||||||
|
|
||||||
name6 = (struct sockaddr_in6*) &storage;
|
name6 = (struct sockaddr_in6*) &storage;
|
||||||
@@ -637,12 +659,16 @@ const char* net_get_local_address(int fd)
|
|||||||
|
|
||||||
if (getsockname(fd, (struct sockaddr*) name, &namelen) != -1)
|
if (getsockname(fd, (struct sockaddr*) name, &namelen) != -1)
|
||||||
{
|
{
|
||||||
int af = name4->sin_family;
|
#ifndef WINSOCK
|
||||||
|
int af = storage.ss_family;
|
||||||
if (af == AF_INET6)
|
if (af == AF_INET6)
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#else
|
||||||
|
int af = AF_INET;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
@@ -668,7 +694,11 @@ ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef WINSOCK
|
||||||
|
if (net_error() != WSAEWOULDBLOCK)
|
||||||
|
#else
|
||||||
if (net_error() != EWOULDBLOCK)
|
if (net_error() != EWOULDBLOCK)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* net_error_out(fd, "net_recv"); */
|
/* net_error_out(fd, "net_recv"); */
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
@@ -687,7 +717,11 @@ ssize_t net_send(int fd, const void* buf, size_t len, int flags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef WINSOCK
|
||||||
|
if (net_error() != WSAEWOULDBLOCK)
|
||||||
|
#else
|
||||||
if (net_error() != EWOULDBLOCK)
|
if (net_error() != EWOULDBLOCK)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* net_error_out(fd, "net_send"); */
|
/* net_error_out(fd, "net_send"); */
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
|
|||||||
@@ -254,46 +254,4 @@ extern void net_stats_add_close();
|
|||||||
extern int net_stats_timeout();
|
extern int net_stats_timeout();
|
||||||
extern void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total);
|
extern void net_stats_get(struct net_statistics** intermediate, struct net_statistics** total);
|
||||||
|
|
||||||
|
|
||||||
#if defined(WINSOCK) && !defined(__CYGWIN__)
|
|
||||||
|
|
||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
|
||||||
#define EINPROGRESS WSAEINPROGRESS
|
|
||||||
#define EALREADY WSAEALREADY
|
|
||||||
#define ENOTSOCK WSAENOTSOCK
|
|
||||||
#define EDESTADDRREQ WSAEDESTADDRREQ
|
|
||||||
#define EMSGSIZE WSAEMSGSIZE
|
|
||||||
#define EPROTOTYPE WSAEPROTOTYPE
|
|
||||||
#define ENOPROTOOPT WSAENOPROTOOPT
|
|
||||||
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
|
|
||||||
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
|
|
||||||
#define EOPNOTSUPP WSAEOPNOTSUPP
|
|
||||||
#define EPFNOSUPPORT WSAEPFNOSUPPORT
|
|
||||||
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
|
||||||
#define EADDRINUSE WSAEADDRINUSE
|
|
||||||
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
|
|
||||||
#define ENETDOWN WSAENETDOWN
|
|
||||||
#define ENETUNREACH WSAENETUNREACH
|
|
||||||
#define ENETRESET WSAENETRESET
|
|
||||||
#define ECONNABORTED WSAECONNABORTED
|
|
||||||
#define ECONNRESET WSAECONNRESET
|
|
||||||
#define ENOBUFS WSAENOBUFS
|
|
||||||
#define EISCONN WSAEISCONN
|
|
||||||
#define ENOTCONN WSAENOTCONN
|
|
||||||
#define ESHUTDOWN WSAESHUTDOWN
|
|
||||||
#define ETOOMANYREFS WSAETOOMANYREFS
|
|
||||||
#define ETIMEDOUT WSAETIMEDOUT
|
|
||||||
#define ECONNREFUSED WSAECONNREFUSED
|
|
||||||
#define ELOOP WSAELOOP
|
|
||||||
#define EHOSTDOWN WSAEHOSTDOWN
|
|
||||||
#define EHOSTUNREACH WSAEHOSTUNREACH
|
|
||||||
#define EPROCLIM WSAEPROCLIM
|
|
||||||
#define EUSERS WSAEUSERS
|
|
||||||
#define EDQUOT WSAEDQUOT
|
|
||||||
#define ESTALE WSAESTALE
|
|
||||||
#define EREMOTE WSAEREMOTE
|
|
||||||
|
|
||||||
#endif /* WINSOCK && !__CYGWIN__ */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_NETWORK_H */
|
#endif /* HAVE_UHUB_NETWORK_H */
|
||||||
|
|||||||
@@ -30,110 +30,74 @@ struct net_connection_select
|
|||||||
NET_CON_STRUCT_COMMON
|
NET_CON_STRUCT_COMMON
|
||||||
};
|
};
|
||||||
|
|
||||||
struct net_backend
|
struct net_backend_select
|
||||||
{
|
{
|
||||||
size_t num;
|
|
||||||
size_t max;
|
|
||||||
struct net_connection_select** conns;
|
struct net_connection_select** conns;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
fd_set wfds;
|
fd_set wfds;
|
||||||
time_t now;
|
fd_set xfds;
|
||||||
struct timeout_queue timeout_queue;
|
int maxfd;
|
||||||
struct net_cleanup_handler* cleaner;
|
struct net_backend_common* common;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct net_backend* g_backend = 0;
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
|
||||||
static void net_con_print(const char* prefix, struct net_connection_select* con)
|
const char* net_backend_name_select()
|
||||||
{
|
{
|
||||||
char buf[512];
|
return "select";
|
||||||
int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, events=%s%s",
|
|
||||||
prefix, con->sd, con->flags, con->callback, con->ptr, (con->flags & NET_EVENT_READ ? "R" : ""),(con->flags & NET_EVENT_WRITE ? "W" : ""));
|
|
||||||
if (con->timeout)
|
|
||||||
{
|
|
||||||
sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(buf + off, ", timeout=NULL");
|
|
||||||
}
|
|
||||||
LOG_TRACE(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int net_backend_poll_select(struct net_backend* data, int ms)
|
||||||
* Initialize the network backend.
|
|
||||||
* Returns 1 on success, or 0 on failure.
|
|
||||||
*/
|
|
||||||
int net_backend_initialize()
|
|
||||||
{
|
{
|
||||||
size_t max = net_get_max_sockets();
|
int res;
|
||||||
g_backend = hub_malloc(sizeof(struct net_backend));
|
size_t n, found;
|
||||||
g_backend->num = 0;
|
|
||||||
g_backend->max = max;
|
|
||||||
g_backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * max);
|
|
||||||
FD_ZERO(&g_backend->rfds);
|
|
||||||
FD_ZERO(&g_backend->wfds);
|
|
||||||
g_backend->now = time(0);
|
|
||||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
|
|
||||||
g_backend->cleaner = net_cleanup_initialize(max);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shutdown the network connection backend.
|
|
||||||
*/
|
|
||||||
void net_backend_shutdown()
|
|
||||||
{
|
|
||||||
timeout_queue_shutdown(&g_backend->timeout_queue);
|
|
||||||
net_cleanup_shutdown(g_backend->cleaner);
|
|
||||||
hub_free(g_backend->conns);
|
|
||||||
hub_free(g_backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process the network backend.
|
|
||||||
*/
|
|
||||||
int net_backend_process()
|
|
||||||
{
|
|
||||||
int n, found, maxfd;
|
|
||||||
struct timeval tval;
|
struct timeval tval;
|
||||||
FD_ZERO(&g_backend->rfds);
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
FD_ZERO(&g_backend->wfds);
|
|
||||||
|
|
||||||
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
tval.tv_sec = ms / 1000;
|
||||||
tval.tv_secs = secs;
|
tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct?
|
||||||
tval.tv_usecs = 0;
|
|
||||||
|
|
||||||
for (n = 0, found = 0; found < g_backend->num && n < g_backend->max; n++)
|
FD_ZERO(&backend->rfds);
|
||||||
|
FD_ZERO(&backend->wfds);
|
||||||
|
FD_ZERO(&backend->xfds);
|
||||||
|
|
||||||
|
backend->maxfd = -1;
|
||||||
|
for (n = 0, found = 0; found < backend->common->num && n < backend->common->max; n++)
|
||||||
{
|
{
|
||||||
struct net_connection_select* con = g_backend->conns[n];
|
struct net_connection_select* con = backend->conns[n];
|
||||||
if (con)
|
if (con)
|
||||||
{
|
{
|
||||||
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &g_backend->rfds);
|
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &backend->rfds);
|
||||||
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &g_backend->wfds);
|
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &backend->wfds);
|
||||||
found++;
|
found++;
|
||||||
maxfd = con->sd;
|
backend->maxfd = con->sd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
backend->maxfd++;
|
||||||
|
|
||||||
int res = select(maxfd+1, &g_backend->rfds, &g_backend->wfds, 0, &tval);
|
res = select(backend->maxfd, &backend->rfds, &backend->wfds, &backend->xfds, &tval);
|
||||||
g_backend->now = time(0);
|
|
||||||
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
|
||||||
|
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
{
|
{
|
||||||
LOG_WARN("select returned -1");
|
printf("Error: %d\n", net_error());
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
if (res == -1 && net_error() == EINTR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (n = 0, found = 0; found < res && n < (maxfd+1); n++)
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_process_select(struct net_backend* data, int res)
|
||||||
|
{
|
||||||
|
int n, found;
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
for (n = 0, found = 0; found < res && n < backend->maxfd; n++)
|
||||||
{
|
{
|
||||||
struct net_connection_select* con = g_backend->conns[n];
|
struct net_connection_select* con = backend->conns[n];
|
||||||
if (con)
|
if (con)
|
||||||
{
|
{
|
||||||
int ev = 0;
|
int ev = 0;
|
||||||
if (FD_ISSET(con->sd, &g_backend->rfds)) ev |= NET_EVENT_READ;
|
if (FD_ISSET(con->sd, &backend->rfds)) ev |= NET_EVENT_READ;
|
||||||
if (FD_ISSET(con->sd, &g_backend->wfds)) ev |= NET_EVENT_WRITE;
|
if (FD_ISSET(con->sd, &backend->wfds)) ev |= NET_EVENT_WRITE;
|
||||||
|
|
||||||
if (ev)
|
if (ev)
|
||||||
{
|
{
|
||||||
@@ -142,75 +106,77 @@ int net_backend_process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
net_cleanup_process(g_backend->cleaner);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timeout_queue* net_backend_get_timeout_queue()
|
struct net_connection* net_con_create_select(struct net_backend* data)
|
||||||
{
|
|
||||||
return &g_backend->timeout_queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct net_connection* net_con_create()
|
|
||||||
{
|
{
|
||||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
|
||||||
con->sd = -1;
|
con->sd = -1;
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_destroy(struct net_connection* con)
|
void net_con_initialize_select(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
{
|
|
||||||
hub_free(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize(struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr, int events)
|
|
||||||
{
|
{
|
||||||
struct net_connection_select* con = (struct net_connection_select*) con_;
|
struct net_connection_select* con = (struct net_connection_select*) con_;
|
||||||
con->sd = sd;
|
con->sd = sd;
|
||||||
con->flags = events;
|
con->flags = 0;
|
||||||
con->callback = callback;
|
con->callback = callback;
|
||||||
con->ptr = (void*) ptr;
|
con->ptr = (void*) ptr;
|
||||||
|
|
||||||
net_set_nonblocking(con->sd, 1);
|
|
||||||
net_set_nosigpipe(con->sd, 1);
|
|
||||||
|
|
||||||
g_backend->conns[sd] = con;
|
|
||||||
g_backend->num++;
|
|
||||||
net_con_print("ADD", con);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
void net_con_backend_add_select(struct net_backend* data, struct net_connection* con, int events)
|
||||||
{
|
{
|
||||||
con->callback = callback;
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
con->ptr = (void*) ptr;
|
backend->conns[con->sd] = (struct net_connection_select*) con;
|
||||||
net_con_update(con, events);
|
con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_update(struct net_connection* con, int events)
|
|
||||||
|
void net_con_backend_mod_select(struct net_backend* data, struct net_connection* con, int events)
|
||||||
{
|
{
|
||||||
con->flags = events;
|
con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE));
|
||||||
net_con_print("MOD", (struct net_connection_select*) con);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_close(struct net_connection* con)
|
void net_con_backend_del_select(struct net_backend* data, struct net_connection* con)
|
||||||
{
|
{
|
||||||
if (con->flags & NET_CLEANUP)
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
return;
|
backend->conns[con->sd] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (con->sd != -1)
|
void net_backend_shutdown_select(struct net_backend* data)
|
||||||
{
|
{
|
||||||
g_backend->conns[con->sd] = 0;
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
g_backend->num--;
|
hub_free(backend->conns);
|
||||||
}
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
net_con_clear_timeout(con);
|
struct net_backend* net_backend_init_select(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend;
|
||||||
|
|
||||||
net_close(con->sd);
|
if (getenv("EVENT_NOSELECT"))
|
||||||
con->sd = -1;
|
return 0;
|
||||||
|
|
||||||
net_con_print("DEL", (struct net_connection_select*) con);
|
backend = hub_malloc_zero(sizeof(struct net_backend_select));
|
||||||
net_cleanup_delayed_free(g_backend->cleaner, con);
|
FD_ZERO(&backend->rfds);
|
||||||
|
FD_ZERO(&backend->wfds);
|
||||||
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * common->max);
|
||||||
|
backend->common = common;
|
||||||
|
net_backend_set_handlers(handler);
|
||||||
|
return (struct net_backend*) backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||||
|
{
|
||||||
|
handler->backend_name = net_backend_name_select;
|
||||||
|
handler->backend_poll = net_backend_poll_select;
|
||||||
|
handler->backend_process = net_backend_process_select;
|
||||||
|
handler->backend_shutdown = net_backend_shutdown_select;
|
||||||
|
handler->con_create = net_con_create_select;
|
||||||
|
handler->con_init = net_con_initialize_select;
|
||||||
|
handler->con_add = net_con_backend_add_select;
|
||||||
|
handler->con_mod = net_con_backend_mod_select;
|
||||||
|
handler->con_del = net_con_backend_del_select;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_SELECT */
|
#endif /* USE_SELECT */
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "util/timeout.h"
|
|
||||||
|
|
||||||
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
||||||
{
|
{
|
||||||
@@ -36,7 +35,7 @@ void timeout_evt_reset(struct timeout_evt* t)
|
|||||||
|
|
||||||
int timeout_evt_is_scheduled(struct timeout_evt* t)
|
int timeout_evt_is_scheduled(struct timeout_evt* t)
|
||||||
{
|
{
|
||||||
return !!t->prev;
|
return t->prev != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
|
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
|
||||||
@@ -55,10 +54,11 @@ void timeout_queue_shutdown(struct timeout_queue* t)
|
|||||||
|
|
||||||
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
||||||
{
|
{
|
||||||
size_t pos;
|
size_t pos = (size_t) t->last;
|
||||||
size_t events = 0;
|
size_t events = 0;
|
||||||
struct timeout_evt* evt = 0;
|
struct timeout_evt* evt = 0;
|
||||||
for (pos = t->last; pos <= now; pos++)
|
t->last = now;
|
||||||
|
for (; pos <= now; pos++)
|
||||||
{
|
{
|
||||||
while ((evt = t->events[pos % t->max]))
|
while ((evt = t->events[pos % t->max]))
|
||||||
{
|
{
|
||||||
@@ -67,7 +67,6 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
|||||||
events++;
|
events++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t->last = now;
|
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +94,7 @@ void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size
|
|||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
uhub_assert(first->timestamp == evt->timestamp);
|
||||||
first->prev->next = evt;
|
first->prev->next = evt;
|
||||||
evt->prev = first->prev;
|
evt->prev = first->prev;
|
||||||
first->prev = evt;
|
first->prev = evt;
|
||||||
79
src/plugin_api/command_api.h
Normal file
79
src/plugin_api/command_api.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_API_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_API_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file describes the interface a plugin implementation may use from
|
||||||
|
* uhub.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "plugin_api/types.h"
|
||||||
|
|
||||||
|
struct plugin_command
|
||||||
|
{
|
||||||
|
const char* message;
|
||||||
|
const char* prefix;
|
||||||
|
struct linked_list* args;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*plugin_command_handler)(struct plugin_handle*, struct plugin_user* to, struct plugin_command*);
|
||||||
|
|
||||||
|
struct plugin_command_handle
|
||||||
|
{
|
||||||
|
void* internal_handle; /**<<< "Internal used by the hub only" */
|
||||||
|
struct plugin_handle* handle; /**<<< "The plugin handle this is associated with" */
|
||||||
|
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" */
|
||||||
|
enum auth_credentials cred; /**<<< "Minimum access level for the command" */
|
||||||
|
plugin_command_handler handler; /**<<< "Function pointer for the command" */
|
||||||
|
const char* description; /**<<< "Description for the command" */
|
||||||
|
const char* origin; /**<<< "Name of plugin where the command originated." */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PLUGIN_COMMAND_INITIALIZE(PTR, HANDLE, PREFIX, ARGS, CRED, CALLBACK, DESC) \
|
||||||
|
do { \
|
||||||
|
PTR->internal_handle = 0; \
|
||||||
|
PTR->handle = HANDLE; \
|
||||||
|
PTR->prefix = PREFIX; \
|
||||||
|
PTR->length = strlen(PREFIX); \
|
||||||
|
PTR->args = ARGS; \
|
||||||
|
PTR->cred = CRED; \
|
||||||
|
PTR->handler = CALLBACK; \
|
||||||
|
PTR->description = DESC; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
extern int plugin_command_add(struct plugin_handle*, struct plugin_command_handle*);
|
||||||
|
extern int plugin_command_del(struct plugin_handle*, struct plugin_command_handle*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message to a user.
|
||||||
|
* From the user's perspective the message will originate from the hub.
|
||||||
|
*/
|
||||||
|
extern int plugin_command_send_message(struct plugin_handle*, struct plugin_user* to, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a reply to a command.
|
||||||
|
*/
|
||||||
|
extern int plugin_command_send_reply(struct plugin_handle*, struct plugin_user* user, struct plugin_command* command, const char* message);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_API_H */
|
||||||
174
src/plugin_api/handle.h
Normal file
174
src/plugin_api/handle.h
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_HANDLE_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_HANDLE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file describes the interface a uhub uses to interact with plugins.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "util/credentials.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
#include "plugin_api/types.h"
|
||||||
|
|
||||||
|
typedef plugin_st (*on_chat_msg_t)(struct plugin_handle*, struct plugin_user* from, const char* message);
|
||||||
|
typedef plugin_st (*on_private_msg_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* message);
|
||||||
|
typedef plugin_st (*on_search_t)(struct plugin_handle*, struct plugin_user* from, const char* data);
|
||||||
|
typedef plugin_st (*on_search_result_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to, const char* data);
|
||||||
|
typedef plugin_st (*on_p2p_connect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
|
||||||
|
typedef plugin_st (*on_p2p_revconnect_t)(struct plugin_handle*, struct plugin_user* from, struct plugin_user* to);
|
||||||
|
|
||||||
|
typedef void (*on_connection_accepted_t)(struct plugin_handle*, struct ip_addr_encap*);
|
||||||
|
typedef void (*on_connection_refused_t)(struct plugin_handle*, struct ip_addr_encap*);
|
||||||
|
|
||||||
|
typedef void (*on_user_login_t)(struct plugin_handle*, struct plugin_user*);
|
||||||
|
typedef void (*on_user_login_error_t)(struct plugin_handle*, struct plugin_user*, const char* reason);
|
||||||
|
typedef void (*on_user_logout_t)(struct plugin_handle*, struct plugin_user*, const char* reason);
|
||||||
|
typedef void (*on_user_nick_change_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick);
|
||||||
|
typedef void (*on_user_update_error_t)(struct plugin_handle*, struct plugin_user*, const char* reason);
|
||||||
|
typedef void (*on_user_chat_msg_t)(struct plugin_handle*, struct plugin_user*, const char* message, int flags);
|
||||||
|
|
||||||
|
typedef void (*on_hub_started_t)(struct plugin_handle*, struct plugin_hub_info*);
|
||||||
|
typedef void (*on_hub_reloaded_t)(struct plugin_handle*, struct plugin_hub_info*);
|
||||||
|
typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*);
|
||||||
|
typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message);
|
||||||
|
|
||||||
|
typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick);
|
||||||
|
|
||||||
|
typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*);
|
||||||
|
typedef plugin_st (*on_check_ip_late_t)(struct plugin_handle*, struct ip_addr_encap*);
|
||||||
|
typedef plugin_st (*on_validate_nick_t)(struct plugin_handle*, const char* nick);
|
||||||
|
typedef plugin_st (*on_validate_cid_t)(struct plugin_handle*, const char* cid);
|
||||||
|
|
||||||
|
typedef plugin_st (*auth_get_user_t)(struct plugin_handle*, const char* nickname, struct auth_info* info);
|
||||||
|
typedef plugin_st (*auth_register_user_t)(struct plugin_handle*, struct auth_info* user);
|
||||||
|
typedef plugin_st (*auth_update_user_t)(struct plugin_handle*, struct auth_info* user);
|
||||||
|
typedef plugin_st (*auth_delete_user_t)(struct plugin_handle*, struct auth_info* user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are callbacks used for the hub to invoke functions in plugins.
|
||||||
|
*/
|
||||||
|
struct plugin_funcs
|
||||||
|
{
|
||||||
|
// Log events for connections
|
||||||
|
on_connection_accepted_t on_connection_accepted; /* Someone successfully connected to the hub */
|
||||||
|
on_connection_refused_t on_connection_refused; /* Someone was refused connection to the hub */
|
||||||
|
|
||||||
|
// Log events for users
|
||||||
|
on_user_login_t on_user_login; /* A user has successfully logged in to the hub */
|
||||||
|
on_user_login_error_t on_user_login_error; /* A user has failed to log in to the hub */
|
||||||
|
on_user_logout_t on_user_logout; /* A user has logged out of the hub (was previously logged in) */
|
||||||
|
on_user_nick_change_t on_user_nick_change; /* A user has changed nickname */
|
||||||
|
on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */
|
||||||
|
on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */
|
||||||
|
|
||||||
|
// Log hub events
|
||||||
|
on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */
|
||||||
|
on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */
|
||||||
|
on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */
|
||||||
|
on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */
|
||||||
|
|
||||||
|
// Activity events (can be intercepted and refused/accepted by a plugin)
|
||||||
|
on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */
|
||||||
|
on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */
|
||||||
|
on_search_t on_search; /* A search is about to be sent (can be intercepted) */
|
||||||
|
on_search_result_t on_search_result; /* A search result is about to be sent (can be intercepted) */
|
||||||
|
on_p2p_connect_t on_p2p_connect; /* A user is about to connect to another user (can be intercepted) */
|
||||||
|
on_p2p_revconnect_t on_p2p_revconnect; /* A user is about to connect to another user (can be intercepted) */
|
||||||
|
|
||||||
|
// Authentication actions.
|
||||||
|
auth_get_user_t auth_get_user; /* Get authentication info from plugin */
|
||||||
|
auth_register_user_t auth_register_user; /* Register user */
|
||||||
|
auth_update_user_t auth_update_user; /* Update a registered user */
|
||||||
|
auth_delete_user_t auth_delete_user; /* Delete a registered user */
|
||||||
|
|
||||||
|
// Login check functions
|
||||||
|
on_check_ip_early_t login_check_ip_early;
|
||||||
|
on_check_ip_late_t login_check_ip_late;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct plugin_command_handle;
|
||||||
|
|
||||||
|
typedef int (*hfunc_send_message)(struct plugin_handle*, struct plugin_user* user, const char* message);
|
||||||
|
typedef int (*hfunc_send_status)(struct plugin_handle*, struct plugin_user* to, int code, const char* message);
|
||||||
|
typedef int (*hfunc_user_disconnect)(struct plugin_handle*, struct plugin_user* user);
|
||||||
|
typedef int (*hfunc_command_add)(struct plugin_handle*, struct plugin_command_handle*);
|
||||||
|
typedef int (*hfunc_command_del)(struct plugin_handle*, struct plugin_command_handle*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are functions created and initialized by the hub and which can be used
|
||||||
|
* by plugins to access functionality internal to the hub.
|
||||||
|
*/
|
||||||
|
struct plugin_hub_funcs
|
||||||
|
{
|
||||||
|
hfunc_send_message send_message;
|
||||||
|
hfunc_send_status send_status_message;
|
||||||
|
hfunc_user_disconnect user_disconnect;
|
||||||
|
hfunc_command_add command_add;
|
||||||
|
hfunc_command_del command_del;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct plugin_handle
|
||||||
|
{
|
||||||
|
struct uhub_plugin* handle; /* Must NOT be modified by the plugin */
|
||||||
|
const char* name; /* plugin name */
|
||||||
|
const char* version; /* plugin version */
|
||||||
|
const char* description; /* plugin description */
|
||||||
|
void* ptr; /* Plugin specific data */
|
||||||
|
const char* error_msg; /* Error message for registration error. */
|
||||||
|
size_t plugin_api_version; /* Plugin API version */
|
||||||
|
size_t plugin_funcs_size; /* Size of the plugin funcs */
|
||||||
|
struct plugin_funcs funcs; /* Table of functions that can be implemented by a plugin */
|
||||||
|
struct plugin_hub_funcs hub; /* Table of core hub functions that can be used by a plugin */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define PLUGIN_INITIALIZE(PTR, NAME, VERSION, DESCRIPTION) \
|
||||||
|
do { \
|
||||||
|
PTR->name = NAME; \
|
||||||
|
PTR->version = VERSION; \
|
||||||
|
PTR->description = DESCRIPTION; \
|
||||||
|
PTR->ptr = NULL; \
|
||||||
|
PTR->error_msg = NULL; \
|
||||||
|
PTR->plugin_api_version = PLUGIN_API_VERSION; \
|
||||||
|
PTR->plugin_funcs_size = sizeof(struct plugin_funcs); \
|
||||||
|
memset(&PTR->funcs, 0, sizeof(struct plugin_funcs)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemented by the plugin.
|
||||||
|
*
|
||||||
|
* @param handle[out] Sets all information by the plugin
|
||||||
|
* @param config A configuration string
|
||||||
|
* @return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
PLUGIN_API int plugin_register(struct plugin_handle* handle, const char* config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
PLUGIN_API int plugin_unregister(struct plugin_handle*);
|
||||||
|
|
||||||
|
typedef int (*plugin_register_f)(struct plugin_handle* handle, const char* config);
|
||||||
|
typedef int (*plugin_unregister_f)(struct plugin_handle*);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_HANDLE_H */
|
||||||
34
src/plugin_api/message_api.h
Normal file
34
src/plugin_api/message_api.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_MESSAGE_API_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_MESSAGE_API_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an informal message to a user.
|
||||||
|
* The user will see the message as if the hub sent it.
|
||||||
|
*/
|
||||||
|
extern int plugin_send_message(struct plugin_handle*, struct plugin_user* to, const char* message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a status message to a user.
|
||||||
|
*/
|
||||||
|
extern int plugin_send_status(struct plugin_handle* struct plugin_user* to, int code, const char* message);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_API_H */
|
||||||
96
src/plugin_api/types.h
Normal file
96
src/plugin_api/types.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_PLUGIN_TYPES_H
|
||||||
|
#define HAVE_UHUB_PLUGIN_TYPES_H
|
||||||
|
|
||||||
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|
||||||
|
#ifndef MAX_NICK_LEN
|
||||||
|
#define MAX_NICK_LEN 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_PASS_LEN
|
||||||
|
#define MAX_PASS_LEN 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_CID_LEN
|
||||||
|
#define MAX_CID_LEN 39
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_UA_LEN
|
||||||
|
#define MAX_UA_LEN 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SID_T_DEFINED
|
||||||
|
typedef uint32_t sid_t;
|
||||||
|
#define SID_T_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct plugin_handle;
|
||||||
|
|
||||||
|
struct plugin_user
|
||||||
|
{
|
||||||
|
sid_t sid;
|
||||||
|
char nick[MAX_NICK_LEN+1];
|
||||||
|
char cid[MAX_CID_LEN+1];
|
||||||
|
char user_agent[MAX_UA_LEN+1];
|
||||||
|
struct ip_addr_encap addr;
|
||||||
|
enum auth_credentials credentials;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct plugin_hub_info
|
||||||
|
{
|
||||||
|
const char* description;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum plugin_status
|
||||||
|
{
|
||||||
|
st_default = 0, /* Use default */
|
||||||
|
st_allow = 1, /* Allow action */
|
||||||
|
st_deny = -1, /* Deny action */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum plugin_status plugin_st;
|
||||||
|
|
||||||
|
struct auth_info
|
||||||
|
{
|
||||||
|
char nickname[MAX_NICK_LEN+1];
|
||||||
|
char password[MAX_PASS_LEN+1];
|
||||||
|
enum auth_credentials credentials;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ban_flags
|
||||||
|
{
|
||||||
|
ban_nickname = 0x01, /* Nickname is banned */
|
||||||
|
ban_cid = 0x02, /* CID is banned */
|
||||||
|
ban_ip = 0x04, /* IP address (range) is banned */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ban_info
|
||||||
|
{
|
||||||
|
unsigned int flags; /* See enum ban_flags. */
|
||||||
|
char nickname[MAX_NICK_LEN+1]; /* Nickname - only defined if (ban_nickname & flags). */
|
||||||
|
char cid[MAX_CID_LEN+1]; /* CID - only defined if (ban_cid & flags). */
|
||||||
|
struct ip_addr_encap ip_addr_lo; /* Low IP address of an IP range */
|
||||||
|
struct ip_addr_encap ip_addr_hi; /* High IP address of an IP range */
|
||||||
|
time_t expiry; /* Time when the ban record expires */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PLUGIN_TYPES_H */
|
||||||
242
src/plugins/mod_auth_simple.c
Normal file
242
src/plugins/mod_auth_simple.c
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/list.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acl_data
|
||||||
|
{
|
||||||
|
struct linked_list* users;
|
||||||
|
char* file;
|
||||||
|
int readonly;
|
||||||
|
int exclusive;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void insert_user(struct linked_list* users, const char* nick, const char* pass, enum auth_credentials cred)
|
||||||
|
{
|
||||||
|
struct auth_info* data = (struct auth_info*) hub_malloc_zero(sizeof(struct auth_info));
|
||||||
|
strncpy(data->nickname, nick, MAX_NICK_LEN);
|
||||||
|
strncpy(data->password, pass, MAX_PASS_LEN);
|
||||||
|
data->credentials = cred;
|
||||||
|
list_append(users, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_acl(struct acl_data* data)
|
||||||
|
{
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data->users)
|
||||||
|
{
|
||||||
|
list_clear(data->users, hub_free);
|
||||||
|
list_destroy(data->users);
|
||||||
|
}
|
||||||
|
hub_free(data->file);
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct acl_data* parse_config(const char* line)
|
||||||
|
{
|
||||||
|
struct acl_data* data = (struct acl_data*) hub_malloc_zero(sizeof(struct acl_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// set defaults
|
||||||
|
data->readonly = 1;
|
||||||
|
data->exclusive = 0;
|
||||||
|
data->users = list_create();
|
||||||
|
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
char* split = strchr(token, '=');
|
||||||
|
size_t len = strlen(token);
|
||||||
|
size_t key = split ? (split - token) : len;
|
||||||
|
if (key == 4 && strncmp(token, "file", 4) == 0)
|
||||||
|
{
|
||||||
|
if (data->file)
|
||||||
|
hub_free(data->file);
|
||||||
|
data->file = strdup(split + 1);
|
||||||
|
}
|
||||||
|
else if (key == 8 && strncmp(token, "readonly", 8) == 0)
|
||||||
|
{
|
||||||
|
if (!string_to_boolean(split + 1, &data->readonly))
|
||||||
|
data->readonly = 1;
|
||||||
|
}
|
||||||
|
else if (key == 9 && strncmp(token, "exclusive", 9) == 0)
|
||||||
|
{
|
||||||
|
if (!string_to_boolean(split + 1, &data->exclusive))
|
||||||
|
data->exclusive = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
free_acl(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_line(char* line, int line_count, void* ptr_data)
|
||||||
|
{
|
||||||
|
struct linked_list* users = (struct linked_list*) ptr_data;
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
enum auth_credentials cred;
|
||||||
|
char* credential;
|
||||||
|
char* username;
|
||||||
|
char* password;
|
||||||
|
|
||||||
|
if (cfg_token_count(tokens) == 0)
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg_token_count(tokens) < 2)
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
credential = cfg_token_get_first(tokens);
|
||||||
|
username = cfg_token_get_next(tokens);
|
||||||
|
password = cfg_token_get_next(tokens);
|
||||||
|
|
||||||
|
if (!auth_string_to_cred(credential, &cred))
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_user(users, username, password, cred);
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct acl_data* load_acl(const char* config, struct plugin_handle* handle)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct acl_data* data = parse_config(config);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data->file || !*data->file)
|
||||||
|
{
|
||||||
|
free_acl(data); data = 0;
|
||||||
|
set_error_message(handle, "No configuration file given, missing \"file=<filename>\" configuration option.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_read_lines(data->file, data->users, &parse_line) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unable to load %s\n", data->file);
|
||||||
|
set_error_message(handle, "Unable to load file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unload_acl(struct acl_data* data)
|
||||||
|
{
|
||||||
|
free_acl(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data)
|
||||||
|
{
|
||||||
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
||||||
|
struct auth_info* info = (struct auth_info*) list_get_first(acl->users);
|
||||||
|
while (info)
|
||||||
|
{
|
||||||
|
if (strcasecmp((char*)info->nickname, nickname) == 0)
|
||||||
|
{
|
||||||
|
memcpy(data, info, sizeof(struct auth_info));
|
||||||
|
return st_allow;
|
||||||
|
}
|
||||||
|
info = (struct auth_info*) list_get_next(acl->users);
|
||||||
|
}
|
||||||
|
if (acl->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
||||||
|
if (acl->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
||||||
|
if (acl->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
||||||
|
if (acl->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_API int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
PLUGIN_INITIALIZE(plugin, "File authentication plugin", "0.1", "Authenticate users based on a read-only text file.");
|
||||||
|
|
||||||
|
// Authentication actions.
|
||||||
|
plugin->funcs.auth_get_user = get_user;
|
||||||
|
plugin->funcs.auth_register_user = register_user;
|
||||||
|
plugin->funcs.auth_update_user = update_user;
|
||||||
|
plugin->funcs.auth_delete_user = delete_user;
|
||||||
|
|
||||||
|
plugin->ptr = load_acl(config, plugin);
|
||||||
|
if (plugin->ptr)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_API int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, 0);
|
||||||
|
unload_acl(plugin->ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
227
src/plugins/mod_auth_sqlite.c
Normal file
227
src/plugins/mod_auth_sqlite.c
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2012, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/list.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
|
||||||
|
// #define DEBUG_SQL
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sql_data
|
||||||
|
{
|
||||||
|
int exclusive;
|
||||||
|
sqlite3* db;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
struct cfg_settings* setting = cfg_settings_split(token);
|
||||||
|
|
||||||
|
if (!setting)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to parse startup parameters");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cfg_settings_get_key(setting), "file") == 0)
|
||||||
|
{
|
||||||
|
if (!data->db)
|
||||||
|
{
|
||||||
|
if (sqlite3_open(cfg_settings_get_value(setting), &data->db))
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
set_error_message(plugin, "Unable to open database file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "exclusive") == 0)
|
||||||
|
{
|
||||||
|
if (!string_to_boolean(cfg_settings_get_value(setting), &data->exclusive))
|
||||||
|
data->exclusive = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unknown startup parameters given");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
|
||||||
|
if (!data->db)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "No database file is given, use file=<database>");
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* sql_escape_string(const char* str)
|
||||||
|
{
|
||||||
|
static char out[1024];
|
||||||
|
size_t i = 0;
|
||||||
|
size_t n = 0;
|
||||||
|
for (; n < strlen(str); n++)
|
||||||
|
{
|
||||||
|
if (str[n] == '\'')
|
||||||
|
out[i++] = '\'';
|
||||||
|
out[i++] = str[n];
|
||||||
|
}
|
||||||
|
out[i++] = '\0';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct data_record {
|
||||||
|
struct auth_info* data;
|
||||||
|
int found;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_user_callback(void* ptr, int argc, char **argv, char **colName){
|
||||||
|
struct data_record* data = (struct data_record*) ptr;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < argc; i++) {
|
||||||
|
if (strcmp(colName[i], "nickname") == 0)
|
||||||
|
strncpy(data->data->nickname, argv[i], MAX_NICK_LEN);
|
||||||
|
else if (strcmp(colName[i], "password") == 0)
|
||||||
|
strncpy(data->data->password, argv[i], MAX_PASS_LEN);
|
||||||
|
else if (strcmp(colName[i], "credentials") == 0)
|
||||||
|
{
|
||||||
|
auth_string_to_cred(argv[i], &data->data->credentials);
|
||||||
|
data->found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_SQL
|
||||||
|
printf("SQL: nickname=%s, password=%s, credentials=%s\n", data->data->nickname, data->data->password, auth_cred_to_string(data->data->credentials));
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
struct data_record result;
|
||||||
|
char query[1024];
|
||||||
|
char* errMsg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
snprintf(query, sizeof(query), "SELECT * FROM users WHERE nickname='%s';", sql_escape_string(nickname));
|
||||||
|
memset(data, 0, sizeof(struct auth_info));
|
||||||
|
|
||||||
|
result.data = data;
|
||||||
|
result.found = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG_SQL
|
||||||
|
printf("SQL: %s\n", query);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = sqlite3_exec(sql->db, query , get_user_callback, &result, &errMsg);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
#ifdef DEBUG_SQL
|
||||||
|
fprintf(stderr, "SQL: ERROR: %s\n", errMsg);
|
||||||
|
#endif
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.found)
|
||||||
|
return st_allow;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
if (sql->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
if (sql->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
if (sql->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
PLUGIN_INITIALIZE(plugin, "SQLite authentication plugin", "0.1", "Authenticate users based on a SQLite database.");
|
||||||
|
|
||||||
|
// Authentication actions.
|
||||||
|
plugin->funcs.auth_get_user = get_user;
|
||||||
|
plugin->funcs.auth_register_user = register_user;
|
||||||
|
plugin->funcs.auth_update_user = update_user;
|
||||||
|
plugin->funcs.auth_delete_user = delete_user;
|
||||||
|
|
||||||
|
plugin->ptr = parse_config(config, plugin);
|
||||||
|
if (plugin->ptr)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct sql_data* sql;
|
||||||
|
set_error_message(plugin, 0);
|
||||||
|
sql = (struct sql_data*) plugin->ptr;
|
||||||
|
sqlite3_close(sql->db);
|
||||||
|
hub_free(sql);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
245
src/plugins/mod_chat_history.c
Normal file
245
src/plugins/mod_chat_history.c
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2012, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include "plugin_api/command_api.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/list.h"
|
||||||
|
#include "util/cbuffer.h"
|
||||||
|
|
||||||
|
#define MAX_HISTORY_SIZE 16384
|
||||||
|
|
||||||
|
struct chat_history_data
|
||||||
|
{
|
||||||
|
size_t history_max; ///<<< "the maximum number of chat messages kept in history."
|
||||||
|
size_t history_default; ///<<< "the default number of chat messages returned if no limit was provided"
|
||||||
|
size_t history_connect; ///<<< "the number of chat messages provided when users connect to the hub."
|
||||||
|
struct linked_list* chat_history; ///<<< "The chat history storage."
|
||||||
|
struct plugin_command_handle* command_history_handle; ///<<< "A handle to the !history command."
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a chat message to history.
|
||||||
|
*/
|
||||||
|
static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags)
|
||||||
|
{
|
||||||
|
size_t loglen = strlen(message) + strlen(from->nick) + 13;
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
char* log = hub_malloc(loglen + 1);
|
||||||
|
|
||||||
|
snprintf(log, loglen, "%s <%s> %s\n", get_timestamp(time(NULL)), from->nick, message);
|
||||||
|
log[loglen] = '\0';
|
||||||
|
list_append(data->chat_history, log);
|
||||||
|
while (list_size(data->chat_history) > data->history_max)
|
||||||
|
{
|
||||||
|
char* msg = list_get_first(data->chat_history);
|
||||||
|
list_remove(data->chat_history, msg);
|
||||||
|
hub_free(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain 'num' messages from the chat history and append them to outbuf.
|
||||||
|
*
|
||||||
|
* @return the number of messages added to the buffer.
|
||||||
|
*/
|
||||||
|
static size_t get_messages(struct chat_history_data* data, size_t num, struct cbuffer* outbuf)
|
||||||
|
{
|
||||||
|
struct linked_list* messages = data->chat_history;
|
||||||
|
char* message;
|
||||||
|
int skiplines = 0;
|
||||||
|
size_t lines = 0;
|
||||||
|
int total = list_size(messages);
|
||||||
|
|
||||||
|
if (total == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (num <= 0 || num > total)
|
||||||
|
num = total;
|
||||||
|
|
||||||
|
if (num != total)
|
||||||
|
skiplines = total - num;
|
||||||
|
|
||||||
|
cbuf_append(outbuf, "\n");
|
||||||
|
message = (char*) list_get_first(messages);
|
||||||
|
while (message)
|
||||||
|
{
|
||||||
|
if (--skiplines < 0)
|
||||||
|
{
|
||||||
|
cbuf_append(outbuf, message);
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
message = (char*) list_get_next(messages);
|
||||||
|
}
|
||||||
|
cbuf_append(outbuf, "\n");
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_login(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
struct cbuffer* buf = NULL;
|
||||||
|
// size_t messages = 0;
|
||||||
|
|
||||||
|
if (data->history_connect > 0 && list_size(data->chat_history) > 0)
|
||||||
|
{
|
||||||
|
buf = cbuf_create(MAX_HISTORY_SIZE);
|
||||||
|
cbuf_append(buf, "Chat history:\n");
|
||||||
|
get_messages(data, data->history_connect, buf);
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a status message back to the user who issued the !history command.
|
||||||
|
*/
|
||||||
|
static int command_status(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd, struct cbuffer* buf)
|
||||||
|
{
|
||||||
|
struct cbuffer* msg = cbuf_create(cbuf_size(buf) + strlen(cmd->prefix) + 8);
|
||||||
|
cbuf_append_format(msg, "*** %s: %s", cmd->prefix, cbuf_get(buf));
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(msg));
|
||||||
|
cbuf_destroy(msg);
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback function for handling the !history command.
|
||||||
|
*/
|
||||||
|
static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
struct cbuffer* buf;
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
int maxlines = 0;
|
||||||
|
|
||||||
|
if (!list_size(data->chat_history))
|
||||||
|
return command_status(plugin, user, cmd, cbuf_create_const("No messages."));
|
||||||
|
|
||||||
|
if (list_size(cmd->args) > 0)
|
||||||
|
maxlines = (int) (intptr_t) ((intptr_t*) (void*) list_get_first(cmd->args));
|
||||||
|
else
|
||||||
|
maxlines = data->history_default;
|
||||||
|
|
||||||
|
buf = cbuf_create(MAX_HISTORY_SIZE);
|
||||||
|
cbuf_append_format(buf, "*** %s: Chat History:\n", cmd->prefix);
|
||||||
|
get_messages(data, maxlines, buf);
|
||||||
|
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct chat_history_data* parse_config(const char* line, struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) hub_malloc_zero(sizeof(struct chat_history_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
data->history_max = 200;
|
||||||
|
data->history_default = 25;
|
||||||
|
data->history_connect = 5;
|
||||||
|
data->chat_history = list_create();
|
||||||
|
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
struct cfg_settings* setting = cfg_settings_split(token);
|
||||||
|
|
||||||
|
if (!setting)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to parse startup parameters");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cfg_settings_get_key(setting), "history_max") == 0)
|
||||||
|
{
|
||||||
|
data->history_max = (size_t) uhub_atoi(cfg_settings_get_value(setting));
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "history_default") == 0)
|
||||||
|
{
|
||||||
|
data->history_default = (size_t) uhub_atoi(cfg_settings_get_value(setting));
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "history_connect") == 0)
|
||||||
|
{
|
||||||
|
data->history_connect = (size_t) uhub_atoi(cfg_settings_get_value(setting));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unknown startup parameters given");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data;
|
||||||
|
PLUGIN_INITIALIZE(plugin, "Chat history plugin", "1.0", "Provide a global chat history log.");
|
||||||
|
|
||||||
|
plugin->funcs.on_user_chat_message = history_add;
|
||||||
|
plugin->funcs.on_user_login = user_login;
|
||||||
|
data = parse_config(config, plugin);
|
||||||
|
if (!data)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
plugin->ptr = data;
|
||||||
|
|
||||||
|
data->command_history_handle = (struct plugin_command_handle*) hub_malloc(sizeof(struct plugin_command_handle));
|
||||||
|
PLUGIN_COMMAND_INITIALIZE(data->command_history_handle, plugin, "history", "?N", auth_cred_guest, &command_history, "Show chat message history.");
|
||||||
|
plugin->hub.command_add(plugin, data->command_history_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct chat_history_data* data = (struct chat_history_data*) plugin->ptr;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
list_clear(data->chat_history, &hub_free);
|
||||||
|
list_destroy(data->chat_history);
|
||||||
|
|
||||||
|
plugin->hub.command_del(plugin, data->command_history_handle);
|
||||||
|
hub_free(data->command_history_handle);
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
163
src/plugins/mod_chat_only.c
Normal file
163
src/plugins/mod_chat_only.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2012, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
|
enum Warnings
|
||||||
|
{
|
||||||
|
WARN_SEARCH = 0x01, ///<<< "Warn about searching."
|
||||||
|
WARN_CONNECT = 0x02, ///<<< "Warn about connecting to a user"
|
||||||
|
WARN_EXTRA = 0x08, ///<<< "Warn about unknown protocol data."
|
||||||
|
};
|
||||||
|
|
||||||
|
struct user_info
|
||||||
|
{
|
||||||
|
sid_t sid; // The SID of the user
|
||||||
|
int warnings; // The number of denies (used to track wether or not a warning should be sent). @see enum Warnings.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chat_only_data
|
||||||
|
{
|
||||||
|
size_t num_users; // number of users tracked.
|
||||||
|
size_t max_users; // max users (hard limit max 1M users due to limitations in the SID (20 bits)).
|
||||||
|
struct user_info* users; // array of max_users
|
||||||
|
int operator_override; // operators are allowed to override these limitations.
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct chat_only_data* co_initialize()
|
||||||
|
{
|
||||||
|
struct chat_only_data* data = (struct chat_only_data*) hub_malloc(sizeof(struct chat_only_data));
|
||||||
|
data->num_users = 0;
|
||||||
|
data->max_users = 512;
|
||||||
|
data->users = hub_malloc_zero(sizeof(struct user_info) * data->max_users);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void co_shutdown(struct chat_only_data* data)
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
hub_free(data->users);
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct user_info* get_user_info(struct chat_only_data* data, sid_t sid)
|
||||||
|
{
|
||||||
|
struct user_info* u;
|
||||||
|
|
||||||
|
// resize buffer if needed.
|
||||||
|
if (sid > data->max_users) // FIXME: >= ?
|
||||||
|
{
|
||||||
|
u = hub_malloc_zero(sizeof(struct user_info) * (sid + 1));
|
||||||
|
memcpy(u, data->users, data->max_users);
|
||||||
|
hub_free(data->users);
|
||||||
|
data->users = u;
|
||||||
|
data->max_users = sid;
|
||||||
|
u = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u = &data->users[sid];
|
||||||
|
|
||||||
|
// reset counters if the user was not previously known.
|
||||||
|
if (!u->sid)
|
||||||
|
{
|
||||||
|
u->sid = sid;
|
||||||
|
u->warnings = 0;
|
||||||
|
data->num_users++;
|
||||||
|
}
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st on_search_result(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to, const char* search_data)
|
||||||
|
{
|
||||||
|
return st_deny;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st on_search(struct plugin_handle* plugin, struct plugin_user* user, const char* search_data)
|
||||||
|
{
|
||||||
|
struct chat_only_data* data = (struct chat_only_data*) plugin->ptr;
|
||||||
|
struct user_info* info = get_user_info(data, user->sid);
|
||||||
|
|
||||||
|
if (user->credentials >= auth_cred_operator && data->operator_override)
|
||||||
|
return st_allow;
|
||||||
|
|
||||||
|
if (!(info->warnings & WARN_SEARCH))
|
||||||
|
{
|
||||||
|
plugin->hub.send_status_message(plugin, user, 000, "Searching is disabled. This is a chat only hub.");
|
||||||
|
info->warnings |= WARN_SEARCH;
|
||||||
|
}
|
||||||
|
return st_deny;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st on_p2p_connect(struct plugin_handle* plugin, struct plugin_user* from, struct plugin_user* to)
|
||||||
|
{
|
||||||
|
struct chat_only_data* data = (struct chat_only_data*) plugin->ptr;
|
||||||
|
struct user_info* info = get_user_info(data, from->sid);
|
||||||
|
|
||||||
|
if (from->credentials >= auth_cred_operator && data->operator_override)
|
||||||
|
return st_allow;
|
||||||
|
|
||||||
|
if (!(info->warnings & WARN_CONNECT))
|
||||||
|
{
|
||||||
|
plugin->hub.send_status_message(plugin, from, 000, "Connection setup denied. This is a chat only hub.");
|
||||||
|
info->warnings |= WARN_CONNECT;
|
||||||
|
}
|
||||||
|
return st_deny;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct chat_only_data* data = (struct chat_only_data*) plugin->ptr;
|
||||||
|
/*struct user_info* info = */
|
||||||
|
get_user_info(data, user->sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason)
|
||||||
|
{
|
||||||
|
struct chat_only_data* data = (struct chat_only_data*) plugin->ptr;
|
||||||
|
struct user_info* info = get_user_info(data, user->sid);
|
||||||
|
if (info->sid)
|
||||||
|
data->num_users--;
|
||||||
|
info->warnings = 0;
|
||||||
|
info->sid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
PLUGIN_INITIALIZE(plugin, "Chat only hub", "1.0", "Disables connection setup, search and results.");
|
||||||
|
plugin->ptr = co_initialize();
|
||||||
|
|
||||||
|
plugin->funcs.on_search = on_search;
|
||||||
|
plugin->funcs.on_search_result = on_search_result;
|
||||||
|
plugin->funcs.on_p2p_connect = on_p2p_connect;
|
||||||
|
plugin->funcs.on_p2p_revconnect = on_p2p_connect;
|
||||||
|
plugin->funcs.on_user_login = on_user_login;
|
||||||
|
plugin->funcs.on_user_logout = on_user_logout;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
co_shutdown((struct chat_only_data*) plugin->ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
67
src/plugins/mod_example.c
Normal file
67
src/plugins/mod_example.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include "plugin_api/command_api.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
|
struct example_plugin_data
|
||||||
|
{
|
||||||
|
struct plugin_command_handle* example;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int example_command_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
plugin->hub.send_message(plugin, user, "Hello from mod_example.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void command_register(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct example_plugin_data* data = (struct example_plugin_data*) hub_malloc(sizeof(struct example_plugin_data));
|
||||||
|
data->example = hub_malloc_zero(sizeof(struct plugin_command_handle));
|
||||||
|
PLUGIN_COMMAND_INITIALIZE(data->example, (void*) data, "example", "", auth_cred_guest, example_command_handler, "This is an example command that is added dynamically by loading the mod_example plug-in.");
|
||||||
|
plugin->hub.command_add(plugin, data->example);
|
||||||
|
plugin->ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void command_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct example_plugin_data* data = (struct example_plugin_data*) plugin->ptr;
|
||||||
|
|
||||||
|
plugin->hub.command_del(plugin, data->example);
|
||||||
|
hub_free(data->example);
|
||||||
|
|
||||||
|
hub_free(data);
|
||||||
|
plugin->ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
PLUGIN_INITIALIZE(plugin, "Example plugin", "1.0", "A simple example plugin");
|
||||||
|
command_register(plugin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
command_unregister(plugin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
251
src/plugins/mod_logging.c
Normal file
251
src/plugins/mod_logging.c
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "adc/adcconst.h"
|
||||||
|
#include "adc/sid.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
struct ip_addr_encap;
|
||||||
|
|
||||||
|
struct log_data
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
mode_file,
|
||||||
|
mode_syslog
|
||||||
|
} logmode;
|
||||||
|
char* logfile;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void reset(struct log_data* data)
|
||||||
|
{
|
||||||
|
/* set defaults */
|
||||||
|
data->logmode = mode_file;
|
||||||
|
data->logfile = NULL;
|
||||||
|
data->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int log_open_file(struct plugin_handle* plugin, struct log_data* data)
|
||||||
|
{
|
||||||
|
int flags = O_CREAT | O_APPEND | O_WRONLY;
|
||||||
|
data->fd = open(data->logfile, flags, 0664);
|
||||||
|
return (data->fd != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int log_open_syslog(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
openlog("uhub", 0, LOG_USER);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct log_data* parse_config(const char* line, struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct log_data* data = (struct log_data*) hub_malloc(sizeof(struct log_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
reset(data);
|
||||||
|
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
struct cfg_settings* setting = cfg_settings_split(token);
|
||||||
|
|
||||||
|
if (!setting)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to parse startup parameters");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cfg_settings_get_key(setting), "file") == 0)
|
||||||
|
{
|
||||||
|
data->logfile = strdup(cfg_settings_get_value(setting));
|
||||||
|
data->logmode = mode_file;
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "syslog") == 0)
|
||||||
|
{
|
||||||
|
int use_syslog = 0;
|
||||||
|
if (!string_to_boolean(cfg_settings_get_value(setting), &use_syslog))
|
||||||
|
{
|
||||||
|
data->logmode = (use_syslog) ? mode_syslog : mode_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unknown startup parameters given");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
|
||||||
|
if (data->logmode == mode_file)
|
||||||
|
{
|
||||||
|
if ((data->logmode == mode_file && !data->logfile))
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "No log file is given, use file=<path>");
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!log_open_file(plugin, data))
|
||||||
|
{
|
||||||
|
hub_free(data->logfile);
|
||||||
|
hub_free(data);
|
||||||
|
set_error_message(plugin, "Unable to open log file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!log_open_syslog(plugin))
|
||||||
|
{
|
||||||
|
hub_free(data->logfile);
|
||||||
|
hub_free(data);
|
||||||
|
set_error_message(plugin, "Unable to open syslog");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_close(struct log_data* data)
|
||||||
|
{
|
||||||
|
if (data->logmode == mode_file)
|
||||||
|
{
|
||||||
|
hub_free(data->logfile);
|
||||||
|
close(data->fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
closelog();
|
||||||
|
}
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_message(struct log_data* data, const char *format, ...)
|
||||||
|
{
|
||||||
|
static char logmsg[1024];
|
||||||
|
struct tm *tmp;
|
||||||
|
time_t t;
|
||||||
|
va_list args;
|
||||||
|
ssize_t size = 0;
|
||||||
|
|
||||||
|
if (data->logmode == mode_file)
|
||||||
|
{
|
||||||
|
t = time(NULL);
|
||||||
|
tmp = localtime(&t);
|
||||||
|
strftime(logmsg, 32, "%Y-%m-%d %H:%M:%S ", tmp);
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
size = vsnprintf(logmsg + 20, 1004, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (write(data->fd, logmsg, size + 20) < (size+20))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unable to write full log. Error=%d: %s\n", errno, strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined _POSIX_SYNCHRONIZED_IO && _POSIX_SYNCHRONIZED_IO > 0
|
||||||
|
fdatasync(data->fd);
|
||||||
|
#else
|
||||||
|
fsync(data->fd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_start(args, format);
|
||||||
|
vsyslog(LOG_INFO, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_user_login(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
const char* cred = auth_cred_to_string(user->credentials);
|
||||||
|
const char* addr = ip_convert_to_string(&user->addr);
|
||||||
|
|
||||||
|
log_message(plugin->ptr, "LoginOK %s/%s %s \"%s\" (%s) \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, cred, user->user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_user_login_error(struct plugin_handle* plugin, struct plugin_user* user, const char* reason)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(&user->addr);
|
||||||
|
log_message(plugin->ptr, "LoginError %s/%s %s \"%s\" (%s) \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, reason, user->user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_user_logout(struct plugin_handle* plugin, struct plugin_user* user, const char* reason)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(&user->addr);
|
||||||
|
log_message(plugin->ptr, "Logout %s/%s %s \"%s\" (%s) \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, reason, user->user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void log_change_nick(struct plugin_handle* plugin, struct plugin_user* user, const char* new_nick)
|
||||||
|
{
|
||||||
|
const char* addr = ip_convert_to_string(&user->addr);
|
||||||
|
log_message(plugin->ptr, "NickChange %s/%s %s \"%s\" -> \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, new_nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
PLUGIN_INITIALIZE(plugin, "Logging plugin", "1.0", "Logs users entering and leaving the hub.");
|
||||||
|
|
||||||
|
plugin->funcs.on_user_login = log_user_login;
|
||||||
|
plugin->funcs.on_user_login_error = log_user_login_error;
|
||||||
|
plugin->funcs.on_user_logout = log_user_logout;
|
||||||
|
plugin->funcs.on_user_nick_change = log_change_nick;
|
||||||
|
|
||||||
|
plugin->ptr = parse_config(config, plugin);
|
||||||
|
if (!plugin->ptr)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
/* No need to do anything! */
|
||||||
|
log_close(plugin->ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
304
src/plugins/mod_welcome.c
Normal file
304
src/plugins/mod_welcome.c
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2012, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "system.h"
|
||||||
|
#include "adc/adcconst.h"
|
||||||
|
#include "adc/sid.h"
|
||||||
|
#include "util/cbuffer.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include "plugin_api/command_api.h"
|
||||||
|
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#define MAX_WELCOME_SIZE 16384
|
||||||
|
|
||||||
|
struct welcome_data
|
||||||
|
{
|
||||||
|
char* motd_file;
|
||||||
|
char* motd;
|
||||||
|
char* rules_file;
|
||||||
|
char* rules;
|
||||||
|
struct plugin_command_handle* cmd_motd;
|
||||||
|
struct plugin_command_handle* cmd_rules;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int command_handler_motd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd);
|
||||||
|
static int command_handler_rules(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd);
|
||||||
|
|
||||||
|
static char* read_file(const char* filename)
|
||||||
|
{
|
||||||
|
char* str;
|
||||||
|
char buf[MAX_WELCOME_SIZE];
|
||||||
|
int fd = open(filename, O_RDONLY);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = read(fd, buf, MAX_WELCOME_SIZE);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
buf[ret > 0 ? ret : 0] = 0;
|
||||||
|
str = strdup(buf);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_motd(struct welcome_data* data)
|
||||||
|
{
|
||||||
|
data->motd = read_file(data->motd_file);
|
||||||
|
return !!data->motd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_rules(struct welcome_data* data)
|
||||||
|
{
|
||||||
|
data->rules = read_file(data->rules_file);
|
||||||
|
return !!data->rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_welcome_data(struct welcome_data* data)
|
||||||
|
{
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hub_free(data->cmd_motd);
|
||||||
|
hub_free(data->motd_file);
|
||||||
|
hub_free(data->motd);
|
||||||
|
hub_free(data->cmd_rules);
|
||||||
|
hub_free(data->rules_file);
|
||||||
|
hub_free(data->rules);
|
||||||
|
hub_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct welcome_data* parse_config(const char* line, struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct welcome_data* data = (struct welcome_data*) hub_malloc_zero(sizeof(struct welcome_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
struct cfg_settings* setting = cfg_settings_split(token);
|
||||||
|
|
||||||
|
if (!setting)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to parse startup parameters");
|
||||||
|
goto cleanup_parse_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cfg_settings_get_key(setting), "motd") == 0)
|
||||||
|
{
|
||||||
|
data->motd_file = strdup(cfg_settings_get_value(setting));
|
||||||
|
if (!read_motd(data))
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to read motd file.");
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
goto cleanup_parse_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->cmd_motd = hub_malloc_zero(sizeof(struct plugin_command_handle));
|
||||||
|
PLUGIN_COMMAND_INITIALIZE(data->cmd_motd, (void*) data, "motd", "", auth_cred_guest, command_handler_motd, "Show the message of the day.");
|
||||||
|
}
|
||||||
|
else if (strcmp(cfg_settings_get_key(setting), "rules") == 0)
|
||||||
|
{
|
||||||
|
data->rules_file = strdup(cfg_settings_get_value(setting));
|
||||||
|
if (!read_rules(data))
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to read rules file.");
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
goto cleanup_parse_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->cmd_rules = hub_malloc_zero(sizeof(struct plugin_command_handle));
|
||||||
|
PLUGIN_COMMAND_INITIALIZE(data->cmd_rules, (void*) data, "rules", "", auth_cred_guest, command_handler_rules, "Show the hub rules.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unknown startup parameters given");
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
goto cleanup_parse_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_settings_free(setting);
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return data;
|
||||||
|
|
||||||
|
cleanup_parse_error:
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
free_welcome_data(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct cbuffer* parse_message(struct plugin_user* user, const char* msg)
|
||||||
|
{
|
||||||
|
struct cbuffer* buf = cbuf_create(strlen(msg));
|
||||||
|
const char* start = msg;
|
||||||
|
const char* offset = NULL;
|
||||||
|
time_t timestamp = time(NULL);
|
||||||
|
struct tm* now = localtime(×tamp);
|
||||||
|
|
||||||
|
while ((offset = strchr(start, '%')))
|
||||||
|
{
|
||||||
|
cbuf_append_bytes(buf, start, (offset - start));
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
switch (offset[0])
|
||||||
|
{
|
||||||
|
case 'n':
|
||||||
|
cbuf_append(buf, user->nick);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
cbuf_append(buf, ip_convert_to_string(&user->addr));
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
cbuf_append(buf, auth_cred_to_string(user->credentials));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
cbuf_append(buf, "%");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'H':
|
||||||
|
cbuf_append_strftime(buf, "%H", now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
cbuf_append_strftime(buf, "%I", now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P':
|
||||||
|
cbuf_append_strftime(buf, "%P", now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
cbuf_append_strftime(buf, "%p", now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'M':
|
||||||
|
cbuf_append_strftime(buf, "%M", now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
cbuf_append_strftime(buf, "%S", now);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = offset + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*start)
|
||||||
|
cbuf_append(buf, start);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_motd(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct welcome_data* data = (struct welcome_data*) plugin->ptr;
|
||||||
|
struct cbuffer* buf = NULL;
|
||||||
|
if (data->motd)
|
||||||
|
{
|
||||||
|
buf = parse_message(user, data->motd);
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_rules(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
struct welcome_data* data = (struct welcome_data*) plugin->ptr;
|
||||||
|
struct cbuffer* buf = NULL;
|
||||||
|
if (data->rules)
|
||||||
|
{
|
||||||
|
buf = parse_message(user, data->rules);
|
||||||
|
plugin->hub.send_message(plugin, user, cbuf_get(buf));
|
||||||
|
cbuf_destroy(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_user_login(struct plugin_handle* plugin, struct plugin_user* user)
|
||||||
|
{
|
||||||
|
send_motd(plugin, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_handler_motd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
send_motd(plugin, user);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_handler_rules(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd)
|
||||||
|
{
|
||||||
|
send_rules(plugin, user);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
struct welcome_data* data;
|
||||||
|
PLUGIN_INITIALIZE(plugin, "Welcome plugin", "0.1", "Sends a welcome message to users when they log into the hub.");
|
||||||
|
data = parse_config(config, plugin);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
plugin->ptr = data;
|
||||||
|
plugin->funcs.on_user_login = on_user_login;
|
||||||
|
|
||||||
|
if (data->cmd_motd)
|
||||||
|
plugin->hub.command_add(plugin, data->cmd_motd);
|
||||||
|
|
||||||
|
if (data->cmd_rules)
|
||||||
|
plugin->hub.command_add(plugin, data->cmd_rules);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct welcome_data* data = (struct welcome_data*) plugin->ptr;
|
||||||
|
|
||||||
|
if (data->cmd_motd)
|
||||||
|
plugin->hub.command_del(plugin, data->cmd_motd);
|
||||||
|
|
||||||
|
if (data->cmd_rules)
|
||||||
|
plugin->hub.command_del(plugin, data->cmd_rules);
|
||||||
|
|
||||||
|
free_welcome_data(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
191
src/system.h
191
src/system.h
@@ -22,35 +22,29 @@
|
|||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
#if USE_REGPARM && __GNUC__ >= 3
|
|
||||||
#define REGPRM1 __attribute__((regparm(1)))
|
|
||||||
#define REGPRM2 __attribute__((regparm(2)))
|
|
||||||
#define REGPRM3 __attribute__((regparm(3)))
|
|
||||||
#else
|
|
||||||
#define REGPRM1
|
|
||||||
#define REGPRM2
|
|
||||||
#define REGPRM3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FORCEINLINE
|
|
||||||
#if __GNUC__ < 3
|
|
||||||
#define FORCEINLINE inline
|
|
||||||
#else
|
|
||||||
#define FORCEINLINE inline __attribute__((always_inline))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__CYGWIN__) || defined(__MINGW32__)
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD_kernel__)
|
||||||
|
#define BSD_LIKE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
|
||||||
#ifndef WINSOCK
|
#ifndef WINSOCK
|
||||||
#define WINSOCK
|
#define WINSOCK
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__) || defined(__MINGW32__)
|
||||||
|
#define HAVE_SSIZE_T
|
||||||
|
#define NEED_GETOPT
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
|
#ifndef FD_SETSIZE
|
||||||
|
#define FD_SETSIZE 4096
|
||||||
|
#endif
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#else
|
#else
|
||||||
@@ -66,22 +60,31 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
|
||||||
|
#ifndef __sun__
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#define HAVE_STRNDUP
|
#define HAVE_STRNDUP
|
||||||
|
#define HAVE_DLOPEN
|
||||||
|
#define HAVE_GETOPT
|
||||||
|
#define HAVE_SSIZE_T
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#ifndef __HAIKU__
|
||||||
#define HAVE_MEMMEM
|
#define HAVE_MEMMEM
|
||||||
|
#endif
|
||||||
#define HAVE_GETRLIMIT
|
#define HAVE_GETRLIMIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -105,16 +108,123 @@
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#define USE_EPOLL
|
#define USE_EPOLL
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef BSD_LIKE
|
||||||
|
/*
|
||||||
|
#define USE_KQUEUE
|
||||||
|
#include <sys/event.h>
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
#define USE_SELECT
|
#define USE_SELECT
|
||||||
|
#ifndef WINSOCK
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__)
|
#if defined(BSD_LIKE) || defined(__sun__)
|
||||||
#undef HAVE_STRNDUP
|
#undef HAVE_STRNDUP
|
||||||
#undef HAVE_MEMMEM
|
#undef HAVE_MEMMEM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GETOPT
|
||||||
|
#include <getopt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect operating system info.
|
||||||
|
* See: http://predef.sourceforge.net/
|
||||||
|
*/
|
||||||
|
#if defined(__linux__)
|
||||||
|
#define OPSYS "Linux"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__MINGW32__) || defined(_WIN64) || defined(__WIN32__) || defined(__WINDOWS__)
|
||||||
|
#define OPSYS "Windows"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
|
#define OPSYS "MacOSX"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||||
|
#define OPSYS "FreeBSD"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
#define OPSYS "OpenBSD"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__NetBSD__)
|
||||||
|
#define OPSYS "NetBSD"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sun__)
|
||||||
|
#if defined(__SVR4) || defined(__svr4__)
|
||||||
|
#define OPSYS "Solaris"
|
||||||
|
#else
|
||||||
|
#define OPSYS "SunOS"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__HAIKU__)
|
||||||
|
#define OPSYS "Haiku"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNU__)
|
||||||
|
#define OPSYS "Hurd"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Detect CPUs */
|
||||||
|
#if defined(__alpha__) || defined(__alpha)
|
||||||
|
#define CPUINFO "Alpha"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(_M_X64)
|
||||||
|
#define CPUINFO "AMD64"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(__TARGET_ARCH_ARM)
|
||||||
|
#define CPUINFO "ARM"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__i386__) || defined(__i386) || defined(i386) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__THW_INTEL__)
|
||||||
|
#define CPUINFO "i386"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__ia64) || defined(_M_IA64)
|
||||||
|
#define CPUINFO "IA64"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__hppa__) || defined(__hppa)
|
||||||
|
#define CPUINFO "PARISC"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__m68k__) || defined(M68000)
|
||||||
|
#define CPUINFO "M68K"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__mips__) || defined(mips) || defined(__mips) || defined(__MIPS__)
|
||||||
|
#define CPUINFO "MIPS"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__POWERPC__) || defined(__ppc__) || defined(_ARCH_PPC) || defined(__powerpc) || defined(__powerpc__)
|
||||||
|
#define CPUINFO "PowerPC"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sparc__) || defined(__sparc)
|
||||||
|
#define CPUINFO "SPARC"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sh__)
|
||||||
|
#define CPUINFO "SuperH"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__s390__) || defined(__s390x__)
|
||||||
|
#define CPUINFO "s390"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
#ifdef MSG_NOSIGNAL
|
#ifdef MSG_NOSIGNAL
|
||||||
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL
|
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL
|
||||||
#else
|
#else
|
||||||
@@ -129,8 +239,41 @@
|
|||||||
#define INET6_ADDRSTRLEN 46
|
#define INET6_ADDRSTRLEN 46
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SSIZE_T
|
||||||
|
typedef int ssize_t;
|
||||||
|
#define HAVE_SSIZE_T
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define strdup _strdup
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#define strncasecmp _strnicmp
|
||||||
|
#define atoll _atoi64
|
||||||
|
#include <io.h>
|
||||||
|
#define open _open
|
||||||
|
#define close _close
|
||||||
|
#define read _read
|
||||||
|
#define NEED_GETOPT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
|
||||||
|
#define PLUGIN_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define PLUGIN_API
|
||||||
|
#endif
|
||||||
#endif /* HAVE_UHUB_SYSTEM_H */
|
#endif /* HAVE_UHUB_SYSTEM_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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -23,10 +23,14 @@
|
|||||||
#define ADC_CID_SIZE 39
|
#define ADC_CID_SIZE 39
|
||||||
#define BIG_BUFSIZE 32768
|
#define BIG_BUFSIZE 32768
|
||||||
#define TIGERSIZE 24
|
#define TIGERSIZE 24
|
||||||
|
// #define ADCC_DEBUG
|
||||||
|
|
||||||
static ssize_t ADC_client_recv(struct ADC_client* client);
|
static ssize_t ADC_client_recv(struct ADC_client* client);
|
||||||
static void ADC_client_send_info(struct ADC_client* client);
|
static void ADC_client_send_info(struct ADC_client* client);
|
||||||
static void ADC_client_on_connected(struct ADC_client* client);
|
static void ADC_client_on_connected(struct ADC_client* client);
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
static void ADC_client_on_connected_ssl(struct ADC_client* client);
|
||||||
|
#endif
|
||||||
static void ADC_client_on_disconnected(struct ADC_client* client);
|
static void ADC_client_on_disconnected(struct ADC_client* client);
|
||||||
static void ADC_client_on_login(struct ADC_client* client);
|
static void ADC_client_on_login(struct ADC_client* client);
|
||||||
static int ADC_client_parse_address(struct ADC_client* client, const char* arg);
|
static int ADC_client_parse_address(struct ADC_client* client, const char* arg);
|
||||||
@@ -42,14 +46,42 @@ static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
|
|||||||
fprintf(stdout, "* [%p] %s\n", client, logmsg);
|
fprintf(stdout, "* [%p] %s\n", client, logmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ADCC_DEBUG
|
||||||
|
#define ADC_TRACE fprintf(stderr, "TRACE: %s\n", __PRETTY_FUNCTION__)
|
||||||
|
#else
|
||||||
|
#define ADC_TRACE do { } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ADCC_DEBUG
|
||||||
|
static const char* ADC_client_state_string[] =
|
||||||
|
{
|
||||||
|
"ps_none",
|
||||||
|
"ps_conn",
|
||||||
|
"ps_conn_ssl",
|
||||||
|
"ps_protocol",
|
||||||
|
"ps_identify",
|
||||||
|
"ps_verify",
|
||||||
|
"ps_normal",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ADC_client_set_state(struct ADC_client* client, enum ADC_client_state state)
|
static void ADC_client_set_state(struct ADC_client* client, enum ADC_client_state state)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
|
if (client->state != state)
|
||||||
|
{
|
||||||
|
#ifdef ADCC_DEBUG
|
||||||
|
ADC_client_debug(client, "Set state %s (was %s)", ADC_client_state_string[(int) state], ADC_client_state_string[(int) client->state]);
|
||||||
|
#endif
|
||||||
client->state = state;
|
client->state = state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void adc_cid_pid(struct ADC_client* client)
|
static void adc_cid_pid(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
char seed[64];
|
char seed[64];
|
||||||
char pid[64];
|
char pid[64];
|
||||||
char cid[64];
|
char cid[64];
|
||||||
@@ -73,17 +105,35 @@ static void adc_cid_pid(struct ADC_client* client)
|
|||||||
|
|
||||||
static void event_callback(struct net_connection* con, int events, void *arg)
|
static void event_callback(struct net_connection* con, int events, void *arg)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con);
|
struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con);
|
||||||
|
|
||||||
|
switch (client->state)
|
||||||
|
{
|
||||||
|
case ps_conn:
|
||||||
if (events == NET_EVENT_TIMEOUT)
|
if (events == NET_EVENT_TIMEOUT)
|
||||||
{
|
|
||||||
if (client->state == ps_conn)
|
|
||||||
{
|
{
|
||||||
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
|
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (events & NET_EVENT_WRITE)
|
||||||
|
ADC_client_connect(client, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
case ps_conn_ssl:
|
||||||
|
if (events == NET_EVENT_TIMEOUT)
|
||||||
|
{
|
||||||
|
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADC_client_on_connected_ssl(client);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
if (events & NET_EVENT_READ)
|
if (events & NET_EVENT_READ)
|
||||||
{
|
{
|
||||||
if (ADC_client_recv(client) == -1)
|
if (ADC_client_recv(client) == -1)
|
||||||
@@ -93,12 +143,6 @@ static void event_callback(struct net_connection* con, int events, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (events & NET_EVENT_WRITE)
|
if (events & NET_EVENT_WRITE)
|
||||||
{
|
|
||||||
if (client->state == ps_conn)
|
|
||||||
{
|
|
||||||
ADC_client_connect(client, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* FIXME: Call send again */
|
/* FIXME: Call send again */
|
||||||
}
|
}
|
||||||
@@ -127,6 +171,7 @@ static void event_callback(struct net_connection* con, int events, void *arg)
|
|||||||
|
|
||||||
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
|
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
#ifdef ADC_CLIENT_DEBUG_PROTO
|
#ifdef ADC_CLIENT_DEBUG_PROTO
|
||||||
ADC_client_debug(client, "- LINE: '%s'", start);
|
ADC_client_debug(client, "- LINE: '%s'", start);
|
||||||
#endif
|
#endif
|
||||||
@@ -213,6 +258,7 @@ static void ADC_client_on_recv_line(struct ADC_client* client, const char* line,
|
|||||||
if (adc_msg_has_named_argument(msg, "ID"))
|
if (adc_msg_has_named_argument(msg, "ID"))
|
||||||
{
|
{
|
||||||
struct ADC_user user;
|
struct ADC_user user;
|
||||||
|
user.sid = msg->source;
|
||||||
EXTRACT_NAMED_ARG(msg, "NI", user.name);
|
EXTRACT_NAMED_ARG(msg, "NI", user.name);
|
||||||
EXTRACT_NAMED_ARG(msg, "DE", user.description);
|
EXTRACT_NAMED_ARG(msg, "DE", user.description);
|
||||||
EXTRACT_NAMED_ARG(msg, "VE", user.version);
|
EXTRACT_NAMED_ARG(msg, "VE", user.version);
|
||||||
@@ -250,6 +296,7 @@ static void ADC_client_on_recv_line(struct ADC_client* client, const char* line,
|
|||||||
|
|
||||||
static ssize_t ADC_client_recv(struct ADC_client* client)
|
static ssize_t ADC_client_recv(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
ssize_t size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset);
|
ssize_t size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset);
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return size;
|
return size;
|
||||||
@@ -285,6 +332,7 @@ static ssize_t ADC_client_recv(struct ADC_client* client)
|
|||||||
|
|
||||||
void ADC_client_send(struct ADC_client* client, char* msg)
|
void ADC_client_send(struct ADC_client* client, char* msg)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
int ret = net_con_send(client->con, msg, strlen(msg));
|
int ret = net_con_send(client->con, msg, strlen(msg));
|
||||||
|
|
||||||
#ifdef ADC_CLIENT_DEBUG_PROTO
|
#ifdef ADC_CLIENT_DEBUG_PROTO
|
||||||
@@ -311,6 +359,7 @@ void ADC_client_send(struct ADC_client* client, char* msg)
|
|||||||
|
|
||||||
void ADC_client_send_info(struct ADC_client* client)
|
void ADC_client_send_info(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
char binf[11];
|
char binf[11];
|
||||||
snprintf(binf, 11, "BINF %s\n", sid_to_string(client->sid));
|
snprintf(binf, 11, "BINF %s\n", sid_to_string(client->sid));
|
||||||
client->info = adc_msg_create(binf);
|
client->info = adc_msg_create(binf);
|
||||||
@@ -330,6 +379,7 @@ void ADC_client_send_info(struct ADC_client* client)
|
|||||||
|
|
||||||
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description)
|
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
memset(client, 0, sizeof(struct ADC_client));
|
memset(client, 0, sizeof(struct ADC_client));
|
||||||
|
|
||||||
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
@@ -355,6 +405,7 @@ int ADC_client_create(struct ADC_client* client, const char* nickname, const cha
|
|||||||
|
|
||||||
void ADC_client_destroy(struct ADC_client* client)
|
void ADC_client_destroy(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
ADC_client_disconnect(client);
|
ADC_client_disconnect(client);
|
||||||
#if 0
|
#if 0
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
@@ -369,6 +420,7 @@ void ADC_client_destroy(struct ADC_client* client)
|
|||||||
|
|
||||||
int ADC_client_connect(struct ADC_client* client, const char* address)
|
int ADC_client_connect(struct ADC_client* client, const char* address)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
if (!client->hub_address)
|
if (!client->hub_address)
|
||||||
{
|
{
|
||||||
if (!ADC_client_parse_address(client, address))
|
if (!ADC_client_parse_address(client, address))
|
||||||
@@ -383,13 +435,10 @@ int ADC_client_connect(struct ADC_client* client, const char* address)
|
|||||||
ADC_client_on_connected(client);
|
ADC_client_on_connected(client);
|
||||||
}
|
}
|
||||||
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
|
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
|
||||||
{
|
|
||||||
if (client->state != ps_conn)
|
|
||||||
{
|
{
|
||||||
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
|
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||||
ADC_client_set_state(client, ps_conn);
|
ADC_client_set_state(client, ps_conn);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ADC_client_on_disconnected(client);
|
ADC_client_on_disconnected(client);
|
||||||
@@ -400,14 +449,38 @@ int ADC_client_connect(struct ADC_client* client, const char* address)
|
|||||||
|
|
||||||
static void ADC_client_on_connected(struct ADC_client* client)
|
static void ADC_client_on_connected(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (client->ssl_enabled)
|
||||||
|
{
|
||||||
|
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||||
|
client->callback(client, ADC_CLIENT_SSL_HANDSHAKE, 0);
|
||||||
|
ADC_client_set_state(client, ps_conn_ssl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
net_con_update(client->con, NET_EVENT_READ);
|
||||||
|
client->callback(client, ADC_CLIENT_CONNECTED, 0);
|
||||||
|
ADC_client_send(client, ADC_HANDSHAKE);
|
||||||
|
ADC_client_set_state(client, ps_protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
static void ADC_client_on_connected_ssl(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
ADC_TRACE;
|
||||||
net_con_update(client->con, NET_EVENT_READ);
|
net_con_update(client->con, NET_EVENT_READ);
|
||||||
client->callback(client, ADC_CLIENT_CONNECTED, 0);
|
client->callback(client, ADC_CLIENT_CONNECTED, 0);
|
||||||
ADC_client_send(client, ADC_HANDSHAKE);
|
ADC_client_send(client, ADC_HANDSHAKE);
|
||||||
ADC_client_set_state(client, ps_protocol);
|
ADC_client_set_state(client, ps_protocol);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ADC_client_on_disconnected(struct ADC_client* client)
|
static void ADC_client_on_disconnected(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
net_con_close(client->con);
|
net_con_close(client->con);
|
||||||
client->con = 0;
|
client->con = 0;
|
||||||
ADC_client_set_state(client, ps_none);
|
ADC_client_set_state(client, ps_none);
|
||||||
@@ -415,12 +488,14 @@ static void ADC_client_on_disconnected(struct ADC_client* client)
|
|||||||
|
|
||||||
static void ADC_client_on_login(struct ADC_client* client)
|
static void ADC_client_on_login(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
ADC_client_set_state(client, ps_normal);
|
ADC_client_set_state(client, ps_normal);
|
||||||
client->callback(client, ADC_CLIENT_LOGGED_IN, 0);
|
client->callback(client, ADC_CLIENT_LOGGED_IN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ADC_client_disconnect(struct ADC_client* client)
|
void ADC_client_disconnect(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
if (client->con && net_con_get_sd(client->con) != -1)
|
if (client->con && net_con_get_sd(client->con) != -1)
|
||||||
{
|
{
|
||||||
net_con_close(client->con);
|
net_con_close(client->con);
|
||||||
@@ -430,6 +505,7 @@ void ADC_client_disconnect(struct ADC_client* client)
|
|||||||
|
|
||||||
static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
|
static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
char* split;
|
char* split;
|
||||||
int ssl = 0;
|
int ssl = 0;
|
||||||
struct hostent* dns;
|
struct hostent* dns;
|
||||||
@@ -446,9 +522,12 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
|
|||||||
|
|
||||||
/* Check for ADC or ADCS */
|
/* Check for ADC or ADCS */
|
||||||
if (!strncmp(arg, "adc://", 6))
|
if (!strncmp(arg, "adc://", 6))
|
||||||
ssl = 0;
|
client->ssl_enabled = 0;
|
||||||
else if (!strncmp(arg, "adcs://", 7))
|
else if (!strncmp(arg, "adcs://", 7))
|
||||||
|
{
|
||||||
|
client->ssl_enabled = 1;
|
||||||
ssl = 1;
|
ssl = 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -481,5 +560,6 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
|
|||||||
|
|
||||||
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb)
|
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb)
|
||||||
{
|
{
|
||||||
|
ADC_TRACE;
|
||||||
client->callback = cb;
|
client->callback = cb;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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-2011, Jan Vidar Krey
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,12 +26,13 @@
|
|||||||
|
|
||||||
enum ADC_client_state
|
enum ADC_client_state
|
||||||
{
|
{
|
||||||
ps_none = 0x00, /* Not connected */
|
ps_none, /* Not connected */
|
||||||
ps_conn = 0x01, /* Connecting... */
|
ps_conn, /* Connecting... */
|
||||||
ps_protocol = 0x02, /* Have sent HSUP */
|
ps_conn_ssl, /* SSL handshake */
|
||||||
ps_identify = 0x04, /* Have sent BINF */
|
ps_protocol, /* Have sent HSUP */
|
||||||
ps_verify = 0x08, /* Have sent HPAS */
|
ps_identify, /* Have sent BINF */
|
||||||
ps_normal = 0x10, /* Are fully logged in */
|
ps_verify, /* Have sent HPAS */
|
||||||
|
ps_normal, /* Are fully logged in */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ADC_client;
|
struct ADC_client;
|
||||||
@@ -41,6 +42,8 @@ enum ADC_client_callback_type
|
|||||||
ADC_CLIENT_CONNECTING = 1001,
|
ADC_CLIENT_CONNECTING = 1001,
|
||||||
ADC_CLIENT_CONNECTED = 1002,
|
ADC_CLIENT_CONNECTED = 1002,
|
||||||
ADC_CLIENT_DISCONNECTED = 1003,
|
ADC_CLIENT_DISCONNECTED = 1003,
|
||||||
|
ADC_CLIENT_SSL_HANDSHAKE = 1101,
|
||||||
|
ADC_CLIENT_SSL_OK = 1102,
|
||||||
|
|
||||||
ADC_CLIENT_LOGGING_IN = 2001,
|
ADC_CLIENT_LOGGING_IN = 2001,
|
||||||
ADC_CLIENT_PASSWORD_REQ = 2002,
|
ADC_CLIENT_PASSWORD_REQ = 2002,
|
||||||
@@ -115,6 +118,11 @@ struct ADC_client
|
|||||||
char* hub_address;
|
char* hub_address;
|
||||||
char* nick;
|
char* nick;
|
||||||
char* desc;
|
char* desc;
|
||||||
|
int ssl_enabled;
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
const SSL_METHOD* ssl_method;
|
||||||
|
SSL_CTX* ssl_ctx;
|
||||||
|
#endif /* SSL_SUPPORT */
|
||||||
};
|
};
|
||||||
|
|
||||||
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description);
|
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user