Compare commits

...

99 Commits

Author SHA1 Message Date
Jan Vidar Krey
8e579f4601 Fix #123: accept() fails if IP is banned. 2010-04-05 13:44:17 +02:00
Jan Vidar Krey
e220357176 Added configuration option to enable support for obsolete pre-ADC/1.0 clients. 2010-04-05 13:43:28 +02:00
Jan Vidar Krey
8bed952022 Fixed nasty hub freeze caused by timers being injected for the same timestamp as it is being removed from. 2010-03-23 01:06:04 +01:00
Jan Vidar Krey
c4604a7e94 Make code clearer. 2010-03-23 00:46:25 +01:00
Jan Vidar Krey
236daeae53 Assert if inserting an invalid timer. 2010-03-15 22:59:16 +01:00
Jan Vidar Krey
862c6a1baf Reduce timeout queue window size. 2010-03-13 00:16:15 +01:00
Jan Vidar Krey
198d86a1ee Added some automatic tests for the timeout handling. 2010-02-25 17:57:50 +01:00
Jan Vidar Krey
2ded9f3e09 Make the revision file if it does not exist. 2010-02-25 16:38:05 +01:00
Jan Vidar Krey
59ed268f4d Added test cases for sid allocation.
This revealed a few bugs:
* when sid allocator is full, then uhub will loop indefinitely when allocating one more (unlikely to occur).
* looking up a user object based on a sid that is out of range (off by one) returns invalid memory.
2010-02-18 16:02:13 +01:00
Jan Vidar Krey
963416ad73 Cleanup reference adc message reference counting somewhat. 2010-02-16 20:51:10 +01:00
Jan Vidar Krey
29c162727c Added lots of new asserts which should trigger in case we double delete a ADC message. 2010-02-15 19:03:19 +01:00
Jan Vidar Krey
1ce258bccf Tidy up the certificate loading code somewhat. 2010-02-15 19:02:31 +01:00
Jan Vidar Krey
0de66286fa Partially fix bug #117 - tls_require ignored entirely in 0.3.0 released
If tls_require is enabled then the hub will simply close the connection if a
user connects without TLS.
In the future we should redirect the user either to another server or to the adcs server.
2010-02-15 19:00:48 +01:00
Jan Vidar Krey
1a98bb6810 Added optional include of local makefile. 2010-02-15 18:56:23 +01:00
Jan Vidar Krey
5e6879dffb Fix for partial read operations. 2010-02-12 20:33:17 +01:00
Jan Vidar Krey
1b56adb8c0 Fix wrong IQUI message. Partially fixes bug #4. 2010-02-12 19:25:09 +01:00
Jan Vidar Krey
685597c795 Make sure we delete the revision.h files when updating.
Also, only use annotated tags for git revision numbers.
2010-02-11 09:16:30 +01:00
Jan Vidar Krey
782f091637 Bump to 0.3.1-rc1 2010-02-11 09:03:07 +01:00
Jan Vidar Krey
82eeaa1fba Fix bug #114: FreeBSD compile error. 2010-02-11 07:54:42 +01:00
Jan Vidar Krey
977b57a385 Prefer the git-describe version number if it exists. 2010-02-11 01:21:08 +01:00
Jan Vidar Krey
19b9f72337 Make sure !version agrees with the connect time banner (same format). 2010-02-11 01:19:58 +01:00
Jan Vidar Krey
56605f7dcb Fix autotest crash. 2010-02-11 01:18:45 +01:00
Jan Vidar Krey
bf1b64db53 Write git revision to a header file, then make version.h depend on that file. 2010-02-11 01:03:09 +01:00
Jan Vidar Krey
915cb56448 Fix bug #106: Show OS/CPU info in !version.
This can be controlled by the configuration variable "show_banner_sys_info" which is enabled by default.
2010-02-10 23:45:51 +01:00
Jan Vidar Krey
6992043f9d Fix bug #113: crash when using epoll backend. 2010-02-10 22:06:49 +01:00
Jan Vidar Krey
896bbfcb5d Compile multiple network backends into the binary and choose which one to use at runtime.
This makes it possible to share more code between the backends and also work around
bugs of certain backends on some (versions of) operating systems.
2010-02-10 22:00:13 +01:00
Jan Vidar Krey
6ac78e1a10 Fix autotest 2010-02-08 00:35:58 +01:00
Jan Vidar Krey
74a2191350 Fix bug #111: Added nmdc-redirector similar to the adc-redirector. 2010-02-07 23:37:21 +01:00
Jan Vidar Krey
be8db21561 Fix bug #109: Confusing debug message for nat_ip. 2010-02-07 23:29:38 +01:00
Jan Vidar Krey
8065903604 Fix bug #108: share limits can be avoided.
This was due to updates to the share limit not being enforced after a succesful login.
2010-02-07 23:08:04 +01:00
Jan Vidar Krey
78ae9fb3ce Fix documentation about file descriptor limits. 2010-02-05 22:40:35 +01:00
root
4715815ba2 Update getstartd.txt for hub with more that 1024 users. 2010-02-05 09:40:57 +03:00
root
cb9625f6a5 update example uhub.conf 2010-02-02 13:43:10 +03:00
root
9934bde050 add in README list of compatible ADC clients 2010-02-01 15:36:46 +03:00
root
9a1c5ee548 - update .spec file; - cosmetic in init.d scripts 2010-02-01 12:22:12 +03:00
Jan Vidar Krey
11df912162 libevent is NOT needed at all (nor is it supported) 2010-01-31 23:40:11 +01:00
root
c8bc2f64fd update .ebuild ; update compile doc ; update RHEL init.d 2010-01-29 22:05:39 +03:00
Jan Vidar Krey
2dc95eca47 SunOS support. 2010-01-28 01:35:09 +01:00
Jan Vidar Krey
7637d9ba68 Added experimental Haiku OS support.
It compiles and it runs with some minor glitches.
2010-01-28 01:35:08 +01:00
Jan Vidar Krey
4e9488dd4d gcc 2.95 compile fixes. 2010-01-28 01:11:11 +01:00
Jan Vidar Krey
e0003ebbb2 Only define MIN/MAX macros if not defined by the system. 2010-01-28 01:07:05 +01:00
Jan Vidar Krey
8e7e8c68f5 gcc v2.95 compile fixes. 2010-01-28 01:06:41 +01:00
root
db32eaeafc update doc/uhub.conf for multiple ports 2010-01-28 10:53:03 +03:00
Jan Vidar Krey
1599f63134 Make sure the autotests work. 2010-01-28 00:07:42 +01:00
Jan Vidar Krey
c3ad006d07 Fix bug #76: added support for multiple server listen ports.
Use server_alt_ports and supply a comma separated list of ports.
2010-01-27 23:55:52 +01:00
Jan Vidar Krey
1faca92167 Added a generic string splitter utility function that is based on callbacks instead of populating a list. 2010-01-27 23:55:05 +01:00
Jan Vidar Krey
f0a13b4c23 Updated .ebuild and .spec files. 2010-01-27 19:01:50 +01:00
Jan Vidar Krey
ccd1c8f160 kqueue() BSD fixes 2010-01-27 17:50:02 +01:00
Jan Vidar Krey
41418f21e7 Winsock compile fix. 2010-01-27 17:48:16 +01:00
Jan Vidar Krey
7a8a737cad More kqueue work in progress. 2010-01-27 01:04:32 +01:00
Jan Vidar Krey
ac48ad01fb Work in progress on the kqueue backend. 2010-01-27 00:43:10 +01:00
Jan Vidar Krey
31a69b1f3f Thanks to E_zombie for all the Centos/RedHat contributions 2010-01-26 23:55:27 +01:00
Jan Vidar Krey
d7a1a52c1a Started working kqueue() backend for OSX and BSD. 2010-01-26 23:30:32 +01:00
Jan Vidar Krey
f54e8dbbba Moved the timeout code to where it belongs, along with the network backend code. 2010-01-26 22:55:08 +01:00
Jan Vidar Krey
de72d4ae63 Merge branch 'master' of baracus-vpn:~/git/uhub 2010-01-26 17:46:51 +01:00
Jan Vidar Krey
01efc6cc20 Fixes for debian init.d scripts. 2010-01-26 17:46:47 +01:00
Jan Vidar Krey
7cf1181e6b Merge branch 'master' of github.com:janvidar/uhub 2010-01-26 17:28:45 +01:00
Jan Vidar Krey
4b64b28777 Added proper debian package scripts. 2010-01-26 17:27:34 +01:00
root
e9f0331ca8 Merge branch 'master' of git://github.com/janvidar/uhub 2010-01-26 19:17:16 +03:00
root
f263534aaf add .ebuild 2010-01-26 19:16:28 +03:00
Jan Vidar Krey
788b644c80 Merge branch 'master' of github.com:janvidar/uhub 2010-01-26 16:16:48 +01:00
Jan Vidar Krey
2d7ffa37fe Fix problem parsing configuration file if the last line is not empty 2010-01-26 16:16:41 +01:00
root
fbaac98483 .spec Require fix 2010-01-26 17:39:57 +03:00
root
bd9d8229ff add .SPEC file for build RPM in RHEL based distrs 2010-01-26 17:32:42 +03:00
Jan Vidar Krey
dfa6d07455 Merge branch 'master' of github.com:janvidar/uhub 2010-01-26 12:04:55 +01:00
root
6bbdd24cb7 Merge branch 'master' of git://github.com/janvidar/uhub 2010-01-26 13:05:56 +03:00
root
e3a644a853 Stupid mistake in path 2010-01-26 13:00:11 +03:00
Jan Vidar Krey
928225fb7b On Mac OS X getrlimit() returns 2^(sizeof(size_t) * 8) instead of the actual number of available socket descriptors. 2010-01-26 08:40:10 +01:00
Jan Vidar Krey
e3cf41cb97 BSD/OSX compile fix. 2010-01-25 14:23:22 +01:00
Jan Vidar Krey
59f67f9e17 Updated ChangeLog and README. 2010-01-24 23:38:25 +01:00
Jan Vidar Krey
bfc7c184a7 Fix release build compile warnings. 2010-01-23 14:59:51 +01:00
Jan Vidar Krey
92c448b855 Dont use SSL by default. 2010-01-23 01:09:00 +01:00
Jan Vidar Krey
304ecda16a Enable the statistics timer again, so that !stats provide up to date network statistics. 2010-01-23 00:43:38 +01:00
Jan Vidar Krey
c670d13369 Make sure we shutdown SSL connections when an error occurs. 2010-01-23 00:20:48 +01:00
Jan Vidar Krey
b2e7a2848f Optimize epoll to never modify the epoll mask unless it actually changed. 2010-01-23 00:03:45 +01:00
Jan Vidar Krey
84bd2591d6 SSL fixes, seems to work with stunnel4 as a client but not linuxdcpp using SSL directly. 2010-01-22 23:43:23 +01:00
Jan Vidar Krey
4aa65733d0 Poll as long as possible until next timeout the earliest. 2010-01-22 23:18:59 +01:00
Jan Vidar Krey
230ca28b46 Some unfinished SSL work. 2010-01-22 18:52:38 +01:00
Jan Vidar Krey
5f353ebe28 Added script to create SSL certificate. 2010-01-22 18:22:39 +01:00
Jan Vidar Krey
68a26e1160 Added proper POSIX signal handler. 2010-01-22 16:57:30 +01:00
Jan Vidar Krey
4711d26c11 Fix broken net_address_to_string(). 2010-01-22 16:09:19 +01:00
Jan Vidar Krey
1bb3bd90c1 Use non-default port to ensure autotests work even though a hub is running on the default port. 2010-01-22 16:05:48 +01:00
Jan Vidar Krey
5e253e8442 Fix compile error. 2010-01-22 16:04:36 +01:00
Jan Vidar Krey
26a2a384b6 Bump to version 0.3.0 2010-01-22 16:01:54 +01:00
Jan Vidar Krey
8b7f09c7f4 Fixed two cases of bad connection close. 2010-01-21 23:54:38 +01:00
Jan Vidar Krey
b29da11f3b Make sure we call the timeout code. 2010-01-21 23:52:04 +01:00
Jan Vidar Krey
78ad9b8572 Fixed bad logic inside the timer scheduling. 2010-01-21 23:13:52 +01:00
Jan Vidar Krey
b04a20c66e fixed off by one bug in due to message escape. 2010-01-21 22:20:26 +01:00
Jan Vidar Krey
21a5981905 Make sure start_listening_socket does everything, this will lead the way to multiple listen ports. 2010-01-21 17:31:55 +01:00
Jan Vidar Krey
c47ea14047 Code cleanup for starting the listening socket. 2010-01-21 01:54:41 +01:00
Jan Vidar Krey
9f5aaf0148 Added a safe connection cleanup procedure for when a connection goes
down while it may be attempted to be used.
2010-01-21 01:12:57 +01:00
Jan Vidar Krey
f645811f37 Merge branch 'master' of github.com:janvidar/uhub 2010-01-20 18:42:45 +01:00
Jan Vidar Krey
2f09fcea84 Added select() backend which can be used as a fallback if epoll is not available. 2010-01-20 18:39:55 +01:00
root
5e679e2d4f - add doc/init.d.RedHat/etc/logrotator.d/uhub file 2010-01-20 11:18:16 +03:00
root
efeb36c492 - update uhub.conf example after add !rules
- add example rules.txt
- fix compile warning in  src/util/timeout.c
- add example config file for rotate log file in RHEL\CentOS
2010-01-20 11:12:43 +03:00
Jan Vidar Krey
7e60919596 sorted the commands shown in help. 2010-01-20 00:24:57 +01:00
Jan Vidar Krey
e7cb4cd277 remove extra space before !broadcast messages 2010-01-20 00:12:39 +01:00
Jan Vidar Krey
e45511827f Added the +rules command.
Also added the +motd command to see the message of the day, which is sent while connecting.
2010-01-19 23:30:26 +01:00
Jan Vidar Krey
80c6ad9d76 Added mute/unmute functionality. 2010-01-19 23:07:55 +01:00
81 changed files with 2743 additions and 1318 deletions

View File

@@ -2,5 +2,5 @@ Authors of uHub
=============== ===============
Jan Vidar Krey, Design and implementation Jan Vidar Krey, Design and implementation
E_zombie, Centos/RedHat customization scripts and heavy load testing

8
BSDmakefile Normal file
View File

@@ -0,0 +1,8 @@
GMAKE=gmake
all:
@${GMAKE} ${.TARGETS}
${.TARGETS}: all

View File

@@ -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: 0.2.8:
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead. - Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
- Fix bug #10: Improve logging, ensure logs are machine readable. - Fix bug #10: Improve logging, ensure logs are machine readable.

View File

@@ -3,13 +3,14 @@
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org> ## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
# #
-include Makefile.private
CC = gcc CC = gcc
LD := $(CC) LD := $(CC)
MV := mv MV := mv
RANLIB := ranlib RANLIB := ranlib
CFLAGS += -pipe -Wall CFLAGS += -pipe -Wall
USE_SSL ?= NO USE_SSL ?= NO
USE_LIBEVENT ?= NO
USE_BIGENDIAN ?= AUTO USE_BIGENDIAN ?= AUTO
BITS ?= AUTO BITS ?= AUTO
SILENT ?= YES SILENT ?= YES
@@ -18,15 +19,22 @@ STACK_PROTECT ?= NO
ifeq ($(OS), Windows_NT) ifeq ($(OS), Windows_NT)
WINDOWS ?= YES WINDOWS ?= YES
OPSYS ?= Windows
else
OPSYS ?= $(shell uname)
endif endif
ifeq (SOLARIS,YES) ifeq ($(OPSYS),SunOS)
LDLIBS += -lsocket -lnsl LDLIBS += -lsocket -lnsl
endif endif
ifeq ($(OPSYS),Haiku)
LDLIBS += -lnetwork
endif
CFLAGS += -I./src/ CFLAGS += -I./src/
ifeq ($(WINDOWS),YES) ifeq ($(OPSYS),Windows)
USE_BIGENDIAN := NO USE_BIGENDIAN := NO
LDLIBS += -lws2_32 LDLIBS += -lws2_32
UHUB_CONF_DIR ?= c:/uhub/ UHUB_CONF_DIR ?= c:/uhub/
@@ -34,7 +42,6 @@ UHUB_PREFIX ?= c:/uhub/
CFLAGS += -mno-cygwin CFLAGS += -mno-cygwin
LDFLAGS += -mno-cygwin LDFLAGS += -mno-cygwin
BIN_EXT ?= .exe BIN_EXT ?= .exe
GIT_REVISION ?= NO
else else
DESTDIR ?= / DESTDIR ?= /
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
@@ -45,7 +52,7 @@ BIN_EXT ?=
endif endif
ifeq ($(SILENT),YES) ifeq ($(SILENT),YES)
MSG_CC=@echo " CC:" $(notdir $^) && MSG_CC=@echo " CC:" $(notdir $<) &&
MSG_LD=@echo " LD:" $(notdir $@) && MSG_LD=@echo " LD:" $(notdir $@) &&
MSG_AR=@echo " AR:" $(notdir $@) && MSG_AR=@echo " AR:" $(notdir $@) &&
else else
@@ -63,15 +70,10 @@ else
MSG_CLEAN="Clean as a whistle" MSG_CLEAN="Clean as a whistle"
endif endif
# CFLAGS += -I/source/libevent
# LDFLAGS += -L/source/libevent
ifeq ($(RELEASE),YES) ifeq ($(RELEASE),YES)
CFLAGS += -O3 -DNDEBUG CFLAGS += -O3 -DNDEBUG
GIT_REVISION ?= NO
else else
CFLAGS += -ggdb -DDEBUG CFLAGS += -ggdb -DDEBUG
GIT_REVISION ?= YES
endif endif
ifeq ($(STACK_PROTECT),YES) ifeq ($(STACK_PROTECT),YES)
@@ -116,18 +118,9 @@ CFLAGS += -DSSL_SUPPORT
LDLIBS += -lssl LDLIBS += -lssl
endif endif
ifeq ($(USE_LIBEVENT),YES) GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
CFLAGS += -DUSE_LIBEVENT GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
LDLIBS += -levent OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
ifneq ($(LIBEVENT_PATH),)
CFLAGS += -I$(LIBEVENT_PATH)
LDFLAGS += -L$(LIBEVENT_PATH)
endif
endif
ifeq ($(GIT_REVISION),YES)
CFLAGS += -DGIT_REVISION=\"$(shell git show --abbrev-commit | head -n 1 | cut -f 2 -d " ")\"
endif
# Sources # Sources
libuhub_SOURCES := \ libuhub_SOURCES := \
@@ -144,17 +137,20 @@ libuhub_SOURCES := \
src/core/route.c \ src/core/route.c \
src/core/user.c \ src/core/user.c \
src/core/usermanager.c \ src/core/usermanager.c \
src/network/backend.c \
src/network/connection.c \ src/network/connection.c \
src/network/epoll.c \ src/network/epoll.c \
src/network/libevent.c \ src/network/kqueue.c \
src/network/network.c \ src/network/network.c \
src/network/select.c \
src/network/timeout.c \
src/network/timer.c \
src/util/ipcalc.c \ src/util/ipcalc.c \
src/util/list.c \ src/util/list.c \
src/util/log.c \ src/util/log.c \
src/util/memory.c \ src/util/memory.c \
src/util/misc.c \ src/util/misc.c \
src/util/rbtree.c \ src/util/rbtree.c \
src/util/timeout.c \
src/util/tiger.c src/util/tiger.c
libadc_common_SOURCES := \ libadc_common_SOURCES := \
@@ -171,16 +167,18 @@ adcrush_SOURCES := src/tools/adcrush.c
admin_SOURCES := src/tools/admin.c admin_SOURCES := src/tools/admin.c
autotest_SOURCES := \ autotest_SOURCES := \
autotest/test_message.tcc \ autotest/test_eventqueue.tcc \
autotest/test_hub.tcc \
autotest/test_inf.tcc \
autotest/test_ipfilter.tcc \
autotest/test_list.tcc \ autotest/test_list.tcc \
autotest/test_memory.tcc \ autotest/test_memory.tcc \
autotest/test_ipfilter.tcc \ autotest/test_message.tcc \
autotest/test_inf.tcc \
autotest/test_hub.tcc \
autotest/test_misc.tcc \ autotest/test_misc.tcc \
autotest/test_sid.tcc \
autotest/test_tiger.tcc \ autotest/test_tiger.tcc \
autotest/test_usermanager.tcc \ autotest/test_timer.tcc \
autotest/test_eventqueue.tcc autotest/test_usermanager.tcc
autotest_OBJECTS = autotest.o autotest_OBJECTS = autotest.o
@@ -200,8 +198,10 @@ adcrush_BINARY=adcrush$(BIN_EXT)
admin_BINARY=uhub-admin$(BIN_EXT) admin_BINARY=uhub-admin$(BIN_EXT)
autotest_BINARY=autotest/test$(BIN_EXT) autotest_BINARY=autotest/test$(BIN_EXT)
%.o: %.c .PHONY: revision.h.tmp
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $^
%.o: %.c version.h revision.h
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
all: $(uhub_BINARY) all: $(uhub_BINARY)
@@ -217,6 +217,18 @@ $(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
autotest.c: $(autotest_SOURCES) autotest.c: $(autotest_SOURCES)
$(shell exotic --standalone $(autotest_SOURCES) > $@) $(shell exotic --standalone $(autotest_SOURCES) > $@)
revision.h.tmp:
@rm -f $@
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
version.h: revision.h
revision.h: revision.h.tmp
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
$(autotest_OBJECTS): autotest.c $(autotest_OBJECTS): autotest.c
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $< $(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
@@ -244,7 +256,7 @@ dist-clean:
@rm -rf $(all_OBJECTS) *~ core @rm -rf $(all_OBJECTS) *~ core
clean: clean:
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c && \ @rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c revision.h revision.h.tmp && \
echo $(MSG_CLEAN) echo $(MSG_CLEAN)

5
README
View File

@@ -1,5 +1,8 @@
Welcome and thanks for downloading uHub, a high performance ADC p2p hub. Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
For the official documentation, bugs and other information, please visit: For the official documentation, bugs and other information, please visit:
http://www.extatic.org/uhub/ http://www.uhub.org/
For a list of compatible ADC clients, see:
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software

View File

@@ -23,6 +23,7 @@ EXO_TEST(hub_net_startup, {
EXO_TEST(hub_config_initialize, { EXO_TEST(hub_config_initialize, {
config_defaults(&g_config); config_defaults(&g_config);
g_config.server_port = 65111;
return 1; return 1;
}); });

View File

@@ -42,7 +42,6 @@ static void inf_create_user()
{ {
if (inf_user) return; if (inf_user) return;
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user)); inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
inf_user->connection = net_con_create();
inf_user->id.sid = 1; inf_user->id.sid = 1;
inf_user->limits.upload_slots = 1; inf_user->limits.upload_slots = 1;
} }

View File

@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
}); });
EXO_TEST(test_message_refc_2, { EXO_TEST(test_message_refc_2, {
return g_msg->references == 0; // 0 return g_msg->references == 1;
}); });
EXO_TEST(test_message_refc_3, { EXO_TEST(test_message_refc_3, {
adc_msg_incref(g_msg); adc_msg_incref(g_msg);
return g_msg->references == 1; // 1 return g_msg->references == 2;
}); });
EXO_TEST(test_message_refc_4, { EXO_TEST(test_message_refc_4, {
adc_msg_incref(g_msg); adc_msg_incref(g_msg);
return g_msg->references == 2; // 2 return g_msg->references == 3;
}); });
EXO_TEST(test_message_refc_5, { EXO_TEST(test_message_refc_5, {
adc_msg_free(g_msg); adc_msg_free(g_msg);
return g_msg->references == 1; // 1 return g_msg->references == 2;
}); });
EXO_TEST(test_message_refc_6, { EXO_TEST(test_message_refc_6, {
adc_msg_free(g_msg); adc_msg_free(g_msg);
return g_msg->references == 0; // 0 return g_msg->references == 1;
}); });
EXO_TEST(test_message_refc_7, { EXO_TEST(test_message_refc_7, {

138
autotest/test_sid.tcc Normal file
View File

@@ -0,0 +1,138 @@
#include <uhub.h>
static struct sid_pool* sid_pool = 0;
struct dummy_user
{
sid_t sid;
};
static struct dummy_user* last = 0;
sid_t last_sid = 0;
EXO_TEST(sid_create_pool, {
sid_pool = sid_pool_create(4);
return sid_pool != 0;
});
EXO_TEST(sid_check_0a, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
return user == 0;
});
EXO_TEST(sid_check_0b, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5);
return user == 0;
});
EXO_TEST(sid_alloc_1, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last = user;
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_1a, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last == user;
});
EXO_TEST(sid_check_1b, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1);
return user == 0;
});
EXO_TEST(sid_alloc_2, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_2, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_3, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_3, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_4, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_4, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_5, {
struct dummy_user user;
sid_t sid;
sid = sid_alloc(sid_pool, (struct hub_user*) &user);
return sid == 0;
});
EXO_TEST(sid_check_6, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
return user == 0;
});
EXO_TEST(sid_list_all_1, {
sid_t s;
size_t n = 0;
int ok = 1;
for (s = last->sid; s <= last_sid; s++)
{
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s);
if (s != (user ? user->sid : -1))
{
ok = 0;
break;
}
n++;
}
return ok && n == 4;
});
#define FREE_SID(N) \
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \
sid_free(sid_pool, N); \
hub_free(user); \
return sid_lookup(sid_pool, N) == NULL;
EXO_TEST(sid_remove_1, {
FREE_SID(2);
});
EXO_TEST(sid_remove_2, {
FREE_SID(1);
});
EXO_TEST(sid_remove_3, {
FREE_SID(4);
});
EXO_TEST(sid_remove_4, {
FREE_SID(3);
});
EXO_TEST(sid_destroy_pool, {
sid_pool_destroy(sid_pool);
sid_pool = 0;
return sid_pool == 0;
});

119
autotest/test_timer.tcc Normal file
View File

@@ -0,0 +1,119 @@
#include <uhub.h>
#define MAX_EVENTS 15
static struct timeout_queue* g_queue;
static time_t g_now;
static size_t g_max;
static struct timeout_evt g_events[MAX_EVENTS];
static size_t g_triggered;
static void timeout_cb(struct timeout_evt* t)
{
g_triggered++;
}
/*
typedef void (*timeout_evt_cb)(struct timeout_evt*);
struct timeout_evt
{
time_t timestamp;
timeout_evt_cb callback;
void* ptr;
struct timeout_evt* prev;
struct timeout_evt* next;
};
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
void timeout_evt_reset(struct timeout_evt*);
int timeout_evt_is_scheduled(struct timeout_evt*);
struct timeout_queue
{
time_t last;
size_t max;
struct timeout_evt** events;
};
void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
void timeout_queue_shutdown(struct timeout_queue*);
size_t timeout_queue_process(struct timeout_queue*, time_t now);
void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now);
*/
EXO_TEST(timer_setup,{
size_t n;
g_queue = hub_malloc_zero(sizeof(struct timeout_queue));
g_now = 0;
g_max = 5;
g_triggered = 0;
timeout_queue_initialize(g_queue, g_now, g_max);
memset(g_events, 0, sizeof(g_events));
for (n = 0; n < MAX_EVENTS; n++)
{
timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]);
}
return g_queue != NULL;
});
EXO_TEST(timer_check_timeout_0,{
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
EXO_TEST(timer_add_event_1,{
timeout_queue_insert(g_queue, &g_events[0], 2);
return g_events[0].prev != NULL;
});
EXO_TEST(timer_check_timeout_1,{
return timeout_queue_get_next_timeout(g_queue, g_now) == 2;
});
EXO_TEST(timer_remove_event_1,{
timeout_queue_remove(g_queue, &g_events[0]);
return g_events[0].prev == NULL;
});
EXO_TEST(timer_check_timeout_2,{
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
/* test re-removing an event - should not crash! */
EXO_TEST(timer_remove_event_1_no_crash,{
timeout_queue_remove(g_queue, &g_events[0]);
return g_events[0].prev == NULL;
});
EXO_TEST(timer_add_5_events_1,{
timeout_queue_insert(g_queue, &g_events[0], 0);
timeout_queue_insert(g_queue, &g_events[1], 1);
timeout_queue_insert(g_queue, &g_events[2], 2);
timeout_queue_insert(g_queue, &g_events[3], 3);
timeout_queue_insert(g_queue, &g_events[4], 4);
return (g_events[0].prev != NULL &&
g_events[1].prev != NULL &&
g_events[2].prev != NULL &&
g_events[3].prev != NULL &&
g_events[4].prev != NULL);
});
EXO_TEST(timer_check_5_events_1,{
return timeout_queue_get_next_timeout(g_queue, g_now) == 1;
});
EXO_TEST(timer_process_5_events_1,{
g_now = 4;
return timeout_queue_process(g_queue, g_now) == g_triggered;
});

13
debian/changelog vendored Normal file
View 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
View File

@@ -0,0 +1 @@
7

24
debian/control vendored Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,4 @@
# uhub - high performance adc hub.
UHUB_ENABLE=0

6
debian/uhub.dirs vendored Normal file
View 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
View File

@@ -0,0 +1,5 @@
AUTHORS
README
BUGS
TODO
doc/getstarted.txt

92
debian/uhub.init vendored Normal file
View 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
View File

@@ -0,0 +1,9 @@
/var/log/uhub/*.log
{
compress
size 10M
rotate 10
missingok
notifempty
}

1
debian/uhub.manpages vendored Normal file
View File

@@ -0,0 +1 @@
doc/uhub.1

27
debian/uhub.postinst vendored Normal file
View 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
View 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
View 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

View File

@@ -8,19 +8,13 @@ Prerequisites
Before you try to compile µHub, please make sure the following prerequisites are met. Before you try to compile µHub, please make sure the following prerequisites are met.
* GNU make * GNU make
* gcc > 3.0 (or MinGW on Windows) * gcc > 3.0 (or MinGW on Windows)
* libevent >= 1.3
* Perl 5 * Perl 5
Linux and Mac OSX Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
----------------- -------------------------------------------
Simply, run: Simply, run:
% make % make
FreeBSD, NetBSD and OpenBSD
---------------------------
Use GNU make, not BSD make:
% gmake
If you have an old gcc compiler, try disabling pre-compiled headers like this: If you have an old gcc compiler, try disabling pre-compiled headers like this:
gmake USE_PCH=NO gmake USE_PCH=NO

View File

@@ -43,4 +43,15 @@ if one wishes to run uhub as a specific user using the -u and -g switches.
Example: Example:
% uhub -f -l mylog.txt -u nobody -g nogroup % uhub -f -l mylog.txt -u nobody -g nogroup
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
This limit needs to be higher than the configured max_users in uhub.conf.
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
* soft nofile 4096
* hard nofile 4096
Or, you can use (as root):
% ulimit -n 4096
Your mileage may vary -- Good luck! Your mileage may vary -- Good luck!

View File

@@ -38,7 +38,7 @@ RETVAL=0
start() { start() {
KIND="UHUB" KIND="Uhub"
echo -n $"Starting $KIND services: " echo -n $"Starting $KIND services: "
daemon uhub $UHUBOPTIONS daemon uhub $UHUBOPTIONS
RETVAL=$? RETVAL=$?
@@ -47,7 +47,7 @@ start() {
} }
stop() { stop() {
KIND="UHUB" KIND="Uhub"
echo -n $"Shutting down $KIND services: " echo -n $"Shutting down $KIND services: "
killproc uhub killproc uhub
RETVAL=$? RETVAL=$?

View File

@@ -0,0 +1,14 @@
# Log rotate for Uhub
# see man logrotate
#
#
/var/log/uhub.log {
compress
size 10M
rotate 10
missingok
notifempty
}

View File

@@ -9,7 +9,5 @@
# -u <user> Run as given user # -u <user> Run as given user
# -g <group> Run with given group permissions # -g <group> Run with given group permissions
# -p <file> Store pid in file (process id) # -p <file> Store pid in file (process id)
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log" UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"

5
doc/rules.txt Normal file
View File

@@ -0,0 +1,5 @@
1. rule #1
2. rule #2
3. rule #3
......
34. Rule #34

View File

@@ -4,7 +4,7 @@
# #
# This file is read only to the uhub deamon, and if you # This file is read only to the uhub deamon, and if you
# make changes to it while uhub is running you can send a # make changes to it while uhub is running you can send a
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX). # HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
# All configuration directives: http://www.uhub.org/config.php # All configuration directives: http://www.uhub.org/config.php
# Bind to this port and address # Bind to this port and address
@@ -13,12 +13,18 @@
server_port=1511 server_port=1511
server_bind_addr=any server_bind_addr=any
# Alternative server ports
# server_alt_ports = 1512, 1513
# The maximum amount of users allowed on the hub. # The maximum amount of users allowed on the hub.
max_users=500 max_users=500
# If 1, will show a "This hub is running uhub/version". # If 1, will show a "Powered by uHub/{VERSION}".
show_banner=1 show_banner=1
# If enabled then operating system and cpu architecture is part of the banner.
show_banner_sys_info=1
# Allow only registered users on the hub if set to 1. # Allow only registered users on the hub if set to 1.
registered_users_only=0 registered_users_only=0
@@ -39,6 +45,11 @@ file_acl=/etc/uhub/users.conf
# Normally this message is sent to clients when connecting. # Normally this message is sent to clients when connecting.
file_motd=/etc/uhub/motd.txt file_motd=/etc/uhub/motd.txt
# This file can contain a rules of the hub.
# Normally this message is sent to clients when write in chat !rules
file_rules=/etc/uhub/rules.txt
# Slots\share\hubs limits # Slots\share\hubs limits
limit_max_hubs_user = 0 limit_max_hubs_user = 0
limit_max_hubs_reg = 0 limit_max_hubs_reg = 0
@@ -48,13 +59,20 @@ limit_min_hubs_user = 0
limit_min_hubs_reg = 0 limit_min_hubs_reg = 0
limit_min_hubs_op = 0 limit_min_hubs_op = 0
limit_min_share = 0 limit_min_share = 0
# Example: # Example:
# To require users to share at least 1 GB in order to enter the hub: # To require users to share at least 1 GB in order to enter the hub:
# limit_min_share = 1024 # limit_min_share = 1024
limit_max_share = 0 limit_max_share = 0
limit_min_slots = 0 limit_min_slots = 0
limit_max_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. # Configure status message as sent to clients in different circumstances.
msg_hub_full = Hub is full msg_hub_full = Hub is full

42
doc/uhub.ebuild Normal file
View 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
View 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

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -26,7 +26,9 @@
uhub_assert(X->capacity); \ uhub_assert(X->capacity); \
uhub_assert(X->length); \ uhub_assert(X->length); \
uhub_assert(X->length <= X->capacity); \ uhub_assert(X->length <= X->capacity); \
uhub_assert(X->references > 0); \
uhub_assert(X->length == strlen(X->cache)); uhub_assert(X->length == strlen(X->cache));
#define ADC_MSG_NULL_ON_FREE
#else #else
#define ADC_MSG_ASSERT(X) do { } while(0) #define ADC_MSG_ASSERT(X) do { } while(0)
#endif /* DEBUG */ #endif /* DEBUG */
@@ -53,40 +55,18 @@ static void* msg_malloc_zero(size_t size)
static void msg_free(void* ptr) static void msg_free(void* ptr)
{ {
LOG_MEMORY("msg_free: %p", ptr); LOG_MEMORY("msg_free: %p", ptr);
// hub_free(ptr); hub_free(ptr);
} }
#include <sys/mman.h>
static void adc_msg_protect(struct adc_message* cmd)
{
LOG_MEMORY("msg_prot: %p %d", cmd, cmd->capacity);
mprotect(cmd, sizeof(cmd), PROT_READ);
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ);
}
static void adc_msg_unprotect(struct adc_message* cmd)
{
LOG_MEMORY("msg_unprot: %p %d", cmd, cmd->capacity);
mprotect(cmd, sizeof(cmd), PROT_READ | PROT_WRITE);
mprotect(cmd->cache, sizeof(cmd->capacity), PROT_READ | PROT_WRITE);
}
#else #else
#define msg_malloc(X) hub_malloc(X) #define msg_malloc(X) hub_malloc(X)
#define msg_malloc_zero(X) hub_malloc_zero(X) #define msg_malloc_zero(X) hub_malloc_zero(X)
#define msg_free(X) hub_free(X) #define msg_free(X) hub_free(X)
#endif /* MSG_MEMORY_DEBUG */ #endif /* MSG_MEMORY_DEBUG */
struct adc_message* adc_msg_incref(struct adc_message* msg) struct adc_message* adc_msg_incref(struct adc_message* msg)
{ {
if (!msg) return 0;
#ifndef ADC_MESSAGE_INCREF #ifndef ADC_MESSAGE_INCREF
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(msg);
#endif
msg->references++; msg->references++;
#ifdef MSG_MEMORY_DEBUG #ifdef MSG_MEMORY_DEBUG
adc_msg_protect(msg); adc_msg_protect(msg);
@@ -201,40 +181,35 @@ int adc_msg_is_empty(struct adc_message* msg)
void adc_msg_free(struct adc_message* msg) void adc_msg_free(struct adc_message* msg)
{ {
if (!msg) return; if (!msg) return;
ADC_MSG_ASSERT(msg); ADC_MSG_ASSERT(msg);
if (msg->references > 0) msg->references--;
if (msg->references == 0)
{ {
#ifdef MSG_MEMORY_DEBUG #ifdef ADC_MSG_NULL_ON_FREE
adc_msg_unprotect(msg); if (msg->cache)
#endif {
msg->references--; *msg->cache = 0;
#ifdef MSG_MEMORY_DEBUG }
adc_msg_protect(msg);
#endif
}
else
{
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(msg);
#endif #endif
msg_free(msg->cache); msg_free(msg->cache);
if (msg->feature_cast_include) if (msg->feature_cast_include)
{ {
list_clear(msg->feature_cast_include, &hub_free); list_clear(msg->feature_cast_include, &hub_free);
list_destroy(msg->feature_cast_include); list_destroy(msg->feature_cast_include);
msg->feature_cast_include = 0; msg->feature_cast_include = 0;
} }
if (msg->feature_cast_exclude) if (msg->feature_cast_exclude)
{ {
list_clear(msg->feature_cast_exclude, &hub_free); list_clear(msg->feature_cast_exclude, &hub_free);
list_destroy(msg->feature_cast_exclude); list_destroy(msg->feature_cast_exclude);
msg->feature_cast_exclude = 0; msg->feature_cast_exclude = 0;
} }
msg_free(msg); msg_free(msg);
} }
} }
@@ -256,7 +231,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
copy->length = cmd->length; copy->length = cmd->length;
copy->capacity = 0; copy->capacity = 0;
copy->priority = cmd->priority; copy->priority = cmd->priority;
copy->references = 0; copy->references = 1;
copy->feature_cast_include = 0; copy->feature_cast_include = 0;
copy->feature_cast_exclude = 0; copy->feature_cast_exclude = 0;
@@ -295,9 +270,6 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
ADC_MSG_ASSERT(copy); ADC_MSG_ASSERT(copy);
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(copy);
#endif
return copy; return copy;
} }
@@ -332,7 +304,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
if (command == NULL) if (command == NULL)
return NULL; /* OOM */ return NULL; /* OOM */
if (!is_printable_utf8(line, length)) if (!is_printable_utf8(line, length))
{ {
LOG_DEBUG("Dropped message with non-printable UTF-8 characters."); LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
@@ -350,17 +322,18 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
msg_free(command); msg_free(command);
return NULL; /* OOM */ return NULL; /* OOM */
} }
adc_msg_set_length(command, length + need_terminate); adc_msg_set_length(command, length + need_terminate);
memcpy(command->cache, line, length); memcpy(command->cache, line, length);
/* Ensure we are zero terminated */ /* Ensure we are zero terminated */
command->cache[length] = 0; command->cache[length] = 0;
command->cache[length+need_terminate] = 0; command->cache[length+need_terminate] = 0;
command->cmd = FOURCC(line[0], line[1], line[2], line[3]); command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
command->priority = 0; command->priority = 0;
command->references = 1;
switch (prefix) switch (prefix)
{ {
case 'U': case 'U':
@@ -368,12 +341,12 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
/* these should never be seen on a hub */ /* these should never be seen on a hub */
ok = 0; ok = 0;
break; break;
case 'I': case 'I':
case 'H': case 'H':
ok = (length > 3); ok = (length > 3);
break; break;
case 'B': case 'B':
ok = (length > 8 && ok = (length > 8 &&
is_space(line[4]) && is_space(line[4]) &&
@@ -381,18 +354,18 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
is_valid_base32_char(line[6]) && is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) && is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8])); is_valid_base32_char(line[8]));
if (!ok) break; if (!ok) break;
temp_sid[0] = line[5]; temp_sid[0] = line[5];
temp_sid[1] = line[6]; temp_sid[1] = line[6];
temp_sid[2] = line[7]; temp_sid[2] = line[7];
temp_sid[3] = line[8]; temp_sid[3] = line[8];
temp_sid[4] = '\0'; temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid); command->source = string_to_sid(temp_sid);
break; break;
case 'F': case 'F':
ok = (length > 8 && ok = (length > 8 &&
is_space(line[4]) && is_space(line[4]) &&
@@ -400,21 +373,21 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
is_valid_base32_char(line[6]) && is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) && is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8])); is_valid_base32_char(line[8]));
if (!ok) break; if (!ok) break;
temp_sid[0] = line[5]; temp_sid[0] = line[5];
temp_sid[1] = line[6]; temp_sid[1] = line[6];
temp_sid[2] = line[7]; temp_sid[2] = line[7];
temp_sid[3] = line[8]; temp_sid[3] = line[8];
temp_sid[4] = '\0'; temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid); command->source = string_to_sid(temp_sid);
/* Create feature cast lists */ /* Create feature cast lists */
command->feature_cast_include = list_create(); command->feature_cast_include = list_create();
command->feature_cast_exclude = list_create(); command->feature_cast_exclude = list_create();
if (!command->feature_cast_include || !command->feature_cast_exclude) if (!command->feature_cast_include || !command->feature_cast_exclude)
{ {
list_destroy(command->feature_cast_include); list_destroy(command->feature_cast_include);
@@ -423,7 +396,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
msg_free(command); msg_free(command);
return NULL; /* OOM */ return NULL; /* OOM */
} }
n = 10; n = 10;
while (line[n] == '+' || line[n] == '-') while (line[n] == '+' || line[n] == '-')
{ {
@@ -431,21 +404,20 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
feature_cast_list = command->feature_cast_include; feature_cast_list = command->feature_cast_include;
else else
feature_cast_list = command->feature_cast_exclude; feature_cast_list = command->feature_cast_exclude;
temp_sid[0] = line[n++]; temp_sid[0] = line[n++];
temp_sid[1] = line[n++]; temp_sid[1] = line[n++];
temp_sid[2] = line[n++]; temp_sid[2] = line[n++];
temp_sid[3] = line[n++]; temp_sid[3] = line[n++];
temp_sid[4] = '\0'; temp_sid[4] = '\0';
list_append(feature_cast_list, hub_strdup(temp_sid)); list_append(feature_cast_list, hub_strdup(temp_sid));
} }
if (n == 10) if (n == 10)
ok = 0; ok = 0;
break; break;
case 'D': case 'D':
case 'E': case 'E':
ok = (length > 13 && ok = (length > 13 &&
@@ -459,41 +431,41 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
is_valid_base32_char(line[11]) && is_valid_base32_char(line[11]) &&
is_valid_base32_char(line[12]) && is_valid_base32_char(line[12]) &&
is_valid_base32_char(line[13])); is_valid_base32_char(line[13]));
if (!ok) break; if (!ok) break;
temp_sid[0] = line[5]; temp_sid[0] = line[5];
temp_sid[1] = line[6]; temp_sid[1] = line[6];
temp_sid[2] = line[7]; temp_sid[2] = line[7];
temp_sid[3] = line[8]; temp_sid[3] = line[8];
temp_sid[4] = '\0'; temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid); command->source = string_to_sid(temp_sid);
temp_sid[0] = line[10]; temp_sid[0] = line[10];
temp_sid[1] = line[11]; temp_sid[1] = line[11];
temp_sid[2] = line[12]; temp_sid[2] = line[12];
temp_sid[3] = line[13]; temp_sid[3] = line[13];
temp_sid[4] = '\0'; temp_sid[4] = '\0';
command->target = string_to_sid(temp_sid); command->target = string_to_sid(temp_sid);
break; break;
default: default:
ok = 0; ok = 0;
} }
if (need_terminate) if (need_terminate)
{ {
command->cache[length] = '\n'; command->cache[length] = '\n';
} }
if (!ok) if (!ok)
{ {
adc_msg_free(command); adc_msg_free(command);
return NULL; return NULL;
} }
/* At this point the arg_offset should point to a space, or the end of message */ /* At this point the arg_offset should point to a space, or the end of message */
n = adc_msg_get_arg_offset(command); n = adc_msg_get_arg_offset(command);
if (command->cache[n] == ' ') if (command->cache[n] == ' ')
@@ -502,18 +474,14 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
} }
else if (command->cache[n] == '\n') ok = 1; else if (command->cache[n] == '\n') ok = 1;
else ok = 0; else ok = 0;
if (!ok) if (!ok)
{ {
adc_msg_free(command); adc_msg_free(command);
return NULL; return NULL;
} }
ADC_MSG_ASSERT(command);
#ifdef MSG_MEMORY_DEBUG ADC_MSG_ASSERT(command);
adc_msg_protect(command);
#endif
return command; return command;
} }
@@ -527,7 +495,6 @@ struct adc_message* adc_msg_create(const char* line)
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size) struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
{ {
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message)); struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
if (!msg) if (!msg)
return NULL; /* OOM */ return NULL; /* OOM */
@@ -538,7 +505,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
msg_free(msg); msg_free(msg);
return NULL; /* OOM */ return NULL; /* OOM */
} }
if (fourcc) if (fourcc)
{ {
msg->cache[0] = (char) ((fourcc >> 24) & 0xff); msg->cache[0] = (char) ((fourcc >> 24) & 0xff);
@@ -546,19 +513,15 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
msg->cache[2] = (char) ((fourcc >> 8) & 0xff); msg->cache[2] = (char) ((fourcc >> 8) & 0xff);
msg->cache[3] = (char) ((fourcc ) & 0xff); msg->cache[3] = (char) ((fourcc ) & 0xff);
msg->cache[4] = '\n'; msg->cache[4] = '\n';
/* Ensure we are zero terminated */ /* Ensure we are zero terminated */
adc_msg_set_length(msg, 5); adc_msg_set_length(msg, 5);
msg->cache[msg->length] = 0; msg->cache[msg->length] = 0;
} }
msg->cmd = fourcc; msg->cmd = fourcc;
msg->priority = 0; msg->priority = 0;
msg->references = 1;
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(msg);
#endif
return msg; return msg;
} }
@@ -625,7 +588,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
int arg_offset = adc_msg_get_arg_offset(cmd); int arg_offset = adc_msg_get_arg_offset(cmd);
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3); start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
while (start) while (start)
{ {
@@ -635,7 +598,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
else else
start = NULL; start = NULL;
} }
return count; return count;
} }
@@ -648,25 +611,25 @@ char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2])
size_t length; size_t length;
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' }; char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
int arg_offset = adc_msg_get_arg_offset(cmd); int arg_offset = adc_msg_get_arg_offset(cmd);
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
start = memmem(&cmd->cache[arg_offset], cmd->length - arg_offset, prefix, 3); start = memmem(&cmd->cache[arg_offset], cmd->length - arg_offset, prefix, 3);
if (!start) if (!start)
return NULL; return NULL;
start = &start[3]; start = &start[3];
end = strchr(start, ' '); end = strchr(start, ' ');
if (!end) end = &cmd->cache[cmd->length]; if (!end) end = &cmd->cache[cmd->length];
length = &end[0] - &start[0]; length = &end[0] - &start[0];
argument = hub_strndup(start, length); argument = hub_strndup(start, length);
if (length > 0 && argument[length-1] == '\n') if (length > 0 && argument[length-1] == '\n')
{ {
argument[length-1] = 0; argument[length-1] = 0;
} }
return argument; return argument;
} }
@@ -684,9 +647,9 @@ int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2]
{ {
return -1; return -1;
} }
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
return 0; return 0;
} }
@@ -698,10 +661,6 @@ void adc_msg_terminate(struct adc_message* cmd)
adc_msg_cache_append(cmd, "\n", 1); adc_msg_cache_append(cmd, "\n", 1);
} }
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(cmd);
#endif
} }
/* FIXME: this looks bogus */ /* FIXME: this looks bogus */
@@ -709,10 +668,6 @@ void adc_msg_unterminate(struct adc_message* cmd)
{ {
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
#ifdef MSG_MEMORY_DEBUG
adc_msg_unprotect(cmd);
#endif
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n') if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
{ {
cmd->length--; cmd->length--;
@@ -725,9 +680,9 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
int ret = 0; int ret = 0;
if (!string) if (!string)
return -1; return -1;
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd); adc_msg_unterminate(cmd);
adc_msg_cache_append(cmd, " ", 1); adc_msg_cache_append(cmd, " ", 1);
adc_msg_cache_append(cmd, prefix, 2); adc_msg_cache_append(cmd, prefix, 2);
@@ -761,7 +716,7 @@ int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix
int adc_msg_add_argument(struct adc_message* cmd, const char* string) int adc_msg_add_argument(struct adc_message* cmd, const char* string)
{ {
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd); adc_msg_unterminate(cmd);
adc_msg_cache_append(cmd, " ", 1); adc_msg_cache_append(cmd, " ", 1);
adc_msg_cache_append(cmd, string, strlen(string)); adc_msg_cache_append(cmd, string, strlen(string));
@@ -827,11 +782,11 @@ int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
char* start; char* start;
char* end; char* end;
int count = 0; int count = 0;
ADC_MSG_ASSERT(cmd); ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd); adc_msg_unterminate(cmd);
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' '); start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
while (start) while (start)
{ {
@@ -884,16 +839,13 @@ int adc_msg_unescape_length(const char* str)
} }
char* adc_msg_unescape(const char* string) char* adc_msg_unescape(const char* string)
{ {
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1); char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
char* ptr = (char*) new_string; char* ptr = (char*) new_string;
char* str = (char*) string; char* str = (char*) string;
int escaped = 0; int escaped = 0;
while (*str) while (*str)
{ {
if (escaped) { if (escaped) {
@@ -905,14 +857,12 @@ char* adc_msg_unescape(const char* string)
*ptr++ = '\n'; *ptr++ = '\n';
else else
*ptr++ = *str; *ptr++ = *str;
escaped = 0; escaped = 0;
} else { } else {
if (*str == '\\') if (*str == '\\')
escaped = 1; escaped = 1;
else else
*ptr++ = *str; *ptr++ = *str;
} }
str++; str++;
} }

View File

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

View File

@@ -119,6 +119,14 @@ void sid_pool_destroy(struct sid_pool* pool)
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user) sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
{ {
if (pool->count >= (pool->max - pool->min))
{
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
#endif
return 0;
}
sid_t n = (++pool->count); sid_t n = (++pool->count);
for (; (pool->map[n % pool->max]); n++) ; for (; (pool->map[n % pool->max]); n++) ;
@@ -140,7 +148,7 @@ void sid_free(struct sid_pool* pool, sid_t sid)
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid) struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
{ {
if (!sid || (sid > pool->max)) if (!sid || (sid >= pool->max))
return 0; return 0;
return pool->map[sid]; return pool->map[sid];
} }

View File

@@ -119,7 +119,7 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
{ {
char buf1[INET6_ADDRSTRLEN+1]; char buf1[INET6_ADDRSTRLEN+1];
char buf2[INET6_ADDRSTRLEN+1]; char buf2[INET6_ADDRSTRLEN+1];
if (info->lo.af == AF_INET) if (info->lo.af == AF_INET)
{ {
net_address_to_string(AF_INET, &info->lo.internal_ip_data.in.s_addr, buf1, INET6_ADDRSTRLEN); 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->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN); net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
} }
LOG_DEBUG("ACL: Deny access for: %s-%s", buf1, buf2); LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
list_append(list, info); list_append(list, info);
} }
@@ -326,7 +326,7 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
} }
#define STR_LIST_CONTAINS(LIST, STR) \ #define STR_LIST_CONTAINS(LIST, STR) \
char* str = (char*) list_get_first(LIST); \ str = (char*) list_get_first(LIST); \
while (str) \ while (str) \
{ \ { \
if (strcasecmp(str, STR) == 0) \ if (strcasecmp(str, STR) == 0) \
@@ -337,18 +337,21 @@ struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, cons
int acl_is_cid_banned(struct acl_handle* handle, const char* data) int acl_is_cid_banned(struct acl_handle* handle, const char* data)
{ {
char* str;
if (!handle) return 0; if (!handle) return 0;
STR_LIST_CONTAINS(handle->cids, data); STR_LIST_CONTAINS(handle->cids, data);
} }
int acl_is_user_banned(struct acl_handle* handle, const char* data) int acl_is_user_banned(struct acl_handle* handle, const char* data)
{ {
char* str;
if (!handle) return 0; if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_banned, data); STR_LIST_CONTAINS(handle->users_banned, data);
} }
int acl_is_user_denied(struct acl_handle* handle, const char* data) int acl_is_user_denied(struct acl_handle* handle, const char* data)
{ {
char* str;
if (!handle) return 0; if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_denied, data); STR_LIST_CONTAINS(handle->users_denied, data);
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -63,20 +63,23 @@ static void command_destroy(struct hub_command* cmd)
static struct hub_command* command_create(const char* message) static struct hub_command* command_create(const char* message)
{ {
char* prefix;
int n;
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command)); struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
if (!cmd) return 0; if (!cmd) return 0;
cmd->message = message; cmd->message = message;
cmd->args = list_create(); cmd->args = list_create();
int n = split_string(message, "\\s", cmd->args, 0); n = split_string(message, "\\s", cmd->args, 0);
if (n <= 0) if (n <= 0)
{ {
command_destroy(cmd); command_destroy(cmd);
return 0; return 0;
} }
char* prefix = list_get_first(cmd->args); prefix = list_get_first(cmd->args);
if (prefix && prefix[0] && prefix[1]) if (prefix && prefix[0] && prefix[1])
{ {
cmd->prefix = hub_strdup(&prefix[1]); cmd->prefix = hub_strdup(&prefix[1]);
@@ -129,8 +132,8 @@ static int command_status_user_not_found(struct hub_info* hub, struct hub_user*
const char* command_get_syntax(struct commands_handler* handler) const char* command_get_syntax(struct commands_handler* handler)
{ {
static char args[128]; static char args[128];
args[0] = 0;
size_t n = 0; size_t n = 0;
args[0] = 0;
if (handler->args) if (handler->args)
{ {
for (n = 0; n < strlen(handler->args); n++) for (n = 0; n < strlen(handler->args); n++)
@@ -235,10 +238,11 @@ static int command_uptime(struct hub_info* hub, struct hub_user* user, struct hu
static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
char* nick = list_get_first(cmd->args); char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick) if (!nick)
return -1; // FIXME: bad syntax. return -1; // FIXME: bad syntax.
struct hub_user* target = uman_get_user_by_nick(hub, nick); target = uman_get_user_by_nick(hub, nick);
if (!target) if (!target)
return command_status_user_not_found(hub, user, cmd, nick); return command_status_user_not_found(hub, user, cmd, nick);
@@ -253,10 +257,11 @@ static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_
static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
char* nick = list_get_first(cmd->args); char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick) if (!nick)
return -1; // FIXME: bad syntax. return -1; // FIXME: bad syntax.
struct hub_user* target = uman_get_user_by_nick(hub, nick); target = uman_get_user_by_nick(hub, nick);
if (!target) if (!target)
return command_status_user_not_found(hub, user, cmd, nick); return command_status_user_not_found(hub, user, cmd, nick);
@@ -276,6 +281,29 @@ static int command_unban(struct hub_info* hub, struct hub_user* user, struct hub
return command_status(hub, user, cmd, "Not implemented"); return command_status(hub, user, cmd, "Not implemented");
} }
static int command_mute(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick)
return -1; // FIXME: bad syntax.
target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
if (strlen(cmd->prefix) == 4)
{
user_flag_set(target, flag_muted);
}
else
{
user_flag_unset(target, flag_muted);
}
return command_status(hub, user, cmd, nick);
}
static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
hub->status = hub_status_restart; hub->status = hub_status_restart;
@@ -290,7 +318,12 @@ static int command_shutdown(struct hub_info* hub, struct hub_user* user, struct
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
return command_status(hub, user, cmd, "Powered by " PRODUCT "/" VERSION); const char* tmp;
if (hub->config->show_banner_sys_info)
tmp = "Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO;
else
tmp = "Powered by " PRODUCT_STRING;
return command_status(hub, user, cmd, tmp);
} }
static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
@@ -303,12 +336,13 @@ static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
char tmp[128]; char tmp[128];
char* nick = list_get_first(cmd->args); char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick); if (!nick);
return -1; // FIXME: bad syntax/OOM return -1; // FIXME: bad syntax/OOM
struct hub_user* target = uman_get_user_by_nick(hub, nick); target = uman_get_user_by_nick(hub, nick);
if (!target) if (!target)
return command_status_user_not_found(hub, user, cmd, nick); return command_status_user_not_found(hub, user, cmd, nick);
@@ -324,6 +358,8 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
struct linked_list* users; struct linked_list* users;
struct hub_user* u; struct hub_user* u;
int ret = 0; int ret = 0;
char tmp[128];
char* buffer;
if (!address) if (!address)
return -1; // FIXME: bad syntax. return -1; // FIXME: bad syntax.
@@ -344,10 +380,9 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
return command_status(hub, user, cmd, "No users found."); return command_status(hub, user, cmd, "No users found.");
} }
char tmp[128];
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : "")); snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
char* buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3); buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
if (!buffer) if (!buffer)
{ {
list_destroy(users); list_destroy(users);
@@ -377,8 +412,8 @@ static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 10)) + 6); struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 12)) + 6);
adc_msg_add_argument(command, (cmd->message + 10)); adc_msg_add_argument(command, (cmd->message + 12));
route_to_all(hub, command); route_to_all(hub, command);
adc_msg_free(command); adc_msg_free(command);
return 0; return 0;
@@ -391,13 +426,13 @@ static int command_history(struct hub_info* hub, struct hub_user* user, struct h
char* message = 0; char* message = 0;
int ret = (int) list_size(messages); int ret = (int) list_size(messages);
size_t bufsize; size_t bufsize;
char tmp[128];
if (!ret) if (!ret)
{ {
return command_status(hub, user, cmd, "No messages."); return command_status(hub, user, cmd, "No messages.");
} }
char tmp[128];
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : "")); snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
bufsize = strlen(tmp); bufsize = strlen(tmp);
message = (char*) list_get_first(messages); message = (char*) list_get_first(messages);
@@ -496,6 +531,20 @@ static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_c
return 0; return 0;
} }
static int command_rules(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
if (!hub_send_rules(hub, user))
return command_status(hub, user, cmd, "no rules defined.");
return 0;
}
static int command_motd(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
if (!hub_send_motd(hub, user))
return command_status(hub, user, cmd, "no motd defined.");
return 0;
}
#ifdef CRASH_DEBUG #ifdef CRASH_DEBUG
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd) static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{ {
@@ -550,24 +599,28 @@ int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* m
} }
static struct commands_handler command_handlers[] = { static struct commands_handler command_handlers[] = {
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
{ "ban", 3, "n", cred_operator, command_ban, "Ban a user" }, { "ban", 3, "n", cred_operator, command_ban, "Ban a user" },
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
{ "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" }, { "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" },
{ "log", 3, 0, cred_operator, command_log, "Display log" },
#ifdef CRASH_DEBUG #ifdef CRASH_DEBUG
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." }, { "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
#endif #endif
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
{ "log", 3, 0, cred_operator, command_log, "Display log" },
{ "motd", 4, 0, cred_guest, command_motd, "Show the message of the day" },
{ "mute", 4, "n", cred_operator, command_mute, "Mute user" },
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
{ "rules", 5, 0, cred_guest, command_rules, "Show the hub rules" },
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
{ "unmute", 6, "n", cred_operator, command_mute, "Unmute user" },
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
{ 0, 0, 0, cred_none, command_help, "" } { 0, 0, 0, cred_none, command_help, "" }
}; };

View File

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

View File

@@ -111,11 +111,13 @@
#define DEF_SERVER_BIND_ADDR "any" #define DEF_SERVER_BIND_ADDR "any"
#define DEF_SERVER_PORT 1511 #define DEF_SERVER_PORT 1511
#define DEF_SERVER_BACKLOG 50 #define DEF_SERVER_BACKLOG 50
#define DEF_SERVER_ALT_PORTS ""
#define DEF_HUB_NAME "uhub" #define DEF_HUB_NAME "uhub"
#define DEF_HUB_DESCRIPTION "" #define DEF_HUB_DESCRIPTION ""
#define DEF_HUB_ENABLED 1 #define DEF_HUB_ENABLED 1
#define DEF_FILE_ACL "" #define DEF_FILE_ACL ""
#define DEF_FILE_MOTD "" #define DEF_FILE_MOTD ""
#define DEF_FILE_RULES ""
#define DEF_MAX_USERS 500 #define DEF_MAX_USERS 500
#define DEF_MAX_CHAT_HISTORY 20 #define DEF_MAX_CHAT_HISTORY 20
#define DEF_MAX_LOGOUT_LOG 100 #define DEF_MAX_LOGOUT_LOG 100
@@ -123,7 +125,9 @@
#define DEF_MAX_SEND_BUFFER 131072 #define DEF_MAX_SEND_BUFFER 131072
#define DEF_MAX_SEND_BUFFER_SOFT 98304 #define DEF_MAX_SEND_BUFFER_SOFT 98304
#define DEF_SHOW_BANNER 1 #define DEF_SHOW_BANNER 1
#define DEF_SHOW_BANNER_SYS_INFO 1
#define DEF_REGISTERED_USERS_ONLY 0 #define DEF_REGISTERED_USERS_ONLY 0
#define DEF_OBSOLETE_CLIENTS 0
#define DEF_CHAT_ONLY 0 #define DEF_CHAT_ONLY 0
#define DEF_CHAT_IS_PRIVILEGED 0 #define DEF_CHAT_IS_PRIVILEGED 0
#define DEF_LOW_BANDWIDTH_MODE 0 #define DEF_LOW_BANDWIDTH_MODE 0
@@ -171,6 +175,8 @@
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots." #define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs." #define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs." #define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
#define DEF_MSG_PROTO_NO_COMMON_HASH "No common hash algorithm."
#define DEF_MSG_PROTO_OBSOLETE_ADC0 "Your client does not support ADC/1.0."
void config_defaults(struct hub_config* config) void config_defaults(struct hub_config* config)
{ {
@@ -180,8 +186,10 @@ void config_defaults(struct hub_config* config)
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED); DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
DEFAULT_STRING (file_acl, DEF_FILE_ACL); DEFAULT_STRING (file_acl, DEF_FILE_ACL);
DEFAULT_STRING (file_motd, DEF_FILE_MOTD); DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT); DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG); 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_users, DEF_MAX_USERS);
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY); DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG); DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
@@ -189,11 +197,13 @@ void config_defaults(struct hub_config* config)
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER); DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT); DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER); DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
DEFAULT_BOOLEAN(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
DEFAULT_BOOLEAN(obsolete_clients, DEF_OBSOLETE_CLIENTS);
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY); DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED); DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE); DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY); DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
/* Limits enforced on users */ /* Limits enforced on users */
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER); DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG); DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
@@ -237,6 +247,8 @@ void config_defaults(struct hub_config* config)
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH); DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW); DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH); DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
DEFAULT_STRING (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
DEFAULT_STRING (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE); DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE); DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
@@ -249,9 +261,11 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
{ {
GET_STR (file_acl); GET_STR (file_acl);
GET_STR (file_motd); GET_STR (file_motd);
GET_STR (file_rules);
GET_STR (server_bind_addr); GET_STR (server_bind_addr);
GET_INT (server_port); GET_INT (server_port);
GET_INT (server_listen_backlog); GET_INT (server_listen_backlog);
GET_STR (server_alt_ports);
GET_STR (hub_name); GET_STR (hub_name);
GET_STR (hub_description); GET_STR (hub_description);
GET_BOOL(hub_enabled); GET_BOOL(hub_enabled);
@@ -262,6 +276,8 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
GET_INT (max_send_buffer); GET_INT (max_send_buffer);
GET_INT (max_send_buffer_soft); GET_INT (max_send_buffer_soft);
GET_BOOL(show_banner); GET_BOOL(show_banner);
GET_BOOL(show_banner_sys_info);
GET_BOOL(obsolete_clients);
GET_BOOL(chat_only); GET_BOOL(chat_only);
GET_BOOL(chat_is_privileged); GET_BOOL(chat_is_privileged);
GET_BOOL(low_bandwidth_mode); GET_BOOL(low_bandwidth_mode);
@@ -279,7 +295,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
GET_INT(limit_max_share); GET_INT(limit_max_share);
GET_INT(limit_min_slots); GET_INT(limit_min_slots);
GET_INT(limit_max_slots); GET_INT(limit_max_slots);
/* Status/error strings */ /* Status/error strings */
GET_STR (msg_hub_full); GET_STR (msg_hub_full);
GET_STR (msg_hub_disabled); GET_STR (msg_hub_disabled);
@@ -310,13 +326,16 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
GET_STR (msg_user_slots_high); GET_STR (msg_user_slots_high);
GET_STR (msg_user_hub_limit_low); GET_STR (msg_user_hub_limit_low);
GET_STR (msg_user_hub_limit_high); GET_STR (msg_user_hub_limit_high);
GET_STR (msg_proto_no_common_hash);
GET_STR (msg_proto_obsolete_adc0);
/* TLS/SSL related */
GET_BOOL(tls_enable); GET_BOOL(tls_enable);
GET_BOOL(tls_require); GET_BOOL(tls_require);
GET_STR (tls_certificate); GET_STR (tls_certificate);
GET_STR (tls_private_key); GET_STR (tls_private_key);
/* Still here -- unknown directive */ /* Still here -- unknown directive */
LOG_ERROR("Unknown configuration directive: '%s'", key); LOG_ERROR("Unknown configuration directive: '%s'", key);
return -1; return -1;
} }
@@ -325,11 +344,13 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
void free_config(struct hub_config* config) void free_config(struct hub_config* config)
{ {
hub_free(config->server_bind_addr); hub_free(config->server_bind_addr);
hub_free(config->server_alt_ports);
hub_free(config->file_motd); hub_free(config->file_motd);
hub_free(config->file_acl); hub_free(config->file_acl);
hub_free(config->file_rules);
hub_free(config->hub_name); hub_free(config->hub_name);
hub_free(config->hub_description); hub_free(config->hub_description);
hub_free(config->msg_hub_full); hub_free(config->msg_hub_full);
hub_free(config->msg_hub_disabled); hub_free(config->msg_hub_disabled);
hub_free(config->msg_hub_registered_users_only); hub_free(config->msg_hub_registered_users_only);
@@ -359,7 +380,9 @@ void free_config(struct hub_config* config)
hub_free(config->msg_user_slots_high); hub_free(config->msg_user_slots_high);
hub_free(config->msg_user_hub_limit_low); hub_free(config->msg_user_hub_limit_low);
hub_free(config->msg_user_hub_limit_high); hub_free(config->msg_user_hub_limit_high);
hub_free(config->msg_proto_no_common_hash);
hub_free(config->msg_proto_obsolete_adc0);
hub_free(config->tls_certificate); hub_free(config->tls_certificate);
hub_free(config->tls_private_key); hub_free(config->tls_private_key);
@@ -398,9 +421,11 @@ void dump_config(struct hub_config* config, int ignore_defaults)
{ {
DUMP_STR (file_acl, DEF_FILE_ACL); DUMP_STR (file_acl, DEF_FILE_ACL);
DUMP_STR (file_motd, DEF_FILE_MOTD); DUMP_STR (file_motd, DEF_FILE_MOTD);
DUMP_STR (file_rules, DEF_FILE_RULES);
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR); DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
DUMP_INT (server_port, DEF_SERVER_PORT); DUMP_INT (server_port, DEF_SERVER_PORT);
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG); 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_name, DEF_HUB_NAME);
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION); DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED); DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
@@ -411,6 +436,8 @@ void dump_config(struct hub_config* config, int ignore_defaults)
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER); DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT); DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DUMP_BOOL(show_banner, DEF_SHOW_BANNER); DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
DUMP_BOOL(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
DUMP_BOOL(obsolete_clients, DEF_OBSOLETE_CLIENTS);
DUMP_BOOL(chat_only, DEF_CHAT_ONLY); DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED); DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE); DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
@@ -466,6 +493,8 @@ void dump_config(struct hub_config* config, int ignore_defaults)
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH); DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW); DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH); DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
DUMP_STR (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
DUMP_STR (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
} }

View File

@@ -25,14 +25,18 @@ struct hub_config
int server_port; /**<<< "Server port to bind to (default: 1511)" */ int server_port; /**<<< "Server port to bind to (default: 1511)" */
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */ char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */ int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
char* server_alt_ports; /**<<< "Comma separated list of alternative ports to listen to (default: '')" */
int hub_enabled; /**<<< "Is server enabled (default: 1)" */ int hub_enabled; /**<<< "Is server enabled (default: 1)" */
int show_banner; /**<<< "Show banner on connect (default: 1)" */ int show_banner; /**<<< "Show banner on connect (default: 1)" */
int show_banner_sys_info; /**<<< "Show banner 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 max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */ int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
int obsolete_clients; /**<<< "Support obsolete clients using a ADC protocol prior to 1.0 (default: off)" */
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */ int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */ int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */ 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_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_name; /**<<< "Name of hub (default: 'My uhub hub')" */
char* hub_description; /**<<< "Name of hub (default: 'no description')" */ char* hub_description; /**<<< "Name of hub (default: 'no description')" */
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */ int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
@@ -86,6 +90,8 @@ struct hub_config
char* msg_user_slots_high; /**<<< "User have too many upload slots." */ char* msg_user_slots_high; /**<<< "User have too many upload slots." */
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */ char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */ char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
char* msg_proto_no_common_hash; /**<<< "No common hash algorithm." */
char* msg_proto_obsolete_adc0; /**<<< "Client is using an obsolete ADC protocol version." */
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */ int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */ int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */

View File

@@ -137,17 +137,46 @@ int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_mess
if (u->state == state_protocol) if (u->state == state_protocol)
{ {
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */ if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
if (!ok)
if (ok)
{
hub_send_handshake(hub, u);
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
}
else
{ {
/* disconnect user. Do not send crap during initial handshake! */ /* disconnect user. Do not send crap during initial handshake! */
hub_disconnect_user(hub, u, quit_logon_error); hub_disconnect_user(hub, u, quit_logon_error);
ret = -1; return -1;
}
if (user_flag_get(u, feature_base))
{
/* User supports ADC/1.0 and a hash we know */
if (user_flag_get(u, feature_tiger))
{
hub_send_handshake(hub, u);
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
}
else
{
// no common hash algorithm.
hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal);
hub_disconnect_user(hub, u, quit_protocol_error);
}
}
else if (user_flag_get(u, feature_bas0))
{
if (hub->config->obsolete_clients)
{
hub_send_handshake(hub, u);
net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
}
else
{
/* disconnect user for using an obsolete client. */
hub_send_status(hub, u, status_msg_proto_obsolete_adc0, status_level_fatal);
hub_disconnect_user(hub, u, quit_protocol_error);
}
}
else
{
/* Not speaking a compatible protocol - just disconnect. */
hub_disconnect_user(hub, u, quit_logon_error);
} }
} }
@@ -183,6 +212,7 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
char* message = adc_msg_get_argument(cmd, 0); char* message = adc_msg_get_argument(cmd, 0);
int ret = 0; int ret = 0;
int relay = 1; int relay = 1;
int offset;
if (!message || !user_is_logged_in(u)) if (!message || !user_is_logged_in(u))
return 0; return 0;
@@ -196,7 +226,7 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
if (message[1] == message[0]) if (message[1] == message[0])
{ {
relay = 1; relay = 1;
int offset = adc_msg_get_arg_offset(cmd); offset = adc_msg_get_arg_offset(cmd);
memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset); memmove(cmd->cache+offset+1, cmd->cache+offset+2, cmd->length - offset);
cmd->length--; cmd->length--;
} }
@@ -206,7 +236,7 @@ int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc
} }
} }
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; relay = 0;
} }
@@ -361,14 +391,27 @@ void hub_send_handshake(struct hub_info* hub, struct hub_user* u)
} }
} }
void hub_send_motd(struct hub_info* hub, struct hub_user* u) int hub_send_motd(struct hub_info* hub, struct hub_user* u)
{ {
if (hub->command_motd) if (hub->command_motd)
{ {
route_to_user(hub, u, hub->command_motd); route_to_user(hub, u, hub->command_motd);
return 1;
} }
return 0;
} }
int hub_send_rules(struct hub_info* hub, struct hub_user* u)
{
if (hub->command_rules)
{
route_to_user(hub, u, hub->command_rules);
return 1;
}
return 0;
}
void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u) void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u)
{ {
struct adc_message* igpa; struct adc_message* igpa;
@@ -437,91 +480,110 @@ static void hub_event_dispatcher(void* callback_data, struct event_data* message
} }
} }
static struct net_connection* start_listening_socket(const char* bind_addr, uint16_t port, int backlog, struct hub_info* hub)
struct hub_info* hub_start_service(struct hub_config* config)
{ {
struct hub_info* hub = 0; struct net_connection* server;
struct sockaddr_storage addr; struct sockaddr_storage addr;
socklen_t sockaddr_size; socklen_t sockaddr_size;
int server_tcp, ret, ipv6_supported, af; int sd, ret;
char address_buf[INET6_ADDRSTRLEN+1];
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_free(hub);
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...", address_buf, config->server_port); if (ip_convert_address(bind_addr, port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
if (server_tcp == -1)
{ {
hub_free(hub);
return 0;
}
ret = net_set_reuseaddress(server_tcp, 1);
if (ret == -1)
{
hub_free(hub);
net_close(server_tcp);
return 0;
}
ret = net_set_nonblocking(server_tcp, 1);
if (ret == -1)
{
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()));
hub_free(hub);
net_close(server_tcp);
return 0; return 0;
} }
ret = net_listen(server_tcp, config->server_listen_backlog); sd = net_socket_create(addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
if (ret == -1) if (sd == -1)
{ {
LOG_FATAL("hub_start_service(): Unable to listen to socket");
hub_free(hub);
net_close(server_tcp);
return 0; return 0;
} }
if ((net_set_reuseaddress(sd, 1) == -1) || (net_set_nonblocking(sd, 1) == -1))
{
net_close(sd);
return 0;
}
ret = net_bind(sd, (struct sockaddr*) &addr, sockaddr_size);
if (ret == -1)
{
LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
net_close(sd);
return 0;
}
ret = net_listen(sd, backlog);
if (ret == -1)
{
LOG_ERROR("hub_start_service(): Unable to listen to socket");
net_close(sd);
return 0;
}
server = net_con_create();
net_con_initialize(server, sd, net_on_accept, hub, NET_EVENT_READ);
return server;
}
struct server_alt_port_data
{
struct hub_info* hub;
struct hub_config* config;
};
static int server_alt_port_start_one(char* line, int count, void* ptr)
{
struct server_alt_port_data* data = (struct server_alt_port_data*) ptr;
int port = uhub_atoi(line);
struct net_connection* con = start_listening_socket(data->config->server_bind_addr, port, data->config->server_listen_backlog, data->hub);
if (con)
{
list_append(data->hub->server_alt_ports, con);
LOG_INFO("Listening on alternate port %d...", port);
return 0;
}
return -1;
}
static void server_alt_port_start(struct hub_info* hub, struct hub_config* config)
{
struct server_alt_port_data data;
if (!config->server_alt_ports || !*config->server_alt_ports)
return;
hub->server_alt_ports = (struct linked_list*) list_create();
data.hub = hub;
data.config = config;
string_split(config->server_alt_ports, ",", &data, server_alt_port_start_one);
}
static void server_alt_port_clear(void* ptr)
{
struct net_connection* con = (struct net_connection*) ptr;
if (con)
{
net_con_close(con);
hub_free(con);
}
}
static void server_alt_port_stop(struct hub_info* hub)
{
if (hub->server_alt_ports)
{
list_clear(hub->server_alt_ports, &server_alt_port_clear);
list_destroy(hub->server_alt_ports);
}
}
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config)
{
if (config->tls_enable) if (config->tls_enable)
{ {
hub->ssl_method = SSLv23_method(); /* TLSv1_method() */ hub->ssl_method = SSLv23_method(); /* TLSv1_method() */
@@ -547,24 +609,69 @@ struct hub_info* hub_start_service(struct hub_config* config)
} }
LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key); LOG_INFO("Enabling TLS, using certificate: %s, private key: %s", config->tls_certificate, config->tls_private_key);
} }
return 1;
}
static void unload_ssl_certificates(struct hub_info* hub)
{
if (hub->ssl_ctx)
{
SSL_CTX_free(hub->ssl_ctx);
}
}
#endif #endif
struct hub_info* hub_start_service(struct hub_config* config)
{
struct hub_info* hub = 0;
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.");
hub->server = start_listening_socket(config->server_bind_addr, config->server_port, config->server_listen_backlog, hub);
if (!hub->server)
{
hub_free(hub);
LOG_FATAL("Unable to start hub service");
return 0;
}
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
#ifdef SSL_SUPPORT
if (!load_ssl_certificates(hub, config))
{
hub_free(hub);
return 0;
}
#endif
hub->config = config; hub->config = config;
hub->users = NULL; hub->users = NULL;
if (uman_init(hub) == -1) if (uman_init(hub) == -1)
{ {
net_con_close(hub->server);
hub_free(hub); hub_free(hub);
net_close(server_tcp);
return 0; return 0;
} }
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1) if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
{ {
net_con_close(hub->server);
uman_shutdown(hub); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
net_close(server_tcp);
return 0; return 0;
} }
@@ -572,11 +679,11 @@ struct hub_info* hub_start_service(struct hub_config* config)
hub->sendbuf = hub_malloc(MAX_SEND_BUF); hub->sendbuf = hub_malloc(MAX_SEND_BUF);
if (!hub->recvbuf || !hub->sendbuf) if (!hub->recvbuf || !hub->sendbuf)
{ {
net_con_close(hub->server);
hub_free(hub->recvbuf); hub_free(hub->recvbuf);
hub_free(hub->sendbuf); hub_free(hub->sendbuf);
uman_shutdown(hub); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
net_close(server_tcp);
return 0; return 0;
} }
@@ -584,21 +691,20 @@ struct hub_info* hub_start_service(struct hub_config* config)
hub->logout_info = (struct linked_list*) list_create(); hub->logout_info = (struct linked_list*) list_create();
if (!hub->chat_history) if (!hub->chat_history)
{ {
net_con_close(hub->server);
list_destroy(hub->chat_history); list_destroy(hub->chat_history);
list_destroy(hub->logout_info); list_destroy(hub->logout_info);
hub_free(hub->recvbuf); hub_free(hub->recvbuf);
hub_free(hub->sendbuf); hub_free(hub->sendbuf);
uman_shutdown(hub); uman_shutdown(hub);
hub_free(hub); hub_free(hub);
net_close(server_tcp);
return 0; return 0;
} }
server_alt_port_start(hub, config);
hub->status = hub_status_running; hub->status = hub_status_running;
hub->server = net_con_create();
net_con_initialize(hub->server, server_tcp, net_on_accept, hub, NET_EVENT_READ);
g_hub = hub; g_hub = hub;
return hub; return hub;
} }
@@ -608,12 +714,14 @@ void hub_shutdown_service(struct hub_info* hub)
{ {
LOG_DEBUG("hub_shutdown_service()"); LOG_DEBUG("hub_shutdown_service()");
event_queue_shutdown(hub->queue); #ifdef SSL_SUPPORT
#ifdef USE_LIBEVENT unload_ssl_certificates(hub);
event_del(&hub->ev_accept);
#endif #endif
event_queue_shutdown(hub->queue);
net_con_close(hub->server); net_con_close(hub->server);
hub_free(hub->server); hub_free(hub->server);
server_alt_port_stop(hub);
uman_shutdown(hub); uman_shutdown(hub);
hub->status = hub_status_stopped; hub->status = hub_status_stopped;
hub_free(hub->sendbuf); hub_free(hub->sendbuf);
@@ -627,17 +735,15 @@ void hub_shutdown_service(struct hub_info* hub)
g_hub = 0; g_hub = 0;
} }
#define SERVER "" PRODUCT "/" VERSION ""
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl) void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
{ {
int fd, ret; int fd, ret;
char buf[MAX_RECV_BUF]; char buf[MAX_RECV_BUF];
char* tmp; char* tmp;
char* server = adc_msg_escape(SERVER); /* FIXME: OOM */ char* server = adc_msg_escape(PRODUCT_STRING); /* FIXME: OOM */
hub->acl = acl; hub->acl = acl;
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15 + strlen(server)); hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15);
if (hub->command_info) if (hub->command_info)
{ {
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB); adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
@@ -669,16 +775,35 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
close(fd); close(fd);
} }
hub->command_rules = 0;
fd = (hub->config->file_rules && *hub->config->file_rules) ? open(hub->config->file_rules, 0) : -1;
if (fd != -1)
{
ret = read(fd, buf, MAX_RECV_BUF);
if (ret > 0)
{
buf[ret] = 0;
tmp = adc_msg_escape(buf);
hub->command_rules = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
adc_msg_add_argument(hub->command_rules, tmp);
hub_free(tmp);
}
close(fd);
}
hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT)); hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT));
if (hub->command_support) if (hub->command_support)
{ {
adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT); adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT);
} }
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 25 + strlen(server)); hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 100 + strlen(server));
if (hub->command_banner) if (hub->command_banner)
{ {
tmp = adc_msg_escape("Powered by " SERVER); if (hub->config->show_banner_sys_info)
tmp = adc_msg_escape("Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO);
else
tmp = adc_msg_escape("Powered by " PRODUCT_STRING);
adc_msg_add_argument(hub->command_banner, "000"); adc_msg_add_argument(hub->command_banner, "000");
adc_msg_add_argument(hub->command_banner, tmp); adc_msg_add_argument(hub->command_banner, tmp);
hub_free(tmp); hub_free(tmp);
@@ -697,6 +822,9 @@ void hub_free_variables(struct hub_info* hub)
if (hub->command_motd) if (hub->command_motd)
adc_msg_free(hub->command_motd); adc_msg_free(hub->command_motd);
if (hub->command_rules)
adc_msg_free(hub->command_rules);
adc_msg_free(hub->command_support); adc_msg_free(hub->command_support);
} }
@@ -749,62 +877,81 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
{ {
struct hub_config* cfg = hub->config; struct hub_config* cfg = hub->config;
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6); struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
if (!cmd) return; struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 256);
char code[4]; char code[4];
char buf[250];
const char* text = 0; const char* text = 0;
const char* flag = 0; const char* flag = 0;
char* escaped_text = 0; char* escaped_text = 0;
int reconnect_time = 0;
#define STATUS(CODE, MSG, FLAG) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; break
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) switch (msg)
{ {
STATUS(11, msg_hub_full, 0); STATUS(11, msg_hub_full, 0, 600); /* FIXME: Proper timeout? */
STATUS(12, msg_hub_disabled, 0); STATUS(12, msg_hub_disabled, 0, -1);
STATUS(26, msg_hub_registered_users_only, 0); STATUS(26, msg_hub_registered_users_only, 0, 0);
STATUS(43, msg_inf_error_nick_missing, 0); STATUS(43, msg_inf_error_nick_missing, 0, 0);
STATUS(43, msg_inf_error_nick_multiple, 0); STATUS(43, msg_inf_error_nick_multiple, 0, 0);
STATUS(21, msg_inf_error_nick_invalid, 0); STATUS(21, msg_inf_error_nick_invalid, 0, 0);
STATUS(21, msg_inf_error_nick_long, 0); STATUS(21, msg_inf_error_nick_long, 0, 0);
STATUS(21, msg_inf_error_nick_short, 0); STATUS(21, msg_inf_error_nick_short, 0, 0);
STATUS(21, msg_inf_error_nick_spaces, 0); STATUS(21, msg_inf_error_nick_spaces, 0, 0);
STATUS(21, msg_inf_error_nick_bad_chars, 0); STATUS(21, msg_inf_error_nick_bad_chars, 0, 0);
STATUS(21, msg_inf_error_nick_not_utf8, 0); STATUS(21, msg_inf_error_nick_not_utf8, 0, 0);
STATUS(22, msg_inf_error_nick_taken, 0); STATUS(22, msg_inf_error_nick_taken, 0, 0);
STATUS(21, msg_inf_error_nick_restricted, 0); STATUS(21, msg_inf_error_nick_restricted, 0, 0);
STATUS(43, msg_inf_error_cid_invalid, "FBID"); STATUS(43, msg_inf_error_cid_invalid, "FBID", 0);
STATUS(43, msg_inf_error_cid_missing, "FMID"); STATUS(43, msg_inf_error_cid_missing, "FMID", 0);
STATUS(24, msg_inf_error_cid_taken, 0); STATUS(24, msg_inf_error_cid_taken, 0, 0);
STATUS(43, msg_inf_error_pid_missing, "FMPD"); STATUS(43, msg_inf_error_pid_missing, "FMPD", 0);
STATUS(27, msg_inf_error_pid_invalid, "FBPD"); STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0);
STATUS(31, msg_ban_permanently, 0); STATUS(31, msg_ban_permanently, 0, 0);
STATUS(32, msg_ban_temporarily, "TL600"); /* FIXME: Use a proper timeout */ STATUS(32, msg_ban_temporarily, "TL600", 600); /* FIXME: Proper timeout? */
STATUS(23, msg_auth_invalid_password, 0); STATUS(23, msg_auth_invalid_password, 0, 0);
STATUS(20, msg_auth_user_not_found, 0); STATUS(20, msg_auth_user_not_found, 0, 0);
STATUS(30, msg_error_no_memory, 0); STATUS(30, msg_error_no_memory, 0, 0);
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE); STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE); STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0);
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS); STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS); STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0);
STATUS(43, msg_user_hub_limit_low, 0); STATUS(43, msg_user_hub_limit_low, 0, 0);
STATUS(43, msg_user_hub_limit_high, 0); STATUS(43, msg_user_hub_limit_high, 0, 0);
STATUS(47, msg_proto_no_common_hash, 0, -1);
STATUS(40, msg_proto_obsolete_adc0, 0, -1);
} }
#undef STATUS #undef STATUS
escaped_text = adc_msg_escape(text); escaped_text = adc_msg_escape(text);
adc_msg_add_argument(cmd, code); adc_msg_add_argument(cmd, code);
adc_msg_add_argument(cmd, escaped_text); adc_msg_add_argument(cmd, escaped_text);
hub_free(escaped_text);
if (flag) if (flag)
{ {
adc_msg_add_argument(cmd, flag); adc_msg_add_argument(cmd, flag);
} }
route_to_user(hub, user, cmd); route_to_user(hub, user, cmd);
if (level >= status_level_fatal)
{
snprintf(buf, 230, "MS%s", escaped_text);
adc_msg_add_argument(qui, buf);
if (reconnect_time != 0)
{
snprintf(buf, 10, "TL%d", reconnect_time);
adc_msg_add_argument(qui, buf);
}
route_to_user(hub, user, qui);
}
hub_free(escaped_text);
adc_msg_free(cmd); adc_msg_free(cmd);
adc_msg_free(qui);
} }
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg) const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
@@ -842,6 +989,8 @@ const char* hub_get_status_message(struct hub_info* hub, enum status_message msg
STATUS(msg_user_slots_high); STATUS(msg_user_slots_high);
STATUS(msg_user_hub_limit_low); STATUS(msg_user_hub_limit_low);
STATUS(msg_user_hub_limit_high); STATUS(msg_user_hub_limit_high);
STATUS(msg_proto_no_common_hash);
STATUS(msg_proto_obsolete_adc0);
} }
#undef STATUS #undef STATUS
return "Unknown"; return "Unknown";
@@ -881,6 +1030,8 @@ const char* hub_get_status_message_log(struct hub_info* hub, enum status_message
STATUS(msg_user_slots_high); STATUS(msg_user_slots_high);
STATUS(msg_user_hub_limit_low); STATUS(msg_user_hub_limit_low);
STATUS(msg_user_hub_limit_high); STATUS(msg_user_hub_limit_high);
STATUS(msg_proto_no_common_hash);
STATUS(msg_proto_obsolete_adc0);
} }
#undef STATUS #undef STATUS
return "unknown"; return "unknown";

View File

@@ -45,7 +45,7 @@ enum status_message
status_msg_auth_invalid_password = -21, /* Password is wrong */ status_msg_auth_invalid_password = -21, /* Password is wrong */
status_msg_auth_user_not_found = -22, /* User not found in password database */ 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_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_low = -40, /* User is not sharing enough. */
status_msg_user_share_size_high = -41, /* User is sharing too much. */ status_msg_user_share_size_high = -41, /* User is sharing too much. */
status_msg_user_slots_low = -42, /* User has too few slots open. */ status_msg_user_slots_low = -42, /* User has too few slots open. */
@@ -53,6 +53,10 @@ enum status_message
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */ status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */ status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
}; };
@@ -91,10 +95,7 @@ struct hub_logout_info
struct hub_info struct hub_info
{ {
struct net_connection* server; struct net_connection* server;
#ifdef USE_LIBEVENT struct linked_list* server_alt_ports;
struct event ev_accept;
struct event ev_timer;
#endif
struct hub_stats stats; struct hub_stats stats;
struct event_queue* queue; struct event_queue* queue;
struct hub_config* config; struct hub_config* config;
@@ -103,6 +104,7 @@ struct hub_info
struct adc_message* command_info; /* The hub's INF command */ struct adc_message* command_info; /* The hub's INF command */
struct adc_message* command_support; /* The hub's SUP command */ struct adc_message* command_support; /* The hub's SUP command */
struct adc_message* command_motd; /* The message of the day */ struct adc_message* command_motd; /* The message of the day */
struct adc_message* command_rules; /* The hub rules */
struct adc_message* command_banner; /* The default welcome message */ struct adc_message* command_banner; /* The default welcome message */
time_t tm_started; time_t tm_started;
int status; int status;
@@ -203,8 +205,15 @@ extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
/** /**
* Send a welcome message containing the message of the day to * Send a welcome message containing the message of the day to
* one particular user. This can be sent in any point in time. * one particular user. This can be sent in any point in time.
* @return 1 if the motd were sent.
*/ */
extern void hub_send_motd(struct hub_info* hub, struct hub_user* u); extern int hub_send_motd(struct hub_info* hub, struct hub_user* u);
/**
* Send the rules if configured.
* @return 1 if the rules were sent.
*/
extern int hub_send_rules(struct hub_info* hub, struct hub_user* u);
/** /**
* Send a password challenge to a user. * Send a password challenge to a user.

View File

@@ -33,6 +33,13 @@ static void log_user_login_error(struct hub_user* u, enum status_message msg)
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent); LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
} }
static void log_user_update_error(struct hub_user* u, enum status_message msg)
{
const char* addr = user_get_address(u);
const char* message = hub_get_status_message_log(u->hub, msg);
LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
}
static void log_user_logout(struct hub_user* u, const char* message) static void log_user_logout(struct hub_user* u, const char* message)
{ {
const char* addr = user_get_address(u); const char* addr = user_get_address(u);
@@ -68,6 +75,10 @@ void on_login_success(struct hub_info* hub, struct hub_user* u)
if (user_is_logged_in(u)) /* Previous send() can fail! */ if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_motd(hub, u); hub_send_motd(hub, u);
/* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_rules(hub, u);
/* reset timeout */ /* reset timeout */
net_con_clear_timeout(u->connection); net_con_clear_timeout(u->connection);
} }
@@ -79,6 +90,13 @@ void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_mess
hub_disconnect_user(hub, u, quit_logon_error); hub_disconnect_user(hub, u, quit_logon_error);
} }
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
{
log_user_update_error(u, msg);
hub_send_status(hub, u, msg, status_level_fatal);
hub_disconnect_user(hub, u, quit_update_error);
}
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick) void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
{ {
if (user_is_logged_in(u)) if (user_is_logged_in(u))

View File

@@ -29,6 +29,7 @@ extern void on_login_success(struct hub_info* hub, struct hub_user* u);
* This event is triggered whenever a user failed to log in to the hub. * This event is triggered whenever a user failed to log in to the hub.
*/ */
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg); extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
/** /**
* This event is triggered whenever a previously logged in user leaves the hub. * This event is triggered whenever a previously logged in user leaves the hub.

View File

@@ -126,6 +126,7 @@ void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
debug_msg("hub_sendq_add", msg); debug_msg("hub_sendq_add", msg);
#endif #endif
assert(msg->cache && *msg->cache);
list_append(q->queue, msg); list_append(q->queue, msg);
q->size += msg->length; q->size += msg->length;
} }
@@ -143,10 +144,11 @@ void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user) int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
{ {
int ret;
struct adc_message* msg = list_get_first(q->queue); struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0; if (!msg) return 0;
assert(msg->cache && *msg->cache);
int ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset); ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0) if (ret > 0)
{ {

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@ static void remove_server_restricted_flags(struct adc_message* cmd)
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd) static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd)
{ {
char *it, *tmp; char *it, *tmp;
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT)) if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
{ {
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT); tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
@@ -58,7 +58,7 @@ static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd
user_set_feature_cast_support(u, it); user_set_feature_cast_support(u, it);
it = &it[5]; it = &it[5];
} }
if (*it) if (*it)
{ {
user_set_feature_cast_support(u, it); user_set_feature_cast_support(u, it);
@@ -74,9 +74,9 @@ static int check_hash_tiger(const char* cid, const char* pid)
char x_pid[64]; char x_pid[64];
char raw_pid[64]; char raw_pid[64];
uint64_t tiger_res[3]; uint64_t tiger_res[3];
memset(x_pid, 0, MAX_CID_LEN+1); memset(x_pid, 0, MAX_CID_LEN+1);
base32_decode(pid, (unsigned char*) raw_pid, MAX_CID_LEN); base32_decode(pid, (unsigned char*) raw_pid, MAX_CID_LEN);
tiger((uint64_t*) raw_pid, TIGERSIZE, (uint64_t*) tiger_res); tiger((uint64_t*) raw_pid, TIGERSIZE, (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, x_pid); base32_encode((unsigned char*) tiger_res, TIGERSIZE, x_pid);
@@ -102,7 +102,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
hub_free(pid); hub_free(pid);
return status_msg_error_no_memory; return status_msg_error_no_memory;
} }
if (strlen(cid) != MAX_CID_LEN) if (strlen(cid) != MAX_CID_LEN)
{ {
hub_free(cid); hub_free(cid);
@@ -125,7 +125,7 @@ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_mes
hub_free(pid); hub_free(pid);
return status_msg_inf_error_cid_invalid; return status_msg_inf_error_cid_invalid;
} }
if (!is_valid_base32_char(pid[pos])) if (!is_valid_base32_char(pid[pos]))
{ {
hub_free(cid); hub_free(cid);
@@ -187,7 +187,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use
* remove any wrong address, and replace it with the correct one * remove any wrong address, and replace it with the correct one
* as seen by the hub. * as seen by the hub.
*/ */
int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
const char* address = user_get_address(user); const char* address = user_get_address(user);
@@ -223,7 +223,7 @@ int check_network(struct hub_info* hub, struct hub_user* user, struct adc_messag
return 0; return 0;
} }
void strip_network(struct hub_user* user, struct adc_message* cmd) static void strip_network(struct hub_user* user, struct adc_message* cmd)
{ {
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
@@ -415,7 +415,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
int64_t shared_size = atoll(arg); int64_t shared_size = atoll(arg);
if (shared_size < 0) if (shared_size < 0)
shared_size = 0; shared_size = 0;
if (user_is_logged_in(user)) if (user_is_logged_in(user))
{ {
hub->users->shared_size -= user->limits.shared_size; hub->users->shared_size -= user->limits.shared_size;
@@ -425,14 +425,14 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
hub_free(arg); hub_free(arg);
arg = 0; arg = 0;
} }
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES); arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
if (arg) if (arg)
{ {
ssize_t shared_files = atoll(arg); ssize_t shared_files = atoll(arg);
if (shared_files < 0) if (shared_files < 0)
shared_files = 0; shared_files = 0;
if (user_is_logged_in(user)) if (user_is_logged_in(user))
{ {
hub->users->shared_files -= user->limits.shared_files; hub->users->shared_files -= user->limits.shared_files;
@@ -442,7 +442,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
hub_free(arg); hub_free(arg);
arg = 0; arg = 0;
} }
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL); arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
if (arg) if (arg)
{ {
@@ -497,7 +497,7 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
{ {
return status_msg_user_share_size_high; return status_msg_user_share_size_high;
} }
if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) || if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) ||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) || (user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) ||
(user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) || (user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) ||
@@ -505,14 +505,14 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
{ {
return status_msg_user_hub_limit_high; return status_msg_user_hub_limit_high;
} }
if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) || if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) ||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) || (user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) ||
(user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub))) (user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub)))
{ {
return status_msg_user_hub_limit_low; return status_msg_user_hub_limit_low;
} }
if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub)) if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub))
{ {
return status_msg_user_slots_low; return status_msg_user_slots_low;
@@ -526,7 +526,6 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_
return 0; return 0;
} }
/* /*
* Set the expected credentials, and returns 1 if authentication is needed, * Set the expected credentials, and returns 1 if authentication is needed,
* or 0 if not. * or 0 if not.
@@ -560,11 +559,11 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
case cred_guest: case cred_guest:
/* Nothing to be added to the info message */ /* Nothing to be added to the info message */
break; break;
case cred_user: case cred_user:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
break; break;
case cred_operator: case cred_operator:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
break; break;
@@ -572,11 +571,11 @@ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct a
case cred_super: case cred_super:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
break; break;
case cred_admin: case cred_admin:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN); adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
break; break;
case cred_link: case cred_link:
break; break;
} }
@@ -648,7 +647,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user*
return ret; \ return ret; \
} while(0) } while(0)
int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{ {
/* Make syntax checks. */ /* Make syntax checks. */
INF_CHECK(check_required_login_flags, hub, user, cmd); INF_CHECK(check_required_login_flags, hub, user, cmd);
@@ -671,13 +670,12 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
int code = 0; int code = 0;
INF_CHECK(hub_perform_login_checks, hub, user, cmd); INF_CHECK(hub_perform_login_checks, hub, user, cmd);
/* Private ID must never be broadcasted - drop it! */ /* Private ID must never be broadcasted - drop it! */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
code = set_credentials(hub, user, cmd); code = set_credentials(hub, user, cmd);
/* Note: this must be done *after* set_credentials. */ /* Note: this must be done *after* set_credentials. */
if (check_is_hub_full(hub, user)) if (check_is_hub_full(hub, user))
{ {
@@ -715,6 +713,7 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
*/ */
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified) int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
{ {
int ret;
struct adc_message* cmd = adc_msg_copy(cmd_unmodified); struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
if (!cmd) return -1; /* OOM */ if (!cmd) return -1; /* OOM */
@@ -736,8 +735,8 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
adc_msg_free(cmd); adc_msg_free(cmd);
return 0; return 0;
} }
int ret = hub_handle_info_login(hub, user, cmd); ret = hub_handle_info_login(hub, user, cmd);
if (ret < 0) if (ret < 0)
{ {
on_login_failure(hub, user, ret); on_login_failure(hub, user, ret);
@@ -762,7 +761,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! */ /* 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_PRIVATE_ID);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
/* /*
* If the nick is not accepted, do not relay it. * If the nick is not accepted, do not relay it.
* Otherwise, the nickname will be updated. * Otherwise, the nickname will be updated.
@@ -774,21 +773,29 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
#endif #endif
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
} }
/* FIXME - What if limits are not met ? */ ret = check_limits(hub, user, cmd);
check_limits(hub, user, cmd); if (ret < 0)
{
on_update_failure(hub, user, ret);
adc_msg_free(cmd);
return -1;
}
strip_network(user, cmd); strip_network(user, cmd);
hub_handle_info_low_bandwidth(hub, user, cmd); hub_handle_info_low_bandwidth(hub, user, cmd);
user_update_info(user, cmd); user_update_info(user, cmd);
if (!adc_msg_is_empty(cmd)) if (!adc_msg_is_empty(cmd))
{ {
route_message(hub, user, cmd); route_message(hub, user, cmd);
} }
adc_msg_free(cmd); adc_msg_free(cmd);
} }
return 0; return 0;
} }

View File

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

View File

@@ -33,13 +33,13 @@ static const char* arg_pid = 0;
static int arg_log_syslog = 0; static int arg_log_syslog = 0;
#if !defined(WIN32) && defined(USE_LIBEVENT) #if !defined(WIN32)
void hub_handle_signal(int fd, short events, void* arg) extern struct hub_info* g_hub;
void hub_handle_signal(int sig)
{ {
struct hub_info* hub = (struct hub_info*) arg; struct hub_info* hub = g_hub;
int signal = fd;
switch (signal) switch (sig)
{ {
case SIGINT: case SIGINT:
LOG_INFO("Interrupted. Shutting down..."); LOG_INFO("Interrupted. Shutting down...");
@@ -65,7 +65,6 @@ void hub_handle_signal(int fd, short events, void* arg)
} }
} }
static struct event signal_events[10];
static int signals[] = static int signals[] =
{ {
SIGINT, /* Interrupt the application */ SIGINT, /* Interrupt the application */
@@ -77,11 +76,18 @@ static int signals[] =
void setup_signal_handlers(struct hub_info* hub) void setup_signal_handlers(struct hub_info* hub)
{ {
int i = 0; sigset_t sig_set;
struct sigaction act;
int i;
sigemptyset(&sig_set);
act.sa_mask = sig_set;
act.sa_flags = SA_ONSTACK | SA_RESTART;
act.sa_handler = hub_handle_signal;
for (i = 0; signals[i]; i++) for (i = 0; signals[i]; i++)
{ {
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub); if (sigaction(signals[i], &act, 0) != 0)
if (signal_add(&signal_events[i], NULL))
{ {
LOG_ERROR("Error setting signal handler %d", signals[i]); LOG_ERROR("Error setting signal handler %d", signals[i]);
} }
@@ -90,14 +96,8 @@ void setup_signal_handlers(struct hub_info* hub)
void shutdown_signal_handlers(struct hub_info* hub) void shutdown_signal_handlers(struct hub_info* hub)
{ {
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_del(&signal_events[i]);
}
} }
#endif /* !WIN32 */
#endif /* !WIN32 && USE_LIBEVENT*/
int main_loop() int main_loop()
@@ -133,7 +133,7 @@ int main_loop()
hub = hub_start_service(&configuration); hub = hub_start_service(&configuration);
if (!hub) if (!hub)
return -1; return -1;
#if !defined(WIN32) && defined(USE_LIBEVENT) #if !defined(WIN32)
setup_signal_handlers(hub); setup_signal_handlers(hub);
#endif #endif
} }
@@ -148,7 +148,7 @@ int main_loop()
} while (hub->status == hub_status_restart); } while (hub->status == hub_status_restart);
#if !defined(WIN32) && defined(USE_LIBEVENT) #if !defined(WIN32)
shutdown_signal_handlers(hub); shutdown_signal_handlers(hub);
#endif #endif
@@ -190,8 +190,8 @@ int check_configuration(int dump)
void print_version() void print_version()
{ {
fprintf(stdout, "" PRODUCT " " VERSION "\n"); fprintf(stdout, PRODUCT_STRING "\n");
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n" fprintf(stdout, COPYRIGHT "\n"
"This is free software with ABSOLUTELY NO WARRANTY.\n\n"); "This is free software with ABSOLUTELY NO WARRANTY.\n\n");
exit(0); exit(0);
} }

View File

@@ -24,41 +24,16 @@
/* FIXME: This should not be needed! */ /* FIXME: This should not be needed! */
extern struct hub_info* g_hub; extern struct hub_info* g_hub;
#ifdef DEBUG_SENDQ
void debug_sendq_send(struct hub_user* user, int sent, int total)
{
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->net.connection.sd, sent, total);
if (sent == -1)
{
int err = net_error();
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
}
}
void debug_sendq_recv(struct hub_user* user, int received, int max, const char* buffer)
{
LOG_DUMP("RECV: %d/%d bytes\n", received, (int) max);
if (received == -1)
{
int err = net_error();
LOG_DUMP(" errno: %d - %s\n", err, net_error_string(err));
}
else if (received > 0)
{
char* data = hub_malloc_zero(received + 1);
memcpy(data, buffer, received);
LOG_DUMP("RECV: \"%s\"\n", data);
hub_free(data);
}
}
#endif
int handle_net_read(struct hub_user* user) int handle_net_read(struct hub_user* user)
{ {
static char buf[MAX_RECV_BUF]; static char buf[MAX_RECV_BUF];
struct hub_recvq* q = user->recv_queue; struct hub_recvq* q = user->recv_queue;
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF); size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
ssize_t size = net_con_recv(user->connection, buf, MAX_RECV_BUF); ssize_t size;
if (user_flag_get(user, flag_maxbuf))
buf_size = 0;
size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size);
if (size > 0) if (size > 0)
buf_size += size; buf_size += size;
@@ -162,26 +137,16 @@ void net_event(struct net_connection* con, int event, void *arg)
int flag_close = 0; int flag_close = 0;
#ifdef DEBUG_SENDQ #ifdef DEBUG_SENDQ
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", fd, (int) event, arg); LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
#endif #endif
if (event == NET_EVENT_SOCKERROR) if (event == NET_EVENT_TIMEOUT)
{
hub_disconnect_user(g_hub, user, quit_socket_error);
return;
}
else if (event == NET_EVENT_CLOSED)
{
hub_disconnect_user(g_hub, user, quit_disconnected);
return;
}
else if (event == NET_EVENT_TIMEOUT)
{ {
if (user_is_connecting(user)) if (user_is_connecting(user))
{ {
hub_disconnect_user(g_hub, user, quit_timeout); hub_disconnect_user(g_hub, user, quit_timeout);
return;
} }
return;
} }
if (event & NET_EVENT_READ) if (event & NET_EVENT_READ)
@@ -229,7 +194,7 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
} }
} }
addr = ip_convert_to_string(&ipaddr); addr = ip_convert_to_string(&ipaddr);
/* FIXME: Should have a plugin log this */ /* FIXME: Should have a plugin log this */
LOG_TRACE("Got connection from %s", addr); LOG_TRACE("Got connection from %s", addr);

View File

@@ -26,8 +26,7 @@ static char probe_recvbuf[PROBE_RECV_SIZE];
static void probe_net_event(struct net_connection* con, int events, void *arg) 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); struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
if (events == NET_EVENT_TIMEOUT)
if (events == NET_EVENT_SOCKERROR || events == NET_EVENT_CLOSED || events == NET_EVENT_TIMEOUT)
{ {
probe_destroy(probe); probe_destroy(probe);
return; return;
@@ -47,6 +46,13 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
if (memcmp(probe_recvbuf, "HSUP", 4) == 0) if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
{ {
LOG_TRACE("Probed ADC"); LOG_TRACE("Probed ADC");
#ifdef SSL_SUPPORT
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
{
LOG_TRACE("Not TLS connection - closing connection.");
}
else
#endif
if (user_create(probe->hub, probe->connection, &probe->addr)) if (user_create(probe->hub, probe->connection, &probe->addr))
{ {
probe->connection = 0; probe->connection = 0;

View File

@@ -106,6 +106,8 @@ int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_messag
if (!user->connection) if (!user->connection)
return 0; return 0;
assert(msg->cache && *msg->cache);
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline)) if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
{ {
/* Perform oportunistic write */ /* Perform oportunistic write */

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -83,7 +83,14 @@ void user_set_state(struct hub_user* user, enum user_state state)
void user_set_info(struct hub_user* user, struct adc_message* cmd) void user_set_info(struct hub_user* user, struct adc_message* cmd)
{ {
adc_msg_free(user->info); adc_msg_free(user->info);
user->info = adc_msg_incref(cmd); if (cmd)
{
user->info = adc_msg_incref(cmd);
}
else
{
user->info = 0;
}
} }
void user_update_info(struct hub_user* u, struct adc_message* cmd) void user_update_info(struct hub_user* u, struct adc_message* cmd)
@@ -97,7 +104,7 @@ void user_update_info(struct hub_user* u, struct adc_message* cmd)
/* FIXME: OOM! */ /* FIXME: OOM! */
return; return;
} }
/* /*
* FIXME: Optimization potential: * FIXME: Optimization potential:
* *
@@ -127,10 +134,9 @@ static int convert_support_fourcc(int fourcc)
{ {
switch (fourcc) switch (fourcc)
{ {
case FOURCC('B','A','S','0'): /* Obsolete */ case FOURCC('B','A','S','0'):
#ifndef OLD_ADC_SUPPORT return feature_bas0;
return 0;
#endif
case FOURCC('B','A','S','E'): case FOURCC('B','A','S','E'):
return feature_base; return feature_base;
@@ -336,6 +342,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
case quit_socket_error: return "socket error"; break; case quit_socket_error: return "socket error"; break;
case quit_protocol_error: return "protocol error"; break; case quit_protocol_error: return "protocol error"; break;
case quit_logon_error: return "login error"; break; case quit_logon_error: return "login error"; break;
case quit_update_error: return "update error"; break;
case quit_hub_disabled: return "hub disabled"; break; case quit_hub_disabled: return "hub disabled"; break;
case quit_ghost_timeout: return "ghost"; break; case quit_ghost_timeout: return "ghost"; break;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* uhub - A tiny ADC p2p connection hub * uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey * Copyright (C) 2007-2010, Jan Vidar Krey
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -45,6 +45,8 @@ enum user_flags
feature_ping = 0x00000080, /** PING: Hub pinger information extension */ feature_ping = 0x00000080, /** PING: Hub pinger information extension */
feature_link = 0x00000100, /** LINK: Hub link (not supported) */ feature_link = 0x00000100, /** LINK: Hub link (not supported) */
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */ feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
flag_muted = 0x00800000, /** User is muted (cannot chat) */
flag_ignore = 0x01000000, /** Ignore further reads */ flag_ignore = 0x01000000, /** Ignore further reads */
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */ flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */ flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
@@ -67,8 +69,9 @@ enum user_quit_reason
quit_socket_error = 7, /** A socket error occured */ quit_socket_error = 7, /** A socket error occured */
quit_protocol_error = 8, /** Fatal protocol error */ quit_protocol_error = 8, /** Fatal protocol error */
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */ quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */ quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */ quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
}; };
/** Returns an apropriate string for the given quit reason */ /** Returns an apropriate string for the given quit reason */

View File

@@ -19,8 +19,6 @@
#include "uhub.h" #include "uhub.h"
#define USERMANAGER_TIMER
/* /*
* This callback function is used to clear user objects from the userlist. * This callback function is used to clear user objects from the userlist.
* Should only be used in uman_shutdown(). * Should only be used in uman_shutdown().
@@ -40,7 +38,6 @@ static void clear_user_list_callback(void* ptr)
} }
} }
void uman_update_stats(struct hub_info* hub) void uman_update_stats(struct hub_info* hub)
{ {
const int factor = TIMEOUT_STATS; const int factor = TIMEOUT_STATS;
@@ -58,7 +55,6 @@ void uman_update_stats(struct hub_info* hub)
net_stats_reset(); net_stats_reset();
} }
void uman_print_stats(struct hub_info* hub) void uman_print_stats(struct hub_info* hub)
{ {
LOG_INFO("Statistics users=" 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)", 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)",
@@ -70,28 +66,16 @@ void uman_print_stats(struct hub_info* hub)
(int) hub->stats.net_rx_peak / 1024); (int) hub->stats.net_rx_peak / 1024);
} }
#ifdef USERMANAGER_TIMER static void timer_statistics(struct timeout_evt* t)
#ifdef USE_LIBEVENT
static void timer_statistics(int fd, short ev, void *arg)
{ {
struct hub_info* hub = (struct hub_info*) arg; struct hub_info* hub = (struct hub_info*) t->ptr;
struct timeval timeout = { TIMEOUT_STATS, 0 };
uman_update_stats(hub); uman_update_stats(hub);
evtimer_set(&hub->ev_timer, timer_statistics, hub); timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->users->timeout, TIMEOUT_STATS);
evtimer_add(&hub->ev_timer, &timeout);
} }
#endif
#endif
int uman_init(struct hub_info* hub) int uman_init(struct hub_info* hub)
{ {
struct hub_user_manager* users = NULL; struct hub_user_manager* users = NULL;
#ifdef USERMANAGER_TIMER
#ifdef USE_LIBEVENT
struct timeval timeout = { TIMEOUT_STATS, 0 };
#endif
#endif
if (!hub) if (!hub)
return -1; return -1;
@@ -109,17 +93,14 @@ int uman_init(struct hub_info* hub)
return -1; return -1;
} }
hub->users = users; if (net_backend_get_timeout_queue())
#ifdef USERMANAGER_TIMER
#ifdef USE_LIBEVENT
if (net_get_evbase())
{ {
evtimer_set(&hub->ev_timer, timer_statistics, hub); users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
evtimer_add(&hub->ev_timer, &timeout); timeout_evt_initialize(users->timeout, timer_statistics, hub);
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
} }
#endif
#endif // 0 hub->users = users;
return 0; return 0;
} }
@@ -129,12 +110,11 @@ int uman_shutdown(struct hub_info* hub)
if (!hub || !hub->users) if (!hub || !hub->users)
return -1; return -1;
#ifdef USERMANAGER_TIMER if (net_backend_get_timeout_queue())
#ifdef USE_LIBEVENT {
if (evtimer_pending(&hub->ev_timer, 0)) timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
evtimer_del(&hub->ev_timer); hub_free(hub->users->timeout);
#endif }
#endif
if (hub->users->list) if (hub->users->list)
{ {
@@ -145,6 +125,7 @@ int uman_shutdown(struct hub_info* hub)
hub_free(hub->users); hub_free(hub->users);
hub->users = 0; hub->users = 0;
return 0; return 0;
} }
@@ -174,7 +155,7 @@ int uman_remove(struct hub_info* hub, struct hub_user* user)
return -1; return -1;
list_remove(hub->users->list, user); list_remove(hub->users->list, user);
if (hub->users->count > 0) if (hub->users->count > 0)
{ {
hub->users->count--; hub->users->count--;
@@ -183,12 +164,12 @@ int uman_remove(struct hub_info* hub, struct hub_user* user)
{ {
assert(!"negative count!"); assert(!"negative count!");
} }
hub->users->shared_size -= user->limits.shared_size; hub->users->shared_size -= user->limits.shared_size;
hub->users->shared_files -= user->limits.shared_files; hub->users->shared_files -= user->limits.shared_files;
user->hub = 0; user->hub = 0;
return 0; return 0;
} }
@@ -243,8 +224,9 @@ size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, st
int uman_send_user_list(struct hub_info* hub, struct hub_user* target) int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
{ {
int ret = 1; int ret = 1;
struct hub_user* user;
user_flag_set(target, flag_user_list); user_flag_set(target, flag_user_list);
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */ user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
while (user) while (user)
{ {
if (user_is_logged_in(user)) if (user_is_logged_in(user))
@@ -255,7 +237,7 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
} }
user = (struct hub_user*) list_get_next(hub->users->list); user = (struct hub_user*) list_get_next(hub->users->list);
} }
#if 0 #if 0
FIXME: FIXME FIXME handle send queue excess FIXME: FIXME FIXME handle send queue excess
if (!target->send_queue_size) if (!target->send_queue_size)
@@ -266,12 +248,11 @@ int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
return ret; return ret;
} }
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving) void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
{ {
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6); struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid)); adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
if (leaving->quit_reason == quit_banned || leaving->quit_reason == quit_kicked) if (leaving->quit_reason == quit_banned || leaving->quit_reason == quit_kicked)
{ {
adc_msg_add_argument(command, ADC_QUI_FLAG_DISCONNECT); adc_msg_add_argument(command, ADC_QUI_FLAG_DISCONNECT);
@@ -280,7 +261,6 @@ void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
adc_msg_free(command); adc_msg_free(command);
} }
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user) sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
{ {
sid_t sid = sid_alloc(hub->users->sids, user); sid_t sid = sid_alloc(hub->users->sids, user);

View File

@@ -28,6 +28,7 @@ struct hub_user_manager
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */ uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */ uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct linked_list* list; /**<< "Contains all logged in 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
View 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, 120); /* FIXME: max 120 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;
}

View File

@@ -20,11 +20,50 @@
#ifndef HAVE_UHUB_NETWORK_BACKEND_H #ifndef HAVE_UHUB_NETWORK_BACKEND_H
#define HAVE_UHUB_NETWORK_BACKEND_H #define HAVE_UHUB_NETWORK_BACKEND_H
struct net_backend;
struct net_backend_common;
struct net_backend_handler;
struct net_cleanup_handler;
struct net_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. * Initialize the network backend.
* Returns 1 on success, or 0 on failure. * Returns 1 on success, or 0 on failure.
*/ */
extern int net_backend_initialize(); extern int net_backend_init();
/** /**
* Shutdown the network connection backend. * Shutdown the network connection backend.
@@ -36,4 +75,15 @@ extern void net_backend_shutdown();
*/ */
extern int net_backend_process(); 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 */ #endif /* HAVE_UHUB_NETWORK_BACKEND_H */

View File

@@ -1,37 +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_READ NET_EVENT_READ
#define NET_WANT_WRITE NET_EVENT_WRITE #define NET_WANT_WRITE NET_EVENT_WRITE
#define NET_WANT_ACCEPT 0x0008 #define NET_WANT_ACCEPT NET_EVENT_READ
#define NET_WANT_SSL_READ 0x0010 #define NET_WANT_SSL_READ 0x0010
#define NET_WANT_SSL_WRITE 0x0020 #define NET_WANT_SSL_WRITE 0x0020
#define NET_WANT_SSL_ACCEPT 0x0040 #define NET_WANT_SSL_ACCEPT 0x0040
#define NET_WANT_SSL_CONNECT 0x0080 #define NET_WANT_SSL_CONNECT 0x0080
#define NET_WANT_SSL_X509_LOOKUP 0x0100 #define NET_WANT_SSL_X509_LOOKUP 0x0100
#define NET_PROCESSING_BUSY 0x8000 #define NET_CLEANUP 0x8000
#define NET_CLEANUP 0x4000
#define NET_INITIALIZED 0x2000
#define NET_TIMER_ENABLED 0x1000
/* FIXME: Meant for debugging */
#define NET_EVENT_SET 0x0800
#define NET_CON_STRUCT_BASIC \ #define NET_CON_STRUCT_BASIC \
int sd; /** socket descriptor */ \ int sd; /** socket descriptor */ \
uint32_t flags; /** Connection flags */ \ uint32_t flags; /** Connection flags */ \
void* ptr; /** data pointer */ \ void* ptr; /** data pointer */ \
net_connection_cb callback; /** Callback function */ \ net_connection_cb callback; /** Callback function */ \
struct timeout_evt* timeout; /** timeout event handler */
#define NET_CON_STRUCT_SSL \ #define NET_CON_STRUCT_SSL \
SSL* ssl; /** SSL handle */ \ 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. */ \ size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */ \
#ifdef USE_SSL #ifdef SSL_SUPPORT
#define NET_CON_STRUCT_COMMON \ #define NET_CON_STRUCT_COMMON \
NET_CON_STRUCT_BASIC \ NET_CON_STRUCT_BASIC \
NET_CON_STRUCT_SSL NET_CON_STRUCT_SSL
#else #else
#define NET_CON_STRUCT_COMMON \ #define NET_CON_STRUCT_COMMON \
NET_CON_STRUCT_BASIC NET_CON_STRUCT_BASIC
#endif #endif /* SSL_SUPPORT */

View File

@@ -21,39 +21,39 @@
#include "network/common.h" #include "network/common.h"
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
enum uhub_tls_state
{
tls_st_none,
tls_st_error,
tls_st_accepting,
tls_st_connecting,
tls_st_connected,
tls_st_disconnecting,
};
static int handle_openssl_error(struct net_connection* con, int ret) static int handle_openssl_error(struct net_connection* con, int ret)
{ {
uhub_assert(con); uhub_assert(con);
int error = SSL_get_error(net_con_get_ssl(con), ret); int error = SSL_get_error(con->ssl, ret);
switch (error) switch (error)
{ {
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error); LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_ZERO_RETURN", ret, error);
con->ssl_state = tls_st_error;
return -1; return -1;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error); LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_READ", ret, error);
net_con_update(con, NET_EVENT_READ | NET_WANT_SSL_READ); con->flags |= NET_WANT_SSL_READ;
net_con_update(con, NET_EVENT_READ);
return 0; return 0;
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error); LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_WRITE", ret, error);
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_WRITE); con->flags |= NET_WANT_SSL_WRITE;
return 0; net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE);
case SSL_ERROR_WANT_CONNECT:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_CONNECT", ret, error);
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_CONNECT);
return 0;
case SSL_ERROR_WANT_ACCEPT:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_ACCEPT", ret, error);
net_con_update(con, NET_EVENT_READ | NET_EVENT_WRITE | NET_WANT_SSL_ACCEPT);
return 0;
case SSL_ERROR_WANT_X509_LOOKUP:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_WANT_X509_LOOKUP", ret, error);
return 0; return 0;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
@@ -67,6 +67,7 @@ static int handle_openssl_error(struct net_connection* con, int ret)
case SSL_ERROR_SSL: case SSL_ERROR_SSL:
LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error); LOG_PROTO("SSL_get_error: ret=%d, error=%d: SSL_ERROR_SSL", ret, error);
/* internal openssl error */ /* internal openssl error */
con->ssl_state = tls_st_error;
return -1; return -1;
} }
@@ -76,14 +77,15 @@ static int handle_openssl_error(struct net_connection* con, int ret)
ssize_t net_con_ssl_accept(struct net_connection* con) ssize_t net_con_ssl_accept(struct net_connection* con)
{ {
uhub_assert(con); uhub_assert(con);
con->ssl_state = tls_st_accepting;
ssize_t ret = SSL_accept(net_con_get_ssl(con)); ssize_t ret = SSL_accept(con->ssl);
#ifdef NETWORK_DUMP_DEBUG #ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_accept() ret=%d", ret); LOG_PROTO("SSL_accept() ret=%d", ret);
#endif #endif
if (ret > 0) if (ret > 0)
{ {
net_con_update(con, NET_EVENT_READ); net_con_update(con, NET_EVENT_READ);
con->ssl_state = tls_st_connected;
} }
else else
{ {
@@ -96,12 +98,14 @@ ssize_t net_con_ssl_connect(struct net_connection* con)
{ {
uhub_assert(con); uhub_assert(con);
ssize_t ret = SSL_connect(net_con_get_ssl(con)); con->ssl_state = tls_st_connecting;
ssize_t ret = SSL_connect(con->ssl);
#ifdef NETWORK_DUMP_DEBUG #ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("SSL_connect() ret=%d", ret); LOG_PROTO("SSL_connect() ret=%d", ret);
#endif #endif
if (ret > 0) if (ret > 0)
{ {
con->ssl_state = tls_st_connected;
net_con_update(con, NET_EVENT_READ); net_con_update(con, NET_EVENT_READ);
} }
else else
@@ -119,14 +123,14 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
if (ssl_mode == net_con_ssl_mode_server) if (ssl_mode == net_con_ssl_mode_server)
{ {
ssl = SSL_new(ssl_ctx); ssl = SSL_new(ssl_ctx);
SSL_set_fd(ssl, net_con_get_sd(con)); SSL_set_fd(ssl, con->sd);
net_con_set_ssl(con, ssl); net_con_set_ssl(con, ssl);
return net_con_ssl_accept(con); return net_con_ssl_accept(con);
} }
else else
{ {
ssl = SSL_new(SSL_CTX_new(TLSv1_method())); ssl = SSL_new(SSL_CTX_new(TLSv1_method()));
SSL_set_fd(ssl, net_con_get_sd(con)); SSL_set_fd(ssl, con->sd);
net_con_set_ssl(con, ssl); net_con_set_ssl(con, ssl);
return net_con_ssl_connect(con); return net_con_ssl_connect(con);
} }
@@ -136,28 +140,42 @@ ssize_t net_con_ssl_handshake(struct net_connection* con, enum net_con_ssl_mode
ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len) ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
{ {
int ret = net_send(net_con_get_sd(con), buf, len, UHUB_SEND_SIGNAL); int ret;
if (ret == -1) #ifdef SSL_SUPPORT
if (!con->ssl)
{ {
if (net_error() == EWOULDBLOCK || net_error() == EINTR) #endif
return 0; ret = net_send(con->sd, buf, len, UHUB_SEND_SIGNAL);
return -1; 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; return ret;
} }
ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len) ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{ {
uhub_assert(con); int ret;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
if (!net_con_is_ssl(con)) if (!net_con_is_ssl(con))
{ {
#endif #endif
int ret = net_recv(net_con_get_sd(con), buf, len, 0); ret = net_recv(con->sd, buf, len, 0);
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("net_recv: ret=%d", ret);
#endif
if (ret == -1) if (ret == -1)
{ {
if (net_error() == EWOULDBLOCK || net_error() == EINTR) if (net_error() == EWOULDBLOCK || net_error() == EINTR)
@@ -168,16 +186,15 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{ {
return -1; return -1;
} }
return ret;
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
} }
else else
{ {
int ret = SSL_read(net_con_get_ssl(con), buf, len); if (con->ssl_state == tls_st_error)
#ifdef NETWORK_DUMP_DEBUG return -1;
LOG_PROTO("net_recv: ret=%d", ret);
#endif 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) if (ret > 0)
{ {
net_con_update(con, NET_EVENT_READ); net_con_update(con, NET_EVENT_READ);
@@ -186,14 +203,14 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
{ {
return -handle_openssl_error(con, ret); return -handle_openssl_error(con, ret);
} }
return ret;
} }
#endif #endif
return ret;
} }
ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len) ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
{ {
int ret = net_recv(net_con_get_sd(con), buf, len, MSG_PEEK); int ret = net_recv(con->sd, buf, len, MSG_PEEK);
if (ret == -1) if (ret == -1)
{ {
if (net_error() == EWOULDBLOCK || net_error() == EINTR) if (net_error() == EWOULDBLOCK || net_error() == EINTR)
@@ -205,6 +222,107 @@ ssize_t net_con_peek(struct net_connection* con, void* buf, size_t len)
return ret; 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;
if (events == NET_EVENT_TIMEOUT)
{
LOG_TRACE("net_con_callback(%p, TIMEOUT", con);
con->callback(con, events, con->ptr);
return;
}
#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
}

View File

@@ -21,16 +21,17 @@
#define HAVE_UHUB_NETWORK_CONNECTION_H #define HAVE_UHUB_NETWORK_CONNECTION_H
#include "uhub.h" #include "uhub.h"
#include "network/common.h"
#include "network/backend.h" #include "network/backend.h"
#define NET_EVENT_TIMEOUT 0x0001 #define NET_EVENT_TIMEOUT 0x0001
#define NET_EVENT_READ 0x0002 #define NET_EVENT_READ 0x0002
#define NET_EVENT_WRITE 0x0004 #define NET_EVENT_WRITE 0x0004
#define NET_EVENT_SOCKERROR 0x1000 /* Socket error, closed */
#define NET_EVENT_CLOSED 0x2000 /* Socket closed */
struct net_connection; struct net_connection
typedef void (*net_connection_cb)(struct net_connection*, int event, void* ptr); {
NET_CON_STRUCT_COMMON
};
extern int net_con_get_sd(struct net_connection* con); extern int net_con_get_sd(struct net_connection* con);
extern void* net_con_get_ptr(struct net_connection* con); extern void* net_con_get_ptr(struct net_connection* con);
@@ -40,14 +41,14 @@ 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_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_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events);
extern void net_con_update(struct net_connection* con, int events); extern void net_con_update(struct net_connection* con, int events);
extern void net_con_callback(struct net_connection* con, int events);
/** /**
* Close the connection. * Close the connection.
* This will ensure a connection is closed properly and will generate a NET_EVENT_DESTROYED event which indicates * 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). * that the con can safely be deleted (or set to NULL).
* @returns 1 if the memory pointed to by con can be freed immediately, or 0 if it needs to go through the NET_EVENT_DESTROYED event.
*/ */
extern int net_con_close(struct net_connection* con); extern void net_con_close(struct net_connection* con);
/** /**
* Send data * Send data

View File

@@ -27,280 +27,160 @@
#define EPOLL_EVBUFFER 512 #define EPOLL_EVBUFFER 512
struct net_connection struct net_connection_epoll
{ {
int sd; NET_CON_STRUCT_COMMON
uint32_t flags; struct epoll_event ev;
net_connection_cb callback;
void* ptr;
struct epoll_event ev;
struct timeout_evt* timeout;
#ifdef SSL_SUPPORT
SSL* ssl;
size_t write_len; /** Length of last SSL_write(), only used if flags is NET_WANT_SSL_READ. */
#endif
}; };
struct net_backend struct net_backend_epoll
{ {
int epfd; int epfd;
size_t num; struct net_connection_epoll** conns;
size_t max;
struct net_connection** conns;
struct epoll_event events[EPOLL_EVBUFFER]; struct epoll_event events[EPOLL_EVBUFFER];
time_t now; struct net_backend_common* common;
struct timeout_queue timeout_queue;
}; };
static struct net_backend* g_backend = 0; static void net_backend_set_handlers(struct net_backend_handler* handler);
static void net_con_print(const char* prefix, struct net_connection* con) const char* net_backend_name_epoll()
{ {
char buf[512]; return "epoll";
int off = snprintf(buf, 512, "%s: net_connection={ sd=%d, flags=%u, callback=%p, ptr=%p, ev={ events=%s%s, data.ptr=%p }",
prefix, con->sd, con->flags, con->callback, con->ptr, (con->ev.events & EPOLLIN ? "R" : ""),(con->ev.events & EPOLLOUT ? "W" : "") , con->ev.data.ptr);
if (con->timeout)
{
sprintf(buf + off, ", timeout={ %d seconds left }", (int) (con->timeout->timestamp - g_backend->now));
}
else
{
sprintf(buf + off, ", timeout=NULL");
}
LOG_TRACE(buf);
} }
/** int net_backend_poll_epoll(struct net_backend* data, int ms)
* Initialize the network backend.
* Returns 1 on success, or 0 on failure.
*/
int net_backend_initialize()
{ {
size_t max = net_get_max_sockets(); struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
g_backend = hub_malloc(sizeof(struct net_backend)); int res = epoll_wait(backend->epfd, backend->events, MIN(backend->common->num, EPOLL_EVBUFFER), ms);
g_backend->epfd = epoll_create(max); if (res == -1 && errno == EINTR)
if (g_backend->epfd == -1)
{
LOG_WARN("Unable to create epoll socket.");
return 0; return 0;
} return res;
g_backend->num = 0;
g_backend->max = max;
g_backend->conns = hub_malloc_zero(sizeof(struct net_connection*) * max);
memset(g_backend->events, 0, sizeof(g_backend->events));
g_backend->now = time(0);
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
return 1;
} }
/** void net_backend_process_epoll(struct net_backend* data, int res)
* Shutdown the network connection backend.
*/
void net_backend_shutdown()
{ {
close(g_backend->epfd); int n, ev;
hub_free(g_backend->conns); struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
hub_free(g_backend);
}
/**
* Process the network backend.
*/
int net_backend_process()
{
int n;
LOG_TRACE("epoll_wait: fd=%d, events=%x, max=%zu", g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER));
int res = epoll_wait(g_backend->epfd, g_backend->events, MIN(g_backend->num, EPOLL_EVBUFFER), 1000);
if (res == -1)
{
LOG_WARN("epoll_wait returned -1");
return 0;
}
for (n = 0; n < res; n++) for (n = 0; n < res; n++)
{ {
struct net_connection* con = (struct net_connection*) g_backend->events[n].data.ptr; struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd];
int ev = 0; if (con)
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ; {
if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE; ev = 0;
con->callback(con, ev, con->ptr); 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);
}
} }
return 1;
} }
struct net_connection* net_con_create_epoll(struct net_backend* data)
struct net_connection* net_con_create()
{ {
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection)); struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
con->sd = -1; con->sd = -1;
return con; return con;
} }
void net_con_destroy(struct net_connection* con) void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
{
hub_free(con);
}
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
{ {
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
con->sd = sd; con->sd = sd;
con->flags = NET_INITIALIZED; con->flags = 0;
con->callback = callback; con->callback = callback;
con->ev.events = 0; con->ev.events = 0;
con->ptr = (void*) ptr; con->ptr = (void*) ptr;
con->ev.data.ptr = (void*) con; con->ev.data.fd = sd;
}
net_set_nonblocking(con->sd, 1); void net_con_backend_add_epoll(struct net_backend* data, struct net_connection* con_, int events)
net_set_nosigpipe(con->sd, 1); {
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN; backend->conns[con->sd] = con;
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT; if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
g_backend->conns[sd] = con; if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
g_backend->num++;
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
{ {
LOG_TRACE("epoll_ctl() add failed."); LOG_TRACE("epoll_ctl() add failed.");
} }
net_con_print("ADD", con);
} }
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events) void net_con_backend_mod_epoll(struct net_backend* data, struct net_connection* con_, int events)
{ {
con->callback = callback; struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
con->ptr = (void*) ptr; struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
net_con_update(con, events);
}
void net_con_update(struct net_connection* con, int events) int newev = 0;
{ if (events & NET_EVENT_READ) newev |= EPOLLIN;
con->ev.events = 0; if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
#ifdef SSL_SUPPORT if (newev == con->ev.events)
if (events & NET_WANT_SSL_WRITE) return;
con->flags |= NET_WANT_SSL_WRITE;
else
con->flags &= ~NET_WANT_SSL_WRITE;
if (events & NET_WANT_SSL_READ) con->ev.events = newev;
con->flags |= NET_WANT_SSL_READ; if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
else
con->flags &= ~NET_WANT_SSL_READ;
if (events & NET_WANT_SSL_ACCEPT)
con->flags |= NET_WANT_SSL_ACCEPT;
else
con->flags &= ~NET_WANT_SSL_ACCEPT;
if (events & NET_WANT_SSL_CONNECT)
con->flags |= NET_WANT_SSL_CONNECT;
else
con->flags &= ~NET_WANT_SSL_CONNECT;
#endif /* SSL_SUPPORT */
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
{ {
LOG_TRACE("epoll_ctl() modify failed."); LOG_TRACE("epoll_ctl() modify failed.");
} }
net_con_print("MOD", con);
} }
int net_con_close(struct net_connection* con) void net_con_backend_del_epoll(struct net_backend* data, struct net_connection* con_)
{ {
if (!(con->flags & NET_INITIALIZED)) struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
return 0; struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
con->flags &= ~NET_INITIALIZED; backend->conns[con->sd] = 0;
if (con->sd != -1) if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
{
g_backend->conns[con->sd] = 0;
g_backend->num--;
}
if (timeout_evt_is_scheduled(con->timeout))
{
timeout_queue_remove(&g_backend->timeout_queue, con->timeout);
hub_free(con->timeout);
con->timeout = 0;
}
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
{ {
LOG_WARN("epoll_ctl() delete failed."); LOG_WARN("epoll_ctl() delete failed.");
} }
net_con_print("DEL", con);
return 0;
} }
#ifdef SSL_SUPPORT void net_backend_shutdown_epoll(struct net_backend* data)
int net_con_is_ssl(struct net_connection* con)
{ {
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
return con->ssl != 0; close(backend->epfd);
hub_free(backend->conns);
hub_free(backend);
} }
SSL* net_con_get_ssl(struct net_connection* con) struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common)
{ {
return con->ssl; struct net_backend_epoll* backend;
}
void net_con_set_ssl(struct net_connection* con, SSL* ssl) if (getenv("EVENT_NOEPOLL"))
{ return 0;
con->ssl = ssl;
}
#endif
int net_con_get_sd(struct net_connection* con) backend = hub_malloc_zero(sizeof(struct net_backend_epoll));
{ backend->epfd = epoll_create(common->max);
return con->sd; if (backend->epfd == -1)
}
void* net_con_get_ptr(struct net_connection* con)
{
return con->ptr;
}
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*);
static void timeout_callback(struct timeout_evt* evt)
{
struct net_connection* con = (struct net_connection*) evt->ptr;
con->callback(con, NET_EVENT_TIMEOUT, con->ptr);
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
if (!con->timeout)
{ {
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt)); LOG_WARN("Unable to create epoll socket.");
timeout_evt_initialize(con->timeout, timeout_callback, con); return 0;
timeout_queue_insert(&g_backend->timeout_queue, con->timeout, seconds);
}
else
{
timeout_queue_reschedule(&g_backend->timeout_queue, con->timeout, seconds);
} }
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;
} }
void net_con_clear_timeout(struct net_connection* con) static void net_backend_set_handlers(struct net_backend_handler* handler)
{ {
if (con->timeout && timeout_evt_is_scheduled(con->timeout)) handler->backend_name = net_backend_name_epoll;
{ handler->backend_poll = net_backend_poll_epoll;
timeout_queue_remove(&g_backend->timeout_queue, con->timeout); handler->backend_process = net_backend_process_epoll;
hub_free(con->timeout); handler->backend_shutdown = net_backend_shutdown_epoll;
con->timeout = 0; handler->con_create = net_con_create_epoll;
} handler->con_init = net_con_initialize_epoll;
handler->con_add = net_con_backend_add_epoll;
handler->con_mod = net_con_backend_mod_epoll;
handler->con_del = net_con_backend_del_epoll;
} }
#endif /* USE_EPOLL */ #endif /* USE_EPOLL */

186
src/network/kqueue.c Normal file
View 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 */

View File

@@ -1,399 +0,0 @@
/*
* 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/>.
*
*/
#ifdef USE_LIBEVENT
struct net_connection
{
NET_CON_STRUCT_COMMON
struct event event; /** libevent struct for read/write events */
struct event timeout; /** Used for internal timeout handling */
};
struct net_timer
{
unsigned int initialized;
struct event timeout;
net_timeout_cb callback;
void* ptr;
};
int net_con_get_sd(struct net_connection* con)
{
return con->sd;
}
void* net_con_get_ptr(struct net_connection* con)
{
return con->ptr;
}
struct net_connection* net_con_create()
{
struct net_connection* con = (struct net_connection*) hub_malloc(sizeof(struct net_connection));
return con;
}
static inline int net_con_flag_get(struct net_connection* con, unsigned int flag)
{
return con->flags & flag;
}
static inline void net_con_flag_set(struct net_connection* con, unsigned int flag)
{
con->flags |= flag;
}
static inline void net_con_flag_unset(struct net_connection* con, unsigned int flag)
{
con->flags &= ~flag;
}
void net_con_destroy(struct net_connection* con)
{
hub_free(con);
}
static inline int net_con_convert_to_libevent_mask(int ev)
{
int events = 0;
if (ev & NET_EVENT_READ) events |= EV_READ;
if (ev & NET_EVENT_WRITE) events |= EV_WRITE;
return events;
}
static inline int net_con_convert_from_libevent_mask(int ev)
{
int events = 0;
if (ev & EV_TIMEOUT) events |= NET_EVENT_TIMEOUT;
if (ev & EV_READ) events |= NET_EVENT_READ;
if (ev & EV_WRITE) events |= NET_EVENT_WRITE;
return events;
}
static void net_con_event(int fd, short ev, void *arg);
int net_con_close(struct net_connection* con)
{
uhub_assert(con);
con->ptr = 0;
if (net_con_flag_get(con, NET_CLEANUP))
return 0;
if (net_con_flag_get(con, NET_PROCESSING_BUSY))
{
net_con_flag_set(con, NET_CLEANUP);
return 0;
}
net_con_after_close(con);
return 1;
}
static void net_con_set(struct net_connection* con)
{
uhub_assert(con);
int ev = 0;
if (net_con_flag_get(con, NET_WANT_READ | NET_WANT_SSL_READ)) ev |= EV_READ;
if (net_con_flag_get(con, NET_WANT_WRITE | NET_WANT_SSL_WRITE)) ev |= EV_WRITE;
if (net_con_flag_get(con, NET_EVENT_SET) != 0)
{
event_del(&con->event);
}
net_con_flag_set(con, NET_EVENT_SET);
LOG_MEMORY("SET: set+add: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, ev);
event_set(&con->event, con->sd, ev, net_con_event, con);
event_add(&con->event, 0);
net_con_flag_set(con, NET_INITIALIZED);
}
static void net_con_after_close(struct net_connection* con)
{
if (net_con_flag_get(con, NET_INITIALIZED))
{
LOG_MEMORY("DEL: close: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, -1);
net_con_flag_unset(con, NET_EVENT_SET);
event_del(&con->event);
net_con_flag_unset(con, NET_INITIALIZED);
}
net_con_clear_timeout(con);
net_close(con->sd);
con->sd = -1;
hub_free(con);
}
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int ev)
{
uhub_assert(con);
int events = net_con_convert_to_libevent_mask(ev);
if (ev & NET_EVENT_READ) net_con_flag_set(con, NET_WANT_READ);
if (ev & NET_EVENT_WRITE) net_con_flag_set(con, NET_WANT_WRITE);
con->sd = sd;
con->flags = 0;
con->ptr = (void*) ptr;
con->callback = callback;
con->last_send = time(0);
con->last_recv = con->last_send;
if (ev)
{
uhub_assert(net_con_flag_get(con, NET_EVENT_SET) == 0);
net_con_flag_set(con, NET_EVENT_SET);
LOG_MEMORY("SET: init: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, ev);
event_set(&con->event, con->sd, events, net_con_event, con);
event_add(&con->event, 0);
net_con_flag_set(con, NET_INITIALIZED);
}
net_set_nonblocking(sd, 1);
net_set_nosigpipe(sd, 1);
#ifdef SSL_SUPPORT
con->ssl = NULL;
con->write_len = 0;
#endif
}
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
{
uhub_assert(con);
con->callback = callback;
con->ptr = (void*) ptr;
net_con_update(con, events);
}
void net_con_update(struct net_connection* con, int ev)
{
uhub_assert(con);
if (ev & NET_EVENT_READ)
net_con_flag_set(con, NET_EVENT_READ);
else
net_con_flag_unset(con, NET_EVENT_READ);
if (ev & NET_EVENT_WRITE)
net_con_flag_set(con, NET_EVENT_WRITE);
else
net_con_flag_unset(con, NET_EVENT_WRITE);
if (!net_con_flag_get(con, NET_PROCESSING_BUSY))
{
net_con_set(con);
}
}
#define CALLBACK(CON, EVENTS) \
if (CON->callback) \
CON->callback(con, EVENTS, CON->ptr);
static void net_con_event(int fd, short ev, void *arg)
{
struct net_connection* con = (struct net_connection*) arg;
int events = net_con_convert_from_libevent_mask(ev);
if (!net_con_flag_get(con, NET_INITIALIZED))
{
return;
}
if (net_con_flag_get(con, NET_CLEANUP))
{
net_con_after_close(con);
return;
}
net_con_flag_set(con, NET_PROCESSING_BUSY);
// uhub_assert(net_con_flag_get(con, NET_EVENT_SET) != 0);
net_con_flag_unset(con, NET_EVENT_SET);
LOG_MEMORY("EVT: process: CON={ %p, %p, %d, %d}", con, &con->event, con->sd, (int) ev);
#ifdef SSL_SUPPORT
if (!con->ssl)
{
#endif
CALLBACK(con, events);
#ifdef SSL_SUPPORT
}
else
{
#ifdef NETWORK_DUMP_DEBUG
LOG_PROTO("net_con_event: events=%d, con=%p", ev, con);
#endif
if (ev & (EV_READ | EV_WRITE))
{
if (net_con_flag_get(con, NET_WANT_SSL_ACCEPT))
{
if (net_con_ssl_accept(con) < 0)
CALLBACK(con, NET_EVENT_SOCKERROR);
}
else if (net_con_flag_get(con, NET_WANT_SSL_CONNECT))
{
if (net_con_ssl_connect(con) < 0)
CALLBACK(con, NET_EVENT_SOCKERROR);
}
else if (ev == EV_READ && net_con_flag_get(con, NET_WANT_SSL_READ))
{
CALLBACK(con, NET_EVENT_WRITE);
}
else if (ev == EV_WRITE && net_con_flag_get(con, NET_WANT_SSL_WRITE))
{
CALLBACK(con, events & NET_EVENT_READ);
}
else
{
CALLBACK(con, events);
}
}
else
{
CALLBACK(con, events);
}
}
#endif
net_con_flag_unset(con, NET_PROCESSING_BUSY);
if (net_con_flag_get(con, NET_CLEANUP))
{
net_con_after_close(con);
}
else
{
net_con_set(con);
}
}
static void net_timer_event(int fd, short ev, void *arg)
{
struct net_timer* timer = (struct net_timer*) arg;
timer->callback(timer, timer->ptr);
}
void net_timer_initialize(struct net_timer* timer, net_timeout_cb callback, void* ptr)
{
timer->initialized = 0;
timer->callback = callback;
timer->ptr = ptr;
}
void net_timer_reset(struct net_timer* timer, int seconds)
{
struct timeval timeout = { seconds, 0 };
if (timer->initialized)
{
evtimer_del(&timer->timeout);
timer->initialized = 0;
}
evtimer_set(&timer->timeout, net_timer_event, timer);
evtimer_add(&timer->timeout, &timeout);
}
void net_timer_shutdown(struct net_timer* timer)
{
if (timer->initialized)
{
evtimer_del(&timer->timeout);
timer->initialized = 0;
}
timer->callback = 0;
timer->ptr = 0;
}
void net_con_set_timeout(struct net_connection* con, int seconds)
{
uhub_assert(con);
struct timeval timeout = { seconds, 0 };
net_con_clear_timeout(con);
evtimer_set(&con->timeout, net_con_event, con);
evtimer_add(&con->timeout, &timeout);
net_con_flag_set(con, NET_TIMER_ENABLED);
}
void net_con_clear_timeout(struct net_connection* con)
{
uhub_assert(con);
if (net_con_flag_get(con, NET_TIMER_ENABLED))
{
evtimer_del(&con->timeout);
net_con_flag_unset(con, NET_TIMER_ENABLED);
}
}
static struct event_base g_evbase = 0;
/**
* Initialize the network backend.
* Returns 1 on success, or 0 on failure.
*/
int net_backend_initialize()
{
g_evbase = event_init();
if (!g_evbase)
{
LOG_ERROR("Unable to initialize libevent.");
return 0;
}
LOG_DEBUG("Using libevent %s, backend: %s", event_get_version(), event_get_method());
return 1;
}
/**
* Shutdown the network connection backend.
*/
void net_backend_shutdown()
{
event_base_free(g_evbase);
}
/**
* Process the network backend.
*/
int net_backend_process()
{
int ret = event_base_loop(g_evbase, EVLOOP_ONCE);
if (ret != 0)
{
LOG_DEBUG("event_base_loop returned: %d", (int) ret);
}
if (ret < 0)
return 0;
return 1;
}
#endif /* USE_LIBEVENT */

View File

@@ -47,7 +47,13 @@ int net_initialize()
} }
#endif /* WINSOCK */ #endif /* WINSOCK */
net_backend_initialize(); if (!net_backend_init())
{
#ifdef WINSOCK
WSACleanup();
#endif
return -1;
}
net_stats_initialize(); net_stats_initialize();
#ifdef SSL_SUPPORT #ifdef SSL_SUPPORT
@@ -69,7 +75,7 @@ size_t net_get_max_sockets()
struct rlimit limits; struct rlimit limits;
if (getrlimit(RLIMIT_NOFILE, &limits) == 0) if (getrlimit(RLIMIT_NOFILE, &limits) == 0)
{ {
return limits.rlim_max; return MIN(limits.rlim_max, 65536);
} }
LOG_ERROR("getrlimit() failed"); LOG_ERROR("getrlimit() failed");
return 1024; return 1024;
@@ -351,6 +357,9 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
{ {
switch (net_error()) switch (net_error())
{ {
#if defined(__HAIKU__)
case ETIMEDOUT:
#endif
#if defined(__linux__) #if defined(__linux__)
case ENETDOWN: case ENETDOWN:
case EPROTO: case EPROTO:
@@ -376,16 +385,16 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
if (ipaddr) if (ipaddr)
{ {
memset(ipaddr, 0, sizeof(struct ip_addr_encap)); memset(ipaddr, 0, sizeof(struct ip_addr_encap));
ipaddr->af = addr4->sin_family; ipaddr->af = addr.ss_family;;
if (ipaddr->af == AF_INET6) if (ipaddr->af == AF_INET6)
{ {
char address[INET6_ADDRSTRLEN+1] = { 0, }; char address[INET6_ADDRSTRLEN+1] = { 0, };
net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1); net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1);
if (!strncmp(address, "::ffff:", 7)) if (strchr(address, '.'))
{ {
/* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */ /* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */
net_string_to_address(AF_INET, address + 7, (void*) &ipaddr->internal_ip_data.in);
ipaddr->af = AF_INET; ipaddr->af = AF_INET;
net_string_to_address(AF_INET, address, (void*) &ipaddr->internal_ip_data.in);
} }
else else
{ {
@@ -526,7 +535,15 @@ const char* net_address_to_string(int af, const void* src, char* dst, socklen_t
return NULL; return NULL;
#else #else
return inet_ntop(af, src, dst, cnt); if (inet_ntop(af, src, dst, cnt))
{
if (af == AF_INET6 && strncmp(dst, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
{
memmove(dst, dst + 7, cnt - 7);
}
return dst;
}
return NULL;
#endif #endif
} }
@@ -573,9 +590,6 @@ int net_string_to_address(int af, const char* src, void* dst)
#endif #endif
} }
const char* net_get_peer_address(int fd) const char* net_get_peer_address(int fd)
{ {
static char address[INET6_ADDRSTRLEN+1]; static char address[INET6_ADDRSTRLEN+1];
@@ -583,9 +597,10 @@ const char* net_get_peer_address(int fd)
struct sockaddr_in6* name6; struct sockaddr_in6* name6;
struct sockaddr_in* name4; struct sockaddr_in* name4;
struct sockaddr* name; struct sockaddr* name;
socklen_t namelen;
memset(address, 0, INET6_ADDRSTRLEN); memset(address, 0, INET6_ADDRSTRLEN);
socklen_t namelen = sizeof(struct sockaddr_storage); namelen = sizeof(struct sockaddr_storage);
memset(&storage, 0, namelen); memset(&storage, 0, namelen);
name6 = (struct sockaddr_in6*) &storage; name6 = (struct sockaddr_in6*) &storage;
@@ -594,21 +609,16 @@ const char* net_get_peer_address(int fd)
if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1) if (getpeername(fd, (struct sockaddr*) name, &namelen) != -1)
{ {
int af = name4->sin_family; int af = storage.ss_family;
if (af == AF_INET6) if (af == AF_INET6)
{ {
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN); net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
if (strncmp(address, "::ffff:", 7) == 0) /* IPv6 mapped IPv4 address. */
{
return &address[7];
}
return address;
} }
else else
{ {
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN); net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
return address;
} }
return address;
} }
else else
{ {
@@ -619,6 +629,46 @@ const char* net_get_peer_address(int fd)
return "0.0.0.0"; return "0.0.0.0";
} }
const char* net_get_local_address(int fd)
{
static char address[INET6_ADDRSTRLEN+1];
struct sockaddr_storage storage;
struct sockaddr_in6* name6;
struct sockaddr_in* name4;
struct sockaddr* name;
socklen_t namelen;
memset(address, 0, INET6_ADDRSTRLEN);
namelen = sizeof(struct sockaddr_storage);
memset(&storage, 0, namelen);
name6 = (struct sockaddr_in6*) &storage;
name4 = (struct sockaddr_in*) &storage;
name = (struct sockaddr*) &storage;
if (getsockname(fd, (struct sockaddr*) name, &namelen) != -1)
{
int af = storage.ss_family;
if (af == AF_INET6)
{
net_address_to_string(af, (void*) &name6->sin6_addr, address, INET6_ADDRSTRLEN);
}
else
{
net_address_to_string(af, (void*) &name4->sin_addr, address, INET6_ADDRSTRLEN);
}
return address;
}
else
{
net_error_out(fd, "net_get_local_address");
net_stats_add_error();
}
return "0.0.0.0";
}
ssize_t net_recv(int fd, void* buf, size_t len, int flags) ssize_t net_recv(int fd, void* buf, size_t len, int flags)
{ {

View File

@@ -224,6 +224,8 @@ extern int net_is_ipv6_supported();
*/ */
extern const char* net_get_peer_address(int fd); extern const char* net_get_peer_address(int fd);
extern const char* net_get_local_address(int fd);
/** /**
* See man(3) inet_ntop. * See man(3) inet_ntop.
*/ */

173
src/network/select.c Normal file
View 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 */

View File

@@ -18,7 +18,6 @@
*/ */
#include "uhub.h" #include "uhub.h"
#include "util/timeout.h"
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr) void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
{ {
@@ -36,8 +35,7 @@ void timeout_evt_reset(struct timeout_evt* t)
int timeout_evt_is_scheduled(struct timeout_evt* t) int timeout_evt_is_scheduled(struct timeout_evt* t)
{ {
if (!t) return 0; return t->prev != NULL;
return !!t->prev;
} }
void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max) void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max)
@@ -56,23 +54,35 @@ void timeout_queue_shutdown(struct timeout_queue* t)
size_t timeout_queue_process(struct timeout_queue* t, time_t now) size_t timeout_queue_process(struct timeout_queue* t, time_t now)
{ {
size_t pos; size_t pos = t->last;
size_t events = 0; size_t events = 0;
struct timeout_evt* evt = 0; struct timeout_evt* evt = 0;
for (pos = t->last; pos < now; pos++) t->last = now;
for (; pos <= now; pos++)
{ {
while ((evt = t->events[pos % t->max])) while ((evt = t->events[pos % t->max]))
{ {
timeout_queue_remove(t, evt); timeout_queue_remove(t, evt);
timeout_evt_reset(evt);
evt->callback(evt); evt->callback(evt);
events++; events++;
} }
} }
t->last = now;
return events; return events;
} }
size_t timeout_queue_get_next_timeout(struct timeout_queue* t, time_t now)
{
size_t seconds = 0;
while (t->events[(now + seconds) % t->max] == NULL && seconds < t->max)
{
seconds++;
}
if (seconds == 0)
return 1;
return seconds;
}
void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
{ {
struct timeout_evt* first; struct timeout_evt* first;
@@ -82,16 +92,19 @@ void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size
first = t->events[pos]; first = t->events[pos];
if (!first) if (first)
{
uhub_assert(first->timestamp == evt->timestamp);
first->prev->next = evt;
evt->prev = first->prev;
first->prev = evt;
}
else
{ {
t->events[pos] = evt; t->events[pos] = evt;
evt->prev = evt; evt->prev = evt;
} }
else evt->next = 0;
{
evt->prev = first->prev;
first->prev = evt;
}
} }
void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt) void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
@@ -99,23 +112,32 @@ void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt)
size_t pos = (evt->timestamp % t->max); size_t pos = (evt->timestamp % t->max);
struct timeout_evt* first = t->events[pos]; struct timeout_evt* first = t->events[pos];
if (!first) if (!first || !evt->prev)
return; return;
if (first == evt) if (first == evt)
{ {
if (first->next) if (first->prev != first)
first->next->prev = first->prev; {
t->events[pos] = first->next; 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 else
{ {
evt->prev->next = evt->next; evt->prev->next = evt->next;
if (evt->next) evt->next->prev = evt->prev;
evt->next->prev = evt->prev;
else
first->prev = evt->prev;
} }
timeout_evt_reset(evt);
} }
void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds)
@@ -123,4 +145,5 @@ void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt,
if (timeout_evt_is_scheduled(evt)) if (timeout_evt_is_scheduled(evt))
timeout_queue_remove(t, evt); timeout_queue_remove(t, evt);
timeout_queue_insert(t, evt, seconds); timeout_queue_insert(t, evt, seconds);
} }

View File

@@ -53,4 +53,6 @@ void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t sec
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*); void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds); 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 */ #endif /* HAVE_UHUB_TIMEOUT_HANDLER_H */

50
src/network/timer.c Normal file
View 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;
}
}

View File

@@ -44,6 +44,10 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #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__) #if defined(__CYGWIN__) || defined(__MINGW32__)
#ifndef WINSOCK #ifndef WINSOCK
#define WINSOCK #define WINSOCK
@@ -66,11 +70,15 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#ifndef __sun__
#include <getopt.h> #include <getopt.h>
#include <stdint.h>
#endif
#include <signal.h> #include <signal.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@@ -81,7 +89,9 @@
#include <pwd.h> #include <pwd.h>
#include <sys/resource.h> #include <sys/resource.h>
#define HAVE_STRNDUP #define HAVE_STRNDUP
#ifndef __HAIKU__
#define HAVE_MEMMEM #define HAVE_MEMMEM
#endif
#define HAVE_GETRLIMIT #define HAVE_GETRLIMIT
#endif #endif
@@ -102,20 +112,113 @@
#define uhub_assert assert #define uhub_assert assert
#ifdef USE_LIBEVENT
#include <event.h>
#else
#ifdef __linux__ #ifdef __linux__
#define USE_EPOLL #define USE_EPOLL
#include <sys/epoll.h> #include <sys/epoll.h>
#endif #endif
#ifdef BSD_LIKE
#define USE_KQUEUE
#include <sys/event.h>
#endif #endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun__) #define USE_SELECT
#ifndef WINSOCK
#include <sys/select.h>
#endif
#if defined(BSD_LIKE) || defined(__sun__)
#undef HAVE_STRNDUP #undef HAVE_STRNDUP
#undef HAVE_MEMMEM #undef HAVE_MEMMEM
#endif #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 #ifdef MSG_NOSIGNAL
#define UHUB_SEND_SIGNAL MSG_NOSIGNAL #define UHUB_SEND_SIGNAL MSG_NOSIGNAL
#else #else
@@ -130,8 +233,12 @@
#define INET6_ADDRSTRLEN 46 #define INET6_ADDRSTRLEN 46
#endif #endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#endif /* HAVE_UHUB_SYSTEM_H */ #endif /* HAVE_UHUB_SYSTEM_H */

View File

@@ -75,19 +75,13 @@ static void event_callback(struct net_connection* con, int events, void *arg)
{ {
struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con); struct ADC_client* client = (struct ADC_client*) net_con_get_ptr(con);
if (events == NET_EVENT_SOCKERROR || events == NET_EVENT_CLOSED)
{
printf("NET_EVENT_SOCKERROR || NET_EVENT_CLOSED\n");
client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
return;
}
if (events == NET_EVENT_TIMEOUT) if (events == NET_EVENT_TIMEOUT)
{ {
if (client->state == ps_conn) if (client->state == ps_conn)
{ {
client->callback(client, ADC_CLIENT_DISCONNECTED, 0); client->callback(client, ADC_CLIENT_DISCONNECTED, 0);
} }
return;
} }
if (events & NET_EVENT_READ) if (events & NET_EVENT_READ)

View File

@@ -330,7 +330,7 @@ void runloop(size_t clients)
while (running) while (running)
{ {
event_base_loop(net_get_evbase(), EVLOOP_ONCE); net_backend_process();
} }
for (n = 0; n < clients; n++) for (n = 0; n < clients; n++)
@@ -413,63 +413,17 @@ void parse_command_line(int argc, char** argv)
} }
} }
#ifndef WIN32
static void handle_signal(int signal, short events, void* arg)
{
switch (signal)
{
case SIGINT:
case SIGTERM:
running = 0;
break;
default:
break;
}
}
static struct event signal_events[10];
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
0
};
void setup_signal_handlers()
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_set(&signal_events[i], signals[i], handle_signal, NULL);
signal_add(&signal_events[i], NULL);
}
}
void shutdown_signal_handlers()
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_del(&signal_events[i]);
}
}
#endif /* WIN32 */
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
parse_command_line(argc, argv); parse_command_line(argc, argv);
net_initialize(); net_initialize();
setup_signal_handlers();
hub_log_initialize(NULL, 0); hub_log_initialize(NULL, 0);
hub_set_log_verbosity(1000); hub_set_log_verbosity(1000);
runloop(cfg_clients); runloop(cfg_clients);
shutdown_signal_handlers();
net_destroy(); net_destroy();
return 0; return 0;
} }

View File

@@ -63,6 +63,7 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
return 1; return 1;
} }
static int running = 1;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@@ -79,7 +80,10 @@ int main(int argc, char** argv)
ADC_client_set_callback(&client, handle); ADC_client_set_callback(&client, handle);
ADC_client_connect(&client, argv[1]); ADC_client_connect(&client, argv[1]);
event_dispatch(); while (running)
{
net_backend_process();
}
ADC_client_destroy(&client); ADC_client_destroy(&client);
net_destroy(); net_destroy();

View File

@@ -62,13 +62,13 @@ extern "C" {
#include "util/log.h" #include "util/log.h"
#include "util/memory.h" #include "util/memory.h"
#include "util/misc.h" #include "util/misc.h"
#include "util/timeout.h"
#include "util/tiger.h" #include "util/tiger.h"
#include "adc/sid.h" #include "adc/sid.h"
#include "adc/message.h" #include "adc/message.h"
#include "network/network.h" #include "network/network.h"
#include "network/connection.h" #include "network/connection.h"
#include "network/timeout.h"
#include "core/auth.h" #include "core/auth.h"
#include "core/config.h" #include "core/config.h"

View File

@@ -451,11 +451,12 @@ int ip_convert_address_to_range(const char* address, struct ip_range* range)
{ {
int ret = 0; int ret = 0;
char* addr = 0; char* addr = 0;
const char* split;
if (!address || !range) if (!address || !range)
return 0; return 0;
const char* split = strrchr(address, '/'); split = strrchr(address, '/');
if (split) if (split)
{ {
int mask = uhub_atoi(split+1); int mask = uhub_atoi(split+1);

View File

@@ -171,14 +171,65 @@ void base32_decode(const char* src, unsigned char* dst, size_t len) {
} }
} }
int string_split(const char* string, const char* split, void* data, string_split_handler_t handler)
{
char* buf = strdup(string);
char* start;
char* pos;
int count = 0;
start = buf;
while ((pos = strstr(start, split)))
{
pos[0] = '\0';
start = strip_white_space(start);
if (*start)
{
if (handler(start, count, data) < 0)
{
hub_free(buf);
return -1;
}
}
start = &pos[1];
count++;
}
start = strip_white_space(start);
if (*start)
{
if (handler(start, count, data) < 0)
{
hub_free(buf);
return -1;
}
}
hub_free(buf);
return count+1;
}
struct file_read_line_data
{
file_line_handler_t handler;
void* data;
};
static int file_read_line_handler(char* line, int count, void* ptr)
{
struct file_read_line_data* data = (struct file_read_line_data*) ptr;
LOG_DUMP("Line: %s", line);
if (data->handler(line, count+1, data->data) < 0)
return -1;
return 0;
}
int file_read_lines(const char* file, void* data, file_line_handler_t handler) int file_read_lines(const char* file, void* data, file_line_handler_t handler)
{ {
int fd; int fd;
ssize_t ret; ssize_t ret;
char buf[MAX_RECV_BUF]; char buf[MAX_RECV_BUF];
char *pos, *start; struct file_read_line_data split_data;
size_t line_count = 0;
memset(buf, 0, MAX_RECV_BUF); memset(buf, 0, MAX_RECV_BUF);
@@ -192,46 +243,24 @@ int file_read_lines(const char* file, void* data, file_line_handler_t handler)
} }
ret = read(fd, buf, MAX_RECV_BUF); ret = read(fd, buf, MAX_RECV_BUF);
close(fd);
if (ret < 0) if (ret < 0)
{ {
LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno)); LOG_ERROR("Unable to read from file %s: %s", file, strerror(errno));
close(fd);
return -1; return -1;
} }
else if (ret == 0) else if (ret == 0)
{ {
close(fd);
LOG_WARN("File is empty."); LOG_WARN("File is empty.");
return 0; return 0;
} }
else
{ /* Parse configuaration */
close(fd); split_data.handler = handler;
split_data.data = data;
/* Parse configuaration */
start = buf; return string_split(buf, "\n", &split_data, file_read_line_handler);
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;
} }

View File

@@ -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 int file_read_lines(const char* file, void* data, file_line_handler_t handler);
extern const char* uhub_itoa(int val); extern const char* uhub_itoa(int val);
extern const char* uhub_ulltoa(uint64_t val); extern const char* uhub_ulltoa(uint64_t val);
@@ -61,6 +62,8 @@ void* memmem(const void *haystack, size_t haystacklen, const void *needle, size_
struct linked_list; struct linked_list;
extern int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty); extern int split_string(const char* string, const char* split, struct linked_list* list, int allow_empty);
typedef int (*string_split_handler_t)(char* string, int count, void* data);
extern int string_split(const char* string, const char* split, void* data, string_split_handler_t handler);
#endif /* HAVE_UHUB_MISC_H */ #endif /* HAVE_UHUB_MISC_H */

16
tools/create_certificate.sh Executable file
View 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
View 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 . "|";

View File

@@ -1,17 +1,25 @@
#include "revision.h"
#ifndef PRODUCT #ifndef PRODUCT
#define PRODUCT "uHub" #define PRODUCT "uhub"
#endif
#ifndef VERSION
#define VERSION "0.3.1"
#endif #endif
#ifndef GIT_REVISION #ifndef GIT_REVISION
#define REVISION "" #define REVISION ""
#define PRODUCT_STRING PRODUCT "/" VERSION
#else #else
#define REVISION " (git: " GIT_REVISION ")" #define REVISION "(git: " GIT_REVISION ")"
#ifdef GIT_VERSION
#define PRODUCT_STRING PRODUCT "/" GIT_VERSION
#else
#define PRODUCT_STRING PRODUCT "/" VERSION " " REVISION
#endif #endif
#ifndef VERSION
#define VERSION "0.3.0-rc4" REVISION
#endif #endif
#ifndef COPYRIGHT #ifndef COPYRIGHT
#define COPYRIGHT "Copyright (c) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>" #define COPYRIGHT "Copyright (c) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>"
#endif #endif