Compare commits
178 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
||||
|
||||
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
|
||||
|
||||
12
ChangeLog
12
ChangeLog
@@ -1,3 +1,15 @@
|
||||
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:
|
||||
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
||||
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
||||
|
||||
161
GNUmakefile
161
GNUmakefile
@@ -1,6 +1,6 @@
|
||||
##
|
||||
## 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>
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
@@ -8,23 +8,31 @@ LD := $(CC)
|
||||
MV := mv
|
||||
RANLIB := ranlib
|
||||
CFLAGS += -pipe -Wall
|
||||
USE_PCH ?= YES
|
||||
USE_SSL ?= NO
|
||||
USE_BIGENDIAN ?= AUTO
|
||||
BITS ?= AUTO
|
||||
SILENT ?= YES
|
||||
LDLIBS += -levent
|
||||
TERSE ?= NO
|
||||
STACK_PROTECT ?= NO
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
WINDOWS ?= YES
|
||||
OPSYS ?= Windows
|
||||
else
|
||||
OPSYS ?= $(shell uname)
|
||||
endif
|
||||
|
||||
ifeq ($(OPSYS),SunOS)
|
||||
LDLIBS += -lsocket -lnsl
|
||||
endif
|
||||
|
||||
ifeq ($(OPSYS),Haiku)
|
||||
LDLIBS += -lnetwork
|
||||
endif
|
||||
|
||||
CFLAGS += -I./src/
|
||||
|
||||
ifeq ($(WINDOWS),YES)
|
||||
ifeq ($(OPSYS),Windows)
|
||||
USE_BIGENDIAN := NO
|
||||
LDLIBS += -lws2_32
|
||||
UHUB_CONF_DIR ?= c:/uhub/
|
||||
@@ -32,7 +40,6 @@ UHUB_PREFIX ?= c:/uhub/
|
||||
CFLAGS += -mno-cygwin
|
||||
LDFLAGS += -mno-cygwin
|
||||
BIN_EXT ?= .exe
|
||||
GIT_REVISION ?= NO
|
||||
else
|
||||
DESTDIR ?= /
|
||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
||||
@@ -43,20 +50,17 @@ BIN_EXT ?=
|
||||
endif
|
||||
|
||||
ifeq ($(SILENT),YES)
|
||||
MSG_CC=@echo " CC:" $(notdir $^) &&
|
||||
MSG_PCH=@echo " PCH:" $(notdir $@) &&
|
||||
MSG_CC=@echo " CC:" $(notdir $<) &&
|
||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
||||
else
|
||||
MSG_CC=
|
||||
MSG_PCH=
|
||||
MSG_LD=
|
||||
MSG_AR=
|
||||
endif
|
||||
|
||||
ifeq ($(TERSE), YES)
|
||||
MSG_CC=@
|
||||
MSG_PCH=@
|
||||
MSG_LD=@
|
||||
MSG_AR=@
|
||||
MSG_CLEAN=-n ""
|
||||
@@ -64,15 +68,10 @@ else
|
||||
MSG_CLEAN="Clean as a whistle"
|
||||
endif
|
||||
|
||||
CFLAGS += -I/source/libevent
|
||||
LDFLAGS += -L/source/libevent
|
||||
|
||||
ifeq ($(RELEASE),YES)
|
||||
CFLAGS += -O3 -DNDEBUG
|
||||
GIT_REVISION ?= NO
|
||||
else
|
||||
CFLAGS += -ggdb -DDEBUG
|
||||
GIT_REVISION ?= YES
|
||||
endif
|
||||
|
||||
ifeq ($(STACK_PROTECT),YES)
|
||||
@@ -90,13 +89,6 @@ CFLAGS += -finstrument-functions
|
||||
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
||||
endif
|
||||
|
||||
ifeq ($(USE_PCH),YES)
|
||||
PCHSRC=src/uhub.h
|
||||
PCH=src/uhub.h.gch
|
||||
else
|
||||
PCH=
|
||||
endif
|
||||
|
||||
ifneq ($(BITS), AUTO)
|
||||
ifeq ($(BITS), 64)
|
||||
CFLAGS += -m64
|
||||
@@ -124,14 +116,9 @@ CFLAGS += -DSSL_SUPPORT
|
||||
LDLIBS += -lssl
|
||||
endif
|
||||
|
||||
ifneq ($(LIBEVENT_PATH),)
|
||||
CFLAGS += -I$(LIBEVENT_PATH)
|
||||
LDFLAGS += -L$(LIBEVENT_PATH)
|
||||
endif
|
||||
|
||||
ifeq ($(GIT_REVISION),YES)
|
||||
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
|
||||
endif
|
||||
GIT_VERSION=$(shell git describe 2>/dev/null || echo "")
|
||||
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
||||
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
||||
|
||||
# Sources
|
||||
libuhub_SOURCES := \
|
||||
@@ -143,54 +130,39 @@ libuhub_SOURCES := \
|
||||
src/core/hubevent.c \
|
||||
src/core/hubio.c \
|
||||
src/core/inf.c \
|
||||
src/core/netevent.c \
|
||||
src/core/probe.c \
|
||||
src/core/route.c \
|
||||
src/core/user.c \
|
||||
src/core/usermanager.c \
|
||||
src/network/backend.c \
|
||||
src/network/connection.c \
|
||||
src/network/epoll.c \
|
||||
src/network/kqueue.c \
|
||||
src/network/network.c \
|
||||
src/network/select.c \
|
||||
src/network/timeout.c \
|
||||
src/network/timer.c \
|
||||
src/util/ipcalc.c \
|
||||
src/util/list.c \
|
||||
src/util/log.c \
|
||||
src/util/memory.c \
|
||||
src/adc/message.c \
|
||||
src/util/misc.c \
|
||||
src/core/netevent.c \
|
||||
src/network/connection.c \
|
||||
src/network/network.c \
|
||||
src/util/rbtree.c \
|
||||
src/core/route.c \
|
||||
src/adc/sid.c \
|
||||
src/util/tiger.c \
|
||||
src/core/user.c \
|
||||
src/core/usermanager.c
|
||||
src/util/tiger.c
|
||||
|
||||
libadc_common_SOURCES := \
|
||||
src/adc/message.c \
|
||||
src/adc/sid.c
|
||||
|
||||
libadc_client_SOURCES := \
|
||||
src/tools/adcclient.c
|
||||
|
||||
uhub_SOURCES := src/core/main.c
|
||||
|
||||
adcrush_SOURCES := src/tools/adcrush.c
|
||||
|
||||
admin_SOURCES := src/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
|
||||
admin_SOURCES := src/tools/admin.c
|
||||
|
||||
autotest_SOURCES := \
|
||||
autotest/test_message.tcc \
|
||||
@@ -207,48 +179,55 @@ autotest_SOURCES := \
|
||||
autotest_OBJECTS = autotest.o
|
||||
|
||||
# Source to objects
|
||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
||||
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
||||
libadc_common_OBJECTS := $(libadc_common_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)
|
||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
||||
|
||||
%.o: %.c
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $^
|
||||
.PHONY: revision.h.tmp
|
||||
|
||||
all: $(uhub_BINARY) $(PCH)
|
||||
%.o: %.c version.h revision.h
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(adcrush_BINARY): $(PCH) $(LIBUHUB) $(adcrush_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $(adcrush_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS)
|
||||
all: $(uhub_BINARY)
|
||||
|
||||
$(admin_BINARY): $(PCH) $(LIBUHUB) $(admin_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $(admin_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS)
|
||||
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
$(uhub_BINARY): $(PCH) $(LIBUHUB) $(uhub_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $(uhub_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS)
|
||||
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
$(LIBUHUB): $(libuhub_OBJECTS)
|
||||
$(MSG_AR) $(AR) rc $@ $^ && $(RANLIB) $@
|
||||
|
||||
ifeq ($(USE_PCH),YES)
|
||||
$(PCH): $(uhub_HEADERS)
|
||||
$(MSG_PCH) $(CC) $(CFLAGS) -o $@ $(PCHSRC)
|
||||
endif
|
||||
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
autotest.c: $(autotest_SOURCES)
|
||||
$(shell exotic --standalone $(autotest_SOURCES) > $@)
|
||||
|
||||
revision.h.tmp:
|
||||
@rm -f $@
|
||||
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
|
||||
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
|
||||
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
|
||||
|
||||
version.h: revision.h
|
||||
|
||||
revision.h: revision.h.tmp
|
||||
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cat $@.tmp > $@; fi
|
||||
|
||||
$(autotest_OBJECTS): autotest.c
|
||||
$(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)
|
||||
|
||||
autotest: $(autotest_BINARY)
|
||||
@@ -269,10 +248,10 @@ install: $(uhub_BINARY)
|
||||
endif
|
||||
|
||||
dist-clean:
|
||||
@rm -rf $(all_OBJECTS) $(PCH) *~ core
|
||||
@rm -rf $(all_OBJECTS) *~ core
|
||||
|
||||
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 && \
|
||||
echo $(MSG_CLEAN)
|
||||
|
||||
|
||||
|
||||
5
README
5
README
@@ -1,5 +1,8 @@
|
||||
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
||||
|
||||
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, {
|
||||
config_defaults(&g_config);
|
||||
g_config.server_port = 15111;
|
||||
return 1;
|
||||
});
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ static void inf_create_user()
|
||||
if (inf_user) return;
|
||||
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||
inf_user->id.sid = 1;
|
||||
inf_user->net.connection.sd = -1;
|
||||
inf_user->limits.upload_slots = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ EXO_TEST(adc_message_parse_1, {
|
||||
|
||||
EXO_TEST(adc_message_parse_2, {
|
||||
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, {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
static struct hub_info um_hub;
|
||||
static struct hub_user um_user[MAX_USERS];
|
||||
// static struct net_connection um_cons[MAX_USERS];
|
||||
|
||||
EXO_TEST(um_test_setup, {
|
||||
int i = 0;
|
||||
@@ -11,9 +12,12 @@ EXO_TEST(um_test_setup, {
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
|
||||
um_cons[i].sd = -1;
|
||||
|
||||
memset(&um_user[i], 0, sizeof(struct hub_user));
|
||||
um_user[i].id.sid = i+1;
|
||||
um_user[i].net.connection.sd = -1;
|
||||
um_user[i].connection = &um_cons[i];*/
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
|
||||
13
debian/changelog
vendored
Normal file
13
debian/changelog
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
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.
|
||||
* GNU make
|
||||
* gcc > 3.0 (or MinGW on Windows)
|
||||
* libevent >= 1.3
|
||||
* Perl 5
|
||||
|
||||
Linux and Mac OSX
|
||||
-----------------
|
||||
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
||||
-------------------------------------------
|
||||
Simply, run:
|
||||
% 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:
|
||||
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:
|
||||
% 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!
|
||||
|
||||
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
|
||||
# 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
|
||||
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
||||
@@ -12,12 +13,18 @@
|
||||
server_port=1511
|
||||
server_bind_addr=any
|
||||
|
||||
# Alternative server ports
|
||||
# server_alt_ports = 1512, 1513
|
||||
|
||||
# The maximum amount of users allowed on the hub.
|
||||
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
|
||||
|
||||
# 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.
|
||||
registered_users_only=0
|
||||
|
||||
@@ -38,6 +45,35 @@ file_acl=/etc/uhub/users.conf
|
||||
# Normally this message is sent to clients when connecting.
|
||||
file_motd=/etc/uhub/motd.txt
|
||||
|
||||
# This file can contain a rules of the hub.
|
||||
# Normally this message is sent to clients when write in chat !rules
|
||||
file_rules=/etc/uhub/rules.txt
|
||||
|
||||
|
||||
# Slots\share\hubs limits
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
# Configure status message as sent to clients in different circumstances.
|
||||
msg_hub_full = Hub is full
|
||||
msg_hub_disabled = Hub is disabled
|
||||
@@ -61,6 +97,12 @@ msg_ban_permanently = Banned permanently
|
||||
msg_ban_temporarily = Banned temporarily
|
||||
msg_auth_invalid_password = Password is wrong
|
||||
msg_auth_user_not_found = User not found in password database
|
||||
msg_user_share_size_low = User is not sharing enough
|
||||
msg_user_share_size_high = User is sharing too much
|
||||
msg_user_slots_low = User have too few upload slots
|
||||
msg_user_slots_high = User have too many upload slots
|
||||
msg_user_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
|
||||
|
||||
|
||||
|
||||
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.0
|
||||
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
|
||||
|
||||
|
||||
@@ -26,17 +26,71 @@
|
||||
uhub_assert(X->capacity); \
|
||||
uhub_assert(X->length); \
|
||||
uhub_assert(X->length <= X->capacity); \
|
||||
uhub_assert(X->length == strlen(X->cache)); \
|
||||
uhub_assert(X->references >= 0);
|
||||
uhub_assert(X->length == strlen(X->cache));
|
||||
#else
|
||||
#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);
|
||||
}
|
||||
|
||||
#include <sys/mman.h>
|
||||
static void adc_msg_protect(struct adc_message* cmd)
|
||||
{
|
||||
LOG_MEMORY("msg_prot: %p %d", cmd, cmd->capacity);
|
||||
mprotect(cmd, sizeof(cmd), PROT_READ);
|
||||
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ);
|
||||
}
|
||||
|
||||
static void adc_msg_unprotect(struct adc_message* cmd)
|
||||
{
|
||||
LOG_MEMORY("msg_unprot: %p %d", cmd, cmd->capacity);
|
||||
mprotect(cmd, sizeof(cmd), PROT_READ | PROT_WRITE);
|
||||
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ | PROT_WRITE);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#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)
|
||||
{
|
||||
if (!msg) return 0;
|
||||
#ifndef ADC_MESSAGE_INCREF
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(msg);
|
||||
#endif
|
||||
msg->references++;
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
#endif
|
||||
return msg;
|
||||
#else
|
||||
struct adc_message* copy = adc_msg_copy(msg);
|
||||
@@ -56,24 +110,25 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
||||
|
||||
if (msg->capacity > size)
|
||||
return 1;
|
||||
|
||||
|
||||
/* Make sure we align our data */
|
||||
newsize = size;
|
||||
newsize += 2; /* termination */
|
||||
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
||||
|
||||
buf = hub_malloc_zero(newsize);
|
||||
|
||||
buf = msg_malloc_zero(newsize);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
|
||||
if (msg->cache)
|
||||
{
|
||||
memcpy(buf, msg->cache, msg->length);
|
||||
hub_free(msg->cache);
|
||||
msg_free(msg->cache);
|
||||
}
|
||||
|
||||
|
||||
msg->cache = buf;
|
||||
msg->capacity = newsize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -85,10 +140,10 @@ static int adc_msg_cache_append(struct adc_message* msg, const char* string, siz
|
||||
/* FIXME: OOM! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
memcpy(&msg->cache[msg->length], string, len);
|
||||
adc_msg_set_length(msg, msg->length + len);
|
||||
|
||||
|
||||
assert(msg->capacity > msg->length);
|
||||
msg->cache[msg->length] = 0;
|
||||
return 1;
|
||||
@@ -148,14 +203,23 @@ void adc_msg_free(struct adc_message* msg)
|
||||
if (!msg) return;
|
||||
|
||||
ADC_MSG_ASSERT(msg);
|
||||
|
||||
|
||||
if (msg->references > 0)
|
||||
{
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(msg);
|
||||
#endif
|
||||
msg->references--;
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_free(msg->cache);
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(msg);
|
||||
#endif
|
||||
msg_free(msg->cache);
|
||||
|
||||
if (msg->feature_cast_include)
|
||||
{
|
||||
@@ -171,7 +235,7 @@ void adc_msg_free(struct adc_message* msg)
|
||||
msg->feature_cast_exclude = 0;
|
||||
}
|
||||
|
||||
hub_free(msg);
|
||||
msg_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,11 +243,11 @@ void adc_msg_free(struct adc_message* msg)
|
||||
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
{
|
||||
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 */
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
/* deep copy */
|
||||
copy->cmd = cmd->cmd;
|
||||
copy->source = cmd->source;
|
||||
@@ -195,7 +259,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
copy->references = 0;
|
||||
copy->feature_cast_include = 0;
|
||||
copy->feature_cast_exclude = 0;
|
||||
|
||||
|
||||
if (cmd->cache)
|
||||
{
|
||||
if (!adc_msg_grow(copy, copy->length))
|
||||
@@ -206,7 +270,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
memcpy(copy->cache, cmd->cache, cmd->length);
|
||||
copy->cache[copy->length] = 0;
|
||||
}
|
||||
|
||||
|
||||
if (cmd->feature_cast_include)
|
||||
{
|
||||
copy->feature_cast_include = list_create();
|
||||
@@ -217,7 +281,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
tmp = list_get_next(cmd->feature_cast_include);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (cmd->feature_cast_exclude)
|
||||
{
|
||||
copy->feature_cast_exclude = list_create();
|
||||
@@ -228,9 +292,12 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
tmp = list_get_next(cmd->feature_cast_exclude);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(copy);
|
||||
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(copy);
|
||||
#endif
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -255,7 +322,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* 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];
|
||||
size_t n = 0;
|
||||
char temp_sid[5];
|
||||
@@ -269,7 +336,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
if (!is_printable_utf8(line, length))
|
||||
{
|
||||
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
|
||||
hub_free(command);
|
||||
msg_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -280,7 +347,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
|
||||
if (!adc_msg_grow(command, length + need_terminate))
|
||||
{
|
||||
hub_free(command);
|
||||
msg_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
@@ -352,8 +419,8 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
{
|
||||
list_destroy(command->feature_cast_include);
|
||||
list_destroy(command->feature_cast_exclude);
|
||||
hub_free(command->cache);
|
||||
hub_free(command);
|
||||
msg_free(command->cache);
|
||||
msg_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
@@ -443,20 +510,23 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
}
|
||||
|
||||
ADC_MSG_ASSERT(command);
|
||||
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(command);
|
||||
#endif
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
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* 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)
|
||||
return NULL; /* OOM */
|
||||
@@ -465,7 +535,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
|
||||
if (!adc_msg_grow(msg, size+1))
|
||||
{
|
||||
hub_free(msg);
|
||||
msg_free(msg);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
@@ -484,7 +554,11 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
|
||||
msg->cmd = fourcc;
|
||||
msg->priority = 0;
|
||||
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
#endif
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -624,12 +698,20 @@ void adc_msg_terminate(struct adc_message* cmd)
|
||||
adc_msg_cache_append(cmd, "\n", 1);
|
||||
}
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* FIXME: this looks bogus */
|
||||
void adc_msg_unterminate(struct adc_message* cmd)
|
||||
{
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_unprotect(cmd);
|
||||
#endif
|
||||
|
||||
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
|
||||
{
|
||||
@@ -654,6 +736,27 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
|
||||
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)
|
||||
{
|
||||
@@ -673,16 +776,15 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
||||
char* end;
|
||||
char* argument;
|
||||
int count = 0;
|
||||
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
|
||||
|
||||
adc_msg_unterminate(cmd);
|
||||
|
||||
|
||||
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
|
||||
while (start)
|
||||
{
|
||||
end = strchr(&start[1], ' ');
|
||||
|
||||
if (count == offset)
|
||||
{
|
||||
if (end)
|
||||
@@ -692,21 +794,27 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
||||
else
|
||||
{
|
||||
argument = hub_strdup(&start[1]);
|
||||
if (argument[strlen(argument)-1] == '\n')
|
||||
if (argument && argument[strlen(argument)-1] == '\n')
|
||||
argument[strlen(argument)-1] = 0;
|
||||
}
|
||||
|
||||
|
||||
if (!argument)
|
||||
return 0; // FIXME: OOM
|
||||
|
||||
if (*argument)
|
||||
{
|
||||
adc_msg_terminate(cmd);
|
||||
return argument;
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_free(argument);
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
start = end;
|
||||
}
|
||||
|
||||
|
||||
adc_msg_terminate(cmd);
|
||||
return 0;
|
||||
}
|
||||
@@ -781,7 +889,7 @@ int adc_msg_unescape_length(const char* str)
|
||||
|
||||
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* str = (char*) string;
|
||||
int escaped = 0;
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @return string or NULL if out of memory
|
||||
|
||||
@@ -88,19 +88,31 @@ struct sid_pool
|
||||
struct sid_pool* sid_pool_create(sid_t max)
|
||||
{
|
||||
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
|
||||
if (!pool)
|
||||
return 0;
|
||||
|
||||
pool->min = 1;
|
||||
pool->max = max + 1;
|
||||
pool->count = 0;
|
||||
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. */
|
||||
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
|
||||
#endif
|
||||
return pool;
|
||||
}
|
||||
|
||||
void sid_pool_destroy(struct sid_pool* pool)
|
||||
{
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
|
||||
#endif
|
||||
hub_free(pool->map);
|
||||
hub_free(pool);
|
||||
}
|
||||
@@ -110,14 +122,18 @@ sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
||||
sid_t n = (++pool->count);
|
||||
for (; (pool->map[n % pool->max]); n++) ;
|
||||
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
|
||||
#endif
|
||||
pool->map[n] = user;
|
||||
return n;
|
||||
}
|
||||
|
||||
void sid_free(struct sid_pool* pool, sid_t sid)
|
||||
{
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_FREE: %d", (int) sid);
|
||||
#endif
|
||||
pool->map[sid] = 0;
|
||||
pool->count--;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
||||
{
|
||||
char buf1[INET6_ADDRSTRLEN+1];
|
||||
char buf2[INET6_ADDRSTRLEN+1];
|
||||
|
||||
|
||||
if (info->lo.af == AF_INET)
|
||||
{
|
||||
net_address_to_string(AF_INET, &info->lo.internal_ip_data.in.s_addr, buf1, INET6_ADDRSTRLEN);
|
||||
@@ -130,8 +130,8 @@ 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->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);
|
||||
}
|
||||
|
||||
@@ -179,26 +179,18 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
||||
char* pos;
|
||||
struct acl_handle* handle = (struct acl_handle*) ptr_data;
|
||||
int ret;
|
||||
|
||||
|
||||
if ((pos = strchr(line, '#')) != NULL)
|
||||
{
|
||||
pos[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
line = strip_white_space(line);
|
||||
if (!*line)
|
||||
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);
|
||||
|
||||
|
||||
ACL_ADD_USER("bot", handle->users, cred_bot);
|
||||
ACL_ADD_USER("user_admin", handle->users, cred_admin);
|
||||
ACL_ADD_USER("user_super", handle->users, cred_super);
|
||||
@@ -210,7 +202,7 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
||||
ACL_ADD_BOOL("ban_cid", handle->cids);
|
||||
ACL_ADD_ADDR("deny_ip", handle->networks);
|
||||
ACL_ADD_ADDR("nat_ip", handle->nat_override);
|
||||
|
||||
|
||||
LOG_ERROR("Unknown ACL command on line %d: '%s'", line_count, line);
|
||||
return -1;
|
||||
}
|
||||
@@ -334,7 +326,7 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
|
||||
}
|
||||
|
||||
#define STR_LIST_CONTAINS(LIST, STR) \
|
||||
char* str = (char*) list_get_first(LIST); \
|
||||
str = (char*) list_get_first(LIST); \
|
||||
while (str) \
|
||||
{ \
|
||||
if (strcasecmp(str, STR) == 0) \
|
||||
@@ -345,43 +337,67 @@ 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)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->cids, data);
|
||||
}
|
||||
|
||||
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->users_banned, data);
|
||||
}
|
||||
|
||||
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->users_denied, data);
|
||||
}
|
||||
|
||||
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
||||
{
|
||||
char* data = 0;
|
||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
||||
|
||||
if (!info)
|
||||
{
|
||||
LOG_ERROR("ACL error: Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
list_append(handle->users_banned, hub_strdup(nick));
|
||||
|
||||
data = hub_strdup(nick);
|
||||
if (!data)
|
||||
{
|
||||
LOG_ERROR("ACL error: Out of memory!");
|
||||
hub_free(info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_append(handle->users_banned, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
||||
{
|
||||
char* data;
|
||||
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
|
||||
if (!info)
|
||||
{
|
||||
LOG_ERROR("ACL error: Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
list_append(handle->cids, hub_strdup(cid));
|
||||
|
||||
data = hub_strdup(cid);
|
||||
if (!data)
|
||||
{
|
||||
LOG_ERROR("ACL error: Out of memory!");
|
||||
hub_free(info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_append(handle->cids, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -439,12 +455,13 @@ 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)
|
||||
{
|
||||
char buf[32];
|
||||
char buf[64];
|
||||
uint64_t tiger_res[3];
|
||||
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);
|
||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
|
||||
tiger_buf[MAX_CID_LEN] = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
char* prefix;
|
||||
int n;
|
||||
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
|
||||
|
||||
if (!cmd) return 0;
|
||||
|
||||
cmd->message = message;
|
||||
cmd->args = list_create();
|
||||
|
||||
int n = split_string(message, "\\s", cmd->args, 0);
|
||||
n = split_string(message, "\\s", cmd->args, 0);
|
||||
if (n <= 0)
|
||||
{
|
||||
command_destroy(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* prefix = list_get_first(cmd->args);
|
||||
if (prefix[0] && prefix[1])
|
||||
prefix = list_get_first(cmd->args);
|
||||
if (prefix && prefix[0] && prefix[1])
|
||||
{
|
||||
cmd->prefix = hub_strdup(&prefix[1]);
|
||||
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)
|
||||
{
|
||||
static char args[128];
|
||||
args[0] = 0;
|
||||
size_t n = 0;
|
||||
args[0] = 0;
|
||||
if (handler->args)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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_peak,
|
||||
(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)
|
||||
{
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
char tmp[128];
|
||||
|
||||
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)
|
||||
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(user));
|
||||
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 hub_user* u;
|
||||
int ret = 0;
|
||||
char tmp[128];
|
||||
char* buffer;
|
||||
|
||||
if (!address)
|
||||
return -1; // FIXME: bad syntax.
|
||||
|
||||
ret = ip_convert_address_to_range(address, &range);
|
||||
if (!ret)
|
||||
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
|
||||
|
||||
users = (struct linked_list*) list_create();
|
||||
if (!users)
|
||||
return -1; // FIXME: OOM
|
||||
|
||||
ret = uman_get_user_by_addr(hub, users, &range);
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
char tmp[128];
|
||||
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, (int) ret, ((ret != 1) ? "es" : ""));
|
||||
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, 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;
|
||||
strcat(buffer, tmp);
|
||||
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, " (");
|
||||
strcat(buffer, ip_convert_to_string(&u->net.ipaddr));
|
||||
strcat(buffer, user_get_address(u));
|
||||
strcat(buffer, ")\n");
|
||||
u = (struct hub_user*) list_get_next(users);
|
||||
}
|
||||
@@ -350,13 +406,14 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
|
||||
|
||||
send_message(hub, user, buffer);
|
||||
hub_free(buffer);
|
||||
list_destroy(users);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
adc_msg_add_argument(command, (cmd->message + 10));
|
||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 12)) + 6);
|
||||
adc_msg_add_argument(command, (cmd->message + 12));
|
||||
route_to_all(hub, command);
|
||||
adc_msg_free(command);
|
||||
return 0;
|
||||
@@ -369,14 +426,14 @@ static int command_history(struct hub_info* hub, struct hub_user* user, struct h
|
||||
char* message = 0;
|
||||
int ret = (int) list_size(messages);
|
||||
size_t bufsize;
|
||||
char tmp[128];
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
return command_status(hub, user, cmd, "No messages.");
|
||||
}
|
||||
|
||||
char tmp[128];
|
||||
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, (int) ret, ((ret != 1) ? "s" : ""));
|
||||
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
|
||||
bufsize = strlen(tmp);
|
||||
message = (char*) list_get_first(messages);
|
||||
while (message)
|
||||
@@ -430,11 +487,11 @@ static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_c
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -467,13 +524,27 @@ static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_c
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
@@ -490,7 +561,7 @@ int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* m
|
||||
|
||||
/* Parse and validate the command */
|
||||
struct hub_command* cmd = command_create(message);
|
||||
if (!cmd) return 1;
|
||||
if (!cmd) return 0;
|
||||
|
||||
for (n = 0; command_handlers[n].prefix; n++)
|
||||
{
|
||||
@@ -524,28 +595,32 @@ int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* m
|
||||
|
||||
command_not_found(hub, user, cmd);
|
||||
command_destroy(cmd);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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" },
|
||||
{ "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" },
|
||||
{ "log", 3, 0, cred_operator, command_log, "Display log" },
|
||||
#ifdef CRASH_DEBUG
|
||||
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
|
||||
#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, "" }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -110,11 +110,14 @@
|
||||
/* default configuration values */
|
||||
#define DEF_SERVER_BIND_ADDR "any"
|
||||
#define DEF_SERVER_PORT 1511
|
||||
#define DEF_SERVER_BACKLOG 50
|
||||
#define DEF_SERVER_ALT_PORTS ""
|
||||
#define DEF_HUB_NAME "uhub"
|
||||
#define DEF_HUB_DESCRIPTION ""
|
||||
#define DEF_HUB_ENABLED 1
|
||||
#define DEF_FILE_ACL ""
|
||||
#define DEF_FILE_MOTD ""
|
||||
#define DEF_FILE_RULES ""
|
||||
#define DEF_MAX_USERS 500
|
||||
#define DEF_MAX_CHAT_HISTORY 20
|
||||
#define DEF_MAX_LOGOUT_LOG 100
|
||||
@@ -122,6 +125,7 @@
|
||||
#define DEF_MAX_SEND_BUFFER 131072
|
||||
#define DEF_MAX_SEND_BUFFER_SOFT 98304
|
||||
#define DEF_SHOW_BANNER 1
|
||||
#define DEF_SHOW_BANNER_SYS_INFO 1
|
||||
#define DEF_REGISTERED_USERS_ONLY 0
|
||||
#define DEF_CHAT_ONLY 0
|
||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
||||
@@ -137,6 +141,10 @@
|
||||
#define DEF_LIMIT_MAX_SHARE 0
|
||||
#define DEF_LIMIT_MIN_SLOTS 0
|
||||
#define DEF_LIMIT_MAX_SLOTS 0
|
||||
#define DEF_TLS_ENABLE 0
|
||||
#define DEF_TLS_REQUIRE 1
|
||||
#define DEF_TLS_PRIVATE_KEY ""
|
||||
#define DEF_TLS_CERTIFICATE ""
|
||||
#define DEF_MSG_HUB_FULL "Hub is full"
|
||||
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
|
||||
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
|
||||
@@ -175,7 +183,10 @@ void config_defaults(struct hub_config* config)
|
||||
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
||||
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
||||
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
||||
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
|
||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
||||
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
|
||||
DEFAULT_STRING (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
||||
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
|
||||
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
|
||||
@@ -183,6 +194,7 @@ void config_defaults(struct hub_config* config)
|
||||
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(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
||||
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);
|
||||
@@ -232,10 +244,10 @@ void config_defaults(struct hub_config* config)
|
||||
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, "");
|
||||
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
|
||||
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
|
||||
DEFAULT_STRING (tls_certificate, DEF_TLS_CERTIFICATE);
|
||||
DEFAULT_STRING (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
||||
}
|
||||
|
||||
|
||||
@@ -243,8 +255,11 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
{
|
||||
GET_STR (file_acl);
|
||||
GET_STR (file_motd);
|
||||
GET_STR (file_rules);
|
||||
GET_STR (server_bind_addr);
|
||||
GET_INT (server_port);
|
||||
GET_INT (server_listen_backlog);
|
||||
GET_STR (server_alt_ports);
|
||||
GET_STR (hub_name);
|
||||
GET_STR (hub_description);
|
||||
GET_BOOL(hub_enabled);
|
||||
@@ -255,6 +270,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
GET_INT (max_send_buffer);
|
||||
GET_INT (max_send_buffer_soft);
|
||||
GET_BOOL(show_banner);
|
||||
GET_BOOL(show_banner_sys_info);
|
||||
GET_BOOL(chat_only);
|
||||
GET_BOOL(chat_is_privileged);
|
||||
GET_BOOL(low_bandwidth_mode);
|
||||
@@ -318,8 +334,10 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
||||
void free_config(struct hub_config* config)
|
||||
{
|
||||
hub_free(config->server_bind_addr);
|
||||
hub_free(config->server_alt_ports);
|
||||
hub_free(config->file_motd);
|
||||
hub_free(config->file_acl);
|
||||
hub_free(config->file_rules);
|
||||
hub_free(config->hub_name);
|
||||
hub_free(config->hub_description);
|
||||
|
||||
@@ -391,8 +409,11 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
{
|
||||
DUMP_STR (file_acl, DEF_FILE_ACL);
|
||||
DUMP_STR (file_motd, DEF_FILE_MOTD);
|
||||
DUMP_STR (file_rules, DEF_FILE_RULES);
|
||||
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
||||
DUMP_INT (server_port, DEF_SERVER_PORT);
|
||||
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG);
|
||||
DUMP_STR (server_alt_ports, DEF_SERVER_ALT_PORTS);
|
||||
DUMP_STR (hub_name, DEF_HUB_NAME);
|
||||
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
||||
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
||||
@@ -403,11 +424,19 @@ void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
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(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
|
||||
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
|
||||
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
||||
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
||||
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
DUMP_BOOL(tls_enable, DEF_TLS_ENABLE);
|
||||
DUMP_BOOL(tls_require, DEF_TLS_REQUIRE);
|
||||
DUMP_STR (tls_certificate, DEF_TLS_CERTIFICATE);
|
||||
DUMP_STR (tls_private_key, DEF_TLS_PRIVATE_KEY);
|
||||
#endif
|
||||
|
||||
/* Limits enforced on users */
|
||||
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
||||
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,14 +24,18 @@ struct hub_config
|
||||
{
|
||||
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
||||
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
||||
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
|
||||
char* server_alt_ports; /**<<< "Comma separated list of alternative ports to listen to (default: '')" */
|
||||
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
||||
int show_banner_sys_info; /**<<< "Show banner system information (default: 1). Has no effect unless show_banner is enabled." */
|
||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
||||
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
||||
char* file_rules; /**<<< "File containing the rules (default: '' - no rules)" */
|
||||
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
||||
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
||||
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
||||
|
||||
@@ -28,10 +28,14 @@
|
||||
/* Send a broadcast message */
|
||||
#define UHUB_EVENT_BROADCAST 0x2000
|
||||
|
||||
/* Shutdown hub */
|
||||
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
|
||||
|
||||
/* Statistics, OOM, reconfigure */
|
||||
#define UHUB_EVENT_STATISTICS 0x4000
|
||||
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
|
||||
#define UHUB_EVENT_RECONFIGURE 0x4002
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_EVENT_ID_H */
|
||||
|
||||
|
||||
527
src/core/hub.c
527
src/core/hub.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -102,12 +102,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)
|
||||
{
|
||||
on_login_failure(hub, u, status_msg_hub_disabled);
|
||||
hub_free(arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
while (arg)
|
||||
{
|
||||
|
||||
if (strlen(arg) == 6)
|
||||
{
|
||||
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
|
||||
@@ -133,7 +133,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
||||
hub_free(arg);
|
||||
arg = adc_msg_get_argument(cmd, index);
|
||||
}
|
||||
|
||||
|
||||
if (u->state == state_protocol)
|
||||
{
|
||||
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
|
||||
@@ -141,7 +141,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
||||
if (ok)
|
||||
{
|
||||
hub_send_handshake(hub, u);
|
||||
user_set_timeout(u, TIMEOUT_HANDSHAKE);
|
||||
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -150,7 +150,7 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -183,18 +183,36 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
|
||||
char* message = adc_msg_get_argument(cmd, 0);
|
||||
int ret = 0;
|
||||
int relay = 1;
|
||||
|
||||
if (message[0] == '!' || message[0] == '+')
|
||||
int offset;
|
||||
|
||||
if (!message || !user_is_logged_in(u))
|
||||
return 0;
|
||||
|
||||
if ((cmd->cache[0] == 'B') && (message[0] == '!' || message[0] == '+'))
|
||||
{
|
||||
relay = command_dipatcher(hub, u, message);
|
||||
/*
|
||||
* 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) && (cmd->cache[0] == 'B' || cmd->cache[0] == 'F'))
|
||||
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;
|
||||
}
|
||||
|
||||
if (relay && user_is_logged_in(u))
|
||||
if (relay)
|
||||
{
|
||||
/* adc_msg_remove_named_argument(cmd, "PM"); */
|
||||
if (cmd->cache[0] == 'B')
|
||||
@@ -344,14 +362,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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct adc_message* igpa;
|
||||
@@ -400,153 +431,212 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
|
||||
user_destroy(user);
|
||||
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:
|
||||
/* FIXME: ignored */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct hub_info* hub_start_service(struct hub_config* config)
|
||||
{
|
||||
struct hub_info* hub = 0;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t sockaddr_size;
|
||||
int server_tcp, ret, ipv6_supported, af;
|
||||
char address_buf[INET6_ADDRSTRLEN+1];
|
||||
|
||||
int ipv6_supported;
|
||||
|
||||
hub = hub_malloc_zero(sizeof(struct hub_info));
|
||||
if (!hub)
|
||||
{
|
||||
LOG_FATAL("Unable to allocate memory for hub");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
hub->tm_started = time(0);
|
||||
|
||||
ipv6_supported = net_is_ipv6_supported();
|
||||
|
||||
if (ipv6_supported)
|
||||
LOG_DEBUG("IPv6 supported.");
|
||||
else
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
||||
|
||||
#ifdef LIBEVENT_1_4
|
||||
hub->evbase = event_base_new();
|
||||
#else
|
||||
hub->evbase = event_init();
|
||||
#ifdef SSL_SUPPORT
|
||||
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);
|
||||
}
|
||||
#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->users = NULL;
|
||||
|
||||
|
||||
if (uman_init(hub) == -1)
|
||||
{
|
||||
net_con_close(hub->server);
|
||||
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;
|
||||
}
|
||||
|
||||
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
|
||||
{
|
||||
net_con_close(hub->server);
|
||||
uman_shutdown(hub);
|
||||
hub_free(hub);
|
||||
net_close(server_tcp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
hub->recvbuf = hub_malloc(MAX_RECV_BUF);
|
||||
hub->sendbuf = hub_malloc(MAX_SEND_BUF);
|
||||
if (!hub->recvbuf || !hub->sendbuf)
|
||||
{
|
||||
net_con_close(hub->server);
|
||||
hub_free(hub->recvbuf);
|
||||
hub_free(hub->sendbuf);
|
||||
uman_shutdown(hub);
|
||||
hub_free(hub);
|
||||
net_close(server_tcp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -554,16 +644,18 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
||||
hub->logout_info = (struct linked_list*) list_create();
|
||||
if (!hub->chat_history)
|
||||
{
|
||||
net_con_close(hub->server);
|
||||
list_destroy(hub->chat_history);
|
||||
list_destroy(hub->logout_info);
|
||||
hub_free(hub->recvbuf);
|
||||
hub_free(hub->sendbuf);
|
||||
uman_shutdown(hub);
|
||||
hub_free(hub);
|
||||
net_close(server_tcp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
server_alt_port_start(hub, config);
|
||||
|
||||
hub->status = hub_status_running;
|
||||
|
||||
g_hub = hub;
|
||||
@@ -573,14 +665,14 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
||||
|
||||
void hub_shutdown_service(struct hub_info* hub)
|
||||
{
|
||||
LOG_TRACE("hub_shutdown_service()");
|
||||
LOG_DEBUG("hub_shutdown_service()");
|
||||
|
||||
event_queue_shutdown(hub->queue);
|
||||
event_del(&hub->ev_accept);
|
||||
net_close(hub->fd_tcp);
|
||||
net_con_close(hub->server);
|
||||
hub_free(hub->server);
|
||||
server_alt_port_stop(hub);
|
||||
uman_shutdown(hub);
|
||||
hub->status = hub_status_stopped;
|
||||
event_base_free(hub->evbase);
|
||||
hub_free(hub->sendbuf);
|
||||
hub_free(hub->recvbuf);
|
||||
hub_chat_history_clear(hub);
|
||||
@@ -592,17 +684,15 @@ void hub_shutdown_service(struct hub_info* hub)
|
||||
g_hub = 0;
|
||||
}
|
||||
|
||||
#define SERVER "" PRODUCT "/" VERSION ""
|
||||
|
||||
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||
{
|
||||
int fd, ret;
|
||||
char buf[MAX_RECV_BUF];
|
||||
char* tmp;
|
||||
char* server = adc_msg_escape(SERVER); /* FIXME: OOM */
|
||||
char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */
|
||||
|
||||
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)
|
||||
{
|
||||
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
|
||||
@@ -616,10 +706,10 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, tmp);
|
||||
hub_free(tmp);
|
||||
}
|
||||
|
||||
|
||||
/* (Re-)read the message of the day */
|
||||
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)
|
||||
{
|
||||
ret = read(fd, buf, MAX_RECV_BUF);
|
||||
@@ -628,31 +718,46 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
|
||||
buf[ret] = 0;
|
||||
tmp = adc_msg_escape(buf);
|
||||
hub->command_motd = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
|
||||
adc_msg_add_argument(hub->command_motd, tmp);
|
||||
adc_msg_add_argument(hub->command_motd, 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);
|
||||
}
|
||||
|
||||
hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT));
|
||||
if (hub->command_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)
|
||||
{
|
||||
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, tmp);
|
||||
hub_free(tmp);
|
||||
}
|
||||
|
||||
|
||||
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
|
||||
hub_free(server);
|
||||
}
|
||||
@@ -662,10 +767,13 @@ void hub_free_variables(struct hub_info* hub)
|
||||
{
|
||||
adc_msg_free(hub->command_info);
|
||||
adc_msg_free(hub->command_banner);
|
||||
|
||||
|
||||
if (hub->command_motd)
|
||||
adc_msg_free(hub->command_motd);
|
||||
|
||||
|
||||
if (hub->command_rules)
|
||||
adc_msg_free(hub->command_rules);
|
||||
|
||||
adc_msg_free(hub->command_support);
|
||||
}
|
||||
|
||||
@@ -718,62 +826,79 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
||||
{
|
||||
struct hub_config* cfg = hub->config;
|
||||
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
|
||||
if (!cmd) return;
|
||||
struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 256);
|
||||
char code[4];
|
||||
char buf[250];
|
||||
const char* text = 0;
|
||||
const char* flag = 0;
|
||||
char* escaped_text = 0;
|
||||
|
||||
#define STATUS(CODE, MSG, FLAG) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; break
|
||||
int reconnect_time = 0;
|
||||
|
||||
if (!cmd) return;
|
||||
|
||||
#define STATUS(CODE, MSG, FLAG, RCONTIME) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; break
|
||||
switch (msg)
|
||||
{
|
||||
STATUS(11, msg_hub_full, 0);
|
||||
STATUS(12, msg_hub_disabled, 0);
|
||||
STATUS(26, msg_hub_registered_users_only, 0);
|
||||
STATUS(43, msg_inf_error_nick_missing, 0);
|
||||
STATUS(43, msg_inf_error_nick_multiple, 0);
|
||||
STATUS(21, msg_inf_error_nick_invalid, 0);
|
||||
STATUS(21, msg_inf_error_nick_long, 0);
|
||||
STATUS(21, msg_inf_error_nick_short, 0);
|
||||
STATUS(21, msg_inf_error_nick_spaces, 0);
|
||||
STATUS(21, msg_inf_error_nick_bad_chars, 0);
|
||||
STATUS(21, msg_inf_error_nick_not_utf8, 0);
|
||||
STATUS(22, msg_inf_error_nick_taken, 0);
|
||||
STATUS(21, msg_inf_error_nick_restricted, 0);
|
||||
STATUS(43, msg_inf_error_cid_invalid, "FBID");
|
||||
STATUS(43, msg_inf_error_cid_missing, "FMID");
|
||||
STATUS(24, msg_inf_error_cid_taken, 0);
|
||||
STATUS(43, msg_inf_error_pid_missing, "FMPD");
|
||||
STATUS(27, msg_inf_error_pid_invalid, "FBPD");
|
||||
STATUS(31, msg_ban_permanently, 0);
|
||||
STATUS(32, msg_ban_temporarily, "TL600"); /* FIXME: Use a proper timeout */
|
||||
STATUS(23, msg_auth_invalid_password, 0);
|
||||
STATUS(20, msg_auth_user_not_found, 0);
|
||||
STATUS(30, msg_error_no_memory, 0);
|
||||
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE);
|
||||
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE);
|
||||
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
|
||||
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
|
||||
STATUS(43, msg_user_hub_limit_low, 0);
|
||||
STATUS(43, msg_user_hub_limit_high, 0);
|
||||
STATUS(11, msg_hub_full, 0, 600); /* FIXME: Proper timeout? */
|
||||
STATUS(12, msg_hub_disabled, 0, -1);
|
||||
STATUS(26, msg_hub_registered_users_only, 0, 0);
|
||||
STATUS(43, msg_inf_error_nick_missing, 0, 0);
|
||||
STATUS(43, msg_inf_error_nick_multiple, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_invalid, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_long, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_short, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_spaces, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_bad_chars, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_not_utf8, 0, 0);
|
||||
STATUS(22, msg_inf_error_nick_taken, 0, 0);
|
||||
STATUS(21, msg_inf_error_nick_restricted, 0, 0);
|
||||
STATUS(43, msg_inf_error_cid_invalid, "FBID", 0);
|
||||
STATUS(43, msg_inf_error_cid_missing, "FMID", 0);
|
||||
STATUS(24, msg_inf_error_cid_taken, 0, 0);
|
||||
STATUS(43, msg_inf_error_pid_missing, "FMPD", 0);
|
||||
STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0);
|
||||
STATUS(31, msg_ban_permanently, 0, 0);
|
||||
STATUS(32, msg_ban_temporarily, "TL600", 600); /* FIXME: Proper timeout? */
|
||||
STATUS(23, msg_auth_invalid_password, 0, 0);
|
||||
STATUS(20, msg_auth_user_not_found, 0, 0);
|
||||
STATUS(30, msg_error_no_memory, 0, 0);
|
||||
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
|
||||
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
|
||||
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
|
||||
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
|
||||
STATUS(43, msg_user_hub_limit_low, 0, 0);
|
||||
STATUS(43, msg_user_hub_limit_high, 0, 0);
|
||||
}
|
||||
#undef STATUS
|
||||
|
||||
escaped_text = adc_msg_escape(text);
|
||||
|
||||
|
||||
adc_msg_add_argument(cmd, code);
|
||||
adc_msg_add_argument(cmd, escaped_text);
|
||||
|
||||
hub_free(escaped_text);
|
||||
|
||||
|
||||
if (flag)
|
||||
{
|
||||
adc_msg_add_argument(cmd, flag);
|
||||
}
|
||||
|
||||
|
||||
route_to_user(hub, user, cmd);
|
||||
|
||||
if (level >= status_level_fatal)
|
||||
{
|
||||
snprintf(buf, 230, "MS%s", escaped_text);
|
||||
adc_msg_add_argument(cmd, buf);
|
||||
|
||||
if (reconnect_time != 0)
|
||||
{
|
||||
snprintf(buf, 10, "TL%d", reconnect_time);
|
||||
adc_msg_add_argument(cmd, buf);
|
||||
}
|
||||
route_to_user(hub, user, cmd);
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -931,27 +1056,6 @@ size_t hub_get_min_hubs_op(struct hub_info* hub)
|
||||
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)
|
||||
{
|
||||
struct event_data post;
|
||||
@@ -966,11 +1070,42 @@ 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)
|
||||
{
|
||||
struct event_data post;
|
||||
int need_notify = 0;
|
||||
|
||||
|
||||
/* is user already being disconnected ? */
|
||||
if (user_is_disconnecting(user))
|
||||
{
|
||||
@@ -978,11 +1113,13 @@ void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
need_notify = user_is_logged_in(user);
|
||||
need_notify = user_is_logged_in(user) && hub->status == hub_status_running;
|
||||
user->quit_reason = reason;
|
||||
user_set_state(user, state_cleanup);
|
||||
|
||||
@@ -1006,7 +1143,7 @@ void hub_logout_log(struct hub_info* hub, struct hub_user* user)
|
||||
loginfo->time = time(NULL);
|
||||
strcpy(loginfo->cid, user->id.cid);
|
||||
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;
|
||||
|
||||
list_append(hub->logout_info, loginfo);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -45,7 +45,7 @@ enum status_message
|
||||
status_msg_auth_invalid_password = -21, /* Password is wrong */
|
||||
status_msg_auth_user_not_found = -22, /* User not found in password database */
|
||||
status_msg_error_no_memory = -23, /* Hub is out of memory */
|
||||
|
||||
|
||||
status_msg_user_share_size_low = -40, /* User is not sharing enough. */
|
||||
status_msg_user_share_size_high = -41, /* User is sharing too much. */
|
||||
status_msg_user_slots_low = -42, /* User has too few slots open. */
|
||||
@@ -90,18 +90,17 @@ struct hub_logout_info
|
||||
|
||||
struct hub_info
|
||||
{
|
||||
int fd_tcp;
|
||||
struct event ev_accept;
|
||||
struct event ev_timer;
|
||||
struct net_connection* server;
|
||||
struct linked_list* server_alt_ports;
|
||||
struct hub_stats stats;
|
||||
struct event_queue* queue;
|
||||
struct event_base* evbase;
|
||||
struct hub_config* config;
|
||||
struct hub_user_manager* users;
|
||||
struct acl_handle* acl;
|
||||
struct adc_message* command_info; /* The hub's INF command */
|
||||
struct adc_message* command_support; /* The hub's SUP command */
|
||||
struct adc_message* command_motd; /* The message of the day */
|
||||
struct adc_message* command_rules; /* The hub rules */
|
||||
struct adc_message* command_banner; /* The default welcome message */
|
||||
time_t tm_started;
|
||||
int status;
|
||||
@@ -202,8 +201,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
|
||||
* 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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||
}
|
||||
|
||||
static void log_user_update_error(struct hub_user* u, enum status_message msg)
|
||||
{
|
||||
const char* addr = user_get_address(u);
|
||||
const char* message = hub_get_status_message_log(u->hub, msg);
|
||||
LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
|
||||
}
|
||||
|
||||
static void log_user_logout(struct hub_user* u, const char* message)
|
||||
{
|
||||
const char* addr = 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -67,9 +74,13 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
|
||||
/* Send message of the day (if any) */
|
||||
if (user_is_logged_in(u)) /* Previous send() can fail! */
|
||||
hub_send_motd(hub, u);
|
||||
|
||||
/* reset to idle timeout */
|
||||
user_set_timeout(u, TIMEOUT_IDLE);
|
||||
|
||||
/* Send message of the day (if any) */
|
||||
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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (user_is_logged_in(u))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,11 +20,6 @@
|
||||
#include "uhub.h"
|
||||
#include "hubio.h"
|
||||
|
||||
// #define SEND_CHUNKS 1
|
||||
|
||||
/* FIXME: This should not be needed! */
|
||||
extern struct hub_info* g_hub;
|
||||
|
||||
#ifdef DEBUG_SENDQ
|
||||
static void debug_msg(const char* prefix, struct adc_message* msg)
|
||||
{
|
||||
@@ -146,58 +141,22 @@ void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
||||
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;
|
||||
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 */
|
||||
int ret;
|
||||
struct adc_message* msg = list_get_first(q->queue);
|
||||
while (msg)
|
||||
{
|
||||
length = MIN(msg->length - offset, (max_send_buf-1) - bytes);
|
||||
memcpy(sbuf + bytes, msg->cache + offset, length);
|
||||
bytes += length;
|
||||
|
||||
if (length < (msg->length - offset))
|
||||
break;
|
||||
offset = 0;
|
||||
msg = list_get_next(q->queue);
|
||||
}
|
||||
if (!msg) return 0;
|
||||
|
||||
msg = list_get_first(q->queue);
|
||||
|
||||
/* Send as much as possible */
|
||||
ret = w(data, sbuf, bytes);
|
||||
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
#ifdef SSL_SUPPORT
|
||||
q->last_write_n = ret;
|
||||
#endif
|
||||
q->offset += ret;
|
||||
if (msg->length - q->offset > 0)
|
||||
return 0;
|
||||
|
||||
/* Remove messages sent */
|
||||
offset = q->offset;
|
||||
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;
|
||||
}
|
||||
hub_sendq_remove(q, msg);
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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.
|
||||
* @returns the number of bytes sent.
|
||||
* FIXME: send error not handled here!
|
||||
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -46,8 +46,11 @@ 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))
|
||||
{
|
||||
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
||||
if (!tmp)
|
||||
return -1; // FIXME: OOM
|
||||
|
||||
user_clear_feature_cast_support(u);
|
||||
|
||||
|
||||
it = tmp;
|
||||
while (strlen(it) > 4)
|
||||
{
|
||||
@@ -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
|
||||
* 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 */
|
||||
if (acl_is_ip_nat_override(hub->acl, address))
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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_UDP_PORT);
|
||||
@@ -523,7 +526,6 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the expected credentials, and returns 1 if authentication is needed,
|
||||
* or 0 if not.
|
||||
@@ -645,7 +647,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
|
||||
return ret; \
|
||||
} 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. */
|
||||
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_acl, hub, user, cmd);
|
||||
INF_CHECK(check_logged_in, hub, user, cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -713,6 +714,7 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
||||
*/
|
||||
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
||||
{
|
||||
int ret;
|
||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||
if (!cmd) return -1; /* OOM */
|
||||
|
||||
@@ -734,8 +736,8 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
||||
adc_msg_free(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ret = hub_handle_info_login(hub, user, cmd);
|
||||
|
||||
ret = hub_handle_info_login(hub, user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
on_login_failure(hub, user, ret);
|
||||
@@ -760,7 +762,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
||||
/* These must not be allowed updated, let's remove them! */
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
|
||||
|
||||
|
||||
/*
|
||||
* If the nick is not accepted, do not relay it.
|
||||
* Otherwise, the nickname will be updated.
|
||||
@@ -772,9 +774,15 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
||||
#endif
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
||||
}
|
||||
|
||||
/* FIXME - What if limits are not met ? */
|
||||
check_limits(hub, user, cmd);
|
||||
|
||||
ret = check_limits(hub, user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
on_update_failure(hub, user, ret);
|
||||
adc_msg_free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strip_network(user, cmd);
|
||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@ static const char* arg_pid = 0;
|
||||
static int arg_log_syslog = 0;
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
void hub_handle_signal(int fd, short events, void* arg)
|
||||
#if !defined(WIN32)
|
||||
extern struct hub_info* g_hub;
|
||||
void hub_handle_signal(int sig)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
int signal = fd;
|
||||
struct hub_info* hub = g_hub;
|
||||
|
||||
switch (signal)
|
||||
switch (sig)
|
||||
{
|
||||
case SIGINT:
|
||||
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[] =
|
||||
{
|
||||
SIGINT, /* Interrupt the application */
|
||||
@@ -77,12 +76,18 @@ static int signals[] =
|
||||
|
||||
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++)
|
||||
{
|
||||
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
|
||||
event_base_set(hub->evbase, &signal_events[i]);
|
||||
if (signal_add(&signal_events[i], NULL))
|
||||
if (sigaction(signals[i], &act, 0) != 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; signals[i]; i++)
|
||||
{
|
||||
signal_del(&signal_events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
#endif /* !WIN32 */
|
||||
|
||||
|
||||
int main_loop()
|
||||
@@ -134,7 +133,7 @@ int main_loop()
|
||||
hub = hub_start_service(&configuration);
|
||||
if (!hub)
|
||||
return -1;
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32)
|
||||
setup_signal_handlers(hub);
|
||||
#endif
|
||||
}
|
||||
@@ -147,9 +146,9 @@ int main_loop()
|
||||
acl_shutdown(&acl);
|
||||
free_config(&configuration);
|
||||
|
||||
} while(hub->status != hub_status_shutdown);
|
||||
} while (hub->status == hub_status_restart);
|
||||
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32)
|
||||
shutdown_signal_handlers(hub);
|
||||
#endif
|
||||
|
||||
@@ -191,8 +190,8 @@ int check_configuration(int dump)
|
||||
|
||||
void print_version()
|
||||
{
|
||||
fprintf(stdout, "" PRODUCT " " VERSION "\n");
|
||||
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
|
||||
fprintf(stdout, PRODUCT_STRING "\n");
|
||||
fprintf(stdout, COPYRIGHT "\n"
|
||||
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +17,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include <uhub.h>
|
||||
#include "hubio.h"
|
||||
#include "probe.h"
|
||||
|
||||
/* FIXME: This should not be needed! */
|
||||
extern struct hub_info* g_hub;
|
||||
@@ -26,7 +27,7 @@ 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);
|
||||
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->connection->sd, sent, total);
|
||||
if (sent == -1)
|
||||
{
|
||||
int err = net_error();
|
||||
@@ -52,105 +53,26 @@ void debug_sendq_recv(struct hub_user* user, int received, int max, const char*
|
||||
}
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
ssize_t size = net_user_recv(user, &buf[buf_size], MAX_RECV_BUF - buf_size);
|
||||
ssize_t size = net_con_recv(user->connection, buf, MAX_RECV_BUF);
|
||||
|
||||
if (size > 0)
|
||||
buf_size += size;
|
||||
|
||||
if (size == -1)
|
||||
if (size < 0)
|
||||
{
|
||||
if (net_error() == EWOULDBLOCK || net_error() == EINTR)
|
||||
return 0;
|
||||
|
||||
return quit_socket_error;
|
||||
if (size == -1)
|
||||
return quit_disconnected;
|
||||
else
|
||||
return quit_socket_error;
|
||||
}
|
||||
else if (size == 0)
|
||||
{
|
||||
return quit_disconnected;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -179,7 +101,6 @@ int handle_net_read(struct hub_user* user)
|
||||
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
|
||||
{
|
||||
return quit_protocol_error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,16 +111,17 @@ int handle_net_read(struct hub_user* user)
|
||||
start = pos;
|
||||
}
|
||||
|
||||
if (lastPos)
|
||||
if (lastPos || remaining)
|
||||
{
|
||||
if (remaining < g_hub->config->max_recv_buffer)
|
||||
{
|
||||
hub_recvq_set(q, lastPos, remaining);
|
||||
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_recvq_set(q, 0, 0);
|
||||
user_flag_set(user, flag_maxbuf);
|
||||
LOG_WARN("Received message past max_recv_buffer, dropping message.");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -212,17 +134,18 @@ int handle_net_read(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);
|
||||
if (ret == -2)
|
||||
break;
|
||||
|
||||
ret = hub_sendq_send(user->send_queue, user);
|
||||
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);
|
||||
}
|
||||
@@ -233,77 +156,53 @@ int handle_net_write(struct hub_user* user)
|
||||
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;
|
||||
int flag_close = 0;
|
||||
|
||||
#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
|
||||
|
||||
if (ev & EV_TIMEOUT)
|
||||
if (event == NET_EVENT_TIMEOUT)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
void net_on_accept(struct net_connection* con, int event, void *arg)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
struct hub_user* user = 0;
|
||||
struct hub_probe* probe = 0;
|
||||
struct ip_addr_encap ipaddr;
|
||||
const char* addr;
|
||||
|
||||
int server_fd = net_con_get_sd(con);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int fd = net_accept(server_fd, &ipaddr);
|
||||
@@ -319,32 +218,27 @@ void net_on_accept(int server_fd, short ev, void *arg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addr = ip_convert_to_string(&ipaddr);
|
||||
|
||||
/* FIXME: Should have a plugin log this */
|
||||
LOG_TRACE("Got connection from %s", addr);
|
||||
|
||||
|
||||
/* FIXME: A plugin should perform this check: is IP banned? */
|
||||
if (acl_is_ip_banned(hub->acl, addr))
|
||||
{
|
||||
LOG_INFO("Denied [%s] (IP banned)", addr);
|
||||
net_close(fd);
|
||||
net_con_close(con);
|
||||
continue;
|
||||
}
|
||||
|
||||
user = user_create(hub, fd);
|
||||
if (!user)
|
||||
|
||||
probe = probe_create(hub, fd, &ipaddr);
|
||||
if (!probe)
|
||||
{
|
||||
LOG_ERROR("Unable to create user after socket accepted. Out of memory?");
|
||||
net_close(fd);
|
||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||
net_con_close(con);
|
||||
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
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,9 +23,8 @@
|
||||
/**
|
||||
* Network callback to accept incoming connections.
|
||||
*/
|
||||
extern void net_on_accept(int fd, short ev, void *arg);
|
||||
|
||||
extern void net_event(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 int handle_net_read(struct hub_user* user);
|
||||
extern int handle_net_write(struct hub_user* user);
|
||||
|
||||
119
src/core/probe.c
Normal file
119
src/core/probe.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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");
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
probe_destroy(probe);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
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;
|
||||
}
|
||||
|
||||
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 1;
|
||||
}
|
||||
@@ -97,17 +103,20 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
|
||||
free(data);
|
||||
#endif
|
||||
|
||||
if (hub_sendq_is_empty(user->net.send_queue) && !user_flag_get(user, flag_pipeline))
|
||||
if (!user->connection)
|
||||
return 0;
|
||||
|
||||
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||
{
|
||||
/* Perform oportunistic write */
|
||||
hub_sendq_add(user->net.send_queue, msg);
|
||||
hub_sendq_add(user->send_queue, msg);
|
||||
handle_net_write(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
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))
|
||||
user_net_io_want_write(user);
|
||||
}
|
||||
@@ -117,7 +126,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)
|
||||
{
|
||||
if (hub_sendq_is_empty(u->net.send_queue))
|
||||
if (hub_sendq_is_empty(u->send_queue))
|
||||
return 0;
|
||||
|
||||
handle_net_write(u);
|
||||
@@ -197,7 +206,7 @@ int route_info_message(struct hub_info* hub, struct hub_user* u)
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -35,28 +35,24 @@ static const char* user_log_str(struct hub_user* user)
|
||||
}
|
||||
#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;
|
||||
|
||||
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));
|
||||
|
||||
if (user == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
user->net.tm_connected = time(NULL);
|
||||
user->net.send_queue = hub_sendq_create();
|
||||
user->net.recv_queue = hub_recvq_create();
|
||||
user->send_queue = hub_sendq_create();
|
||||
user->recv_queue = hub_recvq_create();
|
||||
|
||||
net_con_initialize(&user->net.connection, sd, user, EV_READ);
|
||||
|
||||
evtimer_set(&user->net.timeout, net_event, user);
|
||||
event_base_set(hub->evbase, &user->net.timeout);
|
||||
|
||||
user_set_timeout(user, TIMEOUT_CONNECTED);
|
||||
user->connection = con;
|
||||
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
|
||||
|
||||
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
||||
user_set_state(user, state_protocol);
|
||||
return user;
|
||||
}
|
||||
@@ -66,11 +62,8 @@ void user_destroy(struct hub_user* user)
|
||||
{
|
||||
LOG_TRACE("user_destroy(), user=%p", user);
|
||||
|
||||
net_con_close(&user->net.connection);
|
||||
evtimer_del(&user->net.timeout);
|
||||
|
||||
hub_recvq_destroy(user->net.recv_queue);
|
||||
hub_sendq_destroy(user->net.send_queue);
|
||||
hub_recvq_destroy(user->recv_queue);
|
||||
hub_sendq_destroy(user->send_queue);
|
||||
|
||||
adc_msg_free(user->info);
|
||||
user_clear_feature_cast_support(user);
|
||||
@@ -140,33 +133,36 @@ static int convert_support_fourcc(int fourcc)
|
||||
#endif
|
||||
case FOURCC('B','A','S','E'):
|
||||
return feature_base;
|
||||
|
||||
|
||||
case FOURCC('A','U','T','0'):
|
||||
return feature_auto;
|
||||
|
||||
|
||||
case FOURCC('U','C','M','0'):
|
||||
case FOURCC('U','C','M','D'):
|
||||
return feature_ucmd;
|
||||
|
||||
|
||||
case FOURCC('Z','L','I','F'):
|
||||
return feature_zlif;
|
||||
|
||||
|
||||
case FOURCC('B','B','S','0'):
|
||||
return feature_bbs;
|
||||
|
||||
|
||||
case FOURCC('T','I','G','R'):
|
||||
return feature_tiger;
|
||||
|
||||
|
||||
case FOURCC('B','L','O','M'):
|
||||
case FOURCC('B','L','O','0'):
|
||||
return feature_bloom;
|
||||
|
||||
|
||||
case FOURCC('P','I','N','G'):
|
||||
return feature_ping;
|
||||
|
||||
|
||||
case FOURCC('L','I','N','K'):
|
||||
return feature_link;
|
||||
|
||||
|
||||
case FOURCC('A','D','C','S'):
|
||||
return feature_adcs;
|
||||
|
||||
default:
|
||||
LOG_DEBUG("Unknown extension: %x", fourcc);
|
||||
return 0;
|
||||
@@ -318,37 +314,12 @@ int user_is_registered(struct hub_user* user)
|
||||
|
||||
void user_net_io_want_write(struct hub_user* user)
|
||||
{
|
||||
#ifdef DEBUG_SENDQ
|
||||
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);
|
||||
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||
}
|
||||
|
||||
void user_net_io_want_read(struct hub_user* user)
|
||||
{
|
||||
#ifdef DEBUG_SENDQ
|
||||
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);
|
||||
net_con_update(user->connection, NET_EVENT_READ);
|
||||
}
|
||||
|
||||
const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
||||
@@ -365,6 +336,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
||||
case quit_socket_error: return "socket error"; break;
|
||||
case quit_protocol_error: return "protocol 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_ghost_timeout: return "ghost"; break;
|
||||
}
|
||||
@@ -372,4 +344,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
||||
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
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -44,6 +44,8 @@ enum user_flags
|
||||
feature_bloom = 0x00000040, /** BLO0: Bloom filter (not supported) */
|
||||
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
||||
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
||||
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
|
||||
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
||||
flag_ignore = 0x01000000, /** Ignore further reads */
|
||||
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
||||
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
|
||||
@@ -66,8 +68,9 @@ enum user_quit_reason
|
||||
quit_socket_error = 7, /** A socket error occured */
|
||||
quit_protocol_error = 8, /** Fatal protocol error */
|
||||
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
||||
quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */
|
||||
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */
|
||||
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
|
||||
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 */
|
||||
@@ -78,6 +81,7 @@ struct hub_user_info
|
||||
sid_t sid; /** session ID */
|
||||
char cid[MAX_CID_LEN+1]; /** global client ID */
|
||||
char nick[MAX_NICK_LEN+1]; /** User's nick name */
|
||||
struct ip_addr_encap addr; /** User's IP address */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -87,40 +91,30 @@ struct hub_user_info
|
||||
*/
|
||||
struct hub_user_limits
|
||||
{
|
||||
uint64_t shared_size; /** Shared size in bytes */
|
||||
size_t shared_files; /** The number of shared files */
|
||||
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_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_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 */
|
||||
uint64_t shared_size; /** Shared size in bytes */
|
||||
size_t shared_files; /** The number of shared files */
|
||||
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_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_total; /** The number of hubs connected to in total */
|
||||
};
|
||||
|
||||
struct hub_user
|
||||
{
|
||||
struct hub_user_net_io net; /** Network information data */
|
||||
enum user_state state; /** see enum user_state */
|
||||
enum user_credentials credentials; /** see enum user_credentials */
|
||||
struct hub_user_info id; /** Contains nick name and CID */
|
||||
int flags; /** see enum user_features */
|
||||
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
||||
struct linked_list* feature_cast; /** Features supported by feature cast */
|
||||
struct 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_user_limits limits; /** Data used for limitation */
|
||||
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
||||
enum user_state state; /** see enum user_state */
|
||||
enum user_credentials credentials; /** see enum user_credentials */
|
||||
struct hub_user_info id; /** Contains nick name and CID */
|
||||
uint32_t flags; /** see enum user_features */
|
||||
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
||||
struct linked_list* feature_cast; /** Features supported by feature cast */
|
||||
struct 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_recvq* recv_queue;
|
||||
struct hub_sendq* send_queue;
|
||||
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) */
|
||||
|
||||
};
|
||||
|
||||
@@ -135,7 +129,7 @@ struct hub_user
|
||||
* @param sd socket descriptor associated with the user
|
||||
* @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.
|
||||
@@ -217,6 +211,8 @@ extern void user_support_add(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
|
||||
* subnet as a natted hub to spoof their IP in order to use active mode
|
||||
@@ -269,24 +265,6 @@ extern void user_net_io_want_write(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 */
|
||||
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
#define USERMANAGER_TIMER
|
||||
|
||||
/*
|
||||
* This callback function is used to clear user objects from the userlist.
|
||||
* 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)
|
||||
{
|
||||
const int factor = TIMEOUT_STATS;
|
||||
@@ -58,10 +55,9 @@ void uman_update_stats(struct hub_info* hub)
|
||||
net_stats_reset();
|
||||
}
|
||||
|
||||
|
||||
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_peak,
|
||||
(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);
|
||||
}
|
||||
|
||||
#ifdef USERMANAGER_TIMER
|
||||
static void timer_statistics(int fd, short ev, void *arg)
|
||||
static void timer_statistics(struct timeout_evt* t)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
struct timeval timeout = { TIMEOUT_STATS, 0 };
|
||||
struct hub_info* hub = (struct hub_info*) t->ptr;
|
||||
uman_update_stats(hub);
|
||||
evtimer_set(&hub->ev_timer, timer_statistics, hub);
|
||||
event_base_set(hub->evbase, &hub->ev_timer);
|
||||
evtimer_add(&hub->ev_timer, &timeout);
|
||||
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->users->timeout, TIMEOUT_STATS);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int uman_init(struct hub_info* hub)
|
||||
{
|
||||
struct hub_user_manager* users = NULL;
|
||||
#ifdef USERMANAGER_TIMER
|
||||
struct timeval timeout = { TIMEOUT_STATS, 0 };
|
||||
#endif
|
||||
if (!hub)
|
||||
return -1;
|
||||
|
||||
@@ -102,19 +89,18 @@ int uman_init(struct hub_info* hub)
|
||||
if (!users->list)
|
||||
{
|
||||
list_destroy(users->list);
|
||||
hub_free(users);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hub->users = users;
|
||||
|
||||
#ifdef USERMANAGER_TIMER
|
||||
if (hub->evbase)
|
||||
if (net_backend_get_timeout_queue())
|
||||
{
|
||||
evtimer_set(&hub->ev_timer, timer_statistics, hub);
|
||||
event_base_set(hub->evbase, &hub->ev_timer);
|
||||
evtimer_add(&hub->ev_timer, &timeout);
|
||||
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||
timeout_evt_initialize(users->timeout, timer_statistics, hub);
|
||||
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
hub->users = users;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -124,10 +110,11 @@ int uman_shutdown(struct hub_info* hub)
|
||||
if (!hub || !hub->users)
|
||||
return -1;
|
||||
|
||||
#ifdef USERMANAGER_TIMER
|
||||
if (evtimer_pending(&hub->ev_timer, 0))
|
||||
event_del(&hub->ev_timer);
|
||||
#endif
|
||||
if (net_backend_get_timeout_queue())
|
||||
{
|
||||
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
|
||||
hub_free(hub->users->timeout);
|
||||
}
|
||||
|
||||
if (hub->users->list)
|
||||
{
|
||||
@@ -138,6 +125,7 @@ int uman_shutdown(struct hub_info* hub)
|
||||
hub_free(hub->users);
|
||||
hub->users = 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 */
|
||||
while (user)
|
||||
{
|
||||
if (ip_in_range(&user->net.ipaddr, range))
|
||||
if (ip_in_range(&user->id.addr, range))
|
||||
{
|
||||
list_append(users, user);
|
||||
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 ret = 1;
|
||||
struct hub_user* user;
|
||||
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)
|
||||
{
|
||||
if (user_is_logged_in(user))
|
||||
|
||||
@@ -27,7 +27,8 @@ struct hub_user_manager
|
||||
struct sid_pool* sids;
|
||||
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
|
||||
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
|
||||
struct linked_list* list; /**<< "Contains all users" */
|
||||
struct linked_list* list; /**<< "Contains all logged in users" */
|
||||
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
217
src/network/backend.c
Normal file
217
src/network/backend.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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, 600); /* FIXME: max 600 secs! */
|
||||
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
||||
|
||||
for (n = 0; n < sizeof(net_backend_init_funcs); n++)
|
||||
{
|
||||
if (!net_backend_init_funcs[n])
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
89
src/network/backend.h
Normal file
89
src/network/backend.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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();
|
||||
|
||||
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
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,35 +18,311 @@
|
||||
*/
|
||||
|
||||
#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;
|
||||
con->ptr = (void*) ptr;
|
||||
tls_st_none,
|
||||
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);
|
||||
event_base_set(g_hub->evbase, &con->event);
|
||||
event_add(&con->event, 0);
|
||||
static int handle_openssl_error(struct net_connection* con, int ret)
|
||||
{
|
||||
uhub_assert(con);
|
||||
|
||||
int error = SSL_get_error(con->ssl, ret);
|
||||
switch (error)
|
||||
{
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
|
||||
con->ssl_state = tls_st_error;
|
||||
return -1;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
|
||||
con->flags |= NET_WANT_SSL_READ;
|
||||
net_con_update(con, NET_EVENT_READ);
|
||||
return 0;
|
||||
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
|
||||
con->flags |= NET_WANT_SSL_WRITE;
|
||||
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||
return 0;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SYSCALL", ret, error);
|
||||
/* if ret == 0, connection closed, if ret == -1, check with errno */
|
||||
if (ret == 0)
|
||||
return -1;
|
||||
else
|
||||
return -net_error();
|
||||
|
||||
case SSL_ERROR_SSL:
|
||||
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
|
||||
/* internal openssl error */
|
||||
con->ssl_state = tls_st_error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
event_del(&con->event);
|
||||
event_set(&con->event, con->sd, events | EV_PERSIST, net_event, con->ptr);
|
||||
event_add(&con->event, 0);
|
||||
}
|
||||
|
||||
void net_con_close(struct net_connection* con)
|
||||
{
|
||||
if (!event_pending(&con->event, EV_READ | EV_WRITE, 0))
|
||||
if (events == NET_EVENT_TIMEOUT)
|
||||
{
|
||||
LOG_TRACE("net_con_callback(%p, TIMEOUT", con);
|
||||
con->callback(con, events, con->ptr);
|
||||
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
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,21 +21,91 @@
|
||||
#define HAVE_UHUB_NETWORK_CONNECTION_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
|
||||
{
|
||||
int sd; /** socket descriptor */
|
||||
void* ptr; /** data pointer */
|
||||
struct event event; /** libevent struct for read/write events */
|
||||
#ifdef SSL_SUPPORT
|
||||
SSL* ssl; /** SSL handle */
|
||||
#endif /* SSL_SUPPORT */
|
||||
NET_CON_STRUCT_COMMON
|
||||
};
|
||||
|
||||
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_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);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
|
||||
186
src/network/epoll.c
Normal file
186
src/network/epoll.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.");
|
||||
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 */
|
||||
186
src/network/kqueue.c
Normal file
186
src/network/kqueue.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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;
|
||||
};
|
||||
|
||||
struct net_backend_kqueue
|
||||
{
|
||||
int kqfd;
|
||||
struct net_connection_kqueue** conns;
|
||||
struct kevent** changes;
|
||||
size_t nchanges;
|
||||
struct kevent events[KQUEUE_EVBUFFER];
|
||||
struct net_backend_common* common;
|
||||
};
|
||||
|
||||
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||
|
||||
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;
|
||||
|
||||
tspec.tv_sec = (ms / 1000);
|
||||
tspec.tv_nsec = ((ms % 1000) * 1000000); /* FIXME: correct? */
|
||||
|
||||
res = kevent(backend->kqfd, *backend->changes, backend->nchanges, backend->events, KQUEUE_EVBUFFER, &tspec);
|
||||
backend->nchanges = 0;
|
||||
|
||||
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;
|
||||
int ev = 0;
|
||||
if (backend->events[n].filter & EVFILT_READ) ev |= NET_EVENT_READ;
|
||||
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)
|
||||
{
|
||||
short filter = 0;
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
||||
backend->changes[backend->nchanges++] = &con->ev;
|
||||
backend->conns[con->sd] = con;
|
||||
}
|
||||
|
||||
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||
{
|
||||
short filter = 0;
|
||||
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||
|
||||
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
||||
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
||||
|
||||
if (filter == con->ev.filter)
|
||||
return;
|
||||
|
||||
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
||||
backend->changes[backend->nchanges++] = &con->ev;
|
||||
}
|
||||
|
||||
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_;
|
||||
|
||||
backend->conns[con->sd] = 0;
|
||||
|
||||
/* No need to remove it from the kqueue filter, the kqueue man page says
|
||||
it is automatically removed when the descriptor is closed. */
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||
backend->changes = hub_malloc_zero(sizeof(struct kevent*) * 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;
|
||||
}
|
||||
|
||||
#endif /* USE_KQUEUE */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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 net_initialized = 0;
|
||||
|
||||
static struct net_statistics stats;
|
||||
static struct net_statistics stats_total;
|
||||
|
||||
@@ -35,6 +36,7 @@ int net_initialize()
|
||||
{
|
||||
if (!net_initialized)
|
||||
{
|
||||
LOG_TRACE("Initializing network monitor.");
|
||||
|
||||
#ifdef WINSOCK
|
||||
struct WSAData wsa;
|
||||
@@ -45,13 +47,19 @@ int net_initialize()
|
||||
}
|
||||
#endif /* WINSOCK */
|
||||
|
||||
LOG_TRACE("Initializing network monitor.");
|
||||
if (!net_backend_init())
|
||||
{
|
||||
#ifdef WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
net_stats_initialize();
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
LOG_TRACE("Initializing OpenSSL...");
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
#endif /* SSL_SUPPORT */
|
||||
|
||||
@@ -67,13 +75,19 @@ size_t net_get_max_sockets()
|
||||
struct rlimit limits;
|
||||
if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
|
||||
{
|
||||
return limits.rlim_max;
|
||||
return MIN(limits.rlim_max, 65536);
|
||||
}
|
||||
LOG_ERROR("getrlimit() failed");
|
||||
#else
|
||||
LOG_ERROR("System does not have getrlimit(): constrained to 1024 sockets");
|
||||
#endif /* HAVE_GETRLIMIT */
|
||||
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");
|
||||
|
||||
net_backend_shutdown();
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
/* FIXME: Shutdown OpenSSL here. */
|
||||
#endif
|
||||
@@ -96,6 +112,13 @@ int net_destroy()
|
||||
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)
|
||||
{
|
||||
int err = net_error();
|
||||
@@ -165,8 +188,18 @@ int net_set_nonblocking(int fd, int toggle)
|
||||
#ifdef WINSOCK
|
||||
u_long on = toggle ? 1 : 0;
|
||||
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
|
||||
ret = ioctl(fd, FIONBIO, &toggle);
|
||||
#endif
|
||||
#endif
|
||||
if (ret == -1)
|
||||
{
|
||||
@@ -270,7 +303,7 @@ int net_close(int fd)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fd != -1)
|
||||
if (ret != -1)
|
||||
{
|
||||
net_stats_add_error();
|
||||
}
|
||||
@@ -324,6 +357,9 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
||||
{
|
||||
switch (net_error())
|
||||
{
|
||||
#if defined(__HAIKU__)
|
||||
case ETIMEDOUT:
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
case ENETDOWN:
|
||||
case EPROTO:
|
||||
@@ -349,16 +385,16 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
||||
if (ipaddr)
|
||||
{
|
||||
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
||||
ipaddr->af = addr4->sin_family;
|
||||
ipaddr->af = addr.ss_family;;
|
||||
if (ipaddr->af == AF_INET6)
|
||||
{
|
||||
char address[INET6_ADDRSTRLEN+1] = { 0, };
|
||||
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 */
|
||||
net_string_to_address(AF_INET, address + 7, (void*) &ipaddr->internal_ip_data.in);
|
||||
ipaddr->af = AF_INET;
|
||||
net_string_to_address(AF_INET, address, (void*) &ipaddr->internal_ip_data.in);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -441,6 +477,7 @@ int net_socket_create(int af, int type, int protocol)
|
||||
if (sd == -1)
|
||||
{
|
||||
net_error_out(sd, "net_socket_create");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#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;
|
||||
#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
|
||||
}
|
||||
|
||||
@@ -545,9 +590,6 @@ int net_string_to_address(int af, const char* src, void* dst)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const char* net_get_peer_address(int fd)
|
||||
{
|
||||
static char address[INET6_ADDRSTRLEN+1];
|
||||
@@ -555,9 +597,10 @@ const char* net_get_peer_address(int fd)
|
||||
struct sockaddr_in6* name6;
|
||||
struct sockaddr_in* name4;
|
||||
struct sockaddr* name;
|
||||
socklen_t namelen;
|
||||
|
||||
memset(address, 0, INET6_ADDRSTRLEN);
|
||||
socklen_t namelen = sizeof(struct sockaddr_storage);
|
||||
namelen = sizeof(struct sockaddr_storage);
|
||||
memset(&storage, 0, namelen);
|
||||
|
||||
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)
|
||||
{
|
||||
int af = name4->sin_family;
|
||||
int af = storage.ss_family;
|
||||
if (af == AF_INET6)
|
||||
{
|
||||
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
|
||||
{
|
||||
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
|
||||
return address;
|
||||
}
|
||||
return address;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -591,6 +629,46 @@ const char* net_get_peer_address(int fd)
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -32,15 +32,6 @@ struct net_statistics
|
||||
|
||||
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.
|
||||
* 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 struct event_base* net_get_evbase();
|
||||
|
||||
/**
|
||||
* @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_local_address(int fd);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
148
src/network/timeout.c
Normal file
148
src/network/timeout.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
size_t events = 0;
|
||||
struct timeout_evt* evt = 0;
|
||||
for (pos = t->last; pos <= now; pos++)
|
||||
{
|
||||
while ((evt = t->events[pos % t->max]))
|
||||
{
|
||||
timeout_queue_remove(t, evt);
|
||||
evt->callback(evt);
|
||||
events++;
|
||||
}
|
||||
}
|
||||
t->last = now;
|
||||
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)
|
||||
{
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "adcclient.h"
|
||||
|
||||
#define ADC_CLIENTS_DEFAULT 100
|
||||
#define ADC_MAX_CLIENTS 25000
|
||||
|
||||
#define ADC_BUFSIZE 16384
|
||||
#define ADC_SIDSIZE 4
|
||||
#define ADC_CID_SIZE 39
|
||||
|
||||
#define BIG_BUFSIZE 131072
|
||||
#define BIG_BUFSIZE 32768
|
||||
#define TIGERSIZE 24
|
||||
|
||||
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR\n"
|
||||
#define ADCRUSH "adcrush/0.2"
|
||||
#define ADCRUSH "adcrush/0.3"
|
||||
#define ADC_NICK "[BOT]adcrush"
|
||||
#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 void ADC_client_on_connected(struct ADC_client*);
|
||||
static void ADC_client_on_login(struct ADC_client*);
|
||||
static void ADC_client_connect(struct ADC_client*);
|
||||
static void ADC_client_disconnect(struct ADC_client*);
|
||||
static int ADC_client_create(struct ADC_client* client, int num);
|
||||
static void ADC_client_destroy(struct ADC_client* client);
|
||||
|
||||
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 */
|
||||
};
|
||||
static const char* cfg_uri = 0; /* address */
|
||||
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;
|
||||
|
||||
#define MAX_CHAT_MSGS 35
|
||||
const char* chat_messages[MAX_CHAT_MSGS] = {
|
||||
@@ -155,69 +78,21 @@ const char* search_messages[MAX_SEARCH_MSGS] = {
|
||||
"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, const char* format, ...)
|
||||
static void bot_output(struct ADC_client* client, int level, const char* format, ...)
|
||||
{
|
||||
char logmsg[1024];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(logmsg, 1024, format, args);
|
||||
va_end(args);
|
||||
if (cfg_mode == mode_log)
|
||||
{
|
||||
fprintf(stdout, "%s\n", 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 (cfg_debug >= level)
|
||||
fprintf(stdout, "* [%p] %s\n", client, logmsg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static size_t get_wait_rand(size_t max)
|
||||
{
|
||||
static size_t next = 0;
|
||||
@@ -226,315 +101,9 @@ static size_t get_wait_rand(size_t 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 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)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
@@ -559,7 +128,7 @@ static void perf_chat(struct ADC_client* client, int priv)
|
||||
hub_free(msg);
|
||||
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
ADC_client_send(client, buf);
|
||||
}
|
||||
|
||||
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, "\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)
|
||||
@@ -601,7 +170,7 @@ static void perf_result(struct ADC_client* client, sid_t target, const char* wha
|
||||
strcat(buf, " TO");
|
||||
strcat(buf, token);
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
ADC_client_send(client, buf);
|
||||
}
|
||||
|
||||
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, sid_to_string(client->sid));
|
||||
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, "\n");
|
||||
send_client(client, buf);
|
||||
ADC_client_send(client, buf);
|
||||
}
|
||||
|
||||
|
||||
static void perf_normal_action(struct ADC_client* client)
|
||||
{
|
||||
size_t r = get_wait_rand(5);
|
||||
@@ -645,7 +213,7 @@ static void perf_normal_action(struct ADC_client* client)
|
||||
case 0:
|
||||
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);
|
||||
}
|
||||
break;
|
||||
@@ -653,114 +221,95 @@ static void perf_normal_action(struct ADC_client* client)
|
||||
case 1:
|
||||
if (cfg_chat)
|
||||
{
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> chat");
|
||||
bot_output(client, LVL_VERBOSE, "timeout -> chat");
|
||||
perf_chat(client, 0);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> search");
|
||||
bot_output(client, LVL_VERBOSE, "timeout -> search");
|
||||
perf_search(client);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> update");
|
||||
bot_output(client, LVL_VERBOSE, "timeout -> update");
|
||||
perf_update(client);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> privmsg");
|
||||
bot_output(client, LVL_VERBOSE, "timeout -> privmsg");
|
||||
perf_chat(client, 1);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> ctm/rcm");
|
||||
bot_output(client, LVL_VERBOSE, "timeout -> ctm/rcm");
|
||||
perf_ctm(client);
|
||||
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;
|
||||
|
||||
if (ev & EV_READ)
|
||||
switch (type)
|
||||
{
|
||||
if (recv_client(client) == -1)
|
||||
{
|
||||
ADC_client_on_disconnected(client);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & EV_TIMEOUT)
|
||||
{
|
||||
if (client->state == ps_none)
|
||||
{
|
||||
if (client->sd == -1)
|
||||
{
|
||||
ADC_client_create(client, client->num);
|
||||
}
|
||||
|
||||
ADC_client_connect(client);
|
||||
}
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
if (client->state == ps_normal && cfg_mode == mode_performance)
|
||||
{
|
||||
perf_normal_action(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & EV_WRITE)
|
||||
{
|
||||
if (client->state == ps_conn)
|
||||
{
|
||||
ADC_client_on_connected(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Call send again */
|
||||
}
|
||||
|
||||
case ADC_CLIENT_CONNECTING:
|
||||
bot_output(client, LVL_DEBUG, "*** Connecting...");
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_CONNECTED:
|
||||
bot_output(client, LVL_DEBUG, "*** Connected.");
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_DISCONNECTED:
|
||||
bot_output(client, LVL_DEBUG, "*** Disconnected.");
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_LOGGING_IN:
|
||||
bot_output(client, LVL_DEBUG, "*** Logging in...");
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_PASSWORD_REQ:
|
||||
bot_output(client, LVL_DEBUG, "*** Requesting password.");
|
||||
|
||||
case ADC_CLIENT_LOGGED_IN:
|
||||
bot_output(client, LVL_DEBUG, "*** Logged in.");
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_LOGIN_ERROR:
|
||||
bot_output(client, LVL_DEBUG, "*** Login error");
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_MESSAGE:
|
||||
bot_output(client, LVL_DEBUG, " <%s> %s", sid_to_string(data->chat->from_sid), data->chat->message);
|
||||
break;
|
||||
|
||||
case ADC_CLIENT_USER_JOIN:
|
||||
bot_output(client, LVL_VERBOSE, " JOIN: %s", data->user->name);
|
||||
break;
|
||||
|
||||
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)
|
||||
{
|
||||
size_t n = 0;
|
||||
@@ -771,23 +320,24 @@ void runloop(size_t clients)
|
||||
struct ADC_client* c = malloc(sizeof(struct ADC_client));
|
||||
client[n] = c;
|
||||
|
||||
ADC_client_create(c, n);
|
||||
if (n == 0)
|
||||
{
|
||||
ADC_client_connect(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADC_client_wait_connect(c);
|
||||
}
|
||||
char nick[20];
|
||||
snprintf(nick, 20, "adcrush_%d", (int) n);
|
||||
|
||||
ADC_client_create(c, nick, "stresstester");
|
||||
ADC_client_set_callback(c, handle);
|
||||
ADC_client_connect(c, cfg_uri);
|
||||
}
|
||||
|
||||
while (running)
|
||||
{
|
||||
net_backend_process();
|
||||
}
|
||||
|
||||
event_dispatch();
|
||||
|
||||
for (n = 0; n < clients; n++)
|
||||
{
|
||||
ADC_client_destroy(client[n]);
|
||||
free(client[n]);
|
||||
client[n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,102 +352,29 @@ static void print_usage(const char* program)
|
||||
{
|
||||
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(" Modes\n");
|
||||
printf(" perf Do performance testing using multiple clients\n");
|
||||
printf(" bugs Bugs mode, use fuzzer to construct pseudo-random commands.\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(" 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(" -c Allow broadcasting chat messages.\n");
|
||||
printf(" -d Enable debug 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");
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
char* split;
|
||||
struct hostent* dns;
|
||||
struct in_addr* addr;
|
||||
|
||||
if (!arg)
|
||||
if (!arg || strlen(arg) < 9)
|
||||
return 0;
|
||||
|
||||
if (strncmp(arg, "adc://", 6) && strncmp(arg, "adcs://", 7))
|
||||
return 0;
|
||||
|
||||
if (strlen(arg) < 9)
|
||||
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;
|
||||
|
||||
cfg_uri = arg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -905,7 +382,7 @@ int parse_arguments(int argc, char** argv)
|
||||
{
|
||||
int ok = 1;
|
||||
int opt;
|
||||
for (opt = 3; opt < argc; opt++)
|
||||
for (opt = 2; opt < argc; opt++)
|
||||
{
|
||||
if (!strcmp(argv[opt], "-c"))
|
||||
cfg_chat = 1;
|
||||
@@ -929,9 +406,7 @@ int parse_arguments(int argc, char** argv)
|
||||
void parse_command_line(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2 ||
|
||||
!parse_mode(argv[1]) ||
|
||||
!set_defaults() ||
|
||||
!parse_address(argv[2]) ||
|
||||
!parse_address(argv[1]) ||
|
||||
!parse_arguments(argc, argv))
|
||||
{
|
||||
print_usage(argv[0]);
|
||||
@@ -943,16 +418,12 @@ int main(int argc, char** argv)
|
||||
parse_command_line(argc, argv);
|
||||
|
||||
net_initialize();
|
||||
event_init();
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(cfg_port);
|
||||
net_string_to_address(AF_INET, cfg_host, &saddr.sin_addr);
|
||||
|
||||
runloop(cfg_clients);
|
||||
net_destroy();
|
||||
|
||||
hub_log_initialize(NULL, 0);
|
||||
hub_set_log_verbosity(1000);
|
||||
|
||||
runloop(cfg_clients);
|
||||
|
||||
net_destroy();
|
||||
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 */
|
||||
};
|
||||
|
||||
111
src/uhub.h
111
src/uhub.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,100 +25,7 @@
|
||||
/* #define MEMORY_DEBUG */
|
||||
/* #define DEBUG_SENDQ 1 */
|
||||
|
||||
#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(__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
|
||||
#include "system.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#define SERVER_CONFIG "/etc/uhub/uhub.conf"
|
||||
@@ -134,10 +41,8 @@
|
||||
#define TIMEOUT_CONNECTED 15
|
||||
#define TIMEOUT_HANDSHAKE 30
|
||||
#define TIMEOUT_SENDQ 120
|
||||
#define TIMEOUT_IDLE 7200
|
||||
#define TIMEOUT_STATS 60
|
||||
|
||||
#define MAX_CLIENTS 512
|
||||
#define MAX_CID_LEN 39
|
||||
#define MAX_NICK_LEN 64
|
||||
#define MAX_UA_LEN 32
|
||||
@@ -146,19 +51,12 @@
|
||||
#define MAX_RECV_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
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "adc/adcconst.h"
|
||||
|
||||
#include "util/ipcalc.h"
|
||||
#include "util/list.h"
|
||||
#include "util/log.h"
|
||||
@@ -170,6 +68,7 @@ extern "C" {
|
||||
#include "adc/message.h"
|
||||
#include "network/network.h"
|
||||
#include "network/connection.h"
|
||||
#include "network/timeout.h"
|
||||
|
||||
#include "core/auth.h"
|
||||
#include "core/config.h"
|
||||
|
||||
@@ -451,11 +451,12 @@ int ip_convert_address_to_range(const char* address, struct ip_range* range)
|
||||
{
|
||||
int ret = 0;
|
||||
char* addr = 0;
|
||||
const char* split;
|
||||
|
||||
if (!address || !range)
|
||||
return 0;
|
||||
|
||||
const char* split = strrchr(address, '/');
|
||||
split = strrchr(address, '/');
|
||||
if (split)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (list->last)
|
||||
|
||||
@@ -47,7 +47,7 @@ void internal_debug_print_leaks()
|
||||
size_t n = 0;
|
||||
size_t leak = 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++)
|
||||
{
|
||||
@@ -55,11 +55,11 @@ void internal_debug_print_leaks()
|
||||
{
|
||||
leak += hub_allocs[n].size;
|
||||
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 */
|
||||
|
||||
@@ -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_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;
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ void internal_debug_mem_free(void* ptr)
|
||||
hub_allocs[n].size = 0;
|
||||
hub_allocs[n].stack1 = 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;
|
||||
free(ptr);
|
||||
return;
|
||||
|
||||
104
src/util/misc.c
104
src/util/misc.c
@@ -45,12 +45,15 @@ static int is_printable(unsigned char c)
|
||||
char* strip_white_space(char* string)
|
||||
{
|
||||
char* pos;
|
||||
|
||||
|
||||
if (!string)
|
||||
return "";
|
||||
|
||||
while (string[0] && is_white_space(string[0])) string++;
|
||||
|
||||
|
||||
if (!*string)
|
||||
return 0;
|
||||
|
||||
return string;
|
||||
|
||||
/* Strip appending whitespace */
|
||||
pos = &string[strlen(string)-1];
|
||||
while (&string[0] < &pos[0] && is_white_space(pos[0])) { pos[0] = 0; pos--; }
|
||||
@@ -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 fd;
|
||||
ssize_t ret;
|
||||
char buf[MAX_RECV_BUF];
|
||||
char *pos, *start;
|
||||
size_t line_count = 0;
|
||||
struct file_read_line_data split_data;
|
||||
|
||||
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);
|
||||
close(fd);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
close(fd);
|
||||
LOG_WARN("File is empty.");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
close(fd);
|
||||
|
||||
/* Parse configuaration */
|
||||
start = buf;
|
||||
while ((pos = strchr(start, '\n')))
|
||||
{
|
||||
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)
|
||||
{
|
||||
buf[strlen(start)] = 0;
|
||||
LOG_DUMP("Line: %s", start);
|
||||
if (handler(start, line_count+1, data) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return line_count+1;
|
||||
|
||||
/* Parse configuaration */
|
||||
split_data.handler = handler;
|
||||
split_data.data = data;
|
||||
|
||||
return string_split(buf, "\n", &split_data, file_read_line_handler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ extern char* strip_white_space(char* string);
|
||||
|
||||
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_ulltoa(uint64_t val);
|
||||
|
||||
@@ -61,6 +62,8 @@ void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_
|
||||
struct linked_list;
|
||||
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 */
|
||||
|
||||
|
||||
@@ -47,10 +47,13 @@ extern uint64_t tiger_sboxes[4*256];
|
||||
ROUND(b, c, a, x7, mul)
|
||||
|
||||
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 aa, bb, cc;
|
||||
#if PASSES > 3
|
||||
uint64_t swap;
|
||||
size_t pass_no;
|
||||
#endif
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
@@ -107,7 +110,8 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) {
|
||||
x7 -= x6 ^ 0x0123456789ABCDEFULL;
|
||||
|
||||
PASS(b, c, a, 9);
|
||||
|
||||
|
||||
#if PASSES > 3
|
||||
for (pass_no = 3; pass_no < PASSES; pass_no++)
|
||||
{
|
||||
x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL;
|
||||
@@ -134,7 +138,8 @@ void tiger_compress(uint64_t* str, uint64_t state[3]) {
|
||||
c = b;
|
||||
b = swap;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
a ^= aa;
|
||||
b -= bb;
|
||||
c += cc;
|
||||
|
||||
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
|
||||
#define PRODUCT "uHub"
|
||||
#define PRODUCT "uhub"
|
||||
#endif
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "0.3.1"
|
||||
#endif
|
||||
|
||||
#ifndef GIT_REVISION
|
||||
#define REVISION ""
|
||||
#define PRODUCT_STRING PRODUCT "/" VERSION
|
||||
#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
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "0.3.0-rc4" REVISION
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user