Compare commits
82 Commits
sans_libev
...
0.3.1-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
782f091637 | ||
|
|
82eeaa1fba | ||
|
|
977b57a385 | ||
|
|
19b9f72337 | ||
|
|
56605f7dcb | ||
|
|
bf1b64db53 | ||
|
|
915cb56448 | ||
|
|
6992043f9d | ||
|
|
896bbfcb5d | ||
|
|
6ac78e1a10 | ||
|
|
74a2191350 | ||
|
|
be8db21561 | ||
|
|
8065903604 | ||
|
|
78ae9fb3ce | ||
|
|
4715815ba2 | ||
|
|
cb9625f6a5 | ||
|
|
9934bde050 | ||
|
|
9a1c5ee548 | ||
|
|
11df912162 | ||
|
|
c8bc2f64fd | ||
|
|
2dc95eca47 | ||
|
|
7637d9ba68 | ||
|
|
4e9488dd4d | ||
|
|
e0003ebbb2 | ||
|
|
8e7e8c68f5 | ||
|
|
db32eaeafc | ||
|
|
1599f63134 | ||
|
|
c3ad006d07 | ||
|
|
1faca92167 | ||
|
|
f0a13b4c23 | ||
|
|
ccd1c8f160 | ||
|
|
41418f21e7 | ||
|
|
7a8a737cad | ||
|
|
ac48ad01fb | ||
|
|
31a69b1f3f | ||
|
|
d7a1a52c1a | ||
|
|
f54e8dbbba | ||
|
|
de72d4ae63 | ||
|
|
01efc6cc20 | ||
|
|
7cf1181e6b | ||
|
|
4b64b28777 | ||
|
|
e9f0331ca8 | ||
|
|
f263534aaf | ||
|
|
788b644c80 | ||
|
|
2d7ffa37fe | ||
|
|
fbaac98483 | ||
|
|
bd9d8229ff | ||
|
|
dfa6d07455 | ||
|
|
6bbdd24cb7 | ||
|
|
e3a644a853 | ||
|
|
928225fb7b | ||
|
|
e3cf41cb97 | ||
|
|
59f67f9e17 | ||
|
|
bfc7c184a7 | ||
|
|
92c448b855 | ||
|
|
304ecda16a | ||
|
|
c670d13369 | ||
|
|
b2e7a2848f | ||
|
|
84bd2591d6 | ||
|
|
4aa65733d0 | ||
|
|
230ca28b46 | ||
|
|
5f353ebe28 | ||
|
|
68a26e1160 | ||
|
|
4711d26c11 | ||
|
|
1bb3bd90c1 | ||
|
|
5e253e8442 | ||
|
|
26a2a384b6 | ||
|
|
8b7f09c7f4 | ||
|
|
b29da11f3b | ||
|
|
78ad9b8572 | ||
|
|
b04a20c66e | ||
|
|
21a5981905 | ||
|
|
c47ea14047 | ||
|
|
9f5aaf0148 | ||
|
|
f645811f37 | ||
|
|
2f09fcea84 | ||
|
|
5e679e2d4f | ||
|
|
efeb36c492 | ||
|
|
7e60919596 | ||
|
|
e7cb4cd277 | ||
|
|
e45511827f | ||
|
|
80c6ad9d76 |
2
AUTHORS
2
AUTHORS
@@ -2,5 +2,5 @@ Authors of uHub
|
|||||||
===============
|
===============
|
||||||
|
|
||||||
Jan Vidar Krey, Design and implementation
|
Jan Vidar Krey, Design and implementation
|
||||||
|
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
||||||
|
|
||||||
|
|||||||
8
BSDmakefile
Normal file
8
BSDmakefile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
GMAKE=gmake
|
||||||
|
|
||||||
|
all:
|
||||||
|
@${GMAKE} ${.TARGETS}
|
||||||
|
|
||||||
|
${.TARGETS}: all
|
||||||
|
|
||||||
12
ChangeLog
12
ChangeLog
@@ -1,3 +1,15 @@
|
|||||||
|
0.3.0:
|
||||||
|
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
||||||
|
- Experimental SSL support
|
||||||
|
- Large rewrite of the network stack in order to support SSL.
|
||||||
|
- Added rule file for defining hub rules.
|
||||||
|
- Many crash fixes and other important bug fixes.
|
||||||
|
- Optimizations: O(1) timeout scheduler
|
||||||
|
- New sid allocation code.
|
||||||
|
- Added configurable server_listen_backlog (default 50).
|
||||||
|
- Added init.d scripts for RedHat/CentOS
|
||||||
|
|
||||||
|
|
||||||
0.2.8:
|
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.
|
||||||
|
|||||||
59
GNUmakefile
59
GNUmakefile
@@ -9,7 +9,6 @@ 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 +17,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 +40,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 +50,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 +68,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 +116,9 @@ CFLAGS += -DSSL_SUPPORT
|
|||||||
LDLIBS += -lssl
|
LDLIBS += -lssl
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_LIBEVENT),YES)
|
GIT_VERSION=$(shell git describe 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 +135,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 := \
|
||||||
@@ -200,8 +194,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 +213,17 @@ $(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 cat $@.tmp > $@; fi
|
||||||
|
|
||||||
$(autotest_OBJECTS): autotest.c
|
$(autotest_OBJECTS): autotest.c
|
||||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
||||||
|
|
||||||
|
|||||||
5
README
5
README
@@ -1,5 +1,8 @@
|
|||||||
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
||||||
|
|
||||||
For the official documentation, bugs and other information, please visit:
|
For the official documentation, bugs and other information, please visit:
|
||||||
http://www.extatic.org/uhub/
|
http://www.uhub.org/
|
||||||
|
|
||||||
|
For a list of compatible ADC clients, see:
|
||||||
|
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ EXO_TEST(hub_net_startup, {
|
|||||||
|
|
||||||
EXO_TEST(hub_config_initialize, {
|
EXO_TEST(hub_config_initialize, {
|
||||||
config_defaults(&g_config);
|
config_defaults(&g_config);
|
||||||
|
g_config.server_port = 15111;
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ static void inf_create_user()
|
|||||||
{
|
{
|
||||||
if (inf_user) return;
|
if (inf_user) return;
|
||||||
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||||
inf_user->connection = net_con_create();
|
|
||||||
inf_user->id.sid = 1;
|
inf_user->id.sid = 1;
|
||||||
inf_user->limits.upload_slots = 1;
|
inf_user->limits.upload_slots = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
13
debian/changelog
vendored
Normal file
13
debian/changelog
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
uhub (0.3.0-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fixed init.d scripts.
|
||||||
|
* Fixed lintian warnings.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 19:02:02 +0100
|
||||||
|
|
||||||
|
uhub (0.3.0-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Initial Release.
|
||||||
|
|
||||||
|
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 18:59:02 +0100
|
||||||
|
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
7
|
||||||
24
debian/control
vendored
Normal file
24
debian/control
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Source: uhub
|
||||||
|
Section: net
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
|
||||||
|
Build-Depends: debhelper (>= 7.0.0)
|
||||||
|
Standards-Version: 3.8.3.0
|
||||||
|
|
||||||
|
Package: uhub
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}
|
||||||
|
Description: High performance ADC p2p hub
|
||||||
|
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||||
|
Its low memory footprint allows it to handle several thousand users on
|
||||||
|
high-end servers, or a small private hub on embedded hardware.
|
||||||
|
.
|
||||||
|
Key features:
|
||||||
|
- High performance and low memory usage
|
||||||
|
- IPv4 and IPv6 support
|
||||||
|
- Experimental SSL support (optional)
|
||||||
|
- Advanced access control support
|
||||||
|
- Easy configuration
|
||||||
|
.
|
||||||
|
Homepage: http://www.uhub.org/
|
||||||
|
|
||||||
19
debian/copyright
vendored
Normal file
19
debian/copyright
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
uhub - High performance ADC p2p hub.
|
||||||
|
Copyright (C) 2010 Jan Vidar Krey <janvidar@extatic.org>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||||
|
License can be found in `/usr/share/common-licenses/GPL'.
|
||||||
|
|
||||||
45
debian/rules
vendored
Executable file
45
debian/rules
vendored
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
# export DH_VERBOSE=1
|
||||||
|
|
||||||
|
makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \
|
||||||
|
UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \
|
||||||
|
RELEASE=YES SILENT=YES
|
||||||
|
|
||||||
|
build: build-stamp
|
||||||
|
build-stamp:
|
||||||
|
dh_testdir
|
||||||
|
make $(makeopts)
|
||||||
|
touch build-stamp
|
||||||
|
|
||||||
|
clean:
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
rm -f build-stamp
|
||||||
|
make clean
|
||||||
|
dh_clean
|
||||||
|
|
||||||
|
binary-indep: build
|
||||||
|
|
||||||
|
binary-arch: build
|
||||||
|
dh_testdir
|
||||||
|
dh_testroot
|
||||||
|
dh_clean -k
|
||||||
|
dh_installdirs
|
||||||
|
$(MAKE) install $(makeopts)
|
||||||
|
dh_installdocs
|
||||||
|
dh_installinit
|
||||||
|
dh_installlogrotate
|
||||||
|
dh_installman -A
|
||||||
|
dh_installchangelogs ChangeLog
|
||||||
|
dh_strip
|
||||||
|
dh_compress
|
||||||
|
dh_installdeb
|
||||||
|
dh_shlibdeps
|
||||||
|
dh_gencontrol
|
||||||
|
dh_md5sums
|
||||||
|
dh_builddeb
|
||||||
|
|
||||||
|
binary: binary-indep binary-arch
|
||||||
|
.PHONY: build clean binary-indep binary-arch binary
|
||||||
|
|
||||||
4
debian/uhub.default
vendored
Normal file
4
debian/uhub.default
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# uhub - high performance adc hub.
|
||||||
|
|
||||||
|
UHUB_ENABLE=0
|
||||||
|
|
||||||
6
debian/uhub.dirs
vendored
Normal file
6
debian/uhub.dirs
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
etc/default
|
||||||
|
etc/init.d
|
||||||
|
etc/logrotate.d
|
||||||
|
etc/uhub
|
||||||
|
usr/bin
|
||||||
|
var/log/uhub
|
||||||
5
debian/uhub.docs
vendored
Normal file
5
debian/uhub.docs
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
AUTHORS
|
||||||
|
README
|
||||||
|
BUGS
|
||||||
|
TODO
|
||||||
|
doc/getstarted.txt
|
||||||
92
debian/uhub.init
vendored
Normal file
92
debian/uhub.init
vendored
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: uhub
|
||||||
|
# Required-Start: $remote_fs $network
|
||||||
|
# Required-Stop: $remote_fs $network
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: uhub - High performance ADC p2p hub.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||||
|
|
||||||
|
NAME=uhub
|
||||||
|
DESC="ADC hub"
|
||||||
|
DAEMON=/usr/bin/uhub
|
||||||
|
PIDFILE=/var/run/uhub/uhub.pid
|
||||||
|
LOGFILE=/var/log/uhub/uhub.log
|
||||||
|
SCRIPTNAME=/etc/init.d/uhub
|
||||||
|
|
||||||
|
DEFAULTFILE=/etc/default/uhub
|
||||||
|
[ -r $DEFAULTFILE ] && . $DEFAULTFILE
|
||||||
|
|
||||||
|
DAEMON_ENABLE="${UHUB_ENABLE}"
|
||||||
|
DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}"
|
||||||
|
|
||||||
|
test -x $DAEMON || exit 0
|
||||||
|
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
ulimit -n 65536
|
||||||
|
mkdir -p /var/run/uhub/
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
if [ "$DAEMON_ENABLE" != "true" ]; then
|
||||||
|
log_daemon_msg "Disabled $DESC" $NAME
|
||||||
|
log_end_msg 0
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_daemon_msg "Starting $DESC" $NAME
|
||||||
|
if ! start-stop-daemon --start --quiet --oknodo \
|
||||||
|
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
|
||||||
|
then
|
||||||
|
log_end_msg 1
|
||||||
|
else
|
||||||
|
log_end_msg 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
log_daemon_msg "Stopping $DESC" $NAME
|
||||||
|
if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \
|
||||||
|
--pidfile $PIDFILE --exec $DAEMON
|
||||||
|
then
|
||||||
|
rm -f $PIDFILE
|
||||||
|
log_end_msg 0
|
||||||
|
else
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
reload)
|
||||||
|
log_daemon_msg "Reloading $DESC configuration" $NAME
|
||||||
|
if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \
|
||||||
|
--quiet --pidfile $PIDFILE --exec $DAEMON
|
||||||
|
then
|
||||||
|
if start-stop-daemon --start --quiet \
|
||||||
|
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then
|
||||||
|
log_end_msg 0
|
||||||
|
else
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_end_msg 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart|force-reload)
|
||||||
|
$0 stop
|
||||||
|
$0 start
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
9
debian/uhub.logrotate
vendored
Normal file
9
debian/uhub.logrotate
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/var/log/uhub/*.log
|
||||||
|
{
|
||||||
|
compress
|
||||||
|
size 10M
|
||||||
|
rotate 10
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
}
|
||||||
|
|
||||||
1
debian/uhub.manpages
vendored
Normal file
1
debian/uhub.manpages
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
doc/uhub.1
|
||||||
27
debian/uhub.postinst
vendored
Normal file
27
debian/uhub.postinst
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
configure)
|
||||||
|
chmod 0750 /var/log/uhub
|
||||||
|
|
||||||
|
if [ -x /etc/init.d/uhub ]; then
|
||||||
|
update-rc.d uhub defaults >/dev/null
|
||||||
|
|
||||||
|
if [ -x /usr/sbin/invoke-rc.d ]; then
|
||||||
|
invoke-rc.d uhub restart
|
||||||
|
else
|
||||||
|
/etc/init.d/uhub restart
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
abort-upgrade|abort-remove|abort-deconfigure)
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "postinst: error: unknown argument: $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
6
debian/uhub.postrm
vendored
Normal file
6
debian/uhub.postrm
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if [ "$1" = purge ]; then
|
||||||
|
update-rc.d uhub remove >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
10
debian/uhub.prerm
vendored
Normal file
10
debian/uhub.prerm
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if [ "$1" = remove ]; then
|
||||||
|
if command -v invoke-rc.d >/dev/null 2>&1; then
|
||||||
|
invoke-rc.d uhub stop || true
|
||||||
|
else
|
||||||
|
/etc/init.d/uhub stop
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -8,19 +8,13 @@ Prerequisites
|
|||||||
Before you try to compile µHub, please make sure the following prerequisites are met.
|
Before you try to compile µHub, please make sure the following prerequisites are met.
|
||||||
* GNU make
|
* GNU make
|
||||||
* gcc > 3.0 (or MinGW on Windows)
|
* gcc > 3.0 (or MinGW on Windows)
|
||||||
* libevent >= 1.3
|
|
||||||
* Perl 5
|
* Perl 5
|
||||||
|
|
||||||
Linux and Mac OSX
|
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
||||||
-----------------
|
-------------------------------------------
|
||||||
Simply, run:
|
Simply, run:
|
||||||
% make
|
% make
|
||||||
|
|
||||||
FreeBSD, NetBSD and OpenBSD
|
|
||||||
---------------------------
|
|
||||||
Use GNU make, not BSD make:
|
|
||||||
% gmake
|
|
||||||
|
|
||||||
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
||||||
gmake USE_PCH=NO
|
gmake USE_PCH=NO
|
||||||
|
|
||||||
|
|||||||
@@ -43,4 +43,15 @@ if one wishes to run uhub as a specific user using the -u and -g switches.
|
|||||||
Example:
|
Example:
|
||||||
% uhub -f -l mylog.txt -u nobody -g nogroup
|
% uhub -f -l mylog.txt -u nobody -g nogroup
|
||||||
|
|
||||||
|
|
||||||
|
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
|
||||||
|
This limit needs to be higher than the configured max_users in uhub.conf.
|
||||||
|
|
||||||
|
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
||||||
|
* soft nofile 4096
|
||||||
|
* hard nofile 4096
|
||||||
|
|
||||||
|
Or, you can use (as root):
|
||||||
|
% ulimit -n 4096
|
||||||
|
|
||||||
Your mileage may vary -- Good luck!
|
Your mileage may vary -- Good luck!
|
||||||
|
|||||||
@@ -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=$?
|
||||||
|
|||||||
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Log rotate for Uhub
|
||||||
|
# see man logrotate
|
||||||
|
#
|
||||||
|
#
|
||||||
|
/var/log/uhub.log {
|
||||||
|
compress
|
||||||
|
size 10M
|
||||||
|
rotate 10
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
5
doc/rules.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
1. rule #1
|
||||||
|
2. rule #2
|
||||||
|
3. rule #3
|
||||||
|
......
|
||||||
|
34. Rule #34
|
||||||
@@ -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
|
||||||
@@ -55,6 +66,13 @@ 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
42
doc/uhub.ebuild
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Copyright 1999-2010 Gentoo Foundation
|
||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
# $Header: $
|
||||||
|
inherit eutils
|
||||||
|
|
||||||
|
if [ "$PV" != "9999" ]; then
|
||||||
|
SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
|
||||||
|
KEYWORDS="~amd64 ~x86"
|
||||||
|
else
|
||||||
|
inherit git
|
||||||
|
SRC_URI=""
|
||||||
|
EGIT_REPO_URI="git://github.com/janvidar/uhub.git"
|
||||||
|
KEYWORDS=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
EAPI="2"
|
||||||
|
|
||||||
|
DESCRIPTION="High performance ADC hub"
|
||||||
|
HOMEPAGE="http://www.uhub.org/"
|
||||||
|
|
||||||
|
LICENSE="GPL-3"
|
||||||
|
SLOT="0"
|
||||||
|
IUSE="+ssl"
|
||||||
|
|
||||||
|
DEPEND="=dev-lang/perl-5*
|
||||||
|
ssl? ( >=dev-libs/openssl-0.9.8 )
|
||||||
|
"
|
||||||
|
RDEPEND="${DEPEND}"
|
||||||
|
src_compile() {
|
||||||
|
$opts=""
|
||||||
|
use ssl && opts="USE_SSL=YES $opts"
|
||||||
|
emake $opts
|
||||||
|
}
|
||||||
|
src_install() {
|
||||||
|
dodir /usr/bin
|
||||||
|
dodir /etc/uhub
|
||||||
|
emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed"
|
||||||
|
newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub
|
||||||
|
}
|
||||||
|
pkg_postinst() {
|
||||||
|
enewuser uhub
|
||||||
|
}
|
||||||
85
doc/uhub.spec
Normal file
85
doc/uhub.spec
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
Summary: High performance ADC p2p hub.
|
||||||
|
Name: uhub
|
||||||
|
Version: 0.3.0
|
||||||
|
Release: 3
|
||||||
|
License: GPLv3
|
||||||
|
Group: Networking/File transfer
|
||||||
|
Source: uhub-%{version}.tar.gz
|
||||||
|
URL: http://www.uhub.org
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||||
|
|
||||||
|
|
||||||
|
%description
|
||||||
|
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||||
|
Its low memory footprint allows it to handle several thousand users on
|
||||||
|
high-end servers, or a small private hub on embedded hardware.
|
||||||
|
|
||||||
|
Key features:
|
||||||
|
- High performance and low memory usage
|
||||||
|
- IPv4 and IPv6 support
|
||||||
|
- Experimental SSL support (optional)
|
||||||
|
- Advanced access control support
|
||||||
|
- Easy configuration
|
||||||
|
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q -n %{name}-%{version}
|
||||||
|
|
||||||
|
%build
|
||||||
|
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
|
||||||
|
make
|
||||||
|
|
||||||
|
%install
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/uhub
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
||||||
|
|
||||||
|
install uhub $RPM_BUILD_ROOT/usr/bin/
|
||||||
|
> doc/motd.txt
|
||||||
|
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt $RPM_BUILD_ROOT/etc/uhub
|
||||||
|
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
||||||
|
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
||||||
|
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
||||||
|
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
||||||
|
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
||||||
|
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root)
|
||||||
|
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
|
||||||
|
%config(noreplace) /etc/uhub/uhub.conf
|
||||||
|
#%{_sysconfdir}/uhub/uhub.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
||||||
|
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
||||||
|
%{_sysconfdir}/init.d/uhub
|
||||||
|
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
||||||
|
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
||||||
|
/usr/share/man/man1/uhub.1.gz
|
||||||
|
%{_bindir}/uhub
|
||||||
|
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
%post
|
||||||
|
/sbin/chkconfig --add uhub
|
||||||
|
if [ $1 -gt 1 ] ; then
|
||||||
|
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
||||||
|
fi
|
||||||
|
# need more informations about add services and users in system
|
||||||
|
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Tue Jan 31 2010 E_zombie
|
||||||
|
- change GROUP
|
||||||
|
- chmod for files
|
||||||
|
- add postinstall scripts
|
||||||
|
- fix "License"
|
||||||
|
* Tue Jan 26 2010 E_zombie
|
||||||
|
- first .spec release
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
|||||||
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
||||||
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
LOG_DEBUG("ACL: Deny access for: %s-%s", buf1, buf2);
|
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
|
||||||
|
|
||||||
list_append(list, info);
|
list_append(list, info);
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,6 +125,7 @@
|
|||||||
#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_CHAT_ONLY 0
|
#define DEF_CHAT_ONLY 0
|
||||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
#define DEF_CHAT_IS_PRIVILEGED 0
|
||||||
@@ -180,8 +183,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,6 +194,7 @@ 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(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);
|
||||||
@@ -249,9 +255,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 +270,7 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
|
|||||||
GET_INT (max_send_buffer);
|
GET_INT (max_send_buffer);
|
||||||
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(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);
|
||||||
@@ -325,8 +334,10 @@ 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);
|
||||||
|
|
||||||
@@ -398,9 +409,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 +424,7 @@ 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(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);
|
||||||
|
|||||||
@@ -25,14 +25,17 @@ 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 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)" */
|
||||||
|
|||||||
322
src/core/hub.c
322
src/core/hub.c
@@ -183,6 +183,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 +197,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 +207,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 +362,27 @@ void hub_send_handshake(struct hub_info* hub, struct hub_user* u)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hub_send_motd(struct hub_info* hub, struct hub_user* u)
|
int hub_send_motd(struct hub_info* hub, struct hub_user* u)
|
||||||
{
|
{
|
||||||
if (hub->command_motd)
|
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,14 +451,113 @@ 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 net_connection* server;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t sockaddr_size;
|
||||||
|
int sd, ret;
|
||||||
|
|
||||||
|
if (ip_convert_address(bind_addr, port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sd = net_socket_create(addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (sd == -1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((net_set_reuseaddress(sd, 1) == -1) || (net_set_nonblocking(sd, 1) == -1))
|
||||||
|
{
|
||||||
|
net_close(sd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_bind(sd, (struct sockaddr*) &addr, sockaddr_size);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
LOG_ERROR("hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
|
||||||
|
net_close(sd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = net_listen(sd, backlog);
|
||||||
|
if (ret == -1)
|
||||||
|
{
|
||||||
|
LOG_ERROR("hub_start_service(): Unable to listen to socket");
|
||||||
|
net_close(sd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
server = net_con_create();
|
||||||
|
net_con_initialize(server, sd, net_on_accept, hub, NET_EVENT_READ);
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct server_alt_port_data
|
||||||
|
{
|
||||||
|
struct hub_info* hub;
|
||||||
|
struct hub_config* config;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int server_alt_port_start_one(char* line, int count, void* ptr)
|
||||||
|
{
|
||||||
|
struct server_alt_port_data* data = (struct server_alt_port_data*) ptr;
|
||||||
|
|
||||||
|
int port = uhub_atoi(line);
|
||||||
|
struct net_connection* con = start_listening_socket(data->config->server_bind_addr, port, data->config->server_listen_backlog, data->hub);
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
list_append(data->hub->server_alt_ports, con);
|
||||||
|
LOG_INFO("Listening on alternate port %d...", port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_alt_port_start(struct hub_info* hub, struct hub_config* config)
|
||||||
|
{
|
||||||
|
struct server_alt_port_data data;
|
||||||
|
|
||||||
|
if (!config->server_alt_ports || !*config->server_alt_ports)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hub->server_alt_ports = (struct linked_list*) list_create();
|
||||||
|
|
||||||
|
data.hub = hub;
|
||||||
|
data.config = config;
|
||||||
|
|
||||||
|
string_split(config->server_alt_ports, ",", &data, server_alt_port_start_one);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_alt_port_clear(void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) ptr;
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
net_con_close(con);
|
||||||
|
hub_free(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_alt_port_stop(struct hub_info* hub)
|
||||||
|
{
|
||||||
|
if (hub->server_alt_ports)
|
||||||
|
{
|
||||||
|
list_clear(hub->server_alt_ports, &server_alt_port_clear);
|
||||||
|
list_destroy(hub->server_alt_ports);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct hub_info* hub_start_service(struct hub_config* config)
|
struct hub_info* hub_start_service(struct hub_config* config)
|
||||||
{
|
{
|
||||||
struct hub_info* hub = 0;
|
struct hub_info* hub = 0;
|
||||||
struct sockaddr_storage addr;
|
int ipv6_supported;
|
||||||
socklen_t sockaddr_size;
|
|
||||||
int server_tcp, ret, ipv6_supported, af;
|
|
||||||
char address_buf[INET6_ADDRSTRLEN+1];
|
|
||||||
|
|
||||||
hub = hub_malloc_zero(sizeof(struct hub_info));
|
hub = hub_malloc_zero(sizeof(struct hub_info));
|
||||||
if (!hub)
|
if (!hub)
|
||||||
@@ -454,72 +567,20 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hub->tm_started = time(0);
|
hub->tm_started = time(0);
|
||||||
|
|
||||||
ipv6_supported = net_is_ipv6_supported();
|
ipv6_supported = net_is_ipv6_supported();
|
||||||
|
|
||||||
if (ipv6_supported)
|
if (ipv6_supported)
|
||||||
LOG_DEBUG("IPv6 supported.");
|
LOG_DEBUG("IPv6 supported.");
|
||||||
else
|
else
|
||||||
LOG_DEBUG("IPv6 not supported.");
|
LOG_DEBUG("IPv6 not supported.");
|
||||||
|
|
||||||
if (ip_convert_address(config->server_bind_addr, config->server_port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
|
hub->server = start_listening_socket(config->server_bind_addr, config->server_port, config->server_listen_backlog, hub);
|
||||||
|
if (!hub->server)
|
||||||
{
|
{
|
||||||
hub_free(hub);
|
hub_free(hub);
|
||||||
|
LOG_FATAL("Unable to start hub service");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
LOG_INFO("Starting " PRODUCT "/" VERSION ", listening on %s:%d...", net_get_local_address(hub->server->sd), config->server_port);
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = net_listen(server_tcp, config->server_listen_backlog);
|
|
||||||
if (ret == -1)
|
|
||||||
{
|
|
||||||
LOG_FATAL("hub_start_service(): Unable to listen to socket");
|
|
||||||
hub_free(hub);
|
|
||||||
net_close(server_tcp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
if (config->tls_enable)
|
if (config->tls_enable)
|
||||||
@@ -549,22 +610,21 @@ struct hub_info* hub_start_service(struct hub_config* config)
|
|||||||
}
|
}
|
||||||
#endif
|
#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 +632,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,20 +644,19 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
hub->status = hub_status_running;
|
server_alt_port_start(hub, config);
|
||||||
|
|
||||||
hub->server = net_con_create();
|
hub->status = hub_status_running;
|
||||||
net_con_initialize(hub->server, server_tcp, net_on_accept, hub, NET_EVENT_READ);
|
|
||||||
|
|
||||||
g_hub = hub;
|
g_hub = hub;
|
||||||
return hub;
|
return hub;
|
||||||
@@ -609,11 +668,9 @@ void hub_shutdown_service(struct hub_info* hub)
|
|||||||
LOG_DEBUG("hub_shutdown_service()");
|
LOG_DEBUG("hub_shutdown_service()");
|
||||||
|
|
||||||
event_queue_shutdown(hub->queue);
|
event_queue_shutdown(hub->queue);
|
||||||
#ifdef USE_LIBEVENT
|
|
||||||
event_del(&hub->ev_accept);
|
|
||||||
#endif
|
|
||||||
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 +684,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 +724,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 +771,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,44 +826,48 @@ 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);
|
||||||
}
|
}
|
||||||
#undef STATUS
|
#undef STATUS
|
||||||
|
|
||||||
@@ -795,16 +876,29 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me
|
|||||||
adc_msg_add_argument(cmd, code);
|
adc_msg_add_argument(cmd, code);
|
||||||
adc_msg_add_argument(cmd, escaped_text);
|
adc_msg_add_argument(cmd, escaped_text);
|
||||||
|
|
||||||
hub_free(escaped_text);
|
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
adc_msg_add_argument(cmd, flag);
|
adc_msg_add_argument(cmd, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
route_to_user(hub, user, cmd);
|
route_to_user(hub, user, cmd);
|
||||||
adc_msg_free(cmd);
|
|
||||||
|
|
||||||
|
if (level >= status_level_fatal)
|
||||||
|
{
|
||||||
|
snprintf(buf, 230, "MS%s", escaped_text);
|
||||||
|
adc_msg_add_argument(cmd, buf);
|
||||||
|
|
||||||
|
if (reconnect_time != 0)
|
||||||
|
{
|
||||||
|
snprintf(buf, 10, "TL%d", reconnect_time);
|
||||||
|
adc_msg_add_argument(cmd, buf);
|
||||||
|
}
|
||||||
|
route_to_user(hub, user, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_free(escaped_text);
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
adc_msg_free(qui);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
|
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
|
||||||
|
|||||||
@@ -91,10 +91,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 +100,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 +201,15 @@ extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
|
|||||||
/**
|
/**
|
||||||
* Send a welcome message containing the message of the day to
|
* 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.
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -143,10 +143,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;
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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.
|
||||||
@@ -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);
|
||||||
@@ -715,6 +714,7 @@ int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct ad
|
|||||||
*/
|
*/
|
||||||
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||||
if (!cmd) return -1; /* OOM */
|
if (!cmd) return -1; /* OOM */
|
||||||
|
|
||||||
@@ -737,7 +737,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = hub_handle_info_login(hub, user, cmd);
|
ret = hub_handle_info_login(hub, user, cmd);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
on_login_failure(hub, user, ret);
|
on_login_failure(hub, user, ret);
|
||||||
@@ -775,8 +775,14 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad
|
|||||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME - What if limits are not met ? */
|
ret = check_limits(hub, user, cmd);
|
||||||
check_limits(hub, user, cmd);
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
on_update_failure(hub, user, ret);
|
||||||
|
adc_msg_free(cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
strip_network(user, cmd);
|
strip_network(user, cmd);
|
||||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ extern struct hub_info* g_hub;
|
|||||||
#ifdef DEBUG_SENDQ
|
#ifdef DEBUG_SENDQ
|
||||||
void debug_sendq_send(struct hub_user* user, int sent, int total)
|
void debug_sendq_send(struct hub_user* user, int sent, int total)
|
||||||
{
|
{
|
||||||
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->net.connection.sd, sent, total);
|
LOG_DUMP("SEND: sd=%d, %d/%d bytes\n", user->connection->sd, sent, total);
|
||||||
if (sent == -1)
|
if (sent == -1)
|
||||||
{
|
{
|
||||||
int err = net_error();
|
int err = net_error();
|
||||||
@@ -162,26 +162,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)
|
||||||
@@ -238,7 +228,7 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
if (acl_is_ip_banned(hub->acl, addr))
|
if (acl_is_ip_banned(hub->acl, addr))
|
||||||
{
|
{
|
||||||
LOG_INFO("Denied [%s] (IP banned)", addr);
|
LOG_INFO("Denied [%s] (IP banned)", addr);
|
||||||
net_close(fd);
|
net_con_close(con);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +236,7 @@ void net_on_accept(struct net_connection* con, int event, void *arg)
|
|||||||
if (!probe)
|
if (!probe)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||||
net_close(fd);
|
net_con_close(con);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -336,6 +336,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
|||||||
case quit_socket_error: return "socket error"; break;
|
case quit_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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,7 @@ 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 */
|
||||||
|
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 +68,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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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))
|
||||||
|
|||||||
@@ -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
217
src/network/backend.c
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
|
||||||
|
struct net_backend;
|
||||||
|
struct net_connection;
|
||||||
|
|
||||||
|
struct net_cleanup_handler
|
||||||
|
{
|
||||||
|
size_t num;
|
||||||
|
size_t max;
|
||||||
|
struct net_connection** queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend
|
||||||
|
{
|
||||||
|
struct net_backend_common common;
|
||||||
|
time_t now; /* the time now (used for timeout handling) */
|
||||||
|
struct timeout_queue timeout_queue; /* used for timeout handling */
|
||||||
|
struct net_cleanup_handler* cleaner; /* handler to cleanup connections at a safe point */
|
||||||
|
struct net_backend_handler handler; /* backend event handler */
|
||||||
|
struct net_backend* data; /* backend specific data */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct net_backend* g_backend;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_EPOLL
|
||||||
|
extern struct net_backend* net_backend_init_epoll(struct net_backend_handler*, struct net_backend_common*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_KQUEUE
|
||||||
|
extern struct net_backend* net_backend_init_kqueue(struct net_backend_handler*, struct net_backend_common*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SELECT
|
||||||
|
extern struct net_backend* net_backend_init_select(struct net_backend_handler*, struct net_backend_common*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static net_backend_init_t net_backend_init_funcs[] = {
|
||||||
|
#ifdef USE_EPOLL
|
||||||
|
net_backend_init_epoll,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_KQUEUE
|
||||||
|
net_backend_init_kqueue,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SELECT
|
||||||
|
net_backend_init_select,
|
||||||
|
#endif
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
int net_backend_init()
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
g_backend = hub_malloc_zero(sizeof(struct net_backend));
|
||||||
|
g_backend->common.num = 0;
|
||||||
|
g_backend->common.max = net_get_max_sockets();
|
||||||
|
g_backend->now = time(0);
|
||||||
|
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* FIXME: max 600 secs! */
|
||||||
|
g_backend->cleaner = net_cleanup_initialize(g_backend->common.max);
|
||||||
|
|
||||||
|
for (n = 0; n < sizeof(net_backend_init_funcs); n++)
|
||||||
|
{
|
||||||
|
if (!net_backend_init_funcs[n])
|
||||||
|
break;
|
||||||
|
|
||||||
|
g_backend->data = net_backend_init_funcs[n](&g_backend->handler, &g_backend->common);
|
||||||
|
if (g_backend->data)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Initialized %s network backend.", g_backend->handler.backend_name());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_FATAL("Unable to find a suitable network backend");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown()
|
||||||
|
{
|
||||||
|
g_backend->handler.backend_shutdown(g_backend->data);
|
||||||
|
timeout_queue_shutdown(&g_backend->timeout_queue);
|
||||||
|
net_cleanup_shutdown(g_backend->cleaner);
|
||||||
|
hub_free(g_backend);
|
||||||
|
g_backend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void net_con_reinitialize(struct net_connection* con, net_connection_cb callback, const void* ptr, int events)
|
||||||
|
{
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
net_con_update(con, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_update(struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
g_backend->handler.con_mod(g_backend->data, con, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create()
|
||||||
|
{
|
||||||
|
return g_backend->handler.con_create(g_backend->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeout_queue* net_backend_get_timeout_queue()
|
||||||
|
{
|
||||||
|
if (!g_backend)
|
||||||
|
return 0;
|
||||||
|
return &g_backend->timeout_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the network backend.
|
||||||
|
*/
|
||||||
|
int net_backend_process()
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
size_t secs = timeout_queue_get_next_timeout(&g_backend->timeout_queue, g_backend->now);
|
||||||
|
|
||||||
|
res = g_backend->handler.backend_poll(g_backend->data, secs * 1000);
|
||||||
|
|
||||||
|
g_backend->now = time(0);
|
||||||
|
timeout_queue_process(&g_backend->timeout_queue, g_backend->now);
|
||||||
|
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("backend error.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_backend->handler.backend_process(g_backend->data, res);
|
||||||
|
|
||||||
|
net_cleanup_process(g_backend->cleaner);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
|
||||||
|
{
|
||||||
|
g_backend->handler.con_init(g_backend->data, con, sd, callback, ptr);
|
||||||
|
|
||||||
|
net_set_nonblocking(con->sd, 1);
|
||||||
|
net_set_nosigpipe(con->sd, 1);
|
||||||
|
|
||||||
|
g_backend->handler.con_add(g_backend->data, con, events);
|
||||||
|
g_backend->common.num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_close(struct net_connection* con)
|
||||||
|
{
|
||||||
|
if (con->flags & NET_CLEANUP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_backend->common.num--;
|
||||||
|
net_con_clear_timeout(con);
|
||||||
|
|
||||||
|
g_backend->handler.con_del(g_backend->data, con);
|
||||||
|
|
||||||
|
net_close(con->sd);
|
||||||
|
con->sd = -1;
|
||||||
|
|
||||||
|
net_cleanup_delayed_free(g_backend->cleaner, con);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_cleanup_handler* net_cleanup_initialize(size_t max)
|
||||||
|
{
|
||||||
|
struct net_cleanup_handler* handler = (struct net_cleanup_handler*) hub_malloc(sizeof(struct net_cleanup_handler));
|
||||||
|
handler->num = 0;
|
||||||
|
handler->max = max;
|
||||||
|
handler->queue = hub_malloc_zero(sizeof(struct net_connection*) * max);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_cleanup_shutdown(struct net_cleanup_handler* handler)
|
||||||
|
{
|
||||||
|
hub_free(handler->queue);
|
||||||
|
hub_free(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_cleanup_delayed_free(struct net_cleanup_handler* handler, struct net_connection* con)
|
||||||
|
{
|
||||||
|
handler->queue[handler->num++] = con;
|
||||||
|
con->flags |= NET_CLEANUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_cleanup_process(struct net_cleanup_handler* handler)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
for (n = 0; n < handler->num; n++)
|
||||||
|
{
|
||||||
|
struct net_connection* con = handler->queue[n];
|
||||||
|
LOG_TRACE("net_cleanup_process: free: %p", con);
|
||||||
|
hub_free(con);
|
||||||
|
}
|
||||||
|
handler->num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
return 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_process_epoll(struct net_backend* data, int res)
|
||||||
|
{
|
||||||
|
int n, ev;
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
for (n = 0; n < res; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_epoll* con = backend->conns[backend->events[n].data.fd];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
ev = 0;
|
||||||
|
if (backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
||||||
|
if (backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
||||||
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create_epoll(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_epoll));
|
||||||
|
con->sd = -1;
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize_epoll(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
con->sd = sd;
|
||||||
|
con->flags = 0;
|
||||||
|
con->callback = callback;
|
||||||
|
con->ev.events = 0;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
con->ev.data.fd = sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_add_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = con;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
||||||
|
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
||||||
|
|
||||||
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
||||||
|
{
|
||||||
|
LOG_TRACE("epoll_ctl() add failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_mod_epoll(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
|
||||||
|
int newev = 0;
|
||||||
|
if (events & NET_EVENT_READ) newev |= EPOLLIN;
|
||||||
|
if (events & NET_EVENT_WRITE) newev |= EPOLLOUT;
|
||||||
|
|
||||||
|
if (newev == con->ev.events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
con->ev.events = newev;
|
||||||
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_MOD, con->sd, &con->ev) == -1)
|
||||||
|
{
|
||||||
|
LOG_TRACE("epoll_ctl() modify failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_del_epoll(struct net_backend* data, struct net_connection* con_)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
struct net_connection_epoll* con = (struct net_connection_epoll*) con_;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
|
|
||||||
|
if (epoll_ctl(backend->epfd, EPOLL_CTL_DEL, con->sd, &con->ev) == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("epoll_ctl() delete failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown_epoll(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend = (struct net_backend_epoll*) data;
|
||||||
|
close(backend->epfd);
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
struct net_backend_epoll* backend;
|
||||||
|
|
||||||
|
if (getenv("EVENT_NOEPOLL"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
backend = hub_malloc_zero(sizeof(struct net_backend_epoll));
|
||||||
|
backend->epfd = epoll_create(common->max);
|
||||||
|
if (backend->epfd == -1)
|
||||||
{
|
{
|
||||||
LOG_WARN("Unable to create epoll socket.");
|
LOG_WARN("Unable to create epoll socket.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_backend->num = 0;
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * common->max);
|
||||||
g_backend->max = max;
|
backend->common = common;
|
||||||
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);
|
net_backend_set_handlers(handler);
|
||||||
timeout_queue_initialize(&g_backend->timeout_queue, g_backend->now, 600); /* look max 10 minutes into the future. */
|
return (struct net_backend*) backend;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||||
* Shutdown the network connection backend.
|
|
||||||
*/
|
|
||||||
void net_backend_shutdown()
|
|
||||||
{
|
{
|
||||||
close(g_backend->epfd);
|
handler->backend_name = net_backend_name_epoll;
|
||||||
hub_free(g_backend->conns);
|
handler->backend_poll = net_backend_poll_epoll;
|
||||||
hub_free(g_backend);
|
handler->backend_process = net_backend_process_epoll;
|
||||||
}
|
handler->backend_shutdown = net_backend_shutdown_epoll;
|
||||||
|
handler->con_create = net_con_create_epoll;
|
||||||
/**
|
handler->con_init = net_con_initialize_epoll;
|
||||||
* Process the network backend.
|
handler->con_add = net_con_backend_add_epoll;
|
||||||
*/
|
handler->con_mod = net_con_backend_mod_epoll;
|
||||||
int net_backend_process()
|
handler->con_del = net_con_backend_del_epoll;
|
||||||
{
|
|
||||||
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++)
|
|
||||||
{
|
|
||||||
struct net_connection* con = (struct net_connection*) g_backend->events[n].data.ptr;
|
|
||||||
int ev = 0;
|
|
||||||
if (g_backend->events[n].events & EPOLLIN) ev |= NET_EVENT_READ;
|
|
||||||
if (g_backend->events[n].events & EPOLLOUT) ev |= NET_EVENT_WRITE;
|
|
||||||
con->callback(con, ev, con->ptr);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct net_connection* net_con_create()
|
|
||||||
{
|
|
||||||
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection));
|
|
||||||
con->sd = -1;
|
|
||||||
return con;
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_destroy(struct net_connection* con)
|
|
||||||
{
|
|
||||||
hub_free(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_initialize(struct net_connection* con, int sd, net_connection_cb callback, const void* ptr, int events)
|
|
||||||
{
|
|
||||||
con->sd = sd;
|
|
||||||
con->flags = NET_INITIALIZED;
|
|
||||||
con->callback = callback;
|
|
||||||
con->ev.events = 0;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
con->ev.data.ptr = (void*) con;
|
|
||||||
|
|
||||||
net_set_nonblocking(con->sd, 1);
|
|
||||||
net_set_nosigpipe(con->sd, 1);
|
|
||||||
|
|
||||||
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
|
||||||
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
|
||||||
|
|
||||||
g_backend->conns[sd] = con;
|
|
||||||
g_backend->num++;
|
|
||||||
|
|
||||||
if (epoll_ctl(g_backend->epfd, EPOLL_CTL_ADD, con->sd, &con->ev) == -1)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
con->callback = callback;
|
|
||||||
con->ptr = (void*) ptr;
|
|
||||||
net_con_update(con, events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_con_update(struct net_connection* con, int events)
|
|
||||||
{
|
|
||||||
con->ev.events = 0;
|
|
||||||
if (events & NET_EVENT_READ) con->ev.events |= EPOLLIN;
|
|
||||||
if (events & NET_EVENT_WRITE) con->ev.events |= EPOLLOUT;
|
|
||||||
|
|
||||||
#ifdef SSL_SUPPORT
|
|
||||||
if (events & NET_WANT_SSL_WRITE)
|
|
||||||
con->flags |= NET_WANT_SSL_WRITE;
|
|
||||||
else
|
|
||||||
con->flags &= ~NET_WANT_SSL_WRITE;
|
|
||||||
|
|
||||||
if (events & NET_WANT_SSL_READ)
|
|
||||||
con->flags |= NET_WANT_SSL_READ;
|
|
||||||
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.");
|
|
||||||
}
|
|
||||||
net_con_print("MOD", con);
|
|
||||||
}
|
|
||||||
|
|
||||||
int net_con_close(struct net_connection* con)
|
|
||||||
{
|
|
||||||
if (!(con->flags & NET_INITIALIZED))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
con->flags &= ~NET_INITIALIZED;
|
|
||||||
|
|
||||||
if (con->sd != -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.");
|
|
||||||
}
|
|
||||||
net_con_print("DEL", con);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
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 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));
|
|
||||||
timeout_evt_initialize(con->timeout, timeout_callback, con);
|
|
||||||
timeout_queue_insert(&g_backend->timeout_queue, con->timeout, seconds);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
timeout_queue_reschedule(&g_backend->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(&g_backend->timeout_queue, con->timeout);
|
|
||||||
hub_free(con->timeout);
|
|
||||||
con->timeout = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_EPOLL */
|
#endif /* USE_EPOLL */
|
||||||
|
|||||||
186
src/network/kqueue.c
Normal file
186
src/network/kqueue.c
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#ifdef USE_KQUEUE
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
|
#define KQUEUE_EVBUFFER 512
|
||||||
|
|
||||||
|
struct net_connection_kqueue
|
||||||
|
{
|
||||||
|
NET_CON_STRUCT_COMMON
|
||||||
|
struct kevent ev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend_kqueue
|
||||||
|
{
|
||||||
|
int kqfd;
|
||||||
|
struct net_connection_kqueue** conns;
|
||||||
|
struct kevent** changes;
|
||||||
|
size_t nchanges;
|
||||||
|
struct kevent events[KQUEUE_EVBUFFER];
|
||||||
|
struct net_backend_common* common;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
|
||||||
|
const char* net_backend_name_kqueue()
|
||||||
|
{
|
||||||
|
return "kqueue";
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_backend_poll_kqueue(struct net_backend* data, int ms)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
struct timespec tspec = { 0, };
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
|
||||||
|
tspec.tv_sec = (ms / 1000);
|
||||||
|
tspec.tv_nsec = ((ms % 1000) * 1000000); /* FIXME: correct? */
|
||||||
|
|
||||||
|
res = kevent(backend->kqfd, *backend->changes, backend->nchanges, backend->events, KQUEUE_EVBUFFER, &tspec);
|
||||||
|
backend->nchanges = 0;
|
||||||
|
|
||||||
|
if (res == -1 && errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_process_kqueue(struct net_backend* data, int res)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
|
||||||
|
for (n = 0; n < res; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) backend->events[n].udata;
|
||||||
|
int ev = 0;
|
||||||
|
if (backend->events[n].filter & EVFILT_READ) ev |= NET_EVENT_READ;
|
||||||
|
if (backend->events[n].filter & EVFILT_WRITE) ev |= NET_EVENT_WRITE;
|
||||||
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create_kqueue(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_kqueue));
|
||||||
|
con->sd = -1;
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize_kqueue(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
con->sd = sd;
|
||||||
|
con->flags = 0;
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_add_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
|
{
|
||||||
|
short filter = 0;
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
||||||
|
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
||||||
|
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
||||||
|
backend->changes[backend->nchanges++] = &con->ev;
|
||||||
|
backend->conns[con->sd] = con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_mod_kqueue(struct net_backend* data, struct net_connection* con_, int events)
|
||||||
|
{
|
||||||
|
short filter = 0;
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
|
||||||
|
if (events & NET_EVENT_READ) filter |= EVFILT_READ;
|
||||||
|
if (events & NET_EVENT_WRITE) filter |= EVFILT_READ;
|
||||||
|
|
||||||
|
if (filter == con->ev.filter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EV_SET(&con->ev, con->sd, filter, EV_ADD, 0, 0, con);
|
||||||
|
backend->changes[backend->nchanges++] = &con->ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_del_kqueue(struct net_backend* data, struct net_connection* con_)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
struct net_connection_kqueue* con = (struct net_connection_kqueue*) con_;
|
||||||
|
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
|
|
||||||
|
/* No need to remove it from the kqueue filter, the kqueue man page says
|
||||||
|
it is automatically removed when the descriptor is closed. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown_kqueue(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend = (struct net_backend_kqueue*) data;
|
||||||
|
close(backend->kqfd);
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend->changes);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_backend* net_backend_init_kqueue(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
struct net_backend_kqueue* backend;
|
||||||
|
|
||||||
|
if (getenv("EVENT_NOKQUEUE"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
backend = hub_malloc_zero(sizeof(struct net_backend_kqueue));
|
||||||
|
backend->kqfd = kqueue();
|
||||||
|
if (backend->kqfd == -1)
|
||||||
|
{
|
||||||
|
LOG_WARN("Unable to create kqueue socket.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||||
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_kqueue*) * common->max);
|
||||||
|
backend->changes = hub_malloc_zero(sizeof(struct kevent*) * common->max);
|
||||||
|
backend->common = common;
|
||||||
|
|
||||||
|
net_backend_set_handlers(handler);
|
||||||
|
return (struct net_backend*) backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||||
|
{
|
||||||
|
handler->backend_name = net_backend_name_kqueue;
|
||||||
|
handler->backend_poll = net_backend_poll_kqueue;
|
||||||
|
handler->backend_process = net_backend_process_kqueue;
|
||||||
|
handler->backend_shutdown = net_backend_shutdown_kqueue;
|
||||||
|
handler->con_create = net_con_create_kqueue;
|
||||||
|
handler->con_init = net_con_initialize_kqueue;
|
||||||
|
handler->con_add = net_con_backend_add_kqueue;
|
||||||
|
handler->con_mod = net_con_backend_mod_kqueue;
|
||||||
|
handler->con_del = net_con_backend_del_kqueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_KQUEUE */
|
||||||
@@ -1,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 */
|
|
||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
173
src/network/select.c
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
|
||||||
|
#ifdef USE_SELECT
|
||||||
|
|
||||||
|
#include "network/connection.h"
|
||||||
|
#include "network/common.h"
|
||||||
|
#include "network/backend.h"
|
||||||
|
|
||||||
|
struct net_connection_select
|
||||||
|
{
|
||||||
|
NET_CON_STRUCT_COMMON
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_backend_select
|
||||||
|
{
|
||||||
|
struct net_connection_select** conns;
|
||||||
|
fd_set rfds;
|
||||||
|
fd_set wfds;
|
||||||
|
int maxfd;
|
||||||
|
struct net_backend_common* common;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler);
|
||||||
|
|
||||||
|
const char* net_backend_name_select()
|
||||||
|
{
|
||||||
|
return "select";
|
||||||
|
}
|
||||||
|
|
||||||
|
int net_backend_poll_select(struct net_backend* data, int ms)
|
||||||
|
{
|
||||||
|
int found, res, n;
|
||||||
|
struct timeval tval;
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
|
||||||
|
tval.tv_sec = ms / 1000;
|
||||||
|
tval.tv_usec = ((ms % 1000) * 1000); // FIXME: correct?
|
||||||
|
|
||||||
|
FD_ZERO(&backend->rfds);
|
||||||
|
FD_ZERO(&backend->wfds);
|
||||||
|
|
||||||
|
backend->maxfd = -1;
|
||||||
|
for (n = 0, found = 0; found < backend->common->num && n < backend->common->max; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_select* con = backend->conns[n];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
if (con->flags & NET_EVENT_READ) FD_SET(con->sd, &backend->rfds);
|
||||||
|
if (con->flags & NET_EVENT_WRITE) FD_SET(con->sd, &backend->wfds);
|
||||||
|
found++;
|
||||||
|
backend->maxfd = con->sd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backend->maxfd++;
|
||||||
|
|
||||||
|
res = select(backend->maxfd, &backend->rfds, &backend->wfds, 0, &tval);
|
||||||
|
|
||||||
|
if (res == -1 && errno == EINTR)
|
||||||
|
return 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_process_select(struct net_backend* data, int res)
|
||||||
|
{
|
||||||
|
int n, found;
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
for (n = 0, found = 0; found < res && n < backend->maxfd; n++)
|
||||||
|
{
|
||||||
|
struct net_connection_select* con = backend->conns[n];
|
||||||
|
if (con)
|
||||||
|
{
|
||||||
|
int ev = 0;
|
||||||
|
if (FD_ISSET(con->sd, &backend->rfds)) ev |= NET_EVENT_READ;
|
||||||
|
if (FD_ISSET(con->sd, &backend->wfds)) ev |= NET_EVENT_WRITE;
|
||||||
|
|
||||||
|
if (ev)
|
||||||
|
{
|
||||||
|
net_con_callback((struct net_connection*) con, ev);
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_connection* net_con_create_select(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_connection* con = (struct net_connection*) hub_malloc_zero(sizeof(struct net_connection_select));
|
||||||
|
con->sd = -1;
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_initialize_select(struct net_backend* data, struct net_connection* con_, int sd, net_connection_cb callback, const void* ptr)
|
||||||
|
{
|
||||||
|
struct net_connection_select* con = (struct net_connection_select*) con_;
|
||||||
|
con->sd = sd;
|
||||||
|
con->flags = 0;
|
||||||
|
con->callback = callback;
|
||||||
|
con->ptr = (void*) ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_add_select(struct net_backend* data, struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
backend->conns[con->sd] = (struct net_connection_select*) con;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_mod_select(struct net_backend* data, struct net_connection* con, int events)
|
||||||
|
{
|
||||||
|
con->flags |= (events & (NET_EVENT_READ | NET_EVENT_WRITE));;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_backend_del_select(struct net_backend* data, struct net_connection* con)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
backend->conns[con->sd] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_backend_shutdown_select(struct net_backend* data)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend = (struct net_backend_select*) data;
|
||||||
|
hub_free(backend->conns);
|
||||||
|
hub_free(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_backend* net_backend_init_select(struct net_backend_handler* handler, struct net_backend_common* common)
|
||||||
|
{
|
||||||
|
struct net_backend_select* backend;
|
||||||
|
|
||||||
|
if (getenv("EVENT_NOSELECT"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
backend = hub_malloc_zero(sizeof(struct net_backend_select));
|
||||||
|
FD_ZERO(&backend->rfds);
|
||||||
|
FD_ZERO(&backend->wfds);
|
||||||
|
backend->conns = hub_malloc_zero(sizeof(struct net_connection_select*) * common->max);
|
||||||
|
backend->common = common;
|
||||||
|
net_backend_set_handlers(handler);
|
||||||
|
return (struct net_backend*) backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_backend_set_handlers(struct net_backend_handler* handler)
|
||||||
|
{
|
||||||
|
handler->backend_name = net_backend_name_select;
|
||||||
|
handler->backend_poll = net_backend_poll_select;
|
||||||
|
handler->backend_process = net_backend_process_select;
|
||||||
|
handler->backend_shutdown = net_backend_shutdown_select;
|
||||||
|
handler->con_create = net_con_create_select;
|
||||||
|
handler->con_init = net_con_initialize_select;
|
||||||
|
handler->con_add = net_con_backend_add_select;
|
||||||
|
handler->con_mod = net_con_backend_mod_select;
|
||||||
|
handler->con_del = net_con_backend_del_select;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SELECT */
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uhub.h"
|
#include "uhub.h"
|
||||||
#include "util/timeout.h"
|
|
||||||
|
|
||||||
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr)
|
||||||
{
|
{
|
||||||
@@ -36,7 +35,6 @@ 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;
|
return !!t->prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,12 +57,11 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t now)
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
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++)
|
for (pos = t->last; 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++;
|
||||||
}
|
}
|
||||||
@@ -73,6 +70,19 @@ size_t timeout_queue_process(struct timeout_queue* t, time_t 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,18 @@ 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)
|
||||||
|
{
|
||||||
|
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 +111,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)
|
||||||
@@ -124,3 +145,4 @@ void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt,
|
|||||||
timeout_queue_remove(t, evt);
|
timeout_queue_remove(t, evt);
|
||||||
timeout_queue_insert(t, evt, seconds);
|
timeout_queue_insert(t, evt, seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
50
src/network/timer.c
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uhub.h"
|
||||||
|
#include "network/connection.h"
|
||||||
|
|
||||||
|
static void timeout_callback(struct timeout_evt* evt)
|
||||||
|
{
|
||||||
|
net_con_callback((struct net_connection*) evt->ptr, NET_EVENT_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_set_timeout(struct net_connection* con, int seconds)
|
||||||
|
{
|
||||||
|
if (!con->timeout)
|
||||||
|
{
|
||||||
|
con->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
|
||||||
|
timeout_evt_initialize(con->timeout, timeout_callback, con);
|
||||||
|
timeout_queue_insert(net_backend_get_timeout_queue(), con->timeout, seconds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout_queue_reschedule(net_backend_get_timeout_queue(), con->timeout, seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_con_clear_timeout(struct net_connection* con)
|
||||||
|
{
|
||||||
|
if (con->timeout && timeout_evt_is_scheduled(con->timeout))
|
||||||
|
{
|
||||||
|
timeout_queue_remove(net_backend_get_timeout_queue(), con->timeout);
|
||||||
|
hub_free(con->timeout);
|
||||||
|
con->timeout = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
119
src/system.h
119
src/system.h
@@ -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 */
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* Parse configuaration */
|
/* Parse configuaration */
|
||||||
start = buf;
|
split_data.handler = handler;
|
||||||
while ((pos = strchr(start, '\n')))
|
split_data.data = data;
|
||||||
{
|
|
||||||
pos[0] = '\0';
|
|
||||||
if (*start)
|
|
||||||
{
|
|
||||||
LOG_DUMP("Line: %s", start);
|
|
||||||
if (handler(start, line_count+1, data) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
start = &pos[1];
|
|
||||||
line_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*start)
|
return string_split(buf, "\n", &split_data, file_read_line_handler);
|
||||||
{
|
|
||||||
buf[strlen(start)] = 0;
|
|
||||||
LOG_DUMP("Line: %s", start);
|
|
||||||
if (handler(start, line_count+1, data) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line_count+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
16
tools/create_certificate.sh
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
OPENSSL=/usr/bin/openssl
|
||||||
|
NAME=certificate
|
||||||
|
|
||||||
|
if [ ! -x ${OPENSSL} ]; then
|
||||||
|
echo "Cannot locate the openssl utility: ${OPENSSL}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
${OPENSSL} genrsa -out ${NAME}.key 1024 &&
|
||||||
|
${OPENSSL} req -new -x509 -nodes -sha1 -days 365 -key ${NAME}.key > ${NAME}.crt &&
|
||||||
|
cat ${NAME}.key ${NAME}.crt > ${NAME}.pem && rm -f ${NAME}.key ${NAME}.crt
|
||||||
|
|
||||||
|
echo "Created certificate ${NAME}.pem"
|
||||||
|
|
||||||
20
tools/nmdc-redirector
Executable file
20
tools/nmdc-redirector
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
# Setup using inetd/xinetd or similar.
|
||||||
|
# In /etc/inetd.conf add:
|
||||||
|
# 1511 stream tcp nowait nobody /usr/bin/nmdc-redirector adc://target:port
|
||||||
|
#
|
||||||
|
# Change port to whatever you want.
|
||||||
|
# Make sure the path and the target:port is correct, then you should be good
|
||||||
|
# to go!
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use IO::Handle;
|
||||||
|
autoflush STDIN;
|
||||||
|
autoflush STDOUT;
|
||||||
|
|
||||||
|
my $target = $ARGV[0];
|
||||||
|
|
||||||
|
print "<Redirector> You are being redirected to " . $target . "|";
|
||||||
|
print "\$ForceMove " . $target . "|";
|
||||||
|
|
||||||
20
version.h
20
version.h
@@ -1,17 +1,25 @@
|
|||||||
|
#include "revision.h"
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
#define PRODUCT "uHub"
|
#define PRODUCT "uhub"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef VERSION
|
||||||
|
#define VERSION "0.3.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
|
||||||
|
|||||||
Reference in New Issue
Block a user