Compare commits
224 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac5811633e | ||
|
|
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 | ||
|
|
92c448b855 | ||
|
|
304ecda16a | ||
|
|
c670d13369 | ||
|
|
b2e7a2848f | ||
|
|
84bd2591d6 | ||
|
|
4aa65733d0 | ||
|
|
230ca28b46 | ||
|
|
5f353ebe28 | ||
|
|
68a26e1160 | ||
|
|
4711d26c11 | ||
|
|
1bb3bd90c1 | ||
|
|
5e253e8442 | ||
|
|
26a2a384b6 | ||
|
|
8b7f09c7f4 | ||
|
|
b29da11f3b | ||
|
|
78ad9b8572 | ||
|
|
b04a20c66e | ||
|
|
21a5981905 | ||
|
|
c47ea14047 | ||
|
|
9f5aaf0148 | ||
|
|
f645811f37 | ||
|
|
2f09fcea84 | ||
|
|
5e679e2d4f | ||
|
|
efeb36c492 | ||
|
|
7e60919596 | ||
|
|
e7cb4cd277 | ||
|
|
e45511827f | ||
|
|
80c6ad9d76 | ||
|
|
f84f3b1fff | ||
|
|
f84073f7cc | ||
|
|
af8421fa47 | ||
|
|
001fa6739a | ||
|
|
7dfa3162cb | ||
|
|
314707f499 | ||
|
|
1c58a85de1 | ||
|
|
eb5d3936a9 | ||
|
|
23daa42b72 | ||
|
|
a643bb123d | ||
|
|
6a4b9c58f4 | ||
|
|
f35b2c35cb | ||
|
|
b3aa5332c8 | ||
|
|
1f9cfe58c4 | ||
|
|
50f5ce9d32 | ||
|
|
4a4de0f2ac | ||
|
|
2e2f93d0a4 | ||
|
|
7c093dc5da | ||
|
|
8bcdbdc061 | ||
|
|
53536f191d | ||
|
|
e994f23ea0 | ||
|
|
f489e77602 | ||
|
|
2526c8a9ed | ||
|
|
4556623a87 | ||
|
|
828c19cfc6 | ||
|
|
00995a1946 | ||
|
|
f4e82ef503 | ||
|
|
eb7bec585e | ||
|
|
066b3f5243 | ||
|
|
a51e8830ce | ||
|
|
e6cc47070c | ||
|
|
0c5d98c671 | ||
|
|
0f30ebf045 | ||
|
|
4919c8f2f9 | ||
|
|
2910c571b0 | ||
|
|
11e5683a79 | ||
|
|
17416def35 | ||
|
|
234f04f495 | ||
|
|
4898454c91 | ||
|
|
255255ff20 | ||
|
|
f50b40fb92 | ||
|
|
40fc09a7ef | ||
|
|
582bb58ff9 | ||
|
|
7472e9ae4a | ||
|
|
f076c67c33 | ||
|
|
7eef032584 | ||
|
|
de793ea9d2 | ||
|
|
20ef6f8e53 | ||
|
|
310ddf4e9d | ||
|
|
8592aa80d4 | ||
|
|
c3ba8d52ee | ||
|
|
69f6d811bf | ||
|
|
a53c219f05 | ||
|
|
96ce64ee07 | ||
|
|
a3d6646b99 | ||
|
|
4fd182c55e | ||
|
|
993d9ae33b | ||
|
|
fe9b48f14c | ||
|
|
1e380ecf0f | ||
|
|
af7b52b708 | ||
|
|
aeba7188c0 | ||
|
|
4ca5caa52b | ||
|
|
5203ecdadc | ||
|
|
11b288a669 | ||
|
|
52cbec24b6 | ||
|
|
29d6d59d36 | ||
|
|
96c006ee13 | ||
|
|
e67587b997 | ||
|
|
1af613d9ce | ||
|
|
5bd258ca52 | ||
|
|
86ba3ca86f | ||
|
|
cfb450c3fc | ||
|
|
cd389742e6 | ||
|
|
4afa187f9a | ||
|
|
b3c40f7443 | ||
|
|
d45383fe4d | ||
|
|
1642b8dfbe | ||
|
|
ffd455474a | ||
|
|
5baf277f5a | ||
|
|
ab6eda2bbb | ||
|
|
c17ae06b93 | ||
|
|
faaa3d14e4 | ||
|
|
9f784e808e | ||
|
|
b9adaa4f8b | ||
|
|
80dee0c020 | ||
|
|
604c2d8836 | ||
|
|
eca0f931bd | ||
|
|
fbe98d6011 | ||
|
|
4a5993ccc2 | ||
|
|
a297c08bba | ||
|
|
7229ad68ab | ||
|
|
22f9be95d0 | ||
|
|
4e43746c1b | ||
|
|
27c71a75ee | ||
|
|
1d363ed0b4 | ||
|
|
79cf5ee9db |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,2 +1,8 @@
|
|||||||
*~
|
*~
|
||||||
*.o
|
*.[oa]
|
||||||
|
*.exe
|
||||||
|
*.gch
|
||||||
|
uhub-admin
|
||||||
|
adcrush
|
||||||
|
uhub
|
||||||
|
|
||||||
|
|||||||
2
AUTHORS
2
AUTHORS
@@ -2,5 +2,5 @@ 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
|
||||||
|
|
||||||
|
|||||||
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.
|
||||||
|
|||||||
179
GNUmakefile
179
GNUmakefile
@@ -1,30 +1,40 @@
|
|||||||
##
|
##
|
||||||
## Makefile for uhub (Use GNU make)
|
## Makefile for uhub (Use GNU make)
|
||||||
## Copyright (C) 2007-2009, 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_PCH ?= YES
|
|
||||||
USE_SSL ?= NO
|
USE_SSL ?= NO
|
||||||
USE_BIGENDIAN ?= AUTO
|
USE_BIGENDIAN ?= AUTO
|
||||||
BITS ?= AUTO
|
BITS ?= AUTO
|
||||||
SILENT ?= YES
|
SILENT ?= YES
|
||||||
LDLIBS += -levent
|
|
||||||
TERSE ?= NO
|
TERSE ?= NO
|
||||||
STACK_PROTECT ?= NO
|
STACK_PROTECT ?= NO
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
WINDOWS ?= YES
|
WINDOWS ?= YES
|
||||||
|
OPSYS ?= Windows
|
||||||
|
else
|
||||||
|
OPSYS ?= $(shell uname)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OPSYS),SunOS)
|
||||||
|
LDLIBS += -lsocket -lnsl
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OPSYS),Haiku)
|
||||||
|
LDLIBS += -lnetwork
|
||||||
|
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/
|
||||||
@@ -32,7 +42,6 @@ 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
|
||||||
@@ -43,20 +52,17 @@ BIN_EXT ?=
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SILENT),YES)
|
ifeq ($(SILENT),YES)
|
||||||
MSG_CC=@echo " CC:" $(notdir $^) &&
|
MSG_CC=@echo " CC:" $(notdir $<) &&
|
||||||
MSG_PCH=@echo " PCH:" $(notdir $@) &&
|
|
||||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
MSG_LD=@echo " LD:" $(notdir $@) &&
|
||||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
MSG_AR=@echo " AR:" $(notdir $@) &&
|
||||||
else
|
else
|
||||||
MSG_CC=
|
MSG_CC=
|
||||||
MSG_PCH=
|
|
||||||
MSG_LD=
|
MSG_LD=
|
||||||
MSG_AR=
|
MSG_AR=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TERSE), YES)
|
ifeq ($(TERSE), YES)
|
||||||
MSG_CC=@
|
MSG_CC=@
|
||||||
MSG_PCH=@
|
|
||||||
MSG_LD=@
|
MSG_LD=@
|
||||||
MSG_AR=@
|
MSG_AR=@
|
||||||
MSG_CLEAN=-n ""
|
MSG_CLEAN=-n ""
|
||||||
@@ -64,15 +70,10 @@ else
|
|||||||
MSG_CLEAN="Clean as a whistle"
|
MSG_CLEAN="Clean as a whistle"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS += -I/source/libevent
|
|
||||||
LDFLAGS += -L/source/libevent
|
|
||||||
|
|
||||||
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)
|
||||||
@@ -90,13 +91,6 @@ CFLAGS += -finstrument-functions
|
|||||||
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_PCH),YES)
|
|
||||||
PCHSRC=src/uhub.h
|
|
||||||
PCH=src/uhub.h.gch
|
|
||||||
else
|
|
||||||
PCH=
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(BITS), AUTO)
|
ifneq ($(BITS), AUTO)
|
||||||
ifeq ($(BITS), 64)
|
ifeq ($(BITS), 64)
|
||||||
CFLAGS += -m64
|
CFLAGS += -m64
|
||||||
@@ -124,14 +118,9 @@ CFLAGS += -DSSL_SUPPORT
|
|||||||
LDLIBS += -lssl
|
LDLIBS += -lssl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(LIBEVENT_PATH),)
|
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
|
||||||
CFLAGS += -I$(LIBEVENT_PATH)
|
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
||||||
LDFLAGS += -L$(LIBEVENT_PATH)
|
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(GIT_REVISION),YES)
|
|
||||||
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
libuhub_SOURCES := \
|
libuhub_SOURCES := \
|
||||||
@@ -139,116 +128,112 @@ libuhub_SOURCES := \
|
|||||||
src/core/commands.c \
|
src/core/commands.c \
|
||||||
src/core/config.c \
|
src/core/config.c \
|
||||||
src/core/eventqueue.c \
|
src/core/eventqueue.c \
|
||||||
|
src/core/floodctl.c \
|
||||||
src/core/hub.c \
|
src/core/hub.c \
|
||||||
src/core/hubevent.c \
|
src/core/hubevent.c \
|
||||||
src/core/hubio.c \
|
src/core/hubio.c \
|
||||||
src/core/inf.c \
|
src/core/inf.c \
|
||||||
|
src/core/netevent.c \
|
||||||
|
src/core/probe.c \
|
||||||
|
src/core/route.c \
|
||||||
|
src/core/user.c \
|
||||||
|
src/core/usermanager.c \
|
||||||
|
src/network/backend.c \
|
||||||
|
src/network/connection.c \
|
||||||
|
src/network/epoll.c \
|
||||||
|
src/network/kqueue.c \
|
||||||
|
src/network/network.c \
|
||||||
|
src/network/select.c \
|
||||||
|
src/network/timeout.c \
|
||||||
|
src/network/timer.c \
|
||||||
src/util/ipcalc.c \
|
src/util/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/adc/message.c \
|
|
||||||
src/util/misc.c \
|
src/util/misc.c \
|
||||||
src/core/netevent.c \
|
|
||||||
src/network/connection.c \
|
|
||||||
src/network/network.c \
|
|
||||||
src/util/rbtree.c \
|
src/util/rbtree.c \
|
||||||
src/core/route.c \
|
src/util/tiger.c
|
||||||
src/adc/sid.c \
|
|
||||||
src/util/tiger.c \
|
libadc_common_SOURCES := \
|
||||||
src/core/user.c \
|
src/adc/message.c \
|
||||||
src/core/usermanager.c
|
src/adc/sid.c
|
||||||
|
|
||||||
|
libadc_client_SOURCES := \
|
||||||
|
src/tools/adcclient.c
|
||||||
|
|
||||||
uhub_SOURCES := src/core/main.c
|
uhub_SOURCES := src/core/main.c
|
||||||
|
|
||||||
adcrush_SOURCES := src/tools/adcrush.c
|
adcrush_SOURCES := src/tools/adcrush.c
|
||||||
|
|
||||||
admin_SOURCES := src/admin.c
|
admin_SOURCES := src/tools/admin.c
|
||||||
|
|
||||||
uhub_HEADERS := \
|
|
||||||
src/adc/adcconst.h \
|
|
||||||
src/core/auth.h \
|
|
||||||
src/core/config.h \
|
|
||||||
src/core/eventid.h \
|
|
||||||
src/core/eventqueue.h \
|
|
||||||
src/core/hub.h \
|
|
||||||
src/core/hubevent.h \
|
|
||||||
src/core/hubio.h \
|
|
||||||
src/core/inf.h \
|
|
||||||
src/util/ipcalc.h \
|
|
||||||
src/util/list.h \
|
|
||||||
src/util/log.h \
|
|
||||||
src/util/memory.h \
|
|
||||||
src/adc/message.h \
|
|
||||||
src/util/misc.h \
|
|
||||||
src/core/netevent.h \
|
|
||||||
src/network/connection.h \
|
|
||||||
src/network/network.h \
|
|
||||||
src/util/rbtree.h \
|
|
||||||
src/core/route.h \
|
|
||||||
src/adc/sid.h \
|
|
||||||
src/util/tiger.h \
|
|
||||||
src/uhub.h \
|
|
||||||
src/core/user.h \
|
|
||||||
src/core/usermanager.h
|
|
||||||
|
|
||||||
autotest_SOURCES := \
|
autotest_SOURCES := \
|
||||||
autotest/test_message.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_usermanager.tcc
|
||||||
|
|
||||||
autotest_OBJECTS = autotest.o
|
autotest_OBJECTS = autotest.o
|
||||||
|
|
||||||
# Source to objects
|
# Source to objects
|
||||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||||
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
||||||
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
|
||||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
|
||||||
|
|
||||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS)
|
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
||||||
|
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
||||||
|
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
||||||
|
|
||||||
|
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
|
|
||||||
LIBUHUB=libuhub.a
|
|
||||||
uhub_BINARY=uhub$(BIN_EXT)
|
uhub_BINARY=uhub$(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
|
.PHONY: revision.h.tmp
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $^
|
|
||||||
|
|
||||||
all: $(uhub_BINARY) $(PCH)
|
%.o: %.c version.h revision.h
|
||||||
|
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
$(adcrush_BINARY): $(PCH) $(LIBUHUB) $(adcrush_OBJECTS)
|
all: $(uhub_BINARY)
|
||||||
$(MSG_LD) $(CC) -o $@ $(adcrush_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS)
|
|
||||||
|
|
||||||
$(admin_BINARY): $(PCH) $(LIBUHUB) $(admin_OBJECTS)
|
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $(admin_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
$(uhub_BINARY): $(PCH) $(LIBUHUB) $(uhub_OBJECTS)
|
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
$(MSG_LD) $(CC) -o $@ $(uhub_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS)
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
$(LIBUHUB): $(libuhub_OBJECTS)
|
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
|
||||||
$(MSG_AR) $(AR) rc $@ $^ && $(RANLIB) $@
|
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
ifeq ($(USE_PCH),YES)
|
|
||||||
$(PCH): $(uhub_HEADERS)
|
|
||||||
$(MSG_PCH) $(CC) $(CFLAGS) -o $@ $(PCHSRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
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)
|
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_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)
|
||||||
@@ -269,10 +254,10 @@ install: $(uhub_BINARY)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
dist-clean:
|
dist-clean:
|
||||||
@rm -rf $(all_OBJECTS) $(PCH) *~ core
|
@rm -rf $(all_OBJECTS) *~ core
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(libuhub_OBJECTS) $(PCH) *~ core $(uhub_BINARY) $(LIBUHUB) $(all_OBJECTS) && \
|
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c revision.h revision.h.tmp && \
|
||||||
echo $(MSG_CLEAN)
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +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 = 65111;
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,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->id.sid = 1;
|
inf_user->id.sid = 1;
|
||||||
inf_user->net.connection.sd = -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, {
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ EXO_TEST(adc_message_parse_1, {
|
|||||||
|
|
||||||
EXO_TEST(adc_message_parse_2, {
|
EXO_TEST(adc_message_parse_2, {
|
||||||
struct adc_message* msg = adc_msg_create(test_string2);
|
struct adc_message* msg = adc_msg_create(test_string2);
|
||||||
return msg == NULL;
|
int ok = (msg != NULL);
|
||||||
|
adc_msg_free(msg);
|
||||||
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
EXO_TEST(adc_message_parse_3, {
|
EXO_TEST(adc_message_parse_3, {
|
||||||
|
|||||||
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;
|
||||||
|
});
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
static struct hub_info um_hub;
|
static struct hub_info um_hub;
|
||||||
static struct hub_user um_user[MAX_USERS];
|
static struct hub_user um_user[MAX_USERS];
|
||||||
|
// static struct net_connection um_cons[MAX_USERS];
|
||||||
|
|
||||||
EXO_TEST(um_test_setup, {
|
EXO_TEST(um_test_setup, {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -11,9 +12,12 @@ EXO_TEST(um_test_setup, {
|
|||||||
|
|
||||||
for (i = 0; i < MAX_USERS; i++)
|
for (i = 0; i < MAX_USERS; i++)
|
||||||
{
|
{
|
||||||
|
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
|
||||||
|
um_cons[i].sd = -1;
|
||||||
|
|
||||||
memset(&um_user[i], 0, sizeof(struct hub_user));
|
memset(&um_user[i], 0, sizeof(struct hub_user));
|
||||||
um_user[i].id.sid = i+1;
|
um_user[i].id.sid = i+1;
|
||||||
um_user[i].net.connection.sd = -1;
|
um_user[i].connection = &um_cons[i];*/
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|||||||
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,13 @@ 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
|
||||||
|
|
||||||
Linux and Mac OSX
|
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!
|
||||||
|
|||||||
101
doc/init.d.RedHat/etc/init.d/uhub
Executable file
101
doc/init.d.RedHat/etc/init.d/uhub
Executable file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# chkconfig: - 91 35
|
||||||
|
# description: Starts and stops the Uhub ( http://www.extatic.org/uhub ) daemons on RHEL\CentOS \
|
||||||
|
# used to provide p2p network services.
|
||||||
|
#
|
||||||
|
# pidfile: /var/run/uhub.pid
|
||||||
|
# config: /etc/uhub/uhub.conf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Source function library.
|
||||||
|
if [ -f /etc/init.d/functions ] ; then
|
||||||
|
. /etc/init.d/functions
|
||||||
|
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
||||||
|
. /etc/rc.d/init.d/functions
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Avoid using root's TMPDIR
|
||||||
|
unset TMPDIR
|
||||||
|
|
||||||
|
# Source networking configuration.
|
||||||
|
. /etc/sysconfig/network
|
||||||
|
|
||||||
|
if [ -f /etc/sysconfig/uhub ]; then
|
||||||
|
. /etc/sysconfig/uhub
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that networking is up.
|
||||||
|
[ ${NETWORKING} = "no" ] && exit 1
|
||||||
|
|
||||||
|
# Check that uhub.conf exists.
|
||||||
|
[ -f /etc/uhub/uhub.conf ] || exit 6
|
||||||
|
|
||||||
|
RETVAL=0
|
||||||
|
|
||||||
|
|
||||||
|
start() {
|
||||||
|
KIND="Uhub"
|
||||||
|
echo -n $"Starting $KIND services: "
|
||||||
|
daemon uhub $UHUBOPTIONS
|
||||||
|
RETVAL=$?
|
||||||
|
echo ""
|
||||||
|
return $RETVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
KIND="Uhub"
|
||||||
|
echo -n $"Shutting down $KIND services: "
|
||||||
|
killproc uhub
|
||||||
|
RETVAL=$?
|
||||||
|
echo ""
|
||||||
|
return $RETVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
restart() {
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
echo -n $"Reloading uhub.conf / user.conf file: "
|
||||||
|
killproc uhub -HUP
|
||||||
|
RETVAL=$?
|
||||||
|
echo ""
|
||||||
|
return $RETVAL
|
||||||
|
}
|
||||||
|
|
||||||
|
rhstatus() {
|
||||||
|
status uhub
|
||||||
|
RETVAL=$?
|
||||||
|
if [ $RETVAL -ne 0 ] ; then
|
||||||
|
return $RETVAL
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
restart
|
||||||
|
;;
|
||||||
|
reload)
|
||||||
|
reload
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
rhstatus
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $"Usage: $0 {start|stop|restart|reload|status}"
|
||||||
|
exit 2
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit $?
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
13
doc/init.d.RedHat/etc/sysconfig/uhub
Normal file
13
doc/init.d.RedHat/etc/sysconfig/uhub
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Options to UHUB
|
||||||
|
# -v Verbose mode. Add more -v's for higher verbosity.
|
||||||
|
# -q Quiet mode - no output
|
||||||
|
# -f Fork to background
|
||||||
|
# -l <file> Log messages to given file (default: stderr)
|
||||||
|
# -L Log messages to syslog
|
||||||
|
# -c <file> Specify configuration file (default: /etc/uhub/uhub.conf)
|
||||||
|
# -S Show configuration parameters, but ignore defaults
|
||||||
|
# -u <user> Run as given user
|
||||||
|
# -g <group> Run with given group permissions
|
||||||
|
# -p <file> Store pid in file (process id)
|
||||||
|
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"
|
||||||
|
|
||||||
5
doc/rules.txt
Normal file
5
doc/rules.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
1. rule #1
|
||||||
|
2. rule #2
|
||||||
|
3. rule #3
|
||||||
|
......
|
||||||
|
34. Rule #34
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
#
|
#
|
||||||
# This file is read only to the uhub deamon, and if you
|
# This file is read only to the uhub deamon, and if you
|
||||||
# make changes to it while uhub is running you can send a
|
# make changes to it while uhub is running you can send a
|
||||||
# HUP signal to it, to reparse configuration (only on UNIX).
|
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
||||||
|
# All configuration directives: http://www.uhub.org/config.php
|
||||||
|
|
||||||
# Bind to this port and address
|
# Bind to this port and address
|
||||||
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
||||||
@@ -12,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
|
||||||
|
|
||||||
@@ -38,6 +45,52 @@ file_acl=/etc/uhub/users.conf
|
|||||||
# Normally this message is sent to clients when connecting.
|
# Normally this message is sent to clients when connecting.
|
||||||
file_motd=/etc/uhub/motd.txt
|
file_motd=/etc/uhub/motd.txt
|
||||||
|
|
||||||
|
# This file can contain a rules of the hub.
|
||||||
|
# Normally this message is sent to clients when write in chat !rules
|
||||||
|
file_rules=/etc/uhub/rules.txt
|
||||||
|
|
||||||
|
|
||||||
|
# Slots/share/hubs limits
|
||||||
|
limit_max_hubs_user = 0
|
||||||
|
limit_max_hubs_reg = 0
|
||||||
|
limit_max_hubs_op = 0
|
||||||
|
limit_max_hubs = 0
|
||||||
|
limit_min_hubs_user = 0
|
||||||
|
limit_min_hubs_reg = 0
|
||||||
|
limit_min_hubs_op = 0
|
||||||
|
limit_min_share = 0
|
||||||
|
# Example:
|
||||||
|
# To require users to share at least 1 GB in order to enter the hub:
|
||||||
|
# limit_min_share = 1024
|
||||||
|
limit_max_share = 0
|
||||||
|
limit_min_slots = 0
|
||||||
|
limit_max_slots = 0
|
||||||
|
|
||||||
|
# Flood control support:
|
||||||
|
# set the interval to 5 seconds
|
||||||
|
flood_ctl_interval = 5
|
||||||
|
|
||||||
|
# Then the maximum chat, connect, search, updates etc will be measured over 5 seconds.
|
||||||
|
# So, 3 chat messages per 5 seconds allowed.
|
||||||
|
flood_ctl_chat=3
|
||||||
|
flood_ctl_connect=20
|
||||||
|
flood_ctl_search=1
|
||||||
|
flood_ctl_update=2
|
||||||
|
flood_ctl_extras=5
|
||||||
|
|
||||||
|
# chat control
|
||||||
|
# if chat_is_privileged=yes only registered users may write in main chat
|
||||||
|
chat_is_privileged = no
|
||||||
|
|
||||||
|
# if chat_only = yes then search and transfer functionality is disabled for
|
||||||
|
# non-operator users.
|
||||||
|
chat_only = no
|
||||||
|
|
||||||
|
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
|
||||||
|
# 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
|
||||||
msg_hub_disabled = Hub is disabled
|
msg_hub_disabled = Hub is disabled
|
||||||
@@ -61,6 +114,23 @@ msg_ban_permanently = Banned permanently
|
|||||||
msg_ban_temporarily = Banned temporarily
|
msg_ban_temporarily = Banned temporarily
|
||||||
msg_auth_invalid_password = Password is wrong
|
msg_auth_invalid_password = Password is wrong
|
||||||
msg_auth_user_not_found = User not found in password database
|
msg_auth_user_not_found = User not found in password database
|
||||||
|
msg_user_share_size_low = User is not sharing enough
|
||||||
|
msg_user_share_size_high = User is sharing too much
|
||||||
|
msg_user_slots_low = User have too few upload slots
|
||||||
|
msg_user_slots_high = User have too many upload slots
|
||||||
|
msg_user_hub_limit_low = User is on too few hubs
|
||||||
|
msg_user_hub_limit_high = User is on too many hubs
|
||||||
msg_error_no_memory = No memory
|
msg_error_no_memory = 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
|
||||||
|
}
|
||||||
85
doc/uhub.spec
Normal file
85
doc/uhub.spec
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
Summary: High performance ADC p2p hub.
|
||||||
|
Name: uhub
|
||||||
|
Version: 0.3.2
|
||||||
|
Release: 3
|
||||||
|
License: GPLv3
|
||||||
|
Group: Networking/File transfer
|
||||||
|
Source: uhub-%{version}.tar.gz
|
||||||
|
URL: http://www.uhub.org
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||||
|
|
||||||
|
|
||||||
|
%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
|
||||||
|
|
||||||
|
|
||||||
|
%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
|
||||||
|
|
||||||
|
install uhub $RPM_BUILD_ROOT/usr/bin/
|
||||||
|
> doc/motd.txt
|
||||||
|
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt $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
|
||||||
|
|
||||||
|
|
||||||
|
%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
|
||||||
|
%{_sysconfdir}/init.d/uhub
|
||||||
|
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
||||||
|
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
||||||
|
/usr/share/man/man1/uhub.1.gz
|
||||||
|
%{_bindir}/uhub
|
||||||
|
|
||||||
|
|
||||||
|
%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 ||:
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* 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
|
||||||
|
|
||||||
|
|
||||||
@@ -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,17 +26,51 @@
|
|||||||
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->length == strlen(X->cache)); \
|
uhub_assert(X->references > 0); \
|
||||||
uhub_assert(X->references >= 0);
|
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
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
#ifdef MSG_MEMORY_DEBUG
|
||||||
|
#undef msg_malloc
|
||||||
|
#undef msg_malloc_zero
|
||||||
|
#undef msg_free
|
||||||
|
|
||||||
|
static void* msg_malloc(size_t size)
|
||||||
|
{
|
||||||
|
void* ptr = valloc(size);
|
||||||
|
LOG_MEMORY("msg_malloc: %p %d", ptr, (int) size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* msg_malloc_zero(size_t size)
|
||||||
|
{
|
||||||
|
void* ptr = msg_malloc(size);
|
||||||
|
memset(ptr, 0, size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msg_free(void* ptr)
|
||||||
|
{
|
||||||
|
LOG_MEMORY("msg_free: %p", ptr);
|
||||||
|
hub_free(ptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define msg_malloc(X) hub_malloc(X)
|
||||||
|
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
||||||
|
#define msg_free(X) hub_free(X)
|
||||||
|
#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
|
||||||
msg->references++;
|
msg->references++;
|
||||||
|
#ifdef MSG_MEMORY_DEBUG
|
||||||
|
adc_msg_protect(msg);
|
||||||
|
#endif
|
||||||
return msg;
|
return msg;
|
||||||
#else
|
#else
|
||||||
struct adc_message* copy = adc_msg_copy(msg);
|
struct adc_message* copy = adc_msg_copy(msg);
|
||||||
@@ -54,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;
|
||||||
|
|
||||||
@@ -62,18 +99,19 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
|||||||
newsize += 2; /* termination */
|
newsize += 2; /* termination */
|
||||||
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
||||||
|
|
||||||
buf = hub_malloc_zero(newsize);
|
buf = msg_malloc_zero(newsize);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (msg->cache)
|
if (msg->cache)
|
||||||
{
|
{
|
||||||
memcpy(buf, msg->cache, msg->length);
|
memcpy(buf, msg->cache, msg->length);
|
||||||
hub_free(msg->cache);
|
msg_free(msg->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->cache = buf;
|
msg->cache = buf;
|
||||||
msg->capacity = newsize;
|
msg->capacity = newsize;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,13 +187,17 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
|
|
||||||
ADC_MSG_ASSERT(msg);
|
ADC_MSG_ASSERT(msg);
|
||||||
|
|
||||||
if (msg->references > 0)
|
msg->references--;
|
||||||
|
|
||||||
|
if (msg->references == 0)
|
||||||
{
|
{
|
||||||
msg->references--;
|
#ifdef ADC_MSG_NULL_ON_FREE
|
||||||
}
|
if (msg->cache)
|
||||||
else
|
{
|
||||||
{
|
*msg->cache = 0;
|
||||||
hub_free(msg->cache);
|
}
|
||||||
|
#endif
|
||||||
|
msg_free(msg->cache);
|
||||||
|
|
||||||
if (msg->feature_cast_include)
|
if (msg->feature_cast_include)
|
||||||
{
|
{
|
||||||
@@ -171,7 +213,7 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
msg->feature_cast_exclude = 0;
|
msg->feature_cast_exclude = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hub_free(msg);
|
msg_free(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +221,7 @@ void adc_msg_free(struct adc_message* msg)
|
|||||||
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||||
{
|
{
|
||||||
char* tmp = 0;
|
char* tmp = 0;
|
||||||
struct adc_message* copy = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* copy = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||||
if (!copy) return NULL; /* OOM */
|
if (!copy) return NULL; /* OOM */
|
||||||
|
|
||||||
ADC_MSG_ASSERT(cmd);
|
ADC_MSG_ASSERT(cmd);
|
||||||
@@ -192,21 +234,25 @@ 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);
|
||||||
{
|
return NULL; /* OOM */
|
||||||
adc_msg_free(copy);
|
|
||||||
return NULL; /* OOM */
|
|
||||||
}
|
|
||||||
memcpy(copy->cache, cmd->cache, cmd->length);
|
|
||||||
copy->cache[copy->length] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!copy->cache)
|
||||||
|
{
|
||||||
|
adc_msg_free(copy);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(copy->cache, cmd->cache, cmd->length);
|
||||||
|
copy->cache[copy->length] = 0;
|
||||||
|
|
||||||
if (cmd->feature_cast_include)
|
if (cmd->feature_cast_include)
|
||||||
{
|
{
|
||||||
copy->feature_cast_include = list_create();
|
copy->feature_cast_include = list_create();
|
||||||
@@ -255,7 +301,7 @@ struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, s
|
|||||||
|
|
||||||
struct adc_message* adc_msg_parse(const char* line, size_t length)
|
struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||||
{
|
{
|
||||||
struct adc_message* command = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
struct adc_message* command = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||||
char prefix = line[0];
|
char prefix = line[0];
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
char temp_sid[5];
|
char temp_sid[5];
|
||||||
@@ -269,7 +315,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
if (!is_printable_utf8(line, length))
|
if (!is_printable_utf8(line, length))
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
|
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
|
||||||
hub_free(command);
|
msg_free(command);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +326,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
|
|
||||||
if (!adc_msg_grow(command, length + need_terminate))
|
if (!adc_msg_grow(command, length + need_terminate))
|
||||||
{
|
{
|
||||||
hub_free(command);
|
msg_free(command);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,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)
|
||||||
{
|
{
|
||||||
@@ -352,8 +399,8 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
{
|
{
|
||||||
list_destroy(command->feature_cast_include);
|
list_destroy(command->feature_cast_include);
|
||||||
list_destroy(command->feature_cast_exclude);
|
list_destroy(command->feature_cast_exclude);
|
||||||
hub_free(command->cache);
|
msg_free(command->cache);
|
||||||
hub_free(command);
|
msg_free(command);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,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':
|
||||||
@@ -443,21 +489,19 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ADC_MSG_ASSERT(command);
|
ADC_MSG_ASSERT(command);
|
||||||
|
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct adc_message* adc_msg_create(const char* line)
|
struct adc_message* adc_msg_create(const char* line)
|
||||||
{
|
{
|
||||||
return adc_msg_parse_verify(NULL, line, strlen(line));
|
return adc_msg_parse(line, strlen(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*) hub_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 */
|
||||||
|
|
||||||
@@ -465,7 +509,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
|||||||
|
|
||||||
if (!adc_msg_grow(msg, size+1))
|
if (!adc_msg_grow(msg, size+1))
|
||||||
{
|
{
|
||||||
hub_free(msg);
|
msg_free(msg);
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +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;
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,6 +698,27 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string)
|
||||||
|
{
|
||||||
|
char* escaped = adc_msg_escape(string);
|
||||||
|
int ret = adc_msg_add_named_argument(cmd, prefix, escaped);
|
||||||
|
hub_free(escaped);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int num)
|
||||||
|
{
|
||||||
|
const char* s = uhub_itoa(num);
|
||||||
|
int ret = adc_msg_add_named_argument(cmd, prefix, s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num)
|
||||||
|
{
|
||||||
|
const char* s = uhub_ulltoa(num);
|
||||||
|
int ret = adc_msg_add_named_argument(cmd, prefix, s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
||||||
{
|
{
|
||||||
@@ -682,7 +747,6 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
|||||||
while (start)
|
while (start)
|
||||||
{
|
{
|
||||||
end = strchr(&start[1], ' ');
|
end = strchr(&start[1], ' ');
|
||||||
|
|
||||||
if (count == offset)
|
if (count == offset)
|
||||||
{
|
{
|
||||||
if (end)
|
if (end)
|
||||||
@@ -692,17 +756,23 @@ 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[strlen(argument)-1] == '\n')
|
if (argument && *argument && argument[strlen(argument)-1] == '\n')
|
||||||
argument[strlen(argument)-1] = 0;
|
argument[strlen(argument)-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!argument)
|
||||||
|
return 0; // FIXME: OOM
|
||||||
|
|
||||||
if (*argument)
|
if (*argument)
|
||||||
{
|
{
|
||||||
adc_msg_terminate(cmd);
|
adc_msg_terminate(cmd);
|
||||||
return argument;
|
return argument;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hub_free(argument);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
@@ -776,12 +846,9 @@ 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 = hub_malloc(adc_msg_unescape_length(string)+1);
|
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
||||||
char* ptr = (char*) new_string;
|
char* ptr = (char*) new_string;
|
||||||
char* str = (char*) string;
|
char* str = (char*) string;
|
||||||
int escaped = 0;
|
int escaped = 0;
|
||||||
@@ -797,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++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -173,6 +173,22 @@ extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
|||||||
*/
|
*/
|
||||||
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a string as a named argument.
|
||||||
|
* The string will automatcally be escaped, if you do not wish to escape th string use adc_msg_add_named_argument() instead.
|
||||||
|
*
|
||||||
|
* @arg prefix a 2 character argument prefix
|
||||||
|
* @arg string must NOT be escaped
|
||||||
|
* @return 0 if successful, or -1 if an error occured (out of memory).
|
||||||
|
*/
|
||||||
|
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append an integer as a named argument.
|
||||||
|
*/
|
||||||
|
extern int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int integer);
|
||||||
|
extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a ADC command escaped string to a regular string.
|
* Convert a ADC command escaped string to a regular string.
|
||||||
* @return string or NULL if out of memory
|
* @return string or NULL if out of memory
|
||||||
|
|||||||
@@ -88,43 +88,67 @@ struct sid_pool
|
|||||||
struct sid_pool* sid_pool_create(sid_t max)
|
struct sid_pool* sid_pool_create(sid_t max)
|
||||||
{
|
{
|
||||||
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
|
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
|
||||||
|
if (!pool)
|
||||||
|
return 0;
|
||||||
|
|
||||||
pool->min = 1;
|
pool->min = 1;
|
||||||
pool->max = max + 1;
|
pool->max = max + 1;
|
||||||
pool->count = 0;
|
pool->count = 0;
|
||||||
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
|
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
|
||||||
|
if (!pool->map)
|
||||||
|
{
|
||||||
|
hub_free(pool);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
|
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
|
||||||
|
|
||||||
|
#ifdef DEBUG_SID
|
||||||
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
|
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
|
||||||
|
#endif
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sid_pool_destroy(struct sid_pool* pool)
|
void sid_pool_destroy(struct sid_pool* pool)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_SID
|
||||||
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
|
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
|
||||||
|
#endif
|
||||||
hub_free(pool->map);
|
hub_free(pool->map);
|
||||||
hub_free(pool);
|
hub_free(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)
|
||||||
{
|
{
|
||||||
|
if (pool->count >= (pool->max - pool->min))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_SID
|
||||||
|
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
sid_t n = (++pool->count);
|
sid_t n = (++pool->count);
|
||||||
for (; (pool->map[n % pool->max]); n++) ;
|
for (; (pool->map[n % pool->max]); n++) ;
|
||||||
|
|
||||||
|
#ifdef DEBUG_SID
|
||||||
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
|
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
|
||||||
|
#endif
|
||||||
pool->map[n] = user;
|
pool->map[n] = user;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sid_free(struct sid_pool* pool, sid_t sid)
|
void sid_free(struct sid_pool* pool, sid_t sid)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG_SID
|
||||||
LOG_DUMP("SID_FREE: %d", (int) sid);
|
LOG_DUMP("SID_FREE: %d", (int) sid);
|
||||||
|
#endif
|
||||||
pool->map[sid] = 0;
|
pool->map[sid] = 0;
|
||||||
pool->count--;
|
pool->count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -130,7 +130,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,27 +176,15 @@ 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);
|
||||||
if (!*line)
|
if (!*line)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
LOG_DEBUG("acl_parse_line(): '%s'", line);
|
|
||||||
line = strip_white_space(line);
|
|
||||||
|
|
||||||
if (!*line)
|
|
||||||
{
|
|
||||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, cred_bot);
|
||||||
@@ -334,7 +322,7 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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) \
|
||||||
@@ -345,43 +333,48 @@ 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)
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
char* data = hub_strdup(nick);
|
||||||
if (!info)
|
if (!data)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
LOG_ERROR("ACL error: Out of memory!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
list_append(handle->users_banned, hub_strdup(nick));
|
|
||||||
|
list_append(handle->users_banned, data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
||||||
{
|
{
|
||||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
char* data = hub_strdup(cid);
|
||||||
if (!info)
|
if (!data)
|
||||||
{
|
{
|
||||||
LOG_ERROR("ACL error: Out of memory!");
|
LOG_ERROR("ACL error: Out of memory!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
list_append(handle->cids, hub_strdup(cid));
|
|
||||||
|
list_append(handle->cids, data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,11 +432,12 @@ int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
|||||||
*/
|
*/
|
||||||
const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user)
|
const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[64];
|
||||||
uint64_t tiger_res[3];
|
uint64_t tiger_res[3];
|
||||||
static char tiger_buf[MAX_CID_LEN+1];
|
static char tiger_buf[MAX_CID_LEN+1];
|
||||||
|
|
||||||
snprintf(buf, 32, "%d%d%d", (int) user->net.tm_connected, (int) user->id.sid, (int) user->net.connection.sd);
|
// FIXME: Generate a better nonce scheme.
|
||||||
|
snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection));
|
||||||
|
|
||||||
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
|
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
|
||||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
|
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
|
||||||
|
|||||||
@@ -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-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
|
||||||
@@ -63,21 +63,24 @@ static void command_destroy(struct hub_command* cmd)
|
|||||||
|
|
||||||
static struct hub_command* command_create(const char* message)
|
static struct hub_command* command_create(const char* message)
|
||||||
{
|
{
|
||||||
|
char* prefix;
|
||||||
|
int n;
|
||||||
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
|
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
|
||||||
|
|
||||||
if (!cmd) return 0;
|
if (!cmd) return 0;
|
||||||
|
|
||||||
cmd->message = message;
|
cmd->message = message;
|
||||||
cmd->args = list_create();
|
cmd->args = list_create();
|
||||||
|
|
||||||
int n = split_string(message, "\\s", cmd->args, 0);
|
n = split_string(message, "\\s", cmd->args, 0);
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
{
|
{
|
||||||
command_destroy(cmd);
|
command_destroy(cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* prefix = list_get_first(cmd->args);
|
prefix = list_get_first(cmd->args);
|
||||||
if (prefix[0] && prefix[1])
|
if (prefix && prefix[0] && prefix[1])
|
||||||
{
|
{
|
||||||
cmd->prefix = hub_strdup(&prefix[1]);
|
cmd->prefix = hub_strdup(&prefix[1]);
|
||||||
cmd->prefix_len = strlen(cmd->prefix);
|
cmd->prefix_len = strlen(cmd->prefix);
|
||||||
@@ -129,8 +132,8 @@ static int command_status_user_not_found(struct hub_info* hub, struct hub_user*
|
|||||||
const char* command_get_syntax(struct commands_handler* handler)
|
const char* command_get_syntax(struct commands_handler* handler)
|
||||||
{
|
{
|
||||||
static char args[128];
|
static char args[128];
|
||||||
args[0] = 0;
|
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
|
args[0] = 0;
|
||||||
if (handler->args)
|
if (handler->args)
|
||||||
{
|
{
|
||||||
for (n = 0; n < strlen(handler->args); n++)
|
for (n = 0; n < strlen(handler->args); n++)
|
||||||
@@ -169,7 +172,7 @@ static int command_status(struct hub_info* hub, struct hub_user* user, struct hu
|
|||||||
static int command_stats(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_stats(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
char temp[128];
|
char temp[128];
|
||||||
snprintf(temp, 128, "%zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
snprintf(temp, 128, PRINTF_SIZE_T " users, peak: " PRINTF_SIZE_T ". Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
||||||
hub->users->count,
|
hub->users->count,
|
||||||
hub->users->count_peak,
|
hub->users->count_peak,
|
||||||
(int) hub->stats.net_tx / 1024,
|
(int) hub->stats.net_tx / 1024,
|
||||||
@@ -235,7 +238,11 @@ static int command_uptime(struct hub_info* hub, struct hub_user* user, struct hu
|
|||||||
static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
char* nick = list_get_first(cmd->args);
|
char* nick = list_get_first(cmd->args);
|
||||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
struct hub_user* target;
|
||||||
|
if (!nick)
|
||||||
|
return -1; // FIXME: bad syntax.
|
||||||
|
|
||||||
|
target = uman_get_user_by_nick(hub, nick);
|
||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
return command_status_user_not_found(hub, user, cmd, nick);
|
||||||
@@ -250,7 +257,11 @@ static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_
|
|||||||
static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
char* nick = list_get_first(cmd->args);
|
char* nick = list_get_first(cmd->args);
|
||||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
struct hub_user* target;
|
||||||
|
if (!nick)
|
||||||
|
return -1; // FIXME: bad syntax.
|
||||||
|
|
||||||
|
target = uman_get_user_by_nick(hub, nick);
|
||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
return command_status_user_not_found(hub, user, cmd, nick);
|
||||||
@@ -270,6 +281,29 @@ static int command_unban(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
return command_status(hub, user, cmd, "Not implemented");
|
return command_status(hub, user, cmd, "Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int command_mute(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
char* nick = list_get_first(cmd->args);
|
||||||
|
struct hub_user* target;
|
||||||
|
if (!nick)
|
||||||
|
return -1; // FIXME: bad syntax.
|
||||||
|
|
||||||
|
target = uman_get_user_by_nick(hub, nick);
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
return command_status_user_not_found(hub, user, cmd, nick);
|
||||||
|
|
||||||
|
if (strlen(cmd->prefix) == 4)
|
||||||
|
{
|
||||||
|
user_flag_set(target, flag_muted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user_flag_unset(target, flag_muted);
|
||||||
|
}
|
||||||
|
return command_status(hub, user, cmd, nick);
|
||||||
|
}
|
||||||
|
|
||||||
static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
hub->status = hub_status_restart;
|
hub->status = hub_status_restart;
|
||||||
@@ -284,27 +318,36 @@ static int command_shutdown(struct hub_info* hub, struct hub_user* user, struct
|
|||||||
|
|
||||||
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
return command_status(hub, user, cmd, "Powered by " PRODUCT "/" VERSION);
|
const char* tmp;
|
||||||
|
if (hub->config->show_banner_sys_info)
|
||||||
|
tmp = "Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO;
|
||||||
|
else
|
||||||
|
tmp = "Powered by " PRODUCT_STRING;
|
||||||
|
return command_status(hub, user, cmd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
char tmp[128];
|
char tmp[128];
|
||||||
snprintf(tmp, 128, "Your address is \"%s\"", ip_convert_to_string(&user->net.ipaddr));
|
snprintf(tmp, 128, "Your address is \"%s\"", user_get_address(user));
|
||||||
return command_status(hub, user, cmd, tmp);
|
return command_status(hub, user, cmd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
char tmp[128];
|
char tmp[128];
|
||||||
|
|
||||||
char* nick = list_get_first(cmd->args);
|
char* nick = list_get_first(cmd->args);
|
||||||
struct hub_user* target = uman_get_user_by_nick(hub, nick);
|
struct hub_user* target;
|
||||||
|
|
||||||
|
if (!nick)
|
||||||
|
return -1; // FIXME: bad syntax/OOM
|
||||||
|
|
||||||
|
target = uman_get_user_by_nick(hub, nick);
|
||||||
|
|
||||||
if (!target)
|
if (!target)
|
||||||
return command_status_user_not_found(hub, user, cmd, nick);
|
return command_status_user_not_found(hub, user, cmd, nick);
|
||||||
|
|
||||||
snprintf(tmp, 128, "%s has address \"%s\"", nick, ip_convert_to_string(&target->net.ipaddr));
|
snprintf(tmp, 128, "%s has address \"%s\"", nick, user_get_address(target));
|
||||||
return command_status(hub, user, cmd, tmp);
|
return command_status(hub, user, cmd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,12 +358,20 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
struct linked_list* users;
|
struct linked_list* users;
|
||||||
struct hub_user* u;
|
struct hub_user* u;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
char tmp[128];
|
||||||
|
char* buffer;
|
||||||
|
|
||||||
|
if (!address)
|
||||||
|
return -1; // FIXME: bad syntax.
|
||||||
|
|
||||||
ret = ip_convert_address_to_range(address, &range);
|
ret = ip_convert_address_to_range(address, &range);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
|
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
|
||||||
|
|
||||||
users = (struct linked_list*) list_create();
|
users = (struct linked_list*) list_create();
|
||||||
|
if (!users)
|
||||||
|
return -1; // FIXME: OOM
|
||||||
|
|
||||||
ret = uman_get_user_by_addr(hub, users, &range);
|
ret = uman_get_user_by_addr(hub, users, &range);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
@@ -329,10 +380,15 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
return command_status(hub, user, cmd, "No users found.");
|
return command_status(hub, user, cmd, "No users found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
char tmp[128];
|
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
|
||||||
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, (int) ret, ((ret != 1) ? "es" : ""));
|
|
||||||
|
buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
list_destroy(users);
|
||||||
|
return -1; // FIXME: OOM
|
||||||
|
}
|
||||||
|
|
||||||
char* buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
|
|
||||||
buffer[0] = 0;
|
buffer[0] = 0;
|
||||||
strcat(buffer, tmp);
|
strcat(buffer, tmp);
|
||||||
strcat(buffer, "\n");
|
strcat(buffer, "\n");
|
||||||
@@ -342,7 +398,7 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
{
|
{
|
||||||
strcat(buffer, u->id.nick);
|
strcat(buffer, u->id.nick);
|
||||||
strcat(buffer, " (");
|
strcat(buffer, " (");
|
||||||
strcat(buffer, ip_convert_to_string(&u->net.ipaddr));
|
strcat(buffer, user_get_address(u));
|
||||||
strcat(buffer, ")\n");
|
strcat(buffer, ")\n");
|
||||||
u = (struct hub_user*) list_get_next(users);
|
u = (struct hub_user*) list_get_next(users);
|
||||||
}
|
}
|
||||||
@@ -350,16 +406,54 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
|
|
||||||
send_message(hub, user, buffer);
|
send_message(hub, user, buffer);
|
||||||
hub_free(buffer);
|
hub_free(buffer);
|
||||||
|
list_destroy(users);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 10)) + 6);
|
size_t offset = 12;
|
||||||
adc_msg_add_argument(command, (cmd->message + 10));
|
#if USE_OLD_BROADCAST_STYLE
|
||||||
|
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + offset)) + 6);
|
||||||
|
adc_msg_add_argument(command, (cmd->message + offset));
|
||||||
route_to_all(hub, command);
|
route_to_all(hub, command);
|
||||||
adc_msg_free(command);
|
adc_msg_free(command);
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
size_t message_len = strlen(cmd->message + offset);
|
||||||
|
struct adc_message* command = 0;
|
||||||
|
char pm_flag[7] = "PM";
|
||||||
|
char from_sid[5];
|
||||||
|
char buffer[128];
|
||||||
|
size_t recipients = 0;
|
||||||
|
|
||||||
|
memcpy(from_sid, sid_to_string(user->id.sid), sizeof(from_sid));
|
||||||
|
memcpy(pm_flag + 2, from_sid, sizeof(from_sid));
|
||||||
|
|
||||||
|
struct hub_user* target = (struct hub_user*) list_get_first(hub->users->list);
|
||||||
|
while (target)
|
||||||
|
{
|
||||||
|
if (target != user)
|
||||||
|
{
|
||||||
|
recipients++;
|
||||||
|
command = adc_msg_construct(ADC_CMD_DMSG, message_len + 23);
|
||||||
|
if (!command)
|
||||||
|
break;
|
||||||
|
|
||||||
|
adc_msg_add_argument(command, from_sid);
|
||||||
|
adc_msg_add_argument(command, sid_to_string(target->id.sid));
|
||||||
|
adc_msg_add_argument(command, (cmd->message + offset));
|
||||||
|
adc_msg_add_argument(command, pm_flag);
|
||||||
|
|
||||||
|
route_to_user(hub, target, command);
|
||||||
|
adc_msg_free(command);
|
||||||
|
}
|
||||||
|
target = (struct hub_user*) list_get_next(hub->users->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buffer, sizeof(buffer), "*** %s: Delivered to " PRINTF_SIZE_T " user%s", cmd->prefix, recipients, (recipients != 1 ? "s" : ""));
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
@@ -369,14 +463,14 @@ static int command_history(struct hub_info* hub, struct hub_user* user, struct h
|
|||||||
char* message = 0;
|
char* message = 0;
|
||||||
int ret = (int) list_size(messages);
|
int ret = (int) list_size(messages);
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
|
char tmp[128];
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
return command_status(hub, user, cmd, "No messages.");
|
return command_status(hub, user, cmd, "No messages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
char tmp[128];
|
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
|
||||||
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, (int) ret, ((ret != 1) ? "s" : ""));
|
|
||||||
bufsize = strlen(tmp);
|
bufsize = strlen(tmp);
|
||||||
message = (char*) list_get_first(messages);
|
message = (char*) list_get_first(messages);
|
||||||
while (message)
|
while (message)
|
||||||
@@ -430,11 +524,11 @@ static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_c
|
|||||||
|
|
||||||
if (search_len)
|
if (search_len)
|
||||||
{
|
{
|
||||||
sprintf(tmp, "Logged entries: %d, searching for \"%s\"", (int) list_size(messages), search);
|
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T ", searching for \"%s\"", list_size(messages), search);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(tmp, "Logged entries: %d", (int) list_size(messages));
|
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
|
||||||
}
|
}
|
||||||
command_status(hub, user, cmd, tmp);
|
command_status(hub, user, cmd, tmp);
|
||||||
|
|
||||||
@@ -467,13 +561,27 @@ static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_c
|
|||||||
|
|
||||||
if (search_len)
|
if (search_len)
|
||||||
{
|
{
|
||||||
sprintf(tmp, "%d entries shown.", (int) search_hits);
|
sprintf(tmp, PRINTF_SIZE_T " entries shown.", search_hits);
|
||||||
command_status(hub, user, cmd, tmp);
|
command_status(hub, user, cmd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int command_rules(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
if (!hub_send_rules(hub, user))
|
||||||
|
return command_status(hub, user, cmd, "no rules defined.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_motd(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
if (!hub_send_motd(hub, user))
|
||||||
|
return command_status(hub, user, cmd, "no motd defined.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CRASH_DEBUG
|
#ifdef CRASH_DEBUG
|
||||||
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
@@ -490,7 +598,7 @@ int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* m
|
|||||||
|
|
||||||
/* Parse and validate the command */
|
/* Parse and validate the command */
|
||||||
struct hub_command* cmd = command_create(message);
|
struct hub_command* cmd = command_create(message);
|
||||||
if (!cmd) return 1;
|
if (!cmd) return 0;
|
||||||
|
|
||||||
for (n = 0; command_handlers[n].prefix; n++)
|
for (n = 0; command_handlers[n].prefix; n++)
|
||||||
{
|
{
|
||||||
@@ -524,28 +632,32 @@ int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* m
|
|||||||
|
|
||||||
command_not_found(hub, user, cmd);
|
command_not_found(hub, user, cmd);
|
||||||
command_destroy(cmd);
|
command_destroy(cmd);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct commands_handler command_handlers[] = {
|
static struct commands_handler command_handlers[] = {
|
||||||
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
|
|
||||||
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
|
|
||||||
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
|
|
||||||
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
|
|
||||||
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
|
|
||||||
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
|
|
||||||
{ "ban", 3, "n", cred_operator, command_ban, "Ban a user" },
|
{ "ban", 3, "n", cred_operator, command_ban, "Ban a user" },
|
||||||
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
|
|
||||||
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
|
|
||||||
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
|
|
||||||
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
|
|
||||||
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
|
|
||||||
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
|
|
||||||
{ "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" },
|
{ "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" },
|
||||||
{ "log", 3, 0, cred_operator, command_log, "Display log" },
|
|
||||||
#ifdef CRASH_DEBUG
|
#ifdef CRASH_DEBUG
|
||||||
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
|
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
|
||||||
#endif
|
#endif
|
||||||
|
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
|
||||||
|
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
|
||||||
|
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
|
||||||
|
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
|
||||||
|
{ "log", 3, 0, cred_operator, command_log, "Display log" },
|
||||||
|
{ "motd", 4, 0, cred_guest, command_motd, "Show the message of the day" },
|
||||||
|
{ "mute", 4, "n", cred_operator, command_mute, "Mute user" },
|
||||||
|
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
|
||||||
|
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
|
||||||
|
{ "rules", 5, 0, cred_guest, command_rules, "Show the hub rules" },
|
||||||
|
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
|
||||||
|
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
|
||||||
|
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
|
||||||
|
{ "unmute", 6, "n", cred_operator, command_mute, "Unmute user" },
|
||||||
|
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
|
||||||
|
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
|
||||||
|
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
|
||||||
{ 0, 0, 0, cred_none, command_help, "" }
|
{ 0, 0, 0, cred_none, command_help, "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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-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
|
||||||
@@ -29,430 +29,54 @@
|
|||||||
#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_HUB_NAME "uhub"
|
|
||||||
#define DEF_HUB_DESCRIPTION ""
|
|
||||||
#define DEF_HUB_ENABLED 1
|
|
||||||
#define DEF_FILE_ACL ""
|
|
||||||
#define DEF_FILE_MOTD ""
|
|
||||||
#define DEF_MAX_USERS 500
|
|
||||||
#define DEF_MAX_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_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);
|
if (strlen(data) == 1 && (data[0] == '1')) *target = 1;
|
||||||
DEFAULT_STRING (hub_name, DEF_HUB_NAME);
|
else if (strlen(data) == 1 && (data[0] == '0')) *target = 0;
|
||||||
DEFAULT_STRING (hub_description, DEF_HUB_DESCRIPTION);
|
else if (strncasecmp(data, "true", 4) == 0) *target = 1;
|
||||||
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
else if (strncasecmp(data, "false", 5) == 0) *target = 0;
|
||||||
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
else if (strncasecmp(data, "yes", 3) == 0) *target = 1;
|
||||||
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
else if (strncasecmp(data, "no", 2) == 0) *target = 0;
|
||||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
else if (strncasecmp(data, "on", 2) == 0) *target = 1;
|
||||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
else if (strncasecmp(data, "off", 3) == 0) *target = 0;
|
||||||
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
|
else
|
||||||
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
|
return 0;
|
||||||
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
return 1;
|
||||||
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
|
||||||
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
|
||||||
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
|
||||||
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
|
|
||||||
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
|
||||||
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
|
||||||
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
|
||||||
|
|
||||||
/* Limits enforced on users */
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
|
||||||
DEFAULT_INTEGER(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
|
||||||
DEFAULT_INTEGER(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
|
||||||
DEFAULT_INTEGER(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
|
||||||
DEFAULT_INTEGER(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
|
||||||
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
|
||||||
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
|
||||||
|
|
||||||
/* Status/error strings */
|
|
||||||
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
|
|
||||||
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
|
|
||||||
DEFAULT_STRING (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
|
||||||
DEFAULT_STRING (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
|
||||||
DEFAULT_STRING (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
|
||||||
DEFAULT_STRING (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
|
||||||
DEFAULT_STRING (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
|
||||||
DEFAULT_STRING (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
|
||||||
DEFAULT_STRING (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
|
||||||
DEFAULT_STRING (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
|
||||||
DEFAULT_STRING (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
|
||||||
DEFAULT_STRING (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
|
||||||
DEFAULT_STRING (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
|
||||||
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
|
||||||
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
|
||||||
|
|
||||||
DEFAULT_INTEGER(tls_enable, 0);
|
|
||||||
DEFAULT_INTEGER(tls_require, 0);
|
|
||||||
DEFAULT_STRING (tls_certificate, "");
|
|
||||||
DEFAULT_STRING (tls_private_key, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_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 (server_bind_addr);
|
|
||||||
GET_INT (server_port);
|
|
||||||
GET_STR (hub_name);
|
|
||||||
GET_STR (hub_description);
|
|
||||||
GET_BOOL(hub_enabled);
|
|
||||||
GET_INT (max_users);
|
|
||||||
GET_INT (max_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->hub_name);
|
val = strtol(data, &endptr, 10);
|
||||||
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 (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
|
||||||
DUMP_INT (server_port, DEF_SERVER_PORT);
|
|
||||||
DUMP_STR (hub_name, DEF_HUB_NAME);
|
|
||||||
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
|
||||||
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
|
||||||
DUMP_INT (max_users, DEF_MAX_USERS);
|
|
||||||
DUMP_INT (max_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);
|
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
@@ -461,10 +85,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;
|
||||||
|
|
||||||
@@ -507,6 +128,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)
|
||||||
@@ -521,7 +143,6 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config_defaults(config);
|
|
||||||
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
|
||||||
@@ -20,77 +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 hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
|
||||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
|
||||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
|
||||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
|
||||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
|
||||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
|
||||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
|
||||||
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
|
||||||
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
|
||||||
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
|
||||||
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
|
||||||
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
|
|
||||||
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
|
|
||||||
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
|
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
674
src/core/config.xml
Normal file
674
src/core/config.xml
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
<?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="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_only" type="boolean" default="0">
|
||||||
|
<short>Allow chat only operation on hub</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
If this is enabled the hub will refuse to relay messages for search and connection setup. This effectively makes the hub viable for chat only.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.1</since>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="chat_is_privileged" type="boolean" default="0">
|
||||||
|
<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_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_motd" type="file" default="">
|
||||||
|
<short>File containing the 'message of the day</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This can be specified as a message of the day file. If a valid file is given here it's content will be sent to all users after they have logged in to the hub. If the file is missing or empty this configuration entry will be ignored.
|
||||||
|
]]></description>
|
||||||
|
<since>0.1.3</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
Unix users: <br />
|
||||||
|
file_acl = "/etc/uhub/motd.txt"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Windows users: <br />
|
||||||
|
file_acl = "c:\uhub\motd.txt"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</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_rules" type="file" default="">
|
||||||
|
<short>File containing hub rules</short>
|
||||||
|
<description><![CDATA[
|
||||||
|
This is a text file that is displayed on login as an extended message of the day.
|
||||||
|
In addition the contents of the file is displayed when a user uses the "!rules" command.
|
||||||
|
]]></description>
|
||||||
|
<since>0.3.0</since>
|
||||||
|
<example><![CDATA[
|
||||||
|
<p>
|
||||||
|
Unix users: <br />
|
||||||
|
file_acl = "/etc/uhub/rules.txt"
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Windows users: <br />
|
||||||
|
file_acl = "c:\uhub\rules.txt"
|
||||||
|
</p>
|
||||||
|
]]></example>
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option name="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>
|
||||||
@@ -28,10 +28,14 @@
|
|||||||
/* Send a broadcast message */
|
/* Send a broadcast message */
|
||||||
#define UHUB_EVENT_BROADCAST 0x2000
|
#define UHUB_EVENT_BROADCAST 0x2000
|
||||||
|
|
||||||
|
/* Shutdown hub */
|
||||||
|
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
|
||||||
|
|
||||||
/* Statistics, OOM, reconfigure */
|
/* Statistics, OOM, reconfigure */
|
||||||
#define UHUB_EVENT_STATISTICS 0x4000
|
#define UHUB_EVENT_STATISTICS 0x4000
|
||||||
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
|
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
|
||||||
#define UHUB_EVENT_RECONFIGURE 0x4002
|
#define UHUB_EVENT_RECONFIGURE 0x4002
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_EVENT_ID_H */
|
#endif /* HAVE_UHUB_EVENT_ID_H */
|
||||||
|
|
||||||
|
|||||||
55
src/core/floodctl.c
Normal file
55
src/core/floodctl.c
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
void flood_control_reset(struct flood_control* data)
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(struct flood_control));
|
||||||
|
}
|
||||||
|
|
||||||
|
int flood_control_check(struct flood_control* data, size_t max_count, size_t time_delay, time_t now)
|
||||||
|
{
|
||||||
|
// Is flood control disabled?
|
||||||
|
if (!time_delay || !max_count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data->time)
|
||||||
|
{
|
||||||
|
data->time = now;
|
||||||
|
data->count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((now - data->time) > time_delay)
|
||||||
|
{
|
||||||
|
data->time = now;
|
||||||
|
data->count = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->count <= max_count)
|
||||||
|
{
|
||||||
|
data->count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
47
src/core/floodctl.h
Normal file
47
src/core/floodctl.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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_FLOOD_CTL_H
|
||||||
|
#define HAVE_UHUB_FLOOD_CTL_H
|
||||||
|
|
||||||
|
struct flood_control
|
||||||
|
{
|
||||||
|
time_t time;
|
||||||
|
size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset flood control statistics
|
||||||
|
*/
|
||||||
|
void flood_control_reset(struct flood_control*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ctl Flood control data structure
|
||||||
|
* @param max_count Max count for flood control
|
||||||
|
* @param window Time window for max_count to appear.
|
||||||
|
* @param now The current time.
|
||||||
|
*
|
||||||
|
* @return 0 if flood no flood detected.
|
||||||
|
* 1 if flood detected.
|
||||||
|
*/
|
||||||
|
int flood_control_check(struct flood_control* ctl, size_t max_count, size_t window, time_t now);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_FLOOD_CTL_H */
|
||||||
|
|
||||||
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 obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
|
||||||
|
int chat_only; /*<<< Allow chat only operation on hub (default: 0) */
|
||||||
|
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
|
||||||
|
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_certificate; /*<<< Certificate file (default: ) */
|
||||||
|
char* tls_private_key; /*<<< Private key file (default: ) */
|
||||||
|
char* file_motd; /*<<< File containing the 'message of the day (default: ) */
|
||||||
|
char* file_acl; /*<<< File containing access control lists (default: ) */
|
||||||
|
char* file_rules; /*<<< File containing hub rules (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." */
|
||||||
|
};
|
||||||
|
|
||||||
673
src/core/hub.c
673
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-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,6 +21,31 @@
|
|||||||
|
|
||||||
struct hub_info* g_hub = 0;
|
struct hub_info* g_hub = 0;
|
||||||
|
|
||||||
|
#define CHECK_CHAT_ONLY \
|
||||||
|
if (hub->config->chat_only && u->credentials < cred_operator) \
|
||||||
|
break
|
||||||
|
|
||||||
|
#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 +61,32 @@ 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. */
|
|
||||||
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 +94,27 @@ 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;
|
||||||
|
CHECK_CHAT_ONLY;
|
||||||
|
CHECK_FLOOD(search, 1);
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DRES:
|
case ADC_CMD_DRES:
|
||||||
|
cmd->priority = -1;
|
||||||
|
CHECK_CHAT_ONLY;
|
||||||
|
/* CHECK_FLOOD(search, 0); */
|
||||||
|
ROUTE_MSG;
|
||||||
|
|
||||||
case ADC_CMD_DRCM:
|
case ADC_CMD_DRCM:
|
||||||
case ADC_CMD_DCTM:
|
case ADC_CMD_DCTM:
|
||||||
cmd->priority = -1;
|
cmd->priority = -1;
|
||||||
if (hub->config->chat_only && u->credentials < cred_operator)
|
CHECK_CHAT_ONLY;
|
||||||
{
|
CHECK_FLOOD(connect, 1);
|
||||||
/* These below aren't allowed in chat only hubs */
|
ROUTE_MSG;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -102,12 +140,12 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
|||||||
if (hub->status == hub_status_disabled && u->state == state_protocol)
|
if (hub->status == hub_status_disabled && u->state == state_protocol)
|
||||||
{
|
{
|
||||||
on_login_failure(hub, u, status_msg_hub_disabled);
|
on_login_failure(hub, u, status_msg_hub_disabled);
|
||||||
|
hub_free(arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (arg)
|
while (arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (strlen(arg) == 6)
|
if (strlen(arg) == 6)
|
||||||
{
|
{
|
||||||
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
|
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
|
||||||
@@ -137,17 +175,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)
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
hub_send_handshake(hub, u);
|
|
||||||
user_set_timeout(u, TIMEOUT_HANDSHAKE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* disconnect user. Do not send crap during initial handshake! */
|
/* disconnect user. Do not send crap during initial handshake! */
|
||||||
hub_disconnect_user(hub, u, quit_logon_error);
|
hub_disconnect_user(hub, u, quit_logon_error);
|
||||||
ret = -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,18 +255,42 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
|||||||
char* message = adc_msg_get_argument(cmd, 0);
|
char* message = adc_msg_get_argument(cmd, 0);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int relay = 1;
|
int relay = 1;
|
||||||
|
int offset;
|
||||||
|
|
||||||
if (message[0] == '!' || message[0] == '+')
|
if (!message)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!user_is_logged_in(u))
|
||||||
{
|
{
|
||||||
relay = command_dipatcher(hub, u, message);
|
hub_free(message);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hub->config->chat_is_privileged && !user_is_protected(u) && (cmd->cache[0] == 'B' || cmd->cache[0] == 'F'))
|
if ((cmd->cache[0] == 'B') && (message[0] == '!' || message[0] == '+'))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* A message such as "++message" is handled as "+message", by removing the first character.
|
||||||
|
* The first character is removed by memmoving the string one byte to the left.
|
||||||
|
*/
|
||||||
|
if (message[1] == message[0])
|
||||||
|
{
|
||||||
|
relay = 1;
|
||||||
|
offset = adc_msg_get_arg_offset(cmd);
|
||||||
|
memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset);
|
||||||
|
cmd->length--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relay = command_dipatcher(hub, u, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((hub->config->chat_is_privileged && !user_is_protected(u)) || (user_flag_get(u, flag_muted))) && (cmd->cache[0] == 'B' || cmd->cache[0] == 'F'))
|
||||||
{
|
{
|
||||||
relay = 0;
|
relay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relay && user_is_logged_in(u))
|
if (relay)
|
||||||
{
|
{
|
||||||
/* adc_msg_remove_named_argument(cmd, "PM"); */
|
/* adc_msg_remove_named_argument(cmd, "PM"); */
|
||||||
if (cmd->cache[0] == 'B')
|
if (cmd->cache[0] == 'B')
|
||||||
@@ -344,14 +440,27 @@ void hub_send_handshake(struct hub_info* hub, struct hub_user* u)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_send_motd(struct hub_info* hub, struct hub_user* u)
|
int hub_send_motd(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
if (hub->command_motd)
|
if (hub->command_motd)
|
||||||
{
|
{
|
||||||
route_to_user(hub, u, 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;
|
||||||
@@ -362,6 +471,28 @@ void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u)
|
|||||||
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 void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
|
||||||
{
|
{
|
||||||
struct hub_info* hub = (struct hub_info*) callback_data;
|
struct hub_info* hub = (struct hub_info*) callback_data;
|
||||||
@@ -401,20 +532,170 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case UHUB_EVENT_HUB_SHUTDOWN:
|
||||||
|
{
|
||||||
|
struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list);
|
||||||
|
while (u)
|
||||||
|
{
|
||||||
|
uman_remove(hub, u);
|
||||||
|
user_destroy(u);
|
||||||
|
u = (struct hub_user*) list_get_first(hub->users->list);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* FIXME: ignored */
|
/* FIXME: ignored */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
|
||||||
|
{
|
||||||
|
struct net_connection* server;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t sockaddr_size;
|
||||||
|
int sd, ret;
|
||||||
|
|
||||||
|
if (ip_convert_address(bind_addr, port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd = net_socket_create(addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (sd == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((net_set_reuseaddress(sd, 1) == -1) || (net_set_nonblocking(sd, 1) == -1))
|
||||||
|
{
|
||||||
|
net_close(sd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_bind(sd, (struct sockaddr*) &addr, sockaddr_size);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
|
||||||
|
net_close(sd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_listen(sd, backlog);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
LOG_ERROR("hub_start_service(): Unable to listen to socket");
|
||||||
|
net_close(sd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
server = net_con_create();
|
||||||
|
net_con_initialize(server, sd, net_on_accept, hub, NET_EVENT_READ);
|
||||||
|
|
||||||
|
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 = 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);
|
||||||
|
|
||||||
|
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;
|
||||||
struct sockaddr_storage addr;
|
int ipv6_supported;
|
||||||
socklen_t sockaddr_size;
|
|
||||||
int server_tcp, ret, ipv6_supported, af;
|
|
||||||
char address_buf[INET6_ADDRSTRLEN+1];
|
|
||||||
|
|
||||||
hub = hub_malloc_zero(sizeof(struct hub_info));
|
hub = hub_malloc_zero(sizeof(struct hub_info));
|
||||||
if (!hub)
|
if (!hub)
|
||||||
@@ -424,117 +705,44 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hub->tm_started = time(0);
|
hub->tm_started = time(0);
|
||||||
|
|
||||||
ipv6_supported = net_is_ipv6_supported();
|
ipv6_supported = net_is_ipv6_supported();
|
||||||
|
|
||||||
if (ipv6_supported)
|
if (ipv6_supported)
|
||||||
LOG_DEBUG("IPv6 supported.");
|
LOG_DEBUG("IPv6 supported.");
|
||||||
else
|
else
|
||||||
LOG_DEBUG("IPv6 not supported.");
|
LOG_DEBUG("IPv6 not supported.");
|
||||||
|
|
||||||
if (ip_convert_address(config->server_bind_addr, config->server_port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
|
hub->server = start_listening_socket(config->server_bind_addr, config->server_port, config->server_listen_backlog, hub);
|
||||||
|
if (!hub->server)
|
||||||
|
{
|
||||||
|
hub_free(hub);
|
||||||
|
LOG_FATAL("Unable to start hub service");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (!load_ssl_certificates(hub, config))
|
||||||
{
|
{
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
af = addr.ss_family;
|
|
||||||
if (af == AF_INET)
|
|
||||||
{
|
|
||||||
net_address_to_string(AF_INET, &((struct sockaddr_in*) &addr)->sin_addr, address_buf, INET6_ADDRSTRLEN);
|
|
||||||
}
|
|
||||||
else if (af == AF_INET6)
|
|
||||||
{
|
|
||||||
net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LIBEVENT_1_4
|
|
||||||
hub->evbase = event_base_new();
|
|
||||||
#else
|
|
||||||
hub->evbase = event_init();
|
|
||||||
#endif
|
#endif
|
||||||
if (!hub->evbase)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Unable to initialize libevent.");
|
|
||||||
hub_free(hub);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", address_buf, config->server_port);
|
|
||||||
LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
|
|
||||||
|
|
||||||
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (server_tcp == -1)
|
|
||||||
{
|
|
||||||
event_base_free(hub->evbase);
|
|
||||||
hub_free(hub);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = net_set_reuseaddress(server_tcp, 1);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
event_base_free(hub->evbase);
|
|
||||||
hub_free(hub);
|
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = net_set_nonblocking(server_tcp, 1);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
event_base_free(hub->evbase);
|
|
||||||
hub_free(hub);
|
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = net_bind(server_tcp, (struct sockaddr*) &addr, sockaddr_size);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
LOG_FATAL("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
|
|
||||||
event_base_free(hub->evbase);
|
|
||||||
hub_free(hub);
|
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = net_listen(server_tcp, SERVER_BACKLOG);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
LOG_FATAL("hub_start_service(): Unable to listen to socket");
|
|
||||||
event_base_free(hub->evbase);
|
|
||||||
hub_free(hub);
|
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hub->fd_tcp = server_tcp;
|
|
||||||
hub->config = config;
|
hub->config = config;
|
||||||
hub->users = NULL;
|
hub->users = NULL;
|
||||||
|
|
||||||
if (uman_init(hub) == -1)
|
if (uman_init(hub) == -1)
|
||||||
{
|
{
|
||||||
|
net_con_close(hub->server);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub);
|
|
||||||
event_base_set(hub->evbase, &hub->ev_accept);
|
|
||||||
if (event_add(&hub->ev_accept, NULL) == -1)
|
|
||||||
{
|
|
||||||
uman_shutdown(hub);
|
|
||||||
hub_free(hub);
|
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
|
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
|
||||||
{
|
{
|
||||||
|
net_con_close(hub->server);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,11 +750,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
hub->sendbuf = hub_malloc(MAX_SEND_BUF);
|
hub->sendbuf = hub_malloc(MAX_SEND_BUF);
|
||||||
if (!hub->recvbuf || !hub->sendbuf)
|
if (!hub->recvbuf || !hub->sendbuf)
|
||||||
{
|
{
|
||||||
|
net_con_close(hub->server);
|
||||||
hub_free(hub->recvbuf);
|
hub_free(hub->recvbuf);
|
||||||
hub_free(hub->sendbuf);
|
hub_free(hub->sendbuf);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,16 +762,18 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
hub->logout_info = (struct linked_list*) list_create();
|
hub->logout_info = (struct linked_list*) list_create();
|
||||||
if (!hub->chat_history)
|
if (!hub->chat_history)
|
||||||
{
|
{
|
||||||
|
net_con_close(hub->server);
|
||||||
list_destroy(hub->chat_history);
|
list_destroy(hub->chat_history);
|
||||||
list_destroy(hub->logout_info);
|
list_destroy(hub->logout_info);
|
||||||
hub_free(hub->recvbuf);
|
hub_free(hub->recvbuf);
|
||||||
hub_free(hub->sendbuf);
|
hub_free(hub->sendbuf);
|
||||||
uman_shutdown(hub);
|
uman_shutdown(hub);
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server_alt_port_start(hub, config);
|
||||||
|
|
||||||
hub->status = hub_status_running;
|
hub->status = hub_status_running;
|
||||||
|
|
||||||
g_hub = hub;
|
g_hub = hub;
|
||||||
@@ -573,14 +783,18 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
|
|
||||||
void hub_shutdown_service(struct hub_info* hub)
|
void hub_shutdown_service(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
LOG_TRACE("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);
|
||||||
event_del(&hub->ev_accept);
|
net_con_close(hub->server);
|
||||||
net_close(hub->fd_tcp);
|
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;
|
||||||
event_base_free(hub->evbase);
|
|
||||||
hub_free(hub->sendbuf);
|
hub_free(hub->sendbuf);
|
||||||
hub_free(hub->recvbuf);
|
hub_free(hub->recvbuf);
|
||||||
hub_chat_history_clear(hub);
|
hub_chat_history_clear(hub);
|
||||||
@@ -592,17 +806,15 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
g_hub = 0;
|
g_hub = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SERVER "" PRODUCT "/" VERSION ""
|
|
||||||
|
|
||||||
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;
|
int fd, ret;
|
||||||
char buf[MAX_RECV_BUF];
|
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);
|
||||||
@@ -619,7 +831,7 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
|
|
||||||
/* (Re-)read the message of the day */
|
/* (Re-)read the message of the day */
|
||||||
hub->command_motd = 0;
|
hub->command_motd = 0;
|
||||||
fd = open(hub->config->file_motd, 0);
|
fd = (hub->config->file_motd && *hub->config->file_motd) ? open(hub->config->file_motd, 0) : -1;
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
{
|
{
|
||||||
ret = read(fd, buf, MAX_RECV_BUF);
|
ret = read(fd, buf, MAX_RECV_BUF);
|
||||||
@@ -628,12 +840,24 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
buf[ret] = 0;
|
buf[ret] = 0;
|
||||||
tmp = adc_msg_escape(buf);
|
tmp = adc_msg_escape(buf);
|
||||||
hub->command_motd = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
hub->command_motd = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
||||||
adc_msg_add_argument(hub->command_motd, tmp);
|
adc_msg_add_argument(hub->command_motd, tmp);
|
||||||
hub_free(tmp);
|
hub_free(tmp);
|
||||||
}
|
}
|
||||||
else
|
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);
|
close(fd);
|
||||||
}
|
}
|
||||||
@@ -644,10 +868,13 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
|||||||
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);
|
||||||
@@ -666,6 +893,9 @@ void hub_free_variables(struct hub_info* hub)
|
|||||||
if (hub->command_motd)
|
if (hub->command_motd)
|
||||||
adc_msg_free(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,44 +948,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
|
||||||
|
|
||||||
@@ -764,16 +1006,35 @@ 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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
@@ -811,6 +1072,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";
|
||||||
@@ -850,6 +1113,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";
|
||||||
@@ -931,27 +1196,6 @@ size_t hub_get_min_hubs_op(struct hub_info* hub)
|
|||||||
return hub->config->limit_min_hubs_op;
|
return hub->config->limit_min_hubs_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void hub_event_loop(struct hub_info* hub)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ret = event_base_loop(hub->evbase, EVLOOP_ONCE);
|
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("event_base_loop returned: %d", (int) ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
event_queue_process(hub->queue);
|
|
||||||
}
|
|
||||||
while (hub->status == hub_status_running || hub->status == hub_status_disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user)
|
void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user)
|
||||||
{
|
{
|
||||||
struct event_data post;
|
struct event_data post;
|
||||||
@@ -966,6 +1210,37 @@ void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hub_disconnect_all(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
struct event_data post;
|
||||||
|
memset(&post, 0, sizeof(post));
|
||||||
|
post.id = UHUB_EVENT_HUB_SHUTDOWN;
|
||||||
|
post.ptr = 0;
|
||||||
|
event_queue_post(hub->queue, &post);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hub_event_loop(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
net_backend_process();
|
||||||
|
event_queue_process(hub->queue);
|
||||||
|
}
|
||||||
|
while (hub->status == hub_status_running || hub->status == hub_status_disabled);
|
||||||
|
|
||||||
|
|
||||||
|
if (hub->status == hub_status_shutdown)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Removing all users...");
|
||||||
|
event_queue_process(hub->queue);
|
||||||
|
event_queue_process(hub->queue);
|
||||||
|
hub_disconnect_all(hub);
|
||||||
|
event_queue_process(hub->queue);
|
||||||
|
hub->status = hub_status_stopped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason)
|
void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason)
|
||||||
{
|
{
|
||||||
struct event_data post;
|
struct event_data post;
|
||||||
@@ -978,11 +1253,13 @@ void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* stop reading from user */
|
/* stop reading from user */
|
||||||
net_shutdown_r(user->net.connection.sd);
|
net_shutdown_r(net_con_get_sd(user->connection));
|
||||||
|
net_con_close(user->connection);
|
||||||
|
user->connection = 0;
|
||||||
|
|
||||||
LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state);
|
LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state);
|
||||||
|
|
||||||
need_notify = user_is_logged_in(user);
|
need_notify = user_is_logged_in(user) && hub->status == hub_status_running;
|
||||||
user->quit_reason = reason;
|
user->quit_reason = reason;
|
||||||
user_set_state(user, state_cleanup);
|
user_set_state(user, state_cleanup);
|
||||||
|
|
||||||
@@ -1006,7 +1283,7 @@ void hub_logout_log(struct hub_info* hub, struct hub_user* user)
|
|||||||
loginfo->time = time(NULL);
|
loginfo->time = time(NULL);
|
||||||
strcpy(loginfo->cid, user->id.cid);
|
strcpy(loginfo->cid, user->id.cid);
|
||||||
strcpy(loginfo->nick, user->id.nick);
|
strcpy(loginfo->nick, user->id.nick);
|
||||||
memcpy(&loginfo->addr, &user->net.ipaddr, sizeof(struct ip_addr_encap));
|
memcpy(&loginfo->addr, &user->id.addr, sizeof(struct ip_addr_encap));
|
||||||
loginfo->reason = user->quit_reason;
|
loginfo->reason = user->quit_reason;
|
||||||
|
|
||||||
list_append(hub->logout_info, loginfo);
|
list_append(hub->logout_info, loginfo);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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 */
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -90,18 +94,17 @@ struct hub_logout_info
|
|||||||
|
|
||||||
struct hub_info
|
struct hub_info
|
||||||
{
|
{
|
||||||
int fd_tcp;
|
struct net_connection* server;
|
||||||
struct event ev_accept;
|
struct linked_list* server_alt_ports;
|
||||||
struct event ev_timer;
|
|
||||||
struct hub_stats stats;
|
struct hub_stats stats;
|
||||||
struct event_queue* queue;
|
struct event_queue* queue;
|
||||||
struct event_base* evbase;
|
|
||||||
struct hub_config* config;
|
struct hub_config* config;
|
||||||
struct hub_user_manager* users;
|
struct hub_user_manager* users;
|
||||||
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_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;
|
||||||
@@ -202,8 +205,15 @@ extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
|
|||||||
/**
|
/**
|
||||||
* Send a welcome message containing the message of the day to
|
* Send a welcome message containing the message of the day to
|
||||||
* one particular user. This can be sent in any point in time.
|
* one particular user. This can be sent in any point in time.
|
||||||
|
* @return 1 if the motd were sent.
|
||||||
*/
|
*/
|
||||||
extern void hub_send_motd(struct hub_info* hub, struct hub_user* u);
|
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.
|
||||||
@@ -217,6 +227,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.
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -22,26 +22,33 @@
|
|||||||
static void log_user_login(struct hub_user* u)
|
static void log_user_login(struct hub_user* u)
|
||||||
{
|
{
|
||||||
const char* cred = get_user_credential_string(u->credentials);
|
const char* cred = get_user_credential_string(u->credentials);
|
||||||
const char* addr = ip_convert_to_string(&u->net.ipaddr);
|
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);
|
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)
|
static void log_user_login_error(struct hub_user* u, enum status_message msg)
|
||||||
{
|
{
|
||||||
const char* addr = ip_convert_to_string(&u->net.ipaddr);
|
const char* addr = user_get_address(u);
|
||||||
const char* message = hub_get_status_message_log(u->hub, msg);
|
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);
|
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void log_user_update_error(struct hub_user* u, enum status_message msg)
|
||||||
|
{
|
||||||
|
const char* addr = user_get_address(u);
|
||||||
|
const char* message = hub_get_status_message_log(u->hub, msg);
|
||||||
|
LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
static void log_user_logout(struct hub_user* u, const char* message)
|
static void log_user_logout(struct hub_user* u, const char* message)
|
||||||
{
|
{
|
||||||
const char* addr = ip_convert_to_string(&u->net.ipaddr);
|
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);
|
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)
|
static void log_user_nick_change(struct hub_user* u, const char* nick)
|
||||||
{
|
{
|
||||||
const char* addr = ip_convert_to_string(&u->net.ipaddr);
|
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);
|
LOG_USER("NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,8 +75,12 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
|
|||||||
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
||||||
hub_send_motd(hub, u);
|
hub_send_motd(hub, u);
|
||||||
|
|
||||||
/* reset to idle timeout */
|
/* Send message of the day (if any) */
|
||||||
user_set_timeout(u, TIMEOUT_IDLE);
|
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
||||||
|
hub_send_rules(hub, u);
|
||||||
|
|
||||||
|
/* reset timeout */
|
||||||
|
net_con_clear_timeout(u->connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
||||||
@@ -79,6 +90,13 @@ void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_mess
|
|||||||
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)
|
||||||
|
{
|
||||||
|
log_user_update_error(u, 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))
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -20,11 +20,6 @@
|
|||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "hubio.h"
|
#include "hubio.h"
|
||||||
|
|
||||||
// #define SEND_CHUNKS 1
|
|
||||||
|
|
||||||
/* FIXME: This should not be needed! */
|
|
||||||
extern struct hub_info* g_hub;
|
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
static void debug_msg(const char* prefix, struct adc_message* msg)
|
static void debug_msg(const char* prefix, struct adc_message* msg)
|
||||||
{
|
{
|
||||||
@@ -131,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;
|
||||||
}
|
}
|
||||||
@@ -146,58 +142,22 @@ void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
|||||||
q->offset = 0;
|
q->offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hub_sendq_send(struct hub_sendq* q, hub_recvq_write w, void* data)
|
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
size_t bytes = 0;
|
|
||||||
size_t offset = q->offset; // offset into first message.
|
|
||||||
size_t remain = 0;
|
|
||||||
size_t length = 0;
|
|
||||||
char* sbuf = g_hub->sendbuf;
|
|
||||||
size_t max_send_buf = 4096;
|
|
||||||
|
|
||||||
/* Copy as many messages possible into global send queue */
|
|
||||||
struct adc_message* msg = list_get_first(q->queue);
|
struct adc_message* msg = list_get_first(q->queue);
|
||||||
while (msg)
|
if (!msg) return 0;
|
||||||
{
|
assert(msg->cache && *msg->cache);
|
||||||
length = MIN(msg->length - offset, (max_send_buf-1) - bytes);
|
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||||
memcpy(sbuf + bytes, msg->cache + offset, length);
|
|
||||||
bytes += length;
|
|
||||||
|
|
||||||
if (length < (msg->length - offset))
|
|
||||||
break;
|
|
||||||
offset = 0;
|
|
||||||
msg = list_get_next(q->queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = list_get_first(q->queue);
|
|
||||||
|
|
||||||
/* Send as much as possible */
|
|
||||||
ret = w(data, sbuf, bytes);
|
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
#ifdef SSL_SUPPORT
|
q->offset += ret;
|
||||||
q->last_write_n = ret;
|
if (msg->length - q->offset > 0)
|
||||||
#endif
|
return 0;
|
||||||
|
|
||||||
/* Remove messages sent */
|
hub_sendq_remove(q, msg);
|
||||||
offset = q->offset;
|
return 1;
|
||||||
remain = ret;
|
|
||||||
|
|
||||||
while (msg)
|
|
||||||
{
|
|
||||||
length = msg->length - offset;
|
|
||||||
if (length >= remain)
|
|
||||||
{
|
|
||||||
q->offset += remain;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
remain -= length;
|
|
||||||
hub_sendq_remove(q, msg);
|
|
||||||
msg = list_get_next(q->queue);
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -58,10 +58,9 @@ extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the send queue, and send as many messages as possible.
|
* Process the send queue, and send as many messages as possible.
|
||||||
* @returns the number of bytes sent.
|
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
|
||||||
* FIXME: send error not handled here!
|
|
||||||
*/
|
*/
|
||||||
extern int hub_sendq_send(struct hub_sendq*, hub_recvq_write, void* data);
|
extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns 1 if send queue is empty, 0 otherwise.
|
* @returns 1 if send queue is empty, 0 otherwise.
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -46,6 +46,9 @@ static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd
|
|||||||
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
|
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
|
||||||
{
|
{
|
||||||
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
||||||
|
if (!tmp)
|
||||||
|
return -1; // FIXME: OOM
|
||||||
|
|
||||||
user_clear_feature_cast_support(u);
|
user_clear_feature_cast_support(u);
|
||||||
|
|
||||||
it = tmp;
|
it = tmp;
|
||||||
@@ -184,15 +187,15 @@ 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 = ip_convert_to_string(&user->net.ipaddr);
|
const char* address = user_get_address(user);
|
||||||
|
|
||||||
/* Check for NAT override address */
|
/* Check for NAT override address */
|
||||||
if (acl_is_ip_nat_override(hub->acl, address))
|
if (acl_is_ip_nat_override(hub->acl, address))
|
||||||
{
|
{
|
||||||
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||||
if (strcmp(client_given_ip, "0.0.0.0") != 0)
|
if (client_given_ip && strcmp(client_given_ip, "0.0.0.0") != 0)
|
||||||
{
|
{
|
||||||
user_set_nat_override(user);
|
user_set_nat_override(user);
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||||
@@ -220,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);
|
||||||
@@ -523,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.
|
||||||
@@ -645,7 +647,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);
|
||||||
@@ -655,7 +657,6 @@ int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct
|
|||||||
INF_CHECK(check_user_agent, hub, user, cmd);
|
INF_CHECK(check_user_agent, hub, user, cmd);
|
||||||
INF_CHECK(check_acl, hub, user, cmd);
|
INF_CHECK(check_acl, hub, user, cmd);
|
||||||
INF_CHECK(check_logged_in, hub, user, cmd);
|
INF_CHECK(check_logged_in, hub, user, cmd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,7 +674,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. */
|
||||||
@@ -713,6 +713,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 */
|
||||||
|
|
||||||
@@ -735,7 +736,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);
|
||||||
@@ -773,8 +774,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);
|
||||||
|
|
||||||
@@ -790,3 +797,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
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ static const char* arg_pid = 0;
|
|||||||
static int arg_log_syslog = 0;
|
static int arg_log_syslog = 0;
|
||||||
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#if !defined(WIN32)
|
||||||
void hub_handle_signal(int fd, short events, void* arg)
|
extern struct hub_info* g_hub;
|
||||||
|
void hub_handle_signal(int sig)
|
||||||
{
|
{
|
||||||
struct hub_info* hub = (struct hub_info*) arg;
|
struct hub_info* hub = g_hub;
|
||||||
int signal = fd;
|
|
||||||
|
|
||||||
switch (signal)
|
switch (sig)
|
||||||
{
|
{
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
LOG_INFO("Interrupted. Shutting down...");
|
LOG_INFO("Interrupted. Shutting down...");
|
||||||
@@ -65,7 +65,6 @@ void hub_handle_signal(int fd, short events, void* arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct event signal_events[10];
|
|
||||||
static int signals[] =
|
static int signals[] =
|
||||||
{
|
{
|
||||||
SIGINT, /* Interrupt the application */
|
SIGINT, /* Interrupt the application */
|
||||||
@@ -77,12 +76,18 @@ static int signals[] =
|
|||||||
|
|
||||||
void setup_signal_handlers(struct hub_info* hub)
|
void setup_signal_handlers(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
int i = 0;
|
sigset_t sig_set;
|
||||||
|
struct sigaction act;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sigemptyset(&sig_set);
|
||||||
|
act.sa_mask = sig_set;
|
||||||
|
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
||||||
|
act.sa_handler = hub_handle_signal;
|
||||||
|
|
||||||
for (i = 0; signals[i]; i++)
|
for (i = 0; signals[i]; i++)
|
||||||
{
|
{
|
||||||
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
|
if (sigaction(signals[i], &act, 0) != 0)
|
||||||
event_base_set(hub->evbase, &signal_events[i]);
|
|
||||||
if (signal_add(&signal_events[i], NULL))
|
|
||||||
{
|
{
|
||||||
LOG_ERROR("Error setting signal handler %d", signals[i]);
|
LOG_ERROR("Error setting signal handler %d", signals[i]);
|
||||||
}
|
}
|
||||||
@@ -91,14 +96,8 @@ void setup_signal_handlers(struct hub_info* hub)
|
|||||||
|
|
||||||
void shutdown_signal_handlers(struct hub_info* hub)
|
void shutdown_signal_handlers(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
for (i = 0; signals[i]; i++)
|
|
||||||
{
|
|
||||||
signal_del(&signal_events[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif /* !WIN32 */
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
int main_loop()
|
int main_loop()
|
||||||
@@ -134,7 +133,7 @@ int main_loop()
|
|||||||
hub = hub_start_service(&configuration);
|
hub = hub_start_service(&configuration);
|
||||||
if (!hub)
|
if (!hub)
|
||||||
return -1;
|
return -1;
|
||||||
#ifndef WIN32
|
#if !defined(WIN32)
|
||||||
setup_signal_handlers(hub);
|
setup_signal_handlers(hub);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -147,9 +146,9 @@ int main_loop()
|
|||||||
acl_shutdown(&acl);
|
acl_shutdown(&acl);
|
||||||
free_config(&configuration);
|
free_config(&configuration);
|
||||||
|
|
||||||
} while(hub->status != hub_status_shutdown);
|
} while (hub->status == hub_status_restart);
|
||||||
|
|
||||||
#ifndef WIN32
|
#if !defined(WIN32)
|
||||||
shutdown_signal_handlers(hub);
|
shutdown_signal_handlers(hub);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -191,8 +190,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -17,140 +17,37 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include <uhub.h>
|
||||||
#include "hubio.h"
|
#include "hubio.h"
|
||||||
|
#include "probe.h"
|
||||||
|
|
||||||
/* 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->net.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 net_user_send(void* ptr, const void* buf, size_t len)
|
|
||||||
{
|
|
||||||
struct hub_user* user = (struct hub_user*) ptr;
|
|
||||||
int ret = net_send(user->net.connection.sd, buf, len, UHUB_SEND_SIGNAL);
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
debug_sendq_send(user, ret, len);
|
|
||||||
#endif
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
user_reset_last_write(user);
|
|
||||||
}
|
|
||||||
else if (ret == -1 && (net_error() == EWOULDBLOCK || net_error() == EINTR))
|
|
||||||
{
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// user->close_flag = quit_socket_error;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
int net_user_send_ssl(void* ptr, const void* buf, size_t len)
|
|
||||||
{
|
|
||||||
struct hub_user* user = (struct hub_user*) ptr;
|
|
||||||
int ret = SSL_write(user->net.ssl, buf, (int) len);
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
debug_sendq_send(user, ret, len);
|
|
||||||
#endif
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
user_reset_last_write(user);
|
|
||||||
}
|
|
||||||
else if (ret == -1 && net_error() == EWOULDBLOCK)
|
|
||||||
{
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// user->close_flag = quit_socket_error;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int net_user_recv(void* ptr, void* buf, size_t len)
|
|
||||||
{
|
|
||||||
struct hub_user* user = (struct hub_user*) ptr;
|
|
||||||
int ret = net_recv(user->net.connection.sd, buf, len, 0);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
user_reset_last_read(user);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
debug_sendq_recv(user, ret, len, buf);
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
int net_user_recv_ssl(void* ptr, void* buf, size_t len)
|
|
||||||
{
|
|
||||||
struct hub_user* user = (struct hub_user*) ptr;
|
|
||||||
int ret = SSL_read(user->net.ssl, buf, len);
|
|
||||||
if (ret > 0)
|
|
||||||
{
|
|
||||||
user_reset_last_read(user);
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
debug_sendq_recv(user, ret, len, buf);
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#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->net.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_user_recv(user, &buf[buf_size], MAX_RECV_BUF - buf_size);
|
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;
|
||||||
|
|
||||||
if (size == -1)
|
if (size < 0)
|
||||||
{
|
{
|
||||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
if (size == -1)
|
||||||
return 0;
|
return quit_disconnected;
|
||||||
|
else
|
||||||
return quit_socket_error;
|
return quit_socket_error;
|
||||||
}
|
}
|
||||||
else if (size == 0)
|
else if (size == 0)
|
||||||
{
|
{
|
||||||
return quit_disconnected;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -179,7 +76,6 @@ int handle_net_read(struct hub_user* user)
|
|||||||
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
|
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
|
||||||
{
|
{
|
||||||
return quit_protocol_error;
|
return quit_protocol_error;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,16 +86,17 @@ int handle_net_read(struct hub_user* user)
|
|||||||
start = pos;
|
start = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastPos)
|
if (lastPos || remaining)
|
||||||
{
|
{
|
||||||
if (remaining < g_hub->config->max_recv_buffer)
|
if (remaining < g_hub->config->max_recv_buffer)
|
||||||
{
|
{
|
||||||
hub_recvq_set(q, lastPos, remaining);
|
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hub_recvq_set(q, 0, 0);
|
hub_recvq_set(q, 0, 0);
|
||||||
user_flag_set(user, flag_maxbuf);
|
user_flag_set(user, flag_maxbuf);
|
||||||
|
LOG_WARN("Received message past max_recv_buffer, dropping message.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -212,17 +109,18 @@ int handle_net_read(struct hub_user* user)
|
|||||||
|
|
||||||
int handle_net_write(struct hub_user* user)
|
int handle_net_write(struct hub_user* user)
|
||||||
{
|
{
|
||||||
while (hub_sendq_get_bytes(user->net.send_queue))
|
int ret = 0;
|
||||||
|
while (hub_sendq_get_bytes(user->send_queue))
|
||||||
{
|
{
|
||||||
int ret = hub_sendq_send(user->net.send_queue, net_user_send, user);
|
ret = hub_sendq_send(user->send_queue, user);
|
||||||
if (ret == -2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return quit_socket_error;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hub_sendq_get_bytes(user->net.send_queue))
|
if (ret < 0)
|
||||||
|
return quit_socket_error;
|
||||||
|
|
||||||
|
if (hub_sendq_get_bytes(user->send_queue))
|
||||||
{
|
{
|
||||||
user_net_io_want_write(user);
|
user_net_io_want_write(user);
|
||||||
}
|
}
|
||||||
@@ -233,76 +131,52 @@ int handle_net_write(struct hub_user* user)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_event(int fd, short ev, void *arg)
|
void net_event(struct net_connection* con, int event, void *arg)
|
||||||
{
|
{
|
||||||
struct hub_user* user = (struct hub_user*) arg;
|
struct hub_user* user = (struct hub_user*) arg;
|
||||||
int flag_close = 0;
|
int flag_close = 0;
|
||||||
|
|
||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
LOG_TRACE("net_on_read() : fd=%d, ev=%d, arg=%p", fd, (int) ev, arg);
|
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ev & EV_TIMEOUT)
|
if (event == NET_EVENT_TIMEOUT)
|
||||||
{
|
{
|
||||||
if (user_is_connecting(user))
|
if (user_is_connecting(user))
|
||||||
{
|
{
|
||||||
flag_close = quit_timeout;
|
hub_disconnect_user(g_hub, user, quit_timeout);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// FIXME: hub is not neccesarily set!
|
|
||||||
// hub_send_ping(hub, user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ev & EV_READ)
|
|
||||||
{
|
|
||||||
flag_close = handle_net_read(user);
|
|
||||||
}
|
|
||||||
else if (ev & EV_WRITE)
|
|
||||||
{
|
|
||||||
flag_close = handle_net_write(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag_close)
|
|
||||||
{
|
|
||||||
hub_disconnect_user(g_hub, user, flag_close);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event & NET_EVENT_READ)
|
||||||
|
{
|
||||||
|
flag_close = handle_net_read(user);
|
||||||
|
if (flag_close)
|
||||||
|
{
|
||||||
|
hub_disconnect_user(g_hub, user, flag_close);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event & NET_EVENT_WRITE)
|
||||||
|
{
|
||||||
|
flag_close = handle_net_write(user);
|
||||||
|
if (flag_close)
|
||||||
|
{
|
||||||
|
hub_disconnect_user(g_hub, user, flag_close);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void net_on_accept(struct net_connection* con, int event, void *arg)
|
||||||
static void prepare_user_net(struct hub_info* hub, struct hub_user* user)
|
|
||||||
{
|
|
||||||
int fd = user->net.connection.sd;
|
|
||||||
|
|
||||||
#ifdef SET_SENDBUG
|
|
||||||
size_t sendbuf = 0;
|
|
||||||
size_t recvbuf = 0;
|
|
||||||
|
|
||||||
if (net_get_recvbuf_size(fd, &recvbuf) != -1)
|
|
||||||
{
|
|
||||||
if (recvbuf > MAX_RECV_BUF || !recvbuf) recvbuf = MAX_RECV_BUF;
|
|
||||||
net_set_recvbuf_size(fd, recvbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (net_get_sendbuf_size(fd, &sendbuf) != -1)
|
|
||||||
{
|
|
||||||
if (sendbuf > MAX_SEND_BUF || !sendbuf) sendbuf = MAX_SEND_BUF;
|
|
||||||
net_set_sendbuf_size(fd, sendbuf);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
net_set_nonblocking(fd, 1);
|
|
||||||
net_set_nosigpipe(fd, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_on_accept(int server_fd, short ev, void *arg)
|
|
||||||
{
|
{
|
||||||
struct hub_info* hub = (struct hub_info*) arg;
|
struct hub_info* hub = (struct hub_info*) arg;
|
||||||
struct hub_user* user = 0;
|
struct hub_probe* probe = 0;
|
||||||
struct ip_addr_encap ipaddr;
|
struct ip_addr_encap ipaddr;
|
||||||
const char* addr;
|
const char* addr;
|
||||||
|
int server_fd = net_con_get_sd(con);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@@ -333,18 +207,13 @@ void net_on_accept(int server_fd, short ev, void *arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
user = user_create(hub, fd);
|
probe = probe_create(hub, fd, &ipaddr);
|
||||||
if (!user)
|
if (!probe)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to create user after socket accepted. Out of memory?");
|
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||||
net_close(fd);
|
net_close(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store IP address in user object */
|
|
||||||
memcpy(&user->net.ipaddr, &ipaddr, sizeof(ipaddr));
|
|
||||||
|
|
||||||
prepare_user_net(hub, user);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,9 +23,8 @@
|
|||||||
/**
|
/**
|
||||||
* Network callback to accept incoming connections.
|
* Network callback to accept incoming connections.
|
||||||
*/
|
*/
|
||||||
extern void net_on_accept(int fd, short ev, void *arg);
|
extern void net_on_accept(struct net_connection* con, int event, void *arg);
|
||||||
|
extern void net_event(struct net_connection* con, int event, void *arg);
|
||||||
extern void net_event(int fd, short ev, void *arg);
|
|
||||||
|
|
||||||
extern int handle_net_read(struct hub_user* user);
|
extern int handle_net_read(struct hub_user* user);
|
||||||
extern int handle_net_write(struct hub_user* user);
|
extern int handle_net_write(struct hub_user* user);
|
||||||
|
|||||||
127
src/core/probe.c
Normal file
127
src/core/probe.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
#include "probe.h"
|
||||||
|
|
||||||
|
#define PROBE_RECV_SIZE 12
|
||||||
|
static char probe_recvbuf[PROBE_RECV_SIZE];
|
||||||
|
|
||||||
|
static void probe_net_event(struct net_connection* con, int events, void *arg)
|
||||||
|
{
|
||||||
|
struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
|
||||||
|
if (events == NET_EVENT_TIMEOUT)
|
||||||
|
{
|
||||||
|
probe_destroy(probe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ)
|
||||||
|
{
|
||||||
|
int bytes = net_con_peek(con, probe_recvbuf, PROBE_RECV_SIZE);
|
||||||
|
if (bytes < 0)
|
||||||
|
{
|
||||||
|
probe_destroy(probe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes >= 4)
|
||||||
|
{
|
||||||
|
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
||||||
|
{
|
||||||
|
LOG_TRACE("Probed ADC");
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
|
||||||
|
{
|
||||||
|
LOG_TRACE("Not TLS connection - closing connection.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||||
|
{
|
||||||
|
probe->connection = 0;
|
||||||
|
}
|
||||||
|
probe_destroy(probe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (bytes >= 11 &&
|
||||||
|
probe_recvbuf[0] == 22 &&
|
||||||
|
probe_recvbuf[1] == 3 && /* protocol major version */
|
||||||
|
probe_recvbuf[5] == 1 && /* message type */
|
||||||
|
probe_recvbuf[9] == probe_recvbuf[1] &&
|
||||||
|
probe_recvbuf[10] == probe_recvbuf[2])
|
||||||
|
{
|
||||||
|
if (probe->hub->config->tls_enable)
|
||||||
|
{
|
||||||
|
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
||||||
|
if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||||
|
{
|
||||||
|
probe->connection = 0;
|
||||||
|
}
|
||||||
|
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
||||||
|
}
|
||||||
|
probe_destroy(probe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
||||||
|
|
||||||
|
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
probe_destroy(probe);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr)
|
||||||
|
{
|
||||||
|
struct hub_probe* probe = (struct hub_probe*) hub_malloc_zero(sizeof(struct hub_probe));
|
||||||
|
|
||||||
|
if (probe == NULL)
|
||||||
|
return NULL; /* OOM */
|
||||||
|
|
||||||
|
probe->hub = hub;
|
||||||
|
probe->connection = net_con_create();
|
||||||
|
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
|
||||||
|
net_con_set_timeout(probe->connection, TIMEOUT_CONNECTED);
|
||||||
|
|
||||||
|
memcpy(&probe->addr, addr, sizeof(struct ip_addr_encap));
|
||||||
|
return probe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void probe_destroy(struct hub_probe* probe)
|
||||||
|
{
|
||||||
|
if (probe->connection)
|
||||||
|
{
|
||||||
|
net_con_close(probe->connection);
|
||||||
|
probe->connection = 0;
|
||||||
|
}
|
||||||
|
hub_free(probe);
|
||||||
|
}
|
||||||
35
src/core/probe.h
Normal file
35
src/core/probe.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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_PROBE_H
|
||||||
|
#define HAVE_UHUB_PROBE_H
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
struct hub_probe
|
||||||
|
{
|
||||||
|
struct hub_info* hub; /** The hub instance this probe belong to */
|
||||||
|
struct net_connection* connection; /** Connection data */
|
||||||
|
struct ip_addr_encap addr; /** IP address */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr);
|
||||||
|
extern void probe_destroy(struct hub_probe* probe);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_PROBE_H */
|
||||||
@@ -80,11 +80,17 @@ static inline int check_send_queue(struct hub_info* hub, struct hub_user* user,
|
|||||||
if (user_flag_get(user, flag_user_list))
|
if (user_flag_get(user, flag_user_list))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if ((user->net.send_queue->size + msg->length) > get_max_send_queue(hub))
|
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
|
||||||
|
{
|
||||||
|
LOG_WARN("send queue overflowed, message discarded.");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (user->net.send_queue->size > get_max_send_queue_soft(hub) && msg->priority < 0)
|
if (user->send_queue->size > get_max_send_queue_soft(hub))
|
||||||
|
{
|
||||||
|
LOG_WARN("send queue soft overflowed.");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -97,17 +103,22 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
|||||||
free(data);
|
free(data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hub_sendq_is_empty(user->net.send_queue) && !user_flag_get(user, flag_pipeline))
|
if (!user->connection)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
assert(msg->cache && *msg->cache);
|
||||||
|
|
||||||
|
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||||
{
|
{
|
||||||
/* Perform oportunistic write */
|
/* Perform oportunistic write */
|
||||||
hub_sendq_add(user->net.send_queue, msg);
|
hub_sendq_add(user->send_queue, msg);
|
||||||
handle_net_write(user);
|
handle_net_write(user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (check_send_queue(hub, user, msg) >= 0)
|
if (check_send_queue(hub, user, msg) >= 0)
|
||||||
{
|
{
|
||||||
hub_sendq_add(user->net.send_queue, msg);
|
hub_sendq_add(user->send_queue, msg);
|
||||||
if (!user_flag_get(user, flag_pipeline))
|
if (!user_flag_get(user, flag_pipeline))
|
||||||
user_net_io_want_write(user);
|
user_net_io_want_write(user);
|
||||||
}
|
}
|
||||||
@@ -117,7 +128,7 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
|||||||
|
|
||||||
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
|
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
if (hub_sendq_is_empty(u->net.send_queue))
|
if (hub_sendq_is_empty(u->send_queue))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
handle_net_write(u);
|
handle_net_write(u);
|
||||||
@@ -197,7 +208,7 @@ int route_info_message(struct hub_info* hub, struct hub_user* u)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct adc_message* cmd = adc_msg_copy(u->info);
|
struct adc_message* cmd = adc_msg_copy(u->info);
|
||||||
const char* address = ip_convert_to_string(&u->net.ipaddr);
|
const char* address = user_get_address(u);
|
||||||
struct hub_user* user = 0;
|
struct hub_user* user = 0;
|
||||||
|
|
||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -35,29 +35,31 @@ static const char* user_log_str(struct hub_user* user)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct hub_user* user_create(struct hub_info* hub, int sd)
|
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
|
||||||
{
|
{
|
||||||
struct hub_user* user = NULL;
|
struct hub_user* user = NULL;
|
||||||
|
|
||||||
LOG_TRACE("user_create(), hub=%p, sd=%d", hub, sd);
|
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
|
||||||
|
|
||||||
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||||
|
|
||||||
if (user == NULL)
|
if (user == NULL)
|
||||||
return NULL; /* OOM */
|
return NULL; /* OOM */
|
||||||
|
|
||||||
user->net.tm_connected = time(NULL);
|
user->send_queue = hub_sendq_create();
|
||||||
user->net.send_queue = hub_sendq_create();
|
user->recv_queue = hub_recvq_create();
|
||||||
user->net.recv_queue = hub_recvq_create();
|
|
||||||
|
|
||||||
net_con_initialize(&user->net.connection, sd, user, EV_READ);
|
user->connection = con;
|
||||||
|
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
|
||||||
evtimer_set(&user->net.timeout, net_event, user);
|
|
||||||
event_base_set(hub->evbase, &user->net.timeout);
|
|
||||||
|
|
||||||
user_set_timeout(user, TIMEOUT_CONNECTED);
|
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,11 +68,8 @@ void user_destroy(struct hub_user* user)
|
|||||||
{
|
{
|
||||||
LOG_TRACE("user_destroy(), user=%p", user);
|
LOG_TRACE("user_destroy(), user=%p", user);
|
||||||
|
|
||||||
net_con_close(&user->net.connection);
|
hub_recvq_destroy(user->recv_queue);
|
||||||
evtimer_del(&user->net.timeout);
|
hub_sendq_destroy(user->send_queue);
|
||||||
|
|
||||||
hub_recvq_destroy(user->net.recv_queue);
|
|
||||||
hub_sendq_destroy(user->net.send_queue);
|
|
||||||
|
|
||||||
adc_msg_free(user->info);
|
adc_msg_free(user->info);
|
||||||
user_clear_feature_cast_support(user);
|
user_clear_feature_cast_support(user);
|
||||||
@@ -90,7 +89,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);
|
||||||
user->info = adc_msg_incref(cmd);
|
if (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)
|
||||||
@@ -134,10 +140,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;
|
||||||
|
|
||||||
@@ -167,6 +172,9 @@ static int convert_support_fourcc(int fourcc)
|
|||||||
case FOURCC('L','I','N','K'):
|
case FOURCC('L','I','N','K'):
|
||||||
return feature_link;
|
return feature_link;
|
||||||
|
|
||||||
|
case FOURCC('A','D','C','S'):
|
||||||
|
return feature_adcs;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_DEBUG("Unknown extension: %x", fourcc);
|
LOG_DEBUG("Unknown extension: %x", fourcc);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -318,37 +326,12 @@ int user_is_registered(struct hub_user* user)
|
|||||||
|
|
||||||
void user_net_io_want_write(struct hub_user* user)
|
void user_net_io_want_write(struct hub_user* user)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_SENDQ
|
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||||
LOG_TRACE("user_net_io_want_write: %s (pending: %d)", user_log_str(user), event_pending(&user->net.event, EV_READ | EV_WRITE, 0));
|
|
||||||
#endif
|
|
||||||
net_con_update(&user->net.connection, EV_READ | EV_WRITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_net_io_want_read(struct hub_user* user)
|
void user_net_io_want_read(struct hub_user* user)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_SENDQ
|
net_con_update(user->connection, NET_EVENT_READ);
|
||||||
LOG_TRACE("user_net_io_want_read: %s (pending: %d)", user_log_str(user), event_pending(&user->net.event, EV_READ | EV_WRITE, 0));
|
|
||||||
#endif
|
|
||||||
net_con_update(&user->net.connection, EV_READ);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_reset_last_write(struct hub_user* user)
|
|
||||||
{
|
|
||||||
user->net.tm_last_write = time(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_reset_last_read(struct hub_user* user)
|
|
||||||
{
|
|
||||||
user->net.tm_last_read = time(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_set_timeout(struct hub_user* user, int seconds)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_SENDQ
|
|
||||||
LOG_TRACE("user_set_timeout to %d seconds: %s", seconds, user_log_str(user));
|
|
||||||
#endif
|
|
||||||
struct timeval timeout = { seconds, 0 };
|
|
||||||
evtimer_add(&user->net.timeout, &timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
||||||
@@ -365,6 +348,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;
|
||||||
}
|
}
|
||||||
@@ -372,4 +356,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* user_get_address(struct hub_user* user)
|
||||||
|
{
|
||||||
|
return ip_convert_to_string(&user->id.addr);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
@@ -44,6 +45,10 @@ enum user_flags
|
|||||||
feature_bloom = 0x00000040, /** BLO0: Bloom filter (not supported) */
|
feature_bloom = 0x00000040, /** BLO0: Bloom filter (not supported) */
|
||||||
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_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_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 */
|
||||||
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
|
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
|
||||||
@@ -66,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,6 +84,7 @@ struct hub_user_info
|
|||||||
sid_t sid; /** session ID */
|
sid_t sid; /** session ID */
|
||||||
char cid[MAX_CID_LEN+1]; /** global client 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 */
|
||||||
|
struct ip_addr_encap addr; /** User's IP address */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,41 +94,36 @@ struct hub_user_info
|
|||||||
*/
|
*/
|
||||||
struct hub_user_limits
|
struct hub_user_limits
|
||||||
{
|
{
|
||||||
uint64_t shared_size; /** Shared size in bytes */
|
uint64_t shared_size; /** Shared size in bytes */
|
||||||
size_t shared_files; /** The number of shared files */
|
size_t shared_files; /** The number of shared files */
|
||||||
size_t upload_slots; /** The number of upload slots */
|
size_t upload_slots; /** The number of upload slots */
|
||||||
size_t hub_count_user; /** The number of hubs connected as user */
|
size_t hub_count_user; /** The number of hubs connected as user */
|
||||||
size_t hub_count_registered; /** The number of hubs connected as registered user */
|
size_t hub_count_registered; /** The number of hubs connected as registered user */
|
||||||
size_t hub_count_operator; /** The number of hubs connected as operator */
|
size_t hub_count_operator; /** The number of hubs connected as operator */
|
||||||
size_t hub_count_total; /** The number of hubs connected to in total */
|
size_t hub_count_total; /** The number of hubs connected to in total */
|
||||||
};
|
|
||||||
|
|
||||||
struct hub_user_net_io
|
|
||||||
{
|
|
||||||
struct net_connection connection; /** Connection data */
|
|
||||||
struct event timeout; /** timeout handling */
|
|
||||||
struct hub_recvq* recv_queue;
|
|
||||||
struct hub_sendq* send_queue;
|
|
||||||
time_t tm_connected; /** time when user connected */
|
|
||||||
time_t tm_last_read; /** time the user last received something from the hub */
|
|
||||||
time_t tm_last_write; /** time the user last sent something to the hub */
|
|
||||||
struct ip_addr_encap ipaddr; /** IP address of connected user */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hub_user
|
struct hub_user
|
||||||
{
|
{
|
||||||
struct hub_user_net_io net; /** Network information data */
|
enum user_state state; /** see enum user_state */
|
||||||
enum user_state state; /** see enum user_state */
|
enum user_credentials credentials; /** see enum user_credentials */
|
||||||
enum user_credentials credentials; /** see enum user_credentials */
|
struct hub_user_info id; /** Contains nick name and CID */
|
||||||
struct hub_user_info id; /** Contains nick name and CID */
|
uint32_t flags; /** see enum user_features */
|
||||||
int flags; /** see enum user_features */
|
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
||||||
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 */
|
struct hub_recvq* recv_queue;
|
||||||
struct hub_user_limits limits; /** Data used for limitation */
|
struct hub_sendq* send_queue;
|
||||||
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
struct net_connection* connection; /** Connection data */
|
||||||
|
struct hub_user_limits limits; /** Data used for limitation */
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ struct hub_user
|
|||||||
* @param sd socket descriptor associated with the user
|
* @param sd socket descriptor associated with the user
|
||||||
* @return User object or NULL if not enough memory is available.
|
* @return User object or NULL if not enough memory is available.
|
||||||
*/
|
*/
|
||||||
extern struct hub_user* user_create(struct hub_info* hub, int sd);
|
extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a user.
|
* Delete a user.
|
||||||
@@ -217,6 +219,8 @@ extern void user_support_add(struct hub_user* user, int fourcc);
|
|||||||
*/
|
*/
|
||||||
extern void user_support_remove(struct hub_user* user, int fourcc);
|
extern void user_support_remove(struct hub_user* user, int fourcc);
|
||||||
|
|
||||||
|
extern const char* user_get_address(struct hub_user* user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the nat override flag for a user, this allows users on the same
|
* Sets the nat override flag for a user, this allows users on the same
|
||||||
* subnet as a natted hub to spoof their IP in order to use active mode
|
* subnet as a natted hub to spoof their IP in order to use active mode
|
||||||
@@ -269,24 +273,6 @@ extern void user_net_io_want_write(struct hub_user* user);
|
|||||||
*/
|
*/
|
||||||
extern void user_net_io_want_read(struct hub_user* user);
|
extern void user_net_io_want_read(struct hub_user* user);
|
||||||
|
|
||||||
/**
|
|
||||||
* Set timeout for connetion.
|
|
||||||
* @param seconds the number of seconds into the future.
|
|
||||||
*/
|
|
||||||
extern void user_set_timeout(struct hub_user* user, int seconds);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the last-write timer.
|
|
||||||
*/
|
|
||||||
extern void user_reset_last_write(struct hub_user* user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the last-write timer.
|
|
||||||
*/
|
|
||||||
extern void user_reset_last_read(struct hub_user* user);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_USER_H */
|
#endif /* HAVE_UHUB_USER_H */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
|
||||||
#define USERMANAGER_TIMER
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This callback function is used to clear user objects from the userlist.
|
* This callback function is used to clear user objects from the userlist.
|
||||||
* Should only be used in uman_shutdown().
|
* Should only be used in uman_shutdown().
|
||||||
@@ -40,7 +38,6 @@ static void clear_user_list_callback(void* ptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uman_update_stats(struct hub_info* hub)
|
void uman_update_stats(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
const int factor = TIMEOUT_STATS;
|
const int factor = TIMEOUT_STATS;
|
||||||
@@ -58,10 +55,9 @@ void uman_update_stats(struct hub_info* hub)
|
|||||||
net_stats_reset();
|
net_stats_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uman_print_stats(struct hub_info* hub)
|
void uman_print_stats(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
LOG_INFO("Statistics users=%zu (peak_users=%zu), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
|
LOG_INFO("Statistics users=" PRINTF_SIZE_T " (peak_users=" PRINTF_SIZE_T "), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
|
||||||
hub->users->count,
|
hub->users->count,
|
||||||
hub->users->count_peak,
|
hub->users->count_peak,
|
||||||
(int) hub->stats.net_tx / 1024,
|
(int) hub->stats.net_tx / 1024,
|
||||||
@@ -70,25 +66,16 @@ void uman_print_stats(struct hub_info* hub)
|
|||||||
(int) hub->stats.net_rx_peak / 1024);
|
(int) hub->stats.net_rx_peak / 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USERMANAGER_TIMER
|
static void timer_statistics(struct timeout_evt* t)
|
||||||
static void timer_statistics(int fd, short ev, void *arg)
|
|
||||||
{
|
{
|
||||||
struct hub_info* hub = (struct hub_info*) arg;
|
struct hub_info* hub = (struct hub_info*) t->ptr;
|
||||||
struct timeval timeout = { TIMEOUT_STATS, 0 };
|
|
||||||
uman_update_stats(hub);
|
uman_update_stats(hub);
|
||||||
evtimer_set(&hub->ev_timer, timer_statistics, hub);
|
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->users->timeout, TIMEOUT_STATS);
|
||||||
event_base_set(hub->evbase, &hub->ev_timer);
|
|
||||||
evtimer_add(&hub->ev_timer, &timeout);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int uman_init(struct hub_info* hub)
|
int uman_init(struct hub_info* hub)
|
||||||
{
|
{
|
||||||
struct hub_user_manager* users = NULL;
|
struct hub_user_manager* users = NULL;
|
||||||
#ifdef USERMANAGER_TIMER
|
|
||||||
struct timeval timeout = { TIMEOUT_STATS, 0 };
|
|
||||||
#endif
|
|
||||||
if (!hub)
|
if (!hub)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -102,19 +89,18 @@ int uman_init(struct hub_info* hub)
|
|||||||
if (!users->list)
|
if (!users->list)
|
||||||
{
|
{
|
||||||
list_destroy(users->list);
|
list_destroy(users->list);
|
||||||
|
hub_free(users);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hub->users = users;
|
if (net_backend_get_timeout_queue())
|
||||||
|
|
||||||
#ifdef USERMANAGER_TIMER
|
|
||||||
if (hub->evbase)
|
|
||||||
{
|
{
|
||||||
evtimer_set(&hub->ev_timer, timer_statistics, hub);
|
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||||
event_base_set(hub->evbase, &hub->ev_timer);
|
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
||||||
evtimer_add(&hub->ev_timer, &timeout);
|
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
||||||
}
|
}
|
||||||
#endif // 0
|
|
||||||
|
hub->users = users;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,10 +110,11 @@ int uman_shutdown(struct hub_info* hub)
|
|||||||
if (!hub || !hub->users)
|
if (!hub || !hub->users)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef USERMANAGER_TIMER
|
if (net_backend_get_timeout_queue())
|
||||||
if (evtimer_pending(&hub->ev_timer, 0))
|
{
|
||||||
event_del(&hub->ev_timer);
|
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
||||||
#endif
|
hub_free(hub->users->timeout);
|
||||||
|
}
|
||||||
|
|
||||||
if (hub->users->list)
|
if (hub->users->list)
|
||||||
{
|
{
|
||||||
@@ -138,6 +125,7 @@ int uman_shutdown(struct hub_info* hub)
|
|||||||
hub_free(hub->users);
|
hub_free(hub->users);
|
||||||
hub->users = 0;
|
hub->users = 0;
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +211,7 @@ size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, st
|
|||||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
|
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
|
||||||
while (user)
|
while (user)
|
||||||
{
|
{
|
||||||
if (ip_in_range(&user->net.ipaddr, range))
|
if (ip_in_range(&user->id.addr, range))
|
||||||
{
|
{
|
||||||
list_append(users, user);
|
list_append(users, user);
|
||||||
num++;
|
num++;
|
||||||
@@ -236,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))
|
||||||
@@ -259,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);
|
||||||
@@ -273,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);
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ struct hub_user_manager
|
|||||||
struct sid_pool* sids;
|
struct sid_pool* sids;
|
||||||
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
||||||
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
||||||
struct linked_list* list; /**<< "Contains all users" */
|
struct linked_list* list; /**<< "Contains all logged in users" */
|
||||||
|
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
220
src/network/backend.c
Normal file
220
src/network/backend.c
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
|
||||||
|
struct net_backend;
|
||||||
|
struct net_connection;
|
||||||
|
|
||||||
|
struct net_cleanup_handler
|
||||||
|
{
|
||||||
|
size_t num;
|
||||||
|
size_t max;
|
||||||
|
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 = 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);
|
||||||
|
|
||||||
|
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* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler));
|
||||||
|
handler->num = 0;
|
||||||
|
handler->max = max;
|
||||||
|
handler->queue = hub_malloc_zero(sizeof(struct net_connection*) * max);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_cleanup_shutdown(struct net_cleanup_handler* handler)
|
||||||
|
{
|
||||||
|
hub_free(handler->queue);
|
||||||
|
hub_free(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con)
|
||||||
|
{
|
||||||
|
handler->queue[handler->num++] = con;
|
||||||
|
con->flags |= NET_CLEANUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_cleanup_process(struct net_cleanup_handler* handler)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
for (n = 0; n < handler->num; n++)
|
||||||
|
{
|
||||||
|
struct net_connection* con = handler->queue[n];
|
||||||
|
LOG_TRACE("net_cleanup_process: free: %p", con);
|
||||||
|
hub_free(con);
|
||||||
|
}
|
||||||
|
handler->num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
94
src/network/backend.h
Normal file
94
src/network/backend.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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_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_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)(void);
|
||||||
|
|
||||||
|
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.
|
||||||
|
* Returns 1 on success, or 0 on failure.
|
||||||
|
*/
|
||||||
|
extern int net_backend_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the network connection backend.
|
||||||
|
*/
|
||||||
|
extern void net_backend_shutdown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the network backend.
|
||||||
|
*/
|
||||||
|
extern int net_backend_process();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current time.
|
||||||
|
*/
|
||||||
|
time_t net_get_time();
|
||||||
|
|
||||||
|
extern struct timeout_queue* net_backend_get_timeout_queue();
|
||||||
|
|
||||||
|
struct net_cleanup_handler* net_cleanup_initialize(size_t max);
|
||||||
|
|
||||||
|
void net_cleanup_shutdown(struct net_cleanup_handler* handler);
|
||||||
|
|
||||||
|
void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con);
|
||||||
|
|
||||||
|
void net_cleanup_process(struct net_cleanup_handler* handler);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_NETWORK_BACKEND_H */
|
||||||
51
src/network/common.h
Normal file
51
src/network/common.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NET_WANT_READ NET_EVENT_READ
|
||||||
|
#define NET_WANT_WRITE NET_EVENT_WRITE
|
||||||
|
#define NET_WANT_ACCEPT NET_EVENT_READ
|
||||||
|
#define NET_WANT_SSL_READ 0x0010
|
||||||
|
#define NET_WANT_SSL_WRITE 0x0020
|
||||||
|
#define NET_WANT_SSL_ACCEPT 0x0040
|
||||||
|
#define NET_WANT_SSL_CONNECT 0x0080
|
||||||
|
#define NET_WANT_SSL_X509_LOOKUP 0x0100
|
||||||
|
|
||||||
|
#define NET_CLEANUP 0x8000
|
||||||
|
|
||||||
|
#define NET_CON_STRUCT_BASIC \
|
||||||
|
int sd; /** socket descriptor */ \
|
||||||
|
uint32_t flags; /** Connection flags */ \
|
||||||
|
void* ptr; /** data pointer */ \
|
||||||
|
net_connection_cb callback; /** Callback function */ \
|
||||||
|
struct timeout_evt* timeout; /** timeout event handler */
|
||||||
|
|
||||||
|
#define NET_CON_STRUCT_SSL \
|
||||||
|
SSL* ssl; /** SSL handle */ \
|
||||||
|
uint32_t ssl_state; /** SSL state */ \
|
||||||
|
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
#define NET_CON_STRUCT_COMMON \
|
||||||
|
NET_CON_STRUCT_BASIC \
|
||||||
|
NET_CON_STRUCT_SSL
|
||||||
|
#else
|
||||||
|
#define NET_CON_STRUCT_COMMON \
|
||||||
|
NET_CON_STRUCT_BASIC
|
||||||
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -18,35 +18,311 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
|
||||||
extern struct hub_info* g_hub;
|
#ifdef SSL_SUPPORT
|
||||||
|
|
||||||
void net_con_initialize(struct net_connection* con, int sd, const void* ptr, int events)
|
enum uhub_tls_state
|
||||||
{
|
{
|
||||||
con->sd = sd;
|
tls_st_none,
|
||||||
con->ptr = (void*) ptr;
|
tls_st_error,
|
||||||
|
tls_st_accepting,
|
||||||
|
tls_st_connecting,
|
||||||
|
tls_st_connected,
|
||||||
|
tls_st_disconnecting,
|
||||||
|
};
|
||||||
|
|
||||||
event_set(&con->event, con->sd, events | EV_PERSIST, net_event, con->ptr);
|
static int handle_openssl_error(struct net_connection* con, int ret)
|
||||||
event_base_set(g_hub->evbase, &con->event);
|
{
|
||||||
event_add(&con->event, 0);
|
uhub_assert(con);
|
||||||
|
|
||||||
|
int error = SSL_get_error(con->ssl, ret);
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case SSL_ERROR_ZERO_RETURN:
|
||||||
|
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
|
||||||
|
con->ssl_state = tls_st_error;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_READ:
|
||||||
|
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
|
||||||
|
con->flags |= NET_WANT_SSL_READ;
|
||||||
|
net_con_update(con, NET_EVENT_READ);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case SSL_ERROR_WANT_WRITE:
|
||||||
|
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
|
||||||
|
con->flags |= NET_WANT_SSL_WRITE;
|
||||||
|
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case SSL_ERROR_SYSCALL:
|
||||||
|
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
|
||||||
|
/* if ret == 0, connection closed, if ret == -1, check with errno */
|
||||||
|
if (ret == 0)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return -net_error();
|
||||||
|
|
||||||
|
case SSL_ERROR_SSL:
|
||||||
|
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
|
||||||
|
/* internal openssl error */
|
||||||
|
con->ssl_state = tls_st_error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_con_update(struct net_connection* con, int events)
|
ssize_t net_con_ssl_accept(struct net_connection* con)
|
||||||
{
|
{
|
||||||
if (event_pending(&con->event, EV_READ | EV_WRITE, 0) == events)
|
uhub_assert(con);
|
||||||
|
con->ssl_state = tls_st_accepting;
|
||||||
|
ssize_t ret = SSL_accept(con->ssl);
|
||||||
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
|
LOG_PROTO("SSL_accept() ret=%d", ret);
|
||||||
|
#endif
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
net_con_update(con, NET_EVENT_READ);
|
||||||
|
con->ssl_state = tls_st_connected;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return handle_openssl_error(con, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t net_con_ssl_connect(struct net_connection* con)
|
||||||
|
{
|
||||||
|
uhub_assert(con);
|
||||||
|
|
||||||
|
con->ssl_state = tls_st_connecting;
|
||||||
|
ssize_t ret = SSL_connect(con->ssl);
|
||||||
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
|
LOG_PROTO("SSL_connect() ret=%d", ret);
|
||||||
|
#endif
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
con->ssl_state = tls_st_connected;
|
||||||
|
net_con_update(con, NET_EVENT_READ);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return handle_openssl_error(con, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode ssl_mode, SSL_CTX* ssl_ctx)
|
||||||
|
{
|
||||||
|
uhub_assert(con);
|
||||||
|
SSL* ssl = 0;
|
||||||
|
|
||||||
|
if (ssl_mode == net_con_ssl_mode_server)
|
||||||
|
{
|
||||||
|
ssl = SSL_new(ssl_ctx);
|
||||||
|
SSL_set_fd(ssl, con->sd);
|
||||||
|
net_con_set_ssl(con, ssl);
|
||||||
|
return net_con_ssl_accept(con);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
|
||||||
|
SSL_set_fd(ssl, con->sd);
|
||||||
|
net_con_set_ssl(con, ssl);
|
||||||
|
return net_con_ssl_connect(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (!con->ssl)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
con->write_len = len;
|
||||||
|
ret = SSL_write(con->ssl, buf, len);
|
||||||
|
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
return -handle_openssl_error(con, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
if (!net_con_is_ssl(con))
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
ret = net_recv(con->sd, buf, len, 0);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
||||||
|
return 0;
|
||||||
|
return -net_error();
|
||||||
|
}
|
||||||
|
else if (ret == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (con->ssl_state == tls_st_error)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = SSL_read(con->ssl, buf, len);
|
||||||
|
LOG_PROTO("SSL_read(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
net_con_update(con, NET_EVENT_READ);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -handle_openssl_error(con, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
|
||||||
|
{
|
||||||
|
int ret = net_recv(con->sd, buf, len, MSG_PEEK);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
||||||
|
return 0;
|
||||||
|
return -net_error();
|
||||||
|
}
|
||||||
|
else if (ret == 0)
|
||||||
|
return -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
int net_con_is_ssl(struct net_connection* con)
|
||||||
|
{
|
||||||
|
return con->ssl != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL* net_con_get_ssl(struct net_connection* con)
|
||||||
|
{
|
||||||
|
return con->ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_set_ssl(struct net_connection* con, SSL* ssl)
|
||||||
|
{
|
||||||
|
con->ssl = ssl;
|
||||||
|
}
|
||||||
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
|
int net_con_get_sd(struct net_connection* con)
|
||||||
|
{
|
||||||
|
return con->sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* net_con_get_ptr(struct net_connection* con)
|
||||||
|
{
|
||||||
|
return con->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_destroy(struct net_connection* con)
|
||||||
|
{
|
||||||
|
hub_free(con);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_callback(struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
if (con->flags & NET_CLEANUP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event_del(&con->event);
|
if (events == NET_EVENT_TIMEOUT)
|
||||||
event_set(&con->event, con->sd, events | EV_PERSIST, net_event, con->ptr);
|
{
|
||||||
event_add(&con->event, 0);
|
LOG_TRACE("net_con_callback(%p, TIMEOUT", con);
|
||||||
}
|
con->callback(con, events, con->ptr);
|
||||||
|
|
||||||
void net_con_close(struct net_connection* con)
|
|
||||||
{
|
|
||||||
if (!event_pending(&con->event, EV_READ | EV_WRITE, 0))
|
|
||||||
return;
|
return;
|
||||||
event_del(&con->event);
|
}
|
||||||
net_close(con->sd);
|
|
||||||
con->sd = -1;
|
#ifdef SSL_SUPPORT
|
||||||
|
if (!con->ssl)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
con->callback(con, events, con->ptr);
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef NETWORK_DUMP_DEBUG
|
||||||
|
LOG_PROTO("net_con_event: events=%d, con=%p, state=%d", events, con, con->ssl_state);
|
||||||
|
#endif
|
||||||
|
switch (con->ssl_state)
|
||||||
|
{
|
||||||
|
case tls_st_none:
|
||||||
|
con->callback(con, events, con->ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tls_st_error:
|
||||||
|
con->callback(con, NET_EVENT_READ, con->ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tls_st_accepting:
|
||||||
|
if (net_con_ssl_accept(con) < 0)
|
||||||
|
{
|
||||||
|
con->callback(con, NET_EVENT_READ, con->ptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tls_st_connecting:
|
||||||
|
if (net_con_ssl_connect(con) < 0)
|
||||||
|
{
|
||||||
|
con->callback(con, NET_EVENT_READ, con->ptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tls_st_connected:
|
||||||
|
LOG_PROTO("tls_st_connected, events=%s%s, ssl_flags=%s%s", (events & NET_EVENT_READ ? "R" : ""), (events & NET_EVENT_WRITE ? "W" : ""), con->flags & NET_WANT_SSL_READ ? "R" : "", con->flags & NET_WANT_SSL_WRITE ? "W" : "");
|
||||||
|
if (events & NET_EVENT_WRITE && con->flags & NET_WANT_SSL_READ)
|
||||||
|
{
|
||||||
|
con->callback(con, events & NET_EVENT_READ, con->ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ && con->flags & NET_WANT_SSL_WRITE)
|
||||||
|
{
|
||||||
|
con->callback(con, events & NET_EVENT_READ, con->ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
con->callback(con, events, con->ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tls_st_disconnecting:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,21 +21,91 @@
|
|||||||
#define HAVE_UHUB_NETWORK_CONNECTION_H
|
#define HAVE_UHUB_NETWORK_CONNECTION_H
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
|
#define NET_EVENT_TIMEOUT 0x0001
|
||||||
|
#define NET_EVENT_READ 0x0002
|
||||||
|
#define NET_EVENT_WRITE 0x0004
|
||||||
|
|
||||||
struct net_connection
|
struct net_connection
|
||||||
{
|
{
|
||||||
int sd; /** socket descriptor */
|
NET_CON_STRUCT_COMMON
|
||||||
void* ptr; /** data pointer */
|
|
||||||
struct event event; /** libevent struct for read/write events */
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
SSL* ssl; /** SSL handle */
|
|
||||||
#endif /* SSL_SUPPORT */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void net_con_initialize(struct net_connection* con, int sd, const void* ptr, int events);
|
extern int net_con_get_sd(struct net_connection* con);
|
||||||
|
extern void* net_con_get_ptr(struct net_connection* con);
|
||||||
|
|
||||||
|
extern struct net_connection* net_con_create();
|
||||||
|
extern void net_con_destroy(struct net_connection*);
|
||||||
|
extern void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events);
|
||||||
|
extern void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
|
||||||
extern void net_con_update(struct net_connection* con, int events);
|
extern void net_con_update(struct net_connection* con, int events);
|
||||||
|
extern void net_con_callback(struct net_connection* con, int events);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the connection.
|
||||||
|
* This will ensure a connection is closed properly and will generate a NET_EVENT_DESTROYED event which indicates
|
||||||
|
* that the con can safely be deleted (or set to NULL).
|
||||||
|
*/
|
||||||
extern void net_con_close(struct net_connection* con);
|
extern void net_con_close(struct net_connection* con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send data
|
||||||
|
*
|
||||||
|
* @return returns the number of bytes sent.
|
||||||
|
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
|
||||||
|
* <0 if an error occured, the negative number contains the error code.
|
||||||
|
*/
|
||||||
|
extern ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive data
|
||||||
|
*
|
||||||
|
* @return returns the number of bytes sent.
|
||||||
|
* 0 if no data is sent, and this function should be called again (EWOULDBLOCK/EINTR)
|
||||||
|
* <0 if an error occured, the negative number contains the error code.
|
||||||
|
*/
|
||||||
|
extern ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive data without removing them from the recv() buffer.
|
||||||
|
* NOTE: This does not currently work for SSL connections after the SSL handshake has been
|
||||||
|
* performed.
|
||||||
|
*/
|
||||||
|
extern ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set timeout for connetion.
|
||||||
|
*
|
||||||
|
* @param seconds the number of seconds into the future.
|
||||||
|
*/
|
||||||
|
extern void net_con_set_timeout(struct net_connection* con, int seconds);
|
||||||
|
extern void net_con_clear_timeout(struct net_connection* con);
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
/**
|
||||||
|
* Start SSL_accept()
|
||||||
|
*/
|
||||||
|
extern ssize_t net_con_ssl_accept(struct net_connection*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start SSL_connect()
|
||||||
|
*/
|
||||||
|
extern ssize_t net_con_ssl_connect(struct net_connection*);
|
||||||
|
|
||||||
|
enum net_con_ssl_mode
|
||||||
|
{
|
||||||
|
net_con_ssl_mode_server,
|
||||||
|
net_con_ssl_mode_client,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode, SSL_CTX* ssl_ctx);
|
||||||
|
|
||||||
|
extern int net_con_is_ssl(struct net_connection* con);
|
||||||
|
extern SSL* net_con_get_ssl(struct net_connection* con);
|
||||||
|
extern void net_con_set_ssl(struct net_connection* con, SSL*);
|
||||||
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_NETWORK_CONNECTION_H */
|
#endif /* HAVE_UHUB_NETWORK_CONNECTION_H */
|
||||||
|
|
||||||
|
|||||||
187
src/network/epoll.c
Normal file
187
src/network/epoll.c
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* 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_EPOLL
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
|
#define EPOLL_EVBUFFER 512
|
||||||
|
|
||||||
|
struct net_connection_epoll
|
||||||
|
{
|
||||||
|
NET_CON_STRUCT_COMMON
|
||||||
|
struct epoll_event ev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend_epoll
|
||||||
|
{
|
||||||
|
int epfd;
|
||||||
|
struct net_connection_epoll** conns;
|
||||||
|
struct epoll_event events[EPOLL_EVBUFFER];
|
||||||
|
struct net_backend_common* common;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
|
||||||
|
const char* net_backend_name_epoll()
|
||||||
|
{
|
||||||
|
return "epoll";
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_backend_poll_epoll(struct net_backend* data, int ms)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
int res = epoll_wait(backend->epfd, backend->events, MIN(backend->common->num, EPOLL_EVBUFFER), ms);
|
||||||
|
if (res == -1 && errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_process_epoll(struct net_backend* data, int res)
|
||||||
|
{
|
||||||
|
int n, ev;
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
for (n = 0; n < res; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create_epoll(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
|
||||||
|
con->sd = -1;
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
con->sd = sd;
|
||||||
|
con->flags = 0;
|
||||||
|
con->callback = callback;
|
||||||
|
con->ev.events = 0;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
con->ev.data.fd = sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_add_epoll(struct net_backend* data, 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_;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = con;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
||||||
|
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
||||||
|
|
||||||
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
||||||
|
{
|
||||||
|
LOG_TRACE("epoll_ctl() add failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_mod_epoll(struct net_backend* data, 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_;
|
||||||
|
|
||||||
|
int newev = 0;
|
||||||
|
if (events & NET_EVENT_READ) newev |= EPOLLIN;
|
||||||
|
if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
|
||||||
|
|
||||||
|
if (newev == con->ev.events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
con->ev.events = newev;
|
||||||
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
||||||
|
{
|
||||||
|
LOG_TRACE("epoll_ctl() modify failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
|
|
||||||
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("epoll_ctl() delete failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown_epoll(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
close(backend->epfd);
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
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 */
|
||||||
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 */
|
||||||
@@ -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,6 +21,7 @@
|
|||||||
|
|
||||||
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
|
static int is_ipv6_supported = -1; /* -1 = CHECK, 0 = NO, 1 = YES */
|
||||||
static int net_initialized = 0;
|
static int net_initialized = 0;
|
||||||
|
|
||||||
static struct net_statistics stats;
|
static struct net_statistics stats;
|
||||||
static struct net_statistics stats_total;
|
static struct net_statistics stats_total;
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ int net_initialize()
|
|||||||
{
|
{
|
||||||
if (!net_initialized)
|
if (!net_initialized)
|
||||||
{
|
{
|
||||||
|
LOG_TRACE("Initializing network monitor.");
|
||||||
|
|
||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
struct WSAData wsa;
|
struct WSAData wsa;
|
||||||
@@ -45,13 +47,19 @@ int net_initialize()
|
|||||||
}
|
}
|
||||||
#endif /* WINSOCK */
|
#endif /* WINSOCK */
|
||||||
|
|
||||||
LOG_TRACE("Initializing network monitor.");
|
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_load_error_strings();
|
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
|
SSL_load_error_strings();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
#endif /* SSL_SUPPORT */
|
#endif /* SSL_SUPPORT */
|
||||||
|
|
||||||
@@ -67,13 +75,19 @@ 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");
|
||||||
#else
|
|
||||||
LOG_ERROR("System does not have getrlimit(): constrained to 1024 sockets");
|
|
||||||
#endif /* HAVE_GETRLIMIT */
|
|
||||||
return 1024;
|
return 1024;
|
||||||
|
#else
|
||||||
|
#ifdef WIN32
|
||||||
|
LOG_WARN("Windows system, limited to 4096 connections.");
|
||||||
|
return 4096;
|
||||||
|
#else
|
||||||
|
LOG_WARN("System does not have getrlimit(): constrained to 1024 sockets");
|
||||||
|
return 1024;
|
||||||
|
#endif
|
||||||
|
#endif /* HAVE_GETRLIMIT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -83,6 +97,8 @@ int net_destroy()
|
|||||||
{
|
{
|
||||||
LOG_TRACE("Shutting down network monitor");
|
LOG_TRACE("Shutting down network monitor");
|
||||||
|
|
||||||
|
net_backend_shutdown();
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
/* FIXME: Shutdown OpenSSL here. */
|
/* FIXME: Shutdown OpenSSL here. */
|
||||||
#endif
|
#endif
|
||||||
@@ -96,6 +112,13 @@ int net_destroy()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_LIBEVENT
|
||||||
|
struct event_base* net_get_evbase()
|
||||||
|
{
|
||||||
|
return net_evbase;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void net_error_out(int fd, const char* func)
|
static void net_error_out(int fd, const char* func)
|
||||||
{
|
{
|
||||||
int err = net_error();
|
int err = net_error();
|
||||||
@@ -165,8 +188,18 @@ int net_set_nonblocking(int fd, int toggle)
|
|||||||
#ifdef WINSOCK
|
#ifdef WINSOCK
|
||||||
u_long on = toggle ? 1 : 0;
|
u_long on = toggle ? 1 : 0;
|
||||||
ret = ioctlsocket(fd, FIONBIO, &on);
|
ret = ioctlsocket(fd, FIONBIO, &on);
|
||||||
|
#else
|
||||||
|
#ifdef __sun__
|
||||||
|
int flags = fcntl(fd, F_GETFL, 0);
|
||||||
|
if (flags != -1)
|
||||||
|
{
|
||||||
|
if (toggle) flags |= O_NONBLOCK;
|
||||||
|
else flags &= ~O_NONBLOCK;
|
||||||
|
ret = fcntl(fd, F_SETFL, flags);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
ret = ioctl(fd, FIONBIO, &toggle);
|
ret = ioctl(fd, FIONBIO, &toggle);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
@@ -270,7 +303,7 @@ int net_close(int fd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (fd != -1)
|
if (ret != -1)
|
||||||
{
|
{
|
||||||
net_stats_add_error();
|
net_stats_add_error();
|
||||||
}
|
}
|
||||||
@@ -324,6 +357,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:
|
||||||
@@ -349,16 +385,16 @@ 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, };
|
||||||
net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1);
|
net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1);
|
||||||
if (!strncmp(address, "::ffff:", 7))
|
if (strchr(address, '.'))
|
||||||
{
|
{
|
||||||
/* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */
|
/* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */
|
||||||
net_string_to_address(AF_INET, address + 7, (void*) &ipaddr->internal_ip_data.in);
|
|
||||||
ipaddr->af = AF_INET;
|
ipaddr->af = AF_INET;
|
||||||
|
net_string_to_address(AF_INET, address, (void*) &ipaddr->internal_ip_data.in);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -441,6 +477,7 @@ int net_socket_create(int af, int type, int protocol)
|
|||||||
if (sd == -1)
|
if (sd == -1)
|
||||||
{
|
{
|
||||||
net_error_out(sd, "net_socket_create");
|
net_error_out(sd, "net_socket_create");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SOCK_DUAL_STACK_OPT
|
#ifdef SOCK_DUAL_STACK_OPT
|
||||||
@@ -498,7 +535,15 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
return inet_ntop(af, src, dst, cnt);
|
if (inet_ntop(af, src, dst, cnt))
|
||||||
|
{
|
||||||
|
if (af == AF_INET6 && strncmp(dst, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
|
||||||
|
{
|
||||||
|
memmove(dst, dst + 7, cnt - 7);
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,9 +590,6 @@ int net_string_to_address(int af, const char* src, void* dst)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* net_get_peer_address(int fd)
|
const char* net_get_peer_address(int fd)
|
||||||
{
|
{
|
||||||
static char address[INET6_ADDRSTRLEN+1];
|
static char address[INET6_ADDRSTRLEN+1];
|
||||||
@@ -555,9 +597,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;
|
||||||
@@ -566,21 +609,16 @@ 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);
|
||||||
if (strncmp(address, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
|
|
||||||
{
|
|
||||||
return &address[7];
|
|
||||||
}
|
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
|
return address;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -591,6 +629,46 @@ const char* net_get_peer_address(int fd)
|
|||||||
return "0.0.0.0";
|
return "0.0.0.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* net_get_local_address(int fd)
|
||||||
|
{
|
||||||
|
static char address[INET6_ADDRSTRLEN+1];
|
||||||
|
struct sockaddr_storage storage;
|
||||||
|
struct sockaddr_in6* name6;
|
||||||
|
struct sockaddr_in* name4;
|
||||||
|
struct sockaddr* name;
|
||||||
|
socklen_t namelen;
|
||||||
|
|
||||||
|
memset(address, 0, INET6_ADDRSTRLEN);
|
||||||
|
namelen = sizeof(struct sockaddr_storage);
|
||||||
|
memset(&storage, 0, namelen);
|
||||||
|
|
||||||
|
name6 = (struct sockaddr_in6*) &storage;
|
||||||
|
name4 = (struct sockaddr_in*) &storage;
|
||||||
|
name = (struct sockaddr*) &storage;
|
||||||
|
|
||||||
|
if (getsockname(fd, (struct sockaddr*) name, &namelen) != -1)
|
||||||
|
{
|
||||||
|
int af = storage.ss_family;
|
||||||
|
if (af == AF_INET6)
|
||||||
|
{
|
||||||
|
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
net_error_out(fd, "net_get_local_address");
|
||||||
|
net_stats_add_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0.0.0.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
ssize_t net_recv(int fd, void* buf, size_t len, int flags)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -32,15 +32,6 @@ struct net_statistics
|
|||||||
|
|
||||||
struct net_socket_t;
|
struct net_socket_t;
|
||||||
|
|
||||||
#define NET_WANT_READ 0x01
|
|
||||||
#define NET_WANT_WRITE 0x02
|
|
||||||
#define NET_WANT_ACCEPT 0x08
|
|
||||||
#define NET_WANT_SSL_READ 0x10
|
|
||||||
#define NET_WANT_SSL_WRITE 0x20
|
|
||||||
#define NET_WANT_SSL_ACCEPT 0x40
|
|
||||||
#define NET_WANT_SSL_CONNECT 0x40
|
|
||||||
#define NET_WANT_SSL_X509_LOOKUP 0x80
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the socket monitor subsystem.
|
* Initialize the socket monitor subsystem.
|
||||||
* On some operating systems this will also involve loading the TCP/IP stack
|
* On some operating systems this will also involve loading the TCP/IP stack
|
||||||
@@ -60,6 +51,8 @@ extern int net_initialize();
|
|||||||
*/
|
*/
|
||||||
extern int net_destroy();
|
extern int net_destroy();
|
||||||
|
|
||||||
|
extern struct event_base* net_get_evbase();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the number of sockets currrently being monitored.
|
* @return the number of sockets currrently being monitored.
|
||||||
*/
|
*/
|
||||||
@@ -231,6 +224,8 @@ extern int net_is_ipv6_supported();
|
|||||||
*/
|
*/
|
||||||
extern const char* net_get_peer_address(int fd);
|
extern const char* net_get_peer_address(int fd);
|
||||||
|
|
||||||
|
extern const char* net_get_local_address(int fd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See man(3) inet_ntop.
|
* See man(3) inet_ntop.
|
||||||
*/
|
*/
|
||||||
|
|||||||
173
src/network/select.c
Normal file
173
src/network/select.c
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* 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_SELECT
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
|
struct net_connection_select
|
||||||
|
{
|
||||||
|
NET_CON_STRUCT_COMMON
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend_select
|
||||||
|
{
|
||||||
|
struct net_connection_select** conns;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
int maxfd;
|
||||||
|
struct net_backend_common* common;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
|
||||||
|
const char* net_backend_name_select()
|
||||||
|
{
|
||||||
|
return "select";
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_backend_poll_select(struct net_backend* data, int ms)
|
||||||
|
{
|
||||||
|
int found, res, n;
|
||||||
|
struct timeval tval;
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
|
||||||
|
tval.tv_sec = ms / 1000;
|
||||||
|
tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct?
|
||||||
|
|
||||||
|
FD_ZERO(&backend->rfds);
|
||||||
|
FD_ZERO(&backend->wfds);
|
||||||
|
|
||||||
|
backend->maxfd = -1;
|
||||||
|
for (n = 0, found = 0; found < backend->common->num && n < backend->common->max; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_select* con = backend->conns[n];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &backend->rfds);
|
||||||
|
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &backend->wfds);
|
||||||
|
found++;
|
||||||
|
backend->maxfd = con->sd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backend->maxfd++;
|
||||||
|
|
||||||
|
res = select(backend->maxfd, &backend->rfds, &backend->wfds, 0, &tval);
|
||||||
|
|
||||||
|
if (res == -1 && errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
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 = backend->conns[n];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
int ev = 0;
|
||||||
|
if (FD_ISSET(con->sd, &backend->rfds)) ev |= NET_EVENT_READ;
|
||||||
|
if (FD_ISSET(con->sd, &backend->wfds)) ev |= NET_EVENT_WRITE;
|
||||||
|
|
||||||
|
if (ev)
|
||||||
|
{
|
||||||
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create_select(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
|
||||||
|
con->sd = -1;
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize_select(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection_select* con = (struct net_connection_select*) con_;
|
||||||
|
con->sd = sd;
|
||||||
|
con->flags = 0;
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_add_select(struct net_backend* data, struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
backend->conns[con->sd] = (struct net_connection_select*) con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_mod_select(struct net_backend* data, struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE));;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_del_select(struct net_backend* data, struct net_connection* con)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown_select(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_backend* net_backend_init_select(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend;
|
||||||
|
|
||||||
|
if (getenv("EVENT_NOSELECT"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
backend = hub_malloc_zero(sizeof(struct net_backend_select));
|
||||||
|
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 */
|
||||||
149
src/network/timeout.c
Normal file
149
src/network/timeout.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* 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 wtimeout_evtith this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
||||||
|
{
|
||||||
|
t->callback = cb;
|
||||||
|
t->ptr = ptr;
|
||||||
|
t->prev = 0;
|
||||||
|
t->next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timeout_evt_reset(struct timeout_evt* t)
|
||||||
|
{
|
||||||
|
t->prev = 0;
|
||||||
|
t->next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeout_evt_is_scheduled(struct timeout_evt* t)
|
||||||
|
{
|
||||||
|
return t->prev != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
|
||||||
|
{
|
||||||
|
t->last = now;
|
||||||
|
t->max = max;
|
||||||
|
t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*));
|
||||||
|
}
|
||||||
|
|
||||||
|
void timeout_queue_shutdown(struct timeout_queue* t)
|
||||||
|
{
|
||||||
|
hub_free(t->events);
|
||||||
|
t->events = 0;
|
||||||
|
t->max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
||||||
|
{
|
||||||
|
size_t pos = t->last;
|
||||||
|
size_t events = 0;
|
||||||
|
struct timeout_evt* evt = 0;
|
||||||
|
t->last = now;
|
||||||
|
for (; pos <= now; pos++)
|
||||||
|
{
|
||||||
|
while ((evt = t->events[pos % t->max]))
|
||||||
|
{
|
||||||
|
timeout_queue_remove(t, evt);
|
||||||
|
evt->callback(evt);
|
||||||
|
events++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now)
|
||||||
|
{
|
||||||
|
size_t seconds = 0;
|
||||||
|
while (t->events[(now + seconds) % t->max] == NULL && seconds < t->max)
|
||||||
|
{
|
||||||
|
seconds++;
|
||||||
|
}
|
||||||
|
if (seconds == 0)
|
||||||
|
return 1;
|
||||||
|
return seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
|
||||||
|
{
|
||||||
|
struct timeout_evt* first;
|
||||||
|
size_t pos = ((t->last + seconds) % t->max);
|
||||||
|
evt->timestamp = t->last + seconds;
|
||||||
|
evt->next = 0;
|
||||||
|
|
||||||
|
first = t->events[pos];
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
uhub_assert(first->timestamp == evt->timestamp);
|
||||||
|
first->prev->next = evt;
|
||||||
|
evt->prev = first->prev;
|
||||||
|
first->prev = evt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t->events[pos] = evt;
|
||||||
|
evt->prev = evt;
|
||||||
|
}
|
||||||
|
evt->next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
|
||||||
|
{
|
||||||
|
size_t pos = (evt->timestamp % t->max);
|
||||||
|
struct timeout_evt* first = t->events[pos];
|
||||||
|
|
||||||
|
if (!first || !evt->prev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (first == evt)
|
||||||
|
{
|
||||||
|
if (first->prev != first)
|
||||||
|
{
|
||||||
|
t->events[pos] = first->next;
|
||||||
|
t->events[pos]->prev = evt->prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t->events[pos] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (evt == first->prev)
|
||||||
|
{
|
||||||
|
first->prev = evt->prev;
|
||||||
|
evt->prev->next = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
evt->prev->next = evt->next;
|
||||||
|
evt->next->prev = evt->prev;
|
||||||
|
}
|
||||||
|
timeout_evt_reset(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
|
||||||
|
{
|
||||||
|
if (timeout_evt_is_scheduled(evt))
|
||||||
|
timeout_queue_remove(t, evt);
|
||||||
|
timeout_queue_insert(t, evt, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
58
src/network/timeout.h
Normal file
58
src/network/timeout.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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_TIMEOUT_HANDLER_H
|
||||||
|
#define HAVE_UHUB_TIMEOUT_HANDLER_H
|
||||||
|
|
||||||
|
struct timeout_evt;
|
||||||
|
struct timeout_queue;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_TIMEOUT_HANDLER_H */
|
||||||
50
src/network/timer.c
Normal file
50
src/network/timer.c
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
#include "network/connection.h"
|
||||||
|
|
||||||
|
static void timeout_callback(struct timeout_evt* evt)
|
||||||
|
{
|
||||||
|
net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_set_timeout(struct net_connection* con, int seconds)
|
||||||
|
{
|
||||||
|
if (!con->timeout)
|
||||||
|
{
|
||||||
|
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||||
|
timeout_evt_initialize(con->timeout, timeout_callback, con);
|
||||||
|
timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_clear_timeout(struct net_connection* con)
|
||||||
|
{
|
||||||
|
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
|
||||||
|
{
|
||||||
|
timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
|
||||||
|
hub_free(con->timeout);
|
||||||
|
con->timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
244
src/system.h
Normal file
244
src/system.h
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UHUB_SYSTEM_H
|
||||||
|
#define HAVE_UHUB_SYSTEM_H
|
||||||
|
|
||||||
|
#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
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
|
#define BSD_LIKE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__) || defined(__MINGW32__)
|
||||||
|
#ifndef WINSOCK
|
||||||
|
#define WINSOCK
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WINSOCK
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#ifndef __sun__
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if !defined(WIN32)
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#define HAVE_STRNDUP
|
||||||
|
#ifndef __HAIKU__
|
||||||
|
#define HAVE_MEMMEM
|
||||||
|
#endif
|
||||||
|
#define HAVE_GETRLIMIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* printf and size_t support */
|
||||||
|
#if defined(WIN32)
|
||||||
|
/* Windows uses %Iu for size_t */
|
||||||
|
#define PRINTF_SIZE_T "%Iu"
|
||||||
|
#else
|
||||||
|
#define PRINTF_SIZE_T "%zu"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_SUPPORT
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../version.h"
|
||||||
|
|
||||||
|
#define uhub_assert assert
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#define USE_EPOLL
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BSD_LIKE
|
||||||
|
#define USE_KQUEUE
|
||||||
|
#include <sys/event.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USE_SELECT
|
||||||
|
#ifndef WINSOCK
|
||||||
|
#include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BSD_LIKE) || defined(__sun__)
|
||||||
|
#undef HAVE_STRNDUP
|
||||||
|
#undef HAVE_MEMMEM
|
||||||
|
#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__)
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL
|
||||||
|
#else
|
||||||
|
#ifdef MSG_NOPIPE
|
||||||
|
#define UHUB_SEND_SIGNAL MSG_NOPIPE
|
||||||
|
#else
|
||||||
|
#define UHUB_SEND_SIGNAL 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INET6_ADDRSTRLEN
|
||||||
|
#define INET6_ADDRSTRLEN 46
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_SYSTEM_H */
|
||||||
485
src/tools/adcclient.c
Normal file
485
src/tools/adcclient.c
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tools/adcclient.h"
|
||||||
|
|
||||||
|
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR ADPING\n"
|
||||||
|
#define ADC_CID_SIZE 39
|
||||||
|
#define BIG_BUFSIZE 32768
|
||||||
|
#define TIGERSIZE 24
|
||||||
|
|
||||||
|
static ssize_t ADC_client_recv(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_disconnected(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 void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length);
|
||||||
|
|
||||||
|
static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
|
||||||
|
{
|
||||||
|
char logmsg[1024];
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(logmsg, 1024, format, args);
|
||||||
|
va_end(args);
|
||||||
|
fprintf(stdout, "* [%p] %s\n", client, logmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ADC_client_set_state(struct ADC_client* client, enum ADC_client_state state)
|
||||||
|
{
|
||||||
|
client->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void adc_cid_pid(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
char seed[64];
|
||||||
|
char pid[64];
|
||||||
|
char cid[64];
|
||||||
|
uint64_t tiger_res1[3];
|
||||||
|
uint64_t tiger_res2[3];
|
||||||
|
|
||||||
|
/* create cid+pid pair */
|
||||||
|
memset(seed, 0, 64);
|
||||||
|
snprintf(seed, 64, VERSION "%p", client);
|
||||||
|
|
||||||
|
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
|
||||||
|
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
|
||||||
|
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
|
||||||
|
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
|
||||||
|
cid[ADC_CID_SIZE] = 0;
|
||||||
|
pid[ADC_CID_SIZE] = 0;
|
||||||
|
|
||||||
|
adc_msg_add_named_argument(client->info, ADC_INF_FLAG_PRIVATE_ID, pid);
|
||||||
|
adc_msg_add_named_argument(client->info, ADC_INF_FLAG_CLIENT_ID, cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void event_callback(struct net_connection* con, int events, void *arg)
|
||||||
|
{
|
||||||
|
struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con);
|
||||||
|
|
||||||
|
if (events == NET_EVENT_TIMEOUT)
|
||||||
|
{
|
||||||
|
if (client->state == ps_conn)
|
||||||
|
{
|
||||||
|
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ)
|
||||||
|
{
|
||||||
|
if (ADC_client_recv(client) == -1)
|
||||||
|
{
|
||||||
|
ADC_client_on_disconnected(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & NET_EVENT_WRITE)
|
||||||
|
{
|
||||||
|
if (client->state == ps_conn)
|
||||||
|
{
|
||||||
|
ADC_client_connect(client, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: Call send again */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNESCAPE_ARG(TMP, TARGET) \
|
||||||
|
if (TMP) \
|
||||||
|
TARGET = adc_msg_unescape(TMP); \
|
||||||
|
else \
|
||||||
|
TARGET = NULL; \
|
||||||
|
hub_free(TMP);
|
||||||
|
|
||||||
|
#define EXTRACT_NAMED_ARG(MSG, NAME, TARGET) \
|
||||||
|
do { \
|
||||||
|
char* tmp = adc_msg_get_named_argument(MSG, NAME); \
|
||||||
|
UNESCAPE_ARG(tmp, TARGET); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define EXTRACT_POS_ARG(MSG, POS, TARGET) \
|
||||||
|
do { \
|
||||||
|
char* tmp = adc_msg_get_argument(MSG, POS); \
|
||||||
|
UNESCAPE_ARG(tmp, TARGET); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
static void ADC_client_on_recv_line(struct ADC_client* client, const char* line, size_t length)
|
||||||
|
{
|
||||||
|
#ifdef ADC_CLIENT_DEBUG_PROTO
|
||||||
|
ADC_client_debug(client, "- LINE: '%s'", start);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Parse message */
|
||||||
|
struct adc_message* msg = adc_msg_parse(line, length);
|
||||||
|
if (!msg)
|
||||||
|
{
|
||||||
|
ADC_client_debug(client, "WARNING: Message cannot be decoded: \"%s\"", line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < 4)
|
||||||
|
{
|
||||||
|
ADC_client_debug(client, "Unexpected response from hub: '%s'", line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg->cmd)
|
||||||
|
{
|
||||||
|
case ADC_CMD_ISUP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_ISID:
|
||||||
|
if (client->state == ps_protocol)
|
||||||
|
{
|
||||||
|
client->sid = string_to_sid(&line[5]);
|
||||||
|
client->callback(client, ADC_CLIENT_LOGGING_IN, 0);
|
||||||
|
ADC_client_set_state(client, ps_identify);
|
||||||
|
ADC_client_send_info(client);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CMD_BMSG:
|
||||||
|
case ADC_CMD_EMSG:
|
||||||
|
case ADC_CMD_DMSG:
|
||||||
|
case ADC_CMD_IMSG:
|
||||||
|
{
|
||||||
|
struct ADC_chat_message chat;
|
||||||
|
struct ADC_client_callback_data data;
|
||||||
|
chat.from_sid = msg->source;
|
||||||
|
chat.to_sid = msg->target;
|
||||||
|
data.chat = &chat;
|
||||||
|
EXTRACT_POS_ARG(msg, 0, chat.message);
|
||||||
|
client->callback(client, ADC_CLIENT_MESSAGE, &data);
|
||||||
|
hub_free(chat.message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADC_CMD_IINF:
|
||||||
|
{
|
||||||
|
struct ADC_hub_info hubinfo;
|
||||||
|
EXTRACT_NAMED_ARG(msg, "NI", hubinfo.name);
|
||||||
|
EXTRACT_NAMED_ARG(msg, "DE", hubinfo.description);
|
||||||
|
EXTRACT_NAMED_ARG(msg, "VE", hubinfo.version);
|
||||||
|
|
||||||
|
struct ADC_client_callback_data data;
|
||||||
|
data.hubinfo = &hubinfo;
|
||||||
|
client->callback(client, ADC_CLIENT_HUB_INFO, &data);
|
||||||
|
hub_free(hubinfo.name);
|
||||||
|
hub_free(hubinfo.description);
|
||||||
|
hub_free(hubinfo.version);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADC_CMD_BSCH:
|
||||||
|
case ADC_CMD_FSCH:
|
||||||
|
{
|
||||||
|
client->callback(client, ADC_CLIENT_SEARCH_REQ, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADC_CMD_BINF:
|
||||||
|
{
|
||||||
|
if (msg->source == client->sid)
|
||||||
|
{
|
||||||
|
if (client->state == ps_verify || client->state == ps_identify)
|
||||||
|
{
|
||||||
|
ADC_client_on_login(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (adc_msg_has_named_argument(msg, "ID"))
|
||||||
|
{
|
||||||
|
struct ADC_user user;
|
||||||
|
EXTRACT_NAMED_ARG(msg, "NI", user.name);
|
||||||
|
EXTRACT_NAMED_ARG(msg, "DE", user.description);
|
||||||
|
EXTRACT_NAMED_ARG(msg, "VE", user.version);
|
||||||
|
EXTRACT_NAMED_ARG(msg, "ID", user.cid);
|
||||||
|
EXTRACT_NAMED_ARG(msg, "I4", user.address);
|
||||||
|
|
||||||
|
struct ADC_client_callback_data data;
|
||||||
|
data.user = &user;
|
||||||
|
client->callback(client, ADC_CLIENT_USER_JOIN, &data);
|
||||||
|
|
||||||
|
hub_free(user.name);
|
||||||
|
hub_free(user.description);
|
||||||
|
hub_free(user.version);
|
||||||
|
hub_free(user.cid);
|
||||||
|
hub_free(user.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case ADC_CMD_ISTA:
|
||||||
|
/*
|
||||||
|
if (strncmp(line, "ISTA 000", 8))
|
||||||
|
{
|
||||||
|
ADC_client_debug(client, "status: '%s'\n", (start + 9));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_msg_free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ADC_client_recv(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
ssize_t size = net_con_recv(client->con, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset);
|
||||||
|
if (size <= 0)
|
||||||
|
return size;
|
||||||
|
|
||||||
|
client->r_offset += size;
|
||||||
|
client->recvbuf[client->r_offset] = 0;
|
||||||
|
|
||||||
|
char* start = client->recvbuf;
|
||||||
|
char* pos;
|
||||||
|
char* lastPos = 0;
|
||||||
|
size_t remaining = client->r_offset;
|
||||||
|
|
||||||
|
while ((pos = memchr(start, '\n', remaining)))
|
||||||
|
{
|
||||||
|
pos[0] = 0;
|
||||||
|
|
||||||
|
ADC_client_on_recv_line(client, start, pos - start);
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
remaining -= (pos - start);
|
||||||
|
start = pos;
|
||||||
|
lastPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastPos)
|
||||||
|
{
|
||||||
|
memmove(client->recvbuf, lastPos, remaining);
|
||||||
|
client->r_offset = remaining;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ADC_client_send(struct ADC_client* client, char* msg)
|
||||||
|
{
|
||||||
|
int ret = net_con_send(client->con, msg, strlen(msg));
|
||||||
|
|
||||||
|
#ifdef ADC_CLIENT_DEBUG_PROTO
|
||||||
|
char* dump = strdup(msg);
|
||||||
|
dump[strlen(msg) - 1] = 0;
|
||||||
|
ADC_client_debug(client, "- SEND: '%s'", dump);
|
||||||
|
free(dump);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret != strlen(msg))
|
||||||
|
{
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
if (net_error() != EWOULDBLOCK)
|
||||||
|
ADC_client_on_disconnected(client);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: Not all data sent! */
|
||||||
|
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_send_info(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
char binf[11];
|
||||||
|
snprintf(binf, 11, "BINF %s\n", sid_to_string(client->sid));
|
||||||
|
client->info = adc_msg_create(binf);
|
||||||
|
|
||||||
|
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick);
|
||||||
|
|
||||||
|
if (client->desc)
|
||||||
|
{
|
||||||
|
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION);
|
||||||
|
|
||||||
|
adc_cid_pid(client);
|
||||||
|
ADC_client_send(client, client->info->cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description)
|
||||||
|
{
|
||||||
|
memset(client, 0, sizeof(struct ADC_client));
|
||||||
|
|
||||||
|
int sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (sd == -1) return -1;
|
||||||
|
|
||||||
|
client->con = net_con_create();
|
||||||
|
#if 0
|
||||||
|
/* FIXME */
|
||||||
|
client->timer = 0; /* FIXME: hub_malloc(sizeof(struct net_timer)); */
|
||||||
|
#endif
|
||||||
|
net_con_initialize(client->con, sd, event_callback, client, 0);
|
||||||
|
#if 0
|
||||||
|
/* FIXME */
|
||||||
|
net_timer_initialize(client->timer, timer_callback, client);
|
||||||
|
#endif
|
||||||
|
ADC_client_set_state(client, ps_none);
|
||||||
|
|
||||||
|
client->nick = hub_strdup(nickname);
|
||||||
|
client->desc = hub_strdup(description);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_destroy(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
ADC_client_disconnect(client);
|
||||||
|
#if 0
|
||||||
|
/* FIXME */
|
||||||
|
net_timer_shutdown(client->timer);
|
||||||
|
#endif
|
||||||
|
hub_free(client->timer);
|
||||||
|
adc_msg_free(client->info);
|
||||||
|
hub_free(client->nick);
|
||||||
|
hub_free(client->desc);
|
||||||
|
hub_free(client->hub_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ADC_client_connect(struct ADC_client* client, const char* address)
|
||||||
|
{
|
||||||
|
if (!client->hub_address)
|
||||||
|
{
|
||||||
|
if (!ADC_client_parse_address(client, address))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
client->callback(client, ADC_CLIENT_CONNECTING, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
|
||||||
|
if (ret == 0 || (ret == -1 && net_error() == EISCONN))
|
||||||
|
{
|
||||||
|
ADC_client_on_connected(client);
|
||||||
|
}
|
||||||
|
else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR))
|
||||||
|
{
|
||||||
|
if (client->state != ps_conn)
|
||||||
|
{
|
||||||
|
net_con_update(client->con, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||||
|
ADC_client_set_state(client, ps_conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ADC_client_on_disconnected(client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ADC_client_on_connected(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ADC_client_on_disconnected(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
net_con_close(client->con);
|
||||||
|
client->con = 0;
|
||||||
|
ADC_client_set_state(client, ps_none);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ADC_client_on_login(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
ADC_client_set_state(client, ps_normal);
|
||||||
|
client->callback(client, ADC_CLIENT_LOGGED_IN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_disconnect(struct ADC_client* client)
|
||||||
|
{
|
||||||
|
if (client->con && net_con_get_sd(client->con) != -1)
|
||||||
|
{
|
||||||
|
net_con_close(client->con);
|
||||||
|
client->con = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
|
||||||
|
{
|
||||||
|
char* split;
|
||||||
|
int ssl = 0;
|
||||||
|
struct hostent* dns;
|
||||||
|
struct in_addr* addr;
|
||||||
|
|
||||||
|
if (!arg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
client->hub_address = hub_strdup(arg);
|
||||||
|
|
||||||
|
/* Minimum length of a valid address */
|
||||||
|
if (strlen(arg) < 9)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check for ADC or ADCS */
|
||||||
|
if (!strncmp(arg, "adc://", 6))
|
||||||
|
ssl = 0;
|
||||||
|
else if (!strncmp(arg, "adcs://", 7))
|
||||||
|
ssl = 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Split hostname and port (if possible) */
|
||||||
|
split = strrchr(client->hub_address + 6 + ssl, ':');
|
||||||
|
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Ensure port number is valid */
|
||||||
|
int port = strtol(split+1, NULL, 10);
|
||||||
|
if (port <= 0 || port > 65535)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
split[0] = 0;
|
||||||
|
|
||||||
|
/* Resolve IP address (FIXME: blocking call) */
|
||||||
|
dns = gethostbyname(client->hub_address + 6 + ssl);
|
||||||
|
if (dns)
|
||||||
|
{
|
||||||
|
addr = (struct in_addr*) dns->h_addr_list[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the sockaddr struct.
|
||||||
|
memset(&client->addr, 0, sizeof(client->addr));
|
||||||
|
client->addr.sin_family = AF_INET;
|
||||||
|
client->addr.sin_port = htons(port);
|
||||||
|
memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb cb)
|
||||||
|
{
|
||||||
|
client->callback = cb;
|
||||||
|
}
|
||||||
129
src/tools/adcclient.h
Normal file
129
src/tools/adcclient.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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_ADC_CLIENT_H
|
||||||
|
#define HAVE_UHUB_ADC_CLIENT_H
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#define ADC_BUFSIZE 16384
|
||||||
|
|
||||||
|
enum ADC_client_state
|
||||||
|
{
|
||||||
|
ps_none = 0x00, /* Not connected */
|
||||||
|
ps_conn = 0x01, /* Connecting... */
|
||||||
|
ps_protocol = 0x02, /* Have sent HSUP */
|
||||||
|
ps_identify = 0x04, /* Have sent BINF */
|
||||||
|
ps_verify = 0x08, /* Have sent HPAS */
|
||||||
|
ps_normal = 0x10, /* Are fully logged in */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ADC_client;
|
||||||
|
|
||||||
|
enum ADC_client_callback_type
|
||||||
|
{
|
||||||
|
ADC_CLIENT_CONNECTING = 1001,
|
||||||
|
ADC_CLIENT_CONNECTED = 1002,
|
||||||
|
ADC_CLIENT_DISCONNECTED = 1003,
|
||||||
|
|
||||||
|
ADC_CLIENT_LOGGING_IN = 2001,
|
||||||
|
ADC_CLIENT_PASSWORD_REQ = 2002,
|
||||||
|
ADC_CLIENT_LOGGED_IN = 2003,
|
||||||
|
ADC_CLIENT_LOGIN_ERROR = 2004,
|
||||||
|
|
||||||
|
ADC_CLIENT_PROTOCOL_STATUS = 3001,
|
||||||
|
ADC_CLIENT_MESSAGE = 3002,
|
||||||
|
ADC_CLIENT_CONNECT_REQ = 3003,
|
||||||
|
ADC_CLIENT_REVCONNECT_REQ = 3004,
|
||||||
|
ADC_CLIENT_SEARCH_REQ = 3005,
|
||||||
|
ADC_CLIENT_SEARCH_REP = 3006,
|
||||||
|
|
||||||
|
ADC_CLIENT_USER_JOIN = 4001,
|
||||||
|
ADC_CLIENT_USER_QUIT = 4002,
|
||||||
|
ADC_CLIENT_USER_UPDATE = 4003,
|
||||||
|
|
||||||
|
ADC_CLIENT_HUB_INFO = 5001,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ADC_hub_info
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
char* description;
|
||||||
|
char* version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ADC_chat_message
|
||||||
|
{
|
||||||
|
sid_t from_sid;
|
||||||
|
sid_t to_sid;
|
||||||
|
char* message;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ADC_user
|
||||||
|
{
|
||||||
|
sid_t sid;
|
||||||
|
char* cid;
|
||||||
|
char* name;
|
||||||
|
char* description;
|
||||||
|
char* address;
|
||||||
|
char* version;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ADC_client_callback_data
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct ADC_hub_info* hubinfo;
|
||||||
|
struct ADC_chat_message* chat;
|
||||||
|
struct ADC_user* user;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*adc_client_cb)(struct ADC_client*, enum ADC_client_callback_type, struct ADC_client_callback_data* data);
|
||||||
|
|
||||||
|
struct ADC_client
|
||||||
|
{
|
||||||
|
sid_t sid;
|
||||||
|
enum ADC_client_state state;
|
||||||
|
struct adc_message* info;
|
||||||
|
char recvbuf[ADC_BUFSIZE];
|
||||||
|
char sendbuf[ADC_BUFSIZE];
|
||||||
|
adc_client_cb callback;
|
||||||
|
size_t s_offset;
|
||||||
|
size_t r_offset;
|
||||||
|
size_t timeout;
|
||||||
|
struct net_connection* con;
|
||||||
|
struct net_timer* timer;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
char* hub_address;
|
||||||
|
char* nick;
|
||||||
|
char* desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ADC_client_create(struct ADC_client* client, const char* nickname, const char* description);
|
||||||
|
void ADC_client_set_callback(struct ADC_client* client, adc_client_cb);
|
||||||
|
void ADC_client_destroy(struct ADC_client* client);
|
||||||
|
int ADC_client_connect(struct ADC_client* client, const char* address);
|
||||||
|
void ADC_client_disconnect(struct ADC_client* client);
|
||||||
|
void ADC_client_send(struct ADC_client* client, char* msg);
|
||||||
|
|
||||||
|
#endif /* HAVE_UHUB_ADC_CLIENT_H */
|
||||||
|
|
||||||
|
|
||||||
@@ -2,105 +2,28 @@
|
|||||||
* An ADC client emulator.
|
* An ADC client emulator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "adcclient.h"
|
||||||
|
|
||||||
#define ADC_CLIENTS_DEFAULT 100
|
#define ADC_CLIENTS_DEFAULT 100
|
||||||
#define ADC_MAX_CLIENTS 25000
|
#define ADC_MAX_CLIENTS 25000
|
||||||
|
|
||||||
#define ADC_BUFSIZE 16384
|
|
||||||
#define ADC_SIDSIZE 4
|
|
||||||
#define ADC_CID_SIZE 39
|
#define ADC_CID_SIZE 39
|
||||||
|
#define BIG_BUFSIZE 32768
|
||||||
#define BIG_BUFSIZE 131072
|
|
||||||
#define TIGERSIZE 24
|
#define TIGERSIZE 24
|
||||||
|
#define ADCRUSH "adcrush/0.3"
|
||||||
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR\n"
|
|
||||||
#define ADCRUSH "adcrush/0.2"
|
|
||||||
#define ADC_NICK "[BOT]adcrush"
|
#define ADC_NICK "[BOT]adcrush"
|
||||||
#define ADC_DESC "crash\\stest\\sdummy"
|
#define ADC_DESC "crash\\stest\\sdummy"
|
||||||
|
|
||||||
struct ADC_client;
|
#define LVL_INFO 1
|
||||||
|
#define LVL_DEBUG 2
|
||||||
|
#define LVL_VERBOSE 3
|
||||||
|
|
||||||
static void ADC_client_on_disconnected(struct ADC_client*);
|
static const char* cfg_uri = 0; /* address */
|
||||||
static void ADC_client_on_connected(struct ADC_client*);
|
static int cfg_debug = 0; /* debug level */
|
||||||
static void ADC_client_on_login(struct ADC_client*);
|
static int cfg_level = 1; /* activity level (0..3) */
|
||||||
static void ADC_client_connect(struct ADC_client*);
|
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
|
||||||
static void ADC_client_disconnect(struct ADC_client*);
|
static int cfg_quiet = 0; /* quiet mode (no output) */
|
||||||
static int ADC_client_create(struct ADC_client* client, int num);
|
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
|
||||||
static void ADC_client_destroy(struct ADC_client* client);
|
static int running = 1;
|
||||||
|
|
||||||
static int cfg_mode = 0; // See enum operationMode
|
|
||||||
static char* cfg_host = 0;
|
|
||||||
static int cfg_port = 0;
|
|
||||||
static int cfg_debug = 0; /* debug level */
|
|
||||||
static int cfg_level = 1; /* activity level (0..3) */
|
|
||||||
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
|
|
||||||
static int cfg_quiet = 0; /* quiet mode (no output) */
|
|
||||||
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
|
|
||||||
|
|
||||||
static int running = 1;
|
|
||||||
|
|
||||||
static struct sockaddr_in saddr;
|
|
||||||
|
|
||||||
enum commandMode
|
|
||||||
{
|
|
||||||
cm_bcast = 0x01, /* B - broadcast */
|
|
||||||
cm_dir = 0x02, /* D - direct message */
|
|
||||||
cm_echo = 0x04, /* E - echo message */
|
|
||||||
cm_fcast = 0x08, /* F - feature cast message */
|
|
||||||
cm_c2h = 0x10, /* H - client to hub message */
|
|
||||||
cm_h2c = 0x20, /* I - hub to client message */
|
|
||||||
cm_c2c = 0x40, /* C - client to client message */
|
|
||||||
cm_udp = 0x80, /* U - udp message (client to client) */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum commandValidity
|
|
||||||
{
|
|
||||||
cv_protocol = 0x01,
|
|
||||||
cv_identify = 0x02,
|
|
||||||
cv_verify = 0x04,
|
|
||||||
cv_normal = 0x08,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum protocolState
|
|
||||||
{
|
|
||||||
ps_none = 0x00, /* none or disconnected */
|
|
||||||
ps_conn = 0x01, /* connecting... */
|
|
||||||
ps_protocol = 0x02,
|
|
||||||
ps_identify = 0x04,
|
|
||||||
ps_verify = 0x08,
|
|
||||||
ps_normal = 0x10,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum operationMode
|
|
||||||
{
|
|
||||||
mode_performance = 0x01,
|
|
||||||
mode_bugs = 0x02,
|
|
||||||
mode_security = 0x04,
|
|
||||||
mode_log = 0x08,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct commandPattern
|
|
||||||
{
|
|
||||||
unsigned char mode; /* see enum commandMode */
|
|
||||||
char cmd[3];
|
|
||||||
unsigned char validity; /* see enum commandValidity */
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct commandPattern patterns[] =
|
|
||||||
{
|
|
||||||
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
|
|
||||||
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
|
|
||||||
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
|
|
||||||
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
|
|
||||||
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
|
|
||||||
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
|
|
||||||
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
|
|
||||||
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
|
|
||||||
{ cm_h2c, "QUI", cv_normal }, /* quit message */
|
|
||||||
{ cm_h2c, "GPA", cv_identify }, /* password request */
|
|
||||||
{ cm_c2h, "PAS", cv_verify } /* password response */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_CHAT_MSGS 35
|
#define MAX_CHAT_MSGS 35
|
||||||
const char* chat_messages[MAX_CHAT_MSGS] = {
|
const char* chat_messages[MAX_CHAT_MSGS] = {
|
||||||
@@ -155,69 +78,21 @@ const char* search_messages[MAX_SEARCH_MSGS] = {
|
|||||||
"ANburnout ANps3 TOauto",
|
"ANburnout ANps3 TOauto",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ADC_client
|
|
||||||
{
|
|
||||||
int sd;
|
|
||||||
int num;
|
|
||||||
sid_t sid;
|
|
||||||
enum protocolState state;
|
|
||||||
char info[ADC_BUFSIZE];
|
|
||||||
char recvbuf[BIG_BUFSIZE];
|
|
||||||
char sendbuf[BIG_BUFSIZE];
|
|
||||||
size_t s_offset;
|
|
||||||
size_t r_offset;
|
|
||||||
struct event ev_read;
|
|
||||||
struct event ev_write;
|
|
||||||
struct event ev_timer;
|
|
||||||
size_t timeout;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
static void bot_output(struct ADC_client* client, int level, const char* format, ...)
|
||||||
static void bot_output(struct ADC_client* client, const char* format, ...)
|
|
||||||
{
|
{
|
||||||
char logmsg[1024];
|
char logmsg[1024];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vsnprintf(logmsg, 1024, format, args);
|
vsnprintf(logmsg, 1024, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (cfg_mode == mode_log)
|
|
||||||
{
|
if (cfg_debug >= level)
|
||||||
fprintf(stdout, "%s\n", logmsg);
|
fprintf(stdout, "* [%p] %s\n", client, logmsg);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cfg_debug)
|
|
||||||
fprintf(stdout, "* [%4d] %s\n", client->num, logmsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adc_cid_pid(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
char seed[64];
|
|
||||||
char pid[64];
|
|
||||||
char cid[64];
|
|
||||||
uint64_t tiger_res1[3];
|
|
||||||
uint64_t tiger_res2[3];
|
|
||||||
|
|
||||||
/* create cid+pid pair */
|
|
||||||
memset(seed, 0, 64);
|
|
||||||
snprintf(seed, 64, ADCRUSH "%p/%d", client, (int) client->num);
|
|
||||||
|
|
||||||
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
|
|
||||||
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
|
|
||||||
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
|
|
||||||
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
|
|
||||||
|
|
||||||
cid[ADC_CID_SIZE] = 0;
|
|
||||||
pid[ADC_CID_SIZE] = 0;
|
|
||||||
|
|
||||||
strcat(client->info, " PD");
|
|
||||||
strcat(client->info, pid);
|
|
||||||
strcat(client->info, " ID");
|
|
||||||
strcat(client->info, cid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static size_t get_wait_rand(size_t max)
|
static size_t get_wait_rand(size_t max)
|
||||||
{
|
{
|
||||||
static size_t next = 0;
|
static size_t next = 0;
|
||||||
@@ -226,315 +101,9 @@ static size_t get_wait_rand(size_t max)
|
|||||||
return ((size_t )(next / 65536) % max);
|
return ((size_t )(next / 65536) % max);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void client_reschedule_timeout(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
size_t next_timeout = 0;
|
|
||||||
struct timeval timeout = { 0, 0 };
|
|
||||||
|
|
||||||
switch (client->state)
|
|
||||||
{
|
|
||||||
case ps_conn: next_timeout = 30; break;
|
|
||||||
case ps_protocol: next_timeout = 30; break;
|
|
||||||
case ps_identify: next_timeout = 30; break;
|
|
||||||
case ps_verify: next_timeout = 30; break;
|
|
||||||
case ps_normal: next_timeout = 120; break;
|
|
||||||
case ps_none: next_timeout = 120; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client->state == ps_normal || client->state == ps_none)
|
|
||||||
{
|
|
||||||
switch (cfg_level)
|
|
||||||
{
|
|
||||||
case 0: /* polite */
|
|
||||||
next_timeout *= 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: /* normal */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: /* aggressive */
|
|
||||||
next_timeout /= 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: /* excessive */
|
|
||||||
next_timeout /= 16;
|
|
||||||
|
|
||||||
case 4: /* excessive */
|
|
||||||
next_timeout /= 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (client->state == ps_conn)
|
|
||||||
client->timeout = MAX(next_timeout, 1);
|
|
||||||
else
|
|
||||||
client->timeout = get_wait_rand(MAX(next_timeout, 1));
|
|
||||||
|
|
||||||
if (!client->timeout) client->timeout++;
|
|
||||||
|
|
||||||
timeout.tv_sec = (time_t) client->timeout;
|
|
||||||
evtimer_add(&client->ev_timer, &timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_state_timeout(struct ADC_client* client, enum protocolState state)
|
|
||||||
{
|
|
||||||
client->state = state;
|
|
||||||
client_reschedule_timeout(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_client(struct ADC_client* client, char* msg)
|
|
||||||
{
|
|
||||||
int ret = net_send(client->sd, msg, strlen(msg), UHUB_SEND_SIGNAL);
|
|
||||||
|
|
||||||
if (cfg_debug > 1)
|
|
||||||
{
|
|
||||||
char* dump = strdup(msg);
|
|
||||||
dump[strlen(msg) - 1] = 0;
|
|
||||||
bot_output(client, "- SEND: '%s'", dump);
|
|
||||||
free(dump);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != strlen(msg))
|
|
||||||
{
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
if (net_error() != EWOULDBLOCK)
|
|
||||||
ADC_client_on_disconnected(client);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: Not all data sent! */
|
|
||||||
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void ADC_client_on_connected(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
send_client(client, ADC_HANDSHAKE);
|
|
||||||
set_state_timeout(client, ps_protocol);
|
|
||||||
bot_output(client, "connected.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ADC_client_on_disconnected(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
event_del(&client->ev_read);
|
|
||||||
event_del(&client->ev_write);
|
|
||||||
|
|
||||||
net_close(client->sd);
|
|
||||||
client->sd = -1;
|
|
||||||
|
|
||||||
bot_output(client, "disconnected.");
|
|
||||||
set_state_timeout(client, ps_none);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ADC_client_on_login(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
bot_output(client, "logged in.");
|
|
||||||
set_state_timeout(client, ps_normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void send_client_info(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
client->info[0] = 0;
|
|
||||||
strcat(client->info, "BINF ");
|
|
||||||
strcat(client->info, sid_to_string(client->sid));
|
|
||||||
strcat(client->info, " NI" ADC_NICK);
|
|
||||||
if (cfg_clients > 1)
|
|
||||||
{
|
|
||||||
strcat(client->info, "_");
|
|
||||||
strcat(client->info, uhub_itoa(client->num));
|
|
||||||
}
|
|
||||||
strcat(client->info, " VE" ADCRUSH);
|
|
||||||
strcat(client->info, " DE" ADC_DESC);
|
|
||||||
strcat(client->info, " I40.0.0.0");
|
|
||||||
strcat(client->info, " EMuhub@extatic.org");
|
|
||||||
strcat(client->info, " SL3");
|
|
||||||
strcat(client->info, " HN1");
|
|
||||||
strcat(client->info, " HR1");
|
|
||||||
strcat(client->info, " HO1");
|
|
||||||
|
|
||||||
adc_cid_pid(client);
|
|
||||||
|
|
||||||
strcat(client->info, "\n");
|
|
||||||
|
|
||||||
send_client(client, client->info);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
|
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
|
||||||
|
|
||||||
static int recv_client(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
ssize_t size = 0;
|
|
||||||
if (cfg_mode != mode_performance || (cfg_mode == mode_performance && (get_wait_rand(100) < (90 - (15 * cfg_level)))))
|
|
||||||
{
|
|
||||||
size = net_recv(client->sd, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (get_wait_rand(1000) == 99)
|
|
||||||
return -1; /* Can break tings badly! :-) */
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (size == 0 || ((size == -1 && net_error() != EWOULDBLOCK)))
|
|
||||||
return -1;
|
|
||||||
client->recvbuf[client->r_offset + size] = 0;
|
|
||||||
|
|
||||||
char* start = client->recvbuf;
|
|
||||||
char* pos;
|
|
||||||
char* lastPos = 0;
|
|
||||||
while ((pos = strchr(start, '\n')))
|
|
||||||
{
|
|
||||||
lastPos = pos;
|
|
||||||
pos[0] = 0;
|
|
||||||
|
|
||||||
if (cfg_debug > 1)
|
|
||||||
{
|
|
||||||
bot_output(client, "- RECV: '%s'", start);
|
|
||||||
}
|
|
||||||
|
|
||||||
fourcc_t cmd = 0;
|
|
||||||
if (strlen(start) < 4)
|
|
||||||
{
|
|
||||||
bot_output(client, "Unexpected response from hub: '%s'", start);
|
|
||||||
start = &pos[1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd = FOURCC(start[0], start[1], start[2], start[3]);
|
|
||||||
|
|
||||||
switch (cmd)
|
|
||||||
{
|
|
||||||
case ADC_CMD_ISUP:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ADC_CMD_ISID:
|
|
||||||
if (client->state == ps_protocol)
|
|
||||||
{
|
|
||||||
client->sid = string_to_sid(&start[5]);
|
|
||||||
client->state = ps_identify;
|
|
||||||
send_client_info(client);
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ADC_CMD_IINF:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ADC_CMD_BSCH:
|
|
||||||
case ADC_CMD_FSCH:
|
|
||||||
{
|
|
||||||
if (get_wait_rand(100) > (90 - (10 * cfg_level)) && cfg_mode == mode_performance)
|
|
||||||
{
|
|
||||||
sid_t target = string_to_sid(&start[5]);
|
|
||||||
const char* what = strstr(&start[5], " AN");
|
|
||||||
const char* token = strstr(&start[5], " TO");
|
|
||||||
char* split = 0;
|
|
||||||
if (!token || !what) break;
|
|
||||||
|
|
||||||
token += 3;
|
|
||||||
what += 3;
|
|
||||||
|
|
||||||
split = strchr(what, ' ');
|
|
||||||
if (!split) break;
|
|
||||||
else split[0] = '0';
|
|
||||||
|
|
||||||
split = strchr(token, ' ');
|
|
||||||
if (split) split[0] = '0';
|
|
||||||
|
|
||||||
perf_result(client, target, what, token);
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ADC_CMD_BINF:
|
|
||||||
{
|
|
||||||
if (strlen(start) > 9)
|
|
||||||
{
|
|
||||||
char t = start[9]; start[9] = 0; sid_t sid = string_to_sid(&start[5]); start[9] = t;
|
|
||||||
|
|
||||||
if (sid == client->sid)
|
|
||||||
{
|
|
||||||
if (client->state == ps_verify || client->state == ps_identify)
|
|
||||||
{
|
|
||||||
ADC_client_on_login(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ADC_CMD_ISTA:
|
|
||||||
if (strncmp(start, "ISTA 000", 8))
|
|
||||||
{
|
|
||||||
bot_output(client, "status: '%s'\n", (start + 9));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = &pos[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastPos)
|
|
||||||
{
|
|
||||||
client->r_offset = strlen(lastPos);
|
|
||||||
memmove(client->recvbuf, lastPos, strlen(lastPos));
|
|
||||||
memset(&client->recvbuf[client->r_offset], 0, ADC_BUFSIZE-client->r_offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// client->r_offset = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADC_client_connect(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
struct timeval timeout = { TIMEOUT_IDLE, 0 };
|
|
||||||
net_connect(client->sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in));
|
|
||||||
set_state_timeout(client, ps_conn);
|
|
||||||
event_add(&client->ev_read, &timeout);
|
|
||||||
event_add(&client->ev_write, &timeout);
|
|
||||||
bot_output(client, "connecting...");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADC_client_wait_connect(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
set_state_timeout(client, ps_none);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ADC_client_disconnect(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
if (client->sd != -1)
|
|
||||||
{
|
|
||||||
net_close(client->sd);
|
|
||||||
client->sd = -1;
|
|
||||||
event_del(&client->ev_read);
|
|
||||||
event_del(&client->ev_write);
|
|
||||||
bot_output(client, "disconnected.");
|
|
||||||
|
|
||||||
if (running)
|
|
||||||
{
|
|
||||||
ADC_client_destroy(client);
|
|
||||||
ADC_client_create(client, client->num);
|
|
||||||
ADC_client_connect(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void perf_chat(struct ADC_client* client, int priv)
|
static void perf_chat(struct ADC_client* client, int priv)
|
||||||
{
|
{
|
||||||
char buf[1024] = { 0, };
|
char buf[1024] = { 0, };
|
||||||
@@ -559,7 +128,7 @@ static void perf_chat(struct ADC_client* client, int priv)
|
|||||||
hub_free(msg);
|
hub_free(msg);
|
||||||
|
|
||||||
strcat(buf, "\n");
|
strcat(buf, "\n");
|
||||||
send_client(client, buf);
|
ADC_client_send(client, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perf_search(struct ADC_client* client)
|
static void perf_search(struct ADC_client* client)
|
||||||
@@ -582,7 +151,7 @@ static void perf_search(struct ADC_client* client)
|
|||||||
}
|
}
|
||||||
strcat(buf, search_messages[r]);
|
strcat(buf, search_messages[r]);
|
||||||
strcat(buf, "\n");
|
strcat(buf, "\n");
|
||||||
send_client(client, buf);
|
ADC_client_send(client, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
|
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
|
||||||
@@ -601,7 +170,7 @@ static void perf_result(struct ADC_client* client, sid_t target, const char* wha
|
|||||||
strcat(buf, " TO");
|
strcat(buf, " TO");
|
||||||
strcat(buf, token);
|
strcat(buf, token);
|
||||||
strcat(buf, "\n");
|
strcat(buf, "\n");
|
||||||
send_client(client, buf);
|
ADC_client_send(client, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perf_ctm(struct ADC_client* client)
|
static void perf_ctm(struct ADC_client* client)
|
||||||
@@ -616,7 +185,7 @@ static void perf_ctm(struct ADC_client* client)
|
|||||||
strcat(buf, " TOKEN111");
|
strcat(buf, " TOKEN111");
|
||||||
strcat(buf, sid_to_string(client->sid));
|
strcat(buf, sid_to_string(client->sid));
|
||||||
strcat(buf, "\n");
|
strcat(buf, "\n");
|
||||||
send_client(client, buf);
|
ADC_client_send(client, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -631,10 +200,9 @@ static void perf_update(struct ADC_client* client)
|
|||||||
strcat(buf, uhub_itoa(n));
|
strcat(buf, uhub_itoa(n));
|
||||||
|
|
||||||
strcat(buf, "\n");
|
strcat(buf, "\n");
|
||||||
send_client(client, buf);
|
ADC_client_send(client, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void perf_normal_action(struct ADC_client* client)
|
static void perf_normal_action(struct ADC_client* client)
|
||||||
{
|
{
|
||||||
size_t r = get_wait_rand(5);
|
size_t r = get_wait_rand(5);
|
||||||
@@ -645,7 +213,7 @@ static void perf_normal_action(struct ADC_client* client)
|
|||||||
case 0:
|
case 0:
|
||||||
if (p > (90 - (10 * cfg_level)))
|
if (p > (90 - (10 * cfg_level)))
|
||||||
{
|
{
|
||||||
if (cfg_debug > 1) bot_output(client, "timeout -> disconnect");
|
bot_output(client, LVL_VERBOSE, "timeout -> disconnect");
|
||||||
ADC_client_disconnect(client);
|
ADC_client_disconnect(client);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -653,114 +221,95 @@ static void perf_normal_action(struct ADC_client* client)
|
|||||||
case 1:
|
case 1:
|
||||||
if (cfg_chat)
|
if (cfg_chat)
|
||||||
{
|
{
|
||||||
if (cfg_debug > 1) bot_output(client, "timeout -> chat");
|
bot_output(client, LVL_VERBOSE, "timeout -> chat");
|
||||||
perf_chat(client, 0);
|
perf_chat(client, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
if (cfg_debug > 1) bot_output(client, "timeout -> search");
|
bot_output(client, LVL_VERBOSE, "timeout -> search");
|
||||||
perf_search(client);
|
perf_search(client);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
if (cfg_debug > 1) bot_output(client, "timeout -> update");
|
bot_output(client, LVL_VERBOSE, "timeout -> update");
|
||||||
perf_update(client);
|
perf_update(client);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
if (cfg_debug > 1) bot_output(client, "timeout -> privmsg");
|
bot_output(client, LVL_VERBOSE, "timeout -> privmsg");
|
||||||
perf_chat(client, 1);
|
perf_chat(client, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
if (cfg_debug > 1) bot_output(client, "timeout -> ctm/rcm");
|
bot_output(client, LVL_VERBOSE, "timeout -> ctm/rcm");
|
||||||
perf_ctm(client);
|
perf_ctm(client);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client_reschedule_timeout(client);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void event_callback(int fd, short ev, void *arg)
|
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data)
|
||||||
{
|
{
|
||||||
struct ADC_client* client = (struct ADC_client*) arg;
|
switch (type)
|
||||||
|
|
||||||
if (ev & EV_READ)
|
|
||||||
{
|
{
|
||||||
if (recv_client(client) == -1)
|
case ADC_CLIENT_CONNECTING:
|
||||||
{
|
bot_output(client, LVL_DEBUG, "*** Connecting...");
|
||||||
ADC_client_on_disconnected(client);
|
break;
|
||||||
}
|
|
||||||
}
|
case ADC_CLIENT_CONNECTED:
|
||||||
|
bot_output(client, LVL_DEBUG, "*** Connected.");
|
||||||
if (ev & EV_TIMEOUT)
|
break;
|
||||||
{
|
|
||||||
if (client->state == ps_none)
|
case ADC_CLIENT_DISCONNECTED:
|
||||||
{
|
bot_output(client, LVL_DEBUG, "*** Disconnected.");
|
||||||
if (client->sd == -1)
|
break;
|
||||||
{
|
|
||||||
ADC_client_create(client, client->num);
|
case ADC_CLIENT_LOGGING_IN:
|
||||||
}
|
bot_output(client, LVL_DEBUG, "*** Logging in...");
|
||||||
|
break;
|
||||||
ADC_client_connect(client);
|
|
||||||
}
|
case ADC_CLIENT_PASSWORD_REQ:
|
||||||
|
bot_output(client, LVL_DEBUG, "*** Requesting password.");
|
||||||
if (fd == -1)
|
|
||||||
{
|
case ADC_CLIENT_LOGGED_IN:
|
||||||
if (client->state == ps_normal && cfg_mode == mode_performance)
|
bot_output(client, LVL_DEBUG, "*** Logged in.");
|
||||||
{
|
break;
|
||||||
perf_normal_action(client);
|
|
||||||
}
|
case ADC_CLIENT_LOGIN_ERROR:
|
||||||
}
|
bot_output(client, LVL_DEBUG, "*** Login error");
|
||||||
}
|
break;
|
||||||
|
|
||||||
if (ev & EV_WRITE)
|
case ADC_CLIENT_MESSAGE:
|
||||||
{
|
bot_output(client, LVL_DEBUG, " <%s> %s", sid_to_string(data->chat->from_sid), data->chat->message);
|
||||||
if (client->state == ps_conn)
|
break;
|
||||||
{
|
|
||||||
ADC_client_on_connected(client);
|
case ADC_CLIENT_USER_JOIN:
|
||||||
}
|
bot_output(client, LVL_VERBOSE, " JOIN: %s", data->user->name);
|
||||||
else
|
break;
|
||||||
{
|
|
||||||
/* FIXME: Call send again */
|
case ADC_CLIENT_USER_QUIT:
|
||||||
}
|
bot_output(client, LVL_VERBOSE, " QUIT");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_SEARCH_REQ:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_HUB_INFO:
|
||||||
|
bot_output(client, LVL_DEBUG, " Hub: \"%s\" [%s]\n"
|
||||||
|
" \"%s\"\n", data->hubinfo->name, data->hubinfo->version, data->hubinfo->description);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
bot_output(client, LVL_DEBUG, "Not handled event=%d\n", (int) type);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ADC_client_create(struct ADC_client* client, int num)
|
|
||||||
{
|
|
||||||
struct timeval timeout = { 0, 0 };
|
|
||||||
|
|
||||||
memset(client, 0, sizeof(struct ADC_client));
|
|
||||||
client->num = num;
|
|
||||||
|
|
||||||
client->sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (client->sd == -1) return -1;
|
|
||||||
|
|
||||||
event_set(&client->ev_write, client->sd, EV_WRITE, event_callback, client);
|
|
||||||
event_set(&client->ev_read, client->sd, EV_READ | EV_PERSIST, event_callback, client);
|
|
||||||
|
|
||||||
net_set_nonblocking(client->sd, 1);
|
|
||||||
|
|
||||||
timeout.tv_sec = client->timeout;
|
|
||||||
evtimer_set(&client->ev_timer, event_callback, client);
|
|
||||||
|
|
||||||
set_state_timeout(client, ps_none);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ADC_client_destroy(struct ADC_client* client)
|
|
||||||
{
|
|
||||||
ADC_client_disconnect(client);
|
|
||||||
evtimer_del(&client->ev_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void runloop(size_t clients)
|
void runloop(size_t clients)
|
||||||
{
|
{
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
@@ -771,23 +320,24 @@ void runloop(size_t clients)
|
|||||||
struct ADC_client* c = malloc(sizeof(struct ADC_client));
|
struct ADC_client* c = malloc(sizeof(struct ADC_client));
|
||||||
client[n] = c;
|
client[n] = c;
|
||||||
|
|
||||||
ADC_client_create(c, n);
|
char nick[20];
|
||||||
if (n == 0)
|
snprintf(nick, 20, "adcrush_%d", (int) n);
|
||||||
{
|
|
||||||
ADC_client_connect(c);
|
ADC_client_create(c, nick, "stresstester");
|
||||||
}
|
ADC_client_set_callback(c, handle);
|
||||||
else
|
ADC_client_connect(c, cfg_uri);
|
||||||
{
|
|
||||||
ADC_client_wait_connect(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event_dispatch();
|
while (running)
|
||||||
|
{
|
||||||
|
net_backend_process();
|
||||||
|
}
|
||||||
|
|
||||||
for (n = 0; n < clients; n++)
|
for (n = 0; n < clients; n++)
|
||||||
{
|
{
|
||||||
ADC_client_destroy(client[n]);
|
ADC_client_destroy(client[n]);
|
||||||
free(client[n]);
|
free(client[n]);
|
||||||
|
client[n] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,102 +352,29 @@ static void print_usage(const char* program)
|
|||||||
{
|
{
|
||||||
print_version();
|
print_version();
|
||||||
|
|
||||||
printf("Usage: %s <mode> (adc://<host>:<port>) [options]\n", program);
|
printf("Usage: %s [adc[s]://<host>:<port>] [options]\n", program);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" Modes\n");
|
printf(" OPTIONS\n");
|
||||||
printf(" perf Do performance testing using multiple clients\n");
|
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
|
||||||
printf(" bugs Bugs mode, use fuzzer to construct pseudo-random commands.\n");
|
printf(" -n <num> Number of concurrent connections\n");
|
||||||
printf(" security Perform security tests for the hub.\n");
|
|
||||||
printf(" log Connect one client to the hub and log the output hub.\n");
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
printf(" General options\n");
|
|
||||||
printf(" -c Allow broadcasting chat messages.\n");
|
printf(" -c Allow broadcasting chat messages.\n");
|
||||||
printf(" -d Enable debug output.\n");
|
printf(" -d Enable debug output.\n");
|
||||||
printf(" -q Quiet mode (no output).\n");
|
printf(" -q Quiet mode (no output).\n");
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
printf(" Performance options:\n");
|
|
||||||
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
|
|
||||||
printf(" -n <num> Number of concurrent connections\n");
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int set_defaults()
|
|
||||||
{
|
|
||||||
switch (cfg_mode)
|
|
||||||
{
|
|
||||||
case mode_performance:
|
|
||||||
break;
|
|
||||||
case mode_bugs:
|
|
||||||
break;
|
|
||||||
case mode_security:
|
|
||||||
break;
|
|
||||||
case mode_log:
|
|
||||||
cfg_quiet = 0;
|
|
||||||
cfg_debug = 2;
|
|
||||||
cfg_clients = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_mode(const char* arg)
|
|
||||||
{
|
|
||||||
cfg_mode = 0;
|
|
||||||
|
|
||||||
if (!strcmp(arg, "perf"))
|
|
||||||
cfg_mode = mode_performance;
|
|
||||||
else if (!strcmp(arg, "bugs"))
|
|
||||||
cfg_mode = mode_bugs;
|
|
||||||
else if (!strcmp(arg, "security"))
|
|
||||||
cfg_mode = mode_security;
|
|
||||||
else if (!strcmp(arg, "log"))
|
|
||||||
cfg_mode = mode_log;
|
|
||||||
|
|
||||||
return cfg_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_address(const char* arg)
|
int parse_address(const char* arg)
|
||||||
{
|
{
|
||||||
char* split;
|
if (!arg || strlen(arg) < 9)
|
||||||
struct hostent* dns;
|
|
||||||
struct in_addr* addr;
|
|
||||||
|
|
||||||
if (!arg)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strlen(arg) < 9)
|
if (strncmp(arg, "adc://", 6) && strncmp(arg, "adcs://", 7))
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strncmp(arg, "adc://", 6))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
split = strrchr(arg+6, ':');
|
|
||||||
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cfg_port = strtol(split+1, NULL, 10);
|
|
||||||
if (cfg_port <= 0 || cfg_port > 65535)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
split[0] = 0;
|
|
||||||
|
|
||||||
dns = gethostbyname(arg+6);
|
|
||||||
if (dns)
|
|
||||||
{
|
|
||||||
addr = (struct in_addr*) dns->h_addr_list[0];
|
|
||||||
cfg_host = strdup(inet_ntoa(*addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cfg_host)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
cfg_uri = arg;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -905,7 +382,7 @@ int parse_arguments(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
int opt;
|
int opt;
|
||||||
for (opt = 3; opt < argc; opt++)
|
for (opt = 2; opt < argc; opt++)
|
||||||
{
|
{
|
||||||
if (!strcmp(argv[opt], "-c"))
|
if (!strcmp(argv[opt], "-c"))
|
||||||
cfg_chat = 1;
|
cfg_chat = 1;
|
||||||
@@ -929,9 +406,7 @@ int parse_arguments(int argc, char** argv)
|
|||||||
void parse_command_line(int argc, char** argv)
|
void parse_command_line(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc < 2 ||
|
if (argc < 2 ||
|
||||||
!parse_mode(argv[1]) ||
|
!parse_address(argv[1]) ||
|
||||||
!set_defaults() ||
|
|
||||||
!parse_address(argv[2]) ||
|
|
||||||
!parse_arguments(argc, argv))
|
!parse_arguments(argc, argv))
|
||||||
{
|
{
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
@@ -943,16 +418,12 @@ int main(int argc, char** argv)
|
|||||||
parse_command_line(argc, argv);
|
parse_command_line(argc, argv);
|
||||||
|
|
||||||
net_initialize();
|
net_initialize();
|
||||||
event_init();
|
|
||||||
|
|
||||||
memset(&saddr, 0, sizeof(saddr));
|
hub_log_initialize(NULL, 0);
|
||||||
saddr.sin_family = AF_INET;
|
hub_set_log_verbosity(1000);
|
||||||
saddr.sin_port = htons(cfg_port);
|
|
||||||
net_string_to_address(AF_INET, cfg_host, &saddr.sin_addr);
|
|
||||||
|
|
||||||
runloop(cfg_clients);
|
runloop(cfg_clients);
|
||||||
net_destroy();
|
|
||||||
|
|
||||||
|
net_destroy();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
93
src/tools/admin.c
Normal file
93
src/tools/admin.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* A remote uhub admin client.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "adcclient.h"
|
||||||
|
|
||||||
|
static int handle(struct ADC_client* client, enum ADC_client_callback_type type, struct ADC_client_callback_data* data)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ADC_CLIENT_CONNECTING:
|
||||||
|
puts("*** Connecting...");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_CONNECTED:
|
||||||
|
puts("*** Connected.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_DISCONNECTED:
|
||||||
|
puts("*** Disconnected.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_LOGGING_IN:
|
||||||
|
puts("*** Logging in...");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_PASSWORD_REQ:
|
||||||
|
puts("*** Requesting password.");
|
||||||
|
|
||||||
|
case ADC_CLIENT_LOGGED_IN:
|
||||||
|
puts("*** Logged in.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_LOGIN_ERROR:
|
||||||
|
puts("*** Login error");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_MESSAGE:
|
||||||
|
printf(" <%s> %s\n", sid_to_string(data->chat->from_sid), data->chat->message);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_USER_JOIN:
|
||||||
|
printf(" JOIN: %s\n", data->user->name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_USER_QUIT:
|
||||||
|
printf(" QUIT\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_SEARCH_REQ:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADC_CLIENT_HUB_INFO:
|
||||||
|
printf(" Hub: \"%s\" [%s]\n"
|
||||||
|
" \"%s\"\n", data->hubinfo->name, data->hubinfo->version, data->hubinfo->description);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Not handled event=%d\n", (int) type);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int running = 1;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("Usage: %s adc[s]://host:port\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ADC_client client;
|
||||||
|
net_initialize();
|
||||||
|
|
||||||
|
ADC_client_create(&client, "uhub-admin", "stresstester");
|
||||||
|
ADC_client_set_callback(&client, handle);
|
||||||
|
ADC_client_connect(&client, argv[1]);
|
||||||
|
|
||||||
|
while (running)
|
||||||
|
{
|
||||||
|
net_backend_process();
|
||||||
|
}
|
||||||
|
|
||||||
|
ADC_client_destroy(&client);
|
||||||
|
net_destroy();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
35
src/tools/fuzzer.h
Normal file
35
src/tools/fuzzer.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
enum commandMode
|
||||||
|
{
|
||||||
|
cm_bcast = 0x01, /* B - broadcast */
|
||||||
|
cm_dir = 0x02, /* D - direct message */
|
||||||
|
cm_echo = 0x04, /* E - echo message */
|
||||||
|
cm_fcast = 0x08, /* F - feature cast message */
|
||||||
|
cm_c2h = 0x10, /* H - client to hub message */
|
||||||
|
cm_h2c = 0x20, /* I - hub to client message */
|
||||||
|
cm_c2c = 0x40, /* C - client to client message */
|
||||||
|
cm_udp = 0x80, /* U - udp message (client to client) */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum commandValidity
|
||||||
|
{
|
||||||
|
cv_protocol = 0x01,
|
||||||
|
cv_identify = 0x02,
|
||||||
|
cv_verify = 0x04,
|
||||||
|
cv_normal = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct commandPattern patterns[] =
|
||||||
|
{
|
||||||
|
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
|
||||||
|
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
|
||||||
|
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
|
||||||
|
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
|
||||||
|
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
|
||||||
|
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
|
||||||
|
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
|
||||||
|
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
|
||||||
|
{ cm_h2c, "QUI", cv_normal }, /* quit message */
|
||||||
|
{ cm_h2c, "GPA", cv_identify }, /* password request */
|
||||||
|
{ cm_c2h, "PAS", cv_verify } /* password response */
|
||||||
|
};
|
||||||
|
|
||||||
112
src/uhub.h
112
src/uhub.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-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
|
||||||
@@ -25,100 +25,7 @@
|
|||||||
/* #define MEMORY_DEBUG */
|
/* #define MEMORY_DEBUG */
|
||||||
/* #define DEBUG_SENDQ 1 */
|
/* #define DEBUG_SENDQ 1 */
|
||||||
|
|
||||||
#if USE_REGPARM && __GNUC__ >= 3
|
#include "system.h"
|
||||||
#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
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__CYGWIN__) || defined(__MINGW32__)
|
|
||||||
#ifndef WINSOCK
|
|
||||||
#define WINSOCK
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WINSOCK
|
|
||||||
#include <winsock2.h>
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#else
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <grp.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#define HAVE_STRNDUP
|
|
||||||
#define HAVE_MEMMEM
|
|
||||||
#define HAVE_GETRLIMIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../version.h"
|
|
||||||
|
|
||||||
#define uhub_assert assert
|
|
||||||
|
|
||||||
#include <event.h>
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
|
||||||
#undef HAVE_STRNDUP
|
|
||||||
#undef HAVE_MEMMEM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MSG_NOSIGNAL
|
|
||||||
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL
|
|
||||||
#else
|
|
||||||
#ifdef MSG_NOPIPE
|
|
||||||
#define UHUB_SEND_SIGNAL MSG_NOPIPE
|
|
||||||
#else
|
|
||||||
#define UHUB_SEND_SIGNAL 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define SERVER_PORT 1511
|
|
||||||
#define SERVER_ADDR_IPV6 "::"
|
|
||||||
#define SERVER_ADDR_IPV4 "0.0.0.0"
|
|
||||||
#define SERVER_BACKLOG 50
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#define SERVER_CONFIG "/etc/uhub/uhub.conf"
|
#define SERVER_CONFIG "/etc/uhub/uhub.conf"
|
||||||
@@ -134,10 +41,8 @@
|
|||||||
#define TIMEOUT_CONNECTED 15
|
#define TIMEOUT_CONNECTED 15
|
||||||
#define TIMEOUT_HANDSHAKE 30
|
#define TIMEOUT_HANDSHAKE 30
|
||||||
#define TIMEOUT_SENDQ 120
|
#define TIMEOUT_SENDQ 120
|
||||||
#define TIMEOUT_IDLE 7200
|
|
||||||
#define TIMEOUT_STATS 60
|
#define TIMEOUT_STATS 60
|
||||||
|
|
||||||
#define MAX_CLIENTS 512
|
|
||||||
#define MAX_CID_LEN 39
|
#define MAX_CID_LEN 39
|
||||||
#define MAX_NICK_LEN 64
|
#define MAX_NICK_LEN 64
|
||||||
#define MAX_UA_LEN 32
|
#define MAX_UA_LEN 32
|
||||||
@@ -146,19 +51,12 @@
|
|||||||
#define MAX_RECV_BUF 65535
|
#define MAX_RECV_BUF 65535
|
||||||
#define MAX_SEND_BUF 65535
|
#define MAX_SEND_BUF 65535
|
||||||
|
|
||||||
#ifndef INET6_ADDRSTRLEN
|
|
||||||
#define INET6_ADDRSTRLEN 46
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "adc/adcconst.h"
|
|
||||||
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "adc/adcconst.h"
|
||||||
|
|
||||||
#include "util/ipcalc.h"
|
#include "util/ipcalc.h"
|
||||||
#include "util/list.h"
|
#include "util/list.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
@@ -170,9 +68,11 @@ extern "C" {
|
|||||||
#include "adc/message.h"
|
#include "adc/message.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
#include "network/connection.h"
|
#include "network/connection.h"
|
||||||
|
#include "network/timeout.h"
|
||||||
|
|
||||||
#include "core/auth.h"
|
#include "core/auth.h"
|
||||||
#include "core/config.h"
|
#include "core/config.h"
|
||||||
|
#include "core/floodctl.h"
|
||||||
#include "core/eventid.h"
|
#include "core/eventid.h"
|
||||||
#include "core/eventqueue.h"
|
#include "core/eventqueue.h"
|
||||||
#include "core/netevent.h"
|
#include "core/netevent.h"
|
||||||
|
|||||||
@@ -451,11 +451,12 @@ int ip_convert_address_to_range(const char* address, struct ip_range* range)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char* addr = 0;
|
char* addr = 0;
|
||||||
|
const char* split;
|
||||||
|
|
||||||
if (!address || !range)
|
if (!address || !range)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const char* split = strrchr(address, '/');
|
split = strrchr(address, '/');
|
||||||
if (split)
|
if (split)
|
||||||
{
|
{
|
||||||
int mask = uhub_atoi(split+1);
|
int mask = uhub_atoi(split+1);
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ void list_clear(struct linked_list* list, void (*free_handle)(void* ptr))
|
|||||||
void list_append(struct linked_list* list, void* data_ptr)
|
void list_append(struct linked_list* list, void* data_ptr)
|
||||||
{
|
{
|
||||||
struct node* new_node = (struct node*) hub_malloc_zero(sizeof(struct node));
|
struct node* new_node = (struct node*) hub_malloc_zero(sizeof(struct node));
|
||||||
|
if (!new_node)
|
||||||
|
{
|
||||||
|
LOG_FATAL("Unable to allocate memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
new_node->ptr = data_ptr;
|
new_node->ptr = data_ptr;
|
||||||
|
|
||||||
if (list->last)
|
if (list->last)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void internal_debug_print_leaks()
|
|||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
size_t leak = 0;
|
size_t leak = 0;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
LOG_MEMORY("--- exit (allocs: %d, size: %zu) ---", hub_alloc_count, hub_alloc_size);
|
LOG_MEMORY("--- exit (allocs: %d, size: " PRINTF_SIZE_T ") ---", hub_alloc_count, hub_alloc_size);
|
||||||
|
|
||||||
for (; n < UHUB_MAX_ALLOCS; n++)
|
for (; n < UHUB_MAX_ALLOCS; n++)
|
||||||
{
|
{
|
||||||
@@ -55,11 +55,11 @@ void internal_debug_print_leaks()
|
|||||||
{
|
{
|
||||||
leak += hub_allocs[n].size;
|
leak += hub_allocs[n].size;
|
||||||
count++;
|
count++;
|
||||||
LOG_MEMORY("leak %p size: %zu (bt: %p %p)", hub_allocs[n].ptr, hub_allocs[n].size, hub_allocs[n].stack1, hub_allocs[n].stack2);
|
LOG_MEMORY("leak %p size: " PRINTF_SIZE_T " (bt: %p %p)", hub_allocs[n].ptr, hub_allocs[n].size, hub_allocs[n].stack1, hub_allocs[n].stack2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_MEMORY("--- done (allocs: %d, size: %zu, peak: %d/%zu, oom: %zu) ---", count, leak, hub_alloc_peak_count, hub_alloc_peak_size, hub_alloc_oom);
|
LOG_MEMORY("--- done (allocs: %d, size: " PRINTF_SIZE_T ", peak: %d/" PRINTF_SIZE_T ", oom: " PRINTF_SIZE_T ") ---", count, leak, hub_alloc_peak_count, hub_alloc_peak_size, hub_alloc_oom);
|
||||||
}
|
}
|
||||||
#endif /* REALTIME_MALLOC_TRACKING */
|
#endif /* REALTIME_MALLOC_TRACKING */
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ void* internal_debug_mem_malloc(size_t size, const char* where)
|
|||||||
hub_alloc_peak_count = MAX(hub_alloc_count, hub_alloc_peak_count);
|
hub_alloc_peak_count = MAX(hub_alloc_count, hub_alloc_peak_count);
|
||||||
hub_alloc_peak_size = MAX(hub_alloc_size, hub_alloc_peak_size);
|
hub_alloc_peak_size = MAX(hub_alloc_size, hub_alloc_peak_size);
|
||||||
|
|
||||||
LOG_MEMORY("%s %p (%d bytes) (bt: %p %p) {allocs: %d, size: %zu}", where, ptr, (int) size, hub_allocs[n].stack1, hub_allocs[n].stack2, hub_alloc_count, hub_alloc_size);
|
LOG_MEMORY("%s %p (%d bytes) (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", where, ptr, (int) size, hub_allocs[n].stack1, hub_allocs[n].stack2, hub_alloc_count, hub_alloc_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ void internal_debug_mem_free(void* ptr)
|
|||||||
hub_allocs[n].size = 0;
|
hub_allocs[n].size = 0;
|
||||||
hub_allocs[n].stack1 = 0;
|
hub_allocs[n].stack1 = 0;
|
||||||
hub_allocs[n].stack2 = 0;
|
hub_allocs[n].stack2 = 0;
|
||||||
LOG_MEMORY("free %p (bt: %p %p) {allocs: %d, size: %zu}", ptr, stack1, stack2, hub_alloc_count, hub_alloc_size);
|
LOG_MEMORY("free %p (bt: %p %p) {allocs: %d, size: " PRINTF_SIZE_T "}", ptr, stack1, stack2, hub_alloc_count, hub_alloc_size);
|
||||||
malloc_slot = n;
|
malloc_slot = n;
|
||||||
free(ptr);
|
free(ptr);
|
||||||
return;
|
return;
|
||||||
|
|||||||
142
src/util/misc.c
142
src/util/misc.c
@@ -46,10 +46,13 @@ char* strip_white_space(char* string)
|
|||||||
{
|
{
|
||||||
char* pos;
|
char* pos;
|
||||||
|
|
||||||
|
if (!string)
|
||||||
|
return "";
|
||||||
|
|
||||||
while (string[0] && is_white_space(string[0])) string++;
|
while (string[0] && is_white_space(string[0])) string++;
|
||||||
|
|
||||||
if (!*string)
|
if (!*string)
|
||||||
return 0;
|
return string;
|
||||||
|
|
||||||
/* Strip appending whitespace */
|
/* Strip appending whitespace */
|
||||||
pos = &string[strlen(string)-1];
|
pos = &string[strlen(string)-1];
|
||||||
@@ -168,14 +171,65 @@ void base32_decode(const char* src, unsigned char* dst, size_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int string_split(const char* string, const char* split, void* data, string_split_handler_t handler)
|
||||||
|
{
|
||||||
|
char* buf = strdup(string);
|
||||||
|
char* start;
|
||||||
|
char* pos;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
start = buf;
|
||||||
|
while ((pos = strstr(start, split)))
|
||||||
|
{
|
||||||
|
pos[0] = '\0';
|
||||||
|
start = strip_white_space(start);
|
||||||
|
if (*start)
|
||||||
|
{
|
||||||
|
if (handler(start, count, data) < 0)
|
||||||
|
{
|
||||||
|
hub_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start = &pos[1];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = strip_white_space(start);
|
||||||
|
if (*start)
|
||||||
|
{
|
||||||
|
if (handler(start, count, data) < 0)
|
||||||
|
{
|
||||||
|
hub_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hub_free(buf);
|
||||||
|
return count+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file_read_line_data
|
||||||
|
{
|
||||||
|
file_line_handler_t handler;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int file_read_line_handler(char* line, int count, void* ptr)
|
||||||
|
{
|
||||||
|
struct file_read_line_data* data = (struct file_read_line_data*) ptr;
|
||||||
|
|
||||||
|
LOG_DUMP("Line: %s", line);
|
||||||
|
if (data->handler(line, count+1, data->data) < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
char buf[MAX_RECV_BUF];
|
char buf[MAX_RECV_BUF];
|
||||||
char *pos, *start;
|
struct file_read_line_data split_data;
|
||||||
size_t line_count = 0;
|
|
||||||
|
|
||||||
memset(buf, 0, MAX_RECV_BUF);
|
memset(buf, 0, MAX_RECV_BUF);
|
||||||
|
|
||||||
@@ -189,46 +243,24 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = read(fd, buf, MAX_RECV_BUF);
|
ret = read(fd, buf, MAX_RECV_BUF);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
|
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
|
||||||
close(fd);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (ret == 0)
|
else if (ret == 0)
|
||||||
{
|
{
|
||||||
close(fd);
|
|
||||||
LOG_WARN("File is empty.");
|
LOG_WARN("File is empty.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* Parse configuaration */
|
/* Parse configuaration */
|
||||||
start = buf;
|
split_data.handler = handler;
|
||||||
while ((pos = strchr(start, '\n')))
|
split_data.data = data;
|
||||||
{
|
|
||||||
pos[0] = '\0';
|
|
||||||
if (*start)
|
|
||||||
{
|
|
||||||
LOG_DUMP("Line: %s", start);
|
|
||||||
if (handler(start, line_count+1, data) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
start = &pos[1];
|
|
||||||
line_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*start)
|
return string_split(buf, "\n", &split_data, file_read_line_handler);
|
||||||
{
|
|
||||||
buf[strlen(start)] = 0;
|
|
||||||
LOG_DUMP("Line: %s", start);
|
|
||||||
if (handler(start, line_count+1, data) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line_count+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -368,3 +400,51 @@ const char* get_timestamp(time_t now)
|
|||||||
sprintf(ts, "[%02d:%02d]", t->tm_hour, t->tm_min);
|
sprintf(ts, "[%02d:%02d]", t->tm_hour, t->tm_min);
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void strip_off_ini_line_comments(char* line, int line_count)
|
||||||
|
{
|
||||||
|
char* p = line;
|
||||||
|
char* out = line;
|
||||||
|
int backslash = 0;
|
||||||
|
|
||||||
|
if (!*line)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (; *p; p++)
|
||||||
|
{
|
||||||
|
if (!backslash)
|
||||||
|
{
|
||||||
|
if (*p == '\\')
|
||||||
|
{
|
||||||
|
backslash = 1;
|
||||||
|
}
|
||||||
|
else if (*p == '#')
|
||||||
|
{
|
||||||
|
*out = '\0';
|
||||||
|
out++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*p == '\\' || *p == '#' || *p == '\"')
|
||||||
|
{
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_WARN("Invalid backslash escape on line %d", line_count);
|
||||||
|
*out = *p;
|
||||||
|
out++;
|
||||||
|
}
|
||||||
|
backslash = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out = '\0';
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,9 +33,12 @@ extern int is_valid_base32_char(char c);
|
|||||||
extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
|
extern void base32_encode(const unsigned char* buffer, size_t len, char* result);
|
||||||
extern void base32_decode(const char* src, unsigned char* dst, size_t len);
|
extern void base32_decode(const char* src, unsigned char* dst, size_t len);
|
||||||
extern char* strip_white_space(char* string);
|
extern char* strip_white_space(char* string);
|
||||||
|
extern void strip_off_ini_line_comments(char* line, int line_count);
|
||||||
|
|
||||||
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
|
extern int file_read_lines(const char* file, void* data, file_line_handler_t handler);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern const char* uhub_itoa(int val);
|
extern const char* uhub_itoa(int val);
|
||||||
extern const char* uhub_ulltoa(uint64_t val);
|
extern const char* uhub_ulltoa(uint64_t val);
|
||||||
|
|
||||||
@@ -61,6 +64,8 @@ void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_
|
|||||||
struct linked_list;
|
struct linked_list;
|
||||||
extern int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty);
|
extern int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty);
|
||||||
|
|
||||||
|
typedef int (*string_split_handler_t)(char* string, int count, void* data);
|
||||||
|
extern int string_split(const char* string, const char* split, void* data, string_split_handler_t handler);
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_MISC_H */
|
#endif /* HAVE_UHUB_MISC_H */
|
||||||
|
|
||||||
|
|||||||
@@ -47,10 +47,13 @@ extern uint64_t tiger_sboxes[4*256];
|
|||||||
ROUND(b, c, a, x7, mul)
|
ROUND(b, c, a, x7, mul)
|
||||||
|
|
||||||
void tiger_compress(uint64_t* str, uint64_t state[3]) {
|
void tiger_compress(uint64_t* str, uint64_t state[3]) {
|
||||||
uint64_t a, b, c, swap;
|
uint64_t a, b, c;
|
||||||
uint64_t x0, x1, x2, x3, x4, x5, x6, x7;
|
uint64_t x0, x1, x2, x3, x4, x5, x6, x7;
|
||||||
uint64_t aa, bb, cc;
|
uint64_t aa, bb, cc;
|
||||||
|
#if PASSES > 3
|
||||||
|
uint64_t swap;
|
||||||
size_t pass_no;
|
size_t pass_no;
|
||||||
|
#endif
|
||||||
a = state[0];
|
a = state[0];
|
||||||
b = state[1];
|
b = state[1];
|
||||||
c = state[2];
|
c = state[2];
|
||||||
@@ -108,6 +111,7 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) {
|
|||||||
|
|
||||||
PASS(b, c, a, 9);
|
PASS(b, c, a, 9);
|
||||||
|
|
||||||
|
#if PASSES > 3
|
||||||
for (pass_no = 3; pass_no < PASSES; pass_no++)
|
for (pass_no = 3; pass_no < PASSES; pass_no++)
|
||||||
{
|
{
|
||||||
x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL;
|
x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL;
|
||||||
@@ -134,6 +138,7 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) {
|
|||||||
c = b;
|
c = b;
|
||||||
b = swap;
|
b = swap;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
a ^= aa;
|
a ^= aa;
|
||||||
b -= bb;
|
b -= bb;
|
||||||
|
|||||||
16
tools/create_certificate.sh
Executable file
16
tools/create_certificate.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
OPENSSL=/usr/bin/openssl
|
||||||
|
NAME=certificate
|
||||||
|
|
||||||
|
if [ ! -x ${OPENSSL} ]; then
|
||||||
|
echo "Cannot locate the openssl utility: ${OPENSSL}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
${OPENSSL} genrsa -out ${NAME}.key 1024 &&
|
||||||
|
${OPENSSL} req -new -x509 -nodes -sha1 -days 365 -key ${NAME}.key > ${NAME}.crt &&
|
||||||
|
cat ${NAME}.key ${NAME}.crt > ${NAME}.pem && rm -f ${NAME}.key ${NAME}.crt
|
||||||
|
|
||||||
|
echo "Created certificate ${NAME}.pem"
|
||||||
|
|
||||||
20
tools/nmdc-redirector
Executable file
20
tools/nmdc-redirector
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# Setup using inetd/xinetd or similar.
|
||||||
|
# In /etc/inetd.conf add:
|
||||||
|
# 1511 stream tcp nowait nobody /usr/bin/nmdc-redirector adc://target:port
|
||||||
|
#
|
||||||
|
# Change port to whatever you want.
|
||||||
|
# Make sure the path and the target:port is correct, then you should be good
|
||||||
|
# to go!
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use IO::Handle;
|
||||||
|
autoflush STDIN;
|
||||||
|
autoflush STDOUT;
|
||||||
|
|
||||||
|
my $target = $ARGV[0];
|
||||||
|
|
||||||
|
print "<Redirector> You are being redirected to " . $target . "|";
|
||||||
|
print "\$ForceMove " . $target . "|";
|
||||||
|
|
||||||
20
version.h
20
version.h
@@ -1,17 +1,25 @@
|
|||||||
|
#include "revision.h"
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
#define PRODUCT "uHub"
|
#define PRODUCT "uhub"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef VERSION
|
||||||
|
#define VERSION "0.3.2"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GIT_REVISION
|
#ifndef GIT_REVISION
|
||||||
#define REVISION ""
|
#define REVISION ""
|
||||||
|
#define PRODUCT_STRING PRODUCT "/" VERSION
|
||||||
#else
|
#else
|
||||||
#define REVISION " (git: " GIT_REVISION ")"
|
#define REVISION "(git: " GIT_REVISION ")"
|
||||||
|
#ifdef GIT_VERSION
|
||||||
|
#define PRODUCT_STRING PRODUCT "/" GIT_VERSION
|
||||||
|
#else
|
||||||
|
#define PRODUCT_STRING PRODUCT "/" VERSION " " REVISION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef VERSION
|
|
||||||
#define VERSION "0.3.0-rc4" REVISION
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef COPYRIGHT
|
#ifndef COPYRIGHT
|
||||||
#define COPYRIGHT "Copyright (c) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>"
|
#define COPYRIGHT "Copyright (c) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user